From bc55caa4cc9fc6ae317c3e79a6f7269035cdc3c8 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 3 Aug 2021 12:53:17 +0200 Subject: [PATCH] Add JSDoc based types --- .gitignore | 10 ++- package.json | 21 +++-- packages/remark-cli/cli.js | 1 + packages/remark-cli/package.json | 9 +- packages/remark-cli/test.js | 6 +- packages/remark-cli/tsconfig.json | 4 + packages/remark-parse/index.d.ts | 7 ++ packages/remark-parse/index.js | 17 +--- packages/remark-parse/lib/index.js | 28 ++++++ packages/remark-parse/package.json | 18 +++- packages/remark-parse/tsconfig.json | 4 + packages/remark-parse/types/index.d.ts | 14 --- packages/remark-parse/types/test.ts | 7 -- packages/remark-parse/types/tsconfig.json | 10 --- packages/remark-parse/types/tslint.json | 14 --- packages/remark-stringify/index.d.ts | 7 ++ packages/remark-stringify/index.js | 16 +--- packages/remark-stringify/lib/index.js | 27 ++++++ packages/remark-stringify/package.json | 18 +++- packages/remark-stringify/test.js | 86 +++++++++++-------- packages/remark-stringify/tsconfig.json | 4 + packages/remark-stringify/types/index.d.ts | 14 --- packages/remark-stringify/types/test.ts | 37 -------- packages/remark-stringify/types/tsconfig.json | 10 --- packages/remark-stringify/types/tslint.json | 14 --- packages/remark/package.json | 13 ++- packages/remark/tsconfig.json | 4 + packages/remark/types/index.d.ts | 19 ---- packages/remark/types/test.ts | 21 ----- packages/remark/types/tsconfig.json | 10 --- packages/remark/types/tslint.json | 15 ---- script/regenerate-fixtures.js | 4 + test/fixtures/index.js | 38 ++++++-- tsconfig.json | 17 ++++ 34 files changed, 267 insertions(+), 277 deletions(-) create mode 100644 packages/remark-cli/tsconfig.json create mode 100644 packages/remark-parse/index.d.ts create mode 100644 packages/remark-parse/lib/index.js create mode 100644 packages/remark-parse/tsconfig.json delete mode 100644 packages/remark-parse/types/index.d.ts delete mode 100644 packages/remark-parse/types/test.ts delete mode 100644 packages/remark-parse/types/tsconfig.json delete mode 100644 packages/remark-parse/types/tslint.json create mode 100644 packages/remark-stringify/index.d.ts create mode 100644 packages/remark-stringify/lib/index.js create mode 100644 packages/remark-stringify/tsconfig.json delete mode 100644 packages/remark-stringify/types/index.d.ts delete mode 100644 packages/remark-stringify/types/test.ts delete mode 100644 packages/remark-stringify/types/tsconfig.json delete mode 100644 packages/remark-stringify/types/tslint.json create mode 100644 packages/remark/tsconfig.json delete mode 100644 packages/remark/types/index.d.ts delete mode 100644 packages/remark/types/test.ts delete mode 100644 packages/remark/types/tsconfig.json delete mode 100644 packages/remark/types/tslint.json create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 4fb0e3226..98cb31e5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,13 @@ -node_modules/ coverage/ +node_modules/ +packages/remark/*.d.ts +packages/remark-cli/*.d.ts +packages/remark-parse/lib/*.d.ts +packages/remark-parse/test.d.ts +packages/remark-stringify/lib/*.d.ts +packages/remark-stringify/test.d.ts +script/**/*.d.ts +test/**/*.d.ts .DS_Store *.log yarn.lock diff --git a/package.json b/package.json index 9b7232f43..58e5f006f 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,10 @@ }, "type": "module", "devDependencies": { + "@types/mdast": "^3.0.0", + "@types/tape": "^4.0.0", "c8": "^7.0.0", "camelcase": "^6.0.0", - "dtslint": "^4.0.0", "execa": "^5.0.0", "lerna": "^4.0.0", "mdast-util-assert": "^4.0.0", @@ -21,7 +22,9 @@ "micromark-extension-gfm": "^1.0.0", "prettier": "^2.0.0", "remark-preset-wooorm": "^8.0.0", + "rimraf": "^3.0.0", "tape": "^5.0.0", + "type-coverage": "^2.0.0", "typescript": "^4.0.0", "unified": "^10.0.0", "unist-util-remove-position": "^4.0.0", @@ -29,10 +32,11 @@ }, "scripts": { "postinstall": "lerna bootstrap --no-ci", + "build": "lerna run build && rimraf \"*.d.ts\" \"{test,script}/**/*.d.ts\" && tsc && type-coverage", "format": "./packages/remark-cli/cli.js . -qfo && prettier . -w --loglevel warn && xo --fix", - "test-api": "node --conditions development test/index.js && lerna run test", + "test-api": "lerna run test && node --conditions development test/index.js", "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov npm run test-api", - "test": "npm run format && npm run test-coverage" + "test": "npm run build && npm run format && npm run test-coverage" }, "prettier": { "tabWidth": 2, @@ -43,14 +47,17 @@ "trailingComma": "none" }, "xo": { - "prettier": true, - "ignores": [ - "**/types" - ] + "prettier": true }, "remarkConfig": { "plugins": [ "preset-wooorm" ] + }, + "typeCoverage": { + "atLeast": 100, + "detail": true, + "strict": true, + "ignoreCatch": true } } diff --git a/packages/remark-cli/cli.js b/packages/remark-cli/cli.js index c11907e0d..f8c618999 100755 --- a/packages/remark-cli/cli.js +++ b/packages/remark-cli/cli.js @@ -21,6 +21,7 @@ const extensions = [ ] args({ + // @ts-expect-error: fine. processor: remark, name: proc.name, description: cli.description, diff --git a/packages/remark-cli/package.json b/packages/remark-cli/package.json index 7558dde93..80b1b2545 100644 --- a/packages/remark-cli/package.json +++ b/packages/remark-cli/package.json @@ -35,7 +35,14 @@ "unified-args": "^9.0.0" }, "scripts": { + "build": "rimraf \"*.d.ts\" && tsc && type-coverage", "test": "node --conditions development test.js" }, - "xo": false + "xo": false, + "typeCoverage": { + "atLeast": 100, + "detail": true, + "strict": true, + "ignoreCatch": true + } } diff --git a/packages/remark-cli/test.js b/packages/remark-cli/test.js index a11a8ac99..c741fdd44 100644 --- a/packages/remark-cli/test.js +++ b/packages/remark-cli/test.js @@ -1,4 +1,4 @@ -import url from 'url' +import {URL, fileURLToPath} from 'url' import execa from 'execa' import test from 'tape' @@ -6,7 +6,7 @@ test('remark-cli', (t) => { t.plan(2) t.test('should show help on `--help`', (t) => { - const bin = url.fileURLToPath(new URL('./cli.js', import.meta.url)) + const bin = fileURLToPath(new URL('./cli.js', import.meta.url)) t.plan(1) @@ -63,7 +63,7 @@ test('remark-cli', (t) => { }) t.test('should show version on `--version`', (t) => { - const bin = url.fileURLToPath(new URL('./cli.js', import.meta.url)) + const bin = fileURLToPath(new URL('./cli.js', import.meta.url)) t.plan(2) diff --git a/packages/remark-cli/tsconfig.json b/packages/remark-cli/tsconfig.json new file mode 100644 index 000000000..7e61871a6 --- /dev/null +++ b/packages/remark-cli/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["*.js"] +} diff --git a/packages/remark-parse/index.d.ts b/packages/remark-parse/index.d.ts new file mode 100644 index 000000000..3e449d65a --- /dev/null +++ b/packages/remark-parse/index.d.ts @@ -0,0 +1,7 @@ +// This wrapper exists because JS in TS can’t export a `@type` of a function. +import type {Options} from './lib/index.js' +import type {Root} from 'mdast' +import type {Plugin} from 'unified' +declare const remarkParse: Plugin<[Options?] | void[], string, Root> +export default remarkParse +export type {Options} diff --git a/packages/remark-parse/index.js b/packages/remark-parse/index.js index 6176fedb4..0dc496d5e 100644 --- a/packages/remark-parse/index.js +++ b/packages/remark-parse/index.js @@ -1,16 +1,3 @@ -import {fromMarkdown} from 'mdast-util-from-markdown' +import remarkParse from './lib/index.js' -export default function remarkParse(options) { - this.Parser = (doc) => { - return fromMarkdown( - doc, - Object.assign({}, this.data('settings'), options, { - // Note: these options are not in the readme. - // The goal is for them to be set by plugins on `data` instead of being - // passed by users. - extensions: this.data('micromarkExtensions') || [], - mdastExtensions: this.data('fromMarkdownExtensions') || [] - }) - ) - } -} +export default remarkParse diff --git a/packages/remark-parse/lib/index.js b/packages/remark-parse/lib/index.js new file mode 100644 index 000000000..017af3994 --- /dev/null +++ b/packages/remark-parse/lib/index.js @@ -0,0 +1,28 @@ +/** + * @typedef {import('mdast').Root} Root + * @typedef {import('mdast-util-from-markdown').Options} Options + */ + +import {fromMarkdown} from 'mdast-util-from-markdown' + +/** @type {import('unified').Plugin<[Options?] | void[], string, Root>} */ +export default function remarkParse(options) { + /** @type {import('unified').ParserFunction} */ + const parser = (doc) => { + // Assume options. + const settings = /** @type {Options} */ (this.data('settings')) + + return fromMarkdown( + doc, + Object.assign({}, settings, options, { + // Note: these options are not in the readme. + // The goal is for them to be set by plugins on `data` instead of being + // passed by users. + extensions: this.data('micromarkExtensions') || [], + mdastExtensions: this.data('fromMarkdownExtensions') || [] + }) + ) + } + + Object.assign(this, {Parser: parser}) +} diff --git a/packages/remark-parse/package.json b/packages/remark-parse/package.json index 2e33f938d..531cbeabc 100644 --- a/packages/remark-parse/package.json +++ b/packages/remark-parse/package.json @@ -34,14 +34,26 @@ "sideEffects": false, "type": "module", "main": "index.js", + "types": "index.d.ts", "files": [ + "lib/", + "index.d.ts", "index.js" ], "dependencies": { - "mdast-util-from-markdown": "^1.0.0" + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "unified": "^10.0.0" }, "scripts": { - "test": "node --conditions development test.js" + "test": "node --conditions development test.js", + "build": "rimraf \"test.d.ts\" \"lib/**/*.d.ts\" && tsc && type-coverage" }, - "xo": false + "xo": false, + "typeCoverage": { + "atLeast": 100, + "detail": true, + "strict": true, + "ignoreCatch": true + } } diff --git a/packages/remark-parse/tsconfig.json b/packages/remark-parse/tsconfig.json new file mode 100644 index 000000000..6bb80be01 --- /dev/null +++ b/packages/remark-parse/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["lib/**/*.js", "test.js"] +} diff --git a/packages/remark-parse/types/index.d.ts b/packages/remark-parse/types/index.d.ts deleted file mode 100644 index 5460e2075..000000000 --- a/packages/remark-parse/types/index.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -// TypeScript Version: 3.0 - -import {Plugin} from 'unified' -import {Options} from 'mdast-util-from-markdown' - -declare namespace remarkParse { - interface Parse extends Plugin<[RemarkParseOptions?]> {} - - type RemarkParseOptions = Options -} - -declare const remarkParse: remarkParse.Parse - -export = remarkParse diff --git a/packages/remark-parse/types/test.ts b/packages/remark-parse/types/test.ts deleted file mode 100644 index d3b2dfda9..000000000 --- a/packages/remark-parse/types/test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import unified = require('unified') -import remarkParse = require('remark-parse') - -unified().use(remarkParse) - -// $ExpectError -unified().use(remarkParse, {unknown: 1}) diff --git a/packages/remark-parse/types/tsconfig.json b/packages/remark-parse/types/tsconfig.json deleted file mode 100644 index 03e437921..000000000 --- a/packages/remark-parse/types/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "lib": ["es2015"], - "strict": true, - "baseUrl": ".", - "paths": { - "remark-parse": ["index.d.ts"] - } - } -} diff --git a/packages/remark-parse/types/tslint.json b/packages/remark-parse/types/tslint.json deleted file mode 100644 index 1b0135893..000000000 --- a/packages/remark-parse/types/tslint.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "dtslint/dtslint.json", - "rules": { - "max-line-length": false, - "no-redundant-jsdoc": false, - "no-void-expression": false, - "only-arrow-functions": false, - "semicolon": false, - "unified-signatures": false, - "whitespace": false, - "no-unnecessary-generics": false, - "strict-export-declare-modifiers": false - } -} diff --git a/packages/remark-stringify/index.d.ts b/packages/remark-stringify/index.d.ts new file mode 100644 index 000000000..059a72e6f --- /dev/null +++ b/packages/remark-stringify/index.d.ts @@ -0,0 +1,7 @@ +// This wrapper exists because JS in TS can’t export a `@type` of a function. +import type {Options} from './lib/index.js' +import type {Root} from 'mdast' +import type {Plugin} from 'unified' +declare const remarkStringify: Plugin<[Options?] | void[], Root, string> +export default remarkStringify +export type {Options} diff --git a/packages/remark-stringify/index.js b/packages/remark-stringify/index.js index 80306bb30..514a8afe7 100644 --- a/packages/remark-stringify/index.js +++ b/packages/remark-stringify/index.js @@ -1,15 +1,3 @@ -import {toMarkdown} from 'mdast-util-to-markdown' +import remarkStringify from './lib/index.js' -export default function remarkStringify(options) { - this.Compiler = (tree) => { - return toMarkdown( - tree, - Object.assign({}, this.data('settings'), options, { - // Note: this option is not in the readme. - // The goal is for it to be set by plugins on `data` instead of being - // passed by users. - extensions: this.data('toMarkdownExtensions') || [] - }) - ) - } -} +export default remarkStringify diff --git a/packages/remark-stringify/lib/index.js b/packages/remark-stringify/lib/index.js new file mode 100644 index 000000000..e3170c08a --- /dev/null +++ b/packages/remark-stringify/lib/index.js @@ -0,0 +1,27 @@ +/** + * @typedef {import('mdast').Root|import('mdast').Content} Node + * @typedef {import('mdast-util-to-markdown').Options} Options + */ + +import {toMarkdown} from 'mdast-util-to-markdown' + +/** @type {import('unified').Plugin<[Options]|void[], Node, string>} */ +export default function remarkStringify(options) { + /** @type {import('unified').CompilerFunction} */ + const compiler = (tree) => { + // Assume options. + const settings = /** @type {Options} */ (this.data('settings')) + + return toMarkdown( + tree, + Object.assign({}, settings, options, { + // Note: this option is not in the readme. + // The goal is for it to be set by plugins on `data` instead of being + // passed by users. + extensions: this.data('toMarkdownExtensions') || [] + }) + ) + } + + Object.assign(this, {Compiler: compiler}) +} diff --git a/packages/remark-stringify/package.json b/packages/remark-stringify/package.json index c7d0a8f57..226618893 100644 --- a/packages/remark-stringify/package.json +++ b/packages/remark-stringify/package.json @@ -34,14 +34,26 @@ "sideEffects": false, "type": "module", "main": "index.js", + "types": "index.d.ts", "files": [ + "lib/", + "index.d.ts", "index.js" ], "dependencies": { - "mdast-util-to-markdown": "^1.0.0" + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.0.0", + "unified": "^10.0.0" }, "scripts": { - "test": "node --conditions development test.js" + "test": "node --conditions development test.js", + "build": "rimraf \"test.d.ts\" \"lib/**/*.d.ts\" && tsc && type-coverage" }, - "xo": false + "xo": false, + "typeCoverage": { + "atLeast": 100, + "detail": true, + "strict": true, + "ignoreCatch": true + } } diff --git a/packages/remark-stringify/test.js b/packages/remark-stringify/test.js index 717c3d147..d44b25b5e 100644 --- a/packages/remark-stringify/test.js +++ b/packages/remark-stringify/test.js @@ -1,3 +1,10 @@ +/** + * @typedef {import('mdast').Root} Root + * @typedef {import('mdast').Content} Content + * @typedef {import('mdast').BlockContent} BlockContent + * @typedef {import('./index.js').Options} Options + */ + import test from 'tape' import {unified} from 'unified' import {gfmToMarkdown} from 'mdast-util-gfm' @@ -19,6 +26,7 @@ test('remarkStringify', (t) => { t.throws( () => { + // @ts-expect-error: not a node. unified().use(remarkStringify).stringify(false) }, /false/, @@ -27,6 +35,7 @@ test('remarkStringify', (t) => { t.throws( () => { + // @ts-expect-error: not a known node. unified().use(remarkStringify).stringify({type: 'unicorn'}) }, /unicorn/, @@ -38,7 +47,12 @@ test('remarkStringify', (t) => { unified() .use(remarkStringify) .data('settings', {bullet: true}) - .stringify({type: 'listItem'}) + .stringify({ + type: 'root', + children: [ + {type: 'list', children: [{type: 'listItem', children: []}]} + ] + }) }, /options\.bullet/, 'should throw when `options.bullet` is not a valid list bullet' @@ -49,7 +63,12 @@ test('remarkStringify', (t) => { unified() .use(remarkStringify) .data('settings', {listItemIndent: 'foo'}) - .stringify({type: 'listItem'}) + .stringify({ + type: 'root', + children: [ + {type: 'list', children: [{type: 'listItem', children: []}]} + ] + }) }, /options\.listItemIndent/, 'should throw when `options.listItemIndent` is not a valid constant' @@ -60,7 +79,7 @@ test('remarkStringify', (t) => { unified() .use(remarkStringify) .data('settings', {rule: true}) - .stringify({type: 'thematicBreak'}) + .stringify({type: 'root', children: [{type: 'thematicBreak'}]}) }, /options\.rule/, 'should throw when `options.rule` is not a valid horizontal rule bullet' @@ -71,7 +90,7 @@ test('remarkStringify', (t) => { unified() .use(remarkStringify) .data('settings', {ruleRepetition: 1}) - .stringify({type: 'thematicBreak'}) + .stringify({type: 'root', children: [{type: 'thematicBreak'}]}) }, /options\.ruleRepetition/, 'should throw when `options.ruleRepetition` is too low' @@ -82,7 +101,7 @@ test('remarkStringify', (t) => { unified() .use(remarkStringify) .data('settings', {ruleRepetition: true}) - .stringify({type: 'thematicBreak'}) + .stringify({type: 'root', children: [{type: 'thematicBreak'}]}) }, /options\.ruleRepetition/, 'should throw when `options.ruleRepetition` is not a number' @@ -93,7 +112,7 @@ test('remarkStringify', (t) => { unified() .use(remarkStringify) .data('settings', {emphasis: '-'}) - .stringify({type: 'emphasis'}) + .stringify({type: 'root', children: [{type: 'emphasis', children: []}]}) }, /options\.emphasis/, 'should throw when `options.emphasis` is not a valid emphasis marker' @@ -104,7 +123,7 @@ test('remarkStringify', (t) => { unified() .use(remarkStringify) .data('settings', {strong: '-'}) - .stringify({type: 'strong'}) + .stringify({type: 'root', children: [{type: 'strong', children: []}]}) }, /options\.strong/, 'should throw when `options.strong` is not a valid emphasis marker' @@ -115,7 +134,7 @@ test('remarkStringify', (t) => { unified() .use(remarkStringify) .data('settings', {fence: '-'}) - .stringify({type: 'code'}) + .stringify({type: 'root', children: [{type: 'code', value: ''}]}) }, /options\.fence/, 'should throw when `options.fence` is not a valid fence marker' @@ -248,13 +267,10 @@ test('remarkStringify', (t) => { ) t.end() - - function toString(value) { - return String(unified().use(remarkStringify).stringify(value)) - } }) t.test('should support optional list item fields', (t) => { + /** @type {BlockContent[]} */ const children = [ {type: 'paragraph', children: [{type: 'text', value: 'alpha'}]}, { @@ -284,20 +300,12 @@ test('remarkStringify', (t) => { ) t.end() - - function toString(value) { - return String(unified().use(remarkStringify).stringify(value)) - } }) t.test('should support empty list items', (t) => { t.equal(toString({type: 'listItem', children: []}), '*\n') t.end() - - function toString(value) { - return String(unified().use(remarkStringify).stringify(value)) - } }) t.test('should process references with casing properly', (t) => { @@ -340,6 +348,7 @@ test('remarkStringify', (t) => { toString({ type: 'linkReference', identifier: 'a', + referenceType: 'full', children: [{type: 'text', value: 'b'}] }), '[b][a]\n', @@ -347,16 +356,17 @@ test('remarkStringify', (t) => { ) t.equal( - toString({type: 'imageReference', identifier: 'a', alt: 'b'}), + toString({ + type: 'imageReference', + referenceType: 'full', + identifier: 'a', + alt: 'b' + }), '![b][a]\n', 'image reference' ) t.end() - - function toString(value) { - return String(unified().use(remarkStringify).stringify(value)) - } }) t.test('should stringify mailto links properly', (t) => { @@ -407,12 +417,12 @@ test('stringify escapes', (t) => { t.equal(toString('a&b'), 'a\\&b\n', 'entities') t.equal(toString('a]b'), 'a]b\n', '`]`') t.equal( - toString({type: 'link', children: [{type: 'text', value: 'a]b'}]}), + toString({type: 'link', url: '', children: [{type: 'text', value: 'a]b'}]}), '[a\\]b]()\n', '`]` (in links)' ) t.equal( - toString({type: 'image', alt: 'a]b'}), + toString({type: 'image', url: '', alt: 'a]b'}), '![a\\]b]()\n', '`]` (in images)' ) @@ -456,7 +466,7 @@ test('stringify escapes', (t) => { type: 'paragraph', children: [ {type: 'text', value: '!'}, - {type: 'link', children: [{type: 'text', value: 'a'}]} + {type: 'link', url: '', children: [{type: 'text', value: 'a'}]} ] }), '\\![a]()\n', @@ -549,7 +559,7 @@ test('extensions', (t) => { { type: 'list', ordered: false, - start: null, + start: undefined, spread: false, children: [ { @@ -602,11 +612,19 @@ test('extensions', (t) => { t.end() }) +/** + * @param {Root|Content|string} value + * @param {Options} [options] + * @returns {string} + */ function toString(value, options) { - const tree = - typeof value === 'string' - ? {type: 'paragraph', children: [{type: 'text', value}]} - : value + if (typeof value === 'string') { + value = {type: 'paragraph', children: [{type: 'text', value}]} + } + + if (value.type !== 'root') { + value = {type: 'root', children: [value]} + } - return unified().use(remarkStringify, options).stringify(tree) + return unified().use(remarkStringify, options).stringify(value) } diff --git a/packages/remark-stringify/tsconfig.json b/packages/remark-stringify/tsconfig.json new file mode 100644 index 000000000..6bb80be01 --- /dev/null +++ b/packages/remark-stringify/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["lib/**/*.js", "test.js"] +} diff --git a/packages/remark-stringify/types/index.d.ts b/packages/remark-stringify/types/index.d.ts deleted file mode 100644 index 467e8c14e..000000000 --- a/packages/remark-stringify/types/index.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -// TypeScript Version: 3.0 - -import {Plugin} from 'unified' -import {Options} from 'mdast-util-to-markdown' - -declare namespace remarkStringify { - interface Stringify extends Plugin<[RemarkStringifyOptions?]> {} - - type RemarkStringifyOptions = Options -} - -declare const remarkStringify: remarkStringify.Stringify - -export = remarkStringify diff --git a/packages/remark-stringify/types/test.ts b/packages/remark-stringify/types/test.ts deleted file mode 100644 index 8807396cc..000000000 --- a/packages/remark-stringify/types/test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import remarkStringify = require('remark-stringify') -import unified = require('unified') - -import {Node, Parent} from 'unist' - -const inferredStringifyOptions = { - gfm: true, - fences: true, - incrementListMarker: false -} - -unified().use(remarkStringify) -unified().use(remarkStringify, inferredStringifyOptions) - -// These cannot be automatically inferred by TypeScript -const nonInferredStringifyOptions: remarkStringify.RemarkStringifyOptions = { - fence: '~', - bullet: '+', - listItemIndent: 'tab', - rule: '-', - strong: '_', - emphasis: '*' -} - -unified().use(remarkStringify, nonInferredStringifyOptions) - -const badStringifyOptions = { - gfm: 'true' -} - -// $ExpectError -unified().use(remarkStringify, badStringifyOptions) - -const incompleteStringifyOptions: remarkStringify.RemarkStringifyOptions = { - fences: true, - incrementListMarker: false -} diff --git a/packages/remark-stringify/types/tsconfig.json b/packages/remark-stringify/types/tsconfig.json deleted file mode 100644 index ec6ce3be0..000000000 --- a/packages/remark-stringify/types/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "lib": ["es2015"], - "strict": true, - "baseUrl": ".", - "paths": { - "remark-stringify": ["index.d.ts"] - } - } -} diff --git a/packages/remark-stringify/types/tslint.json b/packages/remark-stringify/types/tslint.json deleted file mode 100644 index 1b0135893..000000000 --- a/packages/remark-stringify/types/tslint.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "dtslint/dtslint.json", - "rules": { - "max-line-length": false, - "no-redundant-jsdoc": false, - "no-void-expression": false, - "only-arrow-functions": false, - "semicolon": false, - "unified-signatures": false, - "whitespace": false, - "no-unnecessary-generics": false, - "strict-export-declare-modifiers": false - } -} diff --git a/packages/remark/package.json b/packages/remark/package.json index 1cadbddf1..fb2c452f6 100644 --- a/packages/remark/package.json +++ b/packages/remark/package.json @@ -32,7 +32,9 @@ "sideEffects": false, "type": "module", "main": "index.js", + "types": "index.d.ts", "files": [ + "index.d.ts", "index.js" ], "dependencies": { @@ -41,7 +43,14 @@ "unified": "^10.0.0" }, "scripts": { - "test": "node --conditions development test.js" + "test": "node --conditions development test.js", + "build": "rimraf \"*.d.ts\" && tsc && type-coverage" }, - "xo": false + "xo": false, + "typeCoverage": { + "atLeast": 100, + "detail": true, + "strict": true, + "ignoreCatch": true + } } diff --git a/packages/remark/tsconfig.json b/packages/remark/tsconfig.json new file mode 100644 index 000000000..7e61871a6 --- /dev/null +++ b/packages/remark/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["*.js"] +} diff --git a/packages/remark/types/index.d.ts b/packages/remark/types/index.d.ts deleted file mode 100644 index 8123eb581..000000000 --- a/packages/remark/types/index.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -// TypeScript Version: 3.0 - -import unified = require('unified') -import remarkParse = require('remark-parse') -import remarkStringify = require('remark-stringify') - -declare namespace remark { - type RemarkOptions = remarkParse.RemarkParseOptions & - remarkStringify.RemarkStringifyOptions - - /** - * @deprecated Use `RemarkOptions` instead. - */ - type PartialRemarkOptions = RemarkOptions -} - -declare const remark: unified.FrozenProcessor - -export = remark diff --git a/packages/remark/types/test.ts b/packages/remark/types/test.ts deleted file mode 100644 index 74a60ced5..000000000 --- a/packages/remark/types/test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import remark = require('remark') - -interface PluginOptions { - example: boolean -} - -const plugin = (options?: PluginOptions) => {} - -remark.parse('# Hello world!') -remark().use(plugin) -remark().use(plugin, {example: true}) -remark().use({settings: {bullet: '+'}}) -// $ExpectError -remark().use({settings: {doesNotExist: true}}) -// $ExpectError -remark().use(plugin, {doesNotExist: 'true'}) - -const badParseOptionsInterface: remark.RemarkOptions = { - // $ExpectError - gfm: 'true' -} diff --git a/packages/remark/types/tsconfig.json b/packages/remark/types/tsconfig.json deleted file mode 100644 index 2c0015e3d..000000000 --- a/packages/remark/types/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "lib": ["es2015"], - "strict": true, - "baseUrl": ".", - "paths": { - "remark": ["index.d.ts"] - } - } -} diff --git a/packages/remark/types/tslint.json b/packages/remark/types/tslint.json deleted file mode 100644 index c72b387b3..000000000 --- a/packages/remark/types/tslint.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "dtslint/dtslint.json", - "rules": { - "max-line-length": false, - "no-redundant-jsdoc": false, - "no-void-expression": false, - "only-arrow-functions": false, - "semicolon": false, - "unified-signatures": false, - "whitespace": false, - "interface-over-type-literal": false, - "no-unnecessary-generics": false, - "strict-export-declare-modifiers": false - } -} diff --git a/script/regenerate-fixtures.js b/script/regenerate-fixtures.js index 96176b59d..3e6502029 100644 --- a/script/regenerate-fixtures.js +++ b/script/regenerate-fixtures.js @@ -1,9 +1,12 @@ +/** @typedef {import('mdast').Root} Root */ + import fs from 'fs' import path from 'path' import {remark} from '../packages/remark/index.js' import {fixtures} from '../test/fixtures/index.js' const base = path.join('test', 'fixtures', 'tree') +/** @type {string[]} */ const generated = [] let index = -1 @@ -11,6 +14,7 @@ while (++index < fixtures.length) { const fixture = fixtures[index] const stem = path.basename(fixture.name, path.extname(fixture.name)) const input = fixture.input + /** @type {Root} */ let result try { diff --git a/test/fixtures/index.js b/test/fixtures/index.js index c26117648..3e52bc150 100644 --- a/test/fixtures/index.js +++ b/test/fixtures/index.js @@ -1,3 +1,5 @@ +/** @typedef {import('mdast').Root} Root */ + import fs from 'fs' import path from 'path' import camelcase from 'camelcase' @@ -12,9 +14,10 @@ const defaults = { incrementListMarker: true, listItemIndent: 'tab', quote: '"', + resourceLink: false, rule: '*', - ruleSpaces: true, ruleRepetition: 3, + ruleSpaces: true, setext: false, strong: '*', tightDefinitions: false @@ -32,10 +35,11 @@ export const fixtures = fs fs.readFileSync(path.join('test', 'fixtures', 'input', basename)) ) const treePath = path.join('test', 'fixtures', 'tree', stem + '.json') + /** @type {Root|undefined} */ let tree if (fs.existsSync(treePath)) { - tree = JSON.parse(fs.readFileSync(treePath)) + tree = JSON.parse(String(fs.readFileSync(treePath))) } return { @@ -47,21 +51,29 @@ export const fixtures = fs } }) -// Parse options from a filename. +/** + * Parse options from a filename. + * + * @param {string} name + */ function parseOptions(name) { const parts = name.split('.') - const length = parts.length - const options = {stringify: Object.assign({}, defaults)} + const options = { + /** @type {boolean|undefined} */ + output: undefined, + /** @type {Record} */ + stringify: Object.assign({}, defaults) + } let index = -1 - while (++index < length) { + while (++index < parts.length) { const part = parts[index].split('=') const augmented = augment(part[0], part.slice(1).join('=')) const key = augmented.key const value = augmented.value if (key === 'output') { - options[key] = value + options[key] = Boolean(value) } else if (key in defaults && value !== options.stringify[key]) { options.stringify[key] = value } @@ -70,8 +82,16 @@ function parseOptions(name) { return options } -// Parse a `string` `value` into a javascript value. -function augment(key, value) { +/** + * Parse a `string` `value` into a javascript value. + * + * @param {string} key + * @param {string} input + */ +function augment(key, input) { + /** @type {string|boolean|number} */ + let value = input + if (!value) { value = key.slice(0, 2) !== 'no' diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..6207d022b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "include": ["script/**/*.js", "test/**/*.js"], + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020"], + "module": "ES2020", + "moduleResolution": "node", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": true, + "declaration": true, + "emitDeclarationOnly": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "strict": true + } +}