diff --git a/packages/docusaurus-mdx-loader/package.json b/packages/docusaurus-mdx-loader/package.json index 0d1ee6bd2193..96d6e15ea9c8 100644 --- a/packages/docusaurus-mdx-loader/package.json +++ b/packages/docusaurus-mdx-loader/package.json @@ -6,6 +6,9 @@ "publishConfig": { "access": "public" }, + "scripts": { + "build": "tsc" + }, "license": "MIT", "dependencies": { "@babel/parser": "^7.9.4", @@ -27,6 +30,7 @@ "url-loader": "^4.1.0" }, "devDependencies": { + "@docusaurus/types": "^2.0.0-alpha.61", "remark": "^12.0.0", "remark-mdx": "^1.5.8", "to-vfile": "^6.0.0", diff --git a/packages/docusaurus-mdx-loader/src/remark/rightToc/search.js b/packages/docusaurus-mdx-loader/src/remark/rightToc/search.js index 5c89b314a269..516dc44d92d6 100644 --- a/packages/docusaurus-mdx-loader/src/remark/rightToc/search.js +++ b/packages/docusaurus-mdx-loader/src/remark/rightToc/search.js @@ -5,11 +5,29 @@ * LICENSE file in the root directory of this source tree. */ +// @ts-check + const toString = require('mdast-util-to-string'); const visit = require('unist-util-visit'); const escapeHtml = require('escape-html'); +/** @typedef {import('@docusaurus/types').MarkdownRightTableOfContents} TOC */ +/** @typedef {import('unist').Node} Node */ + +/** + * @typedef {Object} StringValuedNode + * @property {string} type + * @property {string} value + * @property {number} depth + * @property {Object} data + * @property {StringValuedNode[]} children + */ + // https://github.com/syntax-tree/mdast#heading +/** + * @param {StringValuedNode | undefined} node + * @returns {string} + */ function toValue(node) { if (node && node.type) { switch (node.type) { @@ -34,11 +52,22 @@ function toValue(node) { // Visit all headings. We `slug` all headings (to account for // duplicates), but only take h2 and h3 headings. +/** + * @param {StringValuedNode} node + * @returns {TOC[]} + */ function search(node) { + /** @type {TOC[]} */ const headings = []; let current = -1; let currentDepth = 0; + /** + * @param {StringValuedNode} child + * @param {number} index + * @param {Node | undefined} parent + * @returns {void} + */ const onHeading = (child, index, parent) => { const value = toString(child); diff --git a/packages/docusaurus-mdx-loader/tsconfig.json b/packages/docusaurus-mdx-loader/tsconfig.json new file mode 100644 index 000000000000..460667f655b5 --- /dev/null +++ b/packages/docusaurus-mdx-loader/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "allowJs": true, + "noEmit": true, + "noImplicitAny": false + }, + "include": ["src/"] +} diff --git a/packages/docusaurus-plugin-content-blog/index.d.ts b/packages/docusaurus-plugin-content-blog/index.d.ts index 433c3d39bb4d..23174ea608c5 100644 --- a/packages/docusaurus-plugin-content-blog/index.d.ts +++ b/packages/docusaurus-plugin-content-blog/index.d.ts @@ -8,6 +8,8 @@ /* eslint-disable camelcase */ declare module '@theme/BlogPostPage' { + import type {MarkdownRightTableOfContents} from '@docusaurus/types'; + export type FrontMatter = { readonly title: string; readonly author?: string; @@ -42,7 +44,7 @@ declare module '@theme/BlogPostPage' { export type Content = { readonly frontMatter: FrontMatter; readonly metadata: Metadata; - readonly rightToc: any; // TODO where to define this shared type? + readonly rightToc: MarkdownRightTableOfContents; (): JSX.Element; }; diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index 60806b30e28a..e6fee495d9e7 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -28,6 +28,7 @@ "react-router-dom": "^5.1.2", "react-toggle": "^4.1.1", "use-onclickoutside": "^0.3.1", + "@docusaurus/types": "^2.0.0-alpha.61", "@docusaurus/utils-validation": "^2.0.0-alpha.61" }, "devDependencies": { diff --git a/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx b/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx index a6861e10d23e..ce1483d1fd42 100644 --- a/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx @@ -8,14 +8,17 @@ import React from 'react'; import useTOCHighlight from '@theme/hooks/useTOCHighlight'; +import type {MarkdownRightTableOfContents} from '@docusaurus/types'; import styles from './styles.module.css'; const LINK_CLASS_NAME = 'table-of-contents__link'; const ACTIVE_LINK_CLASS_NAME = 'table-of-contents__link--active'; const TOP_OFFSET = 100; +type TOCProps = {readonly headings: MarkdownRightTableOfContents[]}; + /* eslint-disable jsx-a11y/control-has-associated-label */ -function Headings({headings, isChild}: {headings; isChild?: boolean}) { +function Headings({headings, isChild}: TOCProps & {isChild?: boolean}) { if (!headings.length) { return null; } @@ -40,7 +43,7 @@ function Headings({headings, isChild}: {headings; isChild?: boolean}) { ); } -function TOC({headings}) { +function TOC({headings}: TOCProps): JSX.Element { useTOCHighlight(LINK_CLASS_NAME, ACTIVE_LINK_CLASS_NAME, TOP_OFFSET); return (
diff --git a/packages/docusaurus-types/src/index.d.ts b/packages/docusaurus-types/src/index.d.ts index d2b0bf4c6192..7c93cbc25be0 100644 --- a/packages/docusaurus-types/src/index.d.ts +++ b/packages/docusaurus-types/src/index.d.ts @@ -270,3 +270,9 @@ export interface ValidationSchema { unknown(): ValidationSchema; append(data: any): ValidationSchema; } + +export interface MarkdownRightTableOfContents { + readonly value: string; + readonly id: string; + readonly children: MarkdownRightTableOfContents[]; +}