Skip to content

Commit

Permalink
Merge pull request #678 from mathjax/serialize-xml
Browse files Browse the repository at this point in the history
Add ability to serialize annotation-xml content.
  • Loading branch information
dpvc authored Apr 16, 2021
2 parents c94bd99 + 3abb343 commit cc3ce70
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 8 deletions.
21 changes: 19 additions & 2 deletions ts/adaptors/HTMLAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,22 @@ export interface MinText<N, T> {
/**
* The minimum fields needed for a DOMParser
*
* @template N The HTMLElement node class
* @template T The Text node class
* @template D The Document class
*/
export interface MinDOMParser<D> {
parseFromString(text: string, format?: string): D;
}

/*****************************************************************/
/**
* The minimum fields needed for a DOMParser
*
* @template N The HTMLElement node class
*/
export interface MinXMLSerializer<N> {
serializeToString(node: N): string;
}

/*****************************************************************/
/**
* The minimum fields needed for a Window
Expand All @@ -132,6 +141,9 @@ export interface MinWindow<N, D> {
DOMParser: {
new(): MinDOMParser<D>
};
XMLSerializer: {
new(): MinXMLSerializer<N>;
};
NodeList: any;
HTMLCollection: any;
HTMLElement: any;
Expand Down Expand Up @@ -399,6 +411,11 @@ AbstractDOMAdaptor<N, T, D> implements MinHTMLAdaptor<N, T, D> {
return node.outerHTML;
}

public serializeXML(node: N) {
const serializer = new this.window.XMLSerializer();
return serializer.serializeToString(node) as string;
}

/**
* @override
*/
Expand Down
1 change: 1 addition & 0 deletions ts/adaptors/browserAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ declare global {
interface Window {
Document: typeof Document;
DOMParser: typeof DOMParser;
XMLSerializer: typeof XMLSerializer;
HTMLElement: typeof HTMLElement;
HTMLCollection: typeof HTMLCollection;
NodeList: typeof NodeList;
Expand Down
12 changes: 7 additions & 5 deletions ts/adaptors/lite/Parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,18 +345,20 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
/**
* @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 {string} The serialized element (like outerHTML)
*/
public serialize(adaptor: LiteAdaptor, node: LiteElement): string {
public serialize(adaptor: LiteAdaptor, node: LiteElement, xml: boolean = false): string {
const SELF_CLOSING = (this.constructor as typeof LiteParser).SELF_CLOSING;
const CDATA = (this.constructor as typeof LiteParser).CDATA_ATTR;
const tag = adaptor.kind(node);
const attributes = adaptor.allAttributes(node).map(
(x: AttributeData) => x.name + '="' + (CDATA[x.name] ? x.value : this.protectAttribute(x.value)) + '"'
).join(' ');
const content = this.serializeInner(adaptor, node, xml);
const html =
'<' + tag + (attributes ? ' ' + attributes : '') + '>'
+ (SELF_CLOSING[tag] ? '' : adaptor.innerHTML(node) + '</' + tag + '>');
'<' + tag + (attributes ? ' ' + attributes : '')
+ (content && !SELF_CLOSING[tag] ? `>${content}</${tag}>` : xml ? '/>' : '>');
return html;
}

Expand All @@ -365,7 +367,7 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
* @param {LiteElement} node The node whose innerHTML is needed
* @return {string} The serialized element (like innerHTML)
*/
public serializeInner(adaptor: LiteAdaptor, node: LiteElement): string {
public serializeInner(adaptor: LiteAdaptor, node: LiteElement, xml: boolean = false): string {
const PCDATA = (this.constructor as typeof LiteParser).PCDATA;
if (PCDATA.hasOwnProperty(node.kind)) {
return adaptor.childNodes(node).map(x => adaptor.value(x)).join('');
Expand All @@ -374,7 +376,7 @@ export class LiteParser implements MinDOMParser<LiteDocument> {
const kind = adaptor.kind(x);
return (kind === '#text' ? this.protectHTML(adaptor.value(x)) :
kind === '#comment' ? (x as LiteComment).value :
this.serialize(adaptor, x as LiteElement));
this.serialize(adaptor, x as LiteElement, xml));
}).join('');
}

Expand Down
7 changes: 7 additions & 0 deletions ts/adaptors/liteAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,13 @@ export class LiteAdaptor extends AbstractDOMAdaptor<LiteElement, LiteText, LiteD
return this.parser.serialize(this, node);
}

/**
* @override
*/
public serializeXML(node: LiteElement) {
return this.parser.serialize(this, node, true);
}

/**
* @override
*/
Expand Down
11 changes: 11 additions & 0 deletions ts/core/DOMAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ export interface DOMAdaptor<N, T, D> {
*/
outerHTML(node: N): string;

/**
* @param {N} node The HTML node whose serialized string is to be obtained
* @return {string} The serialized node and its content
*/
serializeXML(node: N): string;

/**
* @param {N} node The HTML node whose attribute is to be set
* @param {string|number} name The name of the attribute to set
Expand Down Expand Up @@ -558,6 +564,11 @@ export abstract class AbstractDOMAdaptor<N, T, D> implements DOMAdaptor<N, T, D>
*/
public abstract outerHTML(node: N): string;

/**
* @override
*/
public abstract serializeXML(node: N): string;

/**
* @override
*/
Expand Down
2 changes: 1 addition & 1 deletion ts/core/MmlTree/MmlNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ export class XMLNode extends AbstractMmlEmptyNode {
* @return {string} The serialized XML content
*/
public getSerializedXML(): string {
return this.adaptor.outerHTML(this.xml);
return this.adaptor.serializeXML(this.xml);
}

/**
Expand Down

0 comments on commit cc3ce70

Please sign in to comment.