mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-12 02:29:59 +00:00
Add esbuild plugin for static file copying with file watching
This commit is contained in:
@@ -1,11 +1,15 @@
|
|||||||
|
// @ts-check
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const esbuild = require("esbuild");
|
|
||||||
const fs = require("fs-extra");
|
const fs = require("fs-extra");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
|
const esbuild = require("esbuild");
|
||||||
const minimist = require("minimist");
|
const minimist = require("minimist");
|
||||||
const webExt = require("web-ext");
|
const webExt = require("web-ext");
|
||||||
|
|
||||||
|
const { copyFilesPlugin } = require("./lib/copyFilesPlugin.js");
|
||||||
|
|
||||||
const BRIDGE_NAME = "fx_cast_bridge";
|
const BRIDGE_NAME = "fx_cast_bridge";
|
||||||
const BRIDGE_VERSION = "0.2.0";
|
const BRIDGE_VERSION = "0.2.0";
|
||||||
|
|
||||||
@@ -71,25 +75,34 @@ const buildOpts = {
|
|||||||
|
|
||||||
entryPoints: [
|
entryPoints: [
|
||||||
// Main
|
// Main
|
||||||
`${srcPath}/background/background.ts`,
|
path.join(srcPath, "background/background.ts"),
|
||||||
// Cast
|
// Cast
|
||||||
`${srcPath}/cast/index.ts`,
|
path.join(srcPath, "cast/index.ts"),
|
||||||
`${srcPath}/cast/content.ts`,
|
path.join(srcPath, "cast/content.ts"),
|
||||||
`${srcPath}/cast/contentBridge.ts`,
|
path.join(srcPath, "cast/contentBridge.ts"),
|
||||||
// Media sender
|
// Media sender
|
||||||
`${srcPath}/cast/senders/media/index.ts`,
|
path.join(srcPath, "cast/senders/media/index.ts"),
|
||||||
// Mirroring sender
|
// Mirroring sender
|
||||||
`${srcPath}/cast/senders/mirroring.ts`,
|
path.join(srcPath, "/cast/senders/mirroring.ts"),
|
||||||
// UI
|
// UI
|
||||||
`${srcPath}/ui/popup/index.tsx`,
|
path.join(srcPath, "ui/popup/index.tsx"),
|
||||||
`${srcPath}/ui/options/index.tsx`
|
path.join(srcPath, "ui/options/index.tsx")
|
||||||
],
|
],
|
||||||
define: {
|
define: {
|
||||||
BRIDGE_NAME: `"${BRIDGE_NAME}"`,
|
BRIDGE_NAME: `"${BRIDGE_NAME}"`,
|
||||||
BRIDGE_VERSION: `"${BRIDGE_VERSION}"`,
|
BRIDGE_VERSION: `"${BRIDGE_VERSION}"`,
|
||||||
MIRRORING_APP_ID: `"${argv.mirroringAppId}"`
|
MIRRORING_APP_ID: `"${argv.mirroringAppId}"`
|
||||||
},
|
},
|
||||||
plugins: [preactCompatPlugin]
|
plugins: [
|
||||||
|
preactCompatPlugin,
|
||||||
|
|
||||||
|
// Copy static files
|
||||||
|
copyFilesPlugin({
|
||||||
|
src: srcPath,
|
||||||
|
dest: outPath,
|
||||||
|
excludePattern: /^(manifest\.json|.*\.(ts|tsx|js|jsx))$/
|
||||||
|
})
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set production options
|
// Set production options
|
||||||
@@ -119,34 +132,6 @@ function onBuildResult(result) {
|
|||||||
: "script-src 'self' 'unsafe-eval'; object-src 'self'";
|
: "script-src 'self' 'unsafe-eval'; object-src 'self'";
|
||||||
|
|
||||||
fs.writeFileSync(`${outPath}/manifest.json`, JSON.stringify(manifest));
|
fs.writeFileSync(`${outPath}/manifest.json`, JSON.stringify(manifest));
|
||||||
|
|
||||||
copy(srcPath, outPath, /^(manifest\.json|.*\.(ts|tsx|js|jsx))$/);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively copy directory contents.
|
|
||||||
*
|
|
||||||
* @param {string} src Source path
|
|
||||||
* @param {string} dest Destination path
|
|
||||||
* @param {RegExp} excludeRegex Match for file exclusion
|
|
||||||
*/
|
|
||||||
function copy(src, dest, excludeRegex) {
|
|
||||||
if (!fs.existsSync(src)) return;
|
|
||||||
|
|
||||||
const stats = fs.statSync(src);
|
|
||||||
if (!stats.isDirectory()) {
|
|
||||||
const dirName = path.dirname(dest);
|
|
||||||
if (!fs.existsSync(dirName)) {
|
|
||||||
fs.mkdirSync(dirName, { recursive: true });
|
|
||||||
}
|
|
||||||
fs.copyFileSync(src, dest);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const file of fs.readdirSync(src)) {
|
|
||||||
if (excludeRegex.test(file)) continue;
|
|
||||||
copy(path.join(src, file), path.join(dest, file), excludeRegex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean
|
// Clean
|
||||||
|
|||||||
124
ext/bin/lib/copyFilesPlugin.js
Normal file
124
ext/bin/lib/copyFilesPlugin.js
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
// @ts-check
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const esbuild = require("esbuild");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape meta characters in a regular expression.
|
||||||
|
*
|
||||||
|
* @param {string} patternSource
|
||||||
|
* @returns {string} Escaped expression source
|
||||||
|
*/
|
||||||
|
function escapeRegExp(patternSource) {
|
||||||
|
let metaChars = ".+*?()|[]{}^$\\";
|
||||||
|
return [...patternSource]
|
||||||
|
.map(c => (metaChars.includes(c) ? `\\${c}` : c))
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} CopyFilesPluginOpts
|
||||||
|
* @prop {string} src Source path
|
||||||
|
* @prop {string} dest Destination path
|
||||||
|
* @prop {RegExp=} excludePattern Exclude path pattern
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Plugin that copies files from specified source to destination after
|
||||||
|
* each build.
|
||||||
|
*
|
||||||
|
* @type {(opts: CopyFilesPluginOpts) => esbuild.Plugin}
|
||||||
|
*/
|
||||||
|
exports.copyFilesPlugin = opts => {
|
||||||
|
// Get matching file paths
|
||||||
|
const matchingFiles = (function getMatchingPaths(relPath = "") {
|
||||||
|
const fullPath = path.join(opts.src, relPath);
|
||||||
|
|
||||||
|
// Must exist
|
||||||
|
if (!fs.existsSync(fullPath)) return;
|
||||||
|
// Must not match exclude pattern
|
||||||
|
if (opts.excludePattern?.test(fullPath)) return;
|
||||||
|
|
||||||
|
if (fs.statSync(fullPath).isFile()) {
|
||||||
|
return [relPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type string[] */
|
||||||
|
let files = [];
|
||||||
|
for (const entry of fs.readdirSync(fullPath)) {
|
||||||
|
const matchingFiles = getMatchingPaths(path.join(relPath, entry));
|
||||||
|
if (matchingFiles) {
|
||||||
|
files = files.concat(matchingFiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
})();
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: "copy-files",
|
||||||
|
setup(build) {
|
||||||
|
/** First run for the set of import paths in each build. */
|
||||||
|
let isFirstRun = true;
|
||||||
|
|
||||||
|
build.onResolve(
|
||||||
|
{
|
||||||
|
filter: new RegExp(`^${escapeRegExp(opts.src + path.sep)}`)
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
/**
|
||||||
|
* Attach watch files to first resolve result.
|
||||||
|
* Presumably there is a much better way of doing
|
||||||
|
* this?
|
||||||
|
*/
|
||||||
|
if (isFirstRun) {
|
||||||
|
isFirstRun = false;
|
||||||
|
return {
|
||||||
|
watchFiles: matchingFiles.map(file =>
|
||||||
|
path.join(opts.src, file)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
build.onEnd(() => {
|
||||||
|
isFirstRun = true;
|
||||||
|
|
||||||
|
// Copy any watched files that changed
|
||||||
|
for (const file of matchingFiles) {
|
||||||
|
const srcPath = path.join(opts.src, file);
|
||||||
|
const destPath = path.join(opts.dest, file);
|
||||||
|
|
||||||
|
// Ignore if source file is missing
|
||||||
|
if (!fs.existsSync(srcPath)) {
|
||||||
|
if (fs.existsSync(destPath)) {
|
||||||
|
fs.rmSync(destPath);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure containing destination directory exists
|
||||||
|
const dirName = path.dirname(destPath);
|
||||||
|
if (!fs.existsSync(dirName)) {
|
||||||
|
fs.mkdirSync(dirName, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if files match
|
||||||
|
if (fs.existsSync(destPath)) {
|
||||||
|
const srcContent = fs.readFileSync(srcPath);
|
||||||
|
const destContent = fs.readFileSync(destPath);
|
||||||
|
|
||||||
|
if (srcContent.equals(destContent)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.copyFileSync(srcPath, destPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user