一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
128 行
4.0 KiB
TypeScript
128 行
4.0 KiB
TypeScript
// React Native WebView cannot load external JS files, however it can load
|
|
// arbitrary JS via the injectedJavaScript property. So we use this to load external
|
|
// files: First here we convert the JS file to a plain string, and that string
|
|
// is then loaded by eg. the Mermaid plugin, and finally injected in the WebView.
|
|
|
|
import { dirname, extname, basename, resolve } from 'path';
|
|
|
|
import * as esbuild from 'esbuild';
|
|
import copyAssets from './copyAssets';
|
|
import { writeFile, readFile } from 'fs-extra';
|
|
|
|
export default class BundledFile {
|
|
private readonly bundleOutputPathBase_: string;
|
|
private readonly bundleBaseName_: string;
|
|
private readonly rootFileDirectory_: string;
|
|
|
|
public constructor(
|
|
public readonly bundleName: string,
|
|
private readonly sourceFilePath_: string,
|
|
) {
|
|
this.rootFileDirectory_ = dirname(sourceFilePath_);
|
|
this.bundleBaseName_ = basename(sourceFilePath_, extname(sourceFilePath_));
|
|
this.bundleOutputPathBase_ = `${this.rootFileDirectory_}/${this.bundleBaseName_}.bundle`;
|
|
}
|
|
|
|
private makeBuildContext(mode: 'production' | 'development') {
|
|
return esbuild.context({
|
|
entryPoints: [this.sourceFilePath_],
|
|
outfile: `${this.bundleOutputPathBase_}.js`,
|
|
minify: mode === 'production',
|
|
bundle: true,
|
|
sourcemap: true,
|
|
format: 'iife',
|
|
globalName: this.bundleName,
|
|
metafile: false,
|
|
|
|
// es5: Have Webpack's generated code target ES5. This doesn't apply to code not
|
|
// generated by Webpack.
|
|
target: ['chrome58', 'safari14'],
|
|
|
|
plugins: [
|
|
{
|
|
name: 'joplin--node-polyfills',
|
|
setup: build => {
|
|
build.onResolve({ filter: /^(path|events)$/ }, args => {
|
|
let path = args.path;
|
|
if (args.path === 'path') {
|
|
path = require.resolve('path-browserify');
|
|
} else if (args.path === 'events') {
|
|
path = require.resolve('events/');
|
|
}
|
|
|
|
return { path };
|
|
});
|
|
},
|
|
},
|
|
{
|
|
// Supports require(...)ing SVG images
|
|
name: 'joplin--require-svg',
|
|
setup: build => {
|
|
// A relative path to an SVG:
|
|
build.onResolve({ filter: /^\.{1,2}\/.*\.svg$/ }, args => ({
|
|
path: resolve(args.resolveDir, args.path),
|
|
namespace: 'joplin-require-svg',
|
|
}));
|
|
|
|
build.onLoad({ filter: /^.*$/, namespace: 'joplin-require-svg' }, async args => {
|
|
const fileContent = await readFile(args.path, 'utf-8');
|
|
return { contents: `
|
|
let svg = null;
|
|
export default () => {
|
|
svg ??= (() => {
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(${JSON.stringify(fileContent)}, 'image/svg+xml');
|
|
return doc.querySelector('svg');
|
|
})();
|
|
return svg.cloneNode(true);
|
|
};
|
|
` };
|
|
});
|
|
},
|
|
},
|
|
{
|
|
name: 'joplin--copy-final',
|
|
setup: build => {
|
|
build.onEnd(async (result) => {
|
|
if (result.errors.length === 0) {
|
|
console.log('copy output');
|
|
await this.copyToImportableFile_();
|
|
} else {
|
|
console.warn('Copying skipped. Build produced errors');
|
|
}
|
|
});
|
|
},
|
|
},
|
|
],
|
|
});
|
|
}
|
|
|
|
// Creates a file that can be imported by React native. This file contains the
|
|
// bundled JS as a string.
|
|
private async copyToImportableFile_() {
|
|
await copyAssets(`${this.bundleName}.bundle`, {
|
|
js: `${this.bundleOutputPathBase_}.js`,
|
|
css: `${this.bundleOutputPathBase_}.css`,
|
|
});
|
|
}
|
|
|
|
// Create a minified JS file in the same directory as `this.sourceFilePath` with
|
|
// the same name.
|
|
public async build() {
|
|
console.info(`Building bundle: ${this.bundleName}...`);
|
|
const compiler = await this.makeBuildContext('production');
|
|
const result = await compiler.rebuild();
|
|
await compiler.dispose();
|
|
|
|
if (result?.metafile) {
|
|
await writeFile(`${this.bundleOutputPathBase_}.meta.json`, JSON.stringify(result.metafile, undefined, '\t'));
|
|
}
|
|
}
|
|
|
|
public async startWatching() {
|
|
console.info(`Watching bundle: ${this.bundleName}...`);
|
|
const compiler = await this.makeBuildContext('development');
|
|
await compiler.watch();
|
|
}
|
|
}
|