Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update LiteParser's serializeXML. (mathjax/MathJax-demos-node#58) #1046

Merged
merged 2 commits into from
Feb 6, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 53 additions & 4 deletions ts/adaptors/lite/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
script: true
};

public static XMLNS: {[name: string]: string} = {
svg: 'http://www.w3.org/2000/svg',
math: 'http://www.w3.org/1998/Math/MathML',
html: 'http://www.w3.org/1999/xhtml'
};

/**
* @override
*/
Expand Down Expand Up @@ -328,8 +334,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 +347,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 +363,57 @@ 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);
//
// If we aren't in XML mode, just use the attributes given
//
if (!xml) {
return attributes;
}
//
// Check that we know the namespace for the kind of node
//
const kind = adaptor.kind(node);
const xmlns = (this.constructor as typeof LiteParser).XMLNS;
if (!xmlns.hasOwnProperty(kind)) {
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: xmlns[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