Linux moodl-moodle-3s8bw1nuh5yqd9-5b875fdd66-8hs4m 4.4.0-186-generic #216-Ubuntu SMP Wed Jul 1 05:34:05 UTC 2020 x86_64
Apache/2.4.41 (Ubuntu)
: 10.39.0.36 | : 10.36.0.0
Cant Read [ /etc/named.conf ]
7.4.3
www-data
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
README
+ Create Folder
+ Create File
/
var /
moodledata /
filedir /
e8 /
dd /
[ HOME SHELL ]
Name
Size
Permission
Action
e8ddc0051d44e396fcb9f1324511e4...
28.52
KB
-rw-rw-rw-
Delete
Unzip
Zip
${this.title}
Close
Code Editor : e8ddc0051d44e396fcb9f1324511e41b041fa694
/*global H5P*/ H5P.Blanks = (function ($, Question) { /** * @constant * @default */ var STATE_ONGOING = 'ongoing'; var STATE_CHECKING = 'checking'; var STATE_SHOWING_SOLUTION = 'showing-solution'; var STATE_FINISHED = 'finished'; const XAPI_ALTERNATIVE_EXTENSION = 'https://h5p.org/x-api/alternatives'; const XAPI_CASE_SENSITIVITY = 'https://h5p.org/x-api/case-sensitivity'; const XAPI_REPORTING_VERSION_EXTENSION = 'https://h5p.org/x-api/h5p-reporting-version'; /** * @typedef {Object} Params * Parameters/configuration object for Blanks * * @property {Object} Params.behaviour * @property {string} Params.behaviour.confirmRetryDialog * @property {string} Params.behaviour.confirmCheckDialog * * @property {Object} Params.confirmRetry * @property {string} Params.confirmRetry.header * @property {string} Params.confirmRetry.body * @property {string} Params.confirmRetry.cancelLabel * @property {string} Params.confirmRetry.confirmLabel * * @property {Object} Params.confirmCheck * @property {string} Params.confirmCheck.header * @property {string} Params.confirmCheck.body * @property {string} Params.confirmCheck.cancelLabel * @property {string} Params.confirmCheck.confirmLabel */ /** * Initialize module. * * @class H5P.Blanks * @extends H5P.Question * @param {Params} params * @param {number} id Content identification * @param {Object} contentData Task specific content data */ function Blanks(params, id, contentData) { var self = this; // Inheritance Question.call(self, 'blanks'); // IDs this.contentId = id; this.contentData = contentData; this.params = $.extend(true, {}, { text: "Fill in", questions: [ "<p>Oslo is the capital of *Norway*.</p>" ], overallFeedback: [], userAnswers: [], // TODO This isn't in semantics? showSolutions: "Show solution", tryAgain: "Try again", checkAnswer: "Check", changeAnswer: "Change answer", notFilledOut: "Please fill in all blanks to view solution", answerIsCorrect: "':ans' is correct", answerIsWrong: "':ans' is wrong", answeredCorrectly: "Answered correctly", answeredIncorrectly: "Answered incorrectly", solutionLabel: "Correct answer:", inputLabel: "Blank input @num of @total", inputHasTipLabel: "Tip available", tipLabel: "Tip", scoreBarLabel: 'You got :num out of :total points', behaviour: { enableRetry: true, enableSolutionsButton: true, enableCheckButton: true, caseSensitive: true, showSolutionsRequiresInput: true, autoCheck: false, separateLines: false }, a11yCheck: 'Check the answers. The responses will be marked as correct, incorrect, or unanswered.', a11yShowSolution: 'Show the solution. The task will be marked with its correct solution.', a11yRetry: 'Retry the task. Reset all responses and start the task over again.', a11yHeader: 'Checking mode', submitAnswer: 'Submit', }, params); // Delete empty questions for (var i = this.params.questions.length - 1; i >= 0; i--) { if (!this.params.questions[i]) { this.params.questions.splice(i, 1); } } // Previous state this.contentData = contentData; if (this.contentData !== undefined && this.contentData.previousState !== undefined) { this.previousState = this.contentData.previousState; } // Clozes this.clozes = []; // Keep track tabbing forward or backwards this.shiftPressed = false; H5P.$body.keydown(function (event) { if (event.keyCode === 16) { self.shiftPressed = true; } }).keyup(function (event) { if (event.keyCode === 16) { self.shiftPressed = false; } }); // Using instructions as label for our text groups this.labelId = 'h5p-blanks-instructions-' + Blanks.idCounter; this.content = self.createQuestions(); // Check for task media var media = self.params.media; if (media && media.type && media.type.library) { media = media.type; var type = media.library.split(' ')[0]; if (type === 'H5P.Image') { if (media.params.file) { // Register task image self.setImage(media.params.file.path, { disableImageZooming: self.params.media.disableImageZooming || false, alt: media.params.alt, title: media.params.title }); } } else if (type === 'H5P.Video') { if (media.params.sources) { // Register task video self.setVideo(media); } } else if (type === 'H5P.Audio') { if (media.params.files) { // Register task audio self.setAudio(media); } } } // Register task introduction text self.setIntroduction('<div id="' + this.labelId + '">' + self.params.text + '</div>'); // Register task content area self.setContent(self.content, { 'class': self.params.behaviour.separateLines ? 'h5p-separate-lines' : '' }); // ... and buttons self.registerButtons(); // Restore previous state self.setH5PUserState(); } // Inheritance Blanks.prototype = Object.create(Question.prototype); Blanks.prototype.constructor = Blanks; /** * Create all the buttons for the task */ Blanks.prototype.registerButtons = function () { var self = this; var $content = $('[data-content-id="' + self.contentId + '"].h5p-content'); var $containerParents = $content.parents('.h5p-container'); // select find container to attach dialogs to var $container; if ($containerParents.length !== 0) { // use parent highest up if any $container = $containerParents.last(); } else if ($content.length !== 0) { $container = $content; } else { $container = $(document.body); } if (!self.params.behaviour.autoCheck && this.params.behaviour.enableCheckButton) { // Check answer button self.addButton('check-answer', self.params.checkAnswer, function () { // Move focus to top of content self.a11yHeader.innerHTML = self.params.a11yHeader; self.a11yHeader.focus(); self.toggleButtonVisibility(STATE_CHECKING); self.markResults(); self.showEvaluation(); self.triggerAnswered(); }, true, { 'aria-label': self.params.a11yCheck, }, { confirmationDialog: { enable: self.params.behaviour.confirmCheckDialog, l10n: self.params.confirmCheck, instance: self, $parentElement: $container }, textIfSubmitting: self.params.submitAnswer, contentData: self.contentData, }); } // Show solution button self.addButton('show-solution', self.params.showSolutions, function () { self.showCorrectAnswers(false); }, self.params.behaviour.enableSolutionsButton, { 'aria-label': self.params.a11yShowSolution, }); // Try again button if (self.params.behaviour.enableRetry === true) { self.addButton('try-again', self.params.tryAgain, function () { self.a11yHeader.innerHTML = ''; self.resetTask(); self.$questions.filter(':first').find('input:first').focus(); }, true, { 'aria-label': self.params.a11yRetry, }, { confirmationDialog: { enable: self.params.behaviour.confirmRetryDialog, l10n: self.params.confirmRetry, instance: self, $parentElement: $container } }); } self.toggleButtonVisibility(STATE_ONGOING); }; /** * Find blanks in a string and run a handler on those blanks * * @param {string} question * Question text containing blanks enclosed in asterisks. * @param {function} handler * Replaces the blanks text with an input field. * @returns {string} * The question with blanks replaced by the given handler. */ Blanks.prototype.handleBlanks = function (question, handler) { // Go through the text and run handler on all asterisk var clozeEnd, clozeStart = question.indexOf('*'); var self = this; while (clozeStart !== -1 && clozeEnd !== -1) { clozeStart++; clozeEnd = question.indexOf('*', clozeStart); if (clozeEnd === -1) { continue; // No end } var clozeContent = question.substring(clozeStart, clozeEnd); var replacer = ''; if (clozeContent.length) { replacer = handler(self.parseSolution(clozeContent)); clozeEnd++; } else { clozeStart += 1; } question = question.slice(0, clozeStart - 1) + replacer + question.slice(clozeEnd); clozeEnd -= clozeEnd - clozeStart - replacer.length; // Find the next cloze clozeStart = question.indexOf('*', clozeEnd); } return question; }; /** * Create questitons html for DOM */ Blanks.prototype.createQuestions = function () { var self = this; var html = ''; var clozeNumber = 0; for (var i = 0; i < self.params.questions.length; i++) { var question = self.params.questions[i]; // Go through the question text and replace all the asterisks with input fields question = self.handleBlanks(question, function (solution) { // Create new cloze clozeNumber += 1; var defaultUserAnswer = (self.params.userAnswers.length > self.clozes.length ? self.params.userAnswers[self.clozes.length] : null); var cloze = new Blanks.Cloze(solution, self.params.behaviour, defaultUserAnswer, { answeredCorrectly: self.params.answeredCorrectly, answeredIncorrectly: self.params.answeredIncorrectly, solutionLabel: self.params.solutionLabel, inputLabel: self.params.inputLabel, inputHasTipLabel: self.params.inputHasTipLabel, tipLabel: self.params.tipLabel }); self.clozes.push(cloze); return cloze; }); html += '<div role="group" aria-labelledby="' + self.labelId + '">' + question + '</div>'; } self.hasClozes = clozeNumber > 0; this.$questions = $(html); self.a11yHeader = document.createElement('div'); self.a11yHeader.classList.add('hidden-but-read'); self.a11yHeader.tabIndex = -1; self.$questions[0].insertBefore(self.a11yHeader, this.$questions[0].childNodes[0] || null); // Set input fields. this.$questions.find('input').each(function (i) { var afterCheck; if (self.params.behaviour.autoCheck) { afterCheck = function () { var answer = $("<div>").text(this.getUserAnswer()).html(); self.read((this.correct() ? self.params.answerIsCorrect : self.params.answerIsWrong).replace(':ans', answer)); if (self.done || self.allBlanksFilledOut()) { // All answers has been given. Show solutions button. self.toggleButtonVisibility(STATE_CHECKING); self.showEvaluation(); self.triggerAnswered(); self.done = true; } }; } self.clozes[i].setInput($(this), afterCheck, function () { self.toggleButtonVisibility(STATE_ONGOING); if (!self.params.behaviour.autoCheck) { self.hideEvaluation(); } }, i, self.clozes.length); }).keydown(function (event) { var $this = $(this); // Adjust width of text input field to match value self.autoGrowTextField($this); var $inputs, isLastInput; var enterPressed = (event.keyCode === 13); var tabPressedAutoCheck = (event.keyCode === 9 && self.params.behaviour.autoCheck); if (enterPressed || tabPressedAutoCheck) { // Figure out which inputs are left to answer $inputs = self.$questions.find('.h5p-input-wrapper:not(.h5p-correct) .h5p-text-input'); // Figure out if this is the last input isLastInput = $this.is($inputs[$inputs.length - 1]); } if ((tabPressedAutoCheck && isLastInput && !self.shiftPressed) || (enterPressed && isLastInput)) { // Focus first button on next tick setTimeout(function () { self.focusButton(); }, 10); } if (enterPressed) { if (isLastInput) { // Check answers $this.trigger('blur'); } else { // Find next input to focus $inputs.eq($inputs.index($this) + 1).focus(); } return false; // Prevent form submission on enter key } }).on('change', function () { self.answered = true; self.triggerXAPI('interacted'); }); self.on('resize', function () { self.resetGrowTextField(); }); return this.$questions; }; /** * */ Blanks.prototype.autoGrowTextField = function ($input) { // Do not set text field size when separate lines is enabled if (this.params.behaviour.separateLines) { return; } var self = this; var fontSize = parseInt($input.css('font-size'), 10); var minEm = 3; var minPx = fontSize * minEm; var rightPadEm = 3.25; var rightPadPx = fontSize * rightPadEm; var static_min_pad = 0.5 * fontSize; setTimeout(function () { var tmp = $('<div>', { 'text': $input.val() }); tmp.css({ 'position': 'absolute', 'white-space': 'nowrap', 'font-size': $input.css('font-size'), 'font-family': $input.css('font-family'), 'padding': $input.css('padding'), 'width': 'initial' }); $input.parent().append(tmp); var width = tmp.width(); var parentWidth = self.$questions.width(); tmp.remove(); if (width <= minPx) { // Apply min width $input.width(minPx + static_min_pad); } else if (width + rightPadPx >= parentWidth) { // Apply max width of parent $input.width(parentWidth - rightPadPx); } else { // Apply width that wraps input $input.width(width + static_min_pad); } }, 1); }; /** * Resize all text field growth to current size. */ Blanks.prototype.resetGrowTextField = function () { var self = this; this.$questions.find('input').each(function () { self.autoGrowTextField($(this)); }); }; /** * Toggle buttons dependent of state. * * Using CSS-rules to conditionally show/hide using the data-attribute [data-state] */ Blanks.prototype.toggleButtonVisibility = function (state) { // The show solutions button is hidden if all answers are correct var allCorrect = (this.getScore() === this.getMaxScore()); if (this.params.behaviour.autoCheck && allCorrect) { // We are viewing the solutions state = STATE_FINISHED; } if (this.params.behaviour.enableSolutionsButton) { if (state === STATE_CHECKING && !allCorrect) { this.showButton('show-solution'); } else { this.hideButton('show-solution'); } } if (this.params.behaviour.enableRetry) { if ((state === STATE_CHECKING && !allCorrect) || state === STATE_SHOWING_SOLUTION) { this.showButton('try-again'); } else { this.hideButton('try-again'); } } if (state === STATE_ONGOING) { this.showButton('check-answer'); } else { this.hideButton('check-answer'); } this.trigger('resize'); }; /** * Check if solution is allowed. Warn user if not */ Blanks.prototype.allowSolution = function () { if (this.params.behaviour.showSolutionsRequiresInput === true) { if (!this.allBlanksFilledOut()) { this.updateFeedbackContent(this.params.notFilledOut); this.read(this.params.notFilledOut); return false; } } return true; }; /** * Check if all blanks are filled out * * @method allBlanksFilledOut * @return {boolean} Returns true if all blanks are filled out. */ Blanks.prototype.allBlanksFilledOut = function () { return !this.clozes.some(function (cloze) { return !cloze.filledOut(); }); }; /** * Mark which answers are correct and which are wrong and disable fields if retry is off. */ Blanks.prototype.markResults = function () { var self = this; for (var i = 0; i < self.clozes.length; i++) { self.clozes[i].checkAnswer(); if (!self.params.behaviour.enableRetry) { self.clozes[i].disableInput(); } } this.trigger('resize'); }; /** * Removed marked results */ Blanks.prototype.removeMarkedResults = function () { this.$questions.find('.h5p-input-wrapper').removeClass('h5p-correct h5p-wrong'); this.$questions.find('.h5p-input-wrapper > input').attr('disabled', false); this.trigger('resize'); }; /** * Displays the correct answers * @param {boolean} [alwaysShowSolution] * Will always show solution if true */ Blanks.prototype.showCorrectAnswers = function (alwaysShowSolution) { if (!alwaysShowSolution && !this.allowSolution()) { return; } this.toggleButtonVisibility(STATE_SHOWING_SOLUTION); this.hideSolutions(); for (var i = 0; i < this.clozes.length; i++) { this.clozes[i].showSolution(); } this.trigger('resize'); }; /** * Toggle input allowed for all input fields * * @method function * @param {boolean} enabled True if fields should allow input, otherwise false */ Blanks.prototype.toggleAllInputs = function (enabled) { for (var i = 0; i < this.clozes.length; i++) { this.clozes[i].toggleInput(enabled); } }; /** * Display the correct solution for the input boxes. * * This is invoked from CP and QS - be carefull! */ Blanks.prototype.showSolutions = function () { this.params.behaviour.enableSolutionsButton = true; this.toggleButtonVisibility(STATE_FINISHED); this.markResults(); this.showEvaluation(); this.showCorrectAnswers(true); this.toggleAllInputs(false); //Hides all buttons in "show solution" mode. this.hideButtons(); }; /** * Resets the complete task. * Used in contracts. * @public */ Blanks.prototype.resetTask = function () { this.answered = false; this.hideEvaluation(); this.hideSolutions(); this.clearAnswers(); this.removeMarkedResults(); this.toggleButtonVisibility(STATE_ONGOING); this.resetGrowTextField(); this.toggleAllInputs(true); this.done = false; }; /** * Hides all buttons. * @public */ Blanks.prototype.hideButtons = function () { this.toggleButtonVisibility(STATE_FINISHED); }; /** * Trigger xAPI answered event */ Blanks.prototype.triggerAnswered = function () { this.answered = true; var xAPIEvent = this.createXAPIEventTemplate('answered'); this.addQuestionToXAPI(xAPIEvent); this.addResponseToXAPI(xAPIEvent); this.trigger(xAPIEvent); }; /** * Get xAPI data. * Contract used by report rendering engine. * * @see contract at {@link https://h5p.org/documentation/developers/contracts#guides-header-6} */ Blanks.prototype.getXAPIData = function () { var xAPIEvent = this.createXAPIEventTemplate('answered'); this.addQuestionToXAPI(xAPIEvent); this.addResponseToXAPI(xAPIEvent); return { statement: xAPIEvent.data.statement }; }; /** * Generate xAPI object definition used in xAPI statements. * @return {Object} */ Blanks.prototype.getxAPIDefinition = function () { var definition = {}; definition.description = { 'en-US': this.params.text }; definition.type = 'http://adlnet.gov/expapi/activities/cmi.interaction'; definition.interactionType = 'fill-in'; const clozeSolutions = []; let crp = ''; // xAPI forces us to create solution patterns for all possible solution combinations for (var i = 0; i < this.params.questions.length; i++) { var question = this.handleBlanks(this.params.questions[i], function (solution) { // Collect all solution combinations for the H5P Alternative extension clozeSolutions.push(solution.solutions); // Create a basic response pattern out of the first alternative for each blanks field crp += (!crp ? '' : '[,]') + solution.solutions[0]; // We replace the solutions in the question with a "blank" return '__________'; }); definition.description['en-US'] += question; } // Set the basic response pattern (not supporting multiple alternatives for blanks) definition.correctResponsesPattern = [ '{case_matters=' + this.params.behaviour.caseSensitive + '}' + crp, ]; // Add the H5P Alternative extension which provides all the combinations of different answers // Reporting software will need to support this extension for alternatives to work. definition.extensions = definition.extensions || {}; definition.extensions[XAPI_CASE_SENSITIVITY] = this.params.behaviour.caseSensitive; definition.extensions[XAPI_ALTERNATIVE_EXTENSION] = clozeSolutions; return definition; }; /** * Add the question itselt to the definition part of an xAPIEvent */ Blanks.prototype.addQuestionToXAPI = function (xAPIEvent) { var definition = xAPIEvent.getVerifiedStatementValue(['object', 'definition']); $.extend(true, definition, this.getxAPIDefinition()); // Set reporting module version if alternative extension is used if (this.hasAlternatives) { const context = xAPIEvent.getVerifiedStatementValue(['context']); context.extensions = context.extensions || {}; context.extensions[XAPI_REPORTING_VERSION_EXTENSION] = '1.1.0'; } }; /** * Parse the solution text (text between the asterisks) * * @param {string} solutionText * @returns {object} with the following properties * - tip: the tip text for this solution, undefined if no tip * - solutions: array of solution words */ Blanks.prototype.parseSolution = function (solutionText) { var tip, solution; var tipStart = solutionText.indexOf(':'); if (tipStart !== -1) { // Found tip, now extract tip = solutionText.slice(tipStart + 1); solution = solutionText.slice(0, tipStart); } else { solution = solutionText; } // Split up alternatives var solutions = solution.split('/'); this.hasAlternatives = this.hasAlternatives || solutions.length > 1; // Trim solutions for (var i = 0; i < solutions.length; i++) { solutions[i] = H5P.trim(solutions[i]); //decodes html entities var elem = document.createElement('textarea'); elem.innerHTML = solutions[i]; solutions[i] = elem.value; } return { tip: tip, solutions: solutions }; }; /** * Add the response part to an xAPI event * * @param {H5P.XAPIEvent} xAPIEvent * The xAPI event we will add a response to */ Blanks.prototype.addResponseToXAPI = function (xAPIEvent) { xAPIEvent.setScoredResult(this.getScore(), this.getMaxScore(), this); xAPIEvent.data.statement.result.response = this.getxAPIResponse(); }; /** * Generate xAPI user response, used in xAPI statements. * @return {string} User answers separated by the "[,]" pattern */ Blanks.prototype.getxAPIResponse = function () { var usersAnswers = this.getCurrentState(); return usersAnswers.join('[,]'); }; /** * Show evaluation widget, i.e: 'You got x of y blanks correct' */ Blanks.prototype.showEvaluation = function () { var maxScore = this.getMaxScore(); var score = this.getScore(); var scoreText = H5P.Question.determineOverallFeedback(this.params.overallFeedback, score / maxScore).replace('@score', score).replace('@total', maxScore); this.setFeedback(scoreText, score, maxScore, this.params.scoreBarLabel); if (score === maxScore) { this.toggleButtonVisibility(STATE_FINISHED); } }; /** * Hide the evaluation widget */ Blanks.prototype.hideEvaluation = function () { // Clear evaluation section. this.removeFeedback(); }; /** * Hide solutions. (/try again) */ Blanks.prototype.hideSolutions = function () { // Clean solution from quiz this.$questions.find('.h5p-correct-answer').remove(); }; /** * Get maximum number of correct answers. * * @returns {Number} Max points */ Blanks.prototype.getMaxScore = function () { var self = this; return self.clozes.length; }; /** * Count the number of correct answers. * * @returns {Number} Points */ Blanks.prototype.getScore = function () { var self = this; var correct = 0; for (var i = 0; i < self.clozes.length; i++) { if (self.clozes[i].correct()) { correct++; } self.params.userAnswers[i] = self.clozes[i].getUserAnswer(); } return correct; }; Blanks.prototype.getTitle = function () { return H5P.createTitle((this.contentData.metadata && this.contentData.metadata.title) ? this.contentData.metadata.title : 'Fill In'); }; /** * Clear the user's answers */ Blanks.prototype.clearAnswers = function () { this.clozes.forEach(function (cloze) { cloze.setUserInput(''); cloze.resetAriaLabel(); }); }; /** * Checks if all has been answered. * * @returns {Boolean} */ Blanks.prototype.getAnswerGiven = function () { return this.answered || !this.hasClozes; }; /** * Helps set focus the given input field. * @param {jQuery} $input */ Blanks.setFocus = function ($input) { setTimeout(function () { $input.focus(); }, 1); }; /** * Returns an object containing content of each cloze * * @returns {object} object containing content for each cloze */ Blanks.prototype.getCurrentState = function () { var clozesContent = []; // Get user input for every cloze this.clozes.forEach(function (cloze) { clozesContent.push(cloze.getUserAnswer()); }); return clozesContent; }; /** * Sets answers to current user state */ Blanks.prototype.setH5PUserState = function () { var self = this; var isValidState = (this.previousState !== undefined && this.previousState.length && this.previousState.length === this.clozes.length); // Check that stored user state is valid if (!isValidState) { return; } // Set input from user state var hasAllClozesFilled = true; this.previousState.forEach(function (clozeContent, ccIndex) { // Register that an answer has been given if (clozeContent.length) { self.answered = true; } var cloze = self.clozes[ccIndex]; cloze.setUserInput(clozeContent); // Handle instant feedback if (self.params.behaviour.autoCheck) { if (cloze.filledOut()) { cloze.checkAnswer(); } else { hasAllClozesFilled = false; } } }); if (self.params.behaviour.autoCheck && hasAllClozesFilled) { self.showEvaluation(); self.toggleButtonVisibility(STATE_CHECKING); } }; /** * Disables any active input. Useful for freezing the task and dis-allowing * modification of wrong answers. */ Blanks.prototype.disableInput = function () { this.$questions.find('input').attr('disabled', true); }; Blanks.idCounter = 0; return Blanks; })(H5P.jQuery, H5P.Question); /** * Static utility method for parsing H5P.Blanks qestion into a format useful * for creating reports. * * Example question: 'H5P content may be edited using a *browser/web-browser:something you use every day*.' * * Produces the following result: * [ * { * type: 'text', * content: 'H5P content may be edited using a ' * }, * { * type: 'answer', * correct: ['browser', 'web-browser'] * }, * { * type: 'text', * content: '.' * } * ] * * @param {string} question */ H5P.Blanks.parseText = function (question) { var blank = new H5P.Blanks({ question: question }); /** * Parses a text into an array where words starting and ending * with an asterisk are separated from other text. * e.g ["this", "*is*", " an ", "*example*"] * * @param {string} text * * @return {string[]} */ function tokenizeQuestionText(text) { return text.split(/(\*.*?\*)/).filter(function (str) { return str.length > 0; } ); } function startsAndEndsWithAnAsterisk(str) { return str.substr(0,1) === '*' && str.substr(-1) === '*'; } function replaceHtmlTags(str, value) { return str.replace(/<[^>]*>/g, value); } return tokenizeQuestionText(replaceHtmlTags(question, '')).map(function (part) { return startsAndEndsWithAnAsterisk(part) ? ({ type: 'answer', correct: blank.parseSolution(part.slice(1, -1)).solutions }) : ({ type: 'text', content: part }); }); };
Close