import { EntityEncoding } from '../OptionTypes'; import Tools from '../util/Tools'; import Entities from './Entities'; /** * This class is used to write HTML tags out it can be used with the Serializer. * * @class tinymce.html.Writer * @version 3.4 * @example * const writer = tinymce.html.Writer({ indent: true }); * writer.start('node', { attr: 'value' }); * writer.end('node'); * console.log(writer.getContent()); */ const makeMap = Tools.makeMap; export interface WriterSettings { element_format?: 'xhtml' | 'html'; entities?: string; entity_encoding?: EntityEncoding; indent?: boolean; indent_after?: string; indent_before?: string; } type Attributes = Array<{ name: string; value: string }>; interface Writer { cdata: (text: string) => void; comment: (text: string) => void; doctype: (text: string) => void; end: (name: string) => void; getContent: () => string; pi: (name: string, text?: string) => void; reset: () => void; start: (name: string, attrs?: Attributes | null, empty?: boolean) => void; text: (text: string, raw?: boolean) => void; } const Writer = (settings?: WriterSettings): Writer => { const html: string[] = []; settings = settings || {}; const indent = settings.indent; const indentBefore = makeMap(settings.indent_before || ''); const indentAfter = makeMap(settings.indent_after || ''); const encode = Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities); const htmlOutput = settings.element_format !== 'xhtml'; return { /** * Writes a start element, such as `
`.
*
* @method start
* @param {String} name Name of the element.
* @param {Array} attrs Optional array of objects containing an attribute name and value, or undefined if the element has no attributes.
* @param {Boolean} empty Optional empty state if the tag should serialize as a void element. For example: ``
*/
start: (name: string, attrs?: Attributes | null, empty?: boolean) => {
if (indent && indentBefore[name] && html.length > 0) {
const value = html[html.length - 1];
if (value.length > 0 && value !== '\n') {
html.push('\n');
}
}
html.push('<', name);
if (attrs) {
for (let i = 0, l = attrs.length; i < l; i++) {
const attr = attrs[i];
html.push(' ', attr.name, '="', encode(attr.value, true), '"');
}
}
if (!empty || htmlOutput) {
html[html.length] = '>';
} else {
html[html.length] = ' />';
}
if (empty && indent && indentAfter[name] && html.length > 0) {
const value = html[html.length - 1];
if (value.length > 0 && value !== '\n') {
html.push('\n');
}
}
},
/**
* Writes an end element, such as `