1
1
'use strict' ;
2
2
3
+ import { h as createElement } from 'hastscript' ;
3
4
import { u as createTree } from 'unist-builder' ;
4
5
5
- import {
6
- DOC_API_STABILITY_SECTION_REF_URL ,
7
- DOC_NODE_BLOB_BASE_URL ,
8
- } from '../../../constants.mjs' ;
9
-
10
- // The regular expression to match the Stability Index prefix
11
- const STABILITY_INDEX_PREFIX_REGEX = / S t a b i l i t y : ( [ 0 - 5 ] ) / ;
6
+ import { DOC_NODE_BLOB_BASE_URL } from '../../../constants.mjs' ;
12
7
13
8
/**
14
9
* Builds a Markdown heading for a given node
15
10
*
16
11
* @param {ApiDocMetadataEntry } node The node to build the Markdown heading for
12
+ * @returns {import('unist').Parent } The HTML AST tree of the heading content
17
13
*/
18
- const buildNodeHeading = node => {
14
+ const buildHeadingElement = node => {
19
15
const [ , headingId ] = node . slug . split ( '#' ) ;
20
16
21
- // Creates the anchor element for the heading (floats on the right side)
22
- const anchor = `<span><a class="mark" href="#${ headingId } " id="${ headingId } ">#</a></span>` ;
17
+ // Creates the element that references the link to the heading
18
+ const headingLinkElement = createElement (
19
+ 'span' ,
20
+ createElement ( 'a.mark#headingId' , { href : `#${ headingId } ` } , '#' )
21
+ ) ;
23
22
24
- // The extra `\n` (new lines) are done to ensure that remark parses Markdown within HTML
25
- // as it would normally do, as it would not parse it if it were in the same line
26
- return `<h${ node . heading . depth + 1 } >\n\n${ node . heading . text } ${ anchor } \n\n</h${ node . heading . depth + 1 } >` ;
23
+ // Creates the heading element with the heading text and the link to the heading
24
+ return createElement ( `h${ node . heading . depth + 1 } ` , [
25
+ node . heading . text ,
26
+ headingLinkElement ,
27
+ ] ) ;
27
28
} ;
28
29
29
30
/**
30
31
* Builds a Markdown Stability Index
31
32
*
32
33
* @param {ApiDocMetadataEntry } node The node to build the Markdown Stability Index for
33
34
* @param {import('remark').remark } remark The Remark instance to be used to process
35
+ * @returns {import('unist').Parent } The AST tree of the Stability Index content
34
36
*/
35
- const buildStabilityIndex = ( node , remark ) => {
36
- // Iterates through the Stability Indexes to build the content
37
- return node . stability . children . reduce ( ( acc , stabilityNode ) => {
38
- // Transforms the Stability Index AST nodes into a HTML string
39
- let stabilityIndex = remark . stringify ( remark . runSync ( stabilityNode ) ) ;
40
-
41
- // If the current node being processed is not the documentation node, we
42
- // define a link to the Stability Index section in the documentation
43
- // as they are originally referenced within the `documentation` node.
44
- if ( node . api !== 'documentation' ) {
45
- stabilityIndex = stabilityIndex . replace (
46
- STABILITY_INDEX_PREFIX_REGEX ,
47
- match => `<a href="${ DOC_API_STABILITY_SECTION_REF_URL } ">${ match } </a>`
48
- ) ;
49
- }
50
-
51
- // Wraps the inner content with an HTML div to apply the CSS styles
52
- acc += `<div class="api_stability api_stability_${ stabilityNode . data . index } ">${ stabilityIndex } </div>` ;
53
-
54
- return acc ;
55
- } , '' ) ;
37
+ const buildStabilityIndexes = ( node , remark ) => {
38
+ // Iterates over each stability index to create a `div` element with the stability index class
39
+ const parsedStabilityIndexes = node . stability . children . map ( stabilityNode =>
40
+ createElement (
41
+ // Creates the `div` element with the class `api_stability` and the stability index class
42
+ `div.api_stability.api_stability_${ stabilityNode . data . index } ` ,
43
+ // Processed the Markdown nodes into HTML nodes
44
+ remark . runSync ( stabilityNode ) . children
45
+ )
46
+ ) ;
47
+
48
+ // Creates a tree to surround the Stability Indexes
49
+ return createTree ( 'root' , parsedStabilityIndexes ) ;
56
50
} ;
57
51
58
52
/**
59
53
* Builds the Metadata Properties into content
60
54
*
61
55
* @param {ApiDocMetadataEntry } node The node to build to build the properties from
56
+ * @returns {import('unist').Parent } The HTML AST tree of the properties content
62
57
*/
63
- const buildProperties = node => {
64
- let metadataSection = '< div class=" api_metadata">' ;
58
+ const buildMetadataElement = node => {
59
+ const metadataElement = createElement ( ' div. api_metadata' ) ;
65
60
66
61
// We use a `span` element to display the source link as a clickable link to the source within Node.js
67
62
if ( node . sourceLink && node . sourceLink . length ) {
68
- metadataSection +=
69
- `<span><b>Source Code:</b> ` +
70
- `<a href="${ DOC_NODE_BLOB_BASE_URL } ${ node . sourceLink } ">${ node . sourceLink } ` +
71
- `</a></span>` ;
63
+ // Creates the source link URL with the base URL and the source link
64
+ const sourceLink = `${ DOC_NODE_BLOB_BASE_URL } ${ node . sourceLink } ` ;
65
+
66
+ // Creates the source link element with the source link and the source link text
67
+ const sourceLinkElement = createElement ( 'span' , [
68
+ createElement ( 'b' , 'Source Code: ' ) ,
69
+ createElement ( 'a' , { href : sourceLink } , node . sourceLink ) ,
70
+ ] ) ;
71
+
72
+ // Appends the source link element to the metadata element
73
+ metadataElement . children . push ( sourceLinkElement ) ;
72
74
}
73
75
74
76
// If there are changes, we create a `details` element with a `table` element to display the changes
75
77
// Differently from the old API docs, on this version we always enforce a table to display the changes
76
78
if ( node . changes && node . changes . length ) {
77
- const mapChangesIntoTable = node . changes . map (
78
- ( { version, description } ) =>
79
- // We use double `\n` to ensure that the Markdown is correctly parsed
80
- `<tr><td>${ version . join ( ', ' ) } </td><td>\n\n${ description } \n\n</td></tr>`
79
+ // Maps the changes into a `tr` element with the version and the description
80
+ const mappedHistoryEntries = node . changes . map ( ( { version, description } ) =>
81
+ createElement ( 'tr' , [
82
+ createElement ( 'td' , version . join ( ', ' ) ) ,
83
+ createElement ( 'td' , description ) ,
84
+ ] )
81
85
) ;
82
86
83
- metadataSection +=
84
- `<details class="changelog"><summary>History</summary><table>` +
85
- `<thead><tr><th>Version</th><th>Changes</th></tr></thead>` +
86
- `<tbody>${ mapChangesIntoTable . reverse ( ) . join ( '\n' ) } </tbody></table></details>` ;
87
+ // Creates the history details element with a summary and a table with the changes
88
+ const historyDetailsElement = createElement ( 'details.changelog' , [
89
+ createElement ( 'summary' , 'History' ) ,
90
+ createElement ( 'table' , [
91
+ createElement ( 'thead' , [
92
+ createElement ( 'tr' , [
93
+ createElement ( 'th' , 'Version' ) ,
94
+ createElement ( 'th' , 'Changes' ) ,
95
+ ] ) ,
96
+ ] ) ,
97
+ createElement ( 'tbody' , mappedHistoryEntries ) ,
98
+ ] ) ,
99
+ ] ) ;
100
+
101
+ // Appends the history details element to the metadata element
102
+ metadataElement . children . push ( historyDetailsElement ) ;
87
103
}
88
104
89
- metadataSection += '</div>' ;
90
-
91
- return metadataSection ;
92
- } ;
93
-
94
- /**
95
- * Builds the aggregated Markdown metadata content for a given node
96
- *
97
- * @param {ApiDocMetadataEntry } node Builds the content of a given node
98
- * @param {import('remark').remark } remark The Remark instance to be used to process
99
- */
100
- const buildMetadata = ( node , remark ) => {
101
- const heading = buildNodeHeading ( node ) ;
102
- const stabilityIndeex = buildStabilityIndex ( node , remark ) ;
103
- const properties = buildProperties ( node ) ;
104
-
105
- // Concatenates all the strings and parses with remark into an AST tree
106
- return remark . parse ( `${ heading } ${ stabilityIndeex } ${ properties } ` ) ;
105
+ // Parses and processes the mixed Markdonw/HTML content into an HTML AST tree
106
+ return metadataElement ;
107
107
} ;
108
108
109
109
/**
@@ -116,23 +116,23 @@ export default (nodes, remark) => {
116
116
'root' ,
117
117
// Parses the metadata pieces of each node and the content
118
118
nodes . map ( node => {
119
- // Parses the metadata into AST, since it they are strings
120
- const parsedMetadata = buildMetadata ( node , remark ) ;
121
-
122
- // aggregate the two AST trees to then be parsed by runSync
123
- return createTree ( 'root' , [ parsedMetadata , node . content ] ) ;
119
+ const headingElement = buildHeadingElement ( node ) ;
120
+ const metadataElement = buildMetadataElement ( node ) ;
121
+ const stabilityIndexes = buildStabilityIndexes ( node , remark ) ;
122
+
123
+ // Processes the Markdown AST tree into an HTML AST tree
124
+ const processedContent = remark . runSync ( node . content ) ;
125
+
126
+ // Concatenates all the strings and parses with remark into an AST tree
127
+ return createElement ( 'section' , [
128
+ headingElement ,
129
+ metadataElement ,
130
+ ...stabilityIndexes . children ,
131
+ ...processedContent . children ,
132
+ ] ) ;
124
133
} )
125
134
) ;
126
135
127
- // Processes the nodes to ensure that the Markdown is correctly parsed
128
- const processedNodes = remark . runSync ( parsedNodes ) ;
129
-
130
- // We transform the outer `div` elements into `section` elements
131
- // This is done to ensure that each section is an actual section in the HTML
132
- processedNodes . children . forEach ( node => {
133
- node . tagName = node . tagName === 'div' ? 'section' : node . tagName ;
134
- } ) ;
135
-
136
136
// Stringifies the processed nodes to return the final Markdown content
137
- return remark . stringify ( processedNodes ) ;
137
+ return remark . stringify ( parsedNodes ) ;
138
138
} ;
0 commit comments