Skip to content

Commit

Permalink
code review (1)
Browse files Browse the repository at this point in the history
  • Loading branch information
RedYetiDev committed Nov 18, 2024
1 parent 3a4b27b commit 35e6f58
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 89 deletions.
6 changes: 6 additions & 0 deletions src/generators/legacy-json-all/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { writeFile } from 'node:fs/promises';
import { join } from 'node:path';

/**
* This generator consolidates data from the `legacy-json` generator into a single
* JSON file (`all.json`).
*
* @typedef {Array<import('../legacy-json/types.d.ts').Section>} Input
*
* @type {import('../types.d.ts').GeneratorMetadata<Input, import('./types.d.ts').Output>}
Expand All @@ -20,6 +23,9 @@ export default {

async generate(input, { output }) {
/**
* The consolidated output object that will contain
* combined data from all sections in the input.
*
* @type {import('./types.d.ts').Output}
*/
const generatedValue = {
Expand Down
71 changes: 40 additions & 31 deletions src/generators/legacy-json/utils/buildSection.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ function parseListItem(child, entry) {

// Recursively parse nested options if a list is found within the list item
const optionsNode = child.children.find(child => child.type === 'list');

if (optionsNode) {
current.options = optionsNode.children.map(child =>
parseListItem(child, entry)
Expand Down Expand Up @@ -175,6 +176,7 @@ function parseStability(section, nodes) {
*/
function parseList(section, nodes, entry) {
const list = nodes[0]?.type === 'list' ? nodes.shift() : null;

const values = list
? list.children.map(child => parseListItem(child, entry))
: [];
Expand All @@ -188,7 +190,8 @@ function parseList(section, nodes, entry) {
case 'property':
if (values.length) {
const { type, ...rest } = values[0];
if (type) section.propertySigType = type;

section.type = type;
Object.assign(section, rest);
section.textRaw = `\`${section.name}\` ${section.textRaw}`;
}
Expand All @@ -197,26 +200,35 @@ function parseList(section, nodes, entry) {
section.params = values;
break;
default:
if (list) nodes.unshift(list); // If the list wasn't processed, add it back for further processing
// If the list wasn't processed, add it back for further processing
if (list) {
nodes.unshift(list);
}
}
}

let lazyHTML;

/**
* Adds a description to the section.
* @param {import('../types.d.ts').Section} section - The section to add description to.
* @param {Array} nodes - The AST nodes.
*/
function addDescription(section, nodes) {
if (!nodes.length) return;
if (!nodes.length) {
return;
}

if (section.desc) {
section.shortDesc = section.desc;
}

const html = getRemarkRehype();
const rendered = html.stringify(
html.runSync({ type: 'root', children: nodes })
lazyHTML ??= getRemarkRehype();

const rendered = lazyHTML.stringify(
lazyHTML.runSync({ type: 'root', children: nodes })
);

section.desc = rendered || undefined;
}

Expand All @@ -241,32 +253,38 @@ function addAdditionalMetadata(section, parentSection, headingNode) {
*/
function addToParent(section, parentSection) {
const pluralType = sectionTypePlurals[section.type];

parentSection[pluralType] = parentSection[pluralType] || [];
parentSection[pluralType].push(section);
}

const notTransferredKeys = ['textRaw', 'name', 'type', 'desc', 'miscs'];

/**
* Promotes children to top-level if the section type is 'misc'.
* Promotes children properties to the parent level if the section type is 'misc'.
*
* @param {import('../types.d.ts').Section} section - The section to promote.
* @param {import('../types.d.ts').Section} parentSection - The parent section.
*/
const makeChildrenTopLevelIfMisc = (section, parentSection) => {
if (section.type !== 'misc' || parentSection.type === 'misc') {
return;
// Only promote if the current section is of type 'misc' and the parent is not 'misc'
if (section.type === 'misc' && parentSection.type !== 'misc') {
Object.entries(section).forEach(([key, value]) => {
// Skip keys that should not be transferred
if (notTransferredKeys.includes(key)) return;

// Merge the section's properties into the parent section
parentSection[key] = parentSection[key]
? // If the parent already has this key, concatenate the values
[].concat(parentSection[key], value)
: // Otherwise, directly assign the section's value to the parent
value;
});
}
};

Object.keys(section).forEach(key => {
if (['textRaw', 'name', 'type', 'desc', 'miscs'].includes(key)) {
return;
}
if (parentSection[key]) {
parentSection[key] = Array.isArray(parentSection[key])
? parentSection[key].concat(section[key])
: section[key];
} else {
parentSection[key] = section[key];
}
});
const handleChildren = (entry, section) => {
entry.hierarchyChildren?.forEach(child => handleEntry(child, section));
};

/**
Expand All @@ -281,19 +299,10 @@ function handleEntry(entry, parentSection) {
parseStability(section, nodes);
parseList(section, nodes, entry);
addDescription(section, nodes);
entry.hierarchyChildren?.forEach(child => handleEntry(child, section));
handleChildren(entry, section);
addAdditionalMetadata(section, parentSection, headingNode);
addToParent(section, parentSection);
makeChildrenTopLevelIfMisc(section, parentSection);

if (section.type === 'property') {
if (section.propertySigType) {
section.type = section.propertySigType;
delete section.propertySigType;
} else {
delete section.type;
}
}
}

/**
Expand Down
95 changes: 48 additions & 47 deletions src/generators/legacy-json/utils/parseSignature.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import { PARAM_EXPRESSION } from '../constants.mjs';

const OPTIONAL_LEVEL_CHANGES = { '[': 1, ']': -1, ' ': 0 };

/**
* @param {String} char
* @param {Number} depth
* @returns {Number}
*/
const updateDepth = (char, depth) =>
depth + (OPTIONAL_LEVEL_CHANGES[char] || 0);

/**
* @param {string} parameterName
* @param {number} optionalDepth
Expand All @@ -14,36 +22,34 @@ function parseNameAndOptionalStatus(parameterName, optionalDepth) {
// We need to see if there's any leading brackets in front of the parameter
// name. While we're doing that, we can also get the index where the
// parameter's name actually starts at.
let startingIdx = 0;
for (; startingIdx < parameterName.length; startingIdx++) {
const levelChange = OPTIONAL_LEVEL_CHANGES[parameterName[startingIdx]];

if (!levelChange) {
break;
}

optionalDepth += levelChange;
}

// Find the starting index where the name begins
const startingIdx = [...parameterName].findIndex(
char => !OPTIONAL_LEVEL_CHANGES[char]
);

// Update optionalDepth based on leading brackets
optionalDepth = [...parameterName.slice(0, startingIdx)].reduce(
updateDepth,
optionalDepth
);

// Find the ending index where the name ends
const endingIdx = [...parameterName].findLastIndex(
char => !OPTIONAL_LEVEL_CHANGES[char]
);

// Update optionalDepth based on trailing brackets
optionalDepth = [...parameterName.slice(endingIdx + 1)].reduce(
updateDepth,
optionalDepth
);

// Extract the actual parameter name
const actualName = parameterName.slice(startingIdx, endingIdx + 1);
const isParameterOptional = optionalDepth > 0;

// Now let's check for any trailing brackets at the end of the parameter's
// name. This will tell us where the parameter's name ends.
let endingIdx = parameterName.length - 1;
for (; endingIdx >= 0; endingIdx--) {
const levelChange = OPTIONAL_LEVEL_CHANGES[parameterName[endingIdx]];
if (!levelChange) {
break;
}

optionalDepth += levelChange;
}

return [
parameterName.substring(startingIdx, endingIdx + 1),
optionalDepth,
isParameterOptional,
];
return [actualName, optionalDepth, isParameterOptional];
}

/**
Expand All @@ -55,8 +61,8 @@ function parseDefaultValue(parameterName) {
* @type {string | undefined}
*/
let defaultValue;

const equalSignPos = parameterName.indexOf('=');

if (equalSignPos !== -1) {
// We do have a default value, let's extract it
defaultValue = parameterName.substring(equalSignPos).trim();
Expand All @@ -75,34 +81,29 @@ function parseDefaultValue(parameterName) {
* @returns {import('../types.d.ts').Parameter}
*/
function findParameter(parameterName, index, markdownParameters) {
let parameter = markdownParameters[index];
if (parameter && parameter.name === parameterName) {
const parameter = markdownParameters[index];
if (parameter?.name === parameterName) {
return parameter;
}

// Method likely has multiple signatures, something like
// `new Console(stdout[, stderr][, ignoreErrors])` and `new Console(options)`
// Try to find the parameter that this is being shared with
for (const markdownProperty of markdownParameters) {
if (markdownProperty.name === parameterName) {
// Found it
return markdownParameters;
} else if (markdownProperty.options) {
for (const option of markdownProperty.options) {
if (option.name === parameterName) {
// Found a matching one in the parameter's options
return Object.assign({}, option);
}
}
for (const property of markdownParameters) {
if (property.name === parameterName) {
return property;
}
}

// At this point, we couldn't find a shared signature
if (parameterName.startsWith('...')) {
return { name: parameterName };
} else {
throw new Error(`Invalid param "${parameterName}"`);
const matchingOption = property.options?.find(
option => option.name === parameterName
);
if (matchingOption) {
return { ...matchingOption };
}
}

// Default return if no matches are found
return { name: parameterName };
}

/**
Expand Down
14 changes: 3 additions & 11 deletions src/metadata.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,8 @@ const createMetadata = slugger => {
internalMetadata.stability.toJSON = () =>
internalMetadata.stability.children.map(node => node.data);

/**
* @type {ApiDocMetadataEntry}
*/
const value = {
// Returns the Metadata entry for the API doc
return {
api: apiDoc.stem,
slug: sectionSlug,
source_link,
Expand All @@ -156,15 +154,9 @@ const createMetadata = slugger => {
stability: internalMetadata.stability,
content: section,
tags,
introduced_in,
rawContent: apiDoc.toString(),
};

if (introduced_in) {
value.introduced_in = introduced_in;
}

// Returns the Metadata entry for the API doc
return value;
},
};
};
Expand Down
3 changes: 3 additions & 0 deletions src/queries.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ const createQueries = () => {
transformTypeToReferenceLink
);

// This changes the type into a link by splitting it up
// into several nodes, and adding those nodes to the
// parent.
const {
children: [newNode],
} = remark.parse(replacedTypes);
Expand Down
1 change: 1 addition & 0 deletions src/test/metadata.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ describe('createMetadata', () => {
deprecated_in: undefined,
heading,
n_api_version: undefined,
introduced_in: undefined,
rawContent: '',
removed_in: undefined,
slug: 'test-heading',
Expand Down
1 change: 1 addition & 0 deletions src/utils/parser.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export const parseHeadingIntoMetadata = (heading, depth) => {
return {
text: heading,
type,
// The highest match group should be used.
name: matches.filter(Boolean).at(-1),
depth,
};
Expand Down

0 comments on commit 35e6f58

Please sign in to comment.