From e6f96ac75261ea3c17035b5ddda26ac74989ac07 Mon Sep 17 00:00:00 2001 From: hemengke1997 <23536175@qq.com> Date: Thu, 14 Sep 2023 19:53:18 +0800 Subject: [PATCH] feat: export `inject-script` plugin --- .gitignore | 3 +- README.md | 72 ++-- __test__/basic.spec.todo.ts | 119 +++++++ __test__/basic.spec.ts | 116 ------- package.json | 2 + playground/spa/package.json | 2 +- playground/spa/public-typescript/index.ts | 4 +- .../spa/public-typescript/manifest.json | 4 +- playground/spa/public-typescript/test.ts | 2 +- playground/spa/public/out/haha.bdaaba63.js | 1 - playground/spa/public/out/index.cccf1b56.js | 1 - playground/spa/public/out/test.40879d01.js | 1 - playground/spa/src/App.tsx | 1 - playground/spa/vite.config.ts | 82 ++--- pnpm-lock.yaml | 309 +++--------------- src/helper/AbsCacheProcessor.ts | 51 ++- src/helper/FileCacheProcessor.ts | 27 +- src/helper/ManifestCache.ts | 82 ++++- src/helper/MemoryCacheProcessor.ts | 11 +- src/helper/build.ts | 30 +- src/helper/html.ts | 73 +++++ src/helper/processor.ts | 12 +- src/helper/utils.ts | 7 + src/index.ts | 110 +++++-- src/plugins/inject-script.ts | 28 ++ vitest.config.ts | 1 + 26 files changed, 591 insertions(+), 560 deletions(-) create mode 100644 __test__/basic.spec.todo.ts delete mode 100644 __test__/basic.spec.ts delete mode 100644 playground/spa/public/out/haha.bdaaba63.js delete mode 100644 playground/spa/public/out/index.cccf1b56.js delete mode 100644 playground/spa/public/out/test.40879d01.js create mode 100644 src/helper/html.ts create mode 100644 src/plugins/inject-script.ts diff --git a/.gitignore b/.gitignore index fa49873..3185bd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules dist -.idea \ No newline at end of file +.idea +.Ds_store diff --git a/README.md b/README.md index 14b5d44..ff7e7d4 100644 --- a/README.md +++ b/README.md @@ -4,51 +4,63 @@ **中文** | [English](./README.md) -**在vite的运行时或构建时打包指定目录下的typescript文件,供独立使用** +**在vite的运行时或构建时打包指定目录下的typescript文件,供开发者独立使用** > 如果你希望项目中所有脚本都使用typescript编写,那么你应该试试此插件 ## 应用场景 -- 独立的第三方脚本,如 `sentry`,`google analytics`,百度统计等 +- 独立的第三方脚本,如 `sentry`,`google analytics`,`百度统计` 等 - 希望在页面完全加载前就执行的脚本,如 `modern-flexible` 等 - 初始化全局函数 ## 功能 -- 运行时和构建时,把指定文件夹中的`typescript`文件编译为`javascript`,浏览器可直接使用 -- 输出带有`hash`的js文件,无需担心缓存 +- 运行时和构建时,把指定文件夹中的`typescript`文件编译为`javascript`,供浏览器直接使用 +- 输出带有 `hash` 的js文件,无需担心缓存 - 自定义编译选项,指定目标浏览器范围,无需担心兼容性 - 支持vite环境变量 -- 支持`HMR` +- 支持 `HMR` - 生产可用 -## Install +## 安装 ```bash pnpm add vite-plugin-public-typescript -D ``` -## Preview - - - ## 用法 ```typescript import { defineConfig } from 'vite' -import { publicTypescript } from 'vite-plugin-public-typescript' +import { publicTypescript, injectScripts } from 'vite-plugin-public-typescript' +import manifest from './public-typescript/manifest.json' export default defineConfig({ - plugins: [publicTypescript()], + plugins: [ + publicTypescript({ + inputDir: 'public-typescript', + manifestName: 'manifest', + hash: true, + outputDir: '/out', + destination: 'memory', + }), + injectScripts([ + { + attrs: { + src: manifest.script, + }, + injectTo: 'head', + }, + ]) + ] }) ``` ### SPA -在 `SPA` 应用中,我们可以通过 vite 的 `transformIndexHtml` hook 注入 script -你也可以使用 [`vite-plugin-html`](https://github.com/vbenjs/vite-plugin-html),这会使得注入更加简单 +在 `SPA` 应用中,我们可以通过 `injectScripts` 插件往 `index.html` 中注入 script 完整示例请参考:[spa playground](./playground/spa/vite.config.ts) @@ -57,30 +69,20 @@ export default defineConfig({ ```typescript import type { HtmlTagDescriptor } from 'vite' import { defineConfig } from 'vite' -import { publicTypescript } from 'vite-plugin-public-typescript' -import manifest from './publicTypescript/manifest.json' +import { publicTypescript, injectScripts } from 'vite-plugin-public-typescript' +import manifest from './public-typescript/manifest.json' export default defineConfig({ plugins: [ publicTypescript(), - { - name: 'add-script', - async transformIndexHtml(html) { - const tags: HtmlTagDescriptor[] = [ - { - tag: 'script', - attrs: { - src: manifest.spa, - }, - injectTo: 'head-prepend', - }, - ] - return { - html, - tags, - } - }, - }, + injectScripts([ + { + attrs: { + src: manifest.spa, + }, + injectTo: 'head-prepend', + } + ]) ], }) ``` @@ -109,7 +111,7 @@ export default defineConfig({ #### server.js ```js -import manifest from './publicTypescript/custom-manifest.json' assert { type: 'json' } +import manifest from './public-typescript/custom-manifest.json' assert { type: 'json' } const html = template // inject js diff --git a/__test__/basic.spec.todo.ts b/__test__/basic.spec.todo.ts new file mode 100644 index 0000000..34e6c3c --- /dev/null +++ b/__test__/basic.spec.todo.ts @@ -0,0 +1,119 @@ +// import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' +// import mock from 'mock-fs' +// import fs from 'fs-extra' +// import type { ResolvedConfig, ViteDevServer } from 'vite' +// import { createServer } from 'vite' +// import { ManifestCache } from '../src/helper/ManifestCache' +// import { eq, isEmptyObject } from '../src/helper/utils' +// import { publicTypescript } from '../src' + +// declare module 'vitest' { +// export interface TestContext { +// cache: ManifestCache +// vite: ResolvedConfig +// viteDevServer: ViteDevServer +// } +// } + +// const manifestPath = 'manifest.json' + +// vi.mock('fs-extra', async () => { +// const actual: any = await vi.importActual('fs-extra') +// return { +// readFileSync: vi.fn(), +// writeFile: vi.fn(), +// ...actual, +// } +// }) + +// function initCache() { +// const cache = new ManifestCache({ watchMode: false, write: false }) +// cache.set({ +// x: { +// path: 'x.js', +// _code: 'console.log("x")', +// }, +// y: { +// path: 'y.js', +// _code: 'console.log("y")', +// }, +// }) +// return cache +// } + +// async function createDevServer() { +// const server = await createServer({ +// define: { hahahaha: JSON.stringify('this is haha') }, +// plugins: [publicTypescript({ destination: 'file' })], +// server: { +// middlewareMode: true, +// port: 4000, +// host: '127.0.0.1', +// }, +// }) +// return server +// } + +// const globalServer = await createDevServer() + +// // beforeAll(() => { +// // vi.spyOn(fs, 'readFileSync').mockImplementation(() => { +// // return '{ "a": "/a.chunk.js" }' +// // }) +// // }) + +// beforeEach((ctx) => { +// ctx.cache = initCache() +// mock({ +// 'manifest.json': '{}', +// }) +// }) + +// beforeEach(async (ctx) => { +// ctx.vite = globalServer.config +// ctx.viteDevServer = globalServer +// }) + +// afterEach(async (ctx) => { +// mock.restore() +// await ctx.viteDevServer.close() +// }) + +// describe('manifestCache', () => { +// test('should set cache and get cache right', ({ cache }) => { +// expect(cache.getByKey('x')).toStrictEqual({ path: 'x.js', _code: 'console.log("x")' }) +// }) + +// test('should remove cache', ({ cache }) => { +// cache.remove('x') + +// expect(cache.getByKey('x')).toBeFalsy() +// }) + +// test('should get all', ({ cache }) => { +// const v = cache.get() +// expect(Object.keys(v).length === 2).toBe(true) +// }) + +// test('should set manifestPath', ({ cache }) => { +// cache.setManifestPath(manifestPath) +// expect(cache.getManifestPath()).toBe(manifestPath) +// }) + +// test('should write manifest', ({ cache }) => { +// cache.setManifestPath(manifestPath) + +// { +// const content = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) +// expect(isEmptyObject(content)).toBe(true) +// } + +// cache.writeManifestJSON() + +// { +// const content = fs.readFileSync(manifestPath, 'utf-8') +// const c = initCache() +// expect(eq(JSON.parse(content), c.extractPath(c.get()))).toBe(true) +// } +// }) +// }) diff --git a/__test__/basic.spec.ts b/__test__/basic.spec.ts deleted file mode 100644 index feea24f..0000000 --- a/__test__/basic.spec.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest' -import mock from 'mock-fs' -import fs from 'fs-extra' -import type { ResolvedConfig, ViteDevServer } from 'vite' -import { createServer } from 'vite' -import { ManifestCache } from '../src/helper/ManifestCache' -import { eq, isEmptyObject } from '../src/helper/utils' -import { publicTypescript } from '../src' - -declare module 'vitest' { - export interface TestContext { - cache: ManifestCache - vite: ResolvedConfig - viteDevServer: ViteDevServer - } -} - -const manifestPath = 'manifest.json' - -vi.mock('fs-extra', async () => { - const actual: any = await vi.importActual('fs-extra') - return { - readFileSync: vi.fn(), - writeFile: vi.fn(), - ...actual, - } -}) - -function initCache() { - const cache = new ManifestCache() - cache.set({ - x: { - path: 'x.js', - _code: 'console.log("x")', - }, - y: { - path: 'y.js', - _code: 'console.log("y")', - }, - }) - return cache -} - -async function createDevServer() { - const server = await createServer({ - define: { hahahaha: JSON.stringify('this is haha') }, - plugins: [publicTypescript()], - server: { - middlewareMode: true, - }, - }) - return server -} - -// beforeAll(() => { -// vi.spyOn(fs, 'readFileSync').mockImplementation(() => { -// return '{ "a": "/a.chunk.js" }' -// }) -// }) - -beforeEach((ctx) => { - ctx.cache = initCache() - mock({ - 'manifest.json': '{}', - }) -}) - -beforeEach(async (ctx) => { - const server = await createDevServer() - ctx.vite = server.config - ctx.viteDevServer = server -}) - -afterEach((ctx) => { - mock.restore() - ctx.viteDevServer.close() -}) - -describe('manifestCache', () => { - test('should set cache and get cache right', ({ cache }) => { - expect(cache.getByKey('x')).toStrictEqual({ path: 'x.js', _code: 'console.log("x")' }) - }) - - test('should remove cache', ({ cache }) => { - cache.remove('x') - - expect(cache.getByKey('x')).toBeFalsy() - }) - - test('should get all', ({ cache }) => { - const v = cache.get() - expect(Object.keys(v).length === 2).toBe(true) - }) - - test('should set manifestPath', ({ cache }) => { - cache.setManifestPath(manifestPath) - expect(cache.getManifestPath()).toBe(manifestPath) - }) - - test('should write manifest', async ({ cache }) => { - cache.setManifestPath(manifestPath) - - { - const content = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) - expect(isEmptyObject(content)).toBe(true) - } - - await cache.writeManifestJSON() - - { - const content = fs.readFileSync(manifestPath, 'utf-8') - const c = initCache() - expect(eq(JSON.parse(content), c.extractPath(c.get()))).toBe(true) - } - }) -}) diff --git a/package.json b/package.json index 7f57735..691350a 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,9 @@ "debug": "^4.3.4", "esbuild": "^0.19.2", "fs-extra": "^11.1.1", + "magic-string": "^0.30.3", "on-change": "^4.0.2", + "parse5": "^7.1.2", "sirv": "^2.0.3", "tiny-glob": "^0.2.9", "watcher": "^2.3.0" diff --git a/playground/spa/package.json b/playground/spa/package.json index a4dcc2e..1193d94 100644 --- a/playground/spa/package.json +++ b/playground/spa/package.json @@ -7,6 +7,7 @@ "dev": "vite", "debug": "cross-env DEBUG=vite-plugin-public-typescript* vite", "build": "vite build", + "debug:build": "cross-env DEBUG=vite-plugin-public-typescript* vite build", "preview": "vite preview" }, "dependencies": { @@ -20,7 +21,6 @@ "cross-env": "^7.0.3", "typescript": "^4.9.5", "vite": "4.4.9", - "vite-plugin-html": "^3.2.0", "vite-plugin-public-typescript": "workspace:*" } } diff --git a/playground/spa/public-typescript/index.ts b/playground/spa/public-typescript/index.ts index a4d5c8a..198ef78 100644 --- a/playground/spa/public-typescript/index.ts +++ b/playground/spa/public-typescript/index.ts @@ -1,3 +1 @@ -console.log(import.meta.env, 'env-') - -export {} +console.log(import.meta.env) diff --git a/playground/spa/public-typescript/manifest.json b/playground/spa/public-typescript/manifest.json index aa8f6c5..f562564 100644 --- a/playground/spa/public-typescript/manifest.json +++ b/playground/spa/public-typescript/manifest.json @@ -1,5 +1,5 @@ { "haha": "/out/haha.bdaaba63.js", - "index": "/out/index.cccf1b56.js", - "test": "/out/test.40879d01.js" + "index": "/out/index.a7db5a4b.js", + "test": "/out/test.e29e5748.js" } diff --git a/playground/spa/public-typescript/test.ts b/playground/spa/public-typescript/test.ts index 7d71fc8..4b2e663 100644 --- a/playground/spa/public-typescript/test.ts +++ b/playground/spa/public-typescript/test.ts @@ -1 +1 @@ -console.log('this is a') +console.log('test') diff --git a/playground/spa/public/out/haha.bdaaba63.js b/playground/spa/public/out/haha.bdaaba63.js deleted file mode 100644 index 351d836..0000000 --- a/playground/spa/public/out/haha.bdaaba63.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var o={hello:"world"};console.log("custom define!");console.log(o);})(); diff --git a/playground/spa/public/out/index.cccf1b56.js b/playground/spa/public/out/index.cccf1b56.js deleted file mode 100644 index ffa0174..0000000 --- a/playground/spa/public/out/index.cccf1b56.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var e={VITE_HAHAH:"hahaha",BASE_URL:"/",MODE:"development",DEV:!0,PROD:!1};console.log(e,"env-");})(); diff --git a/playground/spa/public/out/test.40879d01.js b/playground/spa/public/out/test.40879d01.js deleted file mode 100644 index 582b928..0000000 --- a/playground/spa/public/out/test.40879d01.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{console.log("this is a");})(); diff --git a/playground/spa/src/App.tsx b/playground/spa/src/App.tsx index 17a455c..77c4cb7 100644 --- a/playground/spa/src/App.tsx +++ b/playground/spa/src/App.tsx @@ -27,5 +27,4 @@ function App() { ) } -// eslint-disable-next-line no-restricted-syntax export default App diff --git a/playground/spa/vite.config.ts b/playground/spa/vite.config.ts index 5651f87..4563463 100644 --- a/playground/spa/vite.config.ts +++ b/playground/spa/vite.config.ts @@ -1,35 +1,11 @@ -import type { HtmlTagDescriptor, PluginOption } from 'vite' +import type { HtmlTagDescriptor } from 'vite' import { defineConfig } from 'vite' -import { publicTypescript } from 'vite-plugin-public-typescript' +import { injectScripts, publicTypescript } from 'vite-plugin-public-typescript' import react from '@vitejs/plugin-react' -import { createHtmlPlugin } from 'vite-plugin-html' import manifest from './public-typescript/manifest.json' -function setupHtml() { - const tags: Parameters[0] = { - minify: false, - inject: { - tags: [], - }, - } - - tags.inject?.tags?.push( - ...([ - { - tag: 'script', - attrs: { - src: manifest.index, - }, - injectTo: 'head-prepend', - }, - ] as HtmlTagDescriptor[]), - ) - const htmlPlugin: PluginOption[] = createHtmlPlugin(tags) - return htmlPlugin -} - // https://vitejs.dev/config/ -export default defineConfig({ +export default defineConfig((env) => ({ define: { haha: JSON.stringify('custom define!'), app: JSON.stringify({ hello: 'world' }), @@ -37,35 +13,47 @@ export default defineConfig({ plugins: [ react(), { - name: 'add-script', - transformIndexHtml: { - order: 'pre', - handler(html) { - const tags: HtmlTagDescriptor[] = [ - { - tag: 'script', - attrs: { - src: manifest.test, - }, - injectTo: 'head-prepend', + name: 'transform-demo', + async transformIndexHtml(html) { + const tags: HtmlTagDescriptor[] = [ + { + tag: 'script', + attrs: { + 'src': manifest.test, + 'data-vppt': 'true', }, - ] + injectTo: 'head-prepend', + }, + ] - return { - html, - tags, - } - }, + html = html.replace('Vite + React + TS', env.command === 'build' ? 'build' : 'serve') + + return { + html, + tags, + } }, }, - setupHtml(), publicTypescript({ inputDir: 'public-typescript', manifestName: 'manifest', hash: true, outputDir: '/out', - destination: 'file', }), + injectScripts([ + { + attrs: { + src: manifest.haha, + }, + injectTo: 'head', + }, + { + attrs: { + src: manifest.index, + }, + injectTo: 'head-prepend', + }, + ]), ], clearScreen: true, -}) +})) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1a4d14..72e245a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,9 +17,15 @@ importers: fs-extra: specifier: ^11.1.1 version: 11.1.1 + magic-string: + specifier: ^0.30.3 + version: 0.30.3 on-change: specifier: ^4.0.2 version: 4.0.2 + parse5: + specifier: ^7.1.2 + version: 7.1.2 sirv: specifier: ^2.0.3 version: 2.0.3 @@ -102,10 +108,7 @@ importers: version: 4.9.5 vite: specifier: 4.4.9 - version: 4.4.9(@types/node@20.6.0) - vite-plugin-html: - specifier: ^3.2.0 - version: 3.2.0(vite@4.4.9) + version: 4.4.9 vite-plugin-public-typescript: specifier: workspace:* version: link:../.. @@ -883,16 +886,8 @@ packages: engines: {node: '>=6.0.0'} dev: true - /@jridgewell/source-map@0.3.5: - resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} - dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 - dev: true - /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true /@jridgewell/trace-mapping@0.3.19: resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==} @@ -1151,14 +1146,6 @@ packages: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: false - /@rollup/pluginutils@4.2.1: - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: true - /@sigstore/bundle@1.1.0: resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -1498,7 +1485,7 @@ packages: '@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.22.17) '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.22.17) react-refresh: 0.14.0 - vite: 4.4.9(@types/node@20.6.0) + vite: 4.4.9 transitivePeerDependencies: - supports-color dev: true @@ -1757,10 +1744,6 @@ packages: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true - /async@3.2.4: - resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} - dev: true - /asynciterator.prototype@1.0.0: resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} dependencies: @@ -1836,10 +1819,6 @@ packages: update-browserslist-db: 1.0.11(browserslist@4.21.10) dev: true - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -1942,13 +1921,6 @@ packages: engines: {node: '>=6'} dev: true - /camel-case@4.1.2: - resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - dependencies: - pascal-case: 3.1.2 - tslib: 2.6.2 - dev: true - /caniuse-lite@1.0.30001534: resolution: {integrity: sha512-vlPVrhsCS7XaSh2VvWluIQEzVhefrUQcEsQWSS5A5V+dM07uv1qHeQzAOTGIMy9i3e9bH15+muvI/UHojVgS/Q==} dev: true @@ -2024,13 +1996,6 @@ packages: engines: {node: '>=8'} dev: true - /clean-css@5.3.2: - resolution: {integrity: sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==} - engines: {node: '>= 10.0'} - dependencies: - source-map: 0.6.1 - dev: true - /clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} @@ -2082,20 +2047,11 @@ packages: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} dev: true - /commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} dev: true - /commander@8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - dev: true - /compressible@2.0.18: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} engines: {node: '>= 0.6'} @@ -2122,15 +2078,6 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true - /connect-history-api-fallback@1.6.0: - resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} - engines: {node: '>=0.8'} - dev: true - - /consola@2.15.3: - resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} - dev: true - /console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} dev: true @@ -2177,21 +2124,6 @@ packages: which: 2.0.2 dev: true - /css-select@4.3.0: - resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 4.3.1 - domutils: 2.8.0 - nth-check: 2.1.1 - dev: true - - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - dev: true - /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -2321,14 +2253,6 @@ packages: esutils: 2.0.3 dev: true - /dom-serializer@1.4.1: - resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - entities: 2.2.0 - dev: true - /dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} dependencies: @@ -2341,13 +2265,6 @@ packages: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} dev: true - /domhandler@4.3.1: - resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} - engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - dev: true - /domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} @@ -2355,14 +2272,6 @@ packages: domelementtype: 2.3.0 dev: true - /domutils@2.8.0: - resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} - dependencies: - dom-serializer: 1.4.1 - domelementtype: 2.3.0 - domhandler: 4.3.1 - dev: true - /domutils@3.1.0: resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} dependencies: @@ -2371,18 +2280,6 @@ packages: domhandler: 5.0.3 dev: true - /dot-case@3.0.4: - resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} - dependencies: - no-case: 3.0.4 - tslib: 2.6.2 - dev: true - - /dotenv-expand@8.0.3: - resolution: {integrity: sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==} - engines: {node: '>=12'} - dev: true - /dotenv@16.3.1: resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} engines: {node: '>=12'} @@ -2396,14 +2293,6 @@ packages: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: false - /ejs@3.1.9: - resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==} - engines: {node: '>=0.10.0'} - hasBin: true - dependencies: - jake: 10.8.7 - dev: true - /electron-to-chromium@1.4.519: resolution: {integrity: sha512-kqs9oGYL4UFVkLKhqCTgBCYZv+wZ374yABDMqlDda9HvlkQxvSr7kgf4hfWVjMieDbX+1MwPHFBsOGCMIBaFKg==} dev: true @@ -2429,14 +2318,9 @@ packages: dev: true optional: true - /entities@2.2.0: - resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - dev: true - /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - dev: true /env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} @@ -3037,10 +2921,6 @@ packages: engines: {node: '>=4.0'} dev: true - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true - /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -3164,12 +3044,6 @@ packages: flat-cache: 3.1.0 dev: true - /filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - dependencies: - minimatch: 5.1.6 - dev: true - /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -3250,15 +3124,6 @@ packages: engines: {node: '>= 0.6'} dev: false - /fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.0 - dev: true - /fs-extra@11.1.1: resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} engines: {node: '>=14.14'} @@ -3529,11 +3394,6 @@ packages: dependencies: function-bind: 1.1.1 - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - dev: true - /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: true @@ -3545,20 +3405,6 @@ packages: lru-cache: 7.18.3 dev: true - /html-minifier-terser@6.1.0: - resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} - engines: {node: '>=12'} - hasBin: true - dependencies: - camel-case: 4.1.2 - clean-css: 5.3.2 - commander: 8.3.0 - he: 1.2.0 - param-case: 3.0.4 - relateurl: 0.2.7 - terser: 5.19.4 - dev: true - /htmlparser2@8.0.2: resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} dependencies: @@ -3934,17 +3780,6 @@ packages: '@pkgjs/parseargs': 0.11.0 dev: true - /jake@10.8.7: - resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==} - engines: {node: '>=10'} - hasBin: true - dependencies: - async: 3.2.4 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - dev: true - /jiti@1.20.0: resolution: {integrity: sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==} hasBin: true @@ -4036,6 +3871,7 @@ packages: universalify: 2.0.0 optionalDependencies: graceful-fs: 4.2.11 + dev: false /jsonparse@1.3.1: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} @@ -4128,12 +3964,6 @@ packages: get-func-name: 2.0.0 dev: true - /lower-case@2.0.2: - resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} - dependencies: - tslib: 2.6.2 - dev: true - /lru-cache@10.0.1: resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} engines: {node: 14 || >=16.14} @@ -4162,7 +3992,6 @@ packages: engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /make-fetch-happen@11.1.1: resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} @@ -4282,13 +4111,6 @@ packages: brace-expansion: 1.1.11 dev: true - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - /minimatch@9.0.3: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} @@ -4437,13 +4259,6 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} - /no-case@3.0.4: - resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - dependencies: - lower-case: 2.0.2 - tslib: 2.6.2 - dev: true - /node-fetch-native@1.4.0: resolution: {integrity: sha512-F5kfEj95kX8tkDhUCYdV8dg3/8Olx/94zB8+ZNthFs6Bz31UpUi8Xh40TN3thLwXgrwXry1pEg9lJ++tLWTcqA==} dev: true @@ -4468,13 +4283,6 @@ packages: - supports-color dev: true - /node-html-parser@5.4.2: - resolution: {integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==} - dependencies: - css-select: 4.3.0 - he: 1.2.0 - dev: true - /node-releases@2.0.13: resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} dev: true @@ -4804,13 +4612,6 @@ packages: - supports-color dev: true - /param-case@3.0.4: - resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} - dependencies: - dot-case: 3.0.4 - tslib: 2.6.2 - dev: true - /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -4839,18 +4640,17 @@ packages: lines-and-columns: 1.2.4 dev: true + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: false + /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} dev: false - /pascal-case@3.1.2: - resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} - dependencies: - no-case: 3.0.4 - tslib: 2.6.2 - dev: true - /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -4892,10 +4692,6 @@ packages: engines: {node: '>=8'} dev: true - /pathe@0.2.0: - resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} - dev: true - /pathe@1.1.1: resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} dev: true @@ -5201,11 +4997,6 @@ packages: jsesc: 0.5.0 dev: true - /relateurl@0.2.7: - resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} - engines: {node: '>= 0.10'} - dev: true - /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -5469,13 +5260,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -5712,17 +5496,6 @@ packages: - supports-color dev: true - /terser@5.19.4: - resolution: {integrity: sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.5 - acorn: 8.10.0 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true @@ -5815,10 +5588,6 @@ packages: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} dev: true - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: true - /tsup@7.2.0(typescript@5.2.2): resolution: {integrity: sha512-vDHlczXbgUvY3rWvqFEbSqmC1L7woozbzngMqTtL2PGBODTtWlRwGDDawhvWzr5c1QjKe4OAKqJGfE1xeXUvtQ==} engines: {node: '>=16.14'} @@ -6014,6 +5783,7 @@ packages: /universalify@2.0.0: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} + dev: false /unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} @@ -6087,24 +5857,39 @@ packages: - terser dev: true - /vite-plugin-html@3.2.0(vite@4.4.9): - resolution: {integrity: sha512-2VLCeDiHmV/BqqNn5h2V+4280KRgQzCFN47cst3WiNK848klESPQnzuC3okH5XHtgwHH/6s1Ho/YV6yIO0pgoQ==} + /vite@4.4.9: + resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true peerDependencies: - vite: '>=2.0.0' + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true dependencies: - '@rollup/pluginutils': 4.2.1 - colorette: 2.0.20 - connect-history-api-fallback: 1.6.0 - consola: 2.15.3 - dotenv: 16.3.1 - dotenv-expand: 8.0.3 - ejs: 3.1.9 - fast-glob: 3.3.1 - fs-extra: 10.1.0 - html-minifier-terser: 6.1.0 - node-html-parser: 5.4.2 - pathe: 0.2.0 - vite: 4.4.9(@types/node@20.6.0) + esbuild: 0.18.20 + postcss: 8.4.29 + rollup: 3.29.1 + optionalDependencies: + fsevents: 2.3.3 dev: true /vite@4.4.9(@types/node@18.17.15): diff --git a/src/helper/AbsCacheProcessor.ts b/src/helper/AbsCacheProcessor.ts index 7ec10cd..af639c7 100644 --- a/src/helper/AbsCacheProcessor.ts +++ b/src/helper/AbsCacheProcessor.ts @@ -1,28 +1,59 @@ import { normalizePath } from 'vite' -import type { TGlobalConfig } from './GlobalConfigBuilder' +import createDebug from 'debug' +import type { ManifestCache } from './ManifestCache' + +const debug = createDebug('vite-plugin-public-typescript:AbsCacheProcessor ===> ') + +export type BuildEndArgs = { + tsFileName: string + jsFileNameWithHash: string + code: string + contentHash: string +} export interface IDeleteFile { - fileName: string + tsFileName: string jsFileName?: string - force?: boolean + silent?: boolean } export interface IAddFile { code?: string - fileName: string + tsFileName: string contentHash: string } export abstract class AbsCacheProcessor { + cache: ManifestCache abstract deleteOldJs(args: IDeleteFile): Promise abstract addNewJs(args: IAddFile): Promise - setCache(args: IAddFile, globalConfig: TGlobalConfig) { - const { contentHash, code = '', fileName } = args - const { cache, outputDir } = globalConfig + + constructor(cache: ManifestCache) { + this.cache = cache + } + + async onTsBuildEnd(args: BuildEndArgs) { + const { tsFileName, jsFileNameWithHash, code, contentHash } = args + + debug('onTsBuildEnd:', args) + + await this.deleteOldJs({ tsFileName, jsFileName: jsFileNameWithHash, silent: true }) + + await this.addNewJs({ code, tsFileName, contentHash }) + } + + setCache( + args: IAddFile, + config: { + outputDir: string + }, + ) { + const { contentHash, code = '', tsFileName } = args + const { outputDir } = config function getOutputPath(p: string, hash?: string) { hash = hash ? `.${hash}` : '' - return normalizePath(`${p}/${fileName}${hash}.js`) + return normalizePath(`${p}/${tsFileName}${hash}.js`) } let outputPath = getOutputPath(outputDir) @@ -30,8 +61,8 @@ export abstract class AbsCacheProcessor { outputPath = getOutputPath(outputDir, contentHash) } - cache.set({ - [fileName]: { + this.cache.set({ + [tsFileName]: { path: outputPath, _code: code, _hash: contentHash, diff --git a/src/helper/FileCacheProcessor.ts b/src/helper/FileCacheProcessor.ts index 19bf5eb..fe193c0 100644 --- a/src/helper/FileCacheProcessor.ts +++ b/src/helper/FileCacheProcessor.ts @@ -8,14 +8,19 @@ import { globalConfigBuilder } from './GlobalConfigBuilder' import { AbsCacheProcessor } from './AbsCacheProcessor' import type { IAddFile, IDeleteFile } from './AbsCacheProcessor' import { writeFile } from './utils' +import type { ManifestCache } from './ManifestCache' const debug = createDebug('FileCacheProcessor ===> ') // file-based processor // the final output dir is base on `publicDir` export class FileCacheProcessor extends AbsCacheProcessor { + constructor(cache: ManifestCache) { + super(cache) + } + async deleteOldJs(args: IDeleteFile): Promise { - const { fileName, jsFileName = '', force = false } = args + const { tsFileName, jsFileName = '' } = args const { outputDir, @@ -27,7 +32,7 @@ export class FileCacheProcessor extends AbsCacheProcessor { try { fs.ensureDirSync(path.join(publicDir, outputDir)) - oldFiles = await glob(normalizePath(path.join(publicDir, `${outputDir}/${fileName}.?(*.)js`))) + oldFiles = await glob(normalizePath(path.join(publicDir, `${outputDir}/${tsFileName}.?(*.)js`))) } catch (e) { console.error(e) } @@ -45,18 +50,16 @@ export class FileCacheProcessor extends AbsCacheProcessor { continue } // skip repeat js file if (fs.existsSync(f)) { - debug('deleteOldJsFile - file exists:', f, fileName) - if (cache.getByKey(fileName) || force) { - cache.remove(fileName) - debug('deleteOldJsFile - cache removed:', fileName) - fs.remove(f) - debug('deleteOldJsFile -file removed:', f) - } + debug('deleteOldJsFile - file exists:', f, tsFileName) + cache.remove(tsFileName) + debug('deleteOldJsFile - cache removed:', tsFileName) + fs.remove(f) + debug('deleteOldJsFile -file removed:', f) } } - } else if (force) { - cache.remove(fileName) - debug('cache force removed:', fileName) + } else { + cache.remove(tsFileName) + debug('cache removed:', tsFileName) } } diff --git a/src/helper/ManifestCache.ts b/src/helper/ManifestCache.ts index d2f240a..98686af 100644 --- a/src/helper/ManifestCache.ts +++ b/src/helper/ManifestCache.ts @@ -7,8 +7,11 @@ import { eq, isEmptyObject, writeFile } from './utils' const debug = createDebug('vite-plugin-public-typescript:ManifestCache ===> ') +type PathOnlyCache = Record + export interface IManifestConstructor { watchMode?: boolean + write?: boolean onChange?: (path: string, value: ValueType, previousValue: ValueType, applyData: ApplyData) => void } @@ -32,17 +35,31 @@ export type TDefaultCache = { [fileName in string]: TCacheValue } +const DEFAULT_OPTIONS: IManifestConstructor = { + watchMode: true, + write: true, +} + export class ManifestCache { private cache: T private manifestPath = '' - constructor(options?: IManifestConstructor) { + private inited = false + + constructor(options?: IManifestConstructor) { + options = { + ...DEFAULT_OPTIONS, + ...options, + } + if (options?.watchMode) { - this.cache = onChange({} as T, async (...args) => { - options.onChange?.(...args) - await this.writeManifestJSON() + this.cache = onChange({} as T, (...args) => { debug('cache changed:', this.cache) + options!.onChange?.(...args) + if (options!.write) { + this.writeManifestJSON() + } }) } else { this.cache = Object.create(null) @@ -70,10 +87,15 @@ export class ManifestCache { return this.cache[k] } - remove(k: keyof T) { - if (this.cache[k]) { - delete this.cache[k] + remove(k: keyof T, opts?: { disableWatch?: boolean }) { + if (opts?.disableWatch) { + delete onChange.target(this.cache)[k] + } else { + if (this.cache[k]) { + delete this.cache[k] + } } + return this } @@ -82,6 +104,10 @@ export class ManifestCache { } readManifestFromFile() { + if (!fs.existsSync(this.getManifestPath())) { + return {} + } + const cacheJson = fs.readFileSync(this.getManifestPath(), 'utf-8') if (cacheJson) { return JSON.parse(cacheJson) @@ -92,6 +118,7 @@ export class ManifestCache { setManifestPath(p: string) { this.manifestPath = p + fs.ensureDirSync(path.dirname(p)) } getManifestPath() { @@ -100,19 +127,45 @@ export class ManifestCache { extractPath(c: T) { const cache = Object.assign({}, c) - const pathOnlyCache: Record = {} + const pathOnlyCache: PathOnlyCache = {} for (const key in cache) { pathOnlyCache[key] = cache[key].path } return pathOnlyCache } - async writeManifestJSON() { - const targetPath = this.getManifestPath() + recoverPath(c: PathOnlyCache) { + const cache = Object.assign({}, c) + const recoveredCache = {} as TDefaultCache + for (const key in cache) { + recoveredCache[key] = { + path: cache[key], + _code: '', + } + } + return recoveredCache as T + } + + getManifestJson() { + return this.extractPath(this.get()) + } - await fs.ensureDir(path.dirname(targetPath)) + initCacheFromFile() { + if (this.inited) return + this.inited = true - const cacheObj = this.extractPath(this.get()) + const parsedCache = this.readManifestFromFile() + + if (!isEmptyObject(parsedCache)) { + const cache = this.recoverPath(parsedCache) + this.set(cache, { disableWatch: true }) + } + } + + writeManifestJSON() { + const targetPath = this.getManifestPath() + + const cacheObj = this.getManifestJson() const orderdCache = Object.assign({}, cacheObj) const parsedCache = this.readManifestFromFile() @@ -121,7 +174,10 @@ export class ManifestCache { return } - debug('write manifest json:', JSON.stringify(orderdCache || {}, null, 2)) writeFile(targetPath, JSON.stringify(orderdCache || {}, null, 2)) + + debug('write manifest json:', JSON.stringify(orderdCache || {}, null, 2)) + + return orderdCache } } diff --git a/src/helper/MemoryCacheProcessor.ts b/src/helper/MemoryCacheProcessor.ts index d714140..716b62f 100644 --- a/src/helper/MemoryCacheProcessor.ts +++ b/src/helper/MemoryCacheProcessor.ts @@ -1,13 +1,16 @@ import { AbsCacheProcessor } from './AbsCacheProcessor' import type { IAddFile, IDeleteFile } from './AbsCacheProcessor' import { globalConfigBuilder } from './GlobalConfigBuilder' +import type { ManifestCache } from './ManifestCache' export class MemoryCacheProcessor extends AbsCacheProcessor { - async deleteOldJs(args: IDeleteFile): Promise { - const { fileName } = args - const { cache } = globalConfigBuilder.get() + constructor(cache: ManifestCache) { + super(cache) + } - cache.remove(fileName) + async deleteOldJs(args: IDeleteFile): Promise { + const { tsFileName, silent } = args + this.cache.remove(tsFileName, { disableWatch: silent }) } async addNewJs(args: IAddFile): Promise { diff --git a/src/helper/build.ts b/src/helper/build.ts index 8ef903a..4e386bb 100644 --- a/src/helper/build.ts +++ b/src/helper/build.ts @@ -7,6 +7,7 @@ import type { VPPTPluginOptions } from '..' import { name } from '../../package.json' import { globalConfigBuilder } from './GlobalConfigBuilder' import { getContentHash } from './utils' +import type { BuildEndArgs } from './AbsCacheProcessor' const debug = createDebug('vite-plugin-public-typescript:build ===> ') @@ -100,25 +101,38 @@ export async function esbuildTypescript(buildOptions: IBuildOptions) { return code } -export async function build(options: { filePath: string }) { +export async function build(options: { filePath: string }, onBuildEnd?: (args: BuildEndArgs) => Promise) { const { filePath } = options const globalConfig = globalConfigBuilder.get() - const fileName = path.basename(filePath, path.extname(filePath)) + const originFileName = path.basename(filePath, path.extname(filePath)) let contentHash = '' - let fileNameWithHash = fileName + let fileNameWithHash = originFileName - const code = await esbuildTypescript({ filePath, ...globalConfig }) + const code = (await esbuildTypescript({ filePath, ...globalConfig })) || '' if (globalConfig.hash) { contentHash = getContentHash(code, globalConfig.hash) - fileNameWithHash = `${fileName}.${contentHash}` + fileNameWithHash = `${originFileName}.${contentHash}` } - await globalConfig.cacheProcessor.deleteOldJs({ fileName, jsFileName: fileNameWithHash }) + debug('before onBuildEnd cache:', globalConfig.cache.get()) - await globalConfig.cacheProcessor.addNewJs({ code, fileName, contentHash }) + await onBuildEnd?.({ + tsFileName: originFileName, + jsFileNameWithHash: fileNameWithHash, + code, + contentHash, + }) - debug('cacheManifest:', globalConfig.cache.get()) + debug('after onBuildEnd cache:', globalConfig.cache.get()) +} + +export async function buildAll(tsFilesGlob: string[]) { + const { cacheProcessor } = globalConfigBuilder.get() + + for (const file of tsFilesGlob) { + await build({ filePath: file }, (args) => cacheProcessor.onTsBuildEnd(args)) + } } diff --git a/src/helper/html.ts b/src/helper/html.ts new file mode 100644 index 0000000..fcb3f91 --- /dev/null +++ b/src/helper/html.ts @@ -0,0 +1,73 @@ +import type { DefaultTreeAdapterMap, ParserError, Token } from 'parse5' + +export const VPPT_DATA_ATTR = 'data-vppt' + +export async function traverseHtml( + html: string, + filePath: string, + visitor: (node: DefaultTreeAdapterMap['node']) => void, +): Promise { + const { parse } = await import('parse5') + const ast = parse(html, { + scriptingEnabled: false, // parse inside