course-renderer
Version:
Manages CA School Courses file system storage and HTML conversion
97 lines (60 loc) • 2.68 kB
text/typescript
// Based from markdown-it fence rule
// fences (``` lang, ~~~ lang)
import Reader from '../reader'
import Token from '../Token'
import { HandlerOptionInterface } from '../handlers'
const TICK_MARKER = 0x60 /* ` */
const TILDE_MARKER = 0x7E /* ~ */
export function fence(reader: Reader, tokens: Token[], silent: boolean, options: HandlerOptionInterface): boolean {
const currentLine = reader.currentLine
let pos, initialPos
pos = initialPos = reader.getCurrentLineStartPos()
const marker = reader.getCharCode(pos)
if (marker !== TICK_MARKER && marker !== TILDE_MARKER) return false
let mem = pos
pos = reader.skipChars(pos, marker)
const len = pos - mem
if ( len < 3 ) return false
// Get the current line string
const fenceLine = reader.getLine(reader.currentLine)
const markup = fenceLine.slice(0, len)
const params = fenceLine.slice(len)
if (params.indexOf(String.fromCharCode(marker)) >= 0) return false
// Since start is found, we can report success here for silent mode
if (silent) return true
let hasEndMarker = false
for(;;) {
reader.currentLine++
reader.skipEmptyLines()
if (reader.currentLine >= reader.maxLine) break
pos = mem = reader.skipEmptyChars()
let max = reader.getCurrentLineEndPos()
if (reader.getCharCode(pos) !== marker) continue
pos = reader.skipChars(pos, marker)
if (pos - mem < len) continue
pos = reader.skipEmptyChars(pos)
if (pos < max) continue
hasEndMarker = true
break
}
let token: Token
if (options.sectionMode && options.replMode) {
const sectionTokChildren = tokens[tokens.length -1].children
const replTok = sectionTokChildren[sectionTokChildren.length - 1];
token = replTok.children[replTok.children.length - 1]
} else if (options.sectionMode || options.replMode) {
const lastToken = tokens[tokens.length - 1]
token = lastToken.children[lastToken.children.length - 1]
} else {
token = tokens[tokens.length -1]
}
token.addCode(reader.getLines(currentLine + 1, reader.currentLine - (hasEndMarker ? 1 : 0)));
token.addParam(params.trim());
if (token.getCodes().length > 1) {
// Let's check if the number of code we have is less or equal to the the number of files.
if (token.getCodes().length > token.getFiles().length) {
throw new Error(`Found more fence block than the number files mentioned on the annotation near ${currentLine} ${JSON.stringify(token, null, 4)}`);
}
}
return true
}