build: use vite to get default mermaid config
Adds a vitepress JsonSchema plugin that automatically loads the Mermaid Config JSON Schema from a .schema.yaml file and gets the default values from it.
This commit is contained in:
parent
58b43976ff
commit
52a1243da5
|
@ -2,6 +2,7 @@ import { build, InlineConfig, type PluginOption } from 'vite';
|
|||
import { resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import jisonPlugin from './jisonPlugin.js';
|
||||
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
|
||||
import { readFileSync } from 'fs';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
|
@ -121,6 +122,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
|||
},
|
||||
plugins: [
|
||||
jisonPlugin(),
|
||||
jsonSchemaPlugin(), // handles `.schema.yaml` files
|
||||
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
|
||||
typescript({ compilerOptions: { declaration: false } }),
|
||||
istanbul({
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
import { load, JSON_SCHEMA } from 'js-yaml';
|
||||
import assert from 'node:assert';
|
||||
import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
|
||||
import { PluginOption } from 'vite';
|
||||
|
||||
import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
|
||||
|
||||
/**
|
||||
* All of the keys in the mermaid config that have a mermaid diagram config.
|
||||
*/
|
||||
const MERMAID_CONFIG_DIAGRAM_KEYS = [
|
||||
'flowchart',
|
||||
'sequence',
|
||||
'gantt',
|
||||
'journey',
|
||||
'class',
|
||||
'state',
|
||||
'er',
|
||||
'pie',
|
||||
'quadrantChart',
|
||||
'requirement',
|
||||
'mindmap',
|
||||
'timeline',
|
||||
'gitGraph',
|
||||
'c4',
|
||||
'sankey',
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Generate default values from the JSON Schema.
|
||||
*
|
||||
* AJV does not support nested default values yet (or default values with $ref),
|
||||
* so we need to manually find them (this may be fixed in ajv v9).
|
||||
*
|
||||
* @param mermaidConfigSchema - The Mermaid JSON Schema to use.
|
||||
* @returns The default mermaid config object.
|
||||
*/
|
||||
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
|
||||
const ajv = new Ajv2019({
|
||||
useDefaults: true,
|
||||
allowUnionTypes: true,
|
||||
strict: true,
|
||||
});
|
||||
|
||||
ajv.addKeyword({
|
||||
keyword: 'meta:enum', // used by jsonschema2md
|
||||
errors: false,
|
||||
});
|
||||
ajv.addKeyword({
|
||||
keyword: 'tsType', // used by json-schema-to-typescript
|
||||
errors: false,
|
||||
});
|
||||
|
||||
// ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
|
||||
// (may be fixed in v9) so we need to manually use sub-schemas
|
||||
const mermaidDefaultConfig = {};
|
||||
|
||||
assert.ok(mermaidConfigSchema.$defs);
|
||||
const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
|
||||
|
||||
for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
|
||||
const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
|
||||
const [root, defs, defName] = subSchemaRef.split('/');
|
||||
assert.strictEqual(root, '#');
|
||||
assert.strictEqual(defs, '$defs');
|
||||
const subSchema = {
|
||||
$schema: mermaidConfigSchema.$schema,
|
||||
$defs: mermaidConfigSchema.$defs,
|
||||
...mermaidConfigSchema.$defs[defName],
|
||||
} as JSONSchemaType<BaseDiagramConfig>;
|
||||
|
||||
const validate = ajv.compile(subSchema);
|
||||
|
||||
mermaidDefaultConfig[key] = {};
|
||||
|
||||
for (const required of subSchema.required ?? []) {
|
||||
if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
|
||||
mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
|
||||
}
|
||||
}
|
||||
if (!validate(mermaidDefaultConfig[key])) {
|
||||
throw new Error(
|
||||
`schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
|
||||
validate.errors,
|
||||
undefined,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const validate = ajv.compile(mermaidConfigSchema);
|
||||
|
||||
if (!validate(mermaidDefaultConfig)) {
|
||||
throw new Error(
|
||||
`Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
|
||||
validate.errors,
|
||||
undefined,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
return mermaidDefaultConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vite plugin that handles JSON Schemas saved as a `.schema.yaml` file.
|
||||
*
|
||||
* Use `my-example.schema.yaml?only-defaults=true` to only load the default values.
|
||||
*/
|
||||
export default function jsonSchemaPlugin(): PluginOption {
|
||||
return {
|
||||
name: 'json-schema-plugin',
|
||||
transform(src: string, id: string) {
|
||||
const idAsUrl = new URL(id, 'file:///');
|
||||
|
||||
if (!idAsUrl.pathname.endsWith('schema.yaml')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idAsUrl.searchParams.get('only-defaults')) {
|
||||
const jsonSchema = load(src, {
|
||||
filename: idAsUrl.pathname,
|
||||
// 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"`.
|
||||
schema: JSON_SCHEMA,
|
||||
}) as JSONSchemaType<MermaidConfig>;
|
||||
return {
|
||||
code: `export default ${JSON.stringify(generateDefaults(jsonSchema), undefined, 2)};`,
|
||||
map: null, // no source map
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
code: `export default ${JSON.stringify(
|
||||
load(src, {
|
||||
filename: idAsUrl.pathname,
|
||||
// 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"`.
|
||||
schema: JSON_SCHEMA,
|
||||
}),
|
||||
undefined,
|
||||
2
|
||||
)};`,
|
||||
map: null, // provide source map if available
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#### Defined in
|
||||
|
||||
[defaultConfig.ts:2300](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L2300)
|
||||
[defaultConfig.ts:266](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L266)
|
||||
|
||||
---
|
||||
|
||||
|
@ -22,35 +22,12 @@
|
|||
|
||||
• `Const` **default**: `Partial`<`MermaidConfig`>
|
||||
|
||||
**Configuration methods in Mermaid version 8.6.0 have been updated, to learn more\[[click
|
||||
here](8.6.0_docs.md)].**
|
||||
Default mermaid configuration options.
|
||||
|
||||
## **What follows are config instructions for older versions**
|
||||
|
||||
These are the default options which can be overridden with the initialization call like so:
|
||||
|
||||
**Example 1:**
|
||||
|
||||
```js
|
||||
mermaid.initialize({ flowchart: { htmlLabels: false } });
|
||||
```
|
||||
|
||||
**Example 2:**
|
||||
|
||||
```html
|
||||
<script>
|
||||
const config = {
|
||||
startOnLoad: true,
|
||||
flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
|
||||
securityLevel: 'loose',
|
||||
};
|
||||
mermaid.initialize(config);
|
||||
</script>
|
||||
```
|
||||
|
||||
A summary of all options and their defaults is found [here](#mermaidapi-configuration-defaults).
|
||||
A description of each option follows below.
|
||||
Please see the Mermaid config JSON Schema for the default JSON values.
|
||||
Non-JSON JS default values are listed in this file, e.g. functions, or
|
||||
`undefined` (explicitly set so that `configKeys` finds them).
|
||||
|
||||
#### Defined in
|
||||
|
||||
[defaultConfig.ts:33](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L33)
|
||||
[defaultConfig.ts:16](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L16)
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
"@vitest/coverage-v8": "^0.32.2",
|
||||
"@vitest/spy": "^0.32.2",
|
||||
"@vitest/ui": "^0.32.2",
|
||||
"ajv": "^8.12.0",
|
||||
"concurrently": "^8.0.1",
|
||||
"cors": "^2.8.5",
|
||||
"coveralls": "^3.1.1",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -71,6 +71,9 @@ importers:
|
|||
'@vitest/ui':
|
||||
specifier: ^0.32.2
|
||||
version: 0.32.2(vitest@0.32.2)
|
||||
ajv:
|
||||
specifier: ^8.12.0
|
||||
version: 8.12.0
|
||||
concurrently:
|
||||
specifier: ^8.0.1
|
||||
version: 8.0.1
|
||||
|
@ -663,13 +666,13 @@ packages:
|
|||
resolution: {integrity: sha512-qe8Nmh9rYI/HIspLSTwtbMFPj6dISG6+dJnOguTlPNXtCvS2uezdxscVBb7/3DrmNbQK49TDqpkSQ1chbRGdpQ==}
|
||||
dev: true
|
||||
|
||||
/@apideck/better-ajv-errors@0.3.6(ajv@8.11.0):
|
||||
/@apideck/better-ajv-errors@0.3.6(ajv@8.12.0):
|
||||
resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==}
|
||||
engines: {node: '>=10'}
|
||||
peerDependencies:
|
||||
ajv: '>=8'
|
||||
dependencies:
|
||||
ajv: 8.11.0
|
||||
ajv: 8.12.0
|
||||
json-schema: 0.4.0
|
||||
jsonpointer: 5.0.1
|
||||
leven: 3.1.0
|
||||
|
@ -2258,7 +2261,7 @@ packages:
|
|||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/types': 17.4.4
|
||||
ajv: 8.11.0
|
||||
ajv: 8.12.0
|
||||
dev: true
|
||||
|
||||
/@commitlint/ensure@17.4.4:
|
||||
|
@ -5799,7 +5802,7 @@ packages:
|
|||
indent-string: 5.0.0
|
||||
dev: true
|
||||
|
||||
/ajv-formats@2.1.1(ajv@8.11.0):
|
||||
/ajv-formats@2.1.1(ajv@8.12.0):
|
||||
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
|
||||
peerDependencies:
|
||||
ajv: ^8.0.0
|
||||
|
@ -5807,7 +5810,7 @@ packages:
|
|||
ajv:
|
||||
optional: true
|
||||
dependencies:
|
||||
ajv: 8.11.0
|
||||
ajv: 8.12.0
|
||||
dev: true
|
||||
|
||||
/ajv-keywords@3.5.2(ajv@6.12.6):
|
||||
|
@ -5818,12 +5821,12 @@ packages:
|
|||
ajv: 6.12.6
|
||||
dev: true
|
||||
|
||||
/ajv-keywords@5.1.0(ajv@8.11.0):
|
||||
/ajv-keywords@5.1.0(ajv@8.12.0):
|
||||
resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==}
|
||||
peerDependencies:
|
||||
ajv: ^8.8.2
|
||||
dependencies:
|
||||
ajv: 8.11.0
|
||||
ajv: 8.12.0
|
||||
fast-deep-equal: 3.1.3
|
||||
dev: true
|
||||
|
||||
|
@ -5836,8 +5839,8 @@ packages:
|
|||
uri-js: 4.4.1
|
||||
dev: true
|
||||
|
||||
/ajv@8.11.0:
|
||||
resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==}
|
||||
/ajv@8.12.0:
|
||||
resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
json-schema-traverse: 1.0.0
|
||||
|
@ -11063,7 +11066,7 @@ packages:
|
|||
/light-my-request@4.12.0:
|
||||
resolution: {integrity: sha512-0y+9VIfJEsPVzK5ArSIJ8Dkxp8QMP7/aCuxCUtG/tr9a2NoOf/snATE/OUc05XUplJCEnRh6gTkH7xh9POt1DQ==}
|
||||
dependencies:
|
||||
ajv: 8.11.0
|
||||
ajv: 8.12.0
|
||||
cookie: 0.5.0
|
||||
process-warning: 1.0.0
|
||||
set-cookie-parser: 2.6.0
|
||||
|
@ -13514,9 +13517,9 @@ packages:
|
|||
engines: {node: '>= 12.13.0'}
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.11
|
||||
ajv: 8.11.0
|
||||
ajv-formats: 2.1.1(ajv@8.11.0)
|
||||
ajv-keywords: 5.1.0(ajv@8.11.0)
|
||||
ajv: 8.12.0
|
||||
ajv-formats: 2.1.1(ajv@8.12.0)
|
||||
ajv-keywords: 5.1.0(ajv@8.12.0)
|
||||
dev: true
|
||||
|
||||
/search-insights@2.6.0:
|
||||
|
@ -15924,7 +15927,7 @@ packages:
|
|||
resolution: {integrity: sha512-CttE7WCYW9sZC+nUYhQg3WzzGPr4IHmrPnjKiu3AMXsiNQKx+l4hHl63WTrnicLmKEKHScWDH8xsGBdrYgtBzg==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
dependencies:
|
||||
'@apideck/better-ajv-errors': 0.3.6(ajv@8.11.0)
|
||||
'@apideck/better-ajv-errors': 0.3.6(ajv@8.12.0)
|
||||
'@babel/core': 7.12.3
|
||||
'@babel/preset-env': 7.20.2(@babel/core@7.12.3)
|
||||
'@babel/runtime': 7.21.0
|
||||
|
@ -15932,7 +15935,7 @@ packages:
|
|||
'@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.1)
|
||||
'@rollup/plugin-replace': 2.4.2(rollup@2.79.1)
|
||||
'@surma/rollup-plugin-off-main-thread': 2.2.3
|
||||
ajv: 8.11.0
|
||||
ajv: 8.12.0
|
||||
common-tags: 1.8.2
|
||||
fast-json-stable-stringify: 2.1.0
|
||||
fs-extra: 9.1.0
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import jison from './.vite/jisonPlugin.js';
|
||||
import jsonSchemaPlugin from './.vite/jsonSchemaPlugin.js';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
|
@ -8,6 +9,7 @@ export default defineConfig({
|
|||
},
|
||||
plugins: [
|
||||
jison(),
|
||||
jsonSchemaPlugin(), // handles .schema.yaml JSON Schema files
|
||||
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
|
||||
typescript({ compilerOptions: { declaration: false } }),
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue