forked from nodejs/doc-kit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.mjs
More file actions
141 lines (120 loc) · 5.18 KB
/
index.mjs
File metadata and controls
141 lines (120 loc) · 5.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
'use strict';
import yaml from 'yaml';
import {
DOC_API_HEADING_TYPES,
DOC_MDN_BASE_URL_JS_GLOBALS,
DOC_MDN_BASE_URL_JS_PRIMITIVES,
DOC_TYPES_MAPPING_GLOBALS,
DOC_TYPES_MAPPING_NODE_MODULES,
DOC_TYPES_MAPPING_OTHER,
DOC_TYPES_MAPPING_PRIMITIVES,
} from './constants.mjs';
/**
* This method replaces plain text Types within the Markdown content into Markdown links
* that link to the actual relevant reference for such type (either internal or external link)
*
* @param {string} type The plain type to be transformed into a Markdown link
* @returns {string} The Markdown link as a string (formatted in Markdown)
*/
export const transformTypeToReferenceLink = type => {
// Removes the wrapping tags that wrap the type references such as `<>` and `{}`
const typeInput = type.replace(/[{}<>]/g, '');
/**
* Handles the mapping (if there's a match) of the input text
* into the reference type from the API docs
*
* @param {string} lookupPiece
* @returns {string} The reference URL or empty string if no match
*/
const transformType = lookupPiece => {
// Transform JS primitive type references into Markdown links (MDN)
if (lookupPiece.toLowerCase() in DOC_TYPES_MAPPING_PRIMITIVES) {
const typeValue = DOC_TYPES_MAPPING_PRIMITIVES[lookupPiece.toLowerCase()];
return `${DOC_MDN_BASE_URL_JS_PRIMITIVES}#${typeValue}_type`;
}
// Transforms JS Global type references into Markdown links (MDN)
if (lookupPiece in DOC_TYPES_MAPPING_GLOBALS) {
return `${DOC_MDN_BASE_URL_JS_GLOBALS}${lookupPiece}`;
}
// Transform other external Web/JavaScript type references into Markdown links
// to diverse different external websites. These already are formatted as links
if (lookupPiece in DOC_TYPES_MAPPING_OTHER) {
return DOC_TYPES_MAPPING_OTHER[lookupPiece];
}
// Transform Node.js type/module references into Markdown links
// that refer to other API docs pages within the Node.js API docs
if (lookupPiece in DOC_TYPES_MAPPING_NODE_MODULES) {
return DOC_TYPES_MAPPING_NODE_MODULES[lookupPiece];
}
return '';
};
const typePieces = typeInput.split('|').map(piece => {
// This is the content to render as the text of the Markdown link
const trimmedPiece = piece.trim();
// This is what we will compare against the API types mappings
// The ReGeX below is used to remove `[]` from the end of the type
const result = transformType(trimmedPiece.replace('[]', ''));
// If we have a valid result and the piece is not empty, we return the Markdown link
if (trimmedPiece.length && result.length) {
return `[\`<${trimmedPiece}>\`](${result})`;
}
});
// Filter out pieces that we failed to map and then join the valid ones
// into different links separated by a ` | `
const markdownLinks = typePieces.filter(Boolean).join(' | ');
// Return the replaced links or the original content if they all failed to be replaced
// Note that if some failed to get replaced, only the valid ones will be returned
// If no valid entry exists, we return the original string/type
return markdownLinks || type;
};
/**
* Parses Markdown YAML source into a JavaScript object containing all the metadata
* (this is forwarded to the parser so it knows what to do with said metadata)
*
* @param {string} yamlString The YAML string to be parsed
* @returns {ApiDocRawMetadataEntry} The parsed YAML metadata
*/
export const parseYAMLIntoMetadata = yamlString => {
const replacedContent = yamlString
// special validations for some non-cool formatted properties of the docs schema
.replace('introduced_in=', 'introduced_in: ')
.replace('source_link=', 'source_link: ')
.replace('type=', 'type: ')
.replace('name=', 'name: ')
.replace('llm_description=', 'llm_description: ');
// Ensures that the parsed YAML is an object, because even if it is not
// i.e. a plain string or an array, it will simply not result into anything
/** @type {ApiDocRawMetadataEntry | string} */
let parsedYaml = yaml.parse(replacedContent);
// Ensure that only Objects get parsed on Object.keys(), since some `<!--`
// comments, might be just plain strings and not even a valid YAML metadata
if (typeof parsedYaml === 'string') {
parsedYaml = { tags: [parsedYaml] };
}
return parsedYaml;
};
/**
* Parses a raw Heading string into Heading metadata
*
* @param {string} heading The raw Heading text
* @param {number} depth The depth of the heading
* @returns {HeadingMetadataEntry} Parsed Heading entry
*/
export const parseHeadingIntoMetadata = (heading, depth) => {
for (const { type, regex } of DOC_API_HEADING_TYPES) {
// Attempts to get a match from one of the heading types, if a match is found
// we use that type as the heading type, and extract the regex expression match group
// which should be the inner "plain" heading content (or the title of the heading for navigation)
const [, ...matches] = heading.match(regex) ?? [];
if (matches?.length) {
return {
text: heading,
type,
// The highest match group should be used.
name: matches.filter(Boolean).at(-1),
depth,
};
}
}
return { text: heading, name: heading, depth };
};