From 694e094406e8e95e2e98b0d5351a73503421b5ef Mon Sep 17 00:00:00 2001 From: Johannes Vogt Date: Wed, 11 Feb 2026 13:10:16 +0100 Subject: [PATCH 1/8] add plugins for svg diagrams --- .vitepress/config.js | 2 ++ .vitepress/lib/md-diagram-svg.ts | 28 ++++++++++++++++++++++++++++ .vitepress/theme/styles.scss | 12 ++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 .vitepress/lib/md-diagram-svg.ts diff --git a/.vitepress/config.js b/.vitepress/config.js index 0bfab873f3..4b10f941fc 100644 --- a/.vitepress/config.js +++ b/.vitepress/config.js @@ -194,10 +194,12 @@ if (process.env.VITE_CAPIRE_EXTRA_ASSETS) { import { dl } from '@mdit/plugin-dl' import * as MdAttrsPropagate from './lib/md-attrs-propagate' import * as MdTypedModels from './lib/md-typed-models' +import * as MdDiagramSvg from './lib/md-diagram-svg' config.markdown.config = md => { MdAttrsPropagate.install(md) MdTypedModels.install(md) + MdDiagramSvg.install(md) md.use(dl) } diff --git a/.vitepress/lib/md-diagram-svg.ts b/.vitepress/lib/md-diagram-svg.ts new file mode 100644 index 0000000000..89baa69f3d --- /dev/null +++ b/.vitepress/lib/md-diagram-svg.ts @@ -0,0 +1,28 @@ +import { MarkdownEnv, MarkdownRenderer } from 'vitepress' +import { readFileSync } from 'node:fs'; +import { dirname, join } from 'node:path'; + +/** + * Renders SVG diagrams in markdown files as element. + * This allows the diagrams to be interactive. + * + * To use, add `?raw` to the end of the image source, e.g. `![](diagram.svg?raw)`. + */ +export function install(md: MarkdownRenderer) { + const defaultImage = + md.renderer.rules.image || + ((tokens, idx, options, env, self) => self.renderToken(tokens, idx, options)) + + md.renderer.rules.image = (tokens, idx, options, env: MarkdownEnv, self) => { + const token = tokens[idx] + const src = token.attrGet('src') || '' + + if (!/\.svg\?raw$/.test(src)) { + return defaultImage(tokens, idx, options, env, self) + } + const mdDir = dirname(env.realPath ?? env.path) + const filePath = join(mdDir, src.replace('?raw', '')) + const content = readFileSync(filePath, 'utf-8') + return `${content}` + } +} diff --git a/.vitepress/theme/styles.scss b/.vitepress/theme/styles.scss index 2989dbbbde..78846f49bd 100644 --- a/.vitepress/theme/styles.scss +++ b/.vitepress/theme/styles.scss @@ -312,6 +312,18 @@ img, video.bright { } } +// Raw svg diagrams +.diagram { + all: initial; // preserve original svg formatting + .dark & { // recolor in dark mode + filter: brightness(.884) invert(1) hue-rotate(177deg); + } + svg { + max-width: 100%; + height: auto; + margin: 30px auto; + } +} .VPBadge { From b463d541156562c039167a0e515511e16f4febf5 Mon Sep 17 00:00:00 2001 From: Johannes Vogt Date: Wed, 11 Feb 2026 17:22:56 +0100 Subject: [PATCH 2/8] fixes for safari and more svgs --- .vitepress/lib/md-diagram-svg.ts | 5 ++++- .vitepress/theme/styles.scss | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.vitepress/lib/md-diagram-svg.ts b/.vitepress/lib/md-diagram-svg.ts index 89baa69f3d..ed5d25e607 100644 --- a/.vitepress/lib/md-diagram-svg.ts +++ b/.vitepress/lib/md-diagram-svg.ts @@ -23,6 +23,9 @@ export function install(md: MarkdownRenderer) { const mdDir = dirname(env.realPath ?? env.path) const filePath = join(mdDir, src.replace('?raw', '')) const content = readFileSync(filePath, 'utf-8') - return `${content}` + const sanitized = content.replace(/<\?xml[\s\S]*?\?>/, '') // remove XML declaration + .replace(//, '') // remove DOCTYPE + .replace(/<--([\s\S]*?)-->/g, '') // remove comments + return `${sanitized}` } } diff --git a/.vitepress/theme/styles.scss b/.vitepress/theme/styles.scss index 78846f49bd..63c961a318 100644 --- a/.vitepress/theme/styles.scss +++ b/.vitepress/theme/styles.scss @@ -315,10 +315,10 @@ img, video.bright { // Raw svg diagrams .diagram { all: initial; // preserve original svg formatting - .dark & { // recolor in dark mode - filter: brightness(.884) invert(1) hue-rotate(177deg); - } svg { + .dark & { // recolor in dark mode + filter: brightness(.884) invert(1) hue-rotate(177deg); + } max-width: 100%; height: auto; margin: 30px auto; From fe96c0c7ab8fd8b18eac00f2e0a92d4c3c0ca05a Mon Sep 17 00:00:00 2001 From: Johannes Vogt Date: Wed, 11 Feb 2026 17:23:53 +0100 Subject: [PATCH 3/8] use ?raw for svgs --- cds/cxl.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cds/cxl.md b/cds/cxl.md index 6bfc44f708..9e1a482f4e 100644 --- a/cds/cxl.md +++ b/cds/cxl.md @@ -85,7 +85,7 @@ select from Books { This syntax diagram describes the possible expressions: -![](assets/cxl/expr.drawio.svg) +![](assets/cxl/expr.drawio.svg?raw) > Using: > [Path Expressions](#ref), @@ -262,7 +262,7 @@ A `ref` (short for reference) is used to refer to an element within the model. It can be used to navigate along path segments. Such a navigation is often referred to as a **path expression**. -![](assets/cxl/ref.drawio.svg) +![](assets/cxl/ref.drawio.svg?raw) > Using: > [Infix Filters](#infix-filters) @@ -459,7 +459,7 @@ If we apply this terminology to [path-expressions](#ref), an infix filter condit that is applied to a path-segment of a [path-expression](#ref). This allows you to filter the target of an association based on certain criteria. -![](assets/cxl/infix-filter.drawio.svg) +![](assets/cxl/infix-filter.drawio.svg?raw) > Using: > [Expressions](#expr) @@ -778,7 +778,7 @@ navigates along the `author` association of the `Books` entity only if the autho As depicted in below excerpt of the syntax diagram for `expr`, CXL supports all the standard SQL operators as well as a few additional ones, such as the `?` operator to check for the existence of a path. -![](assets/cxl/operators.drawio.svg) +![](assets/cxl/operators.drawio.svg?raw) > Using: > [Expressions](#expr) @@ -814,7 +814,7 @@ Following table gives an overview of the guaranteed supported operators in CXL: ## Functions (`func`) ###### func -![](assets/cxl/function.drawio.svg) +![](assets/cxl/function.drawio.svg?raw) > Using: > [Expressions](#expr) From 47467dfa0b7777d7bd9882439c5b3f817596cf09 Mon Sep 17 00:00:00 2001 From: Johannes Vogt Date: Wed, 11 Feb 2026 17:47:09 +0100 Subject: [PATCH 4/8] add links --- cds/assets/cxl/expr.drawio.svg | 990 +++++++++++++------------ cds/assets/cxl/function.drawio.svg | 78 +- cds/assets/cxl/infix-filter.drawio.svg | 86 ++- cds/assets/cxl/operators.drawio.svg | 838 +++++++++++---------- cds/assets/cxl/ref.drawio.svg | 118 +-- 5 files changed, 1110 insertions(+), 1000 deletions(-) diff --git a/cds/assets/cxl/expr.drawio.svg b/cds/assets/cxl/expr.drawio.svg index 6db3767ac2..90fd2b9a76 100644 --- a/cds/assets/cxl/expr.drawio.svg +++ b/cds/assets/cxl/expr.drawio.svg @@ -1,4 +1,4 @@ - + @@ -8,27 +8,29 @@ - - - - - - - -
-
- - - - path expression - - + + + path expression + + + - + @@ -39,27 +41,29 @@ - - - - - - - -
-
- - - - literal value - - + + + literal value + + + - + @@ -72,69 +76,75 @@ - - - - - - - -
-
- - - - infix operator - - + + + infix operator + + + - - - - - - - - -
-
- - - - expr - - + + + expr + + + - - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -143,27 +153,29 @@ - - - - - - - -
-
- - - - function call - - + + + function call + + + - + @@ -230,27 +242,29 @@ - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -294,148 +308,160 @@ - - - - - - - -
-
- - - - expr - - + + + expr + + + - + - - - - - - - -
-
- - - - BETWEEN - - + + + BETWEEN + + + - + - - - - - - - -
-
- - - - expr - - + + + expr + + + - + - - - - - - - -
-
- - - - NOT - - + + + NOT + + + - + - - - - - - - -
-
- - - - AND - - + + + AND + + + - - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -448,77 +474,83 @@ - - - - - - - -
-
- - - - expr - - + + + expr + + + - + - - - - - - - -
-
- - - - THEN - - + + + THEN + + + - + - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -531,123 +563,133 @@ - - - - - - - -
-
- - - - expr - - + + + expr + + + - - - - - - - - -
-
- - - - END - - + + + END + + + - + - - - - - - - -
-
- - - - WHEN - - + + + WHEN + + + - + - - - - - - - -
-
- - - - CASE - - + + + CASE + + + - + - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -672,73 +714,79 @@ - - - - - - - -
-
- - - - ELSE - - + + + ELSE + + + - + - - - - - - - -
-
- - - - prefix operator - - + + + prefix operator + + + - - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -747,52 +795,56 @@ - - - - - - - -
-
- - - - postfix operator - - + + + postfix operator + + + - + - - - - - - - -
-
- - - - expr - - + + + expr + + + - + diff --git a/cds/assets/cxl/function.drawio.svg b/cds/assets/cxl/function.drawio.svg index 00d8cc1ba8..02e3325e06 100644 --- a/cds/assets/cxl/function.drawio.svg +++ b/cds/assets/cxl/function.drawio.svg @@ -1,4 +1,4 @@ - + @@ -61,27 +61,29 @@ - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -125,27 +127,29 @@ - - - - - - - -
-
- - - - function name - - + + + function name + + + - + diff --git a/cds/assets/cxl/infix-filter.drawio.svg b/cds/assets/cxl/infix-filter.drawio.svg index 0bebdbcdd9..0b026c270b 100644 --- a/cds/assets/cxl/infix-filter.drawio.svg +++ b/cds/assets/cxl/infix-filter.drawio.svg @@ -1,4 +1,4 @@ - + @@ -61,27 +61,29 @@ - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -90,31 +92,33 @@ - - - - - - - -
-
- - - - where - - + + + where + + + - + diff --git a/cds/assets/cxl/operators.drawio.svg b/cds/assets/cxl/operators.drawio.svg index 9fd85bb38b..a940adfe11 100644 --- a/cds/assets/cxl/operators.drawio.svg +++ b/cds/assets/cxl/operators.drawio.svg @@ -1,4 +1,4 @@ - + @@ -11,69 +11,75 @@ - - - - - - - -
-
- - - - infix operator - - + + + infix operator + + + - - - - - - - - -
-
- - - - expr - - + + + expr + + + - - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -90,148 +96,160 @@ - - - - - - - -
-
- - - - expr - - + + + expr + + + - + - - - - - - - -
-
- - - - BETWEEN - - + + + BETWEEN + + + - + - - - - - - - -
-
- - - - expr - - + + + expr + + + - + - - - - - - - -
-
- - - - NOT - - + + + NOT + + + - + - - - - - - - -
-
- - - - AND - - + + + AND + + + - - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -244,77 +262,83 @@ - - - - - - - -
-
- - - - expr - - + + + expr + + + - + - - - - - - - -
-
- - - - THEN - - + + + THEN + + + - + - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -327,123 +351,133 @@ - - - - - - - -
-
- - - - expr - - + + + expr + + + - - - - - - - - -
-
- - - - END - - + + + END + + + - + - - - - - - - -
-
- - - - WHEN - - + + + WHEN + + + - + - - - - - - - -
-
- - - - CASE - - + + + CASE + + + - + - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -468,73 +502,79 @@ - - - - - - - -
-
- - - - ELSE - - + + + ELSE + + + - + - - - - - - - -
-
- - - - prefix operator - - + + + prefix operator + + + - - - - - - - - -
-
- - - - expr - - + + + expr + + + - + @@ -543,52 +583,56 @@ - - - - - - - -
-
- - - - postfix operator - - + + + postfix operator + + + - + - - - - - - - -
-
- - - - expr - - + + + expr + + + - + diff --git a/cds/assets/cxl/ref.drawio.svg b/cds/assets/cxl/ref.drawio.svg index bcf926dae6..9a81c27335 100644 --- a/cds/assets/cxl/ref.drawio.svg +++ b/cds/assets/cxl/ref.drawio.svg @@ -1,31 +1,33 @@ - + - - - - - - - -
-
- - - - leaf element - - + + + leaf element + + + - + @@ -37,52 +39,56 @@ - - - - - - - -
-
- - - - struct - - + + + struct + + + - + - - - - - - - -
-
- - - - association - - + + + association + + + - + @@ -90,7 +96,7 @@ - + From 93260b57de17b15396a3d4184ff691dd719700e0 Mon Sep 17 00:00:00 2001 From: Johannes Vogt Date: Wed, 11 Feb 2026 19:14:51 +0100 Subject: [PATCH 5/8] enable hot module replacement --- .vitepress/lib/md-diagram-svg.ts | 36 +++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/.vitepress/lib/md-diagram-svg.ts b/.vitepress/lib/md-diagram-svg.ts index ed5d25e607..bf0096e30f 100644 --- a/.vitepress/lib/md-diagram-svg.ts +++ b/.vitepress/lib/md-diagram-svg.ts @@ -20,12 +20,34 @@ export function install(md: MarkdownRenderer) { if (!/\.svg\?raw$/.test(src)) { return defaultImage(tokens, idx, options, env, self) } - const mdDir = dirname(env.realPath ?? env.path) - const filePath = join(mdDir, src.replace('?raw', '')) - const content = readFileSync(filePath, 'utf-8') - const sanitized = content.replace(/<\?xml[\s\S]*?\?>/, '') // remove XML declaration - .replace(//, '') // remove DOCTYPE - .replace(/<--([\s\S]*?)-->/g, '') // remove comments - return `${sanitized}` + + const name = 'svg_' + src.replace('?raw', '').replace(/[^a-zA-Z0-9_]/g, '_') // stable variable name for the imported SVG content + const importPath = src.startsWith('/') && src.startsWith('.') ? src : './' + src + + const sfcBlocks = env.sfcBlocks! + if (!sfcBlocks.scriptSetup) { + sfcBlocks.scriptSetup = { + content: '', + contentStripped: '\n', + tagClose: '', + tagOpen: '