diff --git a/content/deck-test.md b/content/deck-test.md new file mode 100644 index 0000000..9c6dc53 --- /dev/null +++ b/content/deck-test.md @@ -0,0 +1,35 @@ +# yaml/tag 代码块格式测试 + +## 使用 yaml/tag 语法创建 md-deck + +```yaml/tag +tag: md-deck +body: ./sparks.csv +size: 54x86 +grid: 5x8 +bleed: 1 +padding: 2 +font-size: 3 +``` + +## 使用 body 字段添加内容 + +```yaml/tag +tag: tag-box +class: note +body: | + 这是一个提示框 +``` + +## 带引号的值 + +```yaml/tag +tag: tag-alert +type: warning +class: my-alert +body: 这是一个警告信息 +``` + +## 旧的指令语法仍然可用 + +:md-deck[./sparks.csv]{size="54x86" grid="5x8"} diff --git a/package-lock.json b/package-lock.json index cc4ab2e..7866597 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "chokidar": "^5.0.0", "commander": "^12.1.0", "csv-parse": "^5.5.6", + "js-yaml": "^4.1.1", "marked": "^14.1.0", "marked-directive": "^1.0.7", "solid-element": "^1.9.1", @@ -2251,6 +2252,12 @@ "dev": true, "license": "MIT" }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, "node_modules/attributes-parser": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/attributes-parser/-/attributes-parser-2.2.3.tgz", @@ -2669,6 +2676,18 @@ "dev": true, "license": "MIT" }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", diff --git a/package.json b/package.json index c6bede1..7603419 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "chokidar": "^5.0.0", "commander": "^12.1.0", "csv-parse": "^5.5.6", + "js-yaml": "^4.1.1", "marked": "^14.1.0", "marked-directive": "^1.0.7", "solid-element": "^1.9.1", diff --git a/src/markdown/index.ts b/src/markdown/index.ts index d3944f4..0fb9a50 100644 --- a/src/markdown/index.ts +++ b/src/markdown/index.ts @@ -1,5 +1,6 @@ import { Marked } from 'marked'; import {createDirectives, presetDirectiveConfigs} from 'marked-directive'; +import yaml from 'js-yaml'; // 使用 marked-directive 来支持指令语法 const marked = new Marked().use(createDirectives([ @@ -23,7 +24,63 @@ const marked = new Marked().use(createDirectives([ return false; } }, -])); +]), { + // 自定义代码块渲染器,支持 yaml/tag 格式 + extensions: [{ + name: 'code-block-yaml-tag', + level: 'block', + start(src: string) { + // 检测 ```yaml/tag 开头的代码块 + return src.match(/^```yaml\/tag\s*\n/m)?.index; + }, + tokenizer(src: string) { + const rule = /^```yaml\/tag\s*\n([\s\S]*?)\n```/; + const match = rule.exec(src); + if (match) { + const yamlContent = match[1]?.trim() || ''; + const props = yaml.load(yamlContent) as Record || {}; + + // 提取 tag 名称,默认为 tag-unknown + const tagName = (props.tag as string) || 'tag-unknown'; + + // 移除 tag 属性,剩下的作为 HTML 属性 + const { tag, ...rest } = props; + + // 提取 innerText 内容(如果有 body 字段) + let content = ''; + if ('body' in rest) { + content = String(rest.body || ''); + delete (rest as Record).body; + } + + // 构建属性字符串 + const propsStr = Object.entries(rest) + .map(([key, value]) => { + const strValue = String(value); + // 如果值包含空格或特殊字符,添加引号 + if (strValue.includes(' ') || strValue.includes('"')) { + return `${key}="${strValue.replace(/"/g, '"')}"`; + } + return `${key}="${strValue}"`; + }) + .join(' '); + + return { + type: 'code-block-yaml-tag', + raw: match[0], + tagName, + props: propsStr, + content + }; + } + }, + renderer(token: any) { + // 渲染为自定义 HTML 标签 + const propsAttr = token.props ? ` ${token.props}` : ''; + return `<${token.tagName}${propsAttr}>${token.content || ''}\n`; + } + }] +}); export function parseMarkdown(content: string): string { return marked.parse(content.trimStart()) as string;