Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move main Scorer and Validator to PerseusScore #2165

Merged
merged 28 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8aa4028
[LEMS-2737/move-scoring-logic] WIP: start the move
handeyeco Jan 28, 2025
b25fb6c
[LEMS-2737/move-scoring-logic] WIP: scoring registry
handeyeco Jan 28, 2025
d2387fc
[LEMS-2737/move-scoring-logic] WIP: handle noop scorer
handeyeco Jan 28, 2025
3523c8f
[LEMS-2737/move-scoring-logic] WIP: move group scorer
handeyeco Jan 28, 2025
8fc194e
[LEMS-2737/move-scoring-logic] WIP: move alignments
handeyeco Jan 28, 2025
15c03e5
[LEMS-2737/move-scoring-logic] WIP: Perseus Core registry
handeyeco Jan 28, 2025
39efebe
[LEMS-2737/move-scoring-logic] WIP: getSupportedAlignments
handeyeco Jan 28, 2025
0934f34
[LEMS-2737/move-scoring-logic] WIP: add registry helpers
handeyeco Jan 28, 2025
f764d86
[LEMS-2737/move-scoring-logic] WIP: mock widget
handeyeco Jan 28, 2025
5348013
[LEMS-2737/move-scoring-logic] WIP: lint/tsc happy, tests sad
handeyeco Jan 28, 2025
14450db
[LEMS-2737/move-scoring-logic] WIP: fix some tests
handeyeco Jan 28, 2025
38ea7b6
[LEMS-2737/move-scoring-logic] fix tests
handeyeco Jan 28, 2025
de0e4ae
[LEMS-2737/move-scoring-logic] convert Log to Error
handeyeco Jan 28, 2025
e894520
[LEMS-2737/move-scoring-logic] remove validation checks in scorers
handeyeco Jan 28, 2025
7d73db2
[LEMS-2737/move-scoring-logic] fix test util file placement
handeyeco Jan 28, 2025
f231ad4
[LEMS-2737/move-scoring-logic] docs(changeset): Move scorePerseusItem…
handeyeco Jan 28, 2025
4216e8a
[LEMS-2737/move-scoring-logic] more cleanup
handeyeco Jan 29, 2025
d7f2607
[LEMS-2737/move-scoring-logic] fix conflicts
handeyeco Jan 30, 2025
83080a4
[LEMS-2737/move-scoring-logic] add grapher to core registry
handeyeco Jan 30, 2025
34055a0
[LEMS-2737/move-scoring-logic] rename WidgetLogic to CoreWidgetRegistry
handeyeco Jan 30, 2025
19a5d84
[LEMS-2737/move-scoring-logic] add oldWidgetInfo to error metadata
handeyeco Jan 30, 2025
d9a6699
[LEMS-2737/move-scoring-logic] secure getSupportedAlignments a little
handeyeco Jan 30, 2025
488f663
[LEMS-2737/move-scoring-logic] remove underscore extends
handeyeco Jan 30, 2025
a916f59
[LEMS-2737/move-scoring-logic] cleanup getSupportedAlignments more
handeyeco Jan 30, 2025
852109c
[LEMS-2737/move-scoring-logic] cleanup getDefaultAlignment
handeyeco Jan 30, 2025
8fed47e
[LEMS-2737/move-scoring-logic] merge main, resolve conflicts
handeyeco Feb 3, 2025
47569f0
[LEMS-2737/move-scoring-logic] fix conflicts
handeyeco Feb 3, 2025
de42db3
[LEMS-2737/move-scoring-logic] restore external API
handeyeco Feb 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions dev/flipbook.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint monorepo/no-internal-import: "off", monorepo/no-relative-import: "off", import/no-relative-packages: "off" */
import {scorePerseusItem} from "@khanacademy/perseus-score";
import Banner from "@khanacademy/wonder-blocks-banner";
import Button from "@khanacademy/wonder-blocks-button";
import {View} from "@khanacademy/wonder-blocks-core";
Expand All @@ -18,7 +19,6 @@ import {useEffect, useMemo, useReducer, useRef, useState} from "react";

import {Renderer} from "../packages/perseus/src";
import {SvgImage} from "../packages/perseus/src/components";
import {scorePerseusItem} from "../packages/perseus/src/renderer-util";
import {mockStrings} from "../packages/perseus/src/strings";
import {isCorrect} from "../packages/perseus/src/util/scoring";
import {trueForAllMafsSupportedGraphTypes} from "../packages/perseus/src/widgets/interactive-graphs/mafs-supported-graph-types";
Expand Down Expand Up @@ -324,7 +324,6 @@ function GradableRenderer(props: QuestionRendererProps) {
const score = scorePerseusItem(
question,
rendererRef.current.getUserInputMap(),
mockStrings,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now all validators and scorers should be sending error codes instead of error messages, so we don't need strings anymore.

"en",
);
setScore(score);
Expand Down
1 change: 1 addition & 0 deletions dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@khanacademy/math-input": "^22.2.2",
"@khanacademy/perseus-core": "3.3.0",
"@khanacademy/perseus-linter": "^1.2.14",
"@khanacademy/perseus-score": "^2.0.0",
"@khanacademy/pure-markdown": "^0.3.23",
"@khanacademy/simple-markdown": "^0.13.16",
"@khanacademy/wonder-blocks-banner": "4.0.5",
Expand Down
8 changes: 8 additions & 0 deletions packages/perseus-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type {
MarkerType,
InteractiveMarkerType,
Relationship,
Alignment,
} from "./types";
export type {ErrorKind} from "./error/errors";
export type {FunctionTypeMappingKeys} from "./utils/grapher-util";
Expand Down Expand Up @@ -110,8 +111,15 @@ export type {TableDefaultWidgetOptions} from "./widgets/table";
export {default as videoLogic} from "./widgets/video";
export type {VideoDefaultWidgetOptions} from "./widgets/video";

export {
getUpgradedWidgetOptions,
upgradeWidgetInfoToLatestVersion,
} from "./widgets/upgrade";

export type * from "./widgets/logic-export.types";

export * as WidgetLogic from "./widgets/widget-registry";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming difference here feels like perhaps this should be exported as WidgetRegistry. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed the export and file to CoreWidgetRegistry/core-widget-registry


export {default as getOrdererPublicWidgetOptions} from "./widgets/orderer/orderer-util";
export {default as getCategorizerPublicWidgetOptions} from "./widgets/categorizer/categorizer-util";
export {default as getExpressionPublicWidgetOptions} from "./widgets/expression/expression-util";
9 changes: 9 additions & 0 deletions packages/perseus-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,12 @@ export type InteractiveMarkerType = MarkerType & {
// Used for NumberLine
// TODO: can this be merged with PerseusNumberLineWidgetOptions.correctRel?
export type Relationship = "lt" | "gt" | "le" | "ge";

export type Alignment =
| "default"
| "block"
| "inline-block"
| "inline"
| "float-left"
| "float-right"
| "full-width";
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/cs-program/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const defaultWidgetOptions: CSProgramDefaultWidgetOptions = {
const csProgramWidgetLogic: WidgetLogic = {
name: "cs-program",
defaultWidgetOptions,
supportedAlignments: ["block", "full-width"],
};

export default csProgramWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/definition/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const defaultWidgetOptions: DefinitionDefaultWidgetOptions = {
const definitionWidgetLogic: WidgetLogic = {
name: "definition",
defaultWidgetOptions,
defaultAlignment: "inline",
};

export default definitionWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/dropdown/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const defaultWidgetOptions: DropdownDefaultWidgetOptions = {
const dropdownWidgetLogic: WidgetLogic = {
name: "definition",
defaultWidgetOptions,
defaultAlignment: "inline-block",
};

export default dropdownWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/explanation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const defaultWidgetOptions: ExplanationDefaultWidgetOptions = {
const explanationWidgetLogic: WidgetLogic = {
name: "explanation",
defaultWidgetOptions,
defaultAlignment: "inline",
};

export default explanationWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/expression/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const expressionWidgetLogic: WidgetLogic = {
version: currentVersion,
widgetOptionsUpgrades: widgetOptionsUpgrades,
defaultWidgetOptions: defaultWidgetOptions,
defaultAlignment: "inline-block",
};

export default expressionWidgetLogic;
4 changes: 2 additions & 2 deletions packages/perseus-core/src/widgets/graded-group-set/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ const defaultWidgetOptions: GradedGroupSetDefaultWidgetOptions = {
gradedGroups: [],
};

const GradedGroupSetWidgetLogic: WidgetLogic = {
const gradedGroupSetWidgetLogic: WidgetLogic = {
name: "graded-group-set",
defaultWidgetOptions,
};

export default GradedGroupSetWidgetLogic;
export default gradedGroupSetWidgetLogic;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This were just mistakes from previous PRs.

4 changes: 2 additions & 2 deletions packages/perseus-core/src/widgets/graded-group/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ const defaultWidgetOptions: GradedGroupDefaultWidgetOptions = {
hint: null,
};

const GradedGroupWidgetLogic: WidgetLogic = {
const gradedGroupWidgetLogic: WidgetLogic = {
name: "graded-group",
defaultWidgetOptions,
};

export default GradedGroupWidgetLogic;
export default gradedGroupWidgetLogic;
4 changes: 2 additions & 2 deletions packages/perseus-core/src/widgets/group/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ const defaultWidgetOptions: GroupDefaultWidgetOptions = {
metadata: undefined,
};

const GroupWidgetLogic: WidgetLogic = {
const groupWidgetLogic: WidgetLogic = {
name: "group",
defaultWidgetOptions,
};

export default GroupWidgetLogic;
export default groupWidgetLogic;
2 changes: 2 additions & 0 deletions packages/perseus-core/src/widgets/image/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const defaultWidgetOptions: ImageDefaultWidgetOptions = {
const imageWidgetLogic: WidgetLogic = {
name: "image",
defaultWidgetOptions,
supportedAlignments: ["block", "full-width"],
defaultAlignment: "block",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alignment is used during the upgrade process, that's why I moved all of these.

};

export default imageWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/input-number/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const defaultWidgetOptions: InputNumberDefaultWidgetOptions = {
const inputNumberWidgetLogic: WidgetLogic = {
name: "input-number",
defaultWidgetOptions,
defaultAlignment: "inline-block",
};

export default inputNumberWidgetLogic;
3 changes: 3 additions & 0 deletions packages/perseus-core/src/widgets/logic-export.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {Version} from "../data-schema";
import type {Alignment} from "../types";

export type WidgetOptionsUpgradeMap = {
// OldProps => NewProps,
Expand All @@ -10,4 +11,6 @@ export type WidgetLogic = {
version?: Version;
widgetOptionsUpgrades?: WidgetOptionsUpgradeMap;
defaultWidgetOptions?: any;
supportedAlignments?: ReadonlyArray<Alignment>;
defaultAlignment?: Alignment;
};
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/numeric-input/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const defaultWidgetOptions: NumericInputDefaultWidgetOptions = {
const numericInputWidgetLogic: WidgetLogic = {
name: "numeric-input",
defaultWidgetOptions,
defaultAlignment: "inline-block",
};

export default numericInputWidgetLogic;
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const defaultWidgetOptions: PassageRefTargetDefaultWidgetOptions = {
const passageRefTargetWidgetLogic: WidgetLogic = {
name: "passageRefTarget",
defaultWidgetOptions,
defaultAlignment: "inline",
};

export default passageRefTargetWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/passage-ref/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const passageRefWidgetLogic: WidgetLogic = {
name: "passageRef",
version: currentVersion,
defaultWidgetOptions: defaultWidgetOptions,
defaultAlignment: "inline",
};

export default passageRefWidgetLogic;
4 changes: 2 additions & 2 deletions packages/perseus-core/src/widgets/phet-simulation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ const defaultWidgetOptions: PhetSimulationDefaultWidgetOptions = {
description: "",
};

const PhetSimulationWidgetLogic: WidgetLogic = {
const phetSimulationWidgetLogic: WidgetLogic = {
name: "phet-simulation",
defaultWidgetOptions,
};

export default PhetSimulationWidgetLogic;
export default phetSimulationWidgetLogic;
158 changes: 158 additions & 0 deletions packages/perseus-core/src/widgets/upgrade.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import _ from "underscore";

import {Errors} from "../error/errors";
import {PerseusError} from "../error/perseus-error";
import {mapObject} from "../utils/objective_";

import {
getCurrentVersion,
getDefaultWidgetOptions,
getSupportedAlignments,
getWidgetOptionsUpgrades,
isWidgetRegistered,
} from "./widget-registry";

import type {PerseusWidget, PerseusWidgetsMap} from "../data-schema";

const DEFAULT_STATIC = false;

export const upgradeWidgetInfoToLatestVersion = (
oldWidgetInfo: PerseusWidget,
): PerseusWidget => {
const type = oldWidgetInfo.type;
// NOTE(jeremy): This looks like it could be replaced by fixing types so
// that `type` is non-optional. But we're seeing this in Sentry today so I
// suspect we have legacy data (potentially unpublished) and we should
// figure that out before depending solely on types.
if (!_.isString(type)) {
throw new PerseusError(
"widget type must be a string, but was: " + type,
Errors.Internal,
);
}

if (!isWidgetRegistered(type)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change, basically just adding a helper here.

// If we have a widget that isn't registered, we can't upgrade it
// TODO(aria): Figure out what the best thing to do here would be
return oldWidgetInfo;
}

// Unversioned widgets (pre-July 2014) are all implicitly 0.0
const initialVersion = oldWidgetInfo.version || {major: 0, minor: 0};
const latestVersion = getCurrentVersion(type);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change, basically just adding a helper here.


// If the widget version is later than what we understand (major
// version is higher than latest, or major versions are equal and minor
// version is higher than latest), don't perform any upgrades.
if (
initialVersion.major > latestVersion.major ||
(initialVersion.major === latestVersion.major &&
initialVersion.minor > latestVersion.minor)
) {
return oldWidgetInfo;
}

// We do a clone here so that it's safe to mutate the input parameter
// in propUpgrades functions (which I will probably accidentally do at
// some point, and we would like to not break when that happens).
let newEditorOptions = _.clone(oldWidgetInfo.options) || {};

const upgradePropsMap = getWidgetOptionsUpgrades(type);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change, basically just adding a helper here.


// Empty props usually mean a newly created widget by the editor,
// and are always considerered up-to-date.
// Mostly, we'd rather not run upgrade functions on props that are
// not complete.
if (_.keys(newEditorOptions).length !== 0) {
// We loop through all the versions after the current version of
// the loaded widget, up to and including the latest version of the
// loaded widget, and run the upgrade function to bring our loaded
// widget's props up to that version.
// There is a little subtlety here in that we call
// upgradePropsMap[1] to upgrade *to* version 1,
// (not from version 1).
for (
let nextVersion = initialVersion.major + 1;
nextVersion <= latestVersion.major;
nextVersion++
) {
if (upgradePropsMap[String(nextVersion)]) {
newEditorOptions =
upgradePropsMap[String(nextVersion)](newEditorOptions);
} else {
throw new PerseusError(
"No upgrade found for widget. Cannot render.",
Errors.Internal,
{
metadata: {
type,
fromMajorVersion: nextVersion - 1,
toMajorVersion: nextVersion,
},
},
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's an important change. Originally we just Logged and continued. We don't have Log in PerseusCore so I wasn't sure what to do. IMO:

  • I feel like it's unlikely we'll hit a major bump that hasn't been handled by the upgrader
  • If we're worried about it, we could write tests or linters to make sure we don't do a major bump without an upgrader
  • Upgrading might disappear with Ben's current parsing work

So that's why I did what I did. Very open to ideas.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's reasonable to throw here. Perhaps we could include information from the widget options that might help us trace which content is causing this? Maybe just add JSON.serialize(oldWidgetInfo) to metadata here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
}
}

// Minor version upgrades (eg. new optional props) don't have
// transform functions. Instead, we fill in the new props with their
// defaults.
const defaultOptions = getDefaultWidgetOptions(type);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change, basically just adding a helper here.

newEditorOptions = {
...defaultOptions,
...newEditorOptions,
};

let alignment = oldWidgetInfo.alignment;

// Widgets that support multiple alignments will "lock in" the
// alignment to the alignment that would be listed first in the
// select box. If the widget only supports one alignment, the
// alignment value will likely just end up as "default".
if (alignment == null || alignment === "default") {
alignment = getSupportedAlignments(type)[0];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change, basically just adding a helper here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! The array access makes me a bit paranoid. Could we add a safety mechanism in getSupportedAlignments to throw if there are no supported alignments? Fully aware that this is extremely paranoid and you might just want to land this as is. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some safety measures and also now throw if somehow there's still not alignment.

}

let widgetStatic = oldWidgetInfo.static;

if (widgetStatic == null) {
widgetStatic = DEFAULT_STATIC;
}

return _.extend({}, oldWidgetInfo, {
// maintain other info, like type
// After upgrading we guarantee that the version is up-to-date
version: latestVersion,
// Default graded to true (so null/undefined becomes true):
graded: oldWidgetInfo.graded != null ? oldWidgetInfo.graded : true,
alignment: alignment,
static: widgetStatic,
options: newEditorOptions,
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to the changes you're making, but this feels like a really easy improvement:

Suggested change
return _.extend({}, oldWidgetInfo, {
// maintain other info, like type
// After upgrading we guarantee that the version is up-to-date
version: latestVersion,
// Default graded to true (so null/undefined becomes true):
graded: oldWidgetInfo.graded != null ? oldWidgetInfo.graded : true,
alignment: alignment,
static: widgetStatic,
options: newEditorOptions,
});
return {
...oldWidgetInfo,
// maintain other info, like type
// After upgrading we guarantee that the version is up-to-date
version: latestVersion,
// Default graded to true (so null/undefined becomes true):
graded: oldWidgetInfo.graded != null ? oldWidgetInfo.graded : true,
alignment: alignment,
static: widgetStatic,
options: newEditorOptions,
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, but I ran into a hairy type issue so I had to cast as any

};

export function getUpgradedWidgetOptions(
oldWidgetOptions: PerseusWidgetsMap,
): PerseusWidgetsMap {
return mapObject(oldWidgetOptions, (widgetInfo, widgetId) => {
if (!widgetInfo.type || !widgetInfo.alignment) {
const newValues: Record<string, any> = {};

if (!widgetInfo.type) {
// TODO: why does widget have no type?
// We don't want to derive type from widget ID
// see: LEMS-1845
newValues.type = widgetId.split(" ")[0];
Comment on lines +152 to +155
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to start throwing in the face of a missing widget type. Right now, we limp along and gloss over this data this is quite broken (and I suspect oooooold).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make this change, but I wasn't sure if you were asking me to or not. I personally would like to avoid making this PR more risky than it already is, but I don't feel strongly about it either way. I agree that it seems low risk to throw here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was ambiguous. Let's not throw for now.

}

if (!widgetInfo.alignment) {
newValues.alignment = "default";
}

widgetInfo = {...widgetInfo, ...newValues};
}

return upgradeWidgetInfoToLatestVersion(widgetInfo) as any;
});
}
2 changes: 2 additions & 0 deletions packages/perseus-core/src/widgets/video/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const defaultWidgetOptions: VideoDefaultWidgetOptions = {
const videoWidgetLogic: WidgetLogic = {
name: "video",
defaultWidgetOptions,
supportedAlignments: ["block", "float-left", "float-right", "full-width"],
defaultAlignment: "block",
};

export default videoWidgetLogic;
Loading
Loading