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
3 changes: 3 additions & 0 deletions src/generators/metadata/constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export const DOC_API_SLUGS_REPLACEMENTS = [
{ from: /^(?!-)(?!-+$).*?(--+)/g, to: '-' }, // Replace multiple hyphens
];

// Matches Node.js deprecation headings such as "DEP0001: Description".
export const DEPRECATION_HEADING_REGEX = /^(DEP\d+):/;

// These are regular expressions used to determine if a given Markdown heading
// is a specific type of API Doc entry (e.g., Event, Class, Method, etc)
// and to extract the inner content of said Heading to be used as the API doc entry name
Expand Down
32 changes: 32 additions & 0 deletions src/generators/metadata/utils/__tests__/parse.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,38 @@ describe('parseApiDoc', () => {
});
});

describe('deprecation headings', () => {
it('uses the DEP code as the slug for deprecation page headings', () => {
const tree = u('root', [
h('DEP0001: http.OutgoingMessage.prototype.flush'),
]);
const [entry] = parseApiDoc({ path: '/deprecations', tree }, typeMap);

assert.strictEqual(entry.heading.data.slug, 'DEP0001');
});

it('deduplicates repeated DEP code slugs', () => {
const tree = u('root', [
h('DEP0001: first deprecated API'),
h('DEP0001: second deprecated API'),
]);
const results = parseApiDoc({ path: '/deprecations', tree }, typeMap);

assert.strictEqual(results[0].heading.data.slug, 'DEP0001');
assert.strictEqual(results[1].heading.data.slug, 'DEP0001-1');
});

it('uses normal slugs for DEP headings outside the deprecations page', () => {
const tree = u('root', [h('DEP0190: some section heading')]);
const [entry] = parseApiDoc({ path, tree }, typeMap);

assert.strictEqual(
entry.heading.data.slug,
'dep0190-some-section-heading'
);
});
});

describe('YAML metadata', () => {
it('extracts added_in', () => {
const tree = u('root', [h('fs'), yaml('added: v0.1.0')]);
Expand Down
25 changes: 23 additions & 2 deletions src/generators/metadata/utils/parse.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import {
import { UNIST } from '../../../utils/queries/index.mjs';
import { getRemark as remark } from '../../../utils/remark.mjs';
import { relative } from '../../../utils/url.mjs';
import { IGNORE_STABILITY_STEMS } from '../constants.mjs';
import {
DEPRECATION_HEADING_REGEX,
IGNORE_STABILITY_STEMS,
} from '../constants.mjs';

/**
* This generator generates a flattened list of metadata entries from a API doc
Expand All @@ -44,6 +47,24 @@ export const parseApiDoc = ({ path, tree }, typeMap) => {
// Slug the API (We use a non-class slugger, since we are fairly certain that `path` is unique)
const api = slug(path.slice(1).replace(sep, '-'));

const deprecationSlugCounts = new Map();
const getHeadingSlug = text => {
if (api !== 'deprecations') {
return nodeSlugger.slug(text);
}

const deprecationHeading = DEPRECATION_HEADING_REGEX.exec(text);
if (deprecationHeading === null) {
return nodeSlugger.slug(text);
}

const deprecationCode = deprecationHeading[1];
const count = deprecationSlugCounts.get(deprecationCode) ?? 0;
deprecationSlugCounts.set(deprecationCode, count + 1);

return count === 0 ? deprecationCode : `${deprecationCode}-${count}`;
};

// Get all Markdown Footnote definitions from the tree
const markdownDefinitions = selectAll('definition', tree);

Expand Down Expand Up @@ -88,7 +109,7 @@ export const parseApiDoc = ({ path, tree }, typeMap) => {
});

// Generate slug and update heading data
metadata.heading.data.slug = nodeSlugger.slug(metadata.heading.data.text);
metadata.heading.data.slug = getHeadingSlug(metadata.heading.data.text);

// Find the next heading to determine section boundaries
const nextHeadingNode =
Expand Down