chore: Rename types to MermaidConfig and MermaidConfigWithDefaults

This commit is contained in:
Sidharth Vinod
2024-05-22 23:56:30 +05:30
parent 159d85e7f7
commit ea7d28bf1c
31 changed files with 218 additions and 192 deletions

View File

@@ -1,7 +1,10 @@
import { load, JSON_SCHEMA } from 'js-yaml'; import { load, JSON_SCHEMA } from 'js-yaml';
import assert from 'node:assert'; import assert from 'node:assert';
import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js'; import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js'; import type {
MermaidConfigWithDefaults,
BaseDiagramConfig,
} from '../packages/mermaid/src/config.type.js';
/** /**
* All of the keys in the mermaid config that have a mermaid diagram config. * All of the keys in the mermaid config that have a mermaid diagram config.
@@ -36,7 +39,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
* @param mermaidConfigSchema - The Mermaid JSON Schema to use. * @param mermaidConfigSchema - The Mermaid JSON Schema to use.
* @returns The default mermaid config object. * @returns The default mermaid config object.
*/ */
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) { function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfigWithDefaults>) {
const ajv = new Ajv2019({ const ajv = new Ajv2019({
useDefaults: true, useDefaults: true,
allowUnionTypes: true, allowUnionTypes: true,
@@ -105,20 +108,23 @@ function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
return mermaidDefaultConfig; return mermaidDefaultConfig;
} }
export const loadSchema = (src: string, filename: string): JSONSchemaType<MermaidConfig> => { export const loadSchema = (
src: string,
filename: string
): JSONSchemaType<MermaidConfigWithDefaults> => {
const jsonSchema = load(src, { const jsonSchema = load(src, {
filename, filename,
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3) // only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`. // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
schema: JSON_SCHEMA, schema: JSON_SCHEMA,
}) as JSONSchemaType<MermaidConfig>; }) as JSONSchemaType<MermaidConfigWithDefaults>;
return jsonSchema; return jsonSchema;
}; };
export const getDefaults = (schema: JSONSchemaType<MermaidConfig>) => { export const getDefaults = (schema: JSONSchemaType<MermaidConfigWithDefaults>) => {
return `export default ${JSON.stringify(generateDefaults(schema), undefined, 2)};`; return `export default ${JSON.stringify(generateDefaults(schema), undefined, 2)};`;
}; };
export const getSchema = (schema: JSONSchemaType<MermaidConfig>) => { export const getSchema = (schema: JSONSchemaType<MermaidConfigWithDefaults>) => {
return `export default ${JSON.stringify(schema, undefined, 2)};`; return `export default ${JSON.stringify(schema, undefined, 2)};`;
}; };

View File

@@ -1,5 +1,5 @@
import type { JSONSchemaType } from 'ajv/dist/2019.js'; import type { JSONSchemaType } from 'ajv/dist/2019.js';
import type { MermaidConfig } from '../packages/mermaid/src/config.type.js'; import type { MermaidConfigWithDefaults } from '../packages/mermaid/src/config.type.js';
import { readFile } from 'node:fs/promises'; import { readFile } from 'node:fs/promises';
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js'; import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
@@ -12,13 +12,13 @@ import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
export const jsonSchemaPlugin = { export const jsonSchemaPlugin = {
name: 'json-schema-plugin', name: 'json-schema-plugin',
setup(build) { setup(build) {
let schema: JSONSchemaType<MermaidConfig> | undefined = undefined; let schema: JSONSchemaType<MermaidConfigWithDefaults> | undefined = undefined;
let content = ''; let content = '';
build.onLoad({ filter: /config\.schema\.yaml$/ }, async (args) => { build.onLoad({ filter: /config\.schema\.yaml$/ }, async (args) => {
// Load the file from the file system // Load the file from the file system
const source = await readFile(args.path, 'utf8'); const source = await readFile(args.path, 'utf8');
const resolvedSchema: JSONSchemaType<MermaidConfig> = const resolvedSchema: JSONSchemaType<MermaidConfigWithDefaults> =
content === source && schema ? schema : loadSchema(source, args.path); content === source && schema ? schema : loadSchema(source, args.path);
if (content !== source) { if (content !== source) {
content = source; content = source;

View File

@@ -10,7 +10,7 @@
### defaultConfig ### defaultConfig
`Const` **defaultConfig**: `MermaidConfig` `Const` **defaultConfig**: `MermaidConfigWithDefaults`
#### Defined in #### Defined in
@@ -26,9 +26,9 @@ Pushes in a directive to the configuration
#### Parameters #### Parameters
| Name | Type | Description | | Name | Type | Description |
| :---------- | :--------------------------------------- | :----------------------- | | :---------- | :--------------------------------------------------- | :----------------------- |
| `directive` | `PartialObjectDeep`<`MermaidConfig`, {}> | The directive to push in | | `directive` | `PartialObjectDeep`<`MermaidConfigWithDefaults`, {}> | The directive to push in |
#### Returns #### Returns
@@ -42,7 +42,7 @@ Pushes in a directive to the configuration
### getConfig ### getConfig
**getConfig**(): `MermaidConfig` **getConfig**(): `MermaidConfigWithDefaults`
## getConfig ## getConfig
@@ -54,7 +54,7 @@ Pushes in a directive to the configuration
#### Returns #### Returns
`MermaidConfig` `MermaidConfigWithDefaults`
The currentConfig The currentConfig
@@ -66,7 +66,7 @@ The currentConfig
### getSiteConfig ### getSiteConfig
**getSiteConfig**(): `MermaidConfig` **getSiteConfig**(): `MermaidConfigWithDefaults`
## getSiteConfig ## getSiteConfig
@@ -78,7 +78,7 @@ The currentConfig
#### Returns #### Returns
`MermaidConfig` `MermaidConfigWithDefaults`
The siteConfig The siteConfig
@@ -108,9 +108,9 @@ The siteConfig
#### Parameters #### Parameters
| Name | Type | Default value | Description | | Name | Type | Default value | Description |
| :------- | :-------------- | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------ | | :------- | :-------------------------- | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `config` | `MermaidConfig` | `siteConfig` | base set of values, which currentConfig could be **reset** to. Defaults to the current siteConfig (e.g returned by [getSiteConfig](config.md#getsiteconfig)). | | `config` | `MermaidConfigWithDefaults` | `siteConfig` | base set of values, which currentConfig could be **reset** to. Defaults to the current siteConfig (e.g returned by [getSiteConfig](config.md#getsiteconfig)). |
#### Returns #### Returns
@@ -157,9 +157,9 @@ options in-place
#### Parameters #### Parameters
| Name | Type | | Name | Type |
| :----- | :--------------------------------------- | | :----- | :--------------------------------------------------- |
| `conf` | `PartialObjectDeep`<`MermaidConfig`, {}> | | `conf` | `PartialObjectDeep`<`MermaidConfigWithDefaults`, {}> |
#### Returns #### Returns
@@ -173,7 +173,7 @@ options in-place
### setConfig ### setConfig
**setConfig**(`conf`): `MermaidConfig` **setConfig**(`conf`): `MermaidConfigWithDefaults`
## setConfig ## setConfig
@@ -187,13 +187,13 @@ corresponding siteConfig value.
#### Parameters #### Parameters
| Name | Type | Description | | Name | Type | Description |
| :----- | :--------------------------------------- | :-------------------------- | | :----- | :--------------------------------------------------- | :-------------------------- |
| `conf` | `PartialObjectDeep`<`MermaidConfig`, {}> | The potential currentConfig | | `conf` | `PartialObjectDeep`<`MermaidConfigWithDefaults`, {}> | The potential currentConfig |
#### Returns #### Returns
`MermaidConfig` `MermaidConfigWithDefaults`
The currentConfig merged with the sanitized conf The currentConfig merged with the sanitized conf
@@ -205,7 +205,7 @@ The currentConfig merged with the sanitized conf
### setSiteConfig ### setSiteConfig
**setSiteConfig**(`conf`): `MermaidConfig` **setSiteConfig**(`conf`): `MermaidConfigWithDefaults`
## setSiteConfig ## setSiteConfig
@@ -220,13 +220,13 @@ function _Default value: At default, will mirror Global Config_
#### Parameters #### Parameters
| Name | Type | Description | | Name | Type | Description |
| :----- | :--------------------------------------- | :------------------------------------------ | | :----- | :--------------------------------------------------- | :------------------------------------------ |
| `conf` | `PartialObjectDeep`<`MermaidConfig`, {}> | The base currentConfig to use as siteConfig | | `conf` | `PartialObjectDeep`<`MermaidConfigWithDefaults`, {}> | The base currentConfig to use as siteConfig |
#### Returns #### Returns
`MermaidConfig` `MermaidConfigWithDefaults`
The new siteConfig The new siteConfig
@@ -238,18 +238,18 @@ The new siteConfig
### updateCurrentConfig ### updateCurrentConfig
**updateCurrentConfig**(`siteCfg`, `_directives`): `MermaidConfig` **updateCurrentConfig**(`siteCfg`, `_directives`): `MermaidConfigWithDefaults`
#### Parameters #### Parameters
| Name | Type | | Name | Type |
| :------------ | :------------------------------------------ | | :------------ | :------------------------------------------------------ |
| `siteCfg` | `MermaidConfig` | | `siteCfg` | `MermaidConfigWithDefaults` |
| `_directives` | `PartialObjectDeep`<`MermaidConfig`, {}>\[] | | `_directives` | `PartialObjectDeep`<`MermaidConfigWithDefaults`, {}>\[] |
#### Returns #### Returns
`MermaidConfig` `MermaidConfigWithDefaults`
#### Defined in #### Defined in
@@ -259,17 +259,17 @@ The new siteConfig
### updateSiteConfig ### updateSiteConfig
**updateSiteConfig**(`conf`): `MermaidConfig` **updateSiteConfig**(`conf`): `MermaidConfigWithDefaults`
#### Parameters #### Parameters
| Name | Type | | Name | Type |
| :----- | :--------------------------------------- | | :----- | :--------------------------------------------------- |
| `conf` | `PartialObjectDeep`<`MermaidConfig`, {}> | | `conf` | `PartialObjectDeep`<`MermaidConfigWithDefaults`, {}> |
#### Returns #### Returns
`MermaidConfig` `MermaidConfigWithDefaults`
#### Defined in #### Defined in

View File

@@ -20,7 +20,7 @@
### default ### default
`Const` **default**: `RequiredDeep`<`MermaidConfig`> `Const` **default**: `RequiredDeep`<`MermaidConfigWithDefaults`>
Default mermaid configuration options. Default mermaid configuration options.

View File

@@ -32,7 +32,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
### mermaidAPI ### mermaidAPI
`Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `MermaidConfig` = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `PartialObjectDeep`<`MermaidConfig`, {}>) => `void` ; `parse`: (`text`: `string`, `parseOptions`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<[`ParseResult`](../interfaces/mermaidAPI.ParseResult.md) | `false`>(`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<[`ParseResult`](../interfaces/mermaidAPI.ParseResult.md)> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `PartialObjectDeep`<`MermaidConfig`, {}>) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `PartialObjectDeep`<`MermaidConfig`, {}>) => `MermaidConfig` = configApi.updateSiteConfig }> `Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfigWithDefaults` = configApi.defaultConfig; `getConfig`: () => `MermaidConfigWithDefaults` = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => `MermaidConfigWithDefaults` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `PartialObjectDeep`<`MermaidConfigWithDefaults`, {}>) => `void` ; `parse`: (`text`: `string`, `parseOptions`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<[`ParseResult`](../interfaces/mermaidAPI.ParseResult.md) | `false`>(`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<[`ParseResult`](../interfaces/mermaidAPI.ParseResult.md)> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `PartialObjectDeep`<`MermaidConfigWithDefaults`, {}>) => `MermaidConfigWithDefaults` = configApi.setConfig; `updateSiteConfig`: (`conf`: `PartialObjectDeep`<`MermaidConfigWithDefaults`, {}>) => `MermaidConfigWithDefaults` = configApi.updateSiteConfig }>
## mermaidAPI configuration defaults ## mermaidAPI configuration defaults
@@ -169,7 +169,7 @@ Create the user styles
| Name | Type | Description | | Name | Type | Description |
| :---------- | :------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------ | | :---------- | :------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------ |
| `config` | `MermaidConfig` | configuration that has style and theme settings to use | | `config` | `MermaidConfigWithDefaults` | configuration that has style and theme settings to use |
| `classDefs` | `undefined` \| `null` \| `Record`<`string`, `DiagramStyleClassDef`> | the classDefs in the diagram text. Might be null if none were defined. Usually is the result of a call to getClasses(...) | | `classDefs` | `undefined` \| `null` \| `Record`<`string`, `DiagramStyleClassDef`> | the classDefs in the diagram text. Might be null if none were defined. Usually is the result of a call to getClasses(...) |
#### Returns #### Returns
@@ -192,7 +192,7 @@ the string with all the user styles
| Name | Type | | Name | Type |
| :---------- | :-------------------------------------------------------- | | :---------- | :-------------------------------------------------------- |
| `config` | `MermaidConfig` | | `config` | `MermaidConfigWithDefaults` |
| `graphType` | `string` | | `graphType` | `string` |
| `classDefs` | `undefined` \| `Record`<`string`, `DiagramStyleClassDef`> | | `classDefs` | `undefined` \| `Record`<`string`, `DiagramStyleClassDef`> |
| `svgId` | `string` | | `svgId` | `string` |

View File

@@ -1,4 +1,4 @@
import type { MermaidConfig } from 'mermaid'; import type { MermaidConfigWithDefaults } from 'mermaid';
const warning = (s: string) => { const warning = (s: string) => {
// Todo remove debug code // Todo remove debug code
@@ -27,7 +27,7 @@ export const log: Record<keyof typeof LEVELS, typeof console.log> = {
}; };
export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void; export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void;
export let getConfig: () => MermaidConfig; export let getConfig: () => MermaidConfigWithDefaults;
export let sanitizeText: (str: string) => string; export let sanitizeText: (str: string) => string;
// eslint-disable @typescript-eslint/no-explicit-any // eslint-disable @typescript-eslint/no-explicit-any
export let setupGraphViewbox: ( export let setupGraphViewbox: (

View File

@@ -25,7 +25,7 @@ import prettier from 'prettier';
const Ajv2019 = _Ajv2019 as unknown as typeof _Ajv2019.default; const Ajv2019 = _Ajv2019 as unknown as typeof _Ajv2019.default;
// !!! -- The config.type.js file is created by this script -- !!! // !!! -- The config.type.js file is created by this script -- !!!
import type { MermaidConfig } from '../src/config.type.js'; import type { MermaidConfigWithDefaults } from '../src/config.type.js';
// options for running the main command // options for running the main command
const verifyOnly = process.argv.includes('--verify'); const verifyOnly = process.argv.includes('--verify');
@@ -33,7 +33,7 @@ const verifyOnly = process.argv.includes('--verify');
const git = process.argv.includes('--git'); const git = process.argv.includes('--git');
/** /**
* Loads the MermaidConfig JSON schema YAML file. * Loads the MermaidConfigWithDefaults JSON schema YAML file.
* *
* @returns The loaded JSON Schema, use {@link validateSchema} to confirm it is a valid JSON Schema. * @returns The loaded JSON Schema, use {@link validateSchema} to confirm it is a valid JSON Schema.
*/ */
@@ -55,7 +55,9 @@ async function loadJsonSchemaFromYaml() {
* @param jsonSchema - The value to validate as JSON Schema 2019-09 * @param jsonSchema - The value to validate as JSON Schema 2019-09
* @throws {Error} if the given object is invalid. * @throws {Error} if the given object is invalid.
*/ */
function validateSchema(jsonSchema: unknown): asserts jsonSchema is JSONSchemaType<MermaidConfig> { function validateSchema(
jsonSchema: unknown
): asserts jsonSchema is JSONSchemaType<MermaidConfigWithDefaults> {
if (typeof jsonSchema !== 'object') { if (typeof jsonSchema !== 'object') {
throw new Error(`jsonSchema param is not an object: actual type is ${typeof jsonSchema}`); throw new Error(`jsonSchema param is not an object: actual type is ${typeof jsonSchema}`);
} }
@@ -85,7 +87,7 @@ function validateSchema(jsonSchema: unknown): asserts jsonSchema is JSONSchemaTy
* *
* @param mermaidConfigSchema - The input JSON Schema. * @param mermaidConfigSchema - The input JSON Schema.
*/ */
async function generateTypescript(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) { async function generateTypescript(mermaidConfigSchema: JSONSchemaType<MermaidConfigWithDefaults>) {
/** /**
* Replace all usages of `allOf` with `extends`. * Replace all usages of `allOf` with `extends`.
* *
@@ -119,7 +121,7 @@ async function generateTypescript(mermaidConfigSchema: JSONSchemaType<MermaidCon
const typescriptFile = await compile( const typescriptFile = await compile(
modifiedSchema as unknown as JSONSchema, // json-schema-to-typescript only allows JSON Schema 4 as input type modifiedSchema as unknown as JSONSchema, // json-schema-to-typescript only allows JSON Schema 4 as input type
'MermaidConfig', 'MermaidConfigWithDefaults',
{ {
additionalProperties: false, // in JSON Schema 2019-09, these are called `unevaluatedProperties` additionalProperties: false, // in JSON Schema 2019-09, these are called `unevaluatedProperties`
unreachableDefinitions: true, // definition for FontConfig is unreachable unreachableDefinitions: true, // definition for FontConfig is unreachable
@@ -173,6 +175,7 @@ async function main() {
} }
const configJsonSchema = await loadJsonSchemaFromYaml(); const configJsonSchema = await loadJsonSchemaFromYaml();
// TODO: Add code to mark objects with default values as required
removeProp(configJsonSchema, 'default'); removeProp(configJsonSchema, 'default');

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-non-null-assertion */
import { expect, it } from 'vitest';
import * as configApi from './config.js'; import * as configApi from './config.js';
import type { MermaidConfig, PartialMermaidConfig } from './config.type.js'; import type { MermaidConfig, MermaidConfigWithDefaults } from './config.type.js';
describe('when working with site config', () => { describe('when working with site config', () => {
beforeEach(() => { beforeEach(() => {
@@ -22,15 +23,15 @@ describe('when working with site config', () => {
securityLevel: 'strict', // can't be changed securityLevel: 'strict', // can't be changed
fontSize: 12345, // can't be changed fontSize: 12345, // can't be changed
secure: [...configApi.defaultConfig.secure!, 'fontSize'], secure: [...configApi.defaultConfig.secure!, 'fontSize'],
} as MermaidConfig; } as MermaidConfigWithDefaults;
configApi.setSiteConfig(config_0); configApi.setSiteConfig(config_0);
const directive: PartialMermaidConfig = { const directive: MermaidConfig = {
fontFamily: 'baf', fontFamily: 'baf',
// fontSize and securityLevel shouldn't be changed // fontSize and securityLevel shouldn't be changed
fontSize: 54321, fontSize: 54321,
securityLevel: 'loose', securityLevel: 'loose',
}; };
const cfg: MermaidConfig = configApi.updateCurrentConfig(config_0, [directive]); const cfg: MermaidConfigWithDefaults = configApi.updateCurrentConfig(config_0, [directive]);
expect(cfg.fontFamily).toEqual(directive.fontFamily); expect(cfg.fontFamily).toEqual(directive.fontFamily);
expect(cfg.fontSize).toBe(config_0.fontSize); expect(cfg.fontSize).toBe(config_0.fontSize);
expect(cfg.securityLevel).toBe(config_0.securityLevel); expect(cfg.securityLevel).toBe(config_0.securityLevel);

View File

@@ -1,27 +1,27 @@
import assignWithDepth from './assignWithDepth.js'; import assignWithDepth from './assignWithDepth.js';
import type { MermaidConfig, PartialMermaidConfig } from './config.type.js'; import type { MermaidConfigWithDefaults, MermaidConfig } from './config.type.js';
import config from './defaultConfig.js'; import config from './defaultConfig.js';
import { log } from './logger.js'; import { log } from './logger.js';
import theme from './themes/index.js'; import theme from './themes/index.js';
import { sanitizeDirective } from './utils/sanitizeDirective.js'; import { sanitizeDirective } from './utils/sanitizeDirective.js';
export const defaultConfig: MermaidConfig = Object.freeze(config); export const defaultConfig: MermaidConfigWithDefaults = Object.freeze(config);
let siteConfig: MermaidConfig = assignWithDepth({}, defaultConfig); let siteConfig: MermaidConfigWithDefaults = assignWithDepth({}, defaultConfig);
let configFromInitialize: PartialMermaidConfig; let configFromInitialize: MermaidConfig;
let directives: PartialMermaidConfig[] = []; let directives: MermaidConfig[] = [];
let currentConfig: MermaidConfig = assignWithDepth({}, defaultConfig); let currentConfig: MermaidConfigWithDefaults = assignWithDepth({}, defaultConfig);
export const updateCurrentConfig = ( export const updateCurrentConfig = (
siteCfg: MermaidConfig, siteCfg: MermaidConfigWithDefaults,
_directives: PartialMermaidConfig[] _directives: MermaidConfig[]
) => { ) => {
// start with config being the siteConfig // start with config being the siteConfig
let cfg: MermaidConfig = assignWithDepth({}, siteCfg); let cfg: MermaidConfigWithDefaults = assignWithDepth({}, siteCfg);
// let sCfg = assignWithDepth(defaultConfig, siteConfigDelta); // let sCfg = assignWithDepth(defaultConfig, siteConfigDelta);
// Join directives // Join directives
let sumOfDirectives: PartialMermaidConfig = {}; let sumOfDirectives: MermaidConfig = {};
for (const d of _directives) { for (const d of _directives) {
sanitize(d); sanitize(d);
// Apply the data from the directive where the overrides the themeVariables // Apply the data from the directive where the overrides the themeVariables
@@ -61,7 +61,7 @@ export const updateCurrentConfig = (
* @param conf - The base currentConfig to use as siteConfig * @param conf - The base currentConfig to use as siteConfig
* @returns The new siteConfig * @returns The new siteConfig
*/ */
export const setSiteConfig = (conf: PartialMermaidConfig): MermaidConfig => { export const setSiteConfig = (conf: MermaidConfig): MermaidConfigWithDefaults => {
siteConfig = assignWithDepth({}, defaultConfig); siteConfig = assignWithDepth({}, defaultConfig);
siteConfig = assignWithDepth(siteConfig, conf); siteConfig = assignWithDepth(siteConfig, conf);
@@ -75,11 +75,11 @@ export const setSiteConfig = (conf: PartialMermaidConfig): MermaidConfig => {
return siteConfig; return siteConfig;
}; };
export const saveConfigFromInitialize = (conf: PartialMermaidConfig): void => { export const saveConfigFromInitialize = (conf: MermaidConfig): void => {
configFromInitialize = assignWithDepth({}, conf); configFromInitialize = assignWithDepth({}, conf);
}; };
export const updateSiteConfig = (conf: PartialMermaidConfig): MermaidConfig => { export const updateSiteConfig = (conf: MermaidConfig): MermaidConfigWithDefaults => {
siteConfig = assignWithDepth(siteConfig, conf); siteConfig = assignWithDepth(siteConfig, conf);
updateCurrentConfig(siteConfig, directives); updateCurrentConfig(siteConfig, directives);
@@ -96,7 +96,7 @@ export const updateSiteConfig = (conf: PartialMermaidConfig): MermaidConfig => {
* *
* @returns The siteConfig * @returns The siteConfig
*/ */
export const getSiteConfig = (): MermaidConfig => { export const getSiteConfig = (): MermaidConfigWithDefaults => {
return assignWithDepth({}, siteConfig); return assignWithDepth({}, siteConfig);
}; };
/** /**
@@ -113,7 +113,7 @@ export const getSiteConfig = (): MermaidConfig => {
* @param conf - The potential currentConfig * @param conf - The potential currentConfig
* @returns The currentConfig merged with the sanitized conf * @returns The currentConfig merged with the sanitized conf
*/ */
export const setConfig = (conf: PartialMermaidConfig): MermaidConfig => { export const setConfig = (conf: MermaidConfig): MermaidConfigWithDefaults => {
checkConfig(conf); checkConfig(conf);
assignWithDepth(currentConfig, conf); assignWithDepth(currentConfig, conf);
@@ -131,7 +131,7 @@ export const setConfig = (conf: PartialMermaidConfig): MermaidConfig => {
* *
* @returns The currentConfig * @returns The currentConfig
*/ */
export const getConfig = (): MermaidConfig => { export const getConfig = (): MermaidConfigWithDefaults => {
return assignWithDepth({}, currentConfig); return assignWithDepth({}, currentConfig);
}; };
/** /**
@@ -188,7 +188,7 @@ export const sanitize = (options: any) => {
* *
* @param directive - The directive to push in * @param directive - The directive to push in
*/ */
export const addDirective = (directive: PartialMermaidConfig) => { export const addDirective = (directive: MermaidConfig) => {
sanitizeDirective(directive); sanitizeDirective(directive);
// If the directive has a fontFamily, but no themeVariables, add the fontFamily to the themeVariables // If the directive has a fontFamily, but no themeVariables, add the fontFamily to the themeVariables
@@ -239,7 +239,7 @@ const issueWarning = (warning: ConfigWarningStrings) => {
issuedWarnings[warning] = true; issuedWarnings[warning] = true;
}; };
const checkConfig = (config: PartialMermaidConfig) => { const checkConfig = (config: MermaidConfig) => {
if (!config) { if (!config) {
return; return;
} }

View File

@@ -24,7 +24,7 @@
* ``` * ```
* *
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "FontCalculator". * via the `definition` "FontCalculator".
*/ */
export type FontCalculator = () => Partial<FontConfig>; export type FontCalculator = () => Partial<FontConfig>;
@@ -32,7 +32,7 @@ export type FontCalculator = () => Partial<FontConfig>;
* Picks the color of the sankey diagram links, using the colors of the source and/or target of the links. * Picks the color of the sankey diagram links, using the colors of the source and/or target of the links.
* *
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "SankeyLinkColor". * via the `definition` "SankeyLinkColor".
*/ */
export type SankeyLinkColor = 'source' | 'target' | 'gradient'; export type SankeyLinkColor = 'source' | 'target' | 'gradient';
@@ -42,7 +42,7 @@ export type SankeyLinkColor = 'source' | 'target' | 'gradient';
* See <https://github.com/d3/d3-sankey#alignments>. * See <https://github.com/d3/d3-sankey#alignments>.
* *
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "SankeyNodeAlignment". * via the `definition` "SankeyNodeAlignment".
*/ */
export type SankeyNodeAlignment = 'left' | 'right' | 'center' | 'justify'; export type SankeyNodeAlignment = 'left' | 'right' | 'center' | 'justify';
@@ -51,18 +51,18 @@ export type SankeyNodeAlignment = 'left' | 'right' | 'center' | 'justify';
*/ */
export type DOMPurifyConfiguration = import('dompurify').Config; export type DOMPurifyConfiguration = import('dompurify').Config;
/** /**
* MermaidConfig with all fields optional * MermaidConfigWithDefaults with all fields optional
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "PartialMermaidConfig". * via the `definition` "MermaidConfig".
*/ */
export type PartialMermaidConfig = import('type-fest').PartialDeep<MermaidConfig>; export type MermaidConfig = import('type-fest').PartialDeep<MermaidConfigWithDefaults>;
/** /**
* The font size to use * The font size to use
*/ */
export type CSSFontSize = string | number; export type CSSFontSize = string | number;
export interface MermaidConfig { export interface MermaidConfigWithDefaults {
/** /**
* Theme, the CSS style sheet. * Theme, the CSS style sheet.
* You may also use `themeCSS` to override this value. * You may also use `themeCSS` to override this value.
@@ -184,7 +184,7 @@ export interface MermaidConfig {
/** /**
* The object containing configurations specific for flowcharts * The object containing configurations specific for flowcharts
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "FlowchartDiagramConfig". * via the `definition` "FlowchartDiagramConfig".
*/ */
export interface FlowchartDiagramConfig extends BaseDiagramConfig { export interface FlowchartDiagramConfig extends BaseDiagramConfig {
@@ -255,7 +255,7 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
wrappingWidth: number; wrappingWidth: number;
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "BaseDiagramConfig". * via the `definition` "BaseDiagramConfig".
*/ */
export interface BaseDiagramConfig { export interface BaseDiagramConfig {
@@ -271,7 +271,7 @@ export interface BaseDiagramConfig {
/** /**
* The object containing configurations specific for sequence diagrams * The object containing configurations specific for sequence diagrams
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "SequenceDiagramConfig". * via the `definition` "SequenceDiagramConfig".
*/ */
export interface SequenceDiagramConfig extends BaseDiagramConfig { export interface SequenceDiagramConfig extends BaseDiagramConfig {
@@ -414,7 +414,7 @@ export interface SequenceDiagramConfig extends BaseDiagramConfig {
* The object containing configurations specific for gantt diagrams * The object containing configurations specific for gantt diagrams
* *
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "GanttDiagramConfig". * via the `definition` "GanttDiagramConfig".
*/ */
export interface GanttDiagramConfig extends BaseDiagramConfig { export interface GanttDiagramConfig extends BaseDiagramConfig {
@@ -499,7 +499,7 @@ export interface GanttDiagramConfig extends BaseDiagramConfig {
* The object containing configurations specific for journey diagrams * The object containing configurations specific for journey diagrams
* *
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "JourneyDiagramConfig". * via the `definition` "JourneyDiagramConfig".
*/ */
export interface JourneyDiagramConfig extends BaseDiagramConfig { export interface JourneyDiagramConfig extends BaseDiagramConfig {
@@ -577,7 +577,7 @@ export interface JourneyDiagramConfig extends BaseDiagramConfig {
sectionColours?: string[]; sectionColours?: string[];
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "TimelineDiagramConfig". * via the `definition` "TimelineDiagramConfig".
*/ */
export interface TimelineDiagramConfig extends BaseDiagramConfig { export interface TimelineDiagramConfig extends BaseDiagramConfig {
@@ -657,7 +657,7 @@ export interface TimelineDiagramConfig extends BaseDiagramConfig {
disableMulticolor?: boolean; disableMulticolor?: boolean;
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "ClassDiagramConfig". * via the `definition` "ClassDiagramConfig".
*/ */
export interface ClassDiagramConfig extends BaseDiagramConfig { export interface ClassDiagramConfig extends BaseDiagramConfig {
@@ -692,7 +692,7 @@ export interface ClassDiagramConfig extends BaseDiagramConfig {
/** /**
* The object containing configurations specific for entity relationship diagrams * The object containing configurations specific for entity relationship diagrams
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "StateDiagramConfig". * via the `definition` "StateDiagramConfig".
*/ */
export interface StateDiagramConfig extends BaseDiagramConfig { export interface StateDiagramConfig extends BaseDiagramConfig {
@@ -731,7 +731,7 @@ export interface StateDiagramConfig extends BaseDiagramConfig {
/** /**
* The object containing configurations specific for entity relationship diagrams * The object containing configurations specific for entity relationship diagrams
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "ErDiagramConfig". * via the `definition` "ErDiagramConfig".
*/ */
export interface ErDiagramConfig extends BaseDiagramConfig { export interface ErDiagramConfig extends BaseDiagramConfig {
@@ -777,7 +777,7 @@ export interface ErDiagramConfig extends BaseDiagramConfig {
fontSize?: number; fontSize?: number;
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "PieDiagramConfig". * via the `definition` "PieDiagramConfig".
*/ */
export interface PieDiagramConfig extends BaseDiagramConfig { export interface PieDiagramConfig extends BaseDiagramConfig {
@@ -788,7 +788,7 @@ export interface PieDiagramConfig extends BaseDiagramConfig {
textPosition?: number; textPosition?: number;
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "QuadrantChartConfig". * via the `definition` "QuadrantChartConfig".
*/ */
export interface QuadrantChartConfig extends BaseDiagramConfig { export interface QuadrantChartConfig extends BaseDiagramConfig {
@@ -868,7 +868,7 @@ export interface QuadrantChartConfig extends BaseDiagramConfig {
/** /**
* This object contains configuration specific to XYCharts * This object contains configuration specific to XYCharts
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "XYChartConfig". * via the `definition` "XYChartConfig".
*/ */
export interface XYChartConfig extends BaseDiagramConfig { export interface XYChartConfig extends BaseDiagramConfig {
@@ -906,7 +906,7 @@ export interface XYChartConfig extends BaseDiagramConfig {
/** /**
* This object contains configuration for XYChart axis config * This object contains configuration for XYChart axis config
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "XYChartAxisConfig". * via the `definition` "XYChartAxisConfig".
*/ */
export interface XYChartAxisConfig { export interface XYChartAxisConfig {
@@ -958,7 +958,7 @@ export interface XYChartAxisConfig {
/** /**
* The object containing configurations specific for req diagrams * The object containing configurations specific for req diagrams
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "RequirementDiagramConfig". * via the `definition` "RequirementDiagramConfig".
*/ */
export interface RequirementDiagramConfig extends BaseDiagramConfig { export interface RequirementDiagramConfig extends BaseDiagramConfig {
@@ -975,7 +975,7 @@ export interface RequirementDiagramConfig extends BaseDiagramConfig {
/** /**
* The object containing configurations specific for mindmap diagrams * The object containing configurations specific for mindmap diagrams
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "MindmapDiagramConfig". * via the `definition` "MindmapDiagramConfig".
*/ */
export interface MindmapDiagramConfig extends BaseDiagramConfig { export interface MindmapDiagramConfig extends BaseDiagramConfig {
@@ -983,7 +983,7 @@ export interface MindmapDiagramConfig extends BaseDiagramConfig {
maxNodeWidth: number; maxNodeWidth: number;
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "GitGraphDiagramConfig". * via the `definition` "GitGraphDiagramConfig".
*/ */
export interface GitGraphDiagramConfig extends BaseDiagramConfig { export interface GitGraphDiagramConfig extends BaseDiagramConfig {
@@ -1007,7 +1007,7 @@ export interface GitGraphDiagramConfig extends BaseDiagramConfig {
arrowMarkerAbsolute?: boolean; arrowMarkerAbsolute?: boolean;
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "NodeLabel". * via the `definition` "NodeLabel".
*/ */
export interface NodeLabel { export interface NodeLabel {
@@ -1019,7 +1019,7 @@ export interface NodeLabel {
/** /**
* The object containing configurations specific for c4 diagrams * The object containing configurations specific for c4 diagrams
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "C4DiagramConfig". * via the `definition` "C4DiagramConfig".
*/ */
export interface C4DiagramConfig extends BaseDiagramConfig { export interface C4DiagramConfig extends BaseDiagramConfig {
@@ -1400,7 +1400,7 @@ export interface C4DiagramConfig extends BaseDiagramConfig {
/** /**
* The object containing configurations specific for sankey diagrams. * The object containing configurations specific for sankey diagrams.
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "SankeyDiagramConfig". * via the `definition` "SankeyDiagramConfig".
*/ */
export interface SankeyDiagramConfig extends BaseDiagramConfig { export interface SankeyDiagramConfig extends BaseDiagramConfig {
@@ -1432,7 +1432,7 @@ export interface SankeyDiagramConfig extends BaseDiagramConfig {
/** /**
* The object containing configurations specific for packet diagrams. * The object containing configurations specific for packet diagrams.
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "PacketDiagramConfig". * via the `definition` "PacketDiagramConfig".
*/ */
export interface PacketDiagramConfig extends BaseDiagramConfig { export interface PacketDiagramConfig extends BaseDiagramConfig {
@@ -1464,14 +1464,14 @@ export interface PacketDiagramConfig extends BaseDiagramConfig {
/** /**
* The object containing configurations specific for block diagrams. * The object containing configurations specific for block diagrams.
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "BlockDiagramConfig". * via the `definition` "BlockDiagramConfig".
*/ */
export interface BlockDiagramConfig extends BaseDiagramConfig { export interface BlockDiagramConfig extends BaseDiagramConfig {
padding?: number; padding?: number;
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfigWithDefaults`'s JSON-Schema
* via the `definition` "FontConfig". * via the `definition` "FontConfig".
*/ */
export interface FontConfig { export interface FontConfig {

View File

@@ -1,8 +1,5 @@
import type { RequiredDeep } from 'type-fest'; import type { MermaidConfigWithDefaults } from './config.type.js';
import theme from './themes/index.js'; import theme from './themes/index.js';
import type { MermaidConfig } from './config.type.js';
// Uses our custom Vite jsonSchemaPlugin to load only the default values from // Uses our custom Vite jsonSchemaPlugin to load only the default values from
// our JSON Schema // our JSON Schema
// @ts-expect-error This file is automatically generated via a custom Vite plugin // @ts-expect-error This file is automatically generated via a custom Vite plugin
@@ -15,7 +12,7 @@ import defaultConfigJson from './schemas/config.schema.yaml?only-defaults=true';
* Non-JSON JS default values are listed in this file, e.g. functions, or * Non-JSON JS default values are listed in this file, e.g. functions, or
* `undefined` (explicitly set so that `configKeys` finds them). * `undefined` (explicitly set so that `configKeys` finds them).
*/ */
const config: RequiredDeep<MermaidConfig> = { const config: MermaidConfigWithDefaults = {
...defaultConfigJson, ...defaultConfigJson,
// Set, even though they're `undefined` so that `configKeys` finds these keys // Set, even though they're `undefined` so that `configKeys` finds these keys
// TODO: Should we replace these with `null` so that they can go in the JSON Schema? // TODO: Should we replace these with `null` so that they can go in the JSON Schema?

View File

@@ -1,4 +1,4 @@
import type { MermaidConfig } from '../config.type.js'; import type { MermaidConfigWithDefaults } from '../config.type.js';
import { UnknownDiagramError } from '../errors.js'; import { UnknownDiagramError } from '../errors.js';
import { log } from '../logger.js'; import { log } from '../logger.js';
import { anyCommentRegex, directiveRegex, frontMatterRegex } from './regexes.js'; import { anyCommentRegex, directiveRegex, frontMatterRegex } from './regexes.js';
@@ -33,7 +33,7 @@ export const detectors: Record<string, DetectorRecord> = {};
* @param config - The mermaid config. * @param config - The mermaid config.
* @returns A graph definition key * @returns A graph definition key
*/ */
export const detectType = function (text: string, config?: MermaidConfig): string { export const detectType = function (text: string, config?: MermaidConfigWithDefaults): string {
text = text text = text
.replace(frontMatterRegex, '') .replace(frontMatterRegex, '')
.replace(directiveRegex, '') .replace(directiveRegex, '')

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'; import { describe, expect, it, beforeAll } from 'vitest';
import type { MermaidConfig } from '../config.type.js'; import type { MermaidConfigWithDefaults } from '../config.type.js';
import { detectType } from './detectType.js'; import { detectType } from './detectType.js';
import { addDiagrams } from './diagram-orchestration.js'; import { addDiagrams } from './diagram-orchestration.js';
@@ -50,13 +50,13 @@ describe('diagram-orchestration', () => {
expect( expect(
detectType('graph TD; A-->B', { detectType('graph TD; A-->B', {
flowchart: { defaultRenderer: 'dagre-d3' }, flowchart: { defaultRenderer: 'dagre-d3' },
} as MermaidConfig) } as MermaidConfigWithDefaults)
).toBe('flowchart'); ).toBe('flowchart');
// flowchart & dagre-d3 => error // flowchart & dagre-d3 => error
expect(() => expect(() =>
detectType('flowchart TD; A-->B', { detectType('flowchart TD; A-->B', {
flowchart: { defaultRenderer: 'dagre-d3' }, flowchart: { defaultRenderer: 'dagre-d3' },
} as MermaidConfig) } as MermaidConfigWithDefaults)
).toThrowErrorMatchingInlineSnapshot( ).toThrowErrorMatchingInlineSnapshot(
`[UnknownDiagramError: No diagram type detected matching given configuration for text: flowchart TD; A-->B]` `[UnknownDiagramError: No diagram type detected matching given configuration for text: flowchart TD; A-->B]`
); );
@@ -65,7 +65,7 @@ describe('diagram-orchestration', () => {
expect( expect(
detectType('graph TD; A-->B', { detectType('graph TD; A-->B', {
flowchart: { defaultRenderer: 'dagre-wrapper' }, flowchart: { defaultRenderer: 'dagre-wrapper' },
} as MermaidConfig) } as MermaidConfigWithDefaults)
).toBe('flowchart-v2'); ).toBe('flowchart-v2');
// flowchart ==> flowchart-v2 // flowchart ==> flowchart-v2
expect(detectType('flowchart TD; A-->B')).toBe('flowchart-v2'); expect(detectType('flowchart TD; A-->B')).toBe('flowchart-v2');
@@ -73,13 +73,13 @@ describe('diagram-orchestration', () => {
expect( expect(
detectType('flowchart TD; A-->B', { detectType('flowchart TD; A-->B', {
flowchart: { defaultRenderer: 'dagre-wrapper' }, flowchart: { defaultRenderer: 'dagre-wrapper' },
} as MermaidConfig) } as MermaidConfigWithDefaults)
).toBe('flowchart-v2'); ).toBe('flowchart-v2');
// flowchart && elk ==> flowchart-elk // flowchart && elk ==> flowchart-elk
expect( expect(
detectType('flowchart TD; A-->B', { detectType('flowchart TD; A-->B', {
flowchart: { defaultRenderer: 'elk' }, flowchart: { defaultRenderer: 'elk' },
} as MermaidConfig) } as MermaidConfigWithDefaults)
).toBe('flowchart-elk'); ).toBe('flowchart-elk');
}); });

View File

@@ -1,4 +1,4 @@
import type { GanttDiagramConfig, PartialMermaidConfig } from '../config.type.js'; import type { GanttDiagramConfig, MermaidConfig } from '../config.type.js';
import { frontMatterRegex } from './regexes.js'; import { frontMatterRegex } from './regexes.js';
// The "* as yaml" part is necessary for tree-shaking // The "* as yaml" part is necessary for tree-shaking
import * as yaml from 'js-yaml'; import * as yaml from 'js-yaml';
@@ -7,7 +7,7 @@ interface FrontMatterMetadata {
title?: string; title?: string;
// Allows custom display modes. Currently used for compact mode in gantt charts. // Allows custom display modes. Currently used for compact mode in gantt charts.
displayMode?: GanttDiagramConfig['displayMode']; displayMode?: GanttDiagramConfig['displayMode'];
config?: PartialMermaidConfig; config?: MermaidConfig;
} }
export interface FrontMatterResult { export interface FrontMatterResult {

View File

@@ -2,11 +2,11 @@
import type * as d3 from 'd3'; import type * as d3 from 'd3';
import type { SetRequired } from 'type-fest'; import type { SetRequired } from 'type-fest';
import type { Diagram } from '../Diagram.js'; import type { Diagram } from '../Diagram.js';
import type { BaseDiagramConfig, PartialMermaidConfig } from '../config.type.js'; import type { BaseDiagramConfig, MermaidConfig } from '../config.type.js';
export interface DiagramMetadata { export interface DiagramMetadata {
title?: string; title?: string;
config?: PartialMermaidConfig; config?: MermaidConfig;
} }
export interface InjectUtils { export interface InjectUtils {
@@ -78,7 +78,7 @@ export interface DiagramDefinition {
renderer: DiagramRenderer; renderer: DiagramRenderer;
parser: ParserDefinition; parser: ParserDefinition;
styles?: any; styles?: any;
init?: (config: PartialMermaidConfig) => void; init?: (config: MermaidConfig) => void;
injectUtils?: ( injectUtils?: (
_log: InjectUtils['_log'], _log: InjectUtils['_log'],
_setLogLevel: InjectUtils['_setLogLevel'], _setLogLevel: InjectUtils['_setLogLevel'],
@@ -102,7 +102,7 @@ export interface ExternalDiagramDefinition {
loader: DiagramLoader; loader: DiagramLoader;
} }
export type DiagramDetector = (text: string, config?: PartialMermaidConfig) => boolean; export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
export type DiagramLoader = () => Promise<{ id: string; diagram: DiagramDefinition }>; export type DiagramLoader = () => Promise<{ id: string; diagram: DiagramDefinition }>;
/** /**

View File

@@ -5,7 +5,7 @@ import {
} from 'd3'; } from 'd3';
import type { Diagram } from '../../Diagram.js'; import type { Diagram } from '../../Diagram.js';
import * as configApi from '../../config.js'; import * as configApi from '../../config.js';
import type { MermaidConfig } from '../../config.type.js'; import type { MermaidConfigWithDefaults } from '../../config.type.js';
import insertMarkers from '../../dagre-wrapper/markers.js'; import insertMarkers from '../../dagre-wrapper/markers.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { configureSvgSize } from '../../setupGraphViewbox.js'; import { configureSvgSize } from '../../setupGraphViewbox.js';
@@ -75,7 +75,7 @@ export const draw = async function (
const magicFactor = Math.max(1, Math.round(0.125 * (bounds2.width / bounds2.height))); const magicFactor = Math.max(1, Math.round(0.125 * (bounds2.width / bounds2.height)));
const height = bounds2.height + magicFactor + 10; const height = bounds2.height + magicFactor + 10;
const width = bounds2.width + 10; const width = bounds2.width + 10;
const { useMaxWidth } = conf as Exclude<MermaidConfig['block'], undefined>; const { useMaxWidth } = conf as Exclude<MermaidConfigWithDefaults['block'], undefined>;
configureSvgSize(svg, height, width, !!useMaxWidth); configureSvgSize(svg, height, width, !!useMaxWidth);
log.debug('Here Bounds', bounds, bounds2); log.debug('Here Bounds', bounds, bounds2);
svg.attr( svg.attr(

View File

@@ -1,4 +1,5 @@
import type { MermaidConfig } from '../../config.type.js'; import { describe, expect, it } from 'vitest';
import type { MermaidConfigWithDefaults } from '../../config.type.js';
import { countOccurrence, parseGenericTypes, removeScript, sanitizeText } from './common.js'; import { countOccurrence, parseGenericTypes, removeScript, sanitizeText } from './common.js';
describe('when securityLevel is antiscript, all script must be removed', () => { describe('when securityLevel is antiscript, all script must be removed', () => {
@@ -68,7 +69,7 @@ describe('Sanitize text', () => {
const result = sanitizeText(maliciousStr, { const result = sanitizeText(maliciousStr, {
securityLevel: 'strict', securityLevel: 'strict',
flowchart: { htmlLabels: true }, flowchart: { htmlLabels: true },
} as MermaidConfig); } as MermaidConfigWithDefaults);
expect(result).not.toContain('javascript:alert(1)'); expect(result).not.toContain('javascript:alert(1)');
}); });
}); });

View File

@@ -1,5 +1,5 @@
import DOMPurify from 'dompurify'; import DOMPurify from 'dompurify';
import type { MermaidConfig } from '../../config.type.js'; import type { MermaidConfigWithDefaults } from '../../config.type.js';
// Remove and ignore br:s // Remove and ignore br:s
export const lineBreakRegex = /<br\s*\/?>/gi; export const lineBreakRegex = /<br\s*\/?>/gi;
@@ -63,7 +63,7 @@ export const removeScript = (txt: string): string => {
return sanitizedText; return sanitizedText;
}; };
const sanitizeMore = (text: string, config: MermaidConfig) => { const sanitizeMore = (text: string, config: MermaidConfigWithDefaults) => {
if (config.flowchart?.htmlLabels !== false) { if (config.flowchart?.htmlLabels !== false) {
const level = config.securityLevel; const level = config.securityLevel;
if (level === 'antiscript' || level === 'strict') { if (level === 'antiscript' || level === 'strict') {
@@ -78,7 +78,7 @@ const sanitizeMore = (text: string, config: MermaidConfig) => {
return text; return text;
}; };
export const sanitizeText = (text: string, config: MermaidConfig): string => { export const sanitizeText = (text: string, config: MermaidConfigWithDefaults): string => {
if (!text) { if (!text) {
return text; return text;
} }
@@ -94,7 +94,7 @@ export const sanitizeText = (text: string, config: MermaidConfig): string => {
export const sanitizeTextOrArray = ( export const sanitizeTextOrArray = (
a: string | string[] | string[][], a: string | string[] | string[][],
config: MermaidConfig config: MermaidConfigWithDefaults
): string | string[] => { ): string | string[] => {
if (typeof a === 'string') { if (typeof a === 'string') {
return sanitizeText(a, config); return sanitizeText(a, config);
@@ -310,7 +310,10 @@ export const hasKatex = (text: string): boolean => (text.match(katexRegex)?.leng
* @param config - Configuration for Mermaid * @param config - Configuration for Mermaid
* @returns Object containing \{width, height\} * @returns Object containing \{width, height\}
*/ */
export const calculateMathMLDimensions = async (text: string, config: MermaidConfig) => { export const calculateMathMLDimensions = async (
text: string,
config: MermaidConfigWithDefaults
) => {
text = await renderKatex(text, config); text = await renderKatex(text, config);
const divElem = document.createElement('div'); const divElem = document.createElement('div');
divElem.innerHTML = text; divElem.innerHTML = text;
@@ -332,7 +335,10 @@ export const calculateMathMLDimensions = async (text: string, config: MermaidCon
* @param config - Configuration for Mermaid * @param config - Configuration for Mermaid
* @returns String containing MathML if KaTeX is supported, or an error message if it is not and stylesheets aren't present * @returns String containing MathML if KaTeX is supported, or an error message if it is not and stylesheets aren't present
*/ */
export const renderKatex = async (text: string, config: MermaidConfig): Promise<string> => { export const renderKatex = async (
text: string,
config: MermaidConfigWithDefaults
): Promise<string> => {
if (!hasKatex(text)) { if (!hasKatex(text)) {
return text; return text;
} }

View File

@@ -1,8 +1,8 @@
import cytoscape from 'cytoscape'; import cytoscape from 'cytoscape';
// @ts-expect-error No types available // @ts-ignore Types for cose-bilkent are not present
import coseBilkent from 'cytoscape-cose-bilkent'; import coseBilkent from 'cytoscape-cose-bilkent';
import { select } from 'd3'; import { select } from 'd3';
import type { MermaidConfig } from '../../config.type.js'; import type { MermaidConfigWithDefaults } from '../../config.type.js';
import { getConfig } from '../../diagram-api/diagramAPI.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import type { DrawDefinition } from '../../diagram-api/types.js'; import type { DrawDefinition } from '../../diagram-api/types.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
@@ -21,7 +21,7 @@ function drawNodes(
svg: D3Element, svg: D3Element,
mindmap: FilledMindMapNode, mindmap: FilledMindMapNode,
section: number, section: number,
conf: MermaidConfig conf: MermaidConfigWithDefaults
) { ) {
drawNode(db, svg, mindmap, section, conf); drawNode(db, svg, mindmap, section, conf);
if (mindmap.children) { if (mindmap.children) {
@@ -64,7 +64,12 @@ function drawEdges(edgesEl: D3Element, cy: cytoscape.Core) {
}); });
} }
function addNodes(mindmap: MindmapNode, cy: cytoscape.Core, conf: MermaidConfig, level: number) { function addNodes(
mindmap: MindmapNode,
cy: cytoscape.Core,
conf: MermaidConfigWithDefaults,
level: number
) {
cy.add({ cy.add({
group: 'nodes', group: 'nodes',
data: { data: {
@@ -99,7 +104,10 @@ function addNodes(mindmap: MindmapNode, cy: cytoscape.Core, conf: MermaidConfig,
} }
} }
function layoutMindmap(node: MindmapNode, conf: MermaidConfig): Promise<cytoscape.Core> { function layoutMindmap(
node: MindmapNode,
conf: MermaidConfigWithDefaults
): Promise<cytoscape.Core> {
return new Promise((resolve) => { return new Promise((resolve) => {
// Add temporary render element // Add temporary render element
const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none'); const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none');

View File

@@ -3,7 +3,7 @@ import { createText } from '../../rendering-util/createText.js';
import type { FilledMindMapNode, MindmapDB } from './mindmapTypes.js'; import type { FilledMindMapNode, MindmapDB } from './mindmapTypes.js';
import type { Point } from '../../types.js'; import type { Point } from '../../types.js';
import { parseFontSize } from '../../utils.js'; import { parseFontSize } from '../../utils.js';
import type { MermaidConfig } from '../../config.type.js'; import type { MermaidConfigWithDefaults } from '../../config.type.js';
const MAX_SECTIONS = 12; const MAX_SECTIONS = 12;
@@ -180,7 +180,7 @@ export const drawNode = function (
elem: D3Element, elem: D3Element,
node: FilledMindMapNode, node: FilledMindMapNode,
fullSection: number, fullSection: number,
conf: MermaidConfig conf: MermaidConfigWithDefaults
): number { ): number {
const htmlLabels = conf.htmlLabels; const htmlLabels = conf.htmlLabels;
const section = fullSection % (MAX_SECTIONS - 1); const section = fullSection % (MAX_SECTIONS - 1);

View File

@@ -6,7 +6,7 @@ import { getConfig } from '../../diagram-api/diagramAPI.js';
import { cleanAndMerge, parseFontSize } from '../../utils.js'; import { cleanAndMerge, parseFontSize } from '../../utils.js';
import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js'; import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js';
import type { D3Section, PieDB, Sections } from './pieTypes.js'; import type { D3Section, PieDB, Sections } from './pieTypes.js';
import type { MermaidConfig, PieDiagramConfig } from '../../config.type.js'; import type { MermaidConfigWithDefaults, PieDiagramConfig } from '../../config.type.js';
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js'; import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
const createPieArcs = (sections: Sections): d3.PieArcDatum<D3Section>[] => { const createPieArcs = (sections: Sections): d3.PieArcDatum<D3Section>[] => {
@@ -38,7 +38,7 @@ const createPieArcs = (sections: Sections): d3.PieArcDatum<D3Section>[] => {
export const draw: DrawDefinition = (text, id, _version, diagObj) => { export const draw: DrawDefinition = (text, id, _version, diagObj) => {
log.debug('rendering pie chart\n' + text); log.debug('rendering pie chart\n' + text);
const db = diagObj.db as PieDB; const db = diagObj.db as PieDB;
const globalConfig: MermaidConfig = getConfig(); const globalConfig: MermaidConfigWithDefaults = getConfig();
const pieConfig: Required<PieDiagramConfig> = cleanAndMerge(db.getConfig(), globalConfig.pie); const pieConfig: Required<PieDiagramConfig> = cleanAndMerge(db.getConfig(), globalConfig.pie);
const MARGIN = 40; const MARGIN = 40;
const LEGEND_RECT_SIZE = 18; const LEGEND_RECT_SIZE = 18;

View File

@@ -6,7 +6,7 @@ import { log } from '../../logger.js';
import { getConfig } from '../../diagram-api/diagramAPI.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { setupGraphViewbox } from '../../setupGraphViewbox.js'; import { setupGraphViewbox } from '../../setupGraphViewbox.js';
import type { Diagram } from '../../Diagram.js'; import type { Diagram } from '../../Diagram.js';
import type { MermaidConfig } from '../../config.type.js'; import type { MermaidConfigWithDefaults } from '../../config.type.js';
interface Block<TDesc, TSection> { interface Block<TDesc, TSection> {
number: number; number: number;
@@ -241,7 +241,7 @@ export const drawTasks = function (
masterX: number, masterX: number,
masterY: number, masterY: number,
maxTaskHeight: number, maxTaskHeight: number,
conf: MermaidConfig, conf: MermaidConfigWithDefaults,
maxEventCount: number, maxEventCount: number,
maxEventLineLength: number, maxEventLineLength: number,
maxSectionHeight: number, maxSectionHeight: number,
@@ -318,7 +318,7 @@ export const drawEvents = function (
sectionColor: number, sectionColor: number,
masterX: number, masterX: number,
masterY: number, masterY: number,
conf: MermaidConfig conf: MermaidConfigWithDefaults
) { ) {
let maxEventHeight = 0; let maxEventHeight = 0;
const eventBeginY = masterY; const eventBeginY = masterY;

View File

@@ -1,9 +1,13 @@
import mermaid, { type MermaidConfig } from 'mermaid'; import mermaid, { type MermaidConfigWithDefaults } from 'mermaid';
import zenuml from '../../../../../mermaid-zenuml/dist/mermaid-zenuml.core.mjs'; import zenuml from '../../../../../mermaid-zenuml/dist/mermaid-zenuml.core.mjs';
const init = mermaid.registerExternalDiagrams([zenuml]); const init = mermaid.registerExternalDiagrams([zenuml]);
export const render = async (id: string, code: string, config: MermaidConfig): Promise<string> => { export const render = async (
id: string,
code: string,
config: MermaidConfigWithDefaults
): Promise<string> => {
await init; await init;
mermaid.initialize(config); mermaid.initialize(config);
const { svg } = await mermaid.render(id, code); const { svg } = await mermaid.render(id, code);

View File

@@ -3,7 +3,7 @@
* functionality and to render the diagrams to svg code! * functionality and to render the diagrams to svg code!
*/ */
import { dedent } from 'ts-dedent'; import { dedent } from 'ts-dedent';
import type { MermaidConfig } from './config.type.js'; import type { MermaidConfigWithDefaults, MermaidConfig } from './config.type.js';
import { log } from './logger.js'; import { log } from './logger.js';
import utils from './utils.js'; import utils from './utils.js';
import type { ParseOptions, ParseResult, RenderResult } from './mermaidAPI.js'; import type { ParseOptions, ParseResult, RenderResult } from './mermaidAPI.js';
@@ -18,6 +18,7 @@ import type { UnknownDiagramError } from './errors.js';
import { addDiagrams } from './diagram-api/diagram-orchestration.js'; import { addDiagrams } from './diagram-api/diagram-orchestration.js';
export type { export type {
MermaidConfigWithDefaults,
MermaidConfig, MermaidConfig,
DetailedError, DetailedError,
ExternalDiagramDefinition, ExternalDiagramDefinition,
@@ -330,8 +331,8 @@ const executeQueue = async () => {
* // throws Error * // throws Error
* ``` * ```
*/ */
const parse: typeof mermaidAPI.parse = async (text, parseOptions) => { const parse = async (text: string, parseOptions?: ParseOptions & { suppressErrors: true }) => {
return new Promise((resolve, reject) => { return new Promise<ParseResult | false>((resolve, reject) => {
// This promise will resolve when the render call is done. // This promise will resolve when the render call is done.
// It will be queued first and will be executed when it is first in line // It will be queued first and will be executed when it is first in line
const performCall = () => const performCall = () =>

View File

@@ -35,7 +35,7 @@ vi.mock('./diagrams/state/stateRenderer-v2.js');
// ------------------------------------- // -------------------------------------
import assignWithDepth from './assignWithDepth.js'; import assignWithDepth from './assignWithDepth.js';
import type { MermaidConfig } from './config.type.js'; import type { MermaidConfigWithDefaults } from './config.type.js';
import mermaid from './mermaid.js'; import mermaid from './mermaid.js';
import mermaidAPI, { import mermaidAPI, {
appendDivSvgG, appendDivSvgG,
@@ -288,7 +288,7 @@ describe('mermaidAPI', () => {
fontFamily: serif, fontFamily: serif,
altFontFamily: sansSerif, altFontFamily: sansSerif,
htmlLabels: true, htmlLabels: true,
} as MermaidConfig; } as MermaidConfigWithDefaults;
it('gets the cssStyles from the theme', () => { it('gets the cssStyles from the theme', () => {
const styles = createCssStyles(mocked_config_with_htmlLabels, null); const styles = createCssStyles(mocked_config_with_htmlLabels, null);
@@ -367,7 +367,7 @@ describe('mermaidAPI', () => {
} }
// common suite and tests to verify that the right styles are created with the right htmlElements // common suite and tests to verify that the right styles are created with the right htmlElements
function expect_correct_styles_with_htmlElements(mocked_config: MermaidConfig) { function expect_correct_styles_with_htmlElements(mocked_config: MermaidConfigWithDefaults) {
describe('creates styles for "> *" and "span" elements', () => { describe('creates styles for "> *" and "span" elements', () => {
const htmlElements = ['> *', 'span']; const htmlElements = ['> *', 'span'];
@@ -396,7 +396,7 @@ describe('mermaidAPI', () => {
flowchart: { flowchart: {
htmlLabels: true, htmlLabels: true,
}, },
} as MermaidConfig; } as MermaidConfigWithDefaults;
expect_correct_styles_with_htmlElements(mocked_config_flowchart_htmlLabels); expect_correct_styles_with_htmlElements(mocked_config_flowchart_htmlLabels);
}); });
@@ -405,7 +405,7 @@ describe('mermaidAPI', () => {
themeCSS: 'default', themeCSS: 'default',
fontFamily: 'serif', fontFamily: 'serif',
altFontFamily: 'sans-serif', altFontFamily: 'sans-serif',
} as MermaidConfig; } as MermaidConfigWithDefaults;
describe('creates styles for shape elements "rect", "polygon", "ellipse", and "circle"', () => { describe('creates styles for shape elements "rect", "polygon", "ellipse", and "circle"', () => {
const htmlElements = ['rect', 'polygon', 'ellipse', 'circle']; const htmlElements = ['rect', 'polygon', 'ellipse', 'circle'];
@@ -430,7 +430,7 @@ describe('mermaidAPI', () => {
themeCSS: 'default', themeCSS: 'default',
htmlLabels: true, htmlLabels: true,
themeVariables: { fontFamily: 'serif' }, themeVariables: { fontFamily: 'serif' },
} as MermaidConfig; } as MermaidConfigWithDefaults;
const classDef1 = { id: 'classDef1', styles: ['style1-1'], textStyles: [] }; const classDef1 = { id: 'classDef1', styles: ['style1-1'], textStyles: [] };

View File

@@ -20,7 +20,7 @@ import { version } from '../package.json';
import { Diagram } from './Diagram.js'; import { Diagram } from './Diagram.js';
import { addSVGa11yTitleDescription, setA11yDiagramInfo } from './accessibility.js'; import { addSVGa11yTitleDescription, setA11yDiagramInfo } from './accessibility.js';
import * as configApi from './config.js'; import * as configApi from './config.js';
import type { MermaidConfig, PartialMermaidConfig } from './config.type.js'; import type { MermaidConfigWithDefaults, MermaidConfig } from './config.type.js';
import { addDiagrams } from './diagram-api/diagram-orchestration.js'; import { addDiagrams } from './diagram-api/diagram-orchestration.js';
import type { DiagramMetadata, DiagramStyleClassDef } from './diagram-api/types.js'; import type { DiagramMetadata, DiagramStyleClassDef } from './diagram-api/types.js';
import { evaluate } from './diagrams/common/common.js'; import { evaluate } from './diagrams/common/common.js';
@@ -151,7 +151,7 @@ export const cssImportantStyles = (
* @returns the string with all the user styles * @returns the string with all the user styles
*/ */
export const createCssStyles = ( export const createCssStyles = (
config: MermaidConfig, config: MermaidConfigWithDefaults,
classDefs: Record<string, DiagramStyleClassDef> | null | undefined = {} classDefs: Record<string, DiagramStyleClassDef> | null | undefined = {}
): string => { ): string => {
let cssStyles = ''; let cssStyles = '';
@@ -198,7 +198,7 @@ export const createCssStyles = (
}; };
export const createUserStyles = ( export const createUserStyles = (
config: MermaidConfig, config: MermaidConfigWithDefaults,
graphType: string, graphType: string,
classDefs: Record<string, DiagramStyleClassDef> | undefined, classDefs: Record<string, DiagramStyleClassDef> | undefined,
svgId: string svgId: string
@@ -517,7 +517,7 @@ const render = async function (
/** /**
* @param options - Initial Mermaid options * @param options - Initial Mermaid options
*/ */
function initialize(options: PartialMermaidConfig = {}) { function initialize(options: MermaidConfig = {}) {
// Handle legacy location of font-family configuration // Handle legacy location of font-family configuration
if (options?.fontFamily && !options.themeVariables?.fontFamily) { if (options?.fontFamily && !options.themeVariables?.fontFamily) {
if (!options.themeVariables) { if (!options.themeVariables) {

View File

@@ -1,4 +1,4 @@
import type { PartialMermaidConfig } from './config.type.js'; import type { MermaidConfig } from './config.type.js';
import { cleanupComments } from './diagram-api/comments.js'; import { cleanupComments } from './diagram-api/comments.js';
import { extractFrontMatter } from './diagram-api/frontmatter.js'; import { extractFrontMatter } from './diagram-api/frontmatter.js';
import type { DiagramMetadata } from './diagram-api/types.js'; import type { DiagramMetadata } from './diagram-api/types.js';
@@ -31,7 +31,7 @@ const processFrontmatter = (code: string) => {
}; };
const processDirectives = (code: string) => { const processDirectives = (code: string) => {
const initDirective: PartialMermaidConfig = utils.detectInit(code) ?? {}; const initDirective: MermaidConfig = utils.detectInit(code) ?? {};
const wrapDirectives = utils.detectDirective(code, 'wrap'); const wrapDirectives = utils.detectDirective(code, 'wrap');
if (Array.isArray(wrapDirectives)) { if (Array.isArray(wrapDirectives)) {
initDirective.wrap = wrapDirectives.some(({ type }) => { initDirective.wrap = wrapDirectives.some(({ type }) => {

View File

@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
// @ts-nocheck TODO: Fix types // @ts-nocheck TODO: Fix types
import type { MermaidConfig } from '../config.type.js'; import type { MermaidConfigWithDefaults } from '../config.type.js';
import type { Group } from '../diagram-api/types.js'; import type { Group } from '../diagram-api/types.js';
import type { D3TSpanElement, D3TextElement } from '../diagrams/common/commonTypes.js'; import type { D3TSpanElement, D3TextElement } from '../diagrams/common/commonTypes.js';
import { log } from '../logger.js'; import { log } from '../logger.js';
@@ -195,7 +195,7 @@ export const createText = (
width = 200, width = 200,
addSvgBackground = false, addSvgBackground = false,
} = {}, } = {},
config: MermaidConfig config: MermaidConfigWithDefaults
) => { ) => {
log.info('createText', text, style, isTitle, classes, useHtmlLabels, isNode, addSvgBackground); log.info('createText', text, style, isTitle, classes, useHtmlLabels, isNode, addSvgBackground);
if (useHtmlLabels) { if (useHtmlLabels) {

View File

@@ -1,14 +1,16 @@
import type { Content } from 'mdast';
import { fromMarkdown } from 'mdast-util-from-markdown'; import { fromMarkdown } from 'mdast-util-from-markdown';
import { dedent } from 'ts-dedent'; import { dedent } from 'ts-dedent';
import type { PartialMermaidConfig } from '../config.type.js'; import type { MermaidConfigWithDefaults } from '../config.type.js';
import type { MarkdownLine, MarkdownWordType } from './types.js'; import type { MarkdownLine, MarkdownWordType } from './types.js';
import { RootContent } from 'mdast';
type MarkdownConfig = Partial<Pick<MermaidConfigWithDefaults, 'markdownAutoWrap'>>;
/** /**
* @param markdown - markdown to process * @param markdown - markdown to process
* @returns processed markdown * @returns processed markdown
*/ */
function preprocessMarkdown(markdown: string, { markdownAutoWrap }: PartialMermaidConfig): string { function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MarkdownConfig): string {
// Replace multiple newlines with a single newline // Replace multiple newlines with a single newline
const withoutMultipleNewlines = markdown.replace(/\n{2,}/g, '\n'); const withoutMultipleNewlines = markdown.replace(/\n{2,}/g, '\n');
// Remove extra spaces at the beginning of each line // Remove extra spaces at the beginning of each line
@@ -22,16 +24,13 @@ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: PartialMerma
/** /**
* @param markdown - markdown to split into lines * @param markdown - markdown to split into lines
*/ */
export function markdownToLines( export function markdownToLines(markdown: string, config: MarkdownConfig = {}): MarkdownLine[] {
markdown: string,
config: PartialMermaidConfig = {}
): MarkdownLine[] {
const preprocessedMarkdown = preprocessMarkdown(markdown, config); const preprocessedMarkdown = preprocessMarkdown(markdown, config);
const { children } = fromMarkdown(preprocessedMarkdown); const { children } = fromMarkdown(preprocessedMarkdown);
const lines: MarkdownLine[] = [[]]; const lines: MarkdownLine[] = [[]];
let currentLine = 0; let currentLine = 0;
function processNode(node: Content, parentType: MarkdownWordType = 'normal') { function processNode(node: RootContent, parentType: MarkdownWordType = 'normal') {
if (node.type === 'text') { if (node.type === 'text') {
const textLines = node.value.split('\n'); const textLines = node.value.split('\n');
textLines.forEach((textLine, index) => { textLines.forEach((textLine, index) => {
@@ -63,10 +62,10 @@ export function markdownToLines(
return lines; return lines;
} }
export function markdownToHTML(markdown: string, { markdownAutoWrap }: PartialMermaidConfig = {}) { export function markdownToHTML(markdown: string, { markdownAutoWrap }: MarkdownConfig = {}) {
const { children } = fromMarkdown(markdown); const { children } = fromMarkdown(markdown);
function output(node: Content): string { function output(node: RootContent): string {
if (node.type === 'text') { if (node.type === 'text') {
if (markdownAutoWrap === false) { if (markdownAutoWrap === false) {
return node.value.replace(/\n/g, '<br/>').replace(/ /g, '&nbsp;'); return node.value.replace(/\n/g, '<br/>').replace(/ /g, '&nbsp;');

View File

@@ -1,11 +1,11 @@
# Used for VS Code's YAML plugin to automatically error on invalid types # Used for VS Code's YAML plugin to automatically error on invalid types
# yaml-language-server: $schema=https://json-schema.org/draft/2019-09/schema # yaml-language-server: $schema=https://json-schema.org/draft/2019-09/schema
# This file defines the MermaidConfig JSON Schema as a YAML file. # This file defines the MermaidConfigWithDefaults JSON Schema as a YAML file.
# #
# From this file, the following things can be generated: # From this file, the following things can be generated:
# - `scripts/create-types-from-json-schema.mjs` # - `scripts/create-types-from-json-schema.mjs`
# Used to generate the `src/config.type.ts` TypeScript types for MermaidConfig # Used to generate the `src/config.type.ts` TypeScript types for MermaidConfigWithDefaults
# with the `json-schema-to-typescript` NPM package. # with the `json-schema-to-typescript` NPM package.
# - `.build/jsonSchema.ts` # - `.build/jsonSchema.ts`
# Used to generate the default values from the `default` keys in this # Used to generate the default values from the `default` keys in this
@@ -20,13 +20,13 @@
# - Use the `|` character for multi-line strings # - Use the `|` character for multi-line strings
# - Use `meta:enum` to document enum values (from jsonschema2md) # - Use `meta:enum` to document enum values (from jsonschema2md)
# - Use `tsType` to override the TypeScript type (from json-schema-to-typescript) # - Use `tsType` to override the TypeScript type (from json-schema-to-typescript)
# - If adding a new object to `MermaidConfig` (e.g. a new diagram type), # - If adding a new object to `MermaidConfigWithDefaults` (e.g. a new diagram type),
# you may need to add it to `.build/jsonSchema.ts`, `src/docs.mts` # you may need to add it to `.build/jsonSchema.ts`, `src/docs.mts`
# and `scripts/create-types-from-json-schema.mjs` # and `scripts/create-types-from-json-schema.mjs`
# to get the default values/docs/types to generate properly. # to get the default values/docs/types to generate properly.
$id: https://mermaid.js.org/schemas/config.schema.json $id: https://mermaid.js.org/schemas/config.schema.json
$schema: https://json-schema.org/draft/2019-09/schema $schema: https://json-schema.org/draft/2019-09/schema
title: Mermaid Config title: MermaidConfigWithDefaults
type: object type: object
additionalProperties: false additionalProperties: false
required: required:
@@ -261,11 +261,11 @@ properties:
This is useful when you want to control how to handle syntax errors in your application. This is useful when you want to control how to handle syntax errors in your application.
$defs: # JSON Schema definition (maybe we should move these to a separate file) $defs: # JSON Schema definition (maybe we should move these to a separate file)
PartialMermaidConfig: MermaidConfig:
title: PartialMermaidConfig title: MermaidConfig
description: MermaidConfig with all fields optional description: MermaidConfigWithDefaults with all fields optional
type: object type: object
tsType: "import('type-fest').PartialDeep<MermaidConfig>" tsType: "import('type-fest').PartialDeep<MermaidConfigWithDefaults>"
BaseDiagramConfig: BaseDiagramConfig:
# TODO: More config needs to be moved here # TODO: More config needs to be moved here
title: Base Diagram Config title: Base Diagram Config

View File

@@ -26,7 +26,7 @@ import {
import memoize from 'lodash-es/memoize.js'; import memoize from 'lodash-es/memoize.js';
import merge from 'lodash-es/merge.js'; import merge from 'lodash-es/merge.js';
import assignWithDepth from './assignWithDepth.js'; import assignWithDepth from './assignWithDepth.js';
import type { MermaidConfig, PartialMermaidConfig } from './config.type.js'; import type { MermaidConfigWithDefaults, MermaidConfig } from './config.type.js';
import { detectType } from './diagram-api/detectType.js'; import { detectType } from './diagram-api/detectType.js';
import { directiveRegex } from './diagram-api/regexes.js'; import { directiveRegex } from './diagram-api/regexes.js';
import common from './diagrams/common/common.js'; import common from './diagrams/common/common.js';
@@ -97,16 +97,16 @@ const directiveWithoutOpen =
* @param config - Optional mermaid configuration object. * @param config - Optional mermaid configuration object.
* @returns The json object representing the init passed to mermaid.initialize() * @returns The json object representing the init passed to mermaid.initialize()
*/ */
export const detectInit = function (text: string): PartialMermaidConfig | undefined { export const detectInit = function (text: string): MermaidConfig | undefined {
const inits = detectDirective(text, /(?:init\b)|(?:initialize\b)/); const inits = detectDirective(text, /(?:init\b)|(?:initialize\b)/);
let results: PartialMermaidConfig & { config?: unknown } = {}; let results: MermaidConfig & { config?: unknown } = {};
if (Array.isArray(inits)) { if (Array.isArray(inits)) {
const args = inits.map((init) => init.args); const args = inits.map((init) => init.args);
sanitizeDirective(args); sanitizeDirective(args);
results = assignWithDepth(results, [...args]); results = assignWithDepth(results, [...args]);
} else { } else {
results = inits.args as PartialMermaidConfig; results = inits.args as MermaidConfig;
} }
if (!results) { if (!results) {
@@ -121,7 +121,7 @@ export const detectInit = function (text: string): PartialMermaidConfig | undefi
if (type === 'flowchart-v2') { if (type === 'flowchart-v2') {
type = 'flowchart'; type = 'flowchart';
} }
results[type as keyof MermaidConfig] = results[prop]; results[type as keyof MermaidConfigWithDefaults] = results[prop];
delete results[prop]; delete results[prop];
} }
@@ -249,7 +249,7 @@ export function interpolateToCurve(
*/ */
export function formatUrl( export function formatUrl(
linkStr: string, linkStr: string,
config: Pick<MermaidConfig, 'securityLevel'> config: Pick<MermaidConfigWithDefaults, 'securityLevel'>
): string | undefined { ): string | undefined {
const url = linkStr.trim(); const url = linkStr.trim();