Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Custom-ID Markdown Syntax #1636

Merged
merged 3 commits into from
Feb 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ module.exports = {
maxWidth: 840,
},
},
'gatsby-remark-autolink-headers',
'gatsby-remark-header-custom-ids',
{
resolve: 'gatsby-remark-code-repls',
options: {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"gatsby-plugin-react-helmet": "^3.0.0",
"gatsby-plugin-sharp": "^2.0.0",
"gatsby-plugin-twitter": "^2.0.0",
"gatsby-remark-autolink-headers": "^2.0.12",
"gatsby-remark-code-repls": "^2.0.0",
"gatsby-remark-copy-linked-files": "^2.0.0",
"gatsby-remark-embed-snippet": "^3.0.0",
Expand All @@ -40,8 +39,10 @@
"gatsby-source-filesystem": "^2.0.0",
"gatsby-transformer-remark": "^2.0.0",
"gatsby-transformer-sharp": "^2.0.0",
"github-slugger": "^1.2.1",
"glamor": "^2.20.40",
"hex2rgba": "^0.0.1",
"mdast-util-to-string": "^1.0.5",
"normalize.css": "^8.0.0",
"prettier": "^1.7.4",
"prismjs": "^1.15.0",
Expand Down
30 changes: 30 additions & 0 deletions plugins/gatsby-remark-header-custom-ids/gatsby-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
let offsetY = 0;

const getTargetOffset = hash => {
const id = window.decodeURI(hash.replace(`#`, ``));
if (id !== ``) {
const element = document.getElementById(id);
if (element) {
return element.offsetTop - offsetY;
}
}
return null;
};

exports.onInitialClientRender = (_, pluginOptions) => {
if (pluginOptions.offsetY) {
offsetY = pluginOptions.offsetY;
}

requestAnimationFrame(() => {
const offset = getTargetOffset(window.location.hash);
if (offset !== null) {
window.scrollTo(0, offset);
}
});
};

exports.shouldUpdateScroll = ({routerProps: {location}}) => {
const offset = getTargetOffset(location.hash);
return offset !== null ? [0, offset] : true;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a forked+formatted version of gatsby-remark-autolink-headers/src/gatsby-browser.js 👍

76 changes: 76 additions & 0 deletions plugins/gatsby-remark-header-custom-ids/gatsby-ssr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const React = require(`react`);

const pluginDefaults = {
className: `anchor`,
icon: true,
offsetY: 0,
};

exports.onRenderBody = ({setHeadComponents}, pluginOptions) => {
const {className, icon, offsetY} = Object.assign(
pluginDefaults,
pluginOptions,
);

const styles = `
.${className} {
float: left;
padding-right: 4px;
margin-left: -20px;
}
h1 .${className} svg,
h2 .${className} svg,
h3 .${className} svg,
h4 .${className} svg,
h5 .${className} svg,
h6 .${className} svg {
visibility: hidden;
}
h1:hover .${className} svg,
h2:hover .${className} svg,
h3:hover .${className} svg,
h4:hover .${className} svg,
h5:hover .${className} svg,
h6:hover .${className} svg,
h1 .${className}:focus svg,
h2 .${className}:focus svg,
h3 .${className}:focus svg,
h4 .${className}:focus svg,
h5 .${className}:focus svg,
h6 .${className}:focus svg {
visibility: visible;
}
`;

const script = `
document.addEventListener("DOMContentLoaded", function(event) {
var hash = window.decodeURI(location.hash.replace('#', ''))
if (hash !== '') {
var element = document.getElementById(hash)
if (element) {
var offset = element.offsetTop
// Wait for the browser to finish rendering before scrolling.
setTimeout((function() {
window.scrollTo(0, offset - ${offsetY})
}), 0)
}
}
})
`;

const style = icon ? (
<style key="gatsby-remark-header-custom-ids-style" type="text/css">
{styles}
</style>
) : (
undefined
);

return setHeadComponents([
style,
<script
key="gatsby-remark-header-custom-ids-script"
dangerouslySetInnerHTML={{__html: script}}
/>,
]);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a formed+formatted version of gatsby-remark-autolink-headers/src/gatsby-ssr.js 👍

69 changes: 69 additions & 0 deletions plugins/gatsby-remark-header-custom-ids/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*!
* Based on 'gatsby-remark-autolink-headers'
* Original Author: Kyle Mathews <[email protected]>
* Copyright (c) 2015 Gatsbyjs
*/

const toString = require('mdast-util-to-string');
const visit = require('unist-util-visit');
const slugs = require('github-slugger')();

function patch(context, key, value) {
if (!context[key]) {
context[key] = value;
}

return context[key];
}

const svgIcon = `<svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>`;

module.exports = (
{markdownAST},
{icon = svgIcon, className = `anchor`, maintainCase = false},
) => {
slugs.reset();

visit(markdownAST, 'heading', node => {
// Support custom-id syntax.
const rawHeader = toString(node);
const match = /^.+(\s*\{#([a-z0-9\-_]+?)\}\s*)$/.exec(rawHeader);
const id = match ? match[2] : slugs.slug(rawHeader, maintainCase);
if (match) {
// Remove the custom ID part from the text node.
const lastNode = node.children[node.children.length - 1];
lastNode.value = lastNode.value.replace(match[1], '');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a formed+formatted version of gatsby-remark-autolink-headers/src/index.js with the exception of the above ~10 lines 👍


const data = patch(node, 'data', {});

patch(data, 'id', id);
patch(data, 'htmlAttributes', {});
patch(data, 'hProperties', {});
patch(data.htmlAttributes, 'id', id);
patch(data.hProperties, 'id', id);

if (icon !== false) {
node.children.unshift({
type: 'link',
url: `#${id}`,
title: null,
data: {
hProperties: {
'aria-hidden': true,
class: className,
},
hChildren: [
{
type: 'raw',
// The Octicon link icon is the default. But users can set their own icon via the "icon" option.
value: icon,
},
],
},
});
}
});

return markdownAST;
};
4 changes: 4 additions & 0 deletions plugins/gatsby-remark-header-custom-ids/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "gatsby-remark-header-custom-ids",
"version": "0.0.1"
}
19 changes: 8 additions & 11 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5463,16 +5463,6 @@ gatsby-react-router-scroll@^2.0.0:
scroll-behavior "^0.9.9"
warning "^3.0.0"

gatsby-remark-autolink-headers@^2.0.12:
version "2.0.12"
resolved "https://registry.yarnpkg.com/gatsby-remark-autolink-headers/-/gatsby-remark-autolink-headers-2.0.12.tgz#96830bd7496ace7d1b7e07444aa09ecbe2ac59d2"
integrity sha512-TI7dpdHOUohIWCW7i8ta4zZAdWG5C2ZmrHMC9flWGWQ62oq6Q2eW+I1I/v//UZ+vJ1dRaSX2lmsVFmt87rLVHQ==
dependencies:
"@babel/runtime" "^7.0.0"
github-slugger "^1.1.1"
mdast-util-to-string "^1.0.2"
unist-util-visit "^1.3.0"

gatsby-remark-code-repls@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/gatsby-remark-code-repls/-/gatsby-remark-code-repls-2.0.0.tgz#b3290987046f1d325e6e93dbe9295f3cbb3df34a"
Expand Down Expand Up @@ -5814,6 +5804,13 @@ github-slugger@^1.1.1:
dependencies:
emoji-regex ">=6.0.0 <=6.1.1"

github-slugger@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.2.1.tgz#47e904e70bf2dccd0014748142d31126cfd49508"
integrity sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ==
dependencies:
emoji-regex ">=6.0.0 <=6.1.1"

glamor@^2.20.40:
version "2.20.40"
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.40.tgz#f606660357b7cf18dface731ad1a2cfa93817f05"
Expand Down Expand Up @@ -8184,7 +8181,7 @@ mdast-util-to-nlcst@^3.2.0:
unist-util-position "^3.0.0"
vfile-location "^2.0.0"

mdast-util-to-string@^1.0.2:
mdast-util-to-string@^1.0.2, mdast-util-to-string@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.0.5.tgz#3552b05428af22ceda34f156afe62ec8e6d731ca"
integrity sha512-2qLt/DEOo5F6nc2VFScQiHPzQ0XXcabquRJxKMhKte8nt42o08HUxNDPk7tt0YPxnWjAT11I1SYi0X0iPnfI5A==
Expand Down