|
1 | | -import remark from 'remark' |
2 | | -import parents from 'unist-util-parents' |
3 | | -import select from 'unist-util-select' |
4 | | -import findBefore from 'unist-util-find-before' |
| 1 | +import parseCodeBlocks from 'code-blocks/lib/fromString' |
5 | 2 | import htmlToReact from 'html-to-react' |
6 | | -import parsePairs from 'parse-pairs' |
7 | | -import React from 'react' |
8 | | -import ReactDOMServer from 'react-dom/server' |
9 | | -import {Octicon} from '../Octicon' |
10 | 3 |
|
11 | 4 | const htmlParser = new htmlToReact.Parser() |
12 | 5 |
|
13 | | -const railsOcticonToReact = (html) => { |
14 | | - // <%= octicon "tools" %> to <Octicon name="tools" /> |
15 | | - const octre = /<%= octicon[\(\s]["']([a-z\-]+)["'][^%]*%>/gi |
16 | | - html = html.replace(octre, (match, name) => { |
17 | | - return ReactDOMServer.renderToStaticMarkup(<Octicon name={name} />) |
18 | | - }) |
19 | | - return html |
20 | | -} |
21 | | - |
22 | | -const parseBlockAttrs = (node, file) => { |
23 | | - const pairs = node.lang.replace(/^html\s*/, '') |
24 | | - const attrs = pairs.length ? parsePairs(pairs) : {} |
25 | | - attrs.title = attrs.title |
26 | | - || getPreviousHeading(node) |
27 | | - || `story @ ${file}:${node.position.start.line}` |
28 | | - node.block = attrs |
29 | | - return node |
30 | | -} |
31 | | - |
32 | | -const nodeToStory = (node, file) => { |
33 | | - const html = railsOcticonToReact(node.value) |
34 | | - const {title} = node.block |
| 6 | +const blockToStory = block => { |
35 | 7 | return { |
36 | | - title, |
37 | | - story: () => htmlParser.parse(html), |
38 | | - html, |
39 | | - file, |
40 | | - node, |
| 8 | + title: block.title, |
| 9 | + story: () => htmlParser.parse(block.value), |
| 10 | + block, |
41 | 11 | } |
42 | 12 | } |
43 | 13 |
|
44 | | -const getPreviousHeading = node => { |
45 | | - const heading = findBefore(node.parent, node, 'heading') |
46 | | - return (heading && !heading.used) |
47 | | - ? (heading.used = true, heading.children.map(c => c.value).join('')) |
48 | | - : undefined |
49 | | -} |
50 | | - |
51 | | -export default req => { |
52 | | - return req.keys() |
53 | | - .filter(file => !file.match(/node_modules/)) |
54 | | - .reduce((stories, file) => { |
55 | | - const content = req(file) |
56 | | - const ast = parents(remark.parse(content)) |
57 | | - const path = file.replace(/^\.\//, '') |
58 | | - return stories.concat( |
59 | | - select(ast, 'code[lang^=html]') |
60 | | - .map(parseBlockAttrs) |
61 | | - .filter(({block}) => block.story !== "false") |
62 | | - .map(node => nodeToStory(node, path)) |
63 | | - ) |
64 | | - }, []) |
| 14 | +export default function storiesFromMarkdown(req) { |
| 15 | + return req.keys().reduce((stories, file) => { |
| 16 | + const markdown = req(file) |
| 17 | + const path = file.replace(/^\.\//, '') |
| 18 | + const blocks = parseCodeBlocks(markdown, path) |
| 19 | + .filter(block => { |
| 20 | + // read: ```html * |
| 21 | + // skip: ```html * story="false" |
| 22 | + return block.lang === 'html' && block.info.story !== 'false' |
| 23 | + }) |
| 24 | + .map(blockToStory) |
| 25 | + return stories.concat(blocks) |
| 26 | + }, []) |
65 | 27 | } |
0 commit comments