diff --git a/package.json b/package.json index 2b3cb48..ed967d2 100644 --- a/package.json +++ b/package.json @@ -15,32 +15,38 @@ "Titus Wormer (https://wooorm.com)", "Jonathan Haines (https://barrythepenguin.github.io)" ], + "types": "types/index.d.ts", "files": [ + "types/index.d.ts", "lib", "index.js" ], "dependencies": { + "@types/mdast": "^3.0.3", + "@types/unist": "^2.0.3", "extend": "^3.0.2", "github-slugger": "^1.2.1", "mdast-util-to-string": "^1.0.5", - "unist-util-is": "^3.0.0", - "unist-util-visit": "^1.1.0" + "unist-util-is": "^4.0.0", + "unist-util-visit": "^2.0.0" }, "devDependencies": { "browserify": "^16.2.3", + "dtslint": "^1.0.2", "nyc": "^14.0.0", "prettier": "^1.15.2", - "remark": "^10.0.0", - "remark-attr": "^0.8.0", - "remark-cli": "^6.0.0", - "remark-parse": "^6.0.3", - "remark-preset-wooorm": "^5.0.0", - "remark-usage": "^6.1.3", + "remark": "^11.0.1", + "remark-attr": "^0.9.0", + "remark-cli": "^7.0.0", + "remark-parse": "^7.0.1", + "remark-preset-wooorm": "^6.0.1", + "remark-usage": "^7.0.1", "tape": "^4.10.1", "tinyify": "^2.5.0", + "typescript": "^3.0.0", "unified": "^8.0.0", - "unist-builder": "^1.0.3", - "xo": "^0.24.0" + "unist-builder": "^2.0.1", + "xo": "^0.25.3" }, "scripts": { "format": "remark . -qfo && prettier --write \"**/*.js\" && xo --fix", @@ -49,7 +55,8 @@ "build": "npm run build-bundle && npm run build-mangle", "test-api": "node test", "test-coverage": "nyc --reporter lcov tape test/index.js", - "test": "npm run format && npm run build && npm run test-coverage" + "test-types": "dtslint types", + "test": "npm run format && npm run build && npm run test-coverage && npm run test-types" }, "nyc": { "check-coverage": true, diff --git a/readme.md b/readme.md index 0312fc8..2dce655 100644 --- a/readme.md +++ b/readme.md @@ -36,30 +36,21 @@ var tree = u('root', [ u('heading', {depth: 3}, [u('text', 'Charlie')]), u('heading', {depth: 2}, [u('text', 'Delta')]) ]) + var table = toc(tree) ``` Yields: ```javascript - -{ - index: null, +{ index: null, endIndex: null, - map: { - type: 'list', - ordered: false, - spread: true, - children: [ - { - type: 'listItem', - loose: true, - spread: true, - children: [Array] - } - ] - } -} + map: + { type: 'list', + ordered: false, + spread: true, + children: + [ { type: 'listItem', loose: true, spread: true, children: [Array] } ] } } ``` ## API diff --git a/test/index.js b/test/index.js index 8f9a74f..4f970da 100644 --- a/test/index.js +++ b/test/index.js @@ -40,7 +40,7 @@ test('Fixtures', function(t) { try { config = JSON.parse(fs.readFileSync(join(root, name, 'config.json'))) - } catch (error) {} + } catch (_) {} processor.use(remarkParse, config.remarkParseOptions) diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..7aaf683 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,77 @@ +// TypeScript Version: 3.0 + +import {Node} from 'unist' +import {Parent, Heading, Link, Paragraph, List, ListItem} from 'mdast' +import {Test} from 'unist-util-is' + +declare namespace mdastUtilToc { + interface TOCOptions { + /** + * Heading to look for, wrapped in `new RegExp('^(' + value + ')$', 'i')`. + */ + heading?: string + + /** + * Maximum heading depth to include in the table of contents, + * This is inclusive: when set to `3`, + * level three headings are included (those with three hashes, `###`). + * + * @default 6 + */ + maxDepth?: Heading['depth'] + + /** + * Headings to skip, wrapped in `new RegExp('^(' + value + ')$', 'i')`. + * Any heading matching this expression will not be present in the table of contents. + */ + skip?: string + + /** + * Whether to compile list-items tightly. + * + * @default false + */ + tight?: boolean + + /** + * Add a prefix to links to headings in the table of contents. + * Useful for example when later going from mdast to hast and sanitizing with `hast-util-sanitize`. + * + * @default null + */ + prefix?: string + + /** + * Allows headings to be children of certain node types + * Internally, uses `unist-util-is` to check, so `parents` can be any `is`-compatible test. + * + * For example, this would allow headings under either `root` or `blockquote` to be used: + * + * ```ts + * toc(tree, {parents: ['root', 'blockquote']}) + * ``` + * + * @default the to `toc` given `tree`, to only allow top-level headings + */ + parents?: Test | Array> + } + + interface TOCResult { + index: number | null + endIndex: number | null + map: List | null + } +} + +/** + * Generate a Table of Contents from a tree. + * + * @param node searched for headings + * @param options configuration and settings + */ +declare function mdastUtilToc( + node: Node, + options?: mdastUtilToc.TOCOptions +): mdastUtilToc.TOCResult + +export = mdastUtilToc diff --git a/types/mdast-util-toc-tests.ts b/types/mdast-util-toc-tests.ts new file mode 100644 index 0000000..98ac3b9 --- /dev/null +++ b/types/mdast-util-toc-tests.ts @@ -0,0 +1,64 @@ +import {Link, Paragraph, List, ListItem} from 'mdast' + +import unified = require('unified') +import u = require('unist-builder') +import is = require('unist-util-is') +import toc = require('mdast-util-toc') + +const tree = u('root', [ + u('heading', {depth: 1}, [u('text', 'Alpha')]), + u('heading', {depth: 2}, [u('text', 'Bravo')]), + u('heading', {depth: 3}, [u('text', 'Charlie')]), + u('heading', {depth: 2}, [u('text', 'Delta')]) +]) + +const {map} = toc(tree) + +if (is(map, 'list')) { + const [firstListItem] = map.children + + if (is(firstListItem, 'listItem')) { + const [firstParagraph] = firstListItem.children + + if (is(firstParagraph, 'paragraph')) { + const [firstLink] = firstParagraph.children + + is(firstLink, 'link') + } + } +} + +toc(tree, { + heading: 'Table Of Contents' +}) + +toc(tree, { + maxDepth: 2 +}) + +toc(tree, { + skip: 'skip heading' +}) + +toc(tree, { + tight: true +}) + +toc(tree, { + prefix: '/prefix' +}) + +toc(tree, { + parents: ['root', 'blockquote'] +}) + +/*=== usable in unified transform ===*/ +unified().use(() => tree => { + const table = toc(tree) + + if (is(table.map, 'list')) { + // do something + } + + return tree +}) diff --git a/types/tsconfig.json b/types/tsconfig.json new file mode 100644 index 0000000..680123a --- /dev/null +++ b/types/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "lib": ["es2015"], + "strict": true, + "baseUrl": ".", + "paths": { + "mdast-util-toc": ["index.d.ts"] + } + } +} diff --git a/types/tslint.json b/types/tslint.json new file mode 100644 index 0000000..874122f --- /dev/null +++ b/types/tslint.json @@ -0,0 +1,10 @@ +{ + "extends": "dtslint/dtslint.json", + "rules": { + "no-redundant-jsdoc": false, + "semicolon": false, + "unified-signatures": true, + "whitespace": false, + "strict-export-declare-modifiers": false + } +}