@@ -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 */
2628const 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