Skip to content

Commit 5419773

Browse files
committed
code review (4)
1 parent 8becb05 commit 5419773

File tree

3 files changed

+168
-166
lines changed

3 files changed

+168
-166
lines changed

src/generators/legacy-json/index.mjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { writeFile } from 'node:fs/promises';
44
import { join } from 'node:path';
55
import { groupNodesByModule } from '../../utils/generators.mjs';
6-
import buildSection from './utils/buildSection.mjs';
6+
import { createSectionBuilder } from './utils/buildSection.mjs';
77

88
/**
99
* This generator is responsible for generating the legacy JSON files for the
@@ -28,6 +28,8 @@ export default {
2828
dependsOn: 'ast',
2929

3030
async generate(input, { output }) {
31+
const buildSection = createSectionBuilder();
32+
3133
// This array holds all the generated values for each module
3234
const generatedValues = [];
3335

src/generators/legacy-json/utils/buildSection.mjs

Lines changed: 133 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const sectionTypePlurals = {
1717
var: 'vars',
1818
};
1919

20+
const unpromotedKeys = ['textRaw', 'name', 'type', 'desc', 'miscs'];
21+
2022
/**
2123
* Converts a value to an array.
2224
* @template T
@@ -25,171 +27,161 @@ const sectionTypePlurals = {
2527
*/
2628
const enforceArray = val => (Array.isArray(val) ? val : [val]);
2729

28-
/**
29-
* Creates metadata from a hierarchized entry.
30-
* @param {import('../types.d.ts').HierarchizedEntry} entry - The entry to create metadata from.
31-
* @returns {import('../types.d.ts').Meta} The created metadata.
32-
*/
33-
function createMeta(entry) {
34-
const {
30+
export const createSectionBuilder = () => {
31+
const html = getRemarkRehype();
32+
33+
/**
34+
* Creates metadata from a hierarchized entry.
35+
* @param {import('../types.d.ts').HierarchizedEntry} entry - The entry to create metadata from.
36+
* @returns {import('../types.d.ts').Meta} The created metadata.
37+
*/
38+
const createMeta = ({
3539
added_in = [],
3640
n_api_version = [],
3741
deprecated_in = [],
3842
removed_in = [],
3943
changes,
40-
} = entry;
41-
42-
return {
44+
}) => ({
4345
changes,
4446
added: enforceArray(added_in),
4547
napiVersion: enforceArray(n_api_version),
4648
deprecated: enforceArray(deprecated_in),
4749
removed: enforceArray(removed_in),
48-
};
49-
}
50-
51-
/**
52-
* Creates a section from an entry and its heading.
53-
* @param {import('../types.d.ts').HierarchizedEntry} entry - The AST entry.
54-
* @param {HeadingMetadataParent} head - The head node of the entry.
55-
* @returns {import('../types.d.ts').Section} The created section.
56-
*/
57-
function createSection(entry, head) {
58-
return {
50+
});
51+
52+
/**
53+
* Creates a section from an entry and its heading.
54+
* @param {import('../types.d.ts').HierarchizedEntry} entry - The AST entry.
55+
* @param {HeadingMetadataParent} head - The head node of the entry.
56+
* @returns {import('../types.d.ts').Section} The created section.
57+
*/
58+
const createSection = (entry, head) => ({
5959
textRaw: transformNodesToString(head.children),
6060
name: head.data.name,
6161
type: head.data.type,
6262
meta: createMeta(entry),
6363
introduced_in: entry.introduced_in,
64+
});
65+
66+
/**
67+
* Parses stability metadata and adds it to the section.
68+
* @param {import('../types.d.ts').Section} section - The section to update.
69+
* @param {Array} nodes - The remaining AST nodes.
70+
* @param {import('../types.d.ts').HierarchizedEntry} entry - The entry providing stability information.
71+
*/
72+
const parseStability = (section, nodes, { stability }) => {
73+
const stabilityInfo = stability.toJSON()?.[0];
74+
75+
if (stabilityInfo) {
76+
section.stability = stabilityInfo.index;
77+
section.stabilityText = stabilityInfo.description;
78+
nodes.shift(); // Remove stability node from processing
79+
}
6480
};
65-
}
66-
67-
/**
68-
* Parses stability metadata and adds it to the section.
69-
* @param {import('../types.d.ts').Section} section - The section to add stability to.
70-
* @param {Array} nodes - The AST nodes.
71-
* @param {import('../types.d.ts').HierarchizedEntry} entry - The entry to handle.
72-
*/
73-
function parseStability(section, nodes, entry) {
74-
const json = entry.stability.toJSON()[0];
75-
if (json) {
76-
section.stability = json.index;
77-
section.stabilityText = json.description;
78-
nodes.splice(0, 1);
79-
}
80-
}
81-
82-
let lazyHTML;
83-
84-
/**
85-
* Adds a description to the section.
86-
* @param {import('../types.d.ts').Section} section - The section to add description to.
87-
* @param {Array} nodes - The AST nodes.
88-
*/
89-
function addDescription(section, nodes) {
90-
if (!nodes.length) {
91-
return;
92-
}
93-
94-
if (section.desc) {
95-
section.shortDesc = section.desc;
96-
}
97-
98-
lazyHTML ??= getRemarkRehype();
99-
100-
const rendered = lazyHTML.stringify(
101-
lazyHTML.runSync({ type: 'root', children: nodes })
102-
);
10381

104-
section.desc = rendered || undefined;
105-
}
82+
/**
83+
* Adds a description to the section.
84+
* @param {import('../types.d.ts').Section} section - The section to update.
85+
* @param {Array} nodes - The remaining AST nodes.
86+
*/
87+
const addDescription = (section, nodes) => {
88+
if (!nodes.length) {
89+
return;
90+
}
91+
92+
const rendered = html.stringify(
93+
html.runSync({ type: 'root', children: nodes })
94+
);
95+
96+
section.shortDesc = section.desc || undefined;
97+
section.desc = rendered || undefined;
98+
};
10699

107-
/**
108-
* Adds additional metadata to the section based on its type.
109-
* @param {import('../types.d.ts').Section} section - The section to update.
110-
* @param {import('../types.d.ts').Section} parentSection - The parent section.
111-
* @param {import('../../types.d.ts').NodeWithData} headingNode - The heading node.
112-
*/
113-
function addAdditionalMetadata(section, parentSection, headingNode) {
114-
if (!section.type) {
115-
section.name = section.textRaw.toLowerCase().trim().replace(/\s+/g, '_');
116-
section.displayName = headingNode.data.name;
117-
section.type = parentSection.type === 'misc' ? 'misc' : 'module';
118-
}
119-
}
100+
/**
101+
* Adds additional metadata to the section based on its type.
102+
* @param {import('../types.d.ts').Section} section - The section to update.
103+
* @param {import('../types.d.ts').Section} parent - The parent section.
104+
* @param {import('../../types.d.ts').NodeWithData} heading - The heading node of the section.
105+
*/
106+
const addAdditionalMetadata = (section, parent, heading) => {
107+
if (!section.type) {
108+
section.name = section.textRaw.toLowerCase().trim().replace(/\s+/g, '_');
109+
section.displayName = heading.data.name;
110+
section.type = parent.type === 'misc' ? 'misc' : 'module';
111+
}
112+
};
120113

121-
/**
122-
* Adds the section to its parent section.
123-
* @param {import('../types.d.ts').Section} section - The section to add.
124-
* @param {import('../types.d.ts').Section} parentSection - The parent section.
125-
*/
126-
function addToParent(section, parentSection) {
127-
const pluralType = sectionTypePlurals[section.type];
114+
/**
115+
* Adds the section to its parent section.
116+
* @param {import('../types.d.ts').Section} section - The section to add.
117+
* @param {import('../types.d.ts').Section} parent - The parent section.
118+
*/
119+
const addToParent = (section, parent) => {
120+
const key = sectionTypePlurals[section.type] || 'miscs';
128121

129-
parentSection[pluralType] = parentSection[pluralType] || [];
130-
parentSection[pluralType].push(section);
131-
}
122+
parent[key] ??= [];
123+
parent[key].push(section);
124+
};
132125

133-
const notTransferredKeys = ['textRaw', 'name', 'type', 'desc', 'miscs'];
126+
/**
127+
* Promotes children properties to the parent level if the section type is 'misc'.
128+
* @param {import('../types.d.ts').Section} section - The section to promote.
129+
* @param {import('../types.d.ts').Section} parent - The parent section.
130+
*/
131+
const promoteMiscChildren = (section, parent) => {
132+
// Only promote if the current section is of type 'misc' and the parent is not 'misc'
133+
if (section.type === 'misc' && parent.type !== 'misc') {
134+
Object.entries(section).forEach(([key, value]) => {
135+
// Only promote certain keys
136+
if (!unpromotedKeys.includes(key)) {
137+
// Merge the section's properties into the parent section
138+
parent[key] = parent[key]
139+
? // If the parent already has this key, concatenate the values
140+
[].concat(parent[key], value)
141+
: // Otherwise, directly assign the section's value to the parent
142+
[];
143+
}
144+
});
145+
}
146+
};
134147

135-
/**
136-
* Promotes children properties to the parent level if the section type is 'misc'.
137-
*
138-
* @param {import('../types.d.ts').Section} section - The section to promote.
139-
* @param {import('../types.d.ts').Section} parentSection - The parent section.
140-
*/
141-
const makeChildrenTopLevelIfMisc = (section, parentSection) => {
142-
// Only promote if the current section is of type 'misc' and the parent is not 'misc'
143-
if (section.type === 'misc' && parentSection.type !== 'misc') {
144-
Object.entries(section).forEach(([key, value]) => {
145-
// Skip keys that should not be transferred
146-
if (notTransferredKeys.includes(key)) return;
147-
148-
// Merge the section's properties into the parent section
149-
parentSection[key] = parentSection[key]
150-
? // If the parent already has this key, concatenate the values
151-
[].concat(parentSection[key], value)
152-
: // Otherwise, directly assign the section's value to the parent
153-
value;
154-
});
155-
}
156-
};
148+
/**
149+
* Processes children of a given entry and updates the section.
150+
* @param {import('../types.d.ts').HierarchizedEntry} entry - The current entry.
151+
* @param {import('../types.d.ts').Section} section - The current section.
152+
*/
153+
const handleChildren = ({ hierarchyChildren }, section) =>
154+
hierarchyChildren?.forEach(child => handleEntry(child, section));
155+
156+
/**
157+
* Handles an entry and updates the parent section.
158+
* @param {import('../types.d.ts').HierarchizedEntry} entry - The entry to process.
159+
* @param {import('../types.d.ts').Section} parent - The parent section.
160+
*/
161+
const handleEntry = (entry, parent) => {
162+
const [headingNode, ...nodes] = structuredClone(entry.content.children);
163+
const section = createSection(entry, headingNode);
164+
165+
parseStability(section, nodes, entry);
166+
parseList(section, nodes);
167+
addDescription(section, nodes);
168+
handleChildren(entry, section);
169+
addAdditionalMetadata(section, parent, headingNode);
170+
addToParent(section, parent);
171+
promoteMiscChildren(section, parent);
172+
};
157173

158-
const handleChildren = (entry, section) => {
159-
entry.hierarchyChildren?.forEach(child => handleEntry(child, section));
160-
};
174+
/**
175+
* Builds the module section from head metadata and entries.
176+
* @param {ApiDocMetadataEntry} head - The head metadata entry.
177+
* @param {Array<ApiDocMetadataEntry>} entries - The list of metadata entries.
178+
* @returns {import('../types.d.ts').ModuleSection} The constructed module section.
179+
*/
180+
return (head, entries) => {
181+
const rootModule = { type: 'module', source: head.api_doc_source };
161182

162-
/**
163-
* Handles an entry and updates the parent section.
164-
* @param {import('../types.d.ts').HierarchizedEntry} entry - The entry to handle.
165-
* @param {import('../types.d.ts').Section} parentSection - The parent section.
166-
*/
167-
function handleEntry(entry, parentSection) {
168-
const [headingNode, ...nodes] = structuredClone(entry.content.children);
169-
const section = createSection(entry, headingNode);
170-
171-
parseStability(section, nodes, entry);
172-
parseList(section, nodes);
173-
addDescription(section, nodes);
174-
handleChildren(entry, section);
175-
addAdditionalMetadata(section, parentSection, headingNode);
176-
addToParent(section, parentSection);
177-
makeChildrenTopLevelIfMisc(section, parentSection);
178-
}
183+
buildHierarchy(entries).forEach(entry => handleEntry(entry, rootModule));
179184

180-
/**
181-
* Builds the module section from head and entries.
182-
* @param {ApiDocMetadataEntry} head - The head metadata entry.
183-
* @param {Array<ApiDocMetadataEntry>} entries - The list of metadata entries.
184-
* @returns {import('../types.d.ts').ModuleSection} The constructed module section.
185-
*/
186-
export default (head, entries) => {
187-
const rootModule = {
188-
type: 'module',
189-
source: head.api_doc_source,
185+
return rootModule;
190186
};
191-
192-
buildHierarchy(entries).forEach(entry => handleEntry(entry, rootModule));
193-
194-
return rootModule;
195187
};

0 commit comments

Comments
 (0)