docutils-ts
Version:
Port of the Python Docutils library to TypeScript
138 lines (137 loc) • 6 kB
JavaScript
import State from './state.js';
import { InvalidStateError } from "../exceptions.js";
/**
* State superclass specialized for whitespace (blank lines & indents).
*
* Use this class with `StateMachineWS`. The transitions 'blank' (for blank
* lines) and 'indent' (for indented text blocks) are added automatically,
* before any other transitions. The transition method `blank()` handles
* blank lines and `indent()` handles nested indented blocks. Indented
* blocks trigger a new state machine to be created by `indent()` and run.
* The class of the state machine to be created is in `indent_sm`, and the
* constructor keyword arguments are in the dictionary `indent_sm_kwargs`.
*
* The methods `known_indent()` and `firstknown_indent()` are provided for
* indented blocks where the indent (all lines' and first line's only,
* respectively) is known to the transition method, along with the attributes
* `known_indent_sm` and `known_indent_sm_kwargs`. Neither transition method
* is triggered automatically.
*
*/
class StateWS extends State {
constructor(stateMachine, debug = false) {
super(stateMachine, debug);
/**
* The `StateMachine` class handling indented text blocks.
*
* If left as ``None``, `indent_sm` defaults to the value of
* `State.nested_sm`. Override it in subclasses to avoid the default.
*/
//public indentSm: StatemachineConstructor<Statemachine> | undefined;
/**
* Keyword arguments dictionary, passed to the `indent_sm` constructor.
*
* If left as ``None``, `indent_sm_kwargs` defaults to the value of
* `State.nested_sm_kwargs`. Override it in subclasses to avoid the default.
**/
//public indentSmKwArgs: {} | undefined;
/**
* The `StateMachine` class handling known-indented text blocks.
*
* If left as ``None``, `known_indent_sm` defaults to the value of
* `indent_sm`. Override it in subclasses to avoid the default.
*/
//public knownIndentSm: StatemachineConstructor<Statemachine> | undefined;
/**
* Keyword arguments dictionary, passed to the `known_indent_sm` constructor.
*
* If left as ``None``, `known_indent_sm_kwargs` defaults to the value of
* `indent_sm_kwargs`. Override it in subclasses to avoid the default.
*/
//public knownIndentSmKwargs: StateMachineConstructorArgs | undefined;
/** Patterns for default whitespace transitions. May be overridden in subclasses. */
this.wsPatterns = { blank: /^ *$/, indent: /^ +/ };
/**
* Default initial whitespace transitions, added before those listed in
* `State.initial_transitions`. May be overridden in subclasses.
*/
this.wsInitialTransitions = ['blank', 'indent'];
this.debugFn = (line) => { };
this.wsStateMachine = stateMachine;
/* istanbul ignore else */
/*
if (!this.indentSm) {
this.indentSm = this.nestedSm;
}*/
/* istanbul ignore else */
/*if (!this.indentSmKwargs) {
this.indentSmKwargs = this.nestedSmKwargs;
}*/
/* istanbul ignore else */
/*if (!this.knownIndentSm) {
this.knownIndentSm = this.indentSm;
}*/
/* istanbul ignore else */
/*if (!this.knownIndentSmKwargs) {
this.knownIndentSmKwargs = this.indentSmKwargs;
}*/
}
addInitialTransitions() {
super.addInitialTransitions();
//this.logger.silly('addInitialTransitions');
/* Alteration of patterns ! */
this.patterns = { ...this.patterns, ...this.wsPatterns };
if (this.wsInitialTransitions === undefined) {
throw new InvalidStateError();
}
const [names, transitions] = this.makeTransitions(this.wsInitialTransitions);
this.addTransitions(names, transitions);
}
blank(match, context, nextState) {
return this.nop(match, context, nextState);
}
indent(match, context, nextState) {
const [indented, indent, lineOffset, blankFinish] = this.wsStateMachine.getIndented({});
if (!this.createIndentStateMachine) {
throw new InvalidStateError('createIndentStateMachine');
}
const sm = this.createIndentStateMachine();
const results = sm.run(indented, lineOffset);
return [context, nextState, results];
}
knownIndent(match, context, nextState) {
const [indented, lineOffset, blankFinish] = this.wsStateMachine.getKnownIndented({ indent: match.result.index + match.result[0].length }
// match.end(), // ORIGINAL PYTHON
);
if (this.createKnownIndentStateMachine === undefined) {
throw new InvalidStateError("Need knownIndentSm");
}
const sm = this.createKnownIndentStateMachine();
const results = sm.run(indented, lineOffset);
return [context, nextState, results];
}
/**
* Handle an indented text block (first line's indent known).
*
* Extend or override in subclasses.
*
* Recursively run the registered state machine for known-indent indented
* blocks (`self.known_indent_sm`). The indent is the length of the
* match, ``match.end()``.
*/
firstKnownIndent(match, context, nextState) {
const [indented, lineOffset, blankFinish] = this.wsStateMachine.getFirstKnownIndented({
indent: match.result.index + match.result[0].length,
});
let sm;
if (this.createKnownIndentStateMachine !== undefined) {
sm = this.createKnownIndentStateMachine();
const results = sm.run(indented, lineOffset);
return [context, nextState, results];
}
else {
throw new InvalidStateError('createKnownIndentStateMAchine');
}
}
}
export default StateWS;