@wireweave/markdown-plugin 1.1.0 → 1.2.1-beta.1
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 +12 -3
- package/package.json +3 -3
- package/src/index.ts +0 -163
- package/src/markdown-it.ts +0 -43
- package/src/marked.ts +0 -34
- package/src/remarkable.ts +0 -84
package/README.md
CHANGED
|
@@ -32,7 +32,8 @@ import { markdownItWireframe } from '@wireweave/markdown-plugin';
|
|
|
32
32
|
|
|
33
33
|
const md = new MarkdownIt();
|
|
34
34
|
md.use(markdownItWireframe, {
|
|
35
|
-
format: 'svg-img', // or 'html', 'svg'
|
|
35
|
+
format: 'svg-img', // or 'html', 'html-preview', 'svg'
|
|
36
|
+
theme: 'light', // or 'dark'
|
|
36
37
|
});
|
|
37
38
|
|
|
38
39
|
const html = md.render(`
|
|
@@ -59,6 +60,7 @@ import { markedWireframe } from '@wireweave/markdown-plugin';
|
|
|
59
60
|
|
|
60
61
|
marked.use(markedWireframe({
|
|
61
62
|
format: 'svg-img',
|
|
63
|
+
theme: 'light',
|
|
62
64
|
}));
|
|
63
65
|
|
|
64
66
|
const html = marked.parse(`
|
|
@@ -79,6 +81,7 @@ import { remarkableWireframe } from '@wireweave/markdown-plugin';
|
|
|
79
81
|
const md = new Remarkable();
|
|
80
82
|
remarkableWireframe(md, {
|
|
81
83
|
format: 'svg-img',
|
|
84
|
+
theme: 'light',
|
|
82
85
|
});
|
|
83
86
|
|
|
84
87
|
const html = md.render(`
|
|
@@ -94,15 +97,19 @@ All plugins accept the same options:
|
|
|
94
97
|
|
|
95
98
|
| Option | Type | Default | Description |
|
|
96
99
|
|--------|------|---------|-------------|
|
|
97
|
-
| `format` | `'html' \| 'svg' \| 'svg-img'` | `'svg-img'` | Output format |
|
|
100
|
+
| `format` | `'html' \| 'html-preview' \| 'svg' \| 'svg-img'` | `'svg-img'` | Output format |
|
|
101
|
+
| `theme` | `'light' \| 'dark'` | `'light'` | Theme for rendering |
|
|
98
102
|
| `containerClass` | `string` | `'wireframe-container'` | CSS class for wrapper div |
|
|
99
103
|
| `errorHandling` | `'code' \| 'error' \| 'both'` | `'both'` | How to handle parse errors |
|
|
104
|
+
| `containerWidth` | `number` | `0` | Container width for preview scaling (0 = no scaling) |
|
|
105
|
+
| `maxScale` | `number` | `1` | Maximum scale factor (prevents upscaling beyond this value) |
|
|
100
106
|
|
|
101
107
|
### Output Formats
|
|
102
108
|
|
|
103
109
|
- **`svg-img`** (default): Base64-encoded SVG in an `<img>` tag. Best for compatibility.
|
|
104
110
|
- **`svg`**: Inline SVG. Allows CSS styling but may conflict with page styles.
|
|
105
111
|
- **`html`**: Full HTML/CSS rendering. Interactive but may conflict with page styles.
|
|
112
|
+
- **`html-preview`**: HTML with preview container that supports scaling to fit container width.
|
|
106
113
|
|
|
107
114
|
### Error Handling
|
|
108
115
|
|
|
@@ -120,8 +127,10 @@ import { renderWireframe } from '@wireweave/markdown-plugin';
|
|
|
120
127
|
const html = renderWireframe(`
|
|
121
128
|
page { button "Click" primary }
|
|
122
129
|
`, {
|
|
123
|
-
format: '
|
|
130
|
+
format: 'html-preview',
|
|
131
|
+
theme: 'light',
|
|
124
132
|
containerClass: 'my-wireframe',
|
|
133
|
+
containerWidth: 600, // Scale to fit 600px width
|
|
125
134
|
});
|
|
126
135
|
```
|
|
127
136
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wireweave/markdown-plugin",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.2.1-beta.1",
|
|
4
4
|
"description": "Markdown plugins for wireweave",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
32
|
"dist",
|
|
33
|
-
"
|
|
33
|
+
"README.md"
|
|
34
34
|
],
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "tsup",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@wireweave/core": "1.1
|
|
59
|
+
"@wireweave/core": "^1.4.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@release-it/conventional-changelog": "^10.0.4",
|
package/src/index.ts
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @wireweave/markdown-plugin
|
|
3
|
-
*
|
|
4
|
-
* Markdown plugins for wireweave
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
parse,
|
|
9
|
-
render,
|
|
10
|
-
renderToSvg,
|
|
11
|
-
resolveViewport,
|
|
12
|
-
wrapInPreviewContainer,
|
|
13
|
-
} from '@wireweave/core';
|
|
14
|
-
|
|
15
|
-
export interface WireframePluginOptions {
|
|
16
|
-
/**
|
|
17
|
-
* Output format
|
|
18
|
-
* - 'html': HTML/CSS rendering (inline styles)
|
|
19
|
-
* - 'html-preview': HTML with preview container (supports scaling)
|
|
20
|
-
* - 'svg': SVG image
|
|
21
|
-
* - 'svg-img': base64 encoded img tag
|
|
22
|
-
*/
|
|
23
|
-
format?: 'html' | 'html-preview' | 'svg' | 'svg-img';
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Theme for rendering
|
|
27
|
-
* - 'light': Light theme
|
|
28
|
-
* - 'dark': Dark theme
|
|
29
|
-
*/
|
|
30
|
-
theme?: 'light' | 'dark';
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Container class for wrapping SVG/HTML
|
|
34
|
-
*/
|
|
35
|
-
containerClass?: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Error handling mode
|
|
39
|
-
* - 'code': Show original code
|
|
40
|
-
* - 'error': Show error message
|
|
41
|
-
* - 'both': Show both
|
|
42
|
-
*/
|
|
43
|
-
errorHandling?: 'code' | 'error' | 'both';
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Container width for preview scaling (in pixels)
|
|
47
|
-
* When set, the wireframe will be scaled to fit this width
|
|
48
|
-
*/
|
|
49
|
-
containerWidth?: number;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Maximum scale factor (default: 1)
|
|
53
|
-
* Prevents the preview from being scaled up beyond this value
|
|
54
|
-
*/
|
|
55
|
-
maxScale?: number;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const defaultOptions: Required<WireframePluginOptions> = {
|
|
59
|
-
format: 'svg-img',
|
|
60
|
-
theme: 'light',
|
|
61
|
-
containerClass: 'wireframe-container',
|
|
62
|
-
errorHandling: 'both',
|
|
63
|
-
containerWidth: 0, // 0 means no scaling
|
|
64
|
-
maxScale: 1,
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Render wireframe code to output format
|
|
69
|
-
*/
|
|
70
|
-
export function renderWireframe(
|
|
71
|
-
code: string,
|
|
72
|
-
options: WireframePluginOptions = {}
|
|
73
|
-
): string {
|
|
74
|
-
const opts = { ...defaultOptions, ...options };
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
const doc = parse(code);
|
|
78
|
-
|
|
79
|
-
switch (opts.format) {
|
|
80
|
-
case 'html': {
|
|
81
|
-
const { html, css } = render(doc, { theme: opts.theme });
|
|
82
|
-
return `
|
|
83
|
-
<div class="${opts.containerClass}">
|
|
84
|
-
<style>${css}</style>
|
|
85
|
-
${html}
|
|
86
|
-
</div>
|
|
87
|
-
`.trim();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
case 'html-preview': {
|
|
91
|
-
const { html, css } = render(doc, { theme: opts.theme });
|
|
92
|
-
const firstPage = doc.children[0];
|
|
93
|
-
const viewport = resolveViewport(firstPage?.viewport, firstPage?.device);
|
|
94
|
-
|
|
95
|
-
const previewHtml = wrapInPreviewContainer(html, viewport, {
|
|
96
|
-
darkMode: opts.theme === 'dark',
|
|
97
|
-
containerWidth: opts.containerWidth > 0 ? opts.containerWidth : undefined,
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
return `
|
|
101
|
-
<div class="${opts.containerClass}">
|
|
102
|
-
<style>${css}</style>
|
|
103
|
-
${previewHtml}
|
|
104
|
-
</div>
|
|
105
|
-
`.trim();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
case 'svg': {
|
|
109
|
-
const { svg } = renderToSvg(doc);
|
|
110
|
-
return `<div class="${opts.containerClass}">${svg}</div>`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
case 'svg-img':
|
|
114
|
-
default: {
|
|
115
|
-
const { svg } = renderToSvg(doc);
|
|
116
|
-
// Use btoa for browser compatibility, Buffer for Node.js
|
|
117
|
-
const base64 =
|
|
118
|
-
typeof Buffer !== 'undefined'
|
|
119
|
-
? Buffer.from(svg).toString('base64')
|
|
120
|
-
: btoa(svg);
|
|
121
|
-
return `
|
|
122
|
-
<div class="${opts.containerClass}">
|
|
123
|
-
<img src="data:image/svg+xml;base64,${base64}" alt="Wireframe" />
|
|
124
|
-
</div>
|
|
125
|
-
`.trim();
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
} catch (error) {
|
|
129
|
-
return renderError(code, error as Error, opts);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function renderError(
|
|
134
|
-
code: string,
|
|
135
|
-
error: Error,
|
|
136
|
-
options: Required<WireframePluginOptions>
|
|
137
|
-
): string {
|
|
138
|
-
const errorHtml = `<pre class="wireframe-error">${escapeHtml(error.message)}</pre>`;
|
|
139
|
-
const codeHtml = `<pre class="wireframe-source"><code>${escapeHtml(code)}</code></pre>`;
|
|
140
|
-
|
|
141
|
-
switch (options.errorHandling) {
|
|
142
|
-
case 'code':
|
|
143
|
-
return codeHtml;
|
|
144
|
-
case 'error':
|
|
145
|
-
return errorHtml;
|
|
146
|
-
case 'both':
|
|
147
|
-
default:
|
|
148
|
-
return `<div class="${options.containerClass} wireframe-error-container">${errorHtml}${codeHtml}</div>`;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function escapeHtml(text: string): string {
|
|
153
|
-
return text
|
|
154
|
-
.replace(/&/g, '&')
|
|
155
|
-
.replace(/</g, '<')
|
|
156
|
-
.replace(/>/g, '>')
|
|
157
|
-
.replace(/"/g, '"')
|
|
158
|
-
.replace(/'/g, ''');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export { markdownItWireframe } from './markdown-it';
|
|
162
|
-
export { markedWireframe } from './marked';
|
|
163
|
-
export { remarkableWireframe } from './remarkable';
|
package/src/markdown-it.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* markdown-it plugin for wireweave
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type MarkdownIt from 'markdown-it';
|
|
6
|
-
import { renderWireframe, WireframePluginOptions } from './index';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* markdown-it plugin
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* import MarkdownIt from 'markdown-it';
|
|
14
|
-
* import { markdownItWireframe } from '@wireweave/markdown-plugin/markdown-it';
|
|
15
|
-
*
|
|
16
|
-
* const md = new MarkdownIt();
|
|
17
|
-
* md.use(markdownItWireframe, { format: 'svg' });
|
|
18
|
-
*
|
|
19
|
-
* const html = md.render('```wireframe\npage { text "Hello" }\n```');
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
export function markdownItWireframe(
|
|
23
|
-
md: MarkdownIt,
|
|
24
|
-
options: WireframePluginOptions = {}
|
|
25
|
-
): void {
|
|
26
|
-
const defaultFence = md.renderer.rules.fence;
|
|
27
|
-
|
|
28
|
-
md.renderer.rules.fence = (tokens, idx, opts, env, self) => {
|
|
29
|
-
const token = tokens[idx];
|
|
30
|
-
const info = token.info.trim();
|
|
31
|
-
|
|
32
|
-
if (info === 'wireframe' || info === 'wf') {
|
|
33
|
-
return renderWireframe(token.content, options);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Use default renderer for other code blocks
|
|
37
|
-
if (defaultFence) {
|
|
38
|
-
return defaultFence(tokens, idx, opts, env, self);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return `<pre><code class="language-${info}">${md.utils.escapeHtml(token.content)}</code></pre>`;
|
|
42
|
-
};
|
|
43
|
-
}
|
package/src/marked.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* marked extension for wireweave
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { MarkedExtension, Tokens } from 'marked';
|
|
6
|
-
import { renderWireframe, WireframePluginOptions } from './index';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* marked extension
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* import { marked } from 'marked';
|
|
14
|
-
* import { markedWireframe } from '@wireweave/markdown-plugin/marked';
|
|
15
|
-
*
|
|
16
|
-
* marked.use(markedWireframe({ format: 'svg' }));
|
|
17
|
-
*
|
|
18
|
-
* const html = marked.parse('```wireframe\npage { text "Hello" }\n```');
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
export function markedWireframe(
|
|
22
|
-
options: WireframePluginOptions = {}
|
|
23
|
-
): MarkedExtension {
|
|
24
|
-
return {
|
|
25
|
-
renderer: {
|
|
26
|
-
code(token: Tokens.Code): string | false {
|
|
27
|
-
if (token.lang === 'wireframe' || token.lang === 'wf') {
|
|
28
|
-
return renderWireframe(token.text, options);
|
|
29
|
-
}
|
|
30
|
-
return false; // Use default renderer
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
}
|
package/src/remarkable.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* remarkable plugin for wireweave
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { renderWireframe, WireframePluginOptions } from './index';
|
|
6
|
-
|
|
7
|
-
// Type declarations for remarkable (no @types/remarkable available)
|
|
8
|
-
interface RemarkableToken {
|
|
9
|
-
type: string;
|
|
10
|
-
params: string;
|
|
11
|
-
content: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface RemarkableRenderer {
|
|
15
|
-
rules: {
|
|
16
|
-
fence: (
|
|
17
|
-
tokens: RemarkableToken[],
|
|
18
|
-
idx: number,
|
|
19
|
-
options: Record<string, unknown>,
|
|
20
|
-
env: Record<string, unknown>
|
|
21
|
-
) => string;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface RemarkableUtils {
|
|
26
|
-
escapeHtml: (text: string) => string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface Remarkable {
|
|
30
|
-
renderer: RemarkableRenderer;
|
|
31
|
-
utils: RemarkableUtils;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* remarkable plugin
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```typescript
|
|
39
|
-
* import { Remarkable } from 'remarkable';
|
|
40
|
-
* import { remarkableWireframe } from '@wireweave/markdown-plugin/remarkable';
|
|
41
|
-
*
|
|
42
|
-
* const md = new Remarkable();
|
|
43
|
-
* md.use(remarkableWireframe({ format: 'svg' }));
|
|
44
|
-
*
|
|
45
|
-
* const html = md.render('```wireframe\npage { text "Hello" }\n```');
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
/**
|
|
49
|
-
* Escape HTML entities
|
|
50
|
-
*/
|
|
51
|
-
function escapeHtml(text: string): string {
|
|
52
|
-
return text
|
|
53
|
-
.replace(/&/g, '&')
|
|
54
|
-
.replace(/</g, '<')
|
|
55
|
-
.replace(/>/g, '>')
|
|
56
|
-
.replace(/"/g, '"');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function remarkableWireframe(
|
|
60
|
-
options: WireframePluginOptions = {}
|
|
61
|
-
): (md: Remarkable) => void {
|
|
62
|
-
return (md: Remarkable) => {
|
|
63
|
-
const rules = md.renderer.rules;
|
|
64
|
-
|
|
65
|
-
// Override fence rule completely
|
|
66
|
-
rules.fence = (
|
|
67
|
-
tokens: RemarkableToken[],
|
|
68
|
-
idx: number,
|
|
69
|
-
_opts: Record<string, unknown>,
|
|
70
|
-
_env: Record<string, unknown>
|
|
71
|
-
): string => {
|
|
72
|
-
const token = tokens[idx];
|
|
73
|
-
const lang = token.params || '';
|
|
74
|
-
|
|
75
|
-
if (lang === 'wireframe' || lang === 'wf') {
|
|
76
|
-
return renderWireframe(token.content, options);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Render other code blocks with syntax highlighting class
|
|
80
|
-
const langClass = lang ? ` class="language-${escapeHtml(lang)}"` : '';
|
|
81
|
-
return `<pre><code${langClass}>${escapeHtml(token.content)}</code></pre>\n`;
|
|
82
|
-
};
|
|
83
|
-
};
|
|
84
|
-
}
|