Skip to content

Commit bcfef7d

Browse files
committed
feat: ✨ 为方便其他项目使用进行打包
1 parent 17c3162 commit bcfef7d

26 files changed

Lines changed: 534 additions & 216 deletions

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
"build-storybook": "storybook build",
2424
"test-storybook": "test-storybook --maxWorkers=1 --testTimeout 60000",
2525
"percy": "percy exec -- pnpm test-storybook",
26-
"wdio": "wdio run ./wdio.conf.ts",
27-
"npm:build": "rollup --config --environment NODE_ENV:npm --configPlugin rollup-plugin-ts --configImportAttributesKey with"
26+
"wdio": "wdio run ./wdio.conf.ts"
2827
},
2928
"dependencies": {
3029
"@material-design-icons/svg": "^0.14.15",
@@ -70,7 +69,6 @@
7069
"@rollup/plugin-json": "^6.1.0",
7170
"@rollup/plugin-node-resolve": "^16.0.1",
7271
"@rollup/plugin-replace": "^6.0.2",
73-
"@rollup/plugin-terser": "^0.4.4",
7472
"@solidjs/router": "^0.15.3",
7573
"@storybook/test-runner": "^0.23.0",
7674
"@types/libarchive.js": "^1.3.4",
@@ -110,6 +108,7 @@
110108
"release-it": "^19.0.4",
111109
"rfdc": "^1.4.1",
112110
"rollup": "^4.46.2",
111+
"rollup-plugin-dts": "^6.2.3",
113112
"rollup-plugin-styles": "^4.0.0",
114113
"rollup-plugin-ts": "^3.4.5",
115114
"rollup-plugin-watch-external": "^1.0.2",
@@ -125,6 +124,7 @@
125124
"stylelint-prettier": "^5.0.3",
126125
"svgo": "^4.0.0",
127126
"sync-fetch": "^0.5.2",
127+
"terser": "^5.44.0",
128128
"tslib": "^2.8.1",
129129
"type-fest": "^4.41.0",
130130
"typescript": "^5.9.2",

pnpm-lock.yaml

Lines changed: 127 additions & 79 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rollup.config.ts

Lines changed: 104 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,33 @@ import commonjs from '@rollup/plugin-commonjs';
1010
import json from '@rollup/plugin-json';
1111
import { nodeResolve } from '@rollup/plugin-node-resolve';
1212
import replace from '@rollup/plugin-replace';
13-
import terser from '@rollup/plugin-terser';
1413
import { parse as parseMd } from 'marked';
1514
import fs from 'node:fs';
1615
import { dirname, resolve } from 'node:path';
1716
import { fileURLToPath } from 'node:url';
17+
import { dts } from 'rollup-plugin-dts';
1818
import styles from 'rollup-plugin-styles';
1919
import { watchExternal } from 'rollup-plugin-watch-external';
2020
import shell from 'shelljs';
21-
22-
import { inputPlugins, outputPlugins, solidSvg } from './src/rollup-plugin';
21+
import { minify } from 'terser';
22+
23+
import {
24+
escapeTmplText,
25+
inputPlugins,
26+
outputPlugins,
27+
solidSvg,
28+
} from './src/rollup-plugin';
2329
import { getMetaData, updateReadme } from './src/rollup-plugin/metaHeader';
2430
import { siteUrl } from './src/rollup-plugin/siteUrl';
2531

2632
const __dirname = dirname(fileURLToPath(import.meta.url));
2733

2834
const isDevMode = process.env.NODE_ENV === 'development';
29-
const isNpmMode = process.env.NODE_ENV === 'npm';
35+
36+
const minifyCode = async (code: string) => {
37+
const res = await minify(code, { ecma: 2020, mangle: false });
38+
return res.code!;
39+
};
3040

3141
const latestChangeHtml = await (() => {
3242
const md = fs
@@ -75,7 +85,7 @@ const packlist = [
7585
'worker/ImageUpscale',
7686
'userscript/otherSite',
7787
'userscript/ehTagRules',
78-
];
88+
] as const;
7989

8090
const babelConfig = {
8191
presets: ['@babel/preset-env', '@babel/preset-typescript', 'solid'],
@@ -123,6 +133,7 @@ const getPlugins = (...otherPlugins: InputPluginOption[]) => [
123133
isDevMode: `${isDevMode}`,
124134
'process.env.NODE_ENV': isDevMode ? `'development'` : `'production'`,
125135
'inject@LatestChange': latestChangeHtml,
136+
scriptVersion: `'${meta.version}'`,
126137
},
127138
preventAssignment: true,
128139
}),
@@ -138,8 +149,6 @@ const getPlugins = (...otherPlugins: InputPluginOption[]) => [
138149
styles({ mode: 'extract', modules: { generateScopedName } }),
139150
solidSvg(),
140151

141-
// ts({ transpiler: 'babel', transpileOnly: true, babelConfig }),
142-
143152
babel({
144153
babelHelpers: 'runtime',
145154
extensions: ['.ts', '.tsx'],
@@ -166,8 +175,6 @@ export const buildOptions = (
166175
watchFiles && isDevMode && watchExternal({ entries: watchFiles }),
167176
);
168177

169-
if (isNpmMode) options.plugins.push(terser());
170-
171178
Object.assign(options.output, {
172179
file: `dist/${path.replace(/(\/index)?\.tsx?/, '')}.js`,
173180
plugins: [
@@ -227,8 +234,7 @@ shell.rm('-rf', resolve(__dirname, 'dist'));
227234
if (isDevMode)
228235
shell.exec('serve dist --cors -l 2405', { async: true, silent: true });
229236

230-
// oxlint-disable-next-line no-mutable-exports
231-
let optionList: RollupOptions[] = [
237+
const optionList: RollupOptions[] = [
232238
buildOptions('dev'),
233239

234240
...packlist.map((path) => buildOptions(path)),
@@ -252,7 +258,8 @@ let optionList: RollupOptions[] = [
252258
/\s+\/\/ import list/,
253259
packlist
254260
.map((path) => {
255-
if (path === 'userscript/main') return '';
261+
if (path === 'userscript/main')
262+
return `\ncase 'main':\ncode = \`inject('${path}')\`;\nbreak;`;
256263
return `\ncase '${path}':\ncode = \`inject('${path}')\`;\nbreak;`;
257264
})
258265
.join(''),
@@ -333,6 +340,90 @@ if (!isDevMode)
333340
}),
334341
);
335342

336-
if (isNpmMode) optionList = [buildOptions('userscript/dmzjDecrypt')];
343+
const umdPacklist = [
344+
'helper/languages',
345+
'helper',
346+
'request',
347+
'components/Manga',
348+
'components/IconButton',
349+
'components/Toast',
350+
'userscript/detectAd',
351+
'worker/detectAd',
352+
'worker/ImageRecognition',
353+
'worker/ImageUpscale',
354+
];
355+
if (!isDevMode)
356+
optionList.push(
357+
buildOptions(
358+
'userscript/import',
359+
umdPacklist.map((path) => `dist/${path}.js`),
360+
(options) => {
361+
options.output.file = 'dist/umd/import.js';
362+
options.output.plugins.unshift({
363+
name: 'selfImport',
364+
async renderChunk(rawCode) {
365+
let importListCode = '';
366+
367+
for (const path of umdPacklist)
368+
importListCode += `\ncase '${path}':\ncode = \`inject('${path}')\`;\nbreak;\n`;
369+
370+
for (const [name, url] of Object.entries(meta.resource)) {
371+
const res = await fetch(url);
372+
let code = await res.text();
373+
374+
if (name === '@tensorflow/tfjs-backend-webgpu')
375+
code = code.replace(
376+
'@tensorflow/tfjs-core',
377+
'@tensorflow/tfjs',
378+
);
379+
380+
code = await minifyCode(code);
381+
importListCode += `\ncase '${name}':\ncode = \`${escapeTmplText(code)}\`;\nbreak;\n`;
382+
}
383+
384+
return rawCode.replace(/\s+\/\/ import list/, () => importListCode);
385+
},
386+
});
387+
return options;
388+
},
389+
),
390+
buildOptions(
391+
'umd',
392+
[...umdPacklist.map((path) => `dist/${path}.js`), 'dist/umd/import.js'],
393+
(options) => {
394+
options.output.plugins.unshift({
395+
name: 'selfUMD',
396+
async renderChunk(rawCode) {
397+
let code = rawCode;
398+
const importCode = fs
399+
.readFileSync(`dist/umd/import.js`)
400+
.toString()
401+
.replaceAll('require$1', 'require');
402+
code = `${importCode}\n${code}`;
403+
404+
if (!isDevMode) code = await minifyCode(code);
405+
406+
const name = 'initComicReader';
407+
code = `
408+
(function (global, factory) {
409+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
410+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
411+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.${name} = global.${name} || {}));
412+
})(this, (function (exports) {
413+
${code}
414+
}));`;
415+
416+
return code;
417+
},
418+
});
419+
return options;
420+
},
421+
),
422+
{
423+
input: './src/umd.tsx',
424+
output: [{ file: 'dist/umd.d.ts', format: 'es' }],
425+
plugins: [dts()],
426+
},
427+
);
337428

338429
export default optionList;

src/components/Manga/actions/helper.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ export const getImgIndexs = (url: string) => {
2020
};
2121

2222
/** 找到指定 url 图片的 dom */
23-
export const getImgEle = (url: string) =>
24-
refs.mangaFlow.querySelector<HTMLImageElement>(`img[data-src="${url}"]`);
23+
export const getImgEle = (target: string | number) => {
24+
const index =
25+
typeof target === 'number' ? target : store.imgList.indexOf(target);
26+
if (index === -1) return;
27+
return refs.mangaFlow.querySelector<HTMLImageElement>(`#_${index}_0 img`);
28+
};
2529

2630
/** 找到指定页面所处的图片流 */
2731
export const findFillIndex = (pageIndex: number, fillEffect: FillEffect) => {

src/components/Manga/actions/imageUpscale.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ const findUpscaleImage = async (
3131
for (let i = start; i < end; i++) {
3232
const img = typeof i === 'number' ? getImg(i) : i;
3333
if (img.upscaleUrl !== undefined) continue;
34-
const imgEle = await wait(() => getImgEle(img.src), 1000);
34+
const imgEle = await wait(() => getImgEle(i), 1000);
3535
if (imgEle) return [img.src, imgEle];
3636
}
3737
};
3838
const handleUpscaleImage = async () => {
39-
if (upscaleing || !isUpscale()) return;
39+
if (upscaleing || !isUpscale() || store.imgList.length === 0) return;
4040
// 优先放大 当前显示的图片 > 后面的图片 > 前面的图片
4141
const targetImg =
4242
(await findUpscaleImage(activeImgIndex(), store.imgList.length)) ??

src/components/Manga/actions/pointer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const handlePageClick = (e: MouseEvent) => {
3434
for (const i of showImgList()) {
3535
const img = getImg(i);
3636
if (img.loadType !== 'error') continue;
37-
const imgEle = getImgEle(img.src);
37+
const imgEle = getImgEle(i);
3838
if (!imgEle || !findClickEle([imgEle], e)) continue;
3939
return reloadImg(img.src);
4040
}

src/components/Manga/actions/translation/index.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { Accessor } from 'solid-js';
22

3-
import { toast } from 'components/Toast';
43
import { createRootMemo, range, singleThreaded, t } from 'helper';
54

65
import { setState, store } from '../../store';
@@ -12,11 +11,6 @@ import { selfhostedOptions, selfhostedTranslation } from './selfhosted';
1211
/** 翻译指定图片 */
1312
export const translationImage = async (url: string) => {
1413
try {
15-
if (typeof GM_xmlhttpRequest === 'undefined') {
16-
toast?.error(t('pwa.alert.userscript_not_installed'));
17-
throw new Error(t('pwa.alert.userscript_not_installed'));
18-
}
19-
2014
if (!url) return;
2115
const img = store.imgMap[url];
2216

src/components/Manga/actions/translation/selfhosted.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const selfhostedTranslation = async (url: string): Promise<string> => {
3333
} catch (error) {
3434
log.error(error, url);
3535
store.prop.onImgError?.(url);
36-
throw new Error(t('translation.tip.download_img_failed'));
36+
throw new Error(t('translation.tip.download_img_failed'), { cause: error });
3737
}
3838

3939
// 支持旧版 manga-image-translator
@@ -54,7 +54,7 @@ export const selfhostedTranslation = async (url: string): Promise<string> => {
5454
({ task_id } = res.response);
5555
} catch (error) {
5656
log.error(error);
57-
throw new Error(t('translation.tip.upload_error'));
57+
throw new Error(t('translation.tip.upload_error'), { cause: error });
5858
}
5959

6060
let errorNum = 0;
@@ -75,7 +75,9 @@ export const selfhostedTranslation = async (url: string): Promise<string> => {
7575
} catch (error) {
7676
log.error(error);
7777
if (errorNum > 5)
78-
throw new Error(t('translation.tip.check_img_status_failed'));
78+
throw new Error(t('translation.tip.check_img_status_failed'), {
79+
cause: error,
80+
});
7981
errorNum += 1;
8082
}
8183
}

src/components/DownloadButton.tsx renamed to src/components/Manga/components/DownloadButton.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ import { zipSync } from 'fflate';
55
import { createMemo } from 'solid-js';
66

77
import { IconButton } from 'components/IconButton';
8-
import { downloadImg, imgList, store } from 'components/Manga';
98
import { toast } from 'components/Toast';
109
import { createEffectOn, FaviconProgress, saveAs, t, useStore } from 'helper';
1110

11+
import { imgList } from '../actions';
12+
import { downloadImg } from '../helper';
13+
import { store } from '../store';
14+
1215
const getExtName = (mime: string) => /.+\/([^;]+)/.exec(mime)?.[1] ?? 'jpg';
1316

1417
/** 下载按钮 */

src/components/Manga/components/SettingsItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export type SettingsItemProps = {
1010

1111
children?: JSX.Element | JSX.Element[];
1212
class?: string;
13-
classList?: ClassList;
13+
classList?: Record<string, boolean | undefined>;
1414
style?: JSX.CSSProperties;
1515
};
1616

0 commit comments

Comments
 (0)