diff --git a/.esbuild/serve.cjs b/.esbuild/serve.cjs
index c54ff1e9f..30fff7ec0 100644
--- a/.esbuild/serve.cjs
+++ b/.esbuild/serve.cjs
@@ -1,53 +1,71 @@
const esbuild = require('esbuild');
const http = require('http');
-const path = require('path');
-const { iifeBuild } = require('./util.cjs');
+const { iifeBuild, esmBuild, getEntryPoints } = 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: {
+ ...getEntryPoints(format === 'iife' ? '' : '.esm'),
+ 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' : '.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 }),
+ ...getEntryPointsAndExtensions('iife'),
+ }
+ );
+ const esmServer = await esbuild.serve(
+ {},
+ { ...esmBuild({ minify: false }), ...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 });
- });
-
- // Forward the body of the request to esbuild
- req.pipe(proxyReq, { end: true });
- })
- .listen(3000);
- });
+ app.use(express.static('demos'));
+ app.use(express.static('cypress/platform'));
+ app.all('/mermaid.js', generateHandler(iifeServer));
+ app.all('/mermaid.esm.mjs', generateHandler(esmServer));
+ app.listen(3000);
+})();
diff --git a/.esbuild/util.cjs b/.esbuild/util.cjs
index 0cddb7e45..d9b783747 100644
--- a/.esbuild/util.cjs
+++ b/.esbuild/util.cjs
@@ -26,12 +26,14 @@ const buildOptions = (override = {}) => {
};
};
-const getOutFiles = (extension) => {
+const getEntryPoints = (extension) => {
return {
[`mermaid${extension}`]: 'src/mermaid.ts',
[`diagramAPI${extension}`]: 'src/diagram-api/diagramAPI.ts',
};
};
+exports.getEntryPoints = getEntryPoints;
+
/**
* Build options for mermaid.esm.* build.
*
@@ -43,7 +45,7 @@ const getOutFiles = (extension) => {
exports.esmBuild = (override = { minify: true }) => {
return buildOptions({
format: 'esm',
- entryPoints: getOutFiles(`.esm${override.minify ? '.min' : ''}`),
+ entryPoints: getEntryPoints(`.esm${override.minify ? '.min' : ''}`),
outExtension: { '.js': '.mjs' },
...override,
});
@@ -61,7 +63,7 @@ exports.esmBuild = (override = { minify: true }) => {
exports.esmCoreBuild = (override) => {
return buildOptions({
format: 'esm',
- entryPoints: getOutFiles(`.core`),
+ entryPoints: getEntryPoints(`.core`),
outExtension: { '.js': '.mjs' },
external: ['require', 'fs', 'path', ...Object.keys(dependencies)],
platform: 'neutral',
@@ -79,7 +81,7 @@ exports.esmCoreBuild = (override) => {
*/
exports.iifeBuild = (override = { minify: true }) => {
return buildOptions({
- entryPoints: getOutFiles(override.minify ? '.min' : ''),
+ entryPoints: getEntryPoints(override.minify ? '.min' : ''),
format: 'iife',
...override,
});
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/package.json b/package.json
index 94c94ab1a..cf8eab56b 100644
--- a/package.json
+++ b/package.json
@@ -26,22 +26,20 @@
"clean": "rimraf dist",
"build:code": "node .esbuild/esbuild.cjs",
"build:types": "tsc -p ./tsconfig.json --emitDeclarationOnly",
- "build:webpack": "webpack --mode production --progress --color",
"build:watch": "yarn build:code --watch",
- "build:new": "concurrently \"yarn build:code\" \"yarn build:types\"",
- "build": "yarn clean; yarn build:webpack",
+ "build:esbuild": "concurrently \"yarn build:code\" \"yarn build:types\"",
+ "build": "yarn clean; yarn build:esbuild",
+ "dev": "node .esbuild/serve.cjs",
"docs:build": "ts-node-esm src/docs.mts",
"docs:verify": "ts-node-esm src/docs.mts --verify",
"postbuild": "documentation build src/mermaidAPI.ts src/config.ts src/defaultConfig.ts --shallow -f md --markdown-toc false > src/docs/Setup.md && prettier --write src/docs/Setup.md && yarn docs:build",
"release": "yarn build",
"lint": "eslint --cache --ignore-path .gitignore . && prettier --check .",
"lint:fix": "eslint --fix --ignore-path .gitignore . && prettier --write .",
- "e2e:depr": "yarn lint && jest e2e --config e2e/jest.config.js",
"cypress": "cypress run",
"cypress:open": "cypress open",
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
"e2e-upd": "yarn lint && jest e2e -u --config e2e/jest.config.js",
- "dev": "webpack serve --config ./.webpack/webpack.config.e2e.babel.js",
"ci": "jest src/.*",
"test": "yarn lint && jest src/.*",
"test:watch": "jest --watch src",
@@ -89,6 +87,7 @@
"@commitlint/config-conventional": "^17.0.0",
"@types/d3": "^7.4.0",
"@types/dompurify": "^2.3.4",
+ "@types/express": "^4.17.13",
"@types/jest": "^28.1.7",
"@types/lodash": "^4.14.184",
"@types/stylis": "^4.0.2",
@@ -112,6 +111,7 @@
"eslint-plugin-jsdoc": "^39.3.6",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-markdown": "^3.0.0",
+ "express": "^4.18.1",
"globby": "^13.1.2",
"husky": "^8.0.0",
"identity-obj-proxy": "^3.0.0",
diff --git a/yarn.lock b/yarn.lock
index 1967b28b1..ce417808e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3746,6 +3746,24 @@ body-parser@1.19.2:
raw-body "2.4.3"
type-is "~1.6.18"
+body-parser@1.20.0:
+ version "1.20.0"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5"
+ integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==
+ dependencies:
+ bytes "3.1.2"
+ content-type "~1.0.4"
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ http-errors "2.0.0"
+ iconv-lite "0.4.24"
+ on-finished "2.4.1"
+ qs "6.10.3"
+ raw-body "2.5.1"
+ type-is "~1.6.18"
+ unpipe "1.0.0"
+
body@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069"
@@ -4598,6 +4616,11 @@ cookie@0.4.2:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
+cookie@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
+ integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
+
copy-descriptor@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
@@ -5241,6 +5264,11 @@ dequal@^2.0.0:
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d"
integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==
+destroy@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
+ integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
+
destroy@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
@@ -6269,6 +6297,43 @@ express@^4.17.3:
utils-merge "1.0.1"
vary "~1.1.2"
+express@^4.18.1:
+ version "4.18.1"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
+ integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
+ dependencies:
+ accepts "~1.3.8"
+ array-flatten "1.1.1"
+ body-parser "1.20.0"
+ content-disposition "0.5.4"
+ content-type "~1.0.4"
+ cookie "0.5.0"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "2.0.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "1.2.0"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ path-to-regexp "0.1.7"
+ proxy-addr "~2.0.7"
+ qs "6.10.3"
+ range-parser "~1.2.1"
+ safe-buffer "5.2.1"
+ send "0.18.0"
+ serve-static "1.15.0"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ type-is "~1.6.18"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
extend-shallow@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
@@ -6436,6 +6501,19 @@ filter-obj@^1.1.0:
resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==
+finalhandler@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
+ integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ statuses "2.0.1"
+ unpipe "~1.0.0"
+
finalhandler@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
@@ -9676,6 +9754,13 @@ obuf@^1.0.0, obuf@^1.1.2:
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
+on-finished@2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
+ integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
+ dependencies:
+ ee-first "1.1.1"
+
on-finished@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
@@ -10319,6 +10404,13 @@ q@^1.5.1:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
+qs@6.10.3:
+ version "6.10.3"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
+ integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
+ dependencies:
+ side-channel "^1.0.4"
+
qs@6.9.7:
version "6.9.7"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe"
@@ -11065,6 +11157,25 @@ send@0.17.2:
range-parser "~1.2.1"
statuses "~1.5.0"
+send@0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
+ integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
+ dependencies:
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ mime "1.6.0"
+ ms "2.1.3"
+ on-finished "2.4.1"
+ range-parser "~1.2.1"
+ statuses "2.0.1"
+
serialize-javascript@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
@@ -11095,6 +11206,16 @@ serve-static@1.14.2:
parseurl "~1.3.3"
send "0.17.2"
+serve-static@1.15.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
+ integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
+ dependencies:
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.18.0"
+
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"