3.5 KB121 lines
Blame
1import { resolve } from 'path';
2import { fileURLToPath } from 'url';
3import type { BuildOptions } from 'esbuild';
4import { readFileSync } from 'fs';
5import jsonSchemaPlugin from './jsonSchemaPlugin.js';
6import type { PackageOptions } from '../.build/common.js';
7import { jisonPlugin } from './jisonPlugin.js';
8
9const __dirname = fileURLToPath(new URL('.', import.meta.url));
10
11export interface MermaidBuildOptions extends BuildOptions {
12 minify: boolean;
13 core: boolean;
14 metafile: boolean;
15 format: 'esm' | 'iife';
16 options: PackageOptions;
17 includeLargeFeatures: boolean;
18}
19
20export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = {
21 minify: false,
22 metafile: false,
23 core: false,
24 format: 'esm',
25 includeLargeFeatures: true,
26} as const;
27
28const buildOptions = (override: BuildOptions): BuildOptions => {
29 return {
30 bundle: true,
31 minify: true,
32 keepNames: true,
33 platform: 'browser',
34 tsconfig: 'tsconfig.json',
35 resolveExtensions: ['.ts', '.js', '.json', '.jison', '.yaml'],
36 external: ['require', 'fs', 'path'],
37 outdir: 'dist',
38 plugins: [jisonPlugin, jsonSchemaPlugin],
39 sourcemap: 'external',
40 ...override,
41 };
42};
43
44const getFileName = (
45 fileName: string,
46 { core, format, minify, includeLargeFeatures }: MermaidBuildOptions
47) => {
48 if (core) {
49 fileName += '.core';
50 } else if (format === 'esm') {
51 fileName += '.esm';
52 }
53 if (!includeLargeFeatures) {
54 fileName += '.tiny';
55 }
56 if (minify) {
57 fileName += '.min';
58 }
59 return fileName;
60};
61
62export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
63 const {
64 core,
65 format,
66 options: { name, file, packageName },
67 globalName = 'mermaid',
68 includeLargeFeatures,
69 ...rest
70 } = options;
71
72 const external: string[] = ['require', 'fs', 'path'];
73 const outFileName = getFileName(name, options);
74 const { dependencies, version } = JSON.parse(
75 readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
76 );
77 const output: BuildOptions = buildOptions({
78 ...rest,
79 absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
80 entryPoints: {
81 [outFileName]: `src/${file}`,
82 },
83 globalName,
84 logLevel: 'info',
85 chunkNames: `chunks/${outFileName}/[name]-[hash]`,
86 define: {
87 // This needs to be stringified for esbuild
88 'injected.includeLargeFeatures': `${includeLargeFeatures}`,
89 'injected.version': `'${version}'`,
90 'import.meta.vitest': 'undefined',
91 },
92 });
93
94 if (core) {
95 // Core build is used to generate file without bundled dependencies.
96 // This is used by downstream projects to bundle dependencies themselves.
97 // Ignore dependencies and any dependencies of dependencies
98 external.push(...Object.keys(dependencies));
99 output.external = external;
100 }
101
102 if (format === 'iife') {
103 output.format = 'iife';
104 output.splitting = false;
105 const originalGlobalName = output.globalName ?? 'mermaid';
106 output.globalName = `__esbuild_esm_mermaid_nm[${JSON.stringify(originalGlobalName)}]`;
107 // Workaround for removing the .default access in esbuild IIFE.
108 // https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396
109 output.footer = {
110 js: `globalThis[${JSON.stringify(originalGlobalName)}] = globalThis.${output.globalName}.default;`,
111 };
112 output.outExtension = { '.js': '.js' };
113 } else {
114 output.format = 'esm';
115 output.splitting = true;
116 output.outExtension = { '.js': '.mjs' };
117 }
118
119 return output;
120};
121