11'use strict' ;
22
3- // External dependencies
43import { h as createElement } from 'hastscript' ;
54import { u as createTree } from 'unist-builder' ;
65import { SKIP , visit } from 'unist-util-visit' ;
6+ import { rcompare } from 'semver' ;
77
8- // Internal dependencies
9- import createQueries from '../../../utils/queries/index.mjs' ;
8+ import { UNIST } from '../../../utils/queries/index.mjs' ;
109import { createJSXElement } from './ast.mjs' ;
1110import { ICON_SYMBOL_MAP , STABILITY_LEVELS } from '../constants.mjs' ;
1211import { DOC_NODE_BLOB_BASE_URL } from '../../../constants.mjs' ;
12+ import { enforceArray } from '../../../utils/generators.mjs' ;
1313
1414/**
1515 * Transforms a stability node into an AlertBox JSX element
@@ -28,28 +28,75 @@ function visitStabilityNode(node, index, parent) {
2828}
2929
3030/**
31- * Adds the metadata around the header node
31+ * Builds a history of changes for an API element
3232 *
33- * @param {ApiDocMetadataEntry } entry - The content object to process
34- * @param {import('mdast').Heading } node - The stability node to transform
33+ * @param {ApiDocMetadataEntry } entry - The metadata entry containing change information
34+ */
35+ function buildChangeElement ( entry ) {
36+ // Create change entries from version fields (added, deprecated, etc.)
37+ const changeTypes = {
38+ added_in : 'Added in' ,
39+ deprecated_in : 'Deprecated in' ,
40+ removed_in : 'Removed in' ,
41+ introduced_in : 'Introduced in' ,
42+ } ;
43+
44+ const history = Object . entries ( changeTypes )
45+ . filter ( ( [ field ] ) => entry [ field ] )
46+ . map ( ( [ field , label ] ) => {
47+ const versions = enforceArray ( entry [ field ] ) ;
48+ return {
49+ versions,
50+ label : `${ label } : ${ versions . join ( ', ' ) } ` ,
51+ } ;
52+ } ) ;
53+
54+ // Add explicit changes
55+ if ( entry . changes ) {
56+ const changesHistory = entry . changes . map ( change => ( {
57+ versions : enforceArray ( change . version ) ,
58+ label : change . description ,
59+ url : change [ 'pr-url' ] ,
60+ } ) ) ;
61+ history . push ( ...changesHistory ) ;
62+ }
63+
64+ // Sort by version, newest first
65+ return createJSXElement ( 'ChangeHistory' , {
66+ changes : history . sort ( ( a , b ) => rcompare ( a . versions [ 0 ] , b . versions [ 0 ] ) ) ,
67+ } ) ;
68+ }
69+
70+ /**
71+ * Enhances a heading node with metadata, source links, and styling
72+ *
73+ * @param {ApiDocMetadataEntry } entry - The API metadata entry
74+ * @param {import('mdast').Heading } node - The heading node to transform
3575 * @param {number } index - The index of the node in its parent's children array
36- * @param {import('unist').Node } parent - The parent node containing the stability node
76+ * @param {import('unist').Node } parent - The parent node containing the heading
3777 */
38- function visitHeadingNode ( entry , { data, children } , index , parent ) {
39- console . error ( data ) ;
78+ function visitHeadingNode ( entry , node , index , parent ) {
79+ const { data, children } = node ;
80+ const headerChildren = [
81+ createElement ( `h${ data . depth + 1 } ` , [
82+ createElement ( `a.mark#${ data . slug } ` , { href : `#${ data . slug } ` } , children ) ,
83+ ] ) ,
84+ ] ;
85+
4086 // Add type icon if available
4187 if ( ICON_SYMBOL_MAP [ data . type ] ) {
42- // TODO: This hasn't been implemented yet. This is an assumption of what a
43- // potential implementation could look like
44- children . unshift (
88+ headerChildren . unshift (
4589 createJSXElement ( 'CircularIcon' , ICON_SYMBOL_MAP [ data . type ] )
4690 ) ;
4791 }
4892
49- // Replace node with proper heading and anchor
50- parent . children [ index ] = createElement ( `h${ data . depth + 1 } ` , [
51- createElement ( `a.mark#${ data . slug } ` , { href : `#${ data . slug } ` } , children ) ,
52- ] ) ;
93+ const changeElement = buildChangeElement ( entry ) ;
94+ if ( changeElement ) {
95+ headerChildren . push ( changeElement ) ;
96+ }
97+
98+ // Replace node with new heading and anchor
99+ parent . children [ index ] = createElement ( 'div' , headerChildren ) ;
53100
54101 // Add source link if available
55102 if ( entry . source_link ) {
@@ -71,14 +118,13 @@ function visitHeadingNode(entry, { data, children }, index, parent) {
71118}
72119
73120/**
74- * Processes content by transforming stability nodes
121+ * Processes an API documentation entry by applying transformations to its content
75122 *
76- * @param {ApiDocMetadataEntry } entry - The entry
123+ * @param {ApiDocMetadataEntry } entry - The API metadata entry to process
77124 */
78125function process ( entry ) {
79- // Create a shallow copy to avoid modifying the original
126+ // Create a deep copy to avoid modifying the original
80127 const content = structuredClone ( entry . content ) ;
81- const { UNIST } = createQueries ;
82128
83129 // Apply all transformations to the content
84130 visit ( content , UNIST . isStabilityNode , visitStabilityNode ) ;
@@ -92,10 +138,23 @@ function process(entry) {
92138/**
93139 * Transforms API metadata entries into processed MDX content
94140 *
95- * @param {Array< ApiDocMetadataEntry> } metadataEntries - API documentation metadata entries
141+ * @param {ApiDocMetadataEntry[] } metadataEntries - API documentation metadata entries
96142 * @param {import('unified').Processor } remark - Remark processor instance for markdown processing
97143 */
98144export default function buildContent ( metadataEntries , remark ) {
99- const rootNode = createTree ( 'root' , metadataEntries . map ( process ) ) ;
100- return remark . stringify ( remark . runSync ( rootNode ) ) ;
145+ const root = createTree ( 'root' , [
146+ createJSXElement ( 'NavBar' ) ,
147+ createJSXElement ( 'MainLayout' , {
148+ children : [
149+ createJSXElement ( 'SideBar' ) ,
150+ createElement ( 'div' , [
151+ createElement ( 'main' , metadataEntries . map ( process ) ) ,
152+ createElement ( 'MetaBar' ) ,
153+ ] ) ,
154+ createJSXElement ( 'Footer' ) ,
155+ ] ,
156+ } ) ,
157+ ] ) ;
158+
159+ return remark . stringify ( remark . runSync ( root ) ) ;
101160}
0 commit comments