Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/quiet-rules-migrate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@node-core/remark-lint': patch
---

Use `@doc-kit/core` instead of `@node-core/doc-kit` 1.x. Heading anchors now follow doc-kit 2's slugs (`child_process` links as `#child_process`), and `invalid-type-reference` no longer treats HTML comments and tags as type references.
2 changes: 1 addition & 1 deletion packages/remark-lint/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"test:unit": "cross-env NODE_NO_WARNINGS=1 node --experimental-test-coverage --test \"**/*.test.mjs\""
},
"dependencies": {
"@node-core/doc-kit": "^1.2.0",
"@doc-kit/core": "^1.3.1",
"mdast-util-to-string": "^4.0.0",
"remark-gfm": "^4.0.1",
"remark-lint-blockquote-indentation": "^4.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ const value = {invalid};
<div>{invalid}</div>`,
expected: [],
},
{
name: 'ignores HTML comments and tags',
input: `<!--introduced_in=v0.10.0-->

<a id="module_builtins" href="module.html#builtins"></a>`,
expected: [],
},
{
name: 'array reference',
input: 'Takes a {string[]}.',
expected: [],
},
{
name: 'module-qualified reference',
input: 'Returns a {vm.Module}.',
expected: [],
},
{
name: 'union with one resolvable member',
input: 'This is a {Unknown|number}.',
expected: [],
},
{
name: 'multiple references',
input: 'Psst, are you a {string | boolean}',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ describe('validate-links', () => {
'# Existing heading',
'[Existing](#existing%2Dheading)',
'# child_process',
'[Node.js-style slug](#child-process)',
'[Node.js-style slug](#child_process)',
].join('\n\n')
);
const invalid = await processMarkdown(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { QUERIES } from '@node-core/doc-kit/src/utils/queries/index.mjs';
import { QUERIES } from '@doc-kit/core/src/utils/queries/index.mjs';
import { lintRule } from 'unified-lint-rule';
import { visit } from 'unist-util-visit';

Expand Down
33 changes: 27 additions & 6 deletions packages/remark-lint/src/rules/invalid-type-reference.mjs
Original file line number Diff line number Diff line change
@@ -1,30 +1,51 @@
import { transformTypeToReferenceLink } from '@node-core/doc-kit/src/generators/metadata/utils/transformers.mjs';
import { QUERIES } from '@node-core/doc-kit/src/utils/queries/index.mjs';
import { resolveTypeReference } from '@doc-kit/core/src/generators/metadata/utils/transformers.mjs';
import { lintRule } from 'unified-lint-rule';
import { visit } from 'unist-util-visit';

const TYPE_RE = /(\{|<)(?! )[^<({})>]+(?! )(\}|>)/g;
// Excludes HTML comments, closing tags and tags with attributes
const HTML_TYPE_RE = /^<[^\s!/=]+>$/;
Comment on lines +5 to +7

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we import this from somewhere?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like?

const MATCH_RE = /\s\||\| /g;
const REPLACE_RE = /\s*\| */g;

const isTypeNode = node => {
if (node.type === 'text') {
return QUERIES.normalizeTypes.test(node.value);
return TYPE_RE.test(node.value);
}

if (node.type === 'html') {
return node.value.match(QUERIES.normalizeTypes)?.includes(node.value);
return (
HTML_TYPE_RE.test(node.value) &&
node.value.match(TYPE_RE)?.includes(node.value)
);
}

return false;
};

/**
* Whether at least one member of a `{type}` reference links somewhere
* @param {string} type
* @param {Record<string, string>} typeMap
* @returns {boolean}
*/
const isResolvable = (type, typeMap) =>
type
.slice(1, -1)
.split('|')
.some(piece => {
const name = piece.trim().replace(/\[\]$/, '');

return name.length > 0 && resolveTypeReference(name, typeMap) !== '';
Comment on lines +37 to +39
});

/**
* Ensures that all type references are valid
* @type {import('unified-lint-rule').Rule<, import('../api.mjs').Options>}
*/
const invalidTypeReference = (tree, vfile, { typeMap = {} }) => {
visit(tree, isTypeNode, node => {
const types = node.value.match(QUERIES.normalizeTypes);
const types = node.value.match(TYPE_RE);

types.forEach(type => {
// Ensure wrapped in {}
Expand All @@ -50,7 +71,7 @@ const invalidTypeReference = (tree, vfile, { typeMap = {} }) => {
node.value = node.value.replace(type, normalized);
}

if (transformTypeToReferenceLink(type, typeMap) === type) {
if (!isResolvable(type, typeMap)) {
vfile.message(`Invalid type reference: ${type}`, node);
}
});
Expand Down
2 changes: 1 addition & 1 deletion packages/remark-lint/src/rules/validate-links.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { readdir } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';

import createNodeSlugger from '@node-core/doc-kit/src/generators/metadata/utils/slugger.mjs';
import createNodeSlugger from '@doc-kit/core/src/generators/metadata/utils/slugger.mjs';
import { toString } from 'mdast-util-to-string';
import { lintRule } from 'unified-lint-rule';
import { visit } from 'unist-util-visit';
Expand Down
Loading
Loading