Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 1x 1x 1x 1x 1x 1x 1x 18x 18x 18x 18x 18x 38x 38x 27x 27x 27x 27x 3x 3x 38x 18x 1x 1x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 27x 14x 14x 27x 27x 9x 9x 14x 9x | import * as React from "react" import * as ReactDOMServer from "react-dom/server" import { ExpandableInlineBlock_name } from "./ExpandableInlineBlock" import { GlossaryExcerpt_name } from "./GlossaryExcerpt" import { GlossaryItem } from "./glossary" // Do not replace glossary terms within these tags export const FORBIDDEN_TAGS = ["a", "h2", "h3", "h4", "h5", "h6"] export const GlossaryLink = ({ slug, excerpt, match, }: { slug: string excerpt: string match: string }) => ( <span> <script data-type={ExpandableInlineBlock_name} data-block={GlossaryExcerpt_name} data-label={match} type="component/props" dangerouslySetInnerHTML={{ __html: JSON.stringify({ slug, excerpt }), }} ></script> <a className="expandable-block-button" href={`/glossary#${slug}`}> {match} </a> </span> ) export const formatGlossaryTerms = ( $: CheerioStatic, $contents: Cheerio, mutableGlossary: GlossaryItem[] ) => { $contents.each((i, el) => { if (FORBIDDEN_TAGS.includes(el.tagName)) return if (el.type === "text") { $(el).replaceWith( _linkGlossaryTermsInText(el.data, mutableGlossary) ) } else { formatGlossaryTerms($, $(el).contents(), mutableGlossary) } }) } export const _linkGlossaryTermsInText = ( srcText: string = "", glossary: GlossaryItem[] ) => { let textWithGlossaryLinks = srcText // Include periods in matched text to prevent inelegant next line wrapping const regex = new RegExp( `\\b(${glossary.map((item) => item.term).join("|")})\\b\\.?`, "ig" ) const trimLastCharIfPeriod = (text: string) => { return text.replace(/\.$/, "") } const _getGlossaryLink = (match: string) => { const idx = glossary.findIndex( (item) => item.term.toLowerCase() === trimLastCharIfPeriod(match.toLowerCase()) ) if (idx === -1) return match const slug = glossary[idx].slug const excerpt = glossary[idx].excerpt // Remove element in-place so that glossary items are only matched and // linked once per recursive traversal (at the moment, this is set to // once per page section) glossary.splice(idx, 1) return ReactDOMServer.renderToStaticMarkup( <GlossaryLink slug={slug} excerpt={excerpt} match={match} /> ) } textWithGlossaryLinks = textWithGlossaryLinks.replace( regex, _getGlossaryLink ) return textWithGlossaryLinks } |