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/package-lock.json b/package-lock.json index 40682b9..e98d8ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10015,34 +10015,6 @@ } } }, - "gatsby-remark-auto-headers": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gatsby-remark-auto-headers/-/gatsby-remark-auto-headers-1.0.3.tgz", - "integrity": "sha512-bLcZD53sXU3jklGlbtT4MEN+a8w+WocSxe+sqRFkoHWOJeB1ClyqM0IH7wHUV0M/BFyQ54i+ycwjrUa17op1bg==", - "requires": { - "@babel/runtime": "^7.0.0", - "github-slugger": "^1.2.0", - "unist-util-visit": "^1.4.0" - }, - "dependencies": { - "unist-util-visit": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", - "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", - "requires": { - "unist-util-visit-parents": "^2.0.0" - } - }, - "unist-util-visit-parents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", - "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", - "requires": { - "unist-util-is": "^3.0.0" - } - } - } - }, "gatsby-source-filesystem": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/gatsby-source-filesystem/-/gatsby-source-filesystem-2.3.5.tgz", diff --git a/package.json b/package.json index b0c5093..7b44390 100644 --- a/package.json +++ b/package.json @@ -40,10 +40,10 @@ "gatsby-plugin-react-svg": "^3.0.0", "gatsby-plugin-sharp": "^2.6.6", "gatsby-plugin-styled-components": "^3.3.1", - "gatsby-remark-auto-headers": "^1.0.3", "gatsby-source-filesystem": "^2.3.5", "gatsby-transformer-remark": "^2.8.10", "gatsby-transformer-sharp": "^2.5.2", + "github-slugger": "^1.3.0", "lodash": "^4.17.15", "polished": "^3.6.3", "prismjs": "^1.20.0", 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, +