Skip to content
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
47d57f0
delete braces from root package.json
cherriechang Aug 12, 2024
1c5f826
add rollup plugin for building citation
cherriechang Aug 27, 2024
bbd09e2
move citation rollup plugin to config folder
cherriechang Aug 27, 2024
59ce0b3
very broken :(
jodeleeuw Aug 31, 2024
7ca68ea
Merge branch 'main' into add-citation-module
jodeleeuw Sep 11, 2024
62d3427
This fixes build errors, but warnings are still present. Adds rollup/…
jodeleeuw Sep 11, 2024
c8ad1db
Merge branch 'update-config-dependencies' into add-citation-module
bjoluc Sep 11, 2024
e7abded
Update package.json
bjoluc Sep 11, 2024
fd07de6
Merge branch 'update-config-dependencies' into add-citation-module
bjoluc Sep 11, 2024
e2039c4
pulling bjorn fixes
cherriechang Sep 12, 2024
d2ae26c
pulling bjorn fixes
cherriechang Sep 12, 2024
715ed2a
pull bjorn fixes
cherriechang Sep 12, 2024
7963fdc
move additionalPlugin out of outputOptions
cherriechang Sep 12, 2024
bab33ea
fix: error handling chain in building citations
cherriechang Sep 12, 2024
909cb9a
fix build citation rollup plugin to actually generate citation
cherriechang Sep 13, 2024
bceacab
i really hate this library
cherriechang Sep 16, 2024
a2e7918
fix browser tool for citations
cherriechang Sep 19, 2024
8bbf9b7
move citation build logic from rollup to esbuild
cherriechang Oct 23, 2024
00d60fb
remove generateCitation from node scripts and directly call
cherriechang Oct 23, 2024
1365dcc
just not replacing the var
cherriechang Oct 23, 2024
81fd767
fix some config options
jodeleeuw Oct 23, 2024
eace9bf
merge with josh
cherriechang Oct 23, 2024
ef89a80
define works now
cherriechang Oct 23, 2024
99392b4
citation stuff done
cherriechang Oct 30, 2024
2cdf231
clean up dependencies
cherriechang Oct 30, 2024
d02f625
delete console logs
cherriechang Oct 30, 2024
9d5215e
clean up errors
cherriechang Oct 30, 2024
f0bc8ae
add jest tests for citation tool
cherriechang Nov 1, 2024
5753468
update plugins index.ts
cherriechang Nov 1, 2024
b63d8b6
fix double quotes in plugin src to single quotes
cherriechang Dec 6, 2024
df588e9
change prettier to allow single quotes
cherriechang Dec 6, 2024
a28ca04
localize prettier to apply only to lines
cherriechang Dec 6, 2024
1b08438
citation documentation + delete CITATION.cff files
cherriechang Dec 6, 2024
5e878d3
update getCitations() to always print jsPsych + no duplicates; update…
cherriechang Dec 9, 2024
e42ba99
modifiy citation test to check for built version
jodeleeuw Dec 17, 2024
f2d1a03
fix citation logic
cherriechang Dec 18, 2024
466b44c
Merge branch 'add-citation-module' of github.com:jspsych/jsPsych into…
cherriechang Dec 18, 2024
5b64a47
change citations test to include default jspsych citation
cherriechang Dec 18, 2024
81e7473
add prettier-ignore to jspsych.ts
cherriechang Dec 18, 2024
909ac91
update docs
cherriechang Dec 18, 2024
ca6c4eb
add docstring in JsPsych.ts for getCitations()
cherriechang Dec 18, 2024
90ee2c5
add prettier-ignore for IIFE builds
cherriechang Dec 18, 2024
f364931
change contributing.md
cherriechang Dec 18, 2024
f8e454e
delete console spies and mocks
cherriechang Dec 18, 2024
8ffe64a
add changeset
cherriechang Dec 18, 2024
3948fdc
add changeset
cherriechang Dec 18, 2024
5611b3c
remove the overrides
jodeleeuw Dec 18, 2024
4834c96
add getCitations() doc in jspsych.md under reference; delete extra ch…
cherriechang Dec 18, 2024
faf6cce
Merge branch 'add-citation-module' of github.com:jspsych/jsPsych into…
cherriechang Dec 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ coverage/
dist.zip
packages/jspsych/README.md
.turbo
.env
14 changes: 12 additions & 2 deletions docs/about/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,20 @@ jsPsych was created by [Josh de Leeuw](https://www.vassar.edu/faculty/jdeleeuw).

If you use this library in academic work, the preferred citation is:

de Leeuw, J.R., Gilbert, R.A., & Luchterhandt, B. (2023). jsPsych: Enabling an open-source collaborative ecosystem of behavioral experiments. *Journal of Open Source Software*, *8*(85), 5351, [https://joss.theoj.org/papers/10.21105/joss.05351](https://joss.theoj.org/papers/10.21105/joss.05351).
> de Leeuw, J.R., Gilbert, R.A., & Luchterhandt, B. (2023). jsPsych: Enabling an open-source collaborative ecosystem of behavioral experiments. *Journal of Open Source Software*, *8*(85), 5351, [https://joss.theoj.org/papers/10.21105/joss.05351](https://joss.theoj.org/papers/10.21105/joss.05351).

This paper is an updated description of jsPsych and includes all current core team members. It replaces the earlier paper that described jsPsych:

de Leeuw, J.R. (2015). jsPsych: A JavaScript library for creating behavioral experiments in a Web browser. *Behavior Research Methods*, _47_(1), 1-12. doi:[10.3758/s13428-014-0458-y](http://link.springer.com/article/10.3758%2Fs13428-014-0458-y)
> de Leeuw, J.R. (2015). jsPsych: A JavaScript library for creating behavioral experiments in a Web browser. *Behavior Research Methods*, _47_(1), 1-12. doi:[10.3758/s13428-014-0458-y](http://link.springer.com/article/10.3758%2Fs13428-014-0458-y)

Citations help us demonstrate that this library is used and valued, which allows us to continue working on it.

#### Citation tool for third-party plugins/extensions

jsPsych is an open-source, collaborative ecosystem, and many of the plugins/extensions you end up using may be contributed by third-party developers! We want to make sure they get recognition for their good work, so we made a command-line citation tool that you should use to cite this library and the plugins/extensions used in your experiment. You can see this tool in action by following these steps:

1. Launch a jsPsych experiment in your browser
2. Open up the browser console using Ctrl + ⇧ + J (Windows) or ⌘ + ⌥ + J (Mac)
3. Type `jsPsych.getCitations([], "apa")`

This should print the APA format citation for the jsPsych library, which you can then copy and paste into your working document. You can type any number of plugins/extensions by name in the array `[ ]` to generate a list of citations, e.g. `jsPsych.getCitations([jsPsychHtmlKeyboardResponse, jsPsychMouseTrackingExtension], "apa")`. We currently support APA formatting (`"apa"`) and BibTex formatting (`"bibtex"`).
2 changes: 2 additions & 0 deletions docs/developers/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ We welcome contributions of any scope. Before we can merge changes into the main

* **An example file should be included if applicable.** If you are contributing a new feature, new plugin, or new extension, or contributing a modification that changes the behavior of the library in some important way, consider adding an example file to the `/examples` folder in the repository.

* **We strongly encourage including a file containing citation information.** This file should be named `CITATION.cff` and placed at the root of your repository. This allows people who use your plugin/extension in their code to easily cite your work by calling `jsPsych.getCitations([<yourPlugin>])` from their command line. More information on `.cff` files can be found [here](https://citation-file-format.github.io/).

* **A changeset must be included in the pull request**. We use [changesets](https://github.com/atlassian/changesets/blob/main/docs/adding-a-changeset.md) to generate new releases and their corresponding release notes. [This is a good overview of changesets](https://github.com/atlassian/changesets/blob/main/docs/adding-a-changeset.md) that explains how to add one to your pull request. Feel free to ask for help with this!

* **Update the contributors.md file**. If you are a first time contributor to jsPsych please add your name to our [contributors file](https://github.com/jspsych/jsPsych/blob/main/contributors.md). And thanks!
Expand Down
8,285 changes: 4,704 additions & 3,581 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"devDependencies": {
"@changesets/changelog-github": "^0.4.7",
"@changesets/cli": "^2.25.2",
"@jspsych/config": "^1.3.2",
"husky": "^8.0.2",
"@jspsych/config": "^3.0.0",
"husky": "^8.0.3",
"import-sort-style-module": "^6.0.0",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1",
Expand Down
94 changes: 94 additions & 0 deletions packages/config/generateCitations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import "@citation-js/plugin-bibtex";
import "@citation-js/plugin-software-formats";
import "@citation-js/plugin-csl";

import fs from "node:fs";
import path from "node:path";

import { Cite } from "@citation-js/core";
import appRootPath from "app-root-path";
import yaml from "yaml";

/**
* Generate citation data from CITATION.cff file
* Currently supported formats: APA, BibTeX
*
* @returns {Object} - Object containing APA and BibTeX formatted citation data
*/
export default function generateCitations() {
let preferredCitation = false;

// Try to find CITATION.cff file and look for preferred-citation
const citationCff = (() => {
let rawCff;
const getCff = (path) => {
rawCff = fs.readFileSync(path, "utf-8").toString();
const cffData = yaml.parse(rawCff);
if (cffData["preferred-citation"]) {
preferredCitation = true;
}
return yaml.stringify(rawCff);
};

try {
// look for CITATION.cff in the current directory
return getCff("./CITATION.cff");
} catch (error) {
try {
// look for CITATION.cff in the root of the repository
return getCff(path.join(appRootPath.path, "CITATION.cff"));
} catch (error) {
console.warn(
`No CITATION.cff file found: ${error.message}. If you would like to include a citation, please create a CITATION.cff file in the root of your repository.`
);
return null;
}
}
})();

if (!citationCff) {
return { apa: "", bibtex: "" };
}

// Convert CITATION.cff to APA string
const citationApa = (() => {
try {
const apaCite = new Cite(citationCff);
apaCite["data"] = preferredCitation ? apaCite["data"].slice(1) : apaCite["data"];
const citationApa = apaCite.format("bibliography", {
format: "text",
template: "apa",
lang: "en-us",
});
return citationApa;
} catch (error) {
console.log(`Error converting CITATION.cff to APA string: ${error.message}`);
return "";
}
})();

// Convert CITATION.cff to BibTeX string
const citationBibtex = (() => {
try {
const bibtexCite = new Cite(citationCff);
bibtexCite["data"] = preferredCitation ? bibtexCite["data"].slice(1) : bibtexCite["data"];
const citationBibtex = bibtexCite.format("bibtex", {
format: "text",
template: "bibtex",
lang: "en-us",
});
return citationBibtex;
} catch (error) {
console.log(`Error converting CITATION.cff to BibTeX string: ${error.message}`);
return null;
}
})();

// Return formatted citation data
const citationData = {
apa: citationApa.replace(/\n/g, " "),
bibtex: citationBibtex.replace(/\n/g, " "),
};

return citationData;
}
16 changes: 15 additions & 1 deletion packages/config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,18 @@
},
"homepage": "https://www.jspsych.org/latest/developers/configuration",
"dependencies": {
"@citation-js/core": "^0.7.14",
"@citation-js/plugin-bibtex": "^0.7.14",
"@citation-js/plugin-csl": "^0.7.14",
"@citation-js/plugin-software-formats": "^0.6.1",
"@rollup/plugin-commonjs": "26.0.1",
"@rollup/plugin-node-resolve": "15.2.3",
"@rollup/plugin-replace": "^6.0.1",
"@sucrase/jest-plugin": "3.0.0",
"@types/gulp": "4.0.17",
"@types/jest": "29.5.8",
"alias-hq": "6.2.4",
"app-root-path": "^3.1.0",
"canvas": "^2.11.2",
"esbuild": "0.23.1",
"gulp": "5.0.0",
Expand All @@ -55,9 +61,17 @@
"rollup": "4.21.2",
"rollup-plugin-dts": "6.1.1",
"rollup-plugin-esbuild": "6.1.1",
"rollup-plugin-modify": "^3.0.0",
"rollup-plugin-node-externals": "7.1.3",
"sucrase": "3.34.0",
"tslib": "2.6.2",
"typescript": "^5.2.2"
"typescript": "^5.2.2",
"yaml": "^2.5.1"
},
"overrides": {
"alias-hq": {
"jscodeshift": "0.16.1",
"inquirer": "10.1.6"
}
}
}
23 changes: 21 additions & 2 deletions packages/config/rollup.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import resolve from "@rollup/plugin-node-resolve";
import { defineConfig } from "rollup";
import dts from "rollup-plugin-dts";
import esbuild from "rollup-plugin-esbuild";
import modify from "rollup-plugin-modify";
import externals from "rollup-plugin-node-externals";
import ts from "typescript";

import generateCitations from "./generateCitations.js";

const getTsCompilerOptions = () => {
const cwd = process.cwd();
return ts.parseJsonConfigFileContent(
Expand Down Expand Up @@ -38,6 +41,8 @@ const makeConfig = ({
...outputOptions,
};

const citationData = generateCitations();

/** @type{import("rollup-plugin-esbuild").Options} */
const esBuildPluginOptions = {
loaders: { ".json": "json" },
Expand Down Expand Up @@ -71,6 +76,11 @@ const makeConfig = ({
input,
plugins: [
externals(),
modify({
// prettier-ignore
find: /'__CITATIONS__'/g,
replace: JSON.stringify(citationData, null, 2),
}),
esbuild({ ...esBuildPluginOptions, target: "node18" }),
commonjs(commonjsPluginOptions),
],
Expand All @@ -96,6 +106,10 @@ const makeConfig = ({
input,
plugins: [
externals({ deps: false }),
modify({
find: /'__CITATIONS__'/g,
replace: JSON.stringify(citationData, null, 2),
}),
resolve({ preferBuiltins: false }),
esbuild({ ...esBuildPluginOptions, target: "esnext" }),
commonjs(commonjsPluginOptions),
Expand All @@ -115,6 +129,10 @@ const makeConfig = ({
input,
plugins: [
externals({ deps: false }),
modify({
find: /'__CITATIONS__'/g,
replace: JSON.stringify(citationData, null, 2),
}),
resolve({ preferBuiltins: false }),
esbuild({ ...esBuildPluginOptions, target: "es2015", minify: true }),
commonjs(commonjsPluginOptions),
Expand Down Expand Up @@ -164,8 +182,9 @@ export const makeCoreRollupConfig = () =>
/**
* Returns the rollup configuration for Node.js-only packages
*/
export const makeNodeRollupConfig = () =>
makeConfig({
export const makeNodeRollupConfig = () => {
return makeConfig({
globalOptions: { external: ["jspsych"] },
isNodeOnlyBuild: true,
});
};
2 changes: 2 additions & 0 deletions packages/extension-mouse-tracking/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ class MouseTrackingExtension implements JsPsychExtension {
},
},
},
// prettier-ignore
citations: '__CITATIONS__',
};

constructor(private jsPsych: JsPsych) {}
Expand Down
2 changes: 2 additions & 0 deletions packages/extension-record-video/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class RecordVideoExtension implements JsPsychExtension {
type: ParameterType.STRING,
},
},
// prettier-ignore
citations: '__CITATIONS__',
};

constructor(private jsPsych: JsPsych) {
Expand Down
2 changes: 2 additions & 0 deletions packages/extension-webgazer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class WebGazerExtension implements JsPsychExtension {
},
},
},
// prettier-ignore
citations: '__CITATIONS__',
};

constructor(private jsPsych: JsPsych) {}
Expand Down
2 changes: 1 addition & 1 deletion packages/jspsych/src/ExtensionManager.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Class } from "type-fest";

import { TestExtension } from "../tests/extensions/test-extension";
import { TestExtension } from "../tests/extensions/TestExtension";
import { ExtensionManager, ExtensionManagerDependencies } from "./ExtensionManager";
import { JsPsych } from "./JsPsych";
import { JsPsychExtension } from "./modules/extensions";
Expand Down
38 changes: 38 additions & 0 deletions packages/jspsych/src/JsPsych.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import autoBind from "auto-bind";
// To work with citations
import { Class } from "type-fest";

import { version } from "../package.json";
import { ExtensionManager, ExtensionManagerDependencies } from "./ExtensionManager";
import { JsPsychData, JsPsychDataDependencies } from "./modules/data";
import { JsPsychExtension } from "./modules/extensions";
import { PluginAPI, createJointPluginAPIObject } from "./modules/plugin-api";
import { JsPsychPlugin } from "./modules/plugins";
import * as randomization from "./modules/randomization";
import * as turk from "./modules/turk";
import * as utils from "./modules/utils";
Expand Down Expand Up @@ -257,6 +261,40 @@ export class JsPsych {
return this.timeline?.description.timeline;
}

getCitations(
plugins: Array<Class<JsPsychPlugin<any>> | Class<JsPsychExtension>> = [],
format: "apa" | "bibtex" = "apa"
) {
const formatOptions = ["apa", "bibtex"];
// prettier-ignore
const jsPsychCitations: any = '__CITATIONS__';
format = format.toLowerCase() as "apa" | "bibtex";
// Check if plugins is an array
if (!Array.isArray(plugins)) {
throw new Error("Expected array of plugins/extensions");
}
// Check if format is supported
else if (!formatOptions.includes(format)) {
throw new Error("Unsupported citation format");
}
// Print citations
else {
const jsPsychCitation = jsPsychCitations[format];
const citationSet = new Set([jsPsychCitation]);

for (const plugin of plugins) {
try {
const pluginCitation = plugin["info"].citations[format];
citationSet.add(pluginCitation);
} catch {
console.error(`${plugin} does not have citation in ${format} format.`);
}
}
const citationList = Array.from(citationSet).join("\n");
return citationList;
}
}

get extensions() {
return this.extensionManager?.extensions ?? {};
}
Expand Down
1 change: 1 addition & 0 deletions packages/jspsych/src/modules/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface JsPsychExtensionInfo {
name: string;
version?: string;
data?: ParameterInfos;
citations?: Record<string, string> | string;
}

export interface JsPsychExtension {
Expand Down
1 change: 1 addition & 0 deletions packages/jspsych/src/modules/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export interface PluginInfo {
version?: string;
parameters: ParameterInfos;
data?: ParameterInfos;
citations?: Record<string, string> | string;
}

export interface JsPsychPlugin<I extends PluginInfo> {
Expand Down
4 changes: 4 additions & 0 deletions packages/jspsych/tests/TestPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export const testPluginInfo = <const>{
version: "0.0.1",
parameters: {},
data: {},
citations: {
apa: "Test plugin APA citation",
bibtex: "Test plugin BibTeX citation",
},
};

class TestPlugin implements JsPsychPlugin<typeof testPluginInfo> {
Expand Down
Loading
Loading