@@ -83,6 +83,13 @@ class Manager {
8383 } ,
8484 } ;
8585
86+ /**
87+ * System tag attributes
88+ */
89+ protected reservedAttributes = {
90+ order : 'data-order' ,
91+ } ;
92+
8693 /**
8794 * @constructor
8895 */
@@ -116,14 +123,14 @@ class Manager {
116123 */
117124 public getTags ( ) : IMetaManagerTags {
118125 const { meta, body, html, containers } = this . tags ;
119- const sortedMeta = new Map (
126+ const sortedTags = new Map (
120127 [ ...meta . entries ( ) ] . sort ( ( [ , tagA ] , [ , tagB ] ) => tagA . order - tagB . order ) ,
121128 ) ;
122129
123130 return {
124131 body,
125132 html,
126- meta : sortedMeta ,
133+ meta : sortedTags ,
127134 containers,
128135 } ;
129136 }
@@ -209,6 +216,34 @@ class Manager {
209216 return key . endsWith ( '-not-unique' ) ;
210217 }
211218
219+ /**
220+ * Clone react element
221+ */
222+ protected cloneElement ( element : ReactElement ) : {
223+ element : ReactElement ;
224+ elementProps : Record < string , any > ;
225+ } {
226+ const { type } = element ;
227+ const props = { ...( element ?. props ?? { } ) } as Record < string , any > ;
228+
229+ // remove system attributes
230+ Object . values ( this . reservedAttributes ) . forEach ( ( attrName ) => {
231+ if ( props [ attrName ] ) {
232+ delete props [ attrName ] ;
233+ }
234+ } ) ;
235+
236+ // fix multiple nodes for title
237+ if ( type === 'title' && Array . isArray ( props . children ) ) {
238+ props . children = props . children . join ( '' ) ;
239+ }
240+
241+ return {
242+ element : React . createElement ( type , props ) ,
243+ elementProps : props ,
244+ } ;
245+ }
246+
212247 /**
213248 * Push react elements to meta state
214249 */
@@ -224,21 +259,17 @@ class Manager {
224259 return ;
225260 }
226261
227- const { type, props } = child ;
228- const elementProps : Record < string , any > = props ?? { } ;
262+ const { type } = child ;
263+ const { element, elementProps } = this . cloneElement ( child ) ;
264+ const elementOrder = elementProps [ this . reservedAttributes . order ]
265+ ? Number ( elementProps [ this . reservedAttributes . order ] )
266+ : undefined ;
229267
230- let order = this . tagsDefinitions [ type as string ] ?. order ?? 1000 ;
268+ let order = elementOrder ?? this . tagsDefinitions [ type as string ] ?. order ?? 1000 ;
231269 let key = this . tagsDefinitions [ type as string ] ?. key ?? ( type as string ) ;
232- let element = child ;
233270
234271 switch ( type ) {
235272 case 'title' :
236- const { children } = elementProps ;
237-
238- // fix multiple nodes
239- element = Array . isArray ( children )
240- ? React . cloneElement ( child , { children : children . join ( '' ) } )
241- : child ;
242273 break ;
243274
244275 case 'meta' :
@@ -329,21 +360,26 @@ class Manager {
329360 */
330361 protected applyDomElementAttributes ( element : Element , props : Record < string , any > = { } ) : void {
331362 const tagName = element . tagName . toLowerCase ( ) ;
363+ const reservedAttributes = Object . values ( this . reservedAttributes ) ;
332364
333365 // apply attributes
334366 Object . entries ( props ) . forEach ( ( [ name , value ] ) => {
335- if ( name === 'children' ) {
336- element . innerHTML = value ;
367+ switch ( name ) {
368+ case 'children' :
369+ element . innerHTML = value ;
337370
338- return ;
371+ return ;
372+
373+ case 'style' :
374+ return Object . entries ( value as Record < string , string > ) . forEach (
375+ ( [ styleName , styleValue ] ) => {
376+ element [ 'style' ] [ styleName ] = styleValue ;
377+ } ,
378+ ) ;
339379 }
340380
341- if ( name === 'style' ) {
342- return Object . entries ( value as Record < string , string > ) . forEach (
343- ( [ styleName , styleValue ] ) => {
344- element [ 'style' ] [ styleName ] = styleValue ;
345- } ,
346- ) ;
381+ if ( reservedAttributes [ name ] ) {
382+ return ;
347383 }
348384
349385 element . setAttribute ( this . replaceAttribute ( tagName , name ) , value as string ) ;
0 commit comments