From 282e8fcbcc60e4adefbcf900aacdec1d88c4431a Mon Sep 17 00:00:00 2001 From: Lee Yi Date: Tue, 23 Dec 2025 07:06:49 -0500 Subject: [PATCH 01/71] Fix incorrect doc tags --- eslint.config.js | 8 ++ src/bundles/arcade_2d/src/functions.ts | 23 ++-- src/bundles/binary_tree/src/functions.ts | 2 +- src/bundles/curve/src/drawers.ts | 28 ++-- src/bundles/game/src/functions.ts | 10 +- src/bundles/midi/src/index.ts | 15 +- src/bundles/midi/src/utils.ts | 2 +- src/bundles/plotly/src/functions.ts | 153 +-------------------- src/bundles/repeat/src/functions.ts | 6 +- src/bundles/rune/src/display.ts | 8 +- src/bundles/rune/src/functions.ts | 38 ++--- src/bundles/rune/src/rune.ts | 25 +++- src/bundles/rune_in_words/src/functions.ts | 42 +++--- src/bundles/sound/src/functions.ts | 44 +++--- src/bundles/sound/src/play_in_tab.ts | 2 +- src/bundles/stereo_sound/src/functions.ts | 62 ++++----- src/bundles/unity_academy/src/functions.ts | 64 ++++----- 17 files changed, 205 insertions(+), 327 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 788d9a165b..13b487ee2d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -236,6 +236,14 @@ export default defineConfig( checkDestructured: false, disableMissingParamChecks: true }], + 'jsdoc/check-tag-names': ['error', { + // NOTE: Not all Typedoc supported tags are present here. Feel free to add any other + // Typedoc supported tags to this list + definedTags: ['category', 'categoryDescription', 'hidden'] + }], + 'jsdoc/empty-tags': ['error', { + tags: ['hidden'] + }], 'import/first': 'warn', 'import/newline-after-import': 'warn', diff --git a/src/bundles/arcade_2d/src/functions.ts b/src/bundles/arcade_2d/src/functions.ts index 6b16b0cf8c..c70eff0704 100644 --- a/src/bundles/arcade_2d/src/functions.ts +++ b/src/bundles/arcade_2d/src/functions.ts @@ -71,7 +71,7 @@ export const config = { fps: DEFAULT_FPS, isDebugEnabled: DEFAULT_DEBUG_STATE, // User update function - userUpdateFunction: (() => {}) as UpdateFunction + userUpdateFunction: (() => { }) as UpdateFunction }; // ============================================================================= @@ -101,7 +101,8 @@ export function create_rectangle(width: number, height: number): ShapeGameObject * Creates a CircleGameObject that takes in circle shape properties. * * @param radius Radius of the circle to create - * @example```ts + * @example + * ```ts * const circle = create_circle(100); * ``` * @category GameObject @@ -519,15 +520,15 @@ export function query_pointer_position(): PositionXY { * @hidden */ const withinRange: (num: number, min: number, max: number) => number -= (num: number, min: number, max: number) => { - if (num > max) { - return max; - } - if (num < min) { - return min; - } - return num; -}; + = (num: number, min: number, max: number) => { + if (num > max) { + return max; + } + if (num < min) { + return min; + } + return num; + }; /** * Sets the frames per second of the canvas, which should be between the MIN_FPS and MAX_FPS. diff --git a/src/bundles/binary_tree/src/functions.ts b/src/bundles/binary_tree/src/functions.ts index ef2651ff31..da1d87483f 100644 --- a/src/bundles/binary_tree/src/functions.ts +++ b/src/bundles/binary_tree/src/functions.ts @@ -7,7 +7,7 @@ import type { BinaryTree, EmptyBinaryTree, NonEmptyBinaryTree } from './types'; * ```typescript * display(make_empty_tree()); // Shows "null" in the REPL * ``` - * @return An empty binary tree + * @returns An empty binary tree */ export function make_empty_tree(): BinaryTree { return null; diff --git a/src/bundles/curve/src/drawers.ts b/src/bundles/curve/src/drawers.ts index baf7223214..16fe745d6a 100644 --- a/src/bundles/curve/src/drawers.ts +++ b/src/bundles/curve/src/drawers.ts @@ -66,7 +66,7 @@ function createDrawFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_connected(100)(t => make_point(t, t)); @@ -83,7 +83,7 @@ export const draw_connected = createDrawFunction('none', 'lines', '2D', false); * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_connected_full_view(100)(t => make_point(t, t)); @@ -105,7 +105,7 @@ export const draw_connected_full_view = createDrawFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_connected_full_view_proportional(100)(t => make_point(t, t)); @@ -127,7 +127,7 @@ export const draw_connected_full_view_proportional = createDrawFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1,there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_points(100)(t => make_point(t, t)); @@ -145,7 +145,7 @@ export const draw_points = createDrawFunction('none', 'points', '2D', false); * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_points_full_view(100)(t => make_point(t, t)); @@ -168,7 +168,7 @@ export const draw_points_full_view = createDrawFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_points_full_view_proportional(100)(t => make_point(t, t)); @@ -190,7 +190,7 @@ export const draw_points_full_view_proportional = createDrawFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_3D_connected(100)(t => make_3D_point(t, t, t)); @@ -212,7 +212,7 @@ export const draw_3D_connected = createDrawFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_3D_connected_full_view(100)(t => make_3D_point(t, t, t)); @@ -234,7 +234,7 @@ export const draw_3D_connected_full_view = createDrawFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_3D_connected_full_view_proportional(100)(t => make_3D_point(t, t, t)); @@ -256,7 +256,7 @@ export const draw_3D_connected_full_view_proportional = createDrawFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_3D_points(100)(t => make_3D_point(t, t, t)); @@ -273,7 +273,7 @@ export const draw_3D_points = createDrawFunction('none', 'points', '3D', false); * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_3D_points_full_view(100)(t => make_3D_point(t, t, t)); @@ -295,7 +295,7 @@ export const draw_3D_points_full_view = createDrawFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_3D_points_full_view_proportional(100)(t => make_3D_point(t, t, t)); @@ -314,7 +314,7 @@ export const draw_3D_points_full_view_proportional = createDrawFunction( * @param fps Framerate of the animation in frames per second * @param drawer Draw function to the generated curves with * @param func Curve generating function. Takes in a timestamp value and returns a curve - * @return Curve Animation + * @returns Curve Animation */ export function animate_curve( duration: number, @@ -337,7 +337,7 @@ export function animate_curve( * @param fps Framerate of the animation in frames per second * @param drawer Draw function to the generated curves with * @param func Curve generating function. Takes in a timestamp value and returns a curve - * @return 3D Curve Animation + * @returns 3D Curve Animation */ export function animate_3D_curve( duration: number, diff --git a/src/bundles/game/src/functions.ts b/src/bundles/game/src/functions.ts index b494591908..dd265ab19d 100644 --- a/src/bundles/game/src/functions.ts +++ b/src/bundles/game/src/functions.ts @@ -60,7 +60,7 @@ enum ObjectTypes { const ObjTypes = Object.values(ObjectTypes); -const nullFn = () => {}; +const nullFn = () => { }; const mandatory = (obj, errMsg: string) => { if (!obj) { @@ -450,7 +450,7 @@ export function create_spritesheet_config( /** * Get in-game screen width. * - * @return screen width + * @returns screen width */ export function get_screen_width(): number { return screenSize.x; @@ -459,7 +459,7 @@ export function get_screen_width(): number { /** * Get in-game screen height. * - * @return screen height + * @returns screen height */ export function get_screen_height(): number { return screenSize.y; @@ -468,7 +468,7 @@ export function get_screen_height(): number { /** * Get game screen display width (accounting window size). * - * @return screen display width + * @returns screen display width */ export function get_screen_display_width(): number { return scene().scale.displaySize.width; @@ -477,7 +477,7 @@ export function get_screen_display_width(): number { /** * Get game screen display height (accounting window size). * - * @return screen display height + * @returns screen display height */ export function get_screen_display_height(): number { return scene().scale.displaySize.height; diff --git a/src/bundles/midi/src/index.ts b/src/bundles/midi/src/index.ts index e13c75c962..5d893eedf6 100644 --- a/src/bundles/midi/src/index.ts +++ b/src/bundles/midi/src/index.ts @@ -13,12 +13,15 @@ import { midiNoteToNoteName, noteToValues } from './utils'; * Converts a letter name to its corresponding MIDI note. * The letter name is represented in standard pitch notation. * Examples are "A5", "Db3", "C#7". - * Refer to this mapping from + * Refer to [this](https://i.imgur.com/qGQgmYr.png) mapping from * letter name to midi notes. * * @param note given letter name - * @return the corresponding midi note - * @example letter_name_to_midi_note("C4"); // Returns 60 + * @returns the corresponding midi note + * @example + * ``` + * letter_name_to_midi_note("C4"); // Returns 60 + * ``` * @function */ export function letter_name_to_midi_note(note: NoteWithOctave): MIDINote { @@ -88,9 +91,9 @@ export function midi_note_to_letter_name(midiNote: MIDINote, accidental: 'flat' * Converts a MIDI note to its corresponding frequency. * * @param note given MIDI note - * @return the frequency of the MIDI note - * @example midi_note_to_frequency(69); // Returns 440 + * @returns the frequency of the MIDI note * @function + * @example midi_note_to_frequency(69); // Returns 440 */ export function midi_note_to_frequency(note: MIDINote): number { // A4 = 440Hz = midi note 69 @@ -101,7 +104,7 @@ export function midi_note_to_frequency(note: MIDINote): number { * Converts a letter name to its corresponding frequency. * * @param note given letter name - * @return the corresponding frequency + * @returns the corresponding frequency * @example letter_name_to_frequency("A4"); // Returns 440 */ export function letter_name_to_frequency(note: NoteWithOctave): number { diff --git a/src/bundles/midi/src/utils.ts b/src/bundles/midi/src/utils.ts index 75a0450715..7504409b7d 100644 --- a/src/bundles/midi/src/utils.ts +++ b/src/bundles/midi/src/utils.ts @@ -30,7 +30,7 @@ export function noteToValues(note: NoteWithOctave, func_name: string = noteToVal ] as [NoteName, Accidental, number]; } -export function midiNoteToNoteName(midiNote: MIDINote, accidental: 'flat' | 'sharp', func_name: string = midiNoteToNoteName.name): Note { +export function midiNoteToNoteName(midiNote: MIDINote, accidental: 'flat' | 'sharp', func_name: string): Note { switch (midiNote % 12) { case 0: return 'C'; diff --git a/src/bundles/plotly/src/functions.ts b/src/bundles/plotly/src/functions.ts index 4718e82630..e5a446b80d 100644 --- a/src/bundles/plotly/src/functions.ts +++ b/src/bundles/plotly/src/functions.ts @@ -45,77 +45,6 @@ context.moduleContexts.plotly.state = { * ]; * new_plot(list(pair("z", z1), pair("type", "surface"))) // creates a surface plot in Plotly Tab * ``` - * - * - * @Types - * ``` typescript - * // The data format for input [{field_name}, value] from among the following fields - * data = { - * type: PlotType; - * x: Datum[] | Datum[][]; - * y: Datum[] | Datum[][]; - * z: Datum[] | Datum[][] | Datum[][][]; - * mode: - * | 'lines' - * | 'markers' - * | 'text' - * | 'lines+markers' - * | 'text+markers' - * | 'text+lines' - * | 'text+lines+markers' - * } - * - * - * type Datum = string | number | Date | null; - * type PlotType = - * | 'bar' - * | 'barpolar' - * | 'box' - * | 'candlestick' - * | 'carpet' - * | 'choropleth' - * | 'choroplethmapbox' - * | 'cone' - * | 'contour' - * | 'contourcarpet' - * | 'densitymapbox' - * | 'funnel' - * | 'funnelarea' - * | 'heatmap' - * | 'heatmapgl' - * | 'histogram' - * | 'histogram2d' - * | 'histogram2dcontour' - * | 'image' - * | 'indicator' - * | 'isosurface' - * | 'mesh3d' - * | 'ohlc' - * | 'parcats' - * | 'parcoords' - * | 'pie' - * | 'pointcloud' - * | 'sankey' - * | 'scatter' - * | 'scatter3d' - * | 'scattercarpet' - * | 'scattergeo' - * | 'scattergl' - * | 'scattermapbox' - * | 'scatterpolar' - * | 'scatterpolargl' - * | 'scatterternary' - * | 'splom' - * | 'streamtube' - * | 'sunburst' - * | 'surface' - * | 'table' - * | 'treemap' - * | 'violin' - * | 'volume' - * | 'waterfall'; - * - * ``` * @param data The data in the form of list of pair, with the first term in the pair is * the name of the field as a string and the second term is the value of the field * among the fields mentioned above @@ -157,80 +86,6 @@ export function new_plot(data: ListOfPairs): void { * } * const data = [{z: z1, type: 'surface'}, {z: z2 , type: 'surface'}]; * new_plot_json(data) // creates a surface plot in Plotly Tab - * - * - * - * ``` - * - * - * @Types - * ``` typescript - * // The data format for input [{field_name}, value] from among the following fields - * data = { - * type: PlotType; - * x: Datum[] | Datum[][]; - * y: Datum[] | Datum[][]; - * z: Datum[] | Datum[][] | Datum[][][]; - * mode: - * | 'lines' - * | 'markers' - * | 'text' - * | 'lines+markers' - * | 'text+markers' - * | 'text+lines' - * | 'text+lines+markers' - * }[] - * - * - * type Datum = string | number | Date | null; - * type PlotType = - * | 'bar' - * | 'barpolar' - * | 'box' - * | 'candlestick' - * | 'carpet' - * | 'choropleth' - * | 'choroplethmapbox' - * | 'cone' - * | 'contour' - * | 'contourcarpet' - * | 'densitymapbox' - * | 'funnel' - * | 'funnelarea' - * | 'heatmap' - * | 'heatmapgl' - * | 'histogram' - * | 'histogram2d' - * | 'histogram2dcontour' - * | 'image' - * | 'indicator' - * | 'isosurface' - * | 'mesh3d' - * | 'ohlc' - * | 'parcats' - * | 'parcoords' - * | 'pie' - * | 'pointcloud' - * | 'sankey' - * | 'scatter' - * | 'scatter3d' - * | 'scattercarpet' - * | 'scattergeo' - * | 'scattergl' - * | 'scattermapbox' - * | 'scatterpolar' - * | 'scatterpolargl' - * | 'scatterternary' - * | 'splom' - * | 'streamtube' - * | 'sunburst' - * | 'surface' - * | 'table' - * | 'treemap' - * | 'violin' - * | 'volume' - * | 'waterfall'; - * * ``` * @param data The data as an array of json objects having some or all of the given fields */ @@ -314,7 +169,7 @@ function createPlotFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type Curve → Drawing + * @returns function of type Curve → Drawing * @example * ``` * draw_connected_2d(100)(t => make_point(t, t)); @@ -342,7 +197,7 @@ export const draw_connected_2d = createPlotFunction( * @function * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points - * @return function of type 3D Curve → Drawing + * @returns function of type 3D Curve → Drawing * @example * ``` * draw_connected_3d(100)(t => make_point(t, t)); @@ -363,7 +218,7 @@ export const draw_connected_3d = createPlotFunction( * * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points * @function - * @return function of type 2D Curve → Drawing + * @returns function of type 2D Curve → Drawing * @example * ``` * draw_points_2d(100)(t => make_point(t, t)); @@ -389,7 +244,7 @@ export const draw_points_2d = createPlotFunction( * * @param num determines the number of points, lower than 65535, to be sampled. * Including 0 and 1, there are `num + 1` evenly spaced sample points * @function - * @return function of type 3D Curve → Drawing + * @returns function of type 3D Curve → Drawing * @example * ``` * draw_points_3d(100)(t => make_point(t, t)); diff --git a/src/bundles/repeat/src/functions.ts b/src/bundles/repeat/src/functions.ts index 4f2b02dfe5..f27f3e374d 100644 --- a/src/bundles/repeat/src/functions.ts +++ b/src/bundles/repeat/src/functions.ts @@ -13,7 +13,7 @@ * ``` * @param func the function to be repeated * @param n the number of times to repeat the function - * @return the new function that has the same effect as func repeated n times + * @returns the new function that has the same effect as func repeated n times */ export function repeat(func: Function, n: number): Function { return n === 0 ? (x: any) => x : (x: any) => func(repeat(func, n - 1)(x)); @@ -28,7 +28,7 @@ export function repeat(func: Function, n: number): Function { * plusTwo(2); // Returns 4 * ``` * @param func the function to be repeated - * @return the new function that has the same effect as `(x => func(func(x)))` + * @returns the new function that has the same effect as `(x => func(func(x)))` */ export function twice(func: Function): Function { return repeat(func, 2); @@ -43,7 +43,7 @@ export function twice(func: Function): Function { * plusNine(0); // Returns 9 * ``` * @param func the function to be repeated - * @return the new function that has the same effect as `(x => func(func(func(x))))` + * @returns the new function that has the same effect as `(x => func(func(func(x))))` */ export function thrice(func: Function): Function { return repeat(func, 3); diff --git a/src/bundles/rune/src/display.ts b/src/bundles/rune/src/display.ts index 92b5904f1b..c00eb000de 100644 --- a/src/bundles/rune/src/display.ts +++ b/src/bundles/rune/src/display.ts @@ -68,7 +68,7 @@ class RuneDisplay { * Renders the specified Rune in a tab as a basic drawing. * @function * @param rune - The Rune to render - * @return {Rune} The specified Rune + * @returns {Rune} The specified Rune * * @category Main */ @@ -79,7 +79,7 @@ export const show = RuneDisplay.show; * anaglyph. * @function * @param rune - The Rune to render - * @return {Rune} The specified Rune + * @returns {Rune} The specified Rune * * @category Main */ @@ -90,7 +90,7 @@ export const anaglyph = RuneDisplay.anaglyph; * of 0.1. * @function * @param rune - The Rune to render - * @return {Rune} The specified Rune + * @returns {Rune} The specified Rune * * @category Main */ @@ -102,7 +102,7 @@ export const hollusion = RuneDisplay.hollusion; * @function * @param rune - The Rune to render * @param {number} magnitude - The hollusion's magnitude - * @return {Rune} The specified Rune + * @returns {Rune} The specified Rune * * @category Main */ diff --git a/src/bundles/rune/src/functions.ts b/src/bundles/rune/src/functions.ts index 7a34c5f925..84731063b2 100644 --- a/src/bundles/rune/src/functions.ts +++ b/src/bundles/rune/src/functions.ts @@ -633,7 +633,7 @@ export class HollusionRune extends DrawnRune { lastTime = timeInMs; const framePos - = Math.floor(timeInMs / (period / frameCount)) % frameCount; + = Math.floor(timeInMs / (period / frameCount)) % frameCount; const fbObject = frameBuffer[framePos]; gl.clearColor(1.0, 1.0, 1.0, 1.0); // Set clear color to white, fully opaque gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Clear the viewport @@ -659,7 +659,7 @@ export const isHollusionRune = (rune: DrawnRune): rune is HollusionRune => rune * of the result * @param {Rune} rune1 - Given Rune * @param {Rune} rune2 - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -675,7 +675,7 @@ export const beside = RuneFunctions.beside; * @param {number} frac - Fraction between 0 and 1 (inclusive) * @param {Rune} rune1 - Given Rune * @param {Rune} rune2 - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -755,7 +755,7 @@ export const corner = RuneFunctions.corner; * flipping it around a vertical axis, * creating a mirror image * @param {Rune} rune - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -767,7 +767,7 @@ export const flip_horiz = RuneFunctions.flip_horiz; * flipping it around a horizontal axis, * turning it upside down * @param {Rune} rune - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -817,7 +817,7 @@ export const indigo = RuneColours.indigo; * arranging into a square for copies of the * given Rune in different orientations * @param {Rune} rune - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -847,7 +847,7 @@ export const orange = RuneColours.orange; * The depth range of the z-axis of a rune is [0,-1], this function maps the depth range of rune1 and rune2 to [0,-0.5] and [-0.5,-1] respectively. * @param {Rune} rune1 - Given Rune * @param {Rune} rune2 - Given Rune - * @return {Rune} Resulting Runes + * @returns {Rune} Resulting Runes * @function * * @category Main @@ -859,7 +859,7 @@ export const overlay = RuneFunctions.overlay; * @param {number} frac - Fraction between 0 and 1 (inclusive) * @param {Rune} rune1 - Given Rune * @param {Rune} rune2 - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -898,7 +898,7 @@ export const purple = RuneColours.purple; * by turning it a quarter-turn in * anti-clockwise direction. * @param {Rune} rune - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -910,7 +910,7 @@ export const quarter_turn_left = RuneFunctions.quarter_turn_left; * by turning it a quarter-turn around the centre in * clockwise direction. * @param {Rune} rune - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -954,7 +954,7 @@ export const red = RuneColours.red; * @param {number} n - A non-negative integer * @param {function} pattern - Unary function from Rune to Rune * @param {Rune} initial - The initial Rune - * @return {Rune} - Result of n times application of pattern to initial: + * @returns {Rune} - Result of n times application of pattern to initial: * pattern(pattern(...pattern(pattern(initial))...)) * @function * @@ -977,7 +977,7 @@ export const ribbon = RuneFunctions.ribbon; * may be cropped as a result. * @param {number} rad - Angle in radians * @param {Rune} rune - Given Rune - * @return {Rune} Rotated Rune + * @returns {Rune} Rotated Rune * @function * * @category Main @@ -995,7 +995,7 @@ export const sail = RuneFunctions.sail; * Scales a given Rune by a given factor in both x and y direction * @param {number} ratio - Scaling factor * @param {Rune} rune - Given Rune - * @return {Rune} Resulting scaled Rune + * @returns {Rune} Resulting scaled Rune * @function * * @category Main @@ -1007,7 +1007,7 @@ export const scale = RuneFunctions.scale; * @param {number} ratio_x - Scaling factor in x direction * @param {number} ratio_y - Scaling factor in y direction * @param {Rune} rune - Given Rune - * @return {Rune} Resulting scaled Rune + * @returns {Rune} Resulting scaled Rune * @function * * @category Main @@ -1021,7 +1021,7 @@ export const scale_independent = RuneFunctions.scale_independent; * result * @param {Rune} rune1 - Given Rune * @param {Rune} rune2 - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -1037,7 +1037,7 @@ export const stack = RuneFunctions.stack; * @param {number} frac - Fraction between 0 and 1 (inclusive) * @param {Rune} rune1 - Given Rune * @param {Rune} rune2 - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -1049,7 +1049,7 @@ export const stack_frac = RuneFunctions.stack_frac; * by vertically stacking n copies of it * @param {number} n - Positive integer * @param {Rune} rune - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main @@ -1068,7 +1068,7 @@ export const square = RuneFunctions.square; * @param {number} x - Translation in x direction * @param {number} y - Translation in y direction * @param {Rune} rune - Given Rune - * @return {Rune} Resulting translated Rune + * @returns {Rune} Resulting translated Rune * @function * * @category Main @@ -1086,7 +1086,7 @@ export const triangle = RuneFunctions.triangle; * Makes a new Rune from a given Rune * by turning it upside-down * @param {Rune} rune - Given Rune - * @return {Rune} Resulting Rune + * @returns {Rune} Resulting Rune * @function * * @category Main diff --git a/src/bundles/rune/src/rune.ts b/src/bundles/rune/src/rune.ts index aa25a6e255..77426d7890 100644 --- a/src/bundles/rune/src/rune.ts +++ b/src/bundles/rune/src/rune.ts @@ -52,21 +52,32 @@ void main(void) { `; /** * The basic data-representation of a Rune. When the Rune is drawn, every 3 consecutive vertex will form a triangle. - * @field vertices - A list of vertex coordinates, each vertex has 4 coordiante (x,y,z,t). - * @field colors - A list of vertex colors, each vertex has a color (r,g,b,a). - * @field transformMatrix - A mat4 that is applied to all the vertices and the sub runes - * @field subRune - A (potentially empty) list of Runes */ @classDeclaration('Rune') export class Rune { constructor( + /** + * A list of vertex coordinates, each vertex has 4 coordiante (x,y,z,t). + */ public vertices: Float32Array, + + /** + * A list of vertex colors, each vertex has a color (r,g,b,a). + */ public colors: Float32Array | null, + + /** + * A mat4 that is applied to all the vertices and the sub runes + */ public transformMatrix: mat4, + + /** + * A (potentially empty) list of Runes + */ public subRunes: Rune[], public texture: HTMLImageElement | null, public hollusionDistance: number - ) {} + ) { } public copy = () => new Rune( this.vertices, @@ -79,7 +90,7 @@ export class Rune { /** * Flatten the subrunes to return a list of runes - * @return Rune[], a list of runes + * @returns Rune[], a list of runes */ public flatten = () => { const runeList: Rune[] = []; @@ -357,7 +368,7 @@ export abstract class DrawnRune implements ReplResult { constructor( protected readonly rune: Rune, public readonly isHollusion: boolean - ) {} + ) { } public toReplString = () => ''; diff --git a/src/bundles/rune_in_words/src/functions.ts b/src/bundles/rune_in_words/src/functions.ts index 7da7e9e396..b359c37875 100644 --- a/src/bundles/rune_in_words/src/functions.ts +++ b/src/bundles/rune_in_words/src/functions.ts @@ -116,7 +116,7 @@ export function from_url(imageUrl: string): string { * @param ratio_x - Scaling factor in x direction * @param ratio_y - Scaling factor in y direction * @param rune - Given Rune - * @return Resulting scaled Rune + * @returns Resulting scaled Rune * * @category Main */ @@ -133,7 +133,7 @@ export function scale_independent( * Scales a given Rune by a given factor in both x and y direction * @param ratio - Scaling factor * @param rune - Given Rune - * @return Resulting scaled Rune + * @returns Resulting scaled Rune * * @category Main */ @@ -147,7 +147,7 @@ export function scale(ratio: number, rune: string): string { * @param x - Translation in x direction * @param y - Translation in y direction * @param rune - Given Rune - * @return Resulting translated Rune + * @returns Resulting translated Rune * * @category Main */ @@ -163,7 +163,7 @@ export function translate(x: number, y: number, rune: string): string { * may be cropped as a result. * @param rad - Angle in radians * @param rune - Given Rune - * @return Rotated Rune + * @returns Rotated Rune * * @category Main */ @@ -181,7 +181,7 @@ export function rotate(rad: number, rune: string): string { * @param frac - Fraction between 0 and 1 (inclusive) * @param rune1 - Given Rune * @param rune2 - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -199,7 +199,7 @@ export function stack_frac(frac: number, rune1: string, rune2: string): string { * result * @param rune1 - Given Rune * @param rune2 - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -213,7 +213,7 @@ export function stack(rune1: string, rune2: string): string { * by vertically stacking n copies of it * @param n - Positive integer * @param rune - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -228,7 +228,7 @@ export function stackn(n: number, rune: string): string { * by turning it a quarter-turn around the centre in * clockwise direction. * @param rune - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -242,7 +242,7 @@ export function quarter_turn_right(rune: string): string { * by turning it a quarter-turn in * anti-clockwise direction. * @param rune - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -255,7 +255,7 @@ export function quarter_turn_left(rune: string): string { * Makes a new Rune from a given Rune * by turning it upside-down * @param rune - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -273,7 +273,7 @@ export function turn_upside_down(rune: string): string { * @param frac - Fraction between 0 and 1 (inclusive) * @param rune1 - Given Rune * @param rune2 - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -290,7 +290,7 @@ export function beside_frac(frac: number, rune1: string, rune2: string): string * of the result * @param rune1 - Given Rune * @param rune2 - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -304,7 +304,7 @@ export function beside(rune1: string, rune2: string): string { * flipping it around a horizontal axis, * turning it upside down * @param rune - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -318,7 +318,7 @@ export function flip_vert(rune: string): string { * flipping it around a vertical axis, * creating a mirror image * @param rune - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -332,7 +332,7 @@ export function flip_horiz(rune: string): string { * arranging into a square for copies of the * given Rune in different orientations * @param rune - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -349,7 +349,7 @@ export function make_cross(rune: string): string { * @param n - A non-negative integer * @param pattern - Unary function from Rune to Rune * @param initial - The initial Rune - * @return - Result of n times application of pattern to initial: + * @returns - Result of n times application of pattern to initial: * pattern(pattern(...pattern(pattern(initial))...)) * * @category Main @@ -374,7 +374,7 @@ export function repeat_pattern( * @param frac - Fraction between 0 and 1 (inclusive) * @param rune1 - Given Rune * @param rune2 - Given Rune - * @return Resulting Rune + * @returns Resulting Rune * * @category Main */ @@ -388,7 +388,7 @@ export function overlay_frac(frac: number, rune1: string, rune2: string): string * The depth range of the z-axis of a rune is [0,-1], this function maps the depth range of rune1 and rune2 to [0,-0.5] and [-0.5,-1] respectively. * @param rune1 - Given Rune * @param rune2 - Given Rune - * @return Resulting Runes + * @returns Resulting Runes * * @category Main */ @@ -573,7 +573,7 @@ export function white(rune: string): string { /** * Renders the specified Rune in a tab as a basic drawing. * @param rune - The Rune to render - * @return The specified Rune + * @returns The specified Rune * * @category Main */ @@ -586,7 +586,7 @@ export function show(rune: string): string { * Renders the specified Rune in a tab as an anaglyph. Use 3D glasses to view the * anaglyph. * @param rune - The Rune to render - * @return The specified Rune + * @returns The specified Rune * * @category Main */ @@ -599,7 +599,7 @@ export function anaglyph(rune: string): string { * Renders the specified Rune in a tab as a hollusion, with a default magnitude * of 0.1. * @param rune - The Rune to render - * @return The specified Rune + * @returns The specified Rune * * @category Main */ diff --git a/src/bundles/sound/src/functions.ts b/src/bundles/sound/src/functions.ts index 7c6e1fa9f8..70e7c4f7c4 100644 --- a/src/bundles/sound/src/functions.ts +++ b/src/bundles/sound/src/functions.ts @@ -311,7 +311,7 @@ function validateWave(func_name: string, wave: unknown): asserts wave is Wave { * * @param wave wave function of the Sound * @param duration duration of the Sound - * @return with wave as wave function and duration as duration + * @returns with wave as wave function and duration as duration * @example const s = make_sound(t => Math_sin(2 * Math_PI * 440 * t), 5); */ export function make_sound(wave: Wave, duration: number): Sound { @@ -325,7 +325,7 @@ export function make_sound(wave: Wave, duration: number): Sound { * Accesses the wave function of a given Sound. * * @param sound given Sound - * @return the wave function of the Sound + * @returns the wave function of the Sound * @example get_wave(make_sound(t => Math_sin(2 * Math_PI * 440 * t), 5)); // Returns t => Math_sin(2 * Math_PI * 440 * t) */ export function get_wave(sound: Sound): Wave { @@ -336,7 +336,7 @@ export function get_wave(sound: Sound): Wave { * Accesses the duration of a given Sound. * * @param sound given Sound - * @return the duration of the Sound + * @returns the duration of the Sound * @example get_duration(make_sound(t => Math_sin(2 * Math_PI * 440 * t), 5)); // Returns 5 */ export function get_duration(sound: Sound): number { @@ -347,7 +347,7 @@ export function get_duration(sound: Sound): number { * Checks if the argument is a Sound * * @param x input to be checked - * @return true if x is a Sound, false otherwise + * @returns true if x is a Sound, false otherwise * @example is_sound(make_sound(t => 0, 2)); // Returns true */ export function is_sound(x: unknown): x is Sound { @@ -363,7 +363,7 @@ export function is_sound(x: unknown): x is Sound { * given in seconds. * * @param wave the wave function to play, starting at 0 - * @return the resulting Sound + * @returns the resulting Sound * @example play_wave(t => math_sin(t * 3000), 5); */ export function play_wave(wave: Wave, duration: number): Sound { @@ -378,7 +378,7 @@ export function play_wave(wave: Wave, duration: number): Sound { * on top of any Sounds that are currently playing. * * @param sound the Sound to play - * @return the given Sound + * @returns the given Sound * @example play(sine_sound(440, 5)); */ export function play(sound: Sound): Sound { @@ -459,7 +459,7 @@ export function stop(): void { * Makes a noise Sound with given duration * * @param duration the duration of the noise sound - * @return resulting noise Sound + * @returns resulting noise Sound * @example noise_sound(5); * @category Primitive */ @@ -472,7 +472,7 @@ export function noise_sound(duration: number): Sound { * Makes a silence Sound with given duration * * @param duration the duration of the silence Sound - * @return resulting silence Sound + * @returns resulting silence Sound * @example silence_sound(5); * @category Primitive */ @@ -486,7 +486,7 @@ export function silence_sound(duration: number): Sound { * * @param freq the frequency of the sine wave Sound * @param duration the duration of the sine wave Sound - * @return resulting sine wave Sound + * @returns resulting sine wave Sound * @example sine_sound(440, 5); * @category Primitive */ @@ -500,7 +500,7 @@ export function sine_sound(freq: number, duration: number): Sound { * * @param f the frequency of the square wave Sound * @param duration the duration of the square wave Sound - * @return resulting square wave Sound + * @returns resulting square wave Sound * @example square_sound(440, 5); * @category Primitive */ @@ -524,7 +524,7 @@ export function square_sound(f: number, duration: number): Sound { * * @param freq the frequency of the triangle wave Sound * @param duration the duration of the triangle wave Sound - * @return resulting triangle wave Sound + * @returns resulting triangle wave Sound * @example triangle_sound(440, 5); * @category Primitive */ @@ -550,7 +550,7 @@ export function triangle_sound(freq: number, duration: number): Sound { * * @param freq the frequency of the sawtooth wave Sound * @param duration the duration of the sawtooth wave Sound - * @return resulting sawtooth wave Sound + * @returns resulting sawtooth wave Sound * @example sawtooth_sound(440, 5); * @category Primitive */ @@ -578,7 +578,7 @@ export function sawtooth_sound(freq: number, duration: number): Sound { * so on. The effect is that the Sounds in the list are joined end-to-end * * @param list_of_sounds given list of Sounds - * @return the combined Sound + * @returns the combined Sound * @example consecutively(list(sine_sound(200, 2), sine_sound(400, 3))); */ export function consecutively(list_of_sounds: List): Sound { @@ -601,7 +601,7 @@ export function consecutively(list_of_sounds: List): Sound { * and then divided by the length of the list. * * @param list_of_sounds given list of Sounds - * @return the combined Sound + * @returns the combined Sound * @example simultaneously(list(sine_sound(200, 2), sine_sound(400, 3))) */ export function simultaneously(list_of_sounds: List): Sound { @@ -648,7 +648,7 @@ export function simultaneously(list_of_sounds: List): Sound { * @param decay_ratio proportion of Sound decay phase * @param sustain_level sustain level between 0 and 1 * @param release_ratio proportion of Sound in release phase - * @return Envelope a function from Sound to Sound + * @returns Envelope a function from Sound to Sound * @example adsr(0.2, 0.3, 0.3, 0.1)(sound); */ export function adsr( @@ -699,7 +699,7 @@ export function adsr( * @param base_frequency frequency of the first harmonic * @param duration duration of the produced Sound, in seconds * @param envelopes – list of envelopes, which are functions from Sound to Sound - * @return Sound resulting Sound + * @returns Sound resulting Sound * @example stacking_adsr(sine_sound, 300, 5, list(adsr(0.1, 0.3, 0.2, 0.5), adsr(0.2, 0.5, 0.6, 0.1), adsr(0.3, 0.1, 0.7, 0.3))); */ export function stacking_adsr( @@ -733,7 +733,7 @@ export function stacking_adsr( * @param freq the frequency of the sine wave to be modulated * @param duration the duration of the output Sound * @param amount the amount of modulation to apply to the carrier sine wave - * @return function which takes in a Sound and returns a Sound + * @returns function which takes in a Sound and returns a Sound * @example phase_mod(440, 5, 1)(sine_sound(220, 5)); */ export function phase_mod( @@ -757,7 +757,7 @@ export function phase_mod( * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting bell Sound with given pitch and duration + * @returns Sound resulting bell Sound with given pitch and duration * @example bell(40, 1); * @category Instrument */ @@ -780,7 +780,7 @@ export function bell(note: number, duration: number): Sound { * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting cello Sound with given pitch and duration + * @returns Sound resulting cello Sound with given pitch and duration * @example cello(36, 5); * @category Instrument */ @@ -798,7 +798,7 @@ export function cello(note: number, duration: number): Sound { * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting piano Sound with given pitch and duration + * @returns Sound resulting piano Sound with given pitch and duration * @example piano(48, 5); * @category Instrument * @@ -817,7 +817,7 @@ export function piano(note: number, duration: number): Sound { * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting trombone Sound with given pitch and duration + * @returns Sound resulting trombone Sound with given pitch and duration * @example trombone(60, 2); * @category Instrument */ @@ -835,7 +835,7 @@ export function trombone(note: number, duration: number): Sound { * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting violin Sound with given pitch and duration + * @returns Sound resulting violin Sound with given pitch and duration * @example violin(53, 4); * @category Instrument */ diff --git a/src/bundles/sound/src/play_in_tab.ts b/src/bundles/sound/src/play_in_tab.ts index 85e39745cd..a55aa04fb1 100644 --- a/src/bundles/sound/src/play_in_tab.ts +++ b/src/bundles/sound/src/play_in_tab.ts @@ -11,7 +11,7 @@ context.moduleContexts.sound.state = { audioPlayed }; * in a Source Academy tab. * * @param sound the Sound to play - * @return the given Sound + * @returns the given Sound * @example play_in_tab(sine_sound(440, 5)); */ diff --git a/src/bundles/stereo_sound/src/functions.ts b/src/bundles/stereo_sound/src/functions.ts index cfa855776d..c8c193c3dd 100644 --- a/src/bundles/stereo_sound/src/functions.ts +++ b/src/bundles/stereo_sound/src/functions.ts @@ -192,7 +192,7 @@ export function record(buffer: number): () => () => Sound { * play(promise()); * @param duration duration in seconds * @param buffer pause before recording, in seconds - * @return promise: nullary function which returns the recorded sound + * @returns promise: nullary function which returns the recorded sound */ export function record_for(duration: number, buffer: number): () => Sound { recorded_sound = undefined; @@ -253,7 +253,7 @@ function validateWave(func_name: string, wave: unknown, lr?: 'left' | 'right'): * @param left_wave wave function of the left channel of the Sound * @param right_wave wave function of the right channel of the Sound * @param duration duration of the Sound - * @return resulting stereo Sound + * @returns resulting stereo Sound * @example const s = make_stereo_sound(t => math_sin(2 * math_PI * 440 * t), t => math_sin(2 * math_PI * 300 * t), 5); */ export function make_stereo_sound( @@ -282,7 +282,7 @@ export function make_stereo_sound( * * @param wave wave function of the Sound * @param duration duration of the Sound - * @return Sound with the given `wave` function for both channels and `duration` as duration + * @returns Sound with the given `wave` function for both channels and `duration` as duration * @example const s = make_sound(t => math_sin(2 * math_PI * 440 * t), 5); */ export function make_sound(wave: Wave, duration: number): Sound { @@ -302,7 +302,7 @@ export function make_sound(wave: Wave, duration: number): Sound { * Accesses the left wave function of a given Sound. * * @param sound given Sound - * @return the wave function of the Sound + * @returns the wave function of the Sound * @example get_wave(make_sound(t => math_sin(2 * math_PI * 440 * t), 5)); // Returns t => math_sin(2 * math_PI * 440 * t) */ export function get_left_wave(sound: Sound): Wave { @@ -313,7 +313,7 @@ export function get_left_wave(sound: Sound): Wave { * Accesses the left wave function of a given Sound. * * @param sound given Sound - * @return the wave function of the Sound + * @returns the wave function of the Sound * @example get_wave(make_sound(t => math_sin(2 * math_PI * 440 * t), 5)); // Returns t => math_sin(2 * math_PI * 440 * t) */ export function get_right_wave(sound: Sound): Wave { @@ -324,7 +324,7 @@ export function get_right_wave(sound: Sound): Wave { * Accesses the duration of a given Sound. * * @param sound given Sound - * @return the duration of the Sound + * @returns the duration of the Sound * @example get_duration(make_sound(t => math_sin(2 * math_PI * 440 * t), 5)); // Returns 5 */ export function get_duration(sound: Sound): number { @@ -335,7 +335,7 @@ export function get_duration(sound: Sound): number { * Checks if the argument is a Sound * * @param x input to be checked - * @return true if x is a Sound, false otherwise + * @returns true if x is a Sound, false otherwise * @example is_sound(make_sound(t => 0, 2)); // Returns true */ export function is_sound(x: unknown): x is Sound { @@ -352,7 +352,7 @@ export function is_sound(x: unknown): x is Sound { * given in seconds. * * @param wave the wave function to play, starting at 0 - * @return the given Sound + * @returns the given Sound * @example play_wave(t => math_sin(t * 3000), 5); */ export function play_wave(wave: Wave, duration: number): Sound { @@ -368,7 +368,7 @@ export function play_wave(wave: Wave, duration: number): Sound { * * @param left_wave the wave function to play on the left channel, starting at 0 * @param right_wave the wave function to play on the right channel, starting at 0 - * @return the given Sound + * @returns the given Sound * @example play_waves(t => math_sin(t * 3000), t => math_sin(t * 6000), 5); */ export function play_waves( @@ -389,7 +389,7 @@ export function play_waves( * in a Source Academy tab. * * @param sound the Sound to play - * @return the given Sound + * @returns the given Sound * @example play_in_tab(sine_sound(440, 5)); */ export function play_in_tab(sound: Sound): Sound { @@ -401,7 +401,7 @@ export function play_in_tab(sound: Sound): Sound { throw new Error(`${play_in_tab.name}: audio system still playing previous sound`); } - const duration = get_duration(sound) ; + const duration = get_duration(sound); if (duration < 0) { throw new Error(`${play_in_tab.name}: duration of sound is negative`); } else if (duration === 0) { @@ -489,7 +489,7 @@ export function play_in_tab(sound: Sound): Sound { * on top of any Sounds that are currently playing. * * @param sound the Sound to play - * @return the given Sound + * @returns the given Sound * @example play(sine_sound(440, 5)); */ export function play(sound: Sound): Sound { @@ -604,7 +604,7 @@ export function stop(): void { * resulting in an effectively mono sound. * * @param sound the sound to be squashed - * @return a new sound with the left and right channels averaged + * @returns a new sound with the left and right channels averaged */ export function squash(sound: Sound): Sound { const left = get_left_wave(sound); @@ -618,7 +618,7 @@ export function squash(sound: Sound): Sound { * An amount of `-1` is a hard left pan, `0` is balanced, `1` is hard right pan. * * @param amount the pan amount, from -1 to 1 - * @return a Sound Transformer that pans a Sound + * @returns a Sound Transformer that pans a Sound */ export function pan(amount: number): SoundTransformer { return (sound) => { @@ -644,7 +644,7 @@ export function pan(amount: number): SoundTransformer { * `-1` is a hard left pan, `0` is balanced, `1` is hard right pan. * * @param modulator the Sound used to modulate the pan of another sound - * @return a Sound Transformer that pans a Sound + * @returns a Sound Transformer that pans a Sound */ export function pan_mod(modulator: Sound): SoundTransformer { const amount = (t: number) => { @@ -673,7 +673,7 @@ export function pan_mod(modulator: Sound): SoundTransformer { * Makes a noise sound with given duration * * @param duration the duration of the noise sound - * @return resulting noise sound + * @returns resulting noise sound * @example noise_sound(5); */ export function noise_sound(duration: number): Sound { @@ -685,7 +685,7 @@ export function noise_sound(duration: number): Sound { * Makes a silence sound with given duration * * @param duration the duration of the silence sound - * @return resulting silence sound + * @returns resulting silence sound * @example silence_sound(5); */ export function silence_sound(duration: number): Sound { @@ -698,7 +698,7 @@ export function silence_sound(duration: number): Sound { * * @param freq the frequency of the sine wave sound * @param duration the duration of the sine wave sound - * @return resulting sine wave sound + * @returns resulting sine wave sound * @example sine_sound(440, 5); */ export function sine_sound(freq: number, duration: number): Sound { @@ -711,7 +711,7 @@ export function sine_sound(freq: number, duration: number): Sound { * * @param f the frequency of the square wave sound * @param duration the duration of the square wave sound - * @return resulting square wave sound + * @returns resulting square wave sound * @example square_sound(440, 5); */ export function square_sound(f: number, duration: number): Sound { @@ -734,7 +734,7 @@ export function square_sound(f: number, duration: number): Sound { * * @param freq the frequency of the triangle wave sound * @param duration the duration of the triangle wave sound - * @return resulting triangle wave sound + * @returns resulting triangle wave sound * @example triangle_sound(440, 5); */ export function triangle_sound(freq: number, duration: number): Sound { @@ -759,7 +759,7 @@ export function triangle_sound(freq: number, duration: number): Sound { * * @param freq the frequency of the sawtooth wave sound * @param duration the duration of the sawtooth wave sound - * @return resulting sawtooth wave sound + * @returns resulting sawtooth wave sound * @example sawtooth_sound(440, 5); */ export function sawtooth_sound(freq: number, duration: number): Sound { @@ -786,7 +786,7 @@ export function sawtooth_sound(freq: number, duration: number): Sound { * so on. The effect is that the sounds in the list are joined end-to-end * * @param list_of_sounds given list of sounds - * @return the combined Sound + * @returns the combined Sound * @example consecutively(list(sine_sound(200, 2), sine_sound(400, 3))); */ export function consecutively(list_of_sounds: List): Sound { @@ -812,7 +812,7 @@ export function consecutively(list_of_sounds: List): Sound { * and then divided by the length of the list. * * @param list_of_sounds given list of sounds - * @return the combined Sound + * @returns the combined Sound * @example simultaneously(list(sine_sound(200, 2), sine_sound(400, 3))) */ export function simultaneously(list_of_sounds: List): Sound { @@ -853,7 +853,7 @@ export function simultaneously(list_of_sounds: List): Sound { * @param decay_ratio proportion of Sound decay phase * @param sustain_level sustain level between 0 and 1 * @param release_ratio proportion of Sound in release phase - * @return Envelope a function from Sound to Sound + * @returns Envelope a function from Sound to Sound * @example adsr(0.2, 0.3, 0.3, 0.1)(sound); */ export function adsr( @@ -909,7 +909,7 @@ export function adsr( * @param base_frequency frequency of the first harmonic * @param duration duration of the produced Sound, in seconds * @param envelopes – list of envelopes, which are functions from Sound to Sound - * @return Sound resulting Sound + * @returns Sound resulting Sound * @example stacking_adsr(sine_sound, 300, 5, list(adsr(0.1, 0.3, 0.2, 0.5), adsr(0.2, 0.5, 0.6, 0.1), adsr(0.3, 0.1, 0.7, 0.3))); */ export function stacking_adsr( @@ -943,7 +943,7 @@ export function stacking_adsr( * @param freq the frequency of the sine wave to be modulated * @param duration the duration of the output soud * @param amount the amount of modulation to apply to the carrier sine wave - * @return function which takes in a Sound and returns a Sound + * @returns function which takes in a Sound and returns a Sound * @example phase_mod(440, 5, 1)(sine_sound(220, 5)); */ export function phase_mod( @@ -970,7 +970,7 @@ export function phase_mod( * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting bell Sound with given pitch and duration + * @returns Sound resulting bell Sound with given pitch and duration * @example bell(40, 1); */ export function bell(note: number, duration: number): Sound { @@ -992,7 +992,7 @@ export function bell(note: number, duration: number): Sound { * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting cello Sound with given pitch and duration + * @returns Sound resulting cello Sound with given pitch and duration * @example cello(36, 5); */ export function cello(note: number, duration: number): Sound { @@ -1009,7 +1009,7 @@ export function cello(note: number, duration: number): Sound { * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting piano Sound with given pitch and duration + * @returns Sound resulting piano Sound with given pitch and duration * @example piano(48, 5); */ export function piano(note: number, duration: number): Sound { @@ -1026,7 +1026,7 @@ export function piano(note: number, duration: number): Sound { * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting trombone Sound with given pitch and duration + * @returns Sound resulting trombone Sound with given pitch and duration * @example trombone(60, 2); */ export function trombone(note: number, duration: number): Sound { @@ -1043,7 +1043,7 @@ export function trombone(note: number, duration: number): Sound { * a given note for a given duration * @param note MIDI note * @param duration duration in seconds - * @return Sound resulting violin Sound with given pitch and duration + * @returns Sound resulting violin Sound with given pitch and duration * @example violin(53, 4); */ export function violin(note: number, duration: number): Sound { diff --git a/src/bundles/unity_academy/src/functions.ts b/src/bundles/unity_academy/src/functions.ts index 728f5e54ce..531cd7a5fb 100644 --- a/src/bundles/unity_academy/src/functions.ts +++ b/src/bundles/unity_academy/src/functions.ts @@ -88,7 +88,7 @@ function checkParameterType(parameter: any, expectedType: string, numberAllowInf * * @param first The first GameObject identifier to compare with. * @param second The second GameObject identifier to compare with. - * @return Returns true if the two GameObject identifiers refers to the same GameObject and false otherwise. + * @returns Returns true if the two GameObject identifiers refers to the same GameObject and false otherwise. * @category Common */ export function same_gameobject(first: GameObjectIdentifier, second: GameObjectIdentifier): boolean { @@ -143,7 +143,7 @@ export function set_update(gameObjectIdentifier: GameObjectIdentifier, updateFun * Available Prefab Information: Click Here * * @param prefab_name The prefab name - * @return the identifier of the newly created GameObject + * @returns the identifier of the newly created GameObject * * @category Common * @category Outside Lifecycle @@ -166,7 +166,7 @@ export function instantiate(prefab_name: string): GameObjectIdentifier { * **2D mode only** * * @param sourceImageUrl The image url for the sprite. - * @return the identifier of the newly created GameObject + * @returns the identifier of the newly created GameObject * * @category Common * @category Outside Lifecycle @@ -186,7 +186,7 @@ export function instantiate_sprite(sourceImageUrl: string) { * * You may use the empty GameObject to run some general game management code or use the position of the empty GameObject to represent a point in the scene that the rest of your codes can access and utilize. * - * @return the identifier of the newly created GameObject + * @returns the identifier of the newly created GameObject * * @category Common * @category Outside Lifecycle @@ -212,7 +212,7 @@ export function instantiate_empty(): GameObjectIdentifier { * By assigning the above code to a GameObject with `set_update`, that GameObject will move in a constant speed for about 3 units per second along world +Z axis. * * For more information, see https://docs.unity3d.com/ScriptReference/Time-deltaTime.html - * @return the delta time value in decimal + * @returns the delta time value in decimal * * @category Common */ @@ -242,7 +242,7 @@ export function destroy(gameObjectIdentifier: GameObjectIdentifier): void { /** * Returns the world position of a given GameObject * @param gameObjectIdentifier The identifier for the GameObject that you want to get position for. - * @return The position represented in a Vector3. + * @returns The position represented in a Vector3. * * @category Transform */ @@ -271,7 +271,7 @@ export function set_position(gameObjectIdentifier: GameObjectIdentifier, positio /** * Returns the world Euler angle rotation of a given GameObject * @param gameObjectIdentifier The identifier for the GameObject that you want to get rotation for. - * @return The Euler angle rotation represented in a Vector3. + * @returns The Euler angle rotation represented in a Vector3. * * @category Transform */ @@ -302,7 +302,7 @@ export function set_rotation_euler(gameObjectIdentifier: GameObjectIdentifier, r * * By default the scale of a GameObject is (1, 1, 1) * @param gameObjectIdentifier The identifier for the GameObject that you want to get scale for. - * @return The scale represented in a Vector3. + * @returns The scale represented in a Vector3. * * @category Transform */ @@ -468,7 +468,7 @@ export function look_at(gameObjectIdentifier: GameObjectIdentifier, position: Ve * @param gameObjectIdentifier_B The identifier for the second GameObject * * - * @return The value of the distance between these two GameObjects + * @returns The value of the distance between these two GameObjects * @category Transform */ export function gameobject_distance(gameObjectIdentifier_A: GameObjectIdentifier, gameObjectIdentifier_B: GameObjectIdentifier): number { @@ -495,7 +495,7 @@ function checkKeyCodeValidityAndToLowerCase(keyCode: string): string { * When user presses a key on the keyboard or mouse button, this function will return true only at the frame when the key is just pressed down and return false afterwards. * * For more information, see https://docs.unity3d.com/ScriptReference/Input.GetKeyDown.html - * @return A boolean value equivalent to Input.GetKeyDown(keyCode) in Unity. + * @returns A boolean value equivalent to Input.GetKeyDown(keyCode) in Unity. * * @param keyCode The key to detact input for. * @category Input @@ -511,7 +511,7 @@ export function get_key_down(keyCode: string): boolean { * When user presses a key on the keyboard or mouse button, this function will return true in every frame that the key is still being pressed and false otherwise. * * For more information, see https://docs.unity3d.com/ScriptReference/Input.GetKey.html - * @return A boolean value equivalent to Input.GetKey(keyCode) in Unity. + * @returns A boolean value equivalent to Input.GetKey(keyCode) in Unity. * * @param keyCode The key to detact input for. * @category Input @@ -528,7 +528,7 @@ export function get_key(keyCode: string): boolean { * When user releases a pressed key on the keyboard or mouse button, this function will return true only at the frame when the key is just released up and return false otherwise. * * For more information, see https://docs.unity3d.com/ScriptReference/Input.GetKeyUp.html - * @return A boolean value equivalent to Input.GetKeyUp(keyCode) in Unity. + * @returns A boolean value equivalent to Input.GetKeyUp(keyCode) in Unity. * * @param keyCode The key to detact input for. * @category Input @@ -585,7 +585,7 @@ export function apply_rigidbody(gameObjectIdentifier: GameObjectIdentifier): voi * Usage of all physics functions under the Physics - Rigidbody category requires calling `apply_rigidbody` first on the applied game objects. * * @param gameObjectIdentifier The identifier for the GameObject that you want to get mass for. - * @return The mass of the rigidbody attached on the GameObject + * @returns The mass of the rigidbody attached on the GameObject * @category Physics - Rigidbody */ export function get_mass(gameObjectIdentifier: GameObjectIdentifier): number { @@ -618,7 +618,7 @@ export function set_mass(gameObjectIdentifier: GameObjectIdentifier, mass: numbe * Usage of all physics functions under the Physics - Rigidbody category requires calling `apply_rigidbody` first on the applied game objects. * * @param gameObjectIdentifier The identifier for the GameObject that you want to get velocity for. - * @return the velocity at this moment represented in a Vector3. + * @returns the velocity at this moment represented in a Vector3. * @category Physics - Rigidbody */ export function get_velocity(gameObjectIdentifier: GameObjectIdentifier): Vector3 { @@ -653,7 +653,7 @@ export function set_velocity(gameObjectIdentifier: GameObjectIdentifier, velocit * **2D Mode Special: **In 2D mode there is no angular velocity on X nor Y axis, so in the X and Y values in the returned Vector3 will always be zero. * * @param gameObjectIdentifier The identifier for the GameObject that you want to get angular velocity for. - * @return the angular velocity at this moment represented in a Vector3. + * @returns the angular velocity at this moment represented in a Vector3. * @category Physics - Rigidbody */ export function get_angular_velocity(gameObjectIdentifier: GameObjectIdentifier): Vector3 { @@ -938,7 +938,7 @@ export function gui_button(text: string, x: number, y: number, width: number, he * * **If default main camera controllers are disabled (you have called `request_for_main_camera_control`), then the following target GameObject is useless.** * - * @return The GameObject idenfitier for the main camera following target GameObject. + * @returns The GameObject idenfitier for the main camera following target GameObject. * @category Camera * @category Outside Lifecycle */ @@ -955,7 +955,7 @@ export function get_main_camera_following_target(): GameObjectIdentifier { * * This function is for totally customizing the position and rotation of the main camera. If you'd like to simplify the camera controlling with the help of the default camera controllers in Unity Academy, please consider use `get_main_camera_following_target` function. * - * @return The GameObject identifier that can directly be used to control the main camera's position and rotation + * @returns The GameObject identifier that can directly be used to control the main camera's position and rotation * @category Camera * @category Outside Lifecycle */ @@ -988,7 +988,7 @@ export function set_custom_prop(gameObjectIdentifier: GameObjectIdentifier, prop * @param gameObjectIdentifier The identifier for the GameObject that you want to get the custom property on. * @param propName The name (a string) of the custom property * - * @return The value of the custom property with the given name on the given GameObject. If the property value is not set, this function will return `undefined`. + * @returns The value of the custom property with the given name on the given GameObject. If the property value is not set, this function will return `undefined`. * * @category Common */ @@ -1006,7 +1006,7 @@ export function get_custom_prop(gameObjectIdentifier: GameObjectIdentifier, prop * @param y The y component of the new vector * @param z The z component of the new vector * - * @return The 3D vector (x, y, z) + * @returns The 3D vector (x, y, z) * * @category Maths */ @@ -1021,7 +1021,7 @@ export function vector3(x: number, y: number, z: number): Vector3 { * Get the X component of a 3D vector * @param vector The 3D vector * - * @return The X component of the given vector + * @returns The X component of the given vector * * @category Maths */ @@ -1034,7 +1034,7 @@ export function get_x(vector: Vector3): number { * Get the Y component of a 3D vector * @param vector The 3D vector * - * @return The Y component of the given vector + * @returns The Y component of the given vector * * @category Maths */ @@ -1047,7 +1047,7 @@ export function get_y(vector: Vector3): number { * Get the Z component of a 3D vector * @param vector The 3D vector * - * @return The Z component of the given vector + * @returns The Z component of the given vector * * @category Maths */ @@ -1060,7 +1060,7 @@ export function get_z(vector: Vector3): number { * Scales a 3D vector with the given factor. * @param vector The original vector * @param factor The scaling factor. - * @return The scaled vector + * @returns The scaled vector * * @category Maths */ @@ -1074,7 +1074,7 @@ export function scale_vector(vector: Vector3, factor: number): Vector3 { * Add two 3D vectors together. * @param vectorA The first vector * @param vectorB The second vector. - * @return The sum of the two vectors + * @returns The sum of the two vectors * * @category Maths */ @@ -1088,7 +1088,7 @@ export function add_vectors(vectorA: Vector3, vectorB: Vector3): Vector3 { * Calcuate the vector difference between two vectors (vectorA - vectorB). * @param vectorA The minuend vector. * @param vectorB The subtrahend vector. - * @return The result for vectorA - vectorB + * @returns The result for vectorA - vectorB * * @category Maths */ @@ -1102,7 +1102,7 @@ export function vector_difference(vectorA: Vector3, vectorB: Vector3): Vector3 { * Calcuate the dot product of two 3D vectors. * @param vectorA The first vector * @param vectorB The second vector. - * @return The dot product + * @returns The dot product * * @category Maths */ @@ -1116,7 +1116,7 @@ export function dot(vectorA: Vector3, vectorB: Vector3): number { * Calcuate the cross product of two 3D vectors. * @param vectorA The first vector * @param vectorB The second vector. - * @return The cross product + * @returns The cross product * * @category Maths */ @@ -1129,7 +1129,7 @@ export function cross(vectorA: Vector3, vectorB: Vector3): Vector3 { /** * Normalize a vector. The returned vector will have the same direction as the original vector but have a magnitude of 1. * @param vector The original vector - * @return The normalized vector. This function will return a zero vector if the original vector is a zero vector. + * @returns The normalized vector. This function will return a zero vector if the original vector is a zero vector. * * @category Maths */ @@ -1141,7 +1141,7 @@ export function normalize(vector: Vector3): Vector3 { /** * Calcuate the magnitude of a vector * @param vector The vector - * @return The magnitude of the vector + * @returns The magnitude of the vector * * @category Maths */ @@ -1152,7 +1152,7 @@ export function magnitude(vector: Vector3): number { /** * Get the zero vector - * @return The zero vector + * @returns The zero vector * * @category Maths */ @@ -1166,7 +1166,7 @@ export function zero_vector(): Vector3 { * @param pointA The first point * @param pointB The second point * - * @return The value of the distance between the two points + * @returns The value of the distance between the two points * * @category Maths */ @@ -1226,7 +1226,7 @@ export function load_audio_clip_wav(audioUrl: string): AudioClipIdentifier { * So you can still use the audio source as a regular GameObject, like setting its position with `set_position`, using `set_start` and `set_update` to set its `Start` and `Update` funtions, etc. * * @param audioClip the audio clip that you want to use for this audio source - * @return the identifier of the newly created GameObject + * @returns the identifier of the newly created GameObject * * @category Sound / Audio * @category Outside Lifecycle From 1f12e2069075c26a7eeb3d7350a64b15fa208ce0 Mon Sep 17 00:00:00 2001 From: Lee Yi Date: Tue, 23 Dec 2025 07:10:50 -0500 Subject: [PATCH 02/71] Add validation for example tags and hide type guards in generated docs --- lib/buildtools/package.json | 1 + lib/buildtools/src/build/docs/json.ts | 45 +++++++++++++++++++++++- lib/buildtools/src/build/docs/typedoc.ts | 17 +++++++-- yarn.lock | 10 ++++++ 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/lib/buildtools/package.json b/lib/buildtools/package.json index 15d991d8be..d569ddc10b 100644 --- a/lib/buildtools/package.json +++ b/lib/buildtools/package.json @@ -22,6 +22,7 @@ "@vitest/browser-playwright": "^4.0.4", "@vitest/coverage-v8": "^4.0.4", "acorn": "^8.8.1", + "acorn-typescript": "^1.4.13", "astring": "^1.8.6", "chalk": "^5.0.1", "commander": "^14.0.0", diff --git a/lib/buildtools/src/build/docs/json.ts b/lib/buildtools/src/build/docs/json.ts index 03c6e5276b..b447773cb1 100644 --- a/lib/buildtools/src/build/docs/json.ts +++ b/lib/buildtools/src/build/docs/json.ts @@ -2,6 +2,8 @@ import fs from 'fs/promises'; import pathlib from 'path'; import type { BuildResult, ResolvedBundle } from '@sourceacademy/modules-repotools/types'; +import { Parser } from 'acorn'; +import { tsPlugin } from 'acorn-typescript'; import * as td from 'typedoc'; import drawdown from './drawdown.js'; @@ -33,6 +35,34 @@ export interface ParserError { export type ParserResult = ParserError | ParserSuccess; +const markdownRegex = /^```[jt]sx?([\s\S]*)```\s*$/; + +/** + * Checks the declaration's comment for `@example` tags and validates their contents + * to make sure that they are valid Javascript + * + * @returns True if there is an example that doesn't validate, false otherwise + */ +function getInvalidExamples(parts: td.CommentTag[]): string[] { + // @ts-expect-error Idk what the type error here is + const parser = Parser.extend(tsPlugin()); + + return parts.flatMap(part => part.content.map(content => { + if (content.kind !== 'code') return false; + + const match = markdownRegex.exec(content.text); + const text = match ? match[1] : content.text; + + try { + parser.parse(text, { ecmaVersion: 6, sourceType: 'module' }); + return false; + } catch { + return text; + } + })) + .filter(x => x !== false); +} + const typeToName = (type: td.SomeType) => type.stringify(td.TypeContext.none); export const parsers: { [K in td.ReflectionKind]?: (obj: td.DeclarationReflection) => ParserResult @@ -62,6 +92,10 @@ export const parsers: { if (signature.comment) { description = drawdown(signature.comment.summary.map(({ text }) => text) .join('')); + const invalidExamples = getInvalidExamples(signature.comment.blockTags); + invalidExamples.forEach(example => { + warnings.push(`${obj.name} has an example tag that did not validate: ${example}`); + }); } else { description = '

No description available

'; } @@ -80,10 +114,19 @@ export const parsers: { }; }, [td.ReflectionKind.Variable](obj) { + const warnings: string[] = []; + if (obj.signatures) { + warnings.push(`${obj.name} is typed as a Variable, but function signatures were detected. Did you forget a @function tag?`); + } + let description: string; if (obj.comment) { description = drawdown(obj.comment.summary.map(({ text }) => text) .join('')); + const invalidExamples = getInvalidExamples(obj.comment.blockTags); + invalidExamples.forEach(example => { + warnings.push(`${obj.name} has an example tag that did not validate: ${example}`); + }); } else { description = '

No description available

'; } @@ -101,7 +144,7 @@ export const parsers: { description, type: typeToName(obj.type) }, - warnings: [] + warnings }; } }; diff --git a/lib/buildtools/src/build/docs/typedoc.ts b/lib/buildtools/src/build/docs/typedoc.ts index 14f3880da4..820147eab8 100644 --- a/lib/buildtools/src/build/docs/typedoc.ts +++ b/lib/buildtools/src/build/docs/typedoc.ts @@ -16,16 +16,29 @@ const typedocPackageOptions: td.Configuration.TypeDocOptions = { /** * Initialize Typedoc to build the JSON documentation for each bundle */ -export function initTypedocForJson(bundle: ResolvedBundle, logLevel: td.LogLevel) { +export async function initTypedocForJson(bundle: ResolvedBundle, logLevel: td.LogLevel) { // TypeDoc expects POSIX paths const directoryAsPosix = bundle.directory.replace(/\\/g, '/'); - return td.Application.bootstrapWithPlugins({ + const app = await td.Application.bootstrapWithPlugins({ ...typedocPackageOptions, name: bundle.name, logLevel, entryPoints: [`${directoryAsPosix}/src/index.ts`], tsconfig: `${directoryAsPosix}/tsconfig.json`, }); + + app.converter.on(td.Converter.EVENT_CREATE_SIGNATURE, (ctx, signature) => { + // Make sure that type guards get replaced with the appropriate intrinsic types + if (signature.type instanceof td.PredicateType) { + if (signature.type.asserts) { + signature.type = new td.IntrinsicType('void'); + } else { + signature.type = new td.IntrinsicType('boolean'); + } + } + }); + + return app; } /** diff --git a/yarn.lock b/yarn.lock index da500ac1aa..1033889243 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4540,6 +4540,7 @@ __metadata: "@vitest/browser-playwright": "npm:^4.0.4" "@vitest/coverage-v8": "npm:^4.0.4" acorn: "npm:^8.8.1" + acorn-typescript: "npm:^1.4.13" astring: "npm:^1.8.6" chalk: "npm:^5.0.1" commander: "npm:^14.0.0" @@ -6638,6 +6639,15 @@ __metadata: languageName: node linkType: hard +"acorn-typescript@npm:^1.4.13": + version: 1.4.13 + resolution: "acorn-typescript@npm:1.4.13" + peerDependencies: + acorn: ">=8.9.0" + checksum: 10c0/f2f17cf03379d63beeb007f0feea02cebbd9af261f6b5619ea7345b177bd7a5f99752927cbf652baa3fc97962ae4561592093ab0a1c3e00ca4f354ba23c557ae + languageName: node + linkType: hard + "acorn-walk@npm:^8.0.0": version: 8.3.4 resolution: "acorn-walk@npm:8.3.4" From 337042659a61f23bfc9e764fe89122ec88c1d47a Mon Sep 17 00:00:00 2001 From: Lee Yi Date: Tue, 23 Dec 2025 07:11:11 -0500 Subject: [PATCH 03/71] Update docs about documentation --- .../modules/2-bundle/4-conventions/1-basic.md | 54 ++++++++++++++ .../5-documentation/1-cadet/1-cadet.md | 66 +++++++++++++++++- .../5-documentation/1-cadet/docExample.png | Bin 0 -> 26317 bytes .../1-cadet/wrongDocExample.png | Bin 0 -> 28764 bytes 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 docs/src/modules/2-bundle/5-documentation/1-cadet/docExample.png create mode 100644 docs/src/modules/2-bundle/5-documentation/1-cadet/wrongDocExample.png diff --git a/docs/src/modules/2-bundle/4-conventions/1-basic.md b/docs/src/modules/2-bundle/4-conventions/1-basic.md index fcb48d0794..ea52fb94d9 100644 --- a/docs/src/modules/2-bundle/4-conventions/1-basic.md +++ b/docs/src/modules/2-bundle/4-conventions/1-basic.md @@ -2,6 +2,8 @@ This section contains some conventions to follow when writing your bundle. +[[toc]] + ## 1. Cadet facing functions should not have default or rest parameters The function signature below takes in two booleans, the second of which is optional. This is not supported for Module functions in Source, but is fine if your function @@ -211,3 +213,55 @@ Note that not every export from `js-slang` is currently supported. Below is the - `js-slang/dist/utils/stringify` - `js-slang/dist/parser/parser` - `js-slang/dist/cse-machine/interpreter` + +## 6. Cadet Facing Type Guard Conventions + +A [type guard](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) is a function that checks if the provided object has the desired type. +In Typescript, there are two kinds of type guards. Cadet facing type guards should favour the boolean returning form and should begin with the +`is` prefix. Also, the parameter the type guard validates should be of type `unknown`. + +Anywhere you use a boolean check followed by a type assertion: +```ts +// Simple boolean type guard +export function is_sound(obj: unknown): boolean { + return obj instanceof Sound; +} + +function play(obj: Sound) { + // Simple boolean check + if (!is_sound(obj)) return false; + + // followed by type assertion, since obj is still of type unknown + const sound = obj as Sound; + // ...implementatation details +} +``` + +you should replace with a type guard: +```ts +// Typescript boolean Type Guard +export function is_sound(obj: unknown): obj is Sound { + return obj instanceof Sound; +} + +function play(obj: Sound) { + // Check using a type guard + if (!is_sound(obj)) return false; + + // Type assertion is no longer required. Typescript knows that obj + // is a Sound here + + // ...implementatation details +} +``` + +Note that for simple checks (like `instanceof`), Typescript (later versions) is able to automatically infer when you are writing a type guard, +meaning that explicitly typing your type guard may be unnecessary. + +However, if the checks you need to perform are complex, Typescript might +only be able to narrow the return type of your type guard to `boolean`. In such a case you will have to write the return type explicitly. + +> [!TIP] Type Guards in Documentation +> Type guards have a specific syntax for their return types (e.g. `value is null`) that isn't Source compliant. +> These types get replaced with `boolean` when the documentation is generated, so you don't have to worry +> about type guard types appearing in your documentation. diff --git a/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md b/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md index a00b746c6a..3c04fdc613 100644 --- a/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md +++ b/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md @@ -131,7 +131,8 @@ export const draw_connected = createDrawFunction('none', 'lines', '2D', false); The export will now be correctly recognized as a function: ![](./drawFunc.png) -There is no automatic way to make this distinction, so it is up to the bundle authors to make sure that this convention is adhered to. +The buildtools are configured to emit a warning if a variable is detected to have function signatures but cannot automatically rectify +this problem. ### Variables/Constants @@ -195,6 +196,69 @@ This causes `type_map` to be removed from the documentation, even if it is expor > Bundle `type_map`s are supposed to be internal implementation details hidden from users. If you forget to apply a `@hidden` tag to > your bundle's type map export, the build tools will show a warning. +### Use of `@example` + +`@example` blocks allow the developer to provide code snippets that serve as examples for for how the function/variable is intended to be +used. Consider an example from the `midi` bundle below: + +```ts {10-13} +/** + * Converts a letter name to its corresponding MIDI note. + * The letter name is represented in standard pitch notation. + * Examples are "A5", "Db3", "C#7". + * Refer to this mapping from + * letter name to midi notes. + * + * @param note given letter name + * @return the corresponding midi note + * @example + * ``` + * letter_name_to_midi_note("C4"); // Returns 60 + * ``` + * @function + */ +export function letter_name_to_midi_note(note: NoteWithOctave): MIDINote {} +``` + +When the documentation is renderered, a code block is produced: + +![](./docExample.png) + +Note that your code examples should be surrounded in a Markdown code block (using the triple backticks ```` ``` ````). This will +help Typedoc figure out what content belongs to your code block. The language specifier is not required here as it is assumed that +your code examples are written in Typescript. + +::: details Why you should use a code block + +If you use an inline code example, Typedoc might include things in your example that you didn't mean to include. Consider +a modified version of the example above: + +```ts {10} +/** + * Converts a letter name to its corresponding MIDI note. + * The letter name is represented in standard pitch notation. + * Examples are "A5", "Db3", "C#7". + * Refer to this mapping from + * letter name to midi notes. + * + * @param note given letter name + * @return the corresponding midi note + * @example letter_name_to_midi_note("C4"); // Returns 60 + * @function + */ +export function letter_name_to_midi_note(note: NoteWithOctave): MIDINote {} +``` + +Typedoc ends up including the `@function` tag as part of the code block: + +![](./wrongDocExample.png) + +Using a code block makes it clear exactly what is intended to be part of your example code block. +::: + +During documentation generation, the code in your code block will be parsed by a Typescript parser to ensure that you have written +valid Typescript code. It will print a warning message if your example code doesn't produce syntactically valid Typescript. + ### Other Tags There are a variety of tags that Typedoc supports. This list can be found [here](https://typedoc.org/documents/Tags.html). When writing your documentation you should use these tags diff --git a/docs/src/modules/2-bundle/5-documentation/1-cadet/docExample.png b/docs/src/modules/2-bundle/5-documentation/1-cadet/docExample.png new file mode 100644 index 0000000000000000000000000000000000000000..21fc942850d2f9c6a07df184f4051360eb3a1c44 GIT binary patch literal 26317 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

Dw>)i+5~N`c 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 Date: Thu, 25 Dec 2025 21:18:22 +0800 Subject: [PATCH 04/71] Continue updating docs --- docs/src/buildtools/5-builders/2-docs.md | 32 ++- .../5-documentation/1-cadet/1-cadet.md | 10 +- docs/src/repotools/2-linting.md | 11 +- docs/src/repotools/6-docserver/1-overview.md | 24 +- docs/src/repotools/7-workflows/1-actions.md | 25 ++- .../repotools/7-workflows/2-pull-request.md | 20 +- docs/src/repotools/7-workflows/4-changes.md | 205 ++++++++++++++++++ 7 files changed, 317 insertions(+), 10 deletions(-) create mode 100644 docs/src/repotools/7-workflows/4-changes.md diff --git a/docs/src/buildtools/5-builders/2-docs.md b/docs/src/buildtools/5-builders/2-docs.md index d1820b91b4..64f53a7792 100644 --- a/docs/src/buildtools/5-builders/2-docs.md +++ b/docs/src/buildtools/5-builders/2-docs.md @@ -11,7 +11,7 @@ Firstly, the `buildtools build docs` is called on each bundle. This produces two 1. `build/jsons/[bundle_name].json`, which is the JSON documentation used by `js-slang` and the frontend 2. `docs.json`, which is JSON documentation format used by `typedoc` to generate the HTML documentation later -Second, `buildtools manifest` is called, which then takes the `docs.json` files from each bundle and uses the [`merge` entry point strategy](https://typedoc.org/documents/Options.Input.html#merge) to create the HTML +Second, `buildtools html` is called, which then takes the `docs.json` files from each bundle and uses the [`merge` entry point strategy](https://typedoc.org/documents/Options.Input.html#merge) to create the HTML documentation > [!NOTE] @@ -20,6 +20,36 @@ documentation This allows each bundle to have its own Typedoc option set. +## Custom Checks + +There are two important custom checks that our documentation generation must perform: + +### Typing Variables as Functions + +Because Typedoc no longer automatically considers function-like types as functions, developers must use the `@function` tag to allow +Typedoc to properly infer that a function-like variable should be documented as a function. + +When generating the documentation, we simply check if the corresponding item has been assigned a variable type while having function signatures. If this +is the case, then we print a warning advising the developer that they may have forgotten the `@function` tag. + +### Hiding Type Guards + +Typescript has a feature called type guards that allow the compiler to better narrow types, increasing the type safety of module code. + +When Typedoc encounters a type guard, it documents the return type of that type guard as is. + +```ts +export function is_boolean(obj: unknown): obj is boolean { + return typeof obj === 'boolean'; +} +``` + +The function above has its return type rendered as `obj is boolean`. However, this might confuse cadets as type guards are not a concept in Source, +and the return type as rendered also hides the fact that `is_boolean` returns a `boolean` and not some other special value. + +To remedy this, when generating the documentation for type guards, we simply replace the return type of the signature with `boolean` (or `void` if +it's an asserts guard). This modification is done on "conversion" by hooking into the `Converter.EVENT_CREATE_SIGNATURE` event. + ## HTML Generation It is not possible to generate the HTML documentation on a per-bundle basis. Thus, when HTML documentation needs to be regenerated, the source files of every single bundle needs to be processed. diff --git a/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md b/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md index 3c04fdc613..5eb0fd3f2a 100644 --- a/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md +++ b/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md @@ -21,6 +21,7 @@ Documentation should be written in [Markdown](https://www.markdownguide.org/gett the markdown is converted to raw HTML. ::: details Type Aware annotations + [JSDoc](https://jsdoc.app) (and TSDoc) both support annotations that express type information directly like `@type` or annotations that can optionally contain type information like `@param` and `@returns`. Since modules are already written in Typescript, there is no need to use type-aware annotations to document the type of an object. @@ -213,7 +214,7 @@ used. Consider an example from the `midi` bundle below: * @return the corresponding midi note * @example * ``` - * letter_name_to_midi_note("C4"); // Returns 60 + * letter_name_to_midi_note('C4'); // Returns 60 * ``` * @function */ @@ -264,6 +265,13 @@ valid Typescript code. It will print a warning message if your example code does There are a variety of tags that Typedoc supports. This list can be found [here](https://typedoc.org/documents/Tags.html). When writing your documentation you should use these tags to the best of your ability to help make your documentation as comprehensive as possible. +> [!INFO] Configuring Supported Tags +> There is an ESLint rule configured to error when you use an unknown tag. By default, the rule includes all tags supported by JSDoc, but Typedoc +> actually supports many more tags intended for customizing documentaton output. +> +> If you want to use a Typedoc supported tag that hasn't been configured for use, you can simply modify the `jsdoc/check-tag-names` +> rule to include your tag. + ## HTML Documentation The human readable documentation resides in the `build/documentation` folder. You can view its output [here](https://source-academy.github.io/modules/documentation). This is what the output for `make_point` looks like: diff --git a/docs/src/repotools/2-linting.md b/docs/src/repotools/2-linting.md index 7cd580e3bb..ceb44479a4 100644 --- a/docs/src/repotools/2-linting.md +++ b/docs/src/repotools/2-linting.md @@ -25,7 +25,7 @@ When changing a rule's configuration, leave a comment explaining what the origin Where possible, also provide an explanation for why that rule has been configured as such: -<<< ../../../eslint.config.js#typescript {21} +<<< ../../../eslint.config.js#typescript {23} ## Linting Markdown Code Examples @@ -35,6 +35,15 @@ provides a processor that makes these code blocks available to ESLint. Because `typescript-eslint` requires a `tsconfig` to be able to lint any kind of Typescript code, it can't actually be used with any type-aware rules. Furthermore, code examples are usually incomplete snippets of Typescript/Javascript, so a lot of the typical rules in use don't really apply to these. Thus, code examples have their own separate configurations. +## Linting JSDoc Code Examples + +The `eslint-plugin-jsdoc` package provides an ESLint processor that can be used to extract `@example` code blocks and process them for linting. The processor actually +considers the example code blocks as Markdown code examples, so the same block used for configuring those is also used to configure JSDoc code examples. + +Similar to Markdown code blocks, the type-aware rules also do not work with JSDoc code examples. + +The code example processor is configured to only lint code examples that are contained within Markdown code blocks. + ## Linting JSON Files For the most part, there are only stylistic rules that need to be applied to JSON files. This is why this repository doesn't use the official `@eslint/json` package for linting JSON files. diff --git a/docs/src/repotools/6-docserver/1-overview.md b/docs/src/repotools/6-docserver/1-overview.md index 78fe8e9c4e..89fd93678f 100644 --- a/docs/src/repotools/6-docserver/1-overview.md +++ b/docs/src/repotools/6-docserver/1-overview.md @@ -7,13 +7,31 @@ Originally most of the developer documentation was contained within the Github r This documentation server is powered by [Vitepress](https://vitepress.dev), which takes Markdown files and renders them into a (mostly) static site. -## File Structure +## Base URL + +The entire developer documentation server is designed to be deployed at [](https://source-academy.github.io/modules/devdocs), which means that all links throughout +the docserver's source code will be calculated relative to this URL. This setting is controlled by the `base` option in the Vitepress config file. + +## Directory Structure All pages for the server are contained under `src`. [`vitepress-sidebar`](https://vitepress-sidebar.cdget.com) is being used to generate the sidebar for the server. This means that entries in the sidebar appear sorted according to the file/folder names from which they originate. This is why some folder have contents that are labelled `1-something`, `2-something` etc. Each item's value is taken from file's frontmatter, or if not present, the file's first header. -Folders produce item groups, the name of which can be customized using an `index.md` file within that folder. +If there is a file with the same name as its parent folder, then that file is used as the target for the path. For example: + +```dirtree +name: 1-bundles +children: +- 1-bundles.md +- name: example.png + comment: Picture that's displayed in 1-bundles.md +``` + +then the link `./1-bundles.html` will automatically display the `1-bundles.md` page. Using a folder this way lets you group assets intended for a single page. + +If instead you use an `index.md` page, then the the sidebar displays a menu group, the title of which is taken from the `index.md` page. +For example: ```dirtree name: bundles @@ -46,6 +64,8 @@ children: The above file structure produces the menu below: ![image](./menu.png) +Each page can then be referred to using `./bundles/1-getting-started/1-overview.html` or `./bundles/2-bundle/1-overview.html` etc. + Each item takes its title value from either the frontmatter (if available) or the first heading of each page. `index.md` files are only used to title the menus, they are not intended for navigation, though are navigable to if the user enters the address manually, so it is still recommended to keep some basic documentation in those pages or create rewrites so that users are automatically redirected away from those pages. Here are the contents of 2-bundle/index.md: diff --git a/docs/src/repotools/7-workflows/1-actions.md b/docs/src/repotools/7-workflows/1-actions.md index 694399e1b7..43fbed7fce 100644 --- a/docs/src/repotools/7-workflows/1-actions.md +++ b/docs/src/repotools/7-workflows/1-actions.md @@ -25,6 +25,8 @@ In the case of bundles or tabs, it also retrieves the name of the bundle or tab. In case of changes to the lockfile, it also determines which packages need to be rebuilt. This can happen when dependencies of dependencies change, so no change is present in the package's source code itself, but the lockfile itself has changed. +More detail about detecting changes can be found in [this section](./4-changes.md). + This information is used by both the initializer action and the workflows to determine the what tasks need to be executed. ## Initializer Action (`init/action.yml`) @@ -35,9 +37,24 @@ The initializer action combines the initialization steps that are necessary for 2. Install dependencies for that workspace (using `yarn workspaces focus`) 3. Install playwright if necessary (using `yarn playwright install --with-deps`) -> [!INFO] -> Though theoretically this action should also include `actions/checkout` since that action is repeated across -> the different packages, because the initializer action is a custom action, the code for the action needs to be -> checked out before this action can be run. +> [!INFO] What about actions/checkout? +> Theoretically this action should also include `actions/checkout` since this action is repeated across +> the different packages. However, the code for this action sits in the repository, so for Github to be able to execute +> the init action, it needs to first obtain its code, which means the repository must be checked out before this action +> can run. > > Thus, the initializer action has to run _after_ `actions/checkout` has completed and so it has to be a separate step. + +## Load Artifacts Action (`load-artifacts/action.yml`) + +When the CI executes, it will build any tab that has changes relative to the master branch. If the devserver also has +changes, then its tests will run. Since the devserver requires the compiled version of all tabs, we must build all +tabs before running the devserver's tests. + +Since some tabs might already have been built, there is no reason for us to go through the lengthy process of +installing those tabs' dependencies and rebuilding them. Instead, if we save the built tabs as workflow artifacts, +we can restore those tabs before running the devserver's tasks. All that remains then is to build the tabs that +haven't already been built. + +This action does this exact job: figuring out which tabs have already been built successfully and thus can be downloaded +and which tabs need to be built from scratch. diff --git a/docs/src/repotools/7-workflows/2-pull-request.md b/docs/src/repotools/7-workflows/2-pull-request.md index f97ba8ffc3..d915c2ec62 100644 --- a/docs/src/repotools/7-workflows/2-pull-request.md +++ b/docs/src/repotools/7-workflows/2-pull-request.md @@ -16,9 +16,13 @@ This job executes first, using the [Information Action](./1-actions.md#informati > The info action runs `git --no-pager diff master [directory]` from a package's root directory to determine if there > are any changes in the package. Because of this, it is also necessary to run a `git fetch`. +This job does find all the packages within the repository and writes their information to the Github Actions summary. However, it will only output packages +that have changes. This is so that when the following matrix jobs execute, we avoid creating jobs that basically require a single runner to be spun up just +for it to determine that the job need not execute. + ## 2. `libraries`, `bundles` and `tabs` -These three jobs are matrix jobs that run tasks for the individual packages. If the package has changes, then the job will run tests and `tsc` for the package. +These three jobs are matrix jobs that run tasks for the individual packages. The job will run tests and `tsc` for the package. This means that if the package requires `playwright` to run its tests, it will be installed during the init step. @@ -30,10 +34,24 @@ For libraries in particular, the job is run with both the `ubuntu-latest` and `w The `devserver` jobs only executes if there were changes within the dev server. Since it relies on bundles and tabs being compiled, it does rely on both the `bundles` and the `tabs` jobs to have completed. +Because the there might not have been any bundles or tabs with changes, those matrix jobs might not be considered 'completed', so if we just used the `needs` field, +the `devserver` job would not execute if there were no bundle or tab jobs. + +This is why we have to configure the `if` field to use the complex expression it does: if there were bundle and tab jobs that executed, then +check that they all completed successfully before running the devserver job (if necessary). If there weren't, then run the devserver job if there were changes +made to the devserver. + ## 4. `docserver` The `docserver` job only executes if there were changes made to the modules library or the docs themselves. It doesn't deploy the docs here, so it the call to `yarn build` only serves as to way to check that the docs can be generated without errors like dead links. +Similar to the `devserver` job, the `docserver` job must also be configured to execute even if no bundle, tab or library jobs execute. + ## 5. `repo-tasks` This job consists of checking `yarn constraints` and running ESLint for the entire repository. It doesn't rely on any of the other jobs, so it runs in parallel to all of them. + +## 6. `test` + +The final `test` job is a summary step: it only executes if every other job that was supposed to execute did so successfully. The successful completion of this +job represents a successful execution of the entire workflow. diff --git a/docs/src/repotools/7-workflows/4-changes.md b/docs/src/repotools/7-workflows/4-changes.md new file mode 100644 index 0000000000..7b1b068465 --- /dev/null +++ b/docs/src/repotools/7-workflows/4-changes.md @@ -0,0 +1,205 @@ +--- +title: Rebuilding Packages +--- +# Determining When to Rebuild a Package + +For this section, it is important to understand the distinction between workspace packages and Yarn packages: + + + + + + + + + + + + + + + + + + + + + +
WorkspaceYarn
SourceContained entirely within this repositoryPublished to and installed from a remote repository like npm.
Version range looks likeworkspace:^^1.8.1
+ +Specificailly, we are concerned with detecting when to rebuild a workspace package. + +There are many workspace packages contained within this repository. It would be entirely unnecessary to rerun building and +testing for every single workspace package if changes were only made to one. It thus makes sense to implement some kind of +dependency tracking system to rebuild workspace packages only if they were affected by a change. + +Importantly, for the CI/CD pipeline, we are concerned only with changes relative to the **master** branch. + +For each workspace package, there are two main kinds of changes we must detect: +1. Non-transitive +2. Transitive + +## Non-Transitive Changes + +A non-transitive change is the simplest to determine: we can do this by checking if the directory containing the +workspace package contains any diffs relative to the master branch. This can be done using the following git command: + +```sh +git --no-pager diff --quiet origin/master -- directory +``` + +This git command exits with a non-zero exit code if it detected changes and zero if it did not. Programatically, +this is done by using the `@actions/exec` library's `getExecOutput` function: + +```js +const { exitCode } = await getExecOutput( + 'git', + ['--no-pager', 'diff', '--quiet', 'origin/master', '--', directory], + { + failOnStdErr: false, + ignoreReturnCode: true + } +); +return exitCode !== 0; +``` + +## Transitive Changes + +Transitive changes occur when one of the current workspace package's dependencies contain changes. For example, the `sound` bundle +relies on the `midi` bundle, so if the `midi` bundle has changes (and thus needs to be rebuilt), the `sound` bundle would +also need to be rebuilt, even if the `sound` bundle did not contain any changes. +Since the `plotly` bundle relies on the `sound` bundle, it too would also need to be rebuilt. + +```mermaid +graph LR + A[midi] + B[sound] + C[plotly] + + A -- rebuild triggers --> B + B -- rebuild triggers --> C +``` + +However, a workspace package is often dependent on more than just other workspace packages. In fact, most workspace packages +also rely on some Yarn packages, which in turn are also dependent on other Yarn packages. Normally, this dependency resolution process +is handled automatically by Yarn. + +When a change is made to a workspace package's dependencies (e.g. upgrading from `v1.0` to `v2.0` of `gl-matrix` to take advantage +of new features), that workspace package's `package.json` must reflect this change. Then, the [above](#non-transitive-changes) method +will be able to detect that that workspace package needs to be rebuilt. However, a workspace package's dependencies can change even +if there were no changes to its `package.json`. + +This can occur because of [semantic versioning](https://semver.org). Often, the version range specified in a `package.json` doesn't +specify a specific version to be used. For example, the `package.json` below actually specifies that the `curve` bundle is +compatible with anything that is a minor revision to version 2 of `gl-matrix`: + +```jsonc +{ + "name": "@sourceacademy/bundle-curve", + "dependencies": { + "gl-matrix": "^2.0.0" + } +} +``` + +This is good, because it provides us some flexibility: we're able to use newer versions of the same package that are mostly compatible but +might come with things like bug fixes. + +Now suppose that `gl-matrix` itself relies on another Yarn package like `lodash`: + +```jsonc +{ + "name": "gl-matrix", + "dependencies": { + "lodash": "^4.17.0" + } +} +``` + +Because we can only use 1 version of a package at any time, Yarn has to pick from the list of allowed available versions. In this case the +version range allows for `4.17.0` or `4.17.1` or several other possible versions of `lodash`. This process is called "resolution". + +Once Yarn finishes resolving all of these version ranges, it stores these resolutions in the lockfile. This allows us to use the same +resolutions and thus the same versions of packages across multiple machines. + +Suppose that Yarn determines that the version of `lodash` it wants to use for `gl-matrix` is `4.17.0`. This is installed +and the lockfile reflects that `lodash@^4.17.0` got resolved to `lodash@4.17.0` (note the absence of `^`). + +```mermaid +graph LR + A[curve] + B[gl-matrix] + C[lodash] + + D[2.0.0] + E[4.17.0] + + A -- requires --> B + B -- resolved to --> D + B -- requires --> C + C -- resolved to --> E +``` + +Now, suppose that the publishers of `lodash` find a minor bug in one of their functions and release a small patch to rectify it. They +publish this new version as version `4.17.1`. Notice that this version is still compatible with the `^4.17.0` specification. + +When the repository's automated depedency upgrading bot (Renovate Bot) detects this, it will attempt to cause Yarn to install version `4.17.1` +instead of `4.17.0` for `lodash`. It does this by updating the lockfile. But now we have a problem: the `curve` bundle transitively relies +on `lodash` through `gl-matrix`. + +```mermaid +graph LR + A[curve] + B[gl-matrix] + C[lodash] + + D[2.0.0] + E[4.17.0] + F[4.17.1] + + A -- requires --> B + B -- resolved to --> D + B -- requires --> C + C -- X --> E + C -- resolved to --> F +``` + +The `curve` bundle's dependency tree has changed, so we need to rebuiid and test it (to make sure that it works with this new version of `lodash`). + +Yet, because there were no changes made to its `package.json` or to the code of the `curve` bundle, the `git diff` method won't be able +to detect that we need to rebuild the `curve` bundle. + +There is, however, one file that definitely changed: the lockfile. Thus, by parsing the difference between the lockfile on the master branch +and the local lockfile, we can determine which package resolutions changed. + +Then, using the `yarn why` command, we can determine which package is reliant on those specific resolutions. We can do this recursively +until we reach one of our workspace packages, at which point we know that that particular workspace needs to be rebuilt. + +Let us work through the above example: +1. Using `git diff`, we determine that the lockfile has changed relative to the master branch. +2. We compare the local lockfile with the master lockfile and determine that that `lodash@4.17.0` is present in the master lockfile, +while `lodash@4.17.1` is not. So now we know that we need to determine why `lodash@4.17.1` has been included. +3. We run `yarn why lodash` (without the version since the `why` command doesn't accept it) to obtain the list of packages that are +dependent on `lodash`. +4. For each package dependent on `lodash`, we check that that particular package actually depends on `lodash@4.17.1`, since they might +be dependent on other versions of `lodash`. In this case, we see that `gl-matrix@2.0.0` needs `lodash@4.17.1`. +5. We do this recursively until we reach our workspace package, and thus determine that it needs to be rebuilt. In this case, we see +that the `curve` bundle requires `gl-matrix@2.0.0` and thus relies on `lodash@4.17.1`, so it needs to be rebuilt. + +## Building the Dependency Tree + +Once we determine which workspace packages contain either transitive or non-transitive changes, we must then go through the rest of the +workspace packages to determine which other ones need to be rebuilt. From the example above, if the `midi` bundle needs to be rebuilt +because there were changes made to its code, we need to be able to determine that the `sound` bundle also needs to be rebuilt. And since +the `sound` bundle needs to be rebuilt, then the `plotly` bundle also needs to be rebuilt. + +This is done by building a simple dependency graph and then creating a topological ordering. Starting with the workspace packages that aren't +dependent on any other workspace packages and working our way to the end of the topological sort, we are able to determine exactly which +workspace packages need to be rebuilt. + +::: details Circular Dependency Graph + +A topological sort of course requires that our dependency graph doesn't contain a cycle. Yarn won't actually let you create a dependency +graph that is cyclic via workspace dependencies, so we're good to always assume that such a topological sort is possible. + +::: From 1dd8cde7bf2c4bc60bca13c49717ce4027e2089f Mon Sep 17 00:00:00 2001 From: Lee Yi Date: Thu, 25 Dec 2025 21:18:49 +0800 Subject: [PATCH 05/71] Add linting for code examples --- eslint.config.js | 10 ++- package.json | 2 +- src/bundles/arcade_2d/src/functions.ts | 2 +- src/bundles/midi/src/index.ts | 2 +- src/bundles/plotly/src/functions.ts | 2 +- yarn.lock | 98 +++++++++++++++++++++++++- 6 files changed, 109 insertions(+), 7 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 13b487ee2d..9bf6bd4b38 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -8,7 +8,7 @@ import stylePlugin from '@stylistic/eslint-plugin'; import vitestPlugin from '@vitest/eslint-plugin'; import { defineConfig } from 'eslint/config'; import * as importPlugin from 'eslint-plugin-import'; -import jsdocPlugin from 'eslint-plugin-jsdoc'; +import jsdocPlugin, { getJsdocProcessorPlugin } from 'eslint-plugin-jsdoc'; import * as mdx from 'eslint-plugin-mdx'; import reactPlugin from 'eslint-plugin-react'; import reactHooksPlugin from 'eslint-plugin-react-hooks'; @@ -123,7 +123,13 @@ export default defineConfig( name: 'Global JS/TS Stylistic Rules', plugins: { jsdoc: jsdocPlugin, + jsdocExamples: getJsdocProcessorPlugin({ + parser: tseslint.parser, + // Only lint markdown code blocks + exampleCodeRegex: /^[\s*]*```(?:[jt]s\s)?([\s\S]*)```\s*/ + }) }, + processor: 'jsdocExamples/examples', files: [ '**/*.{js,cjs,mjs}', '**/*.{ts,cts,tsx}', @@ -239,7 +245,7 @@ export default defineConfig( 'jsdoc/check-tag-names': ['error', { // NOTE: Not all Typedoc supported tags are present here. Feel free to add any other // Typedoc supported tags to this list - definedTags: ['category', 'categoryDescription', 'hidden'] + definedTags: ['category', 'categoryDescription', 'hidden', 'see'] }], 'jsdoc/empty-tags': ['error', { tags: ['hidden'] diff --git a/package.json b/package.json index 0d7fe53552..bd2cfc31da 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "esbuild": "^0.27.0", "eslint": "^9.35.0", "eslint-plugin-import": "^2.32.0", - "eslint-plugin-jsdoc": "^51.3.1", + "eslint-plugin-jsdoc": "^61.5.0", "eslint-plugin-mdx": "^3.6.2", "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.1.0", diff --git a/src/bundles/arcade_2d/src/functions.ts b/src/bundles/arcade_2d/src/functions.ts index c70eff0704..fea107f3e9 100644 --- a/src/bundles/arcade_2d/src/functions.ts +++ b/src/bundles/arcade_2d/src/functions.ts @@ -142,7 +142,7 @@ export function create_triangle(width: number, height: number): ShapeGameObject * @param text Text string displayed * @example * ``` - * const helloworld = create_text("Hello\nworld!"); + * const helloworld = create_text('Hello\nworld!'); * ``` * @category GameObject */ diff --git a/src/bundles/midi/src/index.ts b/src/bundles/midi/src/index.ts index 5d893eedf6..83d6f6af23 100644 --- a/src/bundles/midi/src/index.ts +++ b/src/bundles/midi/src/index.ts @@ -20,7 +20,7 @@ import { midiNoteToNoteName, noteToValues } from './utils'; * @returns the corresponding midi note * @example * ``` - * letter_name_to_midi_note("C4"); // Returns 60 + * letter_name_to_midi_note('C4'); // Returns 60 * ``` * @function */ diff --git a/src/bundles/plotly/src/functions.ts b/src/bundles/plotly/src/functions.ts index e5a446b80d..9e5bf03916 100644 --- a/src/bundles/plotly/src/functions.ts +++ b/src/bundles/plotly/src/functions.ts @@ -25,7 +25,7 @@ context.moduleContexts.plotly.state = { /** * Adds a new plotly plot to the context which will be rendered in the Plotly Tabs * @example - * ```typescript + * ```ts * const z1 = [ * [8.83,8.89,8.81,8.87,8.9,8.87], * [8.89,8.94,8.85,8.94,8.96,8.92], diff --git a/yarn.lock b/yarn.lock index 1033889243..aa94f0dd3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2021,6 +2021,26 @@ __metadata: languageName: node linkType: hard +"@es-joy/jsdoccomment@npm:~0.76.0": + version: 0.76.0 + resolution: "@es-joy/jsdoccomment@npm:0.76.0" + dependencies: + "@types/estree": "npm:^1.0.8" + "@typescript-eslint/types": "npm:^8.46.0" + comment-parser: "npm:1.4.1" + esquery: "npm:^1.6.0" + jsdoc-type-pratt-parser: "npm:~6.10.0" + checksum: 10c0/8fe4edec7d60562787ea8c77193ebe8737a9e28ec3143d383506b63890d0ffd45a2813e913ad1f00f227cb10e3a1fb913e5a696b33d499dc564272ff1a6f3fdb + languageName: node + linkType: hard + +"@es-joy/resolve.exports@npm:1.2.0": + version: 1.2.0 + resolution: "@es-joy/resolve.exports@npm:1.2.0" + checksum: 10c0/7e4713471f5eccb17a925a12415a2d9e372a42376813a19f6abd9c35e8d01ab1403777265817da67c6150cffd4f558d9ad51e26a8de6911dad89d9cb7eedacd8 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/aix-ppc64@npm:0.21.5" @@ -4082,6 +4102,13 @@ __metadata: languageName: node linkType: hard +"@sindresorhus/base62@npm:^1.0.0": + version: 1.0.0 + resolution: "@sindresorhus/base62@npm:1.0.0" + checksum: 10c0/9a14df0f058fdf4731c30f0f05728a4822144ee42236030039d7fa5a1a1072c2879feba8091fd4a17c8922d1056bc07bada77c31fddc3e15836fc05a266fd918 + languageName: node + linkType: hard + "@sindresorhus/is@npm:^4.0.0": version: 4.6.0 resolution: "@sindresorhus/is@npm:4.6.0" @@ -4693,7 +4720,7 @@ __metadata: esbuild: "npm:^0.27.0" eslint: "npm:^9.35.0" eslint-plugin-import: "npm:^2.32.0" - eslint-plugin-jsdoc: "npm:^51.3.1" + eslint-plugin-jsdoc: "npm:^61.5.0" eslint-plugin-mdx: "npm:^3.6.2" eslint-plugin-react: "npm:^7.37.4" eslint-plugin-react-hooks: "npm:^5.1.0" @@ -5978,6 +6005,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:^8.46.0": + version: 8.50.1 + resolution: "@typescript-eslint/types@npm:8.50.1" + checksum: 10c0/04e3c296d81293e370578762be6736fccd1581476f9d534938d42fe93968571fcaf26d7d8c3de52ed63a5af2c0b2da922b8ee2011fa5fb9fb401fc7f0916367a + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:8.46.4": version: 8.46.4 resolution: "@typescript-eslint/typescript-estree@npm:8.46.4" @@ -9894,6 +9928,30 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-jsdoc@npm:^61.5.0": + version: 61.5.0 + resolution: "eslint-plugin-jsdoc@npm:61.5.0" + dependencies: + "@es-joy/jsdoccomment": "npm:~0.76.0" + "@es-joy/resolve.exports": "npm:1.2.0" + are-docs-informative: "npm:^0.0.2" + comment-parser: "npm:1.4.1" + debug: "npm:^4.4.3" + escape-string-regexp: "npm:^4.0.0" + espree: "npm:^10.4.0" + esquery: "npm:^1.6.0" + html-entities: "npm:^2.6.0" + object-deep-merge: "npm:^2.0.0" + parse-imports-exports: "npm:^0.2.4" + semver: "npm:^7.7.3" + spdx-expression-parse: "npm:^4.0.0" + to-valid-identifier: "npm:^1.0.0" + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + checksum: 10c0/fabb04f6efe58a167a0839d3c05676a76080c6e91d98a269fa768c1bfd835aa0ded5822d400da2874216177044d2d227ebe241d73e923f3fe1c08bafd19cfd3d + languageName: node + linkType: hard + "eslint-plugin-mdx@npm:^3.6.2": version: 3.6.2 resolution: "eslint-plugin-mdx@npm:3.6.2" @@ -11191,6 +11249,13 @@ __metadata: languageName: node linkType: hard +"html-entities@npm:^2.6.0": + version: 2.6.0 + resolution: "html-entities@npm:2.6.0" + checksum: 10c0/7c8b15d9ea0cd00dc9279f61bab002ba6ca8a7a0f3c36ed2db3530a67a9621c017830d1d2c1c65beb9b8e3436ea663e9cf8b230472e0e413359399413b27c8b7 + languageName: node + linkType: hard + "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -12229,6 +12294,13 @@ __metadata: languageName: node linkType: hard +"jsdoc-type-pratt-parser@npm:~6.10.0": + version: 6.10.0 + resolution: "jsdoc-type-pratt-parser@npm:6.10.0" + checksum: 10c0/8ea395df0cae0e41d4bdba5f8d81b8d3e467fe53d1e4182a5d4e653235a5f17d60ed137343d68dbc74fa10e767f1c58fb85b1f6d5489c2cf16fc7216cc6d3e1a + languageName: node + linkType: hard + "jsdom@npm:^26.1.0": version: 26.1.0 resolution: "jsdom@npm:26.1.0" @@ -14367,6 +14439,13 @@ __metadata: languageName: node linkType: hard +"object-deep-merge@npm:^2.0.0": + version: 2.0.0 + resolution: "object-deep-merge@npm:2.0.0" + checksum: 10c0/69e8741131ad49fa8720fb96007a3c82dca1119b5d874151d2ecbcc3b44ccd46e8553c7a30b0abcba752c099ba361bbba97f33a68c9ae54c57eed7be116ffc97 + languageName: node + linkType: hard + "object-hash@npm:^3.0.0": version: 3.0.0 resolution: "object-hash@npm:3.0.0" @@ -15614,6 +15693,13 @@ __metadata: languageName: node linkType: hard +"reserved-identifiers@npm:^1.0.0": + version: 1.2.0 + resolution: "reserved-identifiers@npm:1.2.0" + checksum: 10c0/b82651b12e6c608e80463c3753d275bc20fd89294d0415f04e670aeec3611ae3582ddc19e8fedd497e7d0bcbfaddab6a12823ec86e855b1e6a245e0a734eb43d + languageName: node + linkType: hard + "resolve-alpn@npm:^1.0.0": version: 1.2.1 resolution: "resolve-alpn@npm:1.2.1" @@ -17249,6 +17335,16 @@ __metadata: languageName: node linkType: hard +"to-valid-identifier@npm:^1.0.0": + version: 1.0.0 + resolution: "to-valid-identifier@npm:1.0.0" + dependencies: + "@sindresorhus/base62": "npm:^1.0.0" + reserved-identifiers: "npm:^1.0.0" + checksum: 10c0/569b49f43b5aaaa20677e67f0f1cdcff344855149934cfb80c793c7ac7c30e191b224bc81cab40fb57641af9ca73795c78053c164a2addc617671e2d22c13a4a + languageName: node + linkType: hard + "totalist@npm:^3.0.0": version: 3.0.1 resolution: "totalist@npm:3.0.1" From bbc6970584b1bb071b8ac1d0098e294d25f46a76 Mon Sep 17 00:00:00 2001 From: Lee Yi Date: Thu, 25 Dec 2025 21:19:03 +0800 Subject: [PATCH 06/71] Add compile command --- lib/buildtools/src/build/docs/typedoc.ts | 5 +- .../src/{prebuild => build/modules}/tsc.ts | 127 ++++++++++++------ lib/buildtools/src/commands/build.ts | 22 +++ lib/buildtools/src/prebuild/index.ts | 6 +- 4 files changed, 112 insertions(+), 48 deletions(-) rename lib/buildtools/src/{prebuild => build/modules}/tsc.ts (57%) diff --git a/lib/buildtools/src/build/docs/typedoc.ts b/lib/buildtools/src/build/docs/typedoc.ts index 820147eab8..292ce59009 100644 --- a/lib/buildtools/src/build/docs/typedoc.ts +++ b/lib/buildtools/src/build/docs/typedoc.ts @@ -1,5 +1,6 @@ import pathlib from 'path'; import type { ResolvedBundle } from '@sourceacademy/modules-repotools/types'; +import { convertToPosixPath } from '@sourceacademy/modules-repotools/utils'; import * as td from 'typedoc'; // #region commonOpts @@ -18,7 +19,7 @@ const typedocPackageOptions: td.Configuration.TypeDocOptions = { */ export async function initTypedocForJson(bundle: ResolvedBundle, logLevel: td.LogLevel) { // TypeDoc expects POSIX paths - const directoryAsPosix = bundle.directory.replace(/\\/g, '/'); + const directoryAsPosix = convertToPosixPath(bundle.directory); const app = await td.Application.bootstrapWithPlugins({ ...typedocPackageOptions, name: bundle.name, @@ -52,7 +53,7 @@ export function initTypedocForHtml(bundles: Record, logL logLevel, entryPoints: Object.values(bundles).map(({ directory }) => { // TypeDoc expects POSIX paths - const directoryAsPosix = directory.replace(/\\/g, '/'); + const directoryAsPosix = convertToPosixPath(directory); return `${directoryAsPosix}/dist/docs.json`; }), entryPointStrategy: 'merge', diff --git a/lib/buildtools/src/prebuild/tsc.ts b/lib/buildtools/src/build/modules/tsc.ts similarity index 57% rename from lib/buildtools/src/prebuild/tsc.ts rename to lib/buildtools/src/build/modules/tsc.ts index 74de67c62e..7ad6fbe421 100644 --- a/lib/buildtools/src/prebuild/tsc.ts +++ b/lib/buildtools/src/build/modules/tsc.ts @@ -1,6 +1,6 @@ import fs from 'fs/promises'; import pathlib from 'path'; -import type { InputAsset, Severity } from '@sourceacademy/modules-repotools/types'; +import type { InputAsset, ResolvedBundle, Severity } from '@sourceacademy/modules-repotools/types'; import { findSeverity } from '@sourceacademy/modules-repotools/utils'; import chalk from 'chalk'; import ts from 'typescript'; @@ -27,6 +27,9 @@ export type TscResult = { results: ts.Diagnostic[]; }); +/** + * Find a tsconfig.json in the given directory, then read and parse it. + */ async function getTsconfig(srcDir: string): Promise { // Step 1: Read the text from tsconfig.json const tsconfigLocation = pathlib.join(srcDir, 'tsconfig.json'); @@ -64,18 +67,37 @@ async function getTsconfig(srcDir: string): Promise { } } -export async function runTsc(input: InputAsset, noEmit: boolean): Promise { - const tsconfigRes = await getTsconfig(input.directory); - if (tsconfigRes.severity === 'error') { - return { - ...tsconfigRes, - input - }; - } - - const { results: tsconfig, fileNames } = tsconfigRes; +/** + * Convert a collection of Typescript diagnostics to a Severity + */ +function processDiagnostics(diagnostics: ts.Diagnostic[]) { + return findSeverity(diagnostics, ({ category }) => { + switch (category) { + case ts.DiagnosticCategory.Error: + return 'error'; + case ts.DiagnosticCategory.Warning: + return 'warn'; + default: + return 'success'; + } + }); +} +/** + * Run tsc but only for typechecking + */ +export async function runTypechecking(input: InputAsset): Promise { try { + + const tsconfigRes = await getTsconfig(input.directory); + if (tsconfigRes.severity === 'error') { + return { + ...tsconfigRes, + input + }; + } + + const { results: tsconfig, fileNames } = tsconfigRes; // tsc instance that only does typechecking // Type checking for both tests and source code is performed const typecheckProgram = ts.createProgram({ @@ -89,47 +111,66 @@ export async function runTsc(input: InputAsset, noEmit: boolean): Promise { - switch (category) { - case ts.DiagnosticCategory.Error: - return 'error'; - case ts.DiagnosticCategory.Warning: - return 'warn'; - default: - return 'success'; - } - }); + const severity = processDiagnostics(diagnostics); + return { + severity, + input, + results: diagnostics + }; + } catch (error) { + return { + severity: 'error', + error, + input + }; + } +} - if (input.type === 'bundle' && severity !== 'error' && !noEmit) { - // If noEmit isn't specified, then run tsc again without including test - // files and actually output the files - const filesWithoutTests = fileNames.filter(p => { - const segments = p.split(pathlib.posix.sep); - return !segments.includes('__tests__'); - }); - // tsc instance that does compilation - // only compiles non test files - const compileProgram = ts.createProgram({ - rootNames: filesWithoutTests, - options: { - ...tsconfig, - noEmit: false - }, - oldProgram: typecheckProgram - }); - compileProgram.emit(); +/** + * Run tsc but for compiling bundles + */ +export async function runTscCompile(input: ResolvedBundle, oldProgram?: ts.Program): Promise { + try { + const tsconfigRes = await getTsconfig(input.directory); + if (tsconfigRes.severity === 'error') { + return { + ...tsconfigRes, + input + }; } + const { results: tsconfig, fileNames } = tsconfigRes; + const filesWithoutTests = fileNames.filter(p => { + const segments = p.split(pathlib.posix.sep); + return !segments.includes('__tests__') && !segments.includes('__mocks__'); + }); + // tsc instance that does compilation + // only compiles non test files + const compileProgram = ts.createProgram({ + rootNames: filesWithoutTests, + options: { + ...tsconfig, + noEmit: false + }, + oldProgram + }); + compileProgram.emit(); + + const results = compileProgram.emit(); + const diagnostics = ts.getPreEmitDiagnostics(compileProgram) + .concat(results.diagnostics); + + const severity = processDiagnostics(diagnostics); return { severity, - results: diagnostics, - input + input, + results: diagnostics }; } catch (error) { return { severity: 'error', - input, - error + error, + input }; } } diff --git a/lib/buildtools/src/commands/build.ts b/lib/buildtools/src/commands/build.ts index a57fb4eebb..48f36bec49 100644 --- a/lib/buildtools/src/commands/build.ts +++ b/lib/buildtools/src/commands/build.ts @@ -7,6 +7,7 @@ import { buildHtml, buildSingleBundleDocs } from '../build/docs/index.js'; import { formatResult, formatResultObject } from '../build/formatter.js'; import { buildBundle, buildTab } from '../build/modules/index.js'; import { buildManifest } from '../build/modules/manifest.js'; +import { formatTscResult, runTscCompile } from '../build/modules/tsc.js'; import { runBuilderWithPrebuild } from '../prebuild/index.js'; import * as cmdUtils from './commandUtils.js'; @@ -143,3 +144,24 @@ export const getBuildHtmlCommand = () => new Command('html') console.log(formatResult(htmlResult, 'html')); cmdUtils.processResult(htmlResult, false); }); + +export const getCompileCommand = () => new Command('compile') + .description('Compiles the bundle at the given directory using tsc') + .argument('[bundle]', 'Directory in which the bundle\'s source files are located', process.cwd()) + .action(async directory => { + const bundle = await resolveSingleBundle(directory); + if (!bundle) { + cmdUtils.logCommandErrorAndExit(`No bundle was found at ${directory}`); + } + + if (bundle.severity === 'error') { + cmdUtils.logCommandErrorAndExit(bundle); + } + + const compileResult = await runTscCompile(bundle.bundle); + if (compileResult.severity === 'error') { + cmdUtils.logCommandErrorAndExit(formatTscResult(compileResult)); + } + + console.log(chalk.greenBright(`Finished compiling ${bundle.bundle.name}`)); + }); diff --git a/lib/buildtools/src/prebuild/index.ts b/lib/buildtools/src/prebuild/index.ts index 2b6de58b32..2bb4e23a83 100644 --- a/lib/buildtools/src/prebuild/index.ts +++ b/lib/buildtools/src/prebuild/index.ts @@ -2,8 +2,8 @@ import fs from 'fs/promises'; import pathlib from 'path'; import type { InputAsset } from '@sourceacademy/modules-repotools/types'; import { compareSeverity } from '@sourceacademy/modules-repotools/utils'; +import { runTypechecking, type TscResult } from '../build/modules/tsc.js'; import { runEslint, type LintResult } from './lint.js'; -import { runTsc, type TscResult } from './tsc.js'; export type PrebuildOptions = { tsc?: boolean; @@ -30,7 +30,7 @@ export async function runBuilderWithPrebuild> { const promises: [Promise, Promise] = [ - !tsc ? Promise.resolve(undefined) : runTsc(asset, false), + !tsc ? Promise.resolve(undefined) : runTypechecking(asset), !lint ? Promise.resolve(undefined) : runEslint(asset), ]; @@ -63,7 +63,7 @@ export async function runBuilderWithPrebuild Date: Sun, 28 Dec 2025 17:36:42 +0800 Subject: [PATCH 07/71] Fix bug where markdown directory trees weren't being aligned properly --- lib/markdown-tree/src/transformer.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/markdown-tree/src/transformer.ts b/lib/markdown-tree/src/transformer.ts index 789a0ab676..e37abdc486 100644 --- a/lib/markdown-tree/src/transformer.ts +++ b/lib/markdown-tree/src/transformer.ts @@ -22,9 +22,8 @@ const githubDarkColours = [ ]; // Assemble the Regex expression using the line strings -const reString = Object.entries(LINE_STRINGS) - .filter(([key]) => key !== 'EMPTY') - .map(([, value]) => `(?:${value})`) +const reString = Object.values(LINE_STRINGS) + .map(value => `(?:${value})`) .join('|'); const branchRE = new RegExp(reString, 'g'); From 54c4eed167c9f8751dd0939bfaa25cde4e77d4f6 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Mon, 29 Dec 2025 02:19:09 +0800 Subject: [PATCH 08/71] Add tests for the markdown tree transformer --- docs/src/repotools/6-docserver/2-dirtree.md | 79 ++++++++- lib/markdown-tree/package.json | 2 +- .../src/__tests__/transformer.test.ts | 160 ++++++++++++++++++ lib/markdown-tree/src/transformer.ts | 4 +- lib/markdown-tree/tsconfig.json | 9 +- yarn.lock | 99 ++++++++++- 6 files changed, 338 insertions(+), 15 deletions(-) create mode 100644 lib/markdown-tree/src/__tests__/transformer.test.ts diff --git a/docs/src/repotools/6-docserver/2-dirtree.md b/docs/src/repotools/6-docserver/2-dirtree.md index a59b2a2626..a8280686b4 100644 --- a/docs/src/repotools/6-docserver/2-dirtree.md +++ b/docs/src/repotools/6-docserver/2-dirtree.md @@ -2,14 +2,89 @@ The idea behind this plugin was inspired by [this](https://tree.nathanfriend.com/?) ASCII tree generator. + + +## Plugin Structure + +The plugin itself consists of 3 components: + +### 1. `markdown-it` plugin + +This component hooks into the Markdown code block renderer, allowing us to replace the rendering logic for code blocks when we detect the `dirtree` language. + +The directory plugin is located in the `markdown-tree` folder under the `lib` directory. Because of some of the `lodash` dependencies that get bundled, the plugin needs to be built to CJS rather than ESM. + ::: details Creating a Markdown-It Plugin The documentation for developers looking to create a Markdown-It plugin are woefully inadequate. Thus, most of this plugin was written based on the implementations of other plugins, such as the Vitepress Mermaid plugin and Vitepress Code snippet plugin. -It basically works by detecting when a code block has been assigned the `dirtree` language, parses the code block's content as YAML and converts that object into the directory structure that can then be rendered as text. - ::: +In this case, we first parse the YAML configuration, then render the directory tree as a string before passing it back to the Markdown code renderer so that the +directory tree gets rendered as a code block. + +### 2. Textmate grammar for the `dirtree` language + +To provide the colouring for the rendered directory trees, we first need to instruct Vitepress' builtin highlighter `shiki` on how to parse our rendered directory trees so that it can figure out what elements +need to be highlighted. + +`shiki` relies on [Textmate Grammars](https://macromates.com/manual/en/language_grammars) for parsing, so the plugin defines a grammar so that `shiki` can identify the different components of the directory tree: + + + + + + + + + + + + + + + + + + + + + + + + + + +
ComponentExplanationExamples
BranchGroups of 4 characters that together make up the graphic part of the "tree" +
    +
  •     
  • +
  • │   
  • +
  • ├── 
  • +
  • └── 
  • +
+
IdentifierThe name of a file or directory +
    +
  • filename.js
  • +
  • bin
  • +
+
CommentOptional comment describing the entry, beginning with two forward slashes // that gets rendered at the end the line// This is a comment
+ +Each line in the directory must consist of at least 1 branch (if it's not the root) and exactly 1 identifier. The comment is optional. + +Passing `shiki` this grammar also registers the `dirtree` langauge with `shiki`, so it doesn't get confused when trying to find highlighters. + +### 3. Highlighter for `shiki` + +`shiki` uses the grammar to parse each line of the directory tree, which then breaks that line into an array of tokens that gets passed to the code transformer. +Each token contains one of the aforementioned components. + +Since each branch component has a length of 4, we can determine the level to which each token belongs by dividing its position from the start of the line by 4 (i.e a branch token at +8 characters offset from line start is at level 2). Then we simply assign the colour corresponding to that indent level to that token. + +Vitepress uses the themes from Github by default, so the transformer is configured to select from a set of colours chosen from the `github-dark` and `github-light` themes. + +## Using the plugin within Markdown + To create your own directory tree, use the `dirtree` language with your markdown code block: ````md {1} diff --git a/lib/markdown-tree/package.json b/lib/markdown-tree/package.json index 12dac11b47..fdf2ff7772 100644 --- a/lib/markdown-tree/package.json +++ b/lib/markdown-tree/package.json @@ -5,11 +5,11 @@ "private": true, "type": "module", "devDependencies": { - "@shikijs/types": "^3.15.0", "@sourceacademy/modules-buildtools": "workspace:^", "@sourceacademy/modules-repotools": "workspace:^", "@types/lodash": "^4.14.198", "@types/markdown-it": "^14.1.2", + "shiki": "^3.15.0", "typescript": "^5.8.2" }, "exports": { diff --git a/lib/markdown-tree/src/__tests__/transformer.test.ts b/lib/markdown-tree/src/__tests__/transformer.test.ts new file mode 100644 index 0000000000..5c68d28254 --- /dev/null +++ b/lib/markdown-tree/src/__tests__/transformer.test.ts @@ -0,0 +1,160 @@ +import { createHighlighter, type ShikiTransformer, type ThemedToken } from 'shiki'; +import { describe, expect, it as baseIt } from 'vitest'; +import { dirtreeTransformer, grammar } from '../transformer.js'; +import { parseContent } from '../structure.js'; + +interface Fixtures { + transformer: ShikiTransformer; + transform: (input: string) => ThemedToken[][]; + highlighter: Awaited>; +} + +const it = baseIt.extend({ + transformer: ({}, use) => { + const transformer = dirtreeTransformer({ + lightColours: ['1', '2', '3', '4'], + }); + return use(transformer); + }, + highlighter: async ({}, use) => { + const highlighter = await createHighlighter({ + langs: [grammar], + themes: ['github-light'], + }); + await use(highlighter); + highlighter.dispose(); + }, + transform: ({ highlighter, transformer }, use) => use((input: string) => { + const [generated] = parseContent(input, '/dummy/dir', {}); + + const { tokens } = highlighter.codeToTokens(generated, { + theme: 'github-light', + transformers: [transformer], + // @ts-expect-error dirtree is not in the official Shiki lang list + lang: 'dirtree', + }); + return transformer.tokens!.call({ + options: { + lang: 'dirtree' + } + } as any, tokens)! + }) +}); + +/** + * Convert each line of tokens into a joined string, + * verifying that the beginning offsets for each line are correct + * \ + * Also collects the colours used in each line + */ +function tokenJoiner(tokens: ThemedToken[][]): { + lines: string[], + colours: string[][] + } { + let lineOffset = 0; + + const output: string[] = []; + const colours: string[][] = []; + + for (const line of tokens) { + expect(line[0].offset).toEqual(lineOffset); + const joinedLine = line.map(token => token.content).join(''); + output.push(joinedLine); + + const lineColours: string[] = []; + for (const token of line) { + if (token.content === ' ') continue; // skip spaces + if (token.htmlStyle === undefined) continue; + + lineColours.push(token.htmlStyle['--shiki-light']); + } + colours.push(lineColours); + + lineOffset += joinedLine.length + 1; // +1 for newline + } + + return { lines: output, colours }; +} + +describe(dirtreeTransformer, () => { + it('correctly highlights a simple directory tree', ({ transform }) => { + const input = ` + name: root + children: + - dir1 + - dir2 + `; + + const tokens = transform(input); + const { lines, colours } = tokenJoiner(tokens); + + expect(lines.length).toEqual(3); // 3 lines + expect(lines[0]).toEqual('root'); + + expect(lines[1]).toEqual('├── dir1'); + expect(colours[1]).toEqual(['1', '1']); + + expect(lines[2]).toEqual('└── dir2'); + expect(colours[2]).toEqual(['1', '1']); + }); + + it('correctly handles indent levels with no overlap', ({ transform }) => { + const input = ` + name: root + children: + - name: dir1 + children: + - name: dir2 + children: + - dir3 + `; + const tokens = transform(input); + const { lines, colours } = tokenJoiner(tokens); + + expect(lines.length).toEqual(4); // 4 lines + expect(lines[0]).toEqual('root'); + + expect(lines[1]).toEqual('└── dir1'); + expect(colours[1]).toEqual(['1', '1']); + + expect(lines[2]).toEqual(' └── dir2'); + expect(colours[2]).toEqual(['2', '2']); + + expect(lines[3]).toEqual(' └── dir3'); + expect(colours[3]).toEqual(['3', '3']); + }); + + it('correctly handles indent levels with overlaps', ({ transform }) => { + const input = ` + name: root + children: + - name: dir1 + children: + - name: dir2 + children: + - dir3 + - dir4 + - dir5 + `; + const tokens = transform(input); + const { lines, colours } = tokenJoiner(tokens); + expect(lines.length).toEqual(6); // 6 lines + + expect(lines[0]).toEqual('root'); + + expect(lines[1]).toEqual('├── dir1'); + expect(colours[1]).toEqual(['1', '1']); + + expect(lines[2]).toEqual('│ ├── dir2'); + expect(colours[2]).toEqual(['1', '2', '2']); + + expect(lines[3]).toEqual('│ │ └── dir3'); + expect(colours[3]).toEqual(['1', '2', '3', '3']); + + expect(lines[4]).toEqual('│ └── dir4'); + expect(colours[4]).toEqual(['1', '2', '2']); + + expect(lines[5]).toEqual('└── dir5'); + expect(colours[5]).toEqual(['1', '1']); + }); +}); diff --git a/lib/markdown-tree/src/transformer.ts b/lib/markdown-tree/src/transformer.ts index e37abdc486..c5779015d5 100644 --- a/lib/markdown-tree/src/transformer.ts +++ b/lib/markdown-tree/src/transformer.ts @@ -76,7 +76,7 @@ export interface TransformerOptions { /** * Returns a {@link ShikiTransformer} for colouring dirtree diagrams */ -export function dirtreeTransformer(options: TransformerOptions = {}): ShikiTransformer { +export function dirtreeTransformer(options: TransformerOptions = {}) { const lightColours = options?.lightColours || githubLightColours; const darkColours = options?.darkColours || githubDarkColours; @@ -137,5 +137,5 @@ export function dirtreeTransformer(options: TransformerOptions = {}): ShikiTrans return newTokens; } - }; + } satisfies ShikiTransformer; } diff --git a/lib/markdown-tree/tsconfig.json b/lib/markdown-tree/tsconfig.json index 3ed7a5302f..1aba568b01 100644 --- a/lib/markdown-tree/tsconfig.json +++ b/lib/markdown-tree/tsconfig.json @@ -5,12 +5,5 @@ ], "include": [ "./src" - ], - "compilerOptions": { - "paths": { - "shiki": [ - "../../node_modules/@shikijs/types" - ] - } - } + ] } diff --git a/yarn.lock b/yarn.lock index aa94f0dd3b..461818b605 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3998,6 +3998,18 @@ __metadata: languageName: node linkType: hard +"@shikijs/core@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/core@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + "@types/hast": "npm:^3.0.4" + hast-util-to-html: "npm:^9.0.5" + checksum: 10c0/3df490754e631bf71723aec921de623d0e464c868bccafda89cdb1f061b968ee56385f5709d7401213773dc0c36d9650db436492bd2fa13eac4cf50255f12d26 + languageName: node + linkType: hard + "@shikijs/engine-javascript@npm:2.5.0": version: 2.5.0 resolution: "@shikijs/engine-javascript@npm:2.5.0" @@ -4009,6 +4021,17 @@ __metadata: languageName: node linkType: hard +"@shikijs/engine-javascript@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/engine-javascript@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + oniguruma-to-es: "npm:^4.3.4" + checksum: 10c0/52ee46eba86bd0e4f5ca9520736a17e5a052830685edb319d77a2929ca30bcd176353212b9978d680109fd93d7e13c9ad5b039b69223d817a6331fc9f88389f2 + languageName: node + linkType: hard + "@shikijs/engine-oniguruma@npm:2.5.0": version: 2.5.0 resolution: "@shikijs/engine-oniguruma@npm:2.5.0" @@ -4019,6 +4042,16 @@ __metadata: languageName: node linkType: hard +"@shikijs/engine-oniguruma@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/engine-oniguruma@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + checksum: 10c0/4a5a8f316a8482e799cd836c8e3f8ba83274b3631b2d66ec82ad839b0ee1dd3df50a08480f791d59f22e42bf6b707032f043a9f651445efc04e59b7ec9e669c9 + languageName: node + linkType: hard + "@shikijs/engine-oniguruma@npm:^3.15.0": version: 3.15.0 resolution: "@shikijs/engine-oniguruma@npm:3.15.0" @@ -4038,6 +4071,15 @@ __metadata: languageName: node linkType: hard +"@shikijs/langs@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/langs@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + checksum: 10c0/6830460025d0df4c527ffeacf0a78cd4331ffde1cfcd1e8028aa9814be8a4cea84367dd938528a9b55de72b163c58ad3576915ea08c3d0a29ef1dc80e120116c + languageName: node + linkType: hard + "@shikijs/langs@npm:^3.15.0": version: 3.15.0 resolution: "@shikijs/langs@npm:3.15.0" @@ -4056,6 +4098,15 @@ __metadata: languageName: node linkType: hard +"@shikijs/themes@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/themes@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + checksum: 10c0/d6fc059c51c3c0694e026cc1f80eed927d9b91adaeda0fb3fd5725eabc6d066aaf022919def435245446ae91e3da541ed6d88d875cf59a35bfbabb6920efb6da + languageName: node + linkType: hard + "@shikijs/themes@npm:^3.15.0": version: 3.15.0 resolution: "@shikijs/themes@npm:3.15.0" @@ -4095,6 +4146,16 @@ __metadata: languageName: node linkType: hard +"@shikijs/types@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/types@npm:3.20.0" + dependencies: + "@shikijs/vscode-textmate": "npm:^10.0.2" + "@types/hast": "npm:^3.0.4" + checksum: 10c0/7faea130362a6cdf3d66fcb47d6b609a8e0209e76ba86688f56a65411b6ae400a37414cd1a3a2fe1ee3fe39f18e274585d3972129c7e79244aaa0c15bc8f1c21 + languageName: node + linkType: hard + "@shikijs/vscode-textmate@npm:^10.0.2": version: 10.0.2 resolution: "@shikijs/vscode-textmate@npm:10.0.2" @@ -4538,12 +4599,12 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/markdown-plugin-directory-tree@workspace:lib/markdown-tree" dependencies: - "@shikijs/types": "npm:^3.15.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-repotools": "workspace:^" "@types/lodash": "npm:^4.14.198" "@types/markdown-it": "npm:^14.1.2" lodash: "npm:^4.17.21" + shiki: "npm:^3.15.0" tm-themes: "npm:^1.10.12" typescript: "npm:^5.8.2" yaml: "npm:^2.8.0" @@ -11133,7 +11194,7 @@ __metadata: languageName: node linkType: hard -"hast-util-to-html@npm:^9.0.4": +"hast-util-to-html@npm:^9.0.4, hast-util-to-html@npm:^9.0.5": version: 9.0.5 resolution: "hast-util-to-html@npm:9.0.5" dependencies: @@ -14565,6 +14626,13 @@ __metadata: languageName: node linkType: hard +"oniguruma-parser@npm:^0.12.1": + version: 0.12.1 + resolution: "oniguruma-parser@npm:0.12.1" + checksum: 10c0/b843ea54cda833efb19f856314afcbd43e903ece3de489ab78c527ddec84859208052557daa9fad4bdba89ebdd15b0cc250de86b3daf8c7cbe37bac5a6a185d3 + languageName: node + linkType: hard + "oniguruma-to-es@npm:^3.1.0": version: 3.1.1 resolution: "oniguruma-to-es@npm:3.1.1" @@ -14576,6 +14644,17 @@ __metadata: languageName: node linkType: hard +"oniguruma-to-es@npm:^4.3.4": + version: 4.3.4 + resolution: "oniguruma-to-es@npm:4.3.4" + dependencies: + oniguruma-parser: "npm:^0.12.1" + regex: "npm:^6.0.1" + regex-recursion: "npm:^6.0.2" + checksum: 10c0/fb58459f50db71c2c4785205636186bfbb125b094c4275512a8f41f123ed3fbf61f37c455f4360ef14a56c693981aecd7da3ae2c05614a222e872c4643b463fc + languageName: node + linkType: hard + "opener@npm:^1.5.1": version: 1.5.2 resolution: "opener@npm:1.5.2" @@ -16322,6 +16401,22 @@ __metadata: languageName: node linkType: hard +"shiki@npm:^3.15.0": + version: 3.20.0 + resolution: "shiki@npm:3.20.0" + dependencies: + "@shikijs/core": "npm:3.20.0" + "@shikijs/engine-javascript": "npm:3.20.0" + "@shikijs/engine-oniguruma": "npm:3.20.0" + "@shikijs/langs": "npm:3.20.0" + "@shikijs/themes": "npm:3.20.0" + "@shikijs/types": "npm:3.20.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + "@types/hast": "npm:^3.0.4" + checksum: 10c0/e7f0a8e6b8748b1d25cccc186e5cd32cbc8b272c08b4b554a3328c95714ee564d5525747d5ceb52c1ee766ec25cb7a5fa1de748edeb6508a57be15433de1564f + languageName: node + linkType: hard + "side-channel-list@npm:^1.0.0": version: 1.0.0 resolution: "side-channel-list@npm:1.0.0" From 49cbc9a9c25d814615eef1f489d14a6cde2619f7 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Mon, 29 Dec 2025 02:46:46 +0800 Subject: [PATCH 09/71] Run format --- eslint.config.js | 3 ++- .../src/__tests__/transformer.test.ts | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 9bf6bd4b38..4fcabe8aa9 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -245,7 +245,8 @@ export default defineConfig( 'jsdoc/check-tag-names': ['error', { // NOTE: Not all Typedoc supported tags are present here. Feel free to add any other // Typedoc supported tags to this list - definedTags: ['category', 'categoryDescription', 'hidden', 'see'] + definedTags: ['category', 'categoryDescription', 'hidden', 'title'], + inlineTags: ['link', 'see'], }], 'jsdoc/empty-tags': ['error', { tags: ['hidden'] diff --git a/lib/markdown-tree/src/__tests__/transformer.test.ts b/lib/markdown-tree/src/__tests__/transformer.test.ts index 5c68d28254..9abb5d578e 100644 --- a/lib/markdown-tree/src/__tests__/transformer.test.ts +++ b/lib/markdown-tree/src/__tests__/transformer.test.ts @@ -1,7 +1,7 @@ import { createHighlighter, type ShikiTransformer, type ThemedToken } from 'shiki'; import { describe, expect, it as baseIt } from 'vitest'; -import { dirtreeTransformer, grammar } from '../transformer.js'; -import { parseContent } from '../structure.js'; +import { parseContent } from '../structure'; +import { dirtreeTransformer, grammar } from '../transformer'; interface Fixtures { transformer: ShikiTransformer; @@ -26,7 +26,7 @@ const it = baseIt.extend({ }, transform: ({ highlighter, transformer }, use) => use((input: string) => { const [generated] = parseContent(input, '/dummy/dir', {}); - + const { tokens } = highlighter.codeToTokens(generated, { theme: 'github-light', transformers: [transformer], @@ -37,7 +37,7 @@ const it = baseIt.extend({ options: { lang: 'dirtree' } - } as any, tokens)! + } as any, tokens)!; }) }); @@ -48,9 +48,9 @@ const it = baseIt.extend({ * Also collects the colours used in each line */ function tokenJoiner(tokens: ThemedToken[][]): { - lines: string[], - colours: string[][] - } { + lines: string[]; + colours: string[][]; +} { let lineOffset = 0; const output: string[] = []; From 44d5dc3ca468de8abeb1353b89c8c9ab57904d9f Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 10 Jan 2026 11:27:04 +0800 Subject: [PATCH 10/71] Move buildtools to use tsc compile and typecheck separately --- .../src/build/__tests__/all.test.ts | 12 ++-- lib/buildtools/src/build/all.ts | 4 +- lib/buildtools/src/build/formatter.ts | 2 +- .../build/modules/__tests__/building.test.ts | 2 +- .../modules}/__tests__/tsc.test.ts | 62 +++++++++++-------- lib/buildtools/src/build/modules/tsc.ts | 6 +- .../src/commands/__tests__/build.test.ts | 27 +++++--- .../src/commands/__tests__/compile.test.ts | 44 +++++++++++++ lib/buildtools/src/commands/prebuild.ts | 7 +-- .../src/__tests__/paths/windows.test.ts | 4 ++ 10 files changed, 119 insertions(+), 51 deletions(-) rename lib/buildtools/src/{prebuild => build/modules}/__tests__/tsc.test.ts (68%) create mode 100644 lib/buildtools/src/commands/__tests__/compile.test.ts diff --git a/lib/buildtools/src/build/__tests__/all.test.ts b/lib/buildtools/src/build/__tests__/all.test.ts index a5796aecfb..a6a2e4e33a 100644 --- a/lib/buildtools/src/build/__tests__/all.test.ts +++ b/lib/buildtools/src/build/__tests__/all.test.ts @@ -3,10 +3,10 @@ import { bundlesDir, tabsDir } from '@sourceacademy/modules-repotools/getGitRoot import { afterEach, describe, expect, test, vi } from 'vitest'; import * as docs from '../../build/docs/index.js'; import * as modules from '../../build/modules/index.js'; +import * as tsc from '../../build/modules/tsc.js'; import { getCommandRunner } from '../../commands/__tests__/testingUtils.js'; import { getBuildAllCommand } from '../../commands/build.js'; import * as lint from '../../prebuild/lint.js'; -import * as tsc from '../../prebuild/tsc.js'; import * as all from '../all.js'; vi.spyOn(all, 'buildAll'); @@ -14,7 +14,7 @@ const mockedBuildBundle = vi.spyOn(modules, 'buildBundle'); const mockedBuildTab = vi.spyOn(modules, 'buildTab'); const mockedBuildSingleBundleDocs = vi.spyOn(docs, 'buildSingleBundleDocs'); -const mockedRunTsc = vi.spyOn(tsc, 'runTsc').mockResolvedValue({ +const mockedRunTsc = vi.spyOn(tsc, 'runTypechecking').mockResolvedValue({ severity: 'success', input: {} as any, results: [], @@ -70,7 +70,7 @@ describe('Test the buildAll command', () => { }); await expect(runCommand(bundlePath, '--tsc')).commandSuccess(); - expect(tsc.runTsc).toHaveBeenCalledTimes(1); + expect(tsc.runTypechecking).toHaveBeenCalledTimes(1); }); test('Regular execution for a bundle with --lint', async () => { @@ -115,7 +115,7 @@ describe('Test the buildAll command', () => { await expect(runCommand(bundlePath, '--tsc')).commandExit(); - expect(tsc.runTsc).toHaveBeenCalledTimes(1); + expect(tsc.runTypechecking).toHaveBeenCalledTimes(1); expect(modules.buildBundle).not.toHaveBeenCalled(); expect(docs.buildSingleBundleDocs).not.toHaveBeenCalled(); }); @@ -186,7 +186,7 @@ describe('Test the buildAll command', () => { }); await expect(runCommand(tabPath, '--tsc')).commandSuccess(); - expect(tsc.runTsc).toHaveBeenCalledTimes(1); + expect(tsc.runTypechecking).toHaveBeenCalledTimes(1); }); test('Regular execution for a tab with --lint', async () => { @@ -223,7 +223,7 @@ describe('Test the buildAll command', () => { await expect(runCommand(tabPath, '--tsc')).commandExit(); - expect(tsc.runTsc).toHaveBeenCalledTimes(1); + expect(tsc.runTypechecking).toHaveBeenCalledTimes(1); expect(modules.buildTab).not.toHaveBeenCalled(); }); }); diff --git a/lib/buildtools/src/build/all.ts b/lib/buildtools/src/build/all.ts index bf9bc0add5..0012955428 100644 --- a/lib/buildtools/src/build/all.ts +++ b/lib/buildtools/src/build/all.ts @@ -3,9 +3,9 @@ import { compareSeverity } from '@sourceacademy/modules-repotools/utils'; import type { LogLevel } from 'typedoc'; import type { PrebuildOptions } from '../prebuild/index.js'; import { runEslint, type LintResult } from '../prebuild/lint.js'; -import { runTsc, type TscResult } from '../prebuild/tsc.js'; import { buildSingleBundleDocs } from './docs/index.js'; import { buildBundle, buildTab } from './modules/index.js'; +import { runTypechecking, type TscResult } from './modules/tsc.js'; interface BuildAllPrebuildError { severity: 'error'; @@ -39,7 +39,7 @@ export type BuildAllResult = BuildAllPrebuildError | BuildAllBundleResult | Buil */ export async function buildAll(input: InputAsset, prebuild: PrebuildOptions, outDir: string, logLevel: LogLevel): Promise { const [tscResult, lintResult] = await Promise.all([ - prebuild.tsc ? runTsc(input, true) : Promise.resolve(undefined), + prebuild.tsc ? runTypechecking(input) : Promise.resolve(undefined), prebuild.lint ? runEslint(input) : Promise.resolve(undefined) ]); diff --git a/lib/buildtools/src/build/formatter.ts b/lib/buildtools/src/build/formatter.ts index 2fe6f02643..8666fc190b 100644 --- a/lib/buildtools/src/build/formatter.ts +++ b/lib/buildtools/src/build/formatter.ts @@ -1,7 +1,7 @@ import type { BuildResult, ResultTypeWithWarn } from '@sourceacademy/modules-repotools/types'; import chalk from 'chalk'; import { formatLintResult, type LintResult } from '../prebuild/lint.js'; -import { formatTscResult, type TscResult } from '../prebuild/tsc.js'; +import { formatTscResult, type TscResult } from './modules/tsc.js'; interface ResultsObject { tsc?: TscResult; diff --git a/lib/buildtools/src/build/modules/__tests__/building.test.ts b/lib/buildtools/src/build/modules/__tests__/building.test.ts index 7c3faf12ed..167d10375f 100644 --- a/lib/buildtools/src/build/modules/__tests__/building.test.ts +++ b/lib/buildtools/src/build/modules/__tests__/building.test.ts @@ -84,7 +84,7 @@ test('build tab', async () => { expect(fs.open).toHaveBeenCalledExactlyOnceWith(pathlib.join(outDir, 'tabs', 'tab0.js'), 'w'); function mockRequire(path: string) { - console.log(path); + // console.log(path); if (path === '@sourceacademy/modules-lib/tabs/utils') { return { defineTab: (x: any) => x diff --git a/lib/buildtools/src/prebuild/__tests__/tsc.test.ts b/lib/buildtools/src/build/modules/__tests__/tsc.test.ts similarity index 68% rename from lib/buildtools/src/prebuild/__tests__/tsc.test.ts rename to lib/buildtools/src/build/modules/__tests__/tsc.test.ts index c7eec7f010..3b510e1004 100644 --- a/lib/buildtools/src/prebuild/__tests__/tsc.test.ts +++ b/lib/buildtools/src/build/modules/__tests__/tsc.test.ts @@ -2,7 +2,7 @@ import pathlib from 'path'; import { bundlesDir, tabsDir } from '@sourceacademy/modules-repotools/getGitRoot'; import ts from 'typescript'; import { describe, expect, test, vi } from 'vitest'; -import { runTsc } from '../tsc.js'; +import { runTscCompile, runTypechecking } from '../tsc.js'; const mockedWriteFile = vi.hoisted(() => vi.fn<(arg0: string, arg1: string) => void>(() => undefined)); @@ -36,47 +36,57 @@ vi.mock(import('typescript'), async importOriginal => { }; }); -describe('Test the augmented tsc functionality', () => { - const bundlePath = pathlib.join(bundlesDir, 'test0'); - +describe(runTypechecking, () => { test('tsc on a bundle', async () => { - await runTsc({ + const bundlePath = pathlib.join(bundlesDir, 'test0'); + await runTypechecking({ type: 'bundle', directory: bundlePath, name: 'test0', manifest: {} - }, false); - - expect(ts.createProgram).toHaveBeenCalledTimes(2); - console.log(mockedWriteFile.mock.calls); - expect(mockedWriteFile).toHaveBeenCalledTimes(1); - const [[writePath]] = mockedWriteFile.mock.calls; - - expect(writePath).not.toEqual(pathlib.join(bundlePath, 'src', '__tests__', 'test0.test.js')); - }); - - test('tsc on a bundle with --noEmit', async () => { - await runTsc({ - type: 'bundle', - directory: bundlePath, - name: 'test0', - manifest: {} - }, true); + }); expect(ts.createProgram).toHaveBeenCalledTimes(1); - expect(mockedWriteFile).not.toBeCalled(); + expect(mockedWriteFile).not.toHaveBeenCalled(); }); test('tsc on a tab', async () => { const tabPath = pathlib.join(tabsDir, 'tab0'); - await runTsc({ + await runTypechecking({ type: 'tab', directory: tabPath, entryPoint: pathlib.join(tabPath, 'src', 'index.tsx'), name: 'tab0' - }, false); + }); expect(ts.createProgram).toHaveBeenCalledTimes(1); - expect(mockedWriteFile).not.toBeCalled(); + expect(mockedWriteFile).not.toHaveBeenCalled(); + }); +}); + +describe(runTscCompile, () => { + const bundlePath = pathlib.join(bundlesDir, 'test0'); + + test('tsc compile for bundle', async () => { + await runTscCompile({ + type: 'bundle', + directory: bundlePath, + name: 'test0', + manifest: {} + }); + + expect(ts.createProgram).toHaveBeenCalledOnce(); + expect(mockedWriteFile).toHaveBeenCalledOnce(); + + const [[writePath]] = mockedWriteFile.mock.calls; + + const testOutPath = pathlib.relative( + pathlib.join(bundlesDir, 'dist'), + '__tests__/test0.test.js' + ); + expect(writePath).not.toMatchPath(testOutPath); + + const indexOutPath = pathlib.relative(pathlib.join(bundlesDir, 'dist'), 'index.js'); + expect(writePath).not.toMatchPath(indexOutPath); }); }); diff --git a/lib/buildtools/src/build/modules/tsc.ts b/lib/buildtools/src/build/modules/tsc.ts index 7ad6fbe421..16ed49789d 100644 --- a/lib/buildtools/src/build/modules/tsc.ts +++ b/lib/buildtools/src/build/modules/tsc.ts @@ -83,6 +83,10 @@ function processDiagnostics(diagnostics: ts.Diagnostic[]) { }); } +// Note that in both cases, we use the createProgram overload that takes +// a configuration object rather than each parameter separately. This is +// because this is the overload we mock for testing. + /** * Run tsc but only for typechecking */ @@ -144,6 +148,7 @@ export async function runTscCompile(input: ResolvedBundle, oldProgram?: ts.Progr const segments = p.split(pathlib.posix.sep); return !segments.includes('__tests__') && !segments.includes('__mocks__'); }); + // tsc instance that does compilation // only compiles non test files const compileProgram = ts.createProgram({ @@ -154,7 +159,6 @@ export async function runTscCompile(input: ResolvedBundle, oldProgram?: ts.Progr }, oldProgram }); - compileProgram.emit(); const results = compileProgram.emit(); const diagnostics = ts.getPreEmitDiagnostics(compileProgram) diff --git a/lib/buildtools/src/commands/__tests__/build.test.ts b/lib/buildtools/src/commands/__tests__/build.test.ts index e9631be5a1..d5215af5d9 100644 --- a/lib/buildtools/src/commands/__tests__/build.test.ts +++ b/lib/buildtools/src/commands/__tests__/build.test.ts @@ -6,13 +6,13 @@ import type { BuildResult, Severity } from '@sourceacademy/modules-repotools/typ import { beforeEach, describe, expect, test, vi, type MockInstance } from 'vitest'; import * as json from '../../build/docs/json.js'; import * as modules from '../../build/modules/index.js'; +import * as tscRunner from '../../build/modules/tsc.js'; import * as lintRunner from '../../prebuild/lint.js'; -import * as tscRunner from '../../prebuild/tsc.js'; import * as commands from '../build.js'; import { getCommandRunner } from './testingUtils.js'; const mockedRunEslint = vi.spyOn(lintRunner, 'runEslint'); -const mockedRunTsc = vi.spyOn(tscRunner, 'runTsc'); +const mockedRunTsc = vi.spyOn(tscRunner, 'runTypechecking'); vi.mock(import('typedoc'), async importOriginal => { const original = await importOriginal(); @@ -60,6 +60,7 @@ type BuildFunctionsFilter> = { * @param cmdArgs Arguments to pass to the command handler */ function testBuildCommand>( + this: boolean | void, commandName: string, getter: () => Command, obj: T, @@ -88,7 +89,9 @@ function testBuildCommand>( } } - describe(`Testing ${commandName} command`, { timeout: 10000 }, () => { + const describer = this ? describe.skip : describe; + + describer(`Testing ${commandName} command`, { timeout: 10000 }, () => { const mockedBuilder = vi.spyOn(obj, funcName as any) as MockInstance<() => Promise>; const builder = obj[funcName]; const runCommand = getCommandRunner(getter); @@ -209,7 +212,7 @@ function testBuildCommand>( input: {} as any }); await expect(runCommand(...cmdArgs, '--tsc')).commandSuccess(); - expect(tscRunner.runTsc).toHaveBeenCalledTimes(1); + expect(tscRunner.runTypechecking).toHaveBeenCalledTimes(1); expect(mockedBuilder).toHaveBeenCalledTimes(1); assertDirectories(true); }); @@ -221,7 +224,7 @@ function testBuildCommand>( input: {} as any }); await expect(runCommand(...cmdArgs, '--tsc')).commandExit(); - expect(tscRunner.runTsc).toHaveBeenCalledTimes(1); + expect(tscRunner.runTypechecking).toHaveBeenCalledTimes(1); expect(mockedBuilder).toHaveBeenCalledTimes(0); assertDirectories(false); }); @@ -233,7 +236,7 @@ function testBuildCommand>( input: {} as any }); await expect(runCommand(...cmdArgs, '--tsc')).commandSuccess(); - expect(tscRunner.runTsc).toHaveBeenCalledTimes(1); + expect(tscRunner.runTypechecking).toHaveBeenCalledTimes(1); expect(mockedBuilder).toHaveBeenCalledTimes(1); assertDirectories(true); }); @@ -247,7 +250,7 @@ function testBuildCommand>( input: {} as any }); await expect(runCommand(...cmdArgs, '--tsc')).commandExit(); - expect(tscRunner.runTsc).toHaveBeenCalledTimes(1); + expect(tscRunner.runTypechecking).toHaveBeenCalledTimes(1); expect(mockedBuilder).toHaveBeenCalledTimes(0); assertDirectories(false); } finally { @@ -273,7 +276,7 @@ function testBuildCommand>( await expect(runCommand(...cmdArgs, '--lint', '--tsc')).commandSuccess(); expect(lintRunner.runEslint).toHaveBeenCalledTimes(1); - expect(tscRunner.runTsc).toHaveBeenCalledTimes(1); + expect(tscRunner.runTypechecking).toHaveBeenCalledTimes(1); expect(mockedBuilder).toHaveBeenCalledTimes(1); assertDirectories(true); }); @@ -281,9 +284,13 @@ function testBuildCommand>( }); } +testBuildCommand.skip = function(...args: Parameters) { + return testBuildCommand.call(true, ...args); +} + const bundlePath = pathlib.join(bundlesDir, 'test0'); const tabPath = pathlib.join(tabsDir, 'tab0'); testBuildCommand('Docs', commands.getBuildDocsCommand, json, 'buildJson', false, ['jsons'], bundlePath); -testBuildCommand('Bundles', commands.getBuildBundleCommand, modules, 'buildBundle', true, ['bundles'], bundlePath); -testBuildCommand('Tabs', commands.getBuildTabCommand, modules, 'buildTab', true, ['tabs'], tabPath); +testBuildCommand.skip('Bundles', commands.getBuildBundleCommand, modules, 'buildBundle', true, ['bundles'], bundlePath); +testBuildCommand.skip('Tabs', commands.getBuildTabCommand, modules, 'buildTab', true, ['tabs'], tabPath); diff --git a/lib/buildtools/src/commands/__tests__/compile.test.ts b/lib/buildtools/src/commands/__tests__/compile.test.ts new file mode 100644 index 0000000000..499a4db188 --- /dev/null +++ b/lib/buildtools/src/commands/__tests__/compile.test.ts @@ -0,0 +1,44 @@ +import pathlib from 'path'; +import { bundlesDir, tabsDir } from '@sourceacademy/modules-repotools/getGitRoot'; +import type { ResolvedBundle, ResolvedTab } from '@sourceacademy/modules-repotools/types'; +import { describe, expect, test, vi } from 'vitest'; +import * as tsc from '../../build/modules/tsc.js'; +import { getCompileCommand } from '../build.js'; +import { getCommandRunner } from './testingUtils.js'; + +const mockedTscCompile = vi.spyOn(tsc, 'runTscCompile'); + +describe('Test compile command', () => { + const runCommand = getCommandRunner(getCompileCommand); + + test('Compile a bundle successfully', async () => { + const inputBundle: ResolvedBundle = { + directory: pathlib.join(bundlesDir, 'test0'), + name: 'test0', + manifest: {}, + type: 'bundle' + }; + + mockedTscCompile.mockResolvedValueOnce({ + severity: 'success', + results: [], + input: inputBundle + }); + + await expect(runCommand(inputBundle.directory)).commandSuccess(); + expect(mockedTscCompile).toHaveBeenCalledOnce(); + }); + + test('Compile a tab', async () => { + const tabDir = pathlib.join(tabsDir, 'tab0'); + const inputTab: ResolvedTab = { + type: 'tab', + directory: tabDir, + entryPoint: pathlib.join(tabDir, 'src', 'index.tsx'), + name: 'tab0' + }; + + await expect(runCommand(inputTab.directory)).commandExit(); + expect(mockedTscCompile).not.toHaveBeenCalled(); + }); +}); diff --git a/lib/buildtools/src/commands/prebuild.ts b/lib/buildtools/src/commands/prebuild.ts index 294cbe50e4..7643986108 100644 --- a/lib/buildtools/src/commands/prebuild.ts +++ b/lib/buildtools/src/commands/prebuild.ts @@ -5,9 +5,9 @@ import { resolveEitherBundleOrTab } from '@sourceacademy/modules-repotools/manif import { divideAndRound } from '@sourceacademy/modules-repotools/utils'; import chalk from 'chalk'; import { ESLint } from 'eslint'; +import { formatTscResult, runTypechecking } from '../build/modules/tsc.js'; import { runPrebuild } from '../prebuild/index.js'; import { formatLintResult, lintGlobal, runEslint } from '../prebuild/lint.js'; -import { formatTscResult, runTsc } from '../prebuild/tsc.js'; import { logCommandErrorAndExit } from './commandUtils.js'; export const concurrencyOption = new Option('--concurrency ') @@ -119,9 +119,8 @@ export const getLintGlobalCommand = () => new Command('lintglobal') export const getTscCommand = () => new Command('tsc') .description('Run tsc for the given directory, or the current directory if no directory is specified') .argument('[directory]', 'Directory to run tsc in', process.cwd()) - .option('--no-emit', 'Prevent the typescript compiler from outputting files regardless of the tsconfig setting') .option('--ci', process.env.CI) - .action(async (directory, { emit, ci }) => { + .action(async (directory, { ci }) => { const fullyResolved = pathlib.resolve(directory); const resolveResult = await resolveEitherBundleOrTab(fullyResolved); @@ -133,7 +132,7 @@ export const getTscCommand = () => new Command('tsc') logCommandErrorAndExit(resolveResult); } - const result = await runTsc(resolveResult.asset, !emit); + const result = await runTypechecking(resolveResult.asset); console.log(formatTscResult(result)); switch (result.severity) { diff --git a/lib/repotools/src/__tests__/paths/windows.test.ts b/lib/repotools/src/__tests__/paths/windows.test.ts index 207c751a9f..2199b91f63 100644 --- a/lib/repotools/src/__tests__/paths/windows.test.ts +++ b/lib/repotools/src/__tests__/paths/windows.test.ts @@ -41,4 +41,8 @@ describe('Test convertToPosixPath with Windows paths', () => { test('Converts Windows root paths correctly', () => { expect(convertToPosixPath('D:\\')).toEqual('/D'); }); + + test('Converts Windows absolute path correctly', () => { + expect(convertToPosixPath('E:\\folder\\subfolder\\file.txt')).toEqual('/E/folder/subfolder/file.txt'); + }); }); From ddcd3847181931f17421c73992852ba391bdc8db Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 10 Jan 2026 15:46:31 +0800 Subject: [PATCH 11/71] Add tests for ensuring that typedoc paths are processed correctly --- .../src/build/docs/__tests__/paths.test.ts | 20 +++++++++++++++ lib/buildtools/src/build/docs/typedoc.ts | 25 +++++++++++++------ 2 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 lib/buildtools/src/build/docs/__tests__/paths.test.ts diff --git a/lib/buildtools/src/build/docs/__tests__/paths.test.ts b/lib/buildtools/src/build/docs/__tests__/paths.test.ts new file mode 100644 index 0000000000..bdddbb0cf1 --- /dev/null +++ b/lib/buildtools/src/build/docs/__tests__/paths.test.ts @@ -0,0 +1,20 @@ +import { describe, expect, it, vi } from 'vitest'; +import { convertToTypedocPath } from '../typedoc.js'; + +vi.mock(import('path'), async importOriginal => { + const { win32, posix } = await importOriginal(); + return { + default: win32, + posix, + }; +}); + +describe(convertToTypedocPath, () => { + it('works with rooted windows paths', () => { + expect(convertToTypedocPath('C:\\source\\source_academy\\modules')).toEqual('C:/source/source_academy/modules'); + }); + + it('works with unrooted windows paths', () => { + expect(convertToTypedocPath('source\\source_academy\\modules')).toEqual('source/source_academy/modules'); + }); +}); diff --git a/lib/buildtools/src/build/docs/typedoc.ts b/lib/buildtools/src/build/docs/typedoc.ts index 292ce59009..54563079ed 100644 --- a/lib/buildtools/src/build/docs/typedoc.ts +++ b/lib/buildtools/src/build/docs/typedoc.ts @@ -1,6 +1,5 @@ import pathlib from 'path'; import type { ResolvedBundle } from '@sourceacademy/modules-repotools/types'; -import { convertToPosixPath } from '@sourceacademy/modules-repotools/utils'; import * as td from 'typedoc'; // #region commonOpts @@ -14,21 +13,31 @@ const typedocPackageOptions: td.Configuration.TypeDocOptions = { }; // #endregion commonOpts +/** + * Typedoc wants the format of each path to be that of the OS its running on, but with + * POSIX path separators. This function converts any path to that format. + */ +export function convertToTypedocPath(p: string) { + return p.split(pathlib.sep).join(pathlib.posix.sep); +} + /** * Initialize Typedoc to build the JSON documentation for each bundle */ export async function initTypedocForJson(bundle: ResolvedBundle, logLevel: td.LogLevel) { - // TypeDoc expects POSIX paths - const directoryAsPosix = convertToPosixPath(bundle.directory); + const directoryAsPosix = convertToTypedocPath(bundle.directory); + const app = await td.Application.bootstrapWithPlugins({ ...typedocPackageOptions, name: bundle.name, logLevel, - entryPoints: [`${directoryAsPosix}/src/index.ts`], - tsconfig: `${directoryAsPosix}/tsconfig.json`, + entryPoints: [ + pathlib.posix.join(directoryAsPosix, 'src', 'index.ts') + ], + tsconfig: pathlib.posix.join(directoryAsPosix, 'tsconfig.json'), }); - app.converter.on(td.Converter.EVENT_CREATE_SIGNATURE, (ctx, signature) => { + app.converter.on(td.Converter.EVENT_CREATE_SIGNATURE, (_ctx, signature) => { // Make sure that type guards get replaced with the appropriate intrinsic types if (signature.type instanceof td.PredicateType) { if (signature.type.asserts) { @@ -53,8 +62,8 @@ export function initTypedocForHtml(bundles: Record, logL logLevel, entryPoints: Object.values(bundles).map(({ directory }) => { // TypeDoc expects POSIX paths - const directoryAsPosix = convertToPosixPath(directory); - return `${directoryAsPosix}/dist/docs.json`; + const directoryAsPosix = convertToTypedocPath(directory); + return pathlib.posix.join(directoryAsPosix, 'dist', 'docs.json'); }), entryPointStrategy: 'merge', readme: pathlib.join(import.meta.dirname, 'docsreadme.md'), From 5a8b123ba0f25b13156f2f8effb69f019f982bec Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 10 Jan 2026 15:46:51 +0800 Subject: [PATCH 12/71] Add tests to ensure that typeguards are properly rendered --- .../src/bundles/test0/src/index.ts | 4 + .../src/build/docs/__tests__/json.test.ts | 104 ++++++++---------- .../src/commands/__tests__/build.test.ts | 4 +- 3 files changed, 54 insertions(+), 58 deletions(-) diff --git a/lib/__test_mocks__/src/bundles/test0/src/index.ts b/lib/__test_mocks__/src/bundles/test0/src/index.ts index 7a93a435ab..af8549788d 100644 --- a/lib/__test_mocks__/src/bundles/test0/src/index.ts +++ b/lib/__test_mocks__/src/bundles/test0/src/index.ts @@ -19,3 +19,7 @@ export function test_function(_param0: string) { export function test_function2() { return context.moduleContexts.test0.state.data; } + +export function is_number(x: unknown): x is number { + return typeof x === 'number'; +} diff --git a/lib/buildtools/src/build/docs/__tests__/json.test.ts b/lib/buildtools/src/build/docs/__tests__/json.test.ts index 0b978d997f..78258dc9fc 100644 --- a/lib/buildtools/src/build/docs/__tests__/json.test.ts +++ b/lib/buildtools/src/build/docs/__tests__/json.test.ts @@ -25,38 +25,48 @@ describe(buildJson, () => { type: 'bundle', name: 'test0', manifest: {}, - directory: `${bundlesDir}/test0` + directory: pathlib.join(bundlesDir, 'test0') }), project: async ({ testBundle }, use) => { - const app = await initTypedocForJson(testBundle, td.LogLevel.None); + const app = await initTypedocForJson(testBundle, td.LogLevel.Info); const project = await app.convert(); use(project!); } }); - test('Regular function', async ({ testBundle, project }) => { + test('Regular execution', async ({ testBundle, project }) => { const result = await buildJson(testBundle, outDir, project); expect(result.severity).toEqual('success'); expect(fs.writeFile).toHaveBeenCalledOnce(); const { calls: [[path, data]] } = mockedWriteFile.mock; expect(path).toEqual(pathlib.join(outDir, 'jsons', 'test0.json')); - expect(data).toMatchInlineSnapshot(` - "{ - "test_function": { - "kind": "function", - "name": "test_function", - "description": "

This is just some test function

", - "params": [ - [ - "_param0", - "string" - ] - ], - "retType": "number" - } - }" - `); + + const parsed = JSON.parse(data as string); + + expect(parsed).toHaveProperty('test_function', { + kind: 'function', + name: 'test_function', + description: '

This is just some test function

', + params: [ + ['_param0', 'string'] + ], + retType: 'number' + }); + + expect(parsed).toHaveProperty('is_number', { + kind: 'function', + name: 'is_number', + description: '

No description available

', + params: [ + ['x', 'unknown'] + ], + // validate that type guards have their return types correctly parsed + retType: 'boolean' + }); + + // @hidden or @internal tags should be respected + expect(parsed).not.toHaveProperty('test_function2'); }); test('Encountering an unrecognized type', async ({ testBundle, project }) => { @@ -74,25 +84,9 @@ describe(buildJson, () => { expect(fs.writeFile).toHaveBeenCalledOnce(); const { calls: [[path, data]] } = mockedWriteFile.mock; expect(path).toEqual(pathlib.join(outDir, 'jsons', 'test0.json')); - expect(data).toMatchInlineSnapshot(` - "{ - "test_function": { - "kind": "function", - "name": "test_function", - "description": "

This is just some test function

", - "params": [ - [ - "_param0", - "string" - ] - ], - "retType": "number" - }, - "TestType": { - "kind": "unknown" - } - }" - `); + + const parsed = JSON.parse(data as string); + expect(parsed).toHaveProperty('TestType', { kind: 'unknown' }); }); test('TypeAliases are ignored for JSON building', async ({ testBundle, project }) => { @@ -107,23 +101,19 @@ describe(buildJson, () => { expect(fs.writeFile).toHaveBeenCalledOnce(); const { calls: [[path, data]] } = mockedWriteFile.mock; + expect(path).toEqual(pathlib.join(outDir, 'jsons', 'test0.json')); - expect(data).toMatchInlineSnapshot(` - "{ - "test_function": { - "kind": "function", - "name": "test_function", - "description": "

This is just some test function

", - "params": [ - [ - "_param0", - "string" - ] - ], - "retType": "number" - } - }" - `); + + const parsed = JSON.parse(data as string); + expect(parsed).toHaveProperty('test_function', { + kind: 'function', + name: 'test_function', + description: '

This is just some test function

', + params: [ + ['_param0', 'string'] + ], + retType: 'number' + }); }); }); @@ -144,7 +134,8 @@ describe('Test parsers', () => { const signature = new td.SignatureReflection('testFunction', td.ReflectionKind.CallSignature, decl); signature.type = new td.IntrinsicType('void'); signature.comment = { - summary: [{ kind:'text', text: 'This is a summary' }] + summary: [{ kind:'text', text: 'This is a summary' }], + blockTags: [] as td.CommentTag[] } as td.Comment; decl.signatures = [signature]; @@ -241,7 +232,8 @@ describe('Test parsers', () => { const decl = new td.DeclarationReflection('testVar', td.ReflectionKind.Variable); decl.type = new td.IntrinsicType('string'); decl.comment = { - summary: [{ kind: 'text', text: 'This is a summary' }] + summary: [{ kind: 'text', text: 'This is a summary' }], + blockTags: [] as td.CommentTag[] } as td.Comment; const result = variableParser(decl); diff --git a/lib/buildtools/src/commands/__tests__/build.test.ts b/lib/buildtools/src/commands/__tests__/build.test.ts index d5215af5d9..6311300dc7 100644 --- a/lib/buildtools/src/commands/__tests__/build.test.ts +++ b/lib/buildtools/src/commands/__tests__/build.test.ts @@ -284,9 +284,9 @@ function testBuildCommand>( }); } -testBuildCommand.skip = function(...args: Parameters) { +testBuildCommand.skip = function (...args: Parameters) { return testBuildCommand.call(true, ...args); -} +}; const bundlePath = pathlib.join(bundlesDir, 'test0'); const tabPath = pathlib.join(tabsDir, 'tab0'); From e87456f964c7aeaa517825371a468f421ff5f4aa Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 10 Jan 2026 16:00:10 +0800 Subject: [PATCH 13/71] Add the compile command to bundles --- lib/buildtools/src/commands/main.ts | 3 ++- lib/buildtools/workspacer.py | 22 +++++++++++++++++----- src/bundles/ar/package.json | 2 +- src/bundles/arcade_2d/package.json | 2 +- src/bundles/binary_tree/package.json | 2 +- src/bundles/communication/package.json | 2 +- src/bundles/copy_gc/package.json | 2 +- src/bundles/csg/package.json | 2 +- src/bundles/curve/package.json | 2 +- src/bundles/game/package.json | 2 +- src/bundles/mark_sweep/package.json | 2 +- src/bundles/midi/package.json | 2 +- src/bundles/nbody/package.json | 2 +- src/bundles/painter/package.json | 2 +- src/bundles/physics_2d/package.json | 2 +- src/bundles/pix_n_flix/package.json | 2 +- src/bundles/plotly/package.json | 2 +- src/bundles/remote_execution/package.json | 2 +- src/bundles/repeat/package.json | 2 +- src/bundles/repl/package.json | 2 +- src/bundles/robot_simulation/package.json | 2 +- src/bundles/rune/package.json | 2 +- src/bundles/rune_in_words/package.json | 2 +- src/bundles/scrabble/package.json | 2 +- src/bundles/sound/package.json | 2 +- src/bundles/sound_matrix/package.json | 2 +- src/bundles/stereo_sound/package.json | 2 +- src/bundles/unittest/package.json | 2 +- src/bundles/unity_academy/package.json | 2 +- src/bundles/wasm/package.json | 2 +- 30 files changed, 47 insertions(+), 34 deletions(-) diff --git a/lib/buildtools/src/commands/main.ts b/lib/buildtools/src/commands/main.ts index 1aad7edcd2..9bdb33324c 100644 --- a/lib/buildtools/src/commands/main.ts +++ b/lib/buildtools/src/commands/main.ts @@ -1,5 +1,5 @@ import { Command } from '@commander-js/extra-typings'; -import { getBuildCommand, getBuildHtmlCommand, getManifestCommand } from './build.js'; +import { getBuildCommand, getBuildHtmlCommand, getCompileCommand, getManifestCommand } from './build.js'; import { getListCommand, getValidateCommand } from './list.js'; import { getLintCommand, getLintGlobalCommand, getPrebuildAllCommand, getTscCommand } from './prebuild.js'; import getHttpServerCommand from './server.js'; @@ -9,6 +9,7 @@ import { getTestAllCommand, getTestCommand } from './testing.js'; const commands: (() => Command)[] = [ getBuildCommand, getBuildHtmlCommand, + getCompileCommand, getHttpServerCommand, getLintCommand, getLintGlobalCommand, diff --git a/lib/buildtools/workspacer.py b/lib/buildtools/workspacer.py index 433f215b64..76ea97093a 100644 --- a/lib/buildtools/workspacer.py +++ b/lib/buildtools/workspacer.py @@ -28,7 +28,17 @@ def get_assets(git_root: str, asset: Literal['bundle', 'tab']): continue yield name, full_path -def update_json(git_root: str, asset: Literal['bundle', 'tab'], file_name: Literal['package','tsconfig'], updater: Callable[[str, str, Any], Any]): +def update_jsons(git_root: str, asset: Literal['bundle', 'tab'], file_name: Literal['package','tsconfig'], updater: Callable[[str, str, Any], Any]): + """ + For each bundle or tab (as specified by the asset parameter), load either the tsconfig.json or package.json (as specified by the file_name parameter) + and use the provided updater function to modify its contents. Then save the modified JSON object back to the file it was read from. + + :param git_root: Path to the root of the git repository + :param asset: Asset type. Either 'bundle' or 'tab'. + :param file_name: File to modify. Either 'tsconfig', for tsconfig.jsons or 'package' for package.jsons + :param updater: Function that gets passed the JSON object that is either the tsconfig.json or package.json + for the bundle/tab being processed. It should return the JSON object that represents the new tsconfig or package.json value. + """ for name, full_path in get_assets(git_root, asset): try: with open(f'{full_path}/{file_name}.json') as file: @@ -36,22 +46,24 @@ def update_json(git_root: str, asset: Literal['bundle', 'tab'], file_name: Liter updated = updater(name, full_path, original) if not updated: - raise RuntimeError(f'Updated returned an empty object for {asset} {name}') + raise RuntimeError(f'Updater returned an empty object for {asset} {name}') with open(f'{full_path}/{file_name}.json', 'w') as file: json.dump(updated, file, indent=2) file.write('\n') except Exception as e: - print(f'{e} occurred with {full_path}/{file_name}.json') + print(f'Error occurred with {full_path}/{file_name}.json: {e}') async def main(): git_root = await get_git_root() def updater(name: str, full_path: str, obj: Any): - del obj['compilerOptions']['noEmit'] + if 'postinstall' in obj['scripts']: + obj['scripts']['postinstall'] = 'buildtools compile' + return obj - update_json(git_root, 'bundle', 'tsconfig', updater) + update_jsons(git_root, 'bundle', 'package', updater) if __name__ == '__main__': aio.run(main()) diff --git a/src/bundles/ar/package.json b/src/bundles/ar/package.json index 8382a0aa05..e582d2740d 100644 --- a/src/bundles/ar/package.json +++ b/src/bundles/ar/package.json @@ -25,7 +25,7 @@ "lint": "buildtools lint .", "tsc": "buildtools tsc .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/arcade_2d/package.json b/src/bundles/arcade_2d/package.json index 14f9e239c1..85e18de9be 100644 --- a/src/bundles/arcade_2d/package.json +++ b/src/bundles/arcade_2d/package.json @@ -20,7 +20,7 @@ "lint": "buildtools lint .", "tsc": "buildtools tsc .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/binary_tree/package.json b/src/bundles/binary_tree/package.json index f32eb7d58d..c5f6417e61 100644 --- a/src/bundles/binary_tree/package.json +++ b/src/bundles/binary_tree/package.json @@ -19,7 +19,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/communication/package.json b/src/bundles/communication/package.json index 9bbc7a0f5b..76cda1bc53 100644 --- a/src/bundles/communication/package.json +++ b/src/bundles/communication/package.json @@ -22,7 +22,7 @@ "test": "buildtools test --project .", "tsc": "buildtools tsc .", "lint": "buildtools lint .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/copy_gc/package.json b/src/bundles/copy_gc/package.json index 9907088001..7119962f82 100644 --- a/src/bundles/copy_gc/package.json +++ b/src/bundles/copy_gc/package.json @@ -16,7 +16,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/csg/package.json b/src/bundles/csg/package.json index 65ee3d01a6..2d09c42ba6 100644 --- a/src/bundles/csg/package.json +++ b/src/bundles/csg/package.json @@ -23,7 +23,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/curve/package.json b/src/bundles/curve/package.json index 30dfde69b5..777a139381 100644 --- a/src/bundles/curve/package.json +++ b/src/bundles/curve/package.json @@ -24,7 +24,7 @@ "prepare": "yarn tsc", "test": "buildtools test --project .", "tsc": "buildtools tsc .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/game/package.json b/src/bundles/game/package.json index 1821c11faf..d2cb512aca 100644 --- a/src/bundles/game/package.json +++ b/src/bundles/game/package.json @@ -20,7 +20,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/mark_sweep/package.json b/src/bundles/mark_sweep/package.json index cc197f77aa..69e1990bb9 100644 --- a/src/bundles/mark_sweep/package.json +++ b/src/bundles/mark_sweep/package.json @@ -16,7 +16,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/midi/package.json b/src/bundles/midi/package.json index a90a40502e..fbc592149e 100644 --- a/src/bundles/midi/package.json +++ b/src/bundles/midi/package.json @@ -16,7 +16,7 @@ "prepare": "yarn tsc", "tsc": "buildtools tsc .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "exports": { diff --git a/src/bundles/nbody/package.json b/src/bundles/nbody/package.json index cbf4d4f724..7b0cdc5e48 100644 --- a/src/bundles/nbody/package.json +++ b/src/bundles/nbody/package.json @@ -23,7 +23,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/painter/package.json b/src/bundles/painter/package.json index 0fd76367ab..913d66234d 100644 --- a/src/bundles/painter/package.json +++ b/src/bundles/painter/package.json @@ -21,7 +21,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/physics_2d/package.json b/src/bundles/physics_2d/package.json index 5ba512a551..2dbea63753 100644 --- a/src/bundles/physics_2d/package.json +++ b/src/bundles/physics_2d/package.json @@ -20,7 +20,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/pix_n_flix/package.json b/src/bundles/pix_n_flix/package.json index 14bcafe594..7ddff98142 100644 --- a/src/bundles/pix_n_flix/package.json +++ b/src/bundles/pix_n_flix/package.json @@ -23,7 +23,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/plotly/package.json b/src/bundles/plotly/package.json index 36536a2cc4..e91a715c1c 100644 --- a/src/bundles/plotly/package.json +++ b/src/bundles/plotly/package.json @@ -23,7 +23,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/remote_execution/package.json b/src/bundles/remote_execution/package.json index 9a3aa72a61..3cf279b102 100644 --- a/src/bundles/remote_execution/package.json +++ b/src/bundles/remote_execution/package.json @@ -19,7 +19,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/repeat/package.json b/src/bundles/repeat/package.json index ba7ff6d790..f65d342dab 100644 --- a/src/bundles/repeat/package.json +++ b/src/bundles/repeat/package.json @@ -16,7 +16,7 @@ "test": "buildtools test --project .", "tsc": "buildtools tsc .", "lint": "buildtools lint .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/repl/package.json b/src/bundles/repl/package.json index a0561d4c53..1ef1955cdd 100644 --- a/src/bundles/repl/package.json +++ b/src/bundles/repl/package.json @@ -19,7 +19,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/robot_simulation/package.json b/src/bundles/robot_simulation/package.json index bc10827e5f..84a313480e 100644 --- a/src/bundles/robot_simulation/package.json +++ b/src/bundles/robot_simulation/package.json @@ -24,7 +24,7 @@ "test": "buildtools test --project .", "tsc": "buildtools tsc .", "lint": "buildtools lint .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/rune/package.json b/src/bundles/rune/package.json index 51e90fecb9..4164568546 100644 --- a/src/bundles/rune/package.json +++ b/src/bundles/rune/package.json @@ -21,7 +21,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/rune_in_words/package.json b/src/bundles/rune_in_words/package.json index 1205da91bc..941518069d 100644 --- a/src/bundles/rune_in_words/package.json +++ b/src/bundles/rune_in_words/package.json @@ -16,7 +16,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/scrabble/package.json b/src/bundles/scrabble/package.json index 50619874a9..baa402eebe 100644 --- a/src/bundles/scrabble/package.json +++ b/src/bundles/scrabble/package.json @@ -16,7 +16,7 @@ "test": "buildtools test --project .", "tsc": "buildtools tsc .", "lint": "buildtools lint .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/sound/package.json b/src/bundles/sound/package.json index f4a1aa5e8f..39f689e5cf 100644 --- a/src/bundles/sound/package.json +++ b/src/bundles/sound/package.json @@ -23,7 +23,7 @@ "lint": "buildtools lint .", "tsc": "buildtools tsc .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/sound_matrix/package.json b/src/bundles/sound_matrix/package.json index 120f48dec8..f1f3a570f7 100644 --- a/src/bundles/sound_matrix/package.json +++ b/src/bundles/sound_matrix/package.json @@ -19,7 +19,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/stereo_sound/package.json b/src/bundles/stereo_sound/package.json index 66e50b406f..5dd89cbf4b 100644 --- a/src/bundles/stereo_sound/package.json +++ b/src/bundles/stereo_sound/package.json @@ -20,7 +20,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/unittest/package.json b/src/bundles/unittest/package.json index 99762a0ced..17d1ad09d6 100644 --- a/src/bundles/unittest/package.json +++ b/src/bundles/unittest/package.json @@ -21,7 +21,7 @@ "test": "buildtools test --project .", "tsc": "buildtools tsc .", "lint": "buildtools lint .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/unity_academy/package.json b/src/bundles/unity_academy/package.json index 8339ae4610..9ac91ad3e3 100644 --- a/src/bundles/unity_academy/package.json +++ b/src/bundles/unity_academy/package.json @@ -24,7 +24,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { diff --git a/src/bundles/wasm/package.json b/src/bundles/wasm/package.json index d6d9962782..9410572f1f 100644 --- a/src/bundles/wasm/package.json +++ b/src/bundles/wasm/package.json @@ -20,7 +20,7 @@ "build": "buildtools build bundle .", "lint": "buildtools lint .", "test": "buildtools test --project .", - "postinstall": "yarn tsc", + "postinstall": "buildtools compile", "serve": "yarn buildtools serve" }, "scripts-info": { From 8a1f40c6a7a7786064c12b1c01e5ceb4454a3bc9 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 10 Jan 2026 17:01:56 +0800 Subject: [PATCH 14/71] Update eslint-plugin-json version --- lib/lintplugin/package.json | 2 +- yarn.lock | 51 ++----------------------------------- 2 files changed, 3 insertions(+), 50 deletions(-) diff --git a/lib/lintplugin/package.json b/lib/lintplugin/package.json index f449756fff..7b95167b4d 100644 --- a/lib/lintplugin/package.json +++ b/lib/lintplugin/package.json @@ -34,7 +34,7 @@ "@typescript-eslint/utils": "^8.39.0", "@vitest/eslint-plugin": "^1.3.4", "eslint-plugin-import": "^2.32.0", - "eslint-plugin-jsdoc": "^51.3.1", + "eslint-plugin-jsdoc": "^61.5.0", "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.1.0", "globals": "^15.11.0", diff --git a/yarn.lock b/yarn.lock index 461818b605..4bb7b0db5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2008,19 +2008,6 @@ __metadata: languageName: node linkType: hard -"@es-joy/jsdoccomment@npm:~0.52.0": - version: 0.52.0 - resolution: "@es-joy/jsdoccomment@npm:0.52.0" - dependencies: - "@types/estree": "npm:^1.0.8" - "@typescript-eslint/types": "npm:^8.34.1" - comment-parser: "npm:1.4.1" - esquery: "npm:^1.6.0" - jsdoc-type-pratt-parser: "npm:~4.1.0" - checksum: 10c0/4def78060ef58859f31757b9d30c4939fc33e7d9ee85637a7f568c1d209c33aa0abd2cf5a3a4f3662ec5b12b85ecff2f2035d809dc93b9382a31a6dfb200d83c - languageName: node - linkType: hard - "@es-joy/jsdoccomment@npm:~0.76.0": version: 0.76.0 resolution: "@es-joy/jsdoccomment@npm:0.76.0" @@ -4575,7 +4562,7 @@ __metadata: "@vitest/eslint-plugin": "npm:^1.3.4" eslint: "npm:^9.35.0" eslint-plugin-import: "npm:^2.32.0" - eslint-plugin-jsdoc: "npm:^51.3.1" + eslint-plugin-jsdoc: "npm:^61.5.0" eslint-plugin-react: "npm:^7.37.4" eslint-plugin-react-hooks: "npm:^5.1.0" globals: "npm:^15.11.0" @@ -6059,13 +6046,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:^8.34.1": - version: 8.35.0 - resolution: "@typescript-eslint/types@npm:8.35.0" - checksum: 10c0/a2711a932680805e83252b5d7c55ac30437bdc4d40c444606cf6ccb6ba23a682da015ec03c64635e77bf733f84d9bb76810bf4f7177fd3a660db8a2c8a05e845 - languageName: node - linkType: hard - "@typescript-eslint/types@npm:^8.46.0": version: 8.50.1 resolution: "@typescript-eslint/types@npm:8.50.1" @@ -9969,26 +9949,6 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-jsdoc@npm:^51.3.1": - version: 51.4.1 - resolution: "eslint-plugin-jsdoc@npm:51.4.1" - dependencies: - "@es-joy/jsdoccomment": "npm:~0.52.0" - are-docs-informative: "npm:^0.0.2" - comment-parser: "npm:1.4.1" - debug: "npm:^4.4.1" - escape-string-regexp: "npm:^4.0.0" - espree: "npm:^10.4.0" - esquery: "npm:^1.6.0" - parse-imports-exports: "npm:^0.2.4" - semver: "npm:^7.7.2" - spdx-expression-parse: "npm:^4.0.0" - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10c0/2dc8063f810984bca1ec2cbe4fa4cfa6948a4e6340bfc817c30d603fd7a85bc11375c0a45d6a1825fa28f1bf1c454f98aed74041b16bc6b5c7077ea58c05ff0a - languageName: node - linkType: hard - "eslint-plugin-jsdoc@npm:^61.5.0": version: 61.5.0 resolution: "eslint-plugin-jsdoc@npm:61.5.0" @@ -12348,13 +12308,6 @@ __metadata: languageName: node linkType: hard -"jsdoc-type-pratt-parser@npm:~4.1.0": - version: 4.1.0 - resolution: "jsdoc-type-pratt-parser@npm:4.1.0" - checksum: 10c0/7700372d2e733a32f7ea0a1df9cec6752321a5345c11a91b2ab478a031a426e934f16d5c1f15c8566c7b2c10af9f27892a29c2c789039f595470e929a4aa60ea - languageName: node - linkType: hard - "jsdoc-type-pratt-parser@npm:~6.10.0": version: 6.10.0 resolution: "jsdoc-type-pratt-parser@npm:6.10.0" @@ -16264,7 +16217,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.7.2": +"semver@npm:^7.1.1, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": version: 7.7.2 resolution: "semver@npm:7.7.2" bin: From 68dee49a3156feaaeb0fc8cde6ddec52e4e07f66 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 10 Jan 2026 17:02:13 +0800 Subject: [PATCH 15/71] Update code examples to comply with linting --- src/bundles/arcade_2d/src/functions.ts | 44 +++++++++---------- src/bundles/binary_tree/src/functions.ts | 14 +++--- src/bundles/plotly/src/functions.ts | 15 +++---- src/bundles/repeat/src/functions.ts | 6 +-- .../robot_simulation/src/helper_functions.ts | 22 +++++----- 5 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/bundles/arcade_2d/src/functions.ts b/src/bundles/arcade_2d/src/functions.ts index fea107f3e9..bb3398a299 100644 --- a/src/bundles/arcade_2d/src/functions.ts +++ b/src/bundles/arcade_2d/src/functions.ts @@ -156,7 +156,7 @@ export function create_text(text: string): TextGameObject { /** * Creates a GameObject that contains a Sprite image reference. * Source Academy assets can be used by specifying path without the prepend. - * Source Academy assets can be found at https://source-academy-assets.s3-ap-southeast-1.amazonaws.com/ with Ctrl+f ".png". + * Source Academy assets can be found at https://source-academy-assets.s3-ap-southeast-1.amazonaws.com/ with Ctrl+f '.png'. * Phaser assets can be found at https://labs.phaser.io/assets/. * If Phaser assets are unavailable, go to https://github.com/photonstorm/phaser3-examples/tree/master/public/assets * to get the asset path and append it to `https://labs.phaser.io/assets/`. @@ -165,8 +165,8 @@ export function create_text(text: string): TextGameObject { * @param image_url The image URL of the sprite * @example * ``` - * const shortpath = create_sprite("objects/cmr/splendall.png"); - * const fullpath = create_sprite("https://source-academy-assets.s3-ap-southeast-1.amazonaws.com/objects/cmr/splendall.png"); + * const shortpath = create_sprite('objects/cmr/splendall.png'); + * const fullpath = create_sprite('https://source-academy-assets.s3-ap-southeast-1.amazonaws.com/objects/cmr/splendall.png'); * ``` * @category GameObject */ @@ -195,7 +195,7 @@ export function create_sprite(image_url: string): SpriteGameObject { * @returns the GameObject reference passed in * @example * ``` - * update_position(create_text("Hello world!"), [1, 2]); + * update_position(create_text('Hello world!'), [1, 2]); * ``` * @category GameObject */ @@ -218,7 +218,7 @@ export function update_position(gameObject: GameObject, [x, y]: PositionXY): Gam * @returns the GameObject reference passed in * @example * ``` - * update_scale(create_text("Hello world!"), [2, 0.5]); + * update_scale(create_text('Hello world!'), [2, 0.5]); * ``` * @category GameObject */ @@ -241,7 +241,7 @@ export function update_scale(gameObject: GameObject, [x, y]: ScaleXY): GameObjec * @returns the GameObject reference passed in * @example * ``` - * update_rotation(create_text("Hello world!"), math_PI); + * update_rotation(create_text('Hello world!'), math_PI); * ``` * @category GameObject */ @@ -318,7 +318,7 @@ export function update_flip(gameObject: GameObject, flip: FlipXY): GameObject { * @throws Error if not a TextGameObject is passed in * @example * ``` - * update_text(create_text("Hello world!"), "Goodbye world!"); + * update_text(create_text('Hello world!'), 'Goodbye world!'); * ``` * @category GameObject */ @@ -338,7 +338,7 @@ export function update_text(textGameObject: TextGameObject, text: string): GameO * @param gameObject GameObject reference * @example * ``` - * update_to_top(create_text("Hello world!")); + * update_to_top(create_text('Hello world!')); * ``` * @category GameObject */ @@ -362,9 +362,9 @@ export function update_to_top(gameObject: GameObject): GameObject { * @returns the id of the GameObject reference * @example * ``` - * const id0 = create_text("This has id 0"); - * const id1 = create_text("This has id 1"); - * const id2 = create_text("This has id 2"); + * const id0 = create_text('This has id 0'); + * const id1 = create_text('This has id 1'); + * const id2 = create_text('This has id 2'); * queryGameObjectId(id2); * ``` * @category GameObject @@ -479,7 +479,7 @@ export function query_flip(gameObject: RenderableGameObject): FlipXY { * @throws Error if not a TextGameObject is passed in * @example * ``` - * const text = create_text("Hello World!"); + * const text = create_text('Hello World!'); * query_text(text); * ``` * @category GameObject @@ -633,8 +633,8 @@ export function debug_log(info: string) { * @returns True, in the frame the key is pressed down. * @example * ``` - * if (input_key_down("a")) { - * // "a" key is pressed down + * if (input_key_down('a')) { + * // 'a' key is pressed down * } * ``` * @category Logic @@ -650,7 +650,7 @@ export function input_key_down(key_name: string) { * @returns True, if the left mouse button is pressed down. * @example * ``` - * if(input_left_mouse_down()) { + * if (input_left_mouse_down()) { * // Left mouse button down * } * ``` @@ -686,7 +686,7 @@ export function input_right_mouse_down() { * @example * ``` * // Creating a button using a gameobject - * const button = createTextGameObject("click me"); + * const button = createTextGameObject('click me'); * // Test if button is clicked * if (pointer_over_gameobject(button) && input_left_mouse_down()) { * // Button is clicked @@ -779,7 +779,7 @@ export function get_loop_count() { * game_state[0] = 0; * } * game_state[0] = game_state[0] + 1; - * }) + * }); * ``` */ export function update_loop(update_function: UpdateFunction) { @@ -844,7 +844,7 @@ export function build_game(): BuildGame { /** * Create an audio clip that can be referenced. - * Source Academy assets can be found at https://source-academy-assets.s3-ap-southeast-1.amazonaws.com/ with Ctrl+f ".mp3". + * Source Academy assets can be found at https://source-academy-assets.s3-ap-southeast-1.amazonaws.com/ with Ctrl+f '.mp3'. * Phaser audio assets can be found at https://labs.phaser.io/assets/audio. * Phaser sound effects assets can be found at https://labs.phaser.io/assets/audio/SoundEffects/. * If Phaser assets are unavailable, go to https://github.com/photonstorm/phaser3-examples/tree/master/public/assets @@ -856,7 +856,7 @@ export function build_game(): BuildGame { * @returns The AudioClip reference * @example * ``` - * const audioClip = create_audio("bgm/GalacticHarmony.mp3", 0.5); + * const audioClip = create_audio('bgm/GalacticHarmony.mp3', 0.5); * ``` * @category Audio */ @@ -878,7 +878,7 @@ export function create_audio(audio_url: string, volume_level: number) { * @returns The AudioClip reference * @example * ``` - * const audioClip = loop_audio(create_audio("bgm/GalacticHarmony.mp3", 0.5)); + * const audioClip = loop_audio(create_audio('bgm/GalacticHarmony.mp3', 0.5)); * ``` * @category Audio */ @@ -897,7 +897,7 @@ export function loop_audio(audio_clip: AudioClip) { * @returns The AudioClip reference * @example * ``` - * const audioClip = play_audio(create_audio("bgm/GalacticHarmony.mp3", 0.5)); + * const audioClip = play_audio(create_audio('bgm/GalacticHarmony.mp3', 0.5)); * ``` * @category Audio */ @@ -916,7 +916,7 @@ export function play_audio(audio_clip: AudioClip) { * @returns The AudioClip reference * @example * ``` - * const audioClip = play_audio(create_audio("bgm/GalacticHarmony.mp3", 0.5)); + * const audioClip = play_audio(create_audio('bgm/GalacticHarmony.mp3', 0.5)); * ``` * @category Audio */ diff --git a/src/bundles/binary_tree/src/functions.ts b/src/bundles/binary_tree/src/functions.ts index da1d87483f..06f4507ca5 100644 --- a/src/bundles/binary_tree/src/functions.ts +++ b/src/bundles/binary_tree/src/functions.ts @@ -4,7 +4,7 @@ import type { BinaryTree, EmptyBinaryTree, NonEmptyBinaryTree } from './types'; /** * Returns an empty binary tree, represented by the empty list null * @example - * ```typescript + * ``` * display(make_empty_tree()); // Shows "null" in the REPL * ``` * @returns An empty binary tree @@ -16,7 +16,7 @@ export function make_empty_tree(): BinaryTree { /** * Returns a binary tree node composed of the specified left subtree, value and right subtree. * @example - * ```typescript + * ``` * const tree = make_tree(1, make_empty_tree(), make_empty_tree()); * display(tree); // Shows "[1, [null, [null, null]]]" in the REPL * ``` @@ -33,7 +33,7 @@ export function make_tree(value: any, left: BinaryTree, right: BinaryTree): Bina * Returns a boolean value, indicating whether the given * value is a binary tree. * @example - * ```typescript + * ``` * const tree = make_tree(1, make_empty_tree(), make_empty_tree()); * display(is_tree(tree)); // Shows "true" in the REPL * ``` @@ -58,7 +58,7 @@ export function is_tree(value: any): value is BinaryTree { * Returns a boolean value, indicating whether the given * value is an empty binary tree. * @example - * ```typescript + * ``` * const tree = make_tree(1, make_empty_tree(), make_empty_tree()); * display(is_empty_tree(tree)); // Shows "false" in the REPL * ``` @@ -82,7 +82,7 @@ function throwIfNotNonEmptyTree(value: unknown, func_name: string): asserts valu /** * Returns the entry of a given binary tree. * @example - * ```typescript + * ``` * const tree = make_tree(1, make_empty_tree(), make_empty_tree()); * display(entry(tree)); // Shows "1" in the REPL * ``` @@ -97,7 +97,7 @@ export function entry(t: BinaryTree): any { /** * Returns the left branch of a given binary tree. * @example - * ```typescript + * ``` * const tree = make_tree(1, make_tree(2, make_empty_tree(), make_empty_tree()), make_empty_tree()); * display(entry(left_branch(tree))); // Shows "2" in the REPL * ``` @@ -112,7 +112,7 @@ export function left_branch(t: BinaryTree): BinaryTree { /** * Returns the right branch of a given binary tree. * @example - * ```typescript + * ``` * const tree = make_tree(1, make_empty_tree(), make_tree(2, make_empty_tree(), make_empty_tree())); * display(entry(right_branch(tree))); // Shows "2" in the REPL * ``` diff --git a/src/bundles/plotly/src/functions.ts b/src/bundles/plotly/src/functions.ts index 9e5bf03916..cc910ebec6 100644 --- a/src/bundles/plotly/src/functions.ts +++ b/src/bundles/plotly/src/functions.ts @@ -25,7 +25,7 @@ context.moduleContexts.plotly.state = { /** * Adds a new plotly plot to the context which will be rendered in the Plotly Tabs * @example - * ```ts + * ``` * const z1 = [ * [8.83,8.89,8.81,8.87,8.9,8.87], * [8.89,8.94,8.85,8.94,8.96,8.92], @@ -42,8 +42,8 @@ context.moduleContexts.plotly.state = { * [9,9.01,9,9.2,9.23,9.2], * [8.99,8.99,8.98,9.18,9.2,9.19], * [8.93,8.97,8.97,9.18,9.2,9.18] - * ]; - * new_plot(list(pair("z", z1), pair("type", "surface"))) // creates a surface plot in Plotly Tab + * ]; + * new_plot(list(pair('z', z1), pair('type', 'surface'))); // creates a surface plot in Plotly Tab * ``` * @param data The data in the form of list of pair, with the first term in the pair is * the name of the field as a string and the second term is the value of the field @@ -56,8 +56,7 @@ export function new_plot(data: ListOfPairs): void { /** * Adds a new plotly plot to the context which will be rendered in the Plotly Tabs * @example - * ```typescript - * + * ``` * const z1 = [ * [8.83,8.89,8.81,8.87,8.9,8.87], * [8.89,8.94,8.85,8.94,8.96,8.92], @@ -74,12 +73,12 @@ export function new_plot(data: ListOfPairs): void { * [9,9.01,9,9.2,9.23,9.2], * [8.99,8.99,8.98,9.18,9.2,9.19], * [8.93,8.97,8.97,9.18,9.2,9.18] - * ]; + * ]; * * let z2 = []; - * for (var i=0;i x + 2, 5); * plusTen(0); // Returns 10 * ``` @@ -23,7 +23,7 @@ export function repeat(func: Function, n: number): Function { * Returns a new function which when applied to an argument, has the same effect * as applying the specified function to the same argument 2 times. * @example - * ```typescript + * ``` * const plusTwo = twice(x => x + 1); * plusTwo(2); // Returns 4 * ``` @@ -38,7 +38,7 @@ export function twice(func: Function): Function { * Returns a new function which when applied to an argument, has the same effect * as applying the specified function to the same argument 3 times. * @example - * ```typescript + * ``` * const plusNine = thrice(x => x + 3); * plusNine(0); // Returns 9 * ``` diff --git a/src/bundles/robot_simulation/src/helper_functions.ts b/src/bundles/robot_simulation/src/helper_functions.ts index 8a1d48ca30..49ac78a161 100644 --- a/src/bundles/robot_simulation/src/helper_functions.ts +++ b/src/bundles/robot_simulation/src/helper_functions.ts @@ -235,17 +235,17 @@ export function createWorld( * @example * ``` * init_simulation(() => { - * const physics = createPhysics(); - * const renderer = createRenderer(); - * const timer = createTimer(); - * const robot_console = createRobotConsole(); - * const world = createWorld(physics, renderer, timer, robot_console); + * const physics = createPhysics(); + * const renderer = createRenderer(); + * const timer = createTimer(); + * const robot_console = createRobotConsole(); + * const world = createWorld(physics, renderer, timer, robot_console); * - * const cuboid = createCuboid(...); - * addControllerToWorld(cuboid, world); + * const cuboid = createCuboid(); + * addControllerToWorld(cuboid, world); * - * return world; - * }); + * return world; + * }); * ``` * * @category Controller @@ -473,10 +473,10 @@ export function saveToContext(key: string, value: any) { * @example * ``` * init_simulation(() => { - * ... + * // ... other code * const ev3 = createEv3(physics, renderer); * saveToContext('ev3', ev3); - * }) + * }); * ``` * * @param physics The physics engine of the world. See {@link createPhysics} From 989eba95d54cfbafdbbe5c098e63a513e31be166 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 10 Jan 2026 17:08:22 +0800 Subject: [PATCH 16/71] Fix code example from plotly --- src/bundles/plotly/src/functions.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bundles/plotly/src/functions.ts b/src/bundles/plotly/src/functions.ts index cc910ebec6..f109e461de 100644 --- a/src/bundles/plotly/src/functions.ts +++ b/src/bundles/plotly/src/functions.ts @@ -78,13 +78,13 @@ export function new_plot(data: ListOfPairs): void { * let z2 = []; * for (let i = 0; i < array_length(z1); i = i + 1) { * let z2_row = []; - * for (let j = 0; j < array_length(z1[i]); j = j + 1) { - * z2_row.push(z1[i][j]+1); - * } - * z2.push(z2_row); + * for (let j = 0; j < array_length(z1[i]); j = j + 1) { + * z2_row.push(z1[i][j]+1); + * } + * z2.push(z2_row); * } - * const data = [{z: z1, type: 'surface'}, {z: z2 , type: 'surface'}]; - * new_plot_json(data) // creates a surface plot in Plotly Tab + * const data = [{ z: z1, type: 'surface' }, { z: z2 , type: 'surface' }]; + * new_plot_json(data); // creates a surface plot in Plotly Tab * ``` * @param data The data as an array of json objects having some or all of the given fields */ From f44cfbadf91b2997e2f19c97db84e91bff3341eb Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 10 Jan 2026 17:38:43 +0800 Subject: [PATCH 17/71] Update vitest eslint plugin --- eslint.config.js | 3 + lib/buildtools/vitest.setup.ts | 4 +- lib/lintplugin/package.json | 2 +- .../src/tabs/__tests__/useAnimation.test.ts | 2 +- package.json | 2 +- yarn.lock | 124 +++++++++++++++++- 6 files changed, 131 insertions(+), 6 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 4fcabe8aa9..436186f285 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -476,10 +476,13 @@ export default defineConfig( 'vitest/expect-expect': ['error', { assertFunctionNames: ['expect*'], }], + 'vitest/hoisted-apis-on-top': 'error', 'vitest/no-alias-methods': 'off', // was 'error' 'vitest/no-conditional-expect': 'off', // was 'error' 'vitest/no-focused-tests': ['warn', { fixable: false }], + 'vitest/no-standalone-expect': 'off', // was 'error' 'vitest/prefer-describe-function-title': 'warn', + 'vitest/prefer-import-in-mock': 'warn', 'vitest/require-top-level-describe': 'off', // was 'error' 'vitest/valid-describe-callback': 'off', // was 'error' 'vitest/valid-expect-in-promise': 'error', diff --git a/lib/buildtools/vitest.setup.ts b/lib/buildtools/vitest.setup.ts index 0bce7f3961..9c38fa6d7a 100644 --- a/lib/buildtools/vitest.setup.ts +++ b/lib/buildtools/vitest.setup.ts @@ -11,7 +11,7 @@ class MockProcessExit extends Error { } }; -vi.mock('chalk', () => { +vi.mock(import('chalk'), () => { const mockChalkFunction = new Proxy((x: string) => x, { get: () => mockChalkFunction }); @@ -20,7 +20,7 @@ vi.mock('chalk', () => { default: new Proxy({}, { get: () => mockChalkFunction }) - }; + } as any; }); vi.mock(import('fs/promises'), async importOriginal => { diff --git a/lib/lintplugin/package.json b/lib/lintplugin/package.json index 7b95167b4d..a31064a235 100644 --- a/lib/lintplugin/package.json +++ b/lib/lintplugin/package.json @@ -32,7 +32,7 @@ "@stylistic/eslint-plugin": "^4.4.1", "@typescript-eslint/rule-tester": "^8.39.0", "@typescript-eslint/utils": "^8.39.0", - "@vitest/eslint-plugin": "^1.3.4", + "@vitest/eslint-plugin": "^1.6.6", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^61.5.0", "eslint-plugin-react": "^7.37.4", diff --git a/lib/modules-lib/src/tabs/__tests__/useAnimation.test.ts b/lib/modules-lib/src/tabs/__tests__/useAnimation.test.ts index 270a58fe5b..75b192debd 100644 --- a/lib/modules-lib/src/tabs/__tests__/useAnimation.test.ts +++ b/lib/modules-lib/src/tabs/__tests__/useAnimation.test.ts @@ -132,7 +132,7 @@ test('Animation should not auto start if autoStart is false', async ({ callback, expect(hook.current.isPlaying).toEqual(false); }); -test('Test animation reset', async ({ callback, canvas }) => { +test('Animation reset', async ({ callback, canvas }) => { const { hook, act, advanceFrames } = await getAnimationHook({ autoLoop: false, animationDuration: 1000, diff --git a/package.json b/package.json index bd2cfc31da..3246838594 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", "@vitest/coverage-v8": "^4.0.4", - "@vitest/eslint-plugin": "^1.3.4", + "@vitest/eslint-plugin": "^1.6.6", "@yarnpkg/types": "^4.0.1", "esbuild": "^0.27.0", "eslint": "^9.35.0", diff --git a/yarn.lock b/yarn.lock index 4bb7b0db5a..2825b998de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2568,6 +2568,17 @@ __metadata: languageName: node linkType: hard +"@eslint-community/eslint-utils@npm:^4.9.1": + version: 4.9.1 + resolution: "@eslint-community/eslint-utils@npm:4.9.1" + dependencies: + eslint-visitor-keys: "npm:^3.4.3" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: 10c0/dc4ab5e3e364ef27e33666b11f4b86e1a6c1d7cbf16f0c6ff87b1619b3562335e9201a3d6ce806221887ff780ec9d828962a290bb910759fd40a674686503f02 + languageName: node + linkType: hard + "@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.12.1": version: 4.12.1 resolution: "@eslint-community/regexpp@npm:4.12.1" @@ -4763,7 +4774,7 @@ __metadata: "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" "@vitest/coverage-v8": "npm:^4.0.4" - "@vitest/eslint-plugin": "npm:^1.3.4" + "@vitest/eslint-plugin": "npm:^1.6.6" "@yarnpkg/types": "npm:^4.0.1" esbuild: "npm:^0.27.0" eslint: "npm:^9.35.0" @@ -5987,6 +5998,19 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/project-service@npm:8.52.0": + version: 8.52.0 + resolution: "@typescript-eslint/project-service@npm:8.52.0" + dependencies: + "@typescript-eslint/tsconfig-utils": "npm:^8.52.0" + "@typescript-eslint/types": "npm:^8.52.0" + debug: "npm:^4.4.3" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/2dc7379572b4b1340daff5923fbf7987ebd2de5a4203ece0ec9e8a9e85cf182cd4cd24c25bd7df62b981fb633c91dd35f27fed1341719c2f8a48eb80682b4658 + languageName: node + linkType: hard + "@typescript-eslint/rule-tester@npm:^8.39.0": version: 8.46.4 resolution: "@typescript-eslint/rule-tester@npm:8.46.4" @@ -6014,6 +6038,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:8.52.0, @typescript-eslint/scope-manager@npm:^8.51.0": + version: 8.52.0 + resolution: "@typescript-eslint/scope-manager@npm:8.52.0" + dependencies: + "@typescript-eslint/types": "npm:8.52.0" + "@typescript-eslint/visitor-keys": "npm:8.52.0" + checksum: 10c0/385105ad1bb63eddcfc65039a7c13ec339aef4823c3021110cffe72c545b27c6b197e40ec55000b5b1bf278946a3e1a77eba19203f461c1a77ba3fe82d007f3e + languageName: node + linkType: hard + "@typescript-eslint/tsconfig-utils@npm:8.46.4, @typescript-eslint/tsconfig-utils@npm:^8.46.4": version: 8.46.4 resolution: "@typescript-eslint/tsconfig-utils@npm:8.46.4" @@ -6023,6 +6057,15 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/tsconfig-utils@npm:8.52.0, @typescript-eslint/tsconfig-utils@npm:^8.52.0": + version: 8.52.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.52.0" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/a45f6c1453031c149b2dedaa4e8ace53aa71c751a5702b028cbd9a899928d46141cc4343d8de6260e3e27024f6645b12669d8759f66ebde4cbae2f703b859747 + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:8.46.4": version: 8.46.4 resolution: "@typescript-eslint/type-utils@npm:8.46.4" @@ -6046,6 +6089,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:8.52.0, @typescript-eslint/types@npm:^8.52.0": + version: 8.52.0 + resolution: "@typescript-eslint/types@npm:8.52.0" + checksum: 10c0/ad93803aa92570a96cc9f9a201735e68fecee9056a37563c9e5b70c16436927ac823ec38d9712881910d89dd7314b0a40100ef41ef1aca0d42674d3312d5ec8e + languageName: node + linkType: hard + "@typescript-eslint/types@npm:^8.46.0": version: 8.50.1 resolution: "@typescript-eslint/types@npm:8.50.1" @@ -6073,6 +6123,25 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:8.52.0": + version: 8.52.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.52.0" + dependencies: + "@typescript-eslint/project-service": "npm:8.52.0" + "@typescript-eslint/tsconfig-utils": "npm:8.52.0" + "@typescript-eslint/types": "npm:8.52.0" + "@typescript-eslint/visitor-keys": "npm:8.52.0" + debug: "npm:^4.4.3" + minimatch: "npm:^9.0.5" + semver: "npm:^7.7.3" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.4.0" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/e4158a6364d3f009eac780947504ac1dad2ee3f1fdd4dfd99e4a7b48719ce0d342a769dc05fa5d4bc5de9de28175aa8e9ba612385f6b6f215039ff41e91f2de5 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:8.46.4, @typescript-eslint/utils@npm:^8.24.1, @typescript-eslint/utils@npm:^8.32.1, @typescript-eslint/utils@npm:^8.39.0": version: 8.46.4 resolution: "@typescript-eslint/utils@npm:8.46.4" @@ -6088,6 +6157,21 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:^8.51.0": + version: 8.52.0 + resolution: "@typescript-eslint/utils@npm:8.52.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.52.0" + "@typescript-eslint/types": "npm:8.52.0" + "@typescript-eslint/typescript-estree": "npm:8.52.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/67e501e8ef4c4a5510237e3bfcfee37512137075a18c24f615924559bcca64ce9903118e7e4288cd4f58361979243f457d43684cdafa6c193fa8963a7431d0f3 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:8.46.4": version: 8.46.4 resolution: "@typescript-eslint/visitor-keys@npm:8.46.4" @@ -6098,6 +6182,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:8.52.0": + version: 8.52.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.52.0" + dependencies: + "@typescript-eslint/types": "npm:8.52.0" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10c0/7163735d872df0930301ecccd454602d241a65223b84ff3ef78ede02f27941c0cbb95d0c8b4fe51637d1fbd981e6558d454fc485a2488d7190e264e12a8a355f + languageName: node + linkType: hard + "@typescript/vfs@npm:^1.5.2": version: 1.6.1 resolution: "@typescript/vfs@npm:1.6.1" @@ -6249,6 +6343,25 @@ __metadata: languageName: node linkType: hard +"@vitest/eslint-plugin@npm:^1.6.6": + version: 1.6.6 + resolution: "@vitest/eslint-plugin@npm:1.6.6" + dependencies: + "@typescript-eslint/scope-manager": "npm:^8.51.0" + "@typescript-eslint/utils": "npm:^8.51.0" + peerDependencies: + eslint: ">=8.57.0" + typescript: ">=5.0.0" + vitest: "*" + peerDependenciesMeta: + typescript: + optional: true + vitest: + optional: true + checksum: 10c0/4b3a5ff3b27d6aab17f43a737f1f03bab0739b9d95c75e9c19d44003c605bdd0ce067f14f064def7fab7ab3251a2d23155849ea061a1a9d16569b3e990b11a62 + languageName: node + linkType: hard + "@vitest/expect@npm:4.0.9": version: 4.0.9 resolution: "@vitest/expect@npm:4.0.9" @@ -17492,6 +17605,15 @@ __metadata: languageName: node linkType: hard +"ts-api-utils@npm:^2.4.0": + version: 2.4.0 + resolution: "ts-api-utils@npm:2.4.0" + peerDependencies: + typescript: ">=4.8.4" + checksum: 10c0/ed185861aef4e7124366a3f6561113557a57504267d4d452a51e0ba516a9b6e713b56b4aeaab9fa13de9db9ab755c65c8c13a777dba9133c214632cb7b65c083 + languageName: node + linkType: hard + "ts-dedent@npm:^2.2.0": version: 2.2.0 resolution: "ts-dedent@npm:2.2.0" From d0b1422d8657c1e30f60757a87944b3476dc26e1 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 10 Jan 2026 17:44:56 +0800 Subject: [PATCH 18/71] Change reference to tsc command to instead refer to compile command --- docs/src/modules/2-bundle/6-compiling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/modules/2-bundle/6-compiling.md b/docs/src/modules/2-bundle/6-compiling.md index 7a5a35c931..8c9c2847a2 100644 --- a/docs/src/modules/2-bundle/6-compiling.md +++ b/docs/src/modules/2-bundle/6-compiling.md @@ -64,7 +64,7 @@ If you intend for your bundle to be consumed from other bundles, do the followin "./*": "./dist/*.js" }, "scripts": { - "postinstall": "yarn buildtools tsc" + "postinstall": "buildtools compile" } } ``` From 7bca24081e64929e2fd33151b2ef502300ea4cd8 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Thu, 15 Jan 2026 19:05:49 +0800 Subject: [PATCH 19/71] Fix incorrect eslint rules --- eslint.config.js | 1 + src/bundles/plotly/src/functions.ts | 2 ++ .../ev3/components/__tests__/Chassis.test.ts | 11 +++--- .../Render/__tests__/MeshFactory.test.ts | 7 ++-- .../src/engine/__tests__/Physics.test.ts | 34 +++++++++---------- 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 436186f285..9c701918ef 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -479,6 +479,7 @@ export default defineConfig( 'vitest/hoisted-apis-on-top': 'error', 'vitest/no-alias-methods': 'off', // was 'error' 'vitest/no-conditional-expect': 'off', // was 'error' + 'vitest/no-disabled-tests': 'off', // was 'warn' 'vitest/no-focused-tests': ['warn', { fixable: false }], 'vitest/no-standalone-expect': 'off', // was 'error' 'vitest/prefer-describe-function-title': 'warn', diff --git a/src/bundles/plotly/src/functions.ts b/src/bundles/plotly/src/functions.ts index f109e461de..f7e07f1fe9 100644 --- a/src/bundles/plotly/src/functions.ts +++ b/src/bundles/plotly/src/functions.ts @@ -221,6 +221,7 @@ export const draw_connected_3d = createPlotFunction( * @example * ``` * draw_points_2d(100)(t => make_point(t, t)); + * ``` */ export const draw_points_2d = createPlotFunction( 'scatter', @@ -247,6 +248,7 @@ export const draw_points_2d = createPlotFunction( * @example * ``` * draw_points_3d(100)(t => make_point(t, t)); + * ``` */ export const draw_points_3d = createPlotFunction( 'scatter3d', diff --git a/src/bundles/robot_simulation/src/controllers/ev3/components/__tests__/Chassis.test.ts b/src/bundles/robot_simulation/src/controllers/ev3/components/__tests__/Chassis.test.ts index 3b4921473a..c7760eea54 100644 --- a/src/bundles/robot_simulation/src/controllers/ev3/components/__tests__/Chassis.test.ts +++ b/src/bundles/robot_simulation/src/controllers/ev3/components/__tests__/Chassis.test.ts @@ -4,15 +4,18 @@ import { EntityFactory, MeshFactory, Physics, Renderer } from '../../../../engin import { ChassisWrapper } from '../Chassis'; -vi.mock('../../../../engine', () => ({ +// @ts-expect-error not a complete mock of engine +vi.mock(import('../../../../engine'), () => ({ Physics: vi.fn(), Renderer: vi.fn(), EntityFactory: { addCuboid: vi.fn() }, MeshFactory: { addCuboid: vi.fn() } })); -vi.mock('../../../../engine/Entity/EntityFactory'); -vi.mock('three', async importOriginal => { +vi.mock(import('../../../../engine/Entity/EntityFactory')); + +vi.mock(import('three'), async importOriginal => { + // @ts-expect-error Not a complete mock of three.js return { ...await importOriginal(), Mesh: vi.fn(class { @@ -21,7 +24,7 @@ vi.mock('three', async importOriginal => { visible = false; }), Color: vi.fn() - }; + } as typeof THREE; }); const mockedMeshFactory = vi.mocked(MeshFactory); diff --git a/src/bundles/robot_simulation/src/engine/Render/__tests__/MeshFactory.test.ts b/src/bundles/robot_simulation/src/engine/Render/__tests__/MeshFactory.test.ts index 63380ef46b..703d485a6e 100644 --- a/src/bundles/robot_simulation/src/engine/Render/__tests__/MeshFactory.test.ts +++ b/src/bundles/robot_simulation/src/engine/Render/__tests__/MeshFactory.test.ts @@ -3,8 +3,8 @@ import { describe, expect, it, vi } from 'vitest'; import { addCuboid } from '../../Render/helpers/MeshFactory'; // Mock the necessary Three.js methods and classes -vi.mock('three', async importOriginal => { - const originalModule: any = await importOriginal(); +vi.mock(import('three'), async importOriginal => { + const originalModule = await importOriginal(); class Vector3 { x: number; @@ -46,6 +46,7 @@ vi.mock('three', async importOriginal => { } } + // @ts-expect-error Not a complete mock of threejs return { ...originalModule, BoxGeometry: vi.fn(), @@ -61,7 +62,7 @@ vi.mock('three', async importOriginal => { Color: vi.fn().mockImplementation(function (color) { return { color }; }), - }; + } as typeof THREE; }); describe(addCuboid, () => { diff --git a/src/bundles/robot_simulation/src/engine/__tests__/Physics.test.ts b/src/bundles/robot_simulation/src/engine/__tests__/Physics.test.ts index 6e70a95c2a..ebbd630a83 100644 --- a/src/bundles/robot_simulation/src/engine/__tests__/Physics.test.ts +++ b/src/bundles/robot_simulation/src/engine/__tests__/Physics.test.ts @@ -4,23 +4,23 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; import { Physics } from '../Physics'; // Mock rapier -vi.mock('@dimforge/rapier3d-compat', () => { - return { - default: { - init: vi.fn(), - World: class { - timestep = vi.fn(); - createRigidBody = vi.fn(); - createCollider = vi.fn(); - castRayAndGetNormal = vi.fn(); - step = vi.fn(); - castRay = vi.fn(); - }, - Ray: vi.fn(), - RigidBodyDesc: vi.fn(), - ColliderDesc: vi.fn(), - } - }; +vi.mock(import('@dimforge/rapier3d-compat'), () => { + const mocked: typeof rapier = { + init: vi.fn(), + World: class { + timestep = vi.fn(); + createRigidBody = vi.fn(); + createCollider = vi.fn(); + castRayAndGetNormal = vi.fn(); + step = vi.fn(); + castRay = vi.fn(); + }, + Ray: vi.fn(), + RigidBodyDesc: vi.fn(), + ColliderDesc: vi.fn(), + } as any; + + return { default: mocked }; }); describe(Physics, () => { From 7afa0fd86d86d4d1bd26176a97e819e18c2e040d Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Wed, 21 Jan 2026 20:31:44 +0800 Subject: [PATCH 20/71] Update typescript-eslint versions --- lib/lintplugin/package.json | 6 +- package.json | 2 +- yarn.lock | 288 +++++++++++++++++------------------- 3 files changed, 137 insertions(+), 159 deletions(-) diff --git a/lib/lintplugin/package.json b/lib/lintplugin/package.json index 37b9250f8c..a8f75d0048 100644 --- a/lib/lintplugin/package.json +++ b/lib/lintplugin/package.json @@ -30,8 +30,8 @@ "@sourceacademy/modules-buildtools": "workspace:^", "@sourceacademy/modules-repotools": "workspace:^", "@stylistic/eslint-plugin": "^4.4.1", - "@typescript-eslint/rule-tester": "^8.39.0", - "@typescript-eslint/utils": "^8.39.0", + "@typescript-eslint/rule-tester": "^8.53.1", + "@typescript-eslint/utils": "^8.53.1", "@vitest/eslint-plugin": "^1.6.6", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^62.0.0", @@ -39,7 +39,7 @@ "eslint-plugin-react-hooks": "^5.1.0", "globals": "^15.11.0", "typescript": "^5.8.2", - "typescript-eslint": "^8.33.1" + "typescript-eslint": "^8.53.1" }, "scripts": { "build": "node ./build.js", diff --git a/package.json b/package.json index ebf150187d..2a597b30cb 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "jsdom": "^26.1.0", "jsonc-eslint-parser": "^2.4.0", "typescript": "^5.8.2", - "typescript-eslint": "^8.33.1", + "typescript-eslint": "^8.53.1", "vitest": "^4.0.4", "vitest-browser-react": "^2.0.2" }, diff --git a/yarn.lock b/yarn.lock index 8b923af528..6657725610 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2546,17 +2546,6 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.7.0": - version: 4.7.0 - resolution: "@eslint-community/eslint-utils@npm:4.7.0" - dependencies: - eslint-visitor-keys: "npm:^3.4.3" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10c0/c0f4f2bd73b7b7a9de74b716a664873d08ab71ab439e51befe77d61915af41a81ecec93b408778b3a7856185244c34c2c8ee28912072ec14def84ba2dec70adf - languageName: node - linkType: hard - "@eslint-community/eslint-utils@npm:^4.8.0": version: 4.9.0 resolution: "@eslint-community/eslint-utils@npm:4.9.0" @@ -2579,13 +2568,20 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.12.1": +"@eslint-community/regexpp@npm:^4.12.1": version: 4.12.1 resolution: "@eslint-community/regexpp@npm:4.12.1" checksum: 10c0/a03d98c246bcb9109aec2c08e4d10c8d010256538dcb3f56610191607214523d4fb1b00aa81df830b6dffb74c5fa0be03642513a289c567949d3e550ca11cdf6 languageName: node linkType: hard +"@eslint-community/regexpp@npm:^4.12.2": + version: 4.12.2 + resolution: "@eslint-community/regexpp@npm:4.12.2" + checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d + languageName: node + linkType: hard + "@eslint/config-array@npm:^0.21.1": version: 0.21.1 resolution: "@eslint/config-array@npm:0.21.1" @@ -4578,8 +4574,8 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-repotools": "workspace:^" "@stylistic/eslint-plugin": "npm:^4.4.1" - "@typescript-eslint/rule-tester": "npm:^8.39.0" - "@typescript-eslint/utils": "npm:^8.39.0" + "@typescript-eslint/rule-tester": "npm:^8.53.1" + "@typescript-eslint/utils": "npm:^8.53.1" "@vitest/eslint-plugin": "npm:^1.6.6" eslint: "npm:^9.35.0" eslint-plugin-import: "npm:^2.32.0" @@ -4588,7 +4584,7 @@ __metadata: eslint-plugin-react-hooks: "npm:^5.1.0" globals: "npm:^15.11.0" typescript: "npm:^5.8.2" - typescript-eslint: "npm:^8.33.1" + typescript-eslint: "npm:^8.53.1" peerDependencies: "@eslint/markdown": ^6.6.0 "@stylistic/eslint-plugin": ^4.4.1 @@ -4802,7 +4798,7 @@ __metadata: react: "npm:^18.3.1" react-dom: "npm:^18.3.1" typescript: "npm:^5.8.2" - typescript-eslint: "npm:^8.33.1" + typescript-eslint: "npm:^8.53.1" vitest: "npm:^4.0.4" vitest-browser-react: "npm:^2.0.2" languageName: unknown @@ -5958,53 +5954,39 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/eslint-plugin@npm:8.46.4" +"@typescript-eslint/eslint-plugin@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/eslint-plugin@npm:8.53.1" dependencies: - "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.46.4" - "@typescript-eslint/type-utils": "npm:8.46.4" - "@typescript-eslint/utils": "npm:8.46.4" - "@typescript-eslint/visitor-keys": "npm:8.46.4" - graphemer: "npm:^1.4.0" - ignore: "npm:^7.0.0" + "@eslint-community/regexpp": "npm:^4.12.2" + "@typescript-eslint/scope-manager": "npm:8.53.1" + "@typescript-eslint/type-utils": "npm:8.53.1" + "@typescript-eslint/utils": "npm:8.53.1" + "@typescript-eslint/visitor-keys": "npm:8.53.1" + ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.1.0" + ts-api-utils: "npm:^2.4.0" peerDependencies: - "@typescript-eslint/parser": ^8.46.4 + "@typescript-eslint/parser": ^8.53.1 eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/c487e55c2f35e89126a13a6997f06494c26a3c96b9a7685421e2d92929f3ab302c1c234f0add9113705fbad693b05b3b87cebe5219bc71b2af9ee7aa8e7dc12c + checksum: 10c0/d24e41d0117ef841cc05e4c52d33277de2e57981fa38412f93034082a3467f804201c180f1baca9f967388c7e5965ffcc61e445cf726a0064b8ed71a84f59aa2 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/parser@npm:8.46.4" +"@typescript-eslint/parser@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/parser@npm:8.53.1" dependencies: - "@typescript-eslint/scope-manager": "npm:8.46.4" - "@typescript-eslint/types": "npm:8.46.4" - "@typescript-eslint/typescript-estree": "npm:8.46.4" - "@typescript-eslint/visitor-keys": "npm:8.46.4" - debug: "npm:^4.3.4" + "@typescript-eslint/scope-manager": "npm:8.53.1" + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" + "@typescript-eslint/visitor-keys": "npm:8.53.1" + debug: "npm:^4.4.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/bef98fa9250d5720479c10f803ca66a2a0b382158a8b462fd1c710351f7b423570c273556fb828e64d8a87041d54d51fa5a5e1e88ebdc1c88da0ee1098f9405e - languageName: node - linkType: hard - -"@typescript-eslint/project-service@npm:8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/project-service@npm:8.46.4" - dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.46.4" - "@typescript-eslint/types": "npm:^8.46.4" - debug: "npm:^4.3.4" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/81c5de7b85a2b1bff51ef27d25f11be992b7e550bfe34d4cbc4eb71f0fd03bcc1619644ac8efd594c515c894317f98db9176ef333004718d997c666791ca8b95 + checksum: 10c0/fb7602dc3ea45b838f4da2d0173161b222442ed2007487dfce57d6ce24ff16606ec99de9eb6ac114a815e11a47248303d941dca1a7bf13f70350372cee509886 languageName: node linkType: hard @@ -6034,30 +6016,33 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/rule-tester@npm:^8.39.0": - version: 8.46.4 - resolution: "@typescript-eslint/rule-tester@npm:8.46.4" +"@typescript-eslint/project-service@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/project-service@npm:8.53.1" dependencies: - "@typescript-eslint/parser": "npm:8.46.4" - "@typescript-eslint/typescript-estree": "npm:8.46.4" - "@typescript-eslint/utils": "npm:8.46.4" - ajv: "npm:^6.12.6" - json-stable-stringify-without-jsonify: "npm:^1.0.1" - lodash.merge: "npm:4.6.2" - semver: "npm:^7.6.0" + "@typescript-eslint/tsconfig-utils": "npm:^8.53.1" + "@typescript-eslint/types": "npm:^8.53.1" + debug: "npm:^4.4.3" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - checksum: 10c0/a8b0f108af26bd0fd925fad3c5991888b047397a471b21c72cb636b9b32f6dd2f8fb3331b7758b0dfebc4a17e257aab90a78efaee209a50b4892fed07fe19954 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/eecc7ad86b45c6969a05e984e645a4ece2a1cc27d825af046efb6ed369cab32062c17f33a1154ab6dcab349099885db7b39945f1b318753395630f3dfa1e5895 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/scope-manager@npm:8.46.4" +"@typescript-eslint/rule-tester@npm:^8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/rule-tester@npm:8.53.1" dependencies: - "@typescript-eslint/types": "npm:8.46.4" - "@typescript-eslint/visitor-keys": "npm:8.46.4" - checksum: 10c0/f614b5a95f1803a4298a5192c48f39327fa6085c0753cd67b03728767b8dee79020ebc8896974cba530fe039a5723e157eed74675683f1a4ed87959cd695c997 + "@typescript-eslint/parser": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" + "@typescript-eslint/utils": "npm:8.53.1" + ajv: "npm:^6.12.6" + json-stable-stringify-without-jsonify: "npm:^1.0.1" + lodash.merge: "npm:4.6.2" + semver: "npm:^7.7.3" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + checksum: 10c0/418c5d9c646c9879050a4a4e9f297955fca8862f76363c05bedd0cd48e7f3e2ca3608dffc873658dbc96e485f1cdd97fdbf64289ab10e8cd91940c11323a39b5 languageName: node linkType: hard @@ -6081,12 +6066,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.46.4, @typescript-eslint/tsconfig-utils@npm:^8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.46.4" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/d8ed135c56a15be10822053490b22a4f32ca912deca2c6d3c93a8fec32572842af84d762f0d2ed142b99f1e8251d97402aed9ce9950ef3dc0a8c90e4e1e459fc +"@typescript-eslint/scope-manager@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/scope-manager@npm:8.53.1" + dependencies: + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/visitor-keys": "npm:8.53.1" + checksum: 10c0/d971eb115f2a2c4c25c79df9eee68b93354b32d7cc1174c167241cd2ebbc77858fe7a032c7ecdbacef936b56e8317b56037d21461cb83b4789f7e764e9faa455 languageName: node linkType: hard @@ -6108,26 +6094,28 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/type-utils@npm:8.46.4" - dependencies: - "@typescript-eslint/types": "npm:8.46.4" - "@typescript-eslint/typescript-estree": "npm:8.46.4" - "@typescript-eslint/utils": "npm:8.46.4" - debug: "npm:^4.3.4" - ts-api-utils: "npm:^2.1.0" +"@typescript-eslint/tsconfig-utils@npm:8.53.1, @typescript-eslint/tsconfig-utils@npm:^8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.53.1" peerDependencies: - eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/d4e08a2d2d66b92a93a45c6efd1df272612982ac27204df9a989371f3a7d6eb5a069fc9898ca5b3a5ad70e2df1bc97e77b1f548e229608605b1a1cb33abc2c95 + checksum: 10c0/e2bfa91f9306dbfa82bdcb64bfcf634fee6313b03e93b35b0010907983c9ffc73c732264deff870896dea18f34b872d39d90d32f7631fd4618e4a6866ffff578 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.46.4, @typescript-eslint/types@npm:^8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/types@npm:8.46.4" - checksum: 10c0/b92166dd9b6d8e4cf0a6a90354b6e94af8542d8ab341aed3955990e6599db7a583af638e22909a1417e41fd8a0ef5861c5ba12ad84b307c27d26f3e0c5e2020f +"@typescript-eslint/type-utils@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/type-utils@npm:8.53.1" + dependencies: + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" + "@typescript-eslint/utils": "npm:8.53.1" + debug: "npm:^4.4.3" + ts-api-utils: "npm:^2.4.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/d97ac3bf901eeeb1ad01a423409db654f849d49f8ce7a2b0d482e093d5c8c9cab9ed810554d130a1eaf4921ddb2d98dbe9a8d22bfd08fd6c8ab004fb640a3fbe languageName: node linkType: hard @@ -6145,23 +6133,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/typescript-estree@npm:8.46.4" - dependencies: - "@typescript-eslint/project-service": "npm:8.46.4" - "@typescript-eslint/tsconfig-utils": "npm:8.46.4" - "@typescript-eslint/types": "npm:8.46.4" - "@typescript-eslint/visitor-keys": "npm:8.46.4" - debug: "npm:^4.3.4" - fast-glob: "npm:^3.3.2" - is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.4" - semver: "npm:^7.6.0" - ts-api-utils: "npm:^2.1.0" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/e115dbd8580801e9b8892a19056ccb91e7c912b587b22ee5a9b7ec03547eff89ad18ea18a31210ea779cf9f4ccec9428f98b62151c26709e19e7adbdd5ca990b +"@typescript-eslint/types@npm:8.53.1, @typescript-eslint/types@npm:^8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/types@npm:8.53.1" + checksum: 10c0/fa49f5f60de6851de45a9aff0a3ba3c4d00a0991100414e8af1a5d6f32764a48b6b7c0f65748a651f0da0e57df0745cdb8f11c590fa0fb22dd0e54e4c6b5c878 languageName: node linkType: hard @@ -6203,22 +6178,41 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/utils@npm:8.46.4" +"@typescript-eslint/typescript-estree@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/typescript-estree@npm:8.53.1" + dependencies: + "@typescript-eslint/project-service": "npm:8.53.1" + "@typescript-eslint/tsconfig-utils": "npm:8.53.1" + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/visitor-keys": "npm:8.53.1" + debug: "npm:^4.4.3" + minimatch: "npm:^9.0.5" + semver: "npm:^7.7.3" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.4.0" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/e1b48990ba90f0ee5c9630fe91e2d5123c55348e374e586de6cf25e6e03e6e8274bf15317794d171a2e82d9dc663c229807e603ecc661dbe70d61bd23d0c37c4 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:8.53.1, @typescript-eslint/utils@npm:^8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/utils@npm:8.53.1" dependencies: - "@eslint-community/eslint-utils": "npm:^4.7.0" - "@typescript-eslint/scope-manager": "npm:8.46.4" - "@typescript-eslint/types": "npm:8.46.4" - "@typescript-eslint/typescript-estree": "npm:8.46.4" + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.53.1" + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/6e4f4d51113f74edcfc83b135c73edf7c46919895659c2e7d5945ab084bc051ed5f980918d23a941d1a9f96a38c8ddc22c12b5aafa8e35ef3bb9d9c6b00b6c79 + checksum: 10c0/9a2a11c00b97eb9a053782e303cc384649807779e9adeb0b645bc198c83f54431f7ca56d4b38411dcf7ed06a2c2d9aa129874c20c037de2393a4cd0fa3b93c25 languageName: node linkType: hard -"@typescript-eslint/utils@npm:^8.32.1, @typescript-eslint/utils@npm:^8.39.0": +"@typescript-eslint/utils@npm:^8.32.1": version: 8.53.0 resolution: "@typescript-eslint/utils@npm:8.53.0" dependencies: @@ -6248,16 +6242,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.46.4": - version: 8.46.4 - resolution: "@typescript-eslint/visitor-keys@npm:8.46.4" - dependencies: - "@typescript-eslint/types": "npm:8.46.4" - eslint-visitor-keys: "npm:^4.2.1" - checksum: 10c0/35dd6aa2b53fc3f4f214e9edf730cc69d0eb9f77ffd978354d092feda7358e60052e15d891fa8577e9ebee5fdea8083e02fe286dd3a96bbafcb1305dce15b80c - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:8.52.0": version: 8.52.0 resolution: "@typescript-eslint/visitor-keys@npm:8.52.0" @@ -6278,6 +6262,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/visitor-keys@npm:8.53.1" + dependencies: + "@typescript-eslint/types": "npm:8.53.1" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10c0/73a21d34052bcb0b46ed738f8fddb76ae8f56a0c27932616b49022cf8603c3e36bb6ab30acd709f9bc05c673708180527b4c4aaffcb858acfc66d8fb39cc6c29 + languageName: node + linkType: hard + "@typescript/vfs@npm:^1.5.2": version: 1.6.1 resolution: "@typescript/vfs@npm:1.6.1" @@ -10611,7 +10605,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.2, fast-glob@npm:^3.3.2": +"fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.2": version: 3.3.3 resolution: "fast-glob@npm:3.3.3" dependencies: @@ -11197,13 +11191,6 @@ __metadata: languageName: node linkType: hard -"graphemer@npm:^1.4.0": - version: 1.4.0 - resolution: "graphemer@npm:1.4.0" - checksum: 10c0/e951259d8cd2e0d196c72ec711add7115d42eb9a8146c8eeda5b8d3ac91e5dd816b9cd68920726d9fd4490368e7ed86e9c423f40db87e2d8dfafa00fa17c3a31 - languageName: node - linkType: hard - "gray-matter@npm:4.0.3": version: 4.0.3 resolution: "gray-matter@npm:4.0.3" @@ -11616,10 +11603,10 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^7.0.0": - version: 7.0.4 - resolution: "ignore@npm:7.0.4" - checksum: 10c0/90e1f69ce352b9555caecd9cbfd07abe7626d312a6f90efbbb52c7edca6ea8df065d66303863b30154ab1502afb2da8bc59d5b04e1719a52ef75bbf675c488eb +"ignore@npm:^7.0.5": + version: 7.0.5 + resolution: "ignore@npm:7.0.5" + checksum: 10c0/ae00db89fe873064a093b8999fe4cc284b13ef2a178636211842cceb650b9c3e390d3339191acb145d81ed5379d2074840cf0c33a20bdbd6f32821f79eb4ad5d languageName: node linkType: hard @@ -17691,15 +17678,6 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^2.1.0": - version: 2.1.0 - resolution: "ts-api-utils@npm:2.1.0" - peerDependencies: - typescript: ">=4.8.4" - checksum: 10c0/9806a38adea2db0f6aa217ccc6bc9c391ddba338a9fe3080676d0d50ed806d305bb90e8cef0276e793d28c8a929f400abb184ddd7ff83a416959c0f4d2ce754f - languageName: node - linkType: hard - "ts-api-utils@npm:^2.4.0": version: 2.4.0 resolution: "ts-api-utils@npm:2.4.0" @@ -17912,18 +17890,18 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^8.33.1": - version: 8.46.4 - resolution: "typescript-eslint@npm:8.46.4" +"typescript-eslint@npm:^8.53.1": + version: 8.53.1 + resolution: "typescript-eslint@npm:8.53.1" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.46.4" - "@typescript-eslint/parser": "npm:8.46.4" - "@typescript-eslint/typescript-estree": "npm:8.46.4" - "@typescript-eslint/utils": "npm:8.46.4" + "@typescript-eslint/eslint-plugin": "npm:8.53.1" + "@typescript-eslint/parser": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" + "@typescript-eslint/utils": "npm:8.53.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/e08f1a9a55969df12590b1633f0f6c35d843b7846dc38b60ff900517f8f10dc51f37f1598db92436e858967690bbce1ae732feea2f196071f733d6d2195b0db7 + checksum: 10c0/520d68df8e1e1bba99c2713029b63837b101370c460bf5e75b8065fb0a6bc1ac9c6eb967432dbc220464479fe981630a6b2eddf31cfb378441ee8b8a43c0eb5a languageName: node linkType: hard From 7d3a5b460b67d8f4012da3e276866bce7317626e Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Wed, 21 Jan 2026 20:47:02 +0800 Subject: [PATCH 21/71] Fix spelling --- docs/src/repotools/7-workflows/4-changes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/repotools/7-workflows/4-changes.md b/docs/src/repotools/7-workflows/4-changes.md index 7b1b068465..e96ac7dc10 100644 --- a/docs/src/repotools/7-workflows/4-changes.md +++ b/docs/src/repotools/7-workflows/4-changes.md @@ -27,7 +27,7 @@ For this section, it is important to understand the distinction between workspac -Specificailly, we are concerned with detecting when to rebuild a workspace package. +Specifically, we are concerned with detecting when to rebuild a workspace package. There are many workspace packages contained within this repository. It would be entirely unnecessary to rerun building and testing for every single workspace package if changes were only made to one. It thus makes sense to implement some kind of @@ -143,7 +143,7 @@ graph LR Now, suppose that the publishers of `lodash` find a minor bug in one of their functions and release a small patch to rectify it. They publish this new version as version `4.17.1`. Notice that this version is still compatible with the `^4.17.0` specification. -When the repository's automated depedency upgrading bot (Renovate Bot) detects this, it will attempt to cause Yarn to install version `4.17.1` +When the repository's automated dependency upgrading bot (Renovate Bot) detects this, it will attempt to cause Yarn to install version `4.17.1` instead of `4.17.0` for `lodash`. It does this by updating the lockfile. But now we have a problem: the `curve` bundle transitively relies on `lodash` through `gl-matrix`. @@ -164,7 +164,7 @@ graph LR C -- resolved to --> F ``` -The `curve` bundle's dependency tree has changed, so we need to rebuiid and test it (to make sure that it works with this new version of `lodash`). +The `curve` bundle's dependency tree has changed, so we need to rebuild and test it (to make sure that it works with this new version of `lodash`). Yet, because there were no changes made to its `package.json` or to the code of the `curve` bundle, the `git diff` method won't be able to detect that we need to rebuild the `curve` bundle. From 5794b530358f501774d19b048f1cd864fac5e363 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Fri, 23 Jan 2026 20:59:16 +0800 Subject: [PATCH 22/71] Update blueprintjs versions and add it to packages that didn't specify it as a dependency --- devserver/package.json | 6 +- .../components/sideContent/SideContent.tsx | 2 +- lib/buildtools/src/templates/tab.ts | 2 +- lib/modules-lib/package.json | 6 +- package.json | 6 +- src/bundles/binary_tree/package.json | 2 +- src/bundles/csg/package.json | 1 + src/bundles/curve/package.json | 2 +- src/bundles/game/package.json | 2 +- src/bundles/midi/package.json | 2 +- src/bundles/plotly/package.json | 2 +- src/bundles/remote_execution/package.json | 2 +- src/bundles/repl/package.json | 2 +- src/bundles/robot_simulation/package.json | 1 + src/bundles/rune/package.json | 2 +- src/bundles/sound/package.json | 2 +- src/bundles/sound_matrix/package.json | 2 +- src/bundles/stereo_sound/package.json | 2 +- src/bundles/unittest/package.json | 2 +- src/bundles/unity_academy/package.json | 4 +- src/tabs/ArcadeTwod/package.json | 4 +- src/tabs/AugmentedReality/package.json | 2 +- src/tabs/CopyGc/package.json | 1 + src/tabs/Csg/package.json | 4 +- src/tabs/Curve/package.json | 4 +- src/tabs/MarkSweep/package.json | 1 + src/tabs/Nbody/package.json | 2 + src/tabs/Physics2D/package.json | 2 + src/tabs/Pixnflix/package.json | 2 + src/tabs/Repl/package.json | 2 + src/tabs/RobotSimulation/package.json | 1 + src/tabs/SoundMatrix/package.json | 1 + src/tabs/UnityAcademy/package.json | 4 +- yarn.config.cjs | 2 - yarn.lock | 143 +++++++++--------- 35 files changed, 121 insertions(+), 106 deletions(-) diff --git a/devserver/package.json b/devserver/package.json index 53e90ea654..5888505107 100644 --- a/devserver/package.json +++ b/devserver/package.json @@ -9,15 +9,15 @@ "devserver": "./bin.js" }, "dependencies": { - "@blueprintjs/core": "^5.10.2", - "@blueprintjs/icons": "^5.9.0", + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "@commander-js/extra-typings": "^14.0.0", "@sourceacademy/modules-lib": "workspace:^", "@vitejs/plugin-react": "^5.1.0", "ace-builds": "^1.25.1", "classnames": "^2.3.1", "commander": "^14.0.0", - "js-slang": "^1.0.81", + "js-slang": "^1.0.85", "re-resizable": "^6.9.11", "react": "^18.3.1", "react-ace": "^10.1.0", diff --git a/devserver/src/components/sideContent/SideContent.tsx b/devserver/src/components/sideContent/SideContent.tsx index 74fef9c542..82f6bbdefd 100644 --- a/devserver/src/components/sideContent/SideContent.tsx +++ b/devserver/src/components/sideContent/SideContent.tsx @@ -37,7 +37,7 @@ interface TabIconProps { function TabIcon({ iconName, tooltip, shouldAlert }: TabIconProps) { return
- +
; } diff --git a/lib/buildtools/src/templates/tab.ts b/lib/buildtools/src/templates/tab.ts index a9e8b54d3c..e2f6ab8e04 100644 --- a/lib/buildtools/src/templates/tab.ts +++ b/lib/buildtools/src/templates/tab.ts @@ -50,7 +50,7 @@ export async function addNew(bundlesDir: string, tabsDir: string, rl: Interface) await fs.mkdir(tabsDir, { recursive: true }); - const reactVersion = _package.dependencies.react; + const reactVersion = _package.peerDependencies.react; const { '@types/react': reactTypesVersion, typescript: typescriptVersion diff --git a/lib/modules-lib/package.json b/lib/modules-lib/package.json index 4b7878af1d..05eaf10936 100644 --- a/lib/modules-lib/package.json +++ b/lib/modules-lib/package.json @@ -31,9 +31,9 @@ "./*": "./dist/*.js" }, "dependencies": { - "@blueprintjs/core": "^5.10.2", - "@blueprintjs/icons": "^5.9.0", - "js-slang": "^1.0.81", + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", + "js-slang": "^1.0.85", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/package.json b/package.json index 2a597b30cb..678982e965 100644 --- a/package.json +++ b/package.json @@ -78,8 +78,10 @@ "vitest": "^4.0.4", "vitest-browser-react": "^2.0.2" }, - "dependencies": { - "js-slang": "^1.0.81", + "peerDependencies": { + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", + "js-slang": "^1.0.85", "lodash": "^4.17.21", "react": "^18.3.1", "react-dom": "^18.3.1" diff --git a/src/bundles/binary_tree/package.json b/src/bundles/binary_tree/package.json index c5f6417e61..9e68b5c26a 100644 --- a/src/bundles/binary_tree/package.json +++ b/src/bundles/binary_tree/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { - "js-slang": "^1.0.81" + "js-slang": "^1.0.85" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/bundles/csg/package.json b/src/bundles/csg/package.json index 2d09c42ba6..bd88d203d9 100644 --- a/src/bundles/csg/package.json +++ b/src/bundles/csg/package.json @@ -7,6 +7,7 @@ "@jscad/regl-renderer": "^2.6.1", "@jscad/stl-serializer": "2.1.11", "@sourceacademy/modules-lib": "workspace:^", + "js-slang": "^1.0.85", "save-file": "^2.3.1" }, "exports": { diff --git a/src/bundles/curve/package.json b/src/bundles/curve/package.json index 777a139381..805f8c10d6 100644 --- a/src/bundles/curve/package.json +++ b/src/bundles/curve/package.json @@ -5,7 +5,7 @@ "dependencies": { "@sourceacademy/modules-lib": "workspace:^", "gl-matrix": "^3.3.0", - "js-slang": "^1.0.81" + "js-slang": "^1.0.85" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/bundles/game/package.json b/src/bundles/game/package.json index d2cb512aca..18514e535d 100644 --- a/src/bundles/game/package.json +++ b/src/bundles/game/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { - "js-slang": "^1.0.81", + "js-slang": "^1.0.85", "phaser": "^3.54.0" }, "devDependencies": { diff --git a/src/bundles/midi/package.json b/src/bundles/midi/package.json index fbc592149e..ecda58a0c2 100644 --- a/src/bundles/midi/package.json +++ b/src/bundles/midi/package.json @@ -7,7 +7,7 @@ "typescript": "^5.8.2" }, "dependencies": { - "js-slang": "^1.0.81" + "js-slang": "^1.0.85" }, "type": "module", "scripts": { diff --git a/src/bundles/plotly/package.json b/src/bundles/plotly/package.json index e91a715c1c..778e9fcffe 100644 --- a/src/bundles/plotly/package.json +++ b/src/bundles/plotly/package.json @@ -5,7 +5,7 @@ "dependencies": { "@sourceacademy/bundle-curve": "workspace:^", "@sourceacademy/bundle-sound": "workspace:^", - "js-slang": "^1.0.81", + "js-slang": "^1.0.85", "plotly.js-dist": "^3.0.0" }, "devDependencies": { diff --git a/src/bundles/remote_execution/package.json b/src/bundles/remote_execution/package.json index 3cf279b102..8303d2e315 100644 --- a/src/bundles/remote_execution/package.json +++ b/src/bundles/remote_execution/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { - "js-slang": "^1.0.81" + "js-slang": "^1.0.85" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/bundles/repl/package.json b/src/bundles/repl/package.json index 1ef1955cdd..43f1d31c8f 100644 --- a/src/bundles/repl/package.json +++ b/src/bundles/repl/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { - "js-slang": "^1.0.81" + "js-slang": "^1.0.85" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/bundles/robot_simulation/package.json b/src/bundles/robot_simulation/package.json index 84a313480e..c8d974932b 100644 --- a/src/bundles/robot_simulation/package.json +++ b/src/bundles/robot_simulation/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@sourceacademy/modules-lib": "workspace:^", + "js-slang": "^1.0.85", "three": "^0.181.0" }, "devDependencies": { diff --git a/src/bundles/rune/package.json b/src/bundles/rune/package.json index 4164568546..d30ffd5cfd 100644 --- a/src/bundles/rune/package.json +++ b/src/bundles/rune/package.json @@ -8,7 +8,7 @@ }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", - "js-slang": "^1.0.81", + "js-slang": "^1.0.85", "typescript": "^5.8.2" }, "type": "module", diff --git a/src/bundles/sound/package.json b/src/bundles/sound/package.json index 39f689e5cf..720c5f43e7 100644 --- a/src/bundles/sound/package.json +++ b/src/bundles/sound/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@sourceacademy/bundle-midi": "workspace:^", - "js-slang": "^1.0.81" + "js-slang": "^1.0.85" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/bundles/sound_matrix/package.json b/src/bundles/sound_matrix/package.json index f1f3a570f7..7161042b62 100644 --- a/src/bundles/sound_matrix/package.json +++ b/src/bundles/sound_matrix/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { - "js-slang": "^1.0.81" + "js-slang": "^1.0.85" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/bundles/stereo_sound/package.json b/src/bundles/stereo_sound/package.json index 5dd89cbf4b..b8c3a00a93 100644 --- a/src/bundles/stereo_sound/package.json +++ b/src/bundles/stereo_sound/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "@sourceacademy/bundle-midi": "workspace:^", - "js-slang": "^1.0.81" + "js-slang": "^1.0.85" }, "type": "module", "exports": { diff --git a/src/bundles/unittest/package.json b/src/bundles/unittest/package.json index 17d1ad09d6..99f4476f3b 100644 --- a/src/bundles/unittest/package.json +++ b/src/bundles/unittest/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { - "js-slang": "^1.0.81", + "js-slang": "^1.0.85", "lodash": "^4.17.21" }, "devDependencies": { diff --git a/src/bundles/unity_academy/package.json b/src/bundles/unity_academy/package.json index 9ac91ad3e3..7a398055ee 100644 --- a/src/bundles/unity_academy/package.json +++ b/src/bundles/unity_academy/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { - "@blueprintjs/core": "^5.10.2", - "@blueprintjs/icons": "^5.9.0", + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/src/tabs/ArcadeTwod/package.json b/src/tabs/ArcadeTwod/package.json index 1d81c11203..2a2e7431c6 100644 --- a/src/tabs/ArcadeTwod/package.json +++ b/src/tabs/ArcadeTwod/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { - "@blueprintjs/core": "^5.10.2", - "@blueprintjs/icons": "^5.9.0", + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "@sourceacademy/modules-lib": "workspace:^", "phaser": "^3.54.0", "react": "^18.3.1", diff --git a/src/tabs/AugmentedReality/package.json b/src/tabs/AugmentedReality/package.json index d04773caf9..c475435f84 100644 --- a/src/tabs/AugmentedReality/package.json +++ b/src/tabs/AugmentedReality/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { - "@blueprintjs/icons": "^5.9.0", + "@blueprintjs/icons": "^6.0.0", "@sourceacademy/bundle-ar": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", "react": "^18.3.1", diff --git a/src/tabs/CopyGc/package.json b/src/tabs/CopyGc/package.json index 4ab70be0e6..c592e14636 100644 --- a/src/tabs/CopyGc/package.json +++ b/src/tabs/CopyGc/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { + "@blueprintjs/core": "^6.0.0", "@sourceacademy/bundle-copy_gc": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", "react": "^18.3.1", diff --git a/src/tabs/Csg/package.json b/src/tabs/Csg/package.json index e52e6e1f24..ca9a861b0f 100644 --- a/src/tabs/Csg/package.json +++ b/src/tabs/Csg/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { - "@blueprintjs/core": "^5.10.2", - "@blueprintjs/icons": "^5.9.0", + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "@sourceacademy/bundle-csg": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", "react": "^18.3.1", diff --git a/src/tabs/Curve/package.json b/src/tabs/Curve/package.json index 1d7519582f..3e18665113 100644 --- a/src/tabs/Curve/package.json +++ b/src/tabs/Curve/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { - "@blueprintjs/core": "^5.10.2", - "@blueprintjs/icons": "^5.9.0", + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "@sourceacademy/bundle-curve": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", "react": "^18.3.1", diff --git a/src/tabs/MarkSweep/package.json b/src/tabs/MarkSweep/package.json index 7b5b84ccee..4d63181a33 100644 --- a/src/tabs/MarkSweep/package.json +++ b/src/tabs/MarkSweep/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { + "@blueprintjs/core": "^6.0.0", "@sourceacademy/modules-lib": "workspace:^", "react": "^18.3.1", "react-dom": "^18.3.1" diff --git a/src/tabs/Nbody/package.json b/src/tabs/Nbody/package.json index c4b39b3cbf..7e6af37b99 100644 --- a/src/tabs/Nbody/package.json +++ b/src/tabs/Nbody/package.json @@ -3,6 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "@sourceacademy/modules-lib": "workspace:^", "nbody": "^0.2.0", "plotly.js-dist": "^2.17.1", diff --git a/src/tabs/Physics2D/package.json b/src/tabs/Physics2D/package.json index 8c49b410da..c861933ba0 100644 --- a/src/tabs/Physics2D/package.json +++ b/src/tabs/Physics2D/package.json @@ -3,6 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "@box2d/debug-draw": "^0.10.0", "@sourceacademy/bundle-physics_2d": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", diff --git a/src/tabs/Pixnflix/package.json b/src/tabs/Pixnflix/package.json index dadec2347c..906ff205cd 100644 --- a/src/tabs/Pixnflix/package.json +++ b/src/tabs/Pixnflix/package.json @@ -3,6 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "@sourceacademy/bundle-pix_n_flix": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", "react": "^18.3.1", diff --git a/src/tabs/Repl/package.json b/src/tabs/Repl/package.json index 16752edb73..d34b584313 100644 --- a/src/tabs/Repl/package.json +++ b/src/tabs/Repl/package.json @@ -3,6 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "@sourceacademy/bundle-repl": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", "ace-builds": "^1.25.1", diff --git a/src/tabs/RobotSimulation/package.json b/src/tabs/RobotSimulation/package.json index d1e4f7a1f0..9ee29e9006 100644 --- a/src/tabs/RobotSimulation/package.json +++ b/src/tabs/RobotSimulation/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { + "@blueprintjs/core": "^6.0.0", "@dimforge/rapier3d-compat": "^0.11.2", "@sourceacademy/bundle-robot_simulation": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", diff --git a/src/tabs/SoundMatrix/package.json b/src/tabs/SoundMatrix/package.json index 36a20a9e56..fd57f5a0f5 100644 --- a/src/tabs/SoundMatrix/package.json +++ b/src/tabs/SoundMatrix/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { + "@blueprintjs/core": "^6.0.0", "@sourceacademy/modules-lib": "workspace:^", "classnames": "^2.3.1", "react": "^18.3.1", diff --git a/src/tabs/UnityAcademy/package.json b/src/tabs/UnityAcademy/package.json index 2ef97c5584..324bcf521f 100644 --- a/src/tabs/UnityAcademy/package.json +++ b/src/tabs/UnityAcademy/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { - "@blueprintjs/core": "^5.10.2", - "@blueprintjs/icons": "^5.9.0", + "@blueprintjs/core": "^6.0.0", + "@blueprintjs/icons": "^6.0.0", "@sourceacademy/bundle-unity_academy": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", "react": "^18.3.1", diff --git a/yarn.config.cjs b/yarn.config.cjs index b5936a27da..0053916286 100644 --- a/yarn.config.cjs +++ b/yarn.config.cjs @@ -32,8 +32,6 @@ module.exports = defineConfig({ rootWorkspace.set('resolutions.js-slang', undefined); for (const workspaceDep of Yarn.dependencies({ workspace: rootWorkspace })) { - if (workspaceDep.type === 'peerDependencies') continue; - for (const otherDep of Yarn.dependencies({ ident: workspaceDep.ident })) { if (otherDep.type === 'peerDependencies') continue; diff --git a/yarn.lock b/yarn.lock index 6657725610..19c97722f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1165,58 +1165,57 @@ __metadata: languageName: node linkType: hard -"@blueprintjs/colors@npm:^5.1.8": - version: 5.1.8 - resolution: "@blueprintjs/colors@npm:5.1.8" +"@blueprintjs/colors@npm:^5.1.12": + version: 5.1.12 + resolution: "@blueprintjs/colors@npm:5.1.12" dependencies: tslib: "npm:~2.6.2" - checksum: 10c0/d0a3d500628f60415f830df872244370efb0268f43b03a5c7c27d473ea1be5b8c9fb35fbc47330d7c022f3ddecd7afefb6ee4ef94789fe98feb2be95b15753ac + checksum: 10c0/749a59646082c5605f12b095595e9662587dafcb2fdb253ba57131faa9ce829630bd1cb1709a53ef430ba5fc1159b375523a5a578c9f8ff644d7a0a2e5911a55 languageName: node linkType: hard -"@blueprintjs/core@npm:^5.10.2": - version: 5.19.1 - resolution: "@blueprintjs/core@npm:5.19.1" +"@blueprintjs/core@npm:^6.0.0": + version: 6.6.1 + resolution: "@blueprintjs/core@npm:6.6.1" dependencies: - "@blueprintjs/colors": "npm:^5.1.8" - "@blueprintjs/icons": "npm:^5.23.0" + "@blueprintjs/colors": "npm:^5.1.12" + "@blueprintjs/icons": "npm:^6.5.0" "@popperjs/core": "npm:^2.11.8" classnames: "npm:^2.3.1" normalize.css: "npm:^8.0.1" react-popper: "npm:^2.3.0" react-transition-group: "npm:^4.4.5" - react-uid: "npm:^2.3.3" tslib: "npm:~2.6.2" use-sync-external-store: "npm:^1.2.0" peerDependencies: - "@types/react": ^16.14.41 || 17 || 18 - react: ^16.8 || 17 || 18 - react-dom: ^16.8 || 17 || 18 + "@types/react": 18 + react: 18 + react-dom: 18 peerDependenciesMeta: "@types/react": optional: true bin: upgrade-blueprint-2.0.0-rename: scripts/upgrade-blueprint-2.0.0-rename.sh upgrade-blueprint-3.0.0-rename: scripts/upgrade-blueprint-3.0.0-rename.sh - checksum: 10c0/0805c88b3da989fa242c5acf4dda0bfaf20e937f61e8c3b8e9189f34d5e4b6bde90bf7e55eefb07c18716fed77df9b76bc6197c2e53e2e662d4b82569015253c + checksum: 10c0/a9f90ee376a3a1d16314160f853460d8b279514437deeb907844bebe9749d47a2cb3bcf1f5ff82df4c2f87f7b7ca4fb2e136d3ec8706c650e15cd39dd399c1c1 languageName: node linkType: hard -"@blueprintjs/icons@npm:^5.23.0, @blueprintjs/icons@npm:^5.9.0": - version: 5.23.0 - resolution: "@blueprintjs/icons@npm:5.23.0" +"@blueprintjs/icons@npm:^6.0.0, @blueprintjs/icons@npm:^6.5.0": + version: 6.5.0 + resolution: "@blueprintjs/icons@npm:6.5.0" dependencies: change-case: "npm:^4.1.2" classnames: "npm:^2.3.1" tslib: "npm:~2.6.2" peerDependencies: - "@types/react": ^16.14.41 || 17 || 18 - react: ^16.8 || 17 || 18 - react-dom: ^16.8 || 17 || 18 + "@types/react": 18 + react: 18 + react-dom: 18 peerDependenciesMeta: "@types/react": optional: true - checksum: 10c0/9af904e3b5c2c5e9ac7c9b12e1612184805f60d560a554df8917dafd715bed1cf1586ce31d64c59c2a7c84f595b8999c770036b9ff7f9c9f480ac1b82ccfae70 + checksum: 10c0/ce911dec2d0d91e4ce1eccfd72d242c9484007f4399954f7783aad4c467ebed6ba3e97ce0c2ecce6e9432cdfb99c706ee59bd18acfc224b37792cdd3b724054f languageName: node linkType: hard @@ -4273,7 +4272,7 @@ __metadata: resolution: "@sourceacademy/bundle-binary_tree@workspace:src/bundles/binary_tree" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4309,6 +4308,7 @@ __metadata: "@jscad/stl-serializer": "npm:2.1.11" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" + js-slang: "npm:^1.0.85" save-file: "npm:^2.3.1" typescript: "npm:^5.8.2" languageName: unknown @@ -4321,7 +4321,7 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" gl-matrix: "npm:^3.3.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4331,7 +4331,7 @@ __metadata: resolution: "@sourceacademy/bundle-game@workspace:src/bundles/game" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" phaser: "npm:^3.54.0" typescript: "npm:^5.8.2" languageName: unknown @@ -4351,7 +4351,7 @@ __metadata: resolution: "@sourceacademy/bundle-midi@workspace:src/bundles/midi" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4417,7 +4417,7 @@ __metadata: "@sourceacademy/bundle-sound": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@types/plotly.js": "npm:^3.0.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" plotly.js-dist: "npm:^3.0.0" typescript: "npm:^5.8.2" languageName: unknown @@ -4428,7 +4428,7 @@ __metadata: resolution: "@sourceacademy/bundle-remote_execution@workspace:src/bundles/remote_execution" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4447,7 +4447,7 @@ __metadata: resolution: "@sourceacademy/bundle-repl@workspace:src/bundles/repl" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4460,6 +4460,7 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/three": "npm:^0.181.0" + js-slang: "npm:^1.0.85" three: "npm:^0.181.0" typescript: "npm:^5.8.2" languageName: unknown @@ -4472,7 +4473,7 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" gl-matrix: "npm:^3.3.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4502,7 +4503,7 @@ __metadata: "@sourceacademy/bundle-midi": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4512,7 +4513,7 @@ __metadata: resolution: "@sourceacademy/bundle-sound_matrix@workspace:src/bundles/sound_matrix" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4523,7 +4524,7 @@ __metadata: dependencies: "@sourceacademy/bundle-midi": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4534,7 +4535,7 @@ __metadata: dependencies: "@sourceacademy/modules-buildtools": "workspace:^" "@types/lodash": "npm:^4.14.198" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" lodash: "npm:^4.17.21" typescript: "npm:^5.8.2" languageName: unknown @@ -4544,8 +4545,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/bundle-unity_academy@workspace:src/bundles/unity_academy" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" @@ -4654,8 +4655,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/modules-devserver@workspace:devserver" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@commander-js/extra-typings": "npm:^14.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4667,7 +4668,7 @@ __metadata: classnames: "npm:^2.3.1" commander: "npm:^14.0.0" eslint: "npm:^9.35.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" playwright: "npm:^1.55.1" re-resizable: "npm:^6.9.11" react: "npm:^18.3.1" @@ -4720,15 +4721,15 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/modules-lib@workspace:lib/modules-lib" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" "@vitejs/plugin-react": "npm:^5.1.0" "@vitest/browser-playwright": "npm:^4.0.4" eslint: "npm:^9.35.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" @@ -4791,16 +4792,19 @@ __metadata: eslint-plugin-react-hooks: "npm:^5.1.0" eslint-plugin-yml: "npm:^1.19.0" husky: "npm:^9.1.7" - js-slang: "npm:^1.0.81" jsdom: "npm:^26.1.0" jsonc-eslint-parser: "npm:^2.4.0" - lodash: "npm:^4.17.21" - react: "npm:^18.3.1" - react-dom: "npm:^18.3.1" typescript: "npm:^5.8.2" typescript-eslint: "npm:^8.53.1" vitest: "npm:^4.0.4" vitest-browser-react: "npm:^2.0.2" + peerDependencies: + "@blueprintjs/core": ^6.0.0 + "@blueprintjs/icons": ^6.0.0 + js-slang: ^1.0.85 + lodash: ^4.17.21 + react: ^18.3.1 + react-dom: ^18.3.1 languageName: unknown linkType: soft @@ -4808,8 +4812,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-ArcadeTwod@workspace:src/tabs/ArcadeTwod" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" @@ -4824,7 +4828,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-AugmentedReality@workspace:src/tabs/AugmentedReality" dependencies: - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-ar": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4840,6 +4844,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-CopyGc@workspace:src/tabs/CopyGc" dependencies: + "@blueprintjs/core": "npm:^6.0.0" "@sourceacademy/bundle-copy_gc": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4854,8 +4859,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Csg@workspace:src/tabs/Csg" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-csg": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4870,8 +4875,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Curve@workspace:src/tabs/Curve" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-curve": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4903,6 +4908,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-MarkSweep@workspace:src/tabs/MarkSweep" dependencies: + "@blueprintjs/core": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" @@ -4915,6 +4921,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Nbody@workspace:src/tabs/Nbody" dependencies: + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/plotly.js": "npm:^2.35.4" @@ -4946,6 +4954,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Physics2D@workspace:src/tabs/Physics2D" dependencies: + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@box2d/debug-draw": "npm:^0.10.0" "@sourceacademy/bundle-physics_2d": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" @@ -4960,6 +4970,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Pixnflix@workspace:src/tabs/Pixnflix" dependencies: + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-pix_n_flix": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4998,6 +5010,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Repl@workspace:src/tabs/Repl" dependencies: + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-repl": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -5014,6 +5028,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-RobotSimulation@workspace:src/tabs/RobotSimulation" dependencies: + "@blueprintjs/core": "npm:^6.0.0" "@dimforge/rapier3d-compat": "npm:^0.11.2" "@sourceacademy/bundle-robot_simulation": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" @@ -5058,6 +5073,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-SoundMatrix@workspace:src/tabs/SoundMatrix" dependencies: + "@blueprintjs/core": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" @@ -5099,8 +5115,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-UnityAcademy@workspace:src/tabs/UnityAcademy" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-unity_academy": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -12435,7 +12451,7 @@ __metadata: languageName: node linkType: hard -"js-slang@npm:^1.0.81": +"js-slang@npm:^1.0.85": version: 1.0.85 resolution: "js-slang@npm:1.0.85" dependencies: @@ -15664,21 +15680,6 @@ __metadata: languageName: node linkType: hard -"react-uid@npm:^2.3.3": - version: 2.4.0 - resolution: "react-uid@npm:2.4.0" - dependencies: - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/5e01e8d3a4144d160af26f7ea8300887ed8379ee14b1fad7979ea755d5bfa4badfdab531cb7d4495488e94083f829bd5b28a8f6661522b11729fceb42dcf73ea - languageName: node - linkType: hard - "react-use-measure@npm:^2.1.7": version: 2.1.7 resolution: "react-use-measure@npm:2.1.7" @@ -17713,7 +17714,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2, tslib@npm:^2.0.0, tslib@npm:^2.0.3, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3, tslib@npm:^2.8.1": +"tslib@npm:^2, tslib@npm:^2.0.3, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3, tslib@npm:^2.8.1": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 From 694717456de4be0452a6fd1e294e835d56390721 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Fri, 23 Jan 2026 22:56:28 +0800 Subject: [PATCH 23/71] Fix eslint import paths --- eslint.config.js | 18 +++++++++++++++++- lib/buildtools/src/build/__tests__/all.test.ts | 6 +++--- .../ev3/components/__tests__/Wheel.test.ts | 2 +- .../__tests__/PidController.test.ts | 2 +- .../program/__tests__/Program.test.ts | 6 +++--- .../Core/__tests__/CallbackHandler.test.ts | 2 +- .../engine/Core/__tests__/Controller.test.ts | 4 ++-- .../src/engine/Core/__tests__/Events.test.ts | 2 +- .../engine/Core/__tests__/RobotConsole.test.ts | 2 +- .../src/engine/Core/__tests__/Timer.test.ts | 2 +- .../src/engine/Entity/__tests__/Entity.test.ts | 2 +- .../src/engine/Math/__tests__/Convert.test.ts | 2 +- .../Render/__tests__/MeshFactory.test.ts | 2 +- .../Render/__tests__/helpers/Camera.test.ts | 2 +- 14 files changed, 35 insertions(+), 19 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 9c701918ef..7cb0965110 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -316,6 +316,13 @@ export default defineConfig( rules: { 'no-unused-vars': 'off', // Use the typescript eslint rule instead + 'import/no-unresolved': ['error', { + ignore: [ + 'js-slang/context', + '^virtual:.+$' + ] + }], + 'jsdoc/no-types': 'warn', '@stylistic/type-annotation-spacing': ['warn', { overrides: { colon: { before: false, after: true } } }], @@ -330,6 +337,12 @@ export default defineConfig( // '@typescript-eslint/no-unnecessary-type-assertion': 'error', '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], // Was 'error' '@typescript-eslint/only-throw-error': 'error' + }, + settings: { + 'import/resolver': { + typescript: true, + node: true + } } }, // #endregion typescript @@ -504,7 +517,10 @@ export default defineConfig( '**/vitest.config.{js,ts}' ], rules: { - 'import/extensions': ['error', 'ignorePackages'], + 'import/extensions': ['error', 'ignorePackages', { + ts: 'never', + cts: 'never' + }], } }, { diff --git a/lib/buildtools/src/build/__tests__/all.test.ts b/lib/buildtools/src/build/__tests__/all.test.ts index 222c913c12..8776f77571 100644 --- a/lib/buildtools/src/build/__tests__/all.test.ts +++ b/lib/buildtools/src/build/__tests__/all.test.ts @@ -1,13 +1,13 @@ import pathlib from 'path'; import { bundlesDir, tabsDir } from '@sourceacademy/modules-repotools/getGitRoot'; import { describe, expect, test, vi } from 'vitest'; -import * as docs from '../../build/docs/index.js'; -import * as modules from '../../build/modules/index.js'; -import * as tsc from '../../build/modules/tsc.js'; import { getCommandRunner } from '../../commands/__tests__/testingUtils.js'; import { getBuildAllCommand } from '../../commands/build.js'; import * as lint from '../../prebuild/lint.js'; import * as all from '../all.js'; +import * as docs from '../docs/index.js'; +import * as modules from '../modules/index.js'; +import * as tsc from '../modules/tsc.js'; vi.spyOn(all, 'buildAll'); const mockedBuildBundle = vi.spyOn(modules, 'buildBundle'); diff --git a/src/bundles/robot_simulation/src/controllers/ev3/components/__tests__/Wheel.test.ts b/src/bundles/robot_simulation/src/controllers/ev3/components/__tests__/Wheel.test.ts index e2346993e0..bb5ef0ed94 100644 --- a/src/bundles/robot_simulation/src/controllers/ev3/components/__tests__/Wheel.test.ts +++ b/src/bundles/robot_simulation/src/controllers/ev3/components/__tests__/Wheel.test.ts @@ -1,6 +1,6 @@ import * as THREE from 'three'; import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { Wheel } from '../../../ev3/components/Wheel'; +import { Wheel } from '../Wheel'; vi.mock(import('../../../../engine/Render/debug/DebugArrow'), () => ({ DebugArrow: class { diff --git a/src/bundles/robot_simulation/src/controllers/ev3/feedback_control/__tests__/PidController.test.ts b/src/bundles/robot_simulation/src/controllers/ev3/feedback_control/__tests__/PidController.test.ts index 4538f75b6f..f0c3a02559 100644 --- a/src/bundles/robot_simulation/src/controllers/ev3/feedback_control/__tests__/PidController.test.ts +++ b/src/bundles/robot_simulation/src/controllers/ev3/feedback_control/__tests__/PidController.test.ts @@ -1,6 +1,6 @@ import * as THREE from 'three'; import { beforeEach, describe, expect, it } from 'vitest'; -import { NumberPidController, VectorPidController } from '../../../ev3/feedback_control/PidController'; +import { NumberPidController, VectorPidController } from '../PidController'; const resetPid = (pidController: NumberPidController) => { pidController.errorsSum = 0; diff --git a/src/bundles/robot_simulation/src/controllers/program/__tests__/Program.test.ts b/src/bundles/robot_simulation/src/controllers/program/__tests__/Program.test.ts index eb09b58ec2..e61cbfdf28 100644 --- a/src/bundles/robot_simulation/src/controllers/program/__tests__/Program.test.ts +++ b/src/bundles/robot_simulation/src/controllers/program/__tests__/Program.test.ts @@ -1,10 +1,10 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { CallbackHandler } from '../../../engine/Core/CallbackHandler'; -import { Program, program_controller_identifier } from '../../program/Program'; -import { runECEvaluator } from '../../program/evaluate'; +import { Program, program_controller_identifier } from '../Program'; +import { runECEvaluator } from '../evaluate'; vi.mock(import('../../../engine/Core/CallbackHandler')); -vi.mock(import('../../program/evaluate')); +vi.mock(import('../evaluate')); const mockedRunECEvaluator = vi.mocked(runECEvaluator); const mockedCallbackHandler = vi.mocked(CallbackHandler); diff --git a/src/bundles/robot_simulation/src/engine/Core/__tests__/CallbackHandler.test.ts b/src/bundles/robot_simulation/src/engine/Core/__tests__/CallbackHandler.test.ts index 8b3608a625..b53e2101d8 100644 --- a/src/bundles/robot_simulation/src/engine/Core/__tests__/CallbackHandler.test.ts +++ b/src/bundles/robot_simulation/src/engine/Core/__tests__/CallbackHandler.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test, vi } from 'vitest'; -import { CallbackHandler } from '../../Core/CallbackHandler'; import type { PhysicsTimingInfo } from '../../Physics'; +import { CallbackHandler } from '../CallbackHandler'; // Helper function to create a PhysicsTimingInfo object // CallbackHandler only uses the stepCount and timestep properties diff --git a/src/bundles/robot_simulation/src/engine/Core/__tests__/Controller.test.ts b/src/bundles/robot_simulation/src/engine/Core/__tests__/Controller.test.ts index 523e92105d..bec91a6b1e 100644 --- a/src/bundles/robot_simulation/src/engine/Core/__tests__/Controller.test.ts +++ b/src/bundles/robot_simulation/src/engine/Core/__tests__/Controller.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test, vi, type Mock } from 'vitest'; +import type { PhysicsTimingInfo } from '../../Physics'; import { ControllerGroup, ControllerMap, type Controller, -} from '../../Core/Controller'; -import type { PhysicsTimingInfo } from '../../Physics'; +} from '../Controller'; // Helper function to create a PhysicsTimingInfo object // CallbackHandler only uses the stepCount and timestep properties diff --git a/src/bundles/robot_simulation/src/engine/Core/__tests__/Events.test.ts b/src/bundles/robot_simulation/src/engine/Core/__tests__/Events.test.ts index a5d387ccf9..f8db54d66a 100644 --- a/src/bundles/robot_simulation/src/engine/Core/__tests__/Events.test.ts +++ b/src/bundles/robot_simulation/src/engine/Core/__tests__/Events.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; -import { TypedEventTarget } from '../../Core/Events'; +import { TypedEventTarget } from '../Events'; class StringEvent extends Event { public data: string; diff --git a/src/bundles/robot_simulation/src/engine/Core/__tests__/RobotConsole.test.ts b/src/bundles/robot_simulation/src/engine/Core/__tests__/RobotConsole.test.ts index c43268a4b7..004d0ea3a1 100644 --- a/src/bundles/robot_simulation/src/engine/Core/__tests__/RobotConsole.test.ts +++ b/src/bundles/robot_simulation/src/engine/Core/__tests__/RobotConsole.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, test } from 'vitest'; -import { RobotConsole } from '../../Core/RobotConsole'; // Adjust the import path as necessary +import { RobotConsole } from '../RobotConsole'; describe(RobotConsole, () => { let robotConsole: RobotConsole; diff --git a/src/bundles/robot_simulation/src/engine/Core/__tests__/Timer.test.ts b/src/bundles/robot_simulation/src/engine/Core/__tests__/Timer.test.ts index 5711ceb430..5ec6171238 100644 --- a/src/bundles/robot_simulation/src/engine/Core/__tests__/Timer.test.ts +++ b/src/bundles/robot_simulation/src/engine/Core/__tests__/Timer.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from 'vitest'; -import { Timer } from '../../Core/Timer'; // Adjust the import path as per your project structure +import { Timer } from '../Timer'; // Adjust the import path as per your project structure describe(Timer, () => { let timer; diff --git a/src/bundles/robot_simulation/src/engine/Entity/__tests__/Entity.test.ts b/src/bundles/robot_simulation/src/engine/Entity/__tests__/Entity.test.ts index 72228a64c3..90b239df71 100644 --- a/src/bundles/robot_simulation/src/engine/Entity/__tests__/Entity.test.ts +++ b/src/bundles/robot_simulation/src/engine/Entity/__tests__/Entity.test.ts @@ -1,8 +1,8 @@ import type Rapier from '@dimforge/rapier3d-compat'; import { beforeEach, describe, expect, test, vi } from 'vitest'; -import { Entity } from '../../Entity/Entity'; import { vec3 } from '../../Math/Convert'; import type { SimpleQuaternion, SimpleVector } from '../../Math/Vector'; +import { Entity } from '../Entity'; const createRigidBodyMock = ( translation: SimpleVector, diff --git a/src/bundles/robot_simulation/src/engine/Math/__tests__/Convert.test.ts b/src/bundles/robot_simulation/src/engine/Math/__tests__/Convert.test.ts index 291b9c7f38..4ce63f6fed 100644 --- a/src/bundles/robot_simulation/src/engine/Math/__tests__/Convert.test.ts +++ b/src/bundles/robot_simulation/src/engine/Math/__tests__/Convert.test.ts @@ -1,6 +1,6 @@ import { Euler, Quaternion, Vector3 } from 'three'; import { describe, expect, it } from 'vitest'; -import { euler, quat, vec3 } from '../../Math/Convert'; // Adjust the import path as necessary +import { euler, quat, vec3 } from '../Convert'; // Adjust the import path as necessary describe('Three.js utility functions', () => { describe('quat function', () => { diff --git a/src/bundles/robot_simulation/src/engine/Render/__tests__/MeshFactory.test.ts b/src/bundles/robot_simulation/src/engine/Render/__tests__/MeshFactory.test.ts index 703d485a6e..06fa0ab0a8 100644 --- a/src/bundles/robot_simulation/src/engine/Render/__tests__/MeshFactory.test.ts +++ b/src/bundles/robot_simulation/src/engine/Render/__tests__/MeshFactory.test.ts @@ -1,6 +1,6 @@ import * as THREE from 'three'; import { describe, expect, it, vi } from 'vitest'; -import { addCuboid } from '../../Render/helpers/MeshFactory'; +import { addCuboid } from '../helpers/MeshFactory'; // Mock the necessary Three.js methods and classes vi.mock(import('three'), async importOriginal => { diff --git a/src/bundles/robot_simulation/src/engine/Render/__tests__/helpers/Camera.test.ts b/src/bundles/robot_simulation/src/engine/Render/__tests__/helpers/Camera.test.ts index 73028d8a45..92bdf79595 100644 --- a/src/bundles/robot_simulation/src/engine/Render/__tests__/helpers/Camera.test.ts +++ b/src/bundles/robot_simulation/src/engine/Render/__tests__/helpers/Camera.test.ts @@ -1,7 +1,7 @@ import * as THREE from 'three'; import { describe, expect, test } from 'vitest'; -import { getCamera, type CameraOptions } from '../../../Render/helpers/Camera'; +import { getCamera, type CameraOptions } from '../../helpers/Camera'; describe(getCamera, () => { test('returns a PerspectiveCamera when type is "perspective"', () => { From 915d8e8beba8165bb8157e50adf053be6e2222f6 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Fri, 23 Jan 2026 22:56:51 +0800 Subject: [PATCH 24/71] Add lodash and @types/lodash to packages that were missing them --- .github/actions/package.json | 1 + lib/modules-lib/package.json | 2 + package.json | 1 + src/bundles/rune/package.json | 4 +- src/tabs/Rune/package.json | 1 + yarn.lock | 341 +++++++++++++++++++++++++++++++++- 6 files changed, 347 insertions(+), 3 deletions(-) diff --git a/.github/actions/package.json b/.github/actions/package.json index 91d98d4316..a52cf7cd16 100644 --- a/.github/actions/package.json +++ b/.github/actions/package.json @@ -5,6 +5,7 @@ "type": "module", "devDependencies": { "@sourceacademy/modules-repotools": "workspace:^", + "@types/lodash": "^4.14.198", "@types/node": "^22.15.30", "typescript": "^5.8.2", "vitest": "^4.0.4" diff --git a/lib/modules-lib/package.json b/lib/modules-lib/package.json index 05eaf10936..d40923c0d0 100644 --- a/lib/modules-lib/package.json +++ b/lib/modules-lib/package.json @@ -5,6 +5,7 @@ "type": "module", "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", + "@types/lodash": "^4.14.198", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^5.1.0", @@ -34,6 +35,7 @@ "@blueprintjs/core": "^6.0.0", "@blueprintjs/icons": "^6.0.0", "js-slang": "^1.0.85", + "lodash": "^4.17.21", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/package.json b/package.json index 678982e965..ebdc3bab82 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "@yarnpkg/types": "^4.0.1", "esbuild": "^0.27.0", "eslint": "^9.35.0", + "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^62.0.0", "eslint-plugin-mdx": "^3.6.2", diff --git a/src/bundles/rune/package.json b/src/bundles/rune/package.json index d30ffd5cfd..8d892a4904 100644 --- a/src/bundles/rune/package.json +++ b/src/bundles/rune/package.json @@ -4,10 +4,12 @@ "private": true, "dependencies": { "@sourceacademy/modules-lib": "workspace:^", - "gl-matrix": "^3.3.0" + "gl-matrix": "^3.3.0", + "lodash": "^4.17.21" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", + "@types/lodash": "^4.14.198", "js-slang": "^1.0.85", "typescript": "^5.8.2" }, diff --git a/src/tabs/Rune/package.json b/src/tabs/Rune/package.json index 2879aa9ee1..a3e23d6cf2 100644 --- a/src/tabs/Rune/package.json +++ b/src/tabs/Rune/package.json @@ -5,6 +5,7 @@ "dependencies": { "@sourceacademy/bundle-rune": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", + "lodash": "^4.17.21", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/yarn.lock b/yarn.lock index 19c97722f5..2f1f59812c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1993,6 +1993,34 @@ __metadata: languageName: node linkType: hard +"@emnapi/core@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/core@npm:1.8.1" + dependencies: + "@emnapi/wasi-threads": "npm:1.1.0" + tslib: "npm:^2.4.0" + checksum: 10c0/2c242f4b49779bac403e1cbcc98edacdb1c8ad36562408ba9a20663824669e930bc8493be46a2522d9dc946b8d96cd7073970bae914928c7671b5221c85b432e + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/runtime@npm:1.8.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/f4929d75e37aafb24da77d2f58816761fe3f826aad2e37fa6d4421dac9060cbd5098eea1ac3c9ecc4526b89deb58153852fa432f87021dc57863f2ff726d713f + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.1.0": + version: 1.1.0 + resolution: "@emnapi/wasi-threads@npm:1.1.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/e6d54bf2b1e64cdd83d2916411e44e579b6ae35d5def0dea61a3c452d9921373044dff32a8b8473ae60c80692bdc39323e98b96a3f3d87ba6886b24dd0ef7ca1 + languageName: node + linkType: hard + "@epilot/esbuild-jest@npm:^0.5.2": version: 0.5.2 resolution: "@epilot/esbuild-jest@npm:0.5.2" @@ -3037,6 +3065,17 @@ __metadata: languageName: node linkType: hard +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.12 + resolution: "@napi-rs/wasm-runtime@npm:0.2.12" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.10.0" + checksum: 10c0/6d07922c0613aab30c6a497f4df297ca7c54e5b480e00035e0209b872d5c6aab7162fc49477267556109c2c7ed1eb9c65a174e27e9b87568106a87b0a6e3ca7d + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -4472,8 +4511,10 @@ __metadata: dependencies: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" + "@types/lodash": "npm:^4.14.198" gl-matrix: "npm:^3.3.0" js-slang: "npm:^1.0.85" + lodash: "npm:^4.17.21" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4709,6 +4750,7 @@ __metadata: "@actions/core": "npm:^1.11.1" "@actions/exec": "npm:^1.1.1" "@sourceacademy/modules-repotools": "workspace:^" + "@types/lodash": "npm:^4.14.198" "@types/node": "npm:^22.15.30" lodash: "npm:^4.17.21" snyk-nodejs-lockfile-parser: "npm:^2.4.2" @@ -4724,12 +4766,14 @@ __metadata: "@blueprintjs/core": "npm:^6.0.0" "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" + "@types/lodash": "npm:^4.14.198" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" "@vitejs/plugin-react": "npm:^5.1.0" "@vitest/browser-playwright": "npm:^4.0.4" eslint: "npm:^9.35.0" js-slang: "npm:^1.0.85" + lodash: "npm:^4.17.21" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" @@ -4785,6 +4829,7 @@ __metadata: "@yarnpkg/types": "npm:^4.0.1" esbuild: "npm:^0.27.0" eslint: "npm:^9.35.0" + eslint-import-resolver-typescript: "npm:^4.4.4" eslint-plugin-import: "npm:^2.32.0" eslint-plugin-jsdoc: "npm:^62.0.0" eslint-plugin-mdx: "npm:^3.6.2" @@ -5048,6 +5093,7 @@ __metadata: "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" "@vitest/browser-playwright": "npm:^4.0.4" + lodash: "npm:^4.17.21" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" @@ -5200,6 +5246,15 @@ __metadata: languageName: node linkType: hard +"@tybys/wasm-util@npm:^0.10.0": + version: 0.10.1 + resolution: "@tybys/wasm-util@npm:0.10.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/b255094f293794c6d2289300c5fbcafbb5532a3aed3a5ffd2f8dc1828e639b88d75f6a376dd8f94347a44813fd7a7149d8463477a9a49525c8b2dcaa38c2d1e8 + languageName: node + linkType: hard + "@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.7, @types/babel__core@npm:^7.20.5": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" @@ -6317,6 +6372,141 @@ __metadata: languageName: node linkType: hard +"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.2.11" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@use-gesture/core@npm:10.3.1": version: 10.3.1 resolution: "@use-gesture/core@npm:10.3.1" @@ -10061,6 +10251,21 @@ __metadata: languageName: node linkType: hard +"eslint-import-context@npm:^0.1.8": + version: 0.1.9 + resolution: "eslint-import-context@npm:0.1.9" + dependencies: + get-tsconfig: "npm:^4.10.1" + stable-hash-x: "npm:^0.2.0" + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + checksum: 10c0/07851103443b70af681c5988e2702e681ff9b956e055e11d4bd9b2322847fa0d9e8da50c18fc7cb1165106b043f34fbd0384d7011c239465c4645c52132e56f3 + languageName: node + linkType: hard + "eslint-import-resolver-node@npm:^0.3.9": version: 0.3.9 resolution: "eslint-import-resolver-node@npm:0.3.9" @@ -10072,6 +10277,30 @@ __metadata: languageName: node linkType: hard +"eslint-import-resolver-typescript@npm:^4.4.4": + version: 4.4.4 + resolution: "eslint-import-resolver-typescript@npm:4.4.4" + dependencies: + debug: "npm:^4.4.1" + eslint-import-context: "npm:^0.1.8" + get-tsconfig: "npm:^4.10.1" + is-bun-module: "npm:^2.0.0" + stable-hash-x: "npm:^0.2.0" + tinyglobby: "npm:^0.2.14" + unrs-resolver: "npm:^1.7.11" + peerDependencies: + eslint: "*" + eslint-plugin-import: "*" + eslint-plugin-import-x: "*" + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + checksum: 10c0/3bf8ad77c21660f77a0e455555ab179420f68ae7a132906c85a217ccce51cb6680cf70027cab32a358d193e5b9e476f6ba2e595585242aa97d4f6435ca22104e + languageName: node + linkType: hard + "eslint-mdx@npm:^3.6.2": version: 3.6.2 resolution: "eslint-mdx@npm:3.6.2" @@ -11037,6 +11266,15 @@ __metadata: languageName: node linkType: hard +"get-tsconfig@npm:^4.10.1": + version: 4.13.0 + resolution: "get-tsconfig@npm:4.13.0" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10c0/2c49ef8d3907047a107f229fd610386fe3b7fe9e42dfd6b42e7406499493cdda8c62e83e57e8d7a98125610774b9f604d3a0ff308d7f9de5c7ac6d1b07cb6036 + languageName: node + linkType: hard + "get-value@npm:^2.0.3, get-value@npm:^2.0.6": version: 2.0.6 resolution: "get-value@npm:2.0.6" @@ -11865,6 +12103,15 @@ __metadata: languageName: node linkType: hard +"is-bun-module@npm:^2.0.0": + version: 2.0.0 + resolution: "is-bun-module@npm:2.0.0" + dependencies: + semver: "npm:^7.7.1" + checksum: 10c0/7d27a0679cfa5be1f5052650391f9b11040cd70c48d45112e312c56bc6b6ca9c9aea70dcce6cc40b1e8947bfff8567a5c5715d3b066fb478522dab46ea379240 + languageName: node + linkType: hard + "is-callable@npm:^1.2.7": version: 1.2.7 resolution: "is-callable@npm:1.2.7" @@ -14372,6 +14619,15 @@ __metadata: languageName: node linkType: hard +"napi-postinstall@npm:^0.3.0": + version: 0.3.4 + resolution: "napi-postinstall@npm:0.3.4" + bin: + napi-postinstall: lib/cli.js + checksum: 10c0/b33d64150828bdade3a5d07368a8b30da22ee393f8dd8432f1b9e5486867be21c84ec443dd875dd3ef3c7401a079a7ab7e2aa9d3538a889abbcd96495d5104fe + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -15949,6 +16205,13 @@ __metadata: languageName: node linkType: hard +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab + languageName: node + linkType: hard + "resolve-url@npm:^0.2.1": version: 0.2.1 resolution: "resolve-url@npm:0.2.1" @@ -16404,7 +16667,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.2, semver@npm:^7.3.8, semver@npm:^7.7.3": +"semver@npm:^7.0.0, semver@npm:^7.1.2, semver@npm:^7.3.8, semver@npm:^7.7.1, semver@npm:^7.7.3": version: 7.7.3 resolution: "semver@npm:7.7.3" bin: @@ -16955,6 +17218,13 @@ __metadata: languageName: node linkType: hard +"stable-hash-x@npm:^0.2.0": + version: 0.2.0 + resolution: "stable-hash-x@npm:0.2.0" + checksum: 10c0/c757df58366ee4bb266a9486b8932eab7c1ba730469eaf4b68d2dee404814e9f84089c44c9b5205f8c7d99a0ab036cce2af69139ce5ed44b635923c011a8aea8 + languageName: node + linkType: hard + "stackback@npm:0.0.2": version: 0.0.2 resolution: "stackback@npm:0.0.2" @@ -17461,7 +17731,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.15": +"tinyglobby@npm:^0.2.14, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -18198,6 +18468,73 @@ __metadata: languageName: node linkType: hard +"unrs-resolver@npm:^1.7.11": + version: 1.11.1 + resolution: "unrs-resolver@npm:1.11.1" + dependencies: + "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" + "@unrs/resolver-binding-android-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" + "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" + napi-postinstall: "npm:^0.3.0" + dependenciesMeta: + "@unrs/resolver-binding-android-arm-eabi": + optional: true + "@unrs/resolver-binding-android-arm64": + optional: true + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: 10c0/c91b112c71a33d6b24e5c708dab43ab80911f2df8ee65b87cd7a18fb5af446708e98c4b415ca262026ad8df326debcc7ca6a801b2935504d87fd6f0b9d70dce1 + languageName: node + linkType: hard + "unset-value@npm:^1.0.0": version: 1.0.0 resolution: "unset-value@npm:1.0.0" From 22e21278d6502ccd0e31664e11ebf145c6a03ffc Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Fri, 23 Jan 2026 23:07:46 +0800 Subject: [PATCH 25/71] Disable import/no-unresolved when running in CI --- eslint.config.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 7cb0965110..e7e0179d5f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -316,12 +316,17 @@ export default defineConfig( rules: { 'no-unused-vars': 'off', // Use the typescript eslint rule instead - 'import/no-unresolved': ['error', { - ignore: [ - 'js-slang/context', - '^virtual:.+$' - ] - }], + 'import/no-unresolved': [ + // disable in the CI since we don't install packages so all node packages + // become unresolvable + process.env.CI ? 'off' : 'error', + { + ignore: [ + 'js-slang/context', + '^virtual:.+$' + ] + }] + , 'jsdoc/no-types': 'warn', From 4b2ef021d85c85b4148404eeb7a6968c9a5dcdf8 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 24 Jan 2026 07:25:27 +0800 Subject: [PATCH 26/71] Update vitest packages --- .github/actions/package.json | 2 +- devserver/package.json | 6 +- eslint.config.js | 9 +- lib/buildtools/package.json | 6 +- lib/modules-lib/package.json | 6 +- lib/repotools/package.json | 8 +- lib/vitest-reporter/package.json | 4 +- package.json | 6 +- src/bundles/pix_n_flix/package.json | 6 +- src/tabs/Curve/package.json | 8 +- src/tabs/Rune/package.json | 6 +- yarn.lock | 219 +++++++++++++++++++++++++++- 12 files changed, 247 insertions(+), 39 deletions(-) diff --git a/.github/actions/package.json b/.github/actions/package.json index a52cf7cd16..0d32d50da9 100644 --- a/.github/actions/package.json +++ b/.github/actions/package.json @@ -8,7 +8,7 @@ "@types/lodash": "^4.14.198", "@types/node": "^22.15.30", "typescript": "^5.8.2", - "vitest": "^4.0.4" + "vitest": "^4.0.18" }, "dependencies": { "@actions/artifact": "^2.3.2", diff --git a/devserver/package.json b/devserver/package.json index 5888505107..36e80d80ea 100644 --- a/devserver/package.json +++ b/devserver/package.json @@ -29,13 +29,13 @@ "@sourceacademy/modules-buildtools": "workspace:^", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", - "@vitest/browser-playwright": "^4.0.4", + "@vitest/browser-playwright": "^4.0.18", "eslint": "^9.35.0", "playwright": "^1.55.1", "sass": "^1.85.0", "typescript": "^5.8.2", - "vitest": "^4.0.4", - "vitest-browser-react": "^2.0.2" + "vitest": "^4.0.18", + "vitest-browser-react": "^2.0.4" }, "scripts": { "dev": "vite", diff --git a/eslint.config.js b/eslint.config.js index e7e0179d5f..bd5a53239b 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -320,13 +320,8 @@ export default defineConfig( // disable in the CI since we don't install packages so all node packages // become unresolvable process.env.CI ? 'off' : 'error', - { - ignore: [ - 'js-slang/context', - '^virtual:.+$' - ] - }] - , + { ignore: [ 'js-slang/context', '^virtual:.+$' ] } + ], 'jsdoc/no-types': 'warn', diff --git a/lib/buildtools/package.json b/lib/buildtools/package.json index d569ddc10b..a711f4e0e0 100644 --- a/lib/buildtools/package.json +++ b/lib/buildtools/package.json @@ -19,8 +19,8 @@ "dependencies": { "@sourceacademy/modules-repotools": "workspace:^", "@vitejs/plugin-react": "^5.1.0", - "@vitest/browser-playwright": "^4.0.4", - "@vitest/coverage-v8": "^4.0.4", + "@vitest/browser-playwright": "^4.0.18", + "@vitest/coverage-v8": "^4.0.18", "acorn": "^8.8.1", "acorn-typescript": "^1.4.13", "astring": "^1.8.6", @@ -33,7 +33,7 @@ "lodash": "^4.17.21", "typedoc": "^0.28.9", "vite": "^7.1.11", - "vitest": "^4.0.4" + "vitest": "^4.0.18" }, "scripts": { "build": "node ./build.js --dev", diff --git a/lib/modules-lib/package.json b/lib/modules-lib/package.json index d40923c0d0..c9db9e7a02 100644 --- a/lib/modules-lib/package.json +++ b/lib/modules-lib/package.json @@ -9,7 +9,7 @@ "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^5.1.0", - "@vitest/browser-playwright": "^4.0.4", + "@vitest/browser-playwright": "^4.0.18", "eslint": "^9.35.0", "playwright": "^1.55.1", "typedoc": "^0.28.9", @@ -17,8 +17,8 @@ "typedoc-plugin-markdown": "^4.7.0", "typedoc-plugin-rename-defaults": "^0.7.3", "typescript": "^5.8.2", - "vitest": "^4.0.4", - "vitest-browser-react": "^2.0.2" + "vitest": "^4.0.18", + "vitest-browser-react": "^2.0.4" }, "exports": { "./tabs/index": null, diff --git a/lib/repotools/package.json b/lib/repotools/package.json index f70db02c45..5ac98b3252 100644 --- a/lib/repotools/package.json +++ b/lib/repotools/package.json @@ -9,13 +9,13 @@ "@types/lodash": "^4.14.198", "@types/node": "^22.15.30", "@vitejs/plugin-react": "^5.1.0", - "@vitest/coverage-v8": "^4.0.4", + "@vitest/coverage-v8": "^4.0.18", "typescript": "^5.8.2", - "vitest": "^4.0.4", - "vitest-browser-react": "^2.0.2" + "vitest": "^4.0.18", + "vitest-browser-react": "^2.0.4" }, "dependencies": { - "@vitest/browser-playwright": "^4.0.4", + "@vitest/browser-playwright": "^4.0.18", "chalk": "^5.0.1", "commander": "^14.0.0", "esbuild": "^0.27.0", diff --git a/lib/vitest-reporter/package.json b/lib/vitest-reporter/package.json index a188d4b935..c1116e3ece 100644 --- a/lib/vitest-reporter/package.json +++ b/lib/vitest-reporter/package.json @@ -5,12 +5,12 @@ "type": "module", "dependencies": { "istanbul-lib-report": "^3.0.1", - "vitest": "^4.0.4" + "vitest": "^4.0.18" }, "devDependencies": { "@types/istanbul-lib-report": "^3.0.3", "@types/node": "^22.15.30", - "@vitest/coverage-v8": "^4.0.4", + "@vitest/coverage-v8": "^4.0.18", "esbuild": "^0.27.0", "typescript": "^5.8.2" }, diff --git a/package.json b/package.json index ebdc3bab82..659f76071a 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "@types/node": "^22.15.30", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", - "@vitest/coverage-v8": "^4.0.4", + "@vitest/coverage-v8": "^4.0.18", "@vitest/eslint-plugin": "^1.6.6", "@yarnpkg/types": "^4.0.1", "esbuild": "^0.27.0", @@ -76,8 +76,8 @@ "jsonc-eslint-parser": "^2.4.0", "typescript": "^5.8.2", "typescript-eslint": "^8.53.1", - "vitest": "^4.0.4", - "vitest-browser-react": "^2.0.2" + "vitest": "^4.0.18", + "vitest-browser-react": "^2.0.4" }, "peerDependencies": { "@blueprintjs/core": "^6.0.0", diff --git a/src/bundles/pix_n_flix/package.json b/src/bundles/pix_n_flix/package.json index 7ddff98142..b1ff8a1868 100644 --- a/src/bundles/pix_n_flix/package.json +++ b/src/bundles/pix_n_flix/package.json @@ -5,13 +5,13 @@ "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", "@types/react": "^18.3.1", - "@vitest/browser-playwright": "^4.0.4", + "@vitest/browser-playwright": "^4.0.18", "playwright": "^1.55.1", "react": "^18.3.1", "react-dom": "^18.3.1", "typescript": "^5.8.2", - "vitest": "^4.0.4", - "vitest-browser-react": "^2.0.2" + "vitest": "^4.0.18", + "vitest-browser-react": "^2.0.4" }, "type": "module", "exports": { diff --git a/src/tabs/Curve/package.json b/src/tabs/Curve/package.json index 3e18665113..02a4e7ae23 100644 --- a/src/tabs/Curve/package.json +++ b/src/tabs/Curve/package.json @@ -14,11 +14,11 @@ "@sourceacademy/modules-buildtools": "workspace:^", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", - "@vitest/browser-playwright": "^4.0.4", - "@vitest/coverage-v8": "^4.0.4", + "@vitest/browser-playwright": "^4.0.18", + "@vitest/coverage-v8": "^4.0.18", "playwright": "^1.55.1", - "vitest": "^4.0.4", - "vitest-browser-react": "^2.0.2" + "vitest": "^4.0.18", + "vitest-browser-react": "^2.0.4" }, "scripts": { "build": "buildtools build tab .", diff --git a/src/tabs/Rune/package.json b/src/tabs/Rune/package.json index a3e23d6cf2..efd0dd5a34 100644 --- a/src/tabs/Rune/package.json +++ b/src/tabs/Rune/package.json @@ -12,10 +12,10 @@ "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", "@types/react": "^18.3.1", - "@vitest/browser-playwright": "^4.0.4", + "@vitest/browser-playwright": "^4.0.18", "playwright": "^1.55.1", - "vitest": "^4.0.4", - "vitest-browser-react": "^2.0.2" + "vitest": "^4.0.18", + "vitest-browser-react": "^2.0.4" }, "scripts": { "build": "buildtools build tab .", diff --git a/yarn.lock b/yarn.lock index 2f1f59812c..bfb969511d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4824,7 +4824,7 @@ __metadata: "@types/node": "npm:^22.15.30" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" - "@vitest/coverage-v8": "npm:^4.0.4" + "@vitest/coverage-v8": "npm:^4.0.18" "@vitest/eslint-plugin": "npm:^1.6.6" "@yarnpkg/types": "npm:^4.0.1" esbuild: "npm:^0.27.0" @@ -4841,8 +4841,8 @@ __metadata: jsonc-eslint-parser: "npm:^2.4.0" typescript: "npm:^5.8.2" typescript-eslint: "npm:^8.53.1" - vitest: "npm:^4.0.4" - vitest-browser-react: "npm:^2.0.2" + vitest: "npm:^4.0.18" + vitest-browser-react: "npm:^2.0.4" peerDependencies: "@blueprintjs/core": ^6.0.0 "@blueprintjs/icons": ^6.0.0 @@ -6586,6 +6586,30 @@ __metadata: languageName: node linkType: hard +"@vitest/coverage-v8@npm:^4.0.18": + version: 4.0.18 + resolution: "@vitest/coverage-v8@npm:4.0.18" + dependencies: + "@bcoe/v8-coverage": "npm:^1.0.2" + "@vitest/utils": "npm:4.0.18" + ast-v8-to-istanbul: "npm:^0.3.10" + istanbul-lib-coverage: "npm:^3.2.2" + istanbul-lib-report: "npm:^3.0.1" + istanbul-reports: "npm:^3.2.0" + magicast: "npm:^0.5.1" + obug: "npm:^2.1.1" + std-env: "npm:^3.10.0" + tinyrainbow: "npm:^3.0.3" + peerDependencies: + "@vitest/browser": 4.0.18 + vitest: 4.0.18 + peerDependenciesMeta: + "@vitest/browser": + optional: true + checksum: 10c0/e23e0da86f0b2a020c51562bc40ebdc7fc7553c24f8071dfb39a6df0161badbd5eaf2eebbf8ceaef18933a18c1934ff52d1c0c4bde77bb87e0c1feb0c8cbee4d + languageName: node + linkType: hard + "@vitest/coverage-v8@npm:^4.0.4": version: 4.0.9 resolution: "@vitest/coverage-v8@npm:4.0.9" @@ -6630,6 +6654,20 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/expect@npm:4.0.18" + dependencies: + "@standard-schema/spec": "npm:^1.0.0" + "@types/chai": "npm:^5.2.2" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" + chai: "npm:^6.2.1" + tinyrainbow: "npm:^3.0.3" + checksum: 10c0/123b0aa111682e82ec5289186df18037b1a1768700e468ee0f9879709aaa320cf790463c15c0d8ee10df92b402f4394baf5d27797e604d78e674766d87bcaadc + languageName: node + linkType: hard + "@vitest/expect@npm:4.0.9": version: 4.0.9 resolution: "@vitest/expect@npm:4.0.9" @@ -6644,6 +6682,25 @@ __metadata: languageName: node linkType: hard +"@vitest/mocker@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/mocker@npm:4.0.18" + dependencies: + "@vitest/spy": "npm:4.0.18" + estree-walker: "npm:^3.0.3" + magic-string: "npm:^0.30.21" + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 10c0/fb0a257e7e167759d4ad228d53fa7bad2267586459c4a62188f2043dd7163b4b02e1e496dc3c227837f776e7d73d6c4343613e89e7da379d9d30de8260f1ee4b + languageName: node + linkType: hard + "@vitest/mocker@npm:4.0.9": version: 4.0.9 resolution: "@vitest/mocker@npm:4.0.9" @@ -6663,6 +6720,15 @@ __metadata: languageName: node linkType: hard +"@vitest/pretty-format@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/pretty-format@npm:4.0.18" + dependencies: + tinyrainbow: "npm:^3.0.3" + checksum: 10c0/0086b8c88eeca896d8e4b98fcdef452c8041a1b63eb9e85d3e0bcc96c8aa76d8e9e0b6990ebb0bb0a697c4ebab347e7735888b24f507dbff2742ddce7723fd94 + languageName: node + linkType: hard + "@vitest/pretty-format@npm:4.0.9": version: 4.0.9 resolution: "@vitest/pretty-format@npm:4.0.9" @@ -6672,6 +6738,16 @@ __metadata: languageName: node linkType: hard +"@vitest/runner@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/runner@npm:4.0.18" + dependencies: + "@vitest/utils": "npm:4.0.18" + pathe: "npm:^2.0.3" + checksum: 10c0/fdb4afa411475133c05ba266c8092eaf1e56cbd5fb601f92ec6ccb9bab7ca52e06733ee8626599355cba4ee71cb3a8f28c84d3b69dc972e41047edc50229bc01 + languageName: node + linkType: hard + "@vitest/runner@npm:4.0.9": version: 4.0.9 resolution: "@vitest/runner@npm:4.0.9" @@ -6682,6 +6758,17 @@ __metadata: languageName: node linkType: hard +"@vitest/snapshot@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/snapshot@npm:4.0.18" + dependencies: + "@vitest/pretty-format": "npm:4.0.18" + magic-string: "npm:^0.30.21" + pathe: "npm:^2.0.3" + checksum: 10c0/d3bfefa558db9a69a66886ace6575eb96903a5ba59f4d9a5d0fecb4acc2bb8dbb443ef409f5ac1475f2e1add30bd1d71280f98912da35e89c75829df9e84ea43 + languageName: node + linkType: hard + "@vitest/snapshot@npm:4.0.9": version: 4.0.9 resolution: "@vitest/snapshot@npm:4.0.9" @@ -6693,6 +6780,13 @@ __metadata: languageName: node linkType: hard +"@vitest/spy@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/spy@npm:4.0.18" + checksum: 10c0/6de537890b3994fcadb8e8d8ac05942320ae184f071ec395d978a5fba7fa928cbb0c5de85af86a1c165706c466e840de8779eaff8c93450c511c7abaeb9b8a4e + languageName: node + linkType: hard + "@vitest/spy@npm:4.0.9": version: 4.0.9 resolution: "@vitest/spy@npm:4.0.9" @@ -6700,6 +6794,16 @@ __metadata: languageName: node linkType: hard +"@vitest/utils@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/utils@npm:4.0.18" + dependencies: + "@vitest/pretty-format": "npm:4.0.18" + tinyrainbow: "npm:^3.0.3" + checksum: 10c0/4a3c43c1421eb90f38576926496f6c80056167ba111e63f77cf118983902673737a1a38880b890d7c06ec0a12475024587344ee502b3c43093781533022f2aeb + languageName: node + linkType: hard + "@vitest/utils@npm:4.0.9": version: 4.0.9 resolution: "@vitest/utils@npm:4.0.9" @@ -7462,6 +7566,17 @@ __metadata: languageName: node linkType: hard +"ast-v8-to-istanbul@npm:^0.3.10": + version: 0.3.10 + resolution: "ast-v8-to-istanbul@npm:0.3.10" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.31" + estree-walker: "npm:^3.0.3" + js-tokens: "npm:^9.0.1" + checksum: 10c0/8a7a07c04f8f130b8a5abb76cdb31cce06a8eb4b7d4abbe207bc721132127ae332e857b96aa415ac43ec2c6c9312508210c598f61a7de2d0e3db5615e6b03183 + languageName: node + linkType: hard + "ast-v8-to-istanbul@npm:^0.3.8": version: 0.3.8 resolution: "ast-v8-to-istanbul@npm:0.3.8" @@ -8119,6 +8234,13 @@ __metadata: languageName: node linkType: hard +"chai@npm:^6.2.1": + version: 6.2.2 + resolution: "chai@npm:6.2.2" + checksum: 10c0/e6c69e5f0c11dffe6ea13d0290936ebb68fcc1ad688b8e952e131df6a6d5797d5e860bc55cef1aca2e950c3e1f96daf79e9d5a70fb7dbaab4e46355e2635ed53 + languageName: node + linkType: hard + "chainsaw@npm:~0.1.0": version: 0.1.0 resolution: "chainsaw@npm:0.1.0" @@ -15037,6 +15159,13 @@ __metadata: languageName: node linkType: hard +"obug@npm:^2.1.1": + version: 2.1.1 + resolution: "obug@npm:2.1.1" + checksum: 10c0/59dccd7de72a047e08f8649e94c1015ec72f94eefb6ddb57fb4812c4b425a813bc7e7cd30c9aca20db3c59abc3c85cc7a62bb656a968741d770f4e8e02bc2e78 + languageName: node + linkType: hard + "once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -17721,6 +17850,13 @@ __metadata: languageName: node linkType: hard +"tinyexec@npm:^1.0.2": + version: 1.0.2 + resolution: "tinyexec@npm:1.0.2" + checksum: 10c0/1261a8e34c9b539a9aae3b7f0bb5372045ff28ee1eba035a2a059e532198fe1a182ec61ac60fa0b4a4129f0c4c4b1d2d57355b5cb9aa2d17ac9454ecace502ee + languageName: node + linkType: hard + "tinyglobby@npm:^0.2.12": version: 0.2.13 resolution: "tinyglobby@npm:0.2.13" @@ -18974,6 +19110,83 @@ __metadata: languageName: node linkType: hard +"vitest-browser-react@npm:^2.0.4": + version: 2.0.4 + resolution: "vitest-browser-react@npm:2.0.4" + peerDependencies: + "@types/react": ^18.0.0 || ^19.0.0 + "@types/react-dom": ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + vitest: ^4.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/d5c4c65dbdc42bb9a78ac3545f5294bcabb217b6d70f00464f1f1583e8c7f4e5d71d454e3a84f1dba1ce341b8885e84fcd716eca290a052c342c950b5aaa7c1b + languageName: node + linkType: hard + +"vitest@npm:^4.0.18": + version: 4.0.18 + resolution: "vitest@npm:4.0.18" + dependencies: + "@vitest/expect": "npm:4.0.18" + "@vitest/mocker": "npm:4.0.18" + "@vitest/pretty-format": "npm:4.0.18" + "@vitest/runner": "npm:4.0.18" + "@vitest/snapshot": "npm:4.0.18" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" + es-module-lexer: "npm:^1.7.0" + expect-type: "npm:^1.2.2" + magic-string: "npm:^0.30.21" + obug: "npm:^2.1.1" + pathe: "npm:^2.0.3" + picomatch: "npm:^4.0.3" + std-env: "npm:^3.10.0" + tinybench: "npm:^2.9.0" + tinyexec: "npm:^1.0.2" + tinyglobby: "npm:^0.2.15" + tinyrainbow: "npm:^3.0.3" + vite: "npm:^6.0.0 || ^7.0.0" + why-is-node-running: "npm:^2.3.0" + peerDependencies: + "@edge-runtime/vm": "*" + "@opentelemetry/api": ^1.9.0 + "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 4.0.18 + "@vitest/browser-preview": 4.0.18 + "@vitest/browser-webdriverio": 4.0.18 + "@vitest/ui": 4.0.18 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@opentelemetry/api": + optional: true + "@types/node": + optional: true + "@vitest/browser-playwright": + optional: true + "@vitest/browser-preview": + optional: true + "@vitest/browser-webdriverio": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 10c0/b913cd32032c95f29ff08c931f4b4c6fd6d2da498908d6770952c561a1b8d75c62499a1f04cadf82fb89cc0f9a33f29fb5dfdb899f6dbb27686a9d91571be5fa + languageName: node + linkType: hard + "vitest@npm:^4.0.4": version: 4.0.9 resolution: "vitest@npm:4.0.9" From 6f5c1f4471fadd661cd90e0808ae204752671dc2 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 24 Jan 2026 07:51:20 +0800 Subject: [PATCH 27/71] Fix incorrect classname in test --- devserver/src/components/__tests__/Playground.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devserver/src/components/__tests__/Playground.test.tsx b/devserver/src/components/__tests__/Playground.test.tsx index 3ce156486f..530bae58b5 100644 --- a/devserver/src/components/__tests__/Playground.test.tsx +++ b/devserver/src/components/__tests__/Playground.test.tsx @@ -48,7 +48,8 @@ describe('Playground tests', () => { const settingsButton = component.getByRole('button').filter({ hasText: /^$/ }); await userEvent.click(settingsButton); - const compiledTabsToggle = component.baseElement.getElementsByClassName('bp5-switch').item(0); + const compiledTabsToggle = component.baseElement.getElementsByClassName('bp6-switch').item(0); + expect(compiledTabsToggle).not.toBeNull(); await userEvent.click(compiledTabsToggle!); await userEvent.click(settingsButton); From 88298ee9b0ab3652a92c579d6308cfaed48dee99 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 24 Jan 2026 21:30:31 +0800 Subject: [PATCH 28/71] Fix omit call --- lib/buildtools/src/templates/tab.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/buildtools/src/templates/tab.ts b/lib/buildtools/src/templates/tab.ts index e2f6ab8e04..f689752e1f 100644 --- a/lib/buildtools/src/templates/tab.ts +++ b/lib/buildtools/src/templates/tab.ts @@ -79,7 +79,7 @@ export async function addNew(bundlesDir: string, tabsDir: string, rl: Interface) }; // Version property gets stored in package.json, not manifest.json - const requiredProperties = omit(manifest[moduleName], ['version']); + const requiredProperties = omit(manifest[moduleName], 'version'); const newManifest: BundleManifest = { ...requiredProperties, From b56d39208b6a97ea87b4cc33527806b064e3ffcf Mon Sep 17 00:00:00 2001 From: Lee Yi Date: Thu, 5 Feb 2026 10:26:33 +0800 Subject: [PATCH 29/71] Update lodash packages --- lib/modules-lib/package.json | 2 +- src/bundles/rune/package.json | 2 +- src/tabs/Rune/package.json | 2 +- yarn.lock | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/modules-lib/package.json b/lib/modules-lib/package.json index c9db9e7a02..0227e90625 100644 --- a/lib/modules-lib/package.json +++ b/lib/modules-lib/package.json @@ -35,7 +35,7 @@ "@blueprintjs/core": "^6.0.0", "@blueprintjs/icons": "^6.0.0", "js-slang": "^1.0.85", - "lodash": "^4.17.21", + "lodash": "^4.17.23", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/src/bundles/rune/package.json b/src/bundles/rune/package.json index 8d892a4904..212ea20643 100644 --- a/src/bundles/rune/package.json +++ b/src/bundles/rune/package.json @@ -5,7 +5,7 @@ "dependencies": { "@sourceacademy/modules-lib": "workspace:^", "gl-matrix": "^3.3.0", - "lodash": "^4.17.21" + "lodash": "^4.17.23" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/tabs/Rune/package.json b/src/tabs/Rune/package.json index efd0dd5a34..cc8b731107 100644 --- a/src/tabs/Rune/package.json +++ b/src/tabs/Rune/package.json @@ -5,7 +5,7 @@ "dependencies": { "@sourceacademy/bundle-rune": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", - "lodash": "^4.17.21", + "lodash": "^4.17.23", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/yarn.lock b/yarn.lock index 2555c77af1..6660f5f9d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4514,7 +4514,7 @@ __metadata: "@types/lodash": "npm:^4.14.198" gl-matrix: "npm:^3.3.0" js-slang: "npm:^1.0.85" - lodash: "npm:^4.17.21" + lodash: "npm:^4.17.23" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4773,7 +4773,7 @@ __metadata: "@vitest/browser-playwright": "npm:^4.0.18" eslint: "npm:^9.35.0" js-slang: "npm:^1.0.85" - lodash: "npm:^4.17.21" + lodash: "npm:^4.17.23" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" @@ -5093,7 +5093,7 @@ __metadata: "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" "@vitest/browser-playwright": "npm:^4.0.18" - lodash: "npm:^4.17.21" + lodash: "npm:^4.17.23" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" From 4d8d168201270fd98aa8956dcc78b0b309d632f0 Mon Sep 17 00:00:00 2001 From: Lee Yi Date: Thu, 5 Feb 2026 22:33:22 +0800 Subject: [PATCH 30/71] Add callback parameter checking for curve bundle --- .../{hextocolor.test.ts => utilities.test.ts} | 15 +- lib/modules-lib/src/utilities.ts | 15 + src/bundles/curve/src/__tests__/curve.test.ts | 76 ++- src/bundles/curve/src/drawers.ts | 258 +++++++---- src/bundles/curve/src/functions.ts | 434 ++++++++++-------- src/bundles/curve/src/type_interface.ts | 120 +---- 6 files changed, 512 insertions(+), 406 deletions(-) rename lib/modules-lib/src/__tests__/{hextocolor.test.ts => utilities.test.ts} (56%) diff --git a/lib/modules-lib/src/__tests__/hextocolor.test.ts b/lib/modules-lib/src/__tests__/utilities.test.ts similarity index 56% rename from lib/modules-lib/src/__tests__/hextocolor.test.ts rename to lib/modules-lib/src/__tests__/utilities.test.ts index 51b4c93faf..55c15071bf 100644 --- a/lib/modules-lib/src/__tests__/hextocolor.test.ts +++ b/lib/modules-lib/src/__tests__/utilities.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, test } from 'vitest'; -import { hexToColor } from '../utilities'; +import { hexToColor, isFunctionOfLength } from '../utilities'; describe(hexToColor, () => { test.each([ @@ -19,3 +19,16 @@ describe(hexToColor, () => { expect(() => hexToColor('GGGGGG')).toThrowErrorMatchingInlineSnapshot('[Error: Invalid color hex string: GGGGGG]'); }); }); + +describe(isFunctionOfLength, () => { + it('correctly identifies functions with the specified number of parameters', () => { + const func0 = () => { }; + expect(isFunctionOfLength(func0, 0)).toBe(true); + + const func1 = (_a: number) => { }; + expect(isFunctionOfLength(func1, 1)).toBe(true); + + const func2 = (_a: number, _b: string) => { }; + expect(isFunctionOfLength(func2, 2)).toBe(true); + }); +}); diff --git a/lib/modules-lib/src/utilities.ts b/lib/modules-lib/src/utilities.ts index 63fd9c1225..3eddf6fbcb 100644 --- a/lib/modules-lib/src/utilities.ts +++ b/lib/modules-lib/src/utilities.ts @@ -59,3 +59,18 @@ export function mockDebuggerContext(moduleState: T, name: string) { } } as unknown as DebuggerContext; } + +type ArrayOfLengthHelper = + V['length'] extends T ? V : ArrayOfLengthHelper; + +/** + * Utility type that represents a tuple of a specific length + */ +export type ArrayOfLength = ArrayOfLengthHelper; + +/** + * Type guard for checking that a function has the specified number of parameters. + */ +export function isFunctionOfLength(f: unknown, l: T): f is (...args: ArrayOfLength) => unknown { + return typeof f === 'function' && f.length === l; +} diff --git a/src/bundles/curve/src/__tests__/curve.test.ts b/src/bundles/curve/src/__tests__/curve.test.ts index d747704d76..9024dcdacc 100644 --- a/src/bundles/curve/src/__tests__/curve.test.ts +++ b/src/bundles/curve/src/__tests__/curve.test.ts @@ -3,6 +3,7 @@ import { describe, expect, it, test } from 'vitest'; import type { Color, Curve } from '../curves_webgl'; import * as drawers from '../drawers'; import * as funcs from '../functions'; +import type { RenderFunction } from '../types'; /** * Evaluates the curve at 200 points, then @@ -19,25 +20,70 @@ function evaluatePoints(curve: Curve) { return points; } -test('Ensure that invalid curves error gracefully', () => { - expect(() => drawers.draw_connected(200)(() => 1 as any)) - .toThrow('Expected curve to return a point, got \'1\' at t=0'); -}); +describe('Ensure that invalid curves and animations error gracefully', () => { + test('Curve that returns non-point should throw error', () => { + expect(() => drawers.draw_connected(200)(_x => 1 as any)) + .toThrow('Expected curve to return a point, got \'1\' at t=0'); + }); -test('Using 3D render functions with animate_curve should throw errors', () => { - expect(() => drawers.animate_curve(1, 60, drawers.draw_3D_connected(200), (t0) => (t1) => funcs.make_point(t0, t1))) - .toThrow('animate_curve cannot be used with 3D draw function!'); -}); + test('Curve that takes multiple parameters should throw error', () => { + expect(() => drawers.draw_connected(200)(((t, u) => funcs.make_point(t, u)) as any)) + .toThrow( + 'The provided curve is not a valid Curve function. ' + + 'A Curve function must take exactly one parameter (a number t between 0 and 1) ' + + 'and return a Point or 3D Point depending on whether it is a 2D or 3D curve.' + ); + }); -test('Using 2D render functions with animate_3D_curve should throw errors', () => { - expect(() => drawers.animate_3D_curve(1, 60, drawers.draw_connected(200), (t0) => (t1) => funcs.make_point(t0, t1))) - .toThrow('animate_3D_curve cannot be used with 2D draw function!'); + test('Using 3D render functions with animate_curve should throw errors', () => { + expect(() => drawers.animate_curve(1, 60, drawers.draw_3D_connected(200), (t0) => (t1) => funcs.make_point(t0, t1))) + .toThrow('animate_curve cannot be used with 3D draw function!'); + }); + + test('Using 2D render functions with animate_3D_curve should throw errors', () => { + expect(() => drawers.animate_3D_curve(1, 60, drawers.draw_connected(200), (t0) => (t1) => funcs.make_point(t0, t1))) + .toThrow('animate_3D_curve cannot be used with 2D draw function!'); + }); }); -test('Render functions have nice string representations', () => { - expect(stringify(drawers.draw_connected(200))).toEqual(''); - expect(stringify(drawers.draw_connected_full_view_proportional(400))).toEqual(''); - expect(stringify(drawers.draw_3D_connected(400))).toEqual('<3DRenderFunction(400)>'); +describe('Render function creators', () => { + const names = Object.getOwnPropertyNames(drawers.RenderFunctionCreators); + const renderFuncCreators = names.reduce<[string, (pts: number) => RenderFunction][]>((res, name) => { + if (typeof drawers.RenderFunctionCreators[name] !== 'function') return res; + return [...res, [name, drawers.RenderFunctionCreators[name]]]; + }, []); + describe.each(renderFuncCreators)('%s', (name, func) => { + test('name property is correct', () => { + expect(func.name).toEqual(name); + }); + + it('throws when numPoints is less than 0', () => { + expect(() => func(0)).toThrowError( + `${name}: The number of points must be a positive integer less than or equal to 65535. Got: 0` + ); + }); + + it('throws when numPoints is greater than 65535', () => { + expect(() => func(70000)).toThrowError( + `${name}: The number of points must be a positive integer less than or equal to 65535. Got: 70000` + ); + }); + + it('throws when numPoints is not an integer', () => { + expect(() => func(3.14)).toThrowError( + `${name}: The number of points must be a positive integer less than or equal to 65535. Got: 3.14` + ); + }); + + test('returned render functions have nice string represnentations', () => { + const renderFunc = func(250); + if (renderFunc.is3D) { + expect(stringify(renderFunc)).toEqual('<3DRenderFunction(250)>'); + } else { + expect(stringify(renderFunc)).toEqual(''); + } + }); + }); }); describe('Coloured Points', () => { diff --git a/src/bundles/curve/src/drawers.ts b/src/bundles/curve/src/drawers.ts index 16fe745d6a..79ea31a6dc 100644 --- a/src/bundles/curve/src/drawers.ts +++ b/src/bundles/curve/src/drawers.ts @@ -1,5 +1,8 @@ +import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; import context from 'js-slang/context'; + import { generateCurve, type Curve, type CurveDrawn } from './curves_webgl'; +import { functionDeclaration } from './type_interface'; import { AnimatedCurve, type CurveAnimation, @@ -18,10 +21,26 @@ function createDrawFunction( scaleMode: ScaleMode, drawMode: DrawMode, space: CurveSpace, - isFullView: boolean + isFullView: boolean, + name: string ): (numPoints: number) => RenderFunction { - return (numPoints: number) => { - const func = (curve: Curve) => { + function renderFuncCreator(numPoints: number) { + if (numPoints <= 0 || numPoints > 65535 || !Number.isInteger(numPoints)) { + throw new Error( + `${name}: The number of points must be a positive integer less than or equal to 65535. ` + + `Got: ${numPoints}` + ); + } + + function renderFunc(curve: Curve) { + if (!isFunctionOfLength(curve, 1)) { + throw new Error( + 'The provided curve is not a valid Curve function. ' + + 'A Curve function must take exactly one parameter (a number t between 0 and 1) ' + + 'and return a Point or 3D Point depending on whether it is a 2D or 3D curve.' + ); + } + const curveDrawn = generateCurve( scaleMode, drawMode, @@ -36,18 +55,22 @@ function createDrawFunction( } return curveDrawn; - }; + } + // Because the draw functions are actually functions // we need hacky workarounds like these to pass information around - func.is3D = space === '3D'; + renderFunc.is3D = space === '3D'; const stringifier = () => `<${space === '3D' ? '3D' : ''}RenderFunction(${numPoints})>`; // Retain both properties for compatibility - func.toString = stringifier; - func.toReplString = stringifier; + renderFunc.toString = stringifier; + renderFunc.toReplString = stringifier; + + return renderFunc; + } - return func; - }; + Object.defineProperty(renderFuncCreator, 'name', { value: name }); + return renderFuncCreator; } // ============================================================================= @@ -58,6 +81,90 @@ function createDrawFunction( // graphics library context, see './curves_webgl.ts'. // ============================================================================= +/** @hidden */ +export class RenderFunctionCreators { + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_connected = createDrawFunction('none', 'lines', '2D', false, 'draw_connected'); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_connected_full_view = createDrawFunction( + 'stretch', + 'lines', + '2D', + true, + 'draw_connected_full_view' + ); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_connected_full_view_proportional = createDrawFunction( + 'fit', + 'lines', + '2D', + true, + 'draw_connected_full_view_proportional' + ); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_points = createDrawFunction('none', 'points', '2D', false, 'draw_points'); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_points_full_view = createDrawFunction( + 'stretch', + 'points', + '2D', + true, + 'draw_points_full_view' + ); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_points_full_view_proportional = createDrawFunction( + 'fit', + 'points', + '2D', + true, + 'draw_points_full_view_proportional' + ); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_3D_connected = createDrawFunction( + 'none', + 'lines', + '3D', + false, + 'draw_3D_connected' + ); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_3D_connected_full_view = createDrawFunction( + 'stretch', + 'lines', + '3D', + false, + 'draw_3D_connected_full_view' + ); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_3D_points = createDrawFunction('none', 'points', '3D', false, 'draw_3D_points'); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_3D_points_full_view = createDrawFunction( + 'stretch', + 'points', + '3D', + false, + 'draw_3D_points_full_view' + ); + + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_3D_points_full_view_proportional = createDrawFunction( + 'fit', + 'points', + '3D', + false, + 'draw_3D_points_full_view_proportional' + ); +} + /** * Returns a function that turns a given Curve into a Drawing, by sampling the * Curve at `num` sample points and connecting each pair with a line. @@ -72,7 +179,7 @@ function createDrawFunction( * draw_connected(100)(t => make_point(t, t)); * ``` */ -export const draw_connected = createDrawFunction('none', 'lines', '2D', false); +export const draw_connected = RenderFunctionCreators.draw_connected; /** * Returns a function that turns a given Curve into a Drawing, by sampling the @@ -89,12 +196,7 @@ export const draw_connected = createDrawFunction('none', 'lines', '2D', false); * draw_connected_full_view(100)(t => make_point(t, t)); * ``` */ -export const draw_connected_full_view = createDrawFunction( - 'stretch', - 'lines', - '2D', - true -); +export const draw_connected_full_view = RenderFunctionCreators.draw_connected_full_view; /** * Returns a function that turns a given Curve into a Drawing, by sampling the @@ -111,12 +213,7 @@ export const draw_connected_full_view = createDrawFunction( * draw_connected_full_view_proportional(100)(t => make_point(t, t)); * ``` */ -export const draw_connected_full_view_proportional = createDrawFunction( - 'fit', - 'lines', - '2D', - true -); +export const draw_connected_full_view_proportional = RenderFunctionCreators.draw_connected_full_view_proportional; /** * Returns a function that turns a given Curve into a Drawing, by sampling the @@ -133,7 +230,7 @@ export const draw_connected_full_view_proportional = createDrawFunction( * draw_points(100)(t => make_point(t, t)); * ``` */ -export const draw_points = createDrawFunction('none', 'points', '2D', false); +export const draw_points = RenderFunctionCreators.draw_points; /** * Returns a function that turns a given Curve into a Drawing, by sampling the @@ -151,12 +248,7 @@ export const draw_points = createDrawFunction('none', 'points', '2D', false); * draw_points_full_view(100)(t => make_point(t, t)); * ``` */ -export const draw_points_full_view = createDrawFunction( - 'stretch', - 'points', - '2D', - true -); +export const draw_points_full_view = RenderFunctionCreators.draw_points_full_view; /** * Returns a function that turns a given Curve into a Drawing, by sampling the @@ -174,12 +266,7 @@ export const draw_points_full_view = createDrawFunction( * draw_points_full_view_proportional(100)(t => make_point(t, t)); * ``` */ -export const draw_points_full_view_proportional = createDrawFunction( - 'fit', - 'points', - '2D', - true -); +export const draw_points_full_view_proportional = RenderFunctionCreators.draw_points_full_view_proportional; /** * Returns a function that turns a given 3D Curve into a Drawing, by sampling @@ -196,12 +283,7 @@ export const draw_points_full_view_proportional = createDrawFunction( * draw_3D_connected(100)(t => make_3D_point(t, t, t)); * ``` */ -export const draw_3D_connected = createDrawFunction( - 'none', - 'lines', - '3D', - false -); +export const draw_3D_connected = RenderFunctionCreators.draw_3D_connected; /** * Returns a function that turns a given 3D Curve into a Drawing, by sampling @@ -218,12 +300,7 @@ export const draw_3D_connected = createDrawFunction( * draw_3D_connected_full_view(100)(t => make_3D_point(t, t, t)); * ``` */ -export const draw_3D_connected_full_view = createDrawFunction( - 'stretch', - 'lines', - '3D', - false -); +export const draw_3D_connected_full_view = RenderFunctionCreators.draw_3D_connected_full_view; /** * Returns a function that turns a given 3D Curve into a Drawing, by sampling @@ -240,12 +317,7 @@ export const draw_3D_connected_full_view = createDrawFunction( * draw_3D_connected_full_view_proportional(100)(t => make_3D_point(t, t, t)); * ``` */ -export const draw_3D_connected_full_view_proportional = createDrawFunction( - 'fit', - 'lines', - '3D', - false -); +export const draw_3D_connected_full_view_proportional = RenderFunctionCreators.draw_3D_points_full_view_proportional; /** * Returns a function that turns a given 3D Curve into a Drawing, by sampling @@ -262,7 +334,7 @@ export const draw_3D_connected_full_view_proportional = createDrawFunction( * draw_3D_points(100)(t => make_3D_point(t, t, t)); * ``` */ -export const draw_3D_points = createDrawFunction('none', 'points', '3D', false); +export const draw_3D_points = RenderFunctionCreators.draw_3D_points; /** * Returns a function that turns a given 3D Curve into a Drawing, by sampling @@ -279,12 +351,7 @@ export const draw_3D_points = createDrawFunction('none', 'points', '3D', false); * draw_3D_points_full_view(100)(t => make_3D_point(t, t, t)); * ``` */ -export const draw_3D_points_full_view = createDrawFunction( - 'stretch', - 'points', - '3D', - false -); +export const draw_3D_points_full_view = RenderFunctionCreators.draw_3D_points_full_view; /** * Returns a function that turns a given 3D Curve into a Drawing, by sampling @@ -301,12 +368,41 @@ export const draw_3D_points_full_view = createDrawFunction( * draw_3D_points_full_view_proportional(100)(t => make_3D_point(t, t, t)); * ``` */ -export const draw_3D_points_full_view_proportional = createDrawFunction( - 'fit', - 'points', - '3D', - false -); +export const draw_3D_points_full_view_proportional = RenderFunctionCreators.draw_3D_points_full_view_proportional; + +class CurveAnimators { + @functionDeclaration('duration: number, fps: number, drawer: (func: Curve) => Curve, func: (func: Curve) => Curve', 'AnimatedCurve') + static animate_curve( + duration: number, + fps: number, + drawer: RenderFunction, + func: CurveAnimation + ): AnimatedCurve { + if (drawer.is3D) { + throw new Error(`${animate_curve.name} cannot be used with 3D draw function!`); + } + + const anim = new AnimatedCurve(duration, fps, func, drawer, false); + drawnCurves.push(anim); + return anim; + } + + @functionDeclaration('duration: number, fps: number, drawer: (func: Curve) => Curve, func: (func: Curve) => Curve', 'AnimatedCurve') + static animate_3D_curve( + duration: number, + fps: number, + drawer: RenderFunction, + func: CurveAnimation + ): AnimatedCurve { + if (!drawer.is3D) { + throw new Error(`${animate_3D_curve.name} cannot be used with 2D draw function!`); + } + + const anim = new AnimatedCurve(duration, fps, func, drawer, true); + drawnCurves.push(anim); + return anim; + } +} /** * Create a animation of curves using a curve generating function. @@ -316,20 +412,7 @@ export const draw_3D_points_full_view_proportional = createDrawFunction( * @param func Curve generating function. Takes in a timestamp value and returns a curve * @returns Curve Animation */ -export function animate_curve( - duration: number, - fps: number, - drawer: RenderFunction, - func: CurveAnimation -): AnimatedCurve { - if (drawer.is3D) { - throw new Error('animate_curve cannot be used with 3D draw function!'); - } - - const anim = new AnimatedCurve(duration, fps, func, drawer, false); - drawnCurves.push(anim); - return anim; -} +export const animate_curve = CurveAnimators.animate_curve; /** * Create a animation of curves using a curve generating function. @@ -339,17 +422,4 @@ export function animate_curve( * @param func Curve generating function. Takes in a timestamp value and returns a curve * @returns 3D Curve Animation */ -export function animate_3D_curve( - duration: number, - fps: number, - drawer: RenderFunction, - func: CurveAnimation -): AnimatedCurve { - if (!drawer.is3D) { - throw new Error('animate_3D_curve cannot be used with 2D draw function!'); - } - - const anim = new AnimatedCurve(duration, fps, func, drawer, true); - drawnCurves.push(anim); - return anim; -} +export const animate_3D_curve = CurveAnimators.animate_3D_curve; diff --git a/src/bundles/curve/src/functions.ts b/src/bundles/curve/src/functions.ts index 4faf29a8a4..c2fce8b1b4 100644 --- a/src/bundles/curve/src/functions.ts +++ b/src/bundles/curve/src/functions.ts @@ -1,7 +1,237 @@ import clamp from 'lodash/clamp'; import { Point, type Curve } from './curves_webgl'; +import { functionDeclaration } from './type_interface'; import type { CurveTransformer } from './types'; +function throwIfNotPoint(obj: unknown, func_name: string): asserts obj is Point { + if (!(obj instanceof Point)) { + throw new Error(`${func_name} expects a point as argument`); + } +} + +class CurveFunctions { + @functionDeclaration('x: number, y: number', 'Point') + static make_point(x: number, y: number): Point { + return new Point(x, y, 0, [0, 0, 0, 1]); + } + + @functionDeclaration('x: number, y: number, z: number', 'Point') + static make_3D_point(x: number, y: number, z: number): Point { + return new Point(x, y, z, [0, 0, 0, 1]); + } + + @functionDeclaration('x: number, y: number, r: number, g: number, b: number', 'Point') + static make_color_point( + x: number, + y: number, + r: number, + g: number, + b: number + ): Point { + r = clamp(r, 0, 255); + g = clamp(g, 0, 255); + b = clamp(b, 0, 255); + + return new Point(x, y, 0, [r / 255, g / 255, b / 255, 1]); + } + + @functionDeclaration('x: number, y: number, z: number, r: number, g: number, b: number', 'Point') + static make_3D_color_point( + x: number, + y: number, + z: number, + r: number, + g: number, + b: number + ): Point { + r = clamp(r, 0, 255); + g = clamp(g, 0, 255); + b = clamp(b, 0, 255); + + return new Point(x, y, z, [r / 255, g / 255, b / 255, 1]); + } + + @functionDeclaration('curve1: Curve, curve2: Curve', 'Curve') + static connect_ends(curve1: Curve, curve2: Curve): Curve { + const startPointOfCurve2 = curve2(0); + const endPointOfCurve1 = curve1(1); + return connect_rigidly( + curve1, + translate( + x_of(endPointOfCurve1) - x_of(startPointOfCurve2), + y_of(endPointOfCurve1) - y_of(startPointOfCurve2), + z_of(endPointOfCurve1) - z_of(startPointOfCurve2) + )(curve2) + ); + } + + @functionDeclaration('curve1: Curve, curve2: Curve', 'Curve') + static connect_rigidly(curve1: Curve, curve2: Curve): Curve { + return (t) => (t < 1 / 2 ? curve1(2 * t) : curve2(2 * t - 1)); + } + + @functionDeclaration('x0: number, y0: number, z0: number', '(c: Curve) => Curve') + static translate(x0: number, y0: number, z0: number): CurveTransformer { + return curve => t => { + const ct = curve(t); + return new Point( + x0 + ct.x, + y0 + ct.y, + z0 + ct.z, + [ct.color[0], ct.color[1], ct.color[2], 1] + ); + }; + } + + @functionDeclaration('curve: Curve', 'Curve') + static invert: CurveTransformer = original => t => original(1 - t); + + @functionDeclaration('curve: Curve', 'Curve') + static put_in_standard_position: CurveTransformer = curve => { + const start_point = curve(0); + const curve_started_at_origin = translate( + -x_of(start_point), + -y_of(start_point), + 0 + )(curve); + const new_end_point = curve_started_at_origin(1); + const theta = Math.atan2(y_of(new_end_point), x_of(new_end_point)); + const curve_ended_at_x_axis = rotate_around_origin_3D( + 0, + 0, + -theta + )(curve_started_at_origin); + const end_point_on_x_axis = x_of(curve_ended_at_x_axis(1)); + return scale_proportional(1 / end_point_on_x_axis)(curve_ended_at_x_axis); + }; + + @functionDeclaration('a: number, b: number, c: number', '(c: Curve) => Curve') + static rotate_around_origin_3D(a: number, b: number, c: number): CurveTransformer { + const cthx = Math.cos(a); + const sthx = Math.sin(a); + const cthy = Math.cos(b); + const sthy = Math.sin(b); + const cthz = Math.cos(c); + const sthz = Math.sin(c); + + return curve => t => { + const ct = curve(t); + const coord = [ct.x, ct.y, ct.z]; + const mat = [ + [ + cthz * cthy, + cthz * sthy * sthx - sthz * cthx, + cthz * sthy * cthx + sthz * sthx + ], + [ + sthz * cthy, + sthz * sthy * sthx + cthz * cthx, + sthz * sthy * cthx - cthz * sthx + ], + [-sthy, cthy * sthx, cthy * cthx] + ]; + let xf = 0; + let yf = 0; + let zf = 0; + for (let i = 0; i < 3; i += 1) { + xf += mat[0][i] * coord[i]; + yf += mat[1][i] * coord[i]; + zf += mat[2][i] * coord[i]; + } + return new Point(xf, yf, zf, [ct.color[0], ct.color[1], ct.color[2], 1]); + }; + } + + @functionDeclaration('a: number', '(c: Curve) => Curve') + static rotate_around_origin(a: number): CurveTransformer { + // 1 args + const cth = Math.cos(a); + const sth = Math.sin(a); + return curve => t => { + const ct = curve(t); + return new Point( + cth * ct.x - sth * ct.y, + sth * ct.x + cth * ct.y, + ct.z, + [ct.color[0], ct.color[1], ct.color[2], 1] + ); + }; + } + + @functionDeclaration('x: number, y: number, z: number', '(c: Curve) => Curve') + static scale(x: number, y: number, z: number): CurveTransformer { + return curve => t => { + const ct = curve(t); + + return new Point( + x * ct.x, + y * ct.y, + z * ct.z, + [ct.color[0], ct.color[1], ct.color[2], 1] + ); + }; + } + + @functionDeclaration('s: number', '(c: Curve) => Curve') + static scale_proportional(s: number): CurveTransformer { + return scale(s, s, s); + } + + @functionDeclaration('p: Point', 'number') + static x_of(pt: Point): number { + throwIfNotPoint(pt, x_of.name); + return pt.x; + } + + @functionDeclaration('p: Point', 'number') + static y_of(pt: Point): number { + throwIfNotPoint(pt, y_of.name); + return pt.y; + } + + @functionDeclaration('p: Point', 'number') + static z_of(pt: Point): number { + throwIfNotPoint(pt, z_of.name); + return pt.z; + } + + @functionDeclaration('p: Point', 'number') + static r_of(pt: Point): number { + throwIfNotPoint(pt, r_of.name); + return Math.floor(pt.color[0] * 255); + } + + @functionDeclaration('p: Point', 'number') + static g_of(pt: Point): number { + throwIfNotPoint(pt, g_of.name); + return Math.floor(pt.color[1] * 255); + } + + @functionDeclaration('p: Point', 'number') + static b_of(pt: Point): number { + throwIfNotPoint(pt, b_of.name); + return Math.floor(pt.color[2] * 255); + } + + @functionDeclaration('t: number', 'Point') + static unit_circle: Curve = t => { + return make_point(Math.cos(2 * Math.PI * t), Math.sin(2 * Math.PI * t)); + }; + + @functionDeclaration('t: number', 'Point') + static unit_line: Curve = t => make_point(t, 0); + + @functionDeclaration('t: number', 'Curve') + static unit_line_at(y: number): Curve { + return t => make_point(t, y); + } + + @functionDeclaration('t: number', 'Point') + static arc: Curve = t => { + return make_point(Math.sin(Math.PI * t), Math.cos(Math.PI * t)); + }; +} + /** * Makes a Point with given x and y coordinates. * @@ -13,9 +243,7 @@ import type { CurveTransformer } from './types'; * const point = make_point(0.5, 0.5); * ``` */ -export function make_point(x: number, y: number): Point { - return new Point(x, y, 0, [0, 0, 0, 1]); -} +export const make_point = CurveFunctions.make_point; /** * Makes a 3D Point with given x, y and z coordinates. @@ -29,9 +257,7 @@ export function make_point(x: number, y: number): Point { * const point = make_3D_point(0.5, 0.5, 0.5); * ``` */ -export function make_3D_point(x: number, y: number, z: number): Point { - return new Point(x, y, z, [0, 0, 0, 1]); -} +export const make_3D_point = CurveFunctions.make_3D_point; /** * Makes a color Point with given x and y coordinates, and RGB values ranging @@ -49,19 +275,7 @@ export function make_3D_point(x: number, y: number, z: number): Point { * const redPoint = make_color_point(0.5, 0.5, 255, 0, 0); * ``` */ -export function make_color_point( - x: number, - y: number, - r: number, - g: number, - b: number -): Point { - r = clamp(r, 0, 255); - g = clamp(g, 0, 255); - b = clamp(b, 0, 255); - - return new Point(x, y, 0, [r / 255, g / 255, b / 255, 1]); -} +export const make_color_point = CurveFunctions.make_color_point; /** * Makes a 3D color Point with given x, y and z coordinates, and RGB values @@ -80,26 +294,7 @@ export function make_color_point( * const redPoint = make_color_point(0.5, 0.5, 0.5, 255, 0, 0); * ``` */ -export function make_3D_color_point( - x: number, - y: number, - z: number, - r: number, - g: number, - b: number -): Point { - r = clamp(r, 0, 255); - g = clamp(g, 0, 255); - b = clamp(b, 0, 255); - - return new Point(x, y, z, [r / 255, g / 255, b / 255, 1]); -} - -function throwIfNotPoint(obj: unknown, func_name: string): asserts obj is Point { - if (!(obj instanceof Point)) { - throw new Error(`${func_name} expects a point as argument`); - } -} +export const make_3D_color_point = CurveFunctions.make_3D_color_point; /** * Retrieves the x-coordinate of a given Point. @@ -112,10 +307,7 @@ function throwIfNotPoint(obj: unknown, func_name: string): asserts obj is Point * x_of(point); // Returns 1 * ``` */ -export function x_of(pt: Point): number { - throwIfNotPoint(pt, x_of.name); - return pt.x; -} +export const x_of = CurveFunctions.x_of; /** * Retrieves the y-coordinate of a given Point. @@ -128,10 +320,7 @@ export function x_of(pt: Point): number { * y_of(point); // Returns 2 * ``` */ -export function y_of(pt: Point): number { - throwIfNotPoint(pt, y_of.name); - return pt.y; -} +export const y_of = CurveFunctions.y_of; /** * Retrieves the z-coordinate of a given Point. @@ -144,10 +333,7 @@ export function y_of(pt: Point): number { * z_of(point); // Returns 3 * ``` */ -export function z_of(pt: Point): number { - throwIfNotPoint(pt, z_of.name); - return pt.z; -} +export const z_of = CurveFunctions.z_of; /** * Retrieves the red component of a given Point. @@ -160,10 +346,7 @@ export function z_of(pt: Point): number { * r_of(point); // Returns 50 * ``` */ -export function r_of(pt: Point): number { - throwIfNotPoint(pt, r_of.name); - return Math.floor(pt.color[0] * 255); -} +export const r_of = CurveFunctions.r_of; /** * Retrieves the green component of a given Point. @@ -176,10 +359,7 @@ export function r_of(pt: Point): number { * g_of(point); // Returns 100 * ``` */ -export function g_of(pt: Point): number { - throwIfNotPoint(pt, g_of.name); - return Math.floor(pt.color[1] * 255); -} +export const g_of = CurveFunctions.g_of; /** * Retrieves the blue component of a given Point. @@ -192,10 +372,7 @@ export function g_of(pt: Point): number { * b_of(point); // Returns 150 * ``` */ -export function b_of(pt: Point): number { - throwIfNotPoint(pt, b_of.name); - return Math.floor(pt.color[2] * 255); -} +export const b_of = CurveFunctions.b_of; /** * This function is a Curve transformation: a function from a Curve to a Curve. @@ -206,7 +383,7 @@ export function b_of(pt: Point): number { * @param original original Curve * @returns result Curve */ -export const invert: CurveTransformer = original => t => original(1 - t); +export const invert = CurveFunctions.invert; /** * This function returns a Curve transformation: It takes an x-value x0, a @@ -220,17 +397,7 @@ export const invert: CurveTransformer = original => t => original(1 - t); * @param z0 z-value * @returns Curve transformation */ -export function translate(x0: number, y0: number, z0: number): CurveTransformer { - return curve => t => { - const ct = curve(t); - return new Point( - x0 + ct.x, - y0 + ct.y, - z0 + ct.z, - [ct.color[0], ct.color[1], ct.color[2], 1] - ); - }; -} +export const translate = CurveFunctions.translate; /** * This function takes 3 angles, a, b and c in radians as parameter @@ -243,41 +410,7 @@ export function translate(x0: number, y0: number, z0: number): CurveTransformer * @param c given angle * @returns function that takes a Curve and returns a Curve */ -export function rotate_around_origin_3D(a: number, b: number, c: number): CurveTransformer { - const cthx = Math.cos(a); - const sthx = Math.sin(a); - const cthy = Math.cos(b); - const sthy = Math.sin(b); - const cthz = Math.cos(c); - const sthz = Math.sin(c); - - return curve => t => { - const ct = curve(t); - const coord = [ct.x, ct.y, ct.z]; - const mat = [ - [ - cthz * cthy, - cthz * sthy * sthx - sthz * cthx, - cthz * sthy * cthx + sthz * sthx - ], - [ - sthz * cthy, - sthz * sthy * sthx + cthz * cthx, - sthz * sthy * cthx - cthz * sthx - ], - [-sthy, cthy * sthx, cthy * cthx] - ]; - let xf = 0; - let yf = 0; - let zf = 0; - for (let i = 0; i < 3; i += 1) { - xf += mat[0][i] * coord[i]; - yf += mat[1][i] * coord[i]; - zf += mat[2][i] * coord[i]; - } - return new Point(xf, yf, zf, [ct.color[0], ct.color[1], ct.color[2], 1]); - }; -} +export const rotate_around_origin_3D = CurveFunctions.rotate_around_origin_3D; /** * This function an angle a in radians as parameter @@ -288,20 +421,7 @@ export function rotate_around_origin_3D(a: number, b: number, c: number): CurveT * @param a given angle * @returns function that takes a Curve and returns a Curve */ -export function rotate_around_origin(a: number): CurveTransformer { - // 1 args - const cth = Math.cos(a); - const sth = Math.sin(a); - return curve => t => { - const ct = curve(t); - return new Point( - cth * ct.x - sth * ct.y, - sth * ct.x + cth * ct.y, - ct.z, - [ct.color[0], ct.color[1], ct.color[2], 1] - ); - }; -} +export const rotate_around_origin = CurveFunctions.rotate_around_origin; /** * This function takes scaling factors `a`, `b` and @@ -314,18 +434,7 @@ export function rotate_around_origin(a: number): CurveTransformer { * @param z scaling factor in z-direction * @returns function that takes a Curve and returns a Curve */ -export function scale(x: number, y: number, z: number): CurveTransformer { - return curve => t => { - const ct = curve(t); - - return new Point( - x * ct.x, - y * ct.y, - z * ct.z, - [ct.color[0], ct.color[1], ct.color[2], 1] - ); - }; -} +export const scale = CurveFunctions.scale; /** * This function takes a scaling factor s argument and returns a Curve @@ -334,9 +443,7 @@ export function scale(x: number, y: number, z: number): CurveTransformer { * @param s scaling factor * @returns function that takes a Curve and returns a Curve */ -export function scale_proportional(s: number): CurveTransformer { - return scale(s, s, s); -} +export const scale_proportional = CurveFunctions.scale_proportional; /** * This function is a Curve transformation: It takes a Curve as argument and @@ -350,23 +457,7 @@ export function scale_proportional(s: number): CurveTransformer { * @param curve given Curve * @returns result Curve */ -export const put_in_standard_position: CurveTransformer = curve => { - const start_point = curve(0); - const curve_started_at_origin = translate( - -x_of(start_point), - -y_of(start_point), - 0 - )(curve); - const new_end_point = curve_started_at_origin(1); - const theta = Math.atan2(y_of(new_end_point), x_of(new_end_point)); - const curve_ended_at_x_axis = rotate_around_origin_3D( - 0, - 0, - -theta - )(curve_started_at_origin); - const end_point_on_x_axis = x_of(curve_ended_at_x_axis(1)); - return scale_proportional(1 / end_point_on_x_axis)(curve_ended_at_x_axis); -}; +export const put_in_standard_position = CurveFunctions.put_in_standard_position; /** * This function is a binary Curve operator: It takes two Curves as arguments @@ -379,9 +470,7 @@ export const put_in_standard_position: CurveTransformer = curve => { * @param curve2 second Curve * @returns result Curve */ -export function connect_rigidly(curve1: Curve, curve2: Curve): Curve { - return (t) => (t < 1 / 2 ? curve1(2 * t) : curve2(2 * t - 1)); -} +export const connect_rigidly = CurveFunctions.connect_rigidly; /** * This function is a binary Curve operator: It takes two Curves as arguments @@ -395,18 +484,7 @@ export function connect_rigidly(curve1: Curve, curve2: Curve): Curve { * @param curve2 second Curve * @returns result Curve */ -export function connect_ends(curve1: Curve, curve2: Curve): Curve { - const startPointOfCurve2 = curve2(0); - const endPointOfCurve1 = curve1(1); - return connect_rigidly( - curve1, - translate( - x_of(endPointOfCurve1) - x_of(startPointOfCurve2), - y_of(endPointOfCurve1) - y_of(startPointOfCurve2), - z_of(endPointOfCurve1) - z_of(startPointOfCurve2) - )(curve2) - ); -} +export const connect_ends = CurveFunctions.connect_ends; /** * This function is a curve: a function from a fraction t to a point. The points @@ -416,9 +494,7 @@ export function connect_ends(curve1: Curve, curve2: Curve): Curve { * @param t fraction between 0 and 1 * @returns Point on the circle at t */ -export const unit_circle: Curve = t => { - return make_point(Math.cos(2 * Math.PI * t), Math.sin(2 * Math.PI * t)); -}; +export const unit_circle = CurveFunctions.unit_circle; /** * This function is a curve: a function from a fraction t to a point. The @@ -427,7 +503,7 @@ export const unit_circle: Curve = t => { * @param t fraction between 0 and 1 * @returns Point on the line at t */ -export const unit_line: Curve = t => make_point(t, 0); +export const unit_line = CurveFunctions.unit_line; /** * This function is a Curve generator: it takes a number and returns a @@ -437,9 +513,7 @@ export const unit_line: Curve = t => make_point(t, 0); * @param y fraction between 0 and 1 * @returns horizontal Curve */ -export function unit_line_at(y: number): Curve { - return t => make_point(t, y); -} +export const unit_line_at = CurveFunctions.unit_line_at; /** * This function is a curve: a function from a fraction t to a point. The points @@ -450,6 +524,4 @@ export function unit_line_at(y: number): Curve { * @param t fraction between 0 and 1 * @returns Point in the arc at t */ -export const arc: Curve = t => { - return make_point(Math.sin(Math.PI * t), Math.cos(Math.PI * t)); -}; +export const arc = CurveFunctions.arc; diff --git a/src/bundles/curve/src/type_interface.ts b/src/bundles/curve/src/type_interface.ts index 27c38cc27f..8c22088d9a 100644 --- a/src/bundles/curve/src/type_interface.ts +++ b/src/bundles/curve/src/type_interface.ts @@ -2,129 +2,19 @@ import createTypeMap from '@sourceacademy/modules-lib/type_map'; const typeMapCreator = createTypeMap(); -const { classDeclaration, functionDeclaration, typeDeclaration } = typeMapCreator; +export const { classDeclaration, functionDeclaration, typeDeclaration } = typeMapCreator; @classDeclaration('Point') -class Point {} +class Point { } @classDeclaration('AnimatedCurve') -class AnimatedCurve {} +class AnimatedCurve { } @typeDeclaration('(u: number) => Point') -class Curve {} +class Curve { } @typeDeclaration('(t: number) => Curve') -class CurveAnimation {} - -class TypeInterface { - @functionDeclaration('duration: number, fps: number, drawer: (func: Curve) => Curve, func: (func: Curve) => Curve', 'AnimatedCurve') - animate_3D_curve() {} - - @functionDeclaration('duration: number, fps: number, drawer: (func: Curve) => Curve, func: (func: Curve) => Curve', 'AnimatedCurve') - animate_curve() {} - - @functionDeclaration('t: number', 'number') - arc() {} - - @functionDeclaration('p: Point', 'number') - b_of() {} - - @functionDeclaration('curve1: Curve, curve2: Curve', 'Curve') - connect_ends() {} - - @functionDeclaration('curve1: Curve, curve2: Curve', 'Curve') - connect_rigidly() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_3D_connected() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_3D_connected_full_view() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_3D_connected_full_view_proportional() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_3D_points() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_3D_points_full_view() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_3D_points_full_view_proportional() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_connected() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_connected_full_view() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_connected_full_view_proportional() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_points() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_points_full_view() {} - - @functionDeclaration('numPoints: number', '(func: Curve) => Curve') - draw_points_full_view_proportional() {} - - @functionDeclaration('p: Point', 'number') - g_of() {} - - @functionDeclaration('curve: Curve', 'Curve') - invert() {} - - @functionDeclaration('x: number, y: number, z: number, r: number, g: number, b: number', 'Point') - make_3D_color_point() {} - - @functionDeclaration('x: number, y: number, z: number', 'Point') - make_3D_point() {} - - @functionDeclaration('x: number, y: number, r: number, g: number, b: number', 'Point') - make_color_point() {} - - @functionDeclaration('x: number, y: number', 'Point') - make_point() {} - - @functionDeclaration('curve: Curve', 'Curve') - put_in_standard_position() {} - - @functionDeclaration('p: Point', 'number') - r_of() {} - - @functionDeclaration('theta1: number, theta2: number, theta3: number', '(c: Curve) => Curve') - rotate_around_origin() {} - - @functionDeclaration('x: number, y: number', '(c: Curve) => Curve') - scale() {} - - @functionDeclaration('s: number', '(c: Curve) => Curve') - scale_proportional() {} - - @functionDeclaration('x0: number, y0: number, z0: number', '(c: Curve) => Curve') - translate() {} - - @functionDeclaration('t: number', 'Point') - unit_circle() {} - - @functionDeclaration('t: number', 'Point') - unit_line() {} - - @functionDeclaration('t: number', 'Curve') - unit_line_at() {} - - @functionDeclaration('p: Point', 'number') - x_of() {} - - @functionDeclaration('p: Point', 'number') - y_of() {} - - @functionDeclaration('p: Point', 'number') - z_of() {} -} +class CurveAnimation { } /** @hidden */ export const type_map = typeMapCreator.type_map; From 55a111ed873baed8b463d159aba3b68f375e5c97 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 7 Feb 2026 04:05:30 +0800 Subject: [PATCH 31/71] Update incorrect curve function implementations --- src/bundles/curve/src/__tests__/curve.test.ts | 1 + src/bundles/curve/src/drawers.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bundles/curve/src/__tests__/curve.test.ts b/src/bundles/curve/src/__tests__/curve.test.ts index 9024dcdacc..00ae12a91b 100644 --- a/src/bundles/curve/src/__tests__/curve.test.ts +++ b/src/bundles/curve/src/__tests__/curve.test.ts @@ -52,6 +52,7 @@ describe('Render function creators', () => { if (typeof drawers.RenderFunctionCreators[name] !== 'function') return res; return [...res, [name, drawers.RenderFunctionCreators[name]]]; }, []); + describe.each(renderFuncCreators)('%s', (name, func) => { test('name property is correct', () => { expect(func.name).toEqual(name); diff --git a/src/bundles/curve/src/drawers.ts b/src/bundles/curve/src/drawers.ts index 79ea31a6dc..b62404fab1 100644 --- a/src/bundles/curve/src/drawers.ts +++ b/src/bundles/curve/src/drawers.ts @@ -151,7 +151,7 @@ export class RenderFunctionCreators { 'stretch', 'points', '3D', - false, + true, 'draw_3D_points_full_view' ); @@ -160,7 +160,7 @@ export class RenderFunctionCreators { 'fit', 'points', '3D', - false, + true, 'draw_3D_points_full_view_proportional' ); } From 70ffeb3c4930581b2c58cff824cc5104c57438d0 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 8 Feb 2026 05:44:23 +0800 Subject: [PATCH 32/71] Fix bp6 namespace --- devserver/src/styles/variables.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devserver/src/styles/variables.scss b/devserver/src/styles/variables.scss index 46386505da..ddd79c7e05 100644 --- a/devserver/src/styles/variables.scss +++ b/devserver/src/styles/variables.scss @@ -9,4 +9,4 @@ $images-path: "../assets"; $achievement-assets: "https://source-academy-assets.s3-ap-southeast-1.amazonaws.com/achievement"; // Blueprint -$ns: "bp5"; +$ns: "bp6"; From 23dab3c794a80156811615d8e0ebe649a2873a6d Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 8 Feb 2026 05:49:48 +0800 Subject: [PATCH 33/71] Fix lockfile post-merge --- yarn.lock | 2764 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 1682 insertions(+), 1082 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7997ed7043..3372d14c50 100644 --- a/yarn.lock +++ b/yarn.lock @@ -530,17 +530,6 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/code-frame@npm:7.29.0" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.28.5" - js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.1.1" - checksum: 10c0/d34cc504e7765dfb576a663d97067afb614525806b5cad1a5cc1a7183b916fec8ff57fa233585e3926fd5a9e6b31aae6df91aa81ae9775fb7a28f658d3346f0d - languageName: node - linkType: hard - "@babel/compat-data@npm:^7.27.2": version: 7.27.2 resolution: "@babel/compat-data@npm:7.27.2" @@ -548,13 +537,6 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.28.6": - version: 7.29.0 - resolution: "@babel/compat-data@npm:7.29.0" - checksum: 10c0/08f348554989d23aa801bf1405aa34b15e841c0d52d79da7e524285c77a5f9d298e70e11d91cc578d8e2c9542efc586d50c5f5cf8e1915b254a9dcf786913a94 - languageName: node - linkType: hard - "@babel/core@npm:^7.1.0, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.10": version: 7.27.1 resolution: "@babel/core@npm:7.27.1" @@ -578,26 +560,26 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/core@npm:7.29.0" +"@babel/core@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/core@npm:7.28.5" dependencies: - "@babel/code-frame": "npm:^7.29.0" - "@babel/generator": "npm:^7.29.0" - "@babel/helper-compilation-targets": "npm:^7.28.6" - "@babel/helper-module-transforms": "npm:^7.28.6" - "@babel/helpers": "npm:^7.28.6" - "@babel/parser": "npm:^7.29.0" - "@babel/template": "npm:^7.28.6" - "@babel/traverse": "npm:^7.29.0" - "@babel/types": "npm:^7.29.0" + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.28.5" + "@babel/helper-compilation-targets": "npm:^7.27.2" + "@babel/helper-module-transforms": "npm:^7.28.3" + "@babel/helpers": "npm:^7.28.4" + "@babel/parser": "npm:^7.28.5" + "@babel/template": "npm:^7.27.2" + "@babel/traverse": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" "@jridgewell/remapping": "npm:^2.3.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/5127d2e8e842ae409e11bcbb5c2dff9874abf5415e8026925af7308e903f4f43397341467a130490d1a39884f461bc2b67f3063bce0be44340db89687fd852aa + checksum: 10c0/535f82238027621da6bdffbdbe896ebad3558b311d6f8abc680637a9859b96edbf929ab010757055381570b29cf66c4a295b5618318d27a4273c0e2033925e72 languageName: node linkType: hard @@ -614,16 +596,29 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.29.0": - version: 7.29.1 - resolution: "@babel/generator@npm:7.29.1" +"@babel/generator@npm:^7.28.3": + version: 7.28.3 + resolution: "@babel/generator@npm:7.28.3" + dependencies: + "@babel/parser": "npm:^7.28.3" + "@babel/types": "npm:^7.28.2" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + jsesc: "npm:^3.0.2" + checksum: 10c0/0ff58bcf04f8803dcc29479b547b43b9b0b828ec1ee0668e92d79f9e90f388c28589056637c5ff2fd7bcf8d153c990d29c448d449d852bf9d1bc64753ca462bc + languageName: node + linkType: hard + +"@babel/generator@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/generator@npm:7.28.5" dependencies: - "@babel/parser": "npm:^7.29.0" - "@babel/types": "npm:^7.29.0" + "@babel/parser": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" "@jridgewell/gen-mapping": "npm:^0.3.12" "@jridgewell/trace-mapping": "npm:^0.3.28" jsesc: "npm:^3.0.2" - checksum: 10c0/349086e6876258ef3fb2823030fee0f6c0eb9c3ebe35fc572e16997f8c030d765f636ddc6299edae63e760ea6658f8ee9a2edfa6d6b24c9a80c917916b973551 + checksum: 10c0/9f219fe1d5431b6919f1a5c60db8d5d34fe546c0d8f5a8511b32f847569234ffc8032beb9e7404649a143f54e15224ecb53a3d11b6bb85c3203e573d91fca752 languageName: node linkType: hard @@ -636,7 +631,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.27.1": +"@babel/helper-compilation-targets@npm:^7.27.1, @babel/helper-compilation-targets@npm:^7.27.2": version: 7.27.2 resolution: "@babel/helper-compilation-targets@npm:7.27.2" dependencies: @@ -649,19 +644,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-compilation-targets@npm:7.28.6" - dependencies: - "@babel/compat-data": "npm:^7.28.6" - "@babel/helper-validator-option": "npm:^7.27.1" - browserslist: "npm:^4.24.0" - lru-cache: "npm:^5.1.1" - semver: "npm:^6.3.1" - checksum: 10c0/3fcdf3b1b857a1578e99d20508859dbd3f22f3c87b8a0f3dc540627b4be539bae7f6e61e49d931542fe5b557545347272bbdacd7f58a5c77025a18b745593a50 - languageName: node - linkType: hard - "@babel/helper-create-class-features-plugin@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-create-class-features-plugin@npm:7.27.1" @@ -706,16 +688,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-module-imports@npm:7.28.6" - dependencies: - "@babel/traverse": "npm:^7.28.6" - "@babel/types": "npm:^7.28.6" - checksum: 10c0/b49d8d8f204d9dbfd5ac70c54e533e5269afb3cea966a9d976722b13e9922cc773a653405f53c89acb247d5aebdae4681d631a3ae3df77ec046b58da76eda2ac - languageName: node - linkType: hard - "@babel/helper-module-transforms@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-module-transforms@npm:7.27.1" @@ -729,16 +701,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-module-transforms@npm:7.28.6" +"@babel/helper-module-transforms@npm:^7.28.3": + version: 7.28.3 + resolution: "@babel/helper-module-transforms@npm:7.28.3" dependencies: - "@babel/helper-module-imports": "npm:^7.28.6" - "@babel/helper-validator-identifier": "npm:^7.28.5" - "@babel/traverse": "npm:^7.28.6" + "@babel/helper-module-imports": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.3" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/6f03e14fc30b287ce0b839474b5f271e72837d0cafe6b172d759184d998fbee3903a035e81e07c2c596449e504f453463d58baa65b6f40a37ded5bec74620b2b + checksum: 10c0/549be62515a6d50cd4cfefcab1b005c47f89bd9135a22d602ee6a5e3a01f27571868ada10b75b033569f24dc4a2bb8d04bfa05ee75c16da7ade2d0db1437fcdb languageName: node linkType: hard @@ -819,13 +791,13 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helpers@npm:7.28.6" +"@babel/helpers@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/helpers@npm:7.28.4" dependencies: - "@babel/template": "npm:^7.28.6" - "@babel/types": "npm:^7.28.6" - checksum: 10c0/c4a779c66396bb0cf619402d92f1610601ff3832db2d3b86b9c9dd10983bf79502270e97ac6d5280cea1b1a37de2f06ecbac561bd2271545270407fbe64027cb + "@babel/template": "npm:^7.27.2" + "@babel/types": "npm:^7.28.4" + checksum: 10c0/aaa5fb8098926dfed5f223adf2c5e4c7fbba4b911b73dfec2d7d3083f8ba694d201a206db673da2d9b3ae8c01793e795767654558c450c8c14b4c2175b4fcb44 languageName: node linkType: hard @@ -851,25 +823,25 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/parser@npm:7.28.5" +"@babel/parser@npm:^7.28.3, @babel/parser@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/parser@npm:7.28.4" dependencies: - "@babel/types": "npm:^7.28.5" + "@babel/types": "npm:^7.28.4" bin: parser: ./bin/babel-parser.js - checksum: 10c0/5bbe48bf2c79594ac02b490a41ffde7ef5aa22a9a88ad6bcc78432a6ba8a9d638d531d868bd1f104633f1f6bba9905746e15185b8276a3756c42b765d131b1ef + checksum: 10c0/58b239a5b1477ac7ed7e29d86d675cc81075ca055424eba6485872626db2dc556ce63c45043e5a679cd925e999471dba8a3ed4864e7ab1dbf64306ab72c52707 languageName: node linkType: hard -"@babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/parser@npm:7.29.0" +"@babel/parser@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/parser@npm:7.28.5" dependencies: - "@babel/types": "npm:^7.29.0" + "@babel/types": "npm:^7.28.5" bin: parser: ./bin/babel-parser.js - checksum: 10c0/333b2aa761264b91577a74bee86141ef733f9f9f6d4fc52548e4847dc35dfbf821f58c46832c637bfa761a6d9909d6a68f7d1ed59e17e4ffbb958dc510c17b62 + checksum: 10c0/5bbe48bf2c79594ac02b490a41ffde7ef5aa22a9a88ad6bcc78432a6ba8a9d638d531d868bd1f104633f1f6bba9905746e15185b8276a3756c42b765d131b1ef languageName: node linkType: hard @@ -1131,7 +1103,7 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.27.1, @babel/template@npm:^7.3.3": +"@babel/template@npm:^7.27.1, @babel/template@npm:^7.27.2, @babel/template@npm:^7.3.3": version: 7.27.2 resolution: "@babel/template@npm:7.27.2" dependencies: @@ -1142,17 +1114,6 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/template@npm:7.28.6" - dependencies: - "@babel/code-frame": "npm:^7.28.6" - "@babel/parser": "npm:^7.28.6" - "@babel/types": "npm:^7.28.6" - checksum: 10c0/66d87225ed0bc77f888181ae2d97845021838c619944877f7c4398c6748bcf611f216dfd6be74d39016af502bca876e6ce6873db3c49e4ac354c56d34d57e9f5 - languageName: node - linkType: hard - "@babel/traverse@npm:^7.27.1": version: 7.27.1 resolution: "@babel/traverse@npm:7.27.1" @@ -1168,18 +1129,33 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/traverse@npm:7.29.0" +"@babel/traverse@npm:^7.28.3": + version: 7.28.4 + resolution: "@babel/traverse@npm:7.28.4" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.28.3" + "@babel/helper-globals": "npm:^7.28.0" + "@babel/parser": "npm:^7.28.4" + "@babel/template": "npm:^7.27.2" + "@babel/types": "npm:^7.28.4" + debug: "npm:^4.3.1" + checksum: 10c0/ee678fdd49c9f54a32e07e8455242390d43ce44887cea6567b233fe13907b89240c377e7633478a32c6cf1be0e17c2f7f3b0c59f0666e39c5074cc47b968489c + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/traverse@npm:7.28.5" dependencies: - "@babel/code-frame": "npm:^7.29.0" - "@babel/generator": "npm:^7.29.0" + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.28.5" "@babel/helper-globals": "npm:^7.28.0" - "@babel/parser": "npm:^7.29.0" - "@babel/template": "npm:^7.28.6" - "@babel/types": "npm:^7.29.0" + "@babel/parser": "npm:^7.28.5" + "@babel/template": "npm:^7.27.2" + "@babel/types": "npm:^7.28.5" debug: "npm:^4.3.1" - checksum: 10c0/f63ef6e58d02a9fbf3c0e2e5f1c877da3e0bc57f91a19d2223d53e356a76859cbaf51171c9211c71816d94a0e69efa2732fd27ffc0e1bbc84b636e60932333eb + checksum: 10c0/f6c4a595993ae2b73f2d4cd9c062f2e232174d293edd4abe1d715bd6281da8d99e47c65857e8d0917d9384c65972f4acdebc6749a7c40a8fcc38b3c7fb3e706f languageName: node linkType: hard @@ -1203,23 +1179,33 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/types@npm:7.28.5" +"@babel/types@npm:^7.28.2": + version: 7.28.2 + resolution: "@babel/types@npm:7.28.2" dependencies: "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.28.5" - checksum: 10c0/a5a483d2100befbf125793640dec26b90b95fd233a94c19573325898a5ce1e52cdfa96e495c7dcc31b5eca5b66ce3e6d4a0f5a4a62daec271455959f208ab08a + "@babel/helper-validator-identifier": "npm:^7.27.1" + checksum: 10c0/24b11c9368e7e2c291fe3c1bcd1ed66f6593a3975f479cbb9dd7b8c8d8eab8a962b0d2fca616c043396ce82500ac7d23d594fbbbd013828182c01596370a0b10 + languageName: node + linkType: hard + +"@babel/types@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/types@npm:7.28.4" + dependencies: + "@babel/helper-string-parser": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.27.1" + checksum: 10c0/ac6f909d6191319e08c80efbfac7bd9a25f80cc83b43cd6d82e7233f7a6b9d6e7b90236f3af7400a3f83b576895bcab9188a22b584eb0f224e80e6d4e95f4517 languageName: node linkType: hard -"@babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/types@npm:7.29.0" +"@babel/types@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/types@npm:7.28.5" dependencies: "@babel/helper-string-parser": "npm:^7.27.1" "@babel/helper-validator-identifier": "npm:^7.28.5" - checksum: 10c0/23cc3466e83bcbfab8b9bd0edaafdb5d4efdb88b82b3be6728bbade5ba2f0996f84f63b1c5f7a8c0d67efded28300898a5f930b171bb40b311bca2029c4e9b4f + checksum: 10c0/a5a483d2100befbf125793640dec26b90b95fd233a94c19573325898a5ce1e52cdfa96e495c7dcc31b5eca5b66ce3e6d4a0f5a4a62daec271455959f208ab08a languageName: node linkType: hard @@ -1230,58 +1216,57 @@ __metadata: languageName: node linkType: hard -"@blueprintjs/colors@npm:^5.1.8": - version: 5.1.8 - resolution: "@blueprintjs/colors@npm:5.1.8" +"@blueprintjs/colors@npm:^5.1.12": + version: 5.1.12 + resolution: "@blueprintjs/colors@npm:5.1.12" dependencies: tslib: "npm:~2.6.2" - checksum: 10c0/d0a3d500628f60415f830df872244370efb0268f43b03a5c7c27d473ea1be5b8c9fb35fbc47330d7c022f3ddecd7afefb6ee4ef94789fe98feb2be95b15753ac + checksum: 10c0/749a59646082c5605f12b095595e9662587dafcb2fdb253ba57131faa9ce829630bd1cb1709a53ef430ba5fc1159b375523a5a578c9f8ff644d7a0a2e5911a55 languageName: node linkType: hard -"@blueprintjs/core@npm:^5.10.2": - version: 5.19.1 - resolution: "@blueprintjs/core@npm:5.19.1" +"@blueprintjs/core@npm:^6.0.0": + version: 6.6.1 + resolution: "@blueprintjs/core@npm:6.6.1" dependencies: - "@blueprintjs/colors": "npm:^5.1.8" - "@blueprintjs/icons": "npm:^5.23.0" + "@blueprintjs/colors": "npm:^5.1.12" + "@blueprintjs/icons": "npm:^6.5.0" "@popperjs/core": "npm:^2.11.8" classnames: "npm:^2.3.1" normalize.css: "npm:^8.0.1" react-popper: "npm:^2.3.0" react-transition-group: "npm:^4.4.5" - react-uid: "npm:^2.3.3" tslib: "npm:~2.6.2" use-sync-external-store: "npm:^1.2.0" peerDependencies: - "@types/react": ^16.14.41 || 17 || 18 - react: ^16.8 || 17 || 18 - react-dom: ^16.8 || 17 || 18 + "@types/react": 18 + react: 18 + react-dom: 18 peerDependenciesMeta: "@types/react": optional: true bin: upgrade-blueprint-2.0.0-rename: scripts/upgrade-blueprint-2.0.0-rename.sh upgrade-blueprint-3.0.0-rename: scripts/upgrade-blueprint-3.0.0-rename.sh - checksum: 10c0/0805c88b3da989fa242c5acf4dda0bfaf20e937f61e8c3b8e9189f34d5e4b6bde90bf7e55eefb07c18716fed77df9b76bc6197c2e53e2e662d4b82569015253c + checksum: 10c0/a9f90ee376a3a1d16314160f853460d8b279514437deeb907844bebe9749d47a2cb3bcf1f5ff82df4c2f87f7b7ca4fb2e136d3ec8706c650e15cd39dd399c1c1 languageName: node linkType: hard -"@blueprintjs/icons@npm:^5.23.0, @blueprintjs/icons@npm:^5.9.0": - version: 5.23.0 - resolution: "@blueprintjs/icons@npm:5.23.0" +"@blueprintjs/icons@npm:^6.0.0, @blueprintjs/icons@npm:^6.5.0": + version: 6.5.0 + resolution: "@blueprintjs/icons@npm:6.5.0" dependencies: change-case: "npm:^4.1.2" classnames: "npm:^2.3.1" tslib: "npm:~2.6.2" peerDependencies: - "@types/react": ^16.14.41 || 17 || 18 - react: ^16.8 || 17 || 18 - react-dom: ^16.8 || 17 || 18 + "@types/react": 18 + react: 18 + react-dom: 18 peerDependenciesMeta: "@types/react": optional: true - checksum: 10c0/9af904e3b5c2c5e9ac7c9b12e1612184805f60d560a554df8917dafd715bed1cf1586ce31d64c59c2a7c84f595b8999c770036b9ff7f9c9f480ac1b82ccfae70 + checksum: 10c0/ce911dec2d0d91e4ce1eccfd72d242c9484007f4399954f7783aad4c467ebed6ba3e97ce0c2ecce6e9432cdfb99c706ee59bd18acfc224b37792cdd3b724054f languageName: node linkType: hard @@ -1405,125 +1390,108 @@ __metadata: languageName: node linkType: hard -"@cspell/cspell-bundled-dicts@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/cspell-bundled-dicts@npm:9.6.4" +"@cspell/cspell-bundled-dicts@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/cspell-bundled-dicts@npm:9.3.1" dependencies: "@cspell/dict-ada": "npm:^4.1.1" "@cspell/dict-al": "npm:^1.1.1" - "@cspell/dict-aws": "npm:^4.0.17" + "@cspell/dict-aws": "npm:^4.0.15" "@cspell/dict-bash": "npm:^4.2.2" - "@cspell/dict-companies": "npm:^3.2.10" - "@cspell/dict-cpp": "npm:^7.0.2" + "@cspell/dict-companies": "npm:^3.2.7" + "@cspell/dict-cpp": "npm:^6.0.14" "@cspell/dict-cryptocurrencies": "npm:^5.0.5" - "@cspell/dict-csharp": "npm:^4.0.8" - "@cspell/dict-css": "npm:^4.0.19" - "@cspell/dict-dart": "npm:^2.3.2" - "@cspell/dict-data-science": "npm:^2.0.13" - "@cspell/dict-django": "npm:^4.1.6" - "@cspell/dict-docker": "npm:^1.1.17" - "@cspell/dict-dotnet": "npm:^5.0.11" + "@cspell/dict-csharp": "npm:^4.0.7" + "@cspell/dict-css": "npm:^4.0.18" + "@cspell/dict-dart": "npm:^2.3.1" + "@cspell/dict-data-science": "npm:^2.0.11" + "@cspell/dict-django": "npm:^4.1.5" + "@cspell/dict-docker": "npm:^1.1.16" + "@cspell/dict-dotnet": "npm:^5.0.10" "@cspell/dict-elixir": "npm:^4.0.8" - "@cspell/dict-en-common-misspellings": "npm:^2.1.12" - "@cspell/dict-en-gb-mit": "npm:^3.1.17" - "@cspell/dict-en_us": "npm:^4.4.28" - "@cspell/dict-filetypes": "npm:^3.0.15" + "@cspell/dict-en-common-misspellings": "npm:^2.1.8" + "@cspell/dict-en-gb-mit": "npm:^3.1.14" + "@cspell/dict-en_us": "npm:^4.4.24" + "@cspell/dict-filetypes": "npm:^3.0.14" "@cspell/dict-flutter": "npm:^1.1.1" "@cspell/dict-fonts": "npm:^4.0.5" "@cspell/dict-fsharp": "npm:^1.1.1" - "@cspell/dict-fullstack": "npm:^3.2.8" + "@cspell/dict-fullstack": "npm:^3.2.7" "@cspell/dict-gaming-terms": "npm:^1.1.2" - "@cspell/dict-git": "npm:^3.1.0" - "@cspell/dict-golang": "npm:^6.0.26" + "@cspell/dict-git": "npm:^3.0.7" + "@cspell/dict-golang": "npm:^6.0.24" "@cspell/dict-google": "npm:^1.0.9" "@cspell/dict-haskell": "npm:^4.0.6" - "@cspell/dict-html": "npm:^4.0.14" - "@cspell/dict-html-symbol-entities": "npm:^4.0.5" + "@cspell/dict-html": "npm:^4.0.12" + "@cspell/dict-html-symbol-entities": "npm:^4.0.4" "@cspell/dict-java": "npm:^5.0.12" "@cspell/dict-julia": "npm:^1.1.1" "@cspell/dict-k8s": "npm:^1.0.12" "@cspell/dict-kotlin": "npm:^1.1.1" - "@cspell/dict-latex": "npm:^5.0.0" + "@cspell/dict-latex": "npm:^4.0.4" "@cspell/dict-lorem-ipsum": "npm:^4.0.5" "@cspell/dict-lua": "npm:^4.0.8" "@cspell/dict-makefile": "npm:^1.0.5" - "@cspell/dict-markdown": "npm:^2.0.14" - "@cspell/dict-monkeyc": "npm:^1.0.12" - "@cspell/dict-node": "npm:^5.0.9" - "@cspell/dict-npm": "npm:^5.2.32" - "@cspell/dict-php": "npm:^4.1.1" + "@cspell/dict-markdown": "npm:^2.0.12" + "@cspell/dict-monkeyc": "npm:^1.0.11" + "@cspell/dict-node": "npm:^5.0.8" + "@cspell/dict-npm": "npm:^5.2.20" + "@cspell/dict-php": "npm:^4.1.0" "@cspell/dict-powershell": "npm:^5.0.15" "@cspell/dict-public-licenses": "npm:^2.0.15" - "@cspell/dict-python": "npm:^4.2.25" + "@cspell/dict-python": "npm:^4.2.21" "@cspell/dict-r": "npm:^2.1.1" - "@cspell/dict-ruby": "npm:^5.1.0" - "@cspell/dict-rust": "npm:^4.1.2" - "@cspell/dict-scala": "npm:^5.0.9" + "@cspell/dict-ruby": "npm:^5.0.9" + "@cspell/dict-rust": "npm:^4.0.12" + "@cspell/dict-scala": "npm:^5.0.8" "@cspell/dict-shell": "npm:^1.1.2" - "@cspell/dict-software-terms": "npm:^5.1.20" + "@cspell/dict-software-terms": "npm:^5.1.11" "@cspell/dict-sql": "npm:^2.2.1" "@cspell/dict-svelte": "npm:^1.0.7" "@cspell/dict-swift": "npm:^2.0.6" "@cspell/dict-terraform": "npm:^1.1.3" "@cspell/dict-typescript": "npm:^3.2.3" "@cspell/dict-vue": "npm:^3.0.5" - "@cspell/dict-zig": "npm:^1.0.0" - checksum: 10c0/4f269089534f7c0e172327a1a81fd722185abbb8b80893e0e6a45ecceb652615935a759c28183fe66ff242e2b5804cdd3173510050506ca1a48b9d3dec416813 + checksum: 10c0/b0908ee774aebe01f50d7b187df53d27d45a40f69d5a50026d7387e45ca63966bc1eb3f61ecb23ba598fbc349027e613084017abdb8d27714c24e73a2c1b93e5 languageName: node linkType: hard -"@cspell/cspell-json-reporter@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/cspell-json-reporter@npm:9.6.4" +"@cspell/cspell-json-reporter@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/cspell-json-reporter@npm:9.3.1" dependencies: - "@cspell/cspell-types": "npm:9.6.4" - checksum: 10c0/07d2d4ed2d3ad21391f0597a82742c8a42e1a652f8802b86818f9cd88b7af8de738a9e067ea97c93630f0a082525695f387d0cd9eca7e4bb4129ca2530f8e334 - languageName: node - linkType: hard - -"@cspell/cspell-performance-monitor@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/cspell-performance-monitor@npm:9.6.4" - checksum: 10c0/7dafc2880aba45e5b978f86a1e847106c766935a999165cacad3afadcce41f1838ba2a7ab1f3cc497dd1cf0bd8b4c58aa47a680b386ffa6d8ffab867c499d165 + "@cspell/cspell-types": "npm:9.3.1" + checksum: 10c0/e04ff6749865b985e34b1ec3b893d7098fcc5a6e4a765da722114552fda70188d4ec9ff2aa587cc765eaf190f3d0e88f2d79cc1ea81fa4a5b6d662e1a17b7b12 languageName: node linkType: hard -"@cspell/cspell-pipe@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/cspell-pipe@npm:9.6.4" - checksum: 10c0/cb27011b3591f56286ffaeace20709e73fedef4344f544cffa7a124da92330d950beaa6c99fe1e5f43497f1aebb4d5c6abd312bf19ef7ca8a561f6ecf953a168 +"@cspell/cspell-pipe@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/cspell-pipe@npm:9.3.1" + checksum: 10c0/ebdc05b8ee7505c7ec4ad05269f769a80100807d137e45bfe332a384a4c3a82f2834e7a3cac31a4be68ff6cd6ecb78e930e30e54b7d485bb6bef39a3ca42de3d languageName: node linkType: hard -"@cspell/cspell-resolver@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/cspell-resolver@npm:9.6.4" +"@cspell/cspell-resolver@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/cspell-resolver@npm:9.3.1" dependencies: global-directory: "npm:^4.0.1" - checksum: 10c0/1901f995fb09a4a2b963b4eb88bb5da55d05aac0186f21292b0a9ea31ef6d184a21b92187929e718a421df27a6d85d3eb28081a15d43098c4bb197dfaed65b2e - languageName: node - linkType: hard - -"@cspell/cspell-service-bus@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/cspell-service-bus@npm:9.6.4" - checksum: 10c0/93a8a69016fed7b03cfa70119b7b14fab543398063978e090767e65dc31509d9217940ddefe0ab311ff79768baa957ec67a152e6ac3e1f410461c69851202c4c + checksum: 10c0/c154516ef6c209d0cbd8ee9c492088a5f06bfbe60e085df0d3e83ed2a5f898a498e721ece4b1743ef1bb6c51593dfebc57868d53d320a80bf850e7bc6ede91ab languageName: node linkType: hard -"@cspell/cspell-types@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/cspell-types@npm:9.6.4" - checksum: 10c0/74d7913c9f7a53f0e3470ce05fa356f635ff2a39b84862f72c6ee37e1f1efe9c4559367a4507f97495b292d9359a5fa153bdb7439b8be38034d7f2b784af350c +"@cspell/cspell-service-bus@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/cspell-service-bus@npm:9.3.1" + checksum: 10c0/142695d3d8d550ff93e7881a4b0ba58df4219a4106d5865a8f363151d030f7eb6e7a1f8ef1c867656479c3ed6c661bdf6d447494bb178a0c3f1beed6ba968767 languageName: node linkType: hard -"@cspell/cspell-worker@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/cspell-worker@npm:9.6.4" - dependencies: - cspell-lib: "npm:9.6.4" - checksum: 10c0/b317c29d290c9f61bd4899d293a2319943f38d1fd403cf0935644f30d957c633b212a66c5120cd6cc1534f1252d6f010ebd9c4805a85c79325a588b38a7ad1d3 +"@cspell/cspell-types@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/cspell-types@npm:9.3.1" + checksum: 10c0/c1815480ab85d902cf722220e1b6b5f53dad61b861ca9a15c1141a0652edd38771857fd83f89b4174d64930acaaef50ab8135304d88823c935ea2093e02a3587 languageName: node linkType: hard @@ -1541,10 +1509,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-aws@npm:^4.0.17": - version: 4.0.17 - resolution: "@cspell/dict-aws@npm:4.0.17" - checksum: 10c0/d421a78aee8cc3db78a0bdffad2ceda9ca8e476498398809f2975bae9f03233df1112e713f2d699239600a9019d5e8f11ca60dfcb49fdce56815d5e794285c7b +"@cspell/dict-aws@npm:^4.0.15": + version: 4.0.15 + resolution: "@cspell/dict-aws@npm:4.0.15" + checksum: 10c0/c5983f2e5ce3dd23d5b8ebc818cc963d9b2c91d9b8436b40491a46ebca4cb1bc7875237c443f6e883488ca66174e84bb804f8b6e37439b4ba6c2b52a146eaa20 languageName: node linkType: hard @@ -1557,17 +1525,17 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-companies@npm:^3.2.10": - version: 3.2.10 - resolution: "@cspell/dict-companies@npm:3.2.10" - checksum: 10c0/56ffda78e90a417fb470d3296d17fa74c2b86f1f73de121b12ca9510f81663eea7c20923fe4409c9159eb20b9b36ff4cf4b6cbb1b4fab48da404ebe1ee855f7b +"@cspell/dict-companies@npm:^3.2.7": + version: 3.2.7 + resolution: "@cspell/dict-companies@npm:3.2.7" + checksum: 10c0/ba2e73974560dc61742c05c00ef75719a31f24e05ad7cfe01ed8eb4a614f8f0a4bb3a0b6cfd9bec6d02e746c490d5de4a3310cfc176461bb4d6de0751c868515 languageName: node linkType: hard -"@cspell/dict-cpp@npm:^7.0.2": - version: 7.0.2 - resolution: "@cspell/dict-cpp@npm:7.0.2" - checksum: 10c0/a2926a6e896f04aa795edcd5fe3ac72cf1e05b97719946388cf31cf91737cfee816ffdd220e1960af60d7049daa37262787e76534afa5479fe10691af096b54c +"@cspell/dict-cpp@npm:^6.0.14": + version: 6.0.14 + resolution: "@cspell/dict-cpp@npm:6.0.14" + checksum: 10c0/d109ced99c9b673c57145bbcb4c20a471aac267edd9c418fefb49c78675f3c8e24a2d99834525055e80d2825ee932966edebd2e6641824261837a02e650f8bed languageName: node linkType: hard @@ -1578,52 +1546,52 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-csharp@npm:^4.0.8": - version: 4.0.8 - resolution: "@cspell/dict-csharp@npm:4.0.8" - checksum: 10c0/b55dbe323b973e0e98d76a17205b103fbb52dec01d45d55aa06a14f1acc6c8bec259f7923bbe6138d1af2b11463969d920214ce0fc6e89eaf6fa08f86b10184e +"@cspell/dict-csharp@npm:^4.0.7": + version: 4.0.7 + resolution: "@cspell/dict-csharp@npm:4.0.7" + checksum: 10c0/93afd6cfc973a5543120d1de2ee9cafbcbe64af6743e2ba3a8cfb0965fe19c85c6dee5a32c99a156cc979c8a89803b684e324ca92065b3a32faa7db786072e5e languageName: node linkType: hard -"@cspell/dict-css@npm:^4.0.19": - version: 4.0.19 - resolution: "@cspell/dict-css@npm:4.0.19" - checksum: 10c0/e0ba38ec536ce8a9b88a4afb197b9467622bd6519a84e71435e9f0d8d90d12d94f6e83d5e504337a95f6ce99ee398c920c6367c6252c6c01c794cba61b621bde +"@cspell/dict-css@npm:^4.0.18": + version: 4.0.18 + resolution: "@cspell/dict-css@npm:4.0.18" + checksum: 10c0/6d27fab2c1d2b023bdca93c2b013f69b2e782e2df444fed9406a0f9c1f2c84e6da5bfa9b7ae4c4e235498bbfd06a8822a6d6b228b5d3444fda8499d7a81dddfe languageName: node linkType: hard -"@cspell/dict-dart@npm:^2.3.2": - version: 2.3.2 - resolution: "@cspell/dict-dart@npm:2.3.2" - checksum: 10c0/1c0842ff09785aaf2bc2e68f4c05ec5e20331f3fce1503ef5a87305feb223f6e23404c68e4991bb90c6473825a7f8cd65b3ed86eef0d8032d43b13558ddb1753 +"@cspell/dict-dart@npm:^2.3.1": + version: 2.3.1 + resolution: "@cspell/dict-dart@npm:2.3.1" + checksum: 10c0/40bbb2e20b761da0be513d3476db054211bfa5a514860569c0d46f3b869b782ef8d8118b4a30aa10b51dde280d22d5199988c9a89d2495742e660de8b5bb6792 languageName: node linkType: hard -"@cspell/dict-data-science@npm:^2.0.13": - version: 2.0.13 - resolution: "@cspell/dict-data-science@npm:2.0.13" - checksum: 10c0/63d8291ef0e62defbf4b98e58bd1039747efdb6348fa64c128a01a0b28b93ce1724e878e945b1ca7d8f568a49446a46ed65ef71531130c7b1b1fddb5328a1a0e +"@cspell/dict-data-science@npm:^2.0.11": + version: 2.0.11 + resolution: "@cspell/dict-data-science@npm:2.0.11" + checksum: 10c0/b273db0ce3306355ff75963610810055c517d2aa45ebd12a45b64e8b11de548e53ff980be7e7496c4f9b438a9737142399ff528c8cf1ffc22798fcc4f3fff42c languageName: node linkType: hard -"@cspell/dict-django@npm:^4.1.6": - version: 4.1.6 - resolution: "@cspell/dict-django@npm:4.1.6" - checksum: 10c0/76f71cba5a692df48554a3cd7cff7e27df85ab826e2cddf0594c21062e5c96de3090508314659a9ec708913a4afd61afb0f044ae8c41a1ec573583d516056f2d +"@cspell/dict-django@npm:^4.1.5": + version: 4.1.5 + resolution: "@cspell/dict-django@npm:4.1.5" + checksum: 10c0/df51162b33c31ead2a983dc26face4b2d563382b082cbf13971593cec3687552d4e4e4af444beecb3b00baf1c28b5cb92944dba04de303d0864f7656a11b8921 languageName: node linkType: hard -"@cspell/dict-docker@npm:^1.1.17": - version: 1.1.17 - resolution: "@cspell/dict-docker@npm:1.1.17" - checksum: 10c0/1aaa4ffba7842b9044d1c4c6ae704907e6be3d8407c7feb986b3b7efa2e0139fc2ea3c3ad955d7ba4c92b5f577e05648ffc00a2a27b76d2bb93acde431452e58 +"@cspell/dict-docker@npm:^1.1.16": + version: 1.1.16 + resolution: "@cspell/dict-docker@npm:1.1.16" + checksum: 10c0/0e2c211da4a8d6e23311bc41c4041bf447c5c7a4ab84afe3a0229d11fc0af19ec1f6f8fcfd9c6b6793b538a81026d3957e86f3999baba973520ffe84a9420014 languageName: node linkType: hard -"@cspell/dict-dotnet@npm:^5.0.11": - version: 5.0.11 - resolution: "@cspell/dict-dotnet@npm:5.0.11" - checksum: 10c0/02f13fade5845dc444ce71d20af52add1c4755191d2bd99b17706eba27d7ef52e5e09122a48ff560eb81e06c4da73ffa680bc599d04d2c79ababf92ac0cf96e8 +"@cspell/dict-dotnet@npm:^5.0.10": + version: 5.0.10 + resolution: "@cspell/dict-dotnet@npm:5.0.10" + checksum: 10c0/ddb368955d86059d6d59a82263769af832c90028e20c61cdc1e9ba25ac7de8465fd4da2f1966c4683d870720ef7138b937bdde994ac5e991aafc84e236f218b9 languageName: node linkType: hard @@ -1634,31 +1602,31 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-en-common-misspellings@npm:^2.1.12": - version: 2.1.12 - resolution: "@cspell/dict-en-common-misspellings@npm:2.1.12" - checksum: 10c0/5b7acd175ba76f164dcb5f5b7e910511dbd005bbab77fb5ae082603b01112d352af84bcd8d3ddef020db187b51056c4ce6a02dab8aebfcf0aa0dc416a66729a5 +"@cspell/dict-en-common-misspellings@npm:^2.1.8": + version: 2.1.8 + resolution: "@cspell/dict-en-common-misspellings@npm:2.1.8" + checksum: 10c0/8a9a98216c81f018aa24e76e0e997ceeaff57f5bc97c2831c072085347f403fa2809ad6c6bc298b9127444155d83ac8da9d156df98f4f5313f1d978fddb1bb27 languageName: node linkType: hard -"@cspell/dict-en-gb-mit@npm:^3.1.17": - version: 3.1.17 - resolution: "@cspell/dict-en-gb-mit@npm:3.1.17" - checksum: 10c0/634eb058d347f3d2f95d86b946cd5871d005b89f6d505c72b5515012596bf7c02fa6fc9b99d82038c4c28404991489a0b2c58c0a7ac305b20123f2409b710a7e +"@cspell/dict-en-gb-mit@npm:^3.1.14": + version: 3.1.14 + resolution: "@cspell/dict-en-gb-mit@npm:3.1.14" + checksum: 10c0/44f6f77bacbf8932470eeb75756cc68829be36dc19eddca2b91512fa57ddfb64e18f3a0b282cd20e496aba68b297cd962713ecf68811a7cac619652b2a5ecaad languageName: node linkType: hard -"@cspell/dict-en_us@npm:^4.4.28": - version: 4.4.28 - resolution: "@cspell/dict-en_us@npm:4.4.28" - checksum: 10c0/b1defb0f68db71139d45a7323d4edd168788740d958014931d8295633524b3f8ad16385415c1760d2e81d653674d177083a12044ce5bb59f3c68cb3aedb69b40 +"@cspell/dict-en_us@npm:^4.4.24": + version: 4.4.24 + resolution: "@cspell/dict-en_us@npm:4.4.24" + checksum: 10c0/bf38bc74753439265e80741a2312b539a36623d38ec816b0698e8e667ad291f6d3b1d4700121aab8539639a5a5f26e138f1e02a1864c72a04306bb6dd23dc3e5 languageName: node linkType: hard -"@cspell/dict-filetypes@npm:^3.0.15": - version: 3.0.15 - resolution: "@cspell/dict-filetypes@npm:3.0.15" - checksum: 10c0/2bf7c592fbe4755dfff8375fbe422b0ac6c0daebc71d4641141611520aeb67e043e9016075b7855513306b594980a6b55af2069e10848256493fcb39a34d0725 +"@cspell/dict-filetypes@npm:^3.0.14": + version: 3.0.14 + resolution: "@cspell/dict-filetypes@npm:3.0.14" + checksum: 10c0/cc51a1099e331021b2be77f7aaa554a6e4e3d9af9443c48a59903867f44ea4553056b130c965d4b599191b7c9a72d86aa151f6a76bdcdad7004d34a3050a8ab5 languageName: node linkType: hard @@ -1683,10 +1651,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-fullstack@npm:^3.2.8": - version: 3.2.8 - resolution: "@cspell/dict-fullstack@npm:3.2.8" - checksum: 10c0/90a469b899574bee9fff390e4264cc72468847b4c53fb2bc5991874e7b65c8d949c693615953d836a8b7cba69c5690163d722c07126c0ca3bd798197a86c64e6 +"@cspell/dict-fullstack@npm:^3.2.7": + version: 3.2.7 + resolution: "@cspell/dict-fullstack@npm:3.2.7" + checksum: 10c0/81e19f537553f243fa2ede72cbaf727f71c64ea769952c6bea20d82492b9199761677e1107683abd225dcbd6233bf0502c8faf7ec9be65538fdca2a7138bdf3f languageName: node linkType: hard @@ -1697,17 +1665,17 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-git@npm:^3.1.0": - version: 3.1.0 - resolution: "@cspell/dict-git@npm:3.1.0" - checksum: 10c0/161a9bd35f44173993c84ec2bc394c5fab4fe7d69070daa170be4922e295d60a3e34cecb04869a8b685b761c7ace83241ff4d60db93d2850368d769733a58de9 +"@cspell/dict-git@npm:^3.0.7": + version: 3.0.7 + resolution: "@cspell/dict-git@npm:3.0.7" + checksum: 10c0/db22c7a8eeca4c36fba9fdeae440bfdf0d4fd7ca2aaebe06b8b895273ea93eb48f00bb3216146e2d8e595226ad96668095f6ffa0f80f88ccdd450054aca5f12c languageName: node linkType: hard -"@cspell/dict-golang@npm:^6.0.26": - version: 6.0.26 - resolution: "@cspell/dict-golang@npm:6.0.26" - checksum: 10c0/514c54dc72620975e552ad91ecc8d98143611224e7fe3606fc6041f3248e9f9457be1f25027ff1d9bc2961459c5759dff3a01251054aab83bbcc9f927648b755 +"@cspell/dict-golang@npm:^6.0.24": + version: 6.0.24 + resolution: "@cspell/dict-golang@npm:6.0.24" + checksum: 10c0/2d6e63e606215db7c29fe312d2414da585372d7c994ce1ba2808a4bf13c5410b0e4318efda9b2ccaab020a3bbc6d8f06c910dbd1a5cc24946ff7e378ffbb591b languageName: node linkType: hard @@ -1725,17 +1693,17 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-html-symbol-entities@npm:^4.0.5": - version: 4.0.5 - resolution: "@cspell/dict-html-symbol-entities@npm:4.0.5" - checksum: 10c0/8278b8cca06e6d3654e81b1809227ff1d64e053f79308966ea601194ce51fa3a385dde6844509b26223de70d034e60a85c604a729f021c0de63f8a5e6f29b0ce +"@cspell/dict-html-symbol-entities@npm:^4.0.4": + version: 4.0.4 + resolution: "@cspell/dict-html-symbol-entities@npm:4.0.4" + checksum: 10c0/ff6be66c36845409622b732f010c5c7a3680c759fba55d136be5556f505bd7e7daee85834b2b9aae54c90a6f6b4055a1b39d49a5976c04226fa80f9238fa48a1 languageName: node linkType: hard -"@cspell/dict-html@npm:^4.0.14": - version: 4.0.14 - resolution: "@cspell/dict-html@npm:4.0.14" - checksum: 10c0/8dedb8a20f7bc53db4b933ae118ee0ab654b176648b2451d335ca8bd266f84ce8deb52989aa51a52f872730262e113b73874b88320b115ab2e993876a3f24cb1 +"@cspell/dict-html@npm:^4.0.12": + version: 4.0.12 + resolution: "@cspell/dict-html@npm:4.0.12" + checksum: 10c0/de3d7197859502e2bb7be4206a881cd53bc6b30516cd181116bbe83c9698da34ebaf7e8da2d62afe925bd0cc3a8abb16aea3794eb3a916a83dc1e915c7b6b49f languageName: node linkType: hard @@ -1767,10 +1735,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-latex@npm:^5.0.0": - version: 5.0.0 - resolution: "@cspell/dict-latex@npm:5.0.0" - checksum: 10c0/02d0d3d4a14eba96de6f4f6b51b3f2d1ac1d2de7b1069e3ae6631bdbc53982caead563abb2a568d436fa016bf99aea36d0e6e2c3b9a83c1e9fe9ccbc923d5da7 +"@cspell/dict-latex@npm:^4.0.4": + version: 4.0.4 + resolution: "@cspell/dict-latex@npm:4.0.4" + checksum: 10c0/5050b8b8bede9970224a12ac1b613acf735ef36121acad61a891f28ff2aa5e60ffc2392ad502f7de107a2af485f8fb73e611ba6ac169b41f06101bffd4897aca languageName: node linkType: hard @@ -1795,43 +1763,43 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-markdown@npm:^2.0.14": - version: 2.0.14 - resolution: "@cspell/dict-markdown@npm:2.0.14" +"@cspell/dict-markdown@npm:^2.0.12": + version: 2.0.12 + resolution: "@cspell/dict-markdown@npm:2.0.12" peerDependencies: - "@cspell/dict-css": ^4.0.19 - "@cspell/dict-html": ^4.0.14 - "@cspell/dict-html-symbol-entities": ^4.0.5 + "@cspell/dict-css": ^4.0.18 + "@cspell/dict-html": ^4.0.12 + "@cspell/dict-html-symbol-entities": ^4.0.4 "@cspell/dict-typescript": ^3.2.3 - checksum: 10c0/2198375545579fe4aac7b2a53ae4125bee212fa489be5d19193b227308c3e5c687bfc140111c6263bf2d5a7963eb07f2e4b6c737b2de733fc4e0cf3b2123ece2 + checksum: 10c0/f6d53e71525dff0832950345118abcb2c2ca01aaff51922c5c18f7c3bc0d84a2168bb9bb3e400fe6b91312a5892d0b608db6ea590e2a785474ad355e60d9b535 languageName: node linkType: hard -"@cspell/dict-monkeyc@npm:^1.0.12": - version: 1.0.12 - resolution: "@cspell/dict-monkeyc@npm:1.0.12" - checksum: 10c0/97250565f808cbf37d66f2585db7accf449bc1836c72b3fac0449896fe17b8dfa3e5dc15f27f4e5cbe61dc7c24e9b17c1d7f475c934cd7c68b1aa597386a5bc0 +"@cspell/dict-monkeyc@npm:^1.0.11": + version: 1.0.11 + resolution: "@cspell/dict-monkeyc@npm:1.0.11" + checksum: 10c0/856b7107b2eb70925bf7388f6961548c205b9580298ce28352644b5d20b4779b7d0f8d3ea6888f15aceb124c4bafd51ec896cc55d73cea6853c01a37ee4b97b6 languageName: node linkType: hard -"@cspell/dict-node@npm:^5.0.9": - version: 5.0.9 - resolution: "@cspell/dict-node@npm:5.0.9" - checksum: 10c0/129fa7cd204e26769829912a8a64225af45b5cf0438f597329966e1c3db5ffca04b4c426d9cee594f271d14500e11319bc7ed371207cb18d73966000303e3072 +"@cspell/dict-node@npm:^5.0.8": + version: 5.0.8 + resolution: "@cspell/dict-node@npm:5.0.8" + checksum: 10c0/aaca1c73dc9451171716dbbff0e243a4f4bcba7260875b50a582cca5db70415b7cddaf60443814880da59967433b5934b4a830b9dc69c90fa4f9c06b2f2d8063 languageName: node linkType: hard -"@cspell/dict-npm@npm:^5.2.32": - version: 5.2.32 - resolution: "@cspell/dict-npm@npm:5.2.32" - checksum: 10c0/a7de85d0b7b079d7bd37771b4c2e3e773485d5c51e2d30fb9b20823acd31903b6d24c8549d20b14d444d2281158773c0760cb3afbc929d85651744b51483c29f +"@cspell/dict-npm@npm:^5.2.20": + version: 5.2.20 + resolution: "@cspell/dict-npm@npm:5.2.20" + checksum: 10c0/cf06d77311d3c8665140ec7a8f7cdf23fbc049385d687acf689231548e68dd629ce107e3f8f4f7a99e3d8fdaf58c1a2a3e6e20a30c5d41752c7494500953f274 languageName: node linkType: hard -"@cspell/dict-php@npm:^4.1.1": - version: 4.1.1 - resolution: "@cspell/dict-php@npm:4.1.1" - checksum: 10c0/e11e2a3799b2c9ea590ce8b2e69838965f3d8f83020961720afde9c9c57b6ccdb013d54346900766ccf422c548c916dd2aaa890563d36cf12498ad3ddfe67d7a +"@cspell/dict-php@npm:^4.1.0": + version: 4.1.0 + resolution: "@cspell/dict-php@npm:4.1.0" + checksum: 10c0/ff9227e9ada98f949d543ffd653b88638079b429040a6b1ef69ff7845dcaf4d4854d5303459e32a5aa306d0f87871848db72ed8ec335ede30bfae642c65e4e66 languageName: node linkType: hard @@ -1849,12 +1817,12 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-python@npm:^4.2.25": - version: 4.2.25 - resolution: "@cspell/dict-python@npm:4.2.25" +"@cspell/dict-python@npm:^4.2.21": + version: 4.2.21 + resolution: "@cspell/dict-python@npm:4.2.21" dependencies: - "@cspell/dict-data-science": "npm:^2.0.13" - checksum: 10c0/dcab0aac0075f76b0360fd07d61b4421f543e72a98a482494f9a3decb650d475f4508918c85ef8985eeabac11431bf7f67b496491d58a33cf41c25a6016e84a9 + "@cspell/dict-data-science": "npm:^2.0.11" + checksum: 10c0/138818ba2890983d0a96eda2ac659edc459b051f8d89889e3f3b0104c13aa4f02e1848200fe4d952e8b39d05cf179faabf600306e5a7e870146d05fe89fd3131 languageName: node linkType: hard @@ -1865,24 +1833,24 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-ruby@npm:^5.1.0": - version: 5.1.0 - resolution: "@cspell/dict-ruby@npm:5.1.0" - checksum: 10c0/d9ca8a8d72869b37b201fd5d17d1e7d0094185dde559861b899256b7dd55e80aedba430ac2ca393d0db479c284cc89cd2eec8f9e56e5601ebd715f0463c75b7d +"@cspell/dict-ruby@npm:^5.0.9": + version: 5.0.9 + resolution: "@cspell/dict-ruby@npm:5.0.9" + checksum: 10c0/7a63495fd12d787de9f4f72f070110b26fc3709394fb19bdcac44354ef886c0ff998ad03b90d0d3b252019d112ef34ebf99c94329070978f7d92fd4642dda4b5 languageName: node linkType: hard -"@cspell/dict-rust@npm:^4.1.2": - version: 4.1.2 - resolution: "@cspell/dict-rust@npm:4.1.2" - checksum: 10c0/ccee1ef1652f8855f2fee1c5b7c173eda9660f0c7f1eadb550ab2e4e8e2ee2e31eee903e294a32052996fed4045907b0a53383f6fe74d28a04de94a4ac69a29d +"@cspell/dict-rust@npm:^4.0.12": + version: 4.0.12 + resolution: "@cspell/dict-rust@npm:4.0.12" + checksum: 10c0/023f9844e32e6d22aaaf0f23a9744671a66f1d46c47f08efbe7a74e7a6e1e8671a7c394e1fb15d2b840fdbf605c55b693c539b29ad0eb10908c4bd6f7f4b2231 languageName: node linkType: hard -"@cspell/dict-scala@npm:^5.0.9": - version: 5.0.9 - resolution: "@cspell/dict-scala@npm:5.0.9" - checksum: 10c0/f6b214f4cebcb68a270f4e5cb4163fdd59b58afb28894ac6f523025f411792454c6645c0c616d00af10ea541d5fbd25d34ad7986ddef1bb2181003e39140abbe +"@cspell/dict-scala@npm:^5.0.8": + version: 5.0.8 + resolution: "@cspell/dict-scala@npm:5.0.8" + checksum: 10c0/9ae598e1dbd49554df8e6b22f8590393408690ae644ece4c28ec05c267d11cf90a6f25e088eca5a666e7e56fcd165c20511dd51ec8370a038d8bd485b77e0758 languageName: node linkType: hard @@ -1893,10 +1861,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-software-terms@npm:^5.1.20": - version: 5.1.20 - resolution: "@cspell/dict-software-terms@npm:5.1.20" - checksum: 10c0/ff7513919d842bdb804965852d35aded3a2e32b3535637d7e9ec57fce66ddf69af57d20947bb3db358abe2d0d8e5d0feee029e3e14d1fb66b235d519d5133115 +"@cspell/dict-software-terms@npm:^5.1.11": + version: 5.1.11 + resolution: "@cspell/dict-software-terms@npm:5.1.11" + checksum: 10c0/a997043e401c444762c4cfdbe0093d8155c02360338f62bb26b0b5a3ae5341eaa942edbb750f694a8023b322855abb6d36a464d538d3d71939dec5c9c08e1635 languageName: node linkType: hard @@ -1942,48 +1910,34 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-zig@npm:^1.0.0": - version: 1.0.0 - resolution: "@cspell/dict-zig@npm:1.0.0" - checksum: 10c0/bc302e117002c9d6ebfb5d3e085d9a6f2e65d63440deb9f137dce1d8a75650593f5b83d47488ab394cfbc173be032661dc36bc74c85b9826f60a7d2fc7955ffc - languageName: node - linkType: hard - -"@cspell/dynamic-import@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/dynamic-import@npm:9.6.4" +"@cspell/dynamic-import@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/dynamic-import@npm:9.3.1" dependencies: - "@cspell/url": "npm:9.6.4" + "@cspell/url": "npm:9.3.1" import-meta-resolve: "npm:^4.2.0" - checksum: 10c0/b425752c7d7f421a84c45a753760fac63d58a89b4e47453c62024f404090563a0f8b12788fe41b274670ca5c7ff50532a88788839d87b1b6c9f92e8ebb29a423 + checksum: 10c0/b112cb7b9ed940950331e1cd125050270705a20b5f99a59d4976fffdb32e0f2229aea9e53a0839a8df074c395ee32f16934f39f43d416783a40dc017ce63af55 languageName: node linkType: hard -"@cspell/filetypes@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/filetypes@npm:9.6.4" - checksum: 10c0/f79b096698b671219f92497bab85ffc3bdbeff722717436ff58a07ee4b66e286ac2d6df309a55bf1bed3d96c877bf26a601b049724feadf8693741b661156685 +"@cspell/filetypes@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/filetypes@npm:9.3.1" + checksum: 10c0/80731da70f516dc21e2b6c91f170e854e85af3c2a0135b840977f19a8a73baa784a8a8ac9b702c21d3b5786cb5f8550473a1b6089ea053f8d31f4b2ac634bcae languageName: node linkType: hard -"@cspell/rpc@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/rpc@npm:9.6.4" - checksum: 10c0/a0ccfb54e14bbdfbf7b2f3e1a7a1f090025ebd7fc1a057885d483481d5940a9b22d60ba98d027e3c3c58dc5f5ec3943772a5c7b628361844ba519137d99ab155 +"@cspell/strong-weak-map@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/strong-weak-map@npm:9.3.1" + checksum: 10c0/c07c1a1dd0fc5c9529a14b3dac7ed6b07e209de5d3d8e948fb602f5d36d41e6aebfcb45fb475ca5ecdfebb6ec341cb820fcf2ee6975fb777dee240e37f460996 languageName: node linkType: hard -"@cspell/strong-weak-map@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/strong-weak-map@npm:9.6.4" - checksum: 10c0/934c7fe9a40856d6c482534c584bd277b7549745128ac270c70a79b5afe9fd3ed23fb574bb89789914788ffebc957cb3ccbf9d6bbb304a67d9c51f30ed2c970c - languageName: node - linkType: hard - -"@cspell/url@npm:9.6.4": - version: 9.6.4 - resolution: "@cspell/url@npm:9.6.4" - checksum: 10c0/289c76fbd7724a7b1d278701fd716bc5ee90b04c5ea6b1287756a1965894c4673ab41a8516bbec54e179624a932ba994e50dc7e9c9f03b499581d0efbbbff6df +"@cspell/url@npm:9.3.1": + version: 9.3.1 + resolution: "@cspell/url@npm:9.3.1" + checksum: 10c0/01a6f1a3fba08bc09f8b3deace3fcfe40b40ef52959e92f5500737f8942c2d3aeb2fc95286031ac570e5dbd57ccca355b911937ed92c3183502b9197ea7e27bf languageName: node linkType: hard @@ -2090,6 +2044,34 @@ __metadata: languageName: node linkType: hard +"@emnapi/core@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/core@npm:1.8.1" + dependencies: + "@emnapi/wasi-threads": "npm:1.1.0" + tslib: "npm:^2.4.0" + checksum: 10c0/2c242f4b49779bac403e1cbcc98edacdb1c8ad36562408ba9a20663824669e930bc8493be46a2522d9dc946b8d96cd7073970bae914928c7671b5221c85b432e + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.4.3": + version: 1.8.1 + resolution: "@emnapi/runtime@npm:1.8.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/f4929d75e37aafb24da77d2f58816761fe3f826aad2e37fa6d4421dac9060cbd5098eea1ac3c9ecc4526b89deb58153852fa432f87021dc57863f2ff726d713f + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.1.0": + version: 1.1.0 + resolution: "@emnapi/wasi-threads@npm:1.1.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/e6d54bf2b1e64cdd83d2916411e44e579b6ae35d5def0dea61a3c452d9921373044dff32a8b8473ae60c80692bdc39323e98b96a3f3d87ba6886b24dd0ef7ca1 + languageName: node + linkType: hard + "@epilot/esbuild-jest@npm:^0.5.2": version: 0.5.2 resolution: "@epilot/esbuild-jest@npm:0.5.2" @@ -2104,16 +2086,16 @@ __metadata: languageName: node linkType: hard -"@es-joy/jsdoccomment@npm:~0.84.0": - version: 0.84.0 - resolution: "@es-joy/jsdoccomment@npm:0.84.0" +"@es-joy/jsdoccomment@npm:~0.79.0": + version: 0.79.0 + resolution: "@es-joy/jsdoccomment@npm:0.79.0" dependencies: "@types/estree": "npm:^1.0.8" - "@typescript-eslint/types": "npm:^8.54.0" - comment-parser: "npm:1.4.5" + "@typescript-eslint/types": "npm:^8.52.0" + comment-parser: "npm:1.4.1" esquery: "npm:^1.7.0" - jsdoc-type-pratt-parser: "npm:~7.1.1" - checksum: 10c0/b5562c176dde36cd2956bb115b79229d2253b27d6d7e52820eb55c509f75a72048ae8ea8d57193b33be42728c1aa7a5ee20937b4967175291cb4ae60fdda318d + jsdoc-type-pratt-parser: "npm:~7.0.0" + checksum: 10c0/f5102197cf02bede52115f38569c7de2eee82096fe2c81a6d678f24796cd82f60d074ea19d3b9dd9dc1c55b3cafdd05e1b70595ef4eb6198c2a4b405313127d9 languageName: node linkType: hard @@ -2131,9 +2113,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/aix-ppc64@npm:0.27.2" +"@esbuild/aix-ppc64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/aix-ppc64@npm:0.25.4" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/aix-ppc64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/aix-ppc64@npm:0.27.0" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard @@ -2145,9 +2134,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/android-arm64@npm:0.27.2" +"@esbuild/android-arm64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/android-arm64@npm:0.25.4" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/android-arm64@npm:0.27.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -2159,9 +2155,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/android-arm@npm:0.27.2" +"@esbuild/android-arm@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/android-arm@npm:0.25.4" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/android-arm@npm:0.27.0" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -2173,9 +2176,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/android-x64@npm:0.27.2" +"@esbuild/android-x64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/android-x64@npm:0.25.4" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/android-x64@npm:0.27.0" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -2187,9 +2197,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/darwin-arm64@npm:0.27.2" +"@esbuild/darwin-arm64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/darwin-arm64@npm:0.25.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/darwin-arm64@npm:0.27.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -2201,9 +2218,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/darwin-x64@npm:0.27.2" +"@esbuild/darwin-x64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/darwin-x64@npm:0.25.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/darwin-x64@npm:0.27.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -2215,9 +2239,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/freebsd-arm64@npm:0.27.2" +"@esbuild/freebsd-arm64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/freebsd-arm64@npm:0.25.4" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/freebsd-arm64@npm:0.27.0" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -2229,9 +2260,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/freebsd-x64@npm:0.27.2" +"@esbuild/freebsd-x64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/freebsd-x64@npm:0.25.4" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/freebsd-x64@npm:0.27.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -2243,9 +2281,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-arm64@npm:0.27.2" +"@esbuild/linux-arm64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/linux-arm64@npm:0.25.4" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/linux-arm64@npm:0.27.0" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -2257,9 +2302,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-arm@npm:0.27.2" +"@esbuild/linux-arm@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/linux-arm@npm:0.25.4" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/linux-arm@npm:0.27.0" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -2271,9 +2323,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-ia32@npm:0.27.2" +"@esbuild/linux-ia32@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/linux-ia32@npm:0.25.4" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/linux-ia32@npm:0.27.0" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -2285,9 +2344,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-loong64@npm:0.27.2" +"@esbuild/linux-loong64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/linux-loong64@npm:0.25.4" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/linux-loong64@npm:0.27.0" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -2299,9 +2365,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-mips64el@npm:0.27.2" +"@esbuild/linux-mips64el@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/linux-mips64el@npm:0.25.4" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/linux-mips64el@npm:0.27.0" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -2313,9 +2386,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-ppc64@npm:0.27.2" +"@esbuild/linux-ppc64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/linux-ppc64@npm:0.25.4" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/linux-ppc64@npm:0.27.0" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -2327,9 +2407,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-riscv64@npm:0.27.2" +"@esbuild/linux-riscv64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/linux-riscv64@npm:0.25.4" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/linux-riscv64@npm:0.27.0" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -2341,9 +2428,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-s390x@npm:0.27.2" +"@esbuild/linux-s390x@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/linux-s390x@npm:0.25.4" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/linux-s390x@npm:0.27.0" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -2355,16 +2449,30 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-x64@npm:0.27.2" +"@esbuild/linux-x64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/linux-x64@npm:0.25.4" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/linux-x64@npm:0.27.0" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/netbsd-arm64@npm:0.27.2" +"@esbuild/netbsd-arm64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/netbsd-arm64@npm:0.25.4" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/netbsd-arm64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/netbsd-arm64@npm:0.27.0" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard @@ -2376,16 +2484,30 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/netbsd-x64@npm:0.27.2" +"@esbuild/netbsd-x64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/netbsd-x64@npm:0.25.4" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/netbsd-x64@npm:0.27.0" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/openbsd-arm64@npm:0.27.2" +"@esbuild/openbsd-arm64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/openbsd-arm64@npm:0.25.4" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/openbsd-arm64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/openbsd-arm64@npm:0.27.0" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard @@ -2397,16 +2519,23 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/openbsd-x64@npm:0.27.2" +"@esbuild/openbsd-x64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/openbsd-x64@npm:0.25.4" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openharmony-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/openharmony-arm64@npm:0.27.2" +"@esbuild/openbsd-x64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/openbsd-x64@npm:0.27.0" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openharmony-arm64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/openharmony-arm64@npm:0.27.0" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard @@ -2418,9 +2547,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/sunos-x64@npm:0.27.2" +"@esbuild/sunos-x64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/sunos-x64@npm:0.25.4" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/sunos-x64@npm:0.27.0" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -2432,9 +2568,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/win32-arm64@npm:0.27.2" +"@esbuild/win32-arm64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/win32-arm64@npm:0.25.4" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/win32-arm64@npm:0.27.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -2446,9 +2589,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/win32-ia32@npm:0.27.2" +"@esbuild/win32-ia32@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/win32-ia32@npm:0.25.4" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/win32-ia32@npm:0.27.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -2460,9 +2610,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/win32-x64@npm:0.27.2" +"@esbuild/win32-x64@npm:0.25.4": + version: 0.25.4 + resolution: "@esbuild/win32-x64@npm:0.25.4" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.27.0": + version: 0.27.0 + resolution: "@esbuild/win32-x64@npm:0.27.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2549,10 +2706,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.39.2": - version: 9.39.2 - resolution: "@eslint/js@npm:9.39.2" - checksum: 10c0/00f51c52b04ac79faebfaa65a9652b2093b9c924e945479f1f3945473f78aee83cbc76c8d70bbffbf06f7024626575b16d97b66eab16182e1d0d39daff2f26f5 +"@eslint/js@npm:9.39.1": + version: 9.39.1 + resolution: "@eslint/js@npm:9.39.1" + checksum: 10c0/6f7f26f8cdb7ad6327bbf9741973b6278eb946f18f70e35406e88194b0d5c522d0547a34a02f2a208eec95c5d1388cdf7ccb20039efd2e4cb6655615247a50f1 languageName: node linkType: hard @@ -2597,16 +2754,16 @@ __metadata: languageName: node linkType: hard -"@gerrit0/mini-shiki@npm:^3.17.0": - version: 3.21.0 - resolution: "@gerrit0/mini-shiki@npm:3.21.0" +"@gerrit0/mini-shiki@npm:^3.12.0": + version: 3.15.0 + resolution: "@gerrit0/mini-shiki@npm:3.15.0" dependencies: - "@shikijs/engine-oniguruma": "npm:^3.21.0" - "@shikijs/langs": "npm:^3.21.0" - "@shikijs/themes": "npm:^3.21.0" - "@shikijs/types": "npm:^3.21.0" + "@shikijs/engine-oniguruma": "npm:^3.15.0" + "@shikijs/langs": "npm:^3.15.0" + "@shikijs/themes": "npm:^3.15.0" + "@shikijs/types": "npm:^3.15.0" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10c0/4045d19854abfa4515381a04af07096c1de07471b029ee090375652d0199ed3fed6165a22bd9f8e8250c609124d8c05f5d4604eb6de87cf13513aa89cfb8d14e + checksum: 10c0/8d0d9591267a634a09a8d1abafa92d6fc83385470ff008945b2f370223eb91682d6356e13481499bf824c42ae4b4393cfa16c30103c52161ec25a9559e39c87b languageName: node linkType: hard @@ -2648,12 +2805,12 @@ __metadata: languageName: node linkType: hard -"@iconify-json/logos@npm:^1.2.10": - version: 1.2.10 - resolution: "@iconify-json/logos@npm:1.2.10" +"@iconify-json/logos@npm:^1.2.9": + version: 1.2.9 + resolution: "@iconify-json/logos@npm:1.2.9" dependencies: "@iconify/types": "npm:*" - checksum: 10c0/0d9722cfd1bf333e3b1fe164b4e148d3420f8e809c392dad79846e16f336eef33e18cd6b18c09d38f8d4d4854892b1a8c19a334bb7a4e3d36d1825c1669cc6e9 + checksum: 10c0/7f5e2c8026560fb63489566cfc90497375543ca3649e7c7d13079f0a166dc4a738cf5686ec66a4cb9a319b8213303bc7c5ae74070e88d4bf0e5c1ef57cb3bacc languageName: node linkType: hard @@ -2666,12 +2823,12 @@ __metadata: languageName: node linkType: hard -"@iconify-json/vscode-icons@npm:^1.2.39": - version: 1.2.40 - resolution: "@iconify-json/vscode-icons@npm:1.2.40" +"@iconify-json/vscode-icons@npm:^1.2.32": + version: 1.2.33 + resolution: "@iconify-json/vscode-icons@npm:1.2.33" dependencies: "@iconify/types": "npm:*" - checksum: 10c0/29dce75c16279709cffac19bfffb0d80b19046bc5ffedb172dd00a3d80f34d741ee2b8aacbc053ac8f59f6f9ce066e6e76fd649743d68aa503cb7605432ec091 + checksum: 10c0/b55c3b263643d08a5e7ef9d35e1dd63c11c911b86e344cfaa8e7fe639bdbf5940ca4164d05f2ec5de89627c934bec4e93a4be480be2c3bcc3ade9c57fd119073 languageName: node linkType: hard @@ -2682,7 +2839,7 @@ __metadata: languageName: node linkType: hard -"@iconify/utils@npm:^3.0.1": +"@iconify/utils@npm:^3.0.1, @iconify/utils@npm:^3.0.2": version: 3.0.2 resolution: "@iconify/utils@npm:3.0.2" dependencies: @@ -2698,33 +2855,6 @@ __metadata: languageName: node linkType: hard -"@iconify/utils@npm:^3.1.0": - version: 3.1.0 - resolution: "@iconify/utils@npm:3.1.0" - dependencies: - "@antfu/install-pkg": "npm:^1.1.0" - "@iconify/types": "npm:^2.0.0" - mlly: "npm:^1.8.0" - checksum: 10c0/a39445e892b248486c186306e1ccba4b07ed1d5b21b143ddf279b33062063173feb84954b9a82e05713b927872787d6c0081073d23f55c44294de37615d4a1f7 - languageName: node - linkType: hard - -"@isaacs/balanced-match@npm:^4.0.1": - version: 4.0.1 - resolution: "@isaacs/balanced-match@npm:4.0.1" - checksum: 10c0/7da011805b259ec5c955f01cee903da72ad97c5e6f01ca96197267d3f33103d5b2f8a1af192140f3aa64526c593c8d098ae366c2b11f7f17645d12387c2fd420 - languageName: node - linkType: hard - -"@isaacs/brace-expansion@npm:^5.0.1": - version: 5.0.1 - resolution: "@isaacs/brace-expansion@npm:5.0.1" - dependencies: - "@isaacs/balanced-match": "npm:^4.0.1" - checksum: 10c0/e5d67c7bbf1f17b88132a35bc638af306d48acbb72810d48fa6e6edd8ab375854773108e8bf70f021f7ef6a8273455a6d1f0c3b5aa2aff06ce7894049ab77fb8 - languageName: node - linkType: hard - "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -2739,13 +2869,6 @@ __metadata: languageName: node linkType: hard -"@isaacs/cliui@npm:^9.0.0": - version: 9.0.0 - resolution: "@isaacs/cliui@npm:9.0.0" - checksum: 10c0/971063b7296419f85053dacd0a0285dcadaa3dfc139228b23e016c1a9848121ad4aa5e7fcca7522062014e1eb6239a7424188b9f2cba893a79c90aae5710319c - languageName: node - linkType: hard - "@isaacs/fs-minipass@npm:^4.0.0": version: 4.0.1 resolution: "@isaacs/fs-minipass@npm:4.0.1" @@ -2993,6 +3116,17 @@ __metadata: languageName: node linkType: hard +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.12 + resolution: "@napi-rs/wasm-runtime@npm:0.2.12" + dependencies: + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.10.0" + checksum: 10c0/6d07922c0613aab30c6a497f4df297ca7c54e5b480e00035e0209b872d5c6aab7162fc49477267556109c2c7ed1eb9c65a174e27e9b87568106a87b0a6e3ca7d + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -3702,10 +3836,10 @@ __metadata: languageName: node linkType: hard -"@rolldown/pluginutils@npm:1.0.0-rc.2": - version: 1.0.0-rc.2 - resolution: "@rolldown/pluginutils@npm:1.0.0-rc.2" - checksum: 10c0/35d3dec35e00ab090d5ff8287e27af98a15da897dc8b034fe0e00d03e0931b9e993603c054be9e8925e2bde040c44c18b48cb8aeea6a261fd1c8f46837038927 +"@rolldown/pluginutils@npm:1.0.0-beta.47": + version: 1.0.0-beta.47 + resolution: "@rolldown/pluginutils@npm:1.0.0-beta.47" + checksum: 10c0/eb0cfa7334d66f090c47eaac612174936b05f26e789352428cb6e03575b590f355de30d26b42576ea4e613d8887b587119d19b2e4b3a8909ceb232ca1cf746c8 languageName: node linkType: hard @@ -3916,6 +4050,18 @@ __metadata: languageName: node linkType: hard +"@shikijs/core@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/core@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + "@types/hast": "npm:^3.0.4" + hast-util-to-html: "npm:^9.0.5" + checksum: 10c0/3df490754e631bf71723aec921de623d0e464c868bccafda89cdb1f061b968ee56385f5709d7401213773dc0c36d9650db436492bd2fa13eac4cf50255f12d26 + languageName: node + linkType: hard + "@shikijs/engine-javascript@npm:2.5.0": version: 2.5.0 resolution: "@shikijs/engine-javascript@npm:2.5.0" @@ -3927,6 +4073,17 @@ __metadata: languageName: node linkType: hard +"@shikijs/engine-javascript@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/engine-javascript@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + oniguruma-to-es: "npm:^4.3.4" + checksum: 10c0/52ee46eba86bd0e4f5ca9520736a17e5a052830685edb319d77a2929ca30bcd176353212b9978d680109fd93d7e13c9ad5b039b69223d817a6331fc9f88389f2 + languageName: node + linkType: hard + "@shikijs/engine-oniguruma@npm:2.5.0": version: 2.5.0 resolution: "@shikijs/engine-oniguruma@npm:2.5.0" @@ -3937,13 +4094,23 @@ __metadata: languageName: node linkType: hard -"@shikijs/engine-oniguruma@npm:^3.21.0": - version: 3.21.0 - resolution: "@shikijs/engine-oniguruma@npm:3.21.0" +"@shikijs/engine-oniguruma@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/engine-oniguruma@npm:3.20.0" dependencies: - "@shikijs/types": "npm:3.21.0" + "@shikijs/types": "npm:3.20.0" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10c0/cb17c034b04e1333f90f267081b7fac0b53e56031f7d067723363a72cdbdf79e567dea216bbcae38a6d4b910570c2dd60a953ca941f4834768c0bb721131af5f + checksum: 10c0/4a5a8f316a8482e799cd836c8e3f8ba83274b3631b2d66ec82ad839b0ee1dd3df50a08480f791d59f22e42bf6b707032f043a9f651445efc04e59b7ec9e669c9 + languageName: node + linkType: hard + +"@shikijs/engine-oniguruma@npm:^3.15.0": + version: 3.15.0 + resolution: "@shikijs/engine-oniguruma@npm:3.15.0" + dependencies: + "@shikijs/types": "npm:3.15.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + checksum: 10c0/97cb43d1f3fbace9f5412e516ab87ad38b529550bb696891a518efcefa32680a0b625a17e1fe8db6cf2b1e6e252db7ac408e3294375ec0600a9b07e4e482ca7c languageName: node linkType: hard @@ -3956,12 +4123,21 @@ __metadata: languageName: node linkType: hard -"@shikijs/langs@npm:^3.21.0": - version: 3.21.0 - resolution: "@shikijs/langs@npm:3.21.0" +"@shikijs/langs@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/langs@npm:3.20.0" dependencies: - "@shikijs/types": "npm:3.21.0" - checksum: 10c0/79cfc2b8ac1f5c938bfb18db6233f86ca96948970068c2cc94559e30abac2036c35a2ae52015d07f72b6decfd6b2ae86321f9547ae0f994b6131e362781fbf1f + "@shikijs/types": "npm:3.20.0" + checksum: 10c0/6830460025d0df4c527ffeacf0a78cd4331ffde1cfcd1e8028aa9814be8a4cea84367dd938528a9b55de72b163c58ad3576915ea08c3d0a29ef1dc80e120116c + languageName: node + linkType: hard + +"@shikijs/langs@npm:^3.15.0": + version: 3.15.0 + resolution: "@shikijs/langs@npm:3.15.0" + dependencies: + "@shikijs/types": "npm:3.15.0" + checksum: 10c0/d5a328ec999572f50e4fec77213e7d0f106c90c04e078be29cdb2467f10012221d52435fd9711f963ce30adbf14805d2a31a2e602fa7a074fa450bbf83553eca languageName: node linkType: hard @@ -3974,12 +4150,21 @@ __metadata: languageName: node linkType: hard -"@shikijs/themes@npm:^3.21.0": - version: 3.21.0 - resolution: "@shikijs/themes@npm:3.21.0" +"@shikijs/themes@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/themes@npm:3.20.0" + dependencies: + "@shikijs/types": "npm:3.20.0" + checksum: 10c0/d6fc059c51c3c0694e026cc1f80eed927d9b91adaeda0fb3fd5725eabc6d066aaf022919def435245446ae91e3da541ed6d88d875cf59a35bfbabb6920efb6da + languageName: node + linkType: hard + +"@shikijs/themes@npm:^3.15.0": + version: 3.15.0 + resolution: "@shikijs/themes@npm:3.15.0" dependencies: - "@shikijs/types": "npm:3.21.0" - checksum: 10c0/f128a874231d84d93e16f347557e844c2b6493b41196b52e36a79874598abe2dbf3ee981dfe52dd09f8d7e21ed4ff41ab03c28de7a21313d9a0b691fbd3690c0 + "@shikijs/types": "npm:3.15.0" + checksum: 10c0/2b6a435d991d1fd924622e437c5546ecc5ab3d5c0843edbe2ca444e4e91a9c4d8d9c0a673a32afdb1c262dffcd7839518a9f9154121be8dfa7553f99458d9bab languageName: node linkType: hard @@ -4003,23 +4188,33 @@ __metadata: languageName: node linkType: hard -"@shikijs/types@npm:3.21.0": - version: 3.21.0 - resolution: "@shikijs/types@npm:3.21.0" +"@shikijs/types@npm:3.15.0": + version: 3.15.0 + resolution: "@shikijs/types@npm:3.15.0" dependencies: "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" - checksum: 10c0/a86038c7ad10bb8104ea07cfa0dddf1e0646cf3b70a382978939c6144b21e5891395f5e705b7393476320f6196d86c6d8cd7ad6b3e1b356eb6a7e40c298c98f3 + checksum: 10c0/bc18c7e8b83fbf73f88a26dcf06e777566f8d8568a26ace4dacf5373c51e95213af1181eb389c4d0d7dc57c21824396278d6cbebf57a905676923bfdab00bb23 + languageName: node + linkType: hard + +"@shikijs/types@npm:3.20.0": + version: 3.20.0 + resolution: "@shikijs/types@npm:3.20.0" + dependencies: + "@shikijs/vscode-textmate": "npm:^10.0.2" + "@types/hast": "npm:^3.0.4" + checksum: 10c0/7faea130362a6cdf3d66fcb47d6b609a8e0209e76ba86688f56a65411b6ae400a37414cd1a3a2fe1ee3fe39f18e274585d3972129c7e79244aaa0c15bc8f1c21 languageName: node linkType: hard -"@shikijs/types@npm:^3.15.0, @shikijs/types@npm:^3.21.0": - version: 3.22.0 - resolution: "@shikijs/types@npm:3.22.0" +"@shikijs/types@npm:^3.15.0": + version: 3.21.0 + resolution: "@shikijs/types@npm:3.21.0" dependencies: "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" - checksum: 10c0/68e5bb1827609fc026cba5a88442f41dd948f68fc4f23de0912ef2498944116471b543a5f40ab4ff2c2056399873c755fe717185fd4f8c928002fba934bd3a7b + checksum: 10c0/a86038c7ad10bb8104ea07cfa0dddf1e0646cf3b70a382978939c6144b21e5891395f5e705b7393476320f6196d86c6d8cd7ad6b3e1b356eb6a7e40c298c98f3 languageName: node linkType: hard @@ -4044,9 +4239,9 @@ __metadata: languageName: node linkType: hard -"@snyk/dep-graph@npm:^2.12.0": - version: 2.12.1 - resolution: "@snyk/dep-graph@npm:2.12.1" +"@snyk/dep-graph@npm:^2.3.0": + version: 2.9.0 + resolution: "@snyk/dep-graph@npm:2.9.0" dependencies: event-loop-spinner: "npm:^2.1.0" lodash.clone: "npm:^4.5.0" @@ -4064,10 +4259,10 @@ __metadata: lodash.union: "npm:^4.6.0" lodash.values: "npm:^4.3.0" object-hash: "npm:^3.0.0" - packageurl-js: "npm:2.0.1" + packageurl-js: "npm:1.2.0" semver: "npm:^7.0.0" tslib: "npm:^2" - checksum: 10c0/1d9c9ba1c356f24135d7b8da19bdbd09068521eafa84f173bdd18a2ba6678038feea9df253e5df53eb31ffa853b3345e9f8d2649995d34f31bc32ddf621173e1 + checksum: 10c0/709116c589216b130e51bc7750bb9151ec382f749a9ccb124950a4390f6bb470e42cb6e64b56a8bff35602056685a97b66eda0b2eee2584f759d1e046293cb6e languageName: node linkType: hard @@ -4136,7 +4331,7 @@ __metadata: resolution: "@sourceacademy/bundle-binary_tree@workspace:src/bundles/binary_tree" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4172,6 +4367,7 @@ __metadata: "@jscad/stl-serializer": "npm:2.1.11" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" + js-slang: "npm:^1.0.85" save-file: "npm:^2.3.1" typescript: "npm:^5.8.2" languageName: unknown @@ -4184,7 +4380,7 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" gl-matrix: "npm:^3.3.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4194,7 +4390,7 @@ __metadata: resolution: "@sourceacademy/bundle-game@workspace:src/bundles/game" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" phaser: "npm:^3.54.0" typescript: "npm:^5.8.2" languageName: unknown @@ -4214,7 +4410,7 @@ __metadata: resolution: "@sourceacademy/bundle-midi@workspace:src/bundles/midi" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4262,13 +4458,13 @@ __metadata: dependencies: "@sourceacademy/modules-buildtools": "workspace:^" "@types/react": "npm:^18.3.1" - "@vitest/browser-playwright": "npm:^4.0.4" + "@vitest/browser-playwright": "npm:^4.0.18" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" typescript: "npm:^5.8.2" - vitest: "npm:^4.0.4" - vitest-browser-react: "npm:^2.0.2" + vitest: "npm:^4.0.18" + vitest-browser-react: "npm:^2.0.4" languageName: unknown linkType: soft @@ -4280,7 +4476,7 @@ __metadata: "@sourceacademy/bundle-sound": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@types/plotly.js": "npm:^3.0.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" plotly.js-dist: "npm:^3.0.0" typescript: "npm:^5.8.2" languageName: unknown @@ -4291,7 +4487,7 @@ __metadata: resolution: "@sourceacademy/bundle-remote_execution@workspace:src/bundles/remote_execution" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4310,7 +4506,7 @@ __metadata: resolution: "@sourceacademy/bundle-repl@workspace:src/bundles/repl" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4323,6 +4519,7 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/three": "npm:^0.181.0" + js-slang: "npm:^1.0.85" three: "npm:^0.181.0" typescript: "npm:^5.8.2" languageName: unknown @@ -4334,8 +4531,10 @@ __metadata: dependencies: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" + "@types/lodash": "npm:^4.14.198" gl-matrix: "npm:^3.3.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" + lodash: "npm:^4.17.23" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4365,7 +4564,7 @@ __metadata: "@sourceacademy/bundle-midi": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4375,7 +4574,7 @@ __metadata: resolution: "@sourceacademy/bundle-sound_matrix@workspace:src/bundles/sound_matrix" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4386,7 +4585,7 @@ __metadata: dependencies: "@sourceacademy/bundle-midi": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown linkType: soft @@ -4397,7 +4596,7 @@ __metadata: dependencies: "@sourceacademy/modules-buildtools": "workspace:^" "@types/lodash": "npm:^4.14.198" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" lodash: "npm:^4.17.23" typescript: "npm:^5.8.2" languageName: unknown @@ -4407,8 +4606,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/bundle-unity_academy@workspace:src/bundles/unity_academy" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" @@ -4437,9 +4636,9 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-repotools": "workspace:^" "@stylistic/eslint-plugin": "npm:^5.0.0" - "@typescript-eslint/rule-tester": "npm:^8.39.0" - "@typescript-eslint/utils": "npm:^8.39.0" - "@vitest/eslint-plugin": "npm:^1.3.4" + "@typescript-eslint/rule-tester": "npm:^8.53.1" + "@typescript-eslint/utils": "npm:^8.53.1" + "@vitest/eslint-plugin": "npm:^1.6.6" eslint: "npm:^9.35.0" eslint-plugin-import: "npm:^2.32.0" eslint-plugin-jsdoc: "npm:^62.0.0" @@ -4447,7 +4646,7 @@ __metadata: eslint-plugin-react-hooks: "npm:^5.1.0" globals: "npm:^17.0.0" typescript: "npm:^5.8.2" - typescript-eslint: "npm:^8.33.1" + typescript-eslint: "npm:^8.53.1" peerDependencies: "@eslint/markdown": ^6.6.0 "@stylistic/eslint-plugin": ^4.4.1 @@ -4466,12 +4665,12 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/markdown-plugin-directory-tree@workspace:lib/markdown-tree" dependencies: - "@shikijs/types": "npm:^3.15.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-repotools": "workspace:^" "@types/lodash": "npm:^4.14.198" "@types/markdown-it": "npm:^14.1.2" lodash: "npm:^4.17.23" + shiki: "npm:^3.15.0" tm-themes: "npm:^1.10.12" typescript: "npm:^5.8.2" yaml: "npm:^2.8.0" @@ -4492,9 +4691,10 @@ __metadata: "@types/lodash": "npm:^4.14.198" "@types/node": "npm:^22.15.30" "@vitejs/plugin-react": "npm:^5.1.0" - "@vitest/browser-playwright": "npm:^4.0.4" - "@vitest/coverage-v8": "npm:^4.0.4" + "@vitest/browser-playwright": "npm:^4.0.18" + "@vitest/coverage-v8": "npm:^4.0.18" acorn: "npm:^8.8.1" + acorn-typescript: "npm:^1.4.13" astring: "npm:^1.8.6" chalk: "npm:^5.0.1" commander: "npm:^14.0.0" @@ -4506,7 +4706,7 @@ __metadata: typedoc: "npm:^0.28.9" typescript: "npm:^5.8.2" vite: "npm:^7.1.11" - vitest: "npm:^4.0.4" + vitest: "npm:^4.0.18" bin: buildtools: ./dist/index.js languageName: unknown @@ -4516,20 +4716,20 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/modules-devserver@workspace:devserver" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@commander-js/extra-typings": "npm:^14.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" "@vitejs/plugin-react": "npm:^5.1.0" - "@vitest/browser-playwright": "npm:^4.0.4" + "@vitest/browser-playwright": "npm:^4.0.18" ace-builds: "npm:^1.25.1" classnames: "npm:^2.3.1" commander: "npm:^14.0.0" eslint: "npm:^9.35.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" playwright: "npm:^1.55.1" re-resizable: "npm:^6.9.11" react: "npm:^18.3.1" @@ -4539,8 +4739,8 @@ __metadata: typescript: "npm:^5.8.2" vite: "npm:^7.1.11" vite-plugin-node-polyfills: "npm:^0.25.0" - vitest: "npm:^4.0.4" - vitest-browser-react: "npm:^2.0.2" + vitest: "npm:^4.0.18" + vitest-browser-react: "npm:^2.0.4" bin: devserver: ./bin.js languageName: unknown @@ -4570,11 +4770,12 @@ __metadata: "@actions/core": "npm:^1.11.1" "@actions/exec": "npm:^1.1.1" "@sourceacademy/modules-repotools": "workspace:^" + "@types/lodash": "npm:^4.14.198" "@types/node": "npm:^22.15.30" lodash: "npm:^4.17.23" snyk-nodejs-lockfile-parser: "npm:^2.4.2" typescript: "npm:^5.8.2" - vitest: "npm:^4.0.4" + vitest: "npm:^4.0.18" languageName: unknown linkType: soft @@ -4582,15 +4783,17 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/modules-lib@workspace:lib/modules-lib" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" + "@types/lodash": "npm:^4.14.198" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" "@vitejs/plugin-react": "npm:^5.1.0" - "@vitest/browser-playwright": "npm:^4.0.4" + "@vitest/browser-playwright": "npm:^4.0.18" eslint: "npm:^9.35.0" - js-slang: "npm:^1.0.81" + js-slang: "npm:^1.0.85" + lodash: "npm:^4.17.23" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" @@ -4599,8 +4802,8 @@ __metadata: typedoc-plugin-markdown: "npm:^4.7.0" typedoc-plugin-rename-defaults: "npm:^0.7.3" typescript: "npm:^5.8.2" - vitest: "npm:^4.0.4" - vitest-browser-react: "npm:^2.0.2" + vitest: "npm:^4.0.18" + vitest-browser-react: "npm:^2.0.4" languageName: unknown linkType: soft @@ -4612,16 +4815,16 @@ __metadata: "@types/lodash": "npm:^4.14.198" "@types/node": "npm:^22.15.30" "@vitejs/plugin-react": "npm:^5.1.0" - "@vitest/browser-playwright": "npm:^4.0.4" - "@vitest/coverage-v8": "npm:^4.0.4" + "@vitest/browser-playwright": "npm:^4.0.18" + "@vitest/coverage-v8": "npm:^4.0.18" chalk: "npm:^5.0.1" commander: "npm:^14.0.0" esbuild: "npm:^0.27.0" jsonschema: "npm:^1.5.0" lodash: "npm:^4.17.23" typescript: "npm:^5.8.2" - vitest: "npm:^4.0.4" - vitest-browser-react: "npm:^2.0.2" + vitest: "npm:^4.0.18" + vitest-browser-react: "npm:^2.0.4" peerDependencies: "@vitejs/plugin-react": "*" vitest-browser-react: "*" @@ -4641,11 +4844,12 @@ __metadata: "@types/node": "npm:^22.15.30" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" - "@vitest/coverage-v8": "npm:^4.0.4" - "@vitest/eslint-plugin": "npm:^1.3.4" + "@vitest/coverage-v8": "npm:^4.0.18" + "@vitest/eslint-plugin": "npm:^1.6.6" "@yarnpkg/types": "npm:^4.0.1" esbuild: "npm:^0.27.0" eslint: "npm:^9.35.0" + eslint-import-resolver-typescript: "npm:^4.4.4" eslint-plugin-import: "npm:^2.32.0" eslint-plugin-jsdoc: "npm:^62.0.0" eslint-plugin-mdx: "npm:^3.6.2" @@ -4653,16 +4857,19 @@ __metadata: eslint-plugin-react-hooks: "npm:^5.1.0" eslint-plugin-yml: "npm:^1.19.0" husky: "npm:^9.1.7" - js-slang: "npm:^1.0.81" jsdom: "npm:^26.1.0" jsonc-eslint-parser: "npm:^2.4.0" - lodash: "npm:^4.17.23" - react: "npm:^18.3.1" - react-dom: "npm:^18.3.1" typescript: "npm:^5.8.2" - typescript-eslint: "npm:^8.33.1" - vitest: "npm:^4.0.4" - vitest-browser-react: "npm:^2.0.2" + typescript-eslint: "npm:^8.53.1" + vitest: "npm:^4.0.18" + vitest-browser-react: "npm:^2.0.4" + peerDependencies: + "@blueprintjs/core": ^6.0.0 + "@blueprintjs/icons": ^6.0.0 + js-slang: ^1.0.85 + lodash: ^4.17.23 + react: ^18.3.1 + react-dom: ^18.3.1 languageName: unknown linkType: soft @@ -4670,8 +4877,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-ArcadeTwod@workspace:src/tabs/ArcadeTwod" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" @@ -4686,7 +4893,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-AugmentedReality@workspace:src/tabs/AugmentedReality" dependencies: - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-ar": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4702,6 +4909,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-CopyGc@workspace:src/tabs/CopyGc" dependencies: + "@blueprintjs/core": "npm:^6.0.0" "@sourceacademy/bundle-copy_gc": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4716,8 +4924,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Csg@workspace:src/tabs/Csg" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-csg": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4732,20 +4940,20 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Curve@workspace:src/tabs/Curve" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-curve": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1" - "@vitest/browser-playwright": "npm:^4.0.4" - "@vitest/coverage-v8": "npm:^4.0.4" + "@vitest/browser-playwright": "npm:^4.0.18" + "@vitest/coverage-v8": "npm:^4.0.18" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" - vitest: "npm:^4.0.4" - vitest-browser-react: "npm:^2.0.2" + vitest: "npm:^4.0.18" + vitest-browser-react: "npm:^2.0.4" languageName: unknown linkType: soft @@ -4765,6 +4973,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-MarkSweep@workspace:src/tabs/MarkSweep" dependencies: + "@blueprintjs/core": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" @@ -4777,6 +4986,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Nbody@workspace:src/tabs/Nbody" dependencies: + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/plotly.js": "npm:^2.35.4" @@ -4808,6 +5019,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Physics2D@workspace:src/tabs/Physics2D" dependencies: + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@box2d/debug-draw": "npm:^0.10.0" "@sourceacademy/bundle-physics_2d": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" @@ -4822,6 +5035,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Pixnflix@workspace:src/tabs/Pixnflix" dependencies: + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-pix_n_flix": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4860,6 +5075,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-Repl@workspace:src/tabs/Repl" dependencies: + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-repl": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4876,6 +5093,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-RobotSimulation@workspace:src/tabs/RobotSimulation" dependencies: + "@blueprintjs/core": "npm:^6.0.0" "@dimforge/rapier3d-compat": "npm:^0.11.2" "@sourceacademy/bundle-robot_simulation": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" @@ -4894,12 +5112,13 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" - "@vitest/browser-playwright": "npm:^4.0.4" + "@vitest/browser-playwright": "npm:^4.0.18" + lodash: "npm:^4.17.23" playwright: "npm:^1.55.1" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" - vitest: "npm:^4.0.4" - vitest-browser-react: "npm:^2.0.2" + vitest: "npm:^4.0.18" + vitest-browser-react: "npm:^2.0.4" languageName: unknown linkType: soft @@ -4920,6 +5139,7 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-SoundMatrix@workspace:src/tabs/SoundMatrix" dependencies: + "@blueprintjs/core": "npm:^6.0.0" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" @@ -4961,8 +5181,8 @@ __metadata: version: 0.0.0-use.local resolution: "@sourceacademy/tab-UnityAcademy@workspace:src/tabs/UnityAcademy" dependencies: - "@blueprintjs/core": "npm:^5.10.2" - "@blueprintjs/icons": "npm:^5.9.0" + "@blueprintjs/core": "npm:^6.0.0" + "@blueprintjs/icons": "npm:^6.0.0" "@sourceacademy/bundle-unity_academy": "workspace:^" "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" @@ -4979,11 +5199,11 @@ __metadata: dependencies: "@types/istanbul-lib-report": "npm:^3.0.3" "@types/node": "npm:^22.15.30" - "@vitest/coverage-v8": "npm:^4.0.4" + "@vitest/coverage-v8": "npm:^4.0.18" esbuild: "npm:^0.27.0" istanbul-lib-report: "npm:^3.0.1" typescript: "npm:^5.8.2" - vitest: "npm:^4.0.4" + vitest: "npm:^4.0.18" languageName: unknown linkType: soft @@ -5047,6 +5267,15 @@ __metadata: languageName: node linkType: hard +"@tybys/wasm-util@npm:^0.10.0": + version: 0.10.1 + resolution: "@tybys/wasm-util@npm:0.10.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/b255094f293794c6d2289300c5fbcafbb5532a3aed3a5ffd2f8dc1828e639b88d75f6a376dd8f94347a44813fd7a7149d8463477a9a49525c8b2dcaa38c2d1e8 + languageName: node + linkType: hard + "@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.7, @types/babel__core@npm:^7.20.5": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" @@ -5549,9 +5778,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.198": - version: 4.17.23 - resolution: "@types/lodash@npm:4.17.23" - checksum: 10c0/9d9cbfb684e064a2b78aab9e220d398c9c2a7d36bc51a07b184ff382fa043a99b3d00c16c7f109b4eb8614118f4869678dbae7d5c6700ed16fb9340e26cc0bf6 + version: 4.17.20 + resolution: "@types/lodash@npm:4.17.20" + checksum: 10c0/98cdd0faae22cbb8079a01a3bb65aa8f8c41143367486c1cbf5adc83f16c9272a2a5d2c1f541f61d0d73da543c16ee1d21cf2ef86cb93cd0cc0ac3bced6dd88f languageName: node linkType: hard @@ -5589,20 +5818,20 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 25.2.1 - resolution: "@types/node@npm:25.2.1" + version: 24.10.1 + resolution: "@types/node@npm:24.10.1" dependencies: undici-types: "npm:~7.16.0" - checksum: 10c0/ce42fa07495093c55b6398e3c4346d644a61b8c4f59d2e0c0ed152ea0e4327c60a41d5fdfa3e0fc4f4776eb925e2b783b6b942501fc044328a44980bc2de4dc6 + checksum: 10c0/d6bca7a78f550fbb376f236f92b405d676003a8a09a1b411f55920ef34286ee3ee51f566203920e835478784df52662b5b2af89159d9d319352e9ea21801c002 languageName: node linkType: hard "@types/node@npm:^22.0.0, @types/node@npm:^22.15.30": - version: 22.19.9 - resolution: "@types/node@npm:22.19.9" + version: 22.19.1 + resolution: "@types/node@npm:22.19.1" dependencies: undici-types: "npm:~6.21.0" - checksum: 10c0/7a15c8f6c5e3ce000f5e3589f6e30d3296899fb9f6bf502057d105e19b20e70ca560b4526e032cc6187524aee5593c0a092c21c23845d19dd3185977c83582f3 + checksum: 10c0/6edd93aea86da740cb7872626839cd6f4a67a049d3a3a6639cb592c620ec591408a30989ab7410008d1a0b2d4985ce50f1e488e79c033e4476d3bec6833b0a2f languageName: node linkType: hard @@ -5621,9 +5850,9 @@ __metadata: linkType: hard "@types/plotly.js@npm:^3.0.0": - version: 3.0.9 - resolution: "@types/plotly.js@npm:3.0.9" - checksum: 10c0/8f5aa3cc96f6351e978d491356407e69cd417f6fc64df458cb90a5e382515b37e61dff7fe7416ed7d8ad2f3cdbbe1d7c1629d184bcf33e00111c39b3dce0b28e + version: 3.0.8 + resolution: "@types/plotly.js@npm:3.0.8" + checksum: 10c0/7b8b26a07c8fb863ab1950089eb5c6f67896d65628409f17ab1beaf0a0ffa338cb2171aec108b2460205267ad65e67b10e739f8f74fbf476229202d4487d869b languageName: node linkType: hard @@ -5662,21 +5891,21 @@ __metadata: linkType: hard "@types/react@npm:*": - version: 19.2.13 - resolution: "@types/react@npm:19.2.13" + version: 19.2.2 + resolution: "@types/react@npm:19.2.2" dependencies: - csstype: "npm:^3.2.2" - checksum: 10c0/e512dc53b805b9066f5c6ad42944372e1204290d618dbaec634d8bbd80d3aadcc1b8cdd7251329936bbdafae0425c02f531083213473bb370df903f20bb66e91 + csstype: "npm:^3.0.2" + checksum: 10c0/f830b1204aca4634ce3c6cb3477b5d3d066b80a4dd832a4ee0069acb504b6debd2416548a43a11c1407c12bc60e2dc6cf362934a18fe75fe06a69c0a98cba8ab languageName: node linkType: hard "@types/react@npm:^18.3.1": - version: 18.3.28 - resolution: "@types/react@npm:18.3.28" + version: 18.3.26 + resolution: "@types/react@npm:18.3.26" dependencies: "@types/prop-types": "npm:*" - csstype: "npm:^3.2.2" - checksum: 10c0/683e19cd12b5c691215529af2e32b5ffbaccae3bf0ba93bfafa0e460e8dfee18423afed568be2b8eadf4b837c3749dd296a4f64e2d79f68fa66962c05f5af661 + csstype: "npm:^3.0.2" + checksum: 10c0/7b62d91c33758f14637311921c92db6045b6328e2300666a35ef8130d06385e39acada005eaf317eee93228edc10ea5f0cd34a0385654d2014d24699a65bfeef languageName: node linkType: hard @@ -5817,83 +6046,86 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.54.0" +"@typescript-eslint/eslint-plugin@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/eslint-plugin@npm:8.53.1" dependencies: "@eslint-community/regexpp": "npm:^4.12.2" - "@typescript-eslint/scope-manager": "npm:8.54.0" - "@typescript-eslint/type-utils": "npm:8.54.0" - "@typescript-eslint/utils": "npm:8.54.0" - "@typescript-eslint/visitor-keys": "npm:8.54.0" + "@typescript-eslint/scope-manager": "npm:8.53.1" + "@typescript-eslint/type-utils": "npm:8.53.1" + "@typescript-eslint/utils": "npm:8.53.1" + "@typescript-eslint/visitor-keys": "npm:8.53.1" ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" ts-api-utils: "npm:^2.4.0" peerDependencies: - "@typescript-eslint/parser": ^8.54.0 + "@typescript-eslint/parser": ^8.53.1 eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/e533c8285880b883e02a833f378597c2776e6b0c20a5935440e2a02c1c42f40069a8badcf6d581bb4ec35a6856a806c4b66674c1c15c33cd64cc6b9c0cdd1dad + checksum: 10c0/d24e41d0117ef841cc05e4c52d33277de2e57981fa38412f93034082a3467f804201c180f1baca9f967388c7e5965ffcc61e445cf726a0064b8ed71a84f59aa2 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/parser@npm:8.54.0" +"@typescript-eslint/parser@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/parser@npm:8.53.1" dependencies: - "@typescript-eslint/scope-manager": "npm:8.54.0" - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/typescript-estree": "npm:8.54.0" - "@typescript-eslint/visitor-keys": "npm:8.54.0" + "@typescript-eslint/scope-manager": "npm:8.53.1" + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" + "@typescript-eslint/visitor-keys": "npm:8.53.1" debug: "npm:^4.4.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/60a1cfe94bc23086f03701640f4d83d7e37b8f4d729011e0f029e5accf2b3d099c50938c0a798a399e86046279432ff663f33102ba4338c4c82f7acead2bcbac + checksum: 10c0/fb7602dc3ea45b838f4da2d0173161b222442ed2007487dfce57d6ce24ff16606ec99de9eb6ac114a815e11a47248303d941dca1a7bf13f70350372cee509886 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/project-service@npm:8.54.0" +"@typescript-eslint/project-service@npm:8.52.0": + version: 8.52.0 + resolution: "@typescript-eslint/project-service@npm:8.52.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.54.0" - "@typescript-eslint/types": "npm:^8.54.0" + "@typescript-eslint/tsconfig-utils": "npm:^8.52.0" + "@typescript-eslint/types": "npm:^8.52.0" debug: "npm:^4.4.3" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/3392ae259199021a80616a44d9484d1c363f61bc5c631dff2d08c6a906c98716a20caa7b832b8970120a1eb1eb2de3ee890cd527d6edb04f532f4e48a690a792 + checksum: 10c0/2dc7379572b4b1340daff5923fbf7987ebd2de5a4203ece0ec9e8a9e85cf182cd4cd24c25bd7df62b981fb633c91dd35f27fed1341719c2f8a48eb80682b4658 languageName: node linkType: hard -"@typescript-eslint/rule-tester@npm:^8.39.0": - version: 8.54.0 - resolution: "@typescript-eslint/rule-tester@npm:8.54.0" +"@typescript-eslint/project-service@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/project-service@npm:8.53.1" dependencies: - "@typescript-eslint/parser": "npm:8.54.0" - "@typescript-eslint/typescript-estree": "npm:8.54.0" - "@typescript-eslint/utils": "npm:8.54.0" + "@typescript-eslint/tsconfig-utils": "npm:^8.53.1" + "@typescript-eslint/types": "npm:^8.53.1" + debug: "npm:^4.4.3" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/eecc7ad86b45c6969a05e984e645a4ece2a1cc27d825af046efb6ed369cab32062c17f33a1154ab6dcab349099885db7b39945f1b318753395630f3dfa1e5895 + languageName: node + linkType: hard + +"@typescript-eslint/rule-tester@npm:^8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/rule-tester@npm:8.53.1" + dependencies: + "@typescript-eslint/parser": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" + "@typescript-eslint/utils": "npm:8.53.1" ajv: "npm:^6.12.6" json-stable-stringify-without-jsonify: "npm:^1.0.1" lodash.merge: "npm:4.6.2" semver: "npm:^7.7.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - checksum: 10c0/7c8ecdbe2d3a95c4141fe591c15e9343051a6f9f6333125d7c2bbae1bb156874b8449d175d00c8aba78c8d1cd38510a448aa8536d3ca89f641f1eed92bf8acf0 + checksum: 10c0/418c5d9c646c9879050a4a4e9f297955fca8862f76363c05bedd0cd48e7f3e2ca3608dffc873658dbc96e485f1cdd97fdbf64289ab10e8cd91940c11323a39b5 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/scope-manager@npm:8.54.0" - dependencies: - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/visitor-keys": "npm:8.54.0" - checksum: 10c0/794740a5c0c1afc38d71e6bc59cc62870286e40d99f15e9760e76fb3d4197e961ee151c286c428535c404f5137721242a14da21350b749d0feb1f589f167814f - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:^8.51.0": +"@typescript-eslint/scope-manager@npm:8.52.0, @typescript-eslint/scope-manager@npm:^8.51.0": version: 8.52.0 resolution: "@typescript-eslint/scope-manager@npm:8.52.0" dependencies: @@ -5903,28 +6135,47 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.54.0, @typescript-eslint/tsconfig-utils@npm:^8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.54.0" +"@typescript-eslint/scope-manager@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/scope-manager@npm:8.53.1" + dependencies: + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/visitor-keys": "npm:8.53.1" + checksum: 10c0/d971eb115f2a2c4c25c79df9eee68b93354b32d7cc1174c167241cd2ebbc77858fe7a032c7ecdbacef936b56e8317b56037d21461cb83b4789f7e764e9faa455 + languageName: node + linkType: hard + +"@typescript-eslint/tsconfig-utils@npm:8.52.0, @typescript-eslint/tsconfig-utils@npm:^8.52.0": + version: 8.52.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.52.0" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/a45f6c1453031c149b2dedaa4e8ace53aa71c751a5702b028cbd9a899928d46141cc4343d8de6260e3e27024f6645b12669d8759f66ebde4cbae2f703b859747 + languageName: node + linkType: hard + +"@typescript-eslint/tsconfig-utils@npm:8.53.1, @typescript-eslint/tsconfig-utils@npm:^8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.53.1" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/e8598b0f051650c085d749002138d12249a3efd03e7de02e9e7913939dddd649d159b91f29ca3d28f5ee798b3f528a7195688e23c5e0b315d534e7af20a0c99a + checksum: 10c0/e2bfa91f9306dbfa82bdcb64bfcf634fee6313b03e93b35b0010907983c9ffc73c732264deff870896dea18f34b872d39d90d32f7631fd4618e4a6866ffff578 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/type-utils@npm:8.54.0" +"@typescript-eslint/type-utils@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/type-utils@npm:8.53.1" dependencies: - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/typescript-estree": "npm:8.54.0" - "@typescript-eslint/utils": "npm:8.54.0" + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" + "@typescript-eslint/utils": "npm:8.53.1" debug: "npm:^4.4.3" ts-api-utils: "npm:^2.4.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/ad807800d8b2662f823505249a84a6f5b1246b192a7ff08c49f298e220e4d9bb3d76f1f0852510421e030161604a4b939bff87f11b9074f118a3bd1d26139c6f + checksum: 10c0/d97ac3bf901eeeb1ad01a423409db654f849d49f8ce7a2b0d482e093d5c8c9cab9ed810554d130a1eaf4921ddb2d98dbe9a8d22bfd08fd6c8ab004fb640a3fbe languageName: node linkType: hard @@ -5935,21 +6186,47 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:8.54.0, @typescript-eslint/types@npm:^8.53.1, @typescript-eslint/types@npm:^8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/types@npm:8.54.0" - checksum: 10c0/2219594fe5e8931ff91fd1b7a2606d33cd4f093d43f9ca71bcaa37f106ef79ad51f830dea51392f7e3d8bca77f7077ef98733f87bc008fad2f0bbd9ea5fb8a40 +"@typescript-eslint/types@npm:8.53.1, @typescript-eslint/types@npm:^8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/types@npm:8.53.1" + checksum: 10c0/fa49f5f60de6851de45a9aff0a3ba3c4d00a0991100414e8af1a5d6f32764a48b6b7c0f65748a651f0da0e57df0745cdb8f11c590fa0fb22dd0e54e4c6b5c878 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:^8.52.0": + version: 8.53.0 + resolution: "@typescript-eslint/types@npm:8.53.0" + checksum: 10c0/a88681795becbe857f9868427c0d75c2ab2fb1acde14907b8791709b6d7835400bf9a0b41f22e97a13f1274e0082f5675692b815e30268e6eada492913100306 + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:8.52.0": + version: 8.52.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.52.0" + dependencies: + "@typescript-eslint/project-service": "npm:8.52.0" + "@typescript-eslint/tsconfig-utils": "npm:8.52.0" + "@typescript-eslint/types": "npm:8.52.0" + "@typescript-eslint/visitor-keys": "npm:8.52.0" + debug: "npm:^4.4.3" + minimatch: "npm:^9.0.5" + semver: "npm:^7.7.3" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.4.0" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/e4158a6364d3f009eac780947504ac1dad2ee3f1fdd4dfd99e4a7b48719ce0d342a769dc05fa5d4bc5de9de28175aa8e9ba612385f6b6f215039ff41e91f2de5 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.54.0" +"@typescript-eslint/typescript-estree@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/typescript-estree@npm:8.53.1" dependencies: - "@typescript-eslint/project-service": "npm:8.54.0" - "@typescript-eslint/tsconfig-utils": "npm:8.54.0" - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/visitor-keys": "npm:8.54.0" + "@typescript-eslint/project-service": "npm:8.53.1" + "@typescript-eslint/tsconfig-utils": "npm:8.53.1" + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/visitor-keys": "npm:8.53.1" debug: "npm:^4.4.3" minimatch: "npm:^9.0.5" semver: "npm:^7.7.3" @@ -5957,22 +6234,37 @@ __metadata: ts-api-utils: "npm:^2.4.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/1a1a7c0a318e71f3547ab5573198d36165ea152c50447ef92e6326303f9a5c397606201ba80c7b86a725dcdd2913e924be94466a0c33b1b0c3ee852059e646b6 + checksum: 10c0/e1b48990ba90f0ee5c9630fe91e2d5123c55348e374e586de6cf25e6e03e6e8274bf15317794d171a2e82d9dc663c229807e603ecc661dbe70d61bd23d0c37c4 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.54.0, @typescript-eslint/utils@npm:^8.39.0, @typescript-eslint/utils@npm:^8.51.0": - version: 8.54.0 - resolution: "@typescript-eslint/utils@npm:8.54.0" +"@typescript-eslint/utils@npm:8.53.1, @typescript-eslint/utils@npm:^8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/utils@npm:8.53.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.54.0" - "@typescript-eslint/types": "npm:8.54.0" - "@typescript-eslint/typescript-estree": "npm:8.54.0" + "@typescript-eslint/scope-manager": "npm:8.53.1" + "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/949a97dca8024d39666e04ecdf2d4e12722f5064c387901e72bdcc7adafb96cf650a070dc79f9dd46fa1aae6ac2b5eac5ae3fe5a6979385208c28809a1bd143f + checksum: 10c0/9a2a11c00b97eb9a053782e303cc384649807779e9adeb0b645bc198c83f54431f7ca56d4b38411dcf7ed06a2c2d9aa129874c20c037de2393a4cd0fa3b93c25 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:^8.51.0": + version: 8.52.0 + resolution: "@typescript-eslint/utils@npm:8.52.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.52.0" + "@typescript-eslint/types": "npm:8.52.0" + "@typescript-eslint/typescript-estree": "npm:8.52.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/67e501e8ef4c4a5510237e3bfcfee37512137075a18c24f615924559bcca64ce9903118e7e4288cd4f58361979243f457d43684cdafa6c193fa8963a7431d0f3 languageName: node linkType: hard @@ -5986,13 +6278,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.54.0": - version: 8.54.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.54.0" +"@typescript-eslint/visitor-keys@npm:8.53.1": + version: 8.53.1 + resolution: "@typescript-eslint/visitor-keys@npm:8.53.1" dependencies: - "@typescript-eslint/types": "npm:8.54.0" + "@typescript-eslint/types": "npm:8.53.1" eslint-visitor-keys: "npm:^4.2.1" - checksum: 10c0/f83a9aa92f7f4d1fdb12cbca28c6f5704c36371264606b456388b2c869fc61e73c86d3736556e1bb6e253f3a607128b5b1bf6c68395800ca06f18705576faadd + checksum: 10c0/73a21d34052bcb0b46ed738f8fddb76ae8f56a0c27932616b49022cf8603c3e36bb6ab30acd709f9bc05c673708180527b4c4aaffcb858acfc66d8fb39cc6c29 languageName: node linkType: hard @@ -6018,10 +6310,145 @@ __metadata: languageName: node linkType: hard -"@ungap/structured-clone@npm:^1.0.0": - version: 1.3.0 - resolution: "@ungap/structured-clone@npm:1.3.0" - checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a +"@ungap/structured-clone@npm:^1.0.0": + version: 1.3.0 + resolution: "@ungap/structured-clone@npm:1.3.0" + checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm-eabi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm-eabi@npm:1.11.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-android-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-android-arm64@npm:1.11.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-arm64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.11.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.11.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.11.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.11.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.11.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.11.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.11.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.11.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.11.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.11.1" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.2.11" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.11.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1": + version: 1.11.1 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.11.1" + conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -6044,18 +6471,18 @@ __metadata: linkType: hard "@vitejs/plugin-react@npm:^5.1.0": - version: 5.1.3 - resolution: "@vitejs/plugin-react@npm:5.1.3" + version: 5.1.1 + resolution: "@vitejs/plugin-react@npm:5.1.1" dependencies: - "@babel/core": "npm:^7.29.0" + "@babel/core": "npm:^7.28.5" "@babel/plugin-transform-react-jsx-self": "npm:^7.27.1" "@babel/plugin-transform-react-jsx-source": "npm:^7.27.1" - "@rolldown/pluginutils": "npm:1.0.0-rc.2" + "@rolldown/pluginutils": "npm:1.0.0-beta.47" "@types/babel__core": "npm:^7.20.5" react-refresh: "npm:^0.18.0" peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - checksum: 10c0/814d950f398f13ab5261593952b0a3a10a8b21220923c99817c99456890e1c0df4f1dd4cb2fc538ce4db4f525695e82ba1771a9e13ae1821283b659a7cfedc12 + checksum: 10c0/e590efaea1eabfbb1beb6e8c9fac0742fd299808e3368e63b2825ce24740adb8a28fcb2668b14b7ca1bdb42890cfefe94d02dd358dcbbf8a27ddf377b9a82abf languageName: node linkType: hard @@ -6069,7 +6496,7 @@ __metadata: languageName: node linkType: hard -"@vitest/browser-playwright@npm:^4.0.4": +"@vitest/browser-playwright@npm:^4.0.18": version: 4.0.18 resolution: "@vitest/browser-playwright@npm:4.0.18" dependencies: @@ -6104,7 +6531,7 @@ __metadata: languageName: node linkType: hard -"@vitest/coverage-v8@npm:^4.0.4": +"@vitest/coverage-v8@npm:^4.0.18": version: 4.0.18 resolution: "@vitest/coverage-v8@npm:4.0.18" dependencies: @@ -6128,7 +6555,7 @@ __metadata: languageName: node linkType: hard -"@vitest/eslint-plugin@npm:^1.3.4": +"@vitest/eslint-plugin@npm:^1.6.6": version: 1.6.6 resolution: "@vitest/eslint-plugin@npm:1.6.6" dependencies: @@ -6567,7 +6994,14 @@ __metadata: languageName: node linkType: hard -"ace-builds@npm:^1.25.1, ace-builds@npm:^1.36.3": +"ace-builds@npm:^1.25.1": + version: 1.41.0 + resolution: "ace-builds@npm:1.41.0" + checksum: 10c0/9473ee03c6dea43793fd431f6bfeb1381f1efeb82949e69432c7aea9fe32004067c0dfe837a395a0bc7c9ab61d61aab3a0e136c2bde1cdb808283718eefee603 + languageName: node + linkType: hard + +"ace-builds@npm:^1.36.3": version: 1.43.6 resolution: "ace-builds@npm:1.43.6" checksum: 10c0/33d0159a99650602de83b95766643b8f4f6029fc1ab582e47f7678288cae8e1c89b91747d23be42ec153a88d784fb9488935973f7a100b9093f837ac988f5c96 @@ -6612,6 +7046,15 @@ __metadata: languageName: node linkType: hard +"acorn-typescript@npm:^1.4.13": + version: 1.4.13 + resolution: "acorn-typescript@npm:1.4.13" + peerDependencies: + acorn: ">=8.9.0" + checksum: 10c0/f2f17cf03379d63beeb007f0feea02cebbd9af261f6b5619ea7345b177bd7a5f99752927cbf652baa3fc97962ae4561592093ab0a1c3e00ca4f354ba23c557ae + languageName: node + linkType: hard + "acorn-walk@npm:^8.0.0": version: 8.3.4 resolution: "acorn-walk@npm:8.3.4" @@ -6694,13 +7137,6 @@ __metadata: languageName: node linkType: hard -"ansi-regex@npm:^6.2.2": - version: 6.2.2 - resolution: "ansi-regex@npm:6.2.2" - checksum: 10c0/05d4acb1d2f59ab2cf4b794339c7b168890d44dda4bf0ce01152a8da0213aca207802f930442ce8cd22d7a92f44907664aac6508904e75e038fa944d2601b30f - languageName: node - linkType: hard - "ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": version: 4.3.0 resolution: "ansi-styles@npm:4.3.0" @@ -7899,20 +8335,13 @@ __metadata: languageName: node linkType: hard -"commander@npm:^14.0.0": +"commander@npm:^14.0.0, commander@npm:^14.0.2": version: 14.0.2 resolution: "commander@npm:14.0.2" checksum: 10c0/245abd1349dbad5414cb6517b7b5c584895c02c4f7836ff5395f301192b8566f9796c82d7bd6c92d07eba8775fe4df86602fca5d86d8d10bcc2aded1e21c2aeb languageName: node linkType: hard -"commander@npm:^14.0.3": - version: 14.0.3 - resolution: "commander@npm:14.0.3" - checksum: 10c0/755652564bbf56ff2ff083313912b326450d3f8d8c85f4b71416539c9a05c3c67dbd206821ca72635bf6b160e2afdefcb458e86b317827d5cb333b69ce7f1a24 - languageName: node - linkType: hard - "commander@npm:^8.3.0": version: 8.3.0 resolution: "commander@npm:8.3.0" @@ -7920,21 +8349,21 @@ __metadata: languageName: node linkType: hard -"comment-json@npm:^4.5.1": - version: 4.5.1 - resolution: "comment-json@npm:4.5.1" +"comment-json@npm:^4.4.1": + version: 4.4.1 + resolution: "comment-json@npm:4.4.1" dependencies: array-timsort: "npm:^1.0.3" core-util-is: "npm:^1.0.3" esprima: "npm:^4.0.1" - checksum: 10c0/aea59becb413fef2d21ec8f3d58b0dd024c47901c5f77c8436b19cc17f9ead0841b2f40d7a87a9b4061b8c048cd10c3c502e512eb8756ffc9aa58915ba5e4482 + checksum: 10c0/be6a197132543a3c286c725af412d582882c1eaf450cb124e4148e7542449f216aa717e7be81989f8b8cfe3e38a6f9bc06d209351b8ea82514cafc8feec11a2d languageName: node linkType: hard -"comment-parser@npm:1.4.5": - version: 1.4.5 - resolution: "comment-parser@npm:1.4.5" - checksum: 10c0/6a6a74697c79927e3bd42bde9608a471f1a9d4995affbc22fa3364cc42b4017f82ef477431a1558b0b6bef959f9bb6964c01c1bbfc06a58ba1730dec9c423b44 +"comment-parser@npm:1.4.1": + version: 1.4.1 + resolution: "comment-parser@npm:1.4.1" + checksum: 10c0/d6c4be3f5be058f98b24f2d557f745d8fe1cc9eb75bebbdccabd404a0e1ed41563171b16285f593011f8b6a5ec81f564fb1f2121418ac5cbf0f49255bf0840dd languageName: node linkType: hard @@ -8207,138 +8636,134 @@ __metadata: languageName: node linkType: hard -"cspell-config-lib@npm:9.6.4": - version: 9.6.4 - resolution: "cspell-config-lib@npm:9.6.4" +"cspell-config-lib@npm:9.3.1": + version: 9.3.1 + resolution: "cspell-config-lib@npm:9.3.1" dependencies: - "@cspell/cspell-types": "npm:9.6.4" - comment-json: "npm:^4.5.1" - smol-toml: "npm:^1.6.0" - yaml: "npm:^2.8.2" - checksum: 10c0/e444b5bf1d04e0ccc5f93b0e700d732b29760e61711c6dfca3c4adef32d79ab817a163e0fd5e09f275975cb0e0ef788946cea5390d87c63dcd73372647d48c06 + "@cspell/cspell-types": "npm:9.3.1" + comment-json: "npm:^4.4.1" + smol-toml: "npm:^1.4.2" + yaml: "npm:^2.8.1" + checksum: 10c0/4f3f4f4837a10a378778b4e5a1e930aad94be70072cff2d6c59d4025549354a85ea51253de472ff36da8b8fa75cb23e4c01bbab1ee8274d98cc1b3a32a2b8866 languageName: node linkType: hard -"cspell-dictionary@npm:9.6.4": - version: 9.6.4 - resolution: "cspell-dictionary@npm:9.6.4" +"cspell-dictionary@npm:9.3.1": + version: 9.3.1 + resolution: "cspell-dictionary@npm:9.3.1" dependencies: - "@cspell/cspell-performance-monitor": "npm:9.6.4" - "@cspell/cspell-pipe": "npm:9.6.4" - "@cspell/cspell-types": "npm:9.6.4" - cspell-trie-lib: "npm:9.6.4" - fast-equals: "npm:^6.0.0" - checksum: 10c0/38f31867a92f44139faf05b2f825201b2a21e70dd10ce1acd98464f8230f5edf2a1a95cbce92264cc628ad9be07d344e31fb110133143f1be55e9b653b504bc2 + "@cspell/cspell-pipe": "npm:9.3.1" + "@cspell/cspell-types": "npm:9.3.1" + cspell-trie-lib: "npm:9.3.1" + fast-equals: "npm:^5.3.2" + checksum: 10c0/03cf75a456791c7c54a52cd281ee01d50c0d1237635655115468153e4a35713b7ce9189dd908d0436f30a29a17c03703c90b34ed0493befbe8e62679fcb37c4a languageName: node linkType: hard -"cspell-gitignore@npm:9.6.4": - version: 9.6.4 - resolution: "cspell-gitignore@npm:9.6.4" +"cspell-gitignore@npm:9.3.1": + version: 9.3.1 + resolution: "cspell-gitignore@npm:9.3.1" dependencies: - "@cspell/url": "npm:9.6.4" - cspell-glob: "npm:9.6.4" - cspell-io: "npm:9.6.4" + "@cspell/url": "npm:9.3.1" + cspell-glob: "npm:9.3.1" + cspell-io: "npm:9.3.1" bin: cspell-gitignore: bin.mjs - checksum: 10c0/08c88d98a39081be3f8246caa4d7c9367defc9f6f58c751e39ac5848ffed3eb0d8a608f915da3f658f113c3f448149f33aae90cca5016bcda67da041fc5de976 + checksum: 10c0/a9bf15690e988095deb0e030e6070235567d0337d3c770e5cb1bf7e69581f5120901c367b805bdf7511a3a5ae6acffe266f13395f48e1aacf361d43c93d276b7 languageName: node linkType: hard -"cspell-glob@npm:9.6.4": - version: 9.6.4 - resolution: "cspell-glob@npm:9.6.4" +"cspell-glob@npm:9.3.1": + version: 9.3.1 + resolution: "cspell-glob@npm:9.3.1" dependencies: - "@cspell/url": "npm:9.6.4" + "@cspell/url": "npm:9.3.1" picomatch: "npm:^4.0.3" - checksum: 10c0/1d2b3d0f8da0c4bb745617bdb7dddcc38a511c78f8efb47ed47502203b980a0bc7efbca2bb9885aafadd656b81244c5824e4133afbc26dfaf67a7e573f96290c + checksum: 10c0/37df1c34f1fb6c3a16d29a0b1833ac6f168408fbf6478f962db049dde515e8ad639e005b30fd75d8ffe208b392d4f6b112c81519575612a95d41c3f20d8c442f languageName: node linkType: hard -"cspell-grammar@npm:9.6.4": - version: 9.6.4 - resolution: "cspell-grammar@npm:9.6.4" +"cspell-grammar@npm:9.3.1": + version: 9.3.1 + resolution: "cspell-grammar@npm:9.3.1" dependencies: - "@cspell/cspell-pipe": "npm:9.6.4" - "@cspell/cspell-types": "npm:9.6.4" + "@cspell/cspell-pipe": "npm:9.3.1" + "@cspell/cspell-types": "npm:9.3.1" bin: cspell-grammar: bin.mjs - checksum: 10c0/6039d8adfd8b4c3e1f8a60c26cb026efdba2314dd450a3de6e5ffce44cff78105c9aa17091a5ebc1ad8c866f1b38f91c1425e5d3163ff80f5affb2093099c2b2 + checksum: 10c0/e4e4bb1b8effff50032cb5f0407e1f9f666b4b5502520e49070ed00a9bfd1e863033212ef0523a5898ebc9761133b100592f1d2ec200169326e52409c69b827a languageName: node linkType: hard -"cspell-io@npm:9.6.4": - version: 9.6.4 - resolution: "cspell-io@npm:9.6.4" +"cspell-io@npm:9.3.1": + version: 9.3.1 + resolution: "cspell-io@npm:9.3.1" dependencies: - "@cspell/cspell-service-bus": "npm:9.6.4" - "@cspell/url": "npm:9.6.4" - checksum: 10c0/32bbb621275855df209547857d536e047e0fc78759a5bff36bb3a16c9ff1308d7171452e9e0e94d08dbb8e3716df08e3b9fc0967006ebd4935e3dd4aec290fcc + "@cspell/cspell-service-bus": "npm:9.3.1" + "@cspell/url": "npm:9.3.1" + checksum: 10c0/a4b709bc0ad7f489e33e07a946c7947794bc5b21318c85e0ee1763ef5086c7eca93b9ca276572309b478c7470e8697607542eb2fe46135218783d9c4262de93f languageName: node linkType: hard -"cspell-lib@npm:9.6.4": - version: 9.6.4 - resolution: "cspell-lib@npm:9.6.4" +"cspell-lib@npm:9.3.1": + version: 9.3.1 + resolution: "cspell-lib@npm:9.3.1" dependencies: - "@cspell/cspell-bundled-dicts": "npm:9.6.4" - "@cspell/cspell-performance-monitor": "npm:9.6.4" - "@cspell/cspell-pipe": "npm:9.6.4" - "@cspell/cspell-resolver": "npm:9.6.4" - "@cspell/cspell-types": "npm:9.6.4" - "@cspell/dynamic-import": "npm:9.6.4" - "@cspell/filetypes": "npm:9.6.4" - "@cspell/rpc": "npm:9.6.4" - "@cspell/strong-weak-map": "npm:9.6.4" - "@cspell/url": "npm:9.6.4" + "@cspell/cspell-bundled-dicts": "npm:9.3.1" + "@cspell/cspell-pipe": "npm:9.3.1" + "@cspell/cspell-resolver": "npm:9.3.1" + "@cspell/cspell-types": "npm:9.3.1" + "@cspell/dynamic-import": "npm:9.3.1" + "@cspell/filetypes": "npm:9.3.1" + "@cspell/strong-weak-map": "npm:9.3.1" + "@cspell/url": "npm:9.3.1" clear-module: "npm:^4.1.2" - cspell-config-lib: "npm:9.6.4" - cspell-dictionary: "npm:9.6.4" - cspell-glob: "npm:9.6.4" - cspell-grammar: "npm:9.6.4" - cspell-io: "npm:9.6.4" - cspell-trie-lib: "npm:9.6.4" - env-paths: "npm:^4.0.0" + cspell-config-lib: "npm:9.3.1" + cspell-dictionary: "npm:9.3.1" + cspell-glob: "npm:9.3.1" + cspell-grammar: "npm:9.3.1" + cspell-io: "npm:9.3.1" + cspell-trie-lib: "npm:9.3.1" + env-paths: "npm:^3.0.0" gensequence: "npm:^8.0.8" import-fresh: "npm:^3.3.1" resolve-from: "npm:^5.0.0" vscode-languageserver-textdocument: "npm:^1.0.12" vscode-uri: "npm:^3.1.0" xdg-basedir: "npm:^5.1.0" - checksum: 10c0/46952d51903ce1ee2aa0fb2fdc9ff6d8cb098a4506f1080d8cbba24d5a4a23182f7ab134b6ad33aac568cb90228e4878877cd8ccc988c3355a31b1674ea1f596 + checksum: 10c0/22e6e1e71a0322a5c70d7ca2039fa55c2e65508309885e8442671bdd072944913901e60afd50bcd4a4f7679697b5986b0e4eed6bb60611728fc9d07486cfbd67 languageName: node linkType: hard -"cspell-trie-lib@npm:9.6.4": - version: 9.6.4 - resolution: "cspell-trie-lib@npm:9.6.4" - peerDependencies: - "@cspell/cspell-types": 9.6.4 - checksum: 10c0/f4ac89d659e004bc541a5e7c6c15f013bfb00982a9c1362f7d52d6cfe14179b02c0bf469800020135bbfcdd7594d5669686b57294cd1ae799ce0aefda4b08e06 +"cspell-trie-lib@npm:9.3.1": + version: 9.3.1 + resolution: "cspell-trie-lib@npm:9.3.1" + dependencies: + "@cspell/cspell-pipe": "npm:9.3.1" + "@cspell/cspell-types": "npm:9.3.1" + gensequence: "npm:^8.0.8" + checksum: 10c0/f43b2af1a04d8aeb97a3df465e34d7aa23e2ada1e7666691ba969c55a3f99148d841f6a9eeed2b86b7b4b05c0a885bf1c9ec197dec8925326749b478ea11f091 languageName: node linkType: hard "cspell@npm:^9.2.1": - version: 9.6.4 - resolution: "cspell@npm:9.6.4" - dependencies: - "@cspell/cspell-json-reporter": "npm:9.6.4" - "@cspell/cspell-performance-monitor": "npm:9.6.4" - "@cspell/cspell-pipe": "npm:9.6.4" - "@cspell/cspell-types": "npm:9.6.4" - "@cspell/cspell-worker": "npm:9.6.4" - "@cspell/dynamic-import": "npm:9.6.4" - "@cspell/url": "npm:9.6.4" - ansi-regex: "npm:^6.2.2" + version: 9.3.1 + resolution: "cspell@npm:9.3.1" + dependencies: + "@cspell/cspell-json-reporter": "npm:9.3.1" + "@cspell/cspell-pipe": "npm:9.3.1" + "@cspell/cspell-types": "npm:9.3.1" + "@cspell/dynamic-import": "npm:9.3.1" + "@cspell/url": "npm:9.3.1" chalk: "npm:^5.6.2" chalk-template: "npm:^1.1.2" - commander: "npm:^14.0.3" - cspell-config-lib: "npm:9.6.4" - cspell-dictionary: "npm:9.6.4" - cspell-gitignore: "npm:9.6.4" - cspell-glob: "npm:9.6.4" - cspell-io: "npm:9.6.4" - cspell-lib: "npm:9.6.4" + commander: "npm:^14.0.2" + cspell-config-lib: "npm:9.3.1" + cspell-dictionary: "npm:9.3.1" + cspell-gitignore: "npm:9.3.1" + cspell-glob: "npm:9.3.1" + cspell-io: "npm:9.3.1" + cspell-lib: "npm:9.3.1" fast-json-stable-stringify: "npm:^2.1.0" flatted: "npm:^3.3.3" semver: "npm:^7.7.3" @@ -8346,7 +8771,7 @@ __metadata: bin: cspell: bin.mjs cspell-esm: bin.mjs - checksum: 10c0/717a5f2a9e9c9f930266a6848595402ec39f168f3caf3698c0b8681ad97575dcadbdb54a4e42661bdf87d41ca558c9a2a84e0a510e7ea87d7911a1f7fb65f6ad + checksum: 10c0/15cd54a26ed868fcfb7b672a4305bd04bec18077a71fb039c756194ee324592d32e889616636d050aa45858d221fdac1e1f991114a7ecd0236fb58a4b97cd92d languageName: node linkType: hard @@ -8367,13 +8792,6 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.2.2": - version: 3.2.3 - resolution: "csstype@npm:3.2.3" - checksum: 10c0/cd29c51e70fa822f1cecd8641a1445bed7063697469d35633b516e60fe8c1bde04b08f6c5b6022136bb669b64c63d4173af54864510fbb4ee23281801841a3ce - languageName: node - linkType: hard - "cytoscape-cose-bilkent@npm:^4.1.0": version: 4.1.0 resolution: "cytoscape-cose-bilkent@npm:4.1.0" @@ -9248,12 +9666,10 @@ __metadata: languageName: node linkType: hard -"env-paths@npm:^4.0.0": - version: 4.0.0 - resolution: "env-paths@npm:4.0.0" - dependencies: - is-safe-filename: "npm:^0.1.0" - checksum: 10c0/13ee7fa4047786ca28f1fbf2239606f8a53304bdf71bfc426e95f806e429060181205316f2c45b4ac560e81c854ded5a45fd9dc3105414c01d504b3469a1294b +"env-paths@npm:^3.0.0": + version: 3.0.0 + resolution: "env-paths@npm:3.0.0" + checksum: 10c0/76dec878cee47f841103bacd7fae03283af16f0702dad65102ef0a556f310b98a377885e0f32943831eb08b5ab37842a323d02529f3dfd5d0a40ca71b01b435f languageName: node linkType: hard @@ -9572,36 +9988,122 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.25.0": + version: 0.25.4 + resolution: "esbuild@npm:0.25.4" + dependencies: + "@esbuild/aix-ppc64": "npm:0.25.4" + "@esbuild/android-arm": "npm:0.25.4" + "@esbuild/android-arm64": "npm:0.25.4" + "@esbuild/android-x64": "npm:0.25.4" + "@esbuild/darwin-arm64": "npm:0.25.4" + "@esbuild/darwin-x64": "npm:0.25.4" + "@esbuild/freebsd-arm64": "npm:0.25.4" + "@esbuild/freebsd-x64": "npm:0.25.4" + "@esbuild/linux-arm": "npm:0.25.4" + "@esbuild/linux-arm64": "npm:0.25.4" + "@esbuild/linux-ia32": "npm:0.25.4" + "@esbuild/linux-loong64": "npm:0.25.4" + "@esbuild/linux-mips64el": "npm:0.25.4" + "@esbuild/linux-ppc64": "npm:0.25.4" + "@esbuild/linux-riscv64": "npm:0.25.4" + "@esbuild/linux-s390x": "npm:0.25.4" + "@esbuild/linux-x64": "npm:0.25.4" + "@esbuild/netbsd-arm64": "npm:0.25.4" + "@esbuild/netbsd-x64": "npm:0.25.4" + "@esbuild/openbsd-arm64": "npm:0.25.4" + "@esbuild/openbsd-x64": "npm:0.25.4" + "@esbuild/sunos-x64": "npm:0.25.4" + "@esbuild/win32-arm64": "npm:0.25.4" + "@esbuild/win32-ia32": "npm:0.25.4" + "@esbuild/win32-x64": "npm:0.25.4" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/db9f51248f0560bc46ab219461d338047617f6caf373c95f643b204760bdfa10c95b48cfde948949f7e509599ae4ab61c3f112092a3534936c6abfb800c565b0 + languageName: node + linkType: hard + "esbuild@npm:^0.27.0": - version: 0.27.2 - resolution: "esbuild@npm:0.27.2" - dependencies: - "@esbuild/aix-ppc64": "npm:0.27.2" - "@esbuild/android-arm": "npm:0.27.2" - "@esbuild/android-arm64": "npm:0.27.2" - "@esbuild/android-x64": "npm:0.27.2" - "@esbuild/darwin-arm64": "npm:0.27.2" - "@esbuild/darwin-x64": "npm:0.27.2" - "@esbuild/freebsd-arm64": "npm:0.27.2" - "@esbuild/freebsd-x64": "npm:0.27.2" - "@esbuild/linux-arm": "npm:0.27.2" - "@esbuild/linux-arm64": "npm:0.27.2" - "@esbuild/linux-ia32": "npm:0.27.2" - "@esbuild/linux-loong64": "npm:0.27.2" - "@esbuild/linux-mips64el": "npm:0.27.2" - "@esbuild/linux-ppc64": "npm:0.27.2" - "@esbuild/linux-riscv64": "npm:0.27.2" - "@esbuild/linux-s390x": "npm:0.27.2" - "@esbuild/linux-x64": "npm:0.27.2" - "@esbuild/netbsd-arm64": "npm:0.27.2" - "@esbuild/netbsd-x64": "npm:0.27.2" - "@esbuild/openbsd-arm64": "npm:0.27.2" - "@esbuild/openbsd-x64": "npm:0.27.2" - "@esbuild/openharmony-arm64": "npm:0.27.2" - "@esbuild/sunos-x64": "npm:0.27.2" - "@esbuild/win32-arm64": "npm:0.27.2" - "@esbuild/win32-ia32": "npm:0.27.2" - "@esbuild/win32-x64": "npm:0.27.2" + version: 0.27.0 + resolution: "esbuild@npm:0.27.0" + dependencies: + "@esbuild/aix-ppc64": "npm:0.27.0" + "@esbuild/android-arm": "npm:0.27.0" + "@esbuild/android-arm64": "npm:0.27.0" + "@esbuild/android-x64": "npm:0.27.0" + "@esbuild/darwin-arm64": "npm:0.27.0" + "@esbuild/darwin-x64": "npm:0.27.0" + "@esbuild/freebsd-arm64": "npm:0.27.0" + "@esbuild/freebsd-x64": "npm:0.27.0" + "@esbuild/linux-arm": "npm:0.27.0" + "@esbuild/linux-arm64": "npm:0.27.0" + "@esbuild/linux-ia32": "npm:0.27.0" + "@esbuild/linux-loong64": "npm:0.27.0" + "@esbuild/linux-mips64el": "npm:0.27.0" + "@esbuild/linux-ppc64": "npm:0.27.0" + "@esbuild/linux-riscv64": "npm:0.27.0" + "@esbuild/linux-s390x": "npm:0.27.0" + "@esbuild/linux-x64": "npm:0.27.0" + "@esbuild/netbsd-arm64": "npm:0.27.0" + "@esbuild/netbsd-x64": "npm:0.27.0" + "@esbuild/openbsd-arm64": "npm:0.27.0" + "@esbuild/openbsd-x64": "npm:0.27.0" + "@esbuild/openharmony-arm64": "npm:0.27.0" + "@esbuild/sunos-x64": "npm:0.27.0" + "@esbuild/win32-arm64": "npm:0.27.0" + "@esbuild/win32-ia32": "npm:0.27.0" + "@esbuild/win32-x64": "npm:0.27.0" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -9657,7 +10159,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10c0/cf83f626f55500f521d5fe7f4bc5871bec240d3deb2a01fbd379edc43b3664d1167428738a5aad8794b35d1cca985c44c375b1cd38a2ca613c77ced2c83aafcd + checksum: 10c0/a3a1deec285337b7dfe25cbb9aa8765d27a0192b610a8477a39bf5bd907a6bdb75e98898b61fb4337114cfadb13163bd95977db14e241373115f548e235b40a2 languageName: node linkType: hard @@ -9693,6 +10195,21 @@ __metadata: languageName: node linkType: hard +"eslint-import-context@npm:^0.1.8": + version: 0.1.9 + resolution: "eslint-import-context@npm:0.1.9" + dependencies: + get-tsconfig: "npm:^4.10.1" + stable-hash-x: "npm:^0.2.0" + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + checksum: 10c0/07851103443b70af681c5988e2702e681ff9b956e055e11d4bd9b2322847fa0d9e8da50c18fc7cb1165106b043f34fbd0384d7011c239465c4645c52132e56f3 + languageName: node + linkType: hard + "eslint-import-resolver-node@npm:^0.3.9": version: 0.3.9 resolution: "eslint-import-resolver-node@npm:0.3.9" @@ -9704,6 +10221,30 @@ __metadata: languageName: node linkType: hard +"eslint-import-resolver-typescript@npm:^4.4.4": + version: 4.4.4 + resolution: "eslint-import-resolver-typescript@npm:4.4.4" + dependencies: + debug: "npm:^4.4.1" + eslint-import-context: "npm:^0.1.8" + get-tsconfig: "npm:^4.10.1" + is-bun-module: "npm:^2.0.0" + stable-hash-x: "npm:^0.2.0" + tinyglobby: "npm:^0.2.14" + unrs-resolver: "npm:^1.7.11" + peerDependencies: + eslint: "*" + eslint-plugin-import: "*" + eslint-plugin-import-x: "*" + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + checksum: 10c0/3bf8ad77c21660f77a0e455555ab179420f68ae7a132906c85a217ccce51cb6680cf70027cab32a358d193e5b9e476f6ba2e595585242aa97d4f6435ca22104e + languageName: node + linkType: hard + "eslint-mdx@npm:^3.6.2": version: 3.6.2 resolution: "eslint-mdx@npm:3.6.2" @@ -9773,16 +10314,16 @@ __metadata: linkType: hard "eslint-plugin-jsdoc@npm:^62.0.0": - version: 62.5.4 - resolution: "eslint-plugin-jsdoc@npm:62.5.4" + version: 62.0.0 + resolution: "eslint-plugin-jsdoc@npm:62.0.0" dependencies: - "@es-joy/jsdoccomment": "npm:~0.84.0" + "@es-joy/jsdoccomment": "npm:~0.79.0" "@es-joy/resolve.exports": "npm:1.2.0" are-docs-informative: "npm:^0.0.2" - comment-parser: "npm:1.4.5" + comment-parser: "npm:1.4.1" debug: "npm:^4.4.3" escape-string-regexp: "npm:^4.0.0" - espree: "npm:^11.1.0" + espree: "npm:^11.0.0" esquery: "npm:^1.7.0" html-entities: "npm:^2.6.0" object-deep-merge: "npm:^2.0.0" @@ -9792,7 +10333,7 @@ __metadata: to-valid-identifier: "npm:^1.0.0" peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10c0/576a3dd2279c09ec579cbb944afed78029d5525a18dbef37097d510a0241c3792a597c440e80a299240772d49a6d0624bc90ffec32a72fca1e806e0554ac2119 + checksum: 10c0/9558f9a05109f5eab9433225240f2ac36407b47694731e7ad1f6edb995c5616e51b7475b05409d230dc859ba4ac1f77dc5ed409e16fadf4c454305eab72695bf languageName: node linkType: hard @@ -9854,8 +10395,8 @@ __metadata: linkType: hard "eslint-plugin-yml@npm:^1.19.0": - version: 1.19.1 - resolution: "eslint-plugin-yml@npm:1.19.1" + version: 1.19.0 + resolution: "eslint-plugin-yml@npm:1.19.0" dependencies: debug: "npm:^4.3.2" diff-sequences: "npm:^27.5.1" @@ -9865,7 +10406,7 @@ __metadata: yaml-eslint-parser: "npm:^1.2.1" peerDependencies: eslint: ">=6.0.0" - checksum: 10c0/c442966b7c3bc091b9973ec167408a509802b039643d7fd2b30d7440b72030dec916741925c58d33b098220b7d73809ac7786d970157e356f3a7eec0f74471b0 + checksum: 10c0/5e418d3e5f847491a143f048b9aece30c0bbb6c2218185bfb24d5be2d31974aa71f92ead4fe5f8c51d356577c5b2c36e26b2406f1baeb501bed86344a4d0f40c languageName: node linkType: hard @@ -9908,8 +10449,8 @@ __metadata: linkType: hard "eslint@npm:^9.35.0": - version: 9.39.2 - resolution: "eslint@npm:9.39.2" + version: 9.39.1 + resolution: "eslint@npm:9.39.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.8.0" "@eslint-community/regexpp": "npm:^4.12.1" @@ -9917,7 +10458,7 @@ __metadata: "@eslint/config-helpers": "npm:^0.4.2" "@eslint/core": "npm:^0.17.0" "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.39.2" + "@eslint/js": "npm:9.39.1" "@eslint/plugin-kit": "npm:^0.4.1" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" @@ -9952,7 +10493,7 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10c0/bb88ca8fd16bb7e1ac3e13804c54d41c583214460c0faa7b3e7c574e69c5600c7122295500fb4b0c06067831111db740931e98da1340329527658e1cf80073d3 + checksum: 10c0/59b2480639404ba24578ca480f973683b87b7aac8aa7e349240474a39067804fd13cd8b9cb22fee074170b8c7c563b57bab703ec0f0d3f81ea017e5d2cad299d languageName: node linkType: hard @@ -9978,14 +10519,14 @@ __metadata: languageName: node linkType: hard -"espree@npm:^11.1.0": - version: 11.1.0 - resolution: "espree@npm:11.1.0" +"espree@npm:^11.0.0": + version: 11.0.0 + resolution: "espree@npm:11.0.0" dependencies: acorn: "npm:^8.15.0" acorn-jsx: "npm:^5.3.2" eslint-visitor-keys: "npm:^5.0.0" - checksum: 10c0/32228d12896f5aa09f59fad8bf5df228d73310e436c21389876cdd21513b620c087d24b40646cdcff848540d11b078653db0e37ea67ac9c7012a12595d86630c + checksum: 10c0/1e07fdb2a135bb9996a4b23baad51980dde7bcdf4d7115cdec06437663790f4bbe3416eb560fc7dc7330c01a6006f789722f1e5b243208f4cb6e054efef57afd languageName: node linkType: hard @@ -10246,10 +10787,10 @@ __metadata: languageName: node linkType: hard -"fast-equals@npm:^6.0.0": - version: 6.0.0 - resolution: "fast-equals@npm:6.0.0" - checksum: 10c0/aae54699ce848726679a947c8bbea78f2ea0384e4e1ee213c98f10881a17bb376bd11085eda4d6c89db5285635ee2f809b126d773532fcf602be355008a9d5ed +"fast-equals@npm:^5.3.2": + version: 5.3.3 + resolution: "fast-equals@npm:5.3.3" + checksum: 10c0/a186cbfe4d9171911af9c6bb02d059e28bc177f66527790bf95d35a08f6f070033caea5755d2bbf2ce7af56374c1d4d854ee8184f9e906e3e01b54dbd09c414c languageName: node linkType: hard @@ -10288,13 +10829,13 @@ __metadata: linkType: hard "fast-xml-parser@npm:^5.0.7": - version: 5.3.4 - resolution: "fast-xml-parser@npm:5.3.4" + version: 5.2.5 + resolution: "fast-xml-parser@npm:5.2.5" dependencies: strnum: "npm:^2.1.0" bin: fxparser: src/cli/cli.js - checksum: 10c0/d77866ca860ad185153e12f6ba12274d32026319ad8064e4681342b8a8e1ffad3f1f98daf04d77239fb12eb1d906ee7185fd328deda74529680e8dae0f3e9327 + checksum: 10c0/d1057d2e790c327ccfc42b872b91786a4912a152d44f9507bf053f800102dfb07ece3da0a86b33ff6a0caa5a5cad86da3326744f6ae5efb0c6c571d754fe48cd languageName: node linkType: hard @@ -10481,7 +11022,7 @@ __metadata: languageName: node linkType: hard -"foreground-child@npm:^3.1.0, foreground-child@npm:^3.3.1": +"foreground-child@npm:^3.1.0": version: 3.3.1 resolution: "foreground-child@npm:3.3.1" dependencies: @@ -10676,6 +11217,15 @@ __metadata: languageName: node linkType: hard +"get-tsconfig@npm:^4.10.1": + version: 4.13.0 + resolution: "get-tsconfig@npm:4.13.0" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10c0/2c49ef8d3907047a107f229fd610386fe3b7fe9e42dfd6b42e7406499493cdda8c62e83e57e8d7a98125610774b9f604d3a0ff308d7f9de5c7ac6d1b07cb6036 + languageName: node + linkType: hard + "get-value@npm:^2.0.3, get-value@npm:^2.0.6": version: 2.0.6 resolution: "get-value@npm:2.0.6" @@ -10729,23 +11279,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:11.1.0": - version: 11.1.0 - resolution: "glob@npm:11.1.0" - dependencies: - foreground-child: "npm:^3.3.1" - jackspeak: "npm:^4.1.1" - minimatch: "npm:^10.1.1" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^2.0.0" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/1ceae07f23e316a6fa74581d9a74be6e8c2e590d2f7205034dd5c0435c53f5f7b712c2be00c3b65bf0a49294a1c6f4b98cd84c7637e29453b5aa13b79f1763a2 - languageName: node - linkType: hard - -"glob@npm:^10.0.0, glob@npm:^10.2.2": +"glob@npm:10.4.5, glob@npm:^10.0.0, glob@npm:^10.2.2": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -11027,7 +11561,7 @@ __metadata: languageName: node linkType: hard -"hast-util-to-html@npm:^9.0.4": +"hast-util-to-html@npm:^9.0.4, hast-util-to-html@npm:^9.0.5": version: 9.0.5 resolution: "hast-util-to-html@npm:9.0.5" dependencies: @@ -11527,6 +12061,15 @@ __metadata: languageName: node linkType: hard +"is-bun-module@npm:^2.0.0": + version: 2.0.0 + resolution: "is-bun-module@npm:2.0.0" + dependencies: + semver: "npm:^7.7.1" + checksum: 10c0/7d27a0679cfa5be1f5052650391f9b11040cd70c48d45112e312c56bc6b6ca9c9aea70dcce6cc40b1e8947bfff8567a5c5715d3b066fb478522dab46ea379240 + languageName: node + linkType: hard + "is-callable@npm:^1.2.7": version: 1.2.7 resolution: "is-callable@npm:1.2.7" @@ -11777,13 +12320,6 @@ __metadata: languageName: node linkType: hard -"is-safe-filename@npm:^0.1.0": - version: 0.1.1 - resolution: "is-safe-filename@npm:0.1.1" - checksum: 10c0/45c35d2253b96348e2c26590e14feed51d1e6b72aaa567930ccb34e68c0eef00ebcf3b7e01b46bf45e578a27355cd8f5bc12f7d6d79a34d33dc93d4560c0f6b6 - languageName: node - linkType: hard - "is-set@npm:^2.0.3": version: 2.0.3 resolution: "is-set@npm:2.0.3" @@ -12021,15 +12557,6 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^4.1.1": - version: 4.2.3 - resolution: "jackspeak@npm:4.2.3" - dependencies: - "@isaacs/cliui": "npm:^9.0.0" - checksum: 10c0/b5c0c414f1607c2aa0597f4bf2c03b8443897fccd5fd3c2b3e4f77d556b2bc7c3d3413828ba91e0789f6fb40ad90242f7f89fb20aee9e9d705bc1681f7564f67 - languageName: node - linkType: hard - "jest-haste-map@npm:^26.6.2": version: 26.6.2 resolution: "jest-haste-map@npm:26.6.2" @@ -12111,7 +12638,7 @@ __metadata: languageName: node linkType: hard -"js-slang@npm:^1.0.81": +"js-slang@npm:^1.0.85": version: 1.0.85 resolution: "js-slang@npm:1.0.85" dependencies: @@ -12179,10 +12706,10 @@ __metadata: languageName: node linkType: hard -"jsdoc-type-pratt-parser@npm:~7.1.1": - version: 7.1.1 - resolution: "jsdoc-type-pratt-parser@npm:7.1.1" - checksum: 10c0/5a5216a75962b3a8a3a1e7e09a19b31b5a373c06c726a00b081480daee00196250d4acc8dfbecc0a7846d439a5bcf4a326df6348b879cf95f60c62ce5818dadb +"jsdoc-type-pratt-parser@npm:~7.0.0": + version: 7.0.0 + resolution: "jsdoc-type-pratt-parser@npm:7.0.0" + checksum: 10c0/3ede53c80dddf940a51dcdc79e3923537650f6fb6e9001fc76023c2d5cb0195cc8b24b7eebf9b3f20a7bc00d5e6b7f70318f0b8cb5972f6aff884152e6698014 languageName: node linkType: hard @@ -12277,14 +12804,14 @@ __metadata: linkType: hard "jsonc-eslint-parser@npm:^2.4.0": - version: 2.4.2 - resolution: "jsonc-eslint-parser@npm:2.4.2" + version: 2.4.1 + resolution: "jsonc-eslint-parser@npm:2.4.1" dependencies: acorn: "npm:^8.5.0" eslint-visitor-keys: "npm:^3.0.0" espree: "npm:^9.0.0" semver: "npm:^7.3.5" - checksum: 10c0/821af0231cb8eba2afde34535bd76d723ed5b4b3711fdccff3f300f32de7bbf463ceab3ce2de9e6fd78dc3b24a9c7248ca12eb43e280cfa2695f49bd16908f87 + checksum: 10c0/735bd33435fee002bf7f07d23ba969b994971ab3b333a0e2641b79cd413819fe36540ba6ed29da9ebc69062625e8bfb167ff4415321f9640fdd9d0cf92dfa999 languageName: node linkType: hard @@ -12713,13 +13240,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^11.0.0": - version: 11.2.5 - resolution: "lru-cache@npm:11.2.5" - checksum: 10c0/cc98958d25dddf1c8a8cbdc49588bd3b24450e8dfa78f32168fd188a20d4a0331c7406d0f3250c86a46619ee288056fd7a1195e8df56dc8a9592397f4fbd8e1d - languageName: node - linkType: hard - "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -13172,8 +13692,8 @@ __metadata: linkType: hard "mermaid@npm:^11.10.0": - version: 11.12.2 - resolution: "mermaid@npm:11.12.2" + version: 11.12.1 + resolution: "mermaid@npm:11.12.1" dependencies: "@braintree/sanitize-url": "npm:^7.1.1" "@iconify/utils": "npm:^3.0.1" @@ -13195,7 +13715,7 @@ __metadata: stylis: "npm:^4.3.6" ts-dedent: "npm:^2.2.0" uuid: "npm:^11.1.0" - checksum: 10c0/00969b96171f1f11cf897df205d932237a6303041d9519b82bd727cfca43507b54cbf28dfb951aa7ff5e6129607f2297703a464361fc95942db9364c579da9f3 + checksum: 10c0/0dd07a5986bb25ca038f68f7a187a0b6ccf5fa8c738603c3145bd4b6289d50312053818f52617cf575a6652e6c57809ae115c016725f7ce446496be5971a150a languageName: node linkType: hard @@ -13758,15 +14278,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^10.1.1": - version: 10.1.2 - resolution: "minimatch@npm:10.1.2" - dependencies: - "@isaacs/brace-expansion": "npm:^5.0.1" - checksum: 10c0/0cccef3622201703de6ecf9d772c0be1d5513dcc038ed9feb866c20cf798243e678ac35605dac3f1a054650c28037486713fe9e9a34b184b9097959114daf086 - languageName: node - linkType: hard - "minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -13959,18 +14470,6 @@ __metadata: languageName: node linkType: hard -"mlly@npm:^1.8.0": - version: 1.8.0 - resolution: "mlly@npm:1.8.0" - dependencies: - acorn: "npm:^8.15.0" - pathe: "npm:^2.0.3" - pkg-types: "npm:^1.3.1" - ufo: "npm:^1.6.1" - checksum: 10c0/f174b844ae066c71e9b128046677868e2e28694f0bbeeffbe760b2a9d8ff24de0748d0fde6fabe706700c1d2e11d3c0d7a53071b5ea99671592fac03364604ab - languageName: node - linkType: hard - "mqtt-packet@npm:^6.8.0": version: 6.10.0 resolution: "mqtt-packet@npm:6.10.0" @@ -14067,6 +14566,15 @@ __metadata: languageName: node linkType: hard +"napi-postinstall@npm:^0.3.0": + version: 0.3.4 + resolution: "napi-postinstall@npm:0.3.4" + bin: + napi-postinstall: lib/cli.js + checksum: 10c0/b33d64150828bdade3a5d07368a8b30da22ee393f8dd8432f1b9e5486867be21c84ec443dd875dd3ef3c7401a079a7ab7e2aa9d3538a889abbcd96495d5104fe + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -14478,6 +14986,13 @@ __metadata: languageName: node linkType: hard +"oniguruma-parser@npm:^0.12.1": + version: 0.12.1 + resolution: "oniguruma-parser@npm:0.12.1" + checksum: 10c0/b843ea54cda833efb19f856314afcbd43e903ece3de489ab78c527ddec84859208052557daa9fad4bdba89ebdd15b0cc250de86b3daf8c7cbe37bac5a6a185d3 + languageName: node + linkType: hard + "oniguruma-to-es@npm:^3.1.0": version: 3.1.1 resolution: "oniguruma-to-es@npm:3.1.1" @@ -14489,6 +15004,17 @@ __metadata: languageName: node linkType: hard +"oniguruma-to-es@npm:^4.3.4": + version: 4.3.4 + resolution: "oniguruma-to-es@npm:4.3.4" + dependencies: + oniguruma-parser: "npm:^0.12.1" + regex: "npm:^6.0.1" + regex-recursion: "npm:^6.0.2" + checksum: 10c0/fb58459f50db71c2c4785205636186bfbb125b094c4275512a8f41f123ed3fbf61f37c455f4360ef14a56c693981aecd7da3ae2c05614a222e872c4643b463fc + languageName: node + linkType: hard + "opener@npm:^1.5.1": version: 1.5.2 resolution: "opener@npm:1.5.2" @@ -14631,10 +15157,10 @@ __metadata: languageName: node linkType: hard -"packageurl-js@npm:2.0.1": - version: 2.0.1 - resolution: "packageurl-js@npm:2.0.1" - checksum: 10c0/8a45bc925243bea0fd7f027b54bf7c363ab70dae2b01676d67856eb788352d7344f38b86c8cfa510410220c6848dc57bc152146bf6518fb06c272d3dbe003b55 +"packageurl-js@npm:1.2.0": + version: 1.2.0 + resolution: "packageurl-js@npm:1.2.0" + checksum: 10c0/4ab4f63483e3ae516ec458bc8113d7e86c199698fa66a4b290c039f92415a9d8908a9421155677fe56bc6ba682c5930bf1db432401ad8dbf0a3350a6d92bd3d8 languageName: node linkType: hard @@ -14826,16 +15352,6 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^2.0.0": - version: 2.0.1 - resolution: "path-scurry@npm:2.0.1" - dependencies: - lru-cache: "npm:^11.0.0" - minipass: "npm:^7.1.2" - checksum: 10c0/2a16ed0e81fbc43513e245aa5763354e25e787dab0d539581a6c3f0f967461a159ed6236b2559de23aa5b88e7dc32b469b6c47568833dd142a4b24b4f5cd2620 - languageName: node - linkType: hard - "pathe@npm:^2.0.1, pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" @@ -14865,11 +15381,11 @@ __metadata: linkType: hard "phaser@npm:^3.54.0": - version: 3.90.0 - resolution: "phaser@npm:3.90.0" + version: 3.88.2 + resolution: "phaser@npm:3.88.2" dependencies: eventemitter3: "npm:^5.0.1" - checksum: 10c0/43d405832fc84c8641e22842fe8d4ca954950ffde364bfb60e4d07b05a29f33eb0c9d4a64acda088122ee6649b7b3ed6d9b3b99bbb67671a528c6ceb10d71689 + checksum: 10c0/eb583f741aaa42975180c56e3149dfa762de78c9c2d80c74c545f62bcc1ab8e88be84d99d82bef32aa931a79cc2416f92109a076e051d998b3f173595d8e908e languageName: node linkType: hard @@ -14928,7 +15444,7 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^1.3.0, pkg-types@npm:^1.3.1": +"pkg-types@npm:^1.3.0": version: 1.3.1 resolution: "pkg-types@npm:1.3.1" dependencies: @@ -14950,27 +15466,27 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.58.2": - version: 1.58.2 - resolution: "playwright-core@npm:1.58.2" +"playwright-core@npm:1.56.1": + version: 1.56.1 + resolution: "playwright-core@npm:1.56.1" bin: playwright-core: cli.js - checksum: 10c0/5aa15b2b764e6ffe738293a09081a6f7023847a0dbf4cd05fe10eed2e25450d321baf7482f938f2d2eb330291e197fa23e57b29a5b552b89927ceb791266225b + checksum: 10c0/ffd40142b99c68678b387445d5b42f1fee4ab0b65d983058c37f342e5629f9cdbdac0506ea80a0dfd41a8f9f13345bad54e9a8c35826ef66dc765f4eb3db8da7 languageName: node linkType: hard "playwright@npm:^1.55.1": - version: 1.58.2 - resolution: "playwright@npm:1.58.2" + version: 1.56.1 + resolution: "playwright@npm:1.56.1" dependencies: fsevents: "npm:2.3.2" - playwright-core: "npm:1.58.2" + playwright-core: "npm:1.56.1" dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: 10c0/d060d9b7cc124bd8b5dffebaab5e84f6b34654a553758fe7b19cc598dfbee93f6ecfbdc1832b40a6380ae04eade86ef3285ba03aa0b136799e83402246dc0727 + checksum: 10c0/8e9965aede86df0f4722063385748498977b219630a40a10d1b82b8bd8d4d4e9b6b65ecbfa024331a30800163161aca292fb6dd7446c531a1ad25f4155625ab4 languageName: node linkType: hard @@ -14982,9 +15498,9 @@ __metadata: linkType: hard "plotly.js-dist@npm:^3.0.0": - version: 3.3.1 - resolution: "plotly.js-dist@npm:3.3.1" - checksum: 10c0/8332667bc104a7fa13465f2462cb322c2b445ec4f3e2c522214508bd5eeca6b6471153c9f805e7f8228528a9faf6749fbfbc4f2e4612499397aeff8e928330c4 + version: 3.0.1 + resolution: "plotly.js-dist@npm:3.0.1" + checksum: 10c0/cc5725d043fb052a28952fa8b7f72bbf91cc4460d2742e68f49801fe34cf7164ad0d55fe262da0c2e530ef4541845a030d129aab8d90795987052236bb8372c4 languageName: node linkType: hard @@ -15055,9 +15571,9 @@ __metadata: linkType: hard "preact@npm:^10.0.0": - version: 10.28.2 - resolution: "preact@npm:10.28.2" - checksum: 10c0/eb60bf526eb6971701e6ac9c25236aca451f17f99e9c24704419196989b15bb576ed3101e084b151cd0fb30546b3e5e1ba73b774e8be2f2ed8187db42ec65faf + version: 10.26.9 + resolution: "preact@npm:10.26.9" + checksum: 10c0/15f187e3278ae749b70e887f88bb01be63ebcc2eea46ffa86be69180716db40b8b4304e9768767fd68a5910ef5fd1f9ea6389e17cd25e950be76574d568e8fc3 languageName: node linkType: hard @@ -15187,18 +15703,18 @@ __metadata: linkType: hard "qs@npm:^6.12.3, qs@npm:^6.4.0": - version: 6.14.1 - resolution: "qs@npm:6.14.1" + version: 6.14.0 + resolution: "qs@npm:6.14.0" dependencies: side-channel: "npm:^1.1.0" - checksum: 10c0/0e3b22dc451f48ce5940cbbc7c7d9068d895074f8c969c0801ac15c1313d1859c4d738e46dc4da2f498f41a9ffd8c201bd9fb12df67799b827db94cc373d2613 + checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c languageName: node linkType: hard -"qsu@npm:^1.10.4": - version: 1.11.1 - resolution: "qsu@npm:1.11.1" - checksum: 10c0/e460cfe205c356b7f7f6ebf63f2cc265bb2d3c5fae9aa4a0dd25f4b7e21d26c75bd6bfc6edc55e085470b436f965807eb77261838c130326d17897d41970c6e1 +"qsu@npm:^1.10.0": + version: 1.10.1 + resolution: "qsu@npm:1.10.1" + checksum: 10c0/6997ebce26a14474bfad4b1e5dfb1124b90c18b6427778a7e85cd31ac52017f769063dccd5fb1db028adabe6265ed5a8fd67f0619451e312bfa0aafb9fa75e37 languageName: node linkType: hard @@ -15360,21 +15876,6 @@ __metadata: languageName: node linkType: hard -"react-uid@npm:^2.3.3": - version: 2.4.0 - resolution: "react-uid@npm:2.4.0" - dependencies: - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/5e01e8d3a4144d160af26f7ea8300887ed8379ee14b1fad7979ea755d5bfa4badfdab531cb7d4495488e94083f829bd5b28a8f6661522b11729fceb42dcf73ea - languageName: node - linkType: hard - "react-use-measure@npm:^2.1.7": version: 2.1.7 resolution: "react-use-measure@npm:2.1.7" @@ -15644,6 +16145,13 @@ __metadata: languageName: node linkType: hard +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab + languageName: node + linkType: hard + "resolve-url@npm:^0.2.1": version: 0.2.1 resolution: "resolve-url@npm:0.2.1" @@ -16007,8 +16515,8 @@ __metadata: linkType: hard "sass@npm:^1.85.0": - version: 1.97.3 - resolution: "sass@npm:1.97.3" + version: 1.88.0 + resolution: "sass@npm:1.88.0" dependencies: "@parcel/watcher": "npm:^2.4.1" chokidar: "npm:^4.0.0" @@ -16019,7 +16527,7 @@ __metadata: optional: true bin: sass: sass.js - checksum: 10c0/67f6b5d220f20c1c23a8b16dda5fd1c5d119ad5caf8195b185d553b5b239fb188a3787f04fc00171c62515f2c4e5e0eb5ad4992a80f8543428556883c1240ba3 + checksum: 10c0/dcb16dc29116bfa5a90485d24fd8020d2b0d95155bd2e31285901588729343b59fefe44365c5f146b2ba5a9ebadef90b23a7220b902507bdbd91ca2ba0a0b688 languageName: node linkType: hard @@ -16099,7 +16607,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.2, semver@npm:^7.3.8, semver@npm:^7.7.3": +"semver@npm:^7.0.0, semver@npm:^7.1.2, semver@npm:^7.3.8, semver@npm:^7.7.1, semver@npm:^7.7.3": version: 7.7.3 resolution: "semver@npm:7.7.3" bin: @@ -16245,6 +16753,22 @@ __metadata: languageName: node linkType: hard +"shiki@npm:^3.15.0": + version: 3.20.0 + resolution: "shiki@npm:3.20.0" + dependencies: + "@shikijs/core": "npm:3.20.0" + "@shikijs/engine-javascript": "npm:3.20.0" + "@shikijs/engine-oniguruma": "npm:3.20.0" + "@shikijs/langs": "npm:3.20.0" + "@shikijs/themes": "npm:3.20.0" + "@shikijs/types": "npm:3.20.0" + "@shikijs/vscode-textmate": "npm:^10.0.2" + "@types/hast": "npm:^3.0.4" + checksum: 10c0/e7f0a8e6b8748b1d25cccc186e5cd32cbc8b272c08b4b554a3328c95714ee564d5525747d5ceb52c1ee766ec25cb7a5fa1de748edeb6508a57be15433de1564f + languageName: node + linkType: hard + "side-channel-list@npm:^1.0.0": version: 1.0.0 resolution: "side-channel-list@npm:1.0.0" @@ -16346,10 +16870,10 @@ __metadata: languageName: node linkType: hard -"smol-toml@npm:^1.6.0": - version: 1.6.0 - resolution: "smol-toml@npm:1.6.0" - checksum: 10c0/baf33bb6cd914d481329e31998a12829cd126541458ba400791212c80f1245d5b27dac04a56a52c02b287d2a494f1628c05fc19643286b258b2e0bb9fe67747c +"smol-toml@npm:^1.4.2": + version: 1.4.2 + resolution: "smol-toml@npm:1.4.2" + checksum: 10c0/e01e5f249b1ad852d09aa22f338a6cb3896ac35c92bf0d35744ce1b1e2f4b67901d4a0e886027617a2a8aa9f1a6c67c919c41b544c4aec137b6ebe042ca10d36 languageName: node linkType: hard @@ -16412,10 +16936,10 @@ __metadata: linkType: hard "snyk-nodejs-lockfile-parser@npm:^2.4.2": - version: 2.5.0 - resolution: "snyk-nodejs-lockfile-parser@npm:2.5.0" + version: 2.4.2 + resolution: "snyk-nodejs-lockfile-parser@npm:2.4.2" dependencies: - "@snyk/dep-graph": "npm:^2.12.0" + "@snyk/dep-graph": "npm:^2.3.0" "@snyk/error-catalog-nodejs-public": "npm:^5.16.0" "@snyk/graphlib": "npm:2.1.9-patch.3" "@yarnpkg/core": "npm:^4.4.1" @@ -16435,7 +16959,7 @@ __metadata: uuid: "npm:^8.3.0" bin: parse-nodejs-lockfile: bin/index.js - checksum: 10c0/9cc7d03322d76dd66df9372f542b3d980a0278e458a9402d29c4320e2054dab3821c59b0ac6c43b85fbaa0d216353e2b411b4c61efe8f60bf551c5c481a86518 + checksum: 10c0/205aff1ea79306975a881f63d857af446e61ff7537d94efb591b993bd152e413b8688f360d58f5bcaef833e00395898c35b31ab179d6aa07dce9d1f753617fe0 languageName: node linkType: hard @@ -16634,6 +17158,13 @@ __metadata: languageName: node linkType: hard +"stable-hash-x@npm:^0.2.0": + version: 0.2.0 + resolution: "stable-hash-x@npm:0.2.0" + checksum: 10c0/c757df58366ee4bb266a9486b8932eab7c1ba730469eaf4b68d2dee404814e9f84089c44c9b5205f8c7d99a0ab036cce2af69139ce5ed44b635923c011a8aea8 + languageName: node + linkType: hard + "stackback@npm:0.0.2": version: 0.0.2 resolution: "stackback@npm:0.0.2" @@ -17140,7 +17671,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.15": +"tinyglobby@npm:^0.2.14, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -17183,9 +17714,9 @@ __metadata: linkType: hard "tm-themes@npm:^1.10.12": - version: 1.10.16 - resolution: "tm-themes@npm:1.10.16" - checksum: 10c0/916ed911cb4630a5f069bab44055e96823a7ff9cb85c399736b42c682283a3f8568fe3b420692ca6ae4de2b1ba5a6fb7d4105b4333dd947ca09cbcb236068d7f + version: 1.10.12 + resolution: "tm-themes@npm:1.10.12" + checksum: 10c0/dcb3ef2fede7ed373909caed11d8c6a89837eb7682515182cc9f52f0c580b5bb4d9f0019cb1c1199fea416bb8d327f31d5b696903aeaf66b2a88cbcad80cf632 languageName: node linkType: hard @@ -17386,7 +17917,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2, tslib@npm:^2.0.0, tslib@npm:^2.0.3, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3, tslib@npm:^2.8.1": +"tslib@npm:^2, tslib@npm:^2.0.3, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.6.3, tslib@npm:^2.8.1": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 @@ -17516,22 +18047,22 @@ __metadata: linkType: hard "typedoc-plugin-frontmatter@npm:^1.3.0": - version: 1.3.1 - resolution: "typedoc-plugin-frontmatter@npm:1.3.1" + version: 1.3.0 + resolution: "typedoc-plugin-frontmatter@npm:1.3.0" dependencies: - yaml: "npm:^2.8.1" + yaml: "npm:^2.7.0" peerDependencies: - typedoc-plugin-markdown: ">=4.9.0" - checksum: 10c0/8bdda87c7a89b2a9dfdd3925c4b1a633c92696ca3fa110d96870a9d9bc2433afbe6d48e2b1b899bad4c7ae00970a8af1543d58e3e122db6d61055d1a2aff7dab + typedoc-plugin-markdown: ">=4.5.0" + checksum: 10c0/967ee5c38ab64b94489b9001744bbecc1cb6951bb07232caf2f4925f6a4dc0ac53305c4305e34ba10d6fddaab8f939642a2fbf10f1da884d6d6885d370c94cf3 languageName: node linkType: hard "typedoc-plugin-markdown@npm:^4.7.0": - version: 4.10.0 - resolution: "typedoc-plugin-markdown@npm:4.10.0" + version: 4.7.0 + resolution: "typedoc-plugin-markdown@npm:4.7.0" peerDependencies: typedoc: 0.28.x - checksum: 10c0/20c7bc8ef68bd90053649ce223d02d4aceefed675c09efb1740c7791fbc37c10a1e25d14647605484a198f0695312eb21119015616d91c73fe1d63df5e4fb061 + checksum: 10c0/066cb8a0f96bb24c22069830d189904d624204b7ceaaeab78c72008ebb2c2bddb55170ae39fac31352caf20516a1a2360300cf384c9683f7b42465dc2c354bd1 languageName: node linkType: hard @@ -17547,10 +18078,10 @@ __metadata: linkType: hard "typedoc@npm:^0.28.9": - version: 0.28.16 - resolution: "typedoc@npm:0.28.16" + version: 0.28.14 + resolution: "typedoc@npm:0.28.14" dependencies: - "@gerrit0/mini-shiki": "npm:^3.17.0" + "@gerrit0/mini-shiki": "npm:^3.12.0" lunr: "npm:^2.3.9" markdown-it: "npm:^14.1.0" minimatch: "npm:^9.0.5" @@ -17559,22 +18090,22 @@ __metadata: typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x bin: typedoc: bin/typedoc - checksum: 10c0/ae444913068088e88be6319a017a3a18f69cbd91dbb5b959fbdd0cf87d1a2a07f3a0d4ab29c957a83dd72808ff35bdd6ceec3ad1803fa412ddceffb78fa60ebb + checksum: 10c0/a8727134991ba3f9a982e9f6ceecfbcf0fac531e4865e4865cdee68ea6fe1a594228b8654011d38ffa2332b7e84e4eaa3d0dac04a8bdf36a0686d1c3f327e80b languageName: node linkType: hard -"typescript-eslint@npm:^8.33.1": - version: 8.54.0 - resolution: "typescript-eslint@npm:8.54.0" +"typescript-eslint@npm:^8.53.1": + version: 8.53.1 + resolution: "typescript-eslint@npm:8.53.1" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.54.0" - "@typescript-eslint/parser": "npm:8.54.0" - "@typescript-eslint/typescript-estree": "npm:8.54.0" - "@typescript-eslint/utils": "npm:8.54.0" + "@typescript-eslint/eslint-plugin": "npm:8.53.1" + "@typescript-eslint/parser": "npm:8.53.1" + "@typescript-eslint/typescript-estree": "npm:8.53.1" + "@typescript-eslint/utils": "npm:8.53.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/0ba92aa22c0aa10c88b0f4732950ed64245947f1c4ac17328dff94b43eaeddd3068595788725781fba07a87cc964304a075b3e37f9a86312173498fcc6ab4338 + checksum: 10c0/520d68df8e1e1bba99c2713029b63837b101370c460bf5e75b8065fb0a6bc1ac9c6eb967432dbc220464479fe981630a6b2eddf31cfb378441ee8b8a43c0eb5a languageName: node linkType: hard @@ -17672,13 +18203,6 @@ __metadata: languageName: node linkType: hard -"ufo@npm:^1.6.1": - version: 1.6.3 - resolution: "ufo@npm:1.6.3" - checksum: 10c0/bf0e4ebff99e54da1b9c7182ac2f40475988b41faa881d579bc97bc2a0509672107b0a0e94c4b8d31a0ab8c4bf07f4aa0b469ac6da8536d56bda5b085ea2e953 - languageName: node - linkType: hard - "unbox-primitive@npm:^1.1.0": version: 1.1.0 resolution: "unbox-primitive@npm:1.1.0" @@ -17884,6 +18408,73 @@ __metadata: languageName: node linkType: hard +"unrs-resolver@npm:^1.7.11": + version: 1.11.1 + resolution: "unrs-resolver@npm:1.11.1" + dependencies: + "@unrs/resolver-binding-android-arm-eabi": "npm:1.11.1" + "@unrs/resolver-binding-android-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-arm64": "npm:1.11.1" + "@unrs/resolver-binding-darwin-x64": "npm:1.11.1" + "@unrs/resolver-binding-freebsd-x64": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.11.1" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.11.1" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.11.1" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.11.1" + napi-postinstall: "npm:^0.3.0" + dependenciesMeta: + "@unrs/resolver-binding-android-arm-eabi": + optional: true + "@unrs/resolver-binding-android-arm64": + optional: true + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: 10c0/c91b112c71a33d6b24e5c708dab43ab80911f2df8ee65b87cd7a18fb5af446708e98c4b415ca262026ad8df326debcc7ca6a801b2935504d87fd6f0b9d70dce1 + languageName: node + linkType: hard + "unset-value@npm:^1.0.0": version: 1.0.0 resolution: "unset-value@npm:1.0.0" @@ -18173,10 +18764,10 @@ __metadata: linkType: hard "vite@npm:^6.0.0 || ^7.0.0, vite@npm:^7.1.11": - version: 7.3.1 - resolution: "vite@npm:7.3.1" + version: 7.1.11 + resolution: "vite@npm:7.1.11" dependencies: - esbuild: "npm:^0.27.0" + esbuild: "npm:^0.25.0" fdir: "npm:^6.5.0" fsevents: "npm:~2.3.3" picomatch: "npm:^4.0.3" @@ -18223,23 +18814,23 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/5c7548f5f43a23533e53324304db4ad85f1896b1bfd3ee32ae9b866bac2933782c77b350eb2b52a02c625c8ad1ddd4c000df077419410650c982cd97fde8d014 + checksum: 10c0/c4aa7f47b1fb07f734ed6f4f605d73e5acf7ff9754d75b4adbfbdddf0e520413019834620c1f7b4a207bce7e1d20a2636c584db2b1b17f5a3ba2cd23d47e50ab languageName: node linkType: hard "vitepress-plugin-group-icons@npm:^1.6.5": - version: 1.7.1 - resolution: "vitepress-plugin-group-icons@npm:1.7.1" + version: 1.6.5 + resolution: "vitepress-plugin-group-icons@npm:1.6.5" dependencies: - "@iconify-json/logos": "npm:^1.2.10" - "@iconify-json/vscode-icons": "npm:^1.2.39" - "@iconify/utils": "npm:^3.1.0" + "@iconify-json/logos": "npm:^1.2.9" + "@iconify-json/vscode-icons": "npm:^1.2.32" + "@iconify/utils": "npm:^3.0.2" peerDependencies: vite: ">=3" peerDependenciesMeta: vite: optional: true - checksum: 10c0/9d24c09ef38155d5f2efb61e27162350bb90e9b89677f4af5e4287bebff2899506751ea8ef305f30feeead4416422955c45dbc0c38e48de884ec62c40b04dc56 + checksum: 10c0/8e30800925cdc2ae1aeafcb42d9aae5da4a3c922e8aa0bd629461f29ff1ba3a766cb45f7ee66a350a4be8acce5f7069457da36a3977255bf241858ba8a5dad36 languageName: node linkType: hard @@ -18259,13 +18850,13 @@ __metadata: linkType: hard "vitepress-sidebar@npm:^1.31.1": - version: 1.33.1 - resolution: "vitepress-sidebar@npm:1.33.1" + version: 1.31.1 + resolution: "vitepress-sidebar@npm:1.31.1" dependencies: - glob: "npm:11.1.0" + glob: "npm:10.4.5" gray-matter: "npm:4.0.3" - qsu: "npm:^1.10.4" - checksum: 10c0/9544aeb53ad062ffaf307bc52e47cf429af7275e816b7181d1e26538999f2d19e09fb1c0560ae26bc0114dba7a6925c8aa9a2132657ee42b9be0e1857c296a4c + qsu: "npm:^1.10.0" + checksum: 10c0/0294cf2bdcde0cc48eef6b0dab73a13d1eee6d81a1860a225656185a43c7f842c202aa452f987c0cd1f0b383b3b1bf7242174262a568b2521b8ebffe9eba4962 languageName: node linkType: hard @@ -18305,9 +18896,9 @@ __metadata: languageName: node linkType: hard -"vitest-browser-react@npm:^2.0.2": - version: 2.0.5 - resolution: "vitest-browser-react@npm:2.0.5" +"vitest-browser-react@npm:^2.0.4": + version: 2.0.4 + resolution: "vitest-browser-react@npm:2.0.4" peerDependencies: "@types/react": ^18.0.0 || ^19.0.0 "@types/react-dom": ^18.0.0 || ^19.0.0 @@ -18319,11 +18910,11 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/ae972fa20895c73622c2e724a2e2a716cc2a2e5148da19a60d1185323aeb5f5bd0653cfe3048d081bb086ee0efa68c0c360d28cdf42ddd8df6a5f2d17ffd0c9e + checksum: 10c0/d5c4c65dbdc42bb9a78ac3545f5294bcabb217b6d70f00464f1f1583e8c7f4e5d71d454e3a84f1dba1ce341b8885e84fcd716eca290a052c342c950b5aaa7c1b languageName: node linkType: hard -"vitest@npm:^4.0.4": +"vitest@npm:^4.0.18": version: 4.0.18 resolution: "vitest@npm:4.0.18" dependencies: @@ -18831,7 +19422,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.0.0, yaml@npm:^2.8.0, yaml@npm:^2.8.1, yaml@npm:^2.8.2": +"yaml@npm:^2.0.0, yaml@npm:^2.8.0, yaml@npm:^2.8.1": version: 2.8.2 resolution: "yaml@npm:2.8.2" bin: @@ -18840,6 +19431,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.7.0": + version: 2.8.1 + resolution: "yaml@npm:2.8.1" + bin: + yaml: bin.mjs + checksum: 10c0/7c587be00d9303d2ae1566e03bc5bc7fe978ba0d9bf39cc418c3139d37929dfcb93a230d9749f2cb578b6aa5d9ebebc322415e4b653cb83acd8bc0bc321707f3 + languageName: node + linkType: hard + "yocto-queue@npm:^0.1.0": version: 0.1.0 resolution: "yocto-queue@npm:0.1.0" From ce9953612158451d22b56ae1ed9e2940929c7fce Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 8 Feb 2026 05:55:53 +0800 Subject: [PATCH 34/71] Format markdown files --- docs/src/buildtools/5-builders/2-docs.md | 2 +- docs/src/modules/2-bundle/4-conventions/1-basic.md | 2 ++ .../modules/2-bundle/5-documentation/1-cadet/1-cadet.md | 6 +++--- docs/src/repotools/6-docserver/2-dirtree.md | 2 -- docs/src/repotools/7-workflows/1-actions.md | 2 +- docs/src/repotools/7-workflows/4-changes.md | 9 ++++----- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/src/buildtools/5-builders/2-docs.md b/docs/src/buildtools/5-builders/2-docs.md index 64f53a7792..d13d4e29b3 100644 --- a/docs/src/buildtools/5-builders/2-docs.md +++ b/docs/src/buildtools/5-builders/2-docs.md @@ -34,7 +34,7 @@ is the case, then we print a warning advising the developer that they may have f ### Hiding Type Guards -Typescript has a feature called type guards that allow the compiler to better narrow types, increasing the type safety of module code. +Typescript has a feature called type guards that allow the compiler to better narrow types, increasing the type safety of module code. When Typedoc encounters a type guard, it documents the return type of that type guard as is. diff --git a/docs/src/modules/2-bundle/4-conventions/1-basic.md b/docs/src/modules/2-bundle/4-conventions/1-basic.md index ea52fb94d9..6178bc5dc2 100644 --- a/docs/src/modules/2-bundle/4-conventions/1-basic.md +++ b/docs/src/modules/2-bundle/4-conventions/1-basic.md @@ -221,6 +221,7 @@ In Typescript, there are two kinds of type guards. Cadet facing type guards sho `is` prefix. Also, the parameter the type guard validates should be of type `unknown`. Anywhere you use a boolean check followed by a type assertion: + ```ts // Simple boolean type guard export function is_sound(obj: unknown): boolean { @@ -238,6 +239,7 @@ function play(obj: Sound) { ``` you should replace with a type guard: + ```ts // Typescript boolean Type Guard export function is_sound(obj: unknown): obj is Sound { diff --git a/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md b/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md index 5eb0fd3f2a..e8ad7de629 100644 --- a/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md +++ b/docs/src/modules/2-bundle/5-documentation/1-cadet/1-cadet.md @@ -268,7 +268,7 @@ to the best of your ability to help make your documentation as comprehensive as > [!INFO] Configuring Supported Tags > There is an ESLint rule configured to error when you use an unknown tag. By default, the rule includes all tags supported by JSDoc, but Typedoc > actually supports many more tags intended for customizing documentaton output. -> +> > If you want to use a Typedoc supported tag that hasn't been configured for use, you can simply modify the `jsdoc/check-tag-names` > rule to include your tag. @@ -318,8 +318,8 @@ When building the json documentation for a bundle, the following steps are taken - For constants, their names and types are extracted - For functions, their name, the names and types of each parameter, and return types are extracted.\ The descriptions of both functions are constants are also included, but first they are passed through a Markdown to HTML converter called [drawdown](https://github.com/adamvleggett/drawdown), included in this project as `drawdown.ts` -3. The code then converts it to the HTML format expected by the frontend -3. All the processed strings then get written to a json file in the `jsons` folder. +1. The code then converts it to the HTML format expected by the frontend +1. All the processed strings then get written to a json file in the `jsons` folder. If no documentation could be found, or there was an error parsing the documented code, the system will still output JSONs, just with warnings. diff --git a/docs/src/repotools/6-docserver/2-dirtree.md b/docs/src/repotools/6-docserver/2-dirtree.md index a8280686b4..7eb49714c1 100644 --- a/docs/src/repotools/6-docserver/2-dirtree.md +++ b/docs/src/repotools/6-docserver/2-dirtree.md @@ -2,8 +2,6 @@ The idea behind this plugin was inspired by [this](https://tree.nathanfriend.com/?) ASCII tree generator. - - ## Plugin Structure The plugin itself consists of 3 components: diff --git a/docs/src/repotools/7-workflows/1-actions.md b/docs/src/repotools/7-workflows/1-actions.md index 43fbed7fce..7d466d0c32 100644 --- a/docs/src/repotools/7-workflows/1-actions.md +++ b/docs/src/repotools/7-workflows/1-actions.md @@ -25,7 +25,7 @@ In the case of bundles or tabs, it also retrieves the name of the bundle or tab. In case of changes to the lockfile, it also determines which packages need to be rebuilt. This can happen when dependencies of dependencies change, so no change is present in the package's source code itself, but the lockfile itself has changed. -More detail about detecting changes can be found in [this section](./4-changes.md). +More detail about detecting changes can be found in [this section](./4-changes.md). This information is used by both the initializer action and the workflows to determine the what tasks need to be executed. diff --git a/docs/src/repotools/7-workflows/4-changes.md b/docs/src/repotools/7-workflows/4-changes.md index e96ac7dc10..4f3e091a48 100644 --- a/docs/src/repotools/7-workflows/4-changes.md +++ b/docs/src/repotools/7-workflows/4-changes.md @@ -36,6 +36,7 @@ dependency tracking system to rebuild workspace packages only if they were affec Importantly, for the CI/CD pipeline, we are concerned only with changes relative to the **master** branch. For each workspace package, there are two main kinds of changes we must detect: + 1. Non-transitive 2. Transitive @@ -65,10 +66,7 @@ return exitCode !== 0; ## Transitive Changes -Transitive changes occur when one of the current workspace package's dependencies contain changes. For example, the `sound` bundle -relies on the `midi` bundle, so if the `midi` bundle has changes (and thus needs to be rebuilt), the `sound` bundle would -also need to be rebuilt, even if the `sound` bundle did not contain any changes. -Since the `plotly` bundle relies on the `sound` bundle, it too would also need to be rebuilt. +Transitive changes occur when one of the current workspace package's dependencies contain changes. For example, the `sound` bundle relies on the `midi` bundle, so if the `midi` bundle has changes (and thus needs to be rebuilt), the `sound` bundle would also need to be rebuilt, even if the `sound` bundle did not contain any changes. Since the `plotly` bundle relies on the `sound` bundle, it too would also need to be rebuilt. ```mermaid graph LR @@ -145,7 +143,7 @@ publish this new version as version `4.17.1`. Notice that this version is still When the repository's automated dependency upgrading bot (Renovate Bot) detects this, it will attempt to cause Yarn to install version `4.17.1` instead of `4.17.0` for `lodash`. It does this by updating the lockfile. But now we have a problem: the `curve` bundle transitively relies -on `lodash` through `gl-matrix`. +on `lodash` through `gl-matrix`. ```mermaid graph LR @@ -176,6 +174,7 @@ Then, using the `yarn why` command, we can determine which package is reliant on until we reach one of our workspace packages, at which point we know that that particular workspace needs to be rebuilt. Let us work through the above example: + 1. Using `git diff`, we determine that the lockfile has changed relative to the master branch. 2. We compare the local lockfile with the master lockfile and determine that that `lodash@4.17.0` is present in the master lockfile, while `lodash@4.17.1` is not. So now we know that we need to determine why `lodash@4.17.1` has been included. From f05933a69a1c228e4b349974aa4d0374a5aad294 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 8 Feb 2026 23:53:18 +0800 Subject: [PATCH 35/71] Update lockfile post-merge --- yarn.lock | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 272 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index b40d96963f..628596e782 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2113,6 +2113,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/aix-ppc64@npm:0.25.12" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/aix-ppc64@npm:0.27.3" @@ -2127,6 +2134,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/android-arm64@npm:0.25.12" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/android-arm64@npm:0.27.3" @@ -2141,6 +2155,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/android-arm@npm:0.25.12" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/android-arm@npm:0.27.3" @@ -2155,6 +2176,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/android-x64@npm:0.25.12" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/android-x64@npm:0.27.3" @@ -2169,6 +2197,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/darwin-arm64@npm:0.25.12" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/darwin-arm64@npm:0.27.3" @@ -2183,6 +2218,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/darwin-x64@npm:0.25.12" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/darwin-x64@npm:0.27.3" @@ -2197,6 +2239,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/freebsd-arm64@npm:0.25.12" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/freebsd-arm64@npm:0.27.3" @@ -2211,6 +2260,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/freebsd-x64@npm:0.25.12" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/freebsd-x64@npm:0.27.3" @@ -2225,6 +2281,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-arm64@npm:0.25.12" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/linux-arm64@npm:0.27.3" @@ -2239,6 +2302,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-arm@npm:0.25.12" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/linux-arm@npm:0.27.3" @@ -2253,6 +2323,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-ia32@npm:0.25.12" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/linux-ia32@npm:0.27.3" @@ -2267,6 +2344,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-loong64@npm:0.25.12" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/linux-loong64@npm:0.27.3" @@ -2281,6 +2365,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-mips64el@npm:0.25.12" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/linux-mips64el@npm:0.27.3" @@ -2295,6 +2386,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-ppc64@npm:0.25.12" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/linux-ppc64@npm:0.27.3" @@ -2309,6 +2407,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-riscv64@npm:0.25.12" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/linux-riscv64@npm:0.27.3" @@ -2323,6 +2428,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-s390x@npm:0.25.12" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/linux-s390x@npm:0.27.3" @@ -2337,6 +2449,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/linux-x64@npm:0.25.12" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/linux-x64@npm:0.27.3" @@ -2344,6 +2463,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/netbsd-arm64@npm:0.25.12" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/netbsd-arm64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/netbsd-arm64@npm:0.27.3" @@ -2358,6 +2484,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/netbsd-x64@npm:0.25.12" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/netbsd-x64@npm:0.27.3" @@ -2365,6 +2498,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/openbsd-arm64@npm:0.25.12" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/openbsd-arm64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/openbsd-arm64@npm:0.27.3" @@ -2379,6 +2519,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/openbsd-x64@npm:0.25.12" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/openbsd-x64@npm:0.27.3" @@ -2386,6 +2533,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openharmony-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/openharmony-arm64@npm:0.25.12" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/openharmony-arm64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/openharmony-arm64@npm:0.27.3" @@ -2400,6 +2554,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/sunos-x64@npm:0.25.12" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/sunos-x64@npm:0.27.3" @@ -2414,6 +2575,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/win32-arm64@npm:0.25.12" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/win32-arm64@npm:0.27.3" @@ -2428,6 +2596,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/win32-ia32@npm:0.25.12" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/win32-ia32@npm:0.27.3" @@ -2442,6 +2617,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.25.12": + version: 0.25.12 + resolution: "@esbuild/win32-x64@npm:0.25.12" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.27.3": version: 0.27.3 resolution: "@esbuild/win32-x64@npm:0.27.3" @@ -8179,7 +8361,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^14.0.0, commander@npm:^14.0.3": +"commander@npm:^14.0.0, commander@npm:^14.0.2": version: 14.0.3 resolution: "commander@npm:14.0.3" checksum: 10c0/755652564bbf56ff2ff083313912b326450d3f8d8c85f4b71416539c9a05c3c67dbd206821ca72635bf6b160e2afdefcb458e86b317827d5cb333b69ce7f1a24 @@ -9832,6 +10014,95 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.25.0": + version: 0.25.12 + resolution: "esbuild@npm:0.25.12" + dependencies: + "@esbuild/aix-ppc64": "npm:0.25.12" + "@esbuild/android-arm": "npm:0.25.12" + "@esbuild/android-arm64": "npm:0.25.12" + "@esbuild/android-x64": "npm:0.25.12" + "@esbuild/darwin-arm64": "npm:0.25.12" + "@esbuild/darwin-x64": "npm:0.25.12" + "@esbuild/freebsd-arm64": "npm:0.25.12" + "@esbuild/freebsd-x64": "npm:0.25.12" + "@esbuild/linux-arm": "npm:0.25.12" + "@esbuild/linux-arm64": "npm:0.25.12" + "@esbuild/linux-ia32": "npm:0.25.12" + "@esbuild/linux-loong64": "npm:0.25.12" + "@esbuild/linux-mips64el": "npm:0.25.12" + "@esbuild/linux-ppc64": "npm:0.25.12" + "@esbuild/linux-riscv64": "npm:0.25.12" + "@esbuild/linux-s390x": "npm:0.25.12" + "@esbuild/linux-x64": "npm:0.25.12" + "@esbuild/netbsd-arm64": "npm:0.25.12" + "@esbuild/netbsd-x64": "npm:0.25.12" + "@esbuild/openbsd-arm64": "npm:0.25.12" + "@esbuild/openbsd-x64": "npm:0.25.12" + "@esbuild/openharmony-arm64": "npm:0.25.12" + "@esbuild/sunos-x64": "npm:0.25.12" + "@esbuild/win32-arm64": "npm:0.25.12" + "@esbuild/win32-ia32": "npm:0.25.12" + "@esbuild/win32-x64": "npm:0.25.12" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/openharmony-arm64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/c205357531423220a9de8e1e6c6514242bc9b1666e762cd67ccdf8fdfdc3f1d0bd76f8d9383958b97ad4c953efdb7b6e8c1f9ca5951cd2b7c5235e8755b34a6b + languageName: node + linkType: hard + "esbuild@npm:^0.27.0": version: 0.27.3 resolution: "esbuild@npm:0.27.3" From b639551f2a048ae66bc6a820fb700b1b9535175b Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Wed, 11 Feb 2026 23:12:26 +0800 Subject: [PATCH 36/71] Fix incorrect curve drawer implementations and add tests --- src/bundles/curve/src/__tests__/curve.test.ts | 22 +++++++++++++++-- src/bundles/curve/src/drawers.ts | 24 +++++++++++++++---- src/bundles/curve/src/types.ts | 13 ++++++++++ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/bundles/curve/src/__tests__/curve.test.ts b/src/bundles/curve/src/__tests__/curve.test.ts index 00ae12a91b..8405cc3e0a 100644 --- a/src/bundles/curve/src/__tests__/curve.test.ts +++ b/src/bundles/curve/src/__tests__/curve.test.ts @@ -3,7 +3,7 @@ import { describe, expect, it, test } from 'vitest'; import type { Color, Curve } from '../curves_webgl'; import * as drawers from '../drawers'; import * as funcs from '../functions'; -import type { RenderFunction } from '../types'; +import type { RenderFunctionCreator } from '../types'; /** * Evaluates the curve at 200 points, then @@ -48,7 +48,7 @@ describe('Ensure that invalid curves and animations error gracefully', () => { describe('Render function creators', () => { const names = Object.getOwnPropertyNames(drawers.RenderFunctionCreators); - const renderFuncCreators = names.reduce<[string, (pts: number) => RenderFunction][]>((res, name) => { + const renderFuncCreators = names.reduce<[string, RenderFunctionCreator][]>((res, name) => { if (typeof drawers.RenderFunctionCreators[name] !== 'function') return res; return [...res, [name, drawers.RenderFunctionCreators[name]]]; }, []); @@ -56,6 +56,24 @@ describe('Render function creators', () => { describe.each(renderFuncCreators)('%s', (name, func) => { test('name property is correct', () => { expect(func.name).toEqual(name); + + expect(func.isFullView).toEqual(func.name.includes('full_view')); + + if (func.name.includes('full_view_proportional')) { + expect(func.scaleMode).toEqual('fit'); + } else if (func.name.includes('full_view')) { + expect(func.scaleMode).toEqual('stretch'); + } else { + expect(func.scaleMode).toEqual('none'); + } + + if (func.name.includes('points')) { + expect(func.drawMode).toEqual('points'); + } else if (func.name.includes('connected')) { + expect(func.drawMode).toEqual('lines'); + } else { + throw new Error(`Unknown draw mode for render function creator: ${func.name}`); + } }); it('throws when numPoints is less than 0', () => { diff --git a/src/bundles/curve/src/drawers.ts b/src/bundles/curve/src/drawers.ts index b62404fab1..1aa95b4593 100644 --- a/src/bundles/curve/src/drawers.ts +++ b/src/bundles/curve/src/drawers.ts @@ -9,6 +9,7 @@ import { type CurveSpace, type DrawMode, type RenderFunction, + type RenderFunctionCreator, type ScaleMode } from './types'; @@ -23,7 +24,7 @@ function createDrawFunction( space: CurveSpace, isFullView: boolean, name: string -): (numPoints: number) => RenderFunction { +): RenderFunctionCreator { function renderFuncCreator(numPoints: number) { if (numPoints <= 0 || numPoints > 65535 || !Number.isInteger(numPoints)) { throw new Error( @@ -57,9 +58,8 @@ function createDrawFunction( return curveDrawn; } - // Because the draw functions are actually functions - // we need hacky workarounds like these to pass information around renderFunc.is3D = space === '3D'; + const stringifier = () => `<${space === '3D' ? '3D' : ''}RenderFunction(${numPoints})>`; // Retain both properties for compatibility @@ -70,6 +70,11 @@ function createDrawFunction( } Object.defineProperty(renderFuncCreator, 'name', { value: name }); + renderFuncCreator.scaleMode = scaleMode; + renderFuncCreator.drawMode = drawMode; + renderFuncCreator.space = space; + renderFuncCreator.isFullView = isFullView; + return renderFuncCreator; } @@ -139,10 +144,19 @@ export class RenderFunctionCreators { 'stretch', 'lines', '3D', - false, + true, 'draw_3D_connected_full_view' ); + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') + static draw_3D_connected_full_view_proportional = createDrawFunction( + 'fit', + 'lines', + '3D', + true, + 'draw_3D_connected_full_view_proportional' + ); + @functionDeclaration('numPoints: number', '(func: Curve) => Curve') static draw_3D_points = createDrawFunction('none', 'points', '3D', false, 'draw_3D_points'); @@ -317,7 +331,7 @@ export const draw_3D_connected_full_view = RenderFunctionCreators.draw_3D_connec * draw_3D_connected_full_view_proportional(100)(t => make_3D_point(t, t, t)); * ``` */ -export const draw_3D_connected_full_view_proportional = RenderFunctionCreators.draw_3D_points_full_view_proportional; +export const draw_3D_connected_full_view_proportional = RenderFunctionCreators.draw_3D_connected_full_view_proportional; /** * Returns a function that turns a given 3D Curve into a Drawing, by sampling diff --git a/src/bundles/curve/src/types.ts b/src/bundles/curve/src/types.ts index 1e151d5270..8499509f6a 100644 --- a/src/bundles/curve/src/types.ts +++ b/src/bundles/curve/src/types.ts @@ -26,6 +26,19 @@ export interface RenderFunction extends ReplResult { is3D: boolean; }; +/** + * A function that returns a {@link RenderFunction|RenderFunction} that is bound to + * the specified number of points + */ +export interface RenderFunctionCreator { + (numPoints: number): RenderFunction; + + scaleMode: ScaleMode; + drawMode: DrawMode; + space: CurveSpace; + isFullView: boolean; +} + export class AnimatedCurve extends glAnimation implements ReplResult { constructor( duration: number, From ef9a3670ae6bbac6404d6b712b9d3064ffb987eb Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Wed, 11 Feb 2026 23:12:50 +0800 Subject: [PATCH 37/71] Add a documentation section regarding checking callback parameters --- .../modules/2-bundle/4-conventions/1-basic.md | 2 +- .../2-bundle/4-conventions/3-errors.md | 72 +++++++++++++++++- .../2-bundle/4-conventions/argcount-error.png | Bin 0 -> 12338 bytes 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 docs/src/modules/2-bundle/4-conventions/argcount-error.png diff --git a/docs/src/modules/2-bundle/4-conventions/1-basic.md b/docs/src/modules/2-bundle/4-conventions/1-basic.md index 6178bc5dc2..f11e6a0c72 100644 --- a/docs/src/modules/2-bundle/4-conventions/1-basic.md +++ b/docs/src/modules/2-bundle/4-conventions/1-basic.md @@ -266,4 +266,4 @@ only be able to narrow the return type of your type guard to `boolean`. In such > [!TIP] Type Guards in Documentation > Type guards have a specific syntax for their return types (e.g. `value is null`) that isn't Source compliant. > These types get replaced with `boolean` when the documentation is generated, so you don't have to worry -> about type guard types appearing in your documentation. +> about type guard types appearing in your documentation. \ No newline at end of file diff --git a/docs/src/modules/2-bundle/4-conventions/3-errors.md b/docs/src/modules/2-bundle/4-conventions/3-errors.md index 7c12a40aec..c096587626 100644 --- a/docs/src/modules/2-bundle/4-conventions/3-errors.md +++ b/docs/src/modules/2-bundle/4-conventions/3-errors.md @@ -1,4 +1,4 @@ -# Error Handling +# Error Handling and Type Checking As a continuation of the previous section, and important part of hiding a bundle's implementation details involves handling error conditions and errors that could be thrown. @@ -100,3 +100,73 @@ all cadets would see. As the typing system is improved, we may be able to use one set of typing for cadets and another for internal implementation. ::: + +## Validating the number of expected parameters for callbacks + +By default, Javascript doesn't really mind if you call a function with fewer arguments than it was defined with: + +```js +function foo(x, y) { + return `${x}, ${y}`; +} + +foo(); // is fine, x and y are just `undefined` +``` + +Javascript also doesn't mind if you call a function with more arguments than it was defined with: + +```js +function foo(a, b) { + return a + b; +} + +foo(1, 2, 'z'); // is fine, 3 is returned, last parameter is ignored +``` + +However in Source, both of the above examples will result in evaluation errors like the one below: + +![](./argcount-error.png) + +Source doesn't allow for a mismatch between the number of arguments expected by a function and the number of arguments provided. + +Thus, if your bundle's functions take callback parameters, it is essential that you check that the provided callback accepts the +correct number of parameters. This is done with the `isFunctionOfLength` utility provided by `modules-lib`: + +```ts +import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; + +function draw_connected(pts: number): (c: Curve) => void { + function renderFunction(c: Curve) { + if (!isFunctionOfLength(curve, 1)) { + throw new Error( + `${renderFunction.name}: The provided curve is not a valid Curve function. ` + + 'A Curve function must take exactly one parameter (a number t between 0 and 1) ' + + 'and return a Point or 3D Point depending on whether it is a 2D or 3D curve.' + ); + } + + // ...implementation details + } + + return renderFunction +} + +``` + +Then, in Source, if the cadet provides an invalid curve (a function that takes only 1 parameter), an error is thrown: + +```js +import { draw_connected, make_point } from 'curve'; + +draw_connected(200)((a, b) => make_point(a, 0)); // error: The provided curve is not a valid Curve function. +``` + +The `isFunctionOfLength` function is a type guard that also checks if the given input is a function at all, so it is +not necessary to check for that separately: + +```ts +// A summarized implementation +function isFunctionOfLength(f: unknown, l: number): f is Function { + return typeof f === 'function' && f.length === l; +} +``` diff --git a/docs/src/modules/2-bundle/4-conventions/argcount-error.png b/docs/src/modules/2-bundle/4-conventions/argcount-error.png new file mode 100644 index 0000000000000000000000000000000000000000..ea044210264dde518ca60fa94cbe2f59edae4821 GIT binary patch literal 12338 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

-Lt+(R zr2?0&RkydPaXZr7+|i)`S(a@0l{V5flqA;Xk8@Fa8FjtB(}tinY{-ngY+i*5VOktR zXI485%+8bvKXRBA0j95!kau5dO|vN*?GiI{8)i2xINW~ zT}RZ}TaVkb-av@igjb2##OCu8th$)qqLV>?Pu0Z6vZjE}!`=C&JgtVE{kqS$I3 zI)=kE+c{@Cy7OfbT(@Y)q-jr;0rw{bThWcLy(%3g!px4r?xI}}3AEWvd&p*hZm+Q| zVhk&LbX-*RG+D?0Pa7mxJyd1mC(WDXumW~iyA%AZ25{L+lkB&RPlBtzdu{>bBg?`M z-x;wgsVYL0IX-I%357}J?(NQ=nt8XFONYa;)c9^5Gn&pvBPIrzomjFV?;Ga3PE*Qi z*@|g|mUUf4mCagD^MsydS=%=r+B^Xt)#2N$>!Tv6_WlOOt4l&b_x9P|9U$jImofa( zZO_hHqVni=tVHOtfSbg5oMs`ytA&$iFIqS&WzJu~0;(3Ge4NuZzR7zLFDoR0iX2Fn z49K|+XMTJCgwr!ootq`6+@99=)Oe~&`7rA=R?4g;(@2r4HmG$mDTC0~4QD|6x|M8AR9Tyer%2gujiL$$7KoIz+1J{2vda*NED0M0iq!^9%o@lh*LQvLOZ0|py ztcGjTR%`Nxj+S_b>A8!@@_~QET!C73)%iM4Dcas7slk*Ak?av#Ow$LBLCE1*e>qpF z<1iLB=2`;f%Dk`ko><)75+G>~Q0xQIXmnFJdr4fdCIkLa@Z61mtiuL193=nA7C4pl zzN;_T!QZoa`br&zS!diNlDRn<_I8VuQD&hxWJv_a<_$DQh+6CGES=vA8no7@O{JSW zRSf=^VafBY&m%hS7PH`8_<8v znl1%$_MLlV6VGR)XkIX%7H?_Ug2YF^vll$_ED5GmyQcIlPEZ*!tVIY;*B_2P=twRa zQuab-84AhXVrm)6zmK<2n6Rc8A_N5bGe-0fFk`*mr6fZ<%A|6v?wK>w~ed!NVsLEJs`MQo}T$3AghN440RF)!aHDD42PgS81S1NhzirUB-<1E zJL^J_*>mp%VJyERw)H_7EgVUbcVeSijvCFQ>1HM+PuS)z-kdEa5sKbE_UAJ_yQJC7 zaW2+3FDuDUH`Nh@)lD-bG=*r>&^gphC4PjdmaaDd+gM4@=fRuWv|_i!slf@AKn4@1z`g)I$@I@8DCJu#?M zXOu(KE$gGh^c*uSNXo(E0Q>^rR+her#7<#s6SmN1={keZo_~+U

@Dw107= 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 literal 0 HcmV?d00001 From 7af0cc1d74b8138dacfcb009072c68b0a93ed1b1 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Wed, 11 Feb 2026 23:13:11 +0800 Subject: [PATCH 38/71] Add overloads to the isFunctionOfLength callback --- lib/modules-lib/src/utilities.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/modules-lib/src/utilities.ts b/lib/modules-lib/src/utilities.ts index 3eddf6fbcb..da839938b8 100644 --- a/lib/modules-lib/src/utilities.ts +++ b/lib/modules-lib/src/utilities.ts @@ -71,6 +71,9 @@ export type ArrayOfLength = ArrayOfLengthHelper(f: unknown, l: T): f is (...args: ArrayOfLength) => unknown { +export function isFunctionOfLength any>(f: unknown, l: Parameters['length']): f is T +export function isFunctionOfLength(f: unknown, l: T): f is (...args: ArrayOfLength) => unknown +export function isFunctionOfLength(f: unknown, l: number) { + // TODO: Need a variation for rest parameters return typeof f === 'function' && f.length === l; } From 03c28677d148f993ebcd0527f23bd93fe843aff4 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 14 Feb 2026 15:40:40 +0800 Subject: [PATCH 39/71] Move type checking into its own section for docs --- docs/src/modules/2-bundle/3-editing.md | 2 +- .../modules/2-bundle/4-conventions/1-basic.md | 130 +------- .../2-bundle/4-conventions/3-errors.md | 120 +------- .../modules/2-bundle/4-conventions/4-types.md | 289 ++++++++++++++++++ .../modules/2-bundle/4-conventions/index.md | 1 + 5 files changed, 298 insertions(+), 244 deletions(-) create mode 100644 docs/src/modules/2-bundle/4-conventions/4-types.md diff --git a/docs/src/modules/2-bundle/3-editing.md b/docs/src/modules/2-bundle/3-editing.md index 7ae919975c..69272bea32 100644 --- a/docs/src/modules/2-bundle/3-editing.md +++ b/docs/src/modules/2-bundle/3-editing.md @@ -89,7 +89,7 @@ instructions on how to use them. ## Common Modules Library -There are common functions such as `hexToColor` available in the Common Modules Library. You can make use of these functions +There are common functions such as `hexToColor` available in the Common Modules Library (available as the `@sourceacademy/modules-lib` package). You can make use of these functions instead of implementing your own versions of them. ## Adding Unit Tests diff --git a/docs/src/modules/2-bundle/4-conventions/1-basic.md b/docs/src/modules/2-bundle/4-conventions/1-basic.md index f11e6a0c72..a01eb1a4ff 100644 --- a/docs/src/modules/2-bundle/4-conventions/1-basic.md +++ b/docs/src/modules/2-bundle/4-conventions/1-basic.md @@ -4,127 +4,7 @@ This section contains some conventions to follow when writing your bundle. [[toc]] -## 1. Cadet facing functions should not have default or rest parameters - -The function signature below takes in two booleans, the second of which is optional. This is not supported for Module functions in Source, but is fine if your function -isn't being exposed to cadets. - -```ts -// Don't expose this to cadets! -function configure_options(option_1: boolean, option_2: boolean = false) { - // ...implementation -} - -// or this -function concat_strings(...args: string[]) { - return args.join(','); -} - -// But default and rest parameters are okay for internal use -export function exposed_function() { - configure_options(true); - concat_strings('str1', 'str2'); -} -``` - -::: details Integration with `js-slang` -Neither default nor rest parameters are currently supported due to an [issue](https://github.com/source-academy/js-slang/issues/1238) on the `js-slang` side. -::: - -## 2. Cadet facing functions should not use destructuring for parameters - -Javascript allows us to destruct iterables directly within a function's parameters: - -```ts -export function foo([x, y]: [string, string]) { - return x; -} -``` - -There's nothing inherently wrong with this, but if cadets pass a non-iterable object into the function, -Javascript is going to throw a fairly mysterious error: - -```sh -foo(0); - -function foo([x, y]) { - ^ -TypeError: number 0 is not iterable (cannot read property Symbol(Symbol.iterator)) -``` - -Javascript also supports object destructuring in parameters: - -```ts -interface BarParams { - x: string; - y: string; -} - -function bar({ x, y }: BarParams) { - return x; -} -``` - -However, Javascript doesn't actually throw an error if you pass an invalid object into the function: - -```ts -function bar({ x, y }: BarParams) { - return x; -} - -console.log(bar(0)); // prints undefined -``` - -If an invalid argument gets passed, no error is thrown and the destructured values just take on the value of `undefined` (which you might want to check for). - -However, if you use nested destructuring, Javascript _will_ throw an error: - -```ts -interface Bar2Params { - x: { - a: string; - b: string; - }; -} - -function bar2({ x: { a, b } }: Bar2Params) { - return a; -} - -console.log(bar2(0)); -``` - -The call to `bar2` causes an error like the one below: - -```sh -Uncaught TypeError: Cannot read properties of undefined (reading 'a') - at bar2 (:1:21) - at :1:1 -``` - -because of course, when `bar2` is called with `0`, `x` becomes `undefined` and trying to destructure `undefined` causes the `TypeError`. - -If instead the parameter isn't destructured, it gives you the chance to perform type checking: - -```ts -export function foo(arr: [string, string]) { - if (!Array.isArray(arr)) throw new Error(); - return arr[0]; -} - -export function bar2(obj: Bar2Params) { - if (typeof obj !== 'object' || !('x' in obj)) { - // throw an error.... - } - - return obj.x; -} -``` - -> [!IMPORTANT] -> More information about throwing errors and why this kind of type checking is important can be found [here](./3-errors#source-type-checking). - -## 3. If your bundle requires specific Source features, make sure to indicate it in the manifest +## 1. If your bundle requires specific Source features, make sure to indicate it in the manifest Consider the bundle function below: @@ -169,7 +49,7 @@ Lists are actually introduced in Source 1, which would make the above function c functionality specific to arrays, then consider using Source Lists instead. ::: -## 4. Semantic Versioning +## 2. Semantic Versioning [Semantic Versioning](https://semver.org) refers to a convention on how version numbers should be specified. In your bundle's `package.json`, a `version` field should be specified: @@ -184,7 +64,7 @@ be specified: This version number should follow the rules of semantic versioning. `js-slang` will use this version number to determine if it currently has the latest version of your bundle compatible with its current version. -## 5. Making use of `js-slang` +## 3. Making use of `js-slang` Bundles, where necessary, should use the implementations from `js-slang`: @@ -214,7 +94,7 @@ Note that not every export from `js-slang` is currently supported. Below is the - `js-slang/dist/parser/parser` - `js-slang/dist/cse-machine/interpreter` -## 6. Cadet Facing Type Guard Conventions +## 4. Cadet Facing Type Guard Conventions A [type guard](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) is a function that checks if the provided object has the desired type. In Typescript, there are two kinds of type guards. Cadet facing type guards should favour the boolean returning form and should begin with the @@ -266,4 +146,4 @@ only be able to narrow the return type of your type guard to `boolean`. In such > [!TIP] Type Guards in Documentation > Type guards have a specific syntax for their return types (e.g. `value is null`) that isn't Source compliant. > These types get replaced with `boolean` when the documentation is generated, so you don't have to worry -> about type guard types appearing in your documentation. \ No newline at end of file +> about type guard types appearing in your documentation. diff --git a/docs/src/modules/2-bundle/4-conventions/3-errors.md b/docs/src/modules/2-bundle/4-conventions/3-errors.md index c096587626..7a60c5bbc8 100644 --- a/docs/src/modules/2-bundle/4-conventions/3-errors.md +++ b/docs/src/modules/2-bundle/4-conventions/3-errors.md @@ -1,4 +1,4 @@ -# Error Handling and Type Checking +# Error Handling As a continuation of the previous section, and important part of hiding a bundle's implementation details involves handling error conditions and errors that could be thrown. @@ -53,120 +53,4 @@ Then, the error can be thrown with the correct function name. Otherwise, cadets that is visible to them. Many other functions might rely on `throwIfNotRune`. If they were all called in the same program, it doesn't tell the cadet which function the error was thrown from (was it `show`? or `anaglyph`? or something else?) -## Source Type Checking - -Though bundles are written in Typescript, Source (except for the Typed Variant) does not support anything beyond rudimentary type checking. This means that it can determine that an expression -like `1 - "string"` is badly typed, but it can't type check more complex programs like the one below, especially when bundle functions are involved: - -```ts -import { show } from 'rune'; - -// Error: show expects a rune! -show(1); -``` - -::: details Type Maps -Source is moving toward enabling compile-time (or at least pre-execution since Source programs don't really have a "compilation" step) type checking for Source Modules using a feature known as [type maps](../7-type_map). -::: - -The above call to `show` **won't** a throw compile-time error. Instead, the error is thrown at runtime by bundle code or even in tab code. This is the case even if the function has been annotated with Typescript types. - -In the case of `show`, if no runtime type-checking was performed, no error would be thrown when `show` is called. The error only manifests itself when the Rune tab is displayed: - -![](./rune-error.png) - -This is not helpful for the cadet's debugging, as the error occurred in `show`. Thus, by checking if the passed parameter is indeed a `Rune` before -passing it on to other `rune` bundle functions, we make error tracing a lot simpler for cadets. - -::: details Use the `unknown` or `any` types? -In Typescript, the `any` and `unknown` types represent an object of an unknown type. More information can be found [here](https://www.typescriptlang.org/docs/handbook/type-compatibility.html#any-unknown-object-void-undefined-null-and-never-assignability). This is where type guards really shine, as they allow the compiler to "narrow" the object's type from being anything down to a specific type. In the case of -`show`, it would work like this: - -```ts -export function show(rune: unknown) { - // Compiler only knows that rune has type unknown - throwIfNotRune(show.name, rune); - - // Compiler is able to know that rune here has type Rune! - drawnRunes.push(new NormalRune(rune)); - return rune; -} -``` - -If we're expecting cadets to be able to pass any type of object in, why not use `unknown` in all these places? - -Currently, bundle documentation for cadets relies on these type annotations being present and properly typed. If everything were typed as `unknown`, that's -all cadets would see. - -As the typing system is improved, we may be able to use one set of typing for cadets and another for internal implementation. -::: - -## Validating the number of expected parameters for callbacks - -By default, Javascript doesn't really mind if you call a function with fewer arguments than it was defined with: - -```js -function foo(x, y) { - return `${x}, ${y}`; -} - -foo(); // is fine, x and y are just `undefined` -``` - -Javascript also doesn't mind if you call a function with more arguments than it was defined with: - -```js -function foo(a, b) { - return a + b; -} - -foo(1, 2, 'z'); // is fine, 3 is returned, last parameter is ignored -``` - -However in Source, both of the above examples will result in evaluation errors like the one below: - -![](./argcount-error.png) - -Source doesn't allow for a mismatch between the number of arguments expected by a function and the number of arguments provided. - -Thus, if your bundle's functions take callback parameters, it is essential that you check that the provided callback accepts the -correct number of parameters. This is done with the `isFunctionOfLength` utility provided by `modules-lib`: - -```ts -import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; - -function draw_connected(pts: number): (c: Curve) => void { - function renderFunction(c: Curve) { - if (!isFunctionOfLength(curve, 1)) { - throw new Error( - `${renderFunction.name}: The provided curve is not a valid Curve function. ` + - 'A Curve function must take exactly one parameter (a number t between 0 and 1) ' + - 'and return a Point or 3D Point depending on whether it is a 2D or 3D curve.' - ); - } - - // ...implementation details - } - - return renderFunction -} - -``` - -Then, in Source, if the cadet provides an invalid curve (a function that takes only 1 parameter), an error is thrown: - -```js -import { draw_connected, make_point } from 'curve'; - -draw_connected(200)((a, b) => make_point(a, 0)); // error: The provided curve is not a valid Curve function. -``` - -The `isFunctionOfLength` function is a type guard that also checks if the given input is a function at all, so it is -not necessary to check for that separately: - -```ts -// A summarized implementation -function isFunctionOfLength(f: unknown, l: number): f is Function { - return typeof f === 'function' && f.length === l; -} -``` +An important use for error handling is when it comes to validating types. More information about type checking can be found in the next section. diff --git a/docs/src/modules/2-bundle/4-conventions/4-types.md b/docs/src/modules/2-bundle/4-conventions/4-types.md new file mode 100644 index 0000000000..5d56877d58 --- /dev/null +++ b/docs/src/modules/2-bundle/4-conventions/4-types.md @@ -0,0 +1,289 @@ +--- +title: Developer Type Checking +--- + +# Developer Type Checking in Source + +Though bundles are written in Typescript, Source (except for the Typed Variant) does not support anything beyond rudimentary type checking. This means that it can determine that an expression +like `1 - "string"` is badly typed, but it can't type check more complex programs like the one below, especially when bundle functions are involved: + +```ts +import { show } from 'rune'; + +// Error: show expects a rune! +show(1); +``` + +::: details Type Maps +Source is moving toward enabling compile-time (or at least pre-execution since Source programs don't really have a "compilation" step) type checking for Source Modules using a feature known as [type maps](../7-type_map). +::: + +The above call to `show` **won't** a throw compile-time error. Instead, the error is thrown at runtime by bundle code or even in tab code. This is the case even if the function has been annotated with Typescript types. + +In the case of `show`, if no runtime type-checking was performed, no error would be thrown when `show` is called. The error only manifests itself when the Rune tab is displayed: + +![](./rune-error.png) + +This is not helpful for the cadet's debugging, as the error occurred in `show`. Thus, by checking if the passed parameter is indeed a `Rune` before +passing it on to other `rune` bundle functions, we make error tracing a lot simpler for cadets. + +::: details Use the `unknown` or `any` types? +In Typescript, the `any` and `unknown` types represent an object of an unknown type. More information can be found [here](https://www.typescriptlang.org/docs/handbook/type-compatibility.html#any-unknown-object-void-undefined-null-and-never-assignability). This is where type guards really shine, as they allow the compiler to "narrow" the object's type from being anything down to a specific type. In the case of +`show`, it would work like this: + +```ts +export function show(rune: unknown) { + // Compiler only knows that rune has type unknown + throwIfNotRune(show.name, rune); + + // Compiler is able to know that rune here has type Rune! + drawnRunes.push(new NormalRune(rune)); + return rune; +} +``` + +If we're expecting cadets to be able to pass any type of object in, why not use `unknown` in all these places? + +Currently, bundle documentation for cadets relies on these type annotations being present and properly typed. If everything were typed as `unknown`, that's +all cadets would see. + +As the typing system is improved, we may be able to use one set of typing for cadets and another for internal implementation. +::: + +As part of ensuring type safety, there are several conventions bundle code should abide by: + +## 1. Cadet facing functions should not have default or rest parameters + +The function signature below takes in two booleans, the second of which is optional. This is not supported for Module functions in Source, but is fine if your function +isn't being exposed to cadets. + +```ts +// Don't expose this to cadets! +function configure_options(option_1: boolean, option_2: boolean = false) { + // ...implementation +} + +// or this +function concat_strings(...args: string[]) { + return args.join(','); +} + +// But default and rest parameters are okay for internal use +export function exposed_function() { + configure_options(true); + concat_strings('str1', 'str2'); +} +``` + +::: details Integration with `js-slang` +Neither default nor rest parameters are currently supported due to an [issue](https://github.com/source-academy/js-slang/issues/1238) on the `js-slang` side. +::: + +## 2. Cadet facing functions should not use destructuring for parameters + +Javascript allows us to destruct iterables directly within a function's parameters: + +```ts +export function foo([x, y]: [string, string]) { + return x; +} +``` + +There's nothing inherently wrong with this, but if cadets pass a non-iterable object into the function, +Javascript is going to throw a fairly mysterious error: + +```sh +foo(0); + +function foo([x, y]) { + ^ +TypeError: number 0 is not iterable (cannot read property Symbol(Symbol.iterator)) +``` + +Javascript also supports object destructuring in parameters: + +```ts +interface BarParams { + x: string; + y: string; +} + +function bar({ x, y }: BarParams) { + return x; +} +``` + +However, Javascript doesn't actually throw an error if you pass an invalid object into the function: + +```ts +function bar({ x, y }: BarParams) { + return x; +} + +console.log(bar(0)); // prints undefined +``` + +If an invalid argument gets passed, no error is thrown and the destructured values just take on the value of `undefined` (which you might want to check for). + +However, if you use nested destructuring, Javascript _will_ throw an error: + +```ts +interface Bar2Params { + x: { + a: string; + b: string; + }; +} + +function bar2({ x: { a, b } }: Bar2Params) { + return a; +} + +console.log(bar2(0)); +``` + +The call to `bar2` causes an error like the one below: + +```sh +Uncaught TypeError: Cannot read properties of undefined (reading 'a') + at bar2 (:1:21) + at :1:1 +``` + +because of course, when `bar2` is called with `0`, `x` becomes `undefined` and trying to destructure `undefined` causes the `TypeError`. + +If instead the parameter isn't destructured, it gives you the chance to perform type checking: + +```ts +export function foo(arr: [string, string]) { + if (!Array.isArray(arr)) throw new Error(); + return arr[0]; +} + +export function bar2(obj: Bar2Params) { + if (typeof obj !== 'object' || !('x' in obj)) { + // throw an error.... + } + + return obj.x; +} +``` + + + +## 3. If a callback is passed as a parameter, its number of parameters should be validated + +By default, Javascript doesn't really mind if you call a function with fewer arguments than it was defined with: + +```js +function foo(x, y) { + return `${x}, ${y}`; +} + +foo(); // is fine, x and y are just `undefined` +``` + +Javascript also doesn't mind if you call a function with more arguments than it was defined with: + +```js +function foo(a, b) { + return a + b; +} + +foo(1, 2, 'z'); // is fine, 3 is returned, last parameter is ignored +``` + +However in Source, both of the above examples will result in evaluation errors like the one below: + +![](./argcount-error.png) + +This is because Source doesn't allow for a mismatch between the number of arguments expected by a function and the number of arguments provided. + +Thus, if your bundle's functions take callback parameters, it is essential that you check that the provided callback accepts the +correct number of parameters. This is done with the `isFunctionOfLength` utility provided by `modules-lib`: + +```ts +import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; + +function draw_connected(pts: number): (c: Curve) => void { + function renderFunction(c: Curve) { + if (!isFunctionOfLength(curve, 1)) { + throw new Error( + `${renderFunction.name}: The provided curve is not a valid Curve function. ` + + 'A Curve function must take exactly one parameter (a number t between 0 and 1) ' + + 'and return a Point or 3D Point depending on whether it is a 2D or 3D curve.' + ); + } + + // ...implementation details + } + + return renderFunction +} + +``` + +Then, in Source, if the cadet provides an invalid curve (a function that takes only 1 parameter), an error is thrown: + +```js +import { draw_connected, make_point } from 'curve'; + +draw_connected(200)((a, b) => make_point(a, 0)); // error: The provided curve is not a valid Curve function. +``` + +The `isFunctionOfLength` function is a type guard that also checks if the given input is a function at all, so it is +not necessary to check for that separately: + +```ts +// A summarized implementation +function isFunctionOfLength(f: unknown, l: number): f is Function { + return typeof f === 'function' && f.length === l; +} +``` + +### Limitations of `isFunctionOfLength` + +Of course, `isFunctionOfLength` can only guarantee that the object passed to it is indeed a function and that it takes +the specified number of parameters. It won't actually guarantee at runtime that the provided parameters are of the defined types. For example: + +```ts +export function call_callback(f: (a: string, b: string) => void) { + if (!isFunctionOfLength(f, 2)) { + throw new Error(); + } + + return f('a', 'b'); +} + +// isFunctionOfLength won't be able to guarantee that x and y are strings +call_callback((x, y) => x * y); +``` + +In fact, if you give it something of type `unknown`, the best it can do is narrow it down to a function that takes parameters of type `unknown` +and returns a value with type `unknown`: + +```ts +export function call_callback(f: unknown) { + if (!isFunctionOfLength(f, 2)) { + throw new Error(); + } + + // Then f here gets narrowed to (a: unknown, b: unknown) => unknown + return f('a', 'b'); +} +``` + +For such a case, you can provide the type you want to narrow to as a generic type parameter: + +```ts +type Callback = (a: string, b: string) => void; + +export function call_callback(f: unknown) { + if (!isFunctionOfLength(f, 2)) { + throw new Error(); + } + + // Then f here gets narrowed to Callback + return f('a', 'b'); +} +``` diff --git a/docs/src/modules/2-bundle/4-conventions/index.md b/docs/src/modules/2-bundle/4-conventions/index.md index 6d280a3d4e..3060a86725 100644 --- a/docs/src/modules/2-bundle/4-conventions/index.md +++ b/docs/src/modules/2-bundle/4-conventions/index.md @@ -7,3 +7,4 @@ List of pages: - [Basic Conventions](./1-basic) - [Handling Abstractions](./2-abstractions) - [Error Handling](./3-errors) +- [Type Checking](./4-types) From af5966b9c8ed1a7219c092cad553984289b41a77 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 14 Feb 2026 15:41:03 +0800 Subject: [PATCH 40/71] Add isFunctionOfLength utility function --- .../src/__tests__/utilities.test.ts | 23 +++++++++++++----- lib/modules-lib/src/utilities.ts | 24 +++++++++++-------- src/bundles/curve/src/__tests__/curve.test.ts | 2 +- src/bundles/curve/src/types.ts | 2 +- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/lib/modules-lib/src/__tests__/utilities.test.ts b/lib/modules-lib/src/__tests__/utilities.test.ts index 55c15071bf..c88833ca99 100644 --- a/lib/modules-lib/src/__tests__/utilities.test.ts +++ b/lib/modules-lib/src/__tests__/utilities.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, test } from 'vitest'; +import { assert, describe, expect, expectTypeOf, it, test } from 'vitest'; import { hexToColor, isFunctionOfLength } from '../utilities'; describe(hexToColor, () => { @@ -16,19 +16,30 @@ describe(hexToColor, () => { }); it('throws an error when an invalid hex string is passed', () => { - expect(() => hexToColor('GGGGGG')).toThrowErrorMatchingInlineSnapshot('[Error: Invalid color hex string: GGGGGG]'); + expect(() => hexToColor('GGGGGG')).toThrowErrorMatchingInlineSnapshot('[Error: hexToColor: Invalid color hex string: GGGGGG]'); }); }); describe(isFunctionOfLength, () => { it('correctly identifies functions with the specified number of parameters', () => { const func0 = () => { }; - expect(isFunctionOfLength(func0, 0)).toBe(true); + assert(isFunctionOfLength(func0, 0)); + expectTypeOf(func0).toEqualTypeOf<() => void>(); - const func1 = (_a: number) => { }; - expect(isFunctionOfLength(func1, 1)).toBe(true); + const func1 = (a: number) => a; + assert(isFunctionOfLength(func1, 1)); + expectTypeOf(func1).toEqualTypeOf<(a: number) => number>(); const func2 = (_a: number, _b: string) => { }; - expect(isFunctionOfLength(func2, 2)).toBe(true); + assert(isFunctionOfLength(func2, 2)); + expectTypeOf(func2).toEqualTypeOf<(a: number, b: string) => void>(); + + const func3: unknown = (_a: any) => {}; + if (isFunctionOfLength(func3, 1)) { + expectTypeOf(func3).toEqualTypeOf<(a: unknown) => unknown>(); + } else { + expectTypeOf(func3).toEqualTypeOf(); + throw new Error('Type guard failed unexpectedly'); + } }); }); diff --git a/lib/modules-lib/src/utilities.ts b/lib/modules-lib/src/utilities.ts index da839938b8..d17f224a5b 100644 --- a/lib/modules-lib/src/utilities.ts +++ b/lib/modules-lib/src/utilities.ts @@ -15,6 +15,11 @@ export function degreesToRadians(degrees: number): number { return (degrees / 360) * (2 * Math.PI); } +/** + * Converts an angle in radians into degrees + * @param degrees Angle in radians + * @returns Angle in degrees + */ export function radiansToDegrees(radians: number): number { return radians / Math.PI * 180; } @@ -24,14 +29,12 @@ export function radiansToDegrees(radians: number): number { * between 0 and 1. The leading `#` is optional. * @returns Tuple of three numbers representing the R, G and B components */ -export function hexToColor(hex: string, func_name?: string): [number, number, number] { +export function hexToColor(hex: string, func_name?: string): [r: number, g: number, b: number] { const regex = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/igu; const groups = regex.exec(hex); if (groups == undefined) { - if (func_name === undefined) { - throw new Error(`Invalid color hex string: ${hex}`); - } + func_name = func_name ?? hexToColor.name; throw new Error(`${func_name}: Invalid color hex string: ${hex}`); }; @@ -60,19 +63,20 @@ export function mockDebuggerContext(moduleState: T, name: string) { } as unknown as DebuggerContext; } -type ArrayOfLengthHelper = - V['length'] extends T ? V : ArrayOfLengthHelper; +type TupleOfLengthHelper = + V['length'] extends T ? V : TupleOfLengthHelper; /** * Utility type that represents a tuple of a specific length */ -export type ArrayOfLength = ArrayOfLengthHelper; +export type TupleOfLength = TupleOfLengthHelper; /** - * Type guard for checking that a function has the specified number of parameters. + * Type guard for checking that a function has the specified number of parameters. Of course at runtime parameter types + * are not checked, so this is only useful when combined with TypeScript types. */ -export function isFunctionOfLength any>(f: unknown, l: Parameters['length']): f is T -export function isFunctionOfLength(f: unknown, l: T): f is (...args: ArrayOfLength) => unknown +export function isFunctionOfLength any>(f: (...args: any) => any, l: Parameters['length']): f is T +export function isFunctionOfLength(f: unknown, l: T): f is (...args: TupleOfLength) => unknown export function isFunctionOfLength(f: unknown, l: number) { // TODO: Need a variation for rest parameters return typeof f === 'function' && f.length === l; diff --git a/src/bundles/curve/src/__tests__/curve.test.ts b/src/bundles/curve/src/__tests__/curve.test.ts index 8405cc3e0a..ae0ca283b9 100644 --- a/src/bundles/curve/src/__tests__/curve.test.ts +++ b/src/bundles/curve/src/__tests__/curve.test.ts @@ -94,7 +94,7 @@ describe('Render function creators', () => { ); }); - test('returned render functions have nice string represnentations', () => { + test('returned render functions have nice string representations', () => { const renderFunc = func(250); if (renderFunc.is3D) { expect(stringify(renderFunc)).toEqual('<3DRenderFunction(250)>'); diff --git a/src/bundles/curve/src/types.ts b/src/bundles/curve/src/types.ts index 8499509f6a..52ca36015e 100644 --- a/src/bundles/curve/src/types.ts +++ b/src/bundles/curve/src/types.ts @@ -19,7 +19,7 @@ export type CurveAnimation = (t: number) => Curve; /** * A function that specifies additional rendering information when taking in - * a CurveFunction and returns a ShapeDrawn based on its specifications. + * a {@link Curve|Curve} and returns a ShapeDrawn based on its specifications. */ export interface RenderFunction extends ReplResult { (func: Curve): CurveDrawn; From 8a8db528eec2e18a11ad44421c776496f474b1c2 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 14 Feb 2026 15:41:20 +0800 Subject: [PATCH 41/71] Update constraints file and node version --- package.json | 2 +- yarn.config.cjs | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 347933da59..d897aa29a5 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,7 @@ "devEngines": { "packageManager": { "name": "yarn", - "version": "^4.8.1", + "version": "^4.12.0", "onFail": "warn" }, "runtime": { diff --git a/yarn.config.cjs b/yarn.config.cjs index 0053916286..0b1278cee0 100644 --- a/yarn.config.cjs +++ b/yarn.config.cjs @@ -23,14 +23,14 @@ module.exports = defineConfig({ } } - // Make sure that if the dependency is defined in the root workspace - // that all child workspaces use the same version of that dependency const [rootWorkspace] = Yarn.workspaces({ ident: name }); // There should not be any resolutions value for js-slang, // which might be present if you linked js-slang to a local copy rootWorkspace.set('resolutions.js-slang', undefined); + // Make sure that if the dependency is defined in the root workspace + // that all child workspaces use the same version of that dependency for (const workspaceDep of Yarn.dependencies({ workspace: rootWorkspace })) { for (const otherDep of Yarn.dependencies({ ident: workspaceDep.ident })) { if (otherDep.type === 'peerDependencies') continue; @@ -49,6 +49,12 @@ module.exports = defineConfig({ ) { dep.update('workspace:^'); } + + // @types dependencies should be devDependencies, not dependencies + if (dep.ident.startsWith('@types') && dep.type === 'dependencies') { + dep.workspace.set(`devDependencies.${dep.ident}`, dep.range); + dep.update(undefined); + } } // Repotools should not be allowed to depend on any other packages in this From 9a35743b15fec1cf664b0dfc9507ba8c9c59461a Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:28:20 +0800 Subject: [PATCH 42/71] Bump dependencies --- yarn.lock | 2314 +++++++++++++++++++++++++---------------------------- 1 file changed, 1082 insertions(+), 1232 deletions(-) diff --git a/yarn.lock b/yarn.lock index cf5011f529..fc86f32dcd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -530,6 +530,17 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/code-frame@npm:7.29.0" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.28.5" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10c0/d34cc504e7765dfb576a663d97067afb614525806b5cad1a5cc1a7183b916fec8ff57fa233585e3926fd5a9e6b31aae6df91aa81ae9775fb7a28f658d3346f0d + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.27.2": version: 7.27.2 resolution: "@babel/compat-data@npm:7.27.2" @@ -537,6 +548,13 @@ __metadata: languageName: node linkType: hard +"@babel/compat-data@npm:^7.28.6": + version: 7.29.0 + resolution: "@babel/compat-data@npm:7.29.0" + checksum: 10c0/08f348554989d23aa801bf1405aa34b15e841c0d52d79da7e524285c77a5f9d298e70e11d91cc578d8e2c9542efc586d50c5f5cf8e1915b254a9dcf786913a94 + languageName: node + linkType: hard + "@babel/core@npm:^7.1.0, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.10": version: 7.27.1 resolution: "@babel/core@npm:7.27.1" @@ -560,26 +578,26 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/core@npm:7.28.5" +"@babel/core@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/core@npm:7.29.0" dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.28.5" - "@babel/helper-compilation-targets": "npm:^7.27.2" - "@babel/helper-module-transforms": "npm:^7.28.3" - "@babel/helpers": "npm:^7.28.4" - "@babel/parser": "npm:^7.28.5" - "@babel/template": "npm:^7.27.2" - "@babel/traverse": "npm:^7.28.5" - "@babel/types": "npm:^7.28.5" + "@babel/code-frame": "npm:^7.29.0" + "@babel/generator": "npm:^7.29.0" + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helpers": "npm:^7.28.6" + "@babel/parser": "npm:^7.29.0" + "@babel/template": "npm:^7.28.6" + "@babel/traverse": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" "@jridgewell/remapping": "npm:^2.3.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/535f82238027621da6bdffbdbe896ebad3558b311d6f8abc680637a9859b96edbf929ab010757055381570b29cf66c4a295b5618318d27a4273c0e2033925e72 + checksum: 10c0/5127d2e8e842ae409e11bcbb5c2dff9874abf5415e8026925af7308e903f4f43397341467a130490d1a39884f461bc2b67f3063bce0be44340db89687fd852aa languageName: node linkType: hard @@ -596,29 +614,16 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.28.3": - version: 7.28.3 - resolution: "@babel/generator@npm:7.28.3" +"@babel/generator@npm:^7.29.0": + version: 7.29.1 + resolution: "@babel/generator@npm:7.29.1" dependencies: - "@babel/parser": "npm:^7.28.3" - "@babel/types": "npm:^7.28.2" + "@babel/parser": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" "@jridgewell/gen-mapping": "npm:^0.3.12" "@jridgewell/trace-mapping": "npm:^0.3.28" jsesc: "npm:^3.0.2" - checksum: 10c0/0ff58bcf04f8803dcc29479b547b43b9b0b828ec1ee0668e92d79f9e90f388c28589056637c5ff2fd7bcf8d153c990d29c448d449d852bf9d1bc64753ca462bc - languageName: node - linkType: hard - -"@babel/generator@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/generator@npm:7.28.5" - dependencies: - "@babel/parser": "npm:^7.28.5" - "@babel/types": "npm:^7.28.5" - "@jridgewell/gen-mapping": "npm:^0.3.12" - "@jridgewell/trace-mapping": "npm:^0.3.28" - jsesc: "npm:^3.0.2" - checksum: 10c0/9f219fe1d5431b6919f1a5c60db8d5d34fe546c0d8f5a8511b32f847569234ffc8032beb9e7404649a143f54e15224ecb53a3d11b6bb85c3203e573d91fca752 + checksum: 10c0/349086e6876258ef3fb2823030fee0f6c0eb9c3ebe35fc572e16997f8c030d765f636ddc6299edae63e760ea6658f8ee9a2edfa6d6b24c9a80c917916b973551 languageName: node linkType: hard @@ -631,7 +636,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.27.1, @babel/helper-compilation-targets@npm:^7.27.2": +"@babel/helper-compilation-targets@npm:^7.27.1": version: 7.27.2 resolution: "@babel/helper-compilation-targets@npm:7.27.2" dependencies: @@ -644,6 +649,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-compilation-targets@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-compilation-targets@npm:7.28.6" + dependencies: + "@babel/compat-data": "npm:^7.28.6" + "@babel/helper-validator-option": "npm:^7.27.1" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10c0/3fcdf3b1b857a1578e99d20508859dbd3f22f3c87b8a0f3dc540627b4be539bae7f6e61e49d931542fe5b557545347272bbdacd7f58a5c77025a18b745593a50 + languageName: node + linkType: hard + "@babel/helper-create-class-features-plugin@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-create-class-features-plugin@npm:7.27.1" @@ -688,6 +706,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-imports@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-module-imports@npm:7.28.6" + dependencies: + "@babel/traverse": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10c0/b49d8d8f204d9dbfd5ac70c54e533e5269afb3cea966a9d976722b13e9922cc773a653405f53c89acb247d5aebdae4681d631a3ae3df77ec046b58da76eda2ac + languageName: node + linkType: hard + "@babel/helper-module-transforms@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-module-transforms@npm:7.27.1" @@ -701,16 +729,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.28.3": - version: 7.28.3 - resolution: "@babel/helper-module-transforms@npm:7.28.3" +"@babel/helper-module-transforms@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helper-module-transforms@npm:7.28.6" dependencies: - "@babel/helper-module-imports": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - "@babel/traverse": "npm:^7.28.3" + "@babel/helper-module-imports": "npm:^7.28.6" + "@babel/helper-validator-identifier": "npm:^7.28.5" + "@babel/traverse": "npm:^7.28.6" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/549be62515a6d50cd4cfefcab1b005c47f89bd9135a22d602ee6a5e3a01f27571868ada10b75b033569f24dc4a2bb8d04bfa05ee75c16da7ade2d0db1437fcdb + checksum: 10c0/6f03e14fc30b287ce0b839474b5f271e72837d0cafe6b172d759184d998fbee3903a035e81e07c2c596449e504f453463d58baa65b6f40a37ded5bec74620b2b languageName: node linkType: hard @@ -791,13 +819,13 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.28.4": - version: 7.28.4 - resolution: "@babel/helpers@npm:7.28.4" +"@babel/helpers@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/helpers@npm:7.28.6" dependencies: - "@babel/template": "npm:^7.27.2" - "@babel/types": "npm:^7.28.4" - checksum: 10c0/aaa5fb8098926dfed5f223adf2c5e4c7fbba4b911b73dfec2d7d3083f8ba694d201a206db673da2d9b3ae8c01793e795767654558c450c8c14b4c2175b4fcb44 + "@babel/template": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10c0/c4a779c66396bb0cf619402d92f1610601ff3832db2d3b86b9c9dd10983bf79502270e97ac6d5280cea1b1a37de2f06ecbac561bd2271545270407fbe64027cb languageName: node linkType: hard @@ -823,25 +851,25 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.28.3, @babel/parser@npm:^7.28.4": - version: 7.28.4 - resolution: "@babel/parser@npm:7.28.4" +"@babel/parser@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/parser@npm:7.28.5" dependencies: - "@babel/types": "npm:^7.28.4" + "@babel/types": "npm:^7.28.5" bin: parser: ./bin/babel-parser.js - checksum: 10c0/58b239a5b1477ac7ed7e29d86d675cc81075ca055424eba6485872626db2dc556ce63c45043e5a679cd925e999471dba8a3ed4864e7ab1dbf64306ab72c52707 + checksum: 10c0/5bbe48bf2c79594ac02b490a41ffde7ef5aa22a9a88ad6bcc78432a6ba8a9d638d531d868bd1f104633f1f6bba9905746e15185b8276a3756c42b765d131b1ef languageName: node linkType: hard -"@babel/parser@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/parser@npm:7.28.5" +"@babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/parser@npm:7.29.0" dependencies: - "@babel/types": "npm:^7.28.5" + "@babel/types": "npm:^7.29.0" bin: parser: ./bin/babel-parser.js - checksum: 10c0/5bbe48bf2c79594ac02b490a41ffde7ef5aa22a9a88ad6bcc78432a6ba8a9d638d531d868bd1f104633f1f6bba9905746e15185b8276a3756c42b765d131b1ef + checksum: 10c0/333b2aa761264b91577a74bee86141ef733f9f9f6d4fc52548e4847dc35dfbf821f58c46832c637bfa761a6d9909d6a68f7d1ed59e17e4ffbb958dc510c17b62 languageName: node linkType: hard @@ -1103,7 +1131,7 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.27.1, @babel/template@npm:^7.27.2, @babel/template@npm:^7.3.3": +"@babel/template@npm:^7.27.1, @babel/template@npm:^7.3.3": version: 7.27.2 resolution: "@babel/template@npm:7.27.2" dependencies: @@ -1114,6 +1142,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.28.6": + version: 7.28.6 + resolution: "@babel/template@npm:7.28.6" + dependencies: + "@babel/code-frame": "npm:^7.28.6" + "@babel/parser": "npm:^7.28.6" + "@babel/types": "npm:^7.28.6" + checksum: 10c0/66d87225ed0bc77f888181ae2d97845021838c619944877f7c4398c6748bcf611f216dfd6be74d39016af502bca876e6ce6873db3c49e4ac354c56d34d57e9f5 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.27.1": version: 7.27.1 resolution: "@babel/traverse@npm:7.27.1" @@ -1129,33 +1168,18 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.28.3": - version: 7.28.4 - resolution: "@babel/traverse@npm:7.28.4" +"@babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/traverse@npm:7.29.0" dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.28.3" + "@babel/code-frame": "npm:^7.29.0" + "@babel/generator": "npm:^7.29.0" "@babel/helper-globals": "npm:^7.28.0" - "@babel/parser": "npm:^7.28.4" - "@babel/template": "npm:^7.27.2" - "@babel/types": "npm:^7.28.4" + "@babel/parser": "npm:^7.29.0" + "@babel/template": "npm:^7.28.6" + "@babel/types": "npm:^7.29.0" debug: "npm:^4.3.1" - checksum: 10c0/ee678fdd49c9f54a32e07e8455242390d43ce44887cea6567b233fe13907b89240c377e7633478a32c6cf1be0e17c2f7f3b0c59f0666e39c5074cc47b968489c - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/traverse@npm:7.28.5" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.28.5" - "@babel/helper-globals": "npm:^7.28.0" - "@babel/parser": "npm:^7.28.5" - "@babel/template": "npm:^7.27.2" - "@babel/types": "npm:^7.28.5" - debug: "npm:^4.3.1" - checksum: 10c0/f6c4a595993ae2b73f2d4cd9c062f2e232174d293edd4abe1d715bd6281da8d99e47c65857e8d0917d9384c65972f4acdebc6749a7c40a8fcc38b3c7fb3e706f + checksum: 10c0/f63ef6e58d02a9fbf3c0e2e5f1c877da3e0bc57f91a19d2223d53e356a76859cbaf51171c9211c71816d94a0e69efa2732fd27ffc0e1bbc84b636e60932333eb languageName: node linkType: hard @@ -1179,33 +1203,23 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.28.2": - version: 7.28.2 - resolution: "@babel/types@npm:7.28.2" - dependencies: - "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - checksum: 10c0/24b11c9368e7e2c291fe3c1bcd1ed66f6593a3975f479cbb9dd7b8c8d8eab8a962b0d2fca616c043396ce82500ac7d23d594fbbbd013828182c01596370a0b10 - languageName: node - linkType: hard - -"@babel/types@npm:^7.28.4": - version: 7.28.4 - resolution: "@babel/types@npm:7.28.4" +"@babel/types@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/types@npm:7.28.5" dependencies: "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - checksum: 10c0/ac6f909d6191319e08c80efbfac7bd9a25f80cc83b43cd6d82e7233f7a6b9d6e7b90236f3af7400a3f83b576895bcab9188a22b584eb0f224e80e6d4e95f4517 + "@babel/helper-validator-identifier": "npm:^7.28.5" + checksum: 10c0/a5a483d2100befbf125793640dec26b90b95fd233a94c19573325898a5ce1e52cdfa96e495c7dcc31b5eca5b66ce3e6d4a0f5a4a62daec271455959f208ab08a languageName: node linkType: hard -"@babel/types@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/types@npm:7.28.5" +"@babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0": + version: 7.29.0 + resolution: "@babel/types@npm:7.29.0" dependencies: "@babel/helper-string-parser": "npm:^7.27.1" "@babel/helper-validator-identifier": "npm:^7.28.5" - checksum: 10c0/a5a483d2100befbf125793640dec26b90b95fd233a94c19573325898a5ce1e52cdfa96e495c7dcc31b5eca5b66ce3e6d4a0f5a4a62daec271455959f208ab08a + checksum: 10c0/23cc3466e83bcbfab8b9bd0edaafdb5d4efdb88b82b3be6728bbade5ba2f0996f84f63b1c5f7a8c0d67efded28300898a5f930b171bb40b311bca2029c4e9b4f languageName: node linkType: hard @@ -1216,21 +1230,22 @@ __metadata: languageName: node linkType: hard -"@blueprintjs/colors@npm:^5.1.12": - version: 5.1.12 - resolution: "@blueprintjs/colors@npm:5.1.12" +"@blueprintjs/colors@npm:^5.1.14": + version: 5.1.14 + resolution: "@blueprintjs/colors@npm:5.1.14" dependencies: tslib: "npm:~2.6.2" - checksum: 10c0/749a59646082c5605f12b095595e9662587dafcb2fdb253ba57131faa9ce829630bd1cb1709a53ef430ba5fc1159b375523a5a578c9f8ff644d7a0a2e5911a55 + checksum: 10c0/c4820ad88b6ce221c41b045df12d06c0ff56b6dad12f7e887c26706475f31aacb70a6c7854c98a6470aea0307745e892ada528f2c7b9d44296e3c2631aa541cd languageName: node linkType: hard "@blueprintjs/core@npm:^6.0.0": - version: 6.6.1 - resolution: "@blueprintjs/core@npm:6.6.1" + version: 6.8.0 + resolution: "@blueprintjs/core@npm:6.8.0" dependencies: - "@blueprintjs/colors": "npm:^5.1.12" - "@blueprintjs/icons": "npm:^6.5.0" + "@blueprintjs/colors": "npm:^5.1.14" + "@blueprintjs/icons": "npm:^6.5.2" + "@floating-ui/react": "npm:^0.27.13" "@popperjs/core": "npm:^2.11.8" classnames: "npm:^2.3.1" normalize.css: "npm:^8.0.1" @@ -1248,13 +1263,13 @@ __metadata: bin: upgrade-blueprint-2.0.0-rename: scripts/upgrade-blueprint-2.0.0-rename.sh upgrade-blueprint-3.0.0-rename: scripts/upgrade-blueprint-3.0.0-rename.sh - checksum: 10c0/a9f90ee376a3a1d16314160f853460d8b279514437deeb907844bebe9749d47a2cb3bcf1f5ff82df4c2f87f7b7ca4fb2e136d3ec8706c650e15cd39dd399c1c1 + checksum: 10c0/6b8b7c07bdec4208a7538575041f375249643463d633125c13645674ab0546bc7d39c65decd4ae09e34a959f82967545d50b5424ca21a9deef98638636280ae6 languageName: node linkType: hard -"@blueprintjs/icons@npm:^6.0.0, @blueprintjs/icons@npm:^6.5.0": - version: 6.5.0 - resolution: "@blueprintjs/icons@npm:6.5.0" +"@blueprintjs/icons@npm:^6.0.0, @blueprintjs/icons@npm:^6.5.2": + version: 6.5.2 + resolution: "@blueprintjs/icons@npm:6.5.2" dependencies: change-case: "npm:^4.1.2" classnames: "npm:^2.3.1" @@ -1266,7 +1281,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 10c0/ce911dec2d0d91e4ce1eccfd72d242c9484007f4399954f7783aad4c467ebed6ba3e97ce0c2ecce6e9432cdfb99c706ee59bd18acfc224b37792cdd3b724054f + checksum: 10c0/8db484ab22d61d86d37704207c84626bfbe95927b311d459d855add6150826a59f5b182d3042b0dd5c6241e1772164dce87f3b1ff356fd8840469518aaa9d773 languageName: node linkType: hard @@ -1372,15 +1387,6 @@ __metadata: languageName: node linkType: hard -"@commander-js/extra-typings@npm:^12.0.1": - version: 12.1.0 - resolution: "@commander-js/extra-typings@npm:12.1.0" - peerDependencies: - commander: ~12.1.0 - checksum: 10c0/5d29eaa724b577e2a52a393ad54992924d2559931b8e493ab892477b7a4e878e475c6bf771260f8585d835f7d8e17ae4a2656c191e9595d210ae0b48291c0b3d - languageName: node - linkType: hard - "@commander-js/extra-typings@npm:^14.0.0": version: 14.0.0 resolution: "@commander-js/extra-typings@npm:14.0.0" @@ -1390,108 +1396,125 @@ __metadata: languageName: node linkType: hard -"@cspell/cspell-bundled-dicts@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-bundled-dicts@npm:9.3.1" +"@cspell/cspell-bundled-dicts@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/cspell-bundled-dicts@npm:9.6.4" dependencies: "@cspell/dict-ada": "npm:^4.1.1" "@cspell/dict-al": "npm:^1.1.1" - "@cspell/dict-aws": "npm:^4.0.15" + "@cspell/dict-aws": "npm:^4.0.17" "@cspell/dict-bash": "npm:^4.2.2" - "@cspell/dict-companies": "npm:^3.2.7" - "@cspell/dict-cpp": "npm:^6.0.14" + "@cspell/dict-companies": "npm:^3.2.10" + "@cspell/dict-cpp": "npm:^7.0.2" "@cspell/dict-cryptocurrencies": "npm:^5.0.5" - "@cspell/dict-csharp": "npm:^4.0.7" - "@cspell/dict-css": "npm:^4.0.18" - "@cspell/dict-dart": "npm:^2.3.1" - "@cspell/dict-data-science": "npm:^2.0.11" - "@cspell/dict-django": "npm:^4.1.5" - "@cspell/dict-docker": "npm:^1.1.16" - "@cspell/dict-dotnet": "npm:^5.0.10" + "@cspell/dict-csharp": "npm:^4.0.8" + "@cspell/dict-css": "npm:^4.0.19" + "@cspell/dict-dart": "npm:^2.3.2" + "@cspell/dict-data-science": "npm:^2.0.13" + "@cspell/dict-django": "npm:^4.1.6" + "@cspell/dict-docker": "npm:^1.1.17" + "@cspell/dict-dotnet": "npm:^5.0.11" "@cspell/dict-elixir": "npm:^4.0.8" - "@cspell/dict-en-common-misspellings": "npm:^2.1.8" - "@cspell/dict-en-gb-mit": "npm:^3.1.14" - "@cspell/dict-en_us": "npm:^4.4.24" - "@cspell/dict-filetypes": "npm:^3.0.14" + "@cspell/dict-en-common-misspellings": "npm:^2.1.12" + "@cspell/dict-en-gb-mit": "npm:^3.1.17" + "@cspell/dict-en_us": "npm:^4.4.28" + "@cspell/dict-filetypes": "npm:^3.0.15" "@cspell/dict-flutter": "npm:^1.1.1" "@cspell/dict-fonts": "npm:^4.0.5" "@cspell/dict-fsharp": "npm:^1.1.1" - "@cspell/dict-fullstack": "npm:^3.2.7" + "@cspell/dict-fullstack": "npm:^3.2.8" "@cspell/dict-gaming-terms": "npm:^1.1.2" - "@cspell/dict-git": "npm:^3.0.7" - "@cspell/dict-golang": "npm:^6.0.24" + "@cspell/dict-git": "npm:^3.1.0" + "@cspell/dict-golang": "npm:^6.0.26" "@cspell/dict-google": "npm:^1.0.9" "@cspell/dict-haskell": "npm:^4.0.6" - "@cspell/dict-html": "npm:^4.0.12" - "@cspell/dict-html-symbol-entities": "npm:^4.0.4" + "@cspell/dict-html": "npm:^4.0.14" + "@cspell/dict-html-symbol-entities": "npm:^4.0.5" "@cspell/dict-java": "npm:^5.0.12" "@cspell/dict-julia": "npm:^1.1.1" "@cspell/dict-k8s": "npm:^1.0.12" "@cspell/dict-kotlin": "npm:^1.1.1" - "@cspell/dict-latex": "npm:^4.0.4" + "@cspell/dict-latex": "npm:^5.0.0" "@cspell/dict-lorem-ipsum": "npm:^4.0.5" "@cspell/dict-lua": "npm:^4.0.8" "@cspell/dict-makefile": "npm:^1.0.5" - "@cspell/dict-markdown": "npm:^2.0.12" - "@cspell/dict-monkeyc": "npm:^1.0.11" - "@cspell/dict-node": "npm:^5.0.8" - "@cspell/dict-npm": "npm:^5.2.20" - "@cspell/dict-php": "npm:^4.1.0" + "@cspell/dict-markdown": "npm:^2.0.14" + "@cspell/dict-monkeyc": "npm:^1.0.12" + "@cspell/dict-node": "npm:^5.0.9" + "@cspell/dict-npm": "npm:^5.2.32" + "@cspell/dict-php": "npm:^4.1.1" "@cspell/dict-powershell": "npm:^5.0.15" "@cspell/dict-public-licenses": "npm:^2.0.15" - "@cspell/dict-python": "npm:^4.2.21" + "@cspell/dict-python": "npm:^4.2.25" "@cspell/dict-r": "npm:^2.1.1" - "@cspell/dict-ruby": "npm:^5.0.9" - "@cspell/dict-rust": "npm:^4.0.12" - "@cspell/dict-scala": "npm:^5.0.8" + "@cspell/dict-ruby": "npm:^5.1.0" + "@cspell/dict-rust": "npm:^4.1.2" + "@cspell/dict-scala": "npm:^5.0.9" "@cspell/dict-shell": "npm:^1.1.2" - "@cspell/dict-software-terms": "npm:^5.1.11" + "@cspell/dict-software-terms": "npm:^5.1.20" "@cspell/dict-sql": "npm:^2.2.1" "@cspell/dict-svelte": "npm:^1.0.7" "@cspell/dict-swift": "npm:^2.0.6" "@cspell/dict-terraform": "npm:^1.1.3" "@cspell/dict-typescript": "npm:^3.2.3" "@cspell/dict-vue": "npm:^3.0.5" - checksum: 10c0/b0908ee774aebe01f50d7b187df53d27d45a40f69d5a50026d7387e45ca63966bc1eb3f61ecb23ba598fbc349027e613084017abdb8d27714c24e73a2c1b93e5 + "@cspell/dict-zig": "npm:^1.0.0" + checksum: 10c0/4f269089534f7c0e172327a1a81fd722185abbb8b80893e0e6a45ecceb652615935a759c28183fe66ff242e2b5804cdd3173510050506ca1a48b9d3dec416813 languageName: node linkType: hard -"@cspell/cspell-json-reporter@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-json-reporter@npm:9.3.1" +"@cspell/cspell-json-reporter@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/cspell-json-reporter@npm:9.6.4" dependencies: - "@cspell/cspell-types": "npm:9.3.1" - checksum: 10c0/e04ff6749865b985e34b1ec3b893d7098fcc5a6e4a765da722114552fda70188d4ec9ff2aa587cc765eaf190f3d0e88f2d79cc1ea81fa4a5b6d662e1a17b7b12 + "@cspell/cspell-types": "npm:9.6.4" + checksum: 10c0/07d2d4ed2d3ad21391f0597a82742c8a42e1a652f8802b86818f9cd88b7af8de738a9e067ea97c93630f0a082525695f387d0cd9eca7e4bb4129ca2530f8e334 languageName: node linkType: hard -"@cspell/cspell-pipe@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-pipe@npm:9.3.1" - checksum: 10c0/ebdc05b8ee7505c7ec4ad05269f769a80100807d137e45bfe332a384a4c3a82f2834e7a3cac31a4be68ff6cd6ecb78e930e30e54b7d485bb6bef39a3ca42de3d +"@cspell/cspell-performance-monitor@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/cspell-performance-monitor@npm:9.6.4" + checksum: 10c0/7dafc2880aba45e5b978f86a1e847106c766935a999165cacad3afadcce41f1838ba2a7ab1f3cc497dd1cf0bd8b4c58aa47a680b386ffa6d8ffab867c499d165 languageName: node linkType: hard -"@cspell/cspell-resolver@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-resolver@npm:9.3.1" +"@cspell/cspell-pipe@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/cspell-pipe@npm:9.6.4" + checksum: 10c0/cb27011b3591f56286ffaeace20709e73fedef4344f544cffa7a124da92330d950beaa6c99fe1e5f43497f1aebb4d5c6abd312bf19ef7ca8a561f6ecf953a168 + languageName: node + linkType: hard + +"@cspell/cspell-resolver@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/cspell-resolver@npm:9.6.4" dependencies: global-directory: "npm:^4.0.1" - checksum: 10c0/c154516ef6c209d0cbd8ee9c492088a5f06bfbe60e085df0d3e83ed2a5f898a498e721ece4b1743ef1bb6c51593dfebc57868d53d320a80bf850e7bc6ede91ab + checksum: 10c0/1901f995fb09a4a2b963b4eb88bb5da55d05aac0186f21292b0a9ea31ef6d184a21b92187929e718a421df27a6d85d3eb28081a15d43098c4bb197dfaed65b2e languageName: node linkType: hard -"@cspell/cspell-service-bus@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-service-bus@npm:9.3.1" - checksum: 10c0/142695d3d8d550ff93e7881a4b0ba58df4219a4106d5865a8f363151d030f7eb6e7a1f8ef1c867656479c3ed6c661bdf6d447494bb178a0c3f1beed6ba968767 +"@cspell/cspell-service-bus@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/cspell-service-bus@npm:9.6.4" + checksum: 10c0/93a8a69016fed7b03cfa70119b7b14fab543398063978e090767e65dc31509d9217940ddefe0ab311ff79768baa957ec67a152e6ac3e1f410461c69851202c4c languageName: node linkType: hard -"@cspell/cspell-types@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/cspell-types@npm:9.3.1" - checksum: 10c0/c1815480ab85d902cf722220e1b6b5f53dad61b861ca9a15c1141a0652edd38771857fd83f89b4174d64930acaaef50ab8135304d88823c935ea2093e02a3587 +"@cspell/cspell-types@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/cspell-types@npm:9.6.4" + checksum: 10c0/74d7913c9f7a53f0e3470ce05fa356f635ff2a39b84862f72c6ee37e1f1efe9c4559367a4507f97495b292d9359a5fa153bdb7439b8be38034d7f2b784af350c + languageName: node + linkType: hard + +"@cspell/cspell-worker@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/cspell-worker@npm:9.6.4" + dependencies: + cspell-lib: "npm:9.6.4" + checksum: 10c0/b317c29d290c9f61bd4899d293a2319943f38d1fd403cf0935644f30d957c633b212a66c5120cd6cc1534f1252d6f010ebd9c4805a85c79325a588b38a7ad1d3 languageName: node linkType: hard @@ -1509,10 +1532,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-aws@npm:^4.0.15": - version: 4.0.15 - resolution: "@cspell/dict-aws@npm:4.0.15" - checksum: 10c0/c5983f2e5ce3dd23d5b8ebc818cc963d9b2c91d9b8436b40491a46ebca4cb1bc7875237c443f6e883488ca66174e84bb804f8b6e37439b4ba6c2b52a146eaa20 +"@cspell/dict-aws@npm:^4.0.17": + version: 4.0.17 + resolution: "@cspell/dict-aws@npm:4.0.17" + checksum: 10c0/d421a78aee8cc3db78a0bdffad2ceda9ca8e476498398809f2975bae9f03233df1112e713f2d699239600a9019d5e8f11ca60dfcb49fdce56815d5e794285c7b languageName: node linkType: hard @@ -1525,17 +1548,17 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-companies@npm:^3.2.7": - version: 3.2.7 - resolution: "@cspell/dict-companies@npm:3.2.7" - checksum: 10c0/ba2e73974560dc61742c05c00ef75719a31f24e05ad7cfe01ed8eb4a614f8f0a4bb3a0b6cfd9bec6d02e746c490d5de4a3310cfc176461bb4d6de0751c868515 +"@cspell/dict-companies@npm:^3.2.10": + version: 3.2.10 + resolution: "@cspell/dict-companies@npm:3.2.10" + checksum: 10c0/56ffda78e90a417fb470d3296d17fa74c2b86f1f73de121b12ca9510f81663eea7c20923fe4409c9159eb20b9b36ff4cf4b6cbb1b4fab48da404ebe1ee855f7b languageName: node linkType: hard -"@cspell/dict-cpp@npm:^6.0.14": - version: 6.0.14 - resolution: "@cspell/dict-cpp@npm:6.0.14" - checksum: 10c0/d109ced99c9b673c57145bbcb4c20a471aac267edd9c418fefb49c78675f3c8e24a2d99834525055e80d2825ee932966edebd2e6641824261837a02e650f8bed +"@cspell/dict-cpp@npm:^7.0.2": + version: 7.0.2 + resolution: "@cspell/dict-cpp@npm:7.0.2" + checksum: 10c0/a2926a6e896f04aa795edcd5fe3ac72cf1e05b97719946388cf31cf91737cfee816ffdd220e1960af60d7049daa37262787e76534afa5479fe10691af096b54c languageName: node linkType: hard @@ -1546,52 +1569,52 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-csharp@npm:^4.0.7": - version: 4.0.7 - resolution: "@cspell/dict-csharp@npm:4.0.7" - checksum: 10c0/93afd6cfc973a5543120d1de2ee9cafbcbe64af6743e2ba3a8cfb0965fe19c85c6dee5a32c99a156cc979c8a89803b684e324ca92065b3a32faa7db786072e5e +"@cspell/dict-csharp@npm:^4.0.8": + version: 4.0.8 + resolution: "@cspell/dict-csharp@npm:4.0.8" + checksum: 10c0/b55dbe323b973e0e98d76a17205b103fbb52dec01d45d55aa06a14f1acc6c8bec259f7923bbe6138d1af2b11463969d920214ce0fc6e89eaf6fa08f86b10184e languageName: node linkType: hard -"@cspell/dict-css@npm:^4.0.18": - version: 4.0.18 - resolution: "@cspell/dict-css@npm:4.0.18" - checksum: 10c0/6d27fab2c1d2b023bdca93c2b013f69b2e782e2df444fed9406a0f9c1f2c84e6da5bfa9b7ae4c4e235498bbfd06a8822a6d6b228b5d3444fda8499d7a81dddfe +"@cspell/dict-css@npm:^4.0.19": + version: 4.0.19 + resolution: "@cspell/dict-css@npm:4.0.19" + checksum: 10c0/e0ba38ec536ce8a9b88a4afb197b9467622bd6519a84e71435e9f0d8d90d12d94f6e83d5e504337a95f6ce99ee398c920c6367c6252c6c01c794cba61b621bde languageName: node linkType: hard -"@cspell/dict-dart@npm:^2.3.1": - version: 2.3.1 - resolution: "@cspell/dict-dart@npm:2.3.1" - checksum: 10c0/40bbb2e20b761da0be513d3476db054211bfa5a514860569c0d46f3b869b782ef8d8118b4a30aa10b51dde280d22d5199988c9a89d2495742e660de8b5bb6792 +"@cspell/dict-dart@npm:^2.3.2": + version: 2.3.2 + resolution: "@cspell/dict-dart@npm:2.3.2" + checksum: 10c0/1c0842ff09785aaf2bc2e68f4c05ec5e20331f3fce1503ef5a87305feb223f6e23404c68e4991bb90c6473825a7f8cd65b3ed86eef0d8032d43b13558ddb1753 languageName: node linkType: hard -"@cspell/dict-data-science@npm:^2.0.11": - version: 2.0.11 - resolution: "@cspell/dict-data-science@npm:2.0.11" - checksum: 10c0/b273db0ce3306355ff75963610810055c517d2aa45ebd12a45b64e8b11de548e53ff980be7e7496c4f9b438a9737142399ff528c8cf1ffc22798fcc4f3fff42c +"@cspell/dict-data-science@npm:^2.0.13": + version: 2.0.13 + resolution: "@cspell/dict-data-science@npm:2.0.13" + checksum: 10c0/63d8291ef0e62defbf4b98e58bd1039747efdb6348fa64c128a01a0b28b93ce1724e878e945b1ca7d8f568a49446a46ed65ef71531130c7b1b1fddb5328a1a0e languageName: node linkType: hard -"@cspell/dict-django@npm:^4.1.5": - version: 4.1.5 - resolution: "@cspell/dict-django@npm:4.1.5" - checksum: 10c0/df51162b33c31ead2a983dc26face4b2d563382b082cbf13971593cec3687552d4e4e4af444beecb3b00baf1c28b5cb92944dba04de303d0864f7656a11b8921 +"@cspell/dict-django@npm:^4.1.6": + version: 4.1.6 + resolution: "@cspell/dict-django@npm:4.1.6" + checksum: 10c0/76f71cba5a692df48554a3cd7cff7e27df85ab826e2cddf0594c21062e5c96de3090508314659a9ec708913a4afd61afb0f044ae8c41a1ec573583d516056f2d languageName: node linkType: hard -"@cspell/dict-docker@npm:^1.1.16": - version: 1.1.16 - resolution: "@cspell/dict-docker@npm:1.1.16" - checksum: 10c0/0e2c211da4a8d6e23311bc41c4041bf447c5c7a4ab84afe3a0229d11fc0af19ec1f6f8fcfd9c6b6793b538a81026d3957e86f3999baba973520ffe84a9420014 +"@cspell/dict-docker@npm:^1.1.17": + version: 1.1.17 + resolution: "@cspell/dict-docker@npm:1.1.17" + checksum: 10c0/1aaa4ffba7842b9044d1c4c6ae704907e6be3d8407c7feb986b3b7efa2e0139fc2ea3c3ad955d7ba4c92b5f577e05648ffc00a2a27b76d2bb93acde431452e58 languageName: node linkType: hard -"@cspell/dict-dotnet@npm:^5.0.10": - version: 5.0.10 - resolution: "@cspell/dict-dotnet@npm:5.0.10" - checksum: 10c0/ddb368955d86059d6d59a82263769af832c90028e20c61cdc1e9ba25ac7de8465fd4da2f1966c4683d870720ef7138b937bdde994ac5e991aafc84e236f218b9 +"@cspell/dict-dotnet@npm:^5.0.11": + version: 5.0.11 + resolution: "@cspell/dict-dotnet@npm:5.0.11" + checksum: 10c0/02f13fade5845dc444ce71d20af52add1c4755191d2bd99b17706eba27d7ef52e5e09122a48ff560eb81e06c4da73ffa680bc599d04d2c79ababf92ac0cf96e8 languageName: node linkType: hard @@ -1602,31 +1625,31 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-en-common-misspellings@npm:^2.1.8": - version: 2.1.8 - resolution: "@cspell/dict-en-common-misspellings@npm:2.1.8" - checksum: 10c0/8a9a98216c81f018aa24e76e0e997ceeaff57f5bc97c2831c072085347f403fa2809ad6c6bc298b9127444155d83ac8da9d156df98f4f5313f1d978fddb1bb27 +"@cspell/dict-en-common-misspellings@npm:^2.1.12": + version: 2.1.12 + resolution: "@cspell/dict-en-common-misspellings@npm:2.1.12" + checksum: 10c0/5b7acd175ba76f164dcb5f5b7e910511dbd005bbab77fb5ae082603b01112d352af84bcd8d3ddef020db187b51056c4ce6a02dab8aebfcf0aa0dc416a66729a5 languageName: node linkType: hard -"@cspell/dict-en-gb-mit@npm:^3.1.14": - version: 3.1.14 - resolution: "@cspell/dict-en-gb-mit@npm:3.1.14" - checksum: 10c0/44f6f77bacbf8932470eeb75756cc68829be36dc19eddca2b91512fa57ddfb64e18f3a0b282cd20e496aba68b297cd962713ecf68811a7cac619652b2a5ecaad +"@cspell/dict-en-gb-mit@npm:^3.1.17": + version: 3.1.17 + resolution: "@cspell/dict-en-gb-mit@npm:3.1.17" + checksum: 10c0/634eb058d347f3d2f95d86b946cd5871d005b89f6d505c72b5515012596bf7c02fa6fc9b99d82038c4c28404991489a0b2c58c0a7ac305b20123f2409b710a7e languageName: node linkType: hard -"@cspell/dict-en_us@npm:^4.4.24": - version: 4.4.24 - resolution: "@cspell/dict-en_us@npm:4.4.24" - checksum: 10c0/bf38bc74753439265e80741a2312b539a36623d38ec816b0698e8e667ad291f6d3b1d4700121aab8539639a5a5f26e138f1e02a1864c72a04306bb6dd23dc3e5 +"@cspell/dict-en_us@npm:^4.4.28": + version: 4.4.28 + resolution: "@cspell/dict-en_us@npm:4.4.28" + checksum: 10c0/b1defb0f68db71139d45a7323d4edd168788740d958014931d8295633524b3f8ad16385415c1760d2e81d653674d177083a12044ce5bb59f3c68cb3aedb69b40 languageName: node linkType: hard -"@cspell/dict-filetypes@npm:^3.0.14": - version: 3.0.14 - resolution: "@cspell/dict-filetypes@npm:3.0.14" - checksum: 10c0/cc51a1099e331021b2be77f7aaa554a6e4e3d9af9443c48a59903867f44ea4553056b130c965d4b599191b7c9a72d86aa151f6a76bdcdad7004d34a3050a8ab5 +"@cspell/dict-filetypes@npm:^3.0.15": + version: 3.0.15 + resolution: "@cspell/dict-filetypes@npm:3.0.15" + checksum: 10c0/2bf7c592fbe4755dfff8375fbe422b0ac6c0daebc71d4641141611520aeb67e043e9016075b7855513306b594980a6b55af2069e10848256493fcb39a34d0725 languageName: node linkType: hard @@ -1651,10 +1674,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-fullstack@npm:^3.2.7": - version: 3.2.7 - resolution: "@cspell/dict-fullstack@npm:3.2.7" - checksum: 10c0/81e19f537553f243fa2ede72cbaf727f71c64ea769952c6bea20d82492b9199761677e1107683abd225dcbd6233bf0502c8faf7ec9be65538fdca2a7138bdf3f +"@cspell/dict-fullstack@npm:^3.2.8": + version: 3.2.8 + resolution: "@cspell/dict-fullstack@npm:3.2.8" + checksum: 10c0/90a469b899574bee9fff390e4264cc72468847b4c53fb2bc5991874e7b65c8d949c693615953d836a8b7cba69c5690163d722c07126c0ca3bd798197a86c64e6 languageName: node linkType: hard @@ -1665,17 +1688,17 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-git@npm:^3.0.7": - version: 3.0.7 - resolution: "@cspell/dict-git@npm:3.0.7" - checksum: 10c0/db22c7a8eeca4c36fba9fdeae440bfdf0d4fd7ca2aaebe06b8b895273ea93eb48f00bb3216146e2d8e595226ad96668095f6ffa0f80f88ccdd450054aca5f12c +"@cspell/dict-git@npm:^3.1.0": + version: 3.1.0 + resolution: "@cspell/dict-git@npm:3.1.0" + checksum: 10c0/161a9bd35f44173993c84ec2bc394c5fab4fe7d69070daa170be4922e295d60a3e34cecb04869a8b685b761c7ace83241ff4d60db93d2850368d769733a58de9 languageName: node linkType: hard -"@cspell/dict-golang@npm:^6.0.24": - version: 6.0.24 - resolution: "@cspell/dict-golang@npm:6.0.24" - checksum: 10c0/2d6e63e606215db7c29fe312d2414da585372d7c994ce1ba2808a4bf13c5410b0e4318efda9b2ccaab020a3bbc6d8f06c910dbd1a5cc24946ff7e378ffbb591b +"@cspell/dict-golang@npm:^6.0.26": + version: 6.0.26 + resolution: "@cspell/dict-golang@npm:6.0.26" + checksum: 10c0/514c54dc72620975e552ad91ecc8d98143611224e7fe3606fc6041f3248e9f9457be1f25027ff1d9bc2961459c5759dff3a01251054aab83bbcc9f927648b755 languageName: node linkType: hard @@ -1693,17 +1716,17 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-html-symbol-entities@npm:^4.0.4": - version: 4.0.4 - resolution: "@cspell/dict-html-symbol-entities@npm:4.0.4" - checksum: 10c0/ff6be66c36845409622b732f010c5c7a3680c759fba55d136be5556f505bd7e7daee85834b2b9aae54c90a6f6b4055a1b39d49a5976c04226fa80f9238fa48a1 +"@cspell/dict-html-symbol-entities@npm:^4.0.5": + version: 4.0.5 + resolution: "@cspell/dict-html-symbol-entities@npm:4.0.5" + checksum: 10c0/8278b8cca06e6d3654e81b1809227ff1d64e053f79308966ea601194ce51fa3a385dde6844509b26223de70d034e60a85c604a729f021c0de63f8a5e6f29b0ce languageName: node linkType: hard -"@cspell/dict-html@npm:^4.0.12": - version: 4.0.12 - resolution: "@cspell/dict-html@npm:4.0.12" - checksum: 10c0/de3d7197859502e2bb7be4206a881cd53bc6b30516cd181116bbe83c9698da34ebaf7e8da2d62afe925bd0cc3a8abb16aea3794eb3a916a83dc1e915c7b6b49f +"@cspell/dict-html@npm:^4.0.14": + version: 4.0.14 + resolution: "@cspell/dict-html@npm:4.0.14" + checksum: 10c0/8dedb8a20f7bc53db4b933ae118ee0ab654b176648b2451d335ca8bd266f84ce8deb52989aa51a52f872730262e113b73874b88320b115ab2e993876a3f24cb1 languageName: node linkType: hard @@ -1735,10 +1758,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-latex@npm:^4.0.4": - version: 4.0.4 - resolution: "@cspell/dict-latex@npm:4.0.4" - checksum: 10c0/5050b8b8bede9970224a12ac1b613acf735ef36121acad61a891f28ff2aa5e60ffc2392ad502f7de107a2af485f8fb73e611ba6ac169b41f06101bffd4897aca +"@cspell/dict-latex@npm:^5.0.0": + version: 5.0.0 + resolution: "@cspell/dict-latex@npm:5.0.0" + checksum: 10c0/02d0d3d4a14eba96de6f4f6b51b3f2d1ac1d2de7b1069e3ae6631bdbc53982caead563abb2a568d436fa016bf99aea36d0e6e2c3b9a83c1e9fe9ccbc923d5da7 languageName: node linkType: hard @@ -1763,43 +1786,43 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-markdown@npm:^2.0.12": - version: 2.0.12 - resolution: "@cspell/dict-markdown@npm:2.0.12" +"@cspell/dict-markdown@npm:^2.0.14": + version: 2.0.14 + resolution: "@cspell/dict-markdown@npm:2.0.14" peerDependencies: - "@cspell/dict-css": ^4.0.18 - "@cspell/dict-html": ^4.0.12 - "@cspell/dict-html-symbol-entities": ^4.0.4 + "@cspell/dict-css": ^4.0.19 + "@cspell/dict-html": ^4.0.14 + "@cspell/dict-html-symbol-entities": ^4.0.5 "@cspell/dict-typescript": ^3.2.3 - checksum: 10c0/f6d53e71525dff0832950345118abcb2c2ca01aaff51922c5c18f7c3bc0d84a2168bb9bb3e400fe6b91312a5892d0b608db6ea590e2a785474ad355e60d9b535 + checksum: 10c0/2198375545579fe4aac7b2a53ae4125bee212fa489be5d19193b227308c3e5c687bfc140111c6263bf2d5a7963eb07f2e4b6c737b2de733fc4e0cf3b2123ece2 languageName: node linkType: hard -"@cspell/dict-monkeyc@npm:^1.0.11": - version: 1.0.11 - resolution: "@cspell/dict-monkeyc@npm:1.0.11" - checksum: 10c0/856b7107b2eb70925bf7388f6961548c205b9580298ce28352644b5d20b4779b7d0f8d3ea6888f15aceb124c4bafd51ec896cc55d73cea6853c01a37ee4b97b6 +"@cspell/dict-monkeyc@npm:^1.0.12": + version: 1.0.12 + resolution: "@cspell/dict-monkeyc@npm:1.0.12" + checksum: 10c0/97250565f808cbf37d66f2585db7accf449bc1836c72b3fac0449896fe17b8dfa3e5dc15f27f4e5cbe61dc7c24e9b17c1d7f475c934cd7c68b1aa597386a5bc0 languageName: node linkType: hard -"@cspell/dict-node@npm:^5.0.8": - version: 5.0.8 - resolution: "@cspell/dict-node@npm:5.0.8" - checksum: 10c0/aaca1c73dc9451171716dbbff0e243a4f4bcba7260875b50a582cca5db70415b7cddaf60443814880da59967433b5934b4a830b9dc69c90fa4f9c06b2f2d8063 +"@cspell/dict-node@npm:^5.0.9": + version: 5.0.9 + resolution: "@cspell/dict-node@npm:5.0.9" + checksum: 10c0/129fa7cd204e26769829912a8a64225af45b5cf0438f597329966e1c3db5ffca04b4c426d9cee594f271d14500e11319bc7ed371207cb18d73966000303e3072 languageName: node linkType: hard -"@cspell/dict-npm@npm:^5.2.20": - version: 5.2.20 - resolution: "@cspell/dict-npm@npm:5.2.20" - checksum: 10c0/cf06d77311d3c8665140ec7a8f7cdf23fbc049385d687acf689231548e68dd629ce107e3f8f4f7a99e3d8fdaf58c1a2a3e6e20a30c5d41752c7494500953f274 +"@cspell/dict-npm@npm:^5.2.32": + version: 5.2.32 + resolution: "@cspell/dict-npm@npm:5.2.32" + checksum: 10c0/a7de85d0b7b079d7bd37771b4c2e3e773485d5c51e2d30fb9b20823acd31903b6d24c8549d20b14d444d2281158773c0760cb3afbc929d85651744b51483c29f languageName: node linkType: hard -"@cspell/dict-php@npm:^4.1.0": - version: 4.1.0 - resolution: "@cspell/dict-php@npm:4.1.0" - checksum: 10c0/ff9227e9ada98f949d543ffd653b88638079b429040a6b1ef69ff7845dcaf4d4854d5303459e32a5aa306d0f87871848db72ed8ec335ede30bfae642c65e4e66 +"@cspell/dict-php@npm:^4.1.1": + version: 4.1.1 + resolution: "@cspell/dict-php@npm:4.1.1" + checksum: 10c0/e11e2a3799b2c9ea590ce8b2e69838965f3d8f83020961720afde9c9c57b6ccdb013d54346900766ccf422c548c916dd2aaa890563d36cf12498ad3ddfe67d7a languageName: node linkType: hard @@ -1817,12 +1840,12 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-python@npm:^4.2.21": - version: 4.2.21 - resolution: "@cspell/dict-python@npm:4.2.21" +"@cspell/dict-python@npm:^4.2.25": + version: 4.2.25 + resolution: "@cspell/dict-python@npm:4.2.25" dependencies: - "@cspell/dict-data-science": "npm:^2.0.11" - checksum: 10c0/138818ba2890983d0a96eda2ac659edc459b051f8d89889e3f3b0104c13aa4f02e1848200fe4d952e8b39d05cf179faabf600306e5a7e870146d05fe89fd3131 + "@cspell/dict-data-science": "npm:^2.0.13" + checksum: 10c0/dcab0aac0075f76b0360fd07d61b4421f543e72a98a482494f9a3decb650d475f4508918c85ef8985eeabac11431bf7f67b496491d58a33cf41c25a6016e84a9 languageName: node linkType: hard @@ -1833,24 +1856,24 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-ruby@npm:^5.0.9": - version: 5.0.9 - resolution: "@cspell/dict-ruby@npm:5.0.9" - checksum: 10c0/7a63495fd12d787de9f4f72f070110b26fc3709394fb19bdcac44354ef886c0ff998ad03b90d0d3b252019d112ef34ebf99c94329070978f7d92fd4642dda4b5 +"@cspell/dict-ruby@npm:^5.1.0": + version: 5.1.0 + resolution: "@cspell/dict-ruby@npm:5.1.0" + checksum: 10c0/d9ca8a8d72869b37b201fd5d17d1e7d0094185dde559861b899256b7dd55e80aedba430ac2ca393d0db479c284cc89cd2eec8f9e56e5601ebd715f0463c75b7d languageName: node linkType: hard -"@cspell/dict-rust@npm:^4.0.12": - version: 4.0.12 - resolution: "@cspell/dict-rust@npm:4.0.12" - checksum: 10c0/023f9844e32e6d22aaaf0f23a9744671a66f1d46c47f08efbe7a74e7a6e1e8671a7c394e1fb15d2b840fdbf605c55b693c539b29ad0eb10908c4bd6f7f4b2231 +"@cspell/dict-rust@npm:^4.1.2": + version: 4.1.2 + resolution: "@cspell/dict-rust@npm:4.1.2" + checksum: 10c0/ccee1ef1652f8855f2fee1c5b7c173eda9660f0c7f1eadb550ab2e4e8e2ee2e31eee903e294a32052996fed4045907b0a53383f6fe74d28a04de94a4ac69a29d languageName: node linkType: hard -"@cspell/dict-scala@npm:^5.0.8": - version: 5.0.8 - resolution: "@cspell/dict-scala@npm:5.0.8" - checksum: 10c0/9ae598e1dbd49554df8e6b22f8590393408690ae644ece4c28ec05c267d11cf90a6f25e088eca5a666e7e56fcd165c20511dd51ec8370a038d8bd485b77e0758 +"@cspell/dict-scala@npm:^5.0.9": + version: 5.0.9 + resolution: "@cspell/dict-scala@npm:5.0.9" + checksum: 10c0/f6b214f4cebcb68a270f4e5cb4163fdd59b58afb28894ac6f523025f411792454c6645c0c616d00af10ea541d5fbd25d34ad7986ddef1bb2181003e39140abbe languageName: node linkType: hard @@ -1861,10 +1884,10 @@ __metadata: languageName: node linkType: hard -"@cspell/dict-software-terms@npm:^5.1.11": - version: 5.1.11 - resolution: "@cspell/dict-software-terms@npm:5.1.11" - checksum: 10c0/a997043e401c444762c4cfdbe0093d8155c02360338f62bb26b0b5a3ae5341eaa942edbb750f694a8023b322855abb6d36a464d538d3d71939dec5c9c08e1635 +"@cspell/dict-software-terms@npm:^5.1.20": + version: 5.1.20 + resolution: "@cspell/dict-software-terms@npm:5.1.20" + checksum: 10c0/ff7513919d842bdb804965852d35aded3a2e32b3535637d7e9ec57fce66ddf69af57d20947bb3db358abe2d0d8e5d0feee029e3e14d1fb66b235d519d5133115 languageName: node linkType: hard @@ -1910,34 +1933,48 @@ __metadata: languageName: node linkType: hard -"@cspell/dynamic-import@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/dynamic-import@npm:9.3.1" +"@cspell/dict-zig@npm:^1.0.0": + version: 1.0.0 + resolution: "@cspell/dict-zig@npm:1.0.0" + checksum: 10c0/bc302e117002c9d6ebfb5d3e085d9a6f2e65d63440deb9f137dce1d8a75650593f5b83d47488ab394cfbc173be032661dc36bc74c85b9826f60a7d2fc7955ffc + languageName: node + linkType: hard + +"@cspell/dynamic-import@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/dynamic-import@npm:9.6.4" dependencies: - "@cspell/url": "npm:9.3.1" + "@cspell/url": "npm:9.6.4" import-meta-resolve: "npm:^4.2.0" - checksum: 10c0/b112cb7b9ed940950331e1cd125050270705a20b5f99a59d4976fffdb32e0f2229aea9e53a0839a8df074c395ee32f16934f39f43d416783a40dc017ce63af55 + checksum: 10c0/b425752c7d7f421a84c45a753760fac63d58a89b4e47453c62024f404090563a0f8b12788fe41b274670ca5c7ff50532a88788839d87b1b6c9f92e8ebb29a423 languageName: node linkType: hard -"@cspell/filetypes@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/filetypes@npm:9.3.1" - checksum: 10c0/80731da70f516dc21e2b6c91f170e854e85af3c2a0135b840977f19a8a73baa784a8a8ac9b702c21d3b5786cb5f8550473a1b6089ea053f8d31f4b2ac634bcae +"@cspell/filetypes@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/filetypes@npm:9.6.4" + checksum: 10c0/f79b096698b671219f92497bab85ffc3bdbeff722717436ff58a07ee4b66e286ac2d6df309a55bf1bed3d96c877bf26a601b049724feadf8693741b661156685 languageName: node linkType: hard -"@cspell/strong-weak-map@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/strong-weak-map@npm:9.3.1" - checksum: 10c0/c07c1a1dd0fc5c9529a14b3dac7ed6b07e209de5d3d8e948fb602f5d36d41e6aebfcb45fb475ca5ecdfebb6ec341cb820fcf2ee6975fb777dee240e37f460996 +"@cspell/rpc@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/rpc@npm:9.6.4" + checksum: 10c0/a0ccfb54e14bbdfbf7b2f3e1a7a1f090025ebd7fc1a057885d483481d5940a9b22d60ba98d027e3c3c58dc5f5ec3943772a5c7b628361844ba519137d99ab155 languageName: node linkType: hard -"@cspell/url@npm:9.3.1": - version: 9.3.1 - resolution: "@cspell/url@npm:9.3.1" - checksum: 10c0/01a6f1a3fba08bc09f8b3deace3fcfe40b40ef52959e92f5500737f8942c2d3aeb2fc95286031ac570e5dbd57ccca355b911937ed92c3183502b9197ea7e27bf +"@cspell/strong-weak-map@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/strong-weak-map@npm:9.6.4" + checksum: 10c0/934c7fe9a40856d6c482534c584bd277b7549745128ac270c70a79b5afe9fd3ed23fb574bb89789914788ffebc957cb3ccbf9d6bbb304a67d9c51f30ed2c970c + languageName: node + linkType: hard + +"@cspell/url@npm:9.6.4": + version: 9.6.4 + resolution: "@cspell/url@npm:9.6.4" + checksum: 10c0/289c76fbd7724a7b1d278701fd716bc5ee90b04c5ea6b1287756a1965894c4673ab41a8516bbec54e179624a932ba994e50dc7e9c9f03b499581d0efbbbff6df languageName: node linkType: hard @@ -2086,16 +2123,16 @@ __metadata: languageName: node linkType: hard -"@es-joy/jsdoccomment@npm:~0.79.0": - version: 0.79.0 - resolution: "@es-joy/jsdoccomment@npm:0.79.0" +"@es-joy/jsdoccomment@npm:~0.84.0": + version: 0.84.0 + resolution: "@es-joy/jsdoccomment@npm:0.84.0" dependencies: "@types/estree": "npm:^1.0.8" - "@typescript-eslint/types": "npm:^8.52.0" - comment-parser: "npm:1.4.1" + "@typescript-eslint/types": "npm:^8.54.0" + comment-parser: "npm:1.4.5" esquery: "npm:^1.7.0" - jsdoc-type-pratt-parser: "npm:~7.0.0" - checksum: 10c0/f5102197cf02bede52115f38569c7de2eee82096fe2c81a6d678f24796cd82f60d074ea19d3b9dd9dc1c55b3cafdd05e1b70595ef4eb6198c2a4b405313127d9 + jsdoc-type-pratt-parser: "npm:~7.1.1" + checksum: 10c0/b5562c176dde36cd2956bb115b79229d2253b27d6d7e52820eb55c509f75a72048ae8ea8d57193b33be42728c1aa7a5ee20937b4967175291cb4ae60fdda318d languageName: node linkType: hard @@ -2113,16 +2150,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/aix-ppc64@npm:0.25.4" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/aix-ppc64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/aix-ppc64@npm:0.27.0" +"@esbuild/aix-ppc64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/aix-ppc64@npm:0.27.3" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard @@ -2134,16 +2164,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/android-arm64@npm:0.25.4" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/android-arm64@npm:0.27.0" +"@esbuild/android-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/android-arm64@npm:0.27.3" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -2155,16 +2178,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/android-arm@npm:0.25.4" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/android-arm@npm:0.27.0" +"@esbuild/android-arm@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/android-arm@npm:0.27.3" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -2176,16 +2192,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/android-x64@npm:0.25.4" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/android-x64@npm:0.27.0" +"@esbuild/android-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/android-x64@npm:0.27.3" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -2197,16 +2206,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/darwin-arm64@npm:0.25.4" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/darwin-arm64@npm:0.27.0" +"@esbuild/darwin-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/darwin-arm64@npm:0.27.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -2218,16 +2220,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/darwin-x64@npm:0.25.4" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/darwin-x64@npm:0.27.0" +"@esbuild/darwin-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/darwin-x64@npm:0.27.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -2239,16 +2234,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/freebsd-arm64@npm:0.25.4" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/freebsd-arm64@npm:0.27.0" +"@esbuild/freebsd-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/freebsd-arm64@npm:0.27.3" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -2260,16 +2248,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/freebsd-x64@npm:0.25.4" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/freebsd-x64@npm:0.27.0" +"@esbuild/freebsd-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/freebsd-x64@npm:0.27.3" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -2281,16 +2262,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/linux-arm64@npm:0.25.4" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/linux-arm64@npm:0.27.0" +"@esbuild/linux-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-arm64@npm:0.27.3" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -2302,16 +2276,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/linux-arm@npm:0.25.4" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/linux-arm@npm:0.27.0" +"@esbuild/linux-arm@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-arm@npm:0.27.3" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -2323,16 +2290,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/linux-ia32@npm:0.25.4" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/linux-ia32@npm:0.27.0" +"@esbuild/linux-ia32@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-ia32@npm:0.27.3" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -2344,16 +2304,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/linux-loong64@npm:0.25.4" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/linux-loong64@npm:0.27.0" +"@esbuild/linux-loong64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-loong64@npm:0.27.3" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -2365,16 +2318,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/linux-mips64el@npm:0.25.4" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/linux-mips64el@npm:0.27.0" +"@esbuild/linux-mips64el@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-mips64el@npm:0.27.3" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -2386,16 +2332,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/linux-ppc64@npm:0.25.4" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/linux-ppc64@npm:0.27.0" +"@esbuild/linux-ppc64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-ppc64@npm:0.27.3" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -2407,16 +2346,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/linux-riscv64@npm:0.25.4" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/linux-riscv64@npm:0.27.0" +"@esbuild/linux-riscv64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-riscv64@npm:0.27.3" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -2428,16 +2360,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/linux-s390x@npm:0.25.4" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/linux-s390x@npm:0.27.0" +"@esbuild/linux-s390x@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-s390x@npm:0.27.3" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -2449,30 +2374,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/linux-x64@npm:0.25.4" +"@esbuild/linux-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-x64@npm:0.27.3" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/linux-x64@npm:0.27.0" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/netbsd-arm64@npm:0.25.4" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/netbsd-arm64@npm:0.27.0" +"@esbuild/netbsd-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/netbsd-arm64@npm:0.27.3" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard @@ -2484,30 +2395,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/netbsd-x64@npm:0.25.4" +"@esbuild/netbsd-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/netbsd-x64@npm:0.27.3" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/netbsd-x64@npm:0.27.0" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/openbsd-arm64@npm:0.25.4" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/openbsd-arm64@npm:0.27.0" +"@esbuild/openbsd-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/openbsd-arm64@npm:0.27.3" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard @@ -2519,23 +2416,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/openbsd-x64@npm:0.25.4" +"@esbuild/openbsd-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/openbsd-x64@npm:0.27.3" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/openbsd-x64@npm:0.27.0" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openharmony-arm64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/openharmony-arm64@npm:0.27.0" +"@esbuild/openharmony-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/openharmony-arm64@npm:0.27.3" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard @@ -2547,16 +2437,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/sunos-x64@npm:0.25.4" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/sunos-x64@npm:0.27.0" +"@esbuild/sunos-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/sunos-x64@npm:0.27.3" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -2568,16 +2451,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/win32-arm64@npm:0.25.4" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/win32-arm64@npm:0.27.0" +"@esbuild/win32-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/win32-arm64@npm:0.27.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -2589,16 +2465,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/win32-ia32@npm:0.25.4" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/win32-ia32@npm:0.27.0" +"@esbuild/win32-ia32@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/win32-ia32@npm:0.27.3" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -2610,16 +2479,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.25.4": - version: 0.25.4 - resolution: "@esbuild/win32-x64@npm:0.25.4" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.27.0": - version: 0.27.0 - resolution: "@esbuild/win32-x64@npm:0.27.0" +"@esbuild/win32-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/win32-x64@npm:0.27.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2715,10 +2577,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.39.1": - version: 9.39.1 - resolution: "@eslint/js@npm:9.39.1" - checksum: 10c0/6f7f26f8cdb7ad6327bbf9741973b6278eb946f18f70e35406e88194b0d5c522d0547a34a02f2a208eec95c5d1388cdf7ccb20039efd2e4cb6655615247a50f1 +"@eslint/js@npm:9.39.2": + version: 9.39.2 + resolution: "@eslint/js@npm:9.39.2" + checksum: 10c0/00f51c52b04ac79faebfaa65a9652b2093b9c924e945479f1f3945473f78aee83cbc76c8d70bbffbf06f7024626575b16d97b66eab16182e1d0d39daff2f26f5 languageName: node linkType: hard @@ -2773,16 +2635,68 @@ __metadata: languageName: node linkType: hard -"@gerrit0/mini-shiki@npm:^3.12.0": - version: 3.15.0 - resolution: "@gerrit0/mini-shiki@npm:3.15.0" +"@floating-ui/core@npm:^1.7.4": + version: 1.7.4 + resolution: "@floating-ui/core@npm:1.7.4" + dependencies: + "@floating-ui/utils": "npm:^0.2.10" + checksum: 10c0/b1175d92c0edbd0053c4ba014ad1f798ccc107de87a43a099e97af6265610cc25ef600f2b15d3763d39a79f7d36db11fcb84d0c28027beb3317e13a7ba197516 + languageName: node + linkType: hard + +"@floating-ui/dom@npm:^1.7.5": + version: 1.7.5 + resolution: "@floating-ui/dom@npm:1.7.5" + dependencies: + "@floating-ui/core": "npm:^1.7.4" + "@floating-ui/utils": "npm:^0.2.10" + checksum: 10c0/94bd262127fbf1177e542f4908cb07c17392782b1ca0ab9f2dfd7e102cabcc77b4de807847304dcb4c864d4b48e8ba292b27cdcfaca3ad4e3525ab397b766a3a + languageName: node + linkType: hard + +"@floating-ui/react-dom@npm:^2.1.7": + version: 2.1.7 + resolution: "@floating-ui/react-dom@npm:2.1.7" + dependencies: + "@floating-ui/dom": "npm:^1.7.5" + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 10c0/3ef4a53ac93d2757e7995ce0313b3c14c5c5c66f2cb893256cc70c74713ff1c192f88a1bde02e2f50e951a7a3d8513b14611a4dbcc2d313def1f7003f7296dba + languageName: node + linkType: hard + +"@floating-ui/react@npm:^0.27.13": + version: 0.27.17 + resolution: "@floating-ui/react@npm:0.27.17" + dependencies: + "@floating-ui/react-dom": "npm:^2.1.7" + "@floating-ui/utils": "npm:^0.2.10" + tabbable: "npm:^6.0.0" + peerDependencies: + react: ">=17.0.0" + react-dom: ">=17.0.0" + checksum: 10c0/0233eccc59bbcce18ff042b129821c3e025b79a1c57947ed8463cadbb514c46e516c963cca18e9b73ee2e96648f209026e83b9b9171043466e319facfa181660 + languageName: node + linkType: hard + +"@floating-ui/utils@npm:^0.2.10": + version: 0.2.10 + resolution: "@floating-ui/utils@npm:0.2.10" + checksum: 10c0/e9bc2a1730ede1ee25843937e911ab6e846a733a4488623cd353f94721b05ec2c9ec6437613a2ac9379a94c2fd40c797a2ba6fa1df2716f5ce4aa6ddb1cf9ea4 + languageName: node + linkType: hard + +"@gerrit0/mini-shiki@npm:^3.17.0": + version: 3.21.0 + resolution: "@gerrit0/mini-shiki@npm:3.21.0" dependencies: - "@shikijs/engine-oniguruma": "npm:^3.15.0" - "@shikijs/langs": "npm:^3.15.0" - "@shikijs/themes": "npm:^3.15.0" - "@shikijs/types": "npm:^3.15.0" + "@shikijs/engine-oniguruma": "npm:^3.21.0" + "@shikijs/langs": "npm:^3.21.0" + "@shikijs/themes": "npm:^3.21.0" + "@shikijs/types": "npm:^3.21.0" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10c0/8d0d9591267a634a09a8d1abafa92d6fc83385470ff008945b2f370223eb91682d6356e13481499bf824c42ae4b4393cfa16c30103c52161ec25a9559e39c87b + checksum: 10c0/4045d19854abfa4515381a04af07096c1de07471b029ee090375652d0199ed3fed6165a22bd9f8e8250c609124d8c05f5d4604eb6de87cf13513aa89cfb8d14e languageName: node linkType: hard @@ -2824,12 +2738,12 @@ __metadata: languageName: node linkType: hard -"@iconify-json/logos@npm:^1.2.9": - version: 1.2.9 - resolution: "@iconify-json/logos@npm:1.2.9" +"@iconify-json/logos@npm:^1.2.10": + version: 1.2.10 + resolution: "@iconify-json/logos@npm:1.2.10" dependencies: "@iconify/types": "npm:*" - checksum: 10c0/7f5e2c8026560fb63489566cfc90497375543ca3649e7c7d13079f0a166dc4a738cf5686ec66a4cb9a319b8213303bc7c5ae74070e88d4bf0e5c1ef57cb3bacc + checksum: 10c0/0d9722cfd1bf333e3b1fe164b4e148d3420f8e809c392dad79846e16f336eef33e18cd6b18c09d38f8d4d4854892b1a8c19a334bb7a4e3d36d1825c1669cc6e9 languageName: node linkType: hard @@ -2842,12 +2756,12 @@ __metadata: languageName: node linkType: hard -"@iconify-json/vscode-icons@npm:^1.2.32": - version: 1.2.33 - resolution: "@iconify-json/vscode-icons@npm:1.2.33" +"@iconify-json/vscode-icons@npm:^1.2.39": + version: 1.2.40 + resolution: "@iconify-json/vscode-icons@npm:1.2.40" dependencies: "@iconify/types": "npm:*" - checksum: 10c0/b55c3b263643d08a5e7ef9d35e1dd63c11c911b86e344cfaa8e7fe639bdbf5940ca4164d05f2ec5de89627c934bec4e93a4be480be2c3bcc3ade9c57fd119073 + checksum: 10c0/29dce75c16279709cffac19bfffb0d80b19046bc5ffedb172dd00a3d80f34d741ee2b8aacbc053ac8f59f6f9ce066e6e76fd649743d68aa503cb7605432ec091 languageName: node linkType: hard @@ -2858,7 +2772,7 @@ __metadata: languageName: node linkType: hard -"@iconify/utils@npm:^3.0.1, @iconify/utils@npm:^3.0.2": +"@iconify/utils@npm:^3.0.1": version: 3.0.2 resolution: "@iconify/utils@npm:3.0.2" dependencies: @@ -2874,6 +2788,33 @@ __metadata: languageName: node linkType: hard +"@iconify/utils@npm:^3.1.0": + version: 3.1.0 + resolution: "@iconify/utils@npm:3.1.0" + dependencies: + "@antfu/install-pkg": "npm:^1.1.0" + "@iconify/types": "npm:^2.0.0" + mlly: "npm:^1.8.0" + checksum: 10c0/a39445e892b248486c186306e1ccba4b07ed1d5b21b143ddf279b33062063173feb84954b9a82e05713b927872787d6c0081073d23f55c44294de37615d4a1f7 + languageName: node + linkType: hard + +"@isaacs/balanced-match@npm:^4.0.1": + version: 4.0.1 + resolution: "@isaacs/balanced-match@npm:4.0.1" + checksum: 10c0/7da011805b259ec5c955f01cee903da72ad97c5e6f01ca96197267d3f33103d5b2f8a1af192140f3aa64526c593c8d098ae366c2b11f7f17645d12387c2fd420 + languageName: node + linkType: hard + +"@isaacs/brace-expansion@npm:^5.0.1": + version: 5.0.1 + resolution: "@isaacs/brace-expansion@npm:5.0.1" + dependencies: + "@isaacs/balanced-match": "npm:^4.0.1" + checksum: 10c0/e5d67c7bbf1f17b88132a35bc638af306d48acbb72810d48fa6e6edd8ab375854773108e8bf70f021f7ef6a8273455a6d1f0c3b5aa2aff06ce7894049ab77fb8 + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -2888,6 +2829,13 @@ __metadata: languageName: node linkType: hard +"@isaacs/cliui@npm:^9.0.0": + version: 9.0.0 + resolution: "@isaacs/cliui@npm:9.0.0" + checksum: 10c0/971063b7296419f85053dacd0a0285dcadaa3dfc139228b23e016c1a9848121ad4aa5e7fcca7522062014e1eb6239a7424188b9f2cba893a79c90aae5710319c + languageName: node + linkType: hard + "@isaacs/fs-minipass@npm:^4.0.0": version: 4.0.1 resolution: "@isaacs/fs-minipass@npm:4.0.1" @@ -2953,13 +2901,6 @@ __metadata: languageName: node linkType: hard -"@joeychenofficial/alt-ergo-modified@npm:^2.4.0": - version: 2.4.0 - resolution: "@joeychenofficial/alt-ergo-modified@npm:2.4.0" - checksum: 10c0/b6587dac0a76331602984ed61e482c2f7af2920d7069c873024bbc7575809ef440c7b91a7fb9a144b54abe98dd1d38a942e57f4476a0736a661c79bd66c176fa - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.12": version: 0.3.12 resolution: "@jridgewell/gen-mapping@npm:0.3.12" @@ -3855,10 +3796,10 @@ __metadata: languageName: node linkType: hard -"@rolldown/pluginutils@npm:1.0.0-beta.47": - version: 1.0.0-beta.47 - resolution: "@rolldown/pluginutils@npm:1.0.0-beta.47" - checksum: 10c0/eb0cfa7334d66f090c47eaac612174936b05f26e789352428cb6e03575b590f355de30d26b42576ea4e613d8887b587119d19b2e4b3a8909ceb232ca1cf746c8 +"@rolldown/pluginutils@npm:1.0.0-rc.2": + version: 1.0.0-rc.2 + resolution: "@rolldown/pluginutils@npm:1.0.0-rc.2" + checksum: 10c0/35d3dec35e00ab090d5ff8287e27af98a15da897dc8b034fe0e00d03e0931b9e993603c054be9e8925e2bde040c44c18b48cb8aeea6a261fd1c8f46837038927 languageName: node linkType: hard @@ -4069,15 +4010,15 @@ __metadata: languageName: node linkType: hard -"@shikijs/core@npm:3.20.0": - version: 3.20.0 - resolution: "@shikijs/core@npm:3.20.0" +"@shikijs/core@npm:3.22.0": + version: 3.22.0 + resolution: "@shikijs/core@npm:3.22.0" dependencies: - "@shikijs/types": "npm:3.20.0" + "@shikijs/types": "npm:3.22.0" "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" hast-util-to-html: "npm:^9.0.5" - checksum: 10c0/3df490754e631bf71723aec921de623d0e464c868bccafda89cdb1f061b968ee56385f5709d7401213773dc0c36d9650db436492bd2fa13eac4cf50255f12d26 + checksum: 10c0/4df376f5fa0afaeaa458ba08db1d8a6ad15cb11c7351edc4cabf7e87453a1b1859ded083fdfe8020ac697a47f9a180fd655783be33d2602c9dbaa4cc950b8e13 languageName: node linkType: hard @@ -4092,14 +4033,14 @@ __metadata: languageName: node linkType: hard -"@shikijs/engine-javascript@npm:3.20.0": - version: 3.20.0 - resolution: "@shikijs/engine-javascript@npm:3.20.0" +"@shikijs/engine-javascript@npm:3.22.0": + version: 3.22.0 + resolution: "@shikijs/engine-javascript@npm:3.22.0" dependencies: - "@shikijs/types": "npm:3.20.0" + "@shikijs/types": "npm:3.22.0" "@shikijs/vscode-textmate": "npm:^10.0.2" oniguruma-to-es: "npm:^4.3.4" - checksum: 10c0/52ee46eba86bd0e4f5ca9520736a17e5a052830685edb319d77a2929ca30bcd176353212b9978d680109fd93d7e13c9ad5b039b69223d817a6331fc9f88389f2 + checksum: 10c0/344dee8fd866743ecb762d3f954414d3dec17e31a6c2c5b778abdff320b8c68ff87ef661a46969c1fb34d84c2f55a696159cde2f64576407419664b9fa8dd97b languageName: node linkType: hard @@ -4113,23 +4054,23 @@ __metadata: languageName: node linkType: hard -"@shikijs/engine-oniguruma@npm:3.20.0": - version: 3.20.0 - resolution: "@shikijs/engine-oniguruma@npm:3.20.0" +"@shikijs/engine-oniguruma@npm:3.22.0": + version: 3.22.0 + resolution: "@shikijs/engine-oniguruma@npm:3.22.0" dependencies: - "@shikijs/types": "npm:3.20.0" + "@shikijs/types": "npm:3.22.0" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10c0/4a5a8f316a8482e799cd836c8e3f8ba83274b3631b2d66ec82ad839b0ee1dd3df50a08480f791d59f22e42bf6b707032f043a9f651445efc04e59b7ec9e669c9 + checksum: 10c0/21007cc1f2c714f37a53e163e1d604e6696d310f9e252970a828fe5450e4daa9f1f369b7ceffd1cb9cde348d9ca17e8a4d14180749ac052c74d104cab86834ea languageName: node linkType: hard -"@shikijs/engine-oniguruma@npm:^3.15.0": - version: 3.15.0 - resolution: "@shikijs/engine-oniguruma@npm:3.15.0" +"@shikijs/engine-oniguruma@npm:^3.21.0": + version: 3.21.0 + resolution: "@shikijs/engine-oniguruma@npm:3.21.0" dependencies: - "@shikijs/types": "npm:3.15.0" + "@shikijs/types": "npm:3.21.0" "@shikijs/vscode-textmate": "npm:^10.0.2" - checksum: 10c0/97cb43d1f3fbace9f5412e516ab87ad38b529550bb696891a518efcefa32680a0b625a17e1fe8db6cf2b1e6e252db7ac408e3294375ec0600a9b07e4e482ca7c + checksum: 10c0/cb17c034b04e1333f90f267081b7fac0b53e56031f7d067723363a72cdbdf79e567dea216bbcae38a6d4b910570c2dd60a953ca941f4834768c0bb721131af5f languageName: node linkType: hard @@ -4142,21 +4083,21 @@ __metadata: languageName: node linkType: hard -"@shikijs/langs@npm:3.20.0": - version: 3.20.0 - resolution: "@shikijs/langs@npm:3.20.0" +"@shikijs/langs@npm:3.22.0": + version: 3.22.0 + resolution: "@shikijs/langs@npm:3.22.0" dependencies: - "@shikijs/types": "npm:3.20.0" - checksum: 10c0/6830460025d0df4c527ffeacf0a78cd4331ffde1cfcd1e8028aa9814be8a4cea84367dd938528a9b55de72b163c58ad3576915ea08c3d0a29ef1dc80e120116c + "@shikijs/types": "npm:3.22.0" + checksum: 10c0/68bb7b10a4b8d78540d0518b80b4c57e42ac232e84a5f74a91d6335de80af730008cf269b4c3da46a2fd3c4a59cd427ab1e6f5934c884335f9f648f8c0c0a912 languageName: node linkType: hard -"@shikijs/langs@npm:^3.15.0": - version: 3.15.0 - resolution: "@shikijs/langs@npm:3.15.0" +"@shikijs/langs@npm:^3.21.0": + version: 3.21.0 + resolution: "@shikijs/langs@npm:3.21.0" dependencies: - "@shikijs/types": "npm:3.15.0" - checksum: 10c0/d5a328ec999572f50e4fec77213e7d0f106c90c04e078be29cdb2467f10012221d52435fd9711f963ce30adbf14805d2a31a2e602fa7a074fa450bbf83553eca + "@shikijs/types": "npm:3.21.0" + checksum: 10c0/79cfc2b8ac1f5c938bfb18db6233f86ca96948970068c2cc94559e30abac2036c35a2ae52015d07f72b6decfd6b2ae86321f9547ae0f994b6131e362781fbf1f languageName: node linkType: hard @@ -4169,21 +4110,21 @@ __metadata: languageName: node linkType: hard -"@shikijs/themes@npm:3.20.0": - version: 3.20.0 - resolution: "@shikijs/themes@npm:3.20.0" +"@shikijs/themes@npm:3.22.0": + version: 3.22.0 + resolution: "@shikijs/themes@npm:3.22.0" dependencies: - "@shikijs/types": "npm:3.20.0" - checksum: 10c0/d6fc059c51c3c0694e026cc1f80eed927d9b91adaeda0fb3fd5725eabc6d066aaf022919def435245446ae91e3da541ed6d88d875cf59a35bfbabb6920efb6da + "@shikijs/types": "npm:3.22.0" + checksum: 10c0/f662648e346e0133d84dee058f24db6434eb7e511ffe8e34e9632f1168d46b219fbddcca245166f98200b13549fc3256baf8d2a0df7c23e856c9933c0bd444f9 languageName: node linkType: hard -"@shikijs/themes@npm:^3.15.0": - version: 3.15.0 - resolution: "@shikijs/themes@npm:3.15.0" +"@shikijs/themes@npm:^3.21.0": + version: 3.21.0 + resolution: "@shikijs/themes@npm:3.21.0" dependencies: - "@shikijs/types": "npm:3.15.0" - checksum: 10c0/2b6a435d991d1fd924622e437c5546ecc5ab3d5c0843edbe2ca444e4e91a9c4d8d9c0a673a32afdb1c262dffcd7839518a9f9154121be8dfa7553f99458d9bab + "@shikijs/types": "npm:3.21.0" + checksum: 10c0/f128a874231d84d93e16f347557e844c2b6493b41196b52e36a79874598abe2dbf3ee981dfe52dd09f8d7e21ed4ff41ab03c28de7a21313d9a0b691fbd3690c0 languageName: node linkType: hard @@ -4207,27 +4148,17 @@ __metadata: languageName: node linkType: hard -"@shikijs/types@npm:3.15.0": - version: 3.15.0 - resolution: "@shikijs/types@npm:3.15.0" - dependencies: - "@shikijs/vscode-textmate": "npm:^10.0.2" - "@types/hast": "npm:^3.0.4" - checksum: 10c0/bc18c7e8b83fbf73f88a26dcf06e777566f8d8568a26ace4dacf5373c51e95213af1181eb389c4d0d7dc57c21824396278d6cbebf57a905676923bfdab00bb23 - languageName: node - linkType: hard - -"@shikijs/types@npm:3.20.0": - version: 3.20.0 - resolution: "@shikijs/types@npm:3.20.0" +"@shikijs/types@npm:3.21.0": + version: 3.21.0 + resolution: "@shikijs/types@npm:3.21.0" dependencies: "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" - checksum: 10c0/7faea130362a6cdf3d66fcb47d6b609a8e0209e76ba86688f56a65411b6ae400a37414cd1a3a2fe1ee3fe39f18e274585d3972129c7e79244aaa0c15bc8f1c21 + checksum: 10c0/a86038c7ad10bb8104ea07cfa0dddf1e0646cf3b70a382978939c6144b21e5891395f5e705b7393476320f6196d86c6d8cd7ad6b3e1b356eb6a7e40c298c98f3 languageName: node linkType: hard -"@shikijs/types@npm:^3.15.0": +"@shikijs/types@npm:3.22.0, @shikijs/types@npm:^3.21.0": version: 3.22.0 resolution: "@shikijs/types@npm:3.22.0" dependencies: @@ -4258,9 +4189,9 @@ __metadata: languageName: node linkType: hard -"@snyk/dep-graph@npm:^2.3.0": - version: 2.9.0 - resolution: "@snyk/dep-graph@npm:2.9.0" +"@snyk/dep-graph@npm:^2.12.0": + version: 2.12.1 + resolution: "@snyk/dep-graph@npm:2.12.1" dependencies: event-loop-spinner: "npm:^2.1.0" lodash.clone: "npm:^4.5.0" @@ -4278,10 +4209,10 @@ __metadata: lodash.union: "npm:^4.6.0" lodash.values: "npm:^4.3.0" object-hash: "npm:^3.0.0" - packageurl-js: "npm:1.2.0" + packageurl-js: "npm:2.0.1" semver: "npm:^7.0.0" tslib: "npm:^2" - checksum: 10c0/709116c589216b130e51bc7750bb9151ec382f749a9ccb124950a4390f6bb470e42cb6e64b56a8bff35602056685a97b66eda0b2eee2584f759d1e046293cb6e + checksum: 10c0/1d9c9ba1c356f24135d7b8da19bdbd09068521eafa84f173bdd18a2ba6678038feea9df253e5df53eb31ffa853b3345e9f8d2649995d34f31bc32ddf621173e1 languageName: node linkType: hard @@ -5686,7 +5617,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:1.0.8, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8": +"@types/estree@npm:*, @types/estree@npm:1.0.8, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 @@ -5797,9 +5728,9 @@ __metadata: linkType: hard "@types/lodash@npm:^4.14.198": - version: 4.17.20 - resolution: "@types/lodash@npm:4.17.20" - checksum: 10c0/98cdd0faae22cbb8079a01a3bb65aa8f8c41143367486c1cbf5adc83f16c9272a2a5d2c1f541f61d0d73da543c16ee1d21cf2ef86cb93cd0cc0ac3bced6dd88f + version: 4.17.23 + resolution: "@types/lodash@npm:4.17.23" + checksum: 10c0/9d9cbfb684e064a2b78aab9e220d398c9c2a7d36bc51a07b184ff382fa043a99b3d00c16c7f109b4eb8614118f4869678dbae7d5c6700ed16fb9340e26cc0bf6 languageName: node linkType: hard @@ -5837,20 +5768,20 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 24.10.1 - resolution: "@types/node@npm:24.10.1" + version: 25.2.2 + resolution: "@types/node@npm:25.2.2" dependencies: undici-types: "npm:~7.16.0" - checksum: 10c0/d6bca7a78f550fbb376f236f92b405d676003a8a09a1b411f55920ef34286ee3ee51f566203920e835478784df52662b5b2af89159d9d319352e9ea21801c002 + checksum: 10c0/45aa45b00df0aac4712c2d6e934a6ed21ac54e0284dd726df1c7620b8c7d36a4fb601b9f8fe1d2951298d1ee7618cf8275688e329c295eb36e8b8fa827a8e334 languageName: node linkType: hard "@types/node@npm:^22.0.0, @types/node@npm:^22.15.30": - version: 22.19.1 - resolution: "@types/node@npm:22.19.1" + version: 22.19.10 + resolution: "@types/node@npm:22.19.10" dependencies: undici-types: "npm:~6.21.0" - checksum: 10c0/6edd93aea86da740cb7872626839cd6f4a67a049d3a3a6639cb592c620ec591408a30989ab7410008d1a0b2d4985ce50f1e488e79c033e4476d3bec6833b0a2f + checksum: 10c0/fb1484f68c259abb73b018e6a521dba2ffe7846128d3aacc7fba5672f354ddb364cb4c81b5a0e686cf58ea0067df4d68d4159f668c864238a0c3fe7fee603341 languageName: node linkType: hard @@ -5869,9 +5800,9 @@ __metadata: linkType: hard "@types/plotly.js@npm:^3.0.0": - version: 3.0.8 - resolution: "@types/plotly.js@npm:3.0.8" - checksum: 10c0/7b8b26a07c8fb863ab1950089eb5c6f67896d65628409f17ab1beaf0a0ffa338cb2171aec108b2460205267ad65e67b10e739f8f74fbf476229202d4487d869b + version: 3.0.9 + resolution: "@types/plotly.js@npm:3.0.9" + checksum: 10c0/8f5aa3cc96f6351e978d491356407e69cd417f6fc64df458cb90a5e382515b37e61dff7fe7416ed7d8ad2f3cdbbe1d7c1629d184bcf33e00111c39b3dce0b28e languageName: node linkType: hard @@ -5910,21 +5841,21 @@ __metadata: linkType: hard "@types/react@npm:*": - version: 19.2.2 - resolution: "@types/react@npm:19.2.2" + version: 19.2.13 + resolution: "@types/react@npm:19.2.13" dependencies: - csstype: "npm:^3.0.2" - checksum: 10c0/f830b1204aca4634ce3c6cb3477b5d3d066b80a4dd832a4ee0069acb504b6debd2416548a43a11c1407c12bc60e2dc6cf362934a18fe75fe06a69c0a98cba8ab + csstype: "npm:^3.2.2" + checksum: 10c0/e512dc53b805b9066f5c6ad42944372e1204290d618dbaec634d8bbd80d3aadcc1b8cdd7251329936bbdafae0425c02f531083213473bb370df903f20bb66e91 languageName: node linkType: hard "@types/react@npm:^18.3.1": - version: 18.3.26 - resolution: "@types/react@npm:18.3.26" + version: 18.3.28 + resolution: "@types/react@npm:18.3.28" dependencies: "@types/prop-types": "npm:*" - csstype: "npm:^3.0.2" - checksum: 10c0/7b62d91c33758f14637311921c92db6045b6328e2300666a35ef8130d06385e39acada005eaf317eee93228edc10ea5f0cd34a0385654d2014d24699a65bfeef + csstype: "npm:^3.2.2" + checksum: 10c0/683e19cd12b5c691215529af2e32b5ffbaccae3bf0ba93bfafa0e460e8dfee18423afed568be2b8eadf4b837c3749dd296a4f64e2d79f68fa66962c05f5af661 languageName: node linkType: hard @@ -6065,187 +5996,129 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.53.1" +"@typescript-eslint/eslint-plugin@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.55.0" dependencies: "@eslint-community/regexpp": "npm:^4.12.2" - "@typescript-eslint/scope-manager": "npm:8.53.1" - "@typescript-eslint/type-utils": "npm:8.53.1" - "@typescript-eslint/utils": "npm:8.53.1" - "@typescript-eslint/visitor-keys": "npm:8.53.1" + "@typescript-eslint/scope-manager": "npm:8.55.0" + "@typescript-eslint/type-utils": "npm:8.55.0" + "@typescript-eslint/utils": "npm:8.55.0" + "@typescript-eslint/visitor-keys": "npm:8.55.0" ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" ts-api-utils: "npm:^2.4.0" peerDependencies: - "@typescript-eslint/parser": ^8.53.1 + "@typescript-eslint/parser": ^8.55.0 eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/d24e41d0117ef841cc05e4c52d33277de2e57981fa38412f93034082a3467f804201c180f1baca9f967388c7e5965ffcc61e445cf726a0064b8ed71a84f59aa2 + checksum: 10c0/e15973dfc822f6a455142433fa393ea2dd9fd4ba443e0d2fb68c6be7cd9a36e13412f061ccfe436a2c90fa070c4538bdd50985d374e85606c98800d372c17eb9 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/parser@npm:8.53.1" +"@typescript-eslint/parser@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/parser@npm:8.55.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.53.1" - "@typescript-eslint/types": "npm:8.53.1" - "@typescript-eslint/typescript-estree": "npm:8.53.1" - "@typescript-eslint/visitor-keys": "npm:8.53.1" + "@typescript-eslint/scope-manager": "npm:8.55.0" + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/typescript-estree": "npm:8.55.0" + "@typescript-eslint/visitor-keys": "npm:8.55.0" debug: "npm:^4.4.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/fb7602dc3ea45b838f4da2d0173161b222442ed2007487dfce57d6ce24ff16606ec99de9eb6ac114a815e11a47248303d941dca1a7bf13f70350372cee509886 - languageName: node - linkType: hard - -"@typescript-eslint/project-service@npm:8.52.0": - version: 8.52.0 - resolution: "@typescript-eslint/project-service@npm:8.52.0" - dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.52.0" - "@typescript-eslint/types": "npm:^8.52.0" - debug: "npm:^4.4.3" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/2dc7379572b4b1340daff5923fbf7987ebd2de5a4203ece0ec9e8a9e85cf182cd4cd24c25bd7df62b981fb633c91dd35f27fed1341719c2f8a48eb80682b4658 + checksum: 10c0/8b8f8caf64a43b98bff8e7bb99cd62d7c72daeee44e80e0a5f693dd376d9c898997e0b9fd5521604d1445bcb24552f54aed5cae022072f8c354a2baf2a452284 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/project-service@npm:8.53.1" +"@typescript-eslint/project-service@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/project-service@npm:8.55.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.53.1" - "@typescript-eslint/types": "npm:^8.53.1" + "@typescript-eslint/tsconfig-utils": "npm:^8.55.0" + "@typescript-eslint/types": "npm:^8.55.0" debug: "npm:^4.4.3" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/eecc7ad86b45c6969a05e984e645a4ece2a1cc27d825af046efb6ed369cab32062c17f33a1154ab6dcab349099885db7b39945f1b318753395630f3dfa1e5895 + checksum: 10c0/f35273a63635d2de84409f68dfcea901ed2cd3f08206abb825d742b929c8fce66e0a6a32524d87ce895a7c4c2549e4388baa08644c0a5244c9708151b0f62f52 languageName: node linkType: hard "@typescript-eslint/rule-tester@npm:^8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/rule-tester@npm:8.53.1" + version: 8.55.0 + resolution: "@typescript-eslint/rule-tester@npm:8.55.0" dependencies: - "@typescript-eslint/parser": "npm:8.53.1" - "@typescript-eslint/typescript-estree": "npm:8.53.1" - "@typescript-eslint/utils": "npm:8.53.1" + "@typescript-eslint/parser": "npm:8.55.0" + "@typescript-eslint/typescript-estree": "npm:8.55.0" + "@typescript-eslint/utils": "npm:8.55.0" ajv: "npm:^6.12.6" json-stable-stringify-without-jsonify: "npm:^1.0.1" lodash.merge: "npm:4.6.2" semver: "npm:^7.7.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - checksum: 10c0/418c5d9c646c9879050a4a4e9f297955fca8862f76363c05bedd0cd48e7f3e2ca3608dffc873658dbc96e485f1cdd97fdbf64289ab10e8cd91940c11323a39b5 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:8.52.0, @typescript-eslint/scope-manager@npm:^8.51.0": - version: 8.52.0 - resolution: "@typescript-eslint/scope-manager@npm:8.52.0" - dependencies: - "@typescript-eslint/types": "npm:8.52.0" - "@typescript-eslint/visitor-keys": "npm:8.52.0" - checksum: 10c0/385105ad1bb63eddcfc65039a7c13ec339aef4823c3021110cffe72c545b27c6b197e40ec55000b5b1bf278946a3e1a77eba19203f461c1a77ba3fe82d007f3e + checksum: 10c0/16cf87c9cdf110b666f138d82f3958957b50c8945506f9550a1f1101031be5f21774896b0502383fe1861cd51ef0aba895f606fac10553bea074cbe0a4bff12e languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/scope-manager@npm:8.53.1" +"@typescript-eslint/scope-manager@npm:8.55.0, @typescript-eslint/scope-manager@npm:^8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/scope-manager@npm:8.55.0" dependencies: - "@typescript-eslint/types": "npm:8.53.1" - "@typescript-eslint/visitor-keys": "npm:8.53.1" - checksum: 10c0/d971eb115f2a2c4c25c79df9eee68b93354b32d7cc1174c167241cd2ebbc77858fe7a032c7ecdbacef936b56e8317b56037d21461cb83b4789f7e764e9faa455 - languageName: node - linkType: hard - -"@typescript-eslint/tsconfig-utils@npm:8.52.0, @typescript-eslint/tsconfig-utils@npm:^8.52.0": - version: 8.52.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.52.0" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/a45f6c1453031c149b2dedaa4e8ace53aa71c751a5702b028cbd9a899928d46141cc4343d8de6260e3e27024f6645b12669d8759f66ebde4cbae2f703b859747 + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/visitor-keys": "npm:8.55.0" + checksum: 10c0/c42bd6b8e4936cac8bee3adbc2f707e3aee5f16af3dd18c1d095f4a1b881471b58de73abc0ad176db98654683a808946902e51d86efff39dc7610d29152c3078 languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.53.1, @typescript-eslint/tsconfig-utils@npm:^8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.53.1" +"@typescript-eslint/tsconfig-utils@npm:8.55.0, @typescript-eslint/tsconfig-utils@npm:^8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.55.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/e2bfa91f9306dbfa82bdcb64bfcf634fee6313b03e93b35b0010907983c9ffc73c732264deff870896dea18f34b872d39d90d32f7631fd4618e4a6866ffff578 + checksum: 10c0/77b9a0d0b1d6ab0ce26c81394bb1aa969649016d2857e5f915a15b88012ac3dccec9fc5ff65535e1cc373434e1462513f7964e416a8d7a695f7277dcd39ec2af languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/type-utils@npm:8.53.1" +"@typescript-eslint/type-utils@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/type-utils@npm:8.55.0" dependencies: - "@typescript-eslint/types": "npm:8.53.1" - "@typescript-eslint/typescript-estree": "npm:8.53.1" - "@typescript-eslint/utils": "npm:8.53.1" + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/typescript-estree": "npm:8.55.0" + "@typescript-eslint/utils": "npm:8.55.0" debug: "npm:^4.4.3" ts-api-utils: "npm:^2.4.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/d97ac3bf901eeeb1ad01a423409db654f849d49f8ce7a2b0d482e093d5c8c9cab9ed810554d130a1eaf4921ddb2d98dbe9a8d22bfd08fd6c8ab004fb640a3fbe + checksum: 10c0/4987440d6e1ee2ae8024259796381612ab2fc81821ff93c45400f803726ea4894a25d07afa5f80cdf3081a189d99dc83a3a8dcd94ff9a4cab81461fe28ab9aef languageName: node linkType: hard -"@typescript-eslint/types@npm:8.52.0": - version: 8.52.0 - resolution: "@typescript-eslint/types@npm:8.52.0" - checksum: 10c0/ad93803aa92570a96cc9f9a201735e68fecee9056a37563c9e5b70c16436927ac823ec38d9712881910d89dd7314b0a40100ef41ef1aca0d42674d3312d5ec8e +"@typescript-eslint/types@npm:8.55.0, @typescript-eslint/types@npm:^8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/types@npm:8.55.0" + checksum: 10c0/dc572f55966e2f0fee149e5d5e42a91cedcdeac451bff29704eb701f9336f123bbc7d7abcfbda717f9e1ef6b402fa24679908bc6032e67513287403037ef345f languageName: node linkType: hard -"@typescript-eslint/types@npm:8.53.1, @typescript-eslint/types@npm:^8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/types@npm:8.53.1" - checksum: 10c0/fa49f5f60de6851de45a9aff0a3ba3c4d00a0991100414e8af1a5d6f32764a48b6b7c0f65748a651f0da0e57df0745cdb8f11c590fa0fb22dd0e54e4c6b5c878 +"@typescript-eslint/types@npm:^8.53.1, @typescript-eslint/types@npm:^8.54.0": + version: 8.54.0 + resolution: "@typescript-eslint/types@npm:8.54.0" + checksum: 10c0/2219594fe5e8931ff91fd1b7a2606d33cd4f093d43f9ca71bcaa37f106ef79ad51f830dea51392f7e3d8bca77f7077ef98733f87bc008fad2f0bbd9ea5fb8a40 languageName: node linkType: hard -"@typescript-eslint/types@npm:^8.52.0": - version: 8.53.0 - resolution: "@typescript-eslint/types@npm:8.53.0" - checksum: 10c0/a88681795becbe857f9868427c0d75c2ab2fb1acde14907b8791709b6d7835400bf9a0b41f22e97a13f1274e0082f5675692b815e30268e6eada492913100306 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:8.52.0": - version: 8.52.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.52.0" - dependencies: - "@typescript-eslint/project-service": "npm:8.52.0" - "@typescript-eslint/tsconfig-utils": "npm:8.52.0" - "@typescript-eslint/types": "npm:8.52.0" - "@typescript-eslint/visitor-keys": "npm:8.52.0" - debug: "npm:^4.4.3" - minimatch: "npm:^9.0.5" - semver: "npm:^7.7.3" - tinyglobby: "npm:^0.2.15" - ts-api-utils: "npm:^2.4.0" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/e4158a6364d3f009eac780947504ac1dad2ee3f1fdd4dfd99e4a7b48719ce0d342a769dc05fa5d4bc5de9de28175aa8e9ba612385f6b6f215039ff41e91f2de5 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.53.1" +"@typescript-eslint/typescript-estree@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.55.0" dependencies: - "@typescript-eslint/project-service": "npm:8.53.1" - "@typescript-eslint/tsconfig-utils": "npm:8.53.1" - "@typescript-eslint/types": "npm:8.53.1" - "@typescript-eslint/visitor-keys": "npm:8.53.1" + "@typescript-eslint/project-service": "npm:8.55.0" + "@typescript-eslint/tsconfig-utils": "npm:8.55.0" + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/visitor-keys": "npm:8.55.0" debug: "npm:^4.4.3" minimatch: "npm:^9.0.5" semver: "npm:^7.7.3" @@ -6253,57 +6126,32 @@ __metadata: ts-api-utils: "npm:^2.4.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/e1b48990ba90f0ee5c9630fe91e2d5123c55348e374e586de6cf25e6e03e6e8274bf15317794d171a2e82d9dc663c229807e603ecc661dbe70d61bd23d0c37c4 - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:8.53.1, @typescript-eslint/utils@npm:^8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/utils@npm:8.53.1" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.53.1" - "@typescript-eslint/types": "npm:8.53.1" - "@typescript-eslint/typescript-estree": "npm:8.53.1" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/9a2a11c00b97eb9a053782e303cc384649807779e9adeb0b645bc198c83f54431f7ca56d4b38411dcf7ed06a2c2d9aa129874c20c037de2393a4cd0fa3b93c25 + checksum: 10c0/2db3ff9489945ad04508b14009eb0f6b2b7c6c2469805327fa09ffa460af354cd181ff2e8153f9008bd60254efb54a004a59ccacbdbc9c963956e2c2c1189dbc languageName: node linkType: hard -"@typescript-eslint/utils@npm:^8.51.0": - version: 8.52.0 - resolution: "@typescript-eslint/utils@npm:8.52.0" +"@typescript-eslint/utils@npm:8.55.0, @typescript-eslint/utils@npm:^8.53.1, @typescript-eslint/utils@npm:^8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/utils@npm:8.55.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.52.0" - "@typescript-eslint/types": "npm:8.52.0" - "@typescript-eslint/typescript-estree": "npm:8.52.0" + "@typescript-eslint/scope-manager": "npm:8.55.0" + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/typescript-estree": "npm:8.55.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/67e501e8ef4c4a5510237e3bfcfee37512137075a18c24f615924559bcca64ce9903118e7e4288cd4f58361979243f457d43684cdafa6c193fa8963a7431d0f3 - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:8.52.0": - version: 8.52.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.52.0" - dependencies: - "@typescript-eslint/types": "npm:8.52.0" - eslint-visitor-keys: "npm:^4.2.1" - checksum: 10c0/7163735d872df0930301ecccd454602d241a65223b84ff3ef78ede02f27941c0cbb95d0c8b4fe51637d1fbd981e6558d454fc485a2488d7190e264e12a8a355f + checksum: 10c0/b57b86ac531e433c8057279805e6c903250460bc937cea46ec3b9284181a38f23b7c1ef092e8a1e37179432b39bd587c33db7f031b4243b1207ef37f23e4f24f languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.53.1": - version: 8.53.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.53.1" +"@typescript-eslint/visitor-keys@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.55.0" dependencies: - "@typescript-eslint/types": "npm:8.53.1" + "@typescript-eslint/types": "npm:8.55.0" eslint-visitor-keys: "npm:^4.2.1" - checksum: 10c0/73a21d34052bcb0b46ed738f8fddb76ae8f56a0c27932616b49022cf8603c3e36bb6ab30acd709f9bc05c673708180527b4c4aaffcb858acfc66d8fb39cc6c29 + checksum: 10c0/995c5ca91f7c7c1f3c4fdb4f98654abdff55efa570076b9b012da4cc203ebe7e2aee57ba83208ae51c2aef496c45cb8f6909560349131b779f31ce6f8758da23 languageName: node linkType: hard @@ -6490,18 +6338,18 @@ __metadata: linkType: hard "@vitejs/plugin-react@npm:^5.1.0": - version: 5.1.1 - resolution: "@vitejs/plugin-react@npm:5.1.1" + version: 5.1.3 + resolution: "@vitejs/plugin-react@npm:5.1.3" dependencies: - "@babel/core": "npm:^7.28.5" + "@babel/core": "npm:^7.29.0" "@babel/plugin-transform-react-jsx-self": "npm:^7.27.1" "@babel/plugin-transform-react-jsx-source": "npm:^7.27.1" - "@rolldown/pluginutils": "npm:1.0.0-beta.47" + "@rolldown/pluginutils": "npm:1.0.0-rc.2" "@types/babel__core": "npm:^7.20.5" react-refresh: "npm:^0.18.0" peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - checksum: 10c0/e590efaea1eabfbb1beb6e8c9fac0742fd299808e3368e63b2825ce24740adb8a28fcb2668b14b7ca1bdb42890cfefe94d02dd358dcbbf8a27ddf377b9a82abf + checksum: 10c0/814d950f398f13ab5261593952b0a3a10a8b21220923c99817c99456890e1c0df4f1dd4cb2fc538ce4db4f525695e82ba1771a9e13ae1821283b659a7cfedc12 languageName: node linkType: hard @@ -6575,11 +6423,11 @@ __metadata: linkType: hard "@vitest/eslint-plugin@npm:^1.6.6": - version: 1.6.6 - resolution: "@vitest/eslint-plugin@npm:1.6.6" + version: 1.6.7 + resolution: "@vitest/eslint-plugin@npm:1.6.7" dependencies: - "@typescript-eslint/scope-manager": "npm:^8.51.0" - "@typescript-eslint/utils": "npm:^8.51.0" + "@typescript-eslint/scope-manager": "npm:^8.55.0" + "@typescript-eslint/utils": "npm:^8.55.0" peerDependencies: eslint: ">=8.57.0" typescript: ">=5.0.0" @@ -6589,7 +6437,7 @@ __metadata: optional: true vitest: optional: true - checksum: 10c0/4b3a5ff3b27d6aab17f43a737f1f03bab0739b9d95c75e9c19d44003c605bdd0ce067f14f064def7fab7ab3251a2d23155849ea061a1a9d16569b3e990b11a62 + checksum: 10c0/8dcfa507da5cf2a63826950770ff83426047560e713dedad25c92a6afcf32564993d2053d143d4accff7b812ac5f3d5159d6aeb0caf12248001e5e11e30fd83b languageName: node linkType: hard @@ -7013,14 +6861,7 @@ __metadata: languageName: node linkType: hard -"ace-builds@npm:^1.25.1": - version: 1.41.0 - resolution: "ace-builds@npm:1.41.0" - checksum: 10c0/9473ee03c6dea43793fd431f6bfeb1381f1efeb82949e69432c7aea9fe32004067c0dfe837a395a0bc7c9ab61d61aab3a0e136c2bde1cdb808283718eefee603 - languageName: node - linkType: hard - -"ace-builds@npm:^1.36.3": +"ace-builds@npm:^1.25.1, ace-builds@npm:^1.36.3": version: 1.43.6 resolution: "ace-builds@npm:1.43.6" checksum: 10c0/33d0159a99650602de83b95766643b8f4f6029fc1ab582e47f7678288cae8e1c89b91747d23be42ec153a88d784fb9488935973f7a100b9093f837ac988f5c96 @@ -7156,6 +6997,13 @@ __metadata: languageName: node linkType: hard +"ansi-regex@npm:^6.2.2": + version: 6.2.2 + resolution: "ansi-regex@npm:6.2.2" + checksum: 10c0/05d4acb1d2f59ab2cf4b794339c7b168890d44dda4bf0ce01152a8da0213aca207802f930442ce8cd22d7a92f44907664aac6508904e75e038fa944d2601b30f + languageName: node + linkType: hard + "ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": version: 4.3.0 resolution: "ansi-styles@npm:4.3.0" @@ -8347,17 +8195,10 @@ __metadata: languageName: node linkType: hard -"commander@npm:^12.0.0": - version: 12.1.0 - resolution: "commander@npm:12.1.0" - checksum: 10c0/6e1996680c083b3b897bfc1cfe1c58dfbcd9842fd43e1aaf8a795fbc237f65efcc860a3ef457b318e73f29a4f4a28f6403c3d653d021d960e4632dd45bde54a9 - languageName: node - linkType: hard - -"commander@npm:^14.0.0, commander@npm:^14.0.2": - version: 14.0.2 - resolution: "commander@npm:14.0.2" - checksum: 10c0/245abd1349dbad5414cb6517b7b5c584895c02c4f7836ff5395f301192b8566f9796c82d7bd6c92d07eba8775fe4df86602fca5d86d8d10bcc2aded1e21c2aeb +"commander@npm:^14.0.0, commander@npm:^14.0.3": + version: 14.0.3 + resolution: "commander@npm:14.0.3" + checksum: 10c0/755652564bbf56ff2ff083313912b326450d3f8d8c85f4b71416539c9a05c3c67dbd206821ca72635bf6b160e2afdefcb458e86b317827d5cb333b69ce7f1a24 languageName: node linkType: hard @@ -8368,21 +8209,21 @@ __metadata: languageName: node linkType: hard -"comment-json@npm:^4.4.1": - version: 4.4.1 - resolution: "comment-json@npm:4.4.1" +"comment-json@npm:^4.5.1": + version: 4.5.1 + resolution: "comment-json@npm:4.5.1" dependencies: array-timsort: "npm:^1.0.3" core-util-is: "npm:^1.0.3" esprima: "npm:^4.0.1" - checksum: 10c0/be6a197132543a3c286c725af412d582882c1eaf450cb124e4148e7542449f216aa717e7be81989f8b8cfe3e38a6f9bc06d209351b8ea82514cafc8feec11a2d + checksum: 10c0/aea59becb413fef2d21ec8f3d58b0dd024c47901c5f77c8436b19cc17f9ead0841b2f40d7a87a9b4061b8c048cd10c3c502e512eb8756ffc9aa58915ba5e4482 languageName: node linkType: hard -"comment-parser@npm:1.4.1": - version: 1.4.1 - resolution: "comment-parser@npm:1.4.1" - checksum: 10c0/d6c4be3f5be058f98b24f2d557f745d8fe1cc9eb75bebbdccabd404a0e1ed41563171b16285f593011f8b6a5ec81f564fb1f2121418ac5cbf0f49255bf0840dd +"comment-parser@npm:1.4.5": + version: 1.4.5 + resolution: "comment-parser@npm:1.4.5" + checksum: 10c0/6a6a74697c79927e3bd42bde9608a471f1a9d4995affbc22fa3364cc42b4017f82ef477431a1558b0b6bef959f9bb6964c01c1bbfc06a58ba1730dec9c423b44 languageName: node linkType: hard @@ -8655,134 +8496,138 @@ __metadata: languageName: node linkType: hard -"cspell-config-lib@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-config-lib@npm:9.3.1" +"cspell-config-lib@npm:9.6.4": + version: 9.6.4 + resolution: "cspell-config-lib@npm:9.6.4" dependencies: - "@cspell/cspell-types": "npm:9.3.1" - comment-json: "npm:^4.4.1" - smol-toml: "npm:^1.4.2" - yaml: "npm:^2.8.1" - checksum: 10c0/4f3f4f4837a10a378778b4e5a1e930aad94be70072cff2d6c59d4025549354a85ea51253de472ff36da8b8fa75cb23e4c01bbab1ee8274d98cc1b3a32a2b8866 + "@cspell/cspell-types": "npm:9.6.4" + comment-json: "npm:^4.5.1" + smol-toml: "npm:^1.6.0" + yaml: "npm:^2.8.2" + checksum: 10c0/e444b5bf1d04e0ccc5f93b0e700d732b29760e61711c6dfca3c4adef32d79ab817a163e0fd5e09f275975cb0e0ef788946cea5390d87c63dcd73372647d48c06 languageName: node linkType: hard -"cspell-dictionary@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-dictionary@npm:9.3.1" +"cspell-dictionary@npm:9.6.4": + version: 9.6.4 + resolution: "cspell-dictionary@npm:9.6.4" dependencies: - "@cspell/cspell-pipe": "npm:9.3.1" - "@cspell/cspell-types": "npm:9.3.1" - cspell-trie-lib: "npm:9.3.1" - fast-equals: "npm:^5.3.2" - checksum: 10c0/03cf75a456791c7c54a52cd281ee01d50c0d1237635655115468153e4a35713b7ce9189dd908d0436f30a29a17c03703c90b34ed0493befbe8e62679fcb37c4a + "@cspell/cspell-performance-monitor": "npm:9.6.4" + "@cspell/cspell-pipe": "npm:9.6.4" + "@cspell/cspell-types": "npm:9.6.4" + cspell-trie-lib: "npm:9.6.4" + fast-equals: "npm:^6.0.0" + checksum: 10c0/38f31867a92f44139faf05b2f825201b2a21e70dd10ce1acd98464f8230f5edf2a1a95cbce92264cc628ad9be07d344e31fb110133143f1be55e9b653b504bc2 languageName: node linkType: hard -"cspell-gitignore@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-gitignore@npm:9.3.1" +"cspell-gitignore@npm:9.6.4": + version: 9.6.4 + resolution: "cspell-gitignore@npm:9.6.4" dependencies: - "@cspell/url": "npm:9.3.1" - cspell-glob: "npm:9.3.1" - cspell-io: "npm:9.3.1" + "@cspell/url": "npm:9.6.4" + cspell-glob: "npm:9.6.4" + cspell-io: "npm:9.6.4" bin: cspell-gitignore: bin.mjs - checksum: 10c0/a9bf15690e988095deb0e030e6070235567d0337d3c770e5cb1bf7e69581f5120901c367b805bdf7511a3a5ae6acffe266f13395f48e1aacf361d43c93d276b7 + checksum: 10c0/08c88d98a39081be3f8246caa4d7c9367defc9f6f58c751e39ac5848ffed3eb0d8a608f915da3f658f113c3f448149f33aae90cca5016bcda67da041fc5de976 languageName: node linkType: hard -"cspell-glob@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-glob@npm:9.3.1" +"cspell-glob@npm:9.6.4": + version: 9.6.4 + resolution: "cspell-glob@npm:9.6.4" dependencies: - "@cspell/url": "npm:9.3.1" + "@cspell/url": "npm:9.6.4" picomatch: "npm:^4.0.3" - checksum: 10c0/37df1c34f1fb6c3a16d29a0b1833ac6f168408fbf6478f962db049dde515e8ad639e005b30fd75d8ffe208b392d4f6b112c81519575612a95d41c3f20d8c442f + checksum: 10c0/1d2b3d0f8da0c4bb745617bdb7dddcc38a511c78f8efb47ed47502203b980a0bc7efbca2bb9885aafadd656b81244c5824e4133afbc26dfaf67a7e573f96290c languageName: node linkType: hard -"cspell-grammar@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-grammar@npm:9.3.1" +"cspell-grammar@npm:9.6.4": + version: 9.6.4 + resolution: "cspell-grammar@npm:9.6.4" dependencies: - "@cspell/cspell-pipe": "npm:9.3.1" - "@cspell/cspell-types": "npm:9.3.1" + "@cspell/cspell-pipe": "npm:9.6.4" + "@cspell/cspell-types": "npm:9.6.4" bin: cspell-grammar: bin.mjs - checksum: 10c0/e4e4bb1b8effff50032cb5f0407e1f9f666b4b5502520e49070ed00a9bfd1e863033212ef0523a5898ebc9761133b100592f1d2ec200169326e52409c69b827a + checksum: 10c0/6039d8adfd8b4c3e1f8a60c26cb026efdba2314dd450a3de6e5ffce44cff78105c9aa17091a5ebc1ad8c866f1b38f91c1425e5d3163ff80f5affb2093099c2b2 languageName: node linkType: hard -"cspell-io@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-io@npm:9.3.1" +"cspell-io@npm:9.6.4": + version: 9.6.4 + resolution: "cspell-io@npm:9.6.4" dependencies: - "@cspell/cspell-service-bus": "npm:9.3.1" - "@cspell/url": "npm:9.3.1" - checksum: 10c0/a4b709bc0ad7f489e33e07a946c7947794bc5b21318c85e0ee1763ef5086c7eca93b9ca276572309b478c7470e8697607542eb2fe46135218783d9c4262de93f + "@cspell/cspell-service-bus": "npm:9.6.4" + "@cspell/url": "npm:9.6.4" + checksum: 10c0/32bbb621275855df209547857d536e047e0fc78759a5bff36bb3a16c9ff1308d7171452e9e0e94d08dbb8e3716df08e3b9fc0967006ebd4935e3dd4aec290fcc languageName: node linkType: hard -"cspell-lib@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-lib@npm:9.3.1" +"cspell-lib@npm:9.6.4": + version: 9.6.4 + resolution: "cspell-lib@npm:9.6.4" dependencies: - "@cspell/cspell-bundled-dicts": "npm:9.3.1" - "@cspell/cspell-pipe": "npm:9.3.1" - "@cspell/cspell-resolver": "npm:9.3.1" - "@cspell/cspell-types": "npm:9.3.1" - "@cspell/dynamic-import": "npm:9.3.1" - "@cspell/filetypes": "npm:9.3.1" - "@cspell/strong-weak-map": "npm:9.3.1" - "@cspell/url": "npm:9.3.1" + "@cspell/cspell-bundled-dicts": "npm:9.6.4" + "@cspell/cspell-performance-monitor": "npm:9.6.4" + "@cspell/cspell-pipe": "npm:9.6.4" + "@cspell/cspell-resolver": "npm:9.6.4" + "@cspell/cspell-types": "npm:9.6.4" + "@cspell/dynamic-import": "npm:9.6.4" + "@cspell/filetypes": "npm:9.6.4" + "@cspell/rpc": "npm:9.6.4" + "@cspell/strong-weak-map": "npm:9.6.4" + "@cspell/url": "npm:9.6.4" clear-module: "npm:^4.1.2" - cspell-config-lib: "npm:9.3.1" - cspell-dictionary: "npm:9.3.1" - cspell-glob: "npm:9.3.1" - cspell-grammar: "npm:9.3.1" - cspell-io: "npm:9.3.1" - cspell-trie-lib: "npm:9.3.1" - env-paths: "npm:^3.0.0" + cspell-config-lib: "npm:9.6.4" + cspell-dictionary: "npm:9.6.4" + cspell-glob: "npm:9.6.4" + cspell-grammar: "npm:9.6.4" + cspell-io: "npm:9.6.4" + cspell-trie-lib: "npm:9.6.4" + env-paths: "npm:^4.0.0" gensequence: "npm:^8.0.8" import-fresh: "npm:^3.3.1" resolve-from: "npm:^5.0.0" vscode-languageserver-textdocument: "npm:^1.0.12" vscode-uri: "npm:^3.1.0" xdg-basedir: "npm:^5.1.0" - checksum: 10c0/22e6e1e71a0322a5c70d7ca2039fa55c2e65508309885e8442671bdd072944913901e60afd50bcd4a4f7679697b5986b0e4eed6bb60611728fc9d07486cfbd67 + checksum: 10c0/46952d51903ce1ee2aa0fb2fdc9ff6d8cb098a4506f1080d8cbba24d5a4a23182f7ab134b6ad33aac568cb90228e4878877cd8ccc988c3355a31b1674ea1f596 languageName: node linkType: hard -"cspell-trie-lib@npm:9.3.1": - version: 9.3.1 - resolution: "cspell-trie-lib@npm:9.3.1" - dependencies: - "@cspell/cspell-pipe": "npm:9.3.1" - "@cspell/cspell-types": "npm:9.3.1" - gensequence: "npm:^8.0.8" - checksum: 10c0/f43b2af1a04d8aeb97a3df465e34d7aa23e2ada1e7666691ba969c55a3f99148d841f6a9eeed2b86b7b4b05c0a885bf1c9ec197dec8925326749b478ea11f091 +"cspell-trie-lib@npm:9.6.4": + version: 9.6.4 + resolution: "cspell-trie-lib@npm:9.6.4" + peerDependencies: + "@cspell/cspell-types": 9.6.4 + checksum: 10c0/f4ac89d659e004bc541a5e7c6c15f013bfb00982a9c1362f7d52d6cfe14179b02c0bf469800020135bbfcdd7594d5669686b57294cd1ae799ce0aefda4b08e06 languageName: node linkType: hard "cspell@npm:^9.2.1": - version: 9.3.1 - resolution: "cspell@npm:9.3.1" - dependencies: - "@cspell/cspell-json-reporter": "npm:9.3.1" - "@cspell/cspell-pipe": "npm:9.3.1" - "@cspell/cspell-types": "npm:9.3.1" - "@cspell/dynamic-import": "npm:9.3.1" - "@cspell/url": "npm:9.3.1" + version: 9.6.4 + resolution: "cspell@npm:9.6.4" + dependencies: + "@cspell/cspell-json-reporter": "npm:9.6.4" + "@cspell/cspell-performance-monitor": "npm:9.6.4" + "@cspell/cspell-pipe": "npm:9.6.4" + "@cspell/cspell-types": "npm:9.6.4" + "@cspell/cspell-worker": "npm:9.6.4" + "@cspell/dynamic-import": "npm:9.6.4" + "@cspell/url": "npm:9.6.4" + ansi-regex: "npm:^6.2.2" chalk: "npm:^5.6.2" chalk-template: "npm:^1.1.2" - commander: "npm:^14.0.2" - cspell-config-lib: "npm:9.3.1" - cspell-dictionary: "npm:9.3.1" - cspell-gitignore: "npm:9.3.1" - cspell-glob: "npm:9.3.1" - cspell-io: "npm:9.3.1" - cspell-lib: "npm:9.3.1" + commander: "npm:^14.0.3" + cspell-config-lib: "npm:9.6.4" + cspell-dictionary: "npm:9.6.4" + cspell-gitignore: "npm:9.6.4" + cspell-glob: "npm:9.6.4" + cspell-io: "npm:9.6.4" + cspell-lib: "npm:9.6.4" fast-json-stable-stringify: "npm:^2.1.0" flatted: "npm:^3.3.3" semver: "npm:^7.7.3" @@ -8790,7 +8635,7 @@ __metadata: bin: cspell: bin.mjs cspell-esm: bin.mjs - checksum: 10c0/15cd54a26ed868fcfb7b672a4305bd04bec18077a71fb039c756194ee324592d32e889616636d050aa45858d221fdac1e1f991114a7ecd0236fb58a4b97cd92d + checksum: 10c0/717a5f2a9e9c9f930266a6848595402ec39f168f3caf3698c0b8681ad97575dcadbdb54a4e42661bdf87d41ca558c9a2a84e0a510e7ea87d7911a1f7fb65f6ad languageName: node linkType: hard @@ -8811,6 +8656,13 @@ __metadata: languageName: node linkType: hard +"csstype@npm:^3.2.2": + version: 3.2.3 + resolution: "csstype@npm:3.2.3" + checksum: 10c0/cd29c51e70fa822f1cecd8641a1445bed7063697469d35633b516e60fe8c1bde04b08f6c5b6022136bb669b64c63d4173af54864510fbb4ee23281801841a3ce + languageName: node + linkType: hard + "cytoscape-cose-bilkent@npm:^4.1.0": version: 4.1.0 resolution: "cytoscape-cose-bilkent@npm:4.1.0" @@ -9685,10 +9537,12 @@ __metadata: languageName: node linkType: hard -"env-paths@npm:^3.0.0": - version: 3.0.0 - resolution: "env-paths@npm:3.0.0" - checksum: 10c0/76dec878cee47f841103bacd7fae03283af16f0702dad65102ef0a556f310b98a377885e0f32943831eb08b5ab37842a323d02529f3dfd5d0a40ca71b01b435f +"env-paths@npm:^4.0.0": + version: 4.0.0 + resolution: "env-paths@npm:4.0.0" + dependencies: + is-safe-filename: "npm:^0.1.0" + checksum: 10c0/13ee7fa4047786ca28f1fbf2239606f8a53304bdf71bfc426e95f806e429060181205316f2c45b4ac560e81c854ded5a45fd9dc3105414c01d504b3469a1294b languageName: node linkType: hard @@ -10007,122 +9861,36 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.25.0": - version: 0.25.4 - resolution: "esbuild@npm:0.25.4" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.4" - "@esbuild/android-arm": "npm:0.25.4" - "@esbuild/android-arm64": "npm:0.25.4" - "@esbuild/android-x64": "npm:0.25.4" - "@esbuild/darwin-arm64": "npm:0.25.4" - "@esbuild/darwin-x64": "npm:0.25.4" - "@esbuild/freebsd-arm64": "npm:0.25.4" - "@esbuild/freebsd-x64": "npm:0.25.4" - "@esbuild/linux-arm": "npm:0.25.4" - "@esbuild/linux-arm64": "npm:0.25.4" - "@esbuild/linux-ia32": "npm:0.25.4" - "@esbuild/linux-loong64": "npm:0.25.4" - "@esbuild/linux-mips64el": "npm:0.25.4" - "@esbuild/linux-ppc64": "npm:0.25.4" - "@esbuild/linux-riscv64": "npm:0.25.4" - "@esbuild/linux-s390x": "npm:0.25.4" - "@esbuild/linux-x64": "npm:0.25.4" - "@esbuild/netbsd-arm64": "npm:0.25.4" - "@esbuild/netbsd-x64": "npm:0.25.4" - "@esbuild/openbsd-arm64": "npm:0.25.4" - "@esbuild/openbsd-x64": "npm:0.25.4" - "@esbuild/sunos-x64": "npm:0.25.4" - "@esbuild/win32-arm64": "npm:0.25.4" - "@esbuild/win32-ia32": "npm:0.25.4" - "@esbuild/win32-x64": "npm:0.25.4" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/db9f51248f0560bc46ab219461d338047617f6caf373c95f643b204760bdfa10c95b48cfde948949f7e509599ae4ab61c3f112092a3534936c6abfb800c565b0 - languageName: node - linkType: hard - "esbuild@npm:^0.27.0": - version: 0.27.0 - resolution: "esbuild@npm:0.27.0" - dependencies: - "@esbuild/aix-ppc64": "npm:0.27.0" - "@esbuild/android-arm": "npm:0.27.0" - "@esbuild/android-arm64": "npm:0.27.0" - "@esbuild/android-x64": "npm:0.27.0" - "@esbuild/darwin-arm64": "npm:0.27.0" - "@esbuild/darwin-x64": "npm:0.27.0" - "@esbuild/freebsd-arm64": "npm:0.27.0" - "@esbuild/freebsd-x64": "npm:0.27.0" - "@esbuild/linux-arm": "npm:0.27.0" - "@esbuild/linux-arm64": "npm:0.27.0" - "@esbuild/linux-ia32": "npm:0.27.0" - "@esbuild/linux-loong64": "npm:0.27.0" - "@esbuild/linux-mips64el": "npm:0.27.0" - "@esbuild/linux-ppc64": "npm:0.27.0" - "@esbuild/linux-riscv64": "npm:0.27.0" - "@esbuild/linux-s390x": "npm:0.27.0" - "@esbuild/linux-x64": "npm:0.27.0" - "@esbuild/netbsd-arm64": "npm:0.27.0" - "@esbuild/netbsd-x64": "npm:0.27.0" - "@esbuild/openbsd-arm64": "npm:0.27.0" - "@esbuild/openbsd-x64": "npm:0.27.0" - "@esbuild/openharmony-arm64": "npm:0.27.0" - "@esbuild/sunos-x64": "npm:0.27.0" - "@esbuild/win32-arm64": "npm:0.27.0" - "@esbuild/win32-ia32": "npm:0.27.0" - "@esbuild/win32-x64": "npm:0.27.0" + version: 0.27.3 + resolution: "esbuild@npm:0.27.3" + dependencies: + "@esbuild/aix-ppc64": "npm:0.27.3" + "@esbuild/android-arm": "npm:0.27.3" + "@esbuild/android-arm64": "npm:0.27.3" + "@esbuild/android-x64": "npm:0.27.3" + "@esbuild/darwin-arm64": "npm:0.27.3" + "@esbuild/darwin-x64": "npm:0.27.3" + "@esbuild/freebsd-arm64": "npm:0.27.3" + "@esbuild/freebsd-x64": "npm:0.27.3" + "@esbuild/linux-arm": "npm:0.27.3" + "@esbuild/linux-arm64": "npm:0.27.3" + "@esbuild/linux-ia32": "npm:0.27.3" + "@esbuild/linux-loong64": "npm:0.27.3" + "@esbuild/linux-mips64el": "npm:0.27.3" + "@esbuild/linux-ppc64": "npm:0.27.3" + "@esbuild/linux-riscv64": "npm:0.27.3" + "@esbuild/linux-s390x": "npm:0.27.3" + "@esbuild/linux-x64": "npm:0.27.3" + "@esbuild/netbsd-arm64": "npm:0.27.3" + "@esbuild/netbsd-x64": "npm:0.27.3" + "@esbuild/openbsd-arm64": "npm:0.27.3" + "@esbuild/openbsd-x64": "npm:0.27.3" + "@esbuild/openharmony-arm64": "npm:0.27.3" + "@esbuild/sunos-x64": "npm:0.27.3" + "@esbuild/win32-arm64": "npm:0.27.3" + "@esbuild/win32-ia32": "npm:0.27.3" + "@esbuild/win32-x64": "npm:0.27.3" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -10178,7 +9946,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10c0/a3a1deec285337b7dfe25cbb9aa8765d27a0192b610a8477a39bf5bd907a6bdb75e98898b61fb4337114cfadb13163bd95977db14e241373115f548e235b40a2 + checksum: 10c0/fdc3f87a3f08b3ef98362f37377136c389a0d180fda4b8d073b26ba930cf245521db0a368f119cc7624bc619248fff1439f5811f062d853576f8ffa3df8ee5f1 languageName: node linkType: hard @@ -10322,16 +10090,16 @@ __metadata: linkType: hard "eslint-plugin-jsdoc@npm:^62.0.0": - version: 62.0.0 - resolution: "eslint-plugin-jsdoc@npm:62.0.0" + version: 62.5.4 + resolution: "eslint-plugin-jsdoc@npm:62.5.4" dependencies: - "@es-joy/jsdoccomment": "npm:~0.79.0" + "@es-joy/jsdoccomment": "npm:~0.84.0" "@es-joy/resolve.exports": "npm:1.2.0" are-docs-informative: "npm:^0.0.2" - comment-parser: "npm:1.4.1" + comment-parser: "npm:1.4.5" debug: "npm:^4.4.3" escape-string-regexp: "npm:^4.0.0" - espree: "npm:^11.0.0" + espree: "npm:^11.1.0" esquery: "npm:^1.7.0" html-entities: "npm:^2.6.0" object-deep-merge: "npm:^2.0.0" @@ -10341,7 +10109,7 @@ __metadata: to-valid-identifier: "npm:^1.0.0" peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10c0/9558f9a05109f5eab9433225240f2ac36407b47694731e7ad1f6edb995c5616e51b7475b05409d230dc859ba4ac1f77dc5ed409e16fadf4c454305eab72695bf + checksum: 10c0/576a3dd2279c09ec579cbb944afed78029d5525a18dbef37097d510a0241c3792a597c440e80a299240772d49a6d0624bc90ffec32a72fca1e806e0554ac2119 languageName: node linkType: hard @@ -10458,8 +10226,8 @@ __metadata: linkType: hard "eslint@npm:^9.35.0": - version: 9.39.1 - resolution: "eslint@npm:9.39.1" + version: 9.39.2 + resolution: "eslint@npm:9.39.2" dependencies: "@eslint-community/eslint-utils": "npm:^4.8.0" "@eslint-community/regexpp": "npm:^4.12.1" @@ -10467,7 +10235,7 @@ __metadata: "@eslint/config-helpers": "npm:^0.4.2" "@eslint/core": "npm:^0.17.0" "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.39.1" + "@eslint/js": "npm:9.39.2" "@eslint/plugin-kit": "npm:^0.4.1" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" @@ -10502,7 +10270,7 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10c0/59b2480639404ba24578ca480f973683b87b7aac8aa7e349240474a39067804fd13cd8b9cb22fee074170b8c7c563b57bab703ec0f0d3f81ea017e5d2cad299d + checksum: 10c0/bb88ca8fd16bb7e1ac3e13804c54d41c583214460c0faa7b3e7c574e69c5600c7122295500fb4b0c06067831111db740931e98da1340329527658e1cf80073d3 languageName: node linkType: hard @@ -10528,14 +10296,14 @@ __metadata: languageName: node linkType: hard -"espree@npm:^11.0.0": - version: 11.0.0 - resolution: "espree@npm:11.0.0" +"espree@npm:^11.1.0": + version: 11.1.0 + resolution: "espree@npm:11.1.0" dependencies: acorn: "npm:^8.15.0" acorn-jsx: "npm:^5.3.2" eslint-visitor-keys: "npm:^5.0.0" - checksum: 10c0/1e07fdb2a135bb9996a4b23baad51980dde7bcdf4d7115cdec06437663790f4bbe3416eb560fc7dc7330c01a6006f789722f1e5b243208f4cb6e054efef57afd + checksum: 10c0/32228d12896f5aa09f59fad8bf5df228d73310e436c21389876cdd21513b620c087d24b40646cdcff848540d11b078653db0e37ea67ac9c7012a12595d86630c languageName: node linkType: hard @@ -10796,10 +10564,10 @@ __metadata: languageName: node linkType: hard -"fast-equals@npm:^5.3.2": - version: 5.3.3 - resolution: "fast-equals@npm:5.3.3" - checksum: 10c0/a186cbfe4d9171911af9c6bb02d059e28bc177f66527790bf95d35a08f6f070033caea5755d2bbf2ce7af56374c1d4d854ee8184f9e906e3e01b54dbd09c414c +"fast-equals@npm:^6.0.0": + version: 6.0.0 + resolution: "fast-equals@npm:6.0.0" + checksum: 10c0/aae54699ce848726679a947c8bbea78f2ea0384e4e1ee213c98f10881a17bb376bd11085eda4d6c89db5285635ee2f809b126d773532fcf602be355008a9d5ed languageName: node linkType: hard @@ -10838,13 +10606,13 @@ __metadata: linkType: hard "fast-xml-parser@npm:^5.0.7": - version: 5.2.5 - resolution: "fast-xml-parser@npm:5.2.5" + version: 5.3.4 + resolution: "fast-xml-parser@npm:5.3.4" dependencies: strnum: "npm:^2.1.0" bin: fxparser: src/cli/cli.js - checksum: 10c0/d1057d2e790c327ccfc42b872b91786a4912a152d44f9507bf053f800102dfb07ece3da0a86b33ff6a0caa5a5cad86da3326744f6ae5efb0c6c571d754fe48cd + checksum: 10c0/d77866ca860ad185153e12f6ba12274d32026319ad8064e4681342b8a8e1ffad3f1f98daf04d77239fb12eb1d906ee7185fd328deda74529680e8dae0f3e9327 languageName: node linkType: hard @@ -11031,7 +10799,7 @@ __metadata: languageName: node linkType: hard -"foreground-child@npm:^3.1.0": +"foreground-child@npm:^3.1.0, foreground-child@npm:^3.3.1": version: 3.3.1 resolution: "foreground-child@npm:3.3.1" dependencies: @@ -11227,11 +10995,11 @@ __metadata: linkType: hard "get-tsconfig@npm:^4.10.1": - version: 4.13.0 - resolution: "get-tsconfig@npm:4.13.0" + version: 4.13.6 + resolution: "get-tsconfig@npm:4.13.6" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/2c49ef8d3907047a107f229fd610386fe3b7fe9e42dfd6b42e7406499493cdda8c62e83e57e8d7a98125610774b9f604d3a0ff308d7f9de5c7ac6d1b07cb6036 + checksum: 10c0/bab6937302f542f97217cbe7cbbdfa7e85a56a377bc7a73e69224c1f0b7c9ae8365918e55752ae8648265903f506c1705f63c0de1d4bab1ec2830fef3e539a1a languageName: node linkType: hard @@ -11288,7 +11056,23 @@ __metadata: languageName: node linkType: hard -"glob@npm:10.4.5, glob@npm:^10.0.0, glob@npm:^10.2.2": +"glob@npm:11.1.0": + version: 11.1.0 + resolution: "glob@npm:11.1.0" + dependencies: + foreground-child: "npm:^3.3.1" + jackspeak: "npm:^4.1.1" + minimatch: "npm:^10.1.1" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^2.0.0" + bin: + glob: dist/esm/bin.mjs + checksum: 10c0/1ceae07f23e316a6fa74581d9a74be6e8c2e590d2f7205034dd5c0435c53f5f7b712c2be00c3b65bf0a49294a1c6f4b98cd84c7637e29453b5aa13b79f1763a2 + languageName: node + linkType: hard + +"glob@npm:^10.0.0, glob@npm:^10.2.2": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -12329,6 +12113,13 @@ __metadata: languageName: node linkType: hard +"is-safe-filename@npm:^0.1.0": + version: 0.1.1 + resolution: "is-safe-filename@npm:0.1.1" + checksum: 10c0/45c35d2253b96348e2c26590e14feed51d1e6b72aaa567930ccb34e68c0eef00ebcf3b7e01b46bf45e578a27355cd8f5bc12f7d6d79a34d33dc93d4560c0f6b6 + languageName: node + linkType: hard + "is-set@npm:^2.0.3": version: 2.0.3 resolution: "is-set@npm:2.0.3" @@ -12566,6 +12357,15 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^4.1.1": + version: 4.2.3 + resolution: "jackspeak@npm:4.2.3" + dependencies: + "@isaacs/cliui": "npm:^9.0.0" + checksum: 10c0/b5c0c414f1607c2aa0597f4bf2c03b8443897fccd5fd3c2b3e4f77d556b2bc7c3d3413828ba91e0789f6fb40ad90242f7f89fb20aee9e9d705bc1681f7564f67 + languageName: node + linkType: hard + "jest-haste-map@npm:^26.6.2": version: 26.6.2 resolution: "jest-haste-map@npm:26.6.2" @@ -12648,26 +12448,24 @@ __metadata: linkType: hard "js-slang@npm:^1.0.85": - version: 1.0.85 - resolution: "js-slang@npm:1.0.85" + version: 1.0.86 + resolution: "js-slang@npm:1.0.86" dependencies: "@babel/parser": "npm:^7.19.4" - "@commander-js/extra-typings": "npm:^12.0.1" - "@joeychenofficial/alt-ergo-modified": "npm:^2.4.0" + "@commander-js/extra-typings": "npm:^14.0.0" "@ts-morph/bootstrap": "npm:^0.18.0" - "@types/estree": "npm:^1.0.5" acorn: "npm:^8.8.2" acorn-class-fields: "npm:^1.0.0" acorn-loose: "npm:^8.0.0" acorn-walk: "npm:^8.0.0" astring: "npm:^1.4.3" - commander: "npm:^12.0.0" + commander: "npm:^14.0.0" js-base64: "npm:^3.7.5" lodash: "npm:^4.17.21" source-map: "npm:0.7.6" bin: js-slang: dist/repl/index.js - checksum: 10c0/8a206d6052e5b23a27bda4aef66675b4b7f9bebde936c789a182948478e26fa7aee6289effd0d867725a939e14674ee59fd218e1bec1fd1dc597b6bf7cbbaf42 + checksum: 10c0/ddf17e8df6748e3e6267f780b97db2135104e6b3987ba5633c8dfa94c1ce6524ec88ef48b180473bb30fb43739532d8063d4c6d6212b6b4715d3783e8fce1f8c languageName: node linkType: hard @@ -12715,10 +12513,10 @@ __metadata: languageName: node linkType: hard -"jsdoc-type-pratt-parser@npm:~7.0.0": - version: 7.0.0 - resolution: "jsdoc-type-pratt-parser@npm:7.0.0" - checksum: 10c0/3ede53c80dddf940a51dcdc79e3923537650f6fb6e9001fc76023c2d5cb0195cc8b24b7eebf9b3f20a7bc00d5e6b7f70318f0b8cb5972f6aff884152e6698014 +"jsdoc-type-pratt-parser@npm:~7.1.1": + version: 7.1.1 + resolution: "jsdoc-type-pratt-parser@npm:7.1.1" + checksum: 10c0/5a5216a75962b3a8a3a1e7e09a19b31b5a373c06c726a00b081480daee00196250d4acc8dfbecc0a7846d439a5bcf4a326df6348b879cf95f60c62ce5818dadb languageName: node linkType: hard @@ -12813,14 +12611,14 @@ __metadata: linkType: hard "jsonc-eslint-parser@npm:^2.4.0": - version: 2.4.1 - resolution: "jsonc-eslint-parser@npm:2.4.1" + version: 2.4.2 + resolution: "jsonc-eslint-parser@npm:2.4.2" dependencies: acorn: "npm:^8.5.0" eslint-visitor-keys: "npm:^3.0.0" espree: "npm:^9.0.0" semver: "npm:^7.3.5" - checksum: 10c0/735bd33435fee002bf7f07d23ba969b994971ab3b333a0e2641b79cd413819fe36540ba6ed29da9ebc69062625e8bfb167ff4415321f9640fdd9d0cf92dfa999 + checksum: 10c0/821af0231cb8eba2afde34535bd76d723ed5b4b3711fdccff3f300f32de7bbf463ceab3ce2de9e6fd78dc3b24a9c7248ca12eb43e280cfa2695f49bd16908f87 languageName: node linkType: hard @@ -13249,6 +13047,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^11.0.0": + version: 11.2.5 + resolution: "lru-cache@npm:11.2.5" + checksum: 10c0/cc98958d25dddf1c8a8cbdc49588bd3b24450e8dfa78f32168fd188a20d4a0331c7406d0f3250c86a46619ee288056fd7a1195e8df56dc8a9592397f4fbd8e1d + languageName: node + linkType: hard + "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -13701,8 +13506,8 @@ __metadata: linkType: hard "mermaid@npm:^11.10.0": - version: 11.12.1 - resolution: "mermaid@npm:11.12.1" + version: 11.12.2 + resolution: "mermaid@npm:11.12.2" dependencies: "@braintree/sanitize-url": "npm:^7.1.1" "@iconify/utils": "npm:^3.0.1" @@ -13724,7 +13529,7 @@ __metadata: stylis: "npm:^4.3.6" ts-dedent: "npm:^2.2.0" uuid: "npm:^11.1.0" - checksum: 10c0/0dd07a5986bb25ca038f68f7a187a0b6ccf5fa8c738603c3145bd4b6289d50312053818f52617cf575a6652e6c57809ae115c016725f7ce446496be5971a150a + checksum: 10c0/00969b96171f1f11cf897df205d932237a6303041d9519b82bd727cfca43507b54cbf28dfb951aa7ff5e6129607f2297703a464361fc95942db9364c579da9f3 languageName: node linkType: hard @@ -14287,6 +14092,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^10.1.1": + version: 10.1.2 + resolution: "minimatch@npm:10.1.2" + dependencies: + "@isaacs/brace-expansion": "npm:^5.0.1" + checksum: 10c0/0cccef3622201703de6ecf9d772c0be1d5513dcc038ed9feb866c20cf798243e678ac35605dac3f1a054650c28037486713fe9e9a34b184b9097959114daf086 + languageName: node + linkType: hard + "minimatch@npm:^3.0.4, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -14479,6 +14293,18 @@ __metadata: languageName: node linkType: hard +"mlly@npm:^1.8.0": + version: 1.8.0 + resolution: "mlly@npm:1.8.0" + dependencies: + acorn: "npm:^8.15.0" + pathe: "npm:^2.0.3" + pkg-types: "npm:^1.3.1" + ufo: "npm:^1.6.1" + checksum: 10c0/f174b844ae066c71e9b128046677868e2e28694f0bbeeffbe760b2a9d8ff24de0748d0fde6fabe706700c1d2e11d3c0d7a53071b5ea99671592fac03364604ab + languageName: node + linkType: hard + "mqtt-packet@npm:^6.8.0": version: 6.10.0 resolution: "mqtt-packet@npm:6.10.0" @@ -15166,10 +14992,10 @@ __metadata: languageName: node linkType: hard -"packageurl-js@npm:1.2.0": - version: 1.2.0 - resolution: "packageurl-js@npm:1.2.0" - checksum: 10c0/4ab4f63483e3ae516ec458bc8113d7e86c199698fa66a4b290c039f92415a9d8908a9421155677fe56bc6ba682c5930bf1db432401ad8dbf0a3350a6d92bd3d8 +"packageurl-js@npm:2.0.1": + version: 2.0.1 + resolution: "packageurl-js@npm:2.0.1" + checksum: 10c0/8a45bc925243bea0fd7f027b54bf7c363ab70dae2b01676d67856eb788352d7344f38b86c8cfa510410220c6848dc57bc152146bf6518fb06c272d3dbe003b55 languageName: node linkType: hard @@ -15361,6 +15187,16 @@ __metadata: languageName: node linkType: hard +"path-scurry@npm:^2.0.0": + version: 2.0.1 + resolution: "path-scurry@npm:2.0.1" + dependencies: + lru-cache: "npm:^11.0.0" + minipass: "npm:^7.1.2" + checksum: 10c0/2a16ed0e81fbc43513e245aa5763354e25e787dab0d539581a6c3f0f967461a159ed6236b2559de23aa5b88e7dc32b469b6c47568833dd142a4b24b4f5cd2620 + languageName: node + linkType: hard + "pathe@npm:^2.0.1, pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" @@ -15390,11 +15226,11 @@ __metadata: linkType: hard "phaser@npm:^3.54.0": - version: 3.88.2 - resolution: "phaser@npm:3.88.2" + version: 3.90.0 + resolution: "phaser@npm:3.90.0" dependencies: eventemitter3: "npm:^5.0.1" - checksum: 10c0/eb583f741aaa42975180c56e3149dfa762de78c9c2d80c74c545f62bcc1ab8e88be84d99d82bef32aa931a79cc2416f92109a076e051d998b3f173595d8e908e + checksum: 10c0/43d405832fc84c8641e22842fe8d4ca954950ffde364bfb60e4d07b05a29f33eb0c9d4a64acda088122ee6649b7b3ed6d9b3b99bbb67671a528c6ceb10d71689 languageName: node linkType: hard @@ -15453,7 +15289,7 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^1.3.0": +"pkg-types@npm:^1.3.0, pkg-types@npm:^1.3.1": version: 1.3.1 resolution: "pkg-types@npm:1.3.1" dependencies: @@ -15475,27 +15311,27 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.56.1": - version: 1.56.1 - resolution: "playwright-core@npm:1.56.1" +"playwright-core@npm:1.58.2": + version: 1.58.2 + resolution: "playwright-core@npm:1.58.2" bin: playwright-core: cli.js - checksum: 10c0/ffd40142b99c68678b387445d5b42f1fee4ab0b65d983058c37f342e5629f9cdbdac0506ea80a0dfd41a8f9f13345bad54e9a8c35826ef66dc765f4eb3db8da7 + checksum: 10c0/5aa15b2b764e6ffe738293a09081a6f7023847a0dbf4cd05fe10eed2e25450d321baf7482f938f2d2eb330291e197fa23e57b29a5b552b89927ceb791266225b languageName: node linkType: hard "playwright@npm:^1.55.1": - version: 1.56.1 - resolution: "playwright@npm:1.56.1" + version: 1.58.2 + resolution: "playwright@npm:1.58.2" dependencies: fsevents: "npm:2.3.2" - playwright-core: "npm:1.56.1" + playwright-core: "npm:1.58.2" dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: 10c0/8e9965aede86df0f4722063385748498977b219630a40a10d1b82b8bd8d4d4e9b6b65ecbfa024331a30800163161aca292fb6dd7446c531a1ad25f4155625ab4 + checksum: 10c0/d060d9b7cc124bd8b5dffebaab5e84f6b34654a553758fe7b19cc598dfbee93f6ecfbdc1832b40a6380ae04eade86ef3285ba03aa0b136799e83402246dc0727 languageName: node linkType: hard @@ -15507,9 +15343,9 @@ __metadata: linkType: hard "plotly.js-dist@npm:^3.0.0": - version: 3.0.1 - resolution: "plotly.js-dist@npm:3.0.1" - checksum: 10c0/cc5725d043fb052a28952fa8b7f72bbf91cc4460d2742e68f49801fe34cf7164ad0d55fe262da0c2e530ef4541845a030d129aab8d90795987052236bb8372c4 + version: 3.3.1 + resolution: "plotly.js-dist@npm:3.3.1" + checksum: 10c0/8332667bc104a7fa13465f2462cb322c2b445ec4f3e2c522214508bd5eeca6b6471153c9f805e7f8228528a9faf6749fbfbc4f2e4612499397aeff8e928330c4 languageName: node linkType: hard @@ -15580,9 +15416,9 @@ __metadata: linkType: hard "preact@npm:^10.0.0": - version: 10.26.9 - resolution: "preact@npm:10.26.9" - checksum: 10c0/15f187e3278ae749b70e887f88bb01be63ebcc2eea46ffa86be69180716db40b8b4304e9768767fd68a5910ef5fd1f9ea6389e17cd25e950be76574d568e8fc3 + version: 10.28.2 + resolution: "preact@npm:10.28.2" + checksum: 10c0/eb60bf526eb6971701e6ac9c25236aca451f17f99e9c24704419196989b15bb576ed3101e084b151cd0fb30546b3e5e1ba73b774e8be2f2ed8187db42ec65faf languageName: node linkType: hard @@ -15712,18 +15548,18 @@ __metadata: linkType: hard "qs@npm:^6.12.3, qs@npm:^6.4.0": - version: 6.14.0 - resolution: "qs@npm:6.14.0" + version: 6.14.1 + resolution: "qs@npm:6.14.1" dependencies: side-channel: "npm:^1.1.0" - checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c + checksum: 10c0/0e3b22dc451f48ce5940cbbc7c7d9068d895074f8c969c0801ac15c1313d1859c4d738e46dc4da2f498f41a9ffd8c201bd9fb12df67799b827db94cc373d2613 languageName: node linkType: hard -"qsu@npm:^1.10.0": - version: 1.10.1 - resolution: "qsu@npm:1.10.1" - checksum: 10c0/6997ebce26a14474bfad4b1e5dfb1124b90c18b6427778a7e85cd31ac52017f769063dccd5fb1db028adabe6265ed5a8fd67f0619451e312bfa0aafb9fa75e37 +"qsu@npm:^1.10.4": + version: 1.11.1 + resolution: "qsu@npm:1.11.1" + checksum: 10c0/e460cfe205c356b7f7f6ebf63f2cc265bb2d3c5fae9aa4a0dd25f4b7e21d26c75bd6bfc6edc55e085470b436f965807eb77261838c130326d17897d41970c6e1 languageName: node linkType: hard @@ -16524,8 +16360,8 @@ __metadata: linkType: hard "sass@npm:^1.85.0": - version: 1.88.0 - resolution: "sass@npm:1.88.0" + version: 1.97.3 + resolution: "sass@npm:1.97.3" dependencies: "@parcel/watcher": "npm:^2.4.1" chokidar: "npm:^4.0.0" @@ -16536,7 +16372,7 @@ __metadata: optional: true bin: sass: sass.js - checksum: 10c0/dcb16dc29116bfa5a90485d24fd8020d2b0d95155bd2e31285901588729343b59fefe44365c5f146b2ba5a9ebadef90b23a7220b902507bdbd91ca2ba0a0b688 + checksum: 10c0/67f6b5d220f20c1c23a8b16dda5fd1c5d119ad5caf8195b185d553b5b239fb188a3787f04fc00171c62515f2c4e5e0eb5ad4992a80f8543428556883c1240ba3 languageName: node linkType: hard @@ -16616,7 +16452,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.2, semver@npm:^7.3.8, semver@npm:^7.7.1, semver@npm:^7.7.3": +"semver@npm:^7.0.0, semver@npm:^7.1.2, semver@npm:^7.3.8, semver@npm:^7.7.3": version: 7.7.3 resolution: "semver@npm:7.7.3" bin: @@ -16634,6 +16470,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.1": + version: 7.7.4 + resolution: "semver@npm:7.7.4" + bin: + semver: bin/semver.js + checksum: 10c0/5215ad0234e2845d4ea5bb9d836d42b03499546ddafb12075566899fc617f68794bb6f146076b6881d755de17d6c6cc73372555879ec7dce2c2feee947866ad2 + languageName: node + linkType: hard + "sentence-case@npm:^3.0.4": version: 3.0.4 resolution: "sentence-case@npm:3.0.4" @@ -16763,18 +16608,18 @@ __metadata: linkType: hard "shiki@npm:^3.15.0": - version: 3.20.0 - resolution: "shiki@npm:3.20.0" - dependencies: - "@shikijs/core": "npm:3.20.0" - "@shikijs/engine-javascript": "npm:3.20.0" - "@shikijs/engine-oniguruma": "npm:3.20.0" - "@shikijs/langs": "npm:3.20.0" - "@shikijs/themes": "npm:3.20.0" - "@shikijs/types": "npm:3.20.0" + version: 3.22.0 + resolution: "shiki@npm:3.22.0" + dependencies: + "@shikijs/core": "npm:3.22.0" + "@shikijs/engine-javascript": "npm:3.22.0" + "@shikijs/engine-oniguruma": "npm:3.22.0" + "@shikijs/langs": "npm:3.22.0" + "@shikijs/themes": "npm:3.22.0" + "@shikijs/types": "npm:3.22.0" "@shikijs/vscode-textmate": "npm:^10.0.2" "@types/hast": "npm:^3.0.4" - checksum: 10c0/e7f0a8e6b8748b1d25cccc186e5cd32cbc8b272c08b4b554a3328c95714ee564d5525747d5ceb52c1ee766ec25cb7a5fa1de748edeb6508a57be15433de1564f + checksum: 10c0/a7c91d769b42a69c496848197d876ec4577f789d1e7e3b5c18136a289f1dcac805bf24d56e43abb48be9c7cc6767c0f70eb2e2f33f77f4f5377141fb6851e840 languageName: node linkType: hard @@ -16879,10 +16724,10 @@ __metadata: languageName: node linkType: hard -"smol-toml@npm:^1.4.2": - version: 1.4.2 - resolution: "smol-toml@npm:1.4.2" - checksum: 10c0/e01e5f249b1ad852d09aa22f338a6cb3896ac35c92bf0d35744ce1b1e2f4b67901d4a0e886027617a2a8aa9f1a6c67c919c41b544c4aec137b6ebe042ca10d36 +"smol-toml@npm:^1.6.0": + version: 1.6.0 + resolution: "smol-toml@npm:1.6.0" + checksum: 10c0/baf33bb6cd914d481329e31998a12829cd126541458ba400791212c80f1245d5b27dac04a56a52c02b287d2a494f1628c05fc19643286b258b2e0bb9fe67747c languageName: node linkType: hard @@ -16945,10 +16790,10 @@ __metadata: linkType: hard "snyk-nodejs-lockfile-parser@npm:^2.4.2": - version: 2.4.2 - resolution: "snyk-nodejs-lockfile-parser@npm:2.4.2" + version: 2.5.0 + resolution: "snyk-nodejs-lockfile-parser@npm:2.5.0" dependencies: - "@snyk/dep-graph": "npm:^2.3.0" + "@snyk/dep-graph": "npm:^2.12.0" "@snyk/error-catalog-nodejs-public": "npm:^5.16.0" "@snyk/graphlib": "npm:2.1.9-patch.3" "@yarnpkg/core": "npm:^4.4.1" @@ -16968,7 +16813,7 @@ __metadata: uuid: "npm:^8.3.0" bin: parse-nodejs-lockfile: bin/index.js - checksum: 10c0/205aff1ea79306975a881f63d857af446e61ff7537d94efb591b993bd152e413b8688f360d58f5bcaef833e00395898c35b31ab179d6aa07dce9d1f753617fe0 + checksum: 10c0/9cc7d03322d76dd66df9372f542b3d980a0278e458a9402d29c4320e2054dab3821c59b0ac6c43b85fbaa0d216353e2b411b4c61efe8f60bf551c5c481a86518 languageName: node linkType: hard @@ -17528,6 +17373,13 @@ __metadata: languageName: node linkType: hard +"tabbable@npm:^6.0.0": + version: 6.4.0 + resolution: "tabbable@npm:6.4.0" + checksum: 10c0/d931427f4a96b801fd8801ba296a702119e06f70ad262fed8abc5271225c9f1ca51b89fdec4fb2f22e1d35acb3d2881db0a17cedc758272e9ecb540d00299d76 + languageName: node + linkType: hard + "tabbable@npm:^6.2.0": version: 6.2.0 resolution: "tabbable@npm:6.2.0" @@ -17723,9 +17575,9 @@ __metadata: linkType: hard "tm-themes@npm:^1.10.12": - version: 1.10.12 - resolution: "tm-themes@npm:1.10.12" - checksum: 10c0/dcb3ef2fede7ed373909caed11d8c6a89837eb7682515182cc9f52f0c580b5bb4d9f0019cb1c1199fea416bb8d327f31d5b696903aeaf66b2a88cbcad80cf632 + version: 1.11.1 + resolution: "tm-themes@npm:1.11.1" + checksum: 10c0/65e95f21e66723a67d62c04b697a22bac94eaccf61c6f75a0eb26816237ec68d5e507c770802253cccb2d1e0957a7f05f379e190edb32e346d19809dade3eaed languageName: node linkType: hard @@ -18056,22 +17908,22 @@ __metadata: linkType: hard "typedoc-plugin-frontmatter@npm:^1.3.0": - version: 1.3.0 - resolution: "typedoc-plugin-frontmatter@npm:1.3.0" + version: 1.3.1 + resolution: "typedoc-plugin-frontmatter@npm:1.3.1" dependencies: - yaml: "npm:^2.7.0" + yaml: "npm:^2.8.1" peerDependencies: - typedoc-plugin-markdown: ">=4.5.0" - checksum: 10c0/967ee5c38ab64b94489b9001744bbecc1cb6951bb07232caf2f4925f6a4dc0ac53305c4305e34ba10d6fddaab8f939642a2fbf10f1da884d6d6885d370c94cf3 + typedoc-plugin-markdown: ">=4.9.0" + checksum: 10c0/8bdda87c7a89b2a9dfdd3925c4b1a633c92696ca3fa110d96870a9d9bc2433afbe6d48e2b1b899bad4c7ae00970a8af1543d58e3e122db6d61055d1a2aff7dab languageName: node linkType: hard "typedoc-plugin-markdown@npm:^4.7.0": - version: 4.7.0 - resolution: "typedoc-plugin-markdown@npm:4.7.0" + version: 4.10.0 + resolution: "typedoc-plugin-markdown@npm:4.10.0" peerDependencies: typedoc: 0.28.x - checksum: 10c0/066cb8a0f96bb24c22069830d189904d624204b7ceaaeab78c72008ebb2c2bddb55170ae39fac31352caf20516a1a2360300cf384c9683f7b42465dc2c354bd1 + checksum: 10c0/20c7bc8ef68bd90053649ce223d02d4aceefed675c09efb1740c7791fbc37c10a1e25d14647605484a198f0695312eb21119015616d91c73fe1d63df5e4fb061 languageName: node linkType: hard @@ -18087,10 +17939,10 @@ __metadata: linkType: hard "typedoc@npm:^0.28.9": - version: 0.28.14 - resolution: "typedoc@npm:0.28.14" + version: 0.28.16 + resolution: "typedoc@npm:0.28.16" dependencies: - "@gerrit0/mini-shiki": "npm:^3.12.0" + "@gerrit0/mini-shiki": "npm:^3.17.0" lunr: "npm:^2.3.9" markdown-it: "npm:^14.1.0" minimatch: "npm:^9.0.5" @@ -18099,22 +17951,22 @@ __metadata: typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x bin: typedoc: bin/typedoc - checksum: 10c0/a8727134991ba3f9a982e9f6ceecfbcf0fac531e4865e4865cdee68ea6fe1a594228b8654011d38ffa2332b7e84e4eaa3d0dac04a8bdf36a0686d1c3f327e80b + checksum: 10c0/ae444913068088e88be6319a017a3a18f69cbd91dbb5b959fbdd0cf87d1a2a07f3a0d4ab29c957a83dd72808ff35bdd6ceec3ad1803fa412ddceffb78fa60ebb languageName: node linkType: hard "typescript-eslint@npm:^8.53.1": - version: 8.53.1 - resolution: "typescript-eslint@npm:8.53.1" + version: 8.55.0 + resolution: "typescript-eslint@npm:8.55.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.53.1" - "@typescript-eslint/parser": "npm:8.53.1" - "@typescript-eslint/typescript-estree": "npm:8.53.1" - "@typescript-eslint/utils": "npm:8.53.1" + "@typescript-eslint/eslint-plugin": "npm:8.55.0" + "@typescript-eslint/parser": "npm:8.55.0" + "@typescript-eslint/typescript-estree": "npm:8.55.0" + "@typescript-eslint/utils": "npm:8.55.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/520d68df8e1e1bba99c2713029b63837b101370c460bf5e75b8065fb0a6bc1ac9c6eb967432dbc220464479fe981630a6b2eddf31cfb378441ee8b8a43c0eb5a + checksum: 10c0/92e3e058a57bb29be7498093fd72f875e010170e1ca19214ae1bd1a1c9454354f71613ac9a6981f1e7e1d9e8b52df8888a1f42d0f2809dd5aeaf27f502787fda languageName: node linkType: hard @@ -18212,6 +18064,13 @@ __metadata: languageName: node linkType: hard +"ufo@npm:^1.6.1": + version: 1.6.3 + resolution: "ufo@npm:1.6.3" + checksum: 10c0/bf0e4ebff99e54da1b9c7182ac2f40475988b41faa881d579bc97bc2a0509672107b0a0e94c4b8d31a0ab8c4bf07f4aa0b469ac6da8536d56bda5b085ea2e953 + languageName: node + linkType: hard + "unbox-primitive@npm:^1.1.0": version: 1.1.0 resolution: "unbox-primitive@npm:1.1.0" @@ -18773,10 +18632,10 @@ __metadata: linkType: hard "vite@npm:^6.0.0 || ^7.0.0, vite@npm:^7.1.11": - version: 7.1.11 - resolution: "vite@npm:7.1.11" + version: 7.3.1 + resolution: "vite@npm:7.3.1" dependencies: - esbuild: "npm:^0.25.0" + esbuild: "npm:^0.27.0" fdir: "npm:^6.5.0" fsevents: "npm:~2.3.3" picomatch: "npm:^4.0.3" @@ -18823,23 +18682,23 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/c4aa7f47b1fb07f734ed6f4f605d73e5acf7ff9754d75b4adbfbdddf0e520413019834620c1f7b4a207bce7e1d20a2636c584db2b1b17f5a3ba2cd23d47e50ab + checksum: 10c0/5c7548f5f43a23533e53324304db4ad85f1896b1bfd3ee32ae9b866bac2933782c77b350eb2b52a02c625c8ad1ddd4c000df077419410650c982cd97fde8d014 languageName: node linkType: hard "vitepress-plugin-group-icons@npm:^1.6.5": - version: 1.6.5 - resolution: "vitepress-plugin-group-icons@npm:1.6.5" + version: 1.7.1 + resolution: "vitepress-plugin-group-icons@npm:1.7.1" dependencies: - "@iconify-json/logos": "npm:^1.2.9" - "@iconify-json/vscode-icons": "npm:^1.2.32" - "@iconify/utils": "npm:^3.0.2" + "@iconify-json/logos": "npm:^1.2.10" + "@iconify-json/vscode-icons": "npm:^1.2.39" + "@iconify/utils": "npm:^3.1.0" peerDependencies: vite: ">=3" peerDependenciesMeta: vite: optional: true - checksum: 10c0/8e30800925cdc2ae1aeafcb42d9aae5da4a3c922e8aa0bd629461f29ff1ba3a766cb45f7ee66a350a4be8acce5f7069457da36a3977255bf241858ba8a5dad36 + checksum: 10c0/9d24c09ef38155d5f2efb61e27162350bb90e9b89677f4af5e4287bebff2899506751ea8ef305f30feeead4416422955c45dbc0c38e48de884ec62c40b04dc56 languageName: node linkType: hard @@ -18859,13 +18718,13 @@ __metadata: linkType: hard "vitepress-sidebar@npm:^1.31.1": - version: 1.31.1 - resolution: "vitepress-sidebar@npm:1.31.1" + version: 1.33.1 + resolution: "vitepress-sidebar@npm:1.33.1" dependencies: - glob: "npm:10.4.5" + glob: "npm:11.1.0" gray-matter: "npm:4.0.3" - qsu: "npm:^1.10.0" - checksum: 10c0/0294cf2bdcde0cc48eef6b0dab73a13d1eee6d81a1860a225656185a43c7f842c202aa452f987c0cd1f0b383b3b1bf7242174262a568b2521b8ebffe9eba4962 + qsu: "npm:^1.10.4" + checksum: 10c0/9544aeb53ad062ffaf307bc52e47cf429af7275e816b7181d1e26538999f2d19e09fb1c0560ae26bc0114dba7a6925c8aa9a2132657ee42b9be0e1857c296a4c languageName: node linkType: hard @@ -18906,8 +18765,8 @@ __metadata: linkType: hard "vitest-browser-react@npm:^2.0.4": - version: 2.0.4 - resolution: "vitest-browser-react@npm:2.0.4" + version: 2.0.5 + resolution: "vitest-browser-react@npm:2.0.5" peerDependencies: "@types/react": ^18.0.0 || ^19.0.0 "@types/react-dom": ^18.0.0 || ^19.0.0 @@ -18919,7 +18778,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/d5c4c65dbdc42bb9a78ac3545f5294bcabb217b6d70f00464f1f1583e8c7f4e5d71d454e3a84f1dba1ce341b8885e84fcd716eca290a052c342c950b5aaa7c1b + checksum: 10c0/ae972fa20895c73622c2e724a2e2a716cc2a2e5148da19a60d1185323aeb5f5bd0653cfe3048d081bb086ee0efa68c0c360d28cdf42ddd8df6a5f2d17ffd0c9e languageName: node linkType: hard @@ -19431,7 +19290,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.0.0, yaml@npm:^2.8.0, yaml@npm:^2.8.1": +"yaml@npm:^2.0.0, yaml@npm:^2.8.0, yaml@npm:^2.8.1, yaml@npm:^2.8.2": version: 2.8.2 resolution: "yaml@npm:2.8.2" bin: @@ -19440,15 +19299,6 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.7.0": - version: 2.8.1 - resolution: "yaml@npm:2.8.1" - bin: - yaml: bin.mjs - checksum: 10c0/7c587be00d9303d2ae1566e03bc5bc7fe978ba0d9bf39cc418c3139d37929dfcb93a230d9749f2cb578b6aa5d9ebebc322415e4b653cb83acd8bc0bc321707f3 - languageName: node - linkType: hard - "yocto-queue@npm:^0.1.0": version: 0.1.0 resolution: "yocto-queue@npm:0.1.0" From f4293d2ed5dc3db41d4b7ca27229e2d00bec89a0 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:34:43 +0800 Subject: [PATCH 43/71] Fix format --- docs/src/modules/2-bundle/4-conventions/4-types.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/src/modules/2-bundle/4-conventions/4-types.md b/docs/src/modules/2-bundle/4-conventions/4-types.md index 5d56877d58..46732b7e9d 100644 --- a/docs/src/modules/2-bundle/4-conventions/4-types.md +++ b/docs/src/modules/2-bundle/4-conventions/4-types.md @@ -169,8 +169,6 @@ export function bar2(obj: Bar2Params) { } ``` - - ## 3. If a callback is passed as a parameter, its number of parameters should be validated By default, Javascript doesn't really mind if you call a function with fewer arguments than it was defined with: @@ -218,9 +216,8 @@ function draw_connected(pts: number): (c: Curve) => void { // ...implementation details } - return renderFunction + return renderFunction; } - ``` Then, in Source, if the cadet provides an invalid curve (a function that takes only 1 parameter), an error is thrown: From 54439178b6c166c4f6eb0584c761eccb14bccb86 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:44:23 +0800 Subject: [PATCH 44/71] Revert js-slang due to breaking changes --- yarn.lock | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index fc86f32dcd..577e930f4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1387,6 +1387,15 @@ __metadata: languageName: node linkType: hard +"@commander-js/extra-typings@npm:^12.0.1": + version: 12.1.0 + resolution: "@commander-js/extra-typings@npm:12.1.0" + peerDependencies: + commander: ~12.1.0 + checksum: 10c0/5d29eaa724b577e2a52a393ad54992924d2559931b8e493ab892477b7a4e878e475c6bf771260f8585d835f7d8e17ae4a2656c191e9595d210ae0b48291c0b3d + languageName: node + linkType: hard + "@commander-js/extra-typings@npm:^14.0.0": version: 14.0.0 resolution: "@commander-js/extra-typings@npm:14.0.0" @@ -2901,6 +2910,13 @@ __metadata: languageName: node linkType: hard +"@joeychenofficial/alt-ergo-modified@npm:^2.4.0": + version: 2.4.0 + resolution: "@joeychenofficial/alt-ergo-modified@npm:2.4.0" + checksum: 10c0/b6587dac0a76331602984ed61e482c2f7af2920d7069c873024bbc7575809ef440c7b91a7fb9a144b54abe98dd1d38a942e57f4476a0736a661c79bd66c176fa + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.12": version: 0.3.12 resolution: "@jridgewell/gen-mapping@npm:0.3.12" @@ -5617,7 +5633,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:1.0.8, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8": +"@types/estree@npm:*, @types/estree@npm:1.0.8, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 @@ -8195,6 +8211,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^12.0.0": + version: 12.1.0 + resolution: "commander@npm:12.1.0" + checksum: 10c0/6e1996680c083b3b897bfc1cfe1c58dfbcd9842fd43e1aaf8a795fbc237f65efcc860a3ef457b318e73f29a4f4a28f6403c3d653d021d960e4632dd45bde54a9 + languageName: node + linkType: hard + "commander@npm:^14.0.0, commander@npm:^14.0.3": version: 14.0.3 resolution: "commander@npm:14.0.3" @@ -12448,24 +12471,26 @@ __metadata: linkType: hard "js-slang@npm:^1.0.85": - version: 1.0.86 - resolution: "js-slang@npm:1.0.86" + version: 1.0.85 + resolution: "js-slang@npm:1.0.85" dependencies: "@babel/parser": "npm:^7.19.4" - "@commander-js/extra-typings": "npm:^14.0.0" + "@commander-js/extra-typings": "npm:^12.0.1" + "@joeychenofficial/alt-ergo-modified": "npm:^2.4.0" "@ts-morph/bootstrap": "npm:^0.18.0" + "@types/estree": "npm:^1.0.5" acorn: "npm:^8.8.2" acorn-class-fields: "npm:^1.0.0" acorn-loose: "npm:^8.0.0" acorn-walk: "npm:^8.0.0" astring: "npm:^1.4.3" - commander: "npm:^14.0.0" + commander: "npm:^12.0.0" js-base64: "npm:^3.7.5" lodash: "npm:^4.17.21" source-map: "npm:0.7.6" bin: js-slang: dist/repl/index.js - checksum: 10c0/ddf17e8df6748e3e6267f780b97db2135104e6b3987ba5633c8dfa94c1ce6524ec88ef48b180473bb30fb43739532d8063d4c6d6212b6b4715d3783e8fce1f8c + checksum: 10c0/8a206d6052e5b23a27bda4aef66675b4b7f9bebde936c789a182948478e26fa7aee6289effd0d867725a939e14674ee59fd218e1bec1fd1dc597b6bf7cbbaf42 languageName: node linkType: hard From b3e0d776557a73429136a5e76fa269a9b3b4c486 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:50:58 +0800 Subject: [PATCH 45/71] Fix lint issues --- docs/src/modules/3-tabs/1-overview.md | 2 +- lib/modules-lib/src/utilities.ts | 6 ++--- lib/vitest-reporter/src/coverage-reporter.cts | 22 +++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/src/modules/3-tabs/1-overview.md b/docs/src/modules/3-tabs/1-overview.md index 4455d780b0..3cae201d3b 100644 --- a/docs/src/modules/3-tabs/1-overview.md +++ b/docs/src/modules/3-tabs/1-overview.md @@ -67,7 +67,7 @@ The Frontend expects each tab's entry point to provide a default export of an ob ```ts interface ModuleSideContent { toSpawn: ((context: DebuggerContext) => boolean) | undefined; - body: ((context: DebuggerContext) => JSX.Element); + body: (context: DebuggerContext) => JSX.Element; label: string; iconName: string; } diff --git a/lib/modules-lib/src/utilities.ts b/lib/modules-lib/src/utilities.ts index d17f224a5b..f1641ff242 100644 --- a/lib/modules-lib/src/utilities.ts +++ b/lib/modules-lib/src/utilities.ts @@ -17,7 +17,7 @@ export function degreesToRadians(degrees: number): number { /** * Converts an angle in radians into degrees - * @param degrees Angle in radians + * @param radians Angle in radians * @returns Angle in degrees */ export function radiansToDegrees(radians: number): number { @@ -75,8 +75,8 @@ export type TupleOfLength = TupleOfLengthHelper any>(f: (...args: any) => any, l: Parameters['length']): f is T -export function isFunctionOfLength(f: unknown, l: T): f is (...args: TupleOfLength) => unknown +export function isFunctionOfLength any>(f: (...args: any) => any, l: Parameters['length']): f is T; +export function isFunctionOfLength(f: unknown, l: T): f is (...args: TupleOfLength) => unknown; export function isFunctionOfLength(f: unknown, l: number) { // TODO: Need a variation for rest parameters return typeof f === 'function' && f.length === l; diff --git a/lib/vitest-reporter/src/coverage-reporter.cts b/lib/vitest-reporter/src/coverage-reporter.cts index d9b8748a1e..2829865241 100644 --- a/lib/vitest-reporter/src/coverage-reporter.cts +++ b/lib/vitest-reporter/src/coverage-reporter.cts @@ -49,20 +49,20 @@ function getUncoveredLines(node: report.ReportNode) { let newRange = true; const ranges = coveredLines .reduce<([number] | [number, number])[]>((acum, [line, hit]) => { - if (hit) { - newRange = true; - } else { - const linenum = parseInt(line); - if (newRange) { - acum.push([linenum]); - newRange = false; + if (hit) { + newRange = true; } else { - acum[acum.length - 1][1] = linenum; + const linenum = parseInt(line); + if (newRange) { + acum.push([linenum]); + newRange = false; + } else { + acum[acum.length - 1][1] = linenum; + } } - } - return acum; - }, []); + return acum; + }, []); return ranges; } From f6466865349430a14218d2d52a44fb59387f7881 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:53:10 +0800 Subject: [PATCH 46/71] Update lib/buildtools/src/build/modules/__tests__/building.test.ts --- lib/buildtools/src/build/modules/__tests__/building.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/buildtools/src/build/modules/__tests__/building.test.ts b/lib/buildtools/src/build/modules/__tests__/building.test.ts index 167d10375f..49ed9c2726 100644 --- a/lib/buildtools/src/build/modules/__tests__/building.test.ts +++ b/lib/buildtools/src/build/modules/__tests__/building.test.ts @@ -84,7 +84,6 @@ test('build tab', async () => { expect(fs.open).toHaveBeenCalledExactlyOnceWith(pathlib.join(outDir, 'tabs', 'tab0.js'), 'w'); function mockRequire(path: string) { - // console.log(path); if (path === '@sourceacademy/modules-lib/tabs/utils') { return { defineTab: (x: any) => x From f3b9bf8a3c3d9d295391e9d091718473718c7259 Mon Sep 17 00:00:00 2001 From: Richard Dominick <34370238+RichDom2185@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:54:42 +0800 Subject: [PATCH 47/71] Add yarn checksum --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d897aa29a5..5797b4e9aa 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "onFail": "error" } }, - "packageManager": "yarn@4.12.0", + "packageManager": "yarn@4.12.0+sha512.f45ab632439a67f8bc759bf32ead036a1f413287b9042726b7cc4818b7b49e14e9423ba49b18f9e06ea4941c1ad062385b1d8760a8d5091a1a31e5f6219afca8", "workspaces": [ "./.github/actions", "./devserver", From 6d1fafd7a4bdfbe25a33a0c742ee88cf717818bb Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sun, 15 Feb 2026 02:19:57 +0800 Subject: [PATCH 48/71] Use a new error type to unify errors thrown by type guards --- .../modules/2-bundle/4-conventions/4-types.md | 41 +++++++--------- lib/modules-lib/src/errors.ts | 43 +++++++++++++++++ lib/modules-lib/src/utilities.ts | 11 +++-- src/bundles/curve/src/__tests__/curve.test.ts | 16 +++---- src/bundles/curve/src/drawers.ts | 7 +-- src/bundles/curve/src/functions.ts | 3 +- src/bundles/curve/src/index.ts | 5 +- src/bundles/sound/package.json | 2 +- src/bundles/sound/src/__tests__/sound.test.ts | 47 +++++++++++------- src/bundles/sound/src/functions.ts | 48 ++++++++++++++----- src/bundles/sound/src/play_in_tab.ts | 3 +- 11 files changed, 153 insertions(+), 73 deletions(-) create mode 100644 lib/modules-lib/src/errors.ts diff --git a/docs/src/modules/2-bundle/4-conventions/4-types.md b/docs/src/modules/2-bundle/4-conventions/4-types.md index 5d56877d58..55d487f69f 100644 --- a/docs/src/modules/2-bundle/4-conventions/4-types.md +++ b/docs/src/modules/2-bundle/4-conventions/4-types.md @@ -50,6 +50,18 @@ all cadets would see. As the typing system is improved, we may be able to use one set of typing for cadets and another for internal implementation. ::: +When throwing errors related to type checking, you should throw an `InvalidParameterTypeError`, which can be imported from the `modules-lib`: + +```ts +export function play(value: unknown) { + if (!is_sound(value)) { + throw new InvalidParameterTypeError('Sound', value, play.name); + } + + // ...implementation +} +``` + As part of ensuring type safety, there are several conventions bundle code should abide by: ## 1. Cadet facing functions should not have default or rest parameters @@ -208,11 +220,7 @@ import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; function draw_connected(pts: number): (c: Curve) => void { function renderFunction(c: Curve) { if (!isFunctionOfLength(curve, 1)) { - throw new Error( - `${renderFunction.name}: The provided curve is not a valid Curve function. ` + - 'A Curve function must take exactly one parameter (a number t between 0 and 1) ' + - 'and return a Point or 3D Point depending on whether it is a 2D or 3D curve.' - ); + throw new InvalidCallbackError('Curve', curve, draw_connected.name); } // ...implementation details @@ -220,7 +228,6 @@ function draw_connected(pts: number): (c: Curve) => void { return renderFunction } - ``` Then, in Source, if the cadet provides an invalid curve (a function that takes only 1 parameter), an error is thrown: @@ -231,6 +238,9 @@ import { draw_connected, make_point } from 'curve'; draw_connected(200)((a, b) => make_point(a, 0)); // error: The provided curve is not a valid Curve function. ``` +The `InvalidCallbackError` is a subclass of the `InvalidParameterTypeError`, specifically to be used for the error to be thrown +for invalid callbacks. + The `isFunctionOfLength` function is a type guard that also checks if the given input is a function at all, so it is not necessary to check for that separately: @@ -249,7 +259,7 @@ the specified number of parameters. It won't actually guarantee at runtime that ```ts export function call_callback(f: (a: string, b: string) => void) { if (!isFunctionOfLength(f, 2)) { - throw new Error(); + throw new InvalidCallbackError(2, f, call_callback.name); } return f('a', 'b'); @@ -265,25 +275,10 @@ and returns a value with type `unknown`: ```ts export function call_callback(f: unknown) { if (!isFunctionOfLength(f, 2)) { - throw new Error(); + throw new InvalidCallbackError(2, f, call_callback.name); } // Then f here gets narrowed to (a: unknown, b: unknown) => unknown return f('a', 'b'); } ``` - -For such a case, you can provide the type you want to narrow to as a generic type parameter: - -```ts -type Callback = (a: string, b: string) => void; - -export function call_callback(f: unknown) { - if (!isFunctionOfLength(f, 2)) { - throw new Error(); - } - - // Then f here gets narrowed to Callback - return f('a', 'b'); -} -``` diff --git a/lib/modules-lib/src/errors.ts b/lib/modules-lib/src/errors.ts new file mode 100644 index 0000000000..871d7b20d0 --- /dev/null +++ b/lib/modules-lib/src/errors.ts @@ -0,0 +1,43 @@ +import { RuntimeSourceError } from 'js-slang/dist/errors/runtimeSourceError'; +import { stringify } from 'js-slang/dist/utils/stringify'; + +export class InvalidParameterTypeError extends RuntimeSourceError { + constructor( + public readonly expectedType: string, + public readonly actualValue: unknown, + public readonly func_name: string, + public readonly param_name?: string + ) { + super() + } + + public override explain(): string { + const paramString = this.param_name ? ` for ${this.param_name}` : ''; + return `${this.func_name}: Expected ${this.expectedType}${paramString}, got ${stringify(this.actualValue)}.` + } + + public get message() { + return this.explain(); + } + + public override toString() { + return this.explain(); + } +} + +export class InvalidCallbackError extends InvalidParameterTypeError { + constructor( + expected: number | string, + actualValue: unknown, + func_name: string, + param_name?: string + ) { + const expectedStr = typeof expected === 'number' ? `function with ${expected} parameter${expected === 1 ? 's' : ''}` : expected; + super( + expectedStr, + actualValue, + func_name, + param_name + ) + } +} diff --git a/lib/modules-lib/src/utilities.ts b/lib/modules-lib/src/utilities.ts index d17f224a5b..59c864e5c0 100644 --- a/lib/modules-lib/src/utilities.ts +++ b/lib/modules-lib/src/utilities.ts @@ -4,6 +4,7 @@ * @title Utilities */ +import { InvalidCallbackError, InvalidParameterTypeError } from './errors'; import type { DebuggerContext } from './types'; /** @@ -72,12 +73,16 @@ type TupleOfLengthHelper = export type TupleOfLength = TupleOfLengthHelper; /** - * Type guard for checking that a function has the specified number of parameters. Of course at runtime parameter types - * are not checked, so this is only useful when combined with TypeScript types. + * Type guard for checking that the provided value is a function and that it has the specified number of parameters. + * Of course at runtime parameter types are not checked, so this is only useful when combined with TypeScript types. + * + * If the function's length property is undefined, the parameter count check is skipped. */ export function isFunctionOfLength any>(f: (...args: any) => any, l: Parameters['length']): f is T export function isFunctionOfLength(f: unknown, l: T): f is (...args: TupleOfLength) => unknown export function isFunctionOfLength(f: unknown, l: number) { // TODO: Need a variation for rest parameters - return typeof f === 'function' && f.length === l; + if (typeof f !== 'function') return false; + + return f.length === undefined || f.length === l; } diff --git a/src/bundles/curve/src/__tests__/curve.test.ts b/src/bundles/curve/src/__tests__/curve.test.ts index ae0ca283b9..18aeaf1847 100644 --- a/src/bundles/curve/src/__tests__/curve.test.ts +++ b/src/bundles/curve/src/__tests__/curve.test.ts @@ -4,6 +4,7 @@ import type { Color, Curve } from '../curves_webgl'; import * as drawers from '../drawers'; import * as funcs from '../functions'; import type { RenderFunctionCreator } from '../types'; +import { InvalidCallbackError, InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; /** * Evaluates the curve at 200 points, then @@ -28,11 +29,7 @@ describe('Ensure that invalid curves and animations error gracefully', () => { test('Curve that takes multiple parameters should throw error', () => { expect(() => drawers.draw_connected(200)(((t, u) => funcs.make_point(t, u)) as any)) - .toThrow( - 'The provided curve is not a valid Curve function. ' + - 'A Curve function must take exactly one parameter (a number t between 0 and 1) ' + - 'and return a Point or 3D Point depending on whether it is a 2D or 3D curve.' - ); + .toThrow(InvalidCallbackError); }); test('Using 3D render functions with animate_curve should throw errors', () => { @@ -120,7 +117,8 @@ describe('Coloured Points', () => { }); it('throws when argument is not a point', () => { - expect(() => funcs.r_of(0 as any)).toThrowError('r_of expects a point as argument'); + expect(() => funcs.r_of(0 as any)).toThrowError(InvalidParameterTypeError); + // expect(() => funcs.r_of(0 as any)).toThrowError('r_of: Expected Point, got 0'); }); }); @@ -131,7 +129,8 @@ describe('Coloured Points', () => { }); it('throws when argument is not a point', () => { - expect(() => funcs.g_of(0 as any)).toThrowError('g_of expects a point as argument'); + expect(() => funcs.g_of(0 as any)).toThrowError(InvalidParameterTypeError); + // expect(() => funcs.g_of(0 as any)).toThrowError('g_of: Expected Point, got 0'); }); }); @@ -142,7 +141,8 @@ describe('Coloured Points', () => { }); it('throws when argument is not a point', () => { - expect(() => funcs.b_of(0 as any)).toThrowError('b_of expects a point as argument'); + expect(() => funcs.b_of(0 as any)).toThrowError(InvalidParameterTypeError); + // expect(() => funcs.b_of(0 as any)).toThrowError('b_of: Expected Point, got 0'); }); }); }); diff --git a/src/bundles/curve/src/drawers.ts b/src/bundles/curve/src/drawers.ts index 1aa95b4593..750508ed52 100644 --- a/src/bundles/curve/src/drawers.ts +++ b/src/bundles/curve/src/drawers.ts @@ -12,6 +12,7 @@ import { type RenderFunctionCreator, type ScaleMode } from './types'; +import { InvalidCallbackError } from '@sourceacademy/modules-lib/errors'; const drawnCurves: (AnimatedCurve | CurveDrawn)[] = []; context.moduleContexts.curve.state = { @@ -35,11 +36,7 @@ function createDrawFunction( function renderFunc(curve: Curve) { if (!isFunctionOfLength(curve, 1)) { - throw new Error( - 'The provided curve is not a valid Curve function. ' + - 'A Curve function must take exactly one parameter (a number t between 0 and 1) ' + - 'and return a Point or 3D Point depending on whether it is a 2D or 3D curve.' - ); + throw new InvalidCallbackError('Curve', curve, name); } const curveDrawn = generateCurve( diff --git a/src/bundles/curve/src/functions.ts b/src/bundles/curve/src/functions.ts index c2fce8b1b4..4fd48fa921 100644 --- a/src/bundles/curve/src/functions.ts +++ b/src/bundles/curve/src/functions.ts @@ -2,10 +2,11 @@ import clamp from 'lodash/clamp'; import { Point, type Curve } from './curves_webgl'; import { functionDeclaration } from './type_interface'; import type { CurveTransformer } from './types'; +import { InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; function throwIfNotPoint(obj: unknown, func_name: string): asserts obj is Point { if (!(obj instanceof Point)) { - throw new Error(`${func_name} expects a point as argument`); + throw new InvalidParameterTypeError('Point', obj, func_name); } } diff --git a/src/bundles/curve/src/index.ts b/src/bundles/curve/src/index.ts index 001782b89f..27b111f138 100644 --- a/src/bundles/curve/src/index.ts +++ b/src/bundles/curve/src/index.ts @@ -14,11 +14,11 @@ * A *curve transformation* is a function that takes a curve as argument and * returns a curve. Examples of curve transformations are `scale` and `translate`. * - * A *curve drawer* is function that takes a number argument and returns + * A *render function* is function that takes a number argument and returns * a function that takes a curve as argument and visualises it in the output screen is * shown in the Source Academy in the tab with the "Curves Canvas" icon (image). * The following [example](https://share.sourceacademy.org/unitcircle) uses - * the curve drawer `draw_connected_full_view` to display a curve called + * the render function `draw_connected_full_view` to display a curve called * `unit_circle`. * ``` * import { make_point, draw_connected_full_view } from "curve"; @@ -34,6 +34,7 @@ * @author Lee Zheng Han * @author Ng Yong Xiang */ + export { arc, b_of, diff --git a/src/bundles/sound/package.json b/src/bundles/sound/package.json index 720c5f43e7..72b3c3f4e5 100644 --- a/src/bundles/sound/package.json +++ b/src/bundles/sound/package.json @@ -4,11 +4,11 @@ "private": true, "dependencies": { "@sourceacademy/bundle-midi": "workspace:^", + "@sourceacademy/modules-lib": "workspace:^", "js-slang": "^1.0.85" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", - "@sourceacademy/modules-lib": "workspace:^", "typescript": "^5.8.2" }, "type": "module", diff --git a/src/bundles/sound/src/__tests__/sound.test.ts b/src/bundles/sound/src/__tests__/sound.test.ts index ea9af73b35..485521da7a 100644 --- a/src/bundles/sound/src/__tests__/sound.test.ts +++ b/src/bundles/sound/src/__tests__/sound.test.ts @@ -1,4 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'; +import { stringify } from 'js-slang/dist/utils/stringify'; import * as funcs from '../functions'; import * as play_in_tab from '../play_in_tab'; import type { Sound, Wave } from '../types'; @@ -13,12 +14,12 @@ describe(funcs.make_sound, () => { }); it('Should not error when duration is zero', () => { - expect(() => funcs.make_sound(() => 0, 0)).not.toThrow(); + expect(() => funcs.make_sound(_t => 0, 0)).not.toThrow(); }); it('Should error gracefully when wave is not a function', () => { expect(() => funcs.make_sound(true as any, 1)) - .toThrow('make_sound expects a wave, got true'); + .toThrow('make_sound: Expected Wave, got true'); }); }); @@ -39,7 +40,7 @@ describe('Concurrent playback functions', () => { }); it('Should not error when duration is zero', () => { - const sound = funcs.make_sound(() => 0, 0); + const sound = funcs.make_sound(_t => 0, 0); expect(() => funcs.play(sound)).not.toThrow(); }); @@ -56,22 +57,22 @@ describe('Concurrent playback functions', () => { describe(funcs.play_wave, () => { it('Should error gracefully when duration is negative', () => { - expect(() => funcs.play_wave(() => 0, -1)) + expect(() => funcs.play_wave(_t => 0, -1)) .toThrow('play_wave: Sound duration must be greater than or equal to 0'); }); it('Should error gracefully when duration is not a number', () => { - expect(() => funcs.play_wave(() => 0, true as any)) - .toThrow('play_wave expects a number for duration, got true'); + expect(() => funcs.play_wave(_t => 0, true as any)) + .toThrow('play_wave: Expected number for duration, got true'); }); it('Should error gracefully when wave is not a function', () => { expect(() => funcs.play_wave(true as any, 0)) - .toThrow('play_wave expects a wave, got true'); + .toThrow('play_wave: Expected Wave, got true'); }); test('Concurrently playing two sounds should error', () => { - const wave: Wave = () => 0; + const wave: Wave = _t => 0; expect(() => funcs.play_wave(wave, 10)).not.toThrow(); expect(() => funcs.play_wave(wave, 10)).toThrowError('play: Previous sound still playing'); }); @@ -92,18 +93,18 @@ describe('Concurrent playback functions', () => { describe(play_in_tab.play_in_tab, () => { it('Should error gracefully when duration is negative', () => { - const sound = [() => 0, -1]; + const sound = [_t => 0, -1]; expect(() => play_in_tab.play_in_tab(sound as any)) .toThrow('play_in_tab: duration of sound is negative'); }); it('Should not error when duration is zero', () => { - const sound = funcs.make_sound(() => 0, 0); + const sound = funcs.make_sound(_t => 0, 0); expect(() => play_in_tab.play_in_tab(sound)).not.toThrow(); }); it('Should throw error when given not a sound', () => { - expect(() => play_in_tab.play_in_tab(0 as any)).toThrow('play_in_tab is expecting sound, but encountered 0'); + expect(() => play_in_tab.play_in_tab(0 as any)).toThrow('play_in_tab: Expected Sound, got 0'); }); test('Multiple calls does not cause an error', () => { @@ -127,8 +128,8 @@ function evaluateSound(sound: Sound) { describe(funcs.simultaneously, () => { it('works with sounds of the same duration', () => { - const sound0 = funcs.make_sound(() => 1, 10); - const sound1 = funcs.make_sound(() => 0, 10); + const sound0 = funcs.make_sound(_t => 1, 10); + const sound1 = funcs.make_sound(_t => 0, 10); const newSound = funcs.simultaneously([sound0, [sound1, null]]); const points = evaluateSound(newSound); @@ -141,8 +142,8 @@ describe(funcs.simultaneously, () => { }); it('works with sounds of different durations', () => { - const sound0 = funcs.make_sound(() => 1, 10); - const sound1 = funcs.make_sound(() => 2, 5); + const sound0 = funcs.make_sound(_t => 1, 10); + const sound1 = funcs.make_sound(_t => 2, 5); const newSound = funcs.simultaneously([sound0, [sound1, null]]); const points = evaluateSound(newSound); @@ -161,8 +162,8 @@ describe(funcs.simultaneously, () => { describe(funcs.consecutively, () => { it('works', () => { - const sound0 = funcs.make_sound(() => 1, 2); - const sound1 = funcs.make_sound(() => 2, 1); + const sound0 = funcs.make_sound(_t => 1, 2); + const sound1 = funcs.make_sound(_t => 2, 1); const newSound = funcs.consecutively([sound0, [sound1, null]]); const points = evaluateSound(newSound); @@ -175,3 +176,15 @@ describe(funcs.consecutively, () => { expect(points[2]).toEqual(2); }); }); + +describe('Sound transformers', () => { + describe(funcs.phase_mod, () => { + it('throws when given not a sound', () => { + expect(() => funcs.phase_mod(0, 1, 1)(0 as any)).toThrowError('SoundTransformer: Expected Sound, got 0'); + }); + + test('returned transformer toReplString representation', () => { + expect(stringify(funcs.phase_mod(0, 1, 1))).toEqual(''); + }); + }); +}); diff --git a/src/bundles/sound/src/functions.ts b/src/bundles/sound/src/functions.ts index 70e7c4f7c4..6f1842741c 100644 --- a/src/bundles/sound/src/functions.ts +++ b/src/bundles/sound/src/functions.ts @@ -1,3 +1,4 @@ +import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; import { midi_note_to_frequency } from '@sourceacademy/bundle-midi'; import { accumulate, @@ -17,6 +18,8 @@ import type { SoundTransformer, Wave } from './types'; +import type { MIDINote } from '@sourceacademy/bundle-midi/types'; +import { InvalidCallbackError, InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; // Global Constants and Variables export const FS: number = 44100; // Output sample rate @@ -286,7 +289,7 @@ export function record_for(duration: number, buffer: number): SoundPromise { */ function validateDuration(func_name: string, duration: unknown): asserts duration is number { if (typeof duration !== 'number') { - throw new Error(`${func_name} expects a number for duration, got ${duration}`); + throw new InvalidParameterTypeError('number', duration, func_name, 'duration'); } if (duration < 0) { @@ -298,8 +301,8 @@ function validateDuration(func_name: string, duration: unknown): asserts duratio * Throws an exception if wave is not a function */ function validateWave(func_name: string, wave: unknown): asserts wave is Wave { - if (typeof wave !== 'function') { - throw new Error(`${func_name} expects a wave, got ${wave}`); + if (!isFunctionOfLength(wave, 1)) { + throw new InvalidCallbackError('Wave', wave, func_name); } } @@ -636,6 +639,25 @@ export function simultaneously(list_of_sounds: List): Sound { return make_sound(normalised_wave, highest_duration); } +/** + * Utility function for wrapping Sound transformers. Adds the toReplString representation + * and adds check for verifying that the given input is a Sound. + */ +function wrapSoundTransformer(transformer: SoundTransformer): SoundTransformer { + function wrapped(sound: Sound) { + if (!is_sound(sound)) { + throw new InvalidParameterTypeError('Sound', sound, 'SoundTransformer'); + } + + return transformer(sound); + } + + wrapped.toReplString = () => ''; + // TODO: Remove when ReplResult is properly implemented + wrapped.toString = () => ''; + return wrapped; +} + /** * Returns an envelope: a function from Sound to Sound. * When the adsr envelope is applied to a Sound, it returns @@ -657,12 +679,14 @@ export function adsr( sustain_level: number, release_ratio: number ): SoundTransformer { - return sound => { + return wrapSoundTransformer(sound => { const wave = get_wave(sound); const duration = get_duration(sound); + const attack_time = duration * attack_ratio; const decay_time = duration * decay_ratio; const release_time = duration * release_ratio; + return make_sound((x) => { if (x < attack_time) { return wave(x) * (x / attack_time); @@ -683,7 +707,7 @@ export function adsr( * linear_decay(release_time)(x - (duration - release_time)) ); }, duration); - }; + }); } /** @@ -741,13 +765,13 @@ export function phase_mod( duration: number, amount: number ): SoundTransformer { - return modulator => { + return wrapSoundTransformer(modulator => { const wave = get_wave(modulator); return make_sound( t => Math.sin(2 * Math.PI * t * freq + amount * wave(t)), duration ); - }; + }); } // Instruments @@ -761,7 +785,7 @@ export function phase_mod( * @example bell(40, 1); * @category Instrument */ -export function bell(note: number, duration: number): Sound { +export function bell(note: MIDINote, duration: number): Sound { return stacking_adsr( square_sound, midi_note_to_frequency(note), @@ -784,7 +808,7 @@ export function bell(note: number, duration: number): Sound { * @example cello(36, 5); * @category Instrument */ -export function cello(note: number, duration: number): Sound { +export function cello(note: MIDINote, duration: number): Sound { return stacking_adsr( square_sound, midi_note_to_frequency(note), @@ -803,7 +827,7 @@ export function cello(note: number, duration: number): Sound { * @category Instrument * */ -export function piano(note: number, duration: number): Sound { +export function piano(note: MIDINote, duration: number): Sound { return stacking_adsr( triangle_sound, midi_note_to_frequency(note), @@ -821,7 +845,7 @@ export function piano(note: number, duration: number): Sound { * @example trombone(60, 2); * @category Instrument */ -export function trombone(note: number, duration: number): Sound { +export function trombone(note: MIDINote, duration: number): Sound { return stacking_adsr( square_sound, midi_note_to_frequency(note), @@ -839,7 +863,7 @@ export function trombone(note: number, duration: number): Sound { * @example violin(53, 4); * @category Instrument */ -export function violin(note: number, duration: number): Sound { +export function violin(note: MIDINote, duration: number): Sound { return stacking_adsr( sawtooth_sound, midi_note_to_frequency(note), diff --git a/src/bundles/sound/src/play_in_tab.ts b/src/bundles/sound/src/play_in_tab.ts index a55aa04fb1..3d0b9ec88f 100644 --- a/src/bundles/sound/src/play_in_tab.ts +++ b/src/bundles/sound/src/play_in_tab.ts @@ -2,6 +2,7 @@ import context from 'js-slang/context'; import { FS, get_duration, get_wave, is_sound } from './functions'; import { RIFFWAVE } from './riffwave'; import type { AudioPlayed, Sound } from './types'; +import { InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; export const audioPlayed: AudioPlayed[] = []; context.moduleContexts.sound.state = { audioPlayed }; @@ -18,7 +19,7 @@ context.moduleContexts.sound.state = { audioPlayed }; export function play_in_tab(sound: Sound): Sound { // Type-check sound if (!is_sound(sound)) { - throw new Error(`${play_in_tab.name} is expecting sound, but encountered ${sound}`); + throw new InvalidParameterTypeError('Sound', sound, play_in_tab.name); } const duration = get_duration(sound); From ec87a3b68936b879dfb15e68db74b2b14c0b57c7 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sun, 15 Feb 2026 03:25:23 +0800 Subject: [PATCH 49/71] Add the callback type checks to sound bundle --- src/bundles/sound/src/__tests__/recording.test.ts | 4 ++-- src/bundles/sound/src/__tests__/sound.test.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bundles/sound/src/__tests__/recording.test.ts b/src/bundles/sound/src/__tests__/recording.test.ts index b90d0fe763..f463db90d9 100644 --- a/src/bundles/sound/src/__tests__/recording.test.ts +++ b/src/bundles/sound/src/__tests__/recording.test.ts @@ -67,7 +67,7 @@ describe('Recording functions', () => { }); test('throws error if called concurrently with another sound', () => { - funcs.play_wave(() => 0, 10); + funcs.play_wave(_t => 0, 10); expect(() => funcs.record(1)).toThrowError('record: Cannot record while another sound is playing!'); }); @@ -105,7 +105,7 @@ describe('Recording functions', () => { }); test('throws error if called concurrently with another sound', () => { - funcs.play_wave(() => 0, 10); + funcs.play_wave(_t => 0, 10); expect(() => funcs.record_for(1, 1)).toThrowError('record_for: Cannot record while another sound is playing!'); }); diff --git a/src/bundles/sound/src/__tests__/sound.test.ts b/src/bundles/sound/src/__tests__/sound.test.ts index 485521da7a..133517495b 100644 --- a/src/bundles/sound/src/__tests__/sound.test.ts +++ b/src/bundles/sound/src/__tests__/sound.test.ts @@ -21,6 +21,11 @@ describe(funcs.make_sound, () => { expect(() => funcs.make_sound(true as any, 1)) .toThrow('make_sound: Expected Wave, got true'); }); + + it('Should error if the provided function does not take exactly one parameter', () => { + expect(() => funcs.make_sound(((_t, _u) => 0) as any, 1)) + .toThrow('make_sound: Expected Wave, got (_t, _u) => 0.'); + }); }); describe('Concurrent playback functions', () => { From a952439513de1306e3793cee44ccde9d39cd02e8 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sun, 15 Feb 2026 21:18:24 +0800 Subject: [PATCH 50/71] Linting fixes --- eslint.config.js | 13 ++++- lib/modules-lib/src/__tests__/errors.test.ts | 31 ++++++++++ .../src/__tests__/utilities.test.ts | 4 ++ lib/modules-lib/src/errors.ts | 57 +++++++++++++++++-- lib/modules-lib/src/utilities.ts | 8 ++- src/bundles/curve/src/__tests__/curve.test.ts | 2 +- src/bundles/curve/src/drawers.ts | 2 +- src/bundles/curve/src/functions.ts | 2 +- src/bundles/midi/src/types.ts | 2 +- src/bundles/repl/src/programmable_repl.ts | 2 +- src/bundles/sound/src/__tests__/sound.test.ts | 2 +- src/bundles/sound/src/functions.ts | 6 +- src/bundles/sound/src/play_in_tab.ts | 2 +- 13 files changed, 114 insertions(+), 19 deletions(-) create mode 100644 lib/modules-lib/src/__tests__/errors.test.ts diff --git a/eslint.config.js b/eslint.config.js index bd5a53239b..b65199117f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -168,7 +168,9 @@ export default defineConfig( } ], '@stylistic/no-extra-parens': ['warn', 'all', { - enforceForArrowConditionals: false, + ignoredNodes: [ + 'ArrowFunctionExpression[body.type=ConditionalExpression]' + ], ignoreJSX: 'all', nestedBinaryExpressions: false, }], @@ -336,7 +338,13 @@ export default defineConfig( // This rule doesn't seem to fail locally but fails on the CI // '@typescript-eslint/no-unnecessary-type-assertion': 'error', '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], // Was 'error' - '@typescript-eslint/only-throw-error': 'error' + '@typescript-eslint/only-throw-error': ['error', { + allow: [{ + from: 'package', + name: ['InvalidParameterTypeError', 'InvalidCallbackError'], + package: '@sourceacademy/modules-lib/errors', + }] + }] }, settings: { 'import/resolver': { @@ -371,7 +379,6 @@ export default defineConfig( '@stylistic/jsx-equals-spacing': ['warn', 'never'], '@stylistic/jsx-indent-props': ['warn', 2], - '@stylistic/jsx-props-no-multi-spaces': 'warn', '@stylistic/jsx-self-closing-comp': 'warn', }, settings: { diff --git a/lib/modules-lib/src/__tests__/errors.test.ts b/lib/modules-lib/src/__tests__/errors.test.ts new file mode 100644 index 0000000000..4ce189b613 --- /dev/null +++ b/lib/modules-lib/src/__tests__/errors.test.ts @@ -0,0 +1,31 @@ +import { describe, expect, test } from 'vitest'; +import { InvalidCallbackError, InvalidParameterTypeError } from '../errors'; + +describe(InvalidParameterTypeError, () => { + test('constructing without parameter name', () => { + const error = new InvalidParameterTypeError('number', 'abc', 'foo'); + expect(error.explain()).toEqual('foo: Expected number, got "abc".'); + }); + + test('constructing with parameter name', () => { + const error = new InvalidParameterTypeError('number', 'abc', 'foo', 'x'); + expect(error.explain()).toEqual('foo: Expected number for x, got "abc".'); + }); +}); + +describe(InvalidCallbackError, () => { + test('constructing with expected number of parameters being greater than 0', () => { + const error = new InvalidCallbackError(2, 'abc', 'foo'); + expect(error.explain()).toEqual('foo: Expected function with 2 parameters, got "abc".'); + }); + + test('constructing with expected number of parameters being 0', () => { + const error = new InvalidCallbackError(0, 'abc', 'foo'); + expect(error.explain()).toEqual('foo: Expected function with 0 parameters, got "abc".'); + }); + + test('constructing with expected callback type string', () => { + const error = new InvalidCallbackError('Curve', 'abc', 'foo', 'callback'); + expect(error.explain()).toEqual('foo: Expected Curve for callback, got "abc".'); + }); +}); diff --git a/lib/modules-lib/src/__tests__/utilities.test.ts b/lib/modules-lib/src/__tests__/utilities.test.ts index c88833ca99..5fb17d9aef 100644 --- a/lib/modules-lib/src/__tests__/utilities.test.ts +++ b/lib/modules-lib/src/__tests__/utilities.test.ts @@ -18,6 +18,10 @@ describe(hexToColor, () => { it('throws an error when an invalid hex string is passed', () => { expect(() => hexToColor('GGGGGG')).toThrowErrorMatchingInlineSnapshot('[Error: hexToColor: Invalid color hex string: GGGGGG]'); }); + + it('throws an error when a non-string is passed', () => { + expect(() => hexToColor(123 as any)).toThrowErrorMatchingInlineSnapshot('[Error: hexToColor: Expected a string, got number]'); + }); }); describe(isFunctionOfLength, () => { diff --git a/lib/modules-lib/src/errors.ts b/lib/modules-lib/src/errors.ts index 871d7b20d0..9a814b1ef3 100644 --- a/lib/modules-lib/src/errors.ts +++ b/lib/modules-lib/src/errors.ts @@ -1,19 +1,52 @@ +/** + * This module defines custom error classes for handling errors that occur in Source bundles. + * @module Errors + * @title Errors + */ + import { RuntimeSourceError } from 'js-slang/dist/errors/runtimeSourceError'; import { stringify } from 'js-slang/dist/utils/stringify'; +/** + * A specific {@link RuntimeSourceError|RuntimeSourceError} that is thrown when a function receives a parameter of the wrong type. + * + * @example + * ``` + * function play_sound(sound: unknown) { + * if (!is_sound(sound)) { + * throw new InvalidParameterTypeError('Sound', sound, play_sound.name, 'sound'); + * } + * } + * ``` + */ export class InvalidParameterTypeError extends RuntimeSourceError { constructor( + /** + * String representation of the expected type. Examples include "number", "string", or "Point". + */ public readonly expectedType: string, + + /** + * The actual value that was received. + */ public readonly actualValue: unknown, + + /** + * The name of the function that received the invalid parameter. + */ public readonly func_name: string, + + /** + * The name of the parameter that received the invalid value, if available. + */ public readonly param_name?: string ) { - super() + super(); } public override explain(): string { const paramString = this.param_name ? ` for ${this.param_name}` : ''; - return `${this.func_name}: Expected ${this.expectedType}${paramString}, got ${stringify(this.actualValue)}.` + return `${this.func_name}: Expected ${this.expectedType}${paramString}, got ${stringify(this.actualValue)}.`; } public get message() { @@ -25,19 +58,35 @@ export class InvalidParameterTypeError extends RuntimeSourceError { } } +/** + * A subclass of the {@link InvalidParameterTypeError|InvalidParameterTypeError} that is thrown when a function receives a callback parameter + * that is not a function or does not have the expected number of parameters. + * + * @example + * ``` + * function call_callback(callback: (x: number, y: number) => number) { + * if (!isFunctionOfLength(callback, 2)) { + * throw new InvalidCallbackError(2, callback, call_callback.name, 'callback'); + * } + * } + * ``` + */ export class InvalidCallbackError extends InvalidParameterTypeError { constructor( + /** + * Either the expected number of parameters of the callback function, or a string describing the expected callback type. + */ expected: number | string, actualValue: unknown, func_name: string, param_name?: string ) { - const expectedStr = typeof expected === 'number' ? `function with ${expected} parameter${expected === 1 ? 's' : ''}` : expected; + const expectedStr = typeof expected === 'number' ? `function with ${expected} parameter${expected !== 1 ? 's' : ''}` : expected; super( expectedStr, actualValue, func_name, param_name - ) + ); } } diff --git a/lib/modules-lib/src/utilities.ts b/lib/modules-lib/src/utilities.ts index 756afac17f..8e02e6ef20 100644 --- a/lib/modules-lib/src/utilities.ts +++ b/lib/modules-lib/src/utilities.ts @@ -4,7 +4,6 @@ * @title Utilities */ -import { InvalidCallbackError, InvalidParameterTypeError } from './errors'; import type { DebuggerContext } from './types'; /** @@ -31,6 +30,11 @@ export function radiansToDegrees(radians: number): number { * @returns Tuple of three numbers representing the R, G and B components */ export function hexToColor(hex: string, func_name?: string): [r: number, g: number, b: number] { + if (typeof hex !== 'string') { + func_name = func_name ?? hexToColor.name; + throw new Error(`${func_name}: Expected a string, got ${typeof hex}`); + } + const regex = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/igu; const groups = regex.exec(hex); @@ -75,7 +79,7 @@ export type TupleOfLength = TupleOfLengthHelper any>(f: (...args: any) => any, l: Parameters['length']): f is T; diff --git a/src/bundles/curve/src/__tests__/curve.test.ts b/src/bundles/curve/src/__tests__/curve.test.ts index 18aeaf1847..b78e5d3c68 100644 --- a/src/bundles/curve/src/__tests__/curve.test.ts +++ b/src/bundles/curve/src/__tests__/curve.test.ts @@ -1,10 +1,10 @@ +import { InvalidCallbackError, InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; import { stringify } from 'js-slang/dist/utils/stringify'; import { describe, expect, it, test } from 'vitest'; import type { Color, Curve } from '../curves_webgl'; import * as drawers from '../drawers'; import * as funcs from '../functions'; import type { RenderFunctionCreator } from '../types'; -import { InvalidCallbackError, InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; /** * Evaluates the curve at 200 points, then diff --git a/src/bundles/curve/src/drawers.ts b/src/bundles/curve/src/drawers.ts index 750508ed52..fe6d60946e 100644 --- a/src/bundles/curve/src/drawers.ts +++ b/src/bundles/curve/src/drawers.ts @@ -1,3 +1,4 @@ +import { InvalidCallbackError } from '@sourceacademy/modules-lib/errors'; import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; import context from 'js-slang/context'; @@ -12,7 +13,6 @@ import { type RenderFunctionCreator, type ScaleMode } from './types'; -import { InvalidCallbackError } from '@sourceacademy/modules-lib/errors'; const drawnCurves: (AnimatedCurve | CurveDrawn)[] = []; context.moduleContexts.curve.state = { diff --git a/src/bundles/curve/src/functions.ts b/src/bundles/curve/src/functions.ts index 4fd48fa921..3e33e68637 100644 --- a/src/bundles/curve/src/functions.ts +++ b/src/bundles/curve/src/functions.ts @@ -1,8 +1,8 @@ +import { InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; import clamp from 'lodash/clamp'; import { Point, type Curve } from './curves_webgl'; import { functionDeclaration } from './type_interface'; import type { CurveTransformer } from './types'; -import { InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; function throwIfNotPoint(obj: unknown, func_name: string): asserts obj is Point { if (!(obj instanceof Point)) { diff --git a/src/bundles/midi/src/types.ts b/src/bundles/midi/src/types.ts index 6291c6790a..df28275a29 100644 --- a/src/bundles/midi/src/types.ts +++ b/src/bundles/midi/src/types.ts @@ -11,7 +11,7 @@ type NotesWithFlats = 'A' | 'B' | 'D' | 'E' | 'G'; // & {} is a weird trick with typescript that causes intellisense to evaluate every single option // so you see all the valid notes instead of just the type definition below export type Note = {} & (NoteName | `${NoteName}${Accidental.NATURAL}` | `${NotesWithFlats}${Accidental.FLAT}` | `${NotesWithSharps}${Accidental.SHARP}`); -export type NoteWithOctave = (Note | `${Note}${number}`); +export type NoteWithOctave = Note | `${Note}${number}`; /** * An integer representing a MIDI note value. Refer to {@link https://i.imgur.com/qGQgmYr.png|this} mapping from diff --git a/src/bundles/repl/src/programmable_repl.ts b/src/bundles/repl/src/programmable_repl.ts index 7bb7678417..1d9bfc9720 100644 --- a/src/bundles/repl/src/programmable_repl.ts +++ b/src/bundles/repl/src/programmable_repl.ts @@ -10,7 +10,7 @@ import { COLOR_ERROR_MESSAGE, COLOR_RUN_CODE_RESULT, DEFAULT_EDITOR_HEIGHT } fro import { evaluatorSymbol } from './functions'; export class ProgrammableRepl { - public evalFunction: ((code: string) => any); + public evalFunction: (code: string) => any; public userCodeInEditor: string; public outputStrings: any[]; private _editorInstance; diff --git a/src/bundles/sound/src/__tests__/sound.test.ts b/src/bundles/sound/src/__tests__/sound.test.ts index 133517495b..8e392070c7 100644 --- a/src/bundles/sound/src/__tests__/sound.test.ts +++ b/src/bundles/sound/src/__tests__/sound.test.ts @@ -1,5 +1,5 @@ -import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'; import { stringify } from 'js-slang/dist/utils/stringify'; +import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'; import * as funcs from '../functions'; import * as play_in_tab from '../play_in_tab'; import type { Sound, Wave } from '../types'; diff --git a/src/bundles/sound/src/functions.ts b/src/bundles/sound/src/functions.ts index 6f1842741c..4bfd140dc8 100644 --- a/src/bundles/sound/src/functions.ts +++ b/src/bundles/sound/src/functions.ts @@ -1,5 +1,7 @@ -import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; import { midi_note_to_frequency } from '@sourceacademy/bundle-midi'; +import type { MIDINote } from '@sourceacademy/bundle-midi/types'; +import { InvalidCallbackError, InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; +import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; import { accumulate, head, @@ -18,8 +20,6 @@ import type { SoundTransformer, Wave } from './types'; -import type { MIDINote } from '@sourceacademy/bundle-midi/types'; -import { InvalidCallbackError, InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; // Global Constants and Variables export const FS: number = 44100; // Output sample rate diff --git a/src/bundles/sound/src/play_in_tab.ts b/src/bundles/sound/src/play_in_tab.ts index 3d0b9ec88f..9333f64c75 100644 --- a/src/bundles/sound/src/play_in_tab.ts +++ b/src/bundles/sound/src/play_in_tab.ts @@ -1,8 +1,8 @@ +import { InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; import context from 'js-slang/context'; import { FS, get_duration, get_wave, is_sound } from './functions'; import { RIFFWAVE } from './riffwave'; import type { AudioPlayed, Sound } from './types'; -import { InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; export const audioPlayed: AudioPlayed[] = []; context.moduleContexts.sound.state = { audioPlayed }; From 7db632c29e1d9c32dd77685e6a4d948e03287568 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Thu, 26 Feb 2026 23:42:14 +0800 Subject: [PATCH 51/71] General documentation updates --- .../2-bundle/4-conventions/2-abstractions.md | 10 +- .../2-bundle/4-conventions/3-errors.md | 43 +++++- .../modules/2-bundle/4-conventions/4-types.md | 139 ++++++++++++------ docs/src/modules/3-tabs/1-overview.md | 4 +- eslint.config.js | 19 ++- lib/modules-lib/src/errors.ts | 2 +- lib/modules-lib/src/tabs/useAnimation.ts | 2 +- src/bundles/rune/src/functions.ts | 4 +- 8 files changed, 167 insertions(+), 56 deletions(-) diff --git a/docs/src/modules/2-bundle/4-conventions/2-abstractions.md b/docs/src/modules/2-bundle/4-conventions/2-abstractions.md index c44202432f..b23f5d49ce 100644 --- a/docs/src/modules/2-bundle/4-conventions/2-abstractions.md +++ b/docs/src/modules/2-bundle/4-conventions/2-abstractions.md @@ -257,7 +257,14 @@ interface TextOptions { color: string; size: number; } -export function create_text_options(color: string, size: number): TextOptions; +export function create_text_options(color: string, size: number): TextOptions { + return { + color, + size, + // Of course, don't forget to implement `ReplResult`: + toReplString: () => '' + }; +} export function change_text_options(options: TextOptions): void; // Used like this: @@ -265,4 +272,5 @@ const options = create_text_options('blue', 20); change_text_options(options); ``` + The idea is that the abstraction of the `TextOptions` type is never broken and that the cadet never interacts with the object's component parts directly. diff --git a/docs/src/modules/2-bundle/4-conventions/3-errors.md b/docs/src/modules/2-bundle/4-conventions/3-errors.md index 7a60c5bbc8..b77e5df8b3 100644 --- a/docs/src/modules/2-bundle/4-conventions/3-errors.md +++ b/docs/src/modules/2-bundle/4-conventions/3-errors.md @@ -53,4 +53,45 @@ Then, the error can be thrown with the correct function name. Otherwise, cadets that is visible to them. Many other functions might rely on `throwIfNotRune`. If they were all called in the same program, it doesn't tell the cadet which function the error was thrown from (was it `show`? or `anaglyph`? or something else?) -An important use for error handling is when it comes to validating types. More information about type checking can be found in the next section. +An important use for error handling is when it comes to validating types. More information about type checking can be found in the [next](./4-types) section. + +> [!WARNING] Undefined Name Property +> +> It's possible to create functions without names using anonymous expressions: +> +> ```ts +> function getFunc(value: string) { +> return () => value; +> } +> +> export const getFoo = getFunc('foo'); +> +> // getFoo.name is undefined! +> console.log(getFoo.name); +> ``` +> +> A common case (especially if you are using type maps) is using an expression when defining a class function. This causes an anonymous function to be assigned to that property: +> +> ```ts +> class Functions { +> static bar = () => 'bar'; +> } +> +> // the name is also undefined! +> console.log(Functions.bar.name); +> ``` +> +> In such a case, you should take care to define the `name` property manually (at least on the exported version): +> +> ```ts +> function getFunc(value: string, func_name: string) { +> const func = () => value; +> Object.defineProperty(func, 'name', { value: func_name }); +> return func; +> } +> +> export const getFoo = getFunc('foo', 'foo'); +> +> // Now correctly prints foo! +> console.log(getFoo.name); +> ``` diff --git a/docs/src/modules/2-bundle/4-conventions/4-types.md b/docs/src/modules/2-bundle/4-conventions/4-types.md index c58c13f539..4257361fc1 100644 --- a/docs/src/modules/2-bundle/4-conventions/4-types.md +++ b/docs/src/modules/2-bundle/4-conventions/4-types.md @@ -48,25 +48,52 @@ Currently, bundle documentation for cadets relies on these type annotations bein all cadets would see. As the typing system is improved, we may be able to use one set of typing for cadets and another for internal implementation. + +In effect, all bundle functions really look like this: + +```ts +// Typescript style function overloads +export function show(rune: Rune): Rune; +export function show(rune: unknown) { + throwIfNotRune(show.name, rune); + drawnRunes.push(new NormalRune(rune)); + return rune; +} +``` ::: +## `InvalidTypeParameterError` + When throwing errors related to type checking, you should throw an `InvalidParameterTypeError`, which can be imported from the `modules-lib`: ```ts -export function play(value: unknown) { +import { InvalidTypeParameterError } from '@sourceacademy/modules-lib/errors'; + +export function play(value: unknown): asserts value is Sound { if (!is_sound(value)) { throw new InvalidParameterTypeError('Sound', value, play.name); + + // you can provide the name of the parameter too! + throw new InvalidParameterTypeError('Sound', value, play.name, 'value'); } // ...implementation } ``` -As part of ensuring type safety, there are several conventions bundle code should abide by: +The parameters of the constructor for `InvalidParameterTypeError` are as follows: +1. String representation of the expected type +2. Actual value passed in by the user +3. _Optional_: The name of the function that the error was thrown from (see [here](./3-errors) for more information) +4. _Optional_: The name of the parameter that is being validated + +## Type Safety Conventions + +As part of ensuring type safety, there are several function related conventions bundle code should abide by: -## 1. Cadet facing functions should not have default or rest parameters +### 1. Cadet facing functions should not have default, optional or rest parameters -The function signature below takes in two booleans, the second of which is optional. This is not supported for Module functions in Source, but is fine if your function +The functions make use of default, optional and rest parameters. This is not supported for Module functions in Source, but is fine if your function isn't being exposed to cadets. ```ts @@ -80,6 +107,11 @@ function concat_strings(...args: string[]) { return args.join(','); } +// or this +function configure_other_option(other_option?: boolean) { + // ...implementation +} + // But default and rest parameters are okay for internal use export function exposed_function() { configure_options(true); @@ -91,7 +123,19 @@ export function exposed_function() { Neither default nor rest parameters are currently supported due to an [issue](https://github.com/source-academy/js-slang/issues/1238) on the `js-slang` side. ::: -## 2. Cadet facing functions should not use destructuring for parameters +Instead, if you require such functionality, they should be defined as separate functions: + +```ts +// Equivalent implementation of configure_options from the above example + +export function configure_options_1_and_2(option_1: boolean, option_2: boolean) {} + +export function configure_option_1_only(option_1: boolean) { + configure_options_1_and_2(option_1, false); +} +``` + +### 2. Cadet facing functions should not use destructuring for parameters Javascript allows us to destruct iterables directly within a function's parameters: @@ -125,7 +169,7 @@ function bar({ x, y }: BarParams) { } ``` -However, Javascript doesn't actually throw an error if you pass an invalid object into the function: +In this case, Javascript doesn't actually throw an error if you pass an invalid object into the function: ```ts function bar({ x, y }: BarParams) { @@ -164,11 +208,13 @@ Uncaught TypeError: Cannot read properties of undefined (reading 'a') because of course, when `bar2` is called with `0`, `x` becomes `undefined` and trying to destructure `undefined` causes the `TypeError`. -If instead the parameter isn't destructured, it gives you the chance to perform type checking: +In both cases, if instead the parameter isn't destructured, you have the chance to perform type checking: ```ts export function foo(arr: [string, string]) { - if (!Array.isArray(arr)) throw new Error(); + if (!Array.isArray(arr) && arr.length !== 2) { + throw new InvalidParameterTypeError('Tuple of length 2', arr, foo.name, 'arr'); + } return arr[0]; } @@ -181,7 +227,7 @@ export function bar2(obj: Bar2Params) { } ``` -## 3. If a callback is passed as a parameter, its number of parameters should be validated +### 3. If a callback is passed as a parameter, its number of parameters should be validated By default, Javascript doesn't really mind if you call a function with fewer arguments than it was defined with: @@ -236,8 +282,17 @@ import { draw_connected, make_point } from 'curve'; draw_connected(200)((a, b) => make_point(a, 0)); // error: The provided curve is not a valid Curve function. ``` -The `InvalidCallbackError` is a subclass of the `InvalidParameterTypeError`, specifically to be used for the error to be thrown -for invalid callbacks. +> [!INFO] `InvalidCallbackError` +> +> The `InvalidCallbackError` is a subclass of the `InvalidParameterTypeError`, specifically to be used for the error to be thrown +> for invalid callbacks. The parameters for its constructor are as follows: +> +> 1. Number of Parameters/String representation of expected function: +> - If a number is given, it is assumed that a function with that number of parameters is expected +> - If a string is given, that will be used as a name for the function type. +> 2. The actual value passed in by the user +> 3. _Optional_: The name of the function that the error was thrown from (see [here](./3-errors) for more information) +> 4. _Optional_: The name of the parameter that is being validated The `isFunctionOfLength` function is a type guard that also checks if the given input is a function at all, so it is not necessary to check for that separately: @@ -249,34 +304,34 @@ function isFunctionOfLength(f: unknown, l: number): f is Function { } ``` -### Limitations of `isFunctionOfLength` - -Of course, `isFunctionOfLength` can only guarantee that the object passed to it is indeed a function and that it takes -the specified number of parameters. It won't actually guarantee at runtime that the provided parameters are of the defined types. For example: - -```ts -export function call_callback(f: (a: string, b: string) => void) { - if (!isFunctionOfLength(f, 2)) { - throw new InvalidCallbackError(2, f, call_callback.name); - } - - return f('a', 'b'); -} - -// isFunctionOfLength won't be able to guarantee that x and y are strings -call_callback((x, y) => x * y); -``` - -In fact, if you give it something of type `unknown`, the best it can do is narrow it down to a function that takes parameters of type `unknown` -and returns a value with type `unknown`: - -```ts -export function call_callback(f: unknown) { - if (!isFunctionOfLength(f, 2)) { - throw new InvalidCallbackError(2, f, call_callback.name); - } - - // Then f here gets narrowed to (a: unknown, b: unknown) => unknown - return f('a', 'b'); -} -``` +> [!WARN] Limitations of `isFunctionOfLength` +> +> Of course, `isFunctionOfLength` can only guarantee that the object passed to it is indeed a function and that it takes +> the specified number of parameters. It won't actually guarantee at runtime that the provided parameters are of the defined types. For example: +> +> ```ts +> export function call_callback(f: (a: string, b: string) => void) { +> if (!isFunctionOfLength(f, 2)) { +> throw new InvalidCallbackError(2, f, call_callback.name); +> } +> +> return f('a', 'b'); +> } +> +> // isFunctionOfLength won't be able to guarantee that x and y are strings +> call_callback((x, y) => x * y); +> ``` +> +> In fact, if you give it something of type `unknown`, the best it can do is narrow it down to a function that takes parameters of type `unknown` +> and returns a value with type `unknown`: +> +> ```ts +> export function call_callback(f: unknown) { +> if (!isFunctionOfLength(f, 2)) { +> throw new InvalidCallbackError(2, f, call_callback.name); +> } +> +> // Then f here gets narrowed to (a: unknown, b: unknown) => unknown +> return f('a', 'b'); +> } +> ``` diff --git a/docs/src/modules/3-tabs/1-overview.md b/docs/src/modules/3-tabs/1-overview.md index 3cae201d3b..38fb53f487 100644 --- a/docs/src/modules/3-tabs/1-overview.md +++ b/docs/src/modules/3-tabs/1-overview.md @@ -40,9 +40,9 @@ children: children: - name: __tests__ children: - - name: test.tsx + - name: index.test.tsx comment: You can use a tsx file - - name: test2.ts + - name: index.test.ts comment: Or a regular ts file - index.tsx - component.tsx diff --git a/eslint.config.js b/eslint.config.js index b65199117f..5b97670ea0 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -94,7 +94,6 @@ export default defineConfig( extends: [ymlPlugin.configs['flat/recommended']], files: ['**/*.yml', '**/*.yaml'], plugins: { - // @ts-expect-error Incorrect plugin type yml: ymlPlugin }, rules: { @@ -211,10 +210,11 @@ export default defineConfig( 'no-dupe-keys': 'off', 'no-redeclare': 'off', 'no-undef': 'off', + 'no-unreachable': 'off', 'no-unused-expressions': 'off', - 'react/jsx-no-undef': 'off', 'no-unused-vars': 'off', 'padded-blocks': 'off', + 'react/jsx-no-undef': 'off', // Adding a "use strict" directive at the top of every // code block is tedious and distracting. The config @@ -339,11 +339,16 @@ export default defineConfig( // '@typescript-eslint/no-unnecessary-type-assertion': 'error', '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], // Was 'error' '@typescript-eslint/only-throw-error': ['error', { - allow: [{ - from: 'package', - name: ['InvalidParameterTypeError', 'InvalidCallbackError'], - package: '@sourceacademy/modules-lib/errors', - }] + allowRethrowing: true, + allow: [ + // TODO: Remove these exceptions when js-slang errors inherit from Error + 'InvalidParameterTypeError', 'InvalidCallbackError', + // { + // from: 'package', + // name: ['InvalidParameterTypeError', 'InvalidCallbackError'], + // package: '@sourceacademy/modules-lib', + // } + ] }] }, settings: { diff --git a/lib/modules-lib/src/errors.ts b/lib/modules-lib/src/errors.ts index 9a814b1ef3..3a01846001 100644 --- a/lib/modules-lib/src/errors.ts +++ b/lib/modules-lib/src/errors.ts @@ -12,7 +12,7 @@ import { stringify } from 'js-slang/dist/utils/stringify'; * * @example * ``` - * function play_sound(sound: unknown) { + * function play_sound(sound: unknown): asserts sound is Sound { * if (!is_sound(sound)) { * throw new InvalidParameterTypeError('Sound', sound, play_sound.name, 'sound'); * } diff --git a/lib/modules-lib/src/tabs/useAnimation.ts b/lib/modules-lib/src/tabs/useAnimation.ts index 3445441e27..a2048c24e9 100644 --- a/lib/modules-lib/src/tabs/useAnimation.ts +++ b/lib/modules-lib/src/tabs/useAnimation.ts @@ -172,7 +172,7 @@ export function useAnimation({ * - Sets elapsed to 0 and draws the 0 frame to the canvas * - Sets lastFrameTimestamp to null * - Cancels the current animation request - * - If there was a an animation callback scheduled, call `requestFrame` again + * - If there was an animation callback scheduled, call `requestFrame` again */ function reset() { setElapsed(0); diff --git a/src/bundles/rune/src/functions.ts b/src/bundles/rune/src/functions.ts index 84731063b2..91f7d26de9 100644 --- a/src/bundles/rune/src/functions.ts +++ b/src/bundles/rune/src/functions.ts @@ -35,7 +35,9 @@ export type RuneModuleState = { }; function throwIfNotFraction(val: unknown, param_name: string, func_name: string): asserts val is number { - if (typeof val !== 'number') throw new Error(`${func_name}: ${param_name} must be a number!`); + if (typeof val !== 'number') { + throw new Error(`${func_name}: ${param_name} must be a number!`); + } if (val < 0) { throw new Error(`${func_name}: ${param_name} cannot be less than 0!`); From c43178bf236bb36a53f0a12d250619baca54a802 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 28 Feb 2026 12:04:26 +0800 Subject: [PATCH 52/71] Update linting and documentation --- docs/src/repotools/5-yarn.md | 5 +++++ eslint.config.js | 4 +++- lib/markdown-tree/src/tree.ts | 3 +-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/src/repotools/5-yarn.md b/docs/src/repotools/5-yarn.md index 2abbde97ac..0720f848c2 100644 --- a/docs/src/repotools/5-yarn.md +++ b/docs/src/repotools/5-yarn.md @@ -54,6 +54,11 @@ other package within this repository. Aside from `vitest-browser-react` and `@vitest/eslint-plugin`, all Vitest packages should have the same version range as Vitest throughout the repository. +### 6. `@types` dependencies are specified as Dev Dependencies + +The `@types` packages provide Typescript types for packages that don't come with them bundled. Typescript types should not ever be required at runtime, +so they should be specified as a `devDependency`. + ## Parallel Execution of Scripts Using the various options of the `yarn workspaces foreach` command, you can execute multiple tasks in parallel, which is how many of the commands in the root repository have been set up. diff --git a/eslint.config.js b/eslint.config.js index 5b97670ea0..fe27a57f11 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -152,6 +152,7 @@ export default defineConfig( '@stylistic/brace-style': ['warn', '1tbs', { allowSingleLine: true }], '@stylistic/function-call-spacing': ['warn', 'never'], '@stylistic/function-paren-newline': ['warn', 'multiline-arguments'], + '@stylistic/implicit-arrow-linebreak': ['error', 'beside'], '@stylistic/keyword-spacing': 'warn', '@stylistic/member-delimiter-style': [ 'warn', @@ -185,7 +186,8 @@ export default defineConfig( anonymous: 'always', asyncArrow: 'always', named: 'never' - }] + }], + '@stylistic/template-curly-spacing': 'warn' } }, { diff --git a/lib/markdown-tree/src/tree.ts b/lib/markdown-tree/src/tree.ts index 7c6a728609..1cce7ae5f4 100644 --- a/lib/markdown-tree/src/tree.ts +++ b/lib/markdown-tree/src/tree.ts @@ -174,5 +174,4 @@ const getName = ( * is the last child of its parent * @param structure The file or folder to test */ -const isLastChild = (structure: FileStructure): boolean => - Boolean(structure.parent && last(structure.parent.children) === structure); +const isLastChild = (structure: FileStructure) => !!structure.parent && last(structure.parent.children) === structure; From d39bb8fe218f0d676a542d471dd3ade106b3aac9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 28 Feb 2026 22:05:56 +0000 Subject: [PATCH 53/71] Bump fast-xml-parser from 5.3.6 to 5.4.1 Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 5.3.6 to 5.4.1. - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.3.6...v5.4.1) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-version: 5.4.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index dc4d75cd16..ff11ca8a3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10649,14 +10649,22 @@ __metadata: languageName: node linkType: hard +"fast-xml-builder@npm:^1.0.0": + version: 1.0.0 + resolution: "fast-xml-builder@npm:1.0.0" + checksum: 10c0/2631fda265c81e8008884d08944eeed4e284430116faa5b8b7a43a3602af367223b7bf01c933215c9ad2358b8666e45041bc038d64877156a2f88821841b3014 + languageName: node + linkType: hard + "fast-xml-parser@npm:^5.0.7": - version: 5.3.6 - resolution: "fast-xml-parser@npm:5.3.6" + version: 5.4.1 + resolution: "fast-xml-parser@npm:5.4.1" dependencies: + fast-xml-builder: "npm:^1.0.0" strnum: "npm:^2.1.2" bin: fxparser: src/cli/cli.js - checksum: 10c0/0150cc0566f327a76115de8b11628d717fb179010ed9bb77c52e579a7e6055a0f92f42f83678a6f1ec5b74411faec09713cb1f9b94bc687068ad86884a9199fa + checksum: 10c0/8c696438a0c64135faf93ea6a93879208d649b7c9a3293d30d6eb750dc7f766fd083c0df5a82786b60809c3ead64fad155f28dbed25efea91017aaf9f64c91e5 languageName: node linkType: hard From 47cb851520535ac5e675b7fff52ce9e6309983f0 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Mon, 2 Mar 2026 23:23:17 +0800 Subject: [PATCH 54/71] Remove extraneous line --- docs/src/modules/2-bundle/4-conventions/2-abstractions.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/modules/2-bundle/4-conventions/2-abstractions.md b/docs/src/modules/2-bundle/4-conventions/2-abstractions.md index b23f5d49ce..15fdc95f32 100644 --- a/docs/src/modules/2-bundle/4-conventions/2-abstractions.md +++ b/docs/src/modules/2-bundle/4-conventions/2-abstractions.md @@ -272,5 +272,4 @@ const options = create_text_options('blue', 20); change_text_options(options); ``` - The idea is that the abstraction of the `TextOptions` type is never broken and that the cadet never interacts with the object's component parts directly. From 4bc2449f80dedaf45ab958efa2750720e54ea092 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Tue, 3 Mar 2026 20:22:32 +0800 Subject: [PATCH 55/71] Fix missing lodash package in Unittest tab --- src/archive/.vscode/settings.json | 3 +++ src/tabs/Unittest/package.json | 1 + yarn.lock | 1 + 3 files changed, 5 insertions(+) create mode 100644 src/archive/.vscode/settings.json diff --git a/src/archive/.vscode/settings.json b/src/archive/.vscode/settings.json new file mode 100644 index 0000000000..f2370a27cb --- /dev/null +++ b/src/archive/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsserver.enable": false +} \ No newline at end of file diff --git a/src/tabs/Unittest/package.json b/src/tabs/Unittest/package.json index 3654f6abe4..1b1bfedad0 100644 --- a/src/tabs/Unittest/package.json +++ b/src/tabs/Unittest/package.json @@ -5,6 +5,7 @@ "dependencies": { "@sourceacademy/bundle-unittest": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", + "lodash": "^4.17.23", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/yarn.lock b/yarn.lock index da9e1974ea..0baf027f7d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4870,6 +4870,7 @@ __metadata: "@sourceacademy/modules-buildtools": "workspace:^" "@sourceacademy/modules-lib": "workspace:^" "@types/react": "npm:^18.3.1" + lodash: "npm:^4.17.23" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" languageName: unknown From 45557b9f3bad18f1a1bb9be2b0ab4cc22f73c03c Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Tue, 3 Mar 2026 20:36:32 +0800 Subject: [PATCH 56/71] Add missing dependencies to vitest optimizeDeps for modules-lib --- lib/modules-lib/vitest.config.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/modules-lib/vitest.config.ts b/lib/modules-lib/vitest.config.ts index 1fb0389d8a..8001c8de76 100644 --- a/lib/modules-lib/vitest.config.ts +++ b/lib/modules-lib/vitest.config.ts @@ -13,7 +13,10 @@ export default mergeConfig( '@blueprintjs/core', '@blueprintjs/icons', 'lodash', + 'lodash/clamp', 'vitest-browser-react', + 'js-slang/dist/errors/runtimeSourceError', + 'js-slang/dist/utils/stringify' ] }, plugins: [react()], From eeefeb3cc6e08df103cfe16f353b5624997080b1 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Tue, 3 Mar 2026 22:08:02 +0800 Subject: [PATCH 57/71] Change some errors to use InvalidTypeParameterError --- src/bundles/binary_tree/package.json | 3 ++- src/bundles/binary_tree/src/functions.ts | 5 +++-- src/bundles/curve/src/drawers.ts | 8 ++++++++ src/bundles/rune/src/runes_ops.ts | 5 ++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/bundles/binary_tree/package.json b/src/bundles/binary_tree/package.json index 9e68b5c26a..cecea6e285 100644 --- a/src/bundles/binary_tree/package.json +++ b/src/bundles/binary_tree/package.json @@ -3,7 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { - "js-slang": "^1.0.85" + "js-slang": "^1.0.85", + "@sourceacademy/modules-lib": "workspace:^" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/bundles/binary_tree/src/functions.ts b/src/bundles/binary_tree/src/functions.ts index 06f4507ca5..ee8db87d7e 100644 --- a/src/bundles/binary_tree/src/functions.ts +++ b/src/bundles/binary_tree/src/functions.ts @@ -1,3 +1,4 @@ +import { InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; import { head, is_list, is_pair, list, tail } from 'js-slang/dist/stdlib/list'; import type { BinaryTree, EmptyBinaryTree, NonEmptyBinaryTree } from './types'; @@ -71,11 +72,11 @@ export function is_empty_tree(value: BinaryTree): value is EmptyBinaryTree { function throwIfNotNonEmptyTree(value: unknown, func_name: string): asserts value is NonEmptyBinaryTree { if (!is_tree(value)) { - throw new Error(`${func_name} expects binary tree, received: ${value}`); + throw new InvalidParameterTypeError('binary tree', value, func_name); } if (is_empty_tree(value)) { - throw new Error(`${func_name} received an empty binary tree!`); + throw new InvalidParameterTypeError('non-empty binary tree', value, func_name); } } diff --git a/src/bundles/curve/src/drawers.ts b/src/bundles/curve/src/drawers.ts index fe6d60946e..34da58b0d2 100644 --- a/src/bundles/curve/src/drawers.ts +++ b/src/bundles/curve/src/drawers.ts @@ -393,6 +393,10 @@ class CurveAnimators { throw new Error(`${animate_curve.name} cannot be used with 3D draw function!`); } + if (!isFunctionOfLength(func, 1)) { + throw new InvalidCallbackError('CurveAnimation', func, animate_curve.name); + } + const anim = new AnimatedCurve(duration, fps, func, drawer, false); drawnCurves.push(anim); return anim; @@ -409,6 +413,10 @@ class CurveAnimators { throw new Error(`${animate_3D_curve.name} cannot be used with 2D draw function!`); } + if (!isFunctionOfLength(func, 1)) { + throw new InvalidCallbackError('CurveAnimation', func, animate_3D_curve.name); + } + const anim = new AnimatedCurve(duration, fps, func, drawer, true); drawnCurves.push(anim); return anim; diff --git a/src/bundles/rune/src/runes_ops.ts b/src/bundles/rune/src/runes_ops.ts index 2f327ceb4a..029585f9fa 100644 --- a/src/bundles/rune/src/runes_ops.ts +++ b/src/bundles/rune/src/runes_ops.ts @@ -1,6 +1,7 @@ /** * This file contains the bundle's private functions for runes. */ +import { InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; import { hexToColor as hexToColorUtil } from '@sourceacademy/modules-lib/utilities'; import { Rune } from './rune'; @@ -8,7 +9,9 @@ import { Rune } from './rune'; // Utility Functions // ============================================================================= export function throwIfNotRune(name: string, rune: unknown): asserts rune is Rune { - if (!(rune instanceof Rune)) throw new Error(`${name} expects a rune as argument.`); + if (!(rune instanceof Rune)) { + throw new InvalidParameterTypeError('Rune', rune, name); + } } // ============================================================================= From 7ddda5c2d2bfaebf9a5142823aa4e450f504d610 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Tue, 3 Mar 2026 22:29:49 +0800 Subject: [PATCH 58/71] Add InvalidCallbackError to Rune animations --- src/bundles/binary_tree/package.json | 4 ++-- src/bundles/rune/src/display.ts | 10 ++++++++++ yarn.lock | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/bundles/binary_tree/package.json b/src/bundles/binary_tree/package.json index cecea6e285..ab65f87875 100644 --- a/src/bundles/binary_tree/package.json +++ b/src/bundles/binary_tree/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { - "js-slang": "^1.0.85", - "@sourceacademy/modules-lib": "workspace:^" + "@sourceacademy/modules-lib": "workspace:^", + "js-slang": "^1.0.85" }, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/bundles/rune/src/display.ts b/src/bundles/rune/src/display.ts index c00eb000de..2b4e99226d 100644 --- a/src/bundles/rune/src/display.ts +++ b/src/bundles/rune/src/display.ts @@ -1,3 +1,5 @@ +import { InvalidCallbackError } from '@sourceacademy/modules-lib/errors'; +import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; import context from 'js-slang/context'; import { AnaglyphRune, HollusionRune } from './functions'; import { AnimatedRune, NormalRune, Rune, type DrawnRune, type RuneAnimation } from './rune'; @@ -43,6 +45,10 @@ class RuneDisplay { @functionDeclaration('duration: number, fps: number, func: RuneAnimation', 'AnimatedRune') static animate_rune(duration: number, fps: number, func: RuneAnimation) { + if (!isFunctionOfLength(func, 1)) { + throw new InvalidCallbackError('RuneAnimation', func, RuneDisplay.animate_rune.name); + } + const anim = new AnimatedRune(duration, fps, (n) => { const rune = func(n); throwIfNotRune(RuneDisplay.animate_rune.name, rune); @@ -54,6 +60,10 @@ class RuneDisplay { @functionDeclaration('duration: number, fps: number, func: RuneAnimation', 'AnimatedRune') static animate_anaglyph(duration: number, fps: number, func: RuneAnimation) { + if (!isFunctionOfLength(func, 1)) { + throw new InvalidCallbackError('RuneAnimation', func, RuneDisplay.animate_anaglyph.name); + } + const anim = new AnimatedRune(duration, fps, (n) => { const rune = func(n); throwIfNotRune(RuneDisplay.animate_anaglyph.name, rune); diff --git a/yarn.lock b/yarn.lock index 0baf027f7d..10a194cd2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4055,6 +4055,7 @@ __metadata: resolution: "@sourceacademy/bundle-binary_tree@workspace:src/bundles/binary_tree" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" + "@sourceacademy/modules-lib": "workspace:^" js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown From 884a8a9fa47b6e167f051a207729a451246ee015 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Tue, 3 Mar 2026 23:17:22 +0800 Subject: [PATCH 59/71] Add some missing functionality to midi --- src/bundles/midi/package.json | 1 + src/bundles/midi/src/__tests__/index.test.ts | 75 +++++++++++-- src/bundles/midi/src/index.ts | 105 +++++++++++++++++-- src/bundles/midi/src/utils.ts | 37 ++++--- yarn.lock | 1 + 5 files changed, 189 insertions(+), 30 deletions(-) diff --git a/src/bundles/midi/package.json b/src/bundles/midi/package.json index ecda58a0c2..1a1f51f885 100644 --- a/src/bundles/midi/package.json +++ b/src/bundles/midi/package.json @@ -7,6 +7,7 @@ "typescript": "^5.8.2" }, "dependencies": { + "@sourceacademy/modules-lib": "workspace:^", "js-slang": "^1.0.85" }, "type": "module", diff --git a/src/bundles/midi/src/__tests__/index.test.ts b/src/bundles/midi/src/__tests__/index.test.ts index 1ef04b31f6..6bcca320e1 100644 --- a/src/bundles/midi/src/__tests__/index.test.ts +++ b/src/bundles/midi/src/__tests__/index.test.ts @@ -1,32 +1,32 @@ import { list_to_vector } from 'js-slang/dist/stdlib/list'; import { describe, expect, test } from 'vitest'; -import { letter_name_to_midi_note, midi_note_to_letter_name } from '..'; +import * as funcs from '..'; import { major_scale, minor_scale } from '../scales'; import { Accidental, type Note, type NoteWithOctave } from '../types'; import { noteToValues } from '../utils'; describe('scales', () => { test('major_scale', () => { - const c0 = letter_name_to_midi_note('C0'); + const c0 = funcs.letter_name_to_midi_note('C0'); const scale = major_scale(c0); expect(list_to_vector(scale)).toMatchObject([12, 14, 16, 17, 19, 21, 23, 24]); }); test('minor_scale', () => { - const a0 = letter_name_to_midi_note('A0'); + const a0 = funcs.letter_name_to_midi_note('A0'); const scale = minor_scale(a0); expect(list_to_vector(scale)).toMatchObject([21, 23, 24, 26, 28, 29, 31, 33]); }); }); -describe(midi_note_to_letter_name, () => { +describe(funcs.midi_note_to_letter_name, () => { describe('Test with sharps', () => { test.each([ [12, 'C0'], [13, 'C#0'], [36, 'C2'], [69, 'A4'], - ] as [number, NoteWithOctave][])('%i should equal %s', (note, noteName) => expect(midi_note_to_letter_name(note, 'sharp')).toEqual(noteName)); + ] as [number, NoteWithOctave][])('%i should equal %s', (note, noteName) => expect(funcs.midi_note_to_letter_name(note, Accidental.SHARP)).toEqual(noteName)); }); describe('Test with flats', () => { @@ -35,7 +35,7 @@ describe(midi_note_to_letter_name, () => { [13, 'Db0'], [36, 'C2'], [69, 'A4'], - ] as [number, NoteWithOctave][])('%i should equal %s', (note, noteName) => expect(midi_note_to_letter_name(note, 'flat')).toEqual(noteName)); + ] as [number, NoteWithOctave][])('%i should equal %s', (note, noteName) => expect(funcs.midi_note_to_letter_name(note, Accidental.FLAT)).toEqual(noteName)); }); }); @@ -49,13 +49,72 @@ describe(noteToValues, () => { // Leaving out octave should set it to 4 automatically ['a', 'A', Accidental.NATURAL, 4] ] as [NoteWithOctave, Note, Accidental, number][])('%s', (note, expectedNote, expectedAccidental, expectedOctave) => { - const [actualNote, actualAccidental, actualOctave] = noteToValues(note); + const [actualNote, actualAccidental, actualOctave] = noteToValues(note, ''); expect(actualNote).toEqual(expectedNote); expect(actualAccidental).toEqual(expectedAccidental); expect(actualOctave).toEqual(expectedOctave); }); test('Invalid note should throw an error', () => { - expect(() => noteToValues('Fb9' as any)).toThrowError('noteToValues: Invalid Note with Octave: Fb9'); + expect(() => noteToValues('Fb9' as any, 'noteToValues')).toThrowError('noteToValues: Invalid Note with Octave: Fb9'); + }); +}); + +describe(funcs.add_octave_to_note, () => { + test('Valid note and octave', () => { + expect(funcs.add_octave_to_note('C', 4)).toEqual('C4'); + expect(funcs.add_octave_to_note('F#', 0)).toEqual('F#0'); + }); + + test('Invalid octave should throw an error', () => { + expect(() => funcs.add_octave_to_note('C', -1)).toThrowError('add_octave_to_note: Octave must be an integer greater than 0'); + expect(() => funcs.add_octave_to_note('C', 2.5)).toThrowError('add_octave_to_note: Octave must be an integer greater than 0'); + }); +}); + +describe(funcs.get_octave, () => { + test('Valid note with octave', () => { + expect(funcs.get_octave('C4')).toEqual(4); + expect(funcs.get_octave('F#0')).toEqual(0); + + // If octave is left out, it should default to 4 + expect(funcs.get_octave('F')).toEqual(4); + }); + + test('Invalid note should throw an error', () => { + expect(() => funcs.get_octave('Fb9' as any)).toThrowError('get_octave: Invalid Note with Octave: Fb9'); + }); +}); + +describe(funcs.key_signature_to_keys, () => { + test('Valid key signatures', () => { + expect(funcs.key_signature_to_keys(Accidental.SHARP, 0)).toEqual('C'); + expect(funcs.key_signature_to_keys(Accidental.SHARP, 2)).toEqual('D'); + expect(funcs.key_signature_to_keys(Accidental.FLAT, 3)).toEqual('Eb'); + }); + + test('Invalid number of accidentals should throw an error', () => { + expect(() => funcs.key_signature_to_keys(Accidental.SHARP, -1)).toThrowError('key_signature_to_keys: Number of accidentals must be a number between 0 and 6'); + expect(() => funcs.key_signature_to_keys(Accidental.SHARP, 7)).toThrowError('key_signature_to_keys: Number of accidentals must be a number between 0 and 6'); + expect(() => funcs.key_signature_to_keys(Accidental.SHARP, 2.5)).toThrowError('key_signature_to_keys: Number of accidentals must be a number between 0 and 6'); + }); + + test('Invalid accidental should throw an error', () => { + expect(() => funcs.key_signature_to_keys('invalid' as any, 2)).toThrowError('key_signature_to_keys: Expected accidental, got "invalid".'); + }); +}); + +describe(funcs.is_note_with_octave, () => { + test('Valid NoteWithOctaves', () => { + expect(funcs.is_note_with_octave('C4')).toBe(true); + expect(funcs.is_note_with_octave('F#0')).toBe(true); + expect(funcs.is_note_with_octave('Ab9')).toBe(true); + expect(funcs.is_note_with_octave('C')).toBe(true); + expect(funcs.is_note_with_octave('F#')).toBe(true); + }); + + test('Invalid NoteWithOctaves', () => { + expect(funcs.is_note_with_octave('Invalid')).toBe(false); + expect(funcs.is_note_with_octave(123)).toBe(false); }); }); diff --git a/src/bundles/midi/src/index.ts b/src/bundles/midi/src/index.ts index 83d6f6af23..84296f31cb 100644 --- a/src/bundles/midi/src/index.ts +++ b/src/bundles/midi/src/index.ts @@ -6,8 +6,17 @@ * @author leeyi45 */ -import { Accidental, type MIDINote, type NoteWithOctave } from './types'; -import { midiNoteToNoteName, noteToValues } from './utils'; +import { InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; +import { Accidental, type MIDINote, type Note, type NoteWithOctave } from './types'; +import { midiNoteToNoteName, noteToValues, parseNoteWithOctave } from './utils'; + +/** + * Returns a boolean value indicating whether the given value is a {@link NoteWithOctave|note name with octave}. + */ +export function is_note_with_octave(value: unknown): value is NoteWithOctave { + const res = parseNoteWithOctave(value); + return res !== null; +} /** * Converts a letter name to its corresponding MIDI note. @@ -76,19 +85,30 @@ export function letter_name_to_midi_note(note: NoteWithOctave): MIDINote { } /** - * Convert a MIDI note into its letter representation + * Convert a {@link MIDINote|MIDI note} into its {@link NoteWithOctave|letter representation} + * * @param midiNote Note to convert * @param accidental Whether to return the letter as with a sharp or with a flat * @function + * @example + * ``` + * midi_note_to_letter_name(61, SHARP); // Returns "C#4" + * midi_note_to_letter_name(61, FLAT); // Returns "Db4" + * + * // Notes without accidentals return the same letter name + * // regardless of whether SHARP or FLAT is passed in + * midi_note_to_letter_name(60, FLAT); // Returns "C4" + * midi_note_to_letter_name(60, SHARP); // Returns "C4" + * ``` */ -export function midi_note_to_letter_name(midiNote: MIDINote, accidental: 'flat' | 'sharp'): NoteWithOctave { +export function midi_note_to_letter_name(midiNote: MIDINote, accidental: Accidental.FLAT | Accidental.SHARP): NoteWithOctave { const octave = Math.floor(midiNote / 12) - 1; const note = midiNoteToNoteName(midiNote, accidental, midi_note_to_letter_name.name); return `${note}${octave}`; } /** - * Converts a MIDI note to its corresponding frequency. + * Converts a {@link MIDINote|MIDI note} to its corresponding frequency. * * @param note given MIDI note * @returns the frequency of the MIDI note @@ -101,16 +121,87 @@ export function midi_note_to_frequency(note: MIDINote): number { } /** - * Converts a letter name to its corresponding frequency. + * Converts a {@link NoteWithOctave|note name} to its corresponding frequency. * * @param note given letter name - * @returns the corresponding frequency + * @returns the corresponding frequency (in Hz) * @example letter_name_to_frequency("A4"); // Returns 440 */ export function letter_name_to_frequency(note: NoteWithOctave): number { return midi_note_to_frequency(letter_name_to_midi_note(note)); } +/** + * Takes the given {@link Note|Note} and adds the octave number to it. + * @example + * ``` + * add_octave_to_note('C', 4); // Returns "C4" + * ``` + */ +export function add_octave_to_note(note: Note, octave: number): NoteWithOctave { + if (!Number.isInteger(octave) || octave < 0) { + throw new Error(`${add_octave_to_note.name}: Octave must be an integer greater than 0`); + } + + return `${note}${octave}`; +} + +/** + * Gets the octave number from a given {@link NoteWithOctave|note name with octave}. + */ +export function get_octave(note: NoteWithOctave): number { + const [,, octave] = noteToValues(note, get_octave.name); + return octave; +} + +/** + * Gets the letter name from a given {@link NoteWithOctave|note name with octave} (without the accidental). + * @example + * ``` + * get_note_name('C#4'); // Returns "C" + * get_note_name('Eb3'); // Returns "E" + * ``` + */ +export function get_note_name(note: NoteWithOctave): Note { + const [noteName] = noteToValues(note, get_note_name.name); + return noteName; +} + +/** + * Gets the accidental from a given {@link NoteWithOctave|note name with octave}. + */ +export function get_accidental(note: NoteWithOctave): Accidental { + const [, accidental] = noteToValues(note, get_accidental.name); + return accidental; +} + +/** + * Converts the key signature to the corresponding key + * @example + * ``` + * key_signature_to_keys(SHARP, 2); // Returns "D", since the key of D has 2 sharps + * key_signature_to_keys(FLAT, 3); // Returns "Eb", since the key of Eb has 3 flats + * ``` + */ +export function key_signature_to_keys(accidental: Accidental.FLAT | Accidental.SHARP, numAccidentals: number): Note { + if (!Number.isInteger(numAccidentals) || numAccidentals < 0 || numAccidentals > 6) { + throw new Error(`${key_signature_to_keys.name}: Number of accidentals must be a number between 0 and 6`); + } + + switch (accidental) { + case Accidental.SHARP: { + const keys: Note[] = ['C', 'G', 'D', 'A', 'E', 'B', 'F#']; + return keys[numAccidentals]; + } + case Accidental.FLAT: { + const keys: Note[] = ['C', 'F', 'Bb', 'Eb', 'Ab', 'Db', 'Gb']; + return keys[numAccidentals]; + } + default: + throw new InvalidParameterTypeError('accidental', accidental, key_signature_to_keys.name); + } +} + export * from './scales'; /** diff --git a/src/bundles/midi/src/utils.ts b/src/bundles/midi/src/utils.ts index 7504409b7d..a0a6f0634a 100644 --- a/src/bundles/midi/src/utils.ts +++ b/src/bundles/midi/src/utils.ts @@ -1,23 +1,22 @@ import { Accidental, type MIDINote, type Note, type NoteName, type NoteWithOctave } from './types'; -export function noteToValues(note: NoteWithOctave, func_name: string = noteToValues.name) { +export function parseNoteWithOctave(note: NoteWithOctave): [NoteName, Accidental, number] | null; +export function parseNoteWithOctave(note: unknown): [NoteName, Accidental, number] | null; +export function parseNoteWithOctave(note: unknown): [NoteName, Accidental, number] | null { + if (typeof note !== 'string') return null; + const match = /^([A-Ga-g])([#♮b]?)(\d*)$/.exec(note); - if (match === null) throw new Error(`${func_name}: Invalid Note with Octave: ${note}`); + if (match === null) return null; const [, noteName, accidental, octaveStr] = match; switch (accidental) { case Accidental.SHARP: { - if (noteName === 'B' || noteName === 'E') { - throw new Error(`${func_name}: Invalid Note with Octave: ${note}`); - } - + if (noteName === 'B' || noteName === 'E') return null; break; } case Accidental.FLAT: { - if (noteName === 'F' || noteName === 'C') { - throw new Error(`${func_name}: Invalid Note with Octave: ${note}`); - } + if (noteName === 'F' || noteName === 'C') return null; break; } } @@ -30,30 +29,38 @@ export function noteToValues(note: NoteWithOctave, func_name: string = noteToVal ] as [NoteName, Accidental, number]; } -export function midiNoteToNoteName(midiNote: MIDINote, accidental: 'flat' | 'sharp', func_name: string): Note { +export function noteToValues(note: NoteWithOctave, func_name: string): [NoteName, Accidental, number] { + const res = parseNoteWithOctave(note); + if (res === null) { + throw new Error(`${func_name}: Invalid Note with Octave: ${note}`); + } + return res; +} + +export function midiNoteToNoteName(midiNote: MIDINote, accidental: Accidental.FLAT | Accidental.SHARP, func_name: string): Note { switch (midiNote % 12) { case 0: return 'C'; case 1: - return accidental === 'sharp' ? `C${Accidental.SHARP}` : `D${Accidental.FLAT}`; + return accidental === Accidental.SHARP ? `C${Accidental.SHARP}` : `D${Accidental.FLAT}`; case 2: return 'D'; case 3: - return accidental === 'sharp' ? `D${Accidental.SHARP}` : `E${Accidental.FLAT}`; + return accidental === Accidental.SHARP ? `D${Accidental.SHARP}` : `E${Accidental.FLAT}`; case 4: return 'E'; case 5: return 'F'; case 6: - return accidental === 'sharp' ? `F${Accidental.SHARP}` : `G${Accidental.FLAT}`; + return accidental === Accidental.SHARP ? `F${Accidental.SHARP}` : `G${Accidental.FLAT}`; case 7: return 'G'; case 8: - return accidental === 'sharp' ? `G${Accidental.SHARP}` : `A${Accidental.FLAT}`; + return accidental === Accidental.SHARP ? `G${Accidental.SHARP}` : `A${Accidental.FLAT}`; case 9: return 'A'; case 10: - return accidental === 'sharp' ? `A${Accidental.SHARP}` : `B${Accidental.FLAT}`; + return accidental === Accidental.SHARP ? `A${Accidental.SHARP}` : `B${Accidental.FLAT}`; case 11: return 'B'; default: diff --git a/yarn.lock b/yarn.lock index 10a194cd2f..d218dffe72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4135,6 +4135,7 @@ __metadata: resolution: "@sourceacademy/bundle-midi@workspace:src/bundles/midi" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" + "@sourceacademy/modules-lib": "workspace:^" js-slang: "npm:^1.0.85" typescript: "npm:^5.8.2" languageName: unknown From 0e87bc00d0e7c5086e7a9003462b39bb3dde7caf Mon Sep 17 00:00:00 2001 From: Lee Yi Date: Sat, 7 Mar 2026 12:11:57 +0800 Subject: [PATCH 60/71] Add type checks to repeat --- src/bundles/repeat/package.json | 3 ++ .../repeat/src/__tests__/index.test.ts | 26 ++++++++++++---- src/bundles/repeat/src/functions.ts | 31 ++++++++++++++++++- yarn.lock | 1 + 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/bundles/repeat/package.json b/src/bundles/repeat/package.json index f65d342dab..4e519a1379 100644 --- a/src/bundles/repeat/package.json +++ b/src/bundles/repeat/package.json @@ -6,6 +6,9 @@ "@sourceacademy/modules-buildtools": "workspace:^", "typescript": "^5.8.2" }, + "dependencies": { + "@sourceacademy/modules-lib": "workspace:^" + }, "type": "module", "exports": { ".": "./dist/index.js", diff --git a/src/bundles/repeat/src/__tests__/index.test.ts b/src/bundles/repeat/src/__tests__/index.test.ts index 3a3cff9e81..5b420c7706 100644 --- a/src/bundles/repeat/src/__tests__/index.test.ts +++ b/src/bundles/repeat/src/__tests__/index.test.ts @@ -1,11 +1,25 @@ -import { expect, test } from 'vitest'; - +import { describe, expect, test } from 'vitest'; import { repeat, thrice, twice } from '../functions'; -// Test functions -test('repeat works correctly and repeats function n times', () => { - expect(repeat((x: number) => x + 1, 5)(1)) - .toBe(6); +describe(repeat, () => { + test('repeat works correctly and repeats unary function n times', () => { + expect(repeat((x: number) => x + 1, 5)(1)) + .toBe(6); + }); + + test('when n = 0, f is the identity function', () => { + expect(repeat(x => x + 1, 0)(0)).toEqual(0); + }); + + test('throws an error when the function takes more than 1 parameter', () => { + expect(repeat((x, y) => x + y, 2)).toThrowError(); + expect(repeat(() => 2, 2)).toThrowError('repeat: '); + }); + + test('throws an error when provided incorrect integers', () => { + expect(repeat(x => x, -1)).toThrowError(); + expect(repeat(x => x, 1.5)).toThrowError(); + }); }); test('twice works correctly and repeats function twice', () => { diff --git a/src/bundles/repeat/src/functions.ts b/src/bundles/repeat/src/functions.ts index 04b659da1b..9823d4b048 100644 --- a/src/bundles/repeat/src/functions.ts +++ b/src/bundles/repeat/src/functions.ts @@ -3,6 +3,19 @@ * @module repeat */ +import { InvalidCallbackError } from '@sourceacademy/modules-lib/errors'; +import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; + +/** + * Represents a function that takes in 1 parameter and returns a + * value of the same type + */ +type UnaryFunction = (x: T) => T; + +function repeatInternal(f: UnaryFunction, n: number): UnaryFunction { + return n === 0 ? x => x : x => f(repeat(f, n - 1)(x)); +} + /** * Returns a new function which when applied to an argument, has the same effect * as applying the specified function to the same argument n times. @@ -16,7 +29,15 @@ * @returns the new function that has the same effect as func repeated n times */ export function repeat(func: Function, n: number): Function { - return n === 0 ? (x: any) => x : (x: any) => func(repeat(func, n - 1)(x)); + if (!isFunctionOfLength(func, 1)) { + throw new InvalidCallbackError(1, func, repeat.name); + } + + if (!Number.isInteger(n) || n < 0) { + throw new Error(`${repeat.name}: Expected non-negative integer, got ${n}`); + } + + return repeatInternal(func as UnaryFunction, n); } /** @@ -31,6 +52,10 @@ export function repeat(func: Function, n: number): Function { * @returns the new function that has the same effect as `(x => func(func(x)))` */ export function twice(func: Function): Function { + if (!isFunctionOfLength(func, 1)) { + throw new InvalidCallbackError(1, func, twice.name); + } + return repeat(func, 2); } @@ -46,5 +71,9 @@ export function twice(func: Function): Function { * @returns the new function that has the same effect as `(x => func(func(func(x))))` */ export function thrice(func: Function): Function { + if (!isFunctionOfLength(func, 1)) { + throw new InvalidCallbackError(1, func, thrice.name); + } + return repeat(func, 3); } diff --git a/yarn.lock b/yarn.lock index d218dffe72..aa6987677f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4213,6 +4213,7 @@ __metadata: resolution: "@sourceacademy/bundle-repeat@workspace:src/bundles/repeat" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" + "@sourceacademy/modules-lib": "workspace:^" typescript: "npm:^5.8.2" languageName: unknown linkType: soft From 595b52c01cc0adb8e973e6752b93894319c141f8 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 7 Mar 2026 12:44:37 +0800 Subject: [PATCH 61/71] Add type checking to repeat bundle --- .../repeat/src/__tests__/index.test.ts | 42 ++++++++++++------- src/bundles/repeat/src/functions.ts | 16 ++++--- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/bundles/repeat/src/__tests__/index.test.ts b/src/bundles/repeat/src/__tests__/index.test.ts index 5b420c7706..44d91aec3a 100644 --- a/src/bundles/repeat/src/__tests__/index.test.ts +++ b/src/bundles/repeat/src/__tests__/index.test.ts @@ -1,33 +1,43 @@ -import { describe, expect, test } from 'vitest'; -import { repeat, thrice, twice } from '../functions'; +import { describe, expect, test, vi } from 'vitest'; +import * as funcs from '../functions'; -describe(repeat, () => { +vi.spyOn(funcs, 'repeat'); + +describe(funcs.repeat, () => { test('repeat works correctly and repeats unary function n times', () => { - expect(repeat((x: number) => x + 1, 5)(1)) - .toBe(6); + expect(funcs.repeat((x: number) => x + 1, 5)(1)) + .toEqual(6); }); - test('when n = 0, f is the identity function', () => { - expect(repeat(x => x + 1, 0)(0)).toEqual(0); + test('returns the identity function when n = 0', () => { + expect(funcs.repeat((x: number) => x + 1, 0)(0)).toEqual(0); }); - test('throws an error when the function takes more than 1 parameter', () => { - expect(repeat((x, y) => x + y, 2)).toThrowError(); - expect(repeat(() => 2, 2)).toThrowError('repeat: '); + test('throws an error when the function doesn\'t take 1 parameter', () => { + expect(() => funcs.repeat((x: number, y: number) => x + y, 2)) + .toThrowError('repeat: Expected function with 1 parameter, got (x, y) => x + y.'); + + expect(() => funcs.repeat(() => 2, 2)) + .toThrowError('repeat: Expected function with 1 parameter, got () => 2.'); }); test('throws an error when provided incorrect integers', () => { - expect(repeat(x => x, -1)).toThrowError(); - expect(repeat(x => x, 1.5)).toThrowError(); + expect(() => funcs.repeat((x: number) => x, -1)) + .toThrowError('repeat: Expected non-negative integer, got -1.'); + + expect(() => funcs.repeat((x: number) => x, 1.5)) + .toThrowError('repeat: Expected non-negative integer, got 1.5.'); }); }); test('twice works correctly and repeats function twice', () => { - expect(twice((x: number) => x + 1)(1)) - .toBe(3); + expect(funcs.twice((x: number) => x + 1)(1)) + .toEqual(3); + expect(funcs.repeat).not.toHaveBeenCalled(); }); test('thrice works correctly and repeats function thrice', () => { - expect(thrice((x: number) => x + 1)(1)) - .toBe(4); + expect(funcs.thrice((x: number) => x + 1)(1)) + .toEqual(4); + expect(funcs.repeat).not.toHaveBeenCalled(); }); diff --git a/src/bundles/repeat/src/functions.ts b/src/bundles/repeat/src/functions.ts index 9823d4b048..ab43e06d8e 100644 --- a/src/bundles/repeat/src/functions.ts +++ b/src/bundles/repeat/src/functions.ts @@ -3,7 +3,7 @@ * @module repeat */ -import { InvalidCallbackError } from '@sourceacademy/modules-lib/errors'; +import { InvalidCallbackError, InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; /** @@ -12,7 +12,11 @@ import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; */ type UnaryFunction = (x: T) => T; -function repeatInternal(f: UnaryFunction, n: number): UnaryFunction { +/** + * Internal implementation of the repeat functions so that doesn't perform type checking + * @hidden + */ +export function repeat_internal(f: UnaryFunction, n: number): UnaryFunction { return n === 0 ? x => x : x => f(repeat(f, n - 1)(x)); } @@ -34,10 +38,10 @@ export function repeat(func: Function, n: number): Function { } if (!Number.isInteger(n) || n < 0) { - throw new Error(`${repeat.name}: Expected non-negative integer, got ${n}`); + throw new InvalidParameterTypeError('non-negative integer', n, repeat.name); } - return repeatInternal(func as UnaryFunction, n); + return repeat_internal(func, n); } /** @@ -56,7 +60,7 @@ export function twice(func: Function): Function { throw new InvalidCallbackError(1, func, twice.name); } - return repeat(func, 2); + return repeat_internal(func, 2); } /** @@ -75,5 +79,5 @@ export function thrice(func: Function): Function { throw new InvalidCallbackError(1, func, thrice.name); } - return repeat(func, 3); + return repeat_internal(func, 3); } From 8d7328c5b3e0845cdfe023cc29616658a5fee655 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sat, 7 Mar 2026 18:27:56 +0800 Subject: [PATCH 62/71] Add more type guard checks to unittest and fix broken tests --- .../binary_tree/src/__tests__/index.test.ts | 12 +++---- src/bundles/midi/src/utils.ts | 8 +++-- src/bundles/repeat/src/functions.ts | 2 +- src/bundles/rune/src/__tests__/index.test.ts | 24 +++++++------- src/bundles/unittest/package.json | 1 + .../unittest/src/__tests__/index.test.ts | 33 ++++++++++++++----- src/bundles/unittest/src/asserts.ts | 6 ++++ src/bundles/unittest/src/functions.ts | 9 +++++ src/bundles/unittest/src/mocks.ts | 7 ++-- yarn.lock | 1 + 10 files changed, 71 insertions(+), 32 deletions(-) diff --git a/src/bundles/binary_tree/src/__tests__/index.test.ts b/src/bundles/binary_tree/src/__tests__/index.test.ts index 4b7562ca24..0dc75487cc 100644 --- a/src/bundles/binary_tree/src/__tests__/index.test.ts +++ b/src/bundles/binary_tree/src/__tests__/index.test.ts @@ -49,11 +49,11 @@ describe(funcs.is_tree, () => { describe(funcs.entry, () => { it('throws when argument is not a tree', () => { - expect(() => funcs.entry(0 as any)).toThrowError('entry expects binary tree, received: 0'); + expect(() => funcs.entry(0 as any)).toThrowError('entry: Expected binary tree, got 0.'); }); it('throws when argument is an empty tree', () => { - expect(() => funcs.entry(null)).toThrowError('entry received an empty binary tree!'); + expect(() => funcs.entry(null)).toThrowError('entry: Expected non-empty binary tree, got null.'); }); it('works', () => { @@ -64,11 +64,11 @@ describe(funcs.entry, () => { describe(funcs.left_branch, () => { it('throws when argument is not a tree', () => { - expect(() => funcs.left_branch(0 as any)).toThrowError('left_branch expects binary tree, received: 0'); + expect(() => funcs.left_branch(0 as any)).toThrowError('left_branch: Expected binary tree, got 0.'); }); it('throws when argument is an empty tree', () => { - expect(() => funcs.left_branch(null)).toThrowError('left_branch received an empty binary tree!'); + expect(() => funcs.left_branch(null)).toThrowError('left_branch: Expected non-empty binary tree, got null.'); }); it('works (simple)', () => { @@ -87,11 +87,11 @@ describe(funcs.left_branch, () => { describe(funcs.right_branch, () => { it('throws when argument is not a tree', () => { - expect(() => funcs.right_branch(0 as any)).toThrowError('right_branch expects binary tree, received: 0'); + expect(() => funcs.right_branch(0 as any)).toThrowError('right_branch: Expected binary tree, got 0.'); }); it('throws when argument is an empty tree', () => { - expect(() => funcs.right_branch(null)).toThrowError('right_branch received an empty binary tree!'); + expect(() => funcs.right_branch(null)).toThrowError('right_branch: Expected non-empty binary tree, got null.'); }); it('works (simple)', () => { diff --git a/src/bundles/midi/src/utils.ts b/src/bundles/midi/src/utils.ts index a0a6f0634a..11fc4390bf 100644 --- a/src/bundles/midi/src/utils.ts +++ b/src/bundles/midi/src/utils.ts @@ -1,6 +1,6 @@ import { Accidental, type MIDINote, type Note, type NoteName, type NoteWithOctave } from './types'; -export function parseNoteWithOctave(note: NoteWithOctave): [NoteName, Accidental, number] | null; +export function parseNoteWithOctave(note: NoteWithOctave): [NoteName, Accidental, number]; export function parseNoteWithOctave(note: unknown): [NoteName, Accidental, number] | null; export function parseNoteWithOctave(note: unknown): [NoteName, Accidental, number] | null { if (typeof note !== 'string') return null; @@ -37,7 +37,11 @@ export function noteToValues(note: NoteWithOctave, func_name: string): [NoteName return res; } -export function midiNoteToNoteName(midiNote: MIDINote, accidental: Accidental.FLAT | Accidental.SHARP, func_name: string): Note { +export function midiNoteToNoteName( + midiNote: MIDINote, + accidental: Accidental.FLAT | Accidental.SHARP, + func_name: string +): Note { switch (midiNote % 12) { case 0: return 'C'; diff --git a/src/bundles/repeat/src/functions.ts b/src/bundles/repeat/src/functions.ts index ab43e06d8e..b242a4d2b0 100644 --- a/src/bundles/repeat/src/functions.ts +++ b/src/bundles/repeat/src/functions.ts @@ -17,7 +17,7 @@ type UnaryFunction = (x: T) => T; * @hidden */ export function repeat_internal(f: UnaryFunction, n: number): UnaryFunction { - return n === 0 ? x => x : x => f(repeat(f, n - 1)(x)); + return n === 0 ? x => x : x => f(repeat_internal(f, n - 1)(x)); } /** diff --git a/src/bundles/rune/src/__tests__/index.test.ts b/src/bundles/rune/src/__tests__/index.test.ts index 826a57cb22..0ca084916e 100644 --- a/src/bundles/rune/src/__tests__/index.test.ts +++ b/src/bundles/rune/src/__tests__/index.test.ts @@ -6,7 +6,7 @@ import type { Rune } from '../rune'; describe(display.anaglyph, () => { it('throws when argument is not rune', () => { - expect(() => display.anaglyph(0 as any)).toThrowError('anaglyph expects a rune as argument'); + expect(() => display.anaglyph(0 as any)).toThrowError('anaglyph: Expected Rune, got 0.'); }); it('returns the rune passed to it', () => { @@ -16,7 +16,7 @@ describe(display.anaglyph, () => { describe(display.hollusion, () => { it('throws when argument is not rune', () => { - expect(() => display.hollusion(0 as any)).toThrowError('hollusion expects a rune as argument'); + expect(() => display.hollusion(0 as any)).toThrowError('hollusion: Expected Rune, got 0.'); }); it('returns the rune passed to it', () => { @@ -26,7 +26,7 @@ describe(display.hollusion, () => { describe(display.show, () => { it('throws when argument is not rune', () => { - expect(() => display.show(0 as any)).toThrowError('show expects a rune as argument'); + expect(() => display.show(0 as any)).toThrowError('show: Expected Rune, got 0.'); }); it('returns the rune passed to it', () => { @@ -55,7 +55,7 @@ describe(funcs.color, () => { }); it('throws when argument is not rune', () => { - expect(() => funcs.color(0 as any, 0, 0, 0)).toThrowError('color expects a rune as argument'); + expect(() => funcs.color(0 as any, 0, 0, 0)).toThrowError('color: Expected Rune, got 0.'); }); it('throws when any color parameter is invalid', () => { @@ -67,8 +67,8 @@ describe(funcs.color, () => { describe(funcs.beside_frac, () => { it('throws when argument is not rune', () => { - expect(() => funcs.beside_frac(0, 0 as any, funcs.heart)).toThrowError('beside_frac expects a rune as argument'); - expect(() => funcs.beside_frac(0, funcs.heart, 0 as any)).toThrowError('beside_frac expects a rune as argument'); + expect(() => funcs.beside_frac(0, 0 as any, funcs.heart)).toThrowError('beside_frac: Expected Rune, got 0.'); + expect(() => funcs.beside_frac(0, funcs.heart, 0 as any)).toThrowError('beside_frac: Expected Rune, got 0.'); }); it('throws when frac is out of range', () => { @@ -88,8 +88,8 @@ describe(funcs.beside, () => { describe(funcs.stack_frac, () => { it('throws when argument is not rune', () => { - expect(() => funcs.stack_frac(0, 0 as any, funcs.heart)).toThrowError('stack_frac expects a rune as argument'); - expect(() => funcs.stack_frac(0, funcs.heart, 0 as any)).toThrowError('stack_frac expects a rune as argument'); + expect(() => funcs.stack_frac(0, 0 as any, funcs.heart)).toThrowError('stack_frac: Expected Rune, got 0.'); + expect(() => funcs.stack_frac(0, funcs.heart, 0 as any)).toThrowError('stack_frac: Expected Rune, got 0.'); }); it('throws when frac is out of range', () => { @@ -102,7 +102,7 @@ describe(funcs.stackn, () => { vi.spyOn(funcs.RuneFunctions, 'stack_frac'); it('throws when argument is not rune', () => { - expect(() => funcs.stackn(0, 0 as any)).toThrowError('stackn expects a rune as argument'); + expect(() => funcs.stackn(0, 0 as any)).toThrowError('stackn: Expected Rune, got 0.'); }); it('throws when n is not an integer', () => { @@ -131,8 +131,8 @@ describe(funcs.repeat_pattern, () => { describe(funcs.overlay_frac, () => { it('throws when argument is not rune', () => { - expect(() => funcs.overlay_frac(0, 0 as any, funcs.heart)).toThrowError('overlay_frac expects a rune as argument'); - expect(() => funcs.overlay_frac(0, funcs.heart, 0 as any)).toThrowError('overlay_frac expects a rune as argument'); + expect(() => funcs.overlay_frac(0, 0 as any, funcs.heart)).toThrowError('overlay_frac: Expected Rune, got 0.'); + expect(() => funcs.overlay_frac(0, funcs.heart, 0 as any)).toThrowError('overlay_frac: Expected Rune, got 0.'); }); it('throws when frac is out of range', () => { @@ -150,7 +150,7 @@ describe('Colouring functions', () => { describe.each(colourers)('%s', (_, f) => { it('throws when argument is not rune', () => { - expect(() => f(0 as any)).toThrowError(`${f.name} expects a rune as argument`); + expect(() => f(0 as any)).toThrowError(`${f.name}: Expected Rune, got 0.`); }); it('does not modify the original rune', () => { diff --git a/src/bundles/unittest/package.json b/src/bundles/unittest/package.json index cd0e741960..0a76490156 100644 --- a/src/bundles/unittest/package.json +++ b/src/bundles/unittest/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { + "@sourceacademy/modules-lib": "workspace:^", "js-slang": "^1.0.85", "lodash": "^4.17.23" }, diff --git a/src/bundles/unittest/src/__tests__/index.test.ts b/src/bundles/unittest/src/__tests__/index.test.ts index 4890a8332f..7b0316cab6 100644 --- a/src/bundles/unittest/src/__tests__/index.test.ts +++ b/src/bundles/unittest/src/__tests__/index.test.ts @@ -13,7 +13,7 @@ describe('Test \'it\' and \'describe\'', () => { testing.suiteResults.splice(0); }); - test('it and describe correctly set and resets the value of current test and suite', () => { + test('it() and describe() correctly set and resets the value of current test and suite', () => { expect(testing.currentTest).toBeNull(); expect(testing.currentSuite).toBeNull(); testing.describe('suite', () => { @@ -124,12 +124,29 @@ describe('Test \'it\' and \'describe\'', () => { expect(f).toThrowError('it cannot be called from within another test!'); }); + + test('it() and describe() throw when provided a non-nullary function', () => { + expect(() => testing.it('test name', 0 as any)).toThrow( + 'it: A test or test suite must be a nullary function!' + ); + + expect(() => testing.describe('test name', 0 as any)).toThrow( + 'describe: A test or test suite must be a nullary function!' + ); + }); }); describe('Test assertion functions', () => { - test('assert', () => { - expect(() => asserts.assert(() => true)).not.toThrow(); - expect(() => asserts.assert(() => false)).toThrow('Assert failed'); + describe(asserts.assert, () => { + it('works', () => { + expect(() => asserts.assert(() => true)).not.toThrow(); + expect(() => asserts.assert(() => false)).toThrow('Assert failed'); + }); + + it('will throw an error if not provided a nullary function', () => { + expect(() => asserts.assert(0 as any)).toThrow(`${asserts.assert.name} expects a nullary function that returns a boolean!`); + expect(() => asserts.assert((x => x === true) as any)).toThrow(`${asserts.assert.name} expects a nullary function that returns a boolean!`); + }); }); describe(asserts.assert_equals, () => { @@ -375,19 +392,19 @@ describe('Mocking functions', () => { describe(mocks.get_arg_list, () => { it('throws when function isn\'t a mocked function', () => { - expect(() => mocks.get_arg_list((() => 0) as any)).toThrowError('get_arg_list expects a mocked function as argument'); + expect(() => mocks.get_arg_list((() => 0) as any)).toThrowError('get_arg_list: Expected mocked function, got () => 0.'); }); }); describe(mocks.get_ret_vals, () => { it('throws when function isn\'t a mocked function', () => { - expect(() => mocks.get_ret_vals((() => 0) as any)).toThrowError('get_ret_vals expects a mocked function as argument'); + expect(() => mocks.get_ret_vals((() => 0) as any)).toThrowError('get_ret_vals: Expected mocked function, got () => 0.'); }); }); describe(mocks.clear_mock, () => { it('throws when function isn\'t a mocked function', () => { - expect(() => mocks.clear_mock((() => 0) as any)).toThrowError('clear_mock expects a mocked function as argument'); + expect(() => mocks.clear_mock((() => 0) as any)).toThrowError('clear_mock: Expected mocked function, got () => 0.'); }); it('works', () => { @@ -402,7 +419,7 @@ describe('Mocking functions', () => { describe(mocks.mock_function, () => { it('throws when passed not a function', () => { - expect(() => mocks.mock_function(0 as any)).toThrowError('mock_function expects a function as argument'); + expect(() => mocks.mock_function(0 as any)).toThrowError('mock_function: Expected function, got 0.'); }); }); }); diff --git a/src/bundles/unittest/src/asserts.ts b/src/bundles/unittest/src/asserts.ts index abba0c02ed..1f6977c2f1 100644 --- a/src/bundles/unittest/src/asserts.ts +++ b/src/bundles/unittest/src/asserts.ts @@ -1,6 +1,8 @@ +import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; import * as list from 'js-slang/dist/stdlib/list'; import { stringify } from 'js-slang/dist/utils/stringify'; import isEqualWith from 'lodash/isEqualWith'; +import { UnitestBundleInternalError } from './types'; /** * Asserts that a predicate returns true. @@ -8,6 +10,10 @@ import isEqualWith from 'lodash/isEqualWith'; * @returns */ export function assert(pred: () => boolean) { + if (!isFunctionOfLength(pred, 0)) { + throw new UnitestBundleInternalError(`${assert.name} expects a nullary function that returns a boolean!`); + } + if (!pred()) { throw new Error('Assert failed!'); } diff --git a/src/bundles/unittest/src/functions.ts b/src/bundles/unittest/src/functions.ts index 76c54e4b91..98f5d87b48 100644 --- a/src/bundles/unittest/src/functions.ts +++ b/src/bundles/unittest/src/functions.ts @@ -1,3 +1,4 @@ +import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; import context from 'js-slang/context'; import { @@ -36,6 +37,10 @@ function handleErr(err: any) { } function runTest(name: string, funcName: string, func: Test) { + if (!isFunctionOfLength(func, 0)) { + throw new UnitestBundleInternalError(`${funcName}: A test or test suite must be a nullary function!`); + } + if (currentSuite === null) { throw new UnitestBundleInternalError(`${funcName} must be called from within a test suite!`); } @@ -104,6 +109,10 @@ function determinePassCount(results: (TestResult | SuiteResult)[]): number { * @param func Function containing tests. */ export function describe(msg: string, func: TestSuite): void { + if (!isFunctionOfLength(func, 0)) { + throw new UnitestBundleInternalError(`${describe.name}: A test or test suite must be a nullary function!`); + } + const oldSuite = currentSuite; const newSuite = getNewSuite(msg); diff --git a/src/bundles/unittest/src/mocks.ts b/src/bundles/unittest/src/mocks.ts index 7e927256f2..386770db45 100644 --- a/src/bundles/unittest/src/mocks.ts +++ b/src/bundles/unittest/src/mocks.ts @@ -1,3 +1,4 @@ +import { InvalidCallbackError, InvalidParameterTypeError } from '@sourceacademy/modules-lib/errors'; import { pair, vector_to_list, type List } from 'js-slang/dist/stdlib/list'; /** @@ -13,9 +14,9 @@ interface MockedFunction { }; } -function throwIfNotMockedFunction(obj: (...args: any[]) => any, func_name: string): asserts obj is MockedFunction { +function throwIfNotMockedFunction(obj: (...args: any[]) => any, func_name: string, param_name?: string): asserts obj is MockedFunction { if (!(mockSymbol in obj)) { - throw new Error(`${func_name} expects a mocked function as argument`); + throw new InvalidCallbackError('mocked function', obj, func_name, param_name); } } @@ -28,7 +29,7 @@ function throwIfNotMockedFunction(obj: (...args: any[]) => any, func_name: strin */ export function mock_function(fn: (...args: any[]) => any): MockedFunction { if (typeof fn !== 'function') { - throw new Error(`${mock_function.name} expects a function as argument`); + throw new InvalidParameterTypeError('function', fn, mock_function.name); } const arglist: any[] = []; diff --git a/yarn.lock b/yarn.lock index aa6987677f..1958698c1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4312,6 +4312,7 @@ __metadata: resolution: "@sourceacademy/bundle-unittest@workspace:src/bundles/unittest" dependencies: "@sourceacademy/modules-buildtools": "workspace:^" + "@sourceacademy/modules-lib": "workspace:^" "@types/lodash": "npm:^4.14.198" js-slang: "npm:^1.0.85" lodash: "npm:^4.17.23" From 0f28aea54addb776209e81854a961be58d6ab648 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sun, 8 Mar 2026 18:13:45 +0800 Subject: [PATCH 63/71] Update some documentation --- docs/src/modules/2-bundle/5-documentation/2-dev.md | 2 ++ src/bundles/binary_tree/src/__tests__/index.test.ts | 10 ++++++++++ src/bundles/binary_tree/src/functions.ts | 10 +++++++++- src/bundles/repeat/package.json | 2 +- src/bundles/repeat/src/functions.ts | 2 +- src/bundles/sound/package.json | 2 +- 6 files changed, 24 insertions(+), 4 deletions(-) diff --git a/docs/src/modules/2-bundle/5-documentation/2-dev.md b/docs/src/modules/2-bundle/5-documentation/2-dev.md index 30886280c4..b64cf663ed 100644 --- a/docs/src/modules/2-bundle/5-documentation/2-dev.md +++ b/docs/src/modules/2-bundle/5-documentation/2-dev.md @@ -95,6 +95,8 @@ You should document: - Information flows (like what functions write to the module context etc...) - Any interesting quirks or configurations required to get your bundle working - How the underlying implementation of your bundle actually works +- Some way for other developers to contact you about your code +- A list of places where your bundle is deployed or used (e.g. frontend assessements) ::: details The `pix_n_flix` bundle A good example for the last point is the `pix_n_flix` bundle, where many of the cadet facing functions, when called, diff --git a/src/bundles/binary_tree/src/__tests__/index.test.ts b/src/bundles/binary_tree/src/__tests__/index.test.ts index 0dc75487cc..07600993bb 100644 --- a/src/bundles/binary_tree/src/__tests__/index.test.ts +++ b/src/bundles/binary_tree/src/__tests__/index.test.ts @@ -47,6 +47,16 @@ describe(funcs.is_tree, () => { }); }); +describe(funcs.make_tree, () => { + it('throws an error when \'left\' is not a tree', () => { + expect(() => funcs.make_tree(0, 0 as any, null)).toThrowError('make_tree: Expected binary tree for left, got 0.'); + }); + + it('throws an error when \'right\' is not a tree', () => { + expect(() => funcs.make_tree(0, null, 0 as any)).toThrowError('make_tree: Expected binary tree for right, got 0.'); + }); +}); + describe(funcs.entry, () => { it('throws when argument is not a tree', () => { expect(() => funcs.entry(0 as any)).toThrowError('entry: Expected binary tree, got 0.'); diff --git a/src/bundles/binary_tree/src/functions.ts b/src/bundles/binary_tree/src/functions.ts index ee8db87d7e..0a77e263cf 100644 --- a/src/bundles/binary_tree/src/functions.ts +++ b/src/bundles/binary_tree/src/functions.ts @@ -27,6 +27,14 @@ export function make_empty_tree(): BinaryTree { * @returns A binary tree */ export function make_tree(value: any, left: BinaryTree, right: BinaryTree): BinaryTree { + if (!is_tree(left)) { + throw new InvalidParameterTypeError('binary tree', left, make_tree.name, 'left'); + } + + if (!is_tree(right)) { + throw new InvalidParameterTypeError('binary tree', right, make_tree.name, 'right'); + } + return list(value, left, right); } @@ -66,7 +74,7 @@ export function is_tree(value: any): value is BinaryTree { * @param value Value to be tested * @returns bool */ -export function is_empty_tree(value: BinaryTree): value is EmptyBinaryTree { +export function is_empty_tree(value: unknown): value is EmptyBinaryTree { return value === null; } diff --git a/src/bundles/repeat/package.json b/src/bundles/repeat/package.json index 4e519a1379..39fd83a816 100644 --- a/src/bundles/repeat/package.json +++ b/src/bundles/repeat/package.json @@ -1,6 +1,6 @@ { "name": "@sourceacademy/bundle-repeat", - "version": "1.0.0", + "version": "1.1.0", "private": true, "devDependencies": { "@sourceacademy/modules-buildtools": "workspace:^", diff --git a/src/bundles/repeat/src/functions.ts b/src/bundles/repeat/src/functions.ts index b242a4d2b0..6606496841 100644 --- a/src/bundles/repeat/src/functions.ts +++ b/src/bundles/repeat/src/functions.ts @@ -13,7 +13,7 @@ import { isFunctionOfLength } from '@sourceacademy/modules-lib/utilities'; type UnaryFunction = (x: T) => T; /** - * Internal implementation of the repeat functions so that doesn't perform type checking + * Internal implementation of the repeat function that doesn't perform type checking * @hidden */ export function repeat_internal(f: UnaryFunction, n: number): UnaryFunction { diff --git a/src/bundles/sound/package.json b/src/bundles/sound/package.json index 72b3c3f4e5..c2041d2148 100644 --- a/src/bundles/sound/package.json +++ b/src/bundles/sound/package.json @@ -1,6 +1,6 @@ { "name": "@sourceacademy/bundle-sound", - "version": "1.0.0", + "version": "1.1.0", "private": true, "dependencies": { "@sourceacademy/bundle-midi": "workspace:^", From 2f178b777370a6ffa5c8ff437a36fc0b25381123 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Sun, 8 Mar 2026 22:54:41 +0800 Subject: [PATCH 64/71] Add documentation about bp css styles --- docs/src/modules/1-getting-started/1-overview.md | 2 ++ docs/src/modules/2-bundle/5-documentation/2-dev.md | 2 +- docs/src/modules/3-tabs/3-editing.md | 14 ++++++++++++++ .../src/tabs/MultiItemDisplay/index.tsx | 2 +- src/tabs/Csg/src/canvas_holder.tsx | 2 +- 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/src/modules/1-getting-started/1-overview.md b/docs/src/modules/1-getting-started/1-overview.md index 17f72a77bb..51533beb8d 100644 --- a/docs/src/modules/1-getting-started/1-overview.md +++ b/docs/src/modules/1-getting-started/1-overview.md @@ -31,6 +31,8 @@ children: - name: src children: + - name: archive + comment: Archived bundles and tabs - name: bundles comment: Directories containing bundles - name: tabs diff --git a/docs/src/modules/2-bundle/5-documentation/2-dev.md b/docs/src/modules/2-bundle/5-documentation/2-dev.md index b64cf663ed..84ce51aba6 100644 --- a/docs/src/modules/2-bundle/5-documentation/2-dev.md +++ b/docs/src/modules/2-bundle/5-documentation/2-dev.md @@ -96,7 +96,7 @@ You should document: - Any interesting quirks or configurations required to get your bundle working - How the underlying implementation of your bundle actually works - Some way for other developers to contact you about your code -- A list of places where your bundle is deployed or used (e.g. frontend assessements) +- A list of places where your bundle is deployed or used (e.g. frontend assessments) ::: details The `pix_n_flix` bundle A good example for the last point is the `pix_n_flix` bundle, where many of the cadet facing functions, when called, diff --git a/docs/src/modules/3-tabs/3-editing.md b/docs/src/modules/3-tabs/3-editing.md index 465f410b41..174c2857df 100644 --- a/docs/src/modules/3-tabs/3-editing.md +++ b/docs/src/modules/3-tabs/3-editing.md @@ -104,6 +104,20 @@ There are also several React components defined under `@sourceacademy/modules-li You can see the documentation for these components [here](/lib/modules-lib/) +### Styles from `@blueprintjs` + +Besides providing components, Blueprint also provides CSS Styles that can be attached to your own components: + +```jsx +const component =
+

Hello World!

+
; +``` +You can use these styles directly instead of having to come up with your own. + +Often, these styles will be prefixed with `bp` and the version number (i.e `bp6`). Take care to ensure that this prefix matches the version of Blueprint that +is in use. + ## Export Interface As mentioned in the [overview](./1-overview), all tabs should export a single default export from their entry point using the `defineTab` helper from `@sourceacademy/modules-lib/tabs`: diff --git a/lib/modules-lib/src/tabs/MultiItemDisplay/index.tsx b/lib/modules-lib/src/tabs/MultiItemDisplay/index.tsx index 375d6658d8..9b22eba23f 100644 --- a/lib/modules-lib/src/tabs/MultiItemDisplay/index.tsx +++ b/lib/modules-lib/src/tabs/MultiItemDisplay/index.tsx @@ -69,7 +69,7 @@ export default function MultiItemDisplay(props: MultiItemDisplayProps) { > Previous -

+

Date: Mon, 9 Mar 2026 19:17:39 +0800 Subject: [PATCH 65/71] Update modules-lib to use blueprint/core iconnames --- lib/modules-lib/src/tabs/AnimationCanvas.tsx | 3 +- lib/modules-lib/src/tabs/AnimationError.tsx | 3 +- .../src/tabs/MultiItemDisplay/index.tsx | 5 ++- lib/modules-lib/src/tabs/PlayButton.tsx | 36 +++++++++++++++---- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/lib/modules-lib/src/tabs/AnimationCanvas.tsx b/lib/modules-lib/src/tabs/AnimationCanvas.tsx index 97c6f4731a..85b78a4865 100644 --- a/lib/modules-lib/src/tabs/AnimationCanvas.tsx +++ b/lib/modules-lib/src/tabs/AnimationCanvas.tsx @@ -1,5 +1,4 @@ import { Icon, Slider, Tooltip } from '@blueprintjs/core'; -import { IconNames } from '@blueprintjs/icons'; import { useMemo, useState } from 'react'; import type { glAnimation } from '../types'; import AnimationError from './AnimationError'; @@ -71,7 +70,7 @@ export default function AnimationCanvas(props: AnimCanvasProps) { disabled={Boolean(errored)} onClick={reset} > - + - +
{ changeStep(currentStep - 1); setStepEditorValue(currentStep.toString()); @@ -134,7 +133,7 @@ export default function MultiItemDisplay(props: MultiItemDisplayProps) { }} large outlined - icon={IconNames.ARROW_RIGHT} + icon='arrow-right' tabIndex={0} onClick={() => { changeStep(currentStep + 1); diff --git a/lib/modules-lib/src/tabs/PlayButton.tsx b/lib/modules-lib/src/tabs/PlayButton.tsx index 769d8f1bb6..55933b137c 100644 --- a/lib/modules-lib/src/tabs/PlayButton.tsx +++ b/lib/modules-lib/src/tabs/PlayButton.tsx @@ -1,23 +1,47 @@ /* [Imports] */ -import { Icon, Tooltip } from '@blueprintjs/core'; -import { IconNames } from '@blueprintjs/icons'; +import { Icon, Tooltip, type IconProps } from '@blueprintjs/core'; import ButtonComponent, { type ButtonComponentProps } from './ButtonComponent'; /* [Exports] */ export type PlayButtonProps = ButtonComponentProps & { isPlaying: boolean; - // onClickCallback: () => void, + + /** + * Tooltip string for the button when `isPlaying` is true. Defaults to `Pause`. + */ + playingText?: string; + + /** + * Tooltip string for the button when `isPlaying` is false. Defaults to `Play`. + */ + pausedText?: string; + + /** + * Icon for the button when `isPlaying` is true. Defaults to `pause`. + */ + playingIcon?: IconProps['icon']; + + /** + * Icon for the button when `isPlaying` is false. Defaults to `play`. + */ + pausedIcon?: IconProps['icon']; }; /* [Main] */ -export default function PlayButton(props: PlayButtonProps) { +export default function PlayButton({ + playingText = 'Pause', + playingIcon = 'pause', + pausedText = 'Play', + pausedIcon = 'play', + ...props +}: PlayButtonProps) { return ; From eb0d0250a6871237e1923d52c8fd1a59a29f99cd Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Mon, 9 Mar 2026 19:17:52 +0800 Subject: [PATCH 66/71] Update devserver to use blueprint core icons --- devserver/src/components/Playground.tsx | 10 ++++++++-- .../components/controlBar/ControlBarRefreshButton.tsx | 3 +-- .../src/components/controlBar/ControlBarRunButton.tsx | 3 +-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/devserver/src/components/Playground.tsx b/devserver/src/components/Playground.tsx index 783e7df7eb..6a462d85a4 100644 --- a/devserver/src/components/Playground.tsx +++ b/devserver/src/components/Playground.tsx @@ -1,9 +1,9 @@ import { Button, Classes, Intent, OverlayToaster, Popover, Tooltip, type ToastProps } from '@blueprintjs/core'; -import { IconNames } from '@blueprintjs/icons'; import classNames from 'classnames'; import { SourceDocumentation, getNames, runInContext, type Context } from 'js-slang'; // Importing this straight from js-slang doesn't work for whatever reason import createContext from 'js-slang/dist/createContext'; +import { ModuleInternalError } from 'js-slang/dist/modules/errors'; import { setModulesStaticURL } from 'js-slang/dist/modules/loader'; import { Chapter, Variant } from 'js-slang/dist/types'; import { stringify } from 'js-slang/dist/utils/stringify'; @@ -159,6 +159,12 @@ const Playground: React.FC = () => { value: stringify(result.value) }); } else if (result.status === 'error') { + codeContext.errors.forEach(error => { + if (error instanceof ModuleInternalError) { + console.error(error); + } + }); + setReplOutput({ type: 'errors', errors: codeContext.errors, @@ -210,7 +216,7 @@ const Playground: React.FC = () => {
diff --git a/src/tabs/Csg/src/index.tsx b/src/tabs/Csg/src/index.tsx index 6597da1cdf..92aca22e5f 100644 --- a/src/tabs/Csg/src/index.tsx +++ b/src/tabs/Csg/src/index.tsx @@ -1,5 +1,4 @@ /* [Imports] */ -import { IconNames } from '@blueprintjs/icons'; import { Core } from '@sourceacademy/bundle-csg/core'; import type { CsgModuleState } from '@sourceacademy/bundle-csg/utilities'; import { defineTab } from '@sourceacademy/modules-lib/tabs/utils'; @@ -27,7 +26,7 @@ export default defineTab({ }, // BlueprintJS icon name - iconName: IconNames.SHAPES, + iconName: 'shapes', // Icon tooltip in sidebar label: 'CSG Tab' diff --git a/src/tabs/Csg/src/types.ts b/src/tabs/Csg/src/types.ts index 255db07934..ac25faf95d 100644 --- a/src/tabs/Csg/src/types.ts +++ b/src/tabs/Csg/src/types.ts @@ -1,5 +1,5 @@ /* [Imports] */ -import type { IconName } from '@blueprintjs/icons'; +import type { IconName } from '@blueprintjs/core'; /* [Exports] */ From f9b7ebb83c39ced461e7f1e7ac300d920f28f062 Mon Sep 17 00:00:00 2001 From: "DESKTOP-G08HS3B\\Lee Yi" Date: Mon, 9 Mar 2026 20:13:26 +0800 Subject: [PATCH 68/71] Remove blueprint icons where unnecessary --- .../components/controlBar/ControlBarClearButton.tsx | 3 +-- lib/modules-lib/src/tabs/PlayButton.tsx | 5 +++-- src/tabs/Curve/package.json | 1 - src/tabs/Curve/src/curve_3d_animation_canvas.tsx | 3 +-- src/tabs/Curve/src/index.tsx | 3 +-- src/tabs/Nbody/index.tsx | 11 ++++------- src/tabs/Nbody/package.json | 1 - src/tabs/Pixnflix/index.tsx | 11 +++++------ src/tabs/Pixnflix/package.json | 1 - src/tabs/Repl/index.tsx | 5 ++--- src/tabs/Repl/package.json | 1 - src/tabs/UnityAcademy/index.tsx | 9 ++++----- src/tabs/UnityAcademy/package.json | 1 - yarn.lock | 7 ------- 14 files changed, 21 insertions(+), 41 deletions(-) diff --git a/devserver/src/components/controlBar/ControlBarClearButton.tsx b/devserver/src/components/controlBar/ControlBarClearButton.tsx index 901cca1483..9aa82b5a06 100644 --- a/devserver/src/components/controlBar/ControlBarClearButton.tsx +++ b/devserver/src/components/controlBar/ControlBarClearButton.tsx @@ -1,5 +1,4 @@ import { Tooltip } from '@blueprintjs/core'; -import { IconNames } from '@blueprintjs/icons'; import ControlButton from '../ControlButton'; type Props = { @@ -9,7 +8,7 @@ type Props = { export const ControlBarClearButton = (props: Props) => ; diff --git a/lib/modules-lib/src/tabs/PlayButton.tsx b/lib/modules-lib/src/tabs/PlayButton.tsx index 55933b137c..410969be91 100644 --- a/lib/modules-lib/src/tabs/PlayButton.tsx +++ b/lib/modules-lib/src/tabs/PlayButton.tsx @@ -33,15 +33,16 @@ export default function PlayButton({ playingIcon = 'pause', pausedText = 'Play', pausedIcon = 'play', + isPlaying, ...props }: PlayButtonProps) { return ; diff --git a/src/tabs/Curve/package.json b/src/tabs/Curve/package.json index 02a4e7ae23..338f56b9ad 100644 --- a/src/tabs/Curve/package.json +++ b/src/tabs/Curve/package.json @@ -4,7 +4,6 @@ "private": true, "dependencies": { "@blueprintjs/core": "^6.0.0", - "@blueprintjs/icons": "^6.0.0", "@sourceacademy/bundle-curve": "workspace:^", "@sourceacademy/modules-lib": "workspace:^", "react": "^18.3.1", diff --git a/src/tabs/Curve/src/curve_3d_animation_canvas.tsx b/src/tabs/Curve/src/curve_3d_animation_canvas.tsx index 037e1e3bb2..6c216c01c0 100644 --- a/src/tabs/Curve/src/curve_3d_animation_canvas.tsx +++ b/src/tabs/Curve/src/curve_3d_animation_canvas.tsx @@ -1,5 +1,4 @@ import { Icon, Slider, Tooltip } from '@blueprintjs/core'; -import { IconNames } from '@blueprintjs/icons'; import type { AnimatedCurve } from '@sourceacademy/bundle-curve/types'; import AnimationError from '@sourceacademy/modules-lib/tabs/AnimationError'; import AutoLoopSwitch from '@sourceacademy/modules-lib/tabs/AutoLoopSwitch'; @@ -79,7 +78,7 @@ export default function Curve3DAnimationCanvas({ animation }: Props) { disabled={Boolean(errored)} onClick={reset} > - +
; }, label: 'Curves Tab', - iconName: IconNames.MEDIA // See https://blueprintjs.com/docs/#icons for more options + iconName: 'media' }); diff --git a/src/tabs/Nbody/index.tsx b/src/tabs/Nbody/index.tsx index 7d161df11d..dd768a1d21 100644 --- a/src/tabs/Nbody/index.tsx +++ b/src/tabs/Nbody/index.tsx @@ -1,5 +1,5 @@ import { Button, ButtonGroup, NumericInput } from '@blueprintjs/core'; -import { IconNames } from '@blueprintjs/icons'; +import PlayButton from '@sourceacademy/modules-lib/tabs/PlayButton'; import { defineTab } from '@sourceacademy/modules-lib/tabs/utils'; import type { DebuggerContext } from '@sourceacademy/modules-lib/types/index'; import type { Simulation } from 'nbody'; @@ -86,18 +86,15 @@ class SimulationControl extends React.Component -