@citolab/tspci 2.5.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +28 -28
- package/preset/javascript/src/index.js +92 -0
- package/preset/preact/src/index.tsx +1 -0
- package/preset/{base → typescript}/src/index.ts +9 -2
- package/readme.md +1 -1
- package/src/cli.js +46 -11
package/package.json
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@citolab/tspci",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "an opiniated typescript ims-pci builder with tao integration",
|
|
5
5
|
"author": "patrick <patrick.deklein@cito.nl>",
|
|
6
6
|
"repository": "@citolab/tspci",
|
|
7
7
|
"bin": {
|
|
8
8
|
"tspci": "src/cli.js"
|
|
9
9
|
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"help": "tspci --help",
|
|
12
|
+
"init": "tspci init --force --path=../../pcis"
|
|
13
|
+
},
|
|
10
14
|
"type": "module",
|
|
11
15
|
"types": "types/index.d.ts",
|
|
12
16
|
"dependencies": {
|
|
13
|
-
"@rollup/plugin-alias": "^5.
|
|
14
|
-
"@rollup/plugin-babel": "^6.0.
|
|
15
|
-
"@rollup/plugin-commonjs": "^
|
|
16
|
-
"@rollup/plugin-image": "^3.0.
|
|
17
|
-
"@rollup/plugin-json": "^6.
|
|
18
|
-
"@rollup/plugin-node-resolve": "^15.
|
|
19
|
-
"@rollup/plugin-replace": "^5.0.
|
|
20
|
-
"@rollup/plugin-terser": "^0.4.
|
|
21
|
-
"@rollup/plugin-typescript": "^11.1.
|
|
17
|
+
"@rollup/plugin-alias": "^5.1.0",
|
|
18
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
19
|
+
"@rollup/plugin-commonjs": "^26.0.1",
|
|
20
|
+
"@rollup/plugin-image": "^3.0.3",
|
|
21
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
22
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
23
|
+
"@rollup/plugin-replace": "^5.0.7",
|
|
24
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
25
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
22
26
|
"@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
|
|
23
|
-
"@testing-library/dom": "^
|
|
24
|
-
"@types/node": "^
|
|
25
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
26
|
-
"@typescript-eslint/parser": "^5.
|
|
27
|
-
"autoprefixer": "10.4.
|
|
28
|
-
"chalk": "5.
|
|
27
|
+
"@testing-library/dom": "^10.4.0",
|
|
28
|
+
"@types/node": "^22.5.5",
|
|
29
|
+
"@typescript-eslint/eslint-plugin": "^8.5.0",
|
|
30
|
+
"@typescript-eslint/parser": "^8.5.0",
|
|
31
|
+
"autoprefixer": "10.4.20",
|
|
32
|
+
"chalk": "5.3.0",
|
|
29
33
|
"clear": "0.1.0",
|
|
30
|
-
"figlet": "1.
|
|
31
|
-
"inquirer": "
|
|
34
|
+
"figlet": "1.7.0",
|
|
35
|
+
"inquirer": "11.0.1",
|
|
32
36
|
"live-server": "^1.2.2",
|
|
33
|
-
"postcss": "^8.4.
|
|
34
|
-
"postcss-import": "^
|
|
35
|
-
"rollup": "^
|
|
36
|
-
"rollup-plugin-copy": "^3.
|
|
37
|
+
"postcss": "^8.4.47",
|
|
38
|
+
"postcss-import": "^16.1.0",
|
|
39
|
+
"rollup": "^4.21.3",
|
|
40
|
+
"rollup-plugin-copy": "^3.5.0",
|
|
37
41
|
"rollup-plugin-live-server": "^2.0.0",
|
|
38
42
|
"rollup-plugin-node-builtins": "^2.1.2",
|
|
39
43
|
"rollup-plugin-node-globals": "^1.4.0",
|
|
40
44
|
"rollup-plugin-postcss": "^4.0.2",
|
|
41
45
|
"rollup-plugin-string": "^3.0.0",
|
|
42
46
|
"rollup-plugin-watch-assets": "^1.0.1",
|
|
43
|
-
"tailwindcss": "^3.
|
|
44
|
-
},
|
|
45
|
-
"scripts": {
|
|
46
|
-
"help": "tspci --help",
|
|
47
|
-
"init": "tspci init --force --path=../../pcis"
|
|
47
|
+
"tailwindcss": "^3.4.11"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "c2a5bef4bd27f0251da5b62c049b52d42c8efa71"
|
|
50
50
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as ctx from "qtiCustomInteractionContext";
|
|
2
|
+
import configProps from "./config.json";
|
|
3
|
+
import style from "./styles.css"; // import and bundle this style file ( you can use tailwind and nested css )
|
|
4
|
+
import procenten from "./assets/procenten.png"; // image types are bundled inside the js
|
|
5
|
+
|
|
6
|
+
class Pci {
|
|
7
|
+
/**
|
|
8
|
+
* @constructor
|
|
9
|
+
* @param {string} typeIdentifier - The unique identifier for this PCI type.
|
|
10
|
+
*/
|
|
11
|
+
typeIdentifier; // typeIdentifier is mandatory for all PCI's
|
|
12
|
+
config; // reference to the interface of the config object which you get when getInstance is called by the player
|
|
13
|
+
state; // keep a reference to the state
|
|
14
|
+
shadowdom; // Not mandatory, but its wise to create a shadowroot
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
/**
|
|
18
|
+
* @type {string}
|
|
19
|
+
* @description The unique identifier for this PCI type.
|
|
20
|
+
*/
|
|
21
|
+
this.typeIdentifier = "###___PCI_NAME___###"; // typeIdentifier is mandatory for all PCI's
|
|
22
|
+
ctx && ctx.register(this); // we assume the qtiCustomInteractionContext is avaible due to the import above
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @method getInstance
|
|
27
|
+
* @description Creates a new instance of this portable custom interaction.
|
|
28
|
+
* This method will be called by the qtiCustomInteractionContext.
|
|
29
|
+
*
|
|
30
|
+
* @param {HTMLElement} dom - The DOM element to which this PCI is added.
|
|
31
|
+
* @param {Object<ConfigProperties>} config - The configuration to apply to this PCI.
|
|
32
|
+
* @param {string} state - A previously saved state to restore the PCI instance.
|
|
33
|
+
* This state must have been obtained from a prior call to getState for an instance of the same typeIdentifier.
|
|
34
|
+
*/
|
|
35
|
+
getInstance = (dom, config, state) => {
|
|
36
|
+
config.properties = { ...configProps, ...config.properties }; // merge current props with incoming
|
|
37
|
+
this.config = config;
|
|
38
|
+
this.state = state ? state : "";
|
|
39
|
+
|
|
40
|
+
this.shadowdom = dom.attachShadow({ mode: "closed" });
|
|
41
|
+
this.render();
|
|
42
|
+
|
|
43
|
+
config.onready(this);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
render = () => {
|
|
47
|
+
this.shadowdom.addEventListener("change", (e) => {
|
|
48
|
+
const value = e.target.value;
|
|
49
|
+
this.state = value;
|
|
50
|
+
});
|
|
51
|
+
this.shadowdom.innerHTML = `<div class="pci-container">
|
|
52
|
+
<h1>${this.config.properties.title}</h1>
|
|
53
|
+
<div class="body">
|
|
54
|
+
<img width="${+this.config.properties.width}" height="${+this.config.properties.height}" src="${procenten}" />
|
|
55
|
+
</div>
|
|
56
|
+
<div class="interaction">
|
|
57
|
+
<label for="tentacles">${this.config.properties.prompt}</label>
|
|
58
|
+
<input type="number" value="${this.state}" min="0" max="100">%
|
|
59
|
+
</div>
|
|
60
|
+
</div>`;
|
|
61
|
+
const css = document.createElement("style");
|
|
62
|
+
css.innerHTML = style;
|
|
63
|
+
this.shadowdom.appendChild(css);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @method getResponse
|
|
68
|
+
* @description Retrieves the value to assign to the bound QTI response variable.
|
|
69
|
+
*
|
|
70
|
+
* @returns {Object} - The response value.
|
|
71
|
+
*/
|
|
72
|
+
getResponse = () => {
|
|
73
|
+
const response = this.state === null || this.state === undefined ? undefined : { base: { integer: this.state } };
|
|
74
|
+
return response;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @method getState
|
|
79
|
+
* @description Retrieves the current state of this PCI. This state can be passed to getInstance to restore the instance later.
|
|
80
|
+
*
|
|
81
|
+
* @returns {string} - The current state of the PCI.
|
|
82
|
+
*/
|
|
83
|
+
getState = () => this.state.toString();
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @method oncompleted
|
|
87
|
+
* @description called when the PCI is completed.
|
|
88
|
+
*/
|
|
89
|
+
oncompleted = () => {};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export default new Pci();
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Configuration, IMSpci, QtiVariableJSON } from "@citolab/tspci";
|
|
2
2
|
import * as ctx from "qtiCustomInteractionContext";
|
|
3
3
|
import configProps from "./config.json";
|
|
4
|
+
import Interaction from "./interaction"; // import and bundle this interaction file
|
|
5
|
+
|
|
4
6
|
import style from "./styles.css"; // import and bundle this style file ( you can use tailwind and nested css )
|
|
5
7
|
import procenten from "./assets/procenten.png"; // image types are bundled inside the js
|
|
6
8
|
// Configuration
|
|
@@ -31,7 +33,7 @@ class Pci implements IMSpci<PropTypes> {
|
|
|
31
33
|
|
|
32
34
|
private render = () => {
|
|
33
35
|
this.shadowdom.addEventListener("change", (e: Event) => {
|
|
34
|
-
const value = (e.target as HTMLInputElement)
|
|
36
|
+
const value = (e.target as HTMLInputElement)?.value || "";
|
|
35
37
|
this.state = value;
|
|
36
38
|
});
|
|
37
39
|
this.shadowdom.innerHTML = `<div class="pci-container">
|
|
@@ -50,11 +52,16 @@ class Pci implements IMSpci<PropTypes> {
|
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
getResponse = () => {
|
|
53
|
-
const response =
|
|
55
|
+
const response =
|
|
56
|
+
this.state === null || this.state === undefined
|
|
57
|
+
? undefined
|
|
58
|
+
: ({ base: { integer: this.state } } as QtiVariableJSON);
|
|
54
59
|
return response;
|
|
55
60
|
};
|
|
56
61
|
|
|
57
62
|
getState = () => this.state.toString();
|
|
63
|
+
|
|
64
|
+
oncompleted = () => {};
|
|
58
65
|
}
|
|
59
66
|
|
|
60
67
|
export default new Pci();
|
package/readme.md
CHANGED
|
@@ -38,7 +38,7 @@ Run: ```npx @citolab/tspci@latest init```
|
|
|
38
38
|
2. If agreed; tspci will be downloaded and started.
|
|
39
39
|
3. You should provide a name/identifier for your PCI.
|
|
40
40
|
4. You should provide a description.
|
|
41
|
-
5. Last option is to
|
|
41
|
+
5. Last option is to choose how you want to build your pci, using tailwind and preact, typescript or javascript
|
|
42
42
|
|
|
43
43
|
#### Tailwind
|
|
44
44
|
Tailwind is a popular css framework and can be used to give a nice look and feel of the PCI. The cli will make sure the css is added; and all build stuff that comes with tailwind is setup.
|
package/src/cli.js
CHANGED
|
@@ -132,7 +132,7 @@ function promptYesNo(prompt) {
|
|
|
132
132
|
function selectOptions(prompt, options) {
|
|
133
133
|
return inquirer.prompt([
|
|
134
134
|
{
|
|
135
|
-
type: "
|
|
135
|
+
type: "list",
|
|
136
136
|
message: prompt,
|
|
137
137
|
name: "values",
|
|
138
138
|
choices: options.map((o) => ({ name: o, checked: true })),
|
|
@@ -232,7 +232,10 @@ const run = async () => {
|
|
|
232
232
|
console.log(chalk.green(figlet.textSync("@citolab/tspci", { horizontalLayout: "full" })));
|
|
233
233
|
|
|
234
234
|
// prompt for name
|
|
235
|
-
let pciName =
|
|
235
|
+
let pciName =
|
|
236
|
+
(await askOption(
|
|
237
|
+
"What your pci identifier (typeIdentifier). this can only contain alphanumeric characters (default: myPci) "
|
|
238
|
+
)) || "myPci";
|
|
236
239
|
let destinationFolder = path.join(process.cwd(), pciName);
|
|
237
240
|
if (args.find((arg) => arg.startsWith("--path"))) {
|
|
238
241
|
const pathIndex = args.findIndex((arg) => arg.startsWith("--path"));
|
|
@@ -266,7 +269,7 @@ const run = async () => {
|
|
|
266
269
|
(await askOption("What is the description of your pci? (default: pci created with tspci)")) ||
|
|
267
270
|
"pci created with tspci";
|
|
268
271
|
|
|
269
|
-
const options = await selectOptions("
|
|
272
|
+
const options = await selectOptions("Type of project?", ["preact+tailwind", "typescript", "javascript"]);
|
|
270
273
|
console.log(chalk.green(`Options: ${options.values.length === 0 ? "none" : options.values}`));
|
|
271
274
|
// get relative path to executable
|
|
272
275
|
const cliPath = __dirname;
|
|
@@ -298,7 +301,7 @@ const run = async () => {
|
|
|
298
301
|
}
|
|
299
302
|
packageJsonContentJson.config.tspci.typeIdentifier = pciName;
|
|
300
303
|
|
|
301
|
-
if (options.values.includes("tailwind
|
|
304
|
+
if (options.values.includes("preact+tailwind")) {
|
|
302
305
|
console.log(chalk.green("Adding tailwind css"));
|
|
303
306
|
|
|
304
307
|
// read postcss.config.js
|
|
@@ -325,19 +328,19 @@ const run = async () => {
|
|
|
325
328
|
copyDir(path.resolve(cliPath, "./../preset/tailwind"), destinationFolder);
|
|
326
329
|
}
|
|
327
330
|
|
|
328
|
-
if (options.values.includes("preact")) {
|
|
331
|
+
if (options.values.includes("preact+tailwind")) {
|
|
329
332
|
console.log(chalk.green("Adding preact"));
|
|
330
333
|
const packageJson = path.join(destinationFolder, "package.json");
|
|
331
334
|
const packageJsonContent = fs.readFileSync(packageJson, "utf8");
|
|
332
335
|
let packageJsonContentJson = JSON.parse(packageJsonContent);
|
|
333
336
|
// delete index.ts
|
|
334
|
-
fs.rmSync(path.join(destinationFolder, "src/index.ts"), { force: true });
|
|
337
|
+
// fs.rmSync(path.join(destinationFolder, "src/index.ts"), { force: true });
|
|
335
338
|
const preactPresetFolder = path.resolve(cliPath, "./../preset/preact");
|
|
336
339
|
copyDirAndReplaceInFiles(preactPresetFolder, destinationFolder, pciName);
|
|
337
340
|
// add preact and @citolab/preact-store to the package json
|
|
338
341
|
packageJsonContentJson.dependencies = {
|
|
339
342
|
...packageJsonContentJson.dependencies,
|
|
340
|
-
preact: "^10.
|
|
343
|
+
preact: "^10.24.0",
|
|
341
344
|
"@citolab/preact-store": "latest",
|
|
342
345
|
};
|
|
343
346
|
packageJsonContentJson = { ...packageJsonContentJson, source: "src/index.tsx" };
|
|
@@ -345,6 +348,36 @@ const run = async () => {
|
|
|
345
348
|
fs.writeFileSync(packageJson, newPackageJsonContent);
|
|
346
349
|
}
|
|
347
350
|
|
|
351
|
+
if (options.values.includes("typescript")) {
|
|
352
|
+
copyDirAndReplaceInFiles(
|
|
353
|
+
path.resolve(cliPath, "./../preset/typescript/src"),
|
|
354
|
+
path.join(destinationFolder, "src"),
|
|
355
|
+
pciName
|
|
356
|
+
);
|
|
357
|
+
// point to the javascript file
|
|
358
|
+
const packageJson = path.join(destinationFolder, "package.json");
|
|
359
|
+
const packageJsonContent = fs.readFileSync(packageJson, "utf8");
|
|
360
|
+
let packageJsonContentJson = JSON.parse(packageJsonContent);
|
|
361
|
+
packageJsonContentJson.source = "src/index.ts";
|
|
362
|
+
const newPackageJsonContent = JSON.stringify(packageJsonContentJson, null, 2);
|
|
363
|
+
fs.writeFileSync(packageJson, newPackageJsonContent);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (options.values.includes("javascript")) {
|
|
367
|
+
copyDirAndReplaceInFiles(
|
|
368
|
+
path.resolve(cliPath, "./../preset/javascript/src"),
|
|
369
|
+
path.join(destinationFolder, "src"),
|
|
370
|
+
pciName
|
|
371
|
+
);
|
|
372
|
+
// point to the javascript file
|
|
373
|
+
const packageJson = path.join(destinationFolder, "package.json");
|
|
374
|
+
const packageJsonContent = fs.readFileSync(packageJson, "utf8");
|
|
375
|
+
let packageJsonContentJson = JSON.parse(packageJsonContent);
|
|
376
|
+
packageJsonContentJson.source = "src/index.js";
|
|
377
|
+
const newPackageJsonContent = JSON.stringify(packageJsonContentJson, null, 2);
|
|
378
|
+
fs.writeFileSync(packageJson, newPackageJsonContent);
|
|
379
|
+
}
|
|
380
|
+
|
|
348
381
|
// run npm install in destination folder
|
|
349
382
|
if (args.indexOf("--no-install") === -1) {
|
|
350
383
|
console.log(chalk.green("📦 Installing dependencies"));
|
|
@@ -353,7 +386,7 @@ const run = async () => {
|
|
|
353
386
|
console.log(chalk.blueBright(`Navigate to ${destinationFolder} or open this folder (e.g. with vscode).`));
|
|
354
387
|
console.log(chalk.blueBright(`Start the dev server with: npm run dev`));
|
|
355
388
|
console.log(chalk.blueBright(`Add support for TAO with: npm run tspci -- add --target tao`));
|
|
356
|
-
|
|
389
|
+
|
|
357
390
|
return;
|
|
358
391
|
} else {
|
|
359
392
|
console.log(chalk.yellow("Skipping npm install, run npm install in the project folder to install dependencies"));
|
|
@@ -391,14 +424,16 @@ const run = async () => {
|
|
|
391
424
|
}
|
|
392
425
|
});
|
|
393
426
|
}
|
|
394
|
-
|
|
395
427
|
};
|
|
396
428
|
|
|
397
429
|
// check if `@citolab/tspci-${targetname}]}` is already in devDependencies
|
|
398
430
|
if (!packageJson.devDependencies || !packageJson.devDependencies[`@citolab/tspci-${targetname}`]) {
|
|
399
431
|
console.log(chalk.white(`Adding @citolab/tspci-${targetname}`));
|
|
400
432
|
// install @citolab/tspci-${targetname} to devDepencies
|
|
401
|
-
execSync(`npm install @citolab/tspci-${targetname}@${version} --save-dev`, {
|
|
433
|
+
execSync(`npm install @citolab/tspci-${targetname}@${version} --save-dev`, {
|
|
434
|
+
cwd: PACKAGE_ROOT_PATH,
|
|
435
|
+
stdio: [0, 1, 2],
|
|
436
|
+
});
|
|
402
437
|
}
|
|
403
438
|
modifyPci();
|
|
404
439
|
|
|
@@ -413,7 +448,7 @@ const run = async () => {
|
|
|
413
448
|
if (dev) {
|
|
414
449
|
const devIndex = args.indexOf("--dev");
|
|
415
450
|
if (args.length <= devIndex + 1) {
|
|
416
|
-
console.
|
|
451
|
+
console.log("Using IMS template");
|
|
417
452
|
watchBuild(true);
|
|
418
453
|
} else {
|
|
419
454
|
const target = args[devIndex + 1];
|