Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support code block as component props #67

Merged
merged 5 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading