feat(i18n): xmb serializer
This commit is contained in:
93
modules/@angular/compiler/src/i18n/serializers/xml_helper.ts
Normal file
93
modules/@angular/compiler/src/i18n/serializers/xml_helper.ts
Normal file
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
export interface IVisitor {
|
||||
visitTag(tag: Tag): any;
|
||||
visitText(text: Text): any;
|
||||
visitDeclaration(decl: Declaration): any;
|
||||
}
|
||||
|
||||
class _Visitor implements IVisitor {
|
||||
visitTag(tag: Tag): string {
|
||||
const strAttrs = this._serializeAttributes(tag.attrs);
|
||||
|
||||
if (tag.children.length == 0) {
|
||||
return `<${tag.name}${strAttrs}/>`;
|
||||
}
|
||||
|
||||
const strChildren = tag.children.map(node => node.visit(this));
|
||||
return `<${tag.name}${strAttrs}>${strChildren.join('')}</${tag.name}>`;
|
||||
}
|
||||
|
||||
visitText(text: Text): string { return text.value; }
|
||||
|
||||
visitDeclaration(decl: Declaration): string {
|
||||
return `<? xml${this._serializeAttributes(decl.attrs)} ?>`;
|
||||
}
|
||||
|
||||
private _serializeAttributes(attrs: {[k: string]: string}) {
|
||||
const strAttrs = Object.getOwnPropertyNames(attrs)
|
||||
.map((name: string) => `${name}="${attrs[name]}"`)
|
||||
.join(' ');
|
||||
return strAttrs.length > 0 ? ' ' + strAttrs : '';
|
||||
}
|
||||
}
|
||||
|
||||
const _visitor = new _Visitor();
|
||||
|
||||
export function serialize(nodes: Node[]): string {
|
||||
return nodes.map((node: Node): string => node.visit(_visitor)).join('');
|
||||
}
|
||||
|
||||
export interface Node { visit(visitor: IVisitor): any; }
|
||||
|
||||
export class Declaration implements Node {
|
||||
public attrs: {[k: string]: string} = {};
|
||||
|
||||
constructor(unescapedAttrs: {[k: string]: string}) {
|
||||
Object.getOwnPropertyNames(unescapedAttrs).forEach((k: string) => {
|
||||
this.attrs[k] = _escapeXml(unescapedAttrs[k]);
|
||||
});
|
||||
}
|
||||
|
||||
visit(visitor: IVisitor): any { return visitor.visitDeclaration(this); }
|
||||
}
|
||||
|
||||
export class Tag implements Node {
|
||||
public attrs: {[k: string]: string} = {};
|
||||
|
||||
constructor(
|
||||
public name: string, unescapedAttrs: {[k: string]: string} = {},
|
||||
public children: Node[] = []) {
|
||||
Object.getOwnPropertyNames(unescapedAttrs).forEach((k: string) => {
|
||||
this.attrs[k] = _escapeXml(unescapedAttrs[k]);
|
||||
});
|
||||
}
|
||||
|
||||
visit(visitor: IVisitor): any { return visitor.visitTag(this); }
|
||||
}
|
||||
|
||||
export class Text implements Node {
|
||||
value: string;
|
||||
constructor(unescapedValue: string) { this.value = _escapeXml(unescapedValue); };
|
||||
|
||||
visit(visitor: IVisitor): any { return visitor.visitText(this); }
|
||||
}
|
||||
|
||||
const _ESCAPED_CHARS: [RegExp, string][] = [
|
||||
[/&/g, '&'],
|
||||
[/"/g, '"'],
|
||||
[/'/g, '''],
|
||||
[/</g, '<'],
|
||||
[/>/g, '>'],
|
||||
];
|
||||
|
||||
function _escapeXml(text: string): string {
|
||||
return _ESCAPED_CHARS.reduce(
|
||||
(text: string, entry: [RegExp, string]) => text.replace(entry[0], entry[1]), text);
|
||||
}
|
Reference in New Issue
Block a user