UNPKG

course-renderer

Version:

Manages CA School Courses file system storage and HTML conversion

163 lines (112 loc) 4.59 kB
import Reader from '../reader' const ANNOTATION_MARKER = 0x2F /* / */ export interface AnnotationInterface { type: string, answer: string, readonly?: string, caption?: string, id?: string, init?: string, files?: string, raw: string, choiceType?: string } export function annotation (reader: Reader, silent: boolean): any { let pos = reader.getCurrentLineStartPos() if ( reader.getCharCode(pos++) !== ANNOTATION_MARKER || reader.getCharCode(pos++) !== ANNOTATION_MARKER || reader.getCharCode(pos++) !== ANNOTATION_MARKER ) { return false } if ( silent ) return true // If we're still here, then we need to parse the annotation line and move the position of the reader cursor const annotationText = reader.getLine(reader.currentLine) const parsed: AnnotationInterface = { type: getType(annotationText), answer: getAnswer(annotationText), readonly: getReadonly(annotationText), caption: getCaption(annotationText), id: getId(annotationText), init: getInit(annotationText), files: getFiles(annotationText), choiceType: getChoiceType(annotationText), raw: annotationText } if (parsed.type == null) { throw new Error(`Expecting a 'type' on the annotation but found '${annotationText}`) } if ( (parsed.type === 'SS' || parsed.type === 'MS' || parsed.type === 'CR') && parsed.id == null ) { throw new Error(`SS, MS and CR questions must have an ID at annotation ${annotationText}`) } if (parsed.type !== 'SS' && parsed.type !== 'MS' && parsed.type !== 'CR' && parsed.type !== 'TI' && parsed.type !== 'REPL') { throw new Error(`Annotation type may only have the following value 'SS', 'MS', 'CR' and 'TI' but found ${parsed.type} at annotation ${annotationText}`) } if (parsed.type !== 'REPL' && parsed.answer == null) { throw new Error(`Annotation type CR, SS, MS and TI must have an answer specified at annotation ${annotationText}`) } if (parsed.type === 'REPL' && parsed.answer != null) { throw new Error(`Annotation type REPL cannot have an answer annotation at ${annotationText}`) } if (parsed.type != 'REPL' && parsed.readonly != null) { throw new Error(`readonly annotation can only be applied to REPL type at ${annotationText}`) } if (parsed.type == 'REPL' && parsed.readonly != null && parsed.readonly != 'true') { throw new Error(`readonly annotation can only support a 'true' value at ${annotationText}`) } if (parsed.type == 'SS' && parsed.answer.toString().split(',').length > 1) { throw new Error(`Annotation type SS must only have a single answer at ${annotationText}`) } if (parsed.choiceType != 'TEXT' && parsed.choiceType != 'HTML') { throw new Error(`choiceType annotation can only support a 'TEXT' and 'HTML' value at ${annotationText}`) } reader.nextLine() return parsed; } function getId(annotation: string): string { const ID_RE = /id=(\w+-\w+-\w+-\w+-\w+)/ const match = annotation.match(ID_RE) if (match === null) return null return match[1] } function getType(annotation: string): string { const TYPE_RE = /type=(\w\w(\w\w)?)/ const match = annotation.match(TYPE_RE) if (match == null) return null return match[1] } function getAnswer(annotation: string) { const ANSWER_RE = /answer=\[(.+?)\]/ const match = annotation.match(ANSWER_RE) if (match == null) return null return match[1] } function getReadonly(annotation: string) { const READONLY_RE = /readonly=(\w+)/ const match = annotation.match(READONLY_RE) if (match == null) return null return match[1] } function getInit(annotation: string) { const INITIALIZATION_RE = /init=\[(.+?)\]/ const match = annotation.match(INITIALIZATION_RE) if (match == null) return null return match[1] } function getCaption(annotation: string) { const CAPTION_RE = /caption="(.+)"/ const match = annotation.match(CAPTION_RE) if (match == null) return null return match[1] } function getFiles(annotation: string) { const FILES_RE = /filename=\[(.+?)\]/ const match = annotation.match(FILES_RE) if (match == null) return null return match[1] } function getChoiceType(annotation: string) { const CHOICE_RE = /choiceType=(\w+)/ const match = annotation.match(CHOICE_RE); if (match == null) return 'TEXT'; return match[1]; }