@md-plugins/quasar-app-extension-q-press 0.1.0-beta.19 → 0.1.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/install.js +1 -0
- package/dist/templates/init/src/_q-press/components/MarkdownMermaid.vue +123 -0
- package/dist/templates/init/src/_q-press/css/code-theme.scss +12 -0
- package/dist/templates/init/src/markdown/getting-started/introduction.md +2 -0
- package/dist/templates/init/src/markdown/md-plugins/codeblocks/overview.md +16 -2
- package/dist/templates/init/src/markdown/md-plugins/mermaid/advanced.md +69 -0
- package/dist/templates/init/src/markdown/md-plugins/mermaid/overview.md +73 -0
- package/dist/templates/init/src/markdown/vite-plugins/vite-md-plugin/advanced.md +84 -54
- package/dist/templates/init/src/markdown/vite-plugins/vite-md-plugin/overview.md +1 -0
- package/dist/templates/init/src/siteConfig/index.ts +7 -0
- package/dist/templates/update/src/_q-press/components/MarkdownMermaid.vue +123 -0
- package/dist/templates/update/src/_q-press/css/code-theme.scss +12 -0
- package/package.json +14 -13
- package/src/install.ts +1 -0
- package/src/templates/init/src/_q-press/components/MarkdownMermaid.vue +123 -0
- package/src/templates/init/src/_q-press/css/code-theme.scss +12 -0
- package/src/templates/init/src/markdown/getting-started/introduction.md +2 -0
- package/src/templates/init/src/markdown/md-plugins/codeblocks/overview.md +16 -2
- package/src/templates/init/src/markdown/md-plugins/mermaid/advanced.md +69 -0
- package/src/templates/init/src/markdown/md-plugins/mermaid/overview.md +73 -0
- package/src/templates/init/src/markdown/vite-plugins/vite-md-plugin/advanced.md +84 -54
- package/src/templates/init/src/markdown/vite-plugins/vite-md-plugin/overview.md +1 -0
- package/src/templates/init/src/siteConfig/index.ts +7 -0
- package/src/templates/update/src/_q-press/components/MarkdownMermaid.vue +123 -0
- package/src/templates/update/src/_q-press/css/code-theme.scss +12 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ The Ultimate Markdown Solution for the Quasar Framework.
|
|
|
4
4
|
|
|
5
5
|
See the [documentation](https://md-plugins.netlify.app/quasar-app-extensions/qpress/overview) for more information.
|
|
6
6
|
|
|
7
|
-
> Current beta release: `0.1.0-beta.
|
|
7
|
+
> Current beta release: `0.1.0-beta.20`.
|
|
8
8
|
>
|
|
9
9
|
> Q-Press currently targets Quasar Vite projects using `@quasar/app-vite` `>=3.0.0-beta.33`. TypeScript processing is required.
|
|
10
10
|
|
package/dist/install.js
CHANGED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="markdown-mermaid q-my-md">
|
|
3
|
+
<div
|
|
4
|
+
v-if="errorMessage"
|
|
5
|
+
class="markdown-mermaid__error"
|
|
6
|
+
role="alert"
|
|
7
|
+
>
|
|
8
|
+
{{ errorMessage }}
|
|
9
|
+
</div>
|
|
10
|
+
<div
|
|
11
|
+
v-else-if="isRendering"
|
|
12
|
+
class="markdown-mermaid__loading"
|
|
13
|
+
>
|
|
14
|
+
Rendering diagram...
|
|
15
|
+
</div>
|
|
16
|
+
<div
|
|
17
|
+
ref="containerRef"
|
|
18
|
+
class="markdown-mermaid__diagram"
|
|
19
|
+
></div>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup lang="ts">
|
|
24
|
+
import { uid, useQuasar } from 'quasar'
|
|
25
|
+
import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
26
|
+
|
|
27
|
+
const props = defineProps<{
|
|
28
|
+
code: string
|
|
29
|
+
}>()
|
|
30
|
+
|
|
31
|
+
const $q = useQuasar()
|
|
32
|
+
const containerRef = ref<HTMLElement | null>(null)
|
|
33
|
+
const errorMessage = ref('')
|
|
34
|
+
const isRendering = ref(false)
|
|
35
|
+
|
|
36
|
+
let disposed = false
|
|
37
|
+
let renderRequest = 0
|
|
38
|
+
|
|
39
|
+
async function renderDiagram(): Promise<void> {
|
|
40
|
+
if (import.meta.env.QUASAR_CLIENT !== true || containerRef.value === null) {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const requestId = ++renderRequest
|
|
45
|
+
|
|
46
|
+
errorMessage.value = ''
|
|
47
|
+
isRendering.value = true
|
|
48
|
+
|
|
49
|
+
await nextTick()
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const { default: mermaid } = await import('mermaid')
|
|
53
|
+
|
|
54
|
+
mermaid.initialize({
|
|
55
|
+
securityLevel: 'strict',
|
|
56
|
+
startOnLoad: false,
|
|
57
|
+
theme: $q.dark.isActive === true ? 'dark' : 'default',
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const { svg, bindFunctions } = await mermaid.render(`markdown-mermaid-${uid()}`, props.code)
|
|
61
|
+
|
|
62
|
+
if (disposed === true || requestId !== renderRequest || containerRef.value === null) {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
containerRef.value.innerHTML = svg
|
|
67
|
+
bindFunctions?.(containerRef.value)
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (disposed === false && requestId === renderRequest) {
|
|
70
|
+
errorMessage.value = error instanceof Error ? error.message : 'Unable to render diagram.'
|
|
71
|
+
}
|
|
72
|
+
} finally {
|
|
73
|
+
if (disposed === false && requestId === renderRequest) {
|
|
74
|
+
isRendering.value = false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
onMounted(() => {
|
|
80
|
+
void renderDiagram()
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
watch(
|
|
84
|
+
() => [props.code, $q.dark.isActive] as const,
|
|
85
|
+
() => {
|
|
86
|
+
void renderDiagram()
|
|
87
|
+
},
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
onBeforeUnmount(() => {
|
|
91
|
+
disposed = true
|
|
92
|
+
})
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<style lang="scss">
|
|
96
|
+
.markdown-mermaid {
|
|
97
|
+
border: 1px solid var(--q-separator-color);
|
|
98
|
+
border-radius: 8px;
|
|
99
|
+
overflow-x: auto;
|
|
100
|
+
padding: 1rem;
|
|
101
|
+
|
|
102
|
+
&__diagram {
|
|
103
|
+
min-width: 100%;
|
|
104
|
+
text-align: center;
|
|
105
|
+
|
|
106
|
+
svg {
|
|
107
|
+
max-width: 100%;
|
|
108
|
+
height: auto;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
&__error {
|
|
113
|
+
color: var(--q-negative);
|
|
114
|
+
font-family: monospace;
|
|
115
|
+
white-space: pre-wrap;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&__loading {
|
|
119
|
+
color: var(--q-secondary);
|
|
120
|
+
font-style: italic;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
</style>
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
overflow: auto;
|
|
5
5
|
border-radius: inherit;
|
|
6
6
|
|
|
7
|
+
&.twoslash {
|
|
8
|
+
overflow: visible;
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
code {
|
|
8
12
|
display: block;
|
|
9
13
|
padding: 16px;
|
|
@@ -39,6 +43,10 @@
|
|
|
39
43
|
display: inline-block;
|
|
40
44
|
width: 100%;
|
|
41
45
|
}
|
|
46
|
+
|
|
47
|
+
&:has(.twoslash-query-persisted) > code {
|
|
48
|
+
padding-bottom: calc(16px + 2.2em);
|
|
49
|
+
}
|
|
42
50
|
}
|
|
43
51
|
|
|
44
52
|
.c-line {
|
|
@@ -165,6 +173,10 @@
|
|
|
165
173
|
transform: translateY(1.5em);
|
|
166
174
|
}
|
|
167
175
|
|
|
176
|
+
.twoslash-query-persisted {
|
|
177
|
+
display: inline-block;
|
|
178
|
+
}
|
|
179
|
+
|
|
168
180
|
.twoslash-hover:hover .twoslash-popup-container,
|
|
169
181
|
.twoslash-error-hover:hover .twoslash-popup-container,
|
|
170
182
|
.twoslash-query-persisted .twoslash-popup-container,
|
|
@@ -23,6 +23,7 @@ The core Markdown-it plugins and direct Vite plugins work in Vue/Vite projects a
|
|
|
23
23
|
- **Title Extraction**: Extract the first header in Markdown as the page title.
|
|
24
24
|
- **Script Imports**: Extract and process **<script import>** blocks from Markdown.
|
|
25
25
|
- **Code Block Enhancements**: Enhance code block rendering with syntax highlighting, tabs, and more.
|
|
26
|
+
- **Mermaid Diagrams**: Render Mermaid fenced code blocks as client-side diagrams.
|
|
26
27
|
- **Custom Styling**: Apply custom styles to your Markdown content for a more refined look.
|
|
27
28
|
- **Integration**: Easily integrate with other tools and platforms to streamline your workflow.
|
|
28
29
|
|
|
@@ -59,6 +60,7 @@ Here are some examples of what you can achieve with Markdown Plugins:
|
|
|
59
60
|
- **Title Extraction**: Extract the first header in Markdown as the page title.
|
|
60
61
|
- **Script Imports**: Extract and process `<script import>` blocks from Markdown.
|
|
61
62
|
- **Code Block Enhancements**: Enhance code block rendering with syntax highlighting, tabs, and more.
|
|
63
|
+
- **Mermaid Diagrams**: Add flowcharts, sequence diagrams, and other Mermaid diagrams to Markdown pages.
|
|
62
64
|
|
|
63
65
|
## Support
|
|
64
66
|
|
|
@@ -68,16 +68,30 @@ console.log('Hello, world!')
|
|
|
68
68
|
|
|
69
69
|
### Code Block with TwoSlash
|
|
70
70
|
|
|
71
|
-
Add the `twoslash` attribute to TypeScript or JavaScript examples when you want inferred type information, compiler diagnostics, or
|
|
71
|
+
Add the `twoslash` attribute to TypeScript or JavaScript examples when you want inferred type information, compiler diagnostics, or query output. Hover an identifier in the example below to see the type tooltip.
|
|
72
72
|
|
|
73
73
|
```ts [twoslash]
|
|
74
74
|
const count = 1
|
|
75
|
-
|
|
75
|
+
const label = count.toFixed(0)
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
````markup
|
|
79
79
|
```ts [twoslash]
|
|
80
80
|
const count = 1
|
|
81
|
+
const label = count.toFixed(0)
|
|
82
|
+
```
|
|
83
|
+
````
|
|
84
|
+
|
|
85
|
+
If you add a `// ^?` query marker, TwoSlash renders that query result persistently below the matching expression. That is useful for teaching types directly in the page, while normal identifier details remain hover-based.
|
|
86
|
+
|
|
87
|
+
```ts [twoslash]
|
|
88
|
+
const selectedIcon = 'event' as const
|
|
89
|
+
// ^?
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
````markup
|
|
93
|
+
```ts [twoslash]
|
|
94
|
+
const selectedIcon = 'event' as const
|
|
81
95
|
// ^?
|
|
82
96
|
```
|
|
83
97
|
````
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Mermaid Advanced Topics
|
|
3
|
+
desc: Mermaid plugin options and integration details.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The Mermaid plugin is small, but it has two different integration paths:
|
|
7
|
+
|
|
8
|
+
- **Component mode** is the Q-Press default. It emits `MarkdownMermaid` and lets Vue render Mermaid on the client.
|
|
9
|
+
- **Pre mode** emits a plain `<pre class="mermaid">` block for custom MarkdownIt pipelines.
|
|
10
|
+
|
|
11
|
+
## Options
|
|
12
|
+
|
|
13
|
+
| Option | Type | Default | Description |
|
|
14
|
+
| --------------- | ---------------------- | -------------------- | -------------------------------------------- |
|
|
15
|
+
| `languages` | `string[]` | `['mermaid', 'mmd']` | Fence languages treated as Mermaid diagrams. |
|
|
16
|
+
| `renderMode` | `'component' \| 'pre'` | `'component'` | Output mode for diagrams. |
|
|
17
|
+
| `componentName` | `string` | `'MarkdownMermaid'` | Component used in component mode. |
|
|
18
|
+
| `codeProp` | `string` | `'code'` | Component prop that receives Mermaid source. |
|
|
19
|
+
| `preClass` | `string` | `'mermaid'` | CSS class used in pre mode. |
|
|
20
|
+
| `pageScripts` | `string[]` | Q-Press import | Imports added to generated Vue pages. |
|
|
21
|
+
|
|
22
|
+
## Component Mode
|
|
23
|
+
|
|
24
|
+
Use component mode when Markdown output is compiled into Vue components:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import MarkdownIt from 'markdown-it'
|
|
28
|
+
import { mermaidPlugin } from '@md-plugins/md-plugin-mermaid'
|
|
29
|
+
|
|
30
|
+
const md = new MarkdownIt()
|
|
31
|
+
md.use(mermaidPlugin, {
|
|
32
|
+
componentName: 'MarkdownMermaid',
|
|
33
|
+
codeProp: 'code',
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Component mode adds this import to the generated page when a Mermaid fence is found:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import MarkdownMermaid from '@/.q-press/components/MarkdownMermaid.vue'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Pre Mode
|
|
44
|
+
|
|
45
|
+
Use pre mode when your app has its own Mermaid bootstrapping:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import MarkdownIt from 'markdown-it'
|
|
49
|
+
import { mermaidPlugin } from '@md-plugins/md-plugin-mermaid'
|
|
50
|
+
|
|
51
|
+
const md = new MarkdownIt()
|
|
52
|
+
md.use(mermaidPlugin, {
|
|
53
|
+
renderMode: 'pre',
|
|
54
|
+
preClass: 'mermaid',
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then run Mermaid after the HTML is mounted:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import mermaid from 'mermaid'
|
|
62
|
+
|
|
63
|
+
mermaid.initialize({ startOnLoad: false })
|
|
64
|
+
await mermaid.run({ querySelector: '.mermaid' })
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Security
|
|
68
|
+
|
|
69
|
+
The Q-Press `MarkdownMermaid` component initializes Mermaid with `securityLevel: 'strict'`. Keep that unless you have a specific reason to allow looser rendering.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Mermaid Plugin
|
|
3
|
+
desc: Render Mermaid diagrams from fenced code blocks.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The Mermaid plugin turns `mermaid` and `mmd` fenced code blocks into diagrams. In Q-Press and `viteMdPlugin`, Mermaid diagrams render through the generated `MarkdownMermaid` Vue component so diagrams stay client-side and SSR-safe.
|
|
7
|
+
|
|
8
|
+
## Example
|
|
9
|
+
|
|
10
|
+
```mermaid
|
|
11
|
+
flowchart LR
|
|
12
|
+
Markdown[Markdown file] --> Plugin[md-plugin-mermaid]
|
|
13
|
+
Plugin --> Component[MarkdownMermaid]
|
|
14
|
+
Component --> Diagram[Rendered diagram]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Markdown
|
|
18
|
+
|
|
19
|
+
````markdown
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart LR
|
|
22
|
+
Markdown[Markdown file] --> Plugin[md-plugin-mermaid]
|
|
23
|
+
Plugin --> Component[MarkdownMermaid]
|
|
24
|
+
Component --> Diagram[Rendered diagram]
|
|
25
|
+
```
|
|
26
|
+
````
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
You can install the Mermaid plugin using npm, yarn, pnpm, or bun:
|
|
31
|
+
|
|
32
|
+
```tabs
|
|
33
|
+
<<| bash pnpm |>>
|
|
34
|
+
pnpm add @md-plugins/md-plugin-mermaid mermaid
|
|
35
|
+
<<| bash bun |>>
|
|
36
|
+
bun add @md-plugins/md-plugin-mermaid mermaid
|
|
37
|
+
<<| bash yarn |>>
|
|
38
|
+
yarn add @md-plugins/md-plugin-mermaid mermaid
|
|
39
|
+
<<| bash npm |>>
|
|
40
|
+
npm install @md-plugins/md-plugin-mermaid mermaid
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Q-Press installs `mermaid` for generated documentation projects. Direct MarkdownIt users only need `mermaid` if they render diagrams in the browser.
|
|
44
|
+
|
|
45
|
+
## Basic Usage
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import MarkdownIt from 'markdown-it'
|
|
49
|
+
import { mermaidPlugin } from '@md-plugins/md-plugin-mermaid'
|
|
50
|
+
|
|
51
|
+
const md = new MarkdownIt()
|
|
52
|
+
md.use(mermaidPlugin)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The default output is a Vue component:
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<MarkdownMermaid :code="diagramSource"></MarkdownMermaid>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If you own the browser initialization yourself, use plain pre mode:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
md.use(mermaidPlugin, {
|
|
65
|
+
renderMode: 'pre',
|
|
66
|
+
})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
That renders Mermaid-compatible HTML:
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<pre class="mermaid"><code>flowchart LR...</code></pre>
|
|
73
|
+
```
|
|
@@ -11,7 +11,7 @@ The `viteMdPlugin` is a powerful tool for integrating Markdown processing into y
|
|
|
11
11
|
|
|
12
12
|
```ts
|
|
13
13
|
import { Plugin } from 'vite'
|
|
14
|
-
import { Options } from 'markdown-it'
|
|
14
|
+
import MarkdownIt, { Options } from 'markdown-it'
|
|
15
15
|
import { BlockquotePluginOptions } from '@md-plugins/md-plugin-blockquote'
|
|
16
16
|
import { CodeblockPluginOptions } from '@md-plugins/md-plugin-codeblocks'
|
|
17
17
|
import { FrontmatterPluginOptions } from '@md-plugins/md-plugin-frontmatter'
|
|
@@ -19,21 +19,27 @@ import { HeadersPluginOptions } from '@md-plugins/md-plugin-headers'
|
|
|
19
19
|
import { ImagePluginOptions } from '@md-plugins/md-plugin-image'
|
|
20
20
|
import { InlineCodePluginOptions } from '@md-plugins/md-plugin-inlinecode'
|
|
21
21
|
import { LinkPluginOptions } from '@md-plugins/md-plugin-link'
|
|
22
|
+
import { MermaidPluginOptions } from '@md-plugins/md-plugin-mermaid'
|
|
22
23
|
import { TablePluginOptions } from '@md-plugins/md-plugin-table'
|
|
23
24
|
|
|
25
|
+
type MarkdownItPlugin = (md: MarkdownIt, ...params: any[]) => void
|
|
26
|
+
type MarkdownItPluginEntry = MarkdownItPlugin | [MarkdownItPlugin, ...any[]]
|
|
27
|
+
|
|
24
28
|
interface MarkdownOptions extends Options {
|
|
25
29
|
html?: boolean
|
|
26
30
|
linkify?: boolean
|
|
27
31
|
typographer?: boolean
|
|
28
32
|
breaks?: boolean
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
blockquotePlugin?: BlockquotePluginOptions
|
|
34
|
+
codeblockPlugin?: CodeblockPluginOptions
|
|
35
|
+
frontmatterPlugin?: FrontmatterPluginOptions
|
|
36
|
+
headersPlugin?: HeadersPluginOptions | boolean
|
|
37
|
+
imagePlugin?: ImagePluginOptions
|
|
38
|
+
inlineCodePlugin?: InlineCodePluginOptions
|
|
39
|
+
linkPlugin?: LinkPluginOptions
|
|
40
|
+
mermaidPlugin?: MermaidPluginOptions
|
|
41
|
+
tablePlugin?: TablePluginOptions
|
|
42
|
+
markdownItPlugins?: MarkdownItPluginEntry[]
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
interface MenuItem {
|
|
@@ -128,6 +134,59 @@ export default defineConfig({
|
|
|
128
134
|
})
|
|
129
135
|
```
|
|
130
136
|
|
|
137
|
+
### Using Other Markdown-It Plugins
|
|
138
|
+
|
|
139
|
+
The `viteMdPlugin` already includes the md-plugins used by Q-Press, plus inserted text support for `++text++`. If you need additional Markdown-it syntax, install the plugin and pass it through `config.markdownItPlugins`.
|
|
140
|
+
|
|
141
|
+
```tabs
|
|
142
|
+
<<| bash pnpm |>>
|
|
143
|
+
pnpm add markdown-it-mark markdown-it-sub markdown-it-sup markdown-it-footnote
|
|
144
|
+
<<| bash bun |>>
|
|
145
|
+
bun add markdown-it-mark markdown-it-sub markdown-it-sup markdown-it-footnote
|
|
146
|
+
<<| bash yarn |>>
|
|
147
|
+
yarn add markdown-it-mark markdown-it-sub markdown-it-sup markdown-it-footnote
|
|
148
|
+
<<| bash npm |>>
|
|
149
|
+
npm install markdown-it-mark markdown-it-sub markdown-it-sup markdown-it-footnote
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { defineConfig } from 'vite'
|
|
154
|
+
import vue from '@vitejs/plugin-vue'
|
|
155
|
+
import markdownItFootnote from 'markdown-it-footnote'
|
|
156
|
+
import markdownItMark from 'markdown-it-mark'
|
|
157
|
+
import markdownItSub from 'markdown-it-sub'
|
|
158
|
+
import markdownItSup from 'markdown-it-sup'
|
|
159
|
+
import { viteMdPlugin } from '@md-plugins/vite-md-plugin'
|
|
160
|
+
|
|
161
|
+
export default defineConfig({
|
|
162
|
+
plugins: [
|
|
163
|
+
vue(),
|
|
164
|
+
viteMdPlugin({
|
|
165
|
+
path: './src/markdown',
|
|
166
|
+
menu: [],
|
|
167
|
+
config: {
|
|
168
|
+
markdownItPlugins: [
|
|
169
|
+
markdownItMark, // ==highlight==
|
|
170
|
+
markdownItSub, // H~2~O
|
|
171
|
+
markdownItSup, // E=mc^2^
|
|
172
|
+
markdownItFootnote, // footnote references
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
}),
|
|
176
|
+
],
|
|
177
|
+
})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
If you own a raw MarkdownIt instance instead of using `viteMdPlugin`, wire the plugins directly:
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
import MarkdownIt from 'markdown-it'
|
|
184
|
+
import markdownItMark from 'markdown-it-mark'
|
|
185
|
+
|
|
186
|
+
const md = new MarkdownIt()
|
|
187
|
+
md.use(markdownItMark)
|
|
188
|
+
```
|
|
189
|
+
|
|
131
190
|
### Quasar Framework Configuration
|
|
132
191
|
|
|
133
192
|
If you’re using the Quasar Framework with Vite, additional configuration is needed to enable support for `.md` files:
|
|
@@ -210,55 +269,26 @@ export interface MenuItem {
|
|
|
210
269
|
#### `config`
|
|
211
270
|
|
|
212
271
|
- **Type**: `MarkdownOptions`
|
|
213
|
-
- **Description**: Additional configuration options for the Markdown
|
|
214
|
-
|
|
215
|
-
````ts
|
|
216
|
-
import { Options } from 'markdown-it';
|
|
217
|
-
import { BlockquotePluginOptions } from '@md-plugins/md-plugin-blockquote';
|
|
218
|
-
import { CodeblockPluginOptions } from '@md-plugins/md-plugin-codeblocks';
|
|
219
|
-
import { FrontmatterPluginOptions } from '@md-plugins/md-plugin-frontmatter';
|
|
220
|
-
import { HeadersPluginOptions } from '@md-plugins/md-plugin-headers';
|
|
221
|
-
import { ImagePluginOptions } from '@md-plugins/md-plugin-image';
|
|
222
|
-
import { InlineCodePluginOptions } from '@md-plugins/md-plugin-inlinecode';
|
|
223
|
-
import { LinkPluginOptions } from '@md-plugins/md-plugin-link';
|
|
224
|
-
import { TablePluginOptions } from '@md-plugins/md-plugin-table';
|
|
225
|
-
|
|
226
|
-
interface MarkdownOptions extends Options {
|
|
227
|
-
html?: boolean;
|
|
228
|
-
linkify?: boolean;
|
|
229
|
-
typographer?: boolean;
|
|
230
|
-
breaks?: boolean;
|
|
231
|
-
blockquote?: BlockquotePluginOptions;
|
|
232
|
-
codeblocks?: CodeblockPluginOptions;
|
|
233
|
-
frontmatter?: FrontmatterPluginOptions;
|
|
234
|
-
headers?: HeadersPluginOptions | boolean;
|
|
235
|
-
image?: ImagePluginOptions;
|
|
236
|
-
inlinecode?: InlineCodePluginOptions;
|
|
237
|
-
link?: LinkPluginOptions;
|
|
238
|
-
table?: TablePluginOptions;
|
|
239
|
-
}
|
|
240
|
-
```
|
|
272
|
+
- **Description**: Additional configuration options for the Markdown processor and bundled md-plugins.
|
|
241
273
|
|
|
242
|
-
|
|
274
|
+
Use `config.markdownItPlugins` for extra Markdown-it syntax that md-plugins does not bundle by default. Use `config.mermaidPlugin` to customize Mermaid rendering.
|
|
243
275
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
import { defineConfig } from 'vite'
|
|
248
|
-
import vue from '@vitejs/plugin-vue'
|
|
276
|
+
```ts
|
|
249
277
|
import { viteMdPlugin } from '@md-plugins/vite-md-plugin'
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
278
|
+
import markdownItMark from 'markdown-it-mark'
|
|
279
|
+
|
|
280
|
+
viteMdPlugin({
|
|
281
|
+
path: './src/markdown',
|
|
282
|
+
menu: [],
|
|
283
|
+
config: {
|
|
284
|
+
markdownItPlugins: [markdownItMark],
|
|
285
|
+
mermaidPlugin: {
|
|
286
|
+
renderMode: 'component',
|
|
287
|
+
componentName: 'MarkdownMermaid',
|
|
288
|
+
},
|
|
289
|
+
},
|
|
260
290
|
})
|
|
261
|
-
|
|
291
|
+
```
|
|
262
292
|
|
|
263
293
|
### Using the Plugin
|
|
264
294
|
|
|
@@ -31,6 +31,7 @@ The `viteMdPlugin` is built on top of the following plugins:
|
|
|
31
31
|
| `@md-plugins/md-plugin-inlinecode` | Adds a custom class to inline code blocks for styling. | [README](packages/md-plugin-inlinecode/README.md) | [Docs](/md-plugins/inline-code/overview) |
|
|
32
32
|
| `@md-plugins/md-plugin-imports` | Extracts and processes `<script import>` blocks from Markdown. | [README](packages/md-plugin-imports/README.md) | [Docs](/md-plugins/imports/overview) |
|
|
33
33
|
| `@md-plugins/md-plugin-link` | Converts Markdown links into Vue components for SPA-friendly routing. | [README](packages/md-plugin-link/README.md) | [Docs](/md-plugins/link/overview) |
|
|
34
|
+
| `@md-plugins/md-plugin-mermaid` | Renders Mermaid fenced code blocks as diagrams. | [README](packages/md-plugin-mermaid/README.md) | [Docs](/md-plugins/mermaid/overview) |
|
|
34
35
|
| `@md-plugins/md-plugin-table` | Adds custom classes and attributes to Markdown tables. | [README](packages/md-plugin-table/README.md) | [Docs](/md-plugins/table/overview) |
|
|
35
36
|
| `@md-plugins/md-plugin-title` | Extracts the first header in Markdown as the page title. | [README](packages/md-plugin-title/README.md) | [Docs](/md-plugins/title/overview) |
|
|
36
37
|
| `@md-plugins/md-plugin-frontmatter` | Extracts and processes frontmatter content from Markdown files. | [README](packages/md-plugin-frontmatter/README.md) | [Docs](/md-plugins/frontmatter/overview) |
|
|
@@ -235,6 +235,13 @@ const mdPluginsMenu: SiteMenuItem = {
|
|
|
235
235
|
{ name: 'Advanced', path: '/md-plugins/link/advanced' },
|
|
236
236
|
],
|
|
237
237
|
},
|
|
238
|
+
{
|
|
239
|
+
name: 'Mermaid',
|
|
240
|
+
children: [
|
|
241
|
+
{ name: 'Overview', path: '/md-plugins/mermaid/overview' },
|
|
242
|
+
{ name: 'Advanced', path: '/md-plugins/mermaid/advanced' },
|
|
243
|
+
],
|
|
244
|
+
},
|
|
238
245
|
{
|
|
239
246
|
name: 'Table',
|
|
240
247
|
children: [
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="markdown-mermaid q-my-md">
|
|
3
|
+
<div
|
|
4
|
+
v-if="errorMessage"
|
|
5
|
+
class="markdown-mermaid__error"
|
|
6
|
+
role="alert"
|
|
7
|
+
>
|
|
8
|
+
{{ errorMessage }}
|
|
9
|
+
</div>
|
|
10
|
+
<div
|
|
11
|
+
v-else-if="isRendering"
|
|
12
|
+
class="markdown-mermaid__loading"
|
|
13
|
+
>
|
|
14
|
+
Rendering diagram...
|
|
15
|
+
</div>
|
|
16
|
+
<div
|
|
17
|
+
ref="containerRef"
|
|
18
|
+
class="markdown-mermaid__diagram"
|
|
19
|
+
></div>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup lang="ts">
|
|
24
|
+
import { uid, useQuasar } from 'quasar'
|
|
25
|
+
import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
26
|
+
|
|
27
|
+
const props = defineProps<{
|
|
28
|
+
code: string
|
|
29
|
+
}>()
|
|
30
|
+
|
|
31
|
+
const $q = useQuasar()
|
|
32
|
+
const containerRef = ref<HTMLElement | null>(null)
|
|
33
|
+
const errorMessage = ref('')
|
|
34
|
+
const isRendering = ref(false)
|
|
35
|
+
|
|
36
|
+
let disposed = false
|
|
37
|
+
let renderRequest = 0
|
|
38
|
+
|
|
39
|
+
async function renderDiagram(): Promise<void> {
|
|
40
|
+
if (import.meta.env.QUASAR_CLIENT !== true || containerRef.value === null) {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const requestId = ++renderRequest
|
|
45
|
+
|
|
46
|
+
errorMessage.value = ''
|
|
47
|
+
isRendering.value = true
|
|
48
|
+
|
|
49
|
+
await nextTick()
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const { default: mermaid } = await import('mermaid')
|
|
53
|
+
|
|
54
|
+
mermaid.initialize({
|
|
55
|
+
securityLevel: 'strict',
|
|
56
|
+
startOnLoad: false,
|
|
57
|
+
theme: $q.dark.isActive === true ? 'dark' : 'default',
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const { svg, bindFunctions } = await mermaid.render(`markdown-mermaid-${uid()}`, props.code)
|
|
61
|
+
|
|
62
|
+
if (disposed === true || requestId !== renderRequest || containerRef.value === null) {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
containerRef.value.innerHTML = svg
|
|
67
|
+
bindFunctions?.(containerRef.value)
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (disposed === false && requestId === renderRequest) {
|
|
70
|
+
errorMessage.value = error instanceof Error ? error.message : 'Unable to render diagram.'
|
|
71
|
+
}
|
|
72
|
+
} finally {
|
|
73
|
+
if (disposed === false && requestId === renderRequest) {
|
|
74
|
+
isRendering.value = false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
onMounted(() => {
|
|
80
|
+
void renderDiagram()
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
watch(
|
|
84
|
+
() => [props.code, $q.dark.isActive] as const,
|
|
85
|
+
() => {
|
|
86
|
+
void renderDiagram()
|
|
87
|
+
},
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
onBeforeUnmount(() => {
|
|
91
|
+
disposed = true
|
|
92
|
+
})
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
|
+
<style lang="scss">
|
|
96
|
+
.markdown-mermaid {
|
|
97
|
+
border: 1px solid var(--q-separator-color);
|
|
98
|
+
border-radius: 8px;
|
|
99
|
+
overflow-x: auto;
|
|
100
|
+
padding: 1rem;
|
|
101
|
+
|
|
102
|
+
&__diagram {
|
|
103
|
+
min-width: 100%;
|
|
104
|
+
text-align: center;
|
|
105
|
+
|
|
106
|
+
svg {
|
|
107
|
+
max-width: 100%;
|
|
108
|
+
height: auto;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
&__error {
|
|
113
|
+
color: var(--q-negative);
|
|
114
|
+
font-family: monospace;
|
|
115
|
+
white-space: pre-wrap;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&__loading {
|
|
119
|
+
color: var(--q-secondary);
|
|
120
|
+
font-style: italic;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
</style>
|