UNPKG

docutils-ts

Version:

Port of the Python Docutils library to TypeScript

142 lines (141 loc) 4.7 kB
import BaseWriter from '../writer.js'; import * as docutils from '../index.js'; import * as nodes from '../nodes.js'; import { InvalidStateError } from "../exceptions.js"; export function escapeXml(unsafe) { if (typeof unsafe === 'undefined') { throw new Error('need unsafE'); } return unsafe.replace(/[<>&'"]/g, (c) => { switch (c) { case '<': return '&lt;'; case '>': return '&gt;'; case '&': return '&amp;'; case '\'': return '&apos;'; case '"': return '&quot;'; default: return c; } }); } class XMLTranslator extends nodes.GenericNodeVisitor { constructor(document) { super(document); this.simple_nodes = []; this.doctype = ''; this.generator = `<!-- generated by Docutils ${docutils.__version__} -->\n`; this.document = document; this.warn = this.document.reporter.warning; this.error = this.document.reporter.error; this.output = []; this.settings = document.settings; const settings = this.settings; this.newline = ''; this.indent = ''; const core = this.settings; const outputEncoding = core.outputEncoding; let xmlWriter = settings; if (xmlWriter !== undefined) { if (xmlWriter.newlines) { this.newline = '\n'; } if (xmlWriter.indents) { this.newline = '\n'; this.indent = ' '; } if (xmlWriter.xmlDeclaration && outputEncoding !== undefined) { this.output.push(this.xmlDeclaration(outputEncoding)); } if (xmlWriter.doctypeDeclaration) { this.output.push(this.doctype); } } this.level = 0; this.inSimple = 0; this.fixedText = 0; this.output.push(this.generator); } default_visit(node) { this.simple_nodes = [nodes.TextElement]; // nodes.image, nodes.colspec, nodes.transition] if (!this.inSimple) { this.output.push(Array(this.level + 1).join(this.indent)); } this.output.push(node.starttag()); this.level += 1; // fixme should probably pick this code up if (false) { // node instanceof nodes.FixedTextElement || node instanceof nodes.literal) { this.fixedText += 1; } else { if (this.simple_nodes.findIndex((nt) => node instanceof nt) !== -1) { this.inSimple++; } } if (!this.inSimple) { this.output.push('\n'); } } default_departure(node) { this.level -= 1; if (!this.inSimple) { this.output.push(Array(this.level + 1).join(this.indent)); } this.output.push(node.endtag()); // if(node instanceof nodes['FixedTextElement'] || node instanceof nodes.literal) { // this.fixedText -= 1; // } // bla } visit_Text(node) { const text = escapeXml(node.astext()); this.output.push(text); } depart_Text(node) { } xmlDeclaration(outputEncoding) { return ''; } } export default class XMLWriter extends BaseWriter { constructor() { super(...arguments); this.translatorClass = XMLTranslator; } translate() { if (this.document === undefined) { throw new InvalidStateError('No document'); } const TranslatorClass = this.translatorClass; const visitor = new TranslatorClass(this.document); this.visitor = visitor; this.document.walkabout(visitor); this.output = visitor.output.join(''); } } /* Writer.settingsSpec = [ '"Docutils XML" Writer Options', null, [['Generate XML with newlines before and after tags.', ['--newlines'], { action: 'store_true', validator: 'frontend.validate_boolean' }], ['Generate XML with indents and newlines.', ['--indents'], // #@ TODO use integer value for number of spaces? { action: 'store_true', validator: 'frontend.validate_boolean' }], ['Omit the XML declaration. Use with caution.', ['--no-xml-declaration'], { dest: 'xml_declaration', default: 1, action: 'store_false', validator: 'frontend.validate_boolean', }], ['Omit the DOCTYPE declaration.', ['--no-doctype'], { dest: 'doctype_declaration', default: 1, action: 'store_false', validator: 'frontend.validate_boolean', }]]]; */ export { XMLWriter };