Added autolinking headings in mdx docs
This commit is contained in:
@@ -126,6 +126,7 @@
|
||||
"cache-loader": "^4.1.0",
|
||||
"compare-versions": "^3.5.1",
|
||||
"css-loader": "0.23.x",
|
||||
"extend": "^3.0.2",
|
||||
"glob": "^7.1.4",
|
||||
"json-stringify-pretty-compact": "^2.0.0",
|
||||
"less-loader": "^4.1.0",
|
||||
@@ -149,6 +150,7 @@
|
||||
"unist-util-find-after": "^2.0.4",
|
||||
"unist-util-modify-children": "^1.1.4",
|
||||
"unist-util-select": "^2.0.2",
|
||||
"unist-util-visit": "^2.0.0",
|
||||
"unist-util-visit-parents": "^3.0.0",
|
||||
"webpack": "^4.39.2",
|
||||
"webpack-cli": "3.3.7",
|
||||
|
||||
@@ -1,7 +1,35 @@
|
||||
import styled from 'styled-components';
|
||||
import { Heading } from 'ts/components/text';
|
||||
|
||||
const H1 = styled(Heading).attrs({
|
||||
const MDXHeading = styled(Heading)`
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
.heading-link-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.heading-link-icon {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
position: absolute;
|
||||
transform: translateY(-50%);
|
||||
top: 50%;
|
||||
left: -26px;
|
||||
padding-right: 26px;
|
||||
|
||||
opacity: 0;
|
||||
transition: opacity 200ms ease-in-out;
|
||||
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' %3E%3Cpath d='M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3M8 12h8'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
`;
|
||||
|
||||
const H1 = styled(MDXHeading).attrs({
|
||||
size: 34,
|
||||
asElement: 'h1',
|
||||
marginBottom: '1rem',
|
||||
@@ -12,32 +40,32 @@ const H1 = styled(Heading).attrs({
|
||||
}
|
||||
`;
|
||||
|
||||
const H2 = styled(Heading).attrs({
|
||||
const H2 = styled(MDXHeading).attrs({
|
||||
size: 'default',
|
||||
asElement: 'h2',
|
||||
marginBottom: '1rem',
|
||||
})``;
|
||||
|
||||
const H3 = styled(Heading).attrs({
|
||||
const H3 = styled(MDXHeading).attrs({
|
||||
size: 'small',
|
||||
asElement: 'h3',
|
||||
fontWeight: '300',
|
||||
marginBottom: '1rem',
|
||||
})``;
|
||||
|
||||
const H4 = styled(Heading).attrs({
|
||||
const H4 = styled(MDXHeading).attrs({
|
||||
asElement: 'h4',
|
||||
fontWeight: '300',
|
||||
marginBottom: '1rem',
|
||||
})``;
|
||||
|
||||
const H5 = styled(Heading).attrs({
|
||||
const H5 = styled(MDXHeading).attrs({
|
||||
asElement: 'h5',
|
||||
fontWeight: '300',
|
||||
marginBottom: '1rem',
|
||||
})``;
|
||||
|
||||
const H6 = styled(Heading).attrs({
|
||||
const H6 = styled(MDXHeading).attrs({
|
||||
asElement: 'h6',
|
||||
fontWeight: '300',
|
||||
marginBottom: '1rem',
|
||||
|
||||
@@ -5,6 +5,7 @@ const TerserPlugin = require('terser-webpack-plugin');
|
||||
const RollbarSourceMapPlugin = require('rollbar-sourcemap-webpack-plugin');
|
||||
const childProcess = require('child_process');
|
||||
const remarkSlug = require('remark-slug');
|
||||
const remarkAutolinkHeadings = require('./webpack/remark_autolink_headings');
|
||||
const remarkSectionizeHeadings = require('./webpack/remark_sectionize_headings');
|
||||
const mdxTableOfContents = require('./webpack/mdx_table_of_contents');
|
||||
|
||||
@@ -65,7 +66,7 @@ const config = {
|
||||
{
|
||||
loader: '@mdx-js/loader',
|
||||
options: {
|
||||
remarkPlugins: [remarkSlug, remarkSectionizeHeadings],
|
||||
remarkPlugins: [remarkSlug, remarkAutolinkHeadings, remarkSectionizeHeadings],
|
||||
compilers: [mdxTableOfContents],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -61,11 +61,14 @@ function isSlugifiedSection(node) {
|
||||
}
|
||||
|
||||
function toFragment(nodes) {
|
||||
if (nodes.length === 1 && nodes[0].type === 'text') {
|
||||
return JSON.stringify(nodes[0].value);
|
||||
} else {
|
||||
return '<React.Fragment>' + nodes.map(toJSX).join('') + '</React.Fragment>';
|
||||
// Because of autolinking headings earlier (at remark stage), the headings (nodes)
|
||||
// contain an anchor tag next to the title, we only want to render the text.
|
||||
// Unless there is no text, then we render whatever nodes we get in a Fragment
|
||||
const textNode = nodes.find(node => node.type === 'text');
|
||||
if (textNode) {
|
||||
return JSON.stringify(textNode.value);
|
||||
}
|
||||
return '<React.Fragment>' + nodes.map(toJSX).join('') + '</React.Fragment>';
|
||||
}
|
||||
|
||||
function tableOfContentsListSerializer(nodes, indent = 0) {
|
||||
|
||||
45
packages/website/webpack/remark_autolink_headings.js
Normal file
45
packages/website/webpack/remark_autolink_headings.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const visit = require('unist-util-visit');
|
||||
const extend = require('extend');
|
||||
|
||||
const content = {
|
||||
type: 'element',
|
||||
tagName: 'i',
|
||||
properties: { className: ['heading-link-icon'] },
|
||||
};
|
||||
|
||||
const linkProperties = { ariaHidden: 'true' };
|
||||
|
||||
const hChildren = Array.isArray(content) ? content : [content];
|
||||
|
||||
module.exports = plugin;
|
||||
|
||||
function plugin() {
|
||||
return transform;
|
||||
}
|
||||
|
||||
function transform(tree) {
|
||||
visit(tree, 'heading', visitor);
|
||||
}
|
||||
|
||||
function visitor(node) {
|
||||
const { data } = node;
|
||||
const id = data && data.hProperties && data.hProperties.id;
|
||||
const url = '#' + id;
|
||||
|
||||
if (id) {
|
||||
inject(node, url);
|
||||
}
|
||||
}
|
||||
|
||||
function inject(node, url) {
|
||||
node.children.unshift({
|
||||
type: 'link',
|
||||
url,
|
||||
title: null,
|
||||
children: [],
|
||||
data: {
|
||||
hProperties: extend(true, {}, linkProperties),
|
||||
hChildren: extend(true, [], hChildren),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -8903,9 +8903,10 @@ extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
|
||||
|
||||
extend@~3.0.2:
|
||||
extend@^3.0.2, extend@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||
|
||||
external-editor@^2.0.4:
|
||||
version "2.2.0"
|
||||
@@ -20723,7 +20724,7 @@ unist-util-visit-parents@^3.0.0:
|
||||
"@types/unist" "^2.0.3"
|
||||
unist-util-is "^4.0.0"
|
||||
|
||||
unist-util-visit@2.0.0:
|
||||
unist-util-visit@2.0.0, unist-util-visit@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.0.tgz#1fdae5ea88251651bfe49b7e84390d664fc227c5"
|
||||
integrity sha512-kiTpWKsF54u/78L/UU/i7lxrnqGiEWBgqCpaIZBYP0gwUC+Akq0Ajm4U8JiNIoQNfAioBdsyarnOcTEAb9mLeQ==
|
||||
|
||||
Reference in New Issue
Block a user