feat: publicize doc implemetation
This commit is contained in:
226
one/build/customBlock.js
Normal file
226
one/build/customBlock.js
Normal file
@@ -0,0 +1,226 @@
|
||||
'use strict'
|
||||
|
||||
var trim = require('trim-trailing-lines')
|
||||
|
||||
module.exports = customBlock
|
||||
|
||||
var C_NEWLINE = '\n'
|
||||
var C_TAB = '\t'
|
||||
var C_SPACE = ' '
|
||||
var C_COLON = ':'
|
||||
|
||||
var MIN_FENCE_COUNT = 3
|
||||
var CODE_INDENT_COUNT = 4
|
||||
|
||||
function customBlock (eat, value, silent) {
|
||||
var self = this
|
||||
var length = value.length + 1
|
||||
var index = 0
|
||||
var subvalue = ''
|
||||
var fenceCount
|
||||
var marker
|
||||
var character
|
||||
var flag
|
||||
var queue
|
||||
var content
|
||||
var exdentedContent
|
||||
var closing
|
||||
var exdentedClosing
|
||||
var indent
|
||||
var now
|
||||
|
||||
/* Eat initial spacing. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break
|
||||
}
|
||||
|
||||
subvalue += character
|
||||
index++
|
||||
}
|
||||
|
||||
indent = index
|
||||
|
||||
/* Eat the fence. */
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_COLON) {
|
||||
return
|
||||
}
|
||||
|
||||
index++
|
||||
marker = character
|
||||
fenceCount = 1
|
||||
subvalue += character
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== marker) {
|
||||
break
|
||||
}
|
||||
|
||||
subvalue += character
|
||||
fenceCount++
|
||||
index++
|
||||
}
|
||||
|
||||
if (fenceCount < MIN_FENCE_COUNT) {
|
||||
return
|
||||
}
|
||||
|
||||
/* Eat spacing before flag. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break
|
||||
}
|
||||
|
||||
subvalue += character
|
||||
index++
|
||||
}
|
||||
|
||||
/* Eat flag. */
|
||||
flag = ''
|
||||
queue = ''
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character === C_NEWLINE || character === C_COLON) {
|
||||
break
|
||||
}
|
||||
|
||||
if (character === C_SPACE || character === C_TAB) {
|
||||
queue += character
|
||||
} else {
|
||||
flag += queue + character
|
||||
queue = ''
|
||||
}
|
||||
|
||||
index++
|
||||
}
|
||||
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character && character !== C_NEWLINE) {
|
||||
return
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return true
|
||||
}
|
||||
|
||||
now = eat.now()
|
||||
now.column += subvalue.length
|
||||
now.offset += subvalue.length
|
||||
|
||||
subvalue += flag
|
||||
flag = self.decode.raw(self.unescape(flag), now)
|
||||
|
||||
if (queue) {
|
||||
subvalue += queue
|
||||
}
|
||||
|
||||
queue = ''
|
||||
closing = ''
|
||||
exdentedClosing = ''
|
||||
content = ''
|
||||
exdentedContent = ''
|
||||
|
||||
/* Eat content. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
content += closing
|
||||
exdentedContent += exdentedClosing
|
||||
closing = ''
|
||||
exdentedClosing = ''
|
||||
|
||||
if (character !== C_NEWLINE) {
|
||||
content += character
|
||||
exdentedClosing += character
|
||||
index++
|
||||
continue
|
||||
}
|
||||
|
||||
/* Add the newline to `subvalue` if its the first
|
||||
* character. Otherwise, add it to the `closing`
|
||||
* queue. */
|
||||
if (content) {
|
||||
closing += character
|
||||
exdentedClosing += character
|
||||
} else {
|
||||
subvalue += character
|
||||
}
|
||||
|
||||
queue = ''
|
||||
index++
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE) {
|
||||
break
|
||||
}
|
||||
|
||||
queue += character
|
||||
index++
|
||||
}
|
||||
|
||||
closing += queue
|
||||
exdentedClosing += queue.slice(indent)
|
||||
|
||||
if (queue.length >= CODE_INDENT_COUNT) {
|
||||
continue
|
||||
}
|
||||
|
||||
queue = ''
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== marker) {
|
||||
break
|
||||
}
|
||||
|
||||
queue += character
|
||||
index++
|
||||
}
|
||||
|
||||
closing += queue
|
||||
exdentedClosing += queue
|
||||
|
||||
if (queue.length < fenceCount) {
|
||||
continue
|
||||
}
|
||||
|
||||
queue = ''
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break
|
||||
}
|
||||
|
||||
closing += character
|
||||
exdentedClosing += character
|
||||
index++
|
||||
}
|
||||
|
||||
if (!character || character === C_NEWLINE) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
subvalue += content + closing
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'customblock',
|
||||
className: (flag || '').trim().replace(/\s+/g, ' '),
|
||||
value: trim(exdentedContent)
|
||||
})
|
||||
}
|
48
one/build/deps.js
Normal file
48
one/build/deps.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import path from 'path'
|
||||
import { readFileSync, writeFileSync } from './util'
|
||||
import { merge } from 'lodash'
|
||||
|
||||
function load () {
|
||||
try {
|
||||
return JSON.parse(readFileSync(resolve('./deps.json')))
|
||||
} catch (e) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function save (deps) {
|
||||
writeFileSync(resolve('./deps.json'), JSON.stringify(deps, null, ' '))
|
||||
}
|
||||
|
||||
function resolve (file) {
|
||||
return path.resolve(__dirname, file)
|
||||
}
|
||||
|
||||
export function get (file) {
|
||||
let deps = load()
|
||||
return deps[file]
|
||||
}
|
||||
|
||||
export function add (data) {
|
||||
let deps = load()
|
||||
save(merge(deps, data))
|
||||
}
|
||||
|
||||
export function remove (data) {
|
||||
let deps = load()
|
||||
Object.keys(data).forEach(key => {
|
||||
if (deps[key]) {
|
||||
delete deps[key][data[key]]
|
||||
}
|
||||
})
|
||||
save(deps)
|
||||
}
|
||||
|
||||
export function removeFile (file) {
|
||||
let deps = load()
|
||||
delete deps[file]
|
||||
|
||||
Object.keys(deps).forEach(key => {
|
||||
delete deps[key][file]
|
||||
})
|
||||
}
|
226
one/build/details.js
Normal file
226
one/build/details.js
Normal file
@@ -0,0 +1,226 @@
|
||||
'use strict'
|
||||
|
||||
var trim = require('trim-trailing-lines')
|
||||
|
||||
module.exports = details
|
||||
|
||||
var C_NEWLINE = '\n'
|
||||
var C_TAB = '\t'
|
||||
var C_SPACE = ' '
|
||||
var C_PLUS = '+'
|
||||
|
||||
var MIN_FENCE_COUNT = 3
|
||||
var CODE_INDENT_COUNT = 4
|
||||
|
||||
function details (eat, value, silent) {
|
||||
var self = this
|
||||
var length = value.length + 1
|
||||
var index = 0
|
||||
var subvalue = ''
|
||||
var fenceCount
|
||||
var marker
|
||||
var character
|
||||
var flag
|
||||
var queue
|
||||
var content
|
||||
var exdentedContent
|
||||
var closing
|
||||
var exdentedClosing
|
||||
var indent
|
||||
var now
|
||||
|
||||
/* Eat initial spacing. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break
|
||||
}
|
||||
|
||||
subvalue += character
|
||||
index++
|
||||
}
|
||||
|
||||
indent = index
|
||||
|
||||
/* Eat the fence. */
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_PLUS) {
|
||||
return
|
||||
}
|
||||
|
||||
index++
|
||||
marker = character
|
||||
fenceCount = 1
|
||||
subvalue += character
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== marker) {
|
||||
break
|
||||
}
|
||||
|
||||
subvalue += character
|
||||
fenceCount++
|
||||
index++
|
||||
}
|
||||
|
||||
if (fenceCount < MIN_FENCE_COUNT) {
|
||||
return
|
||||
}
|
||||
|
||||
/* Eat spacing before flag. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break
|
||||
}
|
||||
|
||||
subvalue += character
|
||||
index++
|
||||
}
|
||||
|
||||
/* Eat flag. */
|
||||
flag = ''
|
||||
queue = ''
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character === C_NEWLINE || character === C_PLUS) {
|
||||
break
|
||||
}
|
||||
|
||||
if (character === C_SPACE || character === C_TAB) {
|
||||
queue += character
|
||||
} else {
|
||||
flag += queue + character
|
||||
queue = ''
|
||||
}
|
||||
|
||||
index++
|
||||
}
|
||||
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character && character !== C_NEWLINE) {
|
||||
return
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return true
|
||||
}
|
||||
|
||||
now = eat.now()
|
||||
now.column += subvalue.length
|
||||
now.offset += subvalue.length
|
||||
|
||||
subvalue += flag
|
||||
flag = self.decode.raw(self.unescape(flag), now)
|
||||
|
||||
if (queue) {
|
||||
subvalue += queue
|
||||
}
|
||||
|
||||
queue = ''
|
||||
closing = ''
|
||||
exdentedClosing = ''
|
||||
content = ''
|
||||
exdentedContent = ''
|
||||
|
||||
/* Eat content. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
content += closing
|
||||
exdentedContent += exdentedClosing
|
||||
closing = ''
|
||||
exdentedClosing = ''
|
||||
|
||||
if (character !== C_NEWLINE) {
|
||||
content += character
|
||||
exdentedClosing += character
|
||||
index++
|
||||
continue
|
||||
}
|
||||
|
||||
/* Add the newline to `subvalue` if its the first
|
||||
* character. Otherwise, add it to the `closing`
|
||||
* queue. */
|
||||
if (content) {
|
||||
closing += character
|
||||
exdentedClosing += character
|
||||
} else {
|
||||
subvalue += character
|
||||
}
|
||||
|
||||
queue = ''
|
||||
index++
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE) {
|
||||
break
|
||||
}
|
||||
|
||||
queue += character
|
||||
index++
|
||||
}
|
||||
|
||||
closing += queue
|
||||
exdentedClosing += queue.slice(indent)
|
||||
|
||||
if (queue.length >= CODE_INDENT_COUNT) {
|
||||
continue
|
||||
}
|
||||
|
||||
queue = ''
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== marker) {
|
||||
break
|
||||
}
|
||||
|
||||
queue += character
|
||||
index++
|
||||
}
|
||||
|
||||
closing += queue
|
||||
exdentedClosing += queue
|
||||
|
||||
if (queue.length < fenceCount) {
|
||||
continue
|
||||
}
|
||||
|
||||
queue = ''
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break
|
||||
}
|
||||
|
||||
closing += character
|
||||
exdentedClosing += character
|
||||
index++
|
||||
}
|
||||
|
||||
if (!character || character === C_NEWLINE) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
subvalue += content + closing
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'details',
|
||||
summary: flag || null,
|
||||
value: trim(exdentedContent)
|
||||
})
|
||||
}
|
3
one/build/generate.js
Normal file
3
one/build/generate.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import { generatePages } from './generator'
|
||||
|
||||
generatePages()
|
105
one/build/generator.js
Normal file
105
one/build/generator.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import { statSync } from 'fs'
|
||||
import { resolve, relative, extname, basename, sep } from 'path'
|
||||
import readdirpSync from 'recursive-readdir-sync'
|
||||
import rimraf from 'rimraf'
|
||||
import { copyFileSync, replaceExtSync } from './util'
|
||||
import { renderDocToPage } from './page'
|
||||
import { get, removeFile } from './deps'
|
||||
|
||||
const DOCS_DIR = resolve(__dirname, '../docs')
|
||||
const PAGES_DIR = resolve(__dirname, '../../pages')
|
||||
const DEMOS_DIR = resolve(__dirname, '../../components/demos')
|
||||
const MERMAID_DIR = resolve(__dirname, '../../static/images/mermaid')
|
||||
const ASSETS_DIR = resolve(__dirname, '../../assets')
|
||||
|
||||
export function generatePages (file, stats) {
|
||||
if (!file) {
|
||||
rimraf.sync(PAGES_DIR)
|
||||
rimraf.sync(DEMOS_DIR)
|
||||
rimraf.sync(MERMAID_DIR)
|
||||
rimraf.sync(resolve(__dirname, './deps.json'))
|
||||
console.log('Regenerating all files...')
|
||||
handleFile(DOCS_DIR)
|
||||
console.log('...done.')
|
||||
} else {
|
||||
handleFile(file, stats)
|
||||
}
|
||||
}
|
||||
|
||||
function handleFile (file, stats) {
|
||||
let segments = relative(DOCS_DIR, file).split(sep)
|
||||
if (segments.some(segment => {
|
||||
return segment.startsWith('_') || segment.startsWith('.')
|
||||
})) {
|
||||
return
|
||||
}
|
||||
|
||||
let remove = stats ? stats.remove : false
|
||||
let dir = stats ? stats.dir : statSync(file).isDirectory()
|
||||
if (dir) {
|
||||
if (remove) {
|
||||
rimraf.sync(file)
|
||||
return
|
||||
}
|
||||
|
||||
let children = readdirpSync(file)
|
||||
children.forEach(child => {
|
||||
handleFile(child, remove)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
let ext = extname(file).toLowerCase()
|
||||
|
||||
/* eslint-disable indent */
|
||||
/* There seems to be something wrong with FECS here */
|
||||
switch (ext) {
|
||||
case '.md': {
|
||||
if (remove) {
|
||||
let relDest = replaceExtSync(relative(DOCS_DIR, file), 'vue')
|
||||
rimraf.sync(resolve(PAGES_DIR, relDest))
|
||||
console.log(`[${relDest}] removed.`)
|
||||
} else {
|
||||
let dest = relative(DOCS_DIR, file)
|
||||
renderDocToPage(dest)
|
||||
console.log(`[${dest}] synced.`)
|
||||
}
|
||||
break
|
||||
}
|
||||
case '.json': {
|
||||
if (basename(file) === 'nav.json') {
|
||||
copyFileSync(file, resolve(ASSETS_DIR, 'data', 'nav.json'))
|
||||
console.log('[nav.json] synced.')
|
||||
}
|
||||
break
|
||||
}
|
||||
default: {
|
||||
let relDest = relative(DOCS_DIR, file)
|
||||
|
||||
let dest = relDest.split(sep).indexOf('demo') === -1
|
||||
? resolve(PAGES_DIR, relDest)
|
||||
: resolve(DEMOS_DIR, relDest)
|
||||
if (remove) {
|
||||
rimraf.sync(dest)
|
||||
console.log(`[${relDest}] removed.`)
|
||||
} else {
|
||||
copyFileSync(file, dest)
|
||||
console.log(`[${relDest}] synced.`)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
/* eslint-enable indent */
|
||||
|
||||
if (remove) {
|
||||
removeFile(file)
|
||||
return
|
||||
}
|
||||
|
||||
let deps = get(file)
|
||||
if (deps) {
|
||||
Object.keys(deps).forEach(dep => {
|
||||
handleFile(dep)
|
||||
})
|
||||
}
|
||||
}
|
13
one/build/i18n.js
Normal file
13
one/build/i18n.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export const DEFAULT_LOCALE = 'zh-Hans'
|
||||
export const LOCALES = [
|
||||
{
|
||||
code: DEFAULT_LOCALE,
|
||||
label: '简体ä¸ć–‡'
|
||||
},
|
||||
{
|
||||
code: 'en-US',
|
||||
label: 'English (US)'
|
||||
}
|
||||
]
|
||||
export const LOCALE_CODES = LOCALES.map(l => l.code)
|
||||
export const RE_LOCALE = new RegExp(`^\\/(${LOCALE_CODES.join('|')})\\/`)
|
99
one/build/language.js
Normal file
99
one/build/language.js
Normal file
@@ -0,0 +1,99 @@
|
||||
/* eslint-disable fecs-camelcase */
|
||||
/* eslint-disable babel/new-cap */
|
||||
export function vue (hljs) {
|
||||
const XML_IDENT_RE = '[A-Za-z0-9\\._:-]+'
|
||||
const TAG_INTERNALS = {
|
||||
endsWithParent: true,
|
||||
illegal: /</,
|
||||
relevance: 0,
|
||||
contains: [
|
||||
{
|
||||
className: 'attr',
|
||||
begin: XML_IDENT_RE,
|
||||
relevance: 0
|
||||
},
|
||||
{
|
||||
begin: /=\s*/,
|
||||
relevance: 0,
|
||||
contains: [
|
||||
{
|
||||
className: 'string',
|
||||
endsParent: true,
|
||||
variants: [
|
||||
{begin: /"/, end: /"/},
|
||||
{begin: /'/, end: /'/},
|
||||
{begin: /[^\s"'=<>`]+/}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
return {
|
||||
case_insensitive: true,
|
||||
contains: [
|
||||
hljs.COMMENT(
|
||||
'<!--',
|
||||
'-->',
|
||||
{
|
||||
relevance: 10
|
||||
}
|
||||
),
|
||||
{
|
||||
className: 'tag',
|
||||
/*
|
||||
The lookahead pattern (?=...) ensures that 'begin' only matches
|
||||
'<style' as a single word, followed by a whitespace or an
|
||||
ending braket. The '$' is needed for the lexeme to be recognized
|
||||
by hljs.subMode() that tests lexemes outside the stream.
|
||||
*/
|
||||
begin: '<style(?=\\s|>|$)',
|
||||
end: '>',
|
||||
keywords: {name: 'style'},
|
||||
contains: [TAG_INTERNALS],
|
||||
starts: {
|
||||
end: '</style>',
|
||||
returnEnd: true,
|
||||
subLanguage: ['css', 'less', 'scss', 'stylus']
|
||||
}
|
||||
},
|
||||
{
|
||||
className: 'tag',
|
||||
// See the comment in the <style tag about the lookahead pattern
|
||||
begin: '<script(?=\\s|>|$)',
|
||||
end: '>',
|
||||
keywords: {name: 'script'},
|
||||
contains: [TAG_INTERNALS],
|
||||
starts: {
|
||||
end: '</script>',
|
||||
returnEnd: true,
|
||||
subLanguage: ['javascript']
|
||||
}
|
||||
},
|
||||
{
|
||||
className: 'tag',
|
||||
// See the comment in the <style tag about the lookahead pattern
|
||||
begin: '<template(?=\\s|>|$)',
|
||||
end: '>',
|
||||
keywords: {name: 'template'},
|
||||
contains: [TAG_INTERNALS],
|
||||
starts: {
|
||||
end: '</template>',
|
||||
returnEnd: true,
|
||||
subLanguage: ['html']
|
||||
}
|
||||
},
|
||||
{
|
||||
className: 'tag',
|
||||
begin: '</?',
|
||||
end: '/?>',
|
||||
contains: [
|
||||
{
|
||||
className: 'name', begin: /[^/><\s]+/, relevance: 0
|
||||
},
|
||||
TAG_INTERNALS
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
94
one/build/page.js
Normal file
94
one/build/page.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import { resolve, relative, join } from 'path'
|
||||
import vfile from 'vfile'
|
||||
import remark from 'remark'
|
||||
import slug from 'remark-slug'
|
||||
import frontmatter from 'remark-frontmatter'
|
||||
import highlight from 'remark-highlight.js'
|
||||
import shortcodes from 'remark-shortcodes'
|
||||
import mermaid from 'one-remark-mermaid'
|
||||
import remarkToRehype from 'remark-rehype'
|
||||
import raw from 'rehype-raw'
|
||||
import html from 'rehype-stringify'
|
||||
import etpl from 'etpl'
|
||||
import { readFileSync, writeFileSync, replaceExtSync } from './util'
|
||||
import demo from './remark-demo'
|
||||
import ref from './remark-ref'
|
||||
import details from './remark-details'
|
||||
import custom from './remark-custom'
|
||||
import extractFrontmatter from './remark-extract-frontmatter'
|
||||
import rehypePreviewImg from './rehype-preview-img'
|
||||
import rehypeLink from './rehype-link'
|
||||
import rehypeDemo from './rehype-demo'
|
||||
import { add } from './deps'
|
||||
import lowlight from 'lowlight'
|
||||
import { vue } from './language'
|
||||
|
||||
const DOCS_DIR = resolve(__dirname, '../docs')
|
||||
const PAGES_DIR = resolve(__dirname, '../../pages')
|
||||
const STYLES_DIR = resolve(__dirname, '../../assets/styles')
|
||||
const MERMAID_DIR = resolve(__dirname, '../../static/images/mermaid')
|
||||
const PAGE_TPL = readFileSync(resolve(__dirname, '../templates/page.etpl'))
|
||||
|
||||
const renderPage = etpl.compile(PAGE_TPL)
|
||||
|
||||
lowlight.registerLanguage('vue', vue)
|
||||
|
||||
const md = remark()
|
||||
.use(custom)
|
||||
.use(details)
|
||||
.use(ref)
|
||||
.use(frontmatter)
|
||||
.use(shortcodes)
|
||||
.use(mermaid, {
|
||||
cssFile: join(`${STYLES_DIR}`, 'mermaid-cli.css'),
|
||||
theme: 'none'
|
||||
})
|
||||
.use(demo)
|
||||
.use(extractFrontmatter)
|
||||
.use(highlight)
|
||||
.use(slug)
|
||||
.use(remarkToRehype, { allowDangerousHTML: true })
|
||||
.use(raw)
|
||||
.use(rehypePreviewImg)
|
||||
.use(rehypeLink)
|
||||
.use(rehypeDemo)
|
||||
.use(html, { allowDangerousHTML: true })
|
||||
|
||||
export function render (contents, path, data = {}) {
|
||||
data.destinationDir = MERMAID_DIR
|
||||
return md.processSync(vfile({ contents, path, data }))
|
||||
}
|
||||
|
||||
function renderFile (file) {
|
||||
return render(readFileSync(file), file)
|
||||
}
|
||||
|
||||
export function renderDocToPage (file) {
|
||||
let src = resolve(DOCS_DIR, file)
|
||||
let dest = resolve(PAGES_DIR, replaceExtSync(file, 'vue'))
|
||||
let { contents, data } = renderFile(src, dest)
|
||||
let { demos = {}, components = {}, meta = {}, deps = {} } = data
|
||||
|
||||
Object.keys(deps || {}).forEach(dep => {
|
||||
add({ [dep]: { [src]: true } })
|
||||
})
|
||||
|
||||
let { layout, style } = meta
|
||||
let componentList = Object.keys(components)
|
||||
let demoList = Object.keys(demos)
|
||||
let result = renderPage({
|
||||
content: (contents || '').replace(/\n{3,}/g, '\n\n'),
|
||||
demos: demoList.map(name => {
|
||||
return {
|
||||
name,
|
||||
src: join('@/components/demos', relative(DOCS_DIR, demos[name].path))
|
||||
}
|
||||
}),
|
||||
components: componentList,
|
||||
boilerplate: demoList.length || componentList.length,
|
||||
layout,
|
||||
style: style || 'post'
|
||||
})
|
||||
|
||||
writeFileSync(dest, result)
|
||||
}
|
226
one/build/refBlock.js
Normal file
226
one/build/refBlock.js
Normal file
@@ -0,0 +1,226 @@
|
||||
'use strict'
|
||||
|
||||
var trim = require('trim-trailing-lines')
|
||||
|
||||
module.exports = refBlock
|
||||
|
||||
var C_NEWLINE = '\n'
|
||||
var C_TAB = '\t'
|
||||
var C_SPACE = ' '
|
||||
var C_CARET = '^'
|
||||
|
||||
var MIN_FENCE_COUNT = 3
|
||||
var CODE_INDENT_COUNT = 4
|
||||
|
||||
function refBlock (eat, value, silent) {
|
||||
var self = this
|
||||
var length = value.length + 1
|
||||
var index = 0
|
||||
var subvalue = ''
|
||||
var fenceCount
|
||||
var marker
|
||||
var character
|
||||
var flag
|
||||
var queue
|
||||
var content
|
||||
var exdentedContent
|
||||
var closing
|
||||
var exdentedClosing
|
||||
var indent
|
||||
var now
|
||||
|
||||
/* Eat initial spacing. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break
|
||||
}
|
||||
|
||||
subvalue += character
|
||||
index++
|
||||
}
|
||||
|
||||
indent = index
|
||||
|
||||
/* Eat the fence. */
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_CARET) {
|
||||
return
|
||||
}
|
||||
|
||||
index++
|
||||
marker = character
|
||||
fenceCount = 1
|
||||
subvalue += character
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== marker) {
|
||||
break
|
||||
}
|
||||
|
||||
subvalue += character
|
||||
fenceCount++
|
||||
index++
|
||||
}
|
||||
|
||||
if (fenceCount < MIN_FENCE_COUNT) {
|
||||
return
|
||||
}
|
||||
|
||||
/* Eat spacing before flag. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break
|
||||
}
|
||||
|
||||
subvalue += character
|
||||
index++
|
||||
}
|
||||
|
||||
/* Eat flag. */
|
||||
flag = ''
|
||||
queue = ''
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character === C_NEWLINE || character === C_CARET) {
|
||||
break
|
||||
}
|
||||
|
||||
if (character === C_SPACE || character === C_TAB) {
|
||||
queue += character
|
||||
} else {
|
||||
flag += queue + character
|
||||
queue = ''
|
||||
}
|
||||
|
||||
index++
|
||||
}
|
||||
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character && character !== C_NEWLINE) {
|
||||
return
|
||||
}
|
||||
|
||||
if (silent) {
|
||||
return true
|
||||
}
|
||||
|
||||
now = eat.now()
|
||||
now.column += subvalue.length
|
||||
now.offset += subvalue.length
|
||||
|
||||
subvalue += flag
|
||||
flag = self.decode.raw(self.unescape(flag), now)
|
||||
|
||||
if (queue) {
|
||||
subvalue += queue
|
||||
}
|
||||
|
||||
queue = ''
|
||||
closing = ''
|
||||
exdentedClosing = ''
|
||||
content = ''
|
||||
exdentedContent = ''
|
||||
|
||||
/* Eat content. */
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
content += closing
|
||||
exdentedContent += exdentedClosing
|
||||
closing = ''
|
||||
exdentedClosing = ''
|
||||
|
||||
if (character !== C_NEWLINE) {
|
||||
content += character
|
||||
exdentedClosing += character
|
||||
index++
|
||||
continue
|
||||
}
|
||||
|
||||
/* Add the newline to `subvalue` if its the first
|
||||
* character. Otherwise, add it to the `closing`
|
||||
* queue. */
|
||||
if (content) {
|
||||
closing += character
|
||||
exdentedClosing += character
|
||||
} else {
|
||||
subvalue += character
|
||||
}
|
||||
|
||||
queue = ''
|
||||
index++
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE) {
|
||||
break
|
||||
}
|
||||
|
||||
queue += character
|
||||
index++
|
||||
}
|
||||
|
||||
closing += queue
|
||||
exdentedClosing += queue.slice(indent)
|
||||
|
||||
if (queue.length >= CODE_INDENT_COUNT) {
|
||||
continue
|
||||
}
|
||||
|
||||
queue = ''
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== marker) {
|
||||
break
|
||||
}
|
||||
|
||||
queue += character
|
||||
index++
|
||||
}
|
||||
|
||||
closing += queue
|
||||
exdentedClosing += queue
|
||||
|
||||
if (queue.length < fenceCount) {
|
||||
continue
|
||||
}
|
||||
|
||||
queue = ''
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index)
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break
|
||||
}
|
||||
|
||||
closing += character
|
||||
exdentedClosing += character
|
||||
index++
|
||||
}
|
||||
|
||||
if (!character || character === C_NEWLINE) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
subvalue += content + closing
|
||||
|
||||
return eat(subvalue)({
|
||||
type: 'refblock',
|
||||
id: flag || null,
|
||||
value: trim(exdentedContent)
|
||||
})
|
||||
}
|
54
one/build/rehype-demo.js
Normal file
54
one/build/rehype-demo.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import visit from 'unist-util-visit'
|
||||
import h from 'hastscript'
|
||||
|
||||
const RE_DEMO = /^one-demo-[a-f0-9]+/i
|
||||
export default function attacher () {
|
||||
return (tree, { data }) => {
|
||||
visit(tree, 'element', (node, index, parent) => {
|
||||
let { tagName } = node
|
||||
let [name] = tagName.match(RE_DEMO) || []
|
||||
if (name) {
|
||||
let { code, desc, browser } = data.demos[name] || {}
|
||||
if (!code) {
|
||||
return
|
||||
}
|
||||
|
||||
let demo = h('one-demo',
|
||||
{
|
||||
browser
|
||||
},
|
||||
[
|
||||
node,
|
||||
h(
|
||||
'template',
|
||||
{
|
||||
slot: 'source'
|
||||
},
|
||||
h(
|
||||
'div',
|
||||
{
|
||||
'v-pre': true
|
||||
},
|
||||
{
|
||||
type: 'raw',
|
||||
value: code
|
||||
}
|
||||
)
|
||||
),
|
||||
h(
|
||||
'template',
|
||||
{
|
||||
slot: 'desc'
|
||||
},
|
||||
{
|
||||
type: 'raw',
|
||||
value: desc
|
||||
}
|
||||
)
|
||||
])
|
||||
|
||||
parent.children.splice(index, 1, demo)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
26
one/build/rehype-link.js
Normal file
26
one/build/rehype-link.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { resolve, relative } from 'path'
|
||||
import visit from 'unist-util-visit'
|
||||
import { RE_LOCALE } from './i18n'
|
||||
|
||||
const DOCS_DIR = resolve(__dirname, '../docs')
|
||||
|
||||
export default function attacher () {
|
||||
return (tree, { path }) => {
|
||||
let localPath = `/${relative(DOCS_DIR, path)}`
|
||||
let [, locale] = localPath.match(RE_LOCALE) || []
|
||||
if (!locale) {
|
||||
return
|
||||
}
|
||||
|
||||
visit(tree, 'element', node => {
|
||||
let { tagName, properties, properties: { href } } = node
|
||||
if (tagName !== 'a' || href.match(/^\w+:\/\//)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (locale && href.indexOf('/') === 0) {
|
||||
properties.href = `/${locale}${href}`
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
98
one/build/rehype-preview-img.js
Normal file
98
one/build/rehype-preview-img.js
Normal file
@@ -0,0 +1,98 @@
|
||||
import { resolve, join } from 'path'
|
||||
import visit from 'unist-util-visit'
|
||||
import h from 'hastscript'
|
||||
import { removeClass, addClass, hasClass } from './rehype-util-class'
|
||||
import { readFileSync } from './util'
|
||||
|
||||
const RE_SPACE = /[\w\r\n]*/
|
||||
const MERMAID_DIR = resolve(__dirname, '../../static/images/mermaid')
|
||||
|
||||
export default function attacher () {
|
||||
return tree => {
|
||||
visit(tree, 'element', (node, index, { children }) => {
|
||||
let { tagName, properties, properties: { src, alt, title, className } } = node
|
||||
if (tagName !== 'img' || src.match(/^\w+:\/\//)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (title && title.indexOf('mermaid') !== -1) {
|
||||
let fig = h(
|
||||
'figure.hero.mermaid',
|
||||
{
|
||||
'v-once': true
|
||||
},
|
||||
{
|
||||
type: 'raw',
|
||||
value: readFileSync(join(MERMAID_DIR, src))
|
||||
}
|
||||
)
|
||||
children.splice(index, 1, fig)
|
||||
return
|
||||
}
|
||||
|
||||
src = src.replace(/(\.\.)?\/assets\//g, '/images/content/')
|
||||
|
||||
if (hasClass(node, 'preview')) {
|
||||
removeClass(node, 'preview')
|
||||
let fig = h(`figure${hasClass(node, 'hero') ? '.hero' : ''}`, [
|
||||
h('div.preview', [
|
||||
h('img', {
|
||||
src,
|
||||
alt,
|
||||
title,
|
||||
className,
|
||||
srcset: `${src} 2x`
|
||||
})
|
||||
]),
|
||||
...(title || alt) ? [
|
||||
h('figcaption', [
|
||||
...title ? [
|
||||
h('p.caption', title)
|
||||
] : [],
|
||||
...alt ? [
|
||||
h('p.desc', alt)
|
||||
] : []
|
||||
])
|
||||
] : []
|
||||
])
|
||||
children.splice(index, 1, fig)
|
||||
|
||||
if (hasClass(node, 'bad')) {
|
||||
removeClass(node, 'bad')
|
||||
addClass(fig, 'bad')
|
||||
let prev
|
||||
let prevIndex = index - 1
|
||||
while (true) {
|
||||
prev = children[prevIndex]
|
||||
if (!prev) {
|
||||
break
|
||||
}
|
||||
// skip whitespace-only text nodes
|
||||
if (prev.type === 'text' && RE_SPACE.test(prev.value)) {
|
||||
prevIndex--
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
if (prev) {
|
||||
let prevPreview = (prev.children || [])[0]
|
||||
if (prevPreview && hasClass(prevPreview, 'preview')) {
|
||||
let prevImg = (prevPreview.children || [])[0]
|
||||
if (hasClass(prevImg, 'good')) {
|
||||
removeClass(prevImg, 'good')
|
||||
addClass(prev, 'good')
|
||||
children.splice(index - 1, 2, h('div.comparison', [prev, fig]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
properties.src = src
|
||||
properties.srcset = `${src} 2x`
|
||||
if (className && !className.length) {
|
||||
delete properties.className
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
36
one/build/rehype-util-class.js
Normal file
36
one/build/rehype-util-class.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { remove, get, set } from 'lodash'
|
||||
|
||||
const CLASSNAME_PATH = 'properties.className'
|
||||
|
||||
export function toggleClass (node, name, add) {
|
||||
let className = get(node, CLASSNAME_PATH)
|
||||
if (!className) {
|
||||
set(node, CLASSNAME_PATH, [])
|
||||
className = node.properties.className
|
||||
}
|
||||
|
||||
if (typeof add === 'boolean') {
|
||||
if (add && !className.includes(name)) {
|
||||
className.push(name)
|
||||
} else if (!add) {
|
||||
remove(className, c => c === name)
|
||||
}
|
||||
} else if (className.includes(name)) {
|
||||
remove(className, c => c === name)
|
||||
} else {
|
||||
className.push(name)
|
||||
}
|
||||
}
|
||||
|
||||
export function addClass (node, name) {
|
||||
toggleClass(node, name, true)
|
||||
}
|
||||
|
||||
export function removeClass (node, name) {
|
||||
toggleClass(node, name, false)
|
||||
}
|
||||
|
||||
export function hasClass (node, name) {
|
||||
let className = get(node, CLASSNAME_PATH, [])
|
||||
return className.includes(name)
|
||||
}
|
30
one/build/remark-custom.js
Normal file
30
one/build/remark-custom.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import tokenizer from './customBlock'
|
||||
import visit from 'unist-util-visit'
|
||||
import { render } from './page'
|
||||
|
||||
const NAME = 'customblock'
|
||||
|
||||
export default function attacher () {
|
||||
let proto = this.Parser.prototype
|
||||
|
||||
proto.blockTokenizers[NAME] = tokenizer
|
||||
proto.interruptParagraph.push([NAME])
|
||||
proto.interruptList.push([NAME])
|
||||
proto.interruptBlockquote.push([NAME])
|
||||
|
||||
let methods = proto.blockMethods
|
||||
methods.unshift(NAME)
|
||||
|
||||
return (tree, file) => {
|
||||
let { path } = file
|
||||
|
||||
visit(tree, NAME, ({ className, value }, index, parent) => {
|
||||
let { contents } = render(value, path, {})
|
||||
className = className ? `${className} custom-block` : 'custom-block'
|
||||
parent.children.splice(index, 1, {
|
||||
type: 'html',
|
||||
value: `<div class="${className}">${contents}</div>`
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
125
one/build/remark-demo.js
Normal file
125
one/build/remark-demo.js
Normal file
@@ -0,0 +1,125 @@
|
||||
import { resolve, relative, dirname } from 'path'
|
||||
import { existsSync } from 'fs'
|
||||
import visit from 'unist-util-visit'
|
||||
import { readFileSync, hash } from './util'
|
||||
import { render } from './page'
|
||||
import { parseComponent } from 'vue-template-compiler'
|
||||
import { escape } from 'lodash'
|
||||
import { RE_LOCALE } from './i18n'
|
||||
|
||||
const DOCS_DIR = resolve(__dirname, '../docs')
|
||||
|
||||
export default function attacher () {
|
||||
return (tree, file) => {
|
||||
let { path, data: fileData } = file
|
||||
visit(tree, 'shortcode', node => {
|
||||
let {
|
||||
identifier,
|
||||
data: nodeData,
|
||||
attributes: { src, browser } = {}
|
||||
} = node
|
||||
if (identifier !== 'demo' || !src) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!nodeData) {
|
||||
node.data = nodeData = {}
|
||||
}
|
||||
if (!fileData) {
|
||||
file.data = fileData = {}
|
||||
}
|
||||
if (!fileData.demos) {
|
||||
fileData.demos = {}
|
||||
}
|
||||
if (!fileData.deps) {
|
||||
fileData.deps = {}
|
||||
}
|
||||
|
||||
let demoPath =
|
||||
src.indexOf('/') === 0
|
||||
? resolve(DOCS_DIR, src.slice(1))
|
||||
: resolve(dirname(path), src)
|
||||
|
||||
if (!existsSync(demoPath)) {
|
||||
console.warn(`Demo not found at '${demoPath}'`)
|
||||
return
|
||||
}
|
||||
|
||||
fileData.deps[demoPath] = true
|
||||
|
||||
let name = getComponentName(demoPath)
|
||||
nodeData.hName = name
|
||||
|
||||
let localPath = `/${relative(DOCS_DIR, path)}`
|
||||
let [, locale] = localPath.match(RE_LOCALE) || []
|
||||
|
||||
let { content, doc } = extractDoc(demoPath, { locale })
|
||||
fileData.demos[name] = {
|
||||
path: demoPath,
|
||||
browser,
|
||||
code: render('```vue\n' + content + '\n```', demoPath).contents,
|
||||
desc: render(doc, demoPath).contents
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getComponentName (path) {
|
||||
return `one-demo-${hash(path)}`
|
||||
}
|
||||
|
||||
function extractDoc (file, { locale }) {
|
||||
let content = readFileSync(file)
|
||||
let vueComponent = parseComponent(content)
|
||||
let { customBlocks } = vueComponent
|
||||
let i = customBlocks.findIndex(({ type, attrs }) => {
|
||||
return ((locale && locale === attrs.locale) || !locale) && type === 'docs'
|
||||
})
|
||||
|
||||
let doc = null
|
||||
if (i !== -1) {
|
||||
doc = customBlocks[i].content
|
||||
}
|
||||
|
||||
return {
|
||||
content: stringifyVueComponent(vueComponent),
|
||||
doc
|
||||
}
|
||||
}
|
||||
|
||||
function stringifyVueComponent (component) {
|
||||
let content = []
|
||||
let { template, script, styles } = component
|
||||
if (template) {
|
||||
content.push(
|
||||
`<template${stringifyAttrs(template.attrs)}>${
|
||||
template.content
|
||||
}</template>`
|
||||
)
|
||||
}
|
||||
if (script) {
|
||||
content.push(
|
||||
`<script${stringifyAttrs(script.attrs)}>${script.content}</script>`
|
||||
)
|
||||
}
|
||||
styles.filter(({ attrs }) => !attrs.docs).forEach(style => {
|
||||
content.push(
|
||||
`<style${stringifyAttrs(style.attrs)}>${style.content}</style>`
|
||||
)
|
||||
})
|
||||
return content.join('\n\n')
|
||||
}
|
||||
|
||||
function stringifyAttrs (attrs) {
|
||||
let result = Object.keys(attrs)
|
||||
.map(key => {
|
||||
let val = attrs[key]
|
||||
if (typeof val !== 'boolean') {
|
||||
return `${escape(key)}="${escape(val)}"`
|
||||
}
|
||||
return val ? `${escape(key)}` : ''
|
||||
})
|
||||
.join(' ')
|
||||
|
||||
return result ? ` ${result}` : ''
|
||||
}
|
39
one/build/remark-details.js
Normal file
39
one/build/remark-details.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import tokenizer from './details'
|
||||
import visit from 'unist-util-visit'
|
||||
import { escape } from 'lodash'
|
||||
import { render } from './page'
|
||||
|
||||
const NAME = 'details'
|
||||
|
||||
export default function attacher () {
|
||||
let proto = this.Parser.prototype
|
||||
|
||||
proto.blockTokenizers[NAME] = tokenizer
|
||||
proto.interruptParagraph.push([NAME])
|
||||
proto.interruptList.push([NAME])
|
||||
proto.interruptBlockquote.push([NAME])
|
||||
|
||||
let methods = proto.blockMethods
|
||||
methods.unshift(NAME)
|
||||
|
||||
return (tree, file) => {
|
||||
let { path, data } = file
|
||||
|
||||
if (!data) {
|
||||
file.data = data = {}
|
||||
}
|
||||
if (!data.components) {
|
||||
data.components = {}
|
||||
}
|
||||
|
||||
visit(tree, NAME, ({ summary, value }, index, parent) => {
|
||||
data.components['OneDetails'] = true
|
||||
|
||||
let { contents } = render(value, path, data)
|
||||
parent.children.splice(index, 1, {
|
||||
type: 'html',
|
||||
value: `<one-details summary="${escape(summary)}">${contents}</one-details>`
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
16
one/build/remark-extract-frontmatter.js
Normal file
16
one/build/remark-extract-frontmatter.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import visit from 'unist-util-visit'
|
||||
import remove from 'unist-util-remove'
|
||||
import yaml from 'js-yaml'
|
||||
|
||||
export default function attacher () {
|
||||
return (tree, file) => {
|
||||
let { data } = file
|
||||
|
||||
visit(tree, 'yaml', node => {
|
||||
data.meta = yaml.safeLoad(node.value)
|
||||
return visit.EXIT
|
||||
})
|
||||
|
||||
remove(tree, ['yaml', 'toml'])
|
||||
}
|
||||
}
|
49
one/build/remark-ref.js
Normal file
49
one/build/remark-ref.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import tokenizer from './refBlock'
|
||||
import visit from 'unist-util-visit'
|
||||
import remove from 'unist-util-remove'
|
||||
import { render } from './page'
|
||||
|
||||
const NAME = 'refblock'
|
||||
const RE_REF = /^\^([-_a-z0-9]+)/i
|
||||
|
||||
export default function attacher () {
|
||||
let proto = this.Parser.prototype
|
||||
|
||||
proto.blockTokenizers[NAME] = tokenizer
|
||||
proto.interruptParagraph.push([NAME])
|
||||
proto.interruptList.push([NAME])
|
||||
proto.interruptBlockquote.push([NAME])
|
||||
|
||||
let methods = proto.blockMethods
|
||||
methods.unshift(NAME)
|
||||
|
||||
return (tree, file) => {
|
||||
let { path, data } = file
|
||||
|
||||
if (!data) {
|
||||
file.data = data = {}
|
||||
}
|
||||
if (!data.refs) {
|
||||
data.refs = {}
|
||||
}
|
||||
|
||||
visit(tree, NAME, ({ id, value }) => {
|
||||
let { contents } = render(value, path, data)
|
||||
data.refs[id] = contents
|
||||
})
|
||||
remove(tree, NAME)
|
||||
|
||||
visit(tree, 'linkReference', (node, index, parent) => {
|
||||
let { identifier } = node
|
||||
let [match, id] = identifier.match(RE_REF)
|
||||
if (!match || !id || !data.refs[id]) {
|
||||
return
|
||||
}
|
||||
|
||||
parent.children.splice(index, 1, {
|
||||
type: 'html',
|
||||
value: data.refs[id]
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
29
one/build/util.js
Normal file
29
one/build/util.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { readFileSync as fsReadFileSync, writeFileSync as fsWriteFileSync } from 'fs'
|
||||
import { dirname } from 'path'
|
||||
import mkdirp from 'mkdirp'
|
||||
import crypto from 'crypto'
|
||||
|
||||
export function readFileSync (file) {
|
||||
return fsReadFileSync(file, 'utf8')
|
||||
}
|
||||
|
||||
export function writeFileSync (file, content) {
|
||||
mkdirp.sync(dirname(file))
|
||||
fsWriteFileSync(file, content, 'utf8')
|
||||
}
|
||||
|
||||
export function copyFileSync (src, dest) {
|
||||
mkdirp.sync(dirname(dest))
|
||||
writeFileSync(dest, readFileSync(src))
|
||||
}
|
||||
|
||||
const RE_EXT = /\.([^.]+)$/
|
||||
export function replaceExtSync (file, ext) {
|
||||
return file.replace(RE_EXT, `.${ext}`)
|
||||
}
|
||||
|
||||
export function hash (path) {
|
||||
let hash = crypto.createHash('sha1')
|
||||
hash.update(path)
|
||||
return hash.digest('hex').substring(0, 7)
|
||||
}
|
33
one/build/watch.js
Normal file
33
one/build/watch.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { resolve } from 'path'
|
||||
import { debounce } from 'lodash'
|
||||
import chokidar from 'chokidar'
|
||||
import { generatePages } from './generator'
|
||||
|
||||
let watcher = chokidar.watch(resolve(__dirname, '../docs'), {
|
||||
ignoreInitial: true
|
||||
})
|
||||
|
||||
watcher
|
||||
.on('all', debounce(generate, 1000))
|
||||
|
||||
function generate (type, path) {
|
||||
switch (type) {
|
||||
case 'add':
|
||||
generatePages(path, { dir: false, remove: false })
|
||||
break
|
||||
case 'addDir':
|
||||
generatePages(path, { dir: true, remove: false })
|
||||
break
|
||||
case 'change':
|
||||
generatePages(path)
|
||||
break
|
||||
case 'unlink':
|
||||
generatePages(path, { dir: false, remove: true })
|
||||
break
|
||||
case 'unlinkDir':
|
||||
generatePages(path, { dir: true, remove: true })
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user