refactor: structure

pull/1/head
Evan You 5 years ago
parent 47bddf6ac6
commit fac49e8dbb

@ -1 +1 @@
export * from './server' export * from './server/server'

@ -1,15 +1,15 @@
import MarkdownIt from 'markdown-it' import MarkdownIt from 'markdown-it'
import { parseHeaders } from '../utils/parseHeaders' import { parseHeaders } from '../utils/parseHeaders'
import { highlight } from './highlight' import { highlight } from './plugins/highlight'
import { slugify } from './slugify' import { slugify } from './plugins/slugify'
import { highlightLinePlugin } from './highlightLines' import { highlightLinePlugin } from './plugins/highlightLines'
import { lineNumberPlugin } from './lineNumbers' import { lineNumberPlugin } from './plugins/lineNumbers'
import { componentPlugin } from './component' import { componentPlugin } from './plugins/component'
import { containerPlugin } from './containers' import { containerPlugin } from './plugins/containers'
import { snippetPlugin } from './snippet' import { snippetPlugin } from './plugins/snippet'
import { hoistPlugin } from './hoist' import { hoistPlugin } from './plugins/hoist'
import { preWrapperPlugin } from './preWrapper' import { preWrapperPlugin } from './plugins/preWrapper'
import { linkPlugin } from './link' import { linkPlugin } from './plugins/link'
const emoji = require('markdown-it-emoji') const emoji = require('markdown-it-emoji')
const anchor = require('markdown-it-anchor') const anchor = require('markdown-it-anchor')
@ -28,8 +28,13 @@ export interface MarkdownOpitons extends MarkdownIt.Options {
externalLinks?: Record<string, string> externalLinks?: Record<string, string>
} }
export interface MarkdownParsedData {
hoistedTags?: string[]
links?: string[]
}
export interface MarkdownRenderer { export interface MarkdownRenderer {
__data?: any __data: MarkdownParsedData
render: (src: string, env?: any) => { html: string; data: any } render: (src: string, env?: any) => { html: string; data: any }
} }
@ -91,13 +96,7 @@ export const createMarkdownRenderer = (
md.use(lineNumberPlugin) md.use(lineNumberPlugin)
} }
dataReturnable(md) // wrap render so that we can return both the html and extracted data.
return md as any
}
export const dataReturnable = (md: MarkdownIt) => {
// override render to allow custom plugins return data
const render = md.render const render = md.render
const wrappedRender: MarkdownRenderer['render'] = (src) => { const wrappedRender: MarkdownRenderer['render'] = (src) => {
(md as any).__data = {} (md as any).__data = {}
@ -107,6 +106,7 @@ export const dataReturnable = (md: MarkdownIt) => {
data: (md as any).__data data: (md as any).__data
} }
} }
;(md as any).render = wrappedRender ;(md as any).render = wrappedRender
return md as any
} }

@ -1,14 +1,17 @@
import path from 'path' import path from 'path'
import { createMarkdownRenderer, MarkdownOpitons } from './markdown/index' import { createMarkdownRenderer, MarkdownOpitons } from './markdown'
import LRUCache from 'lru-cache' import LRUCache from 'lru-cache'
const matter = require('gray-matter')
const debug = require('debug')('vitepress:md') const debug = require('debug')('vitepress:md')
const cache = new LRUCache<string, string>({ max: 1024 }) const cache = new LRUCache<string, string>({ max: 1024 })
const matter = require('gray-matter') export function createMarkdownToVueRenderFn(
root: string,
export function createMarkdownFn(root: string, options: MarkdownOpitons = {}) { options: MarkdownOpitons = {}
) {
const md = createMarkdownRenderer(options) const md = createMarkdownRenderer(options)
return (src: string, file: string) => { return (src: string, file: string) => {
file = path.relative(root, file) file = path.relative(root, file)
const cached = cache.get(src) const cached = cache.get(src)
@ -21,9 +24,10 @@ export function createMarkdownFn(root: string, options: MarkdownOpitons = {}) {
const { content, data } = matter(src) const { content, data } = matter(src)
const { html } = md.render(content) const { html } = md.render(content)
// TODO make use of data // TODO validate links?
const vueSrc = `<template>${html}</template>` const vueSrc =
`<template>${html}</template>` + (data.hoistedTags || []).join('\n')
debug(`[render] ${file} in ${Date.now() - start}ms.`, data) debug(`[render] ${file} in ${Date.now() - start}ms.`, data)
cache.set(src, vueSrc) cache.set(src, vueSrc)
return vueSrc return vueSrc

@ -1,6 +1,9 @@
import MarkdownIt from 'markdown-it' import MarkdownIt from 'markdown-it'
import { MarkdownParsedData } from '../markdown'
export const hoistPlugin = (md: MarkdownIt & { __data: any }) => { // hoist <script> and <style> tags out of the returned html
// so that they can be placed outside as SFC blocks.
export const hoistPlugin = (md: MarkdownIt & { __data: MarkdownParsedData }) => {
const RE = /^<(script|style)(?=(\s|>|$))/i const RE = /^<(script|style)(?=(\s|>|$))/i
md.renderer.rules.html_block = (tokens, idx) => { md.renderer.rules.html_block = (tokens, idx) => {

@ -3,11 +3,12 @@
// 2. normalize internal links to end with `.html` // 2. normalize internal links to end with `.html`
import MarkdownIt from 'markdown-it' import MarkdownIt from 'markdown-it'
import { MarkdownParsedData } from '../markdown'
const indexRE = /(^|.*\/)(index|readme).md(#?.*)$/i const indexRE = /(^|.*\/)(index|readme).md(#?.*)$/i
export const linkPlugin = ( export const linkPlugin = (
md: MarkdownIt, md: MarkdownIt & { __data: MarkdownParsedData },
externalAttrs: Record<string, string> externalAttrs: Record<string, string>
) => { ) => {
md.renderer.rules.link_open = (tokens, idx, options, env, self) => { md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
@ -30,7 +31,7 @@ export const linkPlugin = (
} }
function normalizeHref(hrefAttr: [string, string]) { function normalizeHref(hrefAttr: [string, string]) {
const data = (md as any).__data const data = md.__data
let url = hrefAttr[1] let url = hrefAttr[1]
// convert link to filename and export it for existence check // convert link to filename and export it for existence check

@ -2,9 +2,9 @@ import path from 'path'
import { Resolver } from "vite" import { Resolver } from "vite"
// built ts files are placed into /dist // built ts files are placed into /dist
export const APP_PATH = path.join(__dirname, '../lib/app') export const APP_PATH = path.join(__dirname, '../../lib/app')
// TODO detect user configured theme // TODO detect user configured theme
export const THEME_PATH = path.join(__dirname, '../lib/theme-default') export const THEME_PATH = path.join(__dirname, '../../lib/theme-default')
export const VitePressResolver: Resolver = { export const VitePressResolver: Resolver = {
publicToFile(publicPath) { publicToFile(publicPath) {

@ -1,13 +1,13 @@
import path from 'path' import path from 'path'
import { createServer as createViteServer, cachedRead, Plugin } from 'vite' import { createServer as createViteServer, cachedRead, Plugin } from 'vite'
import { createMarkdownFn } from './markdownToVue' import { createMarkdownToVueRenderFn } from '../markdown/markdownToVue'
import { VitePressResolver, THEME_PATH, APP_PATH } from './resolver' import { VitePressResolver, THEME_PATH, APP_PATH } from './resolver'
const debug = require('debug')('vitepress:serve') const debug = require('debug')('vitepress:serve')
const debugHmr = require('debug')('vitepress:hmr') const debugHmr = require('debug')('vitepress:hmr')
const VitePressPlugin: Plugin = ({ app, root, watcher, resolver }) => { const VitePressPlugin: Plugin = ({ app, root, watcher, resolver }) => {
const markdownToVue = createMarkdownFn(root) const markdownToVue = createMarkdownToVueRenderFn(root)
// watch theme files if it's outside of project root // watch theme files if it's outside of project root
if (path.relative(root, THEME_PATH).startsWith('..')) { if (path.relative(root, THEME_PATH).startsWith('..')) {
Loading…
Cancel
Save