From 5f2b2b8c4f4c90c5372f91a3e0bf076f02454fbe Mon Sep 17 00:00:00 2001 From: zenn Date: Thu, 7 May 2026 18:59:12 +0900 Subject: [PATCH] =?UTF-8?q?v0.0.47=20=EA=B3=B5=EA=B0=9C=20=EB=B3=B8?= =?UTF-8?q?=EB=AC=B8=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EA=B0=80=EC=9D=B4?= =?UTF-8?q?=EB=93=9C=20=EA=B8=B0=EB=B0=98=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ordered list, 멀티라인/대체 인용구 문법을 추가하고 Prose 컴포넌트(리스트/인용/이미지/카드/임베드) 기본 스타일을 Thred 톤으로 통일했다. Co-authored-by: Cursor --- .../content/ContentMarkdownRenderer.vue | 48 ++++++++++++++++--- components/content/ProseAudio.vue | 2 +- components/content/ProseBlockquote.vue | 20 +++++++- components/content/ProseButton.vue | 5 +- components/content/ProseCallout.vue | 6 ++- components/content/ProseEmbed.vue | 4 +- components/content/ProseFile.vue | 2 +- components/content/ProseHeaderCard.vue | 5 +- components/content/ProseHeading.vue | 14 +++--- components/content/ProseImage.vue | 8 ++-- components/content/ProseList.vue | 2 +- components/content/ProseProduct.vue | 2 +- components/content/ProseToggle.vue | 6 +-- components/content/ProseVideo.vue | 2 +- docs/spec.md | 25 +++++++++- docs/update.md | 7 +++ package.json | 2 +- 17 files changed, 125 insertions(+), 35 deletions(-) diff --git a/components/content/ContentMarkdownRenderer.vue b/components/content/ContentMarkdownRenderer.vue index 6ea6caf..7ac9ab7 100644 --- a/components/content/ContentMarkdownRenderer.vue +++ b/components/content/ContentMarkdownRenderer.vue @@ -26,6 +26,8 @@ const createBlock = (type = 'paragraph', text = '', level = null, id = '', optio url: options.url || '', alt: options.alt || '', title: options.title || '', + variant: options.variant || '', + ordered: options.ordered || false, width: options.width || 'regular', images: options.images || [] }) @@ -89,6 +91,20 @@ const parseMarkdownBlocks = (markdown) => { continue } + if (trimmedLine === '>>>') { + const contentLines = [] + index += 1 + + while (index < lines.length && lines[index].trim() !== '<<<') { + contentLines.push(lines[index]) + index += 1 + } + + blocks.push(createBlock('quote', contentLines.join('\n').trim(), null, `block-${blocks.length}`, { variant: 'alt' })) + index += 1 + continue + } + if (trimmedLine === ':::gallery') { const { contentLines, nextIndex } = collectFencedLines(lines, index + 1) const images = [] @@ -155,7 +171,7 @@ const parseMarkdownBlocks = (markdown) => { continue } - const headingMatch = trimmedLine.match(/^(#{1,3})\s+(.+)$/) + const headingMatch = trimmedLine.match(/^(#{1,6})\s+(.+)$/) if (headingMatch) { blocks.push(createBlock('heading', headingMatch[2], headingMatch[1].length, `block-${blocks.length}`)) @@ -164,8 +180,14 @@ const parseMarkdownBlocks = (markdown) => { } if (trimmedLine.startsWith('> ')) { - blocks.push(createBlock('quote', trimmedLine.replace(/^>\s?/, ''), null, `block-${blocks.length}`)) - index += 1 + const quoteLines = [] + + while (index < lines.length && lines[index].trim().startsWith('>')) { + quoteLines.push(lines[index].trim().replace(/^>\s?/, '')) + index += 1 + } + + blocks.push(createBlock('quote', quoteLines.join('\n').trim(), null, `block-${blocks.length}`)) continue } @@ -181,6 +203,18 @@ const parseMarkdownBlocks = (markdown) => { continue } + if (/^\d+\.\s+/.test(trimmedLine)) { + const items = [] + + while (index < lines.length && /^\d+\.\s+/.test(lines[index].trim())) { + items.push(lines[index].trim().replace(/^\d+\.\s+/, '')) + index += 1 + } + + blocks.push(createBlock('list', items, null, `block-${blocks.length}`, { ordered: true })) + continue + } + blocks.push(createBlock('paragraph', trimmedLine, null, `block-${blocks.length}`)) index += 1 } @@ -236,10 +270,10 @@ const showNextImage = () => { {{ block.text }} - + {{ block.text }} - +
  • {{ item }}
  • @@ -258,7 +292,7 @@ const showNextImage = () => {