@@ -91,6 +91,12 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
9191 script : true
9292 } ;
9393
94+ public static XMLNS : { [ name : string ] : string } = {
95+ svg : 'http://www.w3.org/2000/svg' ,
96+ math : 'http://www.w3.org/1998/Math/MathML' ,
97+ html : 'http://www.w3.org/1999/xhtml'
98+ } ;
99+
94100 /**
95101 * @override
96102 */
@@ -328,8 +334,8 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
328334 public serialize ( adaptor : LiteAdaptor , node : LiteElement , xml : boolean = false ) : string {
329335 const SELF_CLOSING = ( this . constructor as typeof LiteParser ) . SELF_CLOSING ;
330336 const tag = adaptor . kind ( node ) ;
331- const attributes = adaptor . allAttributes ( node ) . map (
332- ( x : AttributeData ) => x . name + '="' + this . protectAttribute ( x . value ) + '"'
337+ const attributes = this . allAttributes ( adaptor , node , xml ) . map (
338+ ( x ) => x . name + '="' + this . protectAttribute ( x . value , xml ) + '"'
333339 ) . join ( ' ' ) ;
334340 const content = this . serializeInner ( adaptor , node , xml ) ;
335341 const html =
@@ -341,6 +347,7 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
341347 /**
342348 * @param {LiteAdaptor } adaptor The adaptor for managing nodes
343349 * @param {LiteElement } node The node whose innerHTML is needed
350+ * @param {boolean } xml True if XML rules should be used (e.g., self-closing tags)
344351 * @return {string } The serialized element (like innerHTML)
345352 */
346353 public serializeInner ( adaptor : LiteAdaptor , node : LiteElement , xml : boolean = false ) : string {
@@ -356,15 +363,57 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
356363 } ) . join ( '' ) ;
357364 }
358365
366+ /**
367+ * @param {LiteAdaptor } adaptor The adaptor for managing nodes
368+ * @param {LiteElement } node The node to serialize
369+ * @param {boolean } xml True when producing XML, false for HTML
370+ * @return {AttributeData[] } The attribute list
371+ */
372+ protected allAttributes ( adaptor : LiteAdaptor , node : LiteElement , xml : boolean ) : AttributeData [ ] {
373+ let attributes = adaptor . allAttributes ( node ) ;
374+ //
375+ // If we aren't in XML mode, just use the attributes given
376+ //
377+ if ( ! xml ) {
378+ return attributes ;
379+ }
380+ //
381+ // Check that we know the namespace for the kind of node
382+ //
383+ const kind = adaptor . kind ( node ) ;
384+ const xmlns = ( this . constructor as typeof LiteParser ) . XMLNS ;
385+ if ( ! xmlns . hasOwnProperty ( kind ) ) {
386+ return attributes ;
387+ }
388+ //
389+ // Check for existance of xmlns attribute
390+ //
391+ for ( const { name} of attributes ) {
392+ if ( name === 'xmlns' ) {
393+ return attributes ;
394+ }
395+ }
396+ //
397+ // Add one of it is missing
398+ //
399+ attributes . push ( { name : 'xmlns' , value : xmlns [ kind ] } ) ;
400+ return attributes ;
401+ }
402+
359403 /**
360404 * @param {string } text The attribute value to be HTML escaped
405+ * @param {boolean } xml True if XML rules are to be used
361406 * @return {string } The string with " replaced by entities
362407 */
363- public protectAttribute ( text : string ) : string {
408+ public protectAttribute ( text : string , xml : boolean ) : string {
364409 if ( typeof text !== 'string' ) {
365410 text = String ( text ) ;
366411 }
367- return text . replace ( / & / g, '&' ) . replace ( / " / g, '"' ) ;
412+ text = text . replace ( / & / g, '&' ) . replace ( / " / g, '"' ) ;
413+ if ( xml ) {
414+ text = text . replace ( / < / g, '<' ) . replace ( / > / g, '>' ) ;
415+ }
416+ return text ;
368417 }
369418
370419 /**
0 commit comments