mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-24 01:39:53 +02:00
Merge pull request #3591 from mermaid-js/sidv/fixDetectDiagram
fix Detect diagram fallback
This commit is contained in:
14
cypress/platform/sidv.html
Normal file
14
cypress/platform/sidv.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<body>
|
||||
<pre class="mermaid">
|
||||
none
|
||||
hello world
|
||||
</pre>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.initialize({
|
||||
logLevel: 1,
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@@ -47,7 +47,8 @@
|
||||
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
|
||||
"ci": "vitest run",
|
||||
"test": "pnpm lint && vitest run",
|
||||
"test:watch": "vitest --coverage --watch",
|
||||
"test:watch": "vitest --watch",
|
||||
"test:coverage": "vitest --coverage",
|
||||
"prepublishOnly": "pnpm build && pnpm test",
|
||||
"prepare": "concurrently \"husky install\" \"pnpm build\"",
|
||||
"pre-commit": "lint-staged"
|
||||
|
@@ -8,11 +8,18 @@ export class Diagram {
|
||||
parser;
|
||||
renderer;
|
||||
db;
|
||||
private detectTypeFailed = false;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
constructor(public txt: string, parseError?: Function) {
|
||||
const cnf = configApi.getConfig();
|
||||
this.txt = txt;
|
||||
try {
|
||||
this.type = detectType(txt, cnf);
|
||||
} catch (e) {
|
||||
this.handleError(e, parseError);
|
||||
this.type = 'error';
|
||||
this.detectTypeFailed = true;
|
||||
}
|
||||
const diagram = getDiagram(this.type);
|
||||
log.debug('Type ' + this.type);
|
||||
// Setup diagram
|
||||
@@ -32,12 +39,22 @@ export class Diagram {
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
parse(text: string, parseError?: Function): boolean {
|
||||
if (this.detectTypeFailed) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
text = text + '\n';
|
||||
this.db.clear();
|
||||
this.parser.parse(text);
|
||||
return true;
|
||||
} catch (error) {
|
||||
this.handleError(error, parseError);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
handleError(error: unknown, parseError?: Function) {
|
||||
// Is this the correct way to access mermiad's parseError()
|
||||
// method ? (or global.mermaid.parseError()) ?
|
||||
if (parseError) {
|
||||
@@ -54,8 +71,6 @@ export class Diagram {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getParser() {
|
||||
return this.parser;
|
||||
@@ -66,10 +81,8 @@ export class Diagram {
|
||||
}
|
||||
}
|
||||
|
||||
export default Diagram;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export const getDiagramFromText = async (txt: string, parseError?: Function) => {
|
||||
export const getDiagramFromText = async (txt: string, parseError?: Function): Promise<Diagram> => {
|
||||
const type = detectType(txt, configApi.getConfig());
|
||||
try {
|
||||
// Trying to find the diagram
|
||||
@@ -79,24 +92,14 @@ export const getDiagramFromText = async (txt: string, parseError?: Function) =>
|
||||
if (!loader) {
|
||||
throw new Error(`Diagram ${type} not found.`);
|
||||
}
|
||||
// Diagram not avaiable, loading it
|
||||
// const path = getPathForDiagram(type);
|
||||
const { diagram } = await loader(); // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
registerDiagram(
|
||||
type,
|
||||
{
|
||||
db: diagram.db,
|
||||
renderer: diagram.renderer,
|
||||
parser: diagram.parser,
|
||||
styles: diagram.styles,
|
||||
},
|
||||
diagram.injectUtils
|
||||
);
|
||||
// await loadDiagram('./packages/mermaid-mindmap/dist/mermaid-mindmap.js');
|
||||
// await loadDiagram(path + 'mermaid-' + type + '.js');
|
||||
// Diagram not available, loading it
|
||||
const { diagram } = await loader();
|
||||
registerDiagram(type, diagram, undefined, diagram.injectUtils);
|
||||
// new diagram will try getDiagram again and if fails then it is a valid throw
|
||||
}
|
||||
// If either of the above worked, we have the diagram
|
||||
// logic and can continue
|
||||
return new Diagram(txt, parseError);
|
||||
};
|
||||
|
||||
export default Diagram;
|
||||
|
@@ -11,17 +11,13 @@ import Diagram from '../Diagram';
|
||||
// Normally, we could just do the following to get the original `parse()`
|
||||
// implementation, however, requireActual returns a promise and it's not documented how to use withing mock file.
|
||||
|
||||
let hasLoadedDiagrams = false;
|
||||
/**
|
||||
* @param text
|
||||
* @param parseError
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
function parse(text: string, parseError?: Function): boolean {
|
||||
if (!hasLoadedDiagrams) {
|
||||
addDiagrams();
|
||||
hasLoadedDiagrams = true;
|
||||
}
|
||||
const diagram = new Diagram(text, parseError);
|
||||
return diagram.parse(text, parseError);
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
export interface MermaidConfig {
|
||||
lazyLoadedDiagrams?: any;
|
||||
lazyLoadedDiagrams?: string[];
|
||||
theme?: string;
|
||||
themeVariables?: any;
|
||||
themeCSS?: string;
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import { MermaidConfig } from '../config.type';
|
||||
import { log } from '../logger';
|
||||
import { DetectorRecord, DiagramDetector, DiagramLoader } from './types';
|
||||
|
||||
export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
|
||||
export type DiagramLoader = (() => any) | null;
|
||||
export type DetectorRecord = { detector: DiagramDetector; loader: DiagramLoader };
|
||||
const directive =
|
||||
/[%]{2}[{]\s*(?:(?:(\w+)\s*:|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi;
|
||||
const anyComment = /\s*%%.*\n/gm;
|
||||
@@ -34,26 +33,22 @@ const detectors: Record<string, DetectorRecord> = {};
|
||||
*/
|
||||
export const detectType = function (text: string, config?: MermaidConfig): string {
|
||||
text = text.replace(directive, '').replace(anyComment, '\n');
|
||||
|
||||
// console.log(detectors);
|
||||
|
||||
for (const [key, { detector }] of Object.entries(detectors)) {
|
||||
const diagram = detector(text, config);
|
||||
if (diagram) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
// TODO: #3391
|
||||
// throw new Error(`No diagram type detected for text: ${text}`);
|
||||
return 'flowchart';
|
||||
|
||||
throw new Error(`No diagram type detected for text: ${text}`);
|
||||
};
|
||||
|
||||
export const addDetector = (
|
||||
key: string,
|
||||
detector: DiagramDetector,
|
||||
loader: DiagramLoader | null
|
||||
) => {
|
||||
export const addDetector = (key: string, detector: DiagramDetector, loader?: DiagramLoader) => {
|
||||
if (detectors[key]) {
|
||||
throw new Error(`Detector with key ${key} already exists`);
|
||||
}
|
||||
detectors[key] = { detector, loader };
|
||||
log.debug(`Detector with key ${key} added${loader ? ' with loader' : ''}`);
|
||||
};
|
||||
|
||||
export const getDiagramLoader = (key: string) => detectors[key].loader;
|
||||
|
@@ -1,16 +1,4 @@
|
||||
import {
|
||||
registerDiagram,
|
||||
registerDetector,
|
||||
DiagramDefinition,
|
||||
DiagramDetector,
|
||||
} from './diagramAPI';
|
||||
|
||||
// // @ts-ignore: TODO Fix ts errors
|
||||
// import mindmapParser from '../diagrams/mindmap/parser/mindmap';
|
||||
// import * as mindmapDb from '../diagrams/mindmap/mindmapDb';
|
||||
// import { mindmapDetector } from '../diagrams/mindmap/mindmapDetector';
|
||||
// import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer';
|
||||
// import mindmapStyles from '../diagrams/mindmap/styles';
|
||||
import { registerDiagram } from './diagramAPI';
|
||||
|
||||
// @ts-ignore: TODO Fix ts errors
|
||||
import gitGraphParser from '../diagrams/git/parser/gitGraph';
|
||||
@@ -106,17 +94,15 @@ import { setConfig } from '../config';
|
||||
import errorRenderer from '../diagrams/error/errorRenderer';
|
||||
import errorStyles from '../diagrams/error/styles';
|
||||
|
||||
const registerDiagramAndDetector = (
|
||||
id: string,
|
||||
diagram: DiagramDefinition,
|
||||
detector: DiagramDetector
|
||||
) => {
|
||||
registerDiagram(id, diagram);
|
||||
registerDetector(id, detector);
|
||||
};
|
||||
|
||||
let hasLoadedDiagrams = false;
|
||||
export const addDiagrams = () => {
|
||||
registerDiagramAndDetector(
|
||||
if (hasLoadedDiagrams) {
|
||||
return;
|
||||
}
|
||||
// This is added here to avoid race-conditions.
|
||||
// We could optimize the loading logic somehow.
|
||||
hasLoadedDiagrams = true;
|
||||
registerDiagram(
|
||||
'error',
|
||||
// Special diagram with error messages but setup as a regular diagram
|
||||
{
|
||||
@@ -140,7 +126,7 @@ export const addDiagrams = () => {
|
||||
(text) => text.toLowerCase().trim() === 'error'
|
||||
);
|
||||
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'c4',
|
||||
{
|
||||
parser: c4Parser,
|
||||
@@ -153,7 +139,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
c4Detector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'class',
|
||||
{
|
||||
parser: classParser,
|
||||
@@ -170,7 +156,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
classDetector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'classDiagram',
|
||||
{
|
||||
parser: classParser,
|
||||
@@ -187,7 +173,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
classDetectorV2
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'er',
|
||||
{
|
||||
parser: erParser,
|
||||
@@ -197,7 +183,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
erDetector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'gantt',
|
||||
{
|
||||
parser: ganttParser,
|
||||
@@ -207,7 +193,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
ganttDetector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'info',
|
||||
{
|
||||
parser: infoParser,
|
||||
@@ -217,7 +203,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
infoDetector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'pie',
|
||||
{
|
||||
parser: pieParser,
|
||||
@@ -227,7 +213,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
pieDetector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'requirement',
|
||||
{
|
||||
parser: requirementParser,
|
||||
@@ -237,7 +223,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
requirementDetector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'sequence',
|
||||
{
|
||||
parser: sequenceParser,
|
||||
@@ -260,7 +246,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
sequenceDetector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'state',
|
||||
{
|
||||
parser: stateParser,
|
||||
@@ -277,7 +263,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
stateDetector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'stateDiagram',
|
||||
{
|
||||
parser: stateParser,
|
||||
@@ -294,7 +280,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
stateDetectorV2
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'journey',
|
||||
{
|
||||
parser: journeyParser,
|
||||
@@ -309,7 +295,7 @@ export const addDiagrams = () => {
|
||||
journeyDetector
|
||||
);
|
||||
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'flowchart',
|
||||
{
|
||||
parser: flowParser,
|
||||
@@ -329,7 +315,7 @@ export const addDiagrams = () => {
|
||||
},
|
||||
flowDetector
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'flowchart-v2',
|
||||
{
|
||||
parser: flowParser,
|
||||
@@ -350,14 +336,9 @@ export const addDiagrams = () => {
|
||||
},
|
||||
flowDetectorV2
|
||||
);
|
||||
registerDiagramAndDetector(
|
||||
registerDiagram(
|
||||
'gitGraph',
|
||||
{ parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles },
|
||||
gitGraphDetector
|
||||
);
|
||||
// registerDiagram(
|
||||
// 'mindmap',
|
||||
// { parser: mindmapParser, db: mindmapDb, renderer: mindmapRenderer, styles: mindmapStyles },
|
||||
// mindmapDetector
|
||||
// );
|
||||
};
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { detectType, DiagramDetector } from './detectType';
|
||||
import { getDiagram, registerDiagram, registerDetector } from './diagramAPI';
|
||||
import { detectType } from './detectType';
|
||||
import { getDiagram, registerDiagram } from './diagramAPI';
|
||||
import { addDiagrams } from './diagram-orchestration';
|
||||
import { DiagramDetector } from './types';
|
||||
|
||||
addDiagrams();
|
||||
|
||||
@@ -15,17 +16,22 @@ describe('DiagramAPI', () => {
|
||||
|
||||
it('should handle diagram registrations', () => {
|
||||
expect(() => getDiagram('loki')).toThrow();
|
||||
expect(() => detectType('loki diagram')).not.toThrow(); // TODO: #3391
|
||||
expect(() => detectType('loki diagram')).toThrow(
|
||||
'No diagram type detected for text: loki diagram'
|
||||
);
|
||||
const detector: DiagramDetector = (str: string) => {
|
||||
return str.match('loki') !== null;
|
||||
};
|
||||
registerDetector('loki', detector);
|
||||
registerDiagram('loki', {
|
||||
registerDiagram(
|
||||
'loki',
|
||||
{
|
||||
db: {},
|
||||
parser: {},
|
||||
renderer: {},
|
||||
styles: {},
|
||||
});
|
||||
},
|
||||
detector
|
||||
);
|
||||
expect(getDiagram('loki')).not.toBeNull();
|
||||
expect(detectType('loki diagram')).toBe('loki');
|
||||
});
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { addDetector, DiagramDetector as _DiagramDetector } from './detectType';
|
||||
import { addDetector } from './detectType';
|
||||
import { log as _log, setLogLevel as _setLogLevel } from '../logger';
|
||||
import { getConfig as _getConfig } from '../config';
|
||||
import { sanitizeText as _sanitizeText } from '../diagrams/common/common';
|
||||
import { MermaidConfig } from '../config.type';
|
||||
import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox';
|
||||
import { addStylesForDiagram } from '../styles';
|
||||
import { DiagramDefinition, DiagramDetector } from './types';
|
||||
|
||||
/*
|
||||
Packaging and exposing resources for externa diagrams so that they can import
|
||||
@@ -13,41 +13,19 @@ import { addStylesForDiagram } from '../styles';
|
||||
*/
|
||||
export const log = _log;
|
||||
export const setLogLevel = _setLogLevel;
|
||||
export type DiagramDetector = _DiagramDetector;
|
||||
export const getConfig = _getConfig;
|
||||
export const sanitizeText = (text: string) => _sanitizeText(text, getConfig());
|
||||
export const setupGraphViewbox = _setupGraphViewbox;
|
||||
|
||||
export interface InjectUtils {
|
||||
_log: any;
|
||||
_setLogLevel: any;
|
||||
_getConfig: any;
|
||||
_sanitizeText: any;
|
||||
_setupGraphViewbox: any;
|
||||
}
|
||||
|
||||
export interface DiagramDefinition {
|
||||
db: any;
|
||||
renderer: any;
|
||||
parser: any;
|
||||
styles: any;
|
||||
init?: (config: MermaidConfig) => void;
|
||||
injectUtils?: (utils: InjectUtils) => void;
|
||||
}
|
||||
|
||||
const diagrams: Record<string, DiagramDefinition> = {};
|
||||
const connectCallbacks: Record<string, any> = {}; // TODO fix, eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
export interface Detectors {
|
||||
[key: string]: DiagramDetector;
|
||||
}
|
||||
|
||||
export const registerDetector = (id: string, detector: DiagramDetector) => {
|
||||
addDetector(id, detector, null);
|
||||
};
|
||||
|
||||
export const registerDiagram = (
|
||||
id: string,
|
||||
diagram: DiagramDefinition,
|
||||
detector?: DiagramDetector,
|
||||
callback?: (
|
||||
_log: any,
|
||||
_setLogLevel: any,
|
||||
@@ -57,9 +35,12 @@ export const registerDiagram = (
|
||||
) => void
|
||||
) => {
|
||||
if (diagrams[id]) {
|
||||
log.warn(`Diagram ${id} already registered.`);
|
||||
throw new Error(`Diagram ${id} already registered.`);
|
||||
}
|
||||
diagrams[id] = diagram;
|
||||
if (detector) {
|
||||
addDetector(id, detector);
|
||||
}
|
||||
addStylesForDiagram(id, diagram.styles);
|
||||
if (typeof callback !== 'undefined') {
|
||||
callback(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox);
|
||||
@@ -72,19 +53,3 @@ export const getDiagram = (name: string): DiagramDefinition => {
|
||||
}
|
||||
throw new Error(`Diagram ${name} not found.`);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sScriptSrc
|
||||
*/
|
||||
export const loadDiagram = (sScriptSrc: string) =>
|
||||
new Promise((resolve) => {
|
||||
const oHead = document.getElementsByTagName('HEAD')[0];
|
||||
const oScript = document.createElement('script');
|
||||
oScript.type = 'text/javascript';
|
||||
oScript.src = sScriptSrc;
|
||||
oHead.appendChild(oScript);
|
||||
oScript.onload = () => {
|
||||
resolve(true);
|
||||
};
|
||||
});
|
||||
|
@@ -1,227 +0,0 @@
|
||||
export const lineBreakRegex = /<br\s*\/?>/gi;
|
||||
|
||||
/**
|
||||
* Caches results of functions based on input
|
||||
*
|
||||
* @param {Function} fn Function to run
|
||||
* @param {Function} resolver Function that resolves to an ID given arguments the `fn` takes
|
||||
* @returns {Function} An optimized caching function
|
||||
*/
|
||||
const memoize = (fn, resolver) => {
|
||||
let cache = {};
|
||||
return (...args) => {
|
||||
let n = resolver ? resolver.apply(this, args) : args[0];
|
||||
if (n in cache) {
|
||||
return cache[n];
|
||||
} else {
|
||||
let result = fn(...args);
|
||||
cache[n] = result;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
};
|
||||
/**
|
||||
* This calculates the width of the given text, font size and family.
|
||||
*
|
||||
* @param {any} text - The text to calculate the width of
|
||||
* @param {any} config - The config for fontSize, fontFamily, and fontWeight all impacting the resulting size
|
||||
* @returns {any} - The width for the given text
|
||||
*/
|
||||
export const calculateTextWidth = function (text, config) {
|
||||
config = Object.assign({ fontSize: 12, fontWeight: 400, fontFamily: 'Arial' }, config);
|
||||
return calculateTextDimensions(text, config).width;
|
||||
};
|
||||
|
||||
export const getTextObj = function () {
|
||||
return {
|
||||
x: 0,
|
||||
y: 0,
|
||||
fill: undefined,
|
||||
anchor: 'start',
|
||||
style: '#666',
|
||||
width: 100,
|
||||
height: 100,
|
||||
textMargin: 0,
|
||||
rx: 0,
|
||||
ry: 0,
|
||||
valign: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds text to an element
|
||||
*
|
||||
* @param {SVGElement} elem Element to add text to
|
||||
* @param {{
|
||||
* text: string;
|
||||
* x: number;
|
||||
* y: number;
|
||||
* anchor: 'start' | 'middle' | 'end';
|
||||
* fontFamily: string;
|
||||
* fontSize: string | number;
|
||||
* fontWeight: string | number;
|
||||
* fill: string;
|
||||
* class: string | undefined;
|
||||
* textMargin: number;
|
||||
* }} textData
|
||||
* @returns {SVGTextElement} Text element with given styling and content
|
||||
*/
|
||||
export const drawSimpleText = function (elem, textData) {
|
||||
// Remove and ignore br:s
|
||||
const nText = textData.text.replace(lineBreakRegex, ' ');
|
||||
|
||||
const textElem = elem.append('text');
|
||||
textElem.attr('x', textData.x);
|
||||
textElem.attr('y', textData.y);
|
||||
textElem.style('text-anchor', textData.anchor);
|
||||
textElem.style('font-family', textData.fontFamily);
|
||||
textElem.style('font-size', textData.fontSize);
|
||||
textElem.style('font-weight', textData.fontWeight);
|
||||
textElem.attr('fill', textData.fill);
|
||||
if (typeof textData.class !== 'undefined') {
|
||||
textElem.attr('class', textData.class);
|
||||
}
|
||||
|
||||
const span = textElem.append('tspan');
|
||||
span.attr('x', textData.x + textData.textMargin * 2);
|
||||
span.attr('fill', textData.fill);
|
||||
span.text(nText);
|
||||
|
||||
return textElem;
|
||||
};
|
||||
|
||||
/**
|
||||
* This calculates the dimensions of the given text, font size, font family, font weight, and margins.
|
||||
*
|
||||
* @param {any} text - The text to calculate the width of
|
||||
* @param {any} config - The config for fontSize, fontFamily, fontWeight, and margin all impacting
|
||||
* the resulting size
|
||||
* @returns - The width for the given text
|
||||
*/
|
||||
export const calculateTextDimensions = memoize(
|
||||
function (text, config) {
|
||||
config = Object.assign({ fontSize: 12, fontWeight: 400, fontFamily: 'Arial' }, config);
|
||||
const { fontSize, fontFamily, fontWeight } = config;
|
||||
if (!text) {
|
||||
return { width: 0, height: 0 };
|
||||
}
|
||||
|
||||
// We can't really know if the user supplied font family will render on the user agent;
|
||||
// thus, we'll take the max width between the user supplied font family, and a default
|
||||
// of sans-serif.
|
||||
const fontFamilies = ['sans-serif', fontFamily];
|
||||
const lines = text.split(common.lineBreakRegex);
|
||||
let dims = [];
|
||||
|
||||
const body = select('body');
|
||||
// We don't want to leak DOM elements - if a removal operation isn't available
|
||||
// for any reason, do not continue.
|
||||
if (!body.remove) {
|
||||
return { width: 0, height: 0, lineHeight: 0 };
|
||||
}
|
||||
|
||||
const g = body.append('svg');
|
||||
|
||||
for (let fontFamily of fontFamilies) {
|
||||
let cheight = 0;
|
||||
let dim = { width: 0, height: 0, lineHeight: 0 };
|
||||
for (let line of lines) {
|
||||
const textObj = getTextObj();
|
||||
textObj.text = line;
|
||||
const textElem = drawSimpleText(g, textObj)
|
||||
.style('font-size', fontSize)
|
||||
.style('font-weight', fontWeight)
|
||||
.style('font-family', fontFamily);
|
||||
|
||||
let bBox = (textElem._groups || textElem)[0][0].getBBox();
|
||||
dim.width = Math.round(Math.max(dim.width, bBox.width));
|
||||
cheight = Math.round(bBox.height);
|
||||
dim.height += cheight;
|
||||
dim.lineHeight = Math.round(Math.max(dim.lineHeight, cheight));
|
||||
}
|
||||
dims.push(dim);
|
||||
}
|
||||
|
||||
g.remove();
|
||||
|
||||
let index =
|
||||
isNaN(dims[1].height) ||
|
||||
isNaN(dims[1].width) ||
|
||||
isNaN(dims[1].lineHeight) ||
|
||||
(dims[0].height > dims[1].height &&
|
||||
dims[0].width > dims[1].width &&
|
||||
dims[0].lineHeight > dims[1].lineHeight)
|
||||
? 0
|
||||
: 1;
|
||||
return dims[index];
|
||||
},
|
||||
(text, config) => `${text}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}`
|
||||
);
|
||||
|
||||
const breakString = memoize(
|
||||
(word, maxWidth, hyphenCharacter = '-', config) => {
|
||||
config = Object.assign(
|
||||
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', margin: 0 },
|
||||
config
|
||||
);
|
||||
const characters = word.split('');
|
||||
const lines = [];
|
||||
let currentLine = '';
|
||||
characters.forEach((character, index) => {
|
||||
const nextLine = `${currentLine}${character}`;
|
||||
const lineWidth = calculateTextWidth(nextLine, config);
|
||||
if (lineWidth >= maxWidth) {
|
||||
const currentCharacter = index + 1;
|
||||
const isLastLine = characters.length === currentCharacter;
|
||||
const hyphenatedNextLine = `${nextLine}${hyphenCharacter}`;
|
||||
lines.push(isLastLine ? nextLine : hyphenatedNextLine);
|
||||
currentLine = '';
|
||||
} else {
|
||||
currentLine = nextLine;
|
||||
}
|
||||
});
|
||||
return { hyphenatedStrings: lines, remainingWord: currentLine };
|
||||
},
|
||||
(word, maxWidth, hyphenCharacter = '-', config) =>
|
||||
`${word}-${maxWidth}-${hyphenCharacter}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}`
|
||||
);
|
||||
|
||||
export const wrapLabel = memoize(
|
||||
(label, maxWidth, config) => {
|
||||
if (!label) {
|
||||
return label;
|
||||
}
|
||||
config = Object.assign(
|
||||
{ fontSize: 12, fontWeight: 400, fontFamily: 'Arial', joinWith: '<br/>' },
|
||||
config
|
||||
);
|
||||
if (lineBreakRegex.test(label)) {
|
||||
return label;
|
||||
}
|
||||
const words = label.split(' ');
|
||||
const completedLines = [];
|
||||
let nextLine = '';
|
||||
words.forEach((word, index) => {
|
||||
const wordLength = calculateTextWidth(`${word} `, config);
|
||||
const nextLineLength = calculateTextWidth(nextLine, config);
|
||||
if (wordLength > maxWidth) {
|
||||
const { hyphenatedStrings, remainingWord } = breakString(word, maxWidth, '-', config);
|
||||
completedLines.push(nextLine, ...hyphenatedStrings);
|
||||
nextLine = remainingWord;
|
||||
} else if (nextLineLength + wordLength >= maxWidth) {
|
||||
completedLines.push(nextLine);
|
||||
nextLine = word;
|
||||
} else {
|
||||
nextLine = [nextLine, word].filter(Boolean).join(' ');
|
||||
}
|
||||
const currentWord = index + 1;
|
||||
const isLastWord = currentWord === words.length;
|
||||
if (isLastWord) {
|
||||
completedLines.push(nextLine);
|
||||
}
|
||||
});
|
||||
return completedLines.filter((line) => line !== '').join(config.joinWith);
|
||||
},
|
||||
(label, maxWidth, config) =>
|
||||
`${label}-${maxWidth}-${config.fontSize}-${config.fontWeight}-${config.fontFamily}-${config.joinWith}`
|
||||
);
|
26
packages/mermaid/src/diagram-api/types.ts
Normal file
26
packages/mermaid/src/diagram-api/types.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { MermaidConfig } from '../config.type';
|
||||
|
||||
export interface InjectUtils {
|
||||
_log: any;
|
||||
_setLogLevel: any;
|
||||
_getConfig: any;
|
||||
_sanitizeText: any;
|
||||
_setupGraphViewbox: any;
|
||||
}
|
||||
|
||||
export interface DiagramDefinition {
|
||||
db: any;
|
||||
renderer: any;
|
||||
parser: any;
|
||||
styles: any;
|
||||
init?: (config: MermaidConfig) => void;
|
||||
injectUtils?: (utils: InjectUtils) => void;
|
||||
}
|
||||
|
||||
export interface DetectorRecord {
|
||||
detector: DiagramDetector;
|
||||
loader?: DiagramLoader;
|
||||
}
|
||||
|
||||
export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
|
||||
export type DiagramLoader = (() => Promise<{ id: string; diagram: DiagramDefinition }>) | null;
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const c4Detector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/) !== null;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const classDetectorV2: DiagramDetector = (txt, config) => {
|
||||
// If we have confgured to use dagre-wrapper then we should return true in this function for classDiagram code thus making it use the new class diagram
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const classDetector: DiagramDetector = (txt, config) => {
|
||||
// If we have confgured to use dagre-wrapper then we should never return true in this function
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const erDetector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*erDiagram/) !== null;
|
||||
|
@@ -429,8 +429,7 @@ export const clear = function (ver = 'gen-1') {
|
||||
vertices = {};
|
||||
classes = {};
|
||||
edges = [];
|
||||
funs = [];
|
||||
funs.push(setupToolTips);
|
||||
funs = [setupToolTips];
|
||||
subGraphs = [];
|
||||
subGraphLookup = {};
|
||||
subCount = 0;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const flowDetectorV2: DiagramDetector = (txt, config) => {
|
||||
// If we have confgured to use dagre-wrapper then we should return true in this function for graph code thus making it use the new flowchart diagram
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const flowDetector: DiagramDetector = (txt, config) => {
|
||||
// If we have confired to only use new flow charts this function shohuld always return false
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const ganttDetector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*gantt/) !== null;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const gitGraphDetector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*gitGraph/) !== null;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const infoDetector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*info/) !== null;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const pieDetector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*pie/) !== null;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const requirementDetector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*requirement(Diagram)?/) !== null;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const sequenceDetector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*sequenceDiagram/) !== null;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const stateDetectorV2: DiagramDetector = (text, config) => {
|
||||
if (text.match(/^\s*stateDiagram-v2/) !== null) return true;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const stateDetector: DiagramDetector = (txt, config) => {
|
||||
// If we have confired to only use new state diagrams this function should always return false
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { DiagramDetector } from '../../diagram-api/detectType';
|
||||
import type { DiagramDetector } from '../../diagram-api/types';
|
||||
|
||||
export const journeyDetector: DiagramDetector = (txt) => {
|
||||
return txt.match(/^\s*journey/) !== null;
|
||||
|
@@ -7,14 +7,6 @@ import { log } from './logger';
|
||||
import utils from './utils';
|
||||
import { mermaidAPI } from './mermaidAPI';
|
||||
import { addDetector } from './diagram-api/detectType';
|
||||
import {
|
||||
registerDiagram,
|
||||
DiagramDefinition,
|
||||
setLogLevel,
|
||||
getConfig,
|
||||
setupGraphViewbox,
|
||||
sanitizeText,
|
||||
} from './diagram-api/diagramAPI';
|
||||
import { isDetailedError } from './utils';
|
||||
|
||||
/**
|
||||
@@ -53,17 +45,16 @@ const init = async function (
|
||||
callback?: Function
|
||||
) {
|
||||
try {
|
||||
log.info('Detectors in init', mermaid.detectors); // eslint-disable-line
|
||||
const conf = mermaidAPI.getConfig();
|
||||
if (typeof conf.lazyLoadedDiagrams !== 'undefined' && conf.lazyLoadedDiagrams.length > 0) {
|
||||
for (let i = 0; i < conf.lazyLoadedDiagrams.length; i++) {
|
||||
const { id, detector, loadDiagram } = await import(conf.lazyLoadedDiagrams[i]);
|
||||
if (conf?.lazyLoadedDiagrams && conf.lazyLoadedDiagrams.length > 0) {
|
||||
// Load all lazy loaded diagrams in parallel
|
||||
await Promise.allSettled(
|
||||
conf.lazyLoadedDiagrams.map(async (diagram: string) => {
|
||||
const { id, detector, loadDiagram } = await import(diagram);
|
||||
addDetector(id, detector, loadDiagram);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
mermaid.detectors.forEach(({ id, detector, path }) => {
|
||||
addDetector(id, detector, path);
|
||||
});
|
||||
await initThrowsErrors(config, nodes, callback);
|
||||
} catch (e) {
|
||||
log.warn('Syntax Error rendering');
|
||||
@@ -218,22 +209,6 @@ const parse = (txt: string) => {
|
||||
return mermaidAPI.parse(txt, mermaid.parseError);
|
||||
};
|
||||
|
||||
const connectDiagram = (
|
||||
id: string,
|
||||
diagram: DiagramDefinition,
|
||||
callback: (
|
||||
_log: any,
|
||||
_setLogLevel: any,
|
||||
_getConfig: any,
|
||||
_sanitizeText: any,
|
||||
_setupGraphViewbox: any
|
||||
) => void
|
||||
) => {
|
||||
registerDiagram(id, diagram, callback);
|
||||
// Todo move this connect call to after the diagram is actually loaded.
|
||||
callback(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox);
|
||||
};
|
||||
|
||||
const mermaid: {
|
||||
startOnLoad: boolean;
|
||||
diagrams: any;
|
||||
@@ -247,9 +222,6 @@ const mermaid: {
|
||||
initialize: typeof initialize;
|
||||
contentLoaded: typeof contentLoaded;
|
||||
setParseErrorHandler: typeof setParseErrorHandler;
|
||||
// Array of functions to use for detecting diagram types
|
||||
detectors: Array<any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
connectDiagram: (id: string, diagram: DiagramDefinition, callback: (id: string) => void) => void;
|
||||
} = {
|
||||
startOnLoad: true,
|
||||
diagrams: {},
|
||||
@@ -262,8 +234,6 @@ const mermaid: {
|
||||
parseError: undefined,
|
||||
contentLoaded,
|
||||
setParseErrorHandler,
|
||||
detectors: [],
|
||||
connectDiagram: connectDiagram,
|
||||
};
|
||||
|
||||
export default mermaid;
|
||||
|
@@ -18,7 +18,6 @@ import { compile, serialize, stringify } from 'stylis';
|
||||
import pkg from '../package.json';
|
||||
import * as configApi from './config';
|
||||
import { addDiagrams } from './diagram-api/diagram-orchestration';
|
||||
import { addDetector } from './diagram-api/detectType';
|
||||
import classDb from './diagrams/class/classDb';
|
||||
import flowDb from './diagrams/flowchart/flowDb';
|
||||
import flowRenderer from './diagrams/flowchart/flowRenderer';
|
||||
@@ -34,18 +33,13 @@ import DOMPurify from 'dompurify';
|
||||
import { MermaidConfig } from './config.type';
|
||||
import { evaluate } from './diagrams/common/common';
|
||||
|
||||
let hasLoadedDiagrams = false;
|
||||
|
||||
/**
|
||||
* @param text
|
||||
* @param parseError
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
function parse(text: string, parseError?: Function): boolean {
|
||||
if (!hasLoadedDiagrams) {
|
||||
addDiagrams();
|
||||
hasLoadedDiagrams = true;
|
||||
}
|
||||
const diagram = new Diagram(text, parseError);
|
||||
return diagram.parse(text, parseError);
|
||||
}
|
||||
@@ -122,10 +116,7 @@ const render = async function (
|
||||
cb: (svgCode: string, bindFunctions?: (element: Element) => void) => void,
|
||||
container?: Element
|
||||
): Promise<void> {
|
||||
if (!hasLoadedDiagrams) {
|
||||
addDiagrams();
|
||||
hasLoadedDiagrams = true;
|
||||
}
|
||||
configApi.reset();
|
||||
text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;;
|
||||
const graphInit = utils.detectInit(text);
|
||||
@@ -486,11 +477,7 @@ async function initialize(options: MermaidConfig) {
|
||||
typeof options === 'object' ? configApi.setSiteConfig(options) : configApi.getSiteConfig();
|
||||
|
||||
setLogLevel(config.logLevel);
|
||||
|
||||
if (!hasLoadedDiagrams) {
|
||||
addDiagrams();
|
||||
hasLoadedDiagrams = true;
|
||||
}
|
||||
}
|
||||
|
||||
export const mermaidAPI = Object.freeze({
|
||||
|
@@ -1,108 +0,0 @@
|
||||
{
|
||||
"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"]
|
||||
}
|
Reference in New Issue
Block a user