diff --git a/.esbuild/esbuild.cjs b/.esbuild/esbuild.cjs
index e38951bdb..393dadcf3 100644
--- a/.esbuild/esbuild.cjs
+++ b/.esbuild/esbuild.cjs
@@ -13,8 +13,8 @@ build(iifeBuild({ minify: false, watch })).catch(handler);
build(esmBuild({ minify: false, watch })).catch(handler);
// mermaid.min.js
-build(esmBuild()).catch(handler);
-// mermaid.esm.min.mjs
build(iifeBuild()).catch(handler);
+// mermaid.esm.min.mjs
+build(esmBuild()).catch(handler);
// mermaid.core.mjs (node_modules unbundled)
build(esmCoreBuild()).catch(handler);
diff --git a/.esbuild/jisonTransformer.cjs b/.esbuild/jisonTransformer.cjs
new file mode 100644
index 000000000..5f89c6647
--- /dev/null
+++ b/.esbuild/jisonTransformer.cjs
@@ -0,0 +1,14 @@
+const { Generator } = require('jison');
+exports.transformJison = (src) => {
+ const parser = new Generator(src, {
+ moduleType: 'js',
+ 'token-stack': true,
+ });
+ const source = parser.generate({ moduleMain: '() => {}' });
+ const exporter = `
+ parser.parser = parser;
+ export { parser };
+ export default parser;
+ `;
+ return `${source} ${exporter}`;
+};
diff --git a/.esbuild/serve.cjs b/.esbuild/serve.cjs
index c54ff1e9f..4c06572f3 100644
--- a/.esbuild/serve.cjs
+++ b/.esbuild/serve.cjs
@@ -1,53 +1,79 @@
const esbuild = require('esbuild');
const http = require('http');
-const path = require('path');
-const { iifeBuild } = require('./util.cjs');
+const { iifeBuild, esmBuild } = require('./util.cjs');
+const express = require('express');
-// Start esbuild's server on a random local port
-esbuild
- .serve(
- {
- servedir: path.join(__dirname, '..'),
+// Start 2 esbuild servers. One for IIFE and one for ESM
+// Serve 2 static directories: demo & cypress/platform
+// Have 3 entry points:
+// mermaid: './src/mermaid',
+// e2e: './cypress/platform/viewer.js',
+// 'bundle-test': './cypress/platform/bundle-test.js',
+
+const getEntryPointsAndExtensions = (format) => {
+ return {
+ entryPoints: {
+ mermaid: './src/mermaid',
+ e2e: 'cypress/platform/viewer.js',
+ 'bundle-test': 'cypress/platform/bundle-test.js',
},
- iifeBuild({ minify: false })
- )
- .then((result) => {
- // The result tells us where esbuild's local server is
- const { host, port } = result;
+ outExtension: { '.js': format === 'iife' ? '.js' : '.esm.mjs' },
+ };
+};
- // Then start a proxy server on port 3000
- http
- .createServer((req, res) => {
- if (req.url.includes('mermaid.js')) {
- req.url = '/dist/mermaid.js';
+const generateHandler = (server) => {
+ return (req, res) => {
+ const options = {
+ hostname: server.host,
+ port: server.port,
+ path: req.url,
+ method: req.method,
+ headers: req.headers,
+ };
+ // Forward each incoming request to esbuild
+ const proxyReq = http.request(options, (proxyRes) => {
+ // If esbuild returns "not found", send a custom 404 page
+ if (proxyRes.statusCode === 404) {
+ if (!req.url.endsWith('.html')) {
+ res.writeHead(404, { 'Content-Type': 'text/html' });
+ res.end('
A custom 404 page
');
+ return;
}
- const options = {
- hostname: host,
- port: port,
- path: req.url,
- method: req.method,
- headers: req.headers,
- };
+ }
+ // Otherwise, forward the response from esbuild to the client
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
+ proxyRes.pipe(res, { end: true });
+ });
+ // Forward the body of the request to esbuild
+ req.pipe(proxyReq, { end: true });
+ };
+};
- // Forward each incoming request to esbuild
- const proxyReq = http.request(options, (proxyRes) => {
- // If esbuild returns "not found", send a custom 404 page
- console.error('pp', req.url);
- if (proxyRes.statusCode === 404) {
- if (!req.url.endsWith('.html')) {
- res.writeHead(404, { 'Content-Type': 'text/html' });
- res.end('A custom 404 page
');
- return;
- }
- }
+(async () => {
+ const iifeServer = await esbuild.serve(
+ {},
+ {
+ ...iifeBuild({ minify: false, outfile: undefined, outdir: 'dist' }),
+ ...getEntryPointsAndExtensions('iife'),
+ }
+ );
+ const esmServer = await esbuild.serve(
+ {},
+ {
+ ...esmBuild({ minify: false, outfile: undefined, outdir: 'dist' }),
+ ...getEntryPointsAndExtensions('esm'),
+ }
+ );
+ const app = express();
- // Otherwise, forward the response from esbuild to the client
- res.writeHead(proxyRes.statusCode, proxyRes.headers);
- proxyRes.pipe(res, { end: true });
- });
+ app.use(express.static('demos'));
+ app.use(express.static('cypress/platform'));
+ app.all('/mermaid.js', generateHandler(iifeServer));
+ app.all('/mermaid.esm.mjs', generateHandler(esmServer));
- // Forward the body of the request to esbuild
- req.pipe(proxyReq, { end: true });
- })
- .listen(3000);
+ app.all('/e2e.esm.mjs', generateHandler(esmServer));
+ app.all('/bundle-test.esm.mjs', generateHandler(esmServer));
+ app.listen(9000, () => {
+ console.log(`Listening on http://localhost:9000`);
});
+})();
diff --git a/.esbuild/util.cjs b/.esbuild/util.cjs
index 0cddb7e45..4dbcd01c3 100644
--- a/.esbuild/util.cjs
+++ b/.esbuild/util.cjs
@@ -1,4 +1,4 @@
-const { Generator } = require('jison');
+const { transformJison } = require('./jisonTransformer.cjs');
const fs = require('fs');
const { dependencies } = require('../package.json');
@@ -17,21 +17,16 @@ const buildOptions = (override = {}) => {
globalName: 'mermaid',
platform: 'browser',
tsconfig: 'tsconfig.json',
- resolveExtensions: ['.ts', '.js', '.json', '.jison'],
+ resolveExtensions: ['.ts', '.js', '.mjs', '.json', '.jison'],
external: ['require', 'fs', 'path'],
- outdir: 'dist',
+ entryPoints: ['src/mermaid.ts'],
+ outfile: 'dist/mermaid.min.js',
plugins: [jisonPlugin],
sourcemap: 'external',
...override,
};
};
-const getOutFiles = (extension) => {
- return {
- [`mermaid${extension}`]: 'src/mermaid.ts',
- [`diagramAPI${extension}`]: 'src/diagram-api/diagramAPI.ts',
- };
-};
/**
* Build options for mermaid.esm.* build.
*
@@ -43,8 +38,7 @@ const getOutFiles = (extension) => {
exports.esmBuild = (override = { minify: true }) => {
return buildOptions({
format: 'esm',
- entryPoints: getOutFiles(`.esm${override.minify ? '.min' : ''}`),
- outExtension: { '.js': '.mjs' },
+ outfile: `dist/mermaid.esm${override.minify ? '.min' : ''}.mjs`,
...override,
});
};
@@ -61,8 +55,7 @@ exports.esmBuild = (override = { minify: true }) => {
exports.esmCoreBuild = (override) => {
return buildOptions({
format: 'esm',
- entryPoints: getOutFiles(`.core`),
- outExtension: { '.js': '.mjs' },
+ outfile: `dist/mermaid.core.mjs`,
external: ['require', 'fs', 'path', ...Object.keys(dependencies)],
platform: 'neutral',
...override,
@@ -79,8 +72,11 @@ exports.esmCoreBuild = (override) => {
*/
exports.iifeBuild = (override = { minify: true }) => {
return buildOptions({
- entryPoints: getOutFiles(override.minify ? '.min' : ''),
+ outfile: `dist/mermaid${override.minify ? '.min' : ''}.js`,
format: 'iife',
+ footer: {
+ js: 'mermaid = mermaid.default;',
+ },
...override,
});
};
@@ -91,9 +87,7 @@ const jisonPlugin = {
build.onLoad({ filter: /\.jison$/ }, async (args) => {
// Load the file from the file system
const source = await fs.promises.readFile(args.path, 'utf8');
- const contents = new Generator(source, { 'token-stack': true }).generate({
- moduleMain: '() => {}', // disable moduleMain (default one requires Node.JS modules)
- });
+ const contents = transformJison(source);
return { contents, warnings: [] };
});
},
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index e567aba89..44e2f4cb1 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -40,18 +40,3 @@ jobs:
- name: Verify Docs
run: yarn docs:verify
-
- - name: Check no `console.log()` in .jison files
- # ESLint can't parse .jison files directly
- # In the future, it might be worth making a `eslint-plugin-jison`, so
- # that this will be built into the `yarn lint` command.
- run: |
- shopt -s globstar
- mkdir -p tmp/
- for jison_file in src/**/*.jison; do
- outfile="tmp/$(basename -- "$jison_file" .jison)-jison.js"
- echo "Converting $jison_file to $outfile"
- # default module-type (CJS) always adds a console.log()
- yarn jison "$jison_file" --outfile "$outfile" --module-type "amd"
- done
- yarn eslint --no-eslintrc --rule no-console:error --parser "@babel/eslint-parser" "./tmp/*-jison.js"
diff --git a/.lintstagedrc.json b/.lintstagedrc.json
index b88abda4b..1e7c61dd8 100644
--- a/.lintstagedrc.json
+++ b/.lintstagedrc.json
@@ -1,5 +1,6 @@
{
"src/docs/**": ["yarn docs:build --git"],
"src/docs.mts": ["yarn docs:build --git"],
- "*.{ts,js,json,html,md,mts}": ["eslint --fix", "prettier --write"]
+ "*.{ts,js,json,html,md,mts}": ["eslint --fix", "prettier --write"],
+ "*.jison": ["yarn lint:jison"]
}
diff --git a/.webpack/loaders/jison.js b/.webpack/loaders/jison.js
deleted file mode 100644
index 0d5ebc7e5..000000000
--- a/.webpack/loaders/jison.js
+++ /dev/null
@@ -1,25 +0,0 @@
-const { Generator } = require('jison');
-const validate = require('schema-utils');
-
-const schema = {
- title: 'Jison Parser options',
- type: 'object',
- properties: {
- 'token-stack': {
- type: 'boolean',
- },
- debug: {
- type: 'boolean',
- },
- },
- additionalProperties: false,
-};
-
-module.exports = function jisonLoader(source) {
- const options = this.getOptions();
- (validate.validate || validate)(schema, options, {
- name: 'Jison Loader',
- baseDataPath: 'options',
- });
- return new Generator(source, options).generate();
-};
diff --git a/.webpack/webpack.config.babel.js b/.webpack/webpack.config.babel.js
deleted file mode 100644
index 15760b19b..000000000
--- a/.webpack/webpack.config.babel.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { merge, mergeWithCustomize, customizeObject } from 'webpack-merge';
-import nodeExternals from 'webpack-node-externals';
-import baseConfig from './webpack.config.base';
-
-export default (_env, args) => {
- return [
- // non-minified
- merge(baseConfig, {
- optimization: {
- minimize: false,
- },
- }),
- // core [To be used by webpack/esbuild/vite etc to bundle mermaid]
- merge(baseConfig, {
- externals: [nodeExternals()],
- output: {
- filename: '[name].core.js',
- },
- optimization: {
- minimize: false,
- },
- }),
- // umd
- merge(baseConfig, {
- output: {
- filename: '[name].min.js',
- },
- }),
- // esm
- mergeWithCustomize({
- customizeObject: customizeObject({
- 'output.library': 'replace',
- }),
- })(baseConfig, {
- experiments: {
- outputModule: true,
- },
- output: {
- library: {
- type: 'module',
- },
- filename: '[name].esm.min.mjs',
- },
- }),
- ];
-};
diff --git a/.webpack/webpack.config.base.js b/.webpack/webpack.config.base.js
deleted file mode 100644
index 3ebd1863d..000000000
--- a/.webpack/webpack.config.base.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import path from 'path';
-const esbuild = require('esbuild');
-const { ESBuildMinifyPlugin } = require('esbuild-loader');
-export const resolveRoot = (...relativePath) => path.resolve(__dirname, '..', ...relativePath);
-
-export default {
- amd: false, // https://github.com/lodash/lodash/issues/3052
- target: 'web',
- entry: {
- mermaid: './src/mermaid',
- },
- resolve: {
- extensions: ['.wasm', '.mjs', '.js', '.ts', '.json', '.jison'],
- fallback: {
- fs: false, // jison generated code requires 'fs'
- path: require.resolve('path-browserify'),
- },
- },
- output: {
- path: resolveRoot('./dist'),
- filename: '[name].js',
- library: {
- name: 'mermaid',
- type: 'umd',
- export: 'default',
- },
- globalObject: 'typeof self !== "undefined" ? self : this',
- },
- module: {
- rules: [
- {
- test: /\.ts$/,
- use: 'ts-loader',
- exclude: /node_modules/,
- },
- {
- test: /\.js$/,
- include: [resolveRoot('./src'), resolveRoot('./node_modules/dagre-d3-renderer/lib')],
- use: {
- loader: 'esbuild-loader',
- options: {
- implementation: esbuild,
- target: 'es2015',
- },
- },
- },
- {
- // load scss to string
- test: /\.scss$/,
- use: ['css-to-string-loader', 'css-loader', 'sass-loader'],
- },
- {
- test: /\.jison$/,
- use: {
- loader: path.resolve(__dirname, './loaders/jison.js'),
- options: {
- 'token-stack': true,
- },
- },
- },
- ],
- },
- devtool: 'source-map',
- optimization: {
- minimizer: [
- new ESBuildMinifyPlugin({
- target: 'es2015',
- }),
- ],
- },
-};
diff --git a/.webpack/webpack.config.e2e.babel.js b/.webpack/webpack.config.e2e.babel.js
deleted file mode 100644
index 7f26b8aed..000000000
--- a/.webpack/webpack.config.e2e.babel.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import baseConfig, { resolveRoot } from './webpack.config.base';
-import { merge } from 'webpack-merge';
-
-export default merge(baseConfig, {
- mode: 'development',
- entry: {
- mermaid: './src/mermaid',
- e2e: './cypress/platform/viewer.js',
- 'bundle-test': './cypress/platform/bundle-test.js',
- },
- output: {
- globalObject: 'window',
- },
- devServer: {
- compress: true,
- port: 9000,
- static: [
- { directory: resolveRoot('cypress', 'platform') },
- { directory: resolveRoot('dist') },
- { directory: resolveRoot('demos') },
- ],
- },
- externals: {
- mermaid: 'mermaid',
- },
-});
diff --git a/babel.config.js b/babel.config.js
deleted file mode 100644
index 1779657a2..000000000
--- a/babel.config.js
+++ /dev/null
@@ -1,10 +0,0 @@
-module.exports = {
- presets: [
- [
- '@babel/preset-env',
- {
- targets: 'defaults, ie >= 11, current node',
- },
- ],
- ],
-};
diff --git a/cypress.config.js b/cypress.config.cjs
similarity index 100%
rename from cypress.config.js
rename to cypress.config.cjs
diff --git a/cypress/platform/e2e.html b/cypress/platform/e2e.html
index 021e2ad58..a23911334 100644
--- a/cypress/platform/e2e.html
+++ b/cypress/platform/e2e.html
@@ -2,7 +2,7 @@
-
+
-
+
+