UNPKG

docutils-ts

Version:

Port of the Python Docutils library to TypeScript

161 lines (160 loc) 5.83 kB
import ViewList from './viewList.js'; import { columnIndicies } from './utils.js'; import UnexpectedIndentationError from './error/unexpectedIndentationError.js'; import { InvalidStateError } from "./exceptions.js"; class StringList extends ViewList { splice(index, num, ...elems) { const result = super.splice(index, num, ...elems); return new StringList([...result], undefined, undefined, this.parent, this.parentOffset); } slice(start = 0, end = this.length) { const viewList = super.slice(start, end); // Create a new StringList with the content from viewList return new StringList([...viewList], undefined, undefined, this.parent, this.parentOffset); } constructor(initlist, source, items, parent, parentOffset) { super(initlist, source, items, parent, parentOffset); } trimLeft(trimLength, start = 0, end) { let localEnd = end; if (localEnd === undefined) { localEnd = this.length; } for (let i = start; i < Math.min(localEnd, this.length); i += 1) { if (typeof this[i] === 'undefined') { throw new Error(`${i} ${this.length}`); } this[i] = this[i].substring(trimLength); } } getTextBlock(start, flushLeft = false) { let end = start; const last = this.length; while (end < last) { const line = this[end]; if (!line.trim()) { break; } if (flushLeft && (line.substring(0, 1) === ' ')) { const [source, offset] = this.info(end); throw new UnexpectedIndentationError(this.slice(start, end), source, offset === undefined ? undefined : offset + 1); } end += 1; } return this.slice(start, end); } getIndented(args) { const { untilBlank, stripIndent, blockIndent, firstIndent } = args; const cArgs = { ...args }; if (stripIndent == null) { cArgs.stripIndent = true; } if (cArgs.start == null) { cArgs.start = 0; } let indent = blockIndent; let end = cArgs.start; if (blockIndent != null && firstIndent == null) { cArgs.firstIndent = blockIndent; } if (cArgs.firstIndent != null) { end += 1; } const last = this.length; let blankFinish; while (end < last) { const line = this[end]; if (line && (line[0] !== ' ' || (blockIndent != null && line.substring(0, blockIndent).trim()))) { blankFinish = ((end > cArgs.start) && !this[end - 1].trim()); break; } const stripped = line.replace(/^\s*/, ''); if (!stripped) { if (untilBlank) { blankFinish = true; break; } } else if (blockIndent == null) { const lineIndent = line.length - stripped.length; if (indent == null) { indent = lineIndent; } else { indent = Math.min(indent, lineIndent); } } end += 1; } if (end === last) { blankFinish = true; } const block = this.slice(cArgs.start, end); if (firstIndent != null && block && block.length) { if (block[0] === undefined) { throw new InvalidStateError('block[0]is undefined'); } block[0] = block[0].substring(firstIndent); } if (indent && cArgs.stripIndent) { // console.log(block.constructor.name); block.trimLeft(indent, firstIndent != null ? 1 : 0); } return [block, indent || 0, blankFinish || false]; } get2dBlock(top, left, bottom, right, stripIndent = true) { const block = this.slice(top, bottom); let indent = right; for (let i = 0; i < block.length; i += 1) { // get slice from line, care for combining characters const ci = columnIndicies(block[i]); if (left < 0 || left >= ci.length) { left += block[i].length - ci.length; } else { left = ci[left]; } if (right < 0 || right >= ci.length) { right += block[i].length - ci.length; } else { right = ci[right]; } const line = block[i].substring(left, right).trimEnd(); block[i] = line; if (line) { indent = Math.min(indent, line.length - line.trimStart().length); } } if (stripIndent && (indent > 0) && (right > 0)) { for (let i = 0; i < block.length; i += 1) { block[i] = block[i].substring(indent); } } return block; } padDoubleWidth(arg) { // throw new Unimp('padDoublewidth'); } replace(old, newStr) { for (let i = 0; i < this.length; i += 1) { this[i] = this[i].replace(old, newStr); // fix me !! } } trimTop(n = 1) { /* Remove items from the start of the list, without touching the parent. */ if (n > this.length) { throw new Error(`Size of trim too large; can't trim ${n} items ` + `from a list of size ${this.length}`); } else if (n < 0) { throw new Error('Trim size must be >= 0.'); } this.splice(0, n); this.items.splice(0, n); if (this.parent) { this.parentOffset += n; } } } export default StringList;