@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
- 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 throwErrorIfCheatingDetected(){if(!isRealJSONParse(JSON.parse)){throw new Error("Something went wrong.")}}
211
+ const parseCategorizerUserInput=object({values:array(number)});
211
212
 
212
- const libName="@khanacademy/perseus-core";const libVersion="18.0.0";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
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 violatingWidgets(itemData).length===0}
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;