@khanacademy/perseus-core 0.0.0-PR3089-20251204205743 → 0.0.0-PR3089-20251210151846
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/es/index.item-splitting.js.map +1 -1
- package/dist/es/index.js +27 -2
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.item-splitting.js.map +1 -1
- package/dist/index.js +44 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/extract-perseus-ai-data.d.ts +39 -0
- package/dist/utils/generators/definition-widget-generator.d.ts +3 -0
- package/dist/utils/generators/dropdown-widget-generator.d.ts +3 -0
- package/dist/utils/generators/explanation-widget-generator.d.ts +3 -0
- package/dist/utils/generators/expression-widget-generator.d.ts +4 -0
- package/dist/utils/generators/free-response-widget-generator.d.ts +3 -0
- package/dist/utils/generators/numeric-input-widget-generator.d.ts +4 -0
- package/dist/utils/get-default-figure-for-type.d.ts +9 -0
- package/package.json +1 -1
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 wonderStuffCore = require('@khanacademy/wonder-stuff-core');
|
|
9
10
|
var pureMarkdown = require('@khanacademy/pure-markdown');
|
|
10
11
|
|
|
11
12
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
@@ -258,7 +259,7 @@ const parseUserInputMap=(rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx
|
|
|
258
259
|
|
|
259
260
|
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.")}}
|
|
260
261
|
|
|
261
|
-
const libName="@khanacademy/perseus-core";const libVersion="20.
|
|
262
|
+
const libName="@khanacademy/perseus-core";const libVersion="20.4.1";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
262
263
|
|
|
263
264
|
const Errors=Object.freeze({Unknown:"Unknown",Internal:"Internal",InvalidInput:"InvalidInput",NotAllowed:"NotAllowed",TransientService:"TransientService",Service:"Service"});
|
|
264
265
|
|
|
@@ -405,6 +406,8 @@ const defaultWidgetOptions={content:"",widgets:{},images:{}};const traverseChild
|
|
|
405
406
|
|
|
406
407
|
function getDefaultAnswerArea(){return ItemExtras.reduce((acc,curr)=>({...acc,[curr]:false}),{})}
|
|
407
408
|
|
|
409
|
+
const DEFAULT_COLOR="grayH";function getDefaultFigureForType(type){switch(type){case "point":return {type:"point",coord:[0,0],color:DEFAULT_COLOR,filled:true,labels:[]};case "line":return {type:"line",kind:"line",points:[getDefaultFigureForType("point"),{...getDefaultFigureForType("point"),coord:[2,2]}],color:DEFAULT_COLOR,lineStyle:"solid",showPoint1:false,showPoint2:false,weight:"medium",labels:[]};case "vector":return {type:"vector",points:[[0,0],[2,2]],color:DEFAULT_COLOR,weight:"medium",labels:[]};case "ellipse":return {type:"ellipse",center:[0,0],radius:[1,1],angle:0,color:DEFAULT_COLOR,fillStyle:"none",strokeStyle:"solid",weight:"medium",labels:[]};case "polygon":return {type:"polygon",points:[[0,2],[-1,0],[1,0]],color:DEFAULT_COLOR,showVertices:false,fillStyle:"none",strokeStyle:"solid",weight:"medium",labels:[]};case "function":return {type:"function",color:DEFAULT_COLOR,strokeStyle:"solid",weight:"medium",equation:"x^2",domain:[-Infinity,Infinity],directionalAxis:"x",labels:[]};case "label":return {type:"label",coord:[0,0],text:"label",color:DEFAULT_COLOR,size:"medium"};default:throw new wonderStuffCore.UnreachableCaseError(type)}}
|
|
410
|
+
|
|
408
411
|
function splitPerseusItem(original){const item=deepClone(original);return {...item,question:splitPerseusRenderer(item.question),hints:[]}}function splitPerseusItemJSON(data){const parseResult=parseAndMigratePerseusItem(data);if(isFailure(parseResult)){throw new SyntaxError(parseResult.detail.message)}const item=parseResult.value;return JSON.stringify(splitPerseusItem(item))}
|
|
409
412
|
|
|
410
413
|
const PerseusFeatureFlags=["new-radio-widget","image-widget-upgrade"];function isFeatureOn(props,flag){return props.apiOptions?.flags?.[flag]??false}
|
|
@@ -413,10 +416,32 @@ const noop=function(){};const deepCallbackFor=function(contentCallback,widgetCal
|
|
|
413
416
|
|
|
414
417
|
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}
|
|
415
418
|
|
|
419
|
+
function generateDefinitionOptions(options){return {...definitionWidgetLogic.defaultWidgetOptions,...options}}function generateDefinitionWidget(definitionWidgetProperties){return {type:"definition",graded:false,version:{major:0,minor:0},static:false,alignment:"default",options:generateDefinitionOptions(),...definitionWidgetProperties}}
|
|
420
|
+
|
|
421
|
+
function generateDropdownOptions(options){return {...dropdownWidgetLogic.defaultWidgetOptions,...options}}function generateDropdownWidget(dropdownWidgetProperties){return {type:"dropdown",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateDropdownOptions(),...dropdownWidgetProperties}}
|
|
422
|
+
|
|
423
|
+
function generateExplanationOptions(options){return {...explanationWidgetLogic.defaultWidgetOptions,...options}}function generateExplanationWidget(explanationWidgetProperties){return {type:"explanation",graded:false,version:{major:0,minor:0},static:false,alignment:"default",options:generateExplanationOptions(),...explanationWidgetProperties}}
|
|
424
|
+
|
|
425
|
+
function generateExpressionOptions(options){return {...expressionWidgetLogic.defaultWidgetOptions,...options}}function generateExpressionAnswerForm(answerFormOptions){return {value:"",form:false,simplify:false,considered:"wrong",...answerFormOptions}}function generateExpressionWidget(expressionWidgetProperties){return {type:"expression",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateExpressionOptions(),...expressionWidgetProperties}}
|
|
426
|
+
|
|
427
|
+
function generateFreeResponseOptions(options){return {...freeResponseWidgetLogic.defaultWidgetOptions,...options}}function generateFreeResponseWidget(freeResponseWidgetProperties){return {type:"free-response",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateFreeResponseOptions(),...freeResponseWidgetProperties}}
|
|
428
|
+
|
|
416
429
|
function generateImageOptions(options){const defaultImageOptions={backgroundImage:{}};return {...defaultImageOptions,...options}}function generateImageWidget(imageWidgetProperties){return {type:"image",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateImageOptions({}),...imageWidgetProperties}}
|
|
417
430
|
|
|
431
|
+
function generateNumericInputOptions(options){return {...numericInputWidgetLogic.defaultWidgetOptions,static:false,...options}}function generateNumericInputAnswer(answerOptions){return {...numericInputWidgetLogic.defaultWidgetOptions.answers[0],...answerOptions}}function generateNumericInputWidget(numericInputWidgetProperties){return {type:"numeric-input",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:generateNumericInputOptions(),...numericInputWidgetProperties}}
|
|
432
|
+
|
|
418
433
|
function generateVideoWidget(videoWidgetProperties){return {type:"video",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:{location:""},...videoWidgetProperties}}
|
|
419
434
|
|
|
435
|
+
const joinOptionContents=options=>options.map(({content})=>content).join("\n");const toOptionLetter=index=>String.fromCharCode("A".charCodeAt(0)+index);function getAnswersFromWidgets(widgets){const answers=[];wonderStuffCore.keys(widgets).forEach(widgetID=>{const widget=widgets[widgetID];if(!widget.options){return}switch(widget.type){case "radio":const radio=widget;const options=radio.options;if(options?.choices?.length){for(const choice of options.choices){if(choice?.correct){answers.push(choice.content);}}}break;case "categorizer":const categorizer=widget;if(categorizer.options?.categories&&categorizer.options?.items&&categorizer.options?.values){const categories=categorizer.options?.categories;const items=categorizer.options?.items;const values=categorizer.options?.values;answers.push(...values.map((value,index)=>`${items[index]}: ${categories[value]}`));}break;case "dropdown":const dropdown=widget;if(dropdown.options?.choices){for(const choice of dropdown.options.choices){if(choice.correct){answers.push(choice.content);}}}break;case "numeric-input":const numericInput=widget;if(numericInput.options?.answers){for(const ans of numericInput.options.answers){if(ans.status==="correct"&&ans.value!=null){answers.push(ans.value.toString());}}}break;case "input-number":const inputNumber=widget;if(inputNumber.options?.value){answers.push(inputNumber.options.value.toString());}break;case "expression":const expression=widget;if(expression.options?.answerForms){answers.push(...expression.options.answerForms.map(answer=>answer.value));}break;case "group":case "graded-group":const gradedGroup=widget;if(gradedGroup.options?.widgets){answers.push(...getAnswersFromWidgets(gradedGroup.options.widgets));}break;case "plotter":const plotter=widget;if(plotter.options?.categories&&plotter.options?.correct&&plotter.options.categories.length===plotter.options.correct.length){const{categories,correct}=plotter.options;answers.push(`{${categories.map((category,index)=>`${category}: ${correct[index]}`).join(", ")}}`);}break;case "interactive-graph":case "grapher":const grapher=widget;if(grapher.options?.correct?.coords){answers.push(`There should be point(s) on [${grapher.options.correct?.coords.join("], [")}]`);}break;case "orderer":const orderer=widget;if(orderer.options?.correctOptions){answers.push(joinOptionContents(orderer.options.correctOptions));}break;case "sorter":const sorter=widget;if(sorter.options?.correct){answers.push(sorter.options.correct.join(", "));}break;case "label-image":const labelImage=widget;if(labelImage.options?.markers){answers.push(...labelImage.options.markers.map(m=>`{label: "${m.label}", position: {${m.x},${m.y}}, answer: "${m.answers.join(", ")}"}`));}break;case "number-line":const numberLine=widget;if(numberLine.options?.correctX!=null){answers.push(numberLine.options.correctX.toString());}break;case "matrix":const matrix=widget;if(matrix.options?.answers){answers.push(`[${matrix.options.answers.join("], [")}]`);}break;case "matcher":const matcher=widget;if(matcher.options?.left&&matcher.options?.right){const{left,right}=matcher.options;const[leftHeader,rightHeader]=matcher.options.labels;const tableHeader=`| ${leftHeader} | ${rightHeader} |
|
|
436
|
+
| --- | --- |`;const tableRows=left.map((leftItem,index)=>{return `| ${leftItem} | ${right[index]} |`});const table=[tableHeader,...tableRows].join("\n");answers.push(table);}break}});return answers}function injectWidgets(content,widgets,widgetProps){if(!content){return ""}if(!widgets){return content}let context=content;wonderStuffCore.keys(widgets).forEach(widgetID=>{const widget=widgets[widgetID];if(!widget.options){return}switch(widget.type){case "radio":const radio=widget;const radioProps=widgetProps?.[widgetID];if(radio.options?.choices?.length){let radioContext=joinOptionContents(radioProps?radioProps.choices.map(({content},i)=>({content:`Option ${toOptionLetter(i)}: ${content}`})):radio.options.choices);if(!radioProps&&radio.options?.randomize){radioContext+="\nThose options are displayed in a different order to the user. If the user says the letter, number, or ordinal number, always ask them clarify which option they are referring to.\n";}context=context.replace(`[[☃ ${widgetID}]]`,radioContext);}break;case "image":const image=widget;if(image.options?.alt){context=context.replace(`[[☃ ${widgetID}]]`,`<img id="${widgetID}" alt="${image.options.alt}">`);}break;case "label-image":const labelImage=widget;if(labelImage.options?.imageAlt){context=context.replace(`[[☃ ${widgetID}]]`,`[An image with dots that user needs to label. Label choices: [${labelImage.options.choices.join(", ")}]. Image alt text: ${labelImage.options?.imageAlt??""}]`);}break;case "explanation":const explanation=widget;if(explanation.options?.explanation){context=context.replace(`[[☃ ${widgetID}]]`,injectWidgets(explanation.options.explanation,explanation.options.widgets));}break;case "passage":const passage=widget;if(passage.options?.passageTitle||passage.options?.passageText){const{passageTitle,passageText}=passage.options;context=context.replace(`[[☃ ${widgetID}]]`,`# ${passageTitle}
|
|
437
|
+
|
|
438
|
+
${passageText}`);}break;case "group":case "graded-group":const group=widget;if(group.options?.widgets&&group.options.content){context=context.replace(`[[☃ ${widgetID}]]`,injectWidgets(group.options.content,group.options.widgets));}break;case "graded-group-set":const gradedGroup=widget;if(gradedGroup.options?.gradedGroups){const gradedGroups=gradedGroup.options.gradedGroups;const gradedGroupsContent=gradedGroups.reduce((acc,group)=>{if(group.widgets&&group.content){acc+=injectWidgets(group.content,group.widgets)+"\n";}return acc},"");context=context.replace(`[[☃ ${widgetID}]]`,gradedGroupsContent);}break;case "categorizer":const categorizer=widget;if(categorizer.options?.categories&&categorizer.options.items){const categories=categorizer.options.categories;const items=categorizer.options.items;context=context.replace(`[[☃ ${widgetID}]]`,`For each item, select the correct category. Categories: ${categories.join(", ")}.
|
|
439
|
+
Items:
|
|
440
|
+
${items.join("\n")}
|
|
441
|
+
`);}break;case "dropdown":const dropdown=widget;if(dropdown.options?.choices){const choices=dropdown.options.choices.map(choice=>choice.content);context=context.replace(`[[☃ ${widgetID}]]`,`[${choices.join(" | ")}]`);}break;case "definition":const definition=widget;if(definition.options?.togglePrompt){context=context.replace(`[[☃ ${widgetID}]]`,definition.options.togglePrompt);}break;case "orderer":const orderer=widget;if(orderer.options?.options){context=context.replace(`[[☃ ${widgetID}]]`,joinOptionContents(orderer.options.options));}break;case "sorter":const sorter=widget;if(sorter.options?.correct){const choices=sorter.options.correct;context=context.replace(`[[☃ ${widgetID}]]`,`[${choices.join(" | ")}]`);}break;case "interactive-graph":const interactiveGraph=widget;if(interactiveGraph.options?.range.length===2){const[x,y]=interactiveGraph.options.range;context=context.replace(`[[☃ ${widgetID}]]`,`[Graph with an x range of ${x[0]} to ${x[1]} and y range of ${y[0]} to ${y[1]}]`);}break;case "number-line":const numberLine=widget;if(numberLine.options?.range.length===2&&numberLine.options?.tickStep&&numberLine.options?.initialX){const[min,max]=numberLine.options.range;const step=numberLine.options.tickStep;const initialPosition=numberLine.options.initialX;context=context.replace(`[[☃ ${widgetID}]]`,`[Number line with a range of ${min} to ${max}, a step of ${step}, and an initial position of ${initialPosition}]`);}break;case "matrix":const matrix=widget;if(matrix.options?.matrixBoardSize.length===2){const[rows,columns]=matrix.options.matrixBoardSize;context=context.replace(`[[☃ ${widgetID}]]`,`[Matrix with ${rows} rows and ${columns} columns. The user can click on each cell to enter a value]`);}break;case "matcher":const matcher=widget;if(matcher.options?.left&&matcher.options?.right){const{left,right}=matcher.options;const[leftHeader,rightHeader]=matcher.options.labels;const tableHeader=`| ${leftHeader} | ${rightHeader} |
|
|
442
|
+
| --- | --- |`;const tableRows=left.map((leftItem,index)=>{return `| ${leftItem} | ${right[index]} |`});const table=[tableHeader,...tableRows].join("\n");const matcherWidgetExplanation="The user needs to move items in the right column to match the correct option on the left. The order of items on the right side will be different from what the user sees.";context=context.replace(`[[☃ ${widgetID}]]`,`${matcherWidgetExplanation}
|
|
443
|
+
${table}`);}break;case "numeric-input":case "input-number":case "expression":context=context.replace(`[[☃ ${widgetID}]]`,"?");break;default:context=context.replace(`[[☃ ${widgetID}]]`,`[[Unsupported ${widget.type} widget: Explain to the user that you are unable to understand the content in this widget and ask them to describe it.]]`);}});return context}function getPerseusAIData(perseusItem){const answers=getAnswersFromWidgets(perseusItem.question.widgets);const hints=perseusItem.hints.map(hint=>injectWidgets(hint.content,hint.widgets));return {answers,hints}}
|
|
444
|
+
|
|
420
445
|
registerCoreWidgets();
|
|
421
446
|
|
|
422
447
|
exports.CoreWidgetRegistry = coreWidgetRegistry;
|
|
@@ -443,17 +468,33 @@ exports.dropdownLogic = dropdownWidgetLogic;
|
|
|
443
468
|
exports.explanationLogic = explanationWidgetLogic;
|
|
444
469
|
exports.expressionLogic = expressionWidgetLogic;
|
|
445
470
|
exports.freeResponseLogic = freeResponseWidgetLogic;
|
|
471
|
+
exports.generateDefinitionOptions = generateDefinitionOptions;
|
|
472
|
+
exports.generateDefinitionWidget = generateDefinitionWidget;
|
|
473
|
+
exports.generateDropdownOptions = generateDropdownOptions;
|
|
474
|
+
exports.generateDropdownWidget = generateDropdownWidget;
|
|
475
|
+
exports.generateExplanationOptions = generateExplanationOptions;
|
|
476
|
+
exports.generateExplanationWidget = generateExplanationWidget;
|
|
477
|
+
exports.generateExpressionAnswerForm = generateExpressionAnswerForm;
|
|
478
|
+
exports.generateExpressionOptions = generateExpressionOptions;
|
|
479
|
+
exports.generateExpressionWidget = generateExpressionWidget;
|
|
480
|
+
exports.generateFreeResponseOptions = generateFreeResponseOptions;
|
|
481
|
+
exports.generateFreeResponseWidget = generateFreeResponseWidget;
|
|
446
482
|
exports.generateImageOptions = generateImageOptions;
|
|
447
483
|
exports.generateImageWidget = generateImageWidget;
|
|
484
|
+
exports.generateNumericInputAnswer = generateNumericInputAnswer;
|
|
485
|
+
exports.generateNumericInputOptions = generateNumericInputOptions;
|
|
486
|
+
exports.generateNumericInputWidget = generateNumericInputWidget;
|
|
448
487
|
exports.generateTestPerseusItem = generateTestPerseusItem;
|
|
449
488
|
exports.generateTestPerseusRenderer = generateTestPerseusRenderer;
|
|
450
489
|
exports.generateVideoWidget = generateVideoWidget;
|
|
490
|
+
exports.getAnswersFromWidgets = getAnswersFromWidgets;
|
|
451
491
|
exports.getBaseUrl = getBaseUrl;
|
|
452
492
|
exports.getCSProgramPublicWidgetOptions = getCSProgramPublicWidgetOptions;
|
|
453
493
|
exports.getCategorizerPublicWidgetOptions = getCategorizerPublicWidgetOptions;
|
|
454
494
|
exports.getDataUrl = getDataUrl;
|
|
455
495
|
exports.getDecimalSeparator = getDecimalSeparator;
|
|
456
496
|
exports.getDefaultAnswerArea = getDefaultAnswerArea;
|
|
497
|
+
exports.getDefaultFigureForType = getDefaultFigureForType;
|
|
457
498
|
exports.getDivideSymbol = getDivideSymbol;
|
|
458
499
|
exports.getDivideSymbolForTex = getDivideSymbolForTex;
|
|
459
500
|
exports.getDropdownPublicWidgetOptions = getDropdownPublicWidgetOptions;
|
|
@@ -471,6 +512,7 @@ exports.getMatrixSize = getMatrixSize;
|
|
|
471
512
|
exports.getNumberLinePublicWidgetOptions = getNumberLinePublicWidgetOptions;
|
|
472
513
|
exports.getNumericInputPublicWidgetOptions = getNumericInputPublicWidgetOptions;
|
|
473
514
|
exports.getOrdererPublicWidgetOptions = getOrdererPublicWidgetOptions;
|
|
515
|
+
exports.getPerseusAIData = getPerseusAIData;
|
|
474
516
|
exports.getPlotterPublicWidgetOptions = getPlotterPublicWidgetOptions;
|
|
475
517
|
exports.getRadioPublicWidgetOptions = getRadioPublicWidgetOptions;
|
|
476
518
|
exports.getRealImageUrl = getRealImageUrl;
|
|
@@ -485,6 +527,7 @@ exports.grapherLogic = grapherWidgetLogic;
|
|
|
485
527
|
exports.groupLogic = groupWidgetLogic;
|
|
486
528
|
exports.iframeLogic = iframeWidgetLogic;
|
|
487
529
|
exports.imageLogic = imageWidgetLogic;
|
|
530
|
+
exports.injectWidgets = injectWidgets;
|
|
488
531
|
exports.inputNumberLogic = inputNumberWidgetLogic;
|
|
489
532
|
exports.interactionLogic = interactionWidgetLogic;
|
|
490
533
|
exports.interactiveGraphLogic = interactiveGraphWidgetLogic;
|