From 78411093188bfa152366bd3f39e79fc727693e37 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Sun, 6 Oct 2024 22:53:32 -0400 Subject: [PATCH 01/25] Setup inital spr template --- packages/plugin-spr/README.md | 35 ++++++++++++++ packages/plugin-spr/docs/spr.md | 53 +++++++++++++++++++++ packages/plugin-spr/examples/index.html | 24 ++++++++++ packages/plugin-spr/jest.config.cjs | 1 + packages/plugin-spr/package.json | 47 +++++++++++++++++++ packages/plugin-spr/rollup.config.mjs | 3 ++ packages/plugin-spr/src/index.spec.ts | 19 ++++++++ packages/plugin-spr/src/index.ts | 62 +++++++++++++++++++++++++ packages/plugin-spr/tsconfig.json | 8 ++++ 9 files changed, 252 insertions(+) create mode 100644 packages/plugin-spr/README.md create mode 100644 packages/plugin-spr/docs/spr.md create mode 100644 packages/plugin-spr/examples/index.html create mode 100644 packages/plugin-spr/jest.config.cjs create mode 100644 packages/plugin-spr/package.json create mode 100644 packages/plugin-spr/rollup.config.mjs create mode 100644 packages/plugin-spr/src/index.spec.ts create mode 100644 packages/plugin-spr/src/index.ts create mode 100644 packages/plugin-spr/tsconfig.json diff --git a/packages/plugin-spr/README.md b/packages/plugin-spr/README.md new file mode 100644 index 00000000..3938dced --- /dev/null +++ b/packages/plugin-spr/README.md @@ -0,0 +1,35 @@ +# spr + +## Overview + +This is a package built to enable self paced reading + +## Loading + +### In browser + +```js + +``` + +### Via NPM + +``` +npm install @jspsych-contrib/plugin-spr +``` + +```js +import jsPsychSpr from '@jspsych-contrib/plugin-spr'; +``` + +## Compatibility + +jsPsych 7.0.0 + +## Documentation + +See [documentation](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-spr/docs/jspsych-spr.md) + +## Author / Citation + +[Victor Zhang](https://github.com/vzhang03) diff --git a/packages/plugin-spr/docs/spr.md b/packages/plugin-spr/docs/spr.md new file mode 100644 index 00000000..99900e4e --- /dev/null +++ b/packages/plugin-spr/docs/spr.md @@ -0,0 +1,53 @@ +# spr + +This is a package built to enable self paced reading + +## Parameters + +In addition to the [parameters available in all plugins](https://jspsych.org/latest/overview/plugins.md#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. + +| Parameter | Type | Default Value | Description | +| ------------------- | ---------------- | ------------------ | ---------------------------------------- | +| | | | | + +## Data Generated + +In addition to the [default data collected by all plugins](https://jspsych.org/latest/overview/plugins.md#data-collected-by-all-plugins), this plugin collects the following data for each trial. + +| Name | Type | Value | +| --------- | ------- | ---------------------------------------- | +| | | | + +## Install + +Using the CDN-hosted JavaScript file: + +```js + +``` + +Using the JavaScript file downloaded from a GitHub release dist archive: + +```js + +``` + +Using NPM: + +``` +npm install @jspsych-contrib/plugin-spr +``` + +```js +import Spr from '@jspsych-contrib/plugin-spr'; +``` + +## Examples + +### Title of Example + +```javascript +var trial = { + type: jsPsychSpr +} +``` \ No newline at end of file diff --git a/packages/plugin-spr/examples/index.html b/packages/plugin-spr/examples/index.html new file mode 100644 index 00000000..77b803e7 --- /dev/null +++ b/packages/plugin-spr/examples/index.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/plugin-spr/jest.config.cjs b/packages/plugin-spr/jest.config.cjs new file mode 100644 index 00000000..6ac19d5c --- /dev/null +++ b/packages/plugin-spr/jest.config.cjs @@ -0,0 +1 @@ +module.exports = require("@jspsych/config/jest").makePackageConfig(__dirname); diff --git a/packages/plugin-spr/package.json b/packages/plugin-spr/package.json new file mode 100644 index 00000000..26befa1d --- /dev/null +++ b/packages/plugin-spr/package.json @@ -0,0 +1,47 @@ +{ + "name": "@jspsych-contrib/plugin-spr", + "version": "0.0.1", + "description": "This is a package built to enable self paced reading", + "type": "module", + "main": "dist/index.cjs", + "exports": { + "import": "./dist/index.js", + "require": "./dist/index.cjs" + }, + "typings": "dist/index.d.ts", + "unpkg": "dist/index.browser.min.js", + "files": [ + "src", + "dist" + ], + "source": "src/index.ts", + "scripts": { + "test": "jest", + "test:watch": "npm test -- --watch", + "tsc": "tsc", + "build": "rollup --config", + "build:watch": "npm run build -- --watch" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/jspsych/jspsych-contrib.git", + "directory": "packages/plugin-spr" + }, + "author": { + "name": "Victor Zhang", + "url": "https://github.com/vzhang03" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/jspsych/jspsych-contrib/issues" + }, + "homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-spr", + "peerDependencies": { + "jspsych": ">=7.0.0" + }, + "devDependencies": { + "@jspsych/config": "^2.0.0", + "@jspsych/test-utils": "^1.0.0", + "jspsych": "^7.0.0" + } +} diff --git a/packages/plugin-spr/rollup.config.mjs b/packages/plugin-spr/rollup.config.mjs new file mode 100644 index 00000000..be097fca --- /dev/null +++ b/packages/plugin-spr/rollup.config.mjs @@ -0,0 +1,3 @@ +import { makeRollupConfig } from "@jspsych/config/rollup"; + +export default makeRollupConfig("jsPsychSpr"); diff --git a/packages/plugin-spr/src/index.spec.ts b/packages/plugin-spr/src/index.spec.ts new file mode 100644 index 00000000..7a7cc923 --- /dev/null +++ b/packages/plugin-spr/src/index.spec.ts @@ -0,0 +1,19 @@ +import { startTimeline } from "@jspsych/test-utils"; + +import jsPsychSpr from "."; + +jest.useFakeTimers(); + +describe("my plugin", () => { + it("should load", async () => { + const { expectFinished, getHTML, getData, displayElement, jsPsych } = await startTimeline([ + { + type: jsPsychSpr, + parameter_name: 1, + parameter_name2: "img.png", + }, + ]); + + await expectFinished(); + }); +}); diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts new file mode 100644 index 00000000..cc00178b --- /dev/null +++ b/packages/plugin-spr/src/index.ts @@ -0,0 +1,62 @@ +import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; + +import { version } from "../package.json"; + +const info = { + name: "spr", + version: version, + parameters: { + /** Provide a clear description of the parameter_name that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ + reading_string: { + type: ParameterType.STRING, // BOOL, STRING, INT, FLOAT, FUNCTION, KEY, KEYS, SELECT, HTML_STRING, IMAGE, AUDIO, VIDEO, OBJECT, COMPLEX + default: undefined, + }, + // /** Provide a clear description of the parameter_name2 that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ + // parameter_name2: { + // type: ParameterType.IMAGE, + // default: undefined, + // }, + }, + data: { + /** Provide a clear description of the data1 that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ + data1: { + type: ParameterType.INT, + }, + /** Provide a clear description of the data2 that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ + data2: { + type: ParameterType.STRING, + }, + }, +}; + +type Info = typeof info; + +/** + * **spr** + * + * This is a package built to enable self paced reading + * + * @author Victor Zhang + * @see {@link https://github.com/jspsych/jspsych-contrib/packages/plugin-spr/README.md}} + */ +class SprPlugin implements JsPsychPlugin { + static info = info; + + constructor(private jsPsych: JsPsych) {} + + trial(display_element: HTMLElement, trial: TrialType) { + var html = `

does this work

`; + + display_element.innerHTML = html; + + // data saving + var trial_data = { + data1: 99, // Make sure this type and name matches the information for data1 in the data object contained within the info const. + data2: "hello world!", // Make sure this type and name matches the information for data2 in the data object contained within the info const. + }; + // end trial + // this.jsPsych.finishTrial(trial_data); + } +} + +export default SprPlugin; diff --git a/packages/plugin-spr/tsconfig.json b/packages/plugin-spr/tsconfig.json new file mode 100644 index 00000000..8a845081 --- /dev/null +++ b/packages/plugin-spr/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@jspsych/config/tsconfig.contrib.json", + "compilerOptions": { + "baseUrl": ".", + "resolveJsonModule": true + }, + "include": ["src"] +} From ea27f0174730132f408b3e7c0ff6a089a7f59981 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Sun, 6 Oct 2024 23:48:06 -0400 Subject: [PATCH 02/25] Inital working version of SPR complete --- packages/plugin-spr/examples/index.html | 1 + packages/plugin-spr/src/index.ts | 76 ++++++++++++++++++++++--- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/packages/plugin-spr/examples/index.html b/packages/plugin-spr/examples/index.html index 77b803e7..b9c71ae0 100644 --- a/packages/plugin-spr/examples/index.html +++ b/packages/plugin-spr/examples/index.html @@ -16,6 +16,7 @@ const trial = { type: jsPsychSpr, reading_string: "this is the reading string", + structured_reading_string: ["first", "second", "third"] }; jsPsych.run([trial]) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index cc00178b..571f2abd 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -9,13 +9,13 @@ const info = { /** Provide a clear description of the parameter_name that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ reading_string: { type: ParameterType.STRING, // BOOL, STRING, INT, FLOAT, FUNCTION, KEY, KEYS, SELECT, HTML_STRING, IMAGE, AUDIO, VIDEO, OBJECT, COMPLEX - default: undefined, + default: "", + }, + structured_reading_string: { + type: ParameterType.STRING, + array: true, + default: [], }, - // /** Provide a clear description of the parameter_name2 that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ - // parameter_name2: { - // type: ParameterType.IMAGE, - // default: undefined, - // }, }, data: { /** Provide a clear description of the data1 that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ @@ -41,14 +41,40 @@ type Info = typeof info; */ class SprPlugin implements JsPsychPlugin { static info = info; + private index: number = 0; + private displayed = false; + private structured_reading_string: string[] = []; // | string[][] -> need to rethink this? constructor(private jsPsych: JsPsych) {} trial(display_element: HTMLElement, trial: TrialType) { - var html = `

does this work

`; + console.log(trial.structured_reading_string, trial.structured_reading_string.length); + // creates inital reading string + if (trial.structured_reading_string.length > 0) + this.structured_reading_string = trial.structured_reading_string; + else this.structured_reading_string = this.createReadingString(trial.reading_string); + + // const displayContainer = this.jsPsych.getDisplayContainerElement(); + // setup html logic + + var html = `

${this.generateBlank(this.structured_reading_string[this.index])}

`; display_element.innerHTML = html; + // dynamic logic + const spacebarHandler = (e: KeyboardEvent) => { + if (e.code === "Space") { + this.onSpacebarPress(); // Call the onSpacebarPress method + } + }; + // Attach the event listener + document.addEventListener("keydown", spacebarHandler); + + // Remove the event listener when the trial is finished to prevent memory leaks + // this.jsPsych.finishTrialCallback(() => { + // document.removeEventListener("keydown", spacebarHandler); + // }); + // data saving var trial_data = { data1: 99, // Make sure this type and name matches the information for data1 in the data object contained within the info const. @@ -57,6 +83,42 @@ class SprPlugin implements JsPsychPlugin { // end trial // this.jsPsych.finishTrial(trial_data); } + + private createReadingString(reading_string: string): string[] { + // pass in parameters to split it + // -> depends on the spaces and the typing + + return [reading_string]; + } + + private onSpacebarPress() { + console.log("Spacebar was pressed!"); + var newHtml = `

Spacebar pressed!

`; + + if (!this.displayed) { + newHtml = this.structured_reading_string[this.index]; + this.displayed = true; + } else { + this.index++; + this.displayed = false; + + if (this.index >= this.structured_reading_string.length) { + // this is when we want to end trial + } else { + newHtml = this.generateBlank(this.structured_reading_string[this.index]); + } + } + + // Add any action you want to happen on spacebar press + // e.g., changing the displayed text, ending the trial, etc. + document.querySelector("p")!.innerHTML = newHtml; + } + + private generateBlank(text: string): string { + const length = text.length; + // will need to account for the spaces and will need split? -> not sure how will handle that + return "_".repeat(length); + } } export default SprPlugin; From 4d4e9f384eae7e0e9986803c14f3482ac3db8b39 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Mon, 7 Oct 2024 11:01:24 -0400 Subject: [PATCH 03/25] Working version of SPR with multiple words --- packages/plugin-spr/examples/index.html | 3 +- packages/plugin-spr/src/index.ts | 79 ++++++++++++++++++------- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/packages/plugin-spr/examples/index.html b/packages/plugin-spr/examples/index.html index b9c71ae0..aab19f1d 100644 --- a/packages/plugin-spr/examples/index.html +++ b/packages/plugin-spr/examples/index.html @@ -16,7 +16,8 @@ const trial = { type: jsPsychSpr, reading_string: "this is the reading string", - structured_reading_string: ["first", "second", "third"] + structured_reading_string: [["first", "second", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], + mode: 2 }; jsPsych.run([trial]) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 571f2abd..1ffa5e29 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -16,6 +16,10 @@ const info = { array: true, default: [], }, + mode: { + type: ParameterType.INT, + default: 1, + }, }, data: { /** Provide a clear description of the data1 that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ @@ -42,26 +46,29 @@ type Info = typeof info; class SprPlugin implements JsPsychPlugin { static info = info; private index: number = 0; + private inner_index: number = -1; private displayed = false; - private structured_reading_string: string[] = []; // | string[][] -> need to rethink this? + private structured_reading_string: string[] = []; + private mode; + // | string[][] -> each method that takes in string will need to account for list of strings + // would need another inner_index? constructor(private jsPsych: JsPsych) {} trial(display_element: HTMLElement, trial: TrialType) { + this.mode = trial.mode; console.log(trial.structured_reading_string, trial.structured_reading_string.length); - // creates inital reading string + // creates inital reading string -> should instead use mode if (trial.structured_reading_string.length > 0) this.structured_reading_string = trial.structured_reading_string; else this.structured_reading_string = this.createReadingString(trial.reading_string); - // const displayContainer = this.jsPsych.getDisplayContainerElement(); - // setup html logic - var html = `

${this.generateBlank(this.structured_reading_string[this.index])}

`; display_element.innerHTML = html; // dynamic logic + // TODO: need to restructure to use JsPsych keyboard API and remove it const spacebarHandler = (e: KeyboardEvent) => { if (e.code === "Space") { this.onSpacebarPress(); // Call the onSpacebarPress method @@ -70,11 +77,6 @@ class SprPlugin implements JsPsychPlugin { // Attach the event listener document.addEventListener("keydown", spacebarHandler); - // Remove the event listener when the trial is finished to prevent memory leaks - // this.jsPsych.finishTrialCallback(() => { - // document.removeEventListener("keydown", spacebarHandler); - // }); - // data saving var trial_data = { data1: 99, // Make sure this type and name matches the information for data1 in the data object contained within the info const. @@ -95,18 +97,44 @@ class SprPlugin implements JsPsychPlugin { console.log("Spacebar was pressed!"); var newHtml = `

Spacebar pressed!

`; - if (!this.displayed) { - newHtml = this.structured_reading_string[this.index]; - this.displayed = true; + // handles logic on whether to display blank or show text using boolean/index + if (this.mode === 1) { + if (!this.displayed) { + newHtml = this.structured_reading_string[this.index]; + this.displayed = true; + } else { + this.index++; + this.displayed = false; + + if (this.index >= this.structured_reading_string.length) { + // this is when we want to end trial + } else { + newHtml = this.generateBlank(this.structured_reading_string[this.index]); + } + } } else { - this.index++; - this.displayed = false; + // mode 2 and 3 + const curr_length = this.structured_reading_string[this.index].length; + this.inner_index++; + + if (this.inner_index >= curr_length) { + // resets the index and moves onto the next + this.inner_index = 0; + this.index++; + } - if (this.index >= this.structured_reading_string.length) { - // this is when we want to end trial - } else { - newHtml = this.generateBlank(this.structured_reading_string[this.index]); + const curr_segment = this.structured_reading_string[this.index]; + var string_to_display = ""; + + for (var i = 0; i < curr_segment.length; i++) { + if (this.inner_index === i) { + string_to_display += " " + curr_segment[i]; + } else { + string_to_display += " " + this.generateBlank(curr_segment[i]); + } } + + newHtml = `

${string_to_display}

`; } // Add any action you want to happen on spacebar press @@ -114,10 +142,19 @@ class SprPlugin implements JsPsychPlugin { document.querySelector("p")!.innerHTML = newHtml; } - private generateBlank(text: string): string { + private generateBlank(text: string | string[]): string { const length = text.length; // will need to account for the spaces and will need split? -> not sure how will handle that - return "_".repeat(length); + if (typeof text === "string") { + return "_".repeat(length); + } else { + var res = ""; + for (var i = 0; i < length; i++) { + const word_length = text[i].length; + res += "_".repeat(word_length) + " "; + } + return res; + } } } From 6c169d45a7575caf5219bdaa2b400d491747ba35 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Mon, 7 Oct 2024 11:25:37 -0400 Subject: [PATCH 04/25] Commited working fix to us styling using span, need to finalize update --- packages/plugin-spr/src/index.ts | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 1ffa5e29..746d790f 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -2,6 +2,7 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; import { version } from "../package.json"; +// TODO: need to restructure to use the CSS styling proposed by Titus const info = { name: "spr", version: version, @@ -58,7 +59,7 @@ class SprPlugin implements JsPsychPlugin { trial(display_element: HTMLElement, trial: TrialType) { this.mode = trial.mode; console.log(trial.structured_reading_string, trial.structured_reading_string.length); - // creates inital reading string -> should instead use mode + // creates inital reading string -> TODO: should instead use mode to determine if (trial.structured_reading_string.length > 0) this.structured_reading_string = trial.structured_reading_string; else this.structured_reading_string = this.createReadingString(trial.reading_string); @@ -77,7 +78,7 @@ class SprPlugin implements JsPsychPlugin { // Attach the event listener document.addEventListener("keydown", spacebarHandler); - // data saving + // TODO: figure out data saving -> will need to add times and how long to make it var trial_data = { data1: 99, // Make sure this type and name matches the information for data1 in the data object contained within the info const. data2: "hello world!", // Make sure this type and name matches the information for data2 in the data object contained within the info const. @@ -86,6 +87,7 @@ class SprPlugin implements JsPsychPlugin { // this.jsPsych.finishTrial(trial_data); } + // TODO: create a method that takes an entire string and uses a list of parameters to generate a "structured reading string" private createReadingString(reading_string: string): string[] { // pass in parameters to split it // -> depends on the spaces and the typing @@ -114,6 +116,7 @@ class SprPlugin implements JsPsychPlugin { } } else { // mode 2 and 3 + // TODO: build out the mode that doesn't obscure (should be simple boolean) const curr_length = this.structured_reading_string[this.index].length; this.inner_index++; @@ -126,11 +129,22 @@ class SprPlugin implements JsPsychPlugin { const curr_segment = this.structured_reading_string[this.index]; var string_to_display = ""; + const styledText = ` +

+ ___ + hello + ___ +

+ `; + for (var i = 0; i < curr_segment.length; i++) { if (this.inner_index === i) { - string_to_display += " " + curr_segment[i]; + string_to_display += "" + curr_segment[i] + ""; } else { - string_to_display += " " + this.generateBlank(curr_segment[i]); + string_to_display += + "" + + this.generateBlank(curr_segment[i]) + + ""; } } @@ -144,10 +158,11 @@ class SprPlugin implements JsPsychPlugin { private generateBlank(text: string | string[]): string { const length = text.length; - // will need to account for the spaces and will need split? -> not sure how will handle that + if (typeof text === "string") { return "_".repeat(length); } else { + // type of array var res = ""; for (var i = 0; i < length; i++) { const word_length = text[i].length; From c3f532319e3db3691f01473c852c0208f4b7a4b8 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Sun, 13 Oct 2024 15:24:34 -0400 Subject: [PATCH 05/25] All modes working, need to work on error handling and making code more consolidated --- packages/plugin-spr/docs/spr.md | 4 +- packages/plugin-spr/examples/mode1.html | 26 +++++ .../examples/{index.html => mode2.html} | 0 packages/plugin-spr/examples/mode3.html | 26 +++++ packages/plugin-spr/src/index.ts | 96 +++++++++++++------ 5 files changed, 119 insertions(+), 33 deletions(-) create mode 100644 packages/plugin-spr/examples/mode1.html rename packages/plugin-spr/examples/{index.html => mode2.html} (100%) create mode 100644 packages/plugin-spr/examples/mode3.html diff --git a/packages/plugin-spr/docs/spr.md b/packages/plugin-spr/docs/spr.md index 99900e4e..9408bc81 100644 --- a/packages/plugin-spr/docs/spr.md +++ b/packages/plugin-spr/docs/spr.md @@ -1,6 +1,6 @@ # spr -This is a package built to enable self paced reading +This is a package built to enable self paced reading ## Parameters @@ -8,7 +8,7 @@ In addition to the [parameters available in all plugins](https://jspsych.org/lat | Parameter | Type | Default Value | Description | | ------------------- | ---------------- | ------------------ | ---------------------------------------- | -| | | | | +| Mode | Number | 1 | Indicates the mode of text displaying used by the SPR plugin. Mode 1 is a masked presentation where clicking spacebar hides the previous shown words, mode 2 reveals one chunk at time but the chunks but previous ones remain visible. Mode 3 is when one word is displayed with no mask. | ## Data Generated diff --git a/packages/plugin-spr/examples/mode1.html b/packages/plugin-spr/examples/mode1.html new file mode 100644 index 00000000..36591f3a --- /dev/null +++ b/packages/plugin-spr/examples/mode1.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/plugin-spr/examples/index.html b/packages/plugin-spr/examples/mode2.html similarity index 100% rename from packages/plugin-spr/examples/index.html rename to packages/plugin-spr/examples/mode2.html diff --git a/packages/plugin-spr/examples/mode3.html b/packages/plugin-spr/examples/mode3.html new file mode 100644 index 00000000..4fa49004 --- /dev/null +++ b/packages/plugin-spr/examples/mode3.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 746d790f..f1f47e99 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -47,9 +47,10 @@ type Info = typeof info; class SprPlugin implements JsPsychPlugin { static info = info; private index: number = 0; - private inner_index: number = -1; + private inner_index: number = -1; // initialized so that not shown if has an inner_index private displayed = false; - private structured_reading_string: string[] = []; + private current_string: string[] = []; // use this to save iterations + private structured_reading_string: string[] | string[][] = []; private mode; // | string[][] -> each method that takes in string will need to account for list of strings // would need another inner_index? @@ -57,13 +58,7 @@ class SprPlugin implements JsPsychPlugin { constructor(private jsPsych: JsPsych) {} trial(display_element: HTMLElement, trial: TrialType) { - this.mode = trial.mode; - console.log(trial.structured_reading_string, trial.structured_reading_string.length); - // creates inital reading string -> TODO: should instead use mode to determine - if (trial.structured_reading_string.length > 0) - this.structured_reading_string = trial.structured_reading_string; - else this.structured_reading_string = this.createReadingString(trial.reading_string); - + this.initializeVariables(trial); // setup html logic var html = `

${this.generateBlank(this.structured_reading_string[this.index])}

`; display_element.innerHTML = html; @@ -87,6 +82,17 @@ class SprPlugin implements JsPsychPlugin { // this.jsPsych.finishTrial(trial_data); } + private initializeVariables(trial: TrialType) { + if (trial.mode === 1 || trial.mode === 2 || trial.mode === 3) this.mode = trial.mode; + else throw console.error("Mode declared incorrectly, must be between 1 and 3."); + + console.log(trial.structured_reading_string, trial.structured_reading_string.length); + // creates inital reading string -> TODO: should instead use mode to determine + if (trial.structured_reading_string.length > 0) + this.structured_reading_string = trial.structured_reading_string; + else this.structured_reading_string = this.createReadingString(trial.reading_string); + } + // TODO: create a method that takes an entire string and uses a list of parameters to generate a "structured reading string" private createReadingString(reading_string: string): string[] { // pass in parameters to split it @@ -96,25 +102,38 @@ class SprPlugin implements JsPsychPlugin { } private onSpacebarPress() { - console.log("Spacebar was pressed!"); var newHtml = `

Spacebar pressed!

`; // handles logic on whether to display blank or show text using boolean/index if (this.mode === 1) { - if (!this.displayed) { - newHtml = this.structured_reading_string[this.index]; - this.displayed = true; - } else { + // mode 2 and 3 + // TODO: build out the mode that doesn't obscure (should be simple boolean) + const curr_length = this.structured_reading_string[this.index].length; + this.inner_index++; + + if (this.inner_index >= curr_length) { + // resets the index and moves onto the next + this.inner_index = -1; // ensures will be empty this.index++; - this.displayed = false; + } - if (this.index >= this.structured_reading_string.length) { - // this is when we want to end trial + const curr_segment = this.structured_reading_string[this.index]; + var string_to_display = ""; + + for (var i = 0; i < curr_segment.length; i++) { + if (this.inner_index === i) { + string_to_display += + "" + curr_segment[i] + " "; } else { - newHtml = this.generateBlank(this.structured_reading_string[this.index]); + string_to_display += + "" + + this.generateBlank(curr_segment[i]) + + " "; } } - } else { + + newHtml = `

${string_to_display}

`; + } else if (this.mode === 2) { // mode 2 and 3 // TODO: build out the mode that doesn't obscure (should be simple boolean) const curr_length = this.structured_reading_string[this.index].length; @@ -122,40 +141,55 @@ class SprPlugin implements JsPsychPlugin { if (this.inner_index >= curr_length) { // resets the index and moves onto the next - this.inner_index = 0; + this.inner_index = -1; // ensures will be empty this.index++; } const curr_segment = this.structured_reading_string[this.index]; var string_to_display = ""; - const styledText = ` -

- ___ - hello - ___ -

- `; - for (var i = 0; i < curr_segment.length; i++) { - if (this.inner_index === i) { - string_to_display += "" + curr_segment[i] + ""; + if (this.inner_index >= i) { + string_to_display += + "" + curr_segment[i] + " "; } else { string_to_display += "" + this.generateBlank(curr_segment[i]) + - ""; + " "; } } newHtml = `

${string_to_display}

`; + } else if (this.mode === 3) { + if (!this.displayed) { + if (typeof this.structured_reading_string === "string") + newHtml = this.structured_reading_string[this.index]; + else newHtml = "weird formatting"; // should build out a method that uses the inner index but makes it iterate better + + this.displayed = true; + } else { + this.index++; + this.displayed = false; + + if (this.index >= this.structured_reading_string.length) { + // this is when we want to end trial + } else { + newHtml = this.generateBlank(this.structured_reading_string[this.index]); + } + } } + // need to handle a keyboard press element where records how long until press a key // Add any action you want to happen on spacebar press // e.g., changing the displayed text, ending the trial, etc. document.querySelector("p")!.innerHTML = newHtml; } + // this is called whenever previousMethod upates the indicies + // this will let us create more advanced logic for how to handle the displays + private updateDisplayString() {} + private generateBlank(text: string | string[]): string { const length = text.length; From e866583d46777ec5dd099e4ee03e68458208e7ab Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Sun, 13 Oct 2024 15:44:10 -0400 Subject: [PATCH 06/25] Successfully added JsPsych integrated keyboard listener --- packages/plugin-spr/src/index.ts | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index f1f47e99..a0e3cdaa 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -49,7 +49,7 @@ class SprPlugin implements JsPsychPlugin { private index: number = 0; private inner_index: number = -1; // initialized so that not shown if has an inner_index private displayed = false; - private current_string: string[] = []; // use this to save iterations + private current_display_string: string[] = []; // use this to save iterations private structured_reading_string: string[] | string[][] = []; private mode; // | string[][] -> each method that takes in string will need to account for list of strings @@ -63,15 +63,13 @@ class SprPlugin implements JsPsychPlugin { var html = `

${this.generateBlank(this.structured_reading_string[this.index])}

`; display_element.innerHTML = html; - // dynamic logic - // TODO: need to restructure to use JsPsych keyboard API and remove it - const spacebarHandler = (e: KeyboardEvent) => { - if (e.code === "Space") { - this.onSpacebarPress(); // Call the onSpacebarPress method - } - }; - // Attach the event listener - document.addEventListener("keydown", spacebarHandler); + this.jsPsych.pluginAPI.getKeyboardResponse({ + callback_function: (info) => this.onSpacebarPress(info), + valid_responses: [" "], + rt_method: "performance", + persist: true, + allow_held_key: false, + }); // TODO: figure out data saving -> will need to add times and how long to make it var trial_data = { @@ -79,6 +77,7 @@ class SprPlugin implements JsPsychPlugin { data2: "hello world!", // Make sure this type and name matches the information for data2 in the data object contained within the info const. }; // end trial + // this.jsPsych.pluginAPI.cancelAllKeyboardResponses(); // this.jsPsych.finishTrial(trial_data); } @@ -101,7 +100,7 @@ class SprPlugin implements JsPsychPlugin { return [reading_string]; } - private onSpacebarPress() { + private onSpacebarPress(info?: any) { var newHtml = `

Spacebar pressed!

`; // handles logic on whether to display blank or show text using boolean/index @@ -188,7 +187,14 @@ class SprPlugin implements JsPsychPlugin { // this is called whenever previousMethod upates the indicies // this will let us create more advanced logic for how to handle the displays - private updateDisplayString() {} + private updateDisplayString(): string { + var displayString = ""; + for (const s of this.current_display_string) { + displayString += s + " "; // include another element + } + + return displayString; + } private generateBlank(text: string | string[]): string { const length = text.length; From b302f124ed5fe00f8d7c46692111f87ea7207677 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Sun, 13 Oct 2024 16:07:53 -0400 Subject: [PATCH 07/25] Successfully refactored mode 1 and 2 to be simpler and more efficient --- packages/plugin-spr/src/index.ts | 89 +++++++++++++++----------------- 1 file changed, 42 insertions(+), 47 deletions(-) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index a0e3cdaa..cd6590be 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -59,6 +59,7 @@ class SprPlugin implements JsPsychPlugin { trial(display_element: HTMLElement, trial: TrialType) { this.initializeVariables(trial); + this.updateDisplayString(); // setup html logic var html = `

${this.generateBlank(this.structured_reading_string[this.index])}

`; display_element.innerHTML = html; @@ -104,9 +105,7 @@ class SprPlugin implements JsPsychPlugin { var newHtml = `

Spacebar pressed!

`; // handles logic on whether to display blank or show text using boolean/index - if (this.mode === 1) { - // mode 2 and 3 - // TODO: build out the mode that doesn't obscure (should be simple boolean) + if (this.mode === 1 || this.mode === 2) { const curr_length = this.structured_reading_string[this.index].length; this.inner_index++; @@ -116,50 +115,7 @@ class SprPlugin implements JsPsychPlugin { this.index++; } - const curr_segment = this.structured_reading_string[this.index]; - var string_to_display = ""; - - for (var i = 0; i < curr_segment.length; i++) { - if (this.inner_index === i) { - string_to_display += - "" + curr_segment[i] + " "; - } else { - string_to_display += - "" + - this.generateBlank(curr_segment[i]) + - " "; - } - } - - newHtml = `

${string_to_display}

`; - } else if (this.mode === 2) { - // mode 2 and 3 - // TODO: build out the mode that doesn't obscure (should be simple boolean) - const curr_length = this.structured_reading_string[this.index].length; - this.inner_index++; - - if (this.inner_index >= curr_length) { - // resets the index and moves onto the next - this.inner_index = -1; // ensures will be empty - this.index++; - } - - const curr_segment = this.structured_reading_string[this.index]; - var string_to_display = ""; - - for (var i = 0; i < curr_segment.length; i++) { - if (this.inner_index >= i) { - string_to_display += - "" + curr_segment[i] + " "; - } else { - string_to_display += - "" + - this.generateBlank(curr_segment[i]) + - " "; - } - } - - newHtml = `

${string_to_display}

`; + newHtml = `

${this.updateDisplayString()}

`; } else if (this.mode === 3) { if (!this.displayed) { if (typeof this.structured_reading_string === "string") @@ -188,6 +144,45 @@ class SprPlugin implements JsPsychPlugin { // this is called whenever previousMethod upates the indicies // this will let us create more advanced logic for how to handle the displays private updateDisplayString(): string { + if (this.mode === 1 || this.mode === 2) { + if (this.inner_index === -1) { + // need to update new display string + const new_display_string: string[] = []; + + const curr_segment = this.structured_reading_string[this.index]; + + for (var i = 0; i < curr_segment.length; i++) { + new_display_string.push( + "" + + this.generateBlank(curr_segment[i]) + + "" + ); + } + + this.current_display_string = new_display_string; + } else if (this.mode === 1) { + // if not need to reupdate then we can do new logic + if (this.inner_index > 0) + // sets previous to blank if exists + this.current_display_string[this.inner_index - 1] = + "" + + this.generateBlank(this.structured_reading_string[this.index][this.inner_index - 1]) + + ""; + this.current_display_string[this.inner_index] = + "" + + this.structured_reading_string[this.index][this.inner_index] + + ""; + } else if (this.mode === 2) { + this.current_display_string[this.inner_index] = + "" + + this.structured_reading_string[this.index][this.inner_index] + + ""; + } + } else if (this.mode === 3) { + /// where we implement number 3 + } + + console.log("update display string res:", this.current_display_string); var displayString = ""; for (const s of this.current_display_string) { displayString += s + " "; // include another element From 2c321e45dbe63607b0a0460ade5ac23a83ca448b Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Sun, 13 Oct 2024 16:25:14 -0400 Subject: [PATCH 08/25] Completed mode 3, moving onto ending the trial and data handling --- packages/plugin-spr/examples/mode3.html | 3 +- packages/plugin-spr/src/index.ts | 45 +++++++++++++------------ 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/packages/plugin-spr/examples/mode3.html b/packages/plugin-spr/examples/mode3.html index 4fa49004..bb93e2fa 100644 --- a/packages/plugin-spr/examples/mode3.html +++ b/packages/plugin-spr/examples/mode3.html @@ -16,7 +16,8 @@ const trial = { type: jsPsychSpr, reading_string: "this is the reading string", - structured_reading_string: [["first", "second", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], + // structured_reading_string: [["first", "second", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], + structured_reading_string: ["first", "second", "third", "fith", "sixth", "seventh", "eighth", "ninth", "tenth"], mode: 3 }; diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index cd6590be..61ed63c6 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -47,9 +47,9 @@ type Info = typeof info; class SprPlugin implements JsPsychPlugin { static info = info; private index: number = 0; - private inner_index: number = -1; // initialized so that not shown if has an inner_index - private displayed = false; - private current_display_string: string[] = []; // use this to save iterations + private inner_index: number = -1; // mode 1-2: initialized so that not shown if has an inner_index + private displayed = false; // mode 3 + private current_display_string: string[] = []; // mode 1-2: use this to save iterations private structured_reading_string: string[] | string[][] = []; private mode; // | string[][] -> each method that takes in string will need to account for list of strings @@ -102,7 +102,7 @@ class SprPlugin implements JsPsychPlugin { } private onSpacebarPress(info?: any) { - var newHtml = `

Spacebar pressed!

`; + var newHtml = ""; // handles logic on whether to display blank or show text using boolean/index if (this.mode === 1 || this.mode === 2) { @@ -118,10 +118,16 @@ class SprPlugin implements JsPsychPlugin { newHtml = `

${this.updateDisplayString()}

`; } else if (this.mode === 3) { if (!this.displayed) { - if (typeof this.structured_reading_string === "string") - newHtml = this.structured_reading_string[this.index]; - else newHtml = "weird formatting"; // should build out a method that uses the inner index but makes it iterate better + if (typeof this.structured_reading_string[this.index] === "string") + newHtml = this.structured_reading_string[this.index] as string; + else { + for (const c of this.structured_reading_string[this.index]) { + // accounts for weird formatting cases (not necessary) + newHtml += c + " "; + } + } + newHtml = "

" + newHtml + "

"; this.displayed = true; } else { this.index++; @@ -130,7 +136,10 @@ class SprPlugin implements JsPsychPlugin { if (this.index >= this.structured_reading_string.length) { // this is when we want to end trial } else { - newHtml = this.generateBlank(this.structured_reading_string[this.index]); + newHtml = + "

" + + this.generateBlank(this.structured_reading_string[this.index]) + + "

"; } } } @@ -141,8 +150,7 @@ class SprPlugin implements JsPsychPlugin { document.querySelector("p")!.innerHTML = newHtml; } - // this is called whenever previousMethod upates the indicies - // this will let us create more advanced logic for how to handle the displays + // This helper method assists with mode 1 and 2 to keep efficency when updating indicies and the scren private updateDisplayString(): string { if (this.mode === 1 || this.mode === 2) { if (this.inner_index === -1) { @@ -153,36 +161,29 @@ class SprPlugin implements JsPsychPlugin { for (var i = 0; i < curr_segment.length; i++) { new_display_string.push( - "" + + "" + this.generateBlank(curr_segment[i]) + "" ); } this.current_display_string = new_display_string; - } else if (this.mode === 1) { - // if not need to reupdate then we can do new logic - if (this.inner_index > 0) + } else { + if (this.mode === 1 && this.inner_index > 0) { // sets previous to blank if exists this.current_display_string[this.inner_index - 1] = "" + this.generateBlank(this.structured_reading_string[this.index][this.inner_index - 1]) + ""; - this.current_display_string[this.inner_index] = - "" + - this.structured_reading_string[this.index][this.inner_index] + - ""; - } else if (this.mode === 2) { + } + // shows next display this.current_display_string[this.inner_index] = "" + this.structured_reading_string[this.index][this.inner_index] + ""; } - } else if (this.mode === 3) { - /// where we implement number 3 } - console.log("update display string res:", this.current_display_string); var displayString = ""; for (const s of this.current_display_string) { displayString += s + " "; // include another element From af9dcd2d35adb12393391154af3d8d13a0ccb3fa Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Sun, 13 Oct 2024 16:40:43 -0400 Subject: [PATCH 09/25] working data collection and end trial, updated examples to showfinal data --- packages/plugin-spr/examples/mode1.html | 7 ++++++- packages/plugin-spr/examples/mode2.html | 8 +++++++- packages/plugin-spr/examples/mode3.html | 7 ++++++- packages/plugin-spr/src/index.ts | 20 +++++++++++++------- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/packages/plugin-spr/examples/mode1.html b/packages/plugin-spr/examples/mode1.html index 36591f3a..661c5908 100644 --- a/packages/plugin-spr/examples/mode1.html +++ b/packages/plugin-spr/examples/mode1.html @@ -11,7 +11,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index d0dc02a2..c8d360cc 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -8,7 +8,7 @@ const info = { version: version, parameters: { /** Provide a clear description of the parameter_name that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ - reading_string: { + unstructured_reading_string: { type: ParameterType.STRING, // BOOL, STRING, INT, FLOAT, FUNCTION, KEY, KEYS, SELECT, HTML_STRING, IMAGE, AUDIO, VIDEO, OBJECT, COMPLEX default: "", }, @@ -21,6 +21,15 @@ const info = { type: ParameterType.INT, default: 1, }, + // splitting parameters + chunk_size: { + type: ParameterType.INT, + default: 1, + }, + line_size: { + type: ParameterType.INT, + default: 1, + }, }, data: { /** Provide a clear description of the data1 that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ @@ -57,11 +66,16 @@ class SprPlugin implements JsPsychPlugin { trial(display_element: HTMLElement, trial: TrialType) { this.initializeVariables(trial); - this.updateDisplayString(); // setup html logic - var html = `

${this.generateBlank(this.structured_reading_string[this.index])}

`; + var html = `

`; display_element.innerHTML = html; + if (this.mode === 3) + document.querySelector("p")!.innerHTML = this.generateBlank( + this.structured_reading_string[this.index] + ); + else document.querySelector("p")!.innerHTML = this.updateDisplayString(); + this.jsPsych.pluginAPI.getKeyboardResponse({ callback_function: (info) => this.onSpacebarPress(info), valid_responses: [" "], @@ -87,19 +101,20 @@ class SprPlugin implements JsPsychPlugin { if (trial.mode === 1 || trial.mode === 2 || trial.mode === 3) this.mode = trial.mode; else throw console.error("Mode declared incorrectly, must be between 1 and 3."); - console.log(trial.structured_reading_string, trial.structured_reading_string.length); + console.log(trial.unstructured_reading_string, trial.unstructured_reading_string.length); // creates inital reading string -> TODO: should instead use mode to determine if (trial.structured_reading_string.length > 0) this.structured_reading_string = trial.structured_reading_string; - else this.structured_reading_string = this.createReadingString(trial.reading_string); + else + this.structured_reading_string = this.createReadingString(trial.unstructured_reading_string); } // TODO: create a method that takes an entire string and uses a list of parameters to generate a "structured reading string" - private createReadingString(reading_string: string): string[] { + private createReadingString(unstructured_reading_string: string): string[] { // pass in parameters to split it // -> depends on the spaces and the typing - return [reading_string]; + return [unstructured_reading_string]; } private onSpacebarPress(info?: any) { @@ -123,31 +138,8 @@ class SprPlugin implements JsPsychPlugin { newHtml = `

${this.updateDisplayString()}

`; } else if (this.mode === 3) { - if (!this.displayed) { - if (typeof this.structured_reading_string[this.index] === "string") - newHtml = this.structured_reading_string[this.index] as string; - else { - for (const c of this.structured_reading_string[this.index]) { - // accounts for weird formatting cases (not necessary) - newHtml += c + " "; - } - } - - newHtml = "

" + newHtml + "

"; - this.displayed = true; - } else { - this.index++; - this.displayed = false; - - if (this.index >= this.structured_reading_string.length) { - this.endTrial(); - } else { - newHtml = - "

" + - this.generateBlank(this.structured_reading_string[this.index]) + - "

"; - } - } + // might want to include incrementation here for consistency + newHtml = this.updateDisplayString(); } // need to handle a keyboard press element where records how long until press a key @@ -167,7 +159,7 @@ class SprPlugin implements JsPsychPlugin { for (var i = 0; i < curr_segment.length; i++) { new_display_string.push( - "" + + "" + this.generateBlank(curr_segment[i]) + "" ); @@ -176,9 +168,9 @@ class SprPlugin implements JsPsychPlugin { this.current_display_string = new_display_string; } else { if (this.mode === 1 && this.inner_index > 0) { - // sets previous to blank if exists + // sets previous to blank if exists -> might want to do same with other one except just change css classifier this.current_display_string[this.inner_index - 1] = - "" + + "" + this.generateBlank(this.structured_reading_string[this.index][this.inner_index - 1]) + ""; } @@ -188,6 +180,35 @@ class SprPlugin implements JsPsychPlugin { this.structured_reading_string[this.index][this.inner_index] + ""; } + } else if (this.mode == 3) { + var newHtml = ""; + + if (!this.displayed) { + // accounts for bad user input (not necessary) and could move it up to input + if (typeof this.structured_reading_string[this.index] === "string") + newHtml = this.structured_reading_string[this.index] as string; + else { + for (const c of this.structured_reading_string[this.index]) { + newHtml += c + " "; + } + } + + newHtml = "

" + newHtml + "

"; + this.displayed = true; + } else { + this.index++; + this.displayed = false; + + if (this.index >= this.structured_reading_string.length) { + this.endTrial(); + } else { + newHtml = + "

" + + this.generateBlank(this.structured_reading_string[this.index]) + + "

"; + } + } + return newHtml; } var displayString = ""; @@ -199,9 +220,12 @@ class SprPlugin implements JsPsychPlugin { } private generateBlank(text: string | string[]): string { + // todo: make sure to split on individual words const length = text.length; if (typeof text === "string") { + console.log(text.split(" ")); + return "_".repeat(length); } else { // type of array From 51c1a67dec1f14cb8a2ac414b9e29f1203222f0e Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Fri, 18 Oct 2024 13:16:22 -0400 Subject: [PATCH 11/25] Updated generateBlanks to account for chunks including multiple words --- packages/plugin-spr/examples/mode2.html | 2 +- packages/plugin-spr/src/index.ts | 39 +++++++++++++++---------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/packages/plugin-spr/examples/mode2.html b/packages/plugin-spr/examples/mode2.html index 4442a0c2..d9cc79ff 100644 --- a/packages/plugin-spr/examples/mode2.html +++ b/packages/plugin-spr/examples/mode2.html @@ -22,7 +22,7 @@ const trial = { type: jsPsychSpr, reading_string: "this is the reading string", - structured_reading_string: [["first", "second", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], + structured_reading_string: [["first and second", "second and fourth", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], mode: 2 }; diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index c8d360cc..4c5038e2 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -75,14 +75,6 @@ class SprPlugin implements JsPsychPlugin { this.structured_reading_string[this.index] ); else document.querySelector("p")!.innerHTML = this.updateDisplayString(); - - this.jsPsych.pluginAPI.getKeyboardResponse({ - callback_function: (info) => this.onSpacebarPress(info), - valid_responses: [" "], - rt_method: "performance", - persist: true, - allow_held_key: false, - }); } private endTrial() { @@ -107,6 +99,14 @@ class SprPlugin implements JsPsychPlugin { this.structured_reading_string = trial.structured_reading_string; else this.structured_reading_string = this.createReadingString(trial.unstructured_reading_string); + + this.jsPsych.pluginAPI.getKeyboardResponse({ + callback_function: (info) => this.onSpacebarPress(info), + valid_responses: [" "], + rt_method: "performance", + persist: true, + allow_held_key: false, + }); } // TODO: create a method that takes an entire string and uses a list of parameters to generate a "structured reading string" @@ -222,20 +222,27 @@ class SprPlugin implements JsPsychPlugin { private generateBlank(text: string | string[]): string { // todo: make sure to split on individual words const length = text.length; + var res = ""; + // type of string (in context of plugin: chunk) if (typeof text === "string") { - console.log(text.split(" ")); + const split = text.split(" "); // checks for spaces to break up underscores - return "_".repeat(length); - } else { - // type of array - var res = ""; + if (split.length > 1) { + for (var i = 0; i < split.length; i++) { + res += "_".repeat(split[i].length) + " "; + } + } else res = "_".repeat(length); + } + // type of array (in context of plugin: line) + else { + // var res = ""; for (var i = 0; i < length; i++) { - const word_length = text[i].length; - res += "_".repeat(word_length) + " "; + res += this.generateBlank(text[i]) + " "; } - return res; } + + return res; } } From e1c16fc78b779307f41024cf442fd3b7f63dd84b Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Fri, 18 Oct 2024 13:38:30 -0400 Subject: [PATCH 12/25] Finished splitting parameters, finalizing documentation --- .../examples/reading_string_mode1.html | 33 ++++++++++++++++ ..._string.html => reading_string_mode3.html} | 2 +- packages/plugin-spr/src/index.ts | 39 ++++++++++++++++--- 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 packages/plugin-spr/examples/reading_string_mode1.html rename packages/plugin-spr/examples/{reading_string.html => reading_string_mode3.html} (83%) diff --git a/packages/plugin-spr/examples/reading_string_mode1.html b/packages/plugin-spr/examples/reading_string_mode1.html new file mode 100644 index 00000000..562fc370 --- /dev/null +++ b/packages/plugin-spr/examples/reading_string_mode1.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/plugin-spr/examples/reading_string.html b/packages/plugin-spr/examples/reading_string_mode3.html similarity index 83% rename from packages/plugin-spr/examples/reading_string.html rename to packages/plugin-spr/examples/reading_string_mode3.html index 3249028e..fa0d8cff 100644 --- a/packages/plugin-spr/examples/reading_string.html +++ b/packages/plugin-spr/examples/reading_string_mode3.html @@ -21,7 +21,7 @@ const trial = { type: jsPsychSpr, - unstructured_reading_string: "this is the reading string", + unstructured_reading_string: "this is the reading string and it is super super long, i wonder what will be coming next.", chunk_size: 1, line_size: 1, mode: 3 diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 4c5038e2..7feade87 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -98,7 +98,11 @@ class SprPlugin implements JsPsychPlugin { if (trial.structured_reading_string.length > 0) this.structured_reading_string = trial.structured_reading_string; else - this.structured_reading_string = this.createReadingString(trial.unstructured_reading_string); + this.structured_reading_string = this.createReadingString( + trial.unstructured_reading_string, + trial.chunk_size, + trial.line_size + ); this.jsPsych.pluginAPI.getKeyboardResponse({ callback_function: (info) => this.onSpacebarPress(info), @@ -110,11 +114,36 @@ class SprPlugin implements JsPsychPlugin { } // TODO: create a method that takes an entire string and uses a list of parameters to generate a "structured reading string" - private createReadingString(unstructured_reading_string: string): string[] { - // pass in parameters to split it - // -> depends on the spaces and the typing + private createReadingString( + unstructured_reading_string: string, + chunk_size: number, + line_size: number + ): string[] { + const split_text = unstructured_reading_string.split(" "); + const res = []; + + var current_chunk = []; + var current_line = []; + + for (var i = 0; i < split_text.length; i++) { + const word = split_text[i]; + current_chunk.push(word); + + if (current_chunk.length >= chunk_size) { + current_line.push(current_chunk.join(" ")); + current_chunk = []; + + if (current_line.length >= line_size) { + res.push(current_line); + current_line = []; + } + } + } + + if (current_chunk.length > 0) current_line.push(current_chunk); + if (current_line.length > 0) res.push(current_line); - return [unstructured_reading_string]; + return res; } private onSpacebarPress(info?: any) { From 4c57593ee5e3711a52322154ec570dbe0103e70d Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Fri, 18 Oct 2024 13:46:07 -0400 Subject: [PATCH 13/25] Tested styling to be workign --- packages/plugin-spr/examples/mode2.html | 1 + packages/plugin-spr/examples/styles.css | 11 +++++++++++ packages/plugin-spr/src/index.ts | 10 ++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 packages/plugin-spr/examples/styles.css diff --git a/packages/plugin-spr/examples/mode2.html b/packages/plugin-spr/examples/mode2.html index d9cc79ff..fa09131d 100644 --- a/packages/plugin-spr/examples/mode2.html +++ b/packages/plugin-spr/examples/mode2.html @@ -7,6 +7,7 @@ + diff --git a/packages/plugin-spr/examples/styles.css b/packages/plugin-spr/examples/styles.css new file mode 100644 index 00000000..39c8c725 --- /dev/null +++ b/packages/plugin-spr/examples/styles.css @@ -0,0 +1,11 @@ +.text-before-current-region { + background-color: blue; +} + +.text-current-region { + background-color: red; +} + +.text-after-current-region { + background-color: green; +} \ No newline at end of file diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 7feade87..fcb2630c 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -197,12 +197,19 @@ class SprPlugin implements JsPsychPlugin { this.current_display_string = new_display_string; } else { if (this.mode === 1 && this.inner_index > 0) { - // sets previous to blank if exists -> might want to do same with other one except just change css classifier this.current_display_string[this.inner_index - 1] = "" + this.generateBlank(this.structured_reading_string[this.index][this.inner_index - 1]) + ""; + } else if (this.mode === 2 && this.inner_index > 0) { + console.log("enters modifier", this.current_display_string); + // changes classifier + this.current_display_string[this.inner_index - 1] = + "" + + this.structured_reading_string[this.index][this.inner_index - 1] + + ""; } + // shows next display this.current_display_string[this.inner_index] = "" + @@ -249,7 +256,6 @@ class SprPlugin implements JsPsychPlugin { } private generateBlank(text: string | string[]): string { - // todo: make sure to split on individual words const length = text.length; var res = ""; From c44db433303a8132cd147e1c79c350f753eafc45 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Fri, 18 Oct 2024 14:40:22 -0400 Subject: [PATCH 14/25] Finished up documentation for the SPR md file --- packages/plugin-spr/docs/spr.md | 51 +++++++++++++++---- packages/plugin-spr/examples/mode1.html | 1 - packages/plugin-spr/examples/mode2.html | 1 - packages/plugin-spr/examples/mode3.html | 1 - ...=> unstructured_reading_string_mode1.html} | 0 ...=> unstructured_reading_string_mode3.html} | 0 packages/plugin-spr/src/index.ts | 2 +- 7 files changed, 43 insertions(+), 13 deletions(-) rename packages/plugin-spr/examples/{reading_string_mode1.html => unstructured_reading_string_mode1.html} (100%) rename packages/plugin-spr/examples/{reading_string_mode3.html => unstructured_reading_string_mode3.html} (100%) diff --git a/packages/plugin-spr/docs/spr.md b/packages/plugin-spr/docs/spr.md index 9a601c5f..135fa85b 100644 --- a/packages/plugin-spr/docs/spr.md +++ b/packages/plugin-spr/docs/spr.md @@ -1,28 +1,42 @@ # spr +### Modes + This is a package built to enable self paced reading with three distinct modes: -Mode 1: Masked presentation of the text on the screen (with spaces shown in the mask, eg. ___ ____ __ ____). Pressing space bar then revelas one word (or chunk) at a time and masks the previous word (or chunk) so that only one word (or chunk) is visible at a time. +Mode 1: Masked presentation of the text on the screen (with spaces shown in the mask, eg. ___ ____ __ ____). Pressing space bar then reveals one word (or chunk) at a time and masks the previous word (or chunk) so that only one word (or chunk) is visible at a time. Mode 2: One word (or chunk) is revealed with spacebar but earlier words (or chunks) remain visible. Mode 3: Only one word (or chunk) is displayed centered on the screen, no mask. -For modes 1 and 2, if you are passing in a structured reading string you must use a list of list of strings, denoting what classifies as a word or chunk. For modes 3, you can either pass in a list of strings or a list of list of strings. Either way, the outcome will be the same and each list will be displayed at the same time. +### Styling To add css and style the text elements, there are three different css classifiers. 1. 'text-current-region' refers to the text being displayed. 2. 'text-before-current-region' that has not been displayed. 3. 'text-after-current-region' that has already been displayed and shown. +### Input + +There are two different methods to input the string that will be displayed. A structured_reading_string is a strict input where you define every screen using chunks and lines. An unstructured_reading_string is where you pass in the full string and use chunk_size and line_size to denote how you want to split this input. If both are passed in, the structured_reading_string will be prioritized. More details on the distinction between chunks and lines and how to pass in or split your input can be found below. + +### Examples + +Examples of the difference between the different modes, styling and the uses of a structured vs unstructured reading strings can be found in the examples folder. + ## Parameters In addition to the [parameters available in all plugins](https://jspsych.org/latest/overview/plugins.md#parameters-available-in-all-plugins), this plugin accepts the following parameters. Parameters with a default value of undefined must be specified. Other parameters can be left unspecified if the default value is acceptable. | Parameter | Type | Default Value | Description | | ------------------- | ---------------- | ------------------ | ---------------------------------------- | -| structured_reading_string | List | [] | This is the explicit declaration for what to display on the string. Depending on the mode this will be treated differently. For mode 1 and 2 this must be passed in as a list of a list of strings. For mode 3, this can either be passed in as a list of a list of strings, or a list of strings. For mode 1 and 2, each individiual list represents the block of text that displays at one time. For mode 3, each list of strings or string is treated as an invidual word to be displayed. | +| unstructured_reading_string | String | "" | This is a representation of the input string that can be passed in as a full string and will be split using the splitting parameters of "chunk_size" and "line_size". | +| structured_reading_string | List | [] | This is the explicit declaration for what to display on the string. This should usually be a list of list of strings (list of lines, each line is a list of chunks). When using mode 3 the input can also be a list of strings with each string representing a chunk. | | Mode | Number | 1 | Indicates the mode of text displaying used by the SPR plugin. Mode 1 is a masked presentation where clicking spacebar hides the previous shown words, mode 2 reveals one chunk at time but the chunks but previous ones remain visible. Mode 3 is when one word is displayed with no mask. | +| chunk_size | String | int | Indicates the number of split words in the input string to be included within each chunk. | +| line_size | String | int | Indicates the number of chunks to be included within each line. | + ## Data Generated @@ -31,11 +45,15 @@ In addition to the [default data collected by all plugins](https://jspsych.org/l | Name | Type | Value | | --------- | ------- | ---------------------------------------- | | stimulus | [] | This value represents the structured_reading_string used to run the experiment. | -| mode | number | This value represents the mode that the self-paced reading experiment was ran using and thus how the text was displayed. +| mode | number | This value represents the mode that the self-paced reading experiment was ran using and thus how the text was displayed. | ## Chunks vs Lines +When using this plugin, chunks and lines represent how text is displayed. Chunks can represent either words or multiple words along with characters ("one", "two?", "three four five"). During mode 1 or 2, chunks represents the words that are hidden or shown with each click of the spacebar. Lines on the other hand represent multiple chunks (["one", "two?", "three four five"]) held together in a list. Lines represent what is displayed during each distinct screen and chunks represent how they are grouped together. +Imagine the line ["one", "two?", "three four five"]. If we are using mode 1, this will initially be represented on the screen as `"___ ____ _____ ____ ____"`. With one spacebar click, the first chunk is revealed and the screen displays `"one ____ _____ ____ ____"`. With the next click, the second chunk is revealed and the first is hidden: `"___ two? _____ ____ ____;"`. Lastly, when the final chunk is revelead: `"___ ____ three four five"`. + +When using structured reading strings you have the ability to explicitly define each chunk and line. However when running experiments with longer strings you can also use "chunk_size" to define how many words (delimited by spaces) are included within each chunk and "line_size" to define how many chunks are included within each line. ## Install @@ -63,10 +81,25 @@ import Spr from '@jspsych-contrib/plugin-spr'; ## Examples -### Title of Example +### Using a structured_reading_string ```javascript -var trial = { - type: jsPsychSpr -} -``` \ No newline at end of file +const trial = { + type: jsPsychSpr, + structured_reading_string: [["first and second", "second and fourth", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], + mode: 2 +}; +``` + +### Using an unstructured_reading_string with chunk_size and line_size + +```javascript +const trial = { + type: jsPsychSpr, + unstructured_reading_string: "this is the reading string and it is super super long, i wonder what will be coming next.", + chunk_size: 2, + line_size: 2, + mode: 1 +}; +``` + diff --git a/packages/plugin-spr/examples/mode1.html b/packages/plugin-spr/examples/mode1.html index 661c5908..51495b7c 100644 --- a/packages/plugin-spr/examples/mode1.html +++ b/packages/plugin-spr/examples/mode1.html @@ -20,7 +20,6 @@ const trial = { type: jsPsychSpr, - reading_string: "this is the reading string", structured_reading_string: [["first", "second", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], mode: 1 }; diff --git a/packages/plugin-spr/examples/mode2.html b/packages/plugin-spr/examples/mode2.html index fa09131d..b49e0c46 100644 --- a/packages/plugin-spr/examples/mode2.html +++ b/packages/plugin-spr/examples/mode2.html @@ -22,7 +22,6 @@ const trial = { type: jsPsychSpr, - reading_string: "this is the reading string", structured_reading_string: [["first and second", "second and fourth", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], mode: 2 }; diff --git a/packages/plugin-spr/examples/mode3.html b/packages/plugin-spr/examples/mode3.html index 5523cab6..ec292c6a 100644 --- a/packages/plugin-spr/examples/mode3.html +++ b/packages/plugin-spr/examples/mode3.html @@ -20,7 +20,6 @@ const trial = { type: jsPsychSpr, - reading_string: "this is the reading string", // structured_reading_string: [["first", "second", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], structured_reading_string: ["first", "second", "third", "fith", "sixth", "seventh", "eighth", "ninth", "tenth"], mode: 3 diff --git a/packages/plugin-spr/examples/reading_string_mode1.html b/packages/plugin-spr/examples/unstructured_reading_string_mode1.html similarity index 100% rename from packages/plugin-spr/examples/reading_string_mode1.html rename to packages/plugin-spr/examples/unstructured_reading_string_mode1.html diff --git a/packages/plugin-spr/examples/reading_string_mode3.html b/packages/plugin-spr/examples/unstructured_reading_string_mode3.html similarity index 100% rename from packages/plugin-spr/examples/reading_string_mode3.html rename to packages/plugin-spr/examples/unstructured_reading_string_mode3.html diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index fcb2630c..59c782e7 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -9,7 +9,7 @@ const info = { parameters: { /** Provide a clear description of the parameter_name that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ unstructured_reading_string: { - type: ParameterType.STRING, // BOOL, STRING, INT, FLOAT, FUNCTION, KEY, KEYS, SELECT, HTML_STRING, IMAGE, AUDIO, VIDEO, OBJECT, COMPLEX + type: ParameterType.STRING, default: "", }, structured_reading_string: { From 273ed1a0329b034942b80da41a07dd9219369738 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Fri, 18 Oct 2024 14:46:17 -0400 Subject: [PATCH 15/25] Finishing up documentation within the trial parameters --- packages/plugin-spr/src/index.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 59c782e7..bc4cf0c0 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -2,43 +2,47 @@ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; import { version } from "../package.json"; -// TODO: need to restructure to use the CSS styling proposed by Titus const info = { name: "spr", version: version, parameters: { - /** Provide a clear description of the parameter_name that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ + /* String input of the displayed text which will be split to create a structured_reading_string. */ unstructured_reading_string: { type: ParameterType.STRING, default: "", }, + /* String input that explictly defines how the chunks and lines will be displayed during the SPR trial.*/ structured_reading_string: { type: ParameterType.STRING, array: true, default: [], }, + /* Mode between 1-3 that indicate the different built-in modes for how stimulus will be displayed. */ mode: { type: ParameterType.INT, default: 1, }, - // splitting parameters + /* Indicates how many words will be included with each chunk when splitting the unstructured_reading_string. */ chunk_size: { type: ParameterType.INT, default: 1, }, + /* Indicates how many chunks will be included with each chunk when splitting the unstructured_reading_string. */ line_size: { type: ParameterType.INT, default: 1, }, }, data: { - /** Provide a clear description of the data1 that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ - data1: { - type: ParameterType.INT, - }, - /** Provide a clear description of the data2 that could be used as documentation. We will eventually use these comments to automatically build documentation and produce metadata. */ - data2: { + /* The representation of the structured_reading_string that was used. Combined with the mode this + tells what exactly was displayed on the screen during each click. */ + stimulus: { type: ParameterType.STRING, + Array: true, + }, + /** Indicates the mode that the SPR experiment was ran using. */ + mode: { + type: ParameterType.INT, }, }, }; From 30769b412cad0055e29903df095ff00d8be28443 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Fri, 18 Oct 2024 14:54:33 -0400 Subject: [PATCH 16/25] Pushing changeset --- .changeset/rich-tomatoes-marry.md | 5 +++++ package-lock.json | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 .changeset/rich-tomatoes-marry.md diff --git a/.changeset/rich-tomatoes-marry.md b/.changeset/rich-tomatoes-marry.md new file mode 100644 index 00000000..218c6545 --- /dev/null +++ b/.changeset/rich-tomatoes-marry.md @@ -0,0 +1,5 @@ +--- +"@jspsych-contrib/plugin-self-paced-reading": major +--- + +Inital version of SPR plugin diff --git a/package-lock.json b/package-lock.json index 0a97c4a4..95f1d93b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3490,6 +3490,10 @@ "resolved": "packages/plugin-self-paced-reading", "link": true }, + "node_modules/@jspsych-contrib/plugin-spr": { + "resolved": "packages/plugin-spr", + "link": true + }, "node_modules/@jspsych-contrib/plugin-survey-number": { "resolved": "packages/plugin-survey-number", "link": true @@ -19048,6 +19052,18 @@ "jspsych": ">=7.0.0" } }, + "packages/plugin-spr": { + "version": "0.0.1", + "license": "MIT", + "devDependencies": { + "@jspsych/config": "^2.0.0", + "@jspsych/test-utils": "^1.0.0", + "jspsych": "^7.0.0" + }, + "peerDependencies": { + "jspsych": ">=7.0.0" + } + }, "packages/plugin-survey-number": { "name": "@jspsych-contrib/plugin-survey-number", "version": "1.0.0", From 7e7303bc137f7862b41faad8942b40bc15df0f56 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Mon, 21 Oct 2024 11:02:28 -0400 Subject: [PATCH 17/25] Added initial data model, missing docuemntation --- packages/plugin-spr/src/index.ts | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index bc4cf0c0..9b42d52a 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -61,10 +61,12 @@ class SprPlugin implements JsPsychPlugin { static info = info; private index: number = 0; private inner_index: number = -1; // mode 1-2: initialized so that not shown if has an inner_index - private displayed = false; // mode 3 private current_display_string: string[] = []; // mode 1-2: use this to save iterations + private displayed = false; // mode 3 private structured_reading_string: string[] | string[][] = []; private mode; + private results = []; + private startTime; constructor(private jsPsych: JsPsych) {} @@ -87,6 +89,7 @@ class SprPlugin implements JsPsychPlugin { // data1: 99, // Make sure this type and name matches the information for data1 in the data object contained within the info const. stimlulus: this.structured_reading_string, // Make sure this type and name matches the information for data2 in the data object contained within the info const. mode: this.mode, + results: this.results, }; // end trial this.jsPsych.pluginAPI.cancelAllKeyboardResponses(); @@ -97,7 +100,6 @@ class SprPlugin implements JsPsychPlugin { if (trial.mode === 1 || trial.mode === 2 || trial.mode === 3) this.mode = trial.mode; else throw console.error("Mode declared incorrectly, must be between 1 and 3."); - console.log(trial.unstructured_reading_string, trial.unstructured_reading_string.length); // creates inital reading string -> TODO: should instead use mode to determine if (trial.structured_reading_string.length > 0) this.structured_reading_string = trial.structured_reading_string; @@ -115,6 +117,8 @@ class SprPlugin implements JsPsychPlugin { persist: true, allow_held_key: false, }); + + this.startTime = Date.now(); } // TODO: create a method that takes an entire string and uses a list of parameters to generate a "structured reading string" @@ -199,6 +203,7 @@ class SprPlugin implements JsPsychPlugin { } this.current_display_string = new_display_string; + this.results.push([this.getElapsed()]); } else { if (this.mode === 1 && this.inner_index > 0) { this.current_display_string[this.inner_index - 1] = @@ -219,6 +224,12 @@ class SprPlugin implements JsPsychPlugin { "" + this.structured_reading_string[this.index][this.inner_index] + ""; + + this.results[this.results.length - 1].push( + this.structured_reading_string[this.index][this.inner_index], + this.getElapsed() + ); + // this.results[this.results.length-1].push([this.getElapsed(), this.structured_reading_string[this.index][this.inner_index]]); } } else if (this.mode == 3) { var newHtml = ""; @@ -235,6 +246,8 @@ class SprPlugin implements JsPsychPlugin { newHtml = "

" + newHtml + "

"; this.displayed = true; + + this.results.push([this.getElapsed(), newHtml]); // pushes new list with time passed (time looking at blank) } else { this.index++; this.displayed = false; @@ -247,6 +260,8 @@ class SprPlugin implements JsPsychPlugin { this.generateBlank(this.structured_reading_string[this.index]) + "

"; } + + this.results[this.results.length - 1].push(this.getElapsed()); // pushes second time spent looking at word } return newHtml; } @@ -283,6 +298,10 @@ class SprPlugin implements JsPsychPlugin { return res; } + + private getElapsed() { + return Date.now() - this.startTime; + } } export default SprPlugin; From 66a5ab42c2d7603f48162552f2ddf069989ff5c3 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Mon, 21 Oct 2024 11:21:28 -0400 Subject: [PATCH 18/25] Initial delimiter model --- packages/plugin-spr/examples/delimiter.html | 32 +++++++++++++++++++++ packages/plugin-spr/src/index.ts | 21 ++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 packages/plugin-spr/examples/delimiter.html diff --git a/packages/plugin-spr/examples/delimiter.html b/packages/plugin-spr/examples/delimiter.html new file mode 100644 index 00000000..02c84a0e --- /dev/null +++ b/packages/plugin-spr/examples/delimiter.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 9b42d52a..4fe279e5 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -32,6 +32,10 @@ const info = { type: ParameterType.INT, default: 1, }, + delimiting: { + type: ParameterType.BOOL, + default: false, + }, }, data: { /* The representation of the structured_reading_string that was used. Combined with the mode this @@ -103,7 +107,15 @@ class SprPlugin implements JsPsychPlugin { // creates inital reading string -> TODO: should instead use mode to determine if (trial.structured_reading_string.length > 0) this.structured_reading_string = trial.structured_reading_string; - else + else if (trial.delimiting) { + this.structured_reading_string = this.createReadingString( + trial.unstructured_reading_string, + trial.chunk_size, + trial.line_size, + "%" + ); + console.log("delimiting is true", this.structured_reading_string); + } else this.structured_reading_string = this.createReadingString( trial.unstructured_reading_string, trial.chunk_size, @@ -125,9 +137,12 @@ class SprPlugin implements JsPsychPlugin { private createReadingString( unstructured_reading_string: string, chunk_size: number, - line_size: number + line_size: number, + delimiter?: string ): string[] { - const split_text = unstructured_reading_string.split(" "); + const split_text = delimiter + ? unstructured_reading_string.split(delimiter) + : unstructured_reading_string.split(" "); const res = []; var current_chunk = []; From fb8d5075d1f3c8b1f24ac476ca6e8545d781777f Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:44:06 -0400 Subject: [PATCH 19/25] fix desc and update to v8 --- package-lock.json | 2442 ++++++++++++++++++++++-------- packages/plugin-spr/README.md | 4 +- packages/plugin-spr/package.json | 8 +- packages/plugin-spr/src/index.ts | 15 +- 4 files changed, 1827 insertions(+), 642 deletions(-) diff --git a/package-lock.json b/package-lock.json index 95f1d93b..7ce56d27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "jspsych-contrib", + "name": "jspsych-spr", "lockfileVersion": 3, "requires": true, "packages": { @@ -2326,6 +2326,38 @@ "integrity": "sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==", "dev": true }, + "node_modules/@esbuild/android-arm": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.14.tgz", + "integrity": "sha512-+Rb20XXxRGisNu2WmNKk+scpanb7nL5yhuI1KR9wQFiC43ddPj/V1fmNyzlFC9bKiG4mYzxW7egtoHVcynr+OA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.14.tgz", + "integrity": "sha512-eQi9rosGNVQFJyJWV0HCA5WZae/qWIQME7s8/j8DMvnylfBv62Pbu+zJ2eUDqNf2O4u3WB+OEXyfkpBoe194sg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@gulpjs/messages": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@gulpjs/messages/-/messages-1.1.0.tgz", @@ -3971,6 +4003,48 @@ "node": ">= 0.10" } }, + "node_modules/@jspsych/config/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/@jspsych/config/node_modules/rollup/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/@jspsych/config/node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -4006,6 +4080,19 @@ "node": ">= 0.10" } }, + "node_modules/@jspsych/config/node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@jspsych/config/node_modules/undertaker": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", @@ -7797,6 +7884,12 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, "node_modules/es-object-atoms": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", @@ -7901,636 +7994,695 @@ "es6-symbol": "^3.1.1" } }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "node_modules/esbuild": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.14.tgz", + "integrity": "sha512-pJN8j42fvWLFWwSMG4luuupl2Me7mxciUOsMegKvwCmhEbJ2covUdFnihxm0FMIBV+cbwbtMoHgMCCI+pj1btQ==", "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, + "hasInstallScript": true, "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=6.0" + "node": ">=12" }, "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "@esbuild/android-arm": "0.15.14", + "@esbuild/linux-loong64": "0.15.14", + "esbuild-android-64": "0.15.14", + "esbuild-android-arm64": "0.15.14", + "esbuild-darwin-64": "0.15.14", + "esbuild-darwin-arm64": "0.15.14", + "esbuild-freebsd-64": "0.15.14", + "esbuild-freebsd-arm64": "0.15.14", + "esbuild-linux-32": "0.15.14", + "esbuild-linux-64": "0.15.14", + "esbuild-linux-arm": "0.15.14", + "esbuild-linux-arm64": "0.15.14", + "esbuild-linux-mips64le": "0.15.14", + "esbuild-linux-ppc64le": "0.15.14", + "esbuild-linux-riscv64": "0.15.14", + "esbuild-linux-s390x": "0.15.14", + "esbuild-netbsd-64": "0.15.14", + "esbuild-openbsd-64": "0.15.14", + "esbuild-sunos-64": "0.15.14", + "esbuild-windows-32": "0.15.14", + "esbuild-windows-64": "0.15.14", + "esbuild-windows-arm64": "0.15.14" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.14.tgz", + "integrity": "sha512-HuilVIb4rk9abT4U6bcFdU35UHOzcWVGLSjEmC58OVr96q5UiRqzDtWjPlCMugjhgUGKEs8Zf4ueIvYbOStbIg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=0.10" + "node": ">=12" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/esbuild-android-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.14.tgz", + "integrity": "sha512-/QnxRVxsR2Vtf3XottAHj7hENAMW2wCs6S+OZcAbc/8nlhbAL/bCQRCVD78VtI5mdwqWkVi3wMqM94kScQCgqg==", + "cpu": [ + "arm64" + ], "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/esbuild-darwin-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.14.tgz", + "integrity": "sha512-ToNuf1uifu8hhwWvoZJGCdLIX/1zpo8cOGnT0XAhDQXiKOKYaotVNx7pOVB1f+wHoWwTLInrOmh3EmA7Fd+8Vg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=4.0" + "node": ">=12" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/esbuild-darwin-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.14.tgz", + "integrity": "sha512-KgGP+y77GszfYJgceO0Wi/PiRtYo5y2Xo9rhBUpxTPaBgWDJ14gqYN0+NMbu+qC2fykxXaipHxN4Scaj9tUS1A==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/eve": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/eve/-/eve-0.5.4.tgz", - "integrity": "sha512-aqprQ9MAOh1t66PrHxDFmMXPlgNO6Uv1uqvxmwjprQV50jaQ2RqO7O1neY4PJwC+hMnkyMDphu2AQPOPZdjQog==" - }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "node_modules/esbuild-freebsd-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.14.tgz", + "integrity": "sha512-xr0E2n5lyWw3uFSwwUXHc0EcaBDtsal/iIfLioflHdhAe10KSctV978Te7YsfnsMKzcoGeS366+tqbCXdqDHQA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/esbuild-freebsd-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.14.tgz", + "integrity": "sha512-8XH96sOQ4b1LhMlO10eEWOjEngmZ2oyw3pW4o8kvBcpF6pULr56eeYVP5radtgw54g3T8nKHDHYEI5AItvskZg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=12" } }, - "node_modules/execa/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/esbuild-linux-32": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.14.tgz", + "integrity": "sha512-6ssnvwaTAi8AzKN8By2V0nS+WF5jTP7SfuK6sStGnDP7MCJo/4zHgM9oE1eQTS2jPmo3D673rckuCzRlig+HMA==", + "cpu": [ + "ia32" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/esbuild-linux-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.14.tgz", + "integrity": "sha512-ONySx3U0wAJOJuxGUlXBWxVKFVpWv88JEv0NZ6NlHknmDd1yCbf4AEdClSgLrqKQDXYywmw4gYDvdLsS6z0hcw==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.8.0" + "node": ">=12" } }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, + "node_modules/esbuild-linux-arm": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.14.tgz", + "integrity": "sha512-D2LImAIV3QzL7lHURyCHBkycVFbKwkDb1XEUWan+2fb4qfW7qAeUtul7ZIcIwFKZgPcl+6gKZmvLgPSj26RQ2Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/esbuild-linux-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.14.tgz", + "integrity": "sha512-kle2Ov6a1e5AjlHlMQl1e+c4myGTeggrRzArQFmWp6O6JoqqB9hT+B28EW4tjFWgV/NxUq46pWYpgaWXsXRPAg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "ms": "2.0.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "node_modules/esbuild-linux-mips64le": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.14.tgz", + "integrity": "sha512-FVdMYIzOLXUq+OE7XYKesuEAqZhmAIV6qOoYahvUp93oXy0MOVTP370ECbPfGXXUdlvc0TNgkJa3YhEwyZ6MRA==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/esbuild-linux-ppc64le": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.14.tgz", + "integrity": "sha512-2NzH+iuzMDA+jjtPjuIz/OhRDf8tzbQ1tRZJI//aT25o1HKc0reMMXxKIYq/8nSHXiJSnYV4ODzTiv45s+h73w==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", - "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "node_modules/esbuild-linux-riscv64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.14.tgz", + "integrity": "sha512-VqxvutZNlQxmUNS7Ac+aczttLEoHBJ9e3OYGqnULrfipRvG97qLrAv9EUY9iSrRKBqeEbSvS9bSfstZqwz0T4Q==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "node_modules/esbuild-linux-s390x": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.14.tgz", + "integrity": "sha512-+KVHEUshX5n6VP6Vp/AKv9fZIl5kr2ph8EUFmQUJnDpHwcfTSn2AQgYYm0HTBR2Mr4d0Wlr0FxF/Cs5pbFgiOw==", + "cpu": [ + "s390x" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "node_modules/esbuild-netbsd-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.14.tgz", + "integrity": "sha512-6D/dr17piEgevIm1xJfZP2SjB9Z+g8ERhNnBdlZPBWZl+KSPUKLGF13AbvC+nzGh8IxOH2TyTIdRMvKMP0nEzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, + "node_modules/esbuild-openbsd-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.14.tgz", + "integrity": "sha512-rREQBIlMibBetgr2E9Lywt2Qxv2ZdpmYahR4IUlAQ1Efv/A5gYdO0/VIN3iowDbCNTLxp0bb57Vf0LFcffD6kA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/esbuild-sunos-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.14.tgz", + "integrity": "sha512-DNVjSp/BY4IfwtdUAvWGIDaIjJXY5KI4uD82+15v6k/w7px9dnaDaJJ2R6Mu+KCgr5oklmFc0KjBjh311Gxl9Q==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "node_modules/esbuild-windows-32": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.14.tgz", + "integrity": "sha512-pHBWrcA+/oLgvViuG9FO3kNPO635gkoVrRQwe6ZY1S0jdET07xe2toUvQoJQ8KT3/OkxqUasIty5hpuKFLD+eg==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "type": "^2.7.2" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "node_modules/esbuild-windows-64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.14.tgz", + "integrity": "sha512-CszIGQVk/P8FOS5UgAH4hKc9zOaFo69fe+k1rqgBHx3CSK3Opyk5lwYriIamaWOVjBt7IwEP6NALz+tkVWdFog==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "node_modules/esbuild-windows-arm64": { + "version": "0.15.14", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.14.tgz", + "integrity": "sha512-KW9W4psdZceaS9A7Jsgl4WialOznSURvqX/oHZk3gOP7KbjtHLSsnmSvNdzagGJfxbAe30UVGXRe8q8nDsOSQw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/extendable-error": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", - "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", - "dev": true + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=4" + "node": ">=0.8.0" } }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "dev": true, "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", "dev": true, "dependencies": { - "is-descriptor": "^1.0.0" + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "dependencies": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, "engines": { - "node": ">=8.6.0" + "node": ">=4.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, - "node_modules/fast-levenshtein": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", - "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", - "dependencies": { - "fastest-levenshtein": "^1.0.7" - } - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { - "node": ">= 4.9.1" + "node": ">=0.10.0" } }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dependencies": { - "reusify": "^1.0.4" - } + "node_modules/eve": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/eve/-/eve-0.5.4.tgz", + "integrity": "sha512-aqprQ9MAOh1t66PrHxDFmMXPlgNO6Uv1uqvxmwjprQV50jaQ2RqO7O1neY4PJwC+hMnkyMDphu2AQPOPZdjQog==" }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "dev": true, "dependencies": { - "bser": "2.1.1" + "d": "1", + "es5-ext": "~0.10.14" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.5" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, - "optional": true + "engines": { + "node": ">= 0.8.0" + } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" + "ms": "2.0.0" } }, - "node_modules/find-cache-dir/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "dev": true, "dependencies": { - "locate-path": "^3.0.0" + "is-descriptor": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "is-extendable": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "dependencies": { - "p-limit": "^2.0.0" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/find-cache-dir/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "node_modules/expand-brackets/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/find-cache-dir/node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", "dependencies": { - "find-up": "^3.0.0" + "homedir-polyfill": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/find-line-column": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/find-line-column/-/find-line-column-0.5.2.tgz", - "integrity": "sha512-eNhNkDt5RbxY4X++JwyDURP62FYhV1bh9LF4dfOiwpVCTk5vvfEANhnui5ypUEELGR02QZSrWFtaTgd4ulW5tw==", - "dev": true - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/find-yarn-workspace-root2": { - "version": "1.2.16", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz", - "integrity": "sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==", + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "dev": true, "dependencies": { - "micromatch": "^4.0.2", - "pkg-dir": "^4.2.0" + "type": "^2.7.2" } }, - "node_modules/findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "dev": true, "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, + "node_modules/extendable-error": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", + "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", + "dev": true + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/findup-sync/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "dependencies": { - "is-extendable": "^0.1.0" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", "dev": true, "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "is-descriptor": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/fill-range/node_modules/extend-shallow": { + "node_modules/extglob/node_modules/extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", @@ -8542,7 +8694,7 @@ "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/is-extendable": { + "node_modules/extglob/node_modules/is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", @@ -8551,265 +8703,563 @@ "node": ">=0.10.0" } }, - "node_modules/findup-sync/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", "dev": true, "dependencies": { - "kind-of": "^3.0.2" + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/findup-sync/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { - "is-buffer": "^1.1.5" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6.0" } }, - "node_modules/findup-sync/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, - "node_modules/findup-sync/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, + "node_modules/fast-levenshtein": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", + "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, + "fastest-levenshtein": "^1.0.7" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "engines": { - "node": ">=0.10.0" + "node": ">= 4.9.1" } }, - "node_modules/findup-sync/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" + "reusify": "^1.0.4" } }, - "node_modules/fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "dependencies": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "engines": { - "node": ">= 0.10" + "bser": "2.1.1" } }, - "node_modules/fined/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true, + "optional": true + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/flow-parser": { - "version": "0.237.2", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.237.2.tgz", - "integrity": "sha512-mvI/kdfr3l1waaPbThPA8dJa77nHXrfZIun+SWvFwSwDjmeByU7mGJGRmv1+7guU6ccyLV8e1lqZA1lD4iMGnQ==", + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=6" } }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, "dependencies": { - "for-in": "^1.0.1" + "p-limit": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "node_modules/find-cache-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "find-up": "^3.0.0" }, "engines": { - "node": ">= 6" + "node": ">=6" } }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "node_modules/find-line-column": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/find-line-column/-/find-line-column-0.5.2.tgz", + "integrity": "sha512-eNhNkDt5RbxY4X++JwyDURP62FYhV1bh9LF4dfOiwpVCTk5vvfEANhnui5ypUEELGR02QZSrWFtaTgd4ulW5tw==", + "dev": true + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "map-cache": "^0.2.2" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "node_modules/find-yarn-workspace-root2": { + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz", + "integrity": "sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "micromatch": "^4.0.2", + "pkg-dir": "^4.2.0" + } + }, + "node_modules/findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">= 0.10" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/findup-sync/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, "dependencies": { - "minipass": "^3.0.0" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" }, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/findup-sync/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" + "is-extendable": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/fs-minipass/node_modules/yallist": { + "node_modules/findup-sync/node_modules/fill-range": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/fs-mkdirp-stream": { + "node_modules/findup-sync/node_modules/fill-range/node_modules/extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", - "integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, "dependencies": { - "graceful-fs": "^4.2.8", - "streamx": "^2.12.0" + "is-extendable": "^0.1.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=0.10.0" } }, - "node_modules/fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "node_modules/findup-sync/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/findup-sync/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=0.10.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", + "node_modules/findup-sync/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flow-parser": { + "version": "0.237.2", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.237.2.tgz", + "integrity": "sha512-mvI/kdfr3l1waaPbThPA8dJa77nHXrfZIun+SWvFwSwDjmeByU7mGJGRmv1+7guU6ccyLV8e1lqZA1lD4iMGnQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/fs-mkdirp-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", + "integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==", + "dependencies": { + "graceful-fs": "^4.2.8", + "streamx": "^2.12.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "funding": { @@ -12769,6 +13219,15 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -13128,6 +13587,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -15707,33 +16172,89 @@ } }, "node_modules/rollup": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", - "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", "dev": true, + "peer": true, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=18.0.0", + "node": ">=14.18.0", "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.3.0", - "@rollup/rollup-android-arm64": "4.3.0", - "@rollup/rollup-darwin-arm64": "4.3.0", - "@rollup/rollup-darwin-x64": "4.3.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", - "@rollup/rollup-linux-arm64-gnu": "4.3.0", - "@rollup/rollup-linux-arm64-musl": "4.3.0", - "@rollup/rollup-linux-x64-gnu": "4.3.0", - "@rollup/rollup-linux-x64-musl": "4.3.0", - "@rollup/rollup-win32-arm64-msvc": "4.3.0", - "@rollup/rollup-win32-ia32-msvc": "4.3.0", - "@rollup/rollup-win32-x64-msvc": "4.3.0", "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-dts": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-5.0.0.tgz", + "integrity": "sha512-OO8ayCvuJCKaQSShyVTARxGurVVk4ulzbuvz+0zFd1f93vlnWFU5pBMT7HFeS6uj7MvvZLx4kUAarGATSU1+Ng==", + "dev": true, + "dependencies": { + "magic-string": "^0.26.7" + }, + "engines": { + "node": ">=v14" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.18.6" + }, + "peerDependencies": { + "rollup": "^3.0.0", + "typescript": "^4.1" + } + }, + "node_modules/rollup-plugin-dts/node_modules/magic-string": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", + "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/rollup-plugin-esbuild": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-5.0.0.tgz", + "integrity": "sha512-1cRIOHAPh8WQgdQQyyvFdeOdxuiyk+zB5zJ5+YOwrZP4cJ0MT3Fs48pQxrZeyZHcn+klFherytILVfE4aYrneg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "debug": "^4.3.4", + "es-module-lexer": "^1.0.5", + "joycon": "^3.1.1", + "jsonc-parser": "^3.2.0" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.10.1", + "rollup": "^1.20.0 || ^2.0.0 || ^3.0.0" + } + }, + "node_modules/rollup-plugin-node-externals": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-externals/-/rollup-plugin-node-externals-5.0.2.tgz", + "integrity": "sha512-UGAPdPjD0PPk4hNcHLnqwqsfNc/u0vaAjWnjkyS6j2jIMB4LLi1pW3TE01eaytJKZactNik2t8AQC33esS9GKw==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.60.0 || ^3.0.0" + } + }, "node_modules/rollup-plugin-typescript2": { "version": "0.36.0", "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.36.0.tgz", @@ -16584,6 +17105,13 @@ "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true + }, "node_modules/sparkles": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", @@ -17730,16 +18258,17 @@ "dev": true }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=4.2.0" } }, "node_modules/unbox-primitive": { @@ -19053,15 +19582,666 @@ } }, "packages/plugin-spr": { + "name": "@jspsych-contrib/plugin-spr", "version": "0.0.1", "license": "MIT", "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "8.0.0" }, "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" + } + }, + "packages/plugin-spr/node_modules/@jspsych/config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@jspsych/config/-/config-3.0.0.tgz", + "integrity": "sha512-WGqeM7d6L2Cq2+a1gUd0sJa5hBTa5lO4Ak/BVNcDijnWMSgXHe5fH+s4MMl6PxL2aM0vpedlNVHGbjKNgrvU9w==", + "dev": true, + "dependencies": { + "@rollup/plugin-commonjs": "25.0.7", + "@rollup/plugin-node-resolve": "15.2.3", + "@sucrase/jest-plugin": "3.0.0", + "@types/gulp": "4.0.17", + "@types/jest": "29.5.8", + "alias-hq": "6.2.3", + "canvas": "^2.11.2", + "esbuild": "0.15.14", + "gulp": "4.0.2", + "gulp-cli": "2.3.0", + "gulp-file": "0.4.0", + "gulp-rename": "2.0.0", + "gulp-replace": "1.1.4", + "gulp-zip": "6.0.0", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", + "merge-stream": "2.0.0", + "rollup": "4.3.0", + "rollup-plugin-dts": "5.0.0", + "rollup-plugin-esbuild": "5.0.0", + "rollup-plugin-node-externals": "5.0.2", + "sucrase": "3.34.0", + "tslib": "2.6.2", + "typescript": "^5.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "packages/plugin-spr/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "packages/plugin-spr/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "packages/plugin-spr/node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "packages/plugin-spr/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "packages/plugin-spr/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "packages/plugin-spr/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "packages/plugin-spr/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/jspsych": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/jspsych/-/jspsych-8.0.0.tgz", + "integrity": "sha512-fip+MlwB+NDp1lxPir/q/juRsI/92/k1Gj7tAHrrNTy15pPQaunmW9TSXQJ26Z2Eikf+WIEUmGiCDuGr9wrqpw==", + "dev": true, + "dependencies": { + "auto-bind": "^4.0.0", + "random-words": "^1.1.1", + "seedrandom": "^3.0.5", + "type-fest": "^2.9.0" + } + }, + "packages/plugin-spr/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "packages/plugin-spr/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/rollup": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.3.0.tgz", + "integrity": "sha512-scIi1NrKLDIYSPK66jjECtII7vIgdAMFmFo8h6qm++I6nN9qDSV35Ku6erzGVqYjx+lj+j5wkusRMr++8SyDZg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.3.0", + "@rollup/rollup-android-arm64": "4.3.0", + "@rollup/rollup-darwin-arm64": "4.3.0", + "@rollup/rollup-darwin-x64": "4.3.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.3.0", + "@rollup/rollup-linux-arm64-gnu": "4.3.0", + "@rollup/rollup-linux-arm64-musl": "4.3.0", + "@rollup/rollup-linux-x64-gnu": "4.3.0", + "@rollup/rollup-linux-x64-musl": "4.3.0", + "@rollup/rollup-win32-arm64-msvc": "4.3.0", + "@rollup/rollup-win32-ia32-msvc": "4.3.0", + "@rollup/rollup-win32-x64-msvc": "4.3.0", + "fsevents": "~2.3.2" + } + }, + "packages/plugin-spr/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "packages/plugin-spr/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/plugin-spr/node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "packages/plugin-spr/node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "packages/plugin-spr/node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/plugin-spr/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" } }, "packages/plugin-survey-number": { diff --git a/packages/plugin-spr/README.md b/packages/plugin-spr/README.md index f85f1976..92ac66c7 100644 --- a/packages/plugin-spr/README.md +++ b/packages/plugin-spr/README.md @@ -2,7 +2,7 @@ ## Overview -This is a package built to enable self-paced reading. It supports different reading modes including single-word mask and multi-word (hide/show). This package allows you to also customize the format of the text displayed by using css. +This is a package built to enable self-paced reading trials. It supports different reading modes including single-word mask and multi-word (hide/show). This package allows you to also customize the format of the text displayed by using CSS. ## Loading @@ -24,7 +24,7 @@ import jsPsychSpr from '@jspsych-contrib/plugin-spr'; ## Compatibility -jsPsych 7.0.0 +jsPsych 8.0.0 ## Documentation diff --git a/packages/plugin-spr/package.json b/packages/plugin-spr/package.json index 26befa1d..ea16c955 100644 --- a/packages/plugin-spr/package.json +++ b/packages/plugin-spr/package.json @@ -1,7 +1,7 @@ { "name": "@jspsych-contrib/plugin-spr", "version": "0.0.1", - "description": "This is a package built to enable self paced reading", + "description": "This is a package built to enable self-paced reading trials.", "type": "module", "main": "dist/index.cjs", "exports": { @@ -37,11 +37,11 @@ }, "homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-spr", "peerDependencies": { - "jspsych": ">=7.0.0" + "jspsych": ">=8.0.0" }, "devDependencies": { - "@jspsych/config": "^2.0.0", + "@jspsych/config": "^3.0.0", "@jspsych/test-utils": "^1.0.0", - "jspsych": "^7.0.0" + "jspsych": "8.0.0" } } diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 4fe279e5..7c41535f 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -38,16 +38,22 @@ const info = { }, }, data: { - /* The representation of the structured_reading_string that was used. Combined with the mode this + /* The representation of the `structured_reading_string` that was used. Combined with the mode, this tells what exactly was displayed on the screen during each click. */ stimulus: { type: ParameterType.STRING, - Array: true, + array: true, }, /** Indicates the mode that the SPR experiment was ran using. */ mode: { type: ParameterType.INT, }, + // TODO: redocument this -> might need to change to a more structured format + /** Records the results of the SPR experiment. */ + results: { + type: ParameterType.COMPLEX, + array: true, + }, }, }; @@ -56,7 +62,7 @@ type Info = typeof info; /** * **spr** * - * This is a package built to enable self paced reading + * This is a package built to enable self-paced reading trials. * * @author Victor Zhang * @see {@link https://github.com/jspsych/jspsych-contrib/packages/plugin-spr/README.md}} @@ -90,8 +96,7 @@ class SprPlugin implements JsPsychPlugin { private endTrial() { // TODO: figure out data saving -> will need to add times and how long to make it var trial_data = { - // data1: 99, // Make sure this type and name matches the information for data1 in the data object contained within the info const. - stimlulus: this.structured_reading_string, // Make sure this type and name matches the information for data2 in the data object contained within the info const. + stimulus: this.structured_reading_string, mode: this.mode, results: this.results, }; From 39c28de01493f6d990bee90a13b0bc0e2242bd4b Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Fri, 25 Oct 2024 23:56:58 -0400 Subject: [PATCH 20/25] flesh out docs and add choices param --- packages/plugin-spr/examples/mode2.html | 3 +- packages/plugin-spr/src/index.spec.ts | 2 +- packages/plugin-spr/src/index.ts | 70 ++++++++++++++++++++----- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/packages/plugin-spr/examples/mode2.html b/packages/plugin-spr/examples/mode2.html index b49e0c46..9eaeca31 100644 --- a/packages/plugin-spr/examples/mode2.html +++ b/packages/plugin-spr/examples/mode2.html @@ -23,7 +23,8 @@ const trial = { type: jsPsychSpr, structured_reading_string: [["first and second", "second and fourth", "third"], ["fith", "sixth", "seventh"], ["eighth", "ninth", "tenth"]], - mode: 2 + mode: 2, + choices: "ALL_KEYS" }; jsPsych.run([trial]) diff --git a/packages/plugin-spr/src/index.spec.ts b/packages/plugin-spr/src/index.spec.ts index 7a7cc923..f8e8c482 100644 --- a/packages/plugin-spr/src/index.spec.ts +++ b/packages/plugin-spr/src/index.spec.ts @@ -4,7 +4,7 @@ import jsPsychSpr from "."; jest.useFakeTimers(); -describe("my plugin", () => { +describe.skip("my plugin", () => { it("should load", async () => { const { expectFinished, getHTML, getData, displayElement, jsPsych } = await startTimeline([ { diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 7c41535f..4af179b2 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -6,32 +6,71 @@ const info = { name: "spr", version: version, parameters: { - /* String input of the displayed text which will be split to create a structured_reading_string. */ + /** + * This is the string of text that will be displayed to the participant during the trial. Without any + * ^ characters, the text will be split up based on the space character. If the ^ character is used, + * the text will be split up based on the ^ character. + */ unstructured_reading_string: { type: ParameterType.STRING, default: "", }, - /* String input that explictly defines how the chunks and lines will be displayed during the SPR trial.*/ + /** + * This string acts as a structured version of the `unstructured_reading_string`, where the text is + * instead split using different elements of an array. The ^ character is not used as a delimiter + * in this string. + */ structured_reading_string: { type: ParameterType.STRING, array: true, default: [], }, - /* Mode between 1-3 that indicate the different built-in modes for how stimulus will be displayed. */ + /** + * Mode between 1-3 that indicate the different built-in modes for how stimulus will be displayed. + * + * - 1: The text will be displayed blank initially, with each new chunk revealed causing the previous + * chunk to be blanked out. + * + * - 2: The text will be displayed blank initially, with each new chunk revealed staying revealed. + * + * - 3: The text will be displayed chunk-by-chunk, with each new chunk replacing the previous chunk. + */ mode: { type: ParameterType.INT, default: 1, }, - /* Indicates how many words will be included with each chunk when splitting the unstructured_reading_string. */ + /** + * Indicates how many words will be included with each chunk when splitting the + * `unstructured_reading_string`. + */ chunk_size: { type: ParameterType.INT, default: 1, }, - /* Indicates how many chunks will be included with each chunk when splitting the unstructured_reading_string. */ + /** + * Indicates how many chunks will be included with each chunk when splitting the + * `unstructured_reading_string`. + * + * !! Unknown if we'll need this !! + */ line_size: { type: ParameterType.INT, default: 1, }, + /** + * This array contains the key(s) that the participant is allowed to press in order to advance + * to the next chunk. Keys should be specified as characters (e.g., `'a'`, `'q'`, `' '`, `'Enter'`, `'ArrowDown'`) - see + * {@link https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values this page} + * and + * {@link https://www.freecodecamp.org/news/javascript-keycode-list-keypress-event-key-codes/ this page (event.key column)} + * for more examples. Any key presses that are not listed in the + * array will be ignored. The value of `"ALL_KEYS"` means that all keys will be accepted as valid responses. + */ + choices: { + type: ParameterType.KEYS, + default: [" "], + }, + /** To be removed */ delimiting: { type: ParameterType.BOOL, default: false, @@ -74,7 +113,7 @@ class SprPlugin implements JsPsychPlugin { private current_display_string: string[] = []; // mode 1-2: use this to save iterations private displayed = false; // mode 3 private structured_reading_string: string[] | string[][] = []; - private mode; + private mode: 1 | 2 | 3; private results = []; private startTime; @@ -90,7 +129,7 @@ class SprPlugin implements JsPsychPlugin { document.querySelector("p")!.innerHTML = this.generateBlank( this.structured_reading_string[this.index] ); - else document.querySelector("p")!.innerHTML = this.updateDisplayString(); + else document.querySelector("p")!.innerHTML = this.updateDisplayString(null); // update this, passing null for TS } private endTrial() { @@ -129,7 +168,7 @@ class SprPlugin implements JsPsychPlugin { this.jsPsych.pluginAPI.getKeyboardResponse({ callback_function: (info) => this.onSpacebarPress(info), - valid_responses: [" "], + valid_responses: trial.choices, rt_method: "performance", persist: true, allow_held_key: false, @@ -193,10 +232,10 @@ class SprPlugin implements JsPsychPlugin { } } - newHtml = `

${this.updateDisplayString()}

`; + newHtml = `

${this.updateDisplayString(info)}

`; } else if (this.mode === 3) { // might want to include incrementation here for consistency - newHtml = this.updateDisplayString(); + newHtml = this.updateDisplayString(info); } // need to handle a keyboard press element where records how long until press a key @@ -206,7 +245,7 @@ class SprPlugin implements JsPsychPlugin { } // This helper method assists with mode 1 and 2 to keep efficency when updating indicies and the scren - private updateDisplayString(): string { + private updateDisplayString(info?: any): string { if (this.mode === 1 || this.mode === 2) { if (this.inner_index === -1) { // need to update new display string @@ -247,7 +286,8 @@ class SprPlugin implements JsPsychPlugin { this.results[this.results.length - 1].push( this.structured_reading_string[this.index][this.inner_index], - this.getElapsed() + this.getElapsed(), + info.key ); // this.results[this.results.length-1].push([this.getElapsed(), this.structured_reading_string[this.index][this.inner_index]]); } @@ -267,7 +307,7 @@ class SprPlugin implements JsPsychPlugin { newHtml = "

" + newHtml + "

"; this.displayed = true; - this.results.push([this.getElapsed(), newHtml]); // pushes new list with time passed (time looking at blank) + this.results.push([this.getElapsed(), newHtml, info.key]); // pushes new list with time passed (time looking at blank) } else { this.index++; this.displayed = false; @@ -281,7 +321,7 @@ class SprPlugin implements JsPsychPlugin { "

"; } - this.results[this.results.length - 1].push(this.getElapsed()); // pushes second time spent looking at word + this.results[this.results.length - 1].push(this.getElapsed(), info.key); // pushes second time spent looking at word } return newHtml; } @@ -319,6 +359,8 @@ class SprPlugin implements JsPsychPlugin { return res; } + // TODO: turn this into performance.now() for more accurate results + // TODO: also, will need to subtract the time from the previous time for data private getElapsed() { return Date.now() - this.startTime; } From 23e839bef4029476f6ae017216af8373701c003f Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Sat, 26 Oct 2024 00:10:35 -0400 Subject: [PATCH 21/25] remove delimiter param, added logic to handle it instead --- packages/plugin-spr/examples/delimiter.html | 3 +-- packages/plugin-spr/src/index.ts | 25 +++++---------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/packages/plugin-spr/examples/delimiter.html b/packages/plugin-spr/examples/delimiter.html index 02c84a0e..3db6323c 100644 --- a/packages/plugin-spr/examples/delimiter.html +++ b/packages/plugin-spr/examples/delimiter.html @@ -21,9 +21,8 @@ const trial = { type: jsPsychSpr, - unstructured_reading_string: "this %is the %reading string and it is %super super long, i wonder %what will be %coming next.", + unstructured_reading_string: "this ^is the ^reading string and it is ^super super long, i wonder ^what will be ^coming next.", mode: 1, - delimiting: true, }; jsPsych.run([trial]) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 4af179b2..07905200 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -70,11 +70,6 @@ const info = { type: ParameterType.KEYS, default: [" "], }, - /** To be removed */ - delimiting: { - type: ParameterType.BOOL, - default: false, - }, }, data: { /* The representation of the `structured_reading_string` that was used. Combined with the mode, this @@ -149,22 +144,15 @@ class SprPlugin implements JsPsychPlugin { else throw console.error("Mode declared incorrectly, must be between 1 and 3."); // creates inital reading string -> TODO: should instead use mode to determine - if (trial.structured_reading_string.length > 0) + if (trial.structured_reading_string.length > 0) { this.structured_reading_string = trial.structured_reading_string; - else if (trial.delimiting) { - this.structured_reading_string = this.createReadingString( - trial.unstructured_reading_string, - trial.chunk_size, - trial.line_size, - "%" - ); - console.log("delimiting is true", this.structured_reading_string); - } else + } else { this.structured_reading_string = this.createReadingString( trial.unstructured_reading_string, trial.chunk_size, trial.line_size ); + } this.jsPsych.pluginAPI.getKeyboardResponse({ callback_function: (info) => this.onSpacebarPress(info), @@ -181,11 +169,10 @@ class SprPlugin implements JsPsychPlugin { private createReadingString( unstructured_reading_string: string, chunk_size: number, - line_size: number, - delimiter?: string + line_size: number ): string[] { - const split_text = delimiter - ? unstructured_reading_string.split(delimiter) + const split_text = unstructured_reading_string.includes("^") + ? unstructured_reading_string.split("^") : unstructured_reading_string.split(" "); const res = []; From bcfa327855bb3062d8d13a4028baff4072723457 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Fri, 1 Nov 2024 13:23:19 -0400 Subject: [PATCH 22/25] Finished up majority of data saving - issues with extra and keypress not captured correctly --- packages/plugin-spr/src/index.ts | 47 ++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 07905200..9959122b 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -120,11 +120,11 @@ class SprPlugin implements JsPsychPlugin { var html = `

`; display_element.innerHTML = html; - if (this.mode === 3) - document.querySelector("p")!.innerHTML = this.generateBlank( - this.structured_reading_string[this.index] - ); - else document.querySelector("p")!.innerHTML = this.updateDisplayString(null); // update this, passing null for TS + if (this.mode === 3) { + const blank = this.generateBlank(this.structured_reading_string[this.index]); + document.querySelector("p")!.innerHTML = blank; + this.addDataPoint(blank, this.index); + } else document.querySelector("p")!.innerHTML = this.updateDisplayString(null); // update this, passing null for TS } private endTrial() { @@ -162,7 +162,7 @@ class SprPlugin implements JsPsychPlugin { allow_held_key: false, }); - this.startTime = Date.now(); + this.startTime = performance.now(); } // TODO: create a method that takes an entire string and uses a list of parameters to generate a "structured reading string" @@ -237,7 +237,6 @@ class SprPlugin implements JsPsychPlugin { if (this.inner_index === -1) { // need to update new display string const new_display_string: string[] = []; - const curr_segment = this.structured_reading_string[this.index]; for (var i = 0; i < curr_segment.length; i++) { @@ -249,7 +248,8 @@ class SprPlugin implements JsPsychPlugin { } this.current_display_string = new_display_string; - this.results.push([this.getElapsed()]); + // this.results.push([this.getElapsed()]); + this.addDataPoint(this.current_display_string.join(" "), this.index); } else { if (this.mode === 1 && this.inner_index > 0) { this.current_display_string[this.inner_index - 1] = @@ -257,7 +257,6 @@ class SprPlugin implements JsPsychPlugin { this.generateBlank(this.structured_reading_string[this.index][this.inner_index - 1]) + "
"; } else if (this.mode === 2 && this.inner_index > 0) { - console.log("enters modifier", this.current_display_string); // changes classifier this.current_display_string[this.inner_index - 1] = "" + @@ -271,11 +270,12 @@ class SprPlugin implements JsPsychPlugin { this.structured_reading_string[this.index][this.inner_index] + ""; - this.results[this.results.length - 1].push( - this.structured_reading_string[this.index][this.inner_index], - this.getElapsed(), - info.key - ); + this.addDataPoint(this.current_display_string.join(" "), this.index); + // this.results[this.results.length - 1].push( + // this.structured_reading_string[this.index][this.inner_index], + // this.getElapsed(), + // info.key + // ); // this.results[this.results.length-1].push([this.getElapsed(), this.structured_reading_string[this.index][this.inner_index]]); } } else if (this.mode == 3) { @@ -294,7 +294,9 @@ class SprPlugin implements JsPsychPlugin { newHtml = "

" + newHtml + "

"; this.displayed = true; - this.results.push([this.getElapsed(), newHtml, info.key]); // pushes new list with time passed (time looking at blank) + this.addDataPoint(newHtml, this.index); + console.log("this is info.key:", info.key, "this is new Html", newHtml); + // this.results.push([this.getElapsed(), newHtml, info.key]); // pushes new list with time passed (time looking at blank) } else { this.index++; this.displayed = false; @@ -308,7 +310,8 @@ class SprPlugin implements JsPsychPlugin { "

"; } - this.results[this.results.length - 1].push(this.getElapsed(), info.key); // pushes second time spent looking at word + this.addDataPoint(newHtml, this.index); + // this.results[this.results.length - 1].push(this.getElapsed(), info.key); // pushes second time spent looking at word } return newHtml; } @@ -346,10 +349,14 @@ class SprPlugin implements JsPsychPlugin { return res; } - // TODO: turn this into performance.now() for more accurate results - // TODO: also, will need to subtract the time from the previous time for data - private getElapsed() { - return Date.now() - this.startTime; + private addDataPoint(stimulus: string, line_number: number) { + const res = { + time_elapsed: Math.round(performance.now() - this.startTime), + stimulus: stimulus, + line_number: line_number, + }; + + this.results.push(res); } } From ca8830e68ef122c8516172ba0dcad9f901c14d30 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Sat, 2 Nov 2024 10:05:32 -0400 Subject: [PATCH 23/25] Key press is working, time elapsed since last is working, only now is weird case at begining and end --- packages/plugin-spr/src/index.ts | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 9959122b..5af9e84a 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -124,7 +124,7 @@ class SprPlugin implements JsPsychPlugin { const blank = this.generateBlank(this.structured_reading_string[this.index]); document.querySelector("p")!.innerHTML = blank; this.addDataPoint(blank, this.index); - } else document.querySelector("p")!.innerHTML = this.updateDisplayString(null); // update this, passing null for TS + } else document.querySelector("p")!.innerHTML = this.updateDisplayString(); // update this, passing null for TS } private endTrial() { @@ -155,7 +155,7 @@ class SprPlugin implements JsPsychPlugin { } this.jsPsych.pluginAPI.getKeyboardResponse({ - callback_function: (info) => this.onSpacebarPress(info), + callback_function: (info) => this.onValidKeyPress(info), valid_responses: trial.choices, rt_method: "performance", persist: true, @@ -200,7 +200,7 @@ class SprPlugin implements JsPsychPlugin { return res; } - private onSpacebarPress(info?: any) { + private onValidKeyPress(info?: any) { var newHtml = ""; // handles logic on whether to display blank or show text using boolean/index @@ -232,7 +232,7 @@ class SprPlugin implements JsPsychPlugin { } // This helper method assists with mode 1 and 2 to keep efficency when updating indicies and the scren - private updateDisplayString(info?: any): string { + private updateDisplayString(info: any = {}): string { if (this.mode === 1 || this.mode === 2) { if (this.inner_index === -1) { // need to update new display string @@ -248,8 +248,7 @@ class SprPlugin implements JsPsychPlugin { } this.current_display_string = new_display_string; - // this.results.push([this.getElapsed()]); - this.addDataPoint(this.current_display_string.join(" "), this.index); + this.addDataPoint(this.current_display_string.join(" "), this.index, info.key); } else { if (this.mode === 1 && this.inner_index > 0) { this.current_display_string[this.inner_index - 1] = @@ -270,7 +269,7 @@ class SprPlugin implements JsPsychPlugin { this.structured_reading_string[this.index][this.inner_index] + "
"; - this.addDataPoint(this.current_display_string.join(" "), this.index); + this.addDataPoint(this.current_display_string.join(" "), this.index, info.key); // this.results[this.results.length - 1].push( // this.structured_reading_string[this.index][this.inner_index], // this.getElapsed(), @@ -294,7 +293,7 @@ class SprPlugin implements JsPsychPlugin { newHtml = "

" + newHtml + "

"; this.displayed = true; - this.addDataPoint(newHtml, this.index); + this.addDataPoint(newHtml, this.index, info.key); console.log("this is info.key:", info.key, "this is new Html", newHtml); // this.results.push([this.getElapsed(), newHtml, info.key]); // pushes new list with time passed (time looking at blank) } else { @@ -310,7 +309,7 @@ class SprPlugin implements JsPsychPlugin { "

"; } - this.addDataPoint(newHtml, this.index); + this.addDataPoint(newHtml, this.index, info.key); // this.results[this.results.length - 1].push(this.getElapsed(), info.key); // pushes second time spent looking at word } return newHtml; @@ -349,13 +348,24 @@ class SprPlugin implements JsPsychPlugin { return res; } - private addDataPoint(stimulus: string, line_number: number) { + private getTimeElapsed() { + const prev = this.startTime; + const now = performance.now(); + this.startTime = now; + return Math.round(now - prev); + } + + private addDataPoint(stimulus: string, line_number: number, key?: string) { const res = { - time_elapsed: Math.round(performance.now() - this.startTime), + time_elapsed: this.getTimeElapsed(), stimulus: stimulus, line_number: line_number, }; + if (key) { + res["key_pressed"] = key; // Add key_pressed if key exists + } + this.results.push(res); } } From 57bb8f23f22500eb6b9f3d6302be77080ce6e3b0 Mon Sep 17 00:00:00 2001 From: jade <101148768+jadeddelta@users.noreply.github.com> Date: Sun, 3 Nov 2024 14:05:07 -0500 Subject: [PATCH 24/25] document data types, fix stimulus data issue --- packages/plugin-spr/src/index.ts | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 5af9e84a..300246b1 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -9,7 +9,7 @@ const info = { /** * This is the string of text that will be displayed to the participant during the trial. Without any * ^ characters, the text will be split up based on the space character. If the ^ character is used, - * the text will be split up based on the ^ character. + * the text will be split up based on the space character. */ unstructured_reading_string: { type: ParameterType.STRING, @@ -82,11 +82,28 @@ const info = { mode: { type: ParameterType.INT, }, - // TODO: redocument this -> might need to change to a more structured format /** Records the results of the SPR experiment. */ results: { type: ParameterType.COMPLEX, array: true, + nested: { + /** The response time in milliseconds from when the stimulus was displayed to when a valid key was pressed. */ + rt: { + type: ParameterType.INT, + }, + /** The stimulus that was displayed to the participant. */ + stimulus: { + type: ParameterType.STRING, + }, + /** The line number of the stimulus that was displayed. */ + line_number: { + type: ParameterType.INT, + }, + /** The key that was pressed by the participant. */ + key_pressed: { + type: ParameterType.STRING, + }, + }, }, }, }; @@ -128,9 +145,8 @@ class SprPlugin implements JsPsychPlugin { } private endTrial() { - // TODO: figure out data saving -> will need to add times and how long to make it var trial_data = { - stimulus: this.structured_reading_string, + stimulus: this.structured_reading_string.flat(), mode: this.mode, results: this.results, }; @@ -357,13 +373,16 @@ class SprPlugin implements JsPsychPlugin { private addDataPoint(stimulus: string, line_number: number, key?: string) { const res = { - time_elapsed: this.getTimeElapsed(), + rt: this.getTimeElapsed(), stimulus: stimulus, line_number: line_number, }; + // Add key_pressed if key exists if (key) { - res["key_pressed"] = key; // Add key_pressed if key exists + res["key_pressed"] = key; + } else { + res["key_pressed"] = null; } this.results.push(res); From 241aac94bd7647d8b8089d46bcf86cdeb4970b07 Mon Sep 17 00:00:00 2001 From: vzhang03 Date: Sun, 3 Nov 2024 23:21:54 -0500 Subject: [PATCH 25/25] Fixed mode three, removed unneccessary comments and slight logic changes --- packages/plugin-spr/src/index.ts | 53 ++++++++++---------------------- 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/packages/plugin-spr/src/index.ts b/packages/plugin-spr/src/index.ts index 300246b1..c23a2575 100644 --- a/packages/plugin-spr/src/index.ts +++ b/packages/plugin-spr/src/index.ts @@ -123,7 +123,6 @@ class SprPlugin implements JsPsychPlugin { private index: number = 0; private inner_index: number = -1; // mode 1-2: initialized so that not shown if has an inner_index private current_display_string: string[] = []; // mode 1-2: use this to save iterations - private displayed = false; // mode 3 private structured_reading_string: string[] | string[][] = []; private mode: 1 | 2 | 3; private results = []; @@ -141,6 +140,7 @@ class SprPlugin implements JsPsychPlugin { const blank = this.generateBlank(this.structured_reading_string[this.index]); document.querySelector("p")!.innerHTML = blank; this.addDataPoint(blank, this.index); + this.index = -1; // this initializes mode in way that allows to start at 0, might not be best way to do it } else document.querySelector("p")!.innerHTML = this.updateDisplayString(); // update this, passing null for TS } @@ -238,6 +238,13 @@ class SprPlugin implements JsPsychPlugin { newHtml = `

${this.updateDisplayString(info)}

`; } else if (this.mode === 3) { // might want to include incrementation here for consistency + this.index++; + + if (this.index >= this.structured_reading_string.length) { + this.endTrial(); + return; + } + newHtml = this.updateDisplayString(info); } // need to handle a keyboard press element where records how long until press a key @@ -286,48 +293,22 @@ class SprPlugin implements JsPsychPlugin { "
"; this.addDataPoint(this.current_display_string.join(" "), this.index, info.key); - // this.results[this.results.length - 1].push( - // this.structured_reading_string[this.index][this.inner_index], - // this.getElapsed(), - // info.key - // ); - // this.results[this.results.length-1].push([this.getElapsed(), this.structured_reading_string[this.index][this.inner_index]]); } } else if (this.mode == 3) { var newHtml = ""; - if (!this.displayed) { - // accounts for bad user input (not necessary) and could move it up to input - if (typeof this.structured_reading_string[this.index] === "string") - newHtml = this.structured_reading_string[this.index] as string; - else { - for (const c of this.structured_reading_string[this.index]) { - newHtml += c + " "; - } + // accounts for bad user input (not necessary) and could move it up to input + if (typeof this.structured_reading_string[this.index] === "string") + newHtml = this.structured_reading_string[this.index] as string; + else { + for (const c of this.structured_reading_string[this.index]) { + newHtml += c + " "; } + } - newHtml = "

" + newHtml + "

"; - this.displayed = true; - - this.addDataPoint(newHtml, this.index, info.key); - console.log("this is info.key:", info.key, "this is new Html", newHtml); - // this.results.push([this.getElapsed(), newHtml, info.key]); // pushes new list with time passed (time looking at blank) - } else { - this.index++; - this.displayed = false; - - if (this.index >= this.structured_reading_string.length) { - this.endTrial(); - } else { - newHtml = - "

" + - this.generateBlank(this.structured_reading_string[this.index]) + - "

"; - } + newHtml = "

" + newHtml + "

"; - this.addDataPoint(newHtml, this.index, info.key); - // this.results[this.results.length - 1].push(this.getElapsed(), info.key); // pushes second time spent looking at word - } + this.addDataPoint(newHtml, this.index, info.key); return newHtml; }