Skip to content

Commit

Permalink
feat: refac to use mdx
Browse files Browse the repository at this point in the history
  • Loading branch information
pedronauck committed May 5, 2018
1 parent ac6ca67 commit 04b59e5
Show file tree
Hide file tree
Showing 20 changed files with 397 additions and 700 deletions.
14 changes: 14 additions & 0 deletions examples/basic/src/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { doc } from 'docz'

export const meta = doc('Overview')
.route('/')
.order(1)

## Introduction Hello
A design system can help establish a common vocabulary between everyone in an organization. That’s why I’ve spent a great deal of time coming up with structure and naming for Vue Design System that would make sense. To start opening it up, let’s go through each layer in detail and what the terms mean:

- *Principles* are the foundation of the whole system. They form the basis of a good product and help the team with decision making. They are there to guide you and your team when working with the myriad parts of the system and help you do better and more informed decisions.
- *Design* Tokens are the atoms of the system as Salesforce describes them. In Vue Design System they are used instead of hard coded values to ensure a better consistency across any platform.
- *Elements* utilize decisions made on the token level. A simple example of an element would be a button, a link, or an input. Anything that cannot be broken down further. I use the name ‘element’ since everything in Vue and React world is nowadays ‘a component.’ Using that term for anything else would be confusing.
- *Patterns* are UI Patterns that fall on the more complex side of the spectrum. So for example things like a date picker, a data table, or a visualization. Patterns utilize both elements and tokens. If you wonder whether something should be called an element or a pattern, ask yourself this question: “Can this be broken down into smaller pieces?” If the answer is yes, it should most likely be a pattern in Vue Design System.
- *Templates* exist to document the layout and structure of a section. I am not calling these pages since semantically that would be incorrect. While they can be pages, that’s not their only functionality. Templates consist of the three things mentioned above: tokens, elements, and patterns.
22 changes: 11 additions & 11 deletions packages/docz-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@
"dependencies": {
"@babel/core": "^7.0.0-beta.44",
"@babel/runtime": "^7.0.0-beta.44",
"@mdx-js/loader": "^0.8.0",
"@mdx-js/mdx": "^0.8.0",
"@mdx-js/loader": "^0.8.1",
"@mdx-js/mdx": "^0.8.1",
"@mdx-js/mdxast": "^0.7.2",
"@sindresorhus/slugify": "^0.3.0",
"art-template": "^4.12.2",
"babel-file-loader": "^1.0.3",
"babel-generator": "^6.26.1",
"babel-loader": "^8.0.0-beta.1",
"babel-polyfill": "^7.0.0-beta.3",
"babel-preset-react-app": "^4.0.0-next.b2fd8db8",
"babel-traverse": "^6.26.0",
"babel-types": "^6.26.0",
"chokidar": "^2.0.3",
"deepmerge": "^2.1.0",
"del": "3.0.0",
Expand All @@ -46,33 +44,35 @@
"prettier": "^1.12.0",
"react-dev-utils": "^5.0.1",
"react-hot-loader": "^4.0.1",
"remark-parse": "^5.0.0",
"resolve": "^1.7.1",
"socket.io": "^2.1.0",
"thread-loader": "^1.1.5",
"ulid": "^2.3.0",
"unified": "^6.2.0",
"url-loader": "^1.0.1",
"webpack": "^4.5.0",
"webpack": "^4.7.0",
"webpack-chain": "^4.6.0",
"webpack-dev-middleware": "^3.1.2",
"webpack-dev-server-speedy": "^3.1.1",
"webpackbar": "^2.6.1",
"yargs": "^11.0.0"
},
"devDependencies": {
"@types/babel-traverse": "^6.25.3",
"@types/bcryptjs": "^2.4.1",
"@types/chokidar": "^1.7.5",
"@types/deepmerge": "^2.1.0",
"@types/del": "^3.0.1",
"@types/express": "^4.11.1",
"@types/html-webpack-plugin": "^2.30.3",
"@types/mkdirp": "^0.5.2",
"@types/node": "10.0.0",
"@types/prettier": "^1.12.0",
"@types/node": "10.0.4",
"@types/prettier": "^1.12.1",
"@types/resolve": "^0.0.7",
"@types/webpack": "^4.1.3",
"@types/webpack-chain": "^4.0.2",
"@types/yargs": "^11.0.0",
"rollup-plugin-cpy": "^1.0.0",
"tslint": "^5.10.0",
"typescript": "^2.8.3"
}
}
36 changes: 6 additions & 30 deletions packages/docz-core/src/Entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const touch = (file: string, raw: string) => {
const compiled = (file: string) =>
compile(fs.readFileSync(path.join(paths.templates, file), 'utf-8'))

const docs = compiled('docs.tpl.js')
const app = compiled('app.tpl.js')
const js = compiled('index.tpl.js')
const html = compiled('index.tpl.html')
Expand All @@ -54,35 +55,6 @@ export class Entries {
.map(file => new Entry(file, config.src))
}

public find(file: string): Entry | undefined {
return this.entries.find(entry => entry.filepath === file)
}

public findIndex(file: string): number {
return this.entries.findIndex(entry => entry.filepath === file)
}

public add(entry: Entry): void {
this.entries.push(entry)
}

public remove(file: string): void {
const idx = this.findIndex(file)

if (idx > -1) {
this.entries.splice(idx, 1)
}
}

public update(file: string): void {
const idx = this.findIndex(file)
const entry = new Entry(file, this.config.src)

if (idx > -1) {
this.entries.splice(idx, 1, entry)
}
}

public write(): void {
const { plugins, title, description, theme } = this.config

Expand All @@ -96,8 +68,11 @@ export class Entries {
description,
})

const rawAppJs = app({
const rawDocsJs = docs({
imports,
})

const rawAppJs = app({
theme,
wrappers,
})
Expand All @@ -109,6 +84,7 @@ export class Entries {

touch(paths.indexHtml, rawIndexHtml)
touch(paths.appJs, rawAppJs)
touch(paths.docsJs, rawDocsJs)
touch(paths.indexJs, rawIndexJs)

touch(
Expand Down
79 changes: 35 additions & 44 deletions packages/docz-core/src/Entry.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,48 @@
import * as fs from 'fs'
import * as path from 'path'
import * as t from 'babel-types'
import { ulid } from 'ulid'
import { NodePath } from 'babel-traverse'
import generate from 'babel-generator'
import get from 'lodash.get'
import unified from 'unified'
import remark from 'remark-parse'
import toMDXAST from '@mdx-js/mdxast'
import slugify from '@sindresorhus/slugify'

import * as paths from './config/paths'
import { format } from './utils/format'
import { traverseAndAssign, traverseAndAssignEach } from './utils/traverse'

const hasImport = (p: NodePath<any>): boolean =>
t.isImportDeclaration(p) && get(p, 'node.source.value') === `docz`
const parseMdx = (file: string) => {
const raw = fs.readFileSync(file, 'utf-8')
const tree = unified()
.use(remark)
.parse(raw)

const hasDocFn = (p: NodePath<any>): boolean =>
p.node.specifiers &&
p.node.specifiers.some(
(node: NodePath<any>) =>
t.isImportSpecifier(node) && node.imported.name === 'doc'
)
return toMDXAST({})(tree)
}

const checkImport = traverseAndAssign<NodePath<t.Node>, boolean>({
when: p => hasImport(p) && hasDocFn(p),
assign: () => true,
})
const checkImport = (file: string) => {
const ast = parseMdx(file)

const getNameFromDoc = traverseAndAssign<any, string>({
when: p => p.isCallExpression() && get(p, 'node.callee.name') === 'doc',
assign: p => get(p, 'node.arguments[0].value'),
})
return (
ast.children &&
ast.children.some(
(child: any) => child.type === 'import' && /docz/.test(child.value)
)
)
}

const parseSections = traverseAndAssignEach<NodePath<t.Node>, string[]>({
when: 'MemberExpression',
assign: p => {
const name = get(p, 'node.property.name')
const args = get(p, 'parentPath.node.arguments')
const getNameFromDoc = (file: string) => {
const ast = parseMdx(file)
const found =
ast.children &&
ast.children.find(
(child: any) =>
child &&
child.type === 'export' &&
/export const meta/.test(child.value) &&
/doc\(.+\)/.test(child.value)
)

if (name === 'section' && args && args.length > 0) {
for (const arg of args) {
if (arg.type !== 'StringLiteral') {
const { code } = generate(arg.body)
return format(code).slice(1, Infinity) as any
}
}
}
},
})
const name = found.value.match(/(doc\()(.+)(\))/)
return slugify(name[2])
}

export class Entry {
readonly [key: string]: any
Expand All @@ -57,22 +55,15 @@ export class Entry {
return getNameFromDoc(file)
}

public static parseSections(file: string): string[] | null {
const sections = parseSections(file)
return sections && sections.reverse()
}

public id: string
public filepath: string
public name: string | null
public sections: string[] | null

constructor(file: string, src: string) {
const filepath = path.relative(paths.root, file)

this.id = ulid()
this.filepath = filepath
this.name = Entry.parseName(file)
this.sections = Entry.parseSections(file)
}
}
9 changes: 1 addition & 8 deletions packages/docz-core/src/commands/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,6 @@ export interface Config extends Argv {
hastPlugins: any[]
}

const EXTS = '{j,t}{s,sx}'
const DEFAULT_FILES_GLOB = [
`docs/**.${EXTS}`,
`**/__docs__/*.${EXTS}`,
`**/*.doc.${EXTS}`,
]

export const args = (yargs: any) => {
yargs.positional('source', {
alias: 'src',
Expand All @@ -39,7 +32,7 @@ export const args = (yargs: any) => {
})
yargs.positional('files', {
type: 'string',
default: DEFAULT_FILES_GLOB,
default: '**/*.mdx',
})
yargs.positional('title', {
type: 'string',
Expand Down
39 changes: 2 additions & 37 deletions packages/docz-core/src/commands/dev.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,15 @@
import { load } from 'load-cfg'
import { FSWatcher } from 'chokidar'
import * as chokidar from 'chokidar'
import del from 'del'

import * as paths from '../config/paths'

import { Entry } from '../Entry'
import { Entries } from '../Entries'
import { Bundler } from '../Bundler'

import { webpack } from '../bundlers'
import { Config } from './args'

process.env.BABEL_ENV = process.env.BABEL_ENV || 'development'
process.env.NODE_ENV = process.env.NODE_ENV || 'development'

const writeEntriesAndWatch = (watcher: FSWatcher) => (config: Config) => {
const entries = new Entries(config)
const update = () => entries.write()

const onUnlink = (file: string) => {
entries.remove(file)
update()
}

const onChange = (file: string) => {
const name = Entry.parseName(file)
const entry = entries.find(file)

if (name) {
!entry && entries.add(new Entry(file, config.src))
entry && entries.update(file)
update()
}
}

watcher.on('unlink', onUnlink)
watcher.on('change', onChange)

update()
}

const start = async (bundler: Bundler): Promise<void> => {
const config = bundler.getConfig()
const server = await bundler.createServer(config)
Expand All @@ -58,13 +27,9 @@ const INITIAL_CONFIG = {
export const dev = async (args: Config) => {
const config = load('docz', { ...args, ...INITIAL_CONFIG })
const bundler = webpack(config)
const watcher = chokidar.watch(config.files, {
ignored: /(^|[\/\\])\../,
})

const writeEntries = writeEntriesAndWatch(watcher)
const entries = new Entries(config)

await del(paths.docz)
writeEntries(config)
entries.write()
start(bundler)
}
3 changes: 2 additions & 1 deletion packages/docz-core/src/config/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface Paths {
dist: string
templates: string
appJs: string
docsJs: string
indexJs: string
dataJson: string
indexHtml: string
Expand All @@ -52,7 +53,7 @@ export const servedPath = getServedPath(resolveApp('package.json'))
export const dist = path.resolve(docz, 'dist/')

export const appJs = path.resolve(docz, 'app.jsx')
export const docsJs = path.resolve(docz, 'docs.jsx')
export const indexJs = path.resolve(docz, 'index.jsx')
export const dataJson = path.resolve(docz, 'data.json')

export const indexHtml = path.resolve(docz, 'index.html')
7 changes: 5 additions & 2 deletions packages/docz-core/src/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
declare module '@mdx-js/mdxast'
declare module '@mdx-js/mdx'
declare module '@sindresorhus/slugify'
declare module 'unified'
declare module 'remark-parse'
declare module 'art-template'
declare module 'babel-file-loader'
declare module 'babel-generator'
declare module 'friendly-errors-webpack-plugin'
declare module 'json-stringify-pretty-compact'
declare module 'lodash.get'
Expand Down
Loading

0 comments on commit 04b59e5

Please sign in to comment.