@khanacademy/perseus-core 18.0.0 → 18.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export * as GrapherUtil from "./utils/grapher-util";
|
|
|
14
14
|
export { generateTestPerseusItem, generateTestPerseusRenderer, } from "./utils/test-utils";
|
|
15
15
|
export { itemHasRationales } from "./utils/item-has-rationales";
|
|
16
16
|
export { itemHasHints } from "./utils/item-has-hints";
|
|
17
|
-
export { parsePerseusItem, parseAndMigratePerseusItem, parseAndMigratePerseusArticle, type ParseFailureDetail, } from "./parse-perseus-json";
|
|
17
|
+
export { parsePerseusItem, parseAndMigratePerseusItem, parseAndMigratePerseusArticle, parseAndMigrateUserInputMap, type ParseFailureDetail, } from "./parse-perseus-json";
|
|
18
18
|
export { isSuccess, isFailure, type Result, type Success, type Failure, } from "./parse-perseus-json/result";
|
|
19
19
|
export { libVersion } from "./version";
|
|
20
20
|
export { Errors } from "./error/errors";
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ var _ = require('underscore');
|
|
|
6
6
|
require('tiny-invariant');
|
|
7
7
|
var KAS = require('@khanacademy/kas');
|
|
8
8
|
var perseusUtils = require('@khanacademy/perseus-utils');
|
|
9
|
+
var pureMarkdown = require('@khanacademy/pure-markdown');
|
|
9
10
|
|
|
10
11
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
11
12
|
|
|
@@ -207,9 +208,51 @@ const parsePerseusAnswerArea=pipeParsers(defaulted(object({}),()=>({}))).then(co
|
|
|
207
208
|
|
|
208
209
|
const parsePerseusItem$1=object({question:parsePerseusRenderer,hints:defaulted(array(parseHint),()=>[]),answerArea:parsePerseusAnswerArea});
|
|
209
210
|
|
|
210
|
-
|
|
211
|
+
const parseCategorizerUserInput=object({values:array(number)});
|
|
211
212
|
|
|
212
|
-
const
|
|
213
|
+
const parseCSProgramUserInput=object({status:enumeration("correct","incorrect","incomplete"),message:nullable(string)});
|
|
214
|
+
|
|
215
|
+
const parseDropdownUserInput=object({value:number});
|
|
216
|
+
|
|
217
|
+
const parseExpressionUserInput=string;
|
|
218
|
+
|
|
219
|
+
const parseFreeResponseUserInput=object({currentValue:string});
|
|
220
|
+
|
|
221
|
+
const coord=pair(number,number);const coordPair=pair(coord,coord);const parseAbsoluteValueBranch=object({type:constant("absolute_value"),coords:nullable(coordPair)});const parseExponentialBranch=object({type:constant("exponential"),asymptote:coordPair,coords:nullable(coordPair)});const parseLinearBranch=object({type:constant("linear"),coords:nullable(coordPair)});const parseLogarithmBranch=object({type:constant("logarithm"),asymptote:coordPair,coords:nullable(coordPair)});const parseQuadraticBranch=object({type:constant("quadratic"),coords:nullable(coordPair)});const parseSinusoidBranch=object({type:constant("sinusoid"),coords:nullable(coordPair)});const parseTangentBranch=object({type:constant("tangent"),coords:nullable(coordPair)});const parseGrapherUserInput=discriminatedUnionOn("type").withBranch("absolute_value",parseAbsoluteValueBranch).withBranch("exponential",parseExponentialBranch).withBranch("linear",parseLinearBranch).withBranch("logarithm",parseLogarithmBranch).withBranch("quadratic",parseQuadraticBranch).withBranch("sinusoid",parseSinusoidBranch).withBranch("tangent",parseTangentBranch).parser;
|
|
222
|
+
|
|
223
|
+
const parseGroupUserInput=(rawVal,ctx)=>parseUserInputMap(rawVal,ctx);
|
|
224
|
+
|
|
225
|
+
const parseIFrameUserInput=object({status:enumeration("correct","incorrect","incomplete"),message:nullable(string)});
|
|
226
|
+
|
|
227
|
+
const parseInputNumberUserInput=object({currentValue:string});
|
|
228
|
+
|
|
229
|
+
const parseInteractiveGraphUserInput=parsePerseusGraphType;
|
|
230
|
+
|
|
231
|
+
const parseLabelImageUserInput=object({markers:array(object({selected:optional(array(string)),label:string}))});
|
|
232
|
+
|
|
233
|
+
const parseMatcherUserInput=object({left:array(string),right:array(string)});
|
|
234
|
+
|
|
235
|
+
const parseMatrixUserInput=object({answers:array(array(number))});
|
|
236
|
+
|
|
237
|
+
const parseNumberLineUserInput=object({numLinePosition:number,rel:enumeration("eq","lt","gt","le","ge"),numDivisions:number});
|
|
238
|
+
|
|
239
|
+
const parseNumericInputUserInput=object({currentValue:string});
|
|
240
|
+
|
|
241
|
+
const parseOrdererUserInput=object({current:array(string)});
|
|
242
|
+
|
|
243
|
+
const parsePlotterUserInput=array(number);
|
|
244
|
+
|
|
245
|
+
const parseRadioUserInput=object({choicesSelected:array(boolean)});
|
|
246
|
+
|
|
247
|
+
const parseSorterUserInput=object({options:array(string),changed:boolean});
|
|
248
|
+
|
|
249
|
+
const parseTableUserInput=array(array(string));
|
|
250
|
+
|
|
251
|
+
const parseUserInputMap=(rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx.failure("UserInputMap",rawValue)}const userInputMap={};for(const key of Object.keys(rawValue)){const entryResult=parseUserInputMapEntry([key,rawValue[key]],userInputMap,ctx.forSubtree(key));if(isFailure(entryResult)){return entryResult}}return ctx.success(userInputMap)};const parseUserInputMapEntry=([id,userInput],userInputMap,ctx)=>{const idComponentsResult=parseWidgetIdComponents(id.split(" "),ctx.forSubtree("(widget ID)"));if(isFailure(idComponentsResult)){return idComponentsResult}const[type,n]=idComponentsResult.value;function parseAndAssign(key,parse){const userInputResult=parse(userInput,ctx);if(isFailure(userInputResult)){return userInputResult}userInputMap[key]=userInputResult.value;return ctx.success(undefined)}switch(type){case "categorizer":return parseAndAssign(`categorizer ${n}`,parseCategorizerUserInput);case "cs-program":return parseAndAssign(`cs-program ${n}`,parseCSProgramUserInput);case "dropdown":return parseAndAssign(`dropdown ${n}`,parseDropdownUserInput);case "expression":return parseAndAssign(`expression ${n}`,parseExpressionUserInput);case "free-response":return parseAndAssign(`free-response ${n}`,parseFreeResponseUserInput);case "grapher":return parseAndAssign(`grapher ${n}`,parseGrapherUserInput);case "group":return parseAndAssign(`group ${n}`,parseGroupUserInput);case "iframe":return parseAndAssign(`iframe ${n}`,parseIFrameUserInput);case "input-number":return parseAndAssign(`input-number ${n}`,parseInputNumberUserInput);case "interactive-graph":return parseAndAssign(`interactive-graph ${n}`,parseInteractiveGraphUserInput);case "label-image":return parseAndAssign(`label-image ${n}`,parseLabelImageUserInput);case "matcher":return parseAndAssign(`matcher ${n}`,parseMatcherUserInput);case "matrix":return parseAndAssign(`matrix ${n}`,parseMatrixUserInput);case "number-line":return parseAndAssign(`number-line ${n}`,parseNumberLineUserInput);case "numeric-input":return parseAndAssign(`numeric-input ${n}`,parseNumericInputUserInput);case "orderer":return parseAndAssign(`orderer ${n}`,parseOrdererUserInput);case "plotter":return parseAndAssign(`plotter ${n}`,parsePlotterUserInput);case "radio":return parseAndAssign(`radio ${n}`,parseRadioUserInput);case "sorter":return parseAndAssign(`sorter ${n}`,parseSorterUserInput);case "table":return parseAndAssign(`table ${n}`,parseTableUserInput);default:return parseAndAssign(`${type} ${n}`,any)}};
|
|
252
|
+
|
|
253
|
+
function parsePerseusItem(json){if(isRealJSONParse(JSON.parse)){return JSON.parse(json)}throw new Error("Something went wrong.")}function parseAndMigratePerseusItem(data){throwErrorIfCheatingDetected();const object=typeof data==="string"?JSON.parse(data):data;const result=parse(object,parsePerseusItem$1);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function parseAndMigratePerseusArticle(data){throwErrorIfCheatingDetected();const object=typeof data==="string"?JSON.parse(data):data;const result=parse(object,parsePerseusArticle);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function parseAndMigrateUserInputMap(data){const object=typeof data==="string"?JSON.parse(data):data;const result=parse(object,parseUserInputMap);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function throwErrorIfCheatingDetected(){if(!isRealJSONParse(JSON.parse)){throw new Error("Something went wrong.")}}
|
|
254
|
+
|
|
255
|
+
const libName="@khanacademy/perseus-core";const libVersion="18.2.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
213
256
|
|
|
214
257
|
const Errors=Object.freeze({Unknown:"Unknown",Internal:"Internal",InvalidInput:"InvalidInput",NotAllowed:"NotAllowed",TransientService:"TransientService",Service:"Service"});
|
|
215
258
|
|
|
@@ -251,6 +294,8 @@ const defaultWidgetOptions$n={graph:{labels:["x","y"],range:[[-10,10],[-10,10]],
|
|
|
251
294
|
|
|
252
295
|
class Registry{throwIfUnregistered(){if(!this.anythingRegistered){throw new Error(`${this.name} accessed before initialization!`)}}has(key){this.throwIfUnregistered();return Object.prototype.hasOwnProperty.call(this.contents,key)}get(key){this.throwIfUnregistered();return this.contents[key]}keys(){this.throwIfUnregistered();return Object.keys(this.contents)}entries(){this.throwIfUnregistered();return Object.entries(this.contents)}set(key,value){this.anythingRegistered=true;this.contents[key]=value;}constructor(name="Registry"){this.contents={};this.anythingRegistered=false;this.name=name;}}
|
|
253
296
|
|
|
297
|
+
const deprecatedStandinWidgetLogic={name:"deprecated-standin",accessible:true};
|
|
298
|
+
|
|
254
299
|
function getIFramePublicWidgetOptions(options){return options}
|
|
255
300
|
|
|
256
301
|
const defaultWidgetOptions$m={url:"",settings:[{name:"",value:""}],width:"400",height:"400",allowFullScreen:false,allowTopNavigation:false};const iframeWidgetLogic={name:"iframe",defaultWidgetOptions: defaultWidgetOptions$m,getPublicWidgetOptions:getIFramePublicWidgetOptions,accessible:false};
|
|
@@ -327,7 +372,7 @@ const defaultRows=4;const defaultColumns=1;const answers=new Array(defaultRows).
|
|
|
327
372
|
|
|
328
373
|
const defaultWidgetOptions$1={location:""};const videoWidgetLogic={name:"video",defaultWidgetOptions: defaultWidgetOptions$1,supportedAlignments:["block","float-left","float-right","full-width"],defaultAlignment:"block",accessible:true};
|
|
329
374
|
|
|
330
|
-
const widgets=new Registry("Core widget registry");function registerWidget(type,logic){widgets.set(type,logic);}function isWidgetRegistered(type){const widgetLogic=widgets.get(type);return Boolean(widgetLogic)}function getCurrentVersion(type){const widgetLogic=widgets.get(type);return widgetLogic?.version||{major:0,minor:0}}const getPublicWidgetOptionsFunction=type=>{return widgets.get(type)?.getPublicWidgetOptions??(i=>i)};function getDefaultWidgetOptions(type){const widgetLogic=widgets.get(type);return widgetLogic?.defaultWidgetOptions||{}}function isAccessible(type,widgetOptions){const accessible=widgets.get(type)?.accessible;return typeof accessible==="function"?accessible(widgetOptions):!!accessible}const traverseChildWidgets$1=(widgetInfo,traverseRenderer)=>{if(!traverseRenderer){throw new PerseusError("traverseRenderer must be provided, but was not",Errors.Internal)}if(!widgetInfo||!widgetInfo.type||!widgets.get(widgetInfo.type)){return widgetInfo}const widgetExports=widgets.get(widgetInfo.type);const props=widgetInfo.options;if(widgetExports?.traverseChildWidgets!=null&&props!=null){const newProps=widgetExports.traverseChildWidgets(props,traverseRenderer);return {...widgetInfo,options:newProps}}return widgetInfo};const getSupportedAlignments=type=>{const widgetLogic=widgets.get(type);if(!widgetLogic?.supportedAlignments?.[0]){return ["default"]}return widgetLogic?.supportedAlignments};const getDefaultAlignment=type=>{const widgetLogic=widgets.get(type);if(!widgetLogic?.defaultAlignment){return "block"}return widgetLogic.defaultAlignment};function registerCoreWidgets(){const widgets=[categorizerWidgetLogic,csProgramWidgetLogic,definitionWidgetLogic,dropdownWidgetLogic,explanationWidgetLogic,expressionWidgetLogic,gradedGroupWidgetLogic,gradedGroupSetWidgetLogic,grapherWidgetLogic,groupWidgetLogic,iframeWidgetLogic,imageWidgetLogic,inputNumberWidgetLogic,interactionWidgetLogic,interactiveGraphWidgetLogic,labelImageWidgetLogic,matcherWidgetLogic,matrixWidgetLogic,measurerWidgetLogic,numberLineWidgetLogic,numericInputWidgetLogic,ordererWidgetLogic,passageWidgetLogic,passageRefWidgetLogic,passageRefTargetWidgetLogic,phetSimulationWidgetLogic,plotterWidgetLogic,pythonProgramWidgetLogic,radioWidgetLogic,sorterWidgetLogic,tableWidgetLogic,videoWidgetLogic];widgets.forEach(w=>{registerWidget(w.name,w);});}
|
|
375
|
+
const widgets=new Registry("Core widget registry");function registerWidget(type,logic){widgets.set(type,logic);}function isWidgetRegistered(type){const widgetLogic=widgets.get(type);return Boolean(widgetLogic)}function getCurrentVersion(type){const widgetLogic=widgets.get(type);return widgetLogic?.version||{major:0,minor:0}}const getPublicWidgetOptionsFunction=type=>{return widgets.get(type)?.getPublicWidgetOptions??(i=>i)};function getDefaultWidgetOptions(type){const widgetLogic=widgets.get(type);return widgetLogic?.defaultWidgetOptions||{}}function isAccessible(type,widgetOptions){const accessible=widgets.get(type)?.accessible;return typeof accessible==="function"?accessible(widgetOptions):!!accessible}const traverseChildWidgets$1=(widgetInfo,traverseRenderer)=>{if(!traverseRenderer){throw new PerseusError("traverseRenderer must be provided, but was not",Errors.Internal)}if(!widgetInfo||!widgetInfo.type||!widgets.get(widgetInfo.type)){return widgetInfo}const widgetExports=widgets.get(widgetInfo.type);const props=widgetInfo.options;if(widgetExports?.traverseChildWidgets!=null&&props!=null){const newProps=widgetExports.traverseChildWidgets(props,traverseRenderer);return {...widgetInfo,options:newProps}}return widgetInfo};const getSupportedAlignments=type=>{const widgetLogic=widgets.get(type);if(!widgetLogic?.supportedAlignments?.[0]){return ["default"]}return widgetLogic?.supportedAlignments};const getDefaultAlignment=type=>{const widgetLogic=widgets.get(type);if(!widgetLogic?.defaultAlignment){return "block"}return widgetLogic.defaultAlignment};function registerCoreWidgets(){const widgets=[categorizerWidgetLogic,csProgramWidgetLogic,definitionWidgetLogic,deprecatedStandinWidgetLogic,dropdownWidgetLogic,explanationWidgetLogic,expressionWidgetLogic,gradedGroupWidgetLogic,gradedGroupSetWidgetLogic,grapherWidgetLogic,groupWidgetLogic,iframeWidgetLogic,imageWidgetLogic,inputNumberWidgetLogic,interactionWidgetLogic,interactiveGraphWidgetLogic,labelImageWidgetLogic,matcherWidgetLogic,matrixWidgetLogic,measurerWidgetLogic,numberLineWidgetLogic,numericInputWidgetLogic,ordererWidgetLogic,passageWidgetLogic,passageRefWidgetLogic,passageRefTargetWidgetLogic,phetSimulationWidgetLogic,plotterWidgetLogic,pythonProgramWidgetLogic,radioWidgetLogic,sorterWidgetLogic,tableWidgetLogic,videoWidgetLogic];widgets.forEach(w=>{registerWidget(w.name,w);});}
|
|
331
376
|
|
|
332
377
|
var coreWidgetRegistry = /*#__PURE__*/Object.freeze({
|
|
333
378
|
__proto__: null,
|
|
@@ -359,7 +404,7 @@ const PerseusFeatureFlags=["new-radio-widget"];
|
|
|
359
404
|
|
|
360
405
|
const noop=function(){};const deepCallbackFor=function(contentCallback,widgetCallback,optionsCallback){const deepCallback=function(widgetInfo,widgetId){const newWidgetInfo=traverseChildWidgets$1(widgetInfo,rendererOptions=>{return traverseRenderer(rendererOptions,contentCallback,deepCallback,optionsCallback)});const userWidgetInfo=widgetCallback(newWidgetInfo,widgetId);if(userWidgetInfo!==undefined){return userWidgetInfo}return newWidgetInfo};return deepCallback};const traverseRenderer=function(rendererOptions,contentCallback,deepWidgetCallback,optionsCallback){let newContent=rendererOptions.content;if(rendererOptions.content!=null){const modifiedContent=contentCallback(rendererOptions.content);if(modifiedContent!==undefined){newContent=modifiedContent;}}const newWidgets=mapObject(rendererOptions.widgets||{},function(widgetInfo,widgetId){if(widgetInfo==null||widgetInfo.type==null){return widgetInfo}return deepWidgetCallback(widgetInfo,widgetId)});const newOptions=___default.default.extend({},rendererOptions,{content:newContent,widgets:newWidgets});const userOptions=optionsCallback(newOptions);if(userOptions!==undefined){return userOptions}return newOptions};const traverse=function(rendererOptions,contentCallback,widgetCallback,optionsCallback){contentCallback=contentCallback||noop;widgetCallback=widgetCallback||noop;optionsCallback=optionsCallback||noop;return traverseRenderer(rendererOptions,contentCallback,deepCallbackFor(contentCallback,widgetCallback,optionsCallback),optionsCallback)};
|
|
361
406
|
|
|
362
|
-
function violatingWidgets(itemData){const widgetTypes=[];traverse(itemData.question,null,function(info){if(info.type&&!isAccessible(info.type,info.options)){widgetTypes.push(info.type);}});return [...new Set(widgetTypes)]}function isItemAccessible(itemData){return
|
|
407
|
+
function violatingWidgets(itemData){const widgetTypes=[];traverse(itemData.question,null,function(info){if(info.type&&!isAccessible(info.type,info.options)){widgetTypes.push(info.type);}});return [...new Set(widgetTypes)]}function isItemAccessible(itemData){const ast=pureMarkdown.parse(itemData.question.content);const widgetIdsInUse=new Set;let hasInaccessibleImage=false;pureMarkdown.traverseContent(ast,node=>{if(node.type==="image"&&(node.alt==null||node.alt==="")){hasInaccessibleImage=true;return}if(node.type==="widget"){widgetIdsInUse.add(node.id);}});if(hasInaccessibleImage){return false}const itemDataWithOnlyActiveWidgets={...itemData,question:{...itemData.question,widgets:Object.fromEntries(Object.entries(itemData.question.widgets).filter(([id])=>widgetIdsInUse.has(id)))}};return violatingWidgets(itemDataWithOnlyActiveWidgets).length===0}
|
|
363
408
|
|
|
364
409
|
registerCoreWidgets();
|
|
365
410
|
|
|
@@ -446,6 +491,7 @@ exports.numericInputLogic = numericInputWidgetLogic;
|
|
|
446
491
|
exports.ordererLogic = ordererWidgetLogic;
|
|
447
492
|
exports.parseAndMigratePerseusArticle = parseAndMigratePerseusArticle;
|
|
448
493
|
exports.parseAndMigratePerseusItem = parseAndMigratePerseusItem;
|
|
494
|
+
exports.parseAndMigrateUserInputMap = parseAndMigrateUserInputMap;
|
|
449
495
|
exports.parsePerseusItem = parsePerseusItem;
|
|
450
496
|
exports.passageLogic = passageWidgetLogic;
|
|
451
497
|
exports.passageRefLogic = passageRefWidgetLogic;
|