Initial commit
This commit is contained in:
6
.env.development.example
Normal file
6
.env.development.example
Normal file
@@ -0,0 +1,6 @@
|
||||
VITE_DEBUG=true
|
||||
VITE_COMPLETE_URL=
|
||||
VITE_CLOSED_URL=
|
||||
VITE_EXPERIMENT_TITLE=
|
||||
VITE_EXPERIMENT_NAME=
|
||||
VITE_DEPLOY_URL=
|
||||
6
.env.production.example
Normal file
6
.env.production.example
Normal file
@@ -0,0 +1,6 @@
|
||||
VITE_DEBUG=false
|
||||
VITE_COMPLETE_URL=
|
||||
VITE_CLOSED_URL=
|
||||
VITE_EXPERIMENT_TITLE=
|
||||
VITE_EXPERIMENT_NAME=
|
||||
VITE_DEPLOY_URL=
|
||||
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
.env.production
|
||||
.env.development
|
||||
19
.prettierrc
Normal file
19
.prettierrc
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"htmlWhitespaceSensitivity": "ignore",
|
||||
"plugins": ["prettier-plugin-html-template-literals"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.js"],
|
||||
"options": {
|
||||
"htmlTemplateLiterals": {
|
||||
"indent": 2,
|
||||
"format": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
13
index.html
Normal file
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link href="/styles.css" rel="stylesheet" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
32
index.js
Normal file
32
index.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { initJsPsych } from "jspsych";
|
||||
import "jspsych/css/jspsych.css";
|
||||
import "./styles.css";
|
||||
import { delayed_redirect } from "./utils/helpers.js";
|
||||
import jsPsychHtmlKeyboardResponse from "@jspsych/plugin-html-keyboard-response";
|
||||
import { textStimuli } from './scripts/text_stimuli';
|
||||
|
||||
const debug = import.meta.env.VITE_DEBUG;
|
||||
|
||||
const jsPsych = initJsPsych({
|
||||
on_finish: function() {
|
||||
jsPsych.getDisplayElement().innerHTML = textStimuli.complete;
|
||||
},
|
||||
on_close: function() {
|
||||
delayed_redirect(import.meta.env.VITE_CLOSED_URL);
|
||||
},
|
||||
on_data_update: function() {
|
||||
if (debug) {
|
||||
console.log(jsPsych.data.get().json());
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const demo_trial = {
|
||||
type: jsPsychHtmlKeyboardResponse,
|
||||
stimulus: `<h1 class="text-2xl font-bold">Hello, world!</h1>`,
|
||||
choices: [''],
|
||||
};
|
||||
|
||||
const timeline = [demo_trial];
|
||||
|
||||
jsPsych.run(timeline);
|
||||
1960
package-lock.json
generated
Normal file
1960
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
package.json
Normal file
24
package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "jspsych-npm-template",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"deploy": "npm run build && NODE_ENV=production node scripts/deploy.js",
|
||||
"deploy-dev": "npm run build && NODE_ENV=development node scripts/deploy.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"terser": "^5.39.0",
|
||||
"vite": "^6.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jspsych/plugin-html-keyboard-response": "^2.1.0",
|
||||
"@tailwindcss/vite": "^4.1.4",
|
||||
"jspsych": "^8.2.1",
|
||||
"prettier-plugin-html-template-literals": "^1.0.5",
|
||||
"tailwindcss": "^4.1.4",
|
||||
"vite-plugin-static-copy": "^3.0.0"
|
||||
}
|
||||
}
|
||||
9
scripts/text_stimuli.js
Normal file
9
scripts/text_stimuli.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import html from '../utils/html.js';
|
||||
|
||||
export const textStimuli = {
|
||||
complete: html`Experiment complete. Please paste the following link into your browser to confirm completion on Prolific:
|
||||
<span class="text-blue-500">
|
||||
${import.meta.env.VITE_COMPLETE_URL}
|
||||
</a>
|
||||
`,
|
||||
};
|
||||
1
styles.css
Normal file
1
styles.css
Normal file
@@ -0,0 +1 @@
|
||||
@import "tailwindcss";
|
||||
86
utils/deploy.js
Normal file
86
utils/deploy.js
Normal file
@@ -0,0 +1,86 @@
|
||||
const { execSync } = require('child_process');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const archiver = require('archiver');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
// Load environment variables based on NODE_ENV
|
||||
const envFile =
|
||||
process.env.NODE_ENV === 'production'
|
||||
? '.env.production'
|
||||
: '.env.development';
|
||||
dotenv.config({ path: path.join(__dirname, '..', envFile) });
|
||||
|
||||
// Function to create and send zip file
|
||||
function sendZipFile() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const distPath = path.join(__dirname, '../dist');
|
||||
const zipPath = path.join(__dirname, '../dist.zip');
|
||||
|
||||
// Create a file to stream archive data to
|
||||
const output = fs.createWriteStream(zipPath);
|
||||
const archive = archiver('zip', {
|
||||
zlib: { level: 9 }, // Sets the compression level
|
||||
});
|
||||
|
||||
// Listen for all archive data to be written
|
||||
output.on('close', () => {
|
||||
console.log(`✅ Archive created: ${archive.pointer()} total bytes`);
|
||||
|
||||
// Get the deployment URL from environment
|
||||
const deployUrl = process.env.VITE_DEPLOY_URL;
|
||||
if (!deployUrl) {
|
||||
console.error('❌ VITE_DEPLOY_URL not found in environment variables');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Send the zip file via curl
|
||||
try {
|
||||
console.log(`📤 Sending zip file to ${deployUrl}...`);
|
||||
execSync(`curl -X POST -F "file=@${zipPath}" ${deployUrl}`, {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
console.log('✅ Zip file sent successfully');
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to send zip file:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Clean up the zip file
|
||||
fs.unlinkSync(zipPath);
|
||||
resolve();
|
||||
});
|
||||
|
||||
// Handle warnings and errors
|
||||
archive.on('warning', err => {
|
||||
if (err.code === 'ENOENT') {
|
||||
console.warn('⚠️ Archive warning:', err);
|
||||
} else {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
|
||||
archive.on('error', err => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
// Pipe archive data to the file
|
||||
archive.pipe(output);
|
||||
|
||||
// Add the dist directory to the archive
|
||||
archive.directory(distPath, false);
|
||||
|
||||
// Finalize the archive
|
||||
archive.finalize();
|
||||
});
|
||||
}
|
||||
|
||||
// Run the deployment
|
||||
sendZipFile()
|
||||
.then(() => {
|
||||
console.log('✅ Deployment successful!');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('❌ Deployment failed:', error.message);
|
||||
process.exit(1);
|
||||
});
|
||||
5
utils/helpers.js
Normal file
5
utils/helpers.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export function delayed_redirect(url) {
|
||||
setTimeout(() => {
|
||||
window.location.href = url;
|
||||
}, 5000);
|
||||
}
|
||||
6
utils/html.js
Normal file
6
utils/html.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const html = (strings, ...values) =>
|
||||
strings
|
||||
.reduce((result, str, i) => result + str + (values[i] || ""), "")
|
||||
.trim();
|
||||
|
||||
export default html;
|
||||
46
vite.config.mjs
Normal file
46
vite.config.mjs
Normal file
@@ -0,0 +1,46 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
||||
|
||||
export default defineConfig({
|
||||
base: './', // This makes all assets use relative paths
|
||||
plugins: [
|
||||
tailwindcss(),
|
||||
viteStaticCopy({
|
||||
targets: [
|
||||
{
|
||||
src: 'images/*',
|
||||
dest: 'images',
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
server: {
|
||||
watch: {
|
||||
usePolling: true,
|
||||
},
|
||||
},
|
||||
build: {
|
||||
minify: false,
|
||||
terserOptions: {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
},
|
||||
rollupOptions: {
|
||||
input: {
|
||||
main: 'index.html',
|
||||
},
|
||||
output: {
|
||||
format: 'iife',
|
||||
entryFileNames: '[name].js',
|
||||
chunkFileNames: '[name]-[hash].js',
|
||||
assetFileNames: 'assets/[name]-[hash].[ext]',
|
||||
sanitizeFileName: name => name.replace(/\.[jt]sx?$/, ''),
|
||||
},
|
||||
},
|
||||
assetsInlineLimit: 0,
|
||||
target: 'esnext',
|
||||
modulePreload: false,
|
||||
cssCodeSplit: false,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user