@@ -49,23 +49,30 @@ const svgElementsMap = new Map([[GLOBAL_SVG_ATTRIBUTES_NAME, 'SVGElement']]);
4949const mathmlElementsMap = new Map ( ) ;
5050
5151traverse ( ast , {
52- TSInterfaceDeclaration : function ( path ) {
53- if ( path . node . id . name === 'HTMLElementTagNameMap' ) {
54- const items = path . node . body . body ;
55- for ( const item of items ) {
56- htmlElementsMap . set ( item . key . value , item . typeAnnotation . typeAnnotation . typeName . name ) ;
52+ TSInterfaceDeclaration ( path ) {
53+ switch ( path . node . id . name ) {
54+ case 'HTMLElementTagNameMap' : {
55+ path . node . body . body . forEach ( ( { key, typeAnnotation } ) => {
56+ htmlElementsMap . set ( key . value , typeAnnotation . typeAnnotation . typeName . name ) ;
57+ } ) ;
58+
59+ break ;
5760 }
58- }
59- if ( path . node . id . name === 'SVGElementTagNameMap' ) {
60- const items = path . node . body . body ;
61- for ( const item of items ) {
62- svgElementsMap . set ( item . key . value , item . typeAnnotation . typeAnnotation . typeName . name ) ;
61+
62+ case 'MathMLElementTagNameMap' : {
63+ path . node . body . body . forEach ( ( { key, typeAnnotation } ) => {
64+ mathmlElementsMap . set ( key . value , typeAnnotation . typeAnnotation . typeName . name ) ;
65+ } ) ;
66+
67+ break ;
6368 }
64- }
65- if ( path . node . id . name === 'MathMLElementTagNameMap' ) {
66- const items = path . node . body . body ;
67- for ( const item of items ) {
68- mathmlElementsMap . set ( item . key . value , item . typeAnnotation . typeAnnotation . typeName . name ) ;
69+
70+ case 'SVGElementTagNameMap' : {
71+ path . node . body . body . forEach ( ( { key, typeAnnotation } ) => {
72+ svgElementsMap . set ( key . value , typeAnnotation . typeAnnotation . typeName . name ) ;
73+ } ) ;
74+
75+ break ;
6976 }
7077 }
7178 } ,
@@ -81,22 +88,17 @@ function createAriaAttributesInterface() {
8188}
8289
8390function createHtmlElementsAttributesMap ( ) {
84- let htmlElementsContent = `
85- import { AttrValue } from '../index';
91+ let htmlElementsContent = [
92+ `import { AttrValue } from '../index';` ,
93+ `` ,
94+ `declare global {` ,
95+ `` ,
96+ ] . join ( '\n' ) ;
8697
87- declare global {
88- ` ;
8998 const processed = new Set ( ) ;
9099
91100 htmlElementsContent += createAriaAttributesInterface ( ) ;
92101
93- let mergedHtmlElements = `
94- /**
95- * @internal
96- * @private - not for use outside of Glint
97- */
98- interface GlintHtmlElementAttributesMap {\n` ;
99-
100102 function emitAttributeInterface ( type , keys , name ) {
101103 if ( ! type || processed . has ( type ) ) return ;
102104 processed . add ( type ) ;
@@ -125,49 +127,69 @@ interface GlintHtmlElementAttributesMap {\n`;
125127 htmlElementsContent += '}\n' ;
126128 }
127129
128- function addMapEntry ( type ) {
129- const interfaceName =
130- type === 'HTMLElement' ? GLOBAL_HTML_ATTRIBUTES_NAME : type + 'Attributes' ;
131- mergedHtmlElements += ` ['${ type } ']: ${ interfaceName } ;\n` ;
132- }
130+ let elementToAttributes = new Map ( ) ;
133131
134- Object . entries ( htmlElementAttributes ) . forEach ( ( [ name , keys ] ) => {
135- if ( name === '*' ) {
136- name = GLOBAL_HTML_ATTRIBUTES_NAME ;
137- htmlElementsMap . set ( name , 'GlobalHTML' ) ;
132+ Object . entries ( htmlElementAttributes ) . forEach ( ( [ elementName , keys ] ) => {
133+ if ( elementName === '*' ) {
134+ elementName = GLOBAL_HTML_ATTRIBUTES_NAME ;
135+ htmlElementsMap . set ( elementName , 'GlobalHTML' ) ;
138136 }
139- if ( SKIP . has ( name ) ) return ;
140- const type = htmlElementsMap . get ( name ) ;
141137
142- if ( ! type ) return ;
138+ if ( SKIP . has ( elementName ) ) {
139+ return ;
140+ }
143141
144- emitAttributeInterface ( type , keys , name ) ;
142+ const elementType = htmlElementsMap . get ( elementName ) ;
143+
144+ if ( ! elementType ) {
145+ return ;
146+ }
147+
148+ emitAttributeInterface ( elementType , keys , elementName ) ;
145149
146150 // Not an element, but we use this prefix for attributes
147- if ( type === 'GlobalHTML' ) return ;
151+ if ( elementType === 'GlobalHTML' ) {
152+ return ;
153+ }
148154
149- addMapEntry ( type ) ;
155+ elementToAttributes . set ( elementType , ` ${ elementType } Attributes` ) ;
150156 } ) ;
151- emitAttributeInterface ( 'HTMLElement' , [ ] , 'HTMLElement' ) ;
152- addMapEntry ( 'HTMLElement' ) ;
153157
154- mergedHtmlElements += `}\n` ;
158+ emitAttributeInterface ( 'HTMLElement' , [ ] , 'HTMLElement' ) ;
159+ elementToAttributes . set ( 'HTMLElement' , GLOBAL_HTML_ATTRIBUTES_NAME ) ;
160+
161+ // Manually add entries
162+ elementToAttributes . set ( 'HTMLBodyElement' , GLOBAL_HTML_ATTRIBUTES_NAME ) ;
163+ elementToAttributes . set ( 'HTMLDataListElement' , GLOBAL_HTML_ATTRIBUTES_NAME ) ;
164+ elementToAttributes . set ( 'HTMLHtmlElement' , GLOBAL_HTML_ATTRIBUTES_NAME ) ;
165+ elementToAttributes . set ( 'HTMLPictureElement' , GLOBAL_HTML_ATTRIBUTES_NAME ) ;
166+ elementToAttributes . set ( 'HTMLSpanElement' , GLOBAL_HTML_ATTRIBUTES_NAME ) ;
167+ elementToAttributes . set ( 'HTMLTitleElement' , GLOBAL_HTML_ATTRIBUTES_NAME ) ;
168+
169+ // Sort by element type
170+ elementToAttributes = new Map ( [ ...elementToAttributes ] . sort ( ) ) ;
171+
172+ htmlElementsContent += [
173+ `/**` ,
174+ ` * @internal` ,
175+ ` * @private - not for use outside of Glint` ,
176+ ` */` ,
177+ `interface GlintHtmlElementAttributesMap {` ,
178+ ...Array . from ( elementToAttributes . entries ( ) ) . map ( ( [ elementType , attributesType ] ) => {
179+ return ` ['${ elementType } ']: ${ attributesType } ;` ;
180+ } ) ,
181+ `}` ,
182+ `` ,
183+ ] . join ( '\n' ) ;
184+
185+ // Closing brace for `declare global`
186+ htmlElementsContent += '}\n' ;
155187
156- htmlElementsContent += mergedHtmlElements + '}\n' ;
157188 return htmlElementsContent ;
158189}
159190
160191function createSvgElementAttributesMap ( ) {
161- let svgElementsContent = `
162- declare global {
163- ` ;
164- let mergedSvgElements = `
165-
166- /**
167- * @internal
168- * @private - not for use outside of Glint
169- */
170- interface GlintSvgElementAttributesMap {\n` ;
192+ let svgElementsContent = [ `declare global {` , `` ] . join ( '\n' ) ;
171193
172194 function emitAttributeInterface ( type , keys , name ) {
173195 const interfaceName = type + 'Attributes' ;
@@ -192,45 +214,70 @@ interface GlintSvgElementAttributesMap {\n`;
192214 svgElementsContent += ` ['${ k } ']: AttrValue;\n` ;
193215 } ) ;
194216 }
217+
195218 svgElementsContent += `}\n` ;
196219 }
197220
198- function addMapEntry ( type ) {
199- const interfaceName = type === 'SVGElement' ? GLOBAL_SVG_ATTRIBUTES_NAME : type + 'Attributes' ;
200-
201- mergedSvgElements += ` ['${ type } ']: ${ interfaceName } ;\n` ;
202- }
221+ let elementToAttributes = new Map ( ) ;
203222
204- Object . entries ( svgElementAttributes ) . forEach ( ( [ name , keys ] ) => {
205- if ( name === '*' ) {
206- name = GLOBAL_SVG_ATTRIBUTES_NAME ;
207- svgElementsMap . set ( name , 'GlobalSVG' ) ;
223+ Object . entries ( svgElementAttributes ) . forEach ( ( [ elementName , keys ] ) => {
224+ if ( elementName === '*' ) {
225+ elementName = GLOBAL_SVG_ATTRIBUTES_NAME ;
226+ svgElementsMap . set ( elementName , 'GlobalSVG' ) ;
208227 }
209- const type = svgElementsMap . get ( name ) ;
210228
211- if ( ! type ) return ;
229+ const elementType = svgElementsMap . get ( elementName ) ;
212230
213- emitAttributeInterface ( type , keys , name ) ;
231+ if ( ! elementType ) {
232+ return ;
233+ }
234+
235+ emitAttributeInterface ( elementType , keys , elementName ) ;
214236
215237 // Not an element, but we use this prefix for attributes
216- if ( type === 'GlobalSVG' ) return ;
238+ if ( elementType === 'GlobalSVG' ) {
239+ return ;
240+ }
217241
218- addMapEntry ( type ) ;
242+ elementToAttributes . set ( elementType , ` ${ elementType } Attributes` ) ;
219243 } ) ;
244+
220245 emitAttributeInterface ( 'SVGElement' , [ ] , 'SVGElement' ) ;
221- addMapEntry ( 'SVGElement' ) ;
246+ elementToAttributes . set ( 'SVGElement' , GLOBAL_SVG_ATTRIBUTES_NAME ) ;
247+
248+ elementToAttributes = new Map ( [ ...elementToAttributes ] . sort ( ) ) ;
249+
250+ svgElementsContent += [
251+ `/**` ,
252+ ` * @internal` ,
253+ ` * @private - not for use outside of Glint` ,
254+ ` */` ,
255+ `interface GlintSvgElementAttributesMap {` ,
256+ ...Array . from ( elementToAttributes . entries ( ) ) . map ( ( [ elementType , attributesType ] ) => {
257+ return ` ['${ elementType } ']: ${ attributesType } ;` ;
258+ } ) ,
259+ `}` ,
260+ `` ,
261+ ] . join ( '\n' ) ;
262+
263+ // Closing brace for `declare global`
264+ svgElementsContent += '}\n' ;
222265
223- mergedSvgElements += `}\n` ;
224- svgElementsContent += mergedSvgElements + '}\n' ;
225266 return svgElementsContent ;
226267}
227268
228- const prefix = `//generated by scrips/build-elements.mjs
229- // this server to provide the html attributes for each element
230- ` ;
231269const filePath = resolve (
232270 fileURLToPath ( import . meta. url ) ,
233271 '../../packages/template/-private/dsl/elements.d.ts' ,
234272) ;
235- const content = prefix + createHtmlElementsAttributesMap ( ) + createSvgElementAttributesMap ( ) ;
236- writeFileSync ( filePath , content ) ;
273+
274+ writeFileSync (
275+ filePath ,
276+ [
277+ '// Auto-generated by bin/build-elements.mjs' ,
278+ '// this server to provide the html attributes for each element' ,
279+ '' ,
280+ createHtmlElementsAttributesMap ( ) ,
281+ createSvgElementAttributesMap ( ) ,
282+ ] . join ( '\n' ) ,
283+ ) ;
0 commit comments