From baa9580aeb24a72198692d9b9e323bbfcc392d8b Mon Sep 17 00:00:00 2001 From: chenxsan Date: Mon, 7 Feb 2022 18:35:38 +0800 Subject: [PATCH 1/6] fix issue#5945 --- src/components/Markdown/Markdown.scss | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/Markdown/Markdown.scss b/src/components/Markdown/Markdown.scss index f43030c17f0f..12f9e8ce124d 100644 --- a/src/components/Markdown/Markdown.scss +++ b/src/components/Markdown/Markdown.scss @@ -1,4 +1,4 @@ -@use "sass:color"; +@use 'sass:color'; @import 'vars'; @import 'functions'; @import 'prism-theme'; @@ -42,14 +42,15 @@ $topHeightMobileWithBanner: $bannerHeight + $topHeightMobile; h5, h6 { &:before { + width: 0; content: ''; display: block; visibility: hidden; pointer-events: none; - height: $topHeightMobile; + padding-top: $topHeightMobile; margin-top: -#{$topHeightMobile}; @include break { - height: $topHeightDesktop; + padding-top: $topHeightDesktop; margin-top: -#{$topHeightDesktop}; } } From b49a6d9fcd9cbff96f64d8c01cd5cb9b74b443d5 Mon Sep 17 00:00:00 2001 From: chenxsan Date: Mon, 7 Feb 2022 20:04:08 +0800 Subject: [PATCH 2/6] refactor remark plugins --- package.json | 1 + src/components/Markdown/Markdown.scss | 3 +- .../remark-remove-heading-id/index.mjs | 14 +++++ src/remark-plugins/remark-slug/index.mjs | 55 +++++++++++++++++++ src/utilities/content-tree-enhancers.mjs | 4 +- webpack.common.mjs | 4 +- yarn.lock | 15 ++--- 7 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 src/remark-plugins/remark-remove-heading-id/index.mjs create mode 100644 src/remark-plugins/remark-slug/index.mjs diff --git a/package.json b/package.json index 846c04278d56..5d8096abb92e 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,7 @@ "lodash": "^4.17.21", "markdownlint": "^0.25.1", "markdownlint-cli": "^0.30.0", + "mdast-util-to-string": "^3.1.0", "mini-css-extract-plugin": "^2.5.3", "mkdirp": "^1.0.4", "modularscale-sass": "^3.0.3", diff --git a/src/components/Markdown/Markdown.scss b/src/components/Markdown/Markdown.scss index 12f9e8ce124d..6858d6609d65 100644 --- a/src/components/Markdown/Markdown.scss +++ b/src/components/Markdown/Markdown.scss @@ -41,9 +41,8 @@ $topHeightMobileWithBanner: $bannerHeight + $topHeightMobile; h4, h5, h6 { - &:before { + > span[id] { width: 0; - content: ''; display: block; visibility: hidden; pointer-events: none; diff --git a/src/remark-plugins/remark-remove-heading-id/index.mjs b/src/remark-plugins/remark-remove-heading-id/index.mjs new file mode 100644 index 000000000000..fe4df6e0b8ec --- /dev/null +++ b/src/remark-plugins/remark-remove-heading-id/index.mjs @@ -0,0 +1,14 @@ +import { visit } from 'unist-util-visit'; +export default function () { + return function transformer(ast) { + visit(ast, 'heading', visitor); + }; + function visitor(node) { + if (node.data && node.data.id) { + delete node.data.id; + } + if (node.data && node.data.hProperties && node.data.hProperties.id) { + delete node.data.hProperties.id; + } + } +} diff --git a/src/remark-plugins/remark-slug/index.mjs b/src/remark-plugins/remark-slug/index.mjs new file mode 100644 index 000000000000..03a362319632 --- /dev/null +++ b/src/remark-plugins/remark-slug/index.mjs @@ -0,0 +1,55 @@ +// based on https://github.com/remarkjs/remark-slug/blob/8e6394c3dd6232cc9f0fb0b05e7eaf33063effa5/index.js +// to fix https://github.com/webpack/webpack.js.org/pull/5947 +/** + * @typedef {import('mdast').Root} Root + * @typedef {import('hast').Properties} Properties + */ + +import { toString } from 'mdast-util-to-string'; +import { visit } from 'unist-util-visit'; +import BananaSlug from 'github-slugger'; + +const slugs = new BananaSlug(); + +/** + * Plugin to add anchors headings using GitHub’s algorithm. + * + * @type {import('unified').Plugin} + */ +export default function remarkSlug() { + return (tree) => { + slugs.reset(); + + visit(tree, 'heading', (node) => { + const data = node.data || (node.data = {}); + const props = /** @type {Properties} */ ( + data.hProperties || (data.hProperties = {}) + ); + let id = props.id; + + id = id ? slugs.slug(String(id), true) : slugs.slug(toString(node)); + + data.id = id; + props.id = id; + node.children = [ + { + type: 'paragraph', + value: '', + data: { + hName: 'span', + hProperties: { + id, + }, + }, + children: [ + { + type: 'text', + value: '', + }, + ], + }, + ...node.children, + ]; + }); + }; +} diff --git a/src/utilities/content-tree-enhancers.mjs b/src/utilities/content-tree-enhancers.mjs index b9c18e3fd7bc..47ac93f68f75 100644 --- a/src/utilities/content-tree-enhancers.mjs +++ b/src/utilities/content-tree-enhancers.mjs @@ -2,12 +2,13 @@ import fs from 'fs'; import path from 'path'; import frontMatter from 'front-matter'; import {remark} from 'remark'; -import slug from 'remark-slug'; +import slug from '../../src/remark-plugins/remark-slug/index.mjs'; import extractAnchors from 'remark-extract-anchors'; import remarkHtml from 'remark-html'; import frontmatter from 'remark-frontmatter'; import gfm from 'remark-gfm'; import emoji from 'remark-emoji'; +import remarkRemoveHeadingId from '../remark-plugins/remark-remove-heading-id/index.mjs'; export const enhance = (tree, options) => { // delete `./` root directory on node @@ -46,6 +47,7 @@ export const enhance = (tree, options) => { .use(gfm) .use(emoji) .use(extractAnchors, { anchors, levels: 3 }) + .use(remarkRemoveHeadingId) .use(remarkHtml) .process(content, (err) => { if (err) { diff --git a/webpack.common.mjs b/webpack.common.mjs index b8cb05ccbb47..8dd46af61d30 100644 --- a/webpack.common.mjs +++ b/webpack.common.mjs @@ -4,7 +4,7 @@ import webpack from 'webpack'; import h from 'hastscript'; import remarkResponsiveTable from './src/remark-plugins/remark-responsive-table/remark-responsive-table.mjs'; import gfm from 'remark-gfm'; -import slug from 'remark-slug'; +import slug from './src/remark-plugins/remark-slug/index.mjs'; import cleanup from './src/remark-plugins/remark-cleanup-readme/index.mjs'; import aside from './src/remark-plugins/remark-custom-asides/index.mjs'; import autolink from 'remark-autolink-headings'; @@ -13,6 +13,7 @@ import frontmatter from 'remark-frontmatter'; import { createRequire } from 'module'; import remarkEmoji from 'remark-emoji'; import { fileURLToPath } from 'url'; +import remarkRemoveHeadingId from './src/remark-plugins/remark-remove-heading-id/index.mjs'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -44,6 +45,7 @@ const mdPlugins = [ }, ], refractor, + remarkRemoveHeadingId ]; export default ({ ssg = false }) => ({ diff --git a/yarn.lock b/yarn.lock index 2325d2ed5b2e..3c04362f59a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4852,11 +4852,6 @@ emittery@^0.8.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== -"emoji-regex@>=6.0.0 <=6.1.1": - version "6.1.1" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" - integrity sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4= - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -5845,11 +5840,9 @@ gifwrap@^0.9.2: omggif "^1.0.10" github-slugger@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.3.0.tgz#9bd0a95c5efdfc46005e82a906ef8e2a059124c9" - integrity sha512-gwJScWVNhFYSRDvURk/8yhcFBee6aFjye2a7Lhb2bUyRulpIoek9p0I9Kt7PT67d/nUlZbFu8L9RLiA0woQN8Q== - dependencies: - emoji-regex ">=6.0.0 <=6.1.1" + version "1.4.0" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" + integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" @@ -8316,7 +8309,7 @@ mdast-util-to-string@^2.0.0: resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== -mdast-util-to-string@^3.0.0: +mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9" integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA== From 7837183dc7bce95d0c73e0814d66e15fb4d41137 Mon Sep 17 00:00:00 2001 From: chenxsan Date: Mon, 7 Feb 2022 20:11:35 +0800 Subject: [PATCH 3/6] update css --- src/components/Markdown/Markdown.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Markdown/Markdown.scss b/src/components/Markdown/Markdown.scss index 6858d6609d65..daabd9f61816 100644 --- a/src/components/Markdown/Markdown.scss +++ b/src/components/Markdown/Markdown.scss @@ -42,6 +42,7 @@ $topHeightMobileWithBanner: $bannerHeight + $topHeightMobile; h5, h6 { > span[id] { + position: absolute; width: 0; display: block; visibility: hidden; From 534090c70f0487b1bd42d09e4869a40dc90d4ee0 Mon Sep 17 00:00:00 2001 From: chenxsan Date: Mon, 7 Feb 2022 20:20:57 +0800 Subject: [PATCH 4/6] cleanup --- package.json | 2 +- yarn.lock | 16 ++-------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 5d8096abb92e..e416b954e4c8 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", "front-matter": "^4.0.2", + "github-slugger": "^1.4.0", "html-webpack-plugin": "^5.5.0", "http-server": "^14.1.0", "husky": "^7.0.4", @@ -124,7 +125,6 @@ "remark-gfm": "^1.0.0", "remark-html": "^15.0.1", "remark-refractor": "montogeek/remark-refractor", - "remark-slug": "^7.0.1", "rimraf": "^3.0.2", "sass": "^1.49.7", "sass-loader": "^12.4.0", diff --git a/yarn.lock b/yarn.lock index 3c04362f59a4..c52f0ebe9b02 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2486,7 +2486,7 @@ dependencies: "@types/node" "*" -"@types/hast@^2.0.0", "@types/hast@^2.3.2": +"@types/hast@^2.0.0": version "2.3.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== @@ -5839,7 +5839,7 @@ gifwrap@^0.9.2: image-q "^1.1.1" omggif "^1.0.10" -github-slugger@^1.0.0: +github-slugger@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== @@ -10363,18 +10363,6 @@ remark-refractor@montogeek/remark-refractor: refractor "^3.1.0" unist-util-visit "1.3.1" -remark-slug@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/remark-slug/-/remark-slug-7.0.1.tgz#9827ce6d6ee81ca82b79891b0e5931a8123ce63b" - integrity sha512-NRvYePr69LdeCkEGwL4KYAmq7kdWG5rEavCXMzUR4qndLoXHJAOLSUmPY6Qm4NJfKix7/EmgObyVaYivONAFhg== - dependencies: - "@types/hast" "^2.3.2" - "@types/mdast" "^3.0.0" - github-slugger "^1.0.0" - mdast-util-to-string "^3.0.0" - unified "^10.0.0" - unist-util-visit "^4.0.0" - remark-squeeze-paragraphs@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz#76eb0e085295131c84748c8e43810159c5653ead" From f87d79009231e6ba8b9499dc253acb67f5bbb64b Mon Sep 17 00:00:00 2001 From: chenxsan Date: Tue, 8 Feb 2022 13:00:32 +0800 Subject: [PATCH 5/6] add some tests --- .../__snapshots__/index.test.mjs.snap | 7 ++++++ .../remark-remove-heading-id/index.test.mjs | 23 +++++++++++++++++++ .../__snapshots__/index.test.mjs.snap | 7 ++++++ src/remark-plugins/remark-slug/index.mjs | 2 ++ src/remark-plugins/remark-slug/index.test.mjs | 20 ++++++++++++++++ src/remark-plugins/remark-slug/license | 22 ++++++++++++++++++ 6 files changed, 81 insertions(+) create mode 100644 src/remark-plugins/remark-remove-heading-id/__snapshots__/index.test.mjs.snap create mode 100644 src/remark-plugins/remark-remove-heading-id/index.test.mjs create mode 100644 src/remark-plugins/remark-slug/__snapshots__/index.test.mjs.snap create mode 100644 src/remark-plugins/remark-slug/index.test.mjs create mode 100644 src/remark-plugins/remark-slug/license diff --git a/src/remark-plugins/remark-remove-heading-id/__snapshots__/index.test.mjs.snap b/src/remark-plugins/remark-remove-heading-id/__snapshots__/index.test.mjs.snap new file mode 100644 index 000000000000..02e066d7ceb0 --- /dev/null +++ b/src/remark-plugins/remark-remove-heading-id/__snapshots__/index.test.mjs.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`customize blockquote should add id 1`] = ` +"

hello world

+

this is me.

+" +`; diff --git a/src/remark-plugins/remark-remove-heading-id/index.test.mjs b/src/remark-plugins/remark-remove-heading-id/index.test.mjs new file mode 100644 index 000000000000..1782ce1c2676 --- /dev/null +++ b/src/remark-plugins/remark-remove-heading-id/index.test.mjs @@ -0,0 +1,23 @@ +import { remark } from 'remark'; +import remarkHtml from 'remark-html'; +import Plugin from './index.mjs'; +import remarkSlug from '../remark-slug/index.mjs'; +describe('customize blockquote', () => { + it('should add id', () => { + remark() + .use(remarkSlug) + .use(Plugin) + .use(remarkHtml) + .process( + ` +## hello world + +this is me. +`, + function (err, { value: contents }) { + expect(err).toBeNull(); + expect(contents).toMatchSnapshot(); + } + ); + }); +}); diff --git a/src/remark-plugins/remark-slug/__snapshots__/index.test.mjs.snap b/src/remark-plugins/remark-slug/__snapshots__/index.test.mjs.snap new file mode 100644 index 000000000000..16c03e73a1c9 --- /dev/null +++ b/src/remark-plugins/remark-slug/__snapshots__/index.test.mjs.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`remark slug should add id 1`] = ` +"

hello world

+

this is me.

+" +`; diff --git a/src/remark-plugins/remark-slug/index.mjs b/src/remark-plugins/remark-slug/index.mjs index 03a362319632..c9ec88bba44e 100644 --- a/src/remark-plugins/remark-slug/index.mjs +++ b/src/remark-plugins/remark-slug/index.mjs @@ -31,6 +31,8 @@ export default function remarkSlug() { data.id = id; props.id = id; + + // insert for headings node.children = [ { type: 'paragraph', diff --git a/src/remark-plugins/remark-slug/index.test.mjs b/src/remark-plugins/remark-slug/index.test.mjs new file mode 100644 index 000000000000..02eaa9eb64c4 --- /dev/null +++ b/src/remark-plugins/remark-slug/index.test.mjs @@ -0,0 +1,20 @@ +import { remark } from 'remark'; +import remarkHtml from 'remark-html'; +import Plugin from './index.mjs'; +describe('remark slug', () => { + it('should add id', () => { + remark() + .use(Plugin) + .use(remarkHtml) + .process( + `## hello world + +this is me. +`, + function (err, { value: contents }) { + expect(err).toBeNull(); + expect(contents).toMatchSnapshot(); + } + ); + }); +}); diff --git a/src/remark-plugins/remark-slug/license b/src/remark-plugins/remark-slug/license new file mode 100644 index 000000000000..32e7a3d93ca5 --- /dev/null +++ b/src/remark-plugins/remark-slug/license @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2015 Titus Wormer + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From da163cb8902912fc55309c1c5165cdfe07701d42 Mon Sep 17 00:00:00 2001 From: chenxsan Date: Tue, 8 Feb 2022 13:01:37 +0800 Subject: [PATCH 6/6] clean up --- src/remark-plugins/remark-slug/index.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/remark-plugins/remark-slug/index.mjs b/src/remark-plugins/remark-slug/index.mjs index c9ec88bba44e..79fdaef2aa23 100644 --- a/src/remark-plugins/remark-slug/index.mjs +++ b/src/remark-plugins/remark-slug/index.mjs @@ -36,7 +36,6 @@ export default function remarkSlug() { node.children = [ { type: 'paragraph', - value: '', data: { hName: 'span', hProperties: {