@khanacademy/perseus-core 0.0.0-PR3089-20251204205538 → 0.0.0-PR3091-20251204213510

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
@@ -139,3 +139,4 @@ export { isItemAccessible, violatingWidgets } from "./accessibility";
139
139
  export { isLabeledSVG, getRealImageUrl, getBaseUrl, getSvgUrl, getDataUrl, getImageSizeModern, } from "./utils/util.graphie";
140
140
  export { generateImageOptions, generateImageWidget, } from "./utils/generators/image-widget-generator";
141
141
  export { generateVideoWidget } from "./utils/generators/video-widget-generator";
142
+ export { getAnswersFromWidgets, injectWidgets, getPerseusAIData, } from "./utils/extract-perseus-ai-data";
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ require('tiny-invariant');
7
7
  var KAS = require('@khanacademy/kas');
8
8
  var perseusUtils = require('@khanacademy/perseus-utils');
9
9
  var pureMarkdown = require('@khanacademy/pure-markdown');
10
+ var wonderStuffCore = require('@khanacademy/wonder-stuff-core');
10
11
 
11
12
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
12
13
 
@@ -417,6 +418,16 @@ function generateImageOptions(options){const defaultImageOptions={backgroundImag
417
418
 
418
419
  function generateVideoWidget(videoWidgetProperties){return {type:"video",graded:true,version:{major:0,minor:0},static:false,alignment:"default",options:{location:""},...videoWidgetProperties}}
419
420
 
421
+ 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} |
422
+ | --- | --- |`;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}
423
+
424
+ ${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(", ")}.
425
+ Items:
426
+ ${items.join("\n")}
427
+ `);}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} |
428
+ | --- | --- |`;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}
429
+ ${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}}
430
+
420
431
  registerCoreWidgets();
421
432
 
422
433
  exports.CoreWidgetRegistry = coreWidgetRegistry;
@@ -448,6 +459,7 @@ exports.generateImageWidget = generateImageWidget;
448
459
  exports.generateTestPerseusItem = generateTestPerseusItem;
449
460
  exports.generateTestPerseusRenderer = generateTestPerseusRenderer;
450
461
  exports.generateVideoWidget = generateVideoWidget;
462
+ exports.getAnswersFromWidgets = getAnswersFromWidgets;
451
463
  exports.getBaseUrl = getBaseUrl;
452
464
  exports.getCSProgramPublicWidgetOptions = getCSProgramPublicWidgetOptions;
453
465
  exports.getCategorizerPublicWidgetOptions = getCategorizerPublicWidgetOptions;
@@ -471,6 +483,7 @@ exports.getMatrixSize = getMatrixSize;
471
483
  exports.getNumberLinePublicWidgetOptions = getNumberLinePublicWidgetOptions;
472
484
  exports.getNumericInputPublicWidgetOptions = getNumericInputPublicWidgetOptions;
473
485
  exports.getOrdererPublicWidgetOptions = getOrdererPublicWidgetOptions;
486
+ exports.getPerseusAIData = getPerseusAIData;
474
487
  exports.getPlotterPublicWidgetOptions = getPlotterPublicWidgetOptions;
475
488
  exports.getRadioPublicWidgetOptions = getRadioPublicWidgetOptions;
476
489
  exports.getRealImageUrl = getRealImageUrl;
@@ -485,6 +498,7 @@ exports.grapherLogic = grapherWidgetLogic;
485
498
  exports.groupLogic = groupWidgetLogic;
486
499
  exports.iframeLogic = iframeWidgetLogic;
487
500
  exports.imageLogic = imageWidgetLogic;
501
+ exports.injectWidgets = injectWidgets;
488
502
  exports.inputNumberLogic = inputNumberWidgetLogic;
489
503
  exports.interactionLogic = interactionWidgetLogic;
490
504
  exports.interactiveGraphLogic = interactiveGraphWidgetLogic;