1- import { diffKeys , DiffStatus } from 'web-utility' ;
1+ import {
2+ diffKeys ,
3+ DiffStatus ,
4+ elementTypeOf ,
5+ isDOMReadOnly ,
6+ templateOf ,
7+ toCamelCase ,
8+ toHyphenCase
9+ } from 'web-utility' ;
210
311import { DataObject , VDOMNode , VNode } from './VDOM' ;
412
513export class DOMRenderer {
6- eventPattern = / ^ o n \w + / ;
14+ eventPattern = / ^ o n [ A - Z ] / ;
15+ ariaPattern = / ^ a i r a [ A - Z ] / ;
716
817 protected keyOf = ( { key, text, props, selector } : VNode , index ?: number ) =>
918 key || props ?. id || text || ( selector && selector + index ) ;
1019
1120 protected vNodeOf = ( list : VNode [ ] , key : string ) =>
1221 list . find ( ( vNode , index ) => this . keyOf ( vNode , index ) + '' === key ) ;
1322
23+ protected propsKeyOf = ( key : string ) =>
24+ key . startsWith ( 'aria-' )
25+ ? toCamelCase ( key )
26+ : this . eventPattern . test ( key )
27+ ? key . toLowerCase ( )
28+ : key ;
29+
1430 protected updateProps < T extends DataObject > (
1531 node : T ,
1632 oldProps : DataObject = { } ,
@@ -39,7 +55,7 @@ export class DOMRenderer {
3955 return ( vNode . node = document . createTextNode ( vNode . text ) ) ;
4056
4157 vNode . node = vNode . tagName
42- ? document . createElement ( vNode . tagName )
58+ ? document . createElement ( vNode . tagName , { is : vNode . is } )
4359 : document . createDocumentFragment ( ) ;
4460
4561 return this . patch ( { tagName : vNode . tagName , node : vNode . node } , vNode )
@@ -72,17 +88,27 @@ export class DOMRenderer {
7288 }
7389
7490 patch ( oldVNode : VNode , newVNode : VNode ) : VNode {
91+ const { tagName } = oldVNode ;
92+ const isXML = templateOf ( tagName ) && elementTypeOf ( tagName ) === 'xml' ;
93+
7594 this . updateProps (
7695 oldVNode . node as Element ,
7796 oldVNode . props ,
7897 newVNode . props ,
7998 ( node , key ) =>
8099 this . eventPattern . test ( key )
81100 ? ( node [ key . toLowerCase ( ) ] = null )
82- : node . removeAttribute ( VDOMNode . propsMap [ key ] || key ) ,
83- ( node , key , value ) =>
84- ( node [ this . eventPattern . test ( key ) ? key . toLowerCase ( ) : key ] =
85- value )
101+ : node . removeAttribute (
102+ this . ariaPattern . test ( key )
103+ ? toHyphenCase ( key )
104+ : VDOMNode . propsMap [ key ] || key
105+ ) ,
106+ ( node , key , value ) => {
107+ // @ts -ignore
108+ if ( isXML || key . includes ( '-' ) || isDOMReadOnly ( tagName , key ) )
109+ node . setAttribute ( key , value ) ;
110+ else node [ this . propsKeyOf ( key ) ] = value ;
111+ }
86112 ) ;
87113 this . updateProps (
88114 ( oldVNode . node as HTMLElement ) . style ,
@@ -105,4 +131,12 @@ export class DOMRenderer {
105131
106132 return this . patch ( root , { ...root , children : [ vNode ] } ) ;
107133 }
134+
135+ renderToStaticMarkup ( tree : VNode ) {
136+ const { body } = document . implementation . createHTMLDocument ( ) ;
137+
138+ this . render ( tree , body ) ;
139+
140+ return body . innerHTML ;
141+ }
108142}
0 commit comments