Skip to content

Commit

Permalink
feat: support code block as component props (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
ManUtopiK authored May 16, 2024
1 parent 864feea commit cea1c94
Show file tree
Hide file tree
Showing 7 changed files with 744 additions and 19 deletions.
11 changes: 8 additions & 3 deletions playground/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<template>
<div>
<label for="">
<input v-model="mdcOptions.experimental.autoUnwrap" type="checkbox"> auto unwrap
<label for="autoUnwrap">
<input id="autoUnwrap" v-model="mdcOptions.experimental.autoUnwrap" type="checkbox"> auto unwrap
</label>
<label for="componentCodeBlockYamlProps">
<input id="componentCodeBlockYamlProps" v-model="mdcOptions.experimental.componentCodeBlockYamlProps" type="checkbox">
Component props code block style
</label>
<div class="flex">
<textarea v-model="markdown" class="flex-1" />
Expand All @@ -12,7 +16,7 @@
</template>

<script setup lang="ts">
const mdcOptions = ref({ experimental: { autoUnwrap: true } })
const mdcOptions = ref({ experimental: { autoUnwrap: true, componentCodeBlockYamlProps: false } })
const markdown = ref(`# Hello World
{{ $doc.name || 'Nuxt' }}
Expand Down Expand Up @@ -73,6 +77,7 @@ const md = useMarkdownGenerator(ast, mdcOptions)
display: flex;
width: 100%;
}
.flex-1 {
flex: 1;
height: calc(100vh - 40px);
Expand Down
26 changes: 21 additions & 5 deletions src/frontmatter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import yaml from 'js-yaml'
import * as flat from 'flat'

const FRONTMATTER_DELIMITER = '---'
const FRONTMATTER_DELIMITER_DEFAULT = '---'
const FRONTMATTER_DELIMITER_CODEBLOCK_STYLE = '```yaml [props]'

export function stringifyFrontMatter (data: any, content = '') {
if (!Object.keys(data).length) {
Expand All @@ -11,17 +12,32 @@ export function stringifyFrontMatter (data: any, content = '') {
data = flat.unflatten(data || {}, {})

return [
FRONTMATTER_DELIMITER,
FRONTMATTER_DELIMITER_DEFAULT,
yaml.dump(data, { lineWidth: -1 }).trim(),
FRONTMATTER_DELIMITER,
FRONTMATTER_DELIMITER_DEFAULT,
content
].join('\n')
}

export function stringifyCodeBlockProps (data: any, content = '') {
if (!Object.keys(data).length) {
return ''
}

data = flat.unflatten(data || {}, {})

return [
FRONTMATTER_DELIMITER_CODEBLOCK_STYLE,
yaml.dump(data, { lineWidth: -1 }).trim(),
'```',
content
].join('\n')
}

export function parseFrontMatter (content: string) {
let data: any = {}
if (content.startsWith(FRONTMATTER_DELIMITER)) {
const idx = content.indexOf('\n' + FRONTMATTER_DELIMITER)
if (content.startsWith(FRONTMATTER_DELIMITER_DEFAULT)) {
const idx = content.indexOf('\n' + FRONTMATTER_DELIMITER_DEFAULT)
if (idx !== -1) {
const frontmatter = content.slice(4, idx)
if (frontmatter) {
Expand Down
29 changes: 24 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ declare module 'unist' {
}
}

interface ChildrenNode extends Node {
value?: unknown
lang?: string
meta?: string
}

interface ComponentNode extends Node {
name?: string
attributes?: Record<string, any>
fmAttributes?: Record<string, any>
rawData?: string
children?: ChildrenNode[]
}

export default <Plugin<Array<RemarkMDCOptions>>> function (opts: RemarkMDCOptions = {}) {
Expand Down Expand Up @@ -79,14 +86,26 @@ function bindNode (node: ComponentNode) {
}

function getNodeData (node: ComponentNode) {
if (!node.rawData) {
return {}
if (node.rawData) {
const yaml = node.rawData.replace(/\s-+$/, '')
const { data } = parseFrontMatter(toFrontMatter(yaml))
return data
}

const yaml = node.rawData.replace(/\s-+$/, '')
const { data } = parseFrontMatter(toFrontMatter(yaml))
if (
node.children?.length &&
node.children[0].type === 'code' &&
node.children[0].lang === 'yaml' &&
node.children[0].meta === '[props]'
) {
const yaml = node.children[0].value as string
const { data } = parseFrontMatter(toFrontMatter(yaml))
node.rawData = yaml + '\n---'
node.children!.splice(0, 1)
return data
}

return data
return {}
}

function bindData (data: Record<string, any>) {
Expand Down
13 changes: 7 additions & 6 deletions src/to-markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { stringifyEntitiesLight } from 'stringify-entities'
import type { Parents, RootContent } from 'mdast'
import { type State, type Info, type Unsafe, defaultHandlers } from 'mdast-util-to-markdown'
import { containerFlow, containerPhrasing, checkQuote, inlineContainerFlow } from './mdast-util-to-markdown'
import { stringifyFrontMatter } from './frontmatter'
import { stringifyFrontMatter, stringifyCodeBlockProps } from './frontmatter'
import type { RemarkMDCOptions } from './types'
import { NON_UNWRAPPABLE_TYPES } from './utils'
import { type Container } from './micromark-extension/types'
Expand All @@ -26,9 +26,9 @@ function compilePattern (pattern: Unsafe) {

pattern._compiled = new RegExp(
(before ? '(' + before + ')' : '') +
(/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? '\\' : '') +
pattern.character +
(pattern.after ? '(?:' + pattern.after + ')' : ''),
(/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? '\\' : '') +
pattern.character +
(pattern.after ? '(?:' + pattern.after + ')' : ''),
'g'
)
}
Expand Down Expand Up @@ -113,14 +113,15 @@ export default (opts: RemarkMDCOptions = {}) => {
try {
value2 = JSON.parse(value2)
} catch {
// ignore
// ignore
}
key = key.slice(1)
}
acc[key] = value2
return acc
}, {} as Record<string, any>)
value += '\n' + stringifyFrontMatter(attrs).trim()
const fm = opts?.experimental?.componentCodeBlockYamlProps ? stringifyCodeBlockProps(attrs) : stringifyFrontMatter(attrs)
value += '\n' + fm.trim()
}

// Move default slot's children to the beginning of the content
Expand Down
1 change: 1 addition & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export interface RemarkMDCOptions {
components?: ComponentHandler[]
experimental?: {
autoUnwrap?: boolean
componentCodeBlockYamlProps?: boolean
}
}
Loading

0 comments on commit cea1c94

Please sign in to comment.