Skip to content

Commit

Permalink
feat(doc): 添加 PC 文档框架
Browse files Browse the repository at this point in the history
  • Loading branch information
koppthe committed Aug 1, 2018
1 parent 0d80914 commit 624e733
Show file tree
Hide file tree
Showing 58 changed files with 3,596 additions and 1 deletion.
28 changes: 28 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"presets": [
[
"@babel/preset-env",
{
"spec": true,
"modules": false,
"targets": {
"browsers": ["ie >= 9", "Chrome >= 21", "Firefox >= 1", "Edge >= 13", "last 3 versions"]
},
"loose": false,
"forceAllTransforms" : true,
"useBuiltIns": "entry"

}
]
],
"plugins": [
"syntax-dynamic-import",
"@babel/plugin-proposal-class-properties",
[
"@babel/plugin-transform-react-jsx",
{
"pragma": "Nerv.createElement"
}
]
]
}
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ coverage/
.nyc_output/
git_stats/
yarn-offline/
docs/
2 changes: 2 additions & 0 deletions .stylelintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
docs/
.jsx
179 changes: 179 additions & 0 deletions build/addImportLoader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
const mdContainer = require('markdown-it-container')
const frontMatter = require('front-matter')
const highlight = require('highlight.js')

let md = require('markdown-it')

const options = {
className: 'wrap'
}

md = md({
html: true, // Enable HTML tags in source
xhtmlOut: true,
typographer: false,
linkify: false
})
.enable(['smartquotes'])
.set({
highlight (content, languageHint) {
let highlightedContent

highlight.configure({
useBR: true,
tabReplace: ' '
})

if (languageHint && highlight.getLanguage(languageHint)) {
try {
highlightedContent = highlight.highlight(languageHint, content).value
} catch (err) {
console.log(err)
}
}

if (!highlightedContent) {
try {
highlightedContent = highlight.highlightAuto(content).value
} catch (err) {
console.log(err)
}
}

// 把代码中的{}转
highlightedContent = highlightedContent.replace(/[{}]/g, match => `{'${match}'}`)

// 加上 hljs
highlightedContent = highlightedContent
.replace('<code class="', '<code class="hljs ')
.replace('<code>', '<code class="hljs">')

return highlight.fixMarkup(highlightedContent)
}
})

const formatModule = (imports, js, jsx, state, method) => {
const moduleText = `
${imports}
${js}
class MarkdownItReactComponent extends Nerv.Component {
constructor(props){
super(props);
this.state = ${state || '{}'};
Object.assign(this,props.methods)
}
handleToggleCode(flag){
const state = {};
state['showCode' + flag] = !this.state['showCode' + flag];
this.setState(state);
}
handleCopyCode (code) {
copy(code)
}
${method || ''}
render(){
return (
<div className="${options.className}">
${jsx}
</div>
);
}
};
export default MarkdownItReactComponent;`

return moduleText
}

const formatOpening = (code, description, flag) => {
return ` <div className="at-component__container">
<div className="at-component__sample">
${code}
</div>
<div className="${options.className}-demo-meta" >
<div className="at-component__code" style={{display: this.state.showCode${flag}? '' : 'none' }}>
`
}

const formatClosing = flag => {
return `</div>
<div className="at-component__code-toggle" onClick={this.handleToggleCode.bind(this, ${flag})}>
{ this.state.showCode${flag} ? '隐藏代码':'显示代码'}
</div>
</div>
</div>`
}

module.exports = function (source) {
this.cacheable()
// init options
Object.assign(options, this.options.markdownItReact ? this.options.markdownItReact() : {})

const {
body,
attributes: { imports: importMap }
} = frontMatter(source)

const imports = `import * as Nerv from 'nervjs'; import copy from 'copy-to-clipboard';${importMap}`

const moduleJS = []
let state = ''
// 放在这里应该没有问题, 反正是顺序执行的
let flag = ''

md.use(mdContainer, 'demo', {
validate: params => params.trim().match(/^demo\s*(.*)$/),
render: (tokens, idx) => {
// container 从开头到结尾把之间的token跑一遍,其中idx定位到具体的位置

// 获取描述
const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/)

// 有此标记代表 ::: 开始
if (tokens[idx].nesting === 1) {
flag = idx

let jsx = ''
// let state = null
// let method = ''
let i = 1

// 从 ::: 下一个token开始
let token = tokens[idx + i]

// 如果没有到结尾
while (token.markup !== ':::') {
// 只认```,其他忽略
if (token.markup === '```') {
if (token.info === 'js') {
// 插入到import后,component前
moduleJS.push(token.content)
} else if (token.info === 'jsx' || token.info === 'html') {
// 插入render内
jsx = token.content
} else if (token.info === 'state') {
// console.log(typeof )
state = token.content.replace(/\\[a-z]/g, ' ').replace(/'/g, `"`)
}
}
i++
token = tokens[idx + i]
}
// 描述也执行md
return formatOpening(jsx, md.render(m[1]), flag)
}
return formatClosing(flag)
}
})

// md 处理过后的字符串含有 class 和 style ,需要再次处理给到react
const content = md
.render(body)
.replace(/<hr>/g, '<hr />')
.replace(/<br>/g, '<br />')
.replace(/class=/g, 'className=')
return formatModule(imports, moduleJS.join('\n'), content, state)
}
3 changes: 3 additions & 0 deletions build/conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
output: 'siteoutput'
}
77 changes: 77 additions & 0 deletions build/dev-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
// const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpackMerge = require('webpack-merge')
const ora = require('ora')

const { getProjectRoot, prepareUrls, formatTime } = require('./util')
const conf = require('./conf')
const webpackBaseConf = require('./webpack.base.config')
const webpackDevConf = require('./webpack.dev.config')
const formatWebpackMessage = require('./format_webpack_message')
const open = require('./open')

const serveSpinner = ora('Starting build...').start()

const projectRoot = getProjectRoot()
const host = '0.0.0.0'
const port = 8002
const protocol = 'http'
const urls = prepareUrls(protocol, host, port)
const webpackConf = webpackMerge(webpackBaseConf, webpackDevConf)
for (const key in webpackConf.entry) {
const entryItem = webpackConf.entry[key]
if (Array.isArray(entryItem)) {
entryItem.unshift(require.resolve('webpack/hot/dev-server'))
entryItem.unshift(`${require.resolve('webpack-dev-server/client')}?/`)
} else {
webpackConf.entry[key] = [
`${require.resolve('webpack-dev-server/client')}?/`,
require.resolve('webpack/hot/dev-server'),
entryItem
]
}
}
const compiler = webpack(webpackConf)
const webpackDevServerConf = require('./devServer.conf')({
publicPath: '/',
contentBase: path.join(projectRoot, conf.output),
protocol,
host,
publicUrl: urls.lanUrlForConfig
})

const server = new WebpackDevServer(compiler, webpackDevServerConf)
server.listen(port, host, err => {
if (err) {
return console.log(err)
}
})
let isFirstCompile = true
compiler.plugin('invalid', filepath => {
console.log(chalk.grey(`[${formatTime()}]Modified: ${filepath}`))
serveSpinner.text = 'Compiling...🤡~'
serveSpinner.render()
})
compiler.plugin('done', stats => {
const { errors, warnings } = formatWebpackMessage(stats.toJson({}, true))
const isSuccess = !errors.length && !warnings.length
if (isSuccess) {
serveSpinner.succeed(chalk.green('Compile successfully!\n'))
}
if (errors.length) {
errors.splice(1)
serveSpinner.fail(chalk.red('Compile failed!\n'))
console.log(errors.join('\n\n'))
console.log()
}
if (isFirstCompile) {
console.log(chalk.cyan(`> Listening at ${urls.lanUrlForTerminal}`))
console.log(chalk.cyan(`> Listening at ${urls.localUrlForBrowser}`))
console.log()
open(urls.localUrlForBrowser)
isFirstCompile = false
}
})
23 changes: 23 additions & 0 deletions build/devServer.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module.exports = function ({ publicPath, contentBase, protocol, host, publicUrl }) {
return {
disableHostCheck: process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
compress: true,
contentBase,
watchContentBase: true,
hot: true,
inline: true,
quiet: true,
publicPath,
// stats: "errors-only",
watchOptions: {
ignored: /node_modules/
},
https: protocol === 'https',
host,
// overlay: true,
historyApiFallback: {
disableDotRule: true
},
public: publicUrl
}
}
63 changes: 63 additions & 0 deletions build/format_webpack_message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const chalk = require('chalk')

const syntaxErrorLabel = 'Syntax error:'

function isLikelyASyntaxError (message) {
return message.indexOf(syntaxErrorLabel) >= 0
}

function formatMessage (message) {
let lines = message.split('\n')
if (lines.length > 2 && lines[1] === '') {
lines.splice(1, 1)
}
if (lines[0].lastIndexOf('!') >= 0) {
lines[0] = lines[0].substr(lines[0].lastIndexOf('!') + 1)
}
lines = lines.filter(line => line.indexOf(' @ ') !== 0)
if (!lines[0] || !lines[1]) {
return lines.join('\n')
}
if (lines[1].indexOf('Module not found: ') === 0) {
lines = [
lines[0],
lines[1]
.replace("Cannot resolve 'file' or 'directory' ", '')
.replace('Cannot resolve module ', '')
.replace('Error: ', '')
.replace('[CaseSensitivePathsPlugin] ', '')
]
} else if (lines[1].indexOf('Module build failed: ') === 0) {
lines[1] = lines[1].replace(
'Module build failed: SyntaxError:',
syntaxErrorLabel
)
}

const exportError = /\s*(.+?)\s*(")?export '(.+?)' was not found in '(.+?)'/
if (lines[1].match(exportError)) {
lines[1] = lines[1].replace(
exportError,
"$1 '$4' does not contain an export named '$3'."
)
}
lines[0] = chalk.inverse(lines[0])
message = lines.join('\n')

message = message.replace(/^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm, '')
return message.trim()
}

module.exports = function formatWebpackMessage (message) {
const errors = message.errors.map(item => formatMessage(item))
const warnings = message.warnings.map(item => formatMessage(item))

const result = {
errors,
warnings
}
if (result.errors.some(isLikelyASyntaxError)) {
result.errors = result.errors.filter(isLikelyASyntaxError)
}
return result
}
Loading

0 comments on commit 624e733

Please sign in to comment.