@khanacademy/perseus-core 19.0.1 → 19.0.3

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 (34) hide show
  1. package/dist/data-schema.d.ts +0 -6
  2. package/dist/es/index.item-splitting.js +3 -3
  3. package/dist/es/index.item-splitting.js.map +1 -1
  4. package/dist/es/index.js +6 -6
  5. package/dist/es/index.js.map +1 -1
  6. package/dist/feature-flags.d.ts +10 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.item-splitting.js +3 -3
  9. package/dist/index.item-splitting.js.map +1 -1
  10. package/dist/index.js +6 -5
  11. package/dist/index.js.map +1 -1
  12. package/dist/parse-perseus-json/general-purpose-parsers/defaulted.d.ts +7 -0
  13. package/dist/parse-perseus-json/general-purpose-parsers/index.d.ts +1 -0
  14. package/dist/parse-perseus-json/regression-tests/user-input-data/categorizer.d.ts +6 -0
  15. package/dist/parse-perseus-json/regression-tests/user-input-data/cs-program.d.ts +15 -0
  16. package/dist/parse-perseus-json/regression-tests/user-input-data/dropdown.d.ts +6 -0
  17. package/dist/parse-perseus-json/regression-tests/user-input-data/expression.d.ts +4 -0
  18. package/dist/parse-perseus-json/regression-tests/user-input-data/free-response.d.ts +6 -0
  19. package/dist/parse-perseus-json/regression-tests/user-input-data/grapher.d.ts +33 -0
  20. package/dist/parse-perseus-json/regression-tests/user-input-data/group.d.ts +8 -0
  21. package/dist/parse-perseus-json/regression-tests/user-input-data/iframe.d.ts +14 -0
  22. package/dist/parse-perseus-json/regression-tests/user-input-data/input-number.d.ts +6 -0
  23. package/dist/parse-perseus-json/regression-tests/user-input-data/interactive-graph.d.ts +99 -0
  24. package/dist/parse-perseus-json/regression-tests/user-input-data/label-image.d.ts +12 -0
  25. package/dist/parse-perseus-json/regression-tests/user-input-data/matcher.d.ts +7 -0
  26. package/dist/parse-perseus-json/regression-tests/user-input-data/matrix.d.ts +6 -0
  27. package/dist/parse-perseus-json/regression-tests/user-input-data/number-line.d.ts +8 -0
  28. package/dist/parse-perseus-json/regression-tests/user-input-data/numeric-input.d.ts +6 -0
  29. package/dist/parse-perseus-json/regression-tests/user-input-data/orderer.d.ts +6 -0
  30. package/dist/parse-perseus-json/regression-tests/user-input-data/plotter.d.ts +4 -0
  31. package/dist/parse-perseus-json/regression-tests/user-input-data/radio.d.ts +6 -0
  32. package/dist/parse-perseus-json/regression-tests/user-input-data/sorter.d.ts +7 -0
  33. package/dist/parse-perseus-json/regression-tests/user-input-data/table.d.ts +4 -0
  34. package/package.json +3 -3
@@ -7,6 +7,15 @@
7
7
  * 2. Do cleanup unused feature flags
8
8
  * 3. When no active feature flag is available value will be:
9
9
  * export const PerseusFeatureFlags = [];
10
+ * 4. Also update the testing/feature-flags-util.ts for testing purpose
10
11
  */
11
- declare const PerseusFeatureFlags: readonly ["new-radio-widget"];
12
+ declare const PerseusFeatureFlags: readonly ["new-radio-widget", "image-widget-upgrade"];
12
13
  export default PerseusFeatureFlags;
14
+ /**
15
+ * Checks if a feature flag is enabled in the given props.
16
+ */
17
+ export declare function isFeatureOn(props: {
18
+ apiOptions?: {
19
+ flags?: Record<string, boolean>;
20
+ };
21
+ }, flag: string): boolean;
package/dist/index.d.ts CHANGED
@@ -129,7 +129,7 @@ export type { PlotterPublicWidgetOptions } from "./widgets/plotter/plotter-util"
129
129
  export { default as getMatcherPublicWidgetOptions, shuffleMatcher, } from "./widgets/matcher/matcher-util";
130
130
  export type { MatcherPublicWidgetOptions } from "./widgets/matcher/matcher-util";
131
131
  export { shuffle, seededRNG, random } from "./utils/random-util";
132
- export { default as PerseusFeatureFlags } from "./feature-flags";
132
+ export { default as PerseusFeatureFlags, isFeatureOn } from "./feature-flags";
133
133
  export { traverse } from "./traversal";
134
134
  export { isItemAccessible, violatingWidgets } from "./accessibility";
135
135
  export { isLabeledSVG, getRealImageUrl, getBaseUrl, getSvgUrl, getDataUrl, getImageSizeModern, } from "./utils/util.graphie";
@@ -51,6 +51,8 @@ function boolean(rawValue,ctx){if(typeof rawValue==="boolean"){return ctx.succes
51
51
 
52
52
  function constant(acceptedValue){return (rawValue,ctx)=>{if(rawValue!==acceptedValue){return ctx.failure(String(JSON.stringify(acceptedValue)),rawValue)}return ctx.success(acceptedValue)}}
53
53
 
54
+ function defaulted(parser,fallback){return (rawValue,ctx)=>{if(rawValue==null){return success(fallback(rawValue))}return parser(rawValue,ctx)}}function defaultedNonEmptyString(fallback){return (rawValue,ctx)=>{if(rawValue==null){return ctx.success(fallback())}if(typeof rawValue==="string"){if(rawValue.trim()===""){return ctx.success(fallback())}return ctx.success(rawValue)}return ctx.failure("string",rawValue)}}
55
+
54
56
  function enumeration(...acceptedValues){return (rawValue,ctx)=>{if(typeof rawValue==="string"){const index=acceptedValues.indexOf(rawValue);if(index>-1){return ctx.success(acceptedValues[index])}}const expected=acceptedValues.map(v=>JSON.stringify(v));return ctx.failure(expected,rawValue)}}
55
57
 
56
58
  const objectConstructorString=Object.prototype.constructor.toString();const functionToString=Function.prototype.toString;function isPlainObject(x){if(x==null){return false}const prototype=Object.getPrototypeOf(x);if(prototype==null){return true}return typeof prototype.constructor==="function"&&functionToString.call(prototype.constructor)===objectConstructorString}
@@ -75,8 +77,6 @@ function trio(parseA,parseB,parseC){return (rawValue,ctx)=>{if(!Array.isArray(ra
75
77
 
76
78
  function union(parseBranch){return new UnionBuilder(parseBranch)}class UnionBuilder{or(newBranch){return new UnionBuilder(either(this.parser,newBranch))}constructor(parser){this.parser=parser;}}function either(parseA,parseB){return (rawValue,ctx)=>{const resultA=parseA(rawValue,ctx);if(isSuccess(resultA)){return resultA}return parseB(rawValue,ctx)}}
77
79
 
78
- function defaulted(parser,fallback){return (rawValue,ctx)=>{if(rawValue==null){return success(fallback(rawValue))}return parser(rawValue,ctx)}}
79
-
80
80
  const parsePerseusImageDetail=object({width:number,height:number});
81
81
 
82
82
  const parseImages=defaulted(record(string,parsePerseusImageDetail),()=>({}));
@@ -161,7 +161,7 @@ const parsePythonProgramWidget=parseWidget(constant("python-program"),object({pr
161
161
 
162
162
  function deriveNumCorrect(choices){return choices.filter(c=>c.correct).length}
163
163
 
164
- const parseWidgetsMapOrUndefined=defaulted(optional((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx)),()=>undefined);function getDefaultOptions(){return {choices:[{content:"",id:generateChoiceId(0)},{content:"",id:generateChoiceId(1)},{content:"",id:generateChoiceId(2)},{content:"",id:generateChoiceId(3)}]}}const parseOnePerLine=defaulted(optional(boolean),()=>undefined);const parseNoneOfTheAbove=defaulted(optional(constant(false)),()=>undefined);function generateChoiceId(index){return `radio-choice-${index}`}const version3=optional(object({major:constant(3),minor:number}));const parseRadioWidgetV3=parseWidgetWithVersion(version3,constant("radio"),object({numCorrect:optional(number),choices:arrayWithIndex(index=>object({content:defaulted(string,()=>""),rationale:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),id:defaulted(string,()=>generateChoiceId(index))})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean)}));const version2=optional(object({major:constant(2),minor:number}));const parseRadioWidgetV2=parseWidgetWithVersion(version2,constant("radio"),defaulted(object({numCorrect:optional(number),choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:parseOnePerLine,displayCount:optional(any),noneOfTheAbove:parseNoneOfTheAbove}),getDefaultOptions));const version1=optional(object({major:constant(1),minor:number}));const parseRadioWidgetV1=parseWidgetWithVersion(version1,constant("radio"),defaulted(object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:parseOnePerLine,displayCount:optional(any),noneOfTheAbove:parseNoneOfTheAbove}),getDefaultOptions));const version0=optional(object({major:constant(0),minor:number}));const parseRadioWidgetV0=parseWidgetWithVersion(version0,constant("radio"),defaulted(object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:parseOnePerLine,displayCount:optional(any),noneOfTheAbove:parseNoneOfTheAbove}),getDefaultOptions));function migrateV2toV3(widget){const{options}=widget;return {...widget,version:{major:3,minor:0},options:{numCorrect:options.numCorrect,hasNoneOfTheAbove:options.hasNoneOfTheAbove,countChoices:options.countChoices,randomize:options.randomize,multipleSelect:options.multipleSelect,deselectEnabled:options.deselectEnabled,choices:options.choices.map((choice,index)=>({content:choice.content,rationale:choice.clue,correct:choice.correct,isNoneOfTheAbove:choice.isNoneOfTheAbove,id:generateChoiceId(index)}))}}}function migrateV1ToV2(widget){const{options}=widget;return {...widget,version:{major:2,minor:0},options:{...options,numCorrect:deriveNumCorrect(options.choices)}}}function migrateV0ToV1(widget){const{options}=widget;const{noneOfTheAbove:_,...rest}=options;return {...widget,version:{major:1,minor:0},options:{...rest,hasNoneOfTheAbove:false,noneOfTheAbove:undefined}}}const parseRadioWidget=versionedWidgetOptions(3,parseRadioWidgetV3).withMigrationFrom(2,parseRadioWidgetV2,migrateV2toV3).withMigrationFrom(1,parseRadioWidgetV1,migrateV1ToV2).withMigrationFrom(0,parseRadioWidgetV0,migrateV0ToV1).parser;
164
+ const parseWidgetsMapOrUndefined=defaulted(optional((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx)),()=>undefined);function getDefaultOptions(){return {choices:[{content:"",id:generateChoiceId(0)},{content:"",id:generateChoiceId(1)},{content:"",id:generateChoiceId(2)},{content:"",id:generateChoiceId(3)}]}}const parseOnePerLine=defaulted(optional(boolean),()=>undefined);const parseNoneOfTheAbove=defaulted(optional(constant(false)),()=>undefined);function generateChoiceId(index){return `radio-choice-${index}`}const version3=optional(object({major:constant(3),minor:number}));const parseRadioWidgetV3=parseWidgetWithVersion(version3,constant("radio"),object({numCorrect:optional(number),choices:arrayWithIndex(index=>object({content:defaulted(string,()=>""),rationale:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),id:defaultedNonEmptyString(()=>generateChoiceId(index))})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean)}));const version2=optional(object({major:constant(2),minor:number}));const parseRadioWidgetV2=parseWidgetWithVersion(version2,constant("radio"),defaulted(object({numCorrect:optional(number),choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:parseOnePerLine,displayCount:optional(any),noneOfTheAbove:parseNoneOfTheAbove}),getDefaultOptions));const version1=optional(object({major:constant(1),minor:number}));const parseRadioWidgetV1=parseWidgetWithVersion(version1,constant("radio"),defaulted(object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:parseOnePerLine,displayCount:optional(any),noneOfTheAbove:parseNoneOfTheAbove}),getDefaultOptions));const version0=optional(object({major:constant(0),minor:number}));const parseRadioWidgetV0=parseWidgetWithVersion(version0,constant("radio"),defaulted(object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:parseWidgetsMapOrUndefined})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:parseOnePerLine,displayCount:optional(any),noneOfTheAbove:parseNoneOfTheAbove}),getDefaultOptions));function migrateV2toV3(widget){const{options}=widget;return {...widget,version:{major:3,minor:0},options:{numCorrect:options.numCorrect,hasNoneOfTheAbove:options.hasNoneOfTheAbove,countChoices:options.countChoices,randomize:options.randomize,multipleSelect:options.multipleSelect,deselectEnabled:options.deselectEnabled,choices:options.choices.map((choice,index)=>({content:choice.content,rationale:choice.clue,correct:choice.correct,isNoneOfTheAbove:choice.isNoneOfTheAbove,id:generateChoiceId(index)}))}}}function migrateV1ToV2(widget){const{options}=widget;return {...widget,version:{major:2,minor:0},options:{...options,numCorrect:deriveNumCorrect(options.choices)}}}function migrateV0ToV1(widget){const{options}=widget;const{noneOfTheAbove:_,...rest}=options;return {...widget,version:{major:1,minor:0},options:{...rest,hasNoneOfTheAbove:false,noneOfTheAbove:undefined}}}const parseRadioWidget=versionedWidgetOptions(3,parseRadioWidgetV3).withMigrationFrom(2,parseRadioWidgetV2,migrateV2toV3).withMigrationFrom(1,parseRadioWidgetV1,migrateV1ToV2).withMigrationFrom(0,parseRadioWidgetV0,migrateV0ToV1).parser;
165
165
 
166
166
  const parseSorterWidget=parseWidget(constant("sorter"),object({correct:array(string),padding:boolean,layout:enumeration("horizontal","vertical")}));
167
167