From 0c9d660252091559de0779cacafa2cb8040d342a Mon Sep 17 00:00:00 2001 From: Ahad Birang Date: Wed, 29 Jun 2022 12:09:45 +0200 Subject: [PATCH] fix(markdown): attributes of span inside headings --- .../micromark-extension/tokenize-span.ts | 33 ++++++++++++++++++- test/features/parser-markdown.ts | 21 ++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/runtime/markdown-parser/remark-mdc/micromark-extension/tokenize-span.ts b/src/runtime/markdown-parser/remark-mdc/micromark-extension/tokenize-span.ts index b5097e07f..8ddf5f340 100644 --- a/src/runtime/markdown-parser/remark-mdc/micromark-extension/tokenize-span.ts +++ b/src/runtime/markdown-parser/remark-mdc/micromark-extension/tokenize-span.ts @@ -2,9 +2,11 @@ import { markdownSpace } from 'micromark-util-character' import type { Effects, State, Code, TokenizeContext } from 'micromark-util-types' import { Codes } from './constants' import createLabel from './factory-label' +import createAttributes from './factory-attributes' const label: any = { tokenize: tokenizeLabel, partial: true } const gfmCheck: any = { tokenize: checkGfmTaskCheckbox, partial: true } +const attributes: any = { tokenize: tokenizeAttributes, partial: true } function tokenize (this: TokenizeContext, effects: Effects, ok: State, nok: State) { const self = this @@ -33,10 +35,19 @@ function tokenize (this: TokenizeContext, effects: Effects, ok: State, nok: Stat } function exit (code: Code): void | State { - // prevent conflict with link syntax + // Prevent conflict with link syntax if (code === Codes.openingParentheses || code === Codes.openingSquareBracket) { return nok(code) } + // Attemp parsing attributes + if (code === Codes.openingCurlyBracket) { + return effects.attempt(attributes, exitOK, exitOK)(code) + } + + return exitOK(code) + } + + function exitOK (code: Code): void | State { effects.exit('textSpan') return ok(code) } @@ -80,3 +91,23 @@ function checkGfmTaskCheckbox (effects: Effects, ok: State, nok: State) { return nok(code) } } + +function tokenizeAttributes (effects: Effects, ok: State, nok: State) { + // Always a `{` + return createAttributes( + effects, + ok, + nok, + 'componentTextAttributes', + 'componentTextAttributesMarker', + 'componentTextAttribute', + 'componentTextAttributeId', + 'componentTextAttributeClass', + 'componentTextAttributeName', + 'componentTextAttributeInitializerMarker', + 'componentTextAttributeValueLiteral', + 'componentTextAttributeValue', + 'componentTextAttributeValueMarker', + 'componentTextAttributeValueData' + ) +} diff --git a/test/features/parser-markdown.ts b/test/features/parser-markdown.ts index 5cf300193..4857af068 100644 --- a/test/features/parser-markdown.ts +++ b/test/features/parser-markdown.ts @@ -119,5 +119,26 @@ export const testMarkdownParser = () => { expect(parsed.body.children.length).toEqual(1) expect(parsed.body.children[0].tag).toEqual('h1') }) + + test('span attributes', async () => { + const parsed = await $fetch('/api/parse', { + method: 'POST', + body: { + id: 'content:index.md', + content: [ + '# Hello [World]{.text-green}', + 'The answer to life the universe and everything: [42]{.font-bold .text-green}' + ].join('\n') + } + }) + + expect(parsed.body).toHaveProperty('children') + expect(parsed.body.children.length).toEqual(2) + expect(parsed.body.children[0].tag).toEqual('h1') + expect(parsed.body.children[0].children[1].props.class).toEqual('text-green') + + expect(parsed.body.children[1].tag).toEqual('p') + expect(parsed.body.children[1].children[1].props.class).toEqual('font-bold text-green') + }) }) }