Skip to content

Commit

Permalink
fix: bring back CodeBlockFile component
Browse files Browse the repository at this point in the history
  • Loading branch information
hunterliu1003 committed Jan 17, 2023
1 parent 87f6e01 commit 8633f26
Show file tree
Hide file tree
Showing 54 changed files with 4,117 additions and 30 deletions.
58 changes: 58 additions & 0 deletions docs/components/content/CodeBlockFile.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<script setup lang="ts">
import { transformContent } from '../../transformers'
import { useAsyncData } from '#imports'
const props = defineProps<{
path: string
language?: string
filename?: string
}>()
const modules = import.meta.glob(['./*.vue', '!./CodeBlockFile.vue'], { as: 'raw' })
// console.log(`modules → `, modules)
function prepareContent(content: string) {
return `\`\`\`${props.language || ''}${props.filename ? ` [${props.filename}]` : ''}\n${content}\n\`\`\``
}
const { data: doc } = await useAsyncData(`playground-${props.path}`, async () => {
try {
const module = modules[props.path]
if (!module)
console.error('Component Not Found.')
const content = prepareContent(await module() as any)
// console.log(`content → `, content)
const parsed = await transformContent('content:index.md', content)
return parsed
}
catch (e) {
return doc.value
}
})
</script>

<template>
<ContentRenderer :key="doc.updatedAt" class="docus-content" :value="doc">
<template #empty>
<div class="p-8">
<Alert type="warning">
<p class="font-semibold">
Content is empty!
</p>
<br><br>
<p>
Type any <span class="font-semibold">Markdown</span> or <span class="font-semibold">MDC code</span> in
editor to see it replaced by rendered nodes in this panel.
</p>
</Alert>
</div>
</template>
</ContentRenderer>
</template>

<style scoped>
.docus-content :deep(.filename) {
display: block;
}
</style>
2 changes: 1 addition & 1 deletion docs/content/2.get-started/1.guide/2.setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Use plain CSS to define a `<PlainCssConfirmModal>`{lang=ts} component with `<Vue
- Basic example
::code-group
::code-block{label="PlainCssConfirmModal.vue"}
:code-block-file{path="./PlainCssConfirmModal.vue" language="vue"}
<!-- :code-block-file{path="./PlainCssConfirmModal.vue" language="vue"} -->
::

::code-block{label="Preview.vue"}
Expand Down
4 changes: 2 additions & 2 deletions docs/content/4.use-cases/3.confirm-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Create a `<ConfirmModal>` component with `<VueFinalModal>` and TailwindCSS.

::code-group
::code-block{label="ConfirmModal.vue"}
<!-- :code-block-file{path="./ConfirmModal.vue" language="vue"} -->
:code-block-file{path="./ConfirmModal.vue" language="vue"}
::
::

Expand All @@ -22,6 +22,6 @@ Create a `<ConfirmModal>` component with `<VueFinalModal>` and TailwindCSS.
::

::code-block{label="Preview.vue"}
<!-- :code-block-file{path="./ConfirmModalPreview.vue" language="vue"} -->
:code-block-file{path="./ConfirmModalPreview.vue" language="vue"}
::
::
4 changes: 2 additions & 2 deletions docs/content/4.use-cases/4.login-form-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This example use [Vorms](https://vorms.mini-ghost.dev/) to handle the form valid

::code-group
::code-block{label="LoginFormModal.vue"}
<!-- :code-block-file{path="./LoginFormModal.vue" language="vue"} -->
:code-block-file{path="./LoginFormModal.vue" language="vue"}
::
::

Expand All @@ -34,6 +34,6 @@ This example use [Vorms](https://vorms.mini-ghost.dev/) to handle the form valid
::

::code-block{label="Preview.vue"}
<!-- :code-block-file{path="./LoginFormModalPreview.vue" language="vue"} -->
:code-block-file{path="./LoginFormModalPreview.vue" language="vue"}
::
::
4 changes: 2 additions & 2 deletions docs/content/4.use-cases/5.nested-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Use `<ConfirmModal>` to demo how to use nested modal.

::code-group
::code-block{label="ConfirmModal.vue"}
<!-- :code-block-file{path="./ConfirmModal.vue" language="vue"} -->
:code-block-file{path="./ConfirmModal.vue" language="vue"}
::
::

Expand All @@ -22,6 +22,6 @@ Use `<ConfirmModal>` to demo how to use nested modal.
::

::code-block{label="NestedModalPreview.vue"}
<!-- :code-block-file{path="./NestedModalPreview.vue" language="vue"} -->
:code-block-file{path="./NestedModalPreview.vue" language="vue"}
::
::
4 changes: 2 additions & 2 deletions docs/content/4.use-cases/6.fullscreen-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Create a `<Fullscreen>` component with `<ModalFullscreen>` and TailwindCSS.

::code-group
::code-block{label="Fullscreen.vue"}
<!-- :code-block-file{path="./Fullscreen.vue" language="vue"} -->
:code-block-file{path="./Fullscreen.vue" language="vue"}
::
::

Expand All @@ -23,6 +23,6 @@ Create a `<Fullscreen>` component with `<ModalFullscreen>` and TailwindCSS.
::

::code-block{label="FullscreenPreview.vue"}
<!-- :code-block-file{path="./FullscreenPreview.vue" language="vue"} -->
:code-block-file{path="./FullscreenPreview.vue" language="vue"}
::
::
4 changes: 2 additions & 2 deletions docs/content/4.use-cases/7.bottom-sheet-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Create a `<BottomSheet>` component with `<ModalBottom>` and TailwindCSS.

::code-group
::code-block{label="BottomSheet.vue"}
<!-- :code-block-file{path="./BottomSheet.vue" language="vue"} -->
:code-block-file{path="./BottomSheet.vue" language="vue"}
::
::

Expand All @@ -23,6 +23,6 @@ Create a `<BottomSheet>` component with `<ModalBottom>` and TailwindCSS.
::

::code-block{label="BottomSheetPreview.vue"}
<!-- :code-block-file{path="./BottomSheetPreview.vue" language="vue"} -->
:code-block-file{path="./BottomSheetPreview.vue" language="vue"}
::
::
4 changes: 2 additions & 2 deletions docs/content/4.use-cases/8.drag-resize-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Here is a basic drag and resize modal example that using [vue3-drag-resize](http

::code-group
::code-block{label="DragResizeModal.vue"}
<!-- :code-block-file{path="./DragResizeModal.vue" language="vue"} -->
:code-block-file{path="./DragResizeModal.vue" language="vue"}
::
::

Expand All @@ -25,6 +25,6 @@ Here is a basic drag and resize modal example that using [vue3-drag-resize](http
::

::code-block{label="DragResizeModalPreview.vue"}
<!-- :code-block-file{path="./DragResizeModalPreview.vue" language="vue"} -->
:code-block-file{path="./DragResizeModalPreview.vue" language="vue"}
::
::
105 changes: 105 additions & 0 deletions docs/markdown-parser/compiler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import type { Node as UnistNode } from 'unist'
import type { MarkdownNode, MarkdownOptions, MarkdownRoot } from '../types'

type Node = UnistNode & {
tagName?: string
value?: string
children?: Node[]
properties: Record<string, any>
}

/**
* JSON compiler
*/
export default function (this: any, _options: MarkdownOptions) {
/**
* Parses nodes for JSON structure. Attempts to drop
* unwanted properties.
*/
function parseAsJSON(node: Node | Node[]) {
if (Array.isArray(node))
return node.map(parseAsJSON).filter(Boolean)

// Remove double dashes and trailing dash from heading ids
if (node.tagName?.startsWith('h') && node.properties.id) {
node.properties.id = node.properties.id
.replace(/-+/g, '-')
.replace(/-$/, '')
.replace(/^-/, '')
}

/**
* Element node creates an isolated children array to
* allow nested elements
*/
if (node.type === 'element') {
if (node.tagName === 'li') {
// unwrap unwanted paragraphs around `<li>` children
let hasPreviousParagraph = false
node.children = node.children.flatMap((child) => {
if (child.tagName === 'p') {
if (hasPreviousParagraph) {
// Insert line break before new paragraph
child.children.unshift({
type: 'element',
tagName: 'br',
properties: {},
})
}

hasPreviousParagraph = true
return child.children
}
return child
}) as Node[]
}

/**
* Rename component slots tags name
*/
if (node.tagName === 'component-slot')
node.tagName = 'template'

return <MarkdownNode> {
type: 'element',
tag: node.tagName as string,
props: node.properties,
children: parseAsJSON(node.children || []),
}
}

/**
* Text node
*/
if (node.type === 'text') {
// Remove new line nodes
if (node.value === '\n')
return null

return <MarkdownNode> {
type: 'text',
value: node.value as string,
}
}

// Remove comment nodes from AST tree
if (node.type === 'comment')
return null

node.children = parseAsJSON(node.children || [])

return node as MarkdownNode
}

this.Compiler = function (root: Node): MarkdownRoot {
/**
* We do not use `map` operation, since each node can be expanded to multiple top level
* nodes. Instead, we need a array to fill in as many elements inside a single
* iteration
*/
return {
type: 'root',
children: parseAsJSON(root.children || []),
}
}
}
105 changes: 105 additions & 0 deletions docs/markdown-parser/content.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import type { Processor } from 'unified'
import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remark2rehype from 'remark-rehype'
import remarkMDC from 'remark-mdc'
import type { MarkdownOptions, MarkdownPlugin, MarkdownRoot } from '../types'
import handlers from './handler'
import compiler from './compiler'
import { flattenNodeText } from './utils/ast'
import { nodeTextContent } from './utils/node'

const usePlugins = (plugins: Record<string, false | MarkdownPlugin>, stream: Processor) => {
for (const plugin of Object.values(plugins)) {
if (plugin) {
const { instance, ...options } = plugin
stream.use(instance, options)
}
}
}

/**
* Generate text excerpt summary
* @param {string} excerptContent - JSON AST generated from excerpt markdown.
* @returns {string} concatinated excerpt
*/
export function generateDescription(excerptContent: MarkdownRoot) {
return flattenNodeText(excerptContent)
}

/**
* Generate json body
* @param {string} content - file content
* @param {object} data - document data
* @returns {object} JSON AST body
*/
export function generateBody(content: string, options: MarkdownOptions & { data: any }): Promise<MarkdownRoot> {
const rehypeOptions: any = {
handlers,
allowDangerousHtml: true,
}

return new Promise((resolve, reject) => {
const stream = unified().use(remarkParse)

if (options.mdc)
stream.use(remarkMDC)

usePlugins(options.remarkPlugins, stream)
stream.use(remark2rehype, rehypeOptions)
usePlugins(options.rehypePlugins, stream)

stream.use(compiler, options as any)
stream.process(
{
value: content,
data: options.data,
},
(error, file) => {
if (error)
return reject(error)

Object.assign(options.data, file?.data || {})

resolve(file?.result as MarkdownRoot)
},
)
})
}

export function contentHeading(body: MarkdownRoot) {
let title = ''
let description = ''
const children = body.children
// top level `text` and `hr` can be ignored
.filter(node => node.type !== 'text' && node.tag !== 'hr')

if (children.length && children[0].tag === 'h1') {
/**
* Remove node
*/
const node = children.shift()!

/**
* Generate title
*/
title = nodeTextContent(node)
}

if (children.length && children[0].tag === 'p') {
/**
* Remove node
*/
const node = children.shift()!

/**
* Generate description
*/
description = nodeTextContent(node)
}

return {
title,
description,
}
}
7 changes: 7 additions & 0 deletions docs/markdown-parser/handler/blockquote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { H } from 'mdast-util-to-hast'
import { all } from 'mdast-util-to-hast'
import { wrap } from './utils'

export default function blockquote(h: H, node: any) {
return h(node, 'blockquote', wrap(all(h, node), true))
}
Loading

0 comments on commit 8633f26

Please sign in to comment.