Skip to content

Commit

Permalink
Update LiteParser's serializeXML to add xmlns attributes when needed,…
Browse files Browse the repository at this point in the history
… and protect attribute values better. (mathjax/MathJax-demos-node#58)
  • Loading branch information
dpvc committed Jan 28, 2024
1 parent e798b22 commit 429b347
Showing 1 changed file with 44 additions and 4 deletions.
48 changes: 44 additions & 4 deletions ts/adaptors/lite/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,8 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
public serialize(adaptor: LiteAdaptor, node: LiteElement, xml: boolean = false): string {
const SELF_CLOSING = (this.constructor as typeof LiteParser).SELF_CLOSING;
const tag = adaptor.kind(node);
const attributes = adaptor.allAttributes(node).map(
(x: AttributeData) => x.name + '="' + this.protectAttribute(x.value) + '"'
const attributes = this.allAttributes(adaptor, node, xml).map(
(x) => x.name + '="' + this.protectAttribute(x.value, xml) + '"'
).join(' ');
const content = this.serializeInner(adaptor, node, xml);
const html =
Expand All @@ -341,6 +341,7 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
/**
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
* @param {LiteElement} node The node whose innerHTML is needed
* @param {boolean} xml True if XML rules should be used (e.g., self-closing tags)
* @return {string} The serialized element (like innerHTML)
*/
public serializeInner(adaptor: LiteAdaptor, node: LiteElement, xml: boolean = false): string {
Expand All @@ -356,15 +357,54 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
}).join('');
}

/**
* @param {LiteAdaptor} adaptor The adaptor for managing nodes
* @param {LiteElement} node The node to serialize
* @param {boolean} xml True when producing XML, false for HTML
* @return {AttributeData[]} The attribute list
*/
protected allAttributes(adaptor: LiteAdaptor, node: LiteElement, xml: boolean): AttributeData[] {
let attributes = adaptor.allAttributes(node);
const kind = adaptor.kind(node);
if (!xml || (kind !== 'svg' && kind !== 'math' && kind !== 'html')) {
return attributes;
}
//
// Check for existance of xmlns attribute
//
for (const {name} of attributes) {
if (name === 'xmlns') {
return attributes;
}
}
//
// Add one of it is missing
//
attributes.push({
name: 'xmlns',
value: ({
svg: 'http://www.w3.org/2000/svg',
math: 'http://www.w3.org/1998/Math/MathML',
html: 'http://www.w3.org/1999/xhtml'
})[kind]
});
return attributes;
}

/**
* @param {string} text The attribute value to be HTML escaped
* @param {boolean} xml True if XML rules are to be used
* @return {string} The string with " replaced by entities
*/
public protectAttribute(text: string): string {
public protectAttribute(text: string, xml: boolean): string {
if (typeof text !== 'string') {
text = String(text);
}
return text.replace(/&/g, '&amp;').replace(/"/g, '&quot;');
text = text.replace(/&/g, '&amp;').replace(/"/g, '&quot;');
if (xml) {
text = text.replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
return text;
}

/**
Expand Down

0 comments on commit 429b347

Please sign in to comment.