@c2-markdown-ui/marked-ext 0.0.0-stage → 1.4.3
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 +70 -2
- package/dist/ext.d.ts +21 -0
- package/dist/ext.js +69 -0
- package/package.json +39 -4
package/README.md
CHANGED
|
@@ -1,3 +1,71 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @c2-markdown-ui/marked-ext
|
|
2
|
+
**Turn your Markdown parser into a widget factory.**
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
Transform `markdown-ui-widget` code blocks into interactive components with zero configuration.
|
|
5
|
+
|
|
6
|
+
✨ [Try the live demo](https://markdown-ui.com/) ✨
|
|
7
|
+
|
|
8
|
+
Works with any Marked.js setup—just add the extension and widgets come alive.
|
|
9
|
+
|
|
10
|
+
## Get started in 30 seconds
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @c2-markdown-ui/marked-ext marked
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { Marked } from 'marked';
|
|
18
|
+
import { markedUiExtension } from '@c2-markdown-ui/marked-ext';
|
|
19
|
+
|
|
20
|
+
const marked = new Marked();
|
|
21
|
+
marked.use(markedUiExtension);
|
|
22
|
+
|
|
23
|
+
// This markdown...
|
|
24
|
+
const markdown = `
|
|
25
|
+
\`\`\`markdown-ui-widget
|
|
26
|
+
select env [dev staging prod]
|
|
27
|
+
\`\`\`
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
const html = marked.parse(markdown);
|
|
31
|
+
// ...becomes interactive widgets!
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Two syntaxes, same magic
|
|
35
|
+
|
|
36
|
+
Write widgets in **JSON** (traditional) or **DSL** (60% more concise):
|
|
37
|
+
|
|
38
|
+
**DSL** ⚡
|
|
39
|
+
```markdown
|
|
40
|
+
text-input username "Username" "Enter username"
|
|
41
|
+
button-group env [dev staging prod] dev
|
|
42
|
+
select region [us-east-1 us-west-2] us-east-1
|
|
43
|
+
form config "Submit"
|
|
44
|
+
text-input name "Name"
|
|
45
|
+
select env [dev prod]
|
|
46
|
+
chart-line
|
|
47
|
+
title: Revenue Growth
|
|
48
|
+
Month,Sales
|
|
49
|
+
Jan,100
|
|
50
|
+
Feb,150
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**JSON** 📝
|
|
54
|
+
```json
|
|
55
|
+
{"type": "text-input", "id": "username", "label": "Username"}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Both work identically—the extension auto-detects the format.
|
|
59
|
+
|
|
60
|
+
## How it works
|
|
61
|
+
|
|
62
|
+
1. **Detects** `markdown-ui-widget` code blocks in your Markdown
|
|
63
|
+
2. **Encodes** widget config as URL-encoded JSON with unique IDs
|
|
64
|
+
3. **Generates** `<markdown-ui-widget>` custom elements
|
|
65
|
+
4. **Renders** with your framework (React, Svelte, Vue)
|
|
66
|
+
|
|
67
|
+
Perfect separation—any parser, any renderer, any framework.
|
|
68
|
+
|
|
69
|
+
**Next step:** Add a renderer like `@c2-markdown-ui/react` or `@c2-markdown-ui/svelte` to see your widgets come alive.
|
|
70
|
+
|
|
71
|
+
MIT © 2025
|
package/dist/ext.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type MarkedExtension } from 'marked';
|
|
2
|
+
export interface MarkedUiExtensionOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Enable streaming mode for AI content generation.
|
|
5
|
+
* When true, uses streaming-aware parser that handles incomplete input gracefully.
|
|
6
|
+
*/
|
|
7
|
+
streaming?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create a marked extension for markdown-ui widgets.
|
|
11
|
+
* @param options Configuration options
|
|
12
|
+
*/
|
|
13
|
+
export declare function createMarkedUiExtension(options?: MarkedUiExtensionOptions): MarkedExtension;
|
|
14
|
+
/**
|
|
15
|
+
* Default marked extension (non-streaming mode for backward compatibility)
|
|
16
|
+
*/
|
|
17
|
+
export declare const markedUiExtension: MarkedExtension;
|
|
18
|
+
/**
|
|
19
|
+
* Streaming-aware marked extension for AI content generation
|
|
20
|
+
*/
|
|
21
|
+
export declare const markedUiStreamingExtension: MarkedExtension;
|
package/dist/ext.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid';
|
|
2
|
+
import { parseDSL, parseDSLStreaming } from '@c2-markdown-ui/mdui-lang';
|
|
3
|
+
/**
|
|
4
|
+
* Create a marked extension for markdown-ui widgets.
|
|
5
|
+
* @param options Configuration options
|
|
6
|
+
*/
|
|
7
|
+
export function createMarkedUiExtension(options = {}) {
|
|
8
|
+
const { streaming = false } = options;
|
|
9
|
+
return {
|
|
10
|
+
renderer: {
|
|
11
|
+
code(token) {
|
|
12
|
+
const lang = token.lang;
|
|
13
|
+
if (lang === "markdown-ui-widget") {
|
|
14
|
+
const text = token.text.trim();
|
|
15
|
+
let payloadJson = {};
|
|
16
|
+
let finalPayload;
|
|
17
|
+
// Try JSON first
|
|
18
|
+
try {
|
|
19
|
+
payloadJson = JSON.parse(text);
|
|
20
|
+
finalPayload = text; // Use original JSON
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
// Not JSON, try DSL parsing
|
|
24
|
+
if (streaming) {
|
|
25
|
+
// Use streaming-aware parser for AI content
|
|
26
|
+
const result = parseDSLStreaming(text);
|
|
27
|
+
if (result.widget) {
|
|
28
|
+
payloadJson = result.widget;
|
|
29
|
+
// Add streaming metadata
|
|
30
|
+
payloadJson._streaming = !result.complete;
|
|
31
|
+
payloadJson._pending = result.pending;
|
|
32
|
+
finalPayload = JSON.stringify(payloadJson);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Can't even detect widget type, render as code block
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Use standard parser
|
|
41
|
+
const result = parseDSL(text);
|
|
42
|
+
if (result.success && result.widget) {
|
|
43
|
+
payloadJson = result.widget;
|
|
44
|
+
finalPayload = JSON.stringify(result.widget);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Failed to parse, render as code block
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const payload = encodeURIComponent(finalPayload);
|
|
53
|
+
const id = payloadJson.id || nanoid();
|
|
54
|
+
return `<markdown-ui-widget id="${id}" content="${payload}"></markdown-ui-widget>\n`;
|
|
55
|
+
}
|
|
56
|
+
// fall back to default rendering
|
|
57
|
+
return false; // tells marked to use its default renderer for other languages
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Default marked extension (non-streaming mode for backward compatibility)
|
|
64
|
+
*/
|
|
65
|
+
export const markedUiExtension = createMarkedUiExtension({ streaming: false });
|
|
66
|
+
/**
|
|
67
|
+
* Streaming-aware marked extension for AI content generation
|
|
68
|
+
*/
|
|
69
|
+
export const markedUiStreamingExtension = createMarkedUiExtension({ streaming: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
{
|
|
2
|
+
"version": "1.4.3",
|
|
3
|
+
"description": "Marked extension for markdown-ui widgets",
|
|
2
4
|
"name": "@c2-markdown-ui/marked-ext",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/ext.js",
|
|
7
|
+
"types": "./dist/ext.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist/"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/ext.js",
|
|
14
|
+
"require": "./dist/ext.js",
|
|
15
|
+
"types": "./dist/ext.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"marked",
|
|
24
|
+
"markdown",
|
|
25
|
+
"extension",
|
|
26
|
+
"widgets"
|
|
27
|
+
],
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@c2-markdown-ui/mdui-lang": "^0.4.4",
|
|
32
|
+
"nanoid": "^5.1.5"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^24.3.0",
|
|
36
|
+
"marked": "^16.2.0"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
}
|
|
41
|
+
}
|