diff --git a/CHANGELOG.md b/CHANGELOG.md index de71bedc8..daade7ce2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - tiddlywiki - mediawiki - jsx +- Alternative anchor URL formats ### Added diff --git a/package.json b/package.json index 8f30ef3e9..026f4c0b8 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@testing-library/react": "10.4.3", "@testing-library/user-event": "12.0.11", "@types/codemirror": "0.0.96", + "@types/deep-equal": "1.0.1", "@types/highlight.js": "9.12.4", "@types/jest": "26.0.3", "@types/markdown-it": "10.0.1", @@ -28,6 +29,7 @@ "@typescript-eslint/parser": "3.4.0", "bootstrap": "4.5.0", "codemirror": "5.55.0", + "deep-equal": "2.0.3", "eslint-config-react-app": "5.2.1", "eslint-config-standard": "14.1.1", "eslint-plugin-flowtype": "5.1.3", @@ -56,8 +58,8 @@ "markdown-it-regex": "0.2.0", "markdown-it-sub": "1.0.0", "markdown-it-sup": "1.0.0", - "markdown-it-table-of-contents": "0.4.4", "markdown-it-task-lists": "2.1.1", + "markdown-it-toc-done-right": "4.1.0", "mathjax": "3.0.5", "moment": "2.27.0", "node-sass": "4.14.1", @@ -76,7 +78,8 @@ "react-scripts": "3.4.1", "redux": "4.0.5", "typescript": "3.9.5", - "use-media": "1.4.0" + "use-media": "1.4.0", + "use-resize-observer": "6.1.0" }, "scripts": { "start": "react-scripts start", diff --git a/src/components/common/splitter/splitter.tsx b/src/components/common/splitter/splitter.tsx index c125f4f3d..c9b45e2e2 100644 --- a/src/components/common/splitter/splitter.tsx +++ b/src/components/common/splitter/splitter.tsx @@ -54,7 +54,7 @@ export const Splitter: React.FC = ({ containerClassName, left, ri -
+
{right}
diff --git a/src/components/editor/editor.tsx b/src/components/editor/editor.tsx index 96ea19c2d..f5e9413cc 100644 --- a/src/components/editor/editor.tsx +++ b/src/components/editor/editor.tsx @@ -6,7 +6,7 @@ import { setEditorModeConfig } from '../../redux/editor/methods' import { Splitter } from '../common/splitter/splitter' import { InfoBanner } from '../landing/layout/info-banner' import { EditorWindow } from './editor-window/editor-window' -import { MarkdownRenderer } from './markdown-renderer/markdown-renderer' +import { MarkdownRenderWindow } from './renderer-window/markdown-render-window' import { EditorMode } from './task-bar/editor-view-mode' import { TaskBar } from './task-bar/task-bar' @@ -78,7 +78,7 @@ let a = 1 showLeft={editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH} left={ setMarkdownContent(content)} content={markdownContent}/>} showRight={editorMode === EditorMode.PREVIEW || (editorMode === EditorMode.BOTH)} - right={} + right={} containerClassName={'overflow-hidden'}/>
diff --git a/src/components/editor/markdown-renderer/markdown-renderer.scss b/src/components/editor/markdown-renderer/markdown-renderer.scss index cfe156eda..c76cf9a96 100644 --- a/src/components/editor/markdown-renderer/markdown-renderer.scss +++ b/src/components/editor/markdown-renderer/markdown-renderer.scss @@ -1,6 +1,7 @@ @import '../../../../node_modules/github-markdown-css/github-markdown.css'; .markdown-body { + position: relative; font-family: 'Source Sans Pro', "twemoji", sans-serif; .alert > p, .alert > ul { @@ -42,4 +43,5 @@ } } } + } diff --git a/src/components/editor/markdown-renderer/markdown-renderer.tsx b/src/components/editor/markdown-renderer/markdown-renderer.tsx index d8e77892f..149becc4b 100644 --- a/src/components/editor/markdown-renderer/markdown-renderer.tsx +++ b/src/components/editor/markdown-renderer/markdown-renderer.tsx @@ -1,3 +1,4 @@ +import equal from 'deep-equal' import { DomElement } from 'domhandler' import MarkdownIt from 'markdown-it' import abbreviation from 'markdown-it-abbr' @@ -13,11 +14,13 @@ import mathJax from 'markdown-it-mathjax' import markdownItRegex from 'markdown-it-regex' import subscript from 'markdown-it-sub' import superscript from 'markdown-it-sup' -import toc from 'markdown-it-table-of-contents' import taskList from 'markdown-it-task-lists' -import React, { ReactElement, useMemo } from 'react' +import toc from 'markdown-it-toc-done-right' +import React, { ReactElement, useEffect, useMemo, useState } from 'react' import ReactHtmlParser, { convertNodeToElement, Transform } from 'react-html-parser' import MathJaxReact from 'react-mathjax' +import { TocAst } from '../../../external-types/markdown-it-toc-done-right/interface' +import { slugify } from '../../../utils/slugify' import { createRenderContainer, validAlertLevels } from './container-plugins/alert' import { highlightedCode } from './markdown-it-plugins/highlighted-code' import { linkifyExtra } from './markdown-it-plugins/linkify-extra' @@ -38,87 +41,102 @@ import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link' import { ComponentReplacer, SubNodeConverter } from './replace-components/ComponentReplacer' import { GistReplacer } from './replace-components/gist/gist-replacer' import { HighlightedCodeReplacer } from './replace-components/highlighted-fence/highlighted-fence-replacer' -import { PossibleWiderReplacer } from './replace-components/possible-wider/possible-wider-replacer' import { ImageReplacer } from './replace-components/image/image-replacer' import { MathjaxReplacer } from './replace-components/mathjax/mathjax-replacer' import { PdfReplacer } from './replace-components/pdf/pdf-replacer' +import { PossibleWiderReplacer } from './replace-components/possible-wider/possible-wider-replacer' import { QuoteOptionsReplacer } from './replace-components/quote-options/quote-options-replacer' import { TocReplacer } from './replace-components/toc/toc-replacer' import { VimeoReplacer } from './replace-components/vimeo/vimeo-replacer' import { YoutubeReplacer } from './replace-components/youtube/youtube-replacer' -export interface MarkdownPreviewProps { +export interface MarkdownRendererProps { content: string wide?: boolean + className?: string + onTocChange?: (ast: TocAst) => void } -const createMarkdownIt = (): MarkdownIt => { - const md = new MarkdownIt('default', { - html: true, - breaks: true, - langPrefix: '', - typographer: true - }) - md.use(taskList) - md.use(emoji) - md.use(abbreviation) - md.use(definitionList) - md.use(subscript) - md.use(superscript) - md.use(inserted) - md.use(marked) - md.use(footnote) - md.use(imsize) - // noinspection CheckTagEmptyBody - md.use(anchor, { - permalink: true, - permalinkBefore: true, - permalinkClass: 'heading-anchor text-dark', - permalinkSymbol: '' - }) - md.use(toc, { - includeLevel: [1, 2, 3], - markerPattern: /^\[TOC]$/i - }) - md.use(mathJax({ - beforeMath: '', - afterMath: '', - beforeInlineMath: '', - afterInlineMath: '', - beforeDisplayMath: '', - afterDisplayMath: '' - })) - md.use(markdownItRegex, replaceLegacyYoutubeShortCode) - md.use(markdownItRegex, replaceLegacyVimeoShortCode) - md.use(markdownItRegex, replaceLegacyGistShortCode) - md.use(markdownItRegex, replaceLegacySlideshareShortCode) - md.use(markdownItRegex, replaceLegacySpeakerdeckShortCode) - md.use(markdownItRegex, replacePdfShortCode) - md.use(markdownItRegex, replaceYouTubeLink) - md.use(markdownItRegex, replaceVimeoLink) - md.use(markdownItRegex, replaceGistLink) - md.use(highlightedCode) - md.use(markdownItRegex, replaceQuoteExtraAuthor) - md.use(markdownItRegex, replaceQuoteExtraColor) - md.use(markdownItRegex, replaceQuoteExtraTime) - md.use(linkifyExtra) - md.use(MarkdownItParserDebugger) +export const MarkdownRenderer: React.FC = ({ content, className, onTocChange, wide }) => { + const [tocAst, setTocAst] = useState() + const [lastTocAst, setLastTocAst] = useState() - validAlertLevels.forEach(level => { - md.use(markdownItContainer, level, { render: createRenderContainer(level) }) - }) + const markdownIt = useMemo(() => { + const md = new MarkdownIt('default', { + html: true, + breaks: true, + langPrefix: '', + typographer: true + }) + md.use(taskList) + md.use(emoji) + md.use(abbreviation) + md.use(definitionList) + md.use(subscript) + md.use(superscript) + md.use(inserted) + md.use(marked) + md.use(footnote) + md.use(imsize) + // noinspection CheckTagEmptyBody + md.use(anchor, { + permalink: true, + permalinkBefore: true, + permalinkClass: 'heading-anchor text-dark', + permalinkSymbol: '' + }) + md.use(mathJax({ + beforeMath: '', + afterMath: '', + beforeInlineMath: '', + afterInlineMath: '', + beforeDisplayMath: '', + afterDisplayMath: '' + })) + md.use(markdownItRegex, replaceLegacyYoutubeShortCode) + md.use(markdownItRegex, replaceLegacyVimeoShortCode) + md.use(markdownItRegex, replaceLegacyGistShortCode) + md.use(markdownItRegex, replaceLegacySlideshareShortCode) + md.use(markdownItRegex, replaceLegacySpeakerdeckShortCode) + md.use(markdownItRegex, replacePdfShortCode) + md.use(markdownItRegex, replaceYouTubeLink) + md.use(markdownItRegex, replaceVimeoLink) + md.use(markdownItRegex, replaceGistLink) + md.use(highlightedCode) + md.use(markdownItRegex, replaceQuoteExtraAuthor) + md.use(markdownItRegex, replaceQuoteExtraColor) + md.use(markdownItRegex, replaceQuoteExtraTime) + md.use(toc, { + placeholder: '(\\[TOC\\]|\\[toc\\])', + listType: 'ul', + level: [1, 2, 3], + callback: (code: string, ast: TocAst): void => { + setTocAst(ast) + }, + slugify: slugify + }) + md.use(linkifyExtra) + md.use(MarkdownItParserDebugger) - return md -} + validAlertLevels.forEach(level => { + md.use(markdownItContainer, level, { render: createRenderContainer(level) }) + }) -const tryToReplaceNode = (node: DomElement, index: number, allReplacers: ComponentReplacer[], nodeConverter: SubNodeConverter) => { - return allReplacers - .map((componentReplacer) => componentReplacer.getReplacement(node, index, nodeConverter)) - .find((replacement) => !!replacement) -} + return md + }, []) -const MarkdownRenderer: React.FC = ({ content, wide }) => { - const markdownIt = useMemo(createMarkdownIt, []) + useEffect(() => { + if (onTocChange && tocAst && !equal(tocAst, lastTocAst)) { + onTocChange(tocAst) + setLastTocAst(tocAst) + } + }, [tocAst, onTocChange, lastTocAst]) + + const tryToReplaceNode = (node: DomElement, index: number, allReplacers: ComponentReplacer[], nodeConverter: SubNodeConverter) => { + return allReplacers + .map((componentReplacer) => componentReplacer.getReplacement(node, index, nodeConverter)) + .find((replacement) => !!replacement) + } const result: ReactElement[] = useMemo(() => { const allReplacers: ComponentReplacer[] = [ @@ -134,6 +152,7 @@ const MarkdownRenderer: React.FC = ({ content, wide }) => new MathjaxReplacer() ] const html: string = markdownIt.render(content) + const transform: Transform = (node, index) => { const subNodeConverter = (subNode: DomElement, subIndex: number) => convertNodeToElement(subNode, subIndex, transform) return tryToReplaceNode(node, index, allReplacers, subNodeConverter) || convertNodeToElement(node, index, transform) @@ -142,14 +161,10 @@ const MarkdownRenderer: React.FC = ({ content, wide }) => }, [content, markdownIt]) return ( -
-
- - {result} - -
+
+ + {result} +
) } - -export { MarkdownRenderer } diff --git a/src/components/editor/markdown-toc/markdown-toc.scss b/src/components/editor/markdown-toc/markdown-toc.scss new file mode 100644 index 000000000..b8f023f32 --- /dev/null +++ b/src/components/editor/markdown-toc/markdown-toc.scss @@ -0,0 +1,67 @@ +.markdown-toc { + width: 100%; + max-width: 200px; + overflow-y: auto; + overflow-x: hidden; + &.sticky { + position: sticky; + top: 0; + left: 0; + } + + >ul>li { + >a { + padding: 4px 20px; + } + >ul>li { + > a { + padding: 1px 0 1px 30px; + } + >ul>li { + > a { + padding: 1px 0 1px 38px; + } + } + } + } + + + ul { + padding: 0; + margin: 0; + list-style: none; + font-size: 0.9em; + + a { + color: #767676; + overflow: hidden; + text-overflow: ellipsis; + white-space: pre; + display: block; + } + + + li.active { + a { + margin-top: 2px; + margin-bottom: 2px; + color: #000000; + font-weight: bold; + } + } + } +} +.markdown-toc-sidebar-button { + position: absolute; + height: 100%; + right: 20px; + display: flex; + justify-content: flex-end; + flex-direction: column; + + &>.dropup { + position: sticky; + bottom: 20px; + right: 0px; + } +} diff --git a/src/components/editor/markdown-toc/markdown-toc.tsx b/src/components/editor/markdown-toc/markdown-toc.tsx new file mode 100644 index 000000000..e3fc7b45a --- /dev/null +++ b/src/components/editor/markdown-toc/markdown-toc.tsx @@ -0,0 +1,59 @@ +import React, { Fragment, ReactElement, useMemo } from 'react' +import { TocAst } from '../../../external-types/markdown-it-toc-done-right/interface' +import { slugify } from '../../../utils/slugify' +import { ShowIf } from '../../common/show-if/show-if' +import './markdown-toc.scss' + +export interface MarkdownTocProps { + ast: TocAst + maxDepth?: number + sticky?: boolean +} + +const convertLevel = (toc: TocAst, levelsToShowUnderThis: number, headerCounts: Map, wrapInListItem: boolean): ReactElement | null => { + if (levelsToShowUnderThis < 0) { + return null + } + + const rawName = toc.n.trim() + const nameCount = (headerCounts.get(rawName) ?? 0) + 1 + const slug = `#${slugify(rawName)}${nameCount > 1 ? `-${nameCount}` : ''}` + + headerCounts.set(rawName, nameCount) + + const content = ( + + 0}> + {rawName} + + 0}> +
    + { + toc.c.map(child => + (convertLevel(child, levelsToShowUnderThis - 1, headerCounts, true))) + } +
+
+
+ ) + + if (wrapInListItem) { + return ( +
  • + {content} +
  • + ) + } else { + return content + } +} + +export const MarkdownToc: React.FC = ({ ast, maxDepth = 3, sticky }) => { + const tocTree = useMemo(() => convertLevel(ast, maxDepth, new Map(), false), [ast, maxDepth]) + + return ( +
    + {tocTree} +
    + ) +} diff --git a/src/components/editor/renderer-window/markdown-render-window.tsx b/src/components/editor/renderer-window/markdown-render-window.tsx new file mode 100644 index 000000000..44caeea87 --- /dev/null +++ b/src/components/editor/renderer-window/markdown-render-window.tsx @@ -0,0 +1,52 @@ +import React, { useRef, useState } from 'react' +import { Dropdown } from 'react-bootstrap' +import useResizeObserver from 'use-resize-observer' +import { TocAst } from '../../../external-types/markdown-it-toc-done-right/interface' +import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' +import { ShowIf } from '../../common/show-if/show-if' +import { MarkdownRenderer } from '../markdown-renderer/markdown-renderer' +import { MarkdownToc } from '../markdown-toc/markdown-toc' + +interface RenderWindowProps { + content: string + wide?: boolean +} + +export const MarkdownRenderWindow: React.FC = ({ content, wide }) => { + const [tocAst, setTocAst] = useState() + const renderer = useRef(null) + const { width } = useResizeObserver({ ref: renderer }) + + const realWidth = width || 0 + + return ( +
    +
    + setTocAst(tocAst)}/> + +
    + = 1280 && !!tocAst}> + + + +
    + + + + + +
    + +
    +
    +
    +
    +
    +
    +
    + ) +} diff --git a/src/components/landing/pages/history/common/entry-menu.scss b/src/components/landing/pages/history/common/entry-menu.scss index e75fa3df8..d48993a19 100644 --- a/src/components/landing/pages/history/common/entry-menu.scss +++ b/src/components/landing/pages/history/common/entry-menu.scss @@ -13,6 +13,9 @@ } } -.dropdown-toggle.no-arrow::after { - content: initial; +.dropup .dropdown-toggle, .dropdown-toggle { + &.no-arrow::after { + content: initial; + } } + diff --git a/src/external-types/markdown-it-table-of-contents/index.d.ts b/src/external-types/markdown-it-table-of-contents/index.d.ts deleted file mode 100644 index 2c708fceb..000000000 --- a/src/external-types/markdown-it-table-of-contents/index.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module 'markdown-it-table-of-contents' { - import MarkdownIt from 'markdown-it/lib' - import { TOCOptions } from './interface' - const markdownItTableOfContents: MarkdownIt.PluginWithOptions - export = markdownItTableOfContents -} diff --git a/src/external-types/markdown-it-table-of-contents/interface.ts b/src/external-types/markdown-it-table-of-contents/interface.ts deleted file mode 100644 index 9f470233b..000000000 --- a/src/external-types/markdown-it-table-of-contents/interface.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface TOCOptions { - includeLevel: number[] - containerClass: string - slugify: (s: string) => string - markerPattern: RegExp - listType: 'ul' | 'ol' - format: (headingAsString: string) => string - forceFullToc: boolean - containerHeaderHtml: string - containerFooterHtml: string - transformLink: (link: string) => string -} diff --git a/src/external-types/markdown-it-toc-done-right/index.d.ts b/src/external-types/markdown-it-toc-done-right/index.d.ts new file mode 100644 index 000000000..899253043 --- /dev/null +++ b/src/external-types/markdown-it-toc-done-right/index.d.ts @@ -0,0 +1,6 @@ +declare module 'markdown-it-toc-done-right' { + import MarkdownIt from 'markdown-it/lib' + import { TocOptions } from './interface' + const markdownItTocDoneRight: MarkdownIt.PluginWithOptions + export = markdownItTocDoneRight + } diff --git a/src/external-types/markdown-it-toc-done-right/interface.ts b/src/external-types/markdown-it-toc-done-right/interface.ts new file mode 100644 index 000000000..6491e116d --- /dev/null +++ b/src/external-types/markdown-it-toc-done-right/interface.ts @@ -0,0 +1,19 @@ +export interface TocOptions { + placeholder: string + slugify: (s: string) => string + containerClass: string + containerId: string + listClass: string + itemClass: string + linkClass: string + level: number | number[] + listType: 'ol' | 'ul' + format: (s: string) => string + callback: (tocCode: string, ast: TocAst) => void +} + +export interface TocAst { + l: number + n: string + c: TocAst[] +} diff --git a/src/global-style/index.scss b/src/global-style/index.scss index 7d84cbc5e..2d3824a3e 100644 --- a/src/global-style/index.scss +++ b/src/global-style/index.scss @@ -36,3 +36,7 @@ body { .overflow-y-scroll { overflow-y: scroll; } + +.min-h-100 { + min-height: 100%; +} diff --git a/src/utils/slugify.ts b/src/utils/slugify.ts new file mode 100644 index 000000000..b634568bf --- /dev/null +++ b/src/utils/slugify.ts @@ -0,0 +1,3 @@ +export const slugify = (url:string) => { + return encodeURIComponent(String(url).trim().toLowerCase().replace(/\s+/g, '-')) +} diff --git a/yarn.lock b/yarn.lock index 596c5a204..a1049e345 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1486,6 +1486,11 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/deep-equal@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03" + integrity sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg== + "@types/domhandler@*": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/domhandler/-/domhandler-2.4.1.tgz#7b3b347f7762180fbcb1ece1ce3dd0ebbb8c64cf" @@ -2303,6 +2308,11 @@ array-equal@^1.0.0: resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= +array-filter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" + integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= + array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" @@ -2458,6 +2468,13 @@ autoprefixer@^9.6.1: postcss "^7.0.27" postcss-value-parser "^4.0.3" +available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" + integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== + dependencies: + array-filter "^1.0.0" + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -3915,6 +3932,26 @@ deep-equal@^1.0.1, deep-equal@^1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" +deep-equal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.3.tgz#cad1c15277ad78a5c01c49c2dee0f54de8a6a7b0" + integrity sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA== + dependencies: + es-abstract "^1.17.5" + es-get-iterator "^1.1.0" + is-arguments "^1.0.4" + is-date-object "^1.0.2" + is-regex "^1.0.5" + isarray "^2.0.5" + object-is "^1.1.2" + object-keys "^1.1.1" + object.assign "^4.1.0" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.2" + which-boxed-primitive "^1.0.1" + which-collection "^1.0.1" + which-typed-array "^1.1.2" + deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -4321,6 +4358,36 @@ es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstrac string.prototype.trimleft "^2.1.1" string.prototype.trimright "^2.1.1" +es-abstract@^1.17.4: + version "1.17.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" + integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.0" + is-regex "^1.1.0" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-get-iterator@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.0.tgz#bb98ad9d6d63b31aacdc8f89d5d0ee57bcb5b4c8" + integrity sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ== + dependencies: + es-abstract "^1.17.4" + has-symbols "^1.0.1" + is-arguments "^1.0.4" + is-map "^2.0.1" + is-set "^2.0.1" + is-string "^1.0.5" + isarray "^2.0.5" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -5077,6 +5144,11 @@ for-own@^0.1.3: dependencies: for-in "^1.0.1" +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -6013,6 +6085,11 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== +is-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.0.tgz#73da8c33208d00f130e9b5e15d23eac9215601c4" + integrity sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g== + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -6027,6 +6104,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-boolean-object@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e" + integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ== + is-buffer@^1.0.2, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -6037,6 +6119,11 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" + integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -6070,7 +6157,7 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" -is-date-object@^1.0.1: +is-date-object@^1.0.1, is-date-object@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== @@ -6161,6 +6248,16 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1" + integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw== + +is-number-object@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" + integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -6221,6 +6318,13 @@ is-regex@^1.0.4, is-regex@^1.0.5: dependencies: has "^1.0.3" +is-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" + integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== + dependencies: + has-symbols "^1.0.1" + is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" @@ -6236,12 +6340,17 @@ is-root@2.1.0: resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== +is-set@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43" + integrity sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA== + is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= -is-string@^1.0.5: +is-string@^1.0.4, is-string@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== @@ -6260,6 +6369,16 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" +is-typed-array@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.3.tgz#a4ff5a5e672e1a55f99c7f54e59597af5c1df04d" + integrity sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ== + dependencies: + available-typed-arrays "^1.0.0" + es-abstract "^1.17.4" + foreach "^2.0.5" + has-symbols "^1.0.1" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -6270,6 +6389,16 @@ is-utf8@^0.2.0: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= +is-weakmap@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" + integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== + +is-weakset@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.1.tgz#e9a0af88dbd751589f5e50d80f4c98b780884f83" + integrity sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw== + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -6297,6 +6426,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -7380,16 +7514,16 @@ markdown-it-sup@1.0.0: resolved "https://registry.yarnpkg.com/markdown-it-sup/-/markdown-it-sup-1.0.0.tgz#cb9c9ff91a5255ac08f3fd3d63286e15df0a1fc3" integrity sha1-y5yf+RpSVawI8/09YyhuFd8KH8M= -markdown-it-table-of-contents@0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz#3dc7ce8b8fc17e5981c77cc398d1782319f37fbc" - integrity sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw== - markdown-it-task-lists@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz#f68f4d2ac2bad5a2c373ba93081a1a6848417088" integrity sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA== +markdown-it-toc-done-right@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/markdown-it-toc-done-right/-/markdown-it-toc-done-right-4.1.0.tgz#0f73ed531dda427c43c27716a2fc2208daa90605" + integrity sha512-UhD2Oj6cZV3ycYPoelt4hTkwKIK3zbPP1wjjdpCq7UGtWQOFalDFDv1s2zBYV6aR2gMs/X8kpJcOYsQmUbiXDw== + markdown-it@11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-11.0.0.tgz#dbfc30363e43d756ebc52c38586b91b90046b876" @@ -8004,7 +8138,7 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-is@^1.0.1: +object-is@^1.0.1, object-is@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== @@ -10135,6 +10269,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +resize-observer-polyfill@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -10955,7 +11094,7 @@ string.prototype.matchall@^4.0.2: regexp.prototype.flags "^1.3.0" side-channel "^1.0.2" -string.prototype.trimend@^1.0.0: +string.prototype.trimend@^1.0.0, string.prototype.trimend@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== @@ -10981,7 +11120,7 @@ string.prototype.trimright@^2.1.1: es-abstract "^1.17.5" string.prototype.trimend "^1.0.0" -string.prototype.trimstart@^1.0.0: +string.prototype.trimstart@^1.0.0, string.prototype.trimstart@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== @@ -11611,6 +11750,13 @@ use-media@1.4.0: resolved "https://registry.yarnpkg.com/use-media/-/use-media-1.4.0.tgz#e777bf1f382a7aacabbd1f9ce3da2b62e58b2a98" integrity sha512-XsgyUAf3nhzZmEfhc5MqLHwyaPjs78bgytpVJ/xDl0TF4Bptf3vEpBNBBT/EIKOmsOc8UbuECq3mrP3mt1QANA== +use-resize-observer@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/use-resize-observer/-/use-resize-observer-6.1.0.tgz#d4d267a940dbf9c326da6042f8a4bb8c89d29729" + integrity sha512-SiPcWHiIQ1CnHmb6PxbYtygqiZXR0U9dNkkbpX9VYnlstUwF8+QqpUTrzh13pjPwcjMVGR+QIC+nvF5ujfFNng== + dependencies: + resize-observer-polyfill "^1.5.1" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -11920,11 +12066,44 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" +which-boxed-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz#cbe8f838ebe91ba2471bb69e9edbda67ab5a5ec1" + integrity sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ== + dependencies: + is-bigint "^1.0.0" + is-boolean-object "^1.0.0" + is-number-object "^1.0.3" + is-string "^1.0.4" + is-symbol "^1.0.2" + +which-collection@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" + integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== + dependencies: + is-map "^2.0.1" + is-set "^2.0.1" + is-weakmap "^2.0.1" + is-weakset "^2.0.1" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-typed-array@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2" + integrity sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ== + dependencies: + available-typed-arrays "^1.0.2" + es-abstract "^1.17.5" + foreach "^2.0.5" + function-bind "^1.1.1" + has-symbols "^1.0.1" + is-typed-array "^1.1.3" + which@1, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"