diff --git a/components/AnchoredHeading.tsx b/components/AnchoredHeading.tsx index 1eef61371920f..89f2f4ece9271 100644 --- a/components/AnchoredHeading.tsx +++ b/components/AnchoredHeading.tsx @@ -7,11 +7,42 @@ type AnchorHeadingProps = PropsWithChildren<{ id?: string; }>; +/** + * This module will automatically replace the header style words + * (such as `#`,`##`...ect) to an anchor name. + * + * This processor will make all the English characters (26 letters) + * into their lower case, for others in the middle of words, + * they will become `-` in default. For more than one `-` together, + * there's only one left. + * + * If your title has some non-English characters, please use + * `` to quote your English anchor name inside, with your + * own title beside it. Otherwises it will return you what it is. + */ + +// React will ignore "" in the string, +// so we can just use '-- --' to quote the anchor name inside it. +const COMMENT_FOR_HEADANCHOR = /--\x20?([\w\x20-]+)\x20?--/; + const AnchoredHeading = ({ children, level, id }: AnchorHeadingProps) => { const HeadingLevelTag = `h${level}` as any; - // This regex replacement is used for comments within the heading - const sanitizedId = id?.replace(/---(.+)---(.*)/, (_, f) => f); + let sanitizedId = + id ?? children?.toLocaleString().toLocaleLowerCase().replace(/\x20/g, '-'); + + if (sanitizedId) { + const foundAnchorAndTitle = COMMENT_FOR_HEADANCHOR.exec(sanitizedId); + + if (foundAnchorAndTitle) { + sanitizedId = foundAnchorAndTitle[1] + .replace(/(\[([^\]]+)]\([^)]+\))/g, '$2') + .replace(/[^\w]+/g, '-') + .replace(/[\x20]+/g, '-') + .replace(/-{2,}/g, '-') + .replace(/(^-|-$)/g, ''); + } + } return (