From 82ac9f0bae2f487c2f906f5111a74018ede9bb3f Mon Sep 17 00:00:00 2001 From: Jean-Philippe Sirois Date: Thu, 21 May 2020 23:52:33 -0400 Subject: [PATCH 1/4] fix: replace gatsby-remark-auto-headers --- gatsby-config.js | 2 +- .../gatsby-browser.js | 43 ++++++++++ .../gatsby-ssr.js | 85 +++++++++++++++++++ .../index.js | 69 +++++++++++++++ .../package-lock.json | 50 +++++++++++ .../package.json | 14 +++ 6 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 plugins/gatsby-remark-auto-headers-improved/gatsby-browser.js create mode 100644 plugins/gatsby-remark-auto-headers-improved/gatsby-ssr.js create mode 100644 plugins/gatsby-remark-auto-headers-improved/index.js create mode 100644 plugins/gatsby-remark-auto-headers-improved/package-lock.json create mode 100644 plugins/gatsby-remark-auto-headers-improved/package.json diff --git a/gatsby-config.js b/gatsby-config.js index 82b9edd..ee55a7a 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -31,7 +31,7 @@ module.exports = { { resolve: `gatsby-transformer-remark`, options: { - plugins: [`gatsby-remark-auto-headers`], + plugins: [`gatsby-remark-auto-headers-improved`], }, }, { diff --git a/plugins/gatsby-remark-auto-headers-improved/gatsby-browser.js b/plugins/gatsby-remark-auto-headers-improved/gatsby-browser.js new file mode 100644 index 0000000..50e9872 --- /dev/null +++ b/plugins/gatsby-remark-auto-headers-improved/gatsby-browser.js @@ -0,0 +1,43 @@ +var attr = "id" +const getTargetOffset = (hash) => { + const id = window.decodeURI(hash.replace(`#`, ``)) + if (id !== ``) { + const element = document.querySelector("[" + attr + "=" + id + "]") + if (element) { + return getElementTop(element) + } + } + return null +} + +function getElementTop(el) { + let actualTop = el.offsetTop + + let current = el.offsetParent + + while (current !== null) { + actualTop += current.offsetTop + + current = current.offsetParent + } + + return actualTop +} + +exports.onInitialClientRender = (_, pluginOptions) => { + if (pluginOptions.offsetY) { + attr = pluginOptions.attr + } + + 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 +} diff --git a/plugins/gatsby-remark-auto-headers-improved/gatsby-ssr.js b/plugins/gatsby-remark-auto-headers-improved/gatsby-ssr.js new file mode 100644 index 0000000..5404349 --- /dev/null +++ b/plugins/gatsby-remark-auto-headers-improved/gatsby-ssr.js @@ -0,0 +1,85 @@ +const React = require("react") + +const pluginDefaults = { + className: `anchor`, + icon: true, + offsetY: 0, + attr: "id", +} + +exports.onRenderBody = ({ setHeadComponents }, pluginOptions) => { + const { className, icon, attr } = 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 = ` + function getElementTop(el) { + var actualTop = el.offsetTop + + var current = el.offsetParent + + while (current !== null) { + actualTop += current.offsetTop + + current = current.offsetParent + } + + return actualTop + } + + document.addEventListener("DOMContentLoaded", function(event) { + var hash = window.decodeURI(location.hash.replace('#', '')) + if (hash !== '') { + var element = document.querySelector('[${attr}=' + hash + ']') + if (element) { + var offset = getElementTop(element) + // Wait for the browser to finish rendering before scrolling. + setTimeout((function() { + window.scrollTo(0, offset) + }), 0) + } + } + }) + ` + + const style = icon ? ( + + ) : undefined + + return setHeadComponents([ + style, +