diff --git a/package.json b/package.json index 1a78360f57ed..c3a846fc3faf 100644 --- a/package.json +++ b/package.json @@ -84,9 +84,11 @@ "prismjs": "^1.9.0", "raw-loader": "^0.5.1", "redirect-webpack-plugin": "^0.1.1", + "remark": "^9.0.0", "remark-autolink-headings": "^5.0.0", "remark-loader": "^0.3.0", "remark-mermaid": "^0.2.0", + "remark-slug": "^5.0.0", "request-promise": "^4.2.2", "sass-loader": "^6.0.6", "sitemap-static": "^0.4.2", @@ -96,6 +98,7 @@ "tap-parser": "^6.0.1", "through2": "^2.0.3", "uglifyjs-webpack-plugin": "^1.1.6", + "unist-util-visit": "^1.3.0", "url-loader": "^0.5.9", "webpack": "^3.10.0", "webpack-dev-server": "^2.9.7", @@ -106,8 +109,6 @@ "ajv": "^5.5.2", "docsearch.js": "^2.5.2", "gitter-sidecar": "^1.2.3", - "preact": "^8.2.7", - "preact-compat": "3.17.0", "prop-types": "^15.5.10", "react": "^16.2.0", "react-banner": "^1.0.0-rc.0", diff --git a/src/utilities/remark-extract-anchors.js b/src/utilities/remark-extract-anchors.js new file mode 100644 index 000000000000..f7e9098c3838 --- /dev/null +++ b/src/utilities/remark-extract-anchors.js @@ -0,0 +1,27 @@ +const visit = require('unist-util-visit'); + +/** + * A remark plugin to extract anchors markdown headers + * + * @param {object} options - ... + * @return {function} - ... + */ +module.exports = function extractAnchors(options = {}) { + let { anchors, levels } = options + + if ( !Array.isArray(anchors) ) { + throw new Error('Missing or malformed `anchors` in options.') + } + + return function transformer(ast) { + visit(ast, 'heading', visitor); + }; + + function visitor(node) { + // TODO: Default header `levels` and check it to filter the `push`ed anchors + options.anchors.push({ + title: node.children[0].value, + id: node.data.id + }); + } +} diff --git a/src/utilities/treePluginEnhacer.js b/src/utilities/tree-plugin-enhancer.js similarity index 60% rename from src/utilities/treePluginEnhacer.js rename to src/utilities/tree-plugin-enhancer.js index d67fc72d47c8..1fae0143fc79 100644 --- a/src/utilities/treePluginEnhacer.js +++ b/src/utilities/tree-plugin-enhancer.js @@ -1,5 +1,10 @@ const fs = require('fs'); const FrontMatter = require('front-matter'); +const remark = require('remark'); +const slug = require('remark-slug'); + +// TODO: Extract these to separate packages +const ExtractAnchors = require('./remark-extract-anchors'); module.exports = function(item, options) { item.url = item.path @@ -9,16 +14,27 @@ module.exports = function(item, options) { .replace(/^$/, '/'); if (item.type === 'file') { + let anchors = []; + let content = fs.readFileSync(item.path, 'utf8'); + let { attributes } = FrontMatter(content); + // remove underscore from fetched files if (item.name[0] === '_') { item.name = item.name.replace('_', ''); item.url = item.url.replace('_', ''); } - let content = fs.readFileSync(item.path, 'utf8'); - let { attributes } = FrontMatter(content); + remark() + .use(slug) + .use(ExtractAnchors, { anchors }) + .process(content, (err, file) => { + if (err) { + throw err; + } + }); + + item.anchors = anchors; Object.assign(item, attributes); - item.anchors = []; // TODO: Add actual anchors } } diff --git a/webpack.common.js b/webpack.common.js index a1bf3263581e..6a1fb2a29c3f 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -5,7 +5,7 @@ const CleanPlugin = require('clean-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const DirectoryTreePlugin = require('directory-tree-webpack-plugin'); -const treePluginEnhacer = require('./src/utilities/treePluginEnhacer.js'); +const TreeEnhancer = require('./src/utilities/tree-plugin-enhancer.js'); module.exports = (env = {}) => ({ devtool: 'source-map', @@ -35,6 +35,7 @@ module.exports = (env = {}) => ({ options: { plugins: [ // TODO: Add necessary remark plugins + require('remark-slug'), require('remark-autolink-headings'), require('remark-mermaid') ] @@ -109,7 +110,7 @@ module.exports = (env = {}) => ({ dir: 'src/content', path: 'src/_content.json', extensions: /\.md/, - enhance: treePluginEnhacer, + enhance: TreeEnhancer, filter: item => item.name !== 'images', sort: (a, b) => { let group1 = (a.group || '').toLowerCase();