docutils-ts
Version:
Port of the Python Docutils library to TypeScript
103 lines (102 loc) • 4.11 kB
JavaScript
import * as nodes from '../nodes.js';
import * as utils from '../utils.js';
import Transform from '../transform.js';
class Decorations extends Transform {
apply() {
const headerNodes = this.generateHeader();
if (headerNodes && headerNodes.length) {
const decoration = this.document.getDecoration();
const header = decoration.getHeader();
header.add(headerNodes);
}
const footerNodes = this.generateFooter();
if (footerNodes && footerNodes.length) {
const decoration = this.document.getDecoration();
const footer = decoration.getFooter();
if (typeof footer === 'undefined') {
throw new Error('unexpected undefined footer');
}
footer.add(footerNodes);
}
}
generateHeader() {
return undefined;
}
generateFooter() {
// @@@ Text is hard-coded for now.
// Should be made dynamic (language-dependent).
// @@@ Use timestamp from the `SOURCE_DATE_EPOCH`_ environment variable
// for the datestamp?
// See https://sourceforge.net/p/docutils/patches/132/
// and https://reproducible-builds.org/specs/source-date-epoch/
const settings = this.document.settings;
let core = settings;
if (core.generator || core.datestamp || core.sourceLink || core.sourceUrl) {
const text = [];
if ((core.sourceLink && settings._source) || core.sourceUrl) {
const source = core.sourceUrl || utils.relativePath(settings._destination, settings._source);
text.push(new nodes.reference('', 'View document source', [], { refuri: source }), new nodes.Text('.\n'));
}
if (core.datestamp) {
const datestamp = 'fixme'; // get time
text.push(new nodes.Text(`Generated on: ${datestamp}\n`));
}
if (core.generator) {
text.push(new nodes.Text('Generated by '), new nodes.reference('', 'Docutils', [], {
refuri: 'http://docutils.sourceforge.net/',
}), new nodes.Text(' from '), new nodes.reference('', 'reStructuredText', [], { refuri: 'http://docutils.sourceforge.net/rst.html' }), new nodes.Text(' source.\n'));
}
return [new nodes.paragraph('', '', text)];
}
return undefined;
}
}
Decorations.defaultPriority = 820;
/**
* Place any system messages generated after parsing into a dedicated section
* of the document.
*/
class Messages extends Transform {
apply() {
const unfiltered = this.document.transformMessages;
if (unfiltered == null) {
throw new Error('need transformmessages');
}
const threshold = this.document.reporter.reportLevel;
const messages = unfiltered.filter((msg) => msg.attributes.level
>= threshold && msg.parent == null);
if (messages.length) {
const section = new nodes.section('', [], { classes: 'system-messages' });
// @@@ get this from the language module?
section.add([new nodes.title('', 'Docutils System Messages'), ...messages]);
const m = this.document.transformMessages;
m.splice(0, m.length);
this.document.append(section);
}
}
}
Messages.defaultPriority = 860;
/**
* Remove system messages below verbosity threshold.
*/
class FilterMessages extends Transform {
apply() {
this.document.traverse({ condition: nodes.system_message }).forEach((node, i) => {
if (node.attributes.level < this.document.reporter.reportLevel) {
//node.parent!.children.pop(i);
}
});
}
}
FilterMessages.defaultPriority = 870;
/**
* Append all post-parse system messages to the end of the document.
* Used for testing purposes.
* @todo unimplemented
*/
class TestMessages extends Transform {
apply() {
}
}
TestMessages.defaultPriority = 880;
export { Decorations, Messages, FilterMessages, TestMessages, };