Relocation of files

This commit is contained in:
Knut Sveidqvist
2022-09-21 11:03:33 +02:00
parent 24ef5f9fe4
commit 8dd82839cb
292 changed files with 12479 additions and 892 deletions

View File

@@ -1,5 +1,6 @@
{ {
"name": "mermaid", "name": "mermaid-monorepo",
"private": true,
"version": "9.2.0-rc1", "version": "9.2.0-rc1",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"main": "dist/mermaid.core.mjs", "main": "dist/mermaid.core.mjs",

View File

@@ -0,0 +1,20 @@
const { esmBuild, esmCoreBuild, iifeBuild } = require('./util.cjs');
const { build } = require('esbuild');
const handler = (e) => {
console.error(e);
process.exit(1);
};
const watch = process.argv.includes('--watch');
// mermaid.js
build(iifeBuild({ minify: false, watch })).catch(handler);
// mermaid.esm.mjs
build(esmBuild({ minify: false, watch })).catch(handler);
// mermaid.min.js
build(iifeBuild()).catch(handler);
// mermaid.esm.min.mjs
build(esmBuild()).catch(handler);
// mermaid.core.mjs (node_modules unbundled)
build(esmCoreBuild()).catch(handler);

View File

@@ -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}`;
};

View File

@@ -0,0 +1,79 @@
const esbuild = require('esbuild');
const http = require('http');
const { iifeBuild, esmBuild } = require('./util.cjs');
const express = require('express');
// 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',
},
outExtension: { '.js': format === 'iife' ? '.js' : '.esm.mjs' },
};
};
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('<h1>A custom 404 page</h1>');
return;
}
}
// 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 });
};
};
(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();
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.all('/e2e.esm.mjs', generateHandler(esmServer));
app.all('/bundle-test.esm.mjs', generateHandler(esmServer));
app.listen(9000, () => {
console.log(`Listening on http://localhost:9000`);
});
})();

View File

@@ -0,0 +1,94 @@
const { transformJison } = require('./jisonTransformer.cjs');
const fs = require('fs');
const { dependencies } = require('../package.json');
/** @typedef {import('esbuild').BuildOptions} Options */
/**
* @param {Options} override
* @returns {Options}
*/
const buildOptions = (override = {}) => {
return {
bundle: true,
minify: true,
keepNames: true,
banner: { js: '"use strict";' },
globalName: 'mermaid',
platform: 'browser',
tsconfig: 'tsconfig.json',
resolveExtensions: ['.ts', '.js', '.mjs', '.json', '.jison'],
external: ['require', 'fs', 'path'],
entryPoints: ['src/mermaid.ts'],
outfile: 'dist/mermaid-mindmap.min.js',
plugins: [jisonPlugin],
sourcemap: 'external',
...override,
};
};
/**
* Build options for mermaid.esm.* build.
*
* For ESM browser use.
*
* @param {Options} override - Override options.
* @returns {Options} ESBuild build options.
*/
exports.esmBuild = (override = { minify: true }) => {
return buildOptions({
format: 'esm',
outfile: `dist/mermaid.esm${override.minify ? '.min' : ''}.mjs`,
...override,
});
};
/**
* Build options for mermaid.core.* build.
*
* This build does not bundle `./node_modules/`, as it is designed to be used with
* Webpack/ESBuild/Vite to use mermaid inside an app/website.
*
* @param {Options} override - Override options.
* @returns {Options} ESBuild build options.
*/
exports.esmCoreBuild = (override) => {
return buildOptions({
format: 'esm',
outfile: `dist/mermaid.core.mjs`,
external: ['require', 'fs', 'path', ...Object.keys(dependencies)],
platform: 'neutral',
...override,
});
};
/**
* Build options for mermaid.js build.
*
* For IIFE browser use (where ESM is not yet supported).
*
* @param {Options} override - Override options.
* @returns {Options} ESBuild build options.
*/
exports.iifeBuild = (override = { minify: true }) => {
return buildOptions({
outfile: `dist/mermaid${override.minify ? '.min' : ''}.js`,
format: 'iife',
footer: {
js: 'mermaid = mermaid.default;',
},
...override,
});
};
const jisonPlugin = {
name: 'jison',
setup(build) {
build.onLoad({ filter: /\.jison$/ }, async (args) => {
// Load the file from the file system
const source = await fs.promises.readFile(args.path, 'utf8');
const contents = transformJison(source);
return { contents, warnings: [] };
});
},
};

View File

@@ -0,0 +1,78 @@
{
"name": "@mermaid-js/mermaid-mindmap",
"version": "9.2.0-rc1",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"main": "dist/mermaid-mindmap.core.mjs",
"module": "dist/mermaid-mindmap.core.mjs",
"type": "module",
"exports": {
".": {
"require": "./dist/mermaid-mindmap.min.js",
"import": "./dist/mermaid-mindmap.core.mjs"
},
"./*": "./*"
},
"keywords": [
"diagram",
"markdown",
"mindmap",
"mermaid"
],
"scripts": {
"clean": "rimraf dist",
"build:code": "node .esbuild/esbuild.cjs",
"build:types": "tsc -p ./tsconfig.json --emitDeclarationOnly",
"build:watch": "yarn build:code --watch",
"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": "yarn docs:build --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",
"release": "yarn build",
"lint": "eslint --cache --ignore-path .gitignore . && yarn lint:jison && prettier --check .",
"lint:fix": "eslint --fix --ignore-path .gitignore . && prettier --write .",
"lint:jison": "ts-node-esm src/jison/lint.mts",
"cypress": "cypress run",
"cypress:open": "cypress open",
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
"ci": "vitest run",
"test": "yarn lint && vitest run",
"test:watch": "vitest --coverage --watch",
"prepublishOnly": "yarn build && yarn test",
"prepare": "concurrently \"husky install\" \"yarn build\"",
"pre-commit": "lint-staged"
},
"repository": {
"type": "git",
"url": "https://github.com/mermaid-js/mermaid"
},
"author": "Knut Sveidqvist",
"license": "MIT",
"standard": {
"ignore": [
"**/parser/*.js",
"dist/**/*.js",
"cypress/**/*.js"
],
"globals": [
"page"
]
},
"dependencies": {
"@braintree/sanitize-url": "^6.0.0",
"d3": "^7.0.0",
"non-layered-tidy-tree-layout": "^2.0.2"
},
"devDependencies": {},
"resolutions": {
"d3": "^7.0.0"
},
"files": [
"dist"
],
"sideEffects": [
"**/*.css",
"**/*.scss"
]
}

View File

@@ -0,0 +1,6 @@
// @ts-ignore: TODO Fix ts errors
import mindmapParser from './parser/mindmap';
import * as mindmapDb from './mindmapDb';
import { mindmapDetector } from './mindmapDetector';
import mindmapRenderer from './mindmapRenderer';
import mindmapStyles from './styles';

View File

@@ -0,0 +1,108 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
// "incremental": true /* Enable incremental compilation */,
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "ES6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"DOM",
"ES2021"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "ES6" /* Specify what module code is generated. */,
"rootDir": "./src" /* Specify the root folder within your source files. */,
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./src" /* Specify the base directory to resolve non-relative module names. */,
// "paths": {} /* Specify a set of entries that re-map imports to additional lookup locations. */,
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [] /* Specify multiple folders that act like `./node_modules/@types`. */,
"types": [
"vitest/globals"
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
"resolveJsonModule": true /* Enable importing .json files */,
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": ["./src/**/*.ts", "./package.json"]
}

View File

@@ -0,0 +1,20 @@
const { esmBuild, esmCoreBuild, iifeBuild } = require('./util.cjs');
const { build } = require('esbuild');
const handler = (e) => {
console.error(e);
process.exit(1);
};
const watch = process.argv.includes('--watch');
// mermaid.js
build(iifeBuild({ minify: false, watch })).catch(handler);
// mermaid.esm.mjs
build(esmBuild({ minify: false, watch })).catch(handler);
// mermaid.min.js
build(iifeBuild()).catch(handler);
// mermaid.esm.min.mjs
build(esmBuild()).catch(handler);
// mermaid.core.mjs (node_modules unbundled)
build(esmCoreBuild()).catch(handler);

View File

@@ -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}`;
};

View File

@@ -0,0 +1,79 @@
const esbuild = require('esbuild');
const http = require('http');
const { iifeBuild, esmBuild } = require('./util.cjs');
const express = require('express');
// 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',
},
outExtension: { '.js': format === 'iife' ? '.js' : '.esm.mjs' },
};
};
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('<h1>A custom 404 page</h1>');
return;
}
}
// 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 });
};
};
(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();
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.all('/e2e.esm.mjs', generateHandler(esmServer));
app.all('/bundle-test.esm.mjs', generateHandler(esmServer));
app.listen(9000, () => {
console.log(`Listening on http://localhost:9000`);
});
})();

View File

@@ -0,0 +1,94 @@
const { transformJison } = require('./jisonTransformer.cjs');
const fs = require('fs');
const { dependencies } = require('../package.json');
/** @typedef {import('esbuild').BuildOptions} Options */
/**
* @param {Options} override
* @returns {Options}
*/
const buildOptions = (override = {}) => {
return {
bundle: true,
minify: true,
keepNames: true,
banner: { js: '"use strict";' },
globalName: 'mermaid',
platform: 'browser',
tsconfig: 'tsconfig.json',
resolveExtensions: ['.ts', '.js', '.mjs', '.json', '.jison'],
external: ['require', 'fs', 'path'],
entryPoints: ['src/mermaid.ts'],
outfile: 'dist/mermaid.min.js',
plugins: [jisonPlugin],
sourcemap: 'external',
...override,
};
};
/**
* Build options for mermaid.esm.* build.
*
* For ESM browser use.
*
* @param {Options} override - Override options.
* @returns {Options} ESBuild build options.
*/
exports.esmBuild = (override = { minify: true }) => {
return buildOptions({
format: 'esm',
outfile: `dist/mermaid.esm${override.minify ? '.min' : ''}.mjs`,
...override,
});
};
/**
* Build options for mermaid.core.* build.
*
* This build does not bundle `./node_modules/`, as it is designed to be used with
* Webpack/ESBuild/Vite to use mermaid inside an app/website.
*
* @param {Options} override - Override options.
* @returns {Options} ESBuild build options.
*/
exports.esmCoreBuild = (override) => {
return buildOptions({
format: 'esm',
outfile: `dist/mermaid.core.mjs`,
external: ['require', 'fs', 'path', ...Object.keys(dependencies)],
platform: 'neutral',
...override,
});
};
/**
* Build options for mermaid.js build.
*
* For IIFE browser use (where ESM is not yet supported).
*
* @param {Options} override - Override options.
* @returns {Options} ESBuild build options.
*/
exports.iifeBuild = (override = { minify: true }) => {
return buildOptions({
outfile: `dist/mermaid${override.minify ? '.min' : ''}.js`,
format: 'iife',
footer: {
js: 'mermaid = mermaid.default;',
},
...override,
});
};
const jisonPlugin = {
name: 'jison',
setup(build) {
build.onLoad({ filter: /\.jison$/ }, async (args) => {
// Load the file from the file system
const source = await fs.promises.readFile(args.path, 'utf8');
const contents = transformJison(source);
return { contents, warnings: [] };
});
},
};

View File

@@ -0,0 +1,141 @@
{
"name": "mermaid",
"version": "9.2.0-rc1",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"main": "dist/mermaid.core.mjs",
"module": "dist/mermaid.core.mjs",
"types": "dist/mermaid.d.ts",
"type": "module",
"exports": {
".": {
"require": "./dist/mermaid.min.js",
"import": "./dist/mermaid.core.mjs",
"types": "./dist/mermaid.d.ts"
},
"./*": "./*"
},
"keywords": [
"diagram",
"markdown",
"flowchart",
"sequence diagram",
"gantt",
"class diagram",
"git graph"
],
"scripts": {
"clean": "rimraf dist",
"build:code": "node .esbuild/esbuild.cjs",
"build:types": "tsc -p ./tsconfig.json --emitDeclarationOnly",
"build:watch": "yarn build:code --watch",
"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": "yarn docs:build --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",
"release": "yarn build",
"lint": "eslint --cache --ignore-path .gitignore . && yarn lint:jison && prettier --check .",
"lint:fix": "eslint --fix --ignore-path .gitignore . && prettier --write .",
"lint:jison": "ts-node-esm src/jison/lint.mts",
"cypress": "cypress run",
"cypress:open": "cypress open",
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
"ci": "vitest run",
"test": "yarn lint && vitest run",
"test:watch": "vitest --coverage --watch",
"prepublishOnly": "yarn build && yarn test",
"prepare": "concurrently \"husky install\" \"yarn build\"",
"pre-commit": "lint-staged"
},
"repository": {
"type": "git",
"url": "https://github.com/mermaid-js/mermaid"
},
"author": "Knut Sveidqvist",
"license": "MIT",
"standard": {
"ignore": [
"**/parser/*.js",
"dist/**/*.js",
"cypress/**/*.js"
],
"globals": [
"page"
]
},
"dependencies": {
"@braintree/sanitize-url": "^6.0.0",
"d3": "^7.0.0",
"dagre": "^0.8.5",
"dagre-d3": "^0.6.4",
"dompurify": "2.4.0",
"fast-clone": "^1.5.13",
"graphlib": "^2.1.8",
"khroma": "^2.0.0",
"lodash": "^4.17.21",
"moment-mini": "^2.24.0",
"non-layered-tidy-tree-layout": "^2.0.2",
"stylis": "^4.1.2"
},
"devDependencies": {
"@applitools/eyes-cypress": "^3.25.7",
"@commitlint/cli": "^17.1.2",
"@commitlint/config-conventional": "^17.0.0",
"@types/d3": "^7.4.0",
"@types/dompurify": "^2.3.4",
"@types/eslint": "^8.4.6",
"@types/express": "^4.17.13",
"@types/jsdom": "^20.0.0",
"@types/lodash": "^4.14.185",
"@types/prettier": "^2.7.0",
"@types/stylis": "^4.0.2",
"@typescript-eslint/eslint-plugin": "^5.37.0",
"@typescript-eslint/parser": "^5.37.0",
"@vitest/coverage-c8": "^0.23.2",
"@vitest/ui": "^0.23.2",
"concurrently": "^7.4.0",
"coveralls": "^3.1.1",
"cypress": "^10.0.0",
"cypress-image-snapshot": "^4.0.1",
"documentation": "13.2.0",
"esbuild": "^0.15.8",
"eslint": "^8.23.1",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-jest": "^27.0.4",
"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",
"jison": "^0.4.18",
"js-base64": "3.7.2",
"jsdom": "^20.0.0",
"lint-staged": "^13.0.0",
"moment": "^2.23.0",
"path-browserify": "^1.0.1",
"prettier": "^2.7.1",
"prettier-plugin-jsdoc": "^0.4.2",
"remark": "^14.0.2",
"rimraf": "^3.0.2",
"start-server-and-test": "^1.12.6",
"ts-node": "^10.9.1",
"typescript": "^4.8.3",
"unist-util-flatmap": "^1.0.0",
"vitest": "^0.23.1"
},
"resolutions": {
"d3": "^7.0.0"
},
"files": [
"dist"
],
"sideEffects": [
"**/*.css",
"**/*.scss"
]
}

View File

@@ -1,140 +1,140 @@
# Cluster handling # Cluster handling
Dagre does not support edges between nodes and clusters or between clusters to other clusters. In order to remedy this shortcoming the dagre wrapper implements a few work-arounds. Dagre does not support edges between nodes and clusters or between clusters to other clusters. In order to remedy this shortcoming the dagre wrapper implements a few work-arounds.
In the diagram below there are two clusters and there are no edges to nodes outside the own cluster. In the diagram below there are two clusters and there are no edges to nodes outside the own cluster.
```mermaid ```mermaid
flowchart flowchart
subgraph C1 subgraph C1
a --> b a --> b
end end
subgraph C2 subgraph C2
c c
end end
C1 --> C2 C1 --> C2
``` ```
In this case the dagre-wrapper will transform the graph to the graph below. In this case the dagre-wrapper will transform the graph to the graph below.
```mermaid ```mermaid
flowchart flowchart
C1 --> C2 C1 --> C2
``` ```
The new nodes C1 and C2 are a special type of nodes, clusterNodes. ClusterNodes have have the nodes in the cluster including the cluster attached in a graph object. The new nodes C1 and C2 are a special type of nodes, clusterNodes. ClusterNodes have have the nodes in the cluster including the cluster attached in a graph object.
When rendering this diagram it it beeing rendered recursively. The diagram is rendered by the dagre-mermaid:render function which in turn will be used to render the node C1 and the node C2. The result of those renderings will be inserted as nodes in the "root" diagram. With this recursive approach it would be possible to have different layout direction for each cluster. When rendering this diagram it it beeing rendered recursively. The diagram is rendered by the dagre-mermaid:render function which in turn will be used to render the node C1 and the node C2. The result of those renderings will be inserted as nodes in the "root" diagram. With this recursive approach it would be possible to have different layout direction for each cluster.
``` ```
{ clusterNode: true, graph } { clusterNode: true, graph }
``` ```
_Data for a clusterNode_ _Data for a clusterNode_
When a cluster has edges to or from some of its nodes leading outside the cluster the approach of recursive rendering can not be used as the layout of the graph needs to take responsibility for nodes outside of the cluster. When a cluster has edges to or from some of its nodes leading outside the cluster the approach of recursive rendering can not be used as the layout of the graph needs to take responsibility for nodes outside of the cluster.
```mermaid ```mermaid
flowchart flowchart
subgraph C1 subgraph C1
a a
end end
subgraph C2 subgraph C2
b b
end end
a --> C2 a --> C2
``` ```
To handle this case a special type of edge is inserted. The edge to/from the cluster is replaced with an edge to/from a node in the cluster which is tagged with toCluster/fromCluster. When rendering this edge the intersection between the edge and the border of the cluster is calculated making the edge start/stop there. In practice this renders like an an edge to/from the cluster. To handle this case a special type of edge is inserted. The edge to/from the cluster is replaced with an edge to/from a node in the cluster which is tagged with toCluster/fromCluster. When rendering this edge the intersection between the edge and the border of the cluster is calculated making the edge start/stop there. In practice this renders like an an edge to/from the cluster.
In the diagram above the root diagram would be rendered with C1 whereas C2 would be rendered recursively. In the diagram above the root diagram would be rendered with C1 whereas C2 would be rendered recursively.
Of these two approaches the top one renders better and is used when possible. When this is not possible, ie an edge is added crossing the border the non recursive approach is used. Of these two approaches the top one renders better and is used when possible. When this is not possible, ie an edge is added crossing the border the non recursive approach is used.
# Graph objects and their properties # Graph objects and their properties
Explains the representation of various objects used to render the flow charts and what the properties mean. This ofc from the perspective of the dagre-wrapper. Explains the representation of various objects used to render the flow charts and what the properties mean. This ofc from the perspective of the dagre-wrapper.
## node ## node
Sample object: Sample object:
```json ```json
{ {
"shape": "rect", "shape": "rect",
"labelText": "Test", "labelText": "Test",
"rx": 0, "rx": 0,
"ry": 0, "ry": 0,
"class": "default", "class": "default",
"style": "", "style": "",
"id": "Test", "id": "Test",
"type": "group", "type": "group",
"padding": 15 "padding": 15
} }
``` ```
This is set by the renderer of the diagram and insert the data that the wrapper neds for rendering. This is set by the renderer of the diagram and insert the data that the wrapper neds for rendering.
| property | description | | property | description |
| ---------- | ------------------------------------------------------------------------------------------------ | | ---------- | ------------------------------------------------------------------------------------------------ |
| labelStyle | Css styles for the label. User for instance for styling the labels for clusters | | labelStyle | Css styles for the label. User for instance for styling the labels for clusters |
| shape | The shape of the node. | | shape | The shape of the node. |
| labelText | The text on the label | | labelText | The text on the label |
| rx | The corner radius - maybe part of the shape instead? Used for rects. | | rx | The corner radius - maybe part of the shape instead? Used for rects. |
| ry | The corner radius - maybe part of the shape instead? Used for rects. | | ry | The corner radius - maybe part of the shape instead? Used for rects. |
| classes | Classes to be set for the shape. Not used | | classes | Classes to be set for the shape. Not used |
| style | Css styles for the actual shape | | style | Css styles for the actual shape |
| id | id of the shape | | id | id of the shape |
| type | if set to group then this node indicates _a cluster_. | | type | if set to group then this node indicates _a cluster_. |
| padding | Padding. Passed from the render as this might differ between different diagrams. Maybe obsolete. | | padding | Padding. Passed from the render as this might differ between different diagrams. Maybe obsolete. |
| data | Non-generic data specific to the shape. | | data | Non-generic data specific to the shape. |
# edge # edge
arrowType sets the type of arrows to use. The following arrow types are currently supported: arrowType sets the type of arrows to use. The following arrow types are currently supported:
arrow_cross arrow_cross
double_arrow_cross double_arrow_cross
arrow_point arrow_point
double_arrow_point double_arrow_point
arrow_circle arrow_circle
double_arrow_circle double_arrow_circle
Lets try to make these types semantic free so that diagram type semantics does not find its way in to this more generic layer. Lets try to make these types semantic free so that diagram type semantics does not find its way in to this more generic layer.
Required edgeData for proper rendering: Required edgeData for proper rendering:
| property | description | | property | description |
| ---------- | -------------------------------------------------------------------- | | ---------- | -------------------------------------------------------------------- |
| id | Id of the edge | | id | Id of the edge |
| arrowHead | overlap between arrowHead and arrowType? | | arrowHead | overlap between arrowHead and arrowType? |
| arrowType | overlap between arrowHead and arrowType? | | arrowType | overlap between arrowHead and arrowType? |
| style | | | style | |
| labelStyle | | | labelStyle | |
| label | overlap between label and labelText? | | label | overlap between label and labelText? |
| labelPos | | | labelPos | |
| labelType | overlap between label and labelText? | | labelType | overlap between label and labelText? |
| thickness | Sets the thinkess of the edge. Can be \['normal', 'thick'\] | | thickness | Sets the thinkess of the edge. Can be \['normal', 'thick'\] |
| pattern | Sets the pattern of the edge. Can be \['solid', 'dotted', 'dashed'\] | | pattern | Sets the pattern of the edge. Can be \['solid', 'dotted', 'dashed'\] |
# Markers # Markers
Define what markers that should be included in the diagram with the insert markers function. The function takes two arguments, first the element in which the markers should be included and a list of the markers that should be added. Define what markers that should be included in the diagram with the insert markers function. The function takes two arguments, first the element in which the markers should be included and a list of the markers that should be added.
Ex: Ex:
insertMarkers(el, \['point', 'circle'\]) insertMarkers(el, \['point', 'circle'\])
The example above adds the markers point and cross. This means that edges with the arrowTypes arrow_cross, double_arrow_cross, arrow_point and double_arrow_cross will get the corresponding markers but arrowType arrow_cross will have no impact. The example above adds the markers point and cross. This means that edges with the arrowTypes arrow_cross, double_arrow_cross, arrow_point and double_arrow_cross will get the corresponding markers but arrowType arrow_cross will have no impact.
Current markers: Current markers:
- point - the standard arrow from flowcharts - point - the standard arrow from flowcharts
- circle - Arrows ending with circle - circle - Arrows ending with circle
- cross - arrows starting and ending with a cross - cross - arrows starting and ending with a cross
// Todo - in case of common renderer // Todo - in case of common renderer
# Common functions used by the renderer to be implemented by the Db # Common functions used by the renderer to be implemented by the Db
getDirection getDirection
getClasses getClasses

View File

@@ -1,32 +1,32 @@
const intersectRect = (node, point) => { const intersectRect = (node, point) => {
var x = node.x; var x = node.x;
var y = node.y; var y = node.y;
// Rectangle intersection algorithm from: // Rectangle intersection algorithm from:
// https://math.stackexchange.com/questions/108113/find-edge-between-two-boxes // https://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
var dx = point.x - x; var dx = point.x - x;
var dy = point.y - y; var dy = point.y - y;
var w = node.width / 2; var w = node.width / 2;
var h = node.height / 2; var h = node.height / 2;
var sx, sy; var sx, sy;
if (Math.abs(dy) * w > Math.abs(dx) * h) { if (Math.abs(dy) * w > Math.abs(dx) * h) {
// Intersection is top or bottom of rect. // Intersection is top or bottom of rect.
if (dy < 0) { if (dy < 0) {
h = -h; h = -h;
} }
sx = dy === 0 ? 0 : (h * dx) / dy; sx = dy === 0 ? 0 : (h * dx) / dy;
sy = h; sy = h;
} else { } else {
// Intersection is left or right of rect. // Intersection is left or right of rect.
if (dx < 0) { if (dx < 0) {
w = -w; w = -w;
} }
sx = w; sx = w;
sy = dx === 0 ? 0 : (w * dy) / dx; sy = dx === 0 ? 0 : (w * dy) / dx;
} }
return { x: x + sx, y: y + sy }; return { x: x + sx, y: y + sy };
}; };
export default intersectRect; export default intersectRect;

View File

@@ -1,11 +1,11 @@
import { registerDiagram } from './diagramAPI'; import { registerDiagram } from './diagramAPI';
// @ts-ignore: TODO Fix ts errors // // @ts-ignore: TODO Fix ts errors
import mindmapParser from '../diagrams/mindmap/parser/mindmap'; // import mindmapParser from '../diagrams/mindmap/parser/mindmap';
import * as mindmapDb from '../diagrams/mindmap/mindmapDb'; // import * as mindmapDb from '../diagrams/mindmap/mindmapDb';
import { mindmapDetector } from '../diagrams/mindmap/mindmapDetector'; // import { mindmapDetector } from '../diagrams/mindmap/mindmapDetector';
import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer'; // import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer';
import mindmapStyles from '../diagrams/mindmap/styles'; // import mindmapStyles from '../diagrams/mindmap/styles';
// @ts-ignore: TODO Fix ts errors // @ts-ignore: TODO Fix ts errors
import gitGraphParser from '../diagrams/git/parser/gitGraph'; import gitGraphParser from '../diagrams/git/parser/gitGraph';
@@ -96,7 +96,7 @@ import { journeyDetector } from '../diagrams/user-journey/journeyDetector';
import journeyDb from '../diagrams/user-journey/journeyDb'; import journeyDb from '../diagrams/user-journey/journeyDb';
import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; import journeyRenderer from '../diagrams/user-journey/journeyRenderer';
import journeyStyles from '../diagrams/user-journey/styles'; import journeyStyles from '../diagrams/user-journey/styles';
import { getConfig, setConfig } from '../config'; import { setConfig } from '../config';
import errorRenderer from '../diagrams/error/errorRenderer'; import errorRenderer from '../diagrams/error/errorRenderer';
import errorStyles from '../diagrams/error/styles'; import errorStyles from '../diagrams/error/styles';
@@ -340,9 +340,9 @@ export const addDiagrams = () => {
{ parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles }, { parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles },
gitGraphDetector gitGraphDetector
); );
registerDiagram( // registerDiagram(
'mindmap', // 'mindmap',
{ parser: mindmapParser, db: mindmapDb, renderer: mindmapRenderer, styles: mindmapStyles }, // { parser: mindmapParser, db: mindmapDb, renderer: mindmapRenderer, styles: mindmapStyles },
mindmapDetector // mindmapDetector
); // );
}; };

Some files were not shown because too many files have changed in this diff Show More