From 9b8e726282d53aac5ff9783fc5e27e251f1c44b1 Mon Sep 17 00:00:00 2001 From: Jeremy Wiebe Date: Fri, 29 Nov 2024 11:54:44 -0800 Subject: [PATCH] Improve comments --- packages/perseus/src/perseus-types.ts | 37 ++++++++--- packages/perseus/src/renderer.tsx | 3 + packages/perseus/src/types.ts | 92 +++++++++++++++++---------- 3 files changed, 90 insertions(+), 42 deletions(-) diff --git a/packages/perseus/src/perseus-types.ts b/packages/perseus/src/perseus-types.ts index f31451e81b..d55b2625cc 100644 --- a/packages/perseus/src/perseus-types.ts +++ b/packages/perseus/src/perseus-types.ts @@ -114,6 +114,9 @@ export type PerseusArticle = PerseusRenderer | ReadonlyArray; * A "MultiItem" is an advanced Perseus item. It is rendered by the * `MultiRenderer` and you can control the layout of individual parts of the * item. + * + * @deprecated MultiItem support is slated for removal in a future Perseus + * release. */ export type MultiItem = { // Multi-item should only show up in Test Prep content and it is a variant of a PerseusItem @@ -128,20 +131,28 @@ export type Version = { }; export type PerseusRenderer = { - // Translatable Markdown content to be rendered. May include references to - // widgets (as [[☃ widgetName]]) or images (as ![image text](imageUrl)). - // For each image found in this content, there can be an entry in the - // `images` dict (below) with the key being the image's url which defines - // additional attributes for the image. + /** + * Translatable Markdown content to be rendered. May include references to + * widgets (as [[☃ widgetName]]) or images (as ![image text](imageUrl)). + * For each image found in this content, there can be an entry in the + * `images` dict (below) with the key being the image's url which defines + * additional attributes for the image. + */ content: string; - // A dictionary of {[widgetName]: Widget} to be referenced from the content field + /** + * A dictionary of {[widgetName]: Widget} to be referenced from the content + * field. + */ widgets: PerseusWidgetsMap; - // Used in the PerseusGradedGroup widget. A list of "tags" that are keys that represent other content in the system. Not rendered to the user. + // Used in the PerseusGradedGroup widget. A list of "tags" that are keys + // that represent other content in the system. Not rendered to the user. // NOTE: perseus_data.go says this is required even though it isn't necessary. metadata?: ReadonlyArray; - // A dictionary of {[imageUrl]: PerseusImageDetail}. + /** + * A dictionary of {[imageUrl]: PerseusImageDetail}. + */ images: { - [key: string]: PerseusImageDetail; + [imageUrl: string]: PerseusImageDetail; }; }; @@ -183,6 +194,10 @@ export const ItemExtras = [ ] as const; export type PerseusAnswerArea = Record<(typeof ItemExtras)[number], boolean>; +/** + * The type representing the common structure of all widget's options. The + * `Options` generic type represents the widget-specific option data. + */ export type WidgetOptions = { // The "type" of widget which will define what the Options field looks like type: Type; @@ -310,7 +325,9 @@ export type PerseusWidget = | VideoWidget | AutoCorrectWidget; -// A background image applied to various widgets. +/** + * A background image applied to various widgets. + */ export type PerseusImageBackground = { // The URL of the image url: string | null | undefined; diff --git a/packages/perseus/src/renderer.tsx b/packages/perseus/src/renderer.tsx index 41e383a641..7bb5e26a16 100644 --- a/packages/perseus/src/renderer.tsx +++ b/packages/perseus/src/renderer.tsx @@ -1594,6 +1594,9 @@ class Renderer return state; }; + /** + * Returns an array of widget ids that are empty. + */ emptyWidgets(): ReadonlyArray { return emptyWidgetsFunctional( this.state.widgetInfo, diff --git a/packages/perseus/src/types.ts b/packages/perseus/src/types.ts index ec8da5f961..ad6dbf1fc6 100644 --- a/packages/perseus/src/types.ts +++ b/packages/perseus/src/types.ts @@ -65,13 +65,15 @@ export interface Widget { getDOMNodeForPath?: (path: FocusPath) => Element | Text | null; deselectIncorrectSelectedChoices?: () => void; + /** + * Returns widget state that can be passed back to `restoreSerializedState` + * to put the widget back into exactly the same state. If the widget does + * not implement this function, the renderer simply returns all of the + * widget's props. + */ // TODO(jeremy): I think this return value is wrong. The widget // getSerializedState should just return _its_ serialized state, not a // key/value list of all widget states (i think!) - // Returns widget state that can be passed back to `restoreSerializedState` - // to put the widget back into exactly the same state. If the widget does - // not implement this function, the renderer simply returns all of the - // widget's props. getSerializedState?: () => SerializedState; // SUSPECT, restoreSerializedState?: (props: any, callback: () => void) => any; @@ -459,15 +461,17 @@ type InitialRequestUrlInterface = { export type VideoKind = "YOUTUBE_ID" | "READABLE_ID"; -// An object for dependency injection, to allow different clients -// to provide different methods for logging, translation, network -// requests, etc. -// -// NOTE: You should avoid adding new dependencies here as this type was added -// as a quick fix to get around the fact that some of the dependencies Perseus -// needs are used in places where neither `APIOptions` nor a React Context -// could be used. Aim to shrink the footprint of PerseusDependencies and try to -// use alternative methods where possible. +/** + * An object for dependency injection, to allow different clients + * to provide different methods for logging, translation, network + * requests, etc. + * + * NOTE: You should avoid adding new dependencies here as this type was added + * as a quick fix to get around the fact that some of the dependencies Perseus + * needs are used in places where neither `APIOptions` nor a React Context + * could be used. Aim to shrink the footprint of PerseusDependencies and try to + * use alternative methods where possible. + */ export type PerseusDependencies = { // JIPT JIPT: JIPT; @@ -563,9 +567,11 @@ export type Alignment = type WidgetOptions = any; -// A transform that maps the WidgetOptions (sometimes referred to as -// EditorProps) to the props used to render the widget. Often this is an -// identity transform. +/** + * A transform that maps the WidgetOptions (sometimes referred to as + * EditorProps) to the props used to render the widget. Often this is an + * identity transform. + */ // TODO(jeremy): Make this generic so that the WidgetOptions and output type // become strongly typed. export type WidgetTransform = ( @@ -602,11 +608,12 @@ export type WidgetExports< /** Supresses widget from showing up in the dropdown in the content editor */ hidden?: boolean; /** - The widget version. Any time the _major_ version changes, the widget - should provide a new entry in the propUpgrades map to migrate from the - older version to the current (new) version. Minor version changes must - be backwards compatible with previous minor versions widget options. - This key defaults to `{major: 0, minor: 0}` if not provided. + * The widget version. Any time the _major_ version changes, the widget + * should provide a new entry in the propUpgrades map to migrate from the + * older version to the current (new) version. Minor version changes must + * be backwards compatible with previous minor versions widget options. + * + * This key defaults to `{major: 0, minor: 0}` if not provided. */ version?: Version; supportedAlignments?: ReadonlyArray; @@ -617,27 +624,40 @@ export type WidgetExports< traverseChildWidgets?: any; // (Props, traverseRenderer) => NewProps, - /** transforms the widget options to the props used to render the widget */ + /** + * Transforms the widget options to the props used to render the widget. + */ transform?: WidgetTransform; - /** transforms the widget options to the props used to render the widget for - static renders */ + /** + * Transforms the widget options to the props used to render the widget for + * static renders. + */ staticTransform?: WidgetTransform; // this is a function of some sort, + /** + * A function that scores user input (the guess) for the widget. + */ scorer?: WidgetScorerFunction; + getOneCorrectAnswerFromRubric?: ( rubric: Rubric, ) => string | null | undefined; /** - A map of major version numbers (as a string, eg "1") to a function that - migrates from the _previous_ major version. - Example: - propUpgrades: {'1': (options) => ({...options})} - would migrate from major version 0 to 1. - */ + * A map of major version numbers (as a string, eg "1") to a function that + * migrates from the _previous_ major version. + * + * Example: + * ``` + * propUpgrades: {'1': (options) => ({...options})} + * ``` + * + * This configuration would migrate options from major version 0 to 1. + */ propUpgrades?: { - [key: string]: (arg1: any) => any; - }; // OldProps => NewProps, + // OldProps => NewProps, + [targetMajorVersion: string]: (arg1: any) => any; + }; }>; export type FilterCriterion = @@ -648,6 +668,14 @@ export type FilterCriterion = widget?: Widget | null | undefined, ) => boolean); +/** + * The full set of props provided to all widgets when they are rendered. The + * `RenderProps` generic argument are the widget-specific props that originate + * from the stored PerseusItem. Note that they may not match the serialized + * widget options exactly as they are the result of running the options through + * any `propUpgrades` the widget defines as well as its `transform` or + * `staticTransform` functions (depending on the options `static` flag). + */ // NOTE: Rubric should always be the corresponding widget options type for the component. // TODO: in fact, is it really the rubric? WidgetOptions is what we use to configure the widget // (which is what this seems to be for)