From 571b8dd575efa97fc4312a32b2a72e813b26246c Mon Sep 17 00:00:00 2001 From: KoloMl Date: Wed, 8 May 2024 01:47:35 +0400 Subject: [PATCH] Reworking post-svelte build process for the extension --- .vite/lib/content-scripts.js | 125 ++++++++++++++++++++++++++++++ .vite/lib/index-file.js | 46 +++++++++++ .vite/lib/manifest.js | 103 +++++++++++++++++++++++++ .vite/pack-extension.js | 65 ++++++++++++++++ build-extension.js | 11 +++ package.json | 2 +- vite.config.extension.js | 145 ----------------------------------- 7 files changed, 351 insertions(+), 146 deletions(-) create mode 100644 .vite/lib/content-scripts.js create mode 100644 .vite/lib/index-file.js create mode 100644 .vite/lib/manifest.js create mode 100644 .vite/pack-extension.js create mode 100644 build-extension.js delete mode 100644 vite.config.extension.js diff --git a/.vite/lib/content-scripts.js b/.vite/lib/content-scripts.js new file mode 100644 index 0000000..aad275e --- /dev/null +++ b/.vite/lib/content-scripts.js @@ -0,0 +1,125 @@ +import {build} from "vite"; +import {createHash} from "crypto"; +import path from "path"; +import fs from "fs"; + +/** + * Create the result base file name for the file. + * @param {string} inputPath Path to the original filename. + * @return {string} Result base file name without extension. Contains original filename + hash suffix. + */ +function createOutputBaseName(inputPath) { + const hashSuffix = createHash('sha256') + .update( + // Yes, suffix is only dependent on the entry file, dependencies are not included. + fs.readFileSync(inputPath, 'utf8') + ) + .digest('base64url') + .substring(0, 8); + + const baseName = path.basename(inputPath, path.extname(inputPath)); + + return `${baseName}-${hashSuffix}`; +} + +/** + * Small workaround plugin to cover each individual content script into IIFE. This is pretty much mandatory to use, + * otherwise helper functions made by Vite will collide with each other. Only include this plugin into config with + * script! + * @return {import('vite').Plugin} + */ +function wrapScriptIntoIIFE() { + return { + name: 'wrap-scripts-into-iife', + generateBundle(outputBundles, bundle) { + Object.keys(bundle).forEach(fileName => { + const file = bundle[fileName]; + + file.code = `(() => {\n${file.code}})();` + }); + } + } +} + +/** + * Default aliases used inside popup app. + * @param {string} rootDir Root directory of the repo for building paths. + * @return {Record} Aliases to include into the config object. + */ +function makeAliases(rootDir) { + return { + "$lib": path.resolve(rootDir, 'src/lib'), + "$entities": path.resolve(rootDir, 'src/lib/extension/entities'), + "$styles": path.resolve(rootDir, 'src/styles'), + } +} + +/** + * Build the selected script separately. + * @param {AssetBuildOptions} buildOptions Building options for the script. + * @return {Promise} Result file path. + */ +export async function buildScript(buildOptions) { + const outputBaseName = createOutputBaseName(buildOptions.input); + + await build({ + configFile: false, + publicDir: false, + build: { + rollupOptions: { + input: { + [outputBaseName]: buildOptions.input + }, + output: { + dir: buildOptions.outputDir, + entryFileNames: '[name].js' + } + }, + emptyOutDir: false, + }, + resolve: { + alias: makeAliases(buildOptions.rootDir) + }, + plugins: [ + wrapScriptIntoIIFE() + ] + }); + + return path.resolve(buildOptions.outputDir, `${outputBaseName}.js`); +} + +/** + * Build the selected stylesheet. + * @param {AssetBuildOptions} buildOptions Build options for the stylesheet. + * @return {Promise} Result file path. + */ +export async function buildStyle(buildOptions) { + const outputBaseName = createOutputBaseName(buildOptions.input); + + await build({ + configFile: false, + publicDir: false, + build: { + rollupOptions: { + input: { + [outputBaseName]: buildOptions.input + }, + output: { + dir: buildOptions.outputDir, + entryFileNames: '[name].js', + assetFileNames: '[name].[ext]', + } + }, + emptyOutDir: false, + } + }); + + return path.resolve(buildOptions.outputDir, `${outputBaseName}.css`); +} + +/** + * @typedef {Object} AssetBuildOptions + * @property {string} input Full path to the input file to build. + * @property {string} outputDir Destination folder for the script. + * @property {string} rootDir Root directory of the repository. + */ diff --git a/.vite/lib/index-file.js b/.vite/lib/index-file.js new file mode 100644 index 0000000..f422516 --- /dev/null +++ b/.vite/lib/index-file.js @@ -0,0 +1,46 @@ +import fs from "fs"; +import {createHash} from "crypto"; +import {load} from "cheerio"; +import path from "path"; + +/** + * Find and extract all inline scripts injected into index file by the SvelteKit builder. This needs to be done due to + * ManifestV3 restrictions on inline/loaded scripts usage. The only way to run scripts in popup is by specifying + * `