UNPKG

course-renderer

Version:

Manages CA School Courses file system storage and HTML conversion

165 lines (126 loc) 4.03 kB
import { isSpace, isLineFeed, isWhiteSpace } from './utils' export default class Reader { source: string length: number currentLine: number startLinePos: number[] endLinePos: number[] maxLine: number constructor(src: string) { this.source = src.replace(/\r\n/g, "\n") this.length = this.source.length this.currentLine = 0 // Initial line position for reading this.parseSource() } parseSource() { this.startLinePos = [] this.endLinePos = [] let start, pos, len for ( start = pos = 0, len = this.length; pos < len; pos++) { let ch = this.getCharCode(pos) if (ch === 0x0A || pos === len - 1) { if (ch !== 0x0A) pos++ this.startLinePos.push(start) this.endLinePos.push(pos) start = pos + 1 } } this.maxLine = this.startLinePos.length } getCharCode(pos: number = this.getCurrentLineStartPos()) { return this.source.charCodeAt(pos) } getCurrentLineStartPos() { return this.getLineStartPos() } getLineStartPos(line: number = this.currentLine) { return this.startLinePos[line] } getCurrentLineEndPos() { return this.getLineEndPos() } getLineEndPos(line: number = this.currentLine) { return this.endLinePos[line] } getLine(line: number) { return this.source.slice(this.getLineStartPos(line), this.getLineEndPos(line)) } getLines( start: number, end: number) { let queue = [] if (start === end) { return this.getLine(start) } while ( start <= end ) { queue.push(this.getLine(start)) start++ } return queue.join('\n') } // Moves the position to the next line. Needs to REDO nextLine() { this.currentLine++; } isEnd() { return this.currentLine >= this.maxLine } isEmpty(line: number) { let pos: number let max = this.getLineEndPos(line) let isEmpty = true for (pos = this.getLineStartPos(line); pos <= max; pos++) { if (!isSpace(this.getCharCode(pos)) && !isLineFeed(this.getCharCode(pos))) { isEmpty = false break } } return isEmpty } nextNonEmptyLines() { this.nextLine() this.skipEmptyLines() } jumpBeforeEmptyLines(line: number = this.currentLine) { while (line < this.maxLine) { if (!this.isEmpty(line)) break line++ } return line } skipEmptyChars(startPos: number = this.getCurrentLineStartPos()) { let pos: number for (pos = startPos; pos < this.length; pos++) { if (!isWhiteSpace(this.getCharCode(pos))) break } return pos } // Skip empty lines from the current pos skipEmptyLines() { let pos: number let currentLine: number let exit = false for (currentLine = this.currentLine; currentLine < this.maxLine; currentLine++) { for (pos = this.startLinePos[currentLine]; pos <= this.endLinePos[currentLine]; pos++) { let ch = this.getCharCode(pos) if (!isLineFeed(ch) && !isSpace(this.getCharCode(pos))) { this.currentLine = currentLine exit = true break } } if (exit) break } } skipSpaces(pos: number) { for (let max = this.length; pos < max; pos++) { let ch = this.getCharCode(pos) if (!isSpace(ch)) break } return pos } skipChars(pos: number = this.getCurrentLineStartPos(), code: any) { for (const max = this.length; pos < max; pos++) { if (this.getCharCode(pos) !== code) break } return pos } }