docutils-ts
Version:
Port of the Python Docutils library to TypeScript
143 lines (142 loc) • 5.82 kB
JavaScript
import SpecializedText from './specializedText.js';
import { columnWidth } from '../../../utils.js';
import { EOFError, InvalidStateError } from "../../../exceptions.js";
import * as nodes from '../../../nodes.js';
import StateCorrection from '../../../stateCorrection.js';
class Line extends SpecializedText {
constructor() {
super(...arguments);
this.eofcheck = true;
}
indent(match, context, nextState) {
return this.text(match, context, nextState);
}
eof(context) {
if (this.memo === undefined) {
throw new InvalidStateError();
}
const marker = context[0].trim();
if (this.memo.sectionBubbleUpKludge) {
this.memo.sectionBubbleUpKludge = false;
}
else if (marker.length < 4) {
this.stateCorrection(context);
}
if (this.eofcheck) {
const lineno = this.rstStateMachine.absLineNumber() - 1;
const transition = new nodes.transition(context[0]);
transition.line = lineno;
this.parent.add(transition);
}
this.eofcheck = true;
return [];
}
/** Transition marker. */
blank(match, context, nextState) {
const [src, srcline] = this.rstStateMachine.getSourceAndLine();
const marker = context[0].trim();
if (marker.length < 4) {
this.stateCorrection(context);
}
const transition = new nodes.transition(marker);
transition.source = src;
transition.line = srcline === undefined ? -1 : srcline - 1;
this.parent.add(transition);
return [[], 'Body', []];
}
/** Potential over- & underlined title. */
text(match, context, nextState) {
const lineno = this.rstStateMachine.absLineNumber() - 1;
let overline = context[0];
let title = match.result.input;
let underline = '';
try {
underline = this.rstStateMachine.nextLine();
}
catch (error) {
if (error instanceof EOFError) {
const blocktext = `${overline}\n${title}`;
if (overline.trimEnd().length < 4) {
this.shortOverline(context, blocktext, lineno, 2);
}
else {
const msg = this.reporter.severe('Incomplete section title.', [new nodes.literal_block(blocktext, blocktext)], { line: lineno });
this.parent.add(msg);
return [[], 'Body', []];
}
}
else {
throw error;
}
}
const source = [overline, title, underline].join('\n');
overline = overline.trimRight();
underline = underline || '';
underline = underline.trimRight();
if (!this.transitions.underline[0].test(underline)) {
const blocktext = `${overline}\n${title}\n${underline}`;
if (overline.trimEnd().length < 4) {
this.shortOverline(context, blocktext, lineno, 2);
}
else {
const msg = this.reporter.severe('Missing matching underline for section title overline.', [new nodes.literal_block(source, source)], { line: lineno });
this.parent.add(msg);
return [[], 'Body', []];
}
}
else if (overline !== underline) {
const blocktext = `${overline}\n${title}\n${underline}`;
if (overline.trimEnd().length < 4) {
this.shortOverline(context, blocktext, lineno, 2);
}
else {
const msg = this.reporter.severe('Title overline & underline mismatch.', [new nodes.literal_block(source, source)], { line: lineno });
this.parent.add(msg);
return [[], 'Body', []];
}
}
title = title.trimEnd();
const messages = [];
if (columnWidth(title) > overline.length) {
const blocktext = `${overline}\n${title}\n${underline}`;
if (overline.trimEnd().length < 4) {
this.shortOverline(context, blocktext, lineno, 2);
}
else {
const msg = this.reporter.warning('Title overline too short.', [new nodes.literal_block(source, source)], { line: lineno });
messages.push(msg);
}
}
const style = [overline[0], underline[0]];
this.eofcheck = false; // @@@ not sure this is correct
this.section({
title: title.trimStart(), source, style, lineno: lineno + 1, messages,
});
this.eofcheck = true;
return [[], 'Body', []];
}
underline(match, context, nextState) {
const overline = context[0];
const blocktext = `${overline}\n${this.rstStateMachine.line}`;
const lineno = this.rstStateMachine.absLineNumber() - 1;
if (overline.trimEnd().length < 4) {
this.shortOverline(context, blocktext, lineno, 1);
}
const msg = this.reporter.error('Invalid section title or transition marker.', [new nodes.literal_block(blocktext, blocktext)], { line: lineno });
this.parent.add(msg);
return [[], 'Body', []];
}
shortOverline(context, blocktext, lineno, lines = 1) {
const msg = this.reporter.info('Possible incomplete section title.\nTreating the overline as '
+ "ordinary text because it's so short.", [], { line: lineno });
this.parent.add(msg);
this.stateCorrection(context, lines);
}
stateCorrection(context, lines = 1) {
this.rstStateMachine.previousLine(lines);
context.length = 0;
throw new StateCorrection('Body', 'text');
}
}
Line.stateName = 'Line';
export default Line;