UNPKG

course-renderer

Version:

Manages CA School Courses file system storage and HTML conversion

113 lines (112 loc) 4.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const ANNOTATION_MARKER = 0x2F; /* / */ function annotation(reader, silent) { 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 = { 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; } exports.annotation = annotation; function getId(annotation) { 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) { 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) { const ANSWER_RE = /answer=\[(.+?)\]/; const match = annotation.match(ANSWER_RE); if (match == null) return null; return match[1]; } function getReadonly(annotation) { const READONLY_RE = /readonly=(\w+)/; const match = annotation.match(READONLY_RE); if (match == null) return null; return match[1]; } function getInit(annotation) { const INITIALIZATION_RE = /init=\[(.+?)\]/; const match = annotation.match(INITIALIZATION_RE); if (match == null) return null; return match[1]; } function getCaption(annotation) { const CAPTION_RE = /caption="(.+)"/; const match = annotation.match(CAPTION_RE); if (match == null) return null; return match[1]; } function getFiles(annotation) { const FILES_RE = /filename=\[(.+?)\]/; const match = annotation.match(FILES_RE); if (match == null) return null; return match[1]; } function getChoiceType(annotation) { const CHOICE_RE = /choiceType=(\w+)/; const match = annotation.match(CHOICE_RE); if (match == null) return 'TEXT'; return match[1]; }