mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-10 11:10:54 +00:00
add jest tests for citation tool
This commit is contained in:
parent
9d5215e554
commit
f0bc8ae3ac
1061
package-lock.json
generated
1061
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,13 @@ import fs from "node:fs";
|
|||||||
import { Cite } from "@citation-js/core";
|
import { Cite } from "@citation-js/core";
|
||||||
import yaml from "yaml";
|
import yaml from "yaml";
|
||||||
|
|
||||||
export default function generateCitation() {
|
/**
|
||||||
|
* 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;
|
let preferredCitation = false;
|
||||||
|
|
||||||
// Try to find CITATION.cff file and look for preferred-citation
|
// Try to find CITATION.cff file and look for preferred-citation
|
||||||
@ -31,7 +37,7 @@ export default function generateCitation() {
|
|||||||
return { apa: "", bibtex: "" };
|
return { apa: "", bibtex: "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to convert CITATION.cff to APA string
|
// Convert CITATION.cff to APA string
|
||||||
const citationApa = (() => {
|
const citationApa = (() => {
|
||||||
try {
|
try {
|
||||||
const apaCite = new Cite(citationCff);
|
const apaCite = new Cite(citationCff);
|
||||||
@ -48,7 +54,7 @@ export default function generateCitation() {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Try to convert CITATION.cff to bibtex string
|
// Convert CITATION.cff to BibTeX string
|
||||||
const citationBibtex = (() => {
|
const citationBibtex = (() => {
|
||||||
try {
|
try {
|
||||||
const bibtexCite = new Cite(citationCff);
|
const bibtexCite = new Cite(citationCff);
|
||||||
@ -60,7 +66,7 @@ export default function generateCitation() {
|
|||||||
});
|
});
|
||||||
return citationBibtex;
|
return citationBibtex;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(`Error converting CITATION.cff to BibTex string: ${error.message}`);
|
console.log(`Error converting CITATION.cff to BibTeX string: ${error.message}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
})();
|
})();
|
@ -35,16 +35,16 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://www.jspsych.org/latest/developers/configuration",
|
"homepage": "https://www.jspsych.org/latest/developers/configuration",
|
||||||
"dependencies": {
|
"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-commonjs": "26.0.1",
|
||||||
"@rollup/plugin-node-resolve": "15.2.3",
|
"@rollup/plugin-node-resolve": "15.2.3",
|
||||||
"@rollup/plugin-replace": "^6.0.1",
|
"@rollup/plugin-replace": "^6.0.1",
|
||||||
"@sucrase/jest-plugin": "3.0.0",
|
"@sucrase/jest-plugin": "3.0.0",
|
||||||
"@types/gulp": "4.0.17",
|
"@types/gulp": "4.0.17",
|
||||||
"@types/jest": "29.5.8",
|
"@types/jest": "29.5.8",
|
||||||
"@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",
|
|
||||||
"alias-hq": "6.2.4",
|
"alias-hq": "6.2.4",
|
||||||
"canvas": "^2.11.2",
|
"canvas": "^2.11.2",
|
||||||
"esbuild": "0.23.1",
|
"esbuild": "0.23.1",
|
||||||
@ -60,6 +60,7 @@
|
|||||||
"rollup": "4.21.2",
|
"rollup": "4.21.2",
|
||||||
"rollup-plugin-dts": "6.1.1",
|
"rollup-plugin-dts": "6.1.1",
|
||||||
"rollup-plugin-esbuild": "6.1.1",
|
"rollup-plugin-esbuild": "6.1.1",
|
||||||
|
"rollup-plugin-modify": "^3.0.0",
|
||||||
"rollup-plugin-node-externals": "7.1.3",
|
"rollup-plugin-node-externals": "7.1.3",
|
||||||
"sucrase": "3.34.0",
|
"sucrase": "3.34.0",
|
||||||
"tslib": "2.6.2",
|
"tslib": "2.6.2",
|
||||||
|
@ -3,14 +3,14 @@ import path from "path";
|
|||||||
|
|
||||||
import commonjs from "@rollup/plugin-commonjs";
|
import commonjs from "@rollup/plugin-commonjs";
|
||||||
import resolve from "@rollup/plugin-node-resolve";
|
import resolve from "@rollup/plugin-node-resolve";
|
||||||
import replace from "@rollup/plugin-replace";
|
|
||||||
import { defineConfig } from "rollup";
|
import { defineConfig } from "rollup";
|
||||||
import dts from "rollup-plugin-dts";
|
import dts from "rollup-plugin-dts";
|
||||||
import esbuild from "rollup-plugin-esbuild";
|
import esbuild from "rollup-plugin-esbuild";
|
||||||
|
import modify from "rollup-plugin-modify";
|
||||||
import externals from "rollup-plugin-node-externals";
|
import externals from "rollup-plugin-node-externals";
|
||||||
import ts from "typescript";
|
import ts from "typescript";
|
||||||
|
|
||||||
import generateCitation from "./generateCitation.js";
|
import generateCitations from "./generateCitations.js";
|
||||||
|
|
||||||
const getTsCompilerOptions = () => {
|
const getTsCompilerOptions = () => {
|
||||||
const cwd = process.cwd();
|
const cwd = process.cwd();
|
||||||
@ -41,7 +41,7 @@ const makeConfig = ({
|
|||||||
...outputOptions,
|
...outputOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
const citationData = generateCitation();
|
const citationData = generateCitations();
|
||||||
|
|
||||||
/** @type{import("rollup-plugin-esbuild").Options} */
|
/** @type{import("rollup-plugin-esbuild").Options} */
|
||||||
const esBuildPluginOptions = {
|
const esBuildPluginOptions = {
|
||||||
@ -76,11 +76,9 @@ const makeConfig = ({
|
|||||||
input,
|
input,
|
||||||
plugins: [
|
plugins: [
|
||||||
externals(),
|
externals(),
|
||||||
replace({
|
modify({
|
||||||
values: {
|
find: /'__CITATIONS__'/g,
|
||||||
__APACITATION__: citationData.apa,
|
replace: JSON.stringify(citationData, null, 2),
|
||||||
__BIBTEXCITATION__: citationData.bibtex,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
esbuild({ ...esBuildPluginOptions, target: "node18" }),
|
esbuild({ ...esBuildPluginOptions, target: "node18" }),
|
||||||
commonjs(commonjsPluginOptions),
|
commonjs(commonjsPluginOptions),
|
||||||
@ -107,11 +105,9 @@ const makeConfig = ({
|
|||||||
input,
|
input,
|
||||||
plugins: [
|
plugins: [
|
||||||
externals({ deps: false }),
|
externals({ deps: false }),
|
||||||
replace({
|
modify({
|
||||||
values: {
|
find: /'__CITATIONS__'/g,
|
||||||
__APACITATION__: citationData.apa,
|
replace: JSON.stringify(citationData, null, 2),
|
||||||
__BIBTEXCITATION__: citationData.bibtex,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
resolve({ preferBuiltins: false }),
|
resolve({ preferBuiltins: false }),
|
||||||
esbuild({ ...esBuildPluginOptions, target: "esnext" }),
|
esbuild({ ...esBuildPluginOptions, target: "esnext" }),
|
||||||
@ -132,11 +128,9 @@ const makeConfig = ({
|
|||||||
input,
|
input,
|
||||||
plugins: [
|
plugins: [
|
||||||
externals({ deps: false }),
|
externals({ deps: false }),
|
||||||
replace({
|
modify({
|
||||||
values: {
|
find: /'__CITATIONS__'/g,
|
||||||
__APACITATION__: citationData.apa,
|
replace: JSON.stringify(citationData, null, 2),
|
||||||
__BIBTEXCITATION__: citationData.bibtex,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
resolve({ preferBuiltins: false }),
|
resolve({ preferBuiltins: false }),
|
||||||
esbuild({ ...esBuildPluginOptions, target: "es2015", minify: true }),
|
esbuild({ ...esBuildPluginOptions, target: "es2015", minify: true }),
|
||||||
|
47
packages/extension-mouse-tracking/CITATION.cff
Normal file
47
packages/extension-mouse-tracking/CITATION.cff
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
cff-version: "1.2.0"
|
||||||
|
authors:
|
||||||
|
- family-names: Leeuw
|
||||||
|
given-names: Joshua R.
|
||||||
|
name-particle: de
|
||||||
|
orcid: "https://orcid.org/0000-0003-4815-2364"
|
||||||
|
- family-names: Gilbert
|
||||||
|
given-names: Rebecca A.
|
||||||
|
orcid: "https://orcid.org/0000-0003-4574-7792"
|
||||||
|
- family-names: Luchterhandt
|
||||||
|
given-names: Björn
|
||||||
|
orcid: "https://orcid.org/0000-0002-9225-2787"
|
||||||
|
contact:
|
||||||
|
- family-names: Leeuw
|
||||||
|
given-names: Joshua R.
|
||||||
|
name-particle: de
|
||||||
|
orcid: "https://orcid.org/0000-0003-4815-2364"
|
||||||
|
doi: 10.5281/zenodo.7702307
|
||||||
|
message: If you use this software, please cite our article in the
|
||||||
|
Journal of Open Source Software.
|
||||||
|
preferred-citation:
|
||||||
|
authors:
|
||||||
|
- family-names: Leeuw
|
||||||
|
given-names: Joshua R.
|
||||||
|
name-particle: de
|
||||||
|
orcid: "https://orcid.org/0000-0003-4815-2364"
|
||||||
|
- family-names: Gilbert
|
||||||
|
given-names: Rebecca A.
|
||||||
|
orcid: "https://orcid.org/0000-0003-4574-7792"
|
||||||
|
- family-names: Luchterhandt
|
||||||
|
given-names: Björn
|
||||||
|
orcid: "https://orcid.org/0000-0002-9225-2787"
|
||||||
|
date-published: 2023-05-11
|
||||||
|
doi: 10.21105/joss.05351
|
||||||
|
issn: 2475-9066
|
||||||
|
issue: 85
|
||||||
|
journal: Journal of Open Source Software
|
||||||
|
publisher:
|
||||||
|
name: Open Journals
|
||||||
|
start: 5351
|
||||||
|
title: "jsPsych: Enabling an Open-Source Collaborative Ecosystem of
|
||||||
|
Behavioral Experiments"
|
||||||
|
type: article
|
||||||
|
url: "https://joss.theoj.org/papers/10.21105/joss.05351"
|
||||||
|
volume: 8
|
||||||
|
title: "jsPsych: Enabling an Open-Source Collaborative Ecosystem of
|
||||||
|
Behavioral Experiments"
|
@ -95,6 +95,7 @@ class MouseTrackingExtension implements JsPsychExtension {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
citations: "__CITATIONS__",
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private jsPsych: JsPsych) {}
|
constructor(private jsPsych: JsPsych) {}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Class } from "type-fest";
|
import { Class } from "type-fest";
|
||||||
|
|
||||||
import { TestExtension } from "../tests/extensions/test-extension";
|
import { TestExtension } from "../tests/extensions/TestExtension";
|
||||||
import { ExtensionManager, ExtensionManagerDependencies } from "./ExtensionManager";
|
import { ExtensionManager, ExtensionManagerDependencies } from "./ExtensionManager";
|
||||||
import { JsPsych } from "./JsPsych";
|
import { JsPsych } from "./JsPsych";
|
||||||
import { JsPsychExtension } from "./modules/extensions";
|
import { JsPsychExtension } from "./modules/extensions";
|
||||||
|
@ -262,13 +262,29 @@ export class JsPsych {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCitations(
|
getCitations(
|
||||||
plugins: Array<Class<JsPsychPlugin<any>> | JsPsychExtension>,
|
plugins: Array<Class<JsPsychPlugin<any>> | Class<JsPsychExtension>>,
|
||||||
format: "apa" | "bibtex"
|
format?: string
|
||||||
) {
|
) {
|
||||||
|
format = format ? format.toLowerCase() : "apa";
|
||||||
|
// Check if plugins is an array
|
||||||
|
if (!Array.isArray(plugins)) {
|
||||||
|
throw new Error("Expected array of plugins/extensions");
|
||||||
|
}
|
||||||
|
// Check if array is empty
|
||||||
|
else if (plugins.length == 0) {
|
||||||
|
console.warn("No plugins/extensions provided");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check if format is supported
|
||||||
|
else if (!Object.keys(plugins[0]["info"].citations).includes(format)) {
|
||||||
|
throw new Error("Unsupported citation format");
|
||||||
|
} else {
|
||||||
plugins.map((plugin) => {
|
plugins.map((plugin) => {
|
||||||
let pluginCitation = plugin["info"].citation;
|
let pluginCitations = plugin["info"].citations;
|
||||||
|
console.log(format == "apa" ? `${pluginCitations.apa}` : `${pluginCitations.bibtex}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get extensions() {
|
get extensions() {
|
||||||
return this.extensionManager?.extensions ?? {};
|
return this.extensionManager?.extensions ?? {};
|
||||||
|
@ -4,6 +4,7 @@ export interface JsPsychExtensionInfo {
|
|||||||
name: string;
|
name: string;
|
||||||
version?: string;
|
version?: string;
|
||||||
data?: ParameterInfos;
|
data?: ParameterInfos;
|
||||||
|
citations?: Record<string, string> | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JsPsychExtension {
|
export interface JsPsychExtension {
|
||||||
|
@ -141,6 +141,7 @@ export interface PluginInfo {
|
|||||||
version?: string;
|
version?: string;
|
||||||
parameters: ParameterInfos;
|
parameters: ParameterInfos;
|
||||||
data?: ParameterInfos;
|
data?: ParameterInfos;
|
||||||
|
citations?: Record<string, string> | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JsPsychPlugin<I extends PluginInfo> {
|
export interface JsPsychPlugin<I extends PluginInfo> {
|
||||||
|
@ -10,6 +10,10 @@ export const testPluginInfo = <const>{
|
|||||||
version: "0.0.1",
|
version: "0.0.1",
|
||||||
parameters: {},
|
parameters: {},
|
||||||
data: {},
|
data: {},
|
||||||
|
citations: {
|
||||||
|
apa: "Test plugin APA citation",
|
||||||
|
bibtex: "Test plugin BibTeX citation",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestPlugin implements JsPsychPlugin<typeof testPluginInfo> {
|
class TestPlugin implements JsPsychPlugin<typeof testPluginInfo> {
|
||||||
|
77
packages/jspsych/tests/citations/citations.test.ts
Normal file
77
packages/jspsych/tests/citations/citations.test.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { JsPsych } from "../../src/JsPsych";
|
||||||
|
import { TestExtension } from "../extensions/TestExtension";
|
||||||
|
import TestPlugin from "../TestPlugin";
|
||||||
|
|
||||||
|
const testPluginApaCitation = "Test plugin APA citation";
|
||||||
|
const testPluginBibtexCitation = "Test plugin BibTeX citation";
|
||||||
|
const testExtensionApaCitation = "Test extension APA citation";
|
||||||
|
|
||||||
|
let jspsych: JsPsych;
|
||||||
|
let consoleLogSpy: jest.SpyInstance;
|
||||||
|
let consoleWarnSpy: jest.SpyInstance;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jspsych = new JsPsych();
|
||||||
|
consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
|
||||||
|
consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("citing not using an array", () => {
|
||||||
|
test("citing nothing", () => {
|
||||||
|
expect(() => jspsych.getCitations(null)).toThrow("Expected array of plugins/extensions");
|
||||||
|
});
|
||||||
|
test("citing without input and with invalid format", () => {
|
||||||
|
expect(() => jspsych.getCitations(null, "apa")).toThrow("Expected array of plugins/extensions");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("citing using an array in different formats", () => {
|
||||||
|
test("citing empty array with APA format", () => {
|
||||||
|
jspsych.getCitations([], "apa");
|
||||||
|
expect(consoleWarnSpy.mock.calls[0][0]).toBe("No plugins/extensions provided");
|
||||||
|
});
|
||||||
|
test("citing empty array with BibTeX format", () => {
|
||||||
|
jspsych.getCitations([], "bibtex");
|
||||||
|
expect(consoleWarnSpy.mock.calls[0][0]).toBe("No plugins/extensions provided");
|
||||||
|
});
|
||||||
|
test("citing empty array without format", () => {
|
||||||
|
jspsych.getCitations([]);
|
||||||
|
expect(consoleWarnSpy.mock.calls[0][0]).toBe("No plugins/extensions provided");
|
||||||
|
});
|
||||||
|
test("citing one plugin with valid format in all caps", () => {
|
||||||
|
jspsych.getCitations([TestPlugin], "APA");
|
||||||
|
expect(consoleLogSpy.mock.calls[0][0]).toBe(testPluginApaCitation);
|
||||||
|
});
|
||||||
|
test("citing with unsupported format", () => {
|
||||||
|
expect(() => jspsych.getCitations([TestPlugin], "DummyTex")).toThrow(
|
||||||
|
"Unsupported citation format"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("citing mix of valid plugins/extensions", () => {
|
||||||
|
test("citing a plugin", () => {
|
||||||
|
jspsych.getCitations([TestPlugin]);
|
||||||
|
expect(consoleLogSpy.mock.calls[0][0]).toBe(testPluginApaCitation);
|
||||||
|
});
|
||||||
|
test("citing a plugin in BibTeX", () => {
|
||||||
|
jspsych.getCitations([TestPlugin], "bibtex");
|
||||||
|
expect(consoleLogSpy.mock.calls[0][0]).toBe(testPluginBibtexCitation);
|
||||||
|
});
|
||||||
|
test("citing multiple plugins", () => {
|
||||||
|
jspsych.getCitations([TestPlugin, TestPlugin]);
|
||||||
|
expect(consoleLogSpy.mock.calls).toHaveLength(2);
|
||||||
|
expect(consoleLogSpy.mock.calls[0][0]).toBe(testPluginApaCitation);
|
||||||
|
expect(consoleLogSpy.mock.calls[1][0]).toBe(testPluginApaCitation);
|
||||||
|
});
|
||||||
|
test("citing mix of plugins and extensions", () => {
|
||||||
|
jspsych.getCitations([TestPlugin, TestExtension]);
|
||||||
|
expect(consoleLogSpy.mock.calls).toHaveLength(2);
|
||||||
|
expect(consoleLogSpy.mock.calls[0][0]).toBe(testPluginApaCitation);
|
||||||
|
expect(consoleLogSpy.mock.calls[1][0]).toBe(testExtensionApaCitation);
|
||||||
|
});
|
||||||
|
});
|
@ -5,6 +5,10 @@ export class TestExtension implements JsPsychExtension {
|
|||||||
name: "test",
|
name: "test",
|
||||||
version: "0.0.1",
|
version: "0.0.1",
|
||||||
data: {},
|
data: {},
|
||||||
|
citations: {
|
||||||
|
apa: "Test extension APA citation",
|
||||||
|
bibtex: "Test extension BibTeX citation",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private jsPsych: JsPsych) {}
|
constructor(private jsPsych: JsPsych) {}
|
@ -2,7 +2,7 @@ import htmlKeyboardResponse from "@jspsych/plugin-html-keyboard-response";
|
|||||||
import { pressKey, startTimeline } from "@jspsych/test-utils";
|
import { pressKey, startTimeline } from "@jspsych/test-utils";
|
||||||
|
|
||||||
import { JsPsych, initJsPsych } from "../../src";
|
import { JsPsych, initJsPsych } from "../../src";
|
||||||
import { TestExtension } from "./test-extension";
|
import { TestExtension } from "./TestExtension";
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
@ -80,10 +80,7 @@ const info = <const>{
|
|||||||
type: ParameterType.STRING,
|
type: ParameterType.STRING,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
citation: {
|
citations: "__CITATIONS__",
|
||||||
apa: "__APACITATION__",
|
|
||||||
bibtex: "__BIBTEXCITATION__",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type Info = typeof info;
|
type Info = typeof info;
|
||||||
|
47
packages/plugin-preload/CITATION.cff
Normal file
47
packages/plugin-preload/CITATION.cff
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
cff-version: "1.2.0"
|
||||||
|
authors:
|
||||||
|
- family-names: Leeuw
|
||||||
|
given-names: Joshua R.
|
||||||
|
name-particle: de
|
||||||
|
orcid: "https://orcid.org/0000-0003-4815-2364"
|
||||||
|
- family-names: Gilbert
|
||||||
|
given-names: Rebecca A.
|
||||||
|
orcid: "https://orcid.org/0000-0003-4574-7792"
|
||||||
|
- family-names: Luchterhandt
|
||||||
|
given-names: Björn
|
||||||
|
orcid: "https://orcid.org/0000-0002-9225-2787"
|
||||||
|
contact:
|
||||||
|
- family-names: Leeuw
|
||||||
|
given-names: Joshua R.
|
||||||
|
name-particle: de
|
||||||
|
orcid: "https://orcid.org/0000-0003-4815-2364"
|
||||||
|
doi: 10.5281/zenodo.7702307
|
||||||
|
message: If you use this software, please cite our article in the
|
||||||
|
Journal of Open Source Software.
|
||||||
|
preferred-citation:
|
||||||
|
authors:
|
||||||
|
- family-names: Leeuw
|
||||||
|
given-names: Joshua R.
|
||||||
|
name-particle: de
|
||||||
|
orcid: "https://orcid.org/0000-0003-4815-2364"
|
||||||
|
- family-names: Gilbert
|
||||||
|
given-names: Rebecca A.
|
||||||
|
orcid: "https://orcid.org/0000-0003-4574-7792"
|
||||||
|
- family-names: Luchterhandt
|
||||||
|
given-names: Björn
|
||||||
|
orcid: "https://orcid.org/0000-0002-9225-2787"
|
||||||
|
date-published: 2023-05-11
|
||||||
|
doi: 10.21105/joss.05351
|
||||||
|
issn: 2475-9066
|
||||||
|
issue: 85
|
||||||
|
journal: Journal of Open Source Software
|
||||||
|
publisher:
|
||||||
|
name: Open Journals
|
||||||
|
start: 5351
|
||||||
|
title: "jsPsych: Enabling an Open-Source Collaborative Ecosystem of
|
||||||
|
Behavioral Experiments"
|
||||||
|
type: article
|
||||||
|
url: "https://joss.theoj.org/papers/10.21105/joss.05351"
|
||||||
|
volume: 8
|
||||||
|
title: "jsPsych: Enabling an Open-Source Collaborative Ecosystem of
|
||||||
|
Behavioral Experiments"
|
@ -134,6 +134,7 @@ const info = <const>{
|
|||||||
array: true,
|
array: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
citations: "__CITATIONS__",
|
||||||
};
|
};
|
||||||
|
|
||||||
type Info = typeof info;
|
type Info = typeof info;
|
||||||
|
Loading…
Reference in New Issue
Block a user