@khanacademy/perseus-core 0.0.0-PR3147-20251218001733 → 0.0.0-PR3150-20251218141019

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.
Files changed (27) hide show
  1. package/dist/data-schema.d.ts +23 -4
  2. package/dist/es/index.item-splitting.js +7 -3
  3. package/dist/es/index.item-splitting.js.map +1 -1
  4. package/dist/es/index.js +51 -29
  5. package/dist/es/index.js.map +1 -1
  6. package/dist/index.d.ts +10 -0
  7. package/dist/index.item-splitting.js +7 -3
  8. package/dist/index.item-splitting.js.map +1 -1
  9. package/dist/index.js +78 -28
  10. package/dist/index.js.map +1 -1
  11. package/dist/parse-perseus-json/perseus-parsers/hint.d.ts +1 -0
  12. package/dist/parse-perseus-json/perseus-parsers/passage-ref-widget.d.ts +5 -0
  13. package/dist/parse-perseus-json/perseus-parsers/passage-ref-widget.typetest.d.ts +1 -0
  14. package/dist/parse-perseus-json/perseus-parsers/passage-widget.d.ts +7 -0
  15. package/dist/parse-perseus-json/perseus-parsers/passage-widget.typetest.d.ts +1 -0
  16. package/dist/parse-perseus-json/regression-tests/item-data/passage-missing-footnotes-and-title.d.ts +47 -0
  17. package/dist/parse-perseus-json/regression-tests/item-data/passage-ref-missing-summaryText.d.ts +147 -0
  18. package/dist/utils/generators/graded-group-set-widget-generator.d.ts +2 -0
  19. package/dist/utils/generators/graded-group-widget-generator.d.ts +3 -0
  20. package/dist/utils/generators/group-widget-generator.d.ts +3 -0
  21. package/dist/utils/generators/interactive-graph-widget-generator.d.ts +21 -0
  22. package/dist/widgets/interactive-graph/index.d.ts +1 -1
  23. package/dist/widgets/passage/index.d.ts +5 -0
  24. package/dist/widgets/passage-ref/index.d.ts +4 -0
  25. package/dist/widgets/passage-ref/passage-ref-upgrade.d.ts +7 -0
  26. package/dist/widgets/passage-ref-target/index.d.ts +5 -0
  27. package/package.json +2 -2
@@ -151,6 +151,9 @@ export interface PerseusWidgetTypes {
151
151
  "number-line": NumberLineWidget;
152
152
  "numeric-input": NumericInputWidget;
153
153
  orderer: OrdererWidget;
154
+ "passage-ref-target": RefTargetWidget;
155
+ "passage-ref": PassageRefWidget;
156
+ passage: PassageWidget;
154
157
  "phet-simulation": PhetSimulationWidget;
155
158
  "python-program": PythonProgramWidget;
156
159
  plotter: PlotterWidget;
@@ -158,9 +161,6 @@ export interface PerseusWidgetTypes {
158
161
  sorter: SorterWidget;
159
162
  table: TableWidget;
160
163
  video: VideoWidget;
161
- "passage-ref-target": DeprecatedStandinWidget;
162
- "passage-ref": DeprecatedStandinWidget;
163
- passage: DeprecatedStandinWidget;
164
164
  "lights-puzzle": DeprecatedStandinWidget;
165
165
  sequence: DeprecatedStandinWidget;
166
166
  simulator: DeprecatedStandinWidget;
@@ -246,6 +246,7 @@ export type Hint = PerseusRenderer & {
246
246
  * is displayed. This allows for hints that build upon each other.
247
247
  */
248
248
  replace?: boolean;
249
+ placeholder?: boolean;
249
250
  };
250
251
  export type PerseusImageDetail = {
251
252
  width: number;
@@ -288,6 +289,8 @@ export type MeasurerWidget = WidgetOptions<'measurer', PerseusMeasurerWidgetOpti
288
289
  export type NumberLineWidget = WidgetOptions<'number-line', PerseusNumberLineWidgetOptions>;
289
290
  export type NumericInputWidget = WidgetOptions<'numeric-input', PerseusNumericInputWidgetOptions>;
290
291
  export type OrdererWidget = WidgetOptions<'orderer', PerseusOrdererWidgetOptions>;
292
+ export type PassageRefWidget = WidgetOptions<'passage-ref', PerseusPassageRefWidgetOptions>;
293
+ export type PassageWidget = WidgetOptions<'passage', PerseusPassageWidgetOptions>;
291
294
  export type PhetSimulationWidget = WidgetOptions<'phet-simulation', PerseusPhetSimulationWidgetOptions>;
292
295
  export type PlotterWidget = WidgetOptions<'plotter', PerseusPlotterWidgetOptions>;
293
296
  export type PythonProgramWidget = WidgetOptions<'python-program', PerseusPythonProgramWidgetOptions>;
@@ -296,6 +299,7 @@ export type SorterWidget = WidgetOptions<'sorter', PerseusSorterWidgetOptions>;
296
299
  export type TableWidget = WidgetOptions<'table', PerseusTableWidgetOptions>;
297
300
  export type InputNumberWidget = WidgetOptions<'input-number', PerseusInputNumberWidgetOptions>;
298
301
  export type MoleculeRendererWidget = WidgetOptions<'molecule-renderer', PerseusMoleculeRendererWidgetOptions>;
302
+ export type RefTargetWidget = WidgetOptions<'passage-ref-target', PerseusPassageRefTargetWidgetOptions>;
299
303
  export type VideoWidget = WidgetOptions<'video', PerseusVideoWidgetOptions>;
300
304
  export type DeprecatedStandinWidget = WidgetOptions<'deprecated-standin', object>;
301
305
  /**
@@ -817,6 +821,18 @@ export type PerseusOrdererWidgetOptions = {
817
821
  height: "normal" | "auto";
818
822
  layout: "horizontal" | "vertical";
819
823
  };
824
+ export type PerseusPassageWidgetOptions = {
825
+ footnotes: string;
826
+ passageText: string;
827
+ passageTitle: string;
828
+ showLineNumbers: boolean;
829
+ static: boolean;
830
+ };
831
+ export type PerseusPassageRefWidgetOptions = {
832
+ passageNumber: number;
833
+ referenceNumber: number;
834
+ summaryText?: string;
835
+ };
820
836
  export declare const plotterPlotTypes: readonly ["bar", "line", "pic", "histogram", "dotplot"];
821
837
  export type PlotType = (typeof plotterPlotTypes)[number];
822
838
  export type PerseusPlotterWidgetOptions = {
@@ -1054,5 +1070,8 @@ export type PerseusMoleculeRendererWidgetOptions = {
1054
1070
  rotationAngle?: number;
1055
1071
  smiles?: string;
1056
1072
  };
1057
- export type PerseusWidgetOptions = PerseusCategorizerWidgetOptions | PerseusCSProgramWidgetOptions | PerseusDefinitionWidgetOptions | PerseusDropdownWidgetOptions | PerseusExplanationWidgetOptions | PerseusExpressionWidgetOptions | PerseusFreeResponseWidgetOptions | PerseusGradedGroupSetWidgetOptions | PerseusGradedGroupWidgetOptions | PerseusIFrameWidgetOptions | PerseusImageWidgetOptions | PerseusInputNumberWidgetOptions | PerseusInteractionWidgetOptions | PerseusInteractiveGraphWidgetOptions | PerseusLabelImageWidgetOptions | PerseusMatcherWidgetOptions | PerseusMatrixWidgetOptions | PerseusMeasurerWidgetOptions | PerseusMoleculeRendererWidgetOptions | PerseusNumberLineWidgetOptions | PerseusNumericInputWidgetOptions | PerseusOrdererWidgetOptions | PerseusPhetSimulationWidgetOptions | PerseusPlotterWidgetOptions | PerseusRadioWidgetOptions | PerseusSorterWidgetOptions | PerseusTableWidgetOptions | PerseusVideoWidgetOptions;
1073
+ export type PerseusPassageRefTargetWidgetOptions = {
1074
+ content: string;
1075
+ };
1076
+ export type PerseusWidgetOptions = PerseusCategorizerWidgetOptions | PerseusCSProgramWidgetOptions | PerseusDefinitionWidgetOptions | PerseusDropdownWidgetOptions | PerseusExplanationWidgetOptions | PerseusExpressionWidgetOptions | PerseusFreeResponseWidgetOptions | PerseusGradedGroupSetWidgetOptions | PerseusGradedGroupWidgetOptions | PerseusIFrameWidgetOptions | PerseusImageWidgetOptions | PerseusInputNumberWidgetOptions | PerseusInteractionWidgetOptions | PerseusInteractiveGraphWidgetOptions | PerseusLabelImageWidgetOptions | PerseusMatcherWidgetOptions | PerseusMatrixWidgetOptions | PerseusMeasurerWidgetOptions | PerseusMoleculeRendererWidgetOptions | PerseusNumberLineWidgetOptions | PerseusNumericInputWidgetOptions | PerseusOrdererWidgetOptions | PerseusPassageRefTargetWidgetOptions | PerseusPassageRefWidgetOptions | PerseusPassageWidgetOptions | PerseusPhetSimulationWidgetOptions | PerseusPlotterWidgetOptions | PerseusRadioWidgetOptions | PerseusSorterWidgetOptions | PerseusTableWidgetOptions | PerseusVideoWidgetOptions;
1058
1077
  export {};
@@ -122,6 +122,10 @@ const parseMathFormat=enumeration("integer","mixed","improper","proper","decimal
122
122
 
123
123
  function parseRenderer(rawValue,ctx){return parsePerseusRenderer(rawValue,ctx)}const largeToAuto=(height,ctx)=>{if(height==="large"){return ctx.success("auto")}return ctx.success(height)};const parseOrdererWidget=parseWidget(constant("orderer"),object({options:defaulted(array(parseRenderer),()=>[]),correctOptions:defaulted(array(parseRenderer),()=>[]),otherOptions:defaulted(array(parseRenderer),()=>[]),height:pipeParsers(enumeration("normal","auto","large")).then(largeToAuto).parser,layout:defaulted(enumeration("horizontal","vertical"),()=>"horizontal")}));
124
124
 
125
+ const parsePassageRefWidget=parseWidget(constant("passage-ref"),object({passageNumber:number,referenceNumber:number,summaryText:optional(string)}));
126
+
127
+ const parsePassageWidget=parseWidget(constant("passage"),object({footnotes:defaulted(string,()=>""),passageText:string,passageTitle:defaulted(string,()=>""),showLineNumbers:boolean,static:defaulted(boolean,()=>false)}));
128
+
125
129
  const parsePhetSimulationWidget=parseWidget(constant("phet-simulation"),object({url:string,description:string}));
126
130
 
127
131
  const parsePlotterWidget=parseWidget(constant("plotter"),object({labels:array(string),categories:array(string),type:enumeration(...plotterPlotTypes),maxY:number,scaleY:defaulted(number,()=>1),labelInterval:optional(nullable(number)),snapsPerLine:defaulted(number,()=>2),starting:array(number),correct:defaulted(array(number),()=>[]),picUrl:optional(nullable(string)),picSize:optional(nullable(number)),picBoxHeight:optional(nullable(number)),plotDimensions:defaulted(array(number),()=>[380,300])}));
@@ -140,13 +144,13 @@ const parseVideoWidget=parseWidget(constant("video"),object({location:string,sta
140
144
 
141
145
  const parseStringToNonNegativeInt=(rawValue,ctx)=>{if(typeof rawValue!=="string"||!/^(0|[1-9][0-9]*)$/.test(rawValue)){return ctx.failure("a string representing a non-negative integer",rawValue)}return ctx.success(+rawValue)};const parseWidgetIdComponents=pair(string,parseStringToNonNegativeInt);
142
146
 
143
- const parseWidgetsMap=(rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx.failure("PerseusWidgetsMap",rawValue)}const widgetsMap={};for(const key of Object.keys(rawValue)){const entryResult=parseWidgetsMapEntry([key,rawValue[key]],widgetsMap,ctx.forSubtree(key));if(isFailure(entryResult)){return entryResult}}return ctx.success(widgetsMap)};const parseWidgetsMapEntry=([id,widget],widgetMap,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 widgetResult=parse(widget,ctx);if(isFailure(widgetResult)){return widgetResult}widgetMap[key]=widgetResult.value;return ctx.success(undefined)}switch(type){case "categorizer":return parseAndAssign(`categorizer ${n}`,parseCategorizerWidget);case "cs-program":return parseAndAssign(`cs-program ${n}`,parseCSProgramWidget);case "definition":return parseAndAssign(`definition ${n}`,parseDefinitionWidget);case "dropdown":return parseAndAssign(`dropdown ${n}`,parseDropdownWidget);case "explanation":return parseAndAssign(`explanation ${n}`,parseExplanationWidget);case "expression":return parseAndAssign(`expression ${n}`,parseExpressionWidget);case "free-response":return parseAndAssign(`free-response ${n}`,parseFreeResponseWidget);case "grapher":return parseAndAssign(`grapher ${n}`,parseGrapherWidget);case "group":return parseAndAssign(`group ${n}`,parseGroupWidget);case "graded-group":return parseAndAssign(`graded-group ${n}`,parseGradedGroupWidget);case "graded-group-set":return parseAndAssign(`graded-group-set ${n}`,parseGradedGroupSetWidget);case "iframe":return parseAndAssign(`iframe ${n}`,parseIframeWidget);case "image":return parseAndAssign(`image ${n}`,parseImageWidget);case "input-number":return parseAndAssign(`input-number ${n}`,parseInputNumberWidget);case "interaction":return parseAndAssign(`interaction ${n}`,parseInteractionWidget);case "interactive-graph":return parseAndAssign(`interactive-graph ${n}`,parseInteractiveGraphWidget);case "label-image":return parseAndAssign(`label-image ${n}`,parseLabelImageWidget);case "matcher":return parseAndAssign(`matcher ${n}`,parseMatcherWidget);case "matrix":return parseAndAssign(`matrix ${n}`,parseMatrixWidget);case "measurer":return parseAndAssign(`measurer ${n}`,parseMeasurerWidget);case "molecule-renderer":return parseAndAssign(`molecule-renderer ${n}`,parseMoleculeRendererWidget);case "number-line":return parseAndAssign(`number-line ${n}`,parseNumberLineWidget);case "numeric-input":return parseAndAssign(`numeric-input ${n}`,parseNumericInputWidget);case "orderer":return parseAndAssign(`orderer ${n}`,parseOrdererWidget);case "phet-simulation":return parseAndAssign(`phet-simulation ${n}`,parsePhetSimulationWidget);case "plotter":return parseAndAssign(`plotter ${n}`,parsePlotterWidget);case "python-program":return parseAndAssign(`python-program ${n}`,parsePythonProgramWidget);case "radio":return parseAndAssign(`radio ${n}`,parseRadioWidget);case "sorter":return parseAndAssign(`sorter ${n}`,parseSorterWidget);case "table":return parseAndAssign(`table ${n}`,parseTableWidget);case "video":return parseAndAssign(`video ${n}`,parseVideoWidget);case "sequence":return parseAndAssign(`sequence ${n}`,parseDeprecatedWidget);case "lights-puzzle":return parseAndAssign(`lights-puzzle ${n}`,parseDeprecatedWidget);case "simulator":return parseAndAssign(`simulator ${n}`,parseDeprecatedWidget);case "transformer":return parseAndAssign(`transformer ${n}`,parseDeprecatedWidget);case "passage":return parseAndAssign(`passage ${n}`,parseDeprecatedWidget);case "passage-ref":return parseAndAssign(`passage-ref ${n}`,parseDeprecatedWidget);case "passage-ref-target":return parseAndAssign(`passage-ref-target ${n}`,parseDeprecatedWidget);default:return parseAndAssign(`${type} ${n}`,parseWidget(constant(type),any))}};const parseDeprecatedWidget=parseWidget((_,ctx)=>ctx.success("deprecated-standin"),object({}));
147
+ const parseWidgetsMap=(rawValue,ctx)=>{if(!isPlainObject(rawValue)){return ctx.failure("PerseusWidgetsMap",rawValue)}const widgetsMap={};for(const key of Object.keys(rawValue)){const entryResult=parseWidgetsMapEntry([key,rawValue[key]],widgetsMap,ctx.forSubtree(key));if(isFailure(entryResult)){return entryResult}}return ctx.success(widgetsMap)};const parseWidgetsMapEntry=([id,widget],widgetMap,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 widgetResult=parse(widget,ctx);if(isFailure(widgetResult)){return widgetResult}widgetMap[key]=widgetResult.value;return ctx.success(undefined)}switch(type){case "categorizer":return parseAndAssign(`categorizer ${n}`,parseCategorizerWidget);case "cs-program":return parseAndAssign(`cs-program ${n}`,parseCSProgramWidget);case "definition":return parseAndAssign(`definition ${n}`,parseDefinitionWidget);case "dropdown":return parseAndAssign(`dropdown ${n}`,parseDropdownWidget);case "explanation":return parseAndAssign(`explanation ${n}`,parseExplanationWidget);case "expression":return parseAndAssign(`expression ${n}`,parseExpressionWidget);case "free-response":return parseAndAssign(`free-response ${n}`,parseFreeResponseWidget);case "grapher":return parseAndAssign(`grapher ${n}`,parseGrapherWidget);case "group":return parseAndAssign(`group ${n}`,parseGroupWidget);case "graded-group":return parseAndAssign(`graded-group ${n}`,parseGradedGroupWidget);case "graded-group-set":return parseAndAssign(`graded-group-set ${n}`,parseGradedGroupSetWidget);case "iframe":return parseAndAssign(`iframe ${n}`,parseIframeWidget);case "image":return parseAndAssign(`image ${n}`,parseImageWidget);case "input-number":return parseAndAssign(`input-number ${n}`,parseInputNumberWidget);case "interaction":return parseAndAssign(`interaction ${n}`,parseInteractionWidget);case "interactive-graph":return parseAndAssign(`interactive-graph ${n}`,parseInteractiveGraphWidget);case "label-image":return parseAndAssign(`label-image ${n}`,parseLabelImageWidget);case "matcher":return parseAndAssign(`matcher ${n}`,parseMatcherWidget);case "matrix":return parseAndAssign(`matrix ${n}`,parseMatrixWidget);case "measurer":return parseAndAssign(`measurer ${n}`,parseMeasurerWidget);case "molecule-renderer":return parseAndAssign(`molecule-renderer ${n}`,parseMoleculeRendererWidget);case "number-line":return parseAndAssign(`number-line ${n}`,parseNumberLineWidget);case "numeric-input":return parseAndAssign(`numeric-input ${n}`,parseNumericInputWidget);case "orderer":return parseAndAssign(`orderer ${n}`,parseOrdererWidget);case "passage":return parseAndAssign(`passage ${n}`,parsePassageWidget);case "passage-ref":return parseAndAssign(`passage-ref ${n}`,parsePassageRefWidget);case "passage-ref-target":return parseAndAssign(`passage-ref-target ${n}`,any);case "phet-simulation":return parseAndAssign(`phet-simulation ${n}`,parsePhetSimulationWidget);case "plotter":return parseAndAssign(`plotter ${n}`,parsePlotterWidget);case "python-program":return parseAndAssign(`python-program ${n}`,parsePythonProgramWidget);case "radio":return parseAndAssign(`radio ${n}`,parseRadioWidget);case "sorter":return parseAndAssign(`sorter ${n}`,parseSorterWidget);case "table":return parseAndAssign(`table ${n}`,parseTableWidget);case "video":return parseAndAssign(`video ${n}`,parseVideoWidget);case "sequence":return parseAndAssign(`sequence ${n}`,parseDeprecatedWidget);case "lights-puzzle":return parseAndAssign(`lights-puzzle ${n}`,parseDeprecatedWidget);case "simulator":return parseAndAssign(`simulator ${n}`,parseDeprecatedWidget);case "transformer":return parseAndAssign(`transformer ${n}`,parseDeprecatedWidget);default:return parseAndAssign(`${type} ${n}`,parseWidget(constant(type),any))}};const parseDeprecatedWidget=parseWidget((_,ctx)=>ctx.success("deprecated-standin"),object({}));
144
148
 
145
149
  const parsePerseusRenderer=defaulted(object({content:defaulted(string,()=>""),widgets:defaulted((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),()=>({})),images:parseImages,metadata:any}),()=>({content:"",widgets:{},images:{}}));
146
150
 
147
151
  union(parsePerseusRenderer).or(array(parsePerseusRenderer)).parser;
148
152
 
149
- const parseHint=object({replace:defaulted(optional(boolean),()=>undefined),content:string,widgets:defaulted(parseWidgetsMap,()=>({})),images:parseImages,metadata:any});
153
+ const parseHint=object({replace:defaulted(optional(boolean),()=>undefined),placeholder:defaulted(optional(boolean),()=>undefined),content:string,widgets:defaulted(parseWidgetsMap,()=>({})),images:parseImages,metadata:any});
150
154
 
151
155
  const parsePerseusAnswerArea=pipeParsers(defaulted(object({}),()=>({}))).then(convert(toAnswerArea)).parser;function toAnswerArea(raw){return {calculator:!!raw.calculator,financialCalculatorMonthlyPayment:!!raw.financialCalculatorMonthlyPayment,financialCalculatorTotalAmount:!!raw.financialCalculatorTotalAmount,financialCalculatorTimeToPayOff:!!raw.financialCalculatorTimeToPayOff,periodicTable:!!raw.periodicTable,periodicTableWithKey:!!raw.periodicTableWithKey}}
152
156
 
@@ -182,7 +186,7 @@ const DEFAULT_STATIC=false;const applyDefaultsToWidget=oldWidgetInfo=>{const typ
182
186
 
183
187
  function splitPerseusRenderer(original){const clone=deepClone(original);const originalWidgets=clone.widgets??{};const upgradedWidgets=applyDefaultsToWidgets(originalWidgets);const splitWidgets={};for(const[id,widget]of Object.entries(upgradedWidgets)){if(widget.static){splitWidgets[id]=widget;}else {const publicWidgetOptionsFun=getPublicWidgetOptionsFunction(widget.type);splitWidgets[id]={...widget,options:publicWidgetOptionsFun(widget.options)};}}return {...original,widgets:splitWidgets}}
184
188
 
185
- 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))}
189
+ function splitPerseusItem(original){const item=deepClone(original);return {...item,question:splitPerseusRenderer(item.question),hints:original.hints.map(()=>({content:"",widgets:{},images:{},placeholder:true}))}}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))}
186
190
 
187
191
  export { splitPerseusItem, splitPerseusItemJSON };
188
192
  //# sourceMappingURL=index.item-splitting.js.map