@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 CHANGED
@@ -1,50 +1,50 @@
1
1
  {
2
2
  "name": "@citolab/tspci",
3
- "version": "2.5.0",
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.0.0",
14
- "@rollup/plugin-babel": "^6.0.3",
15
- "@rollup/plugin-commonjs": "^24.1.0",
16
- "@rollup/plugin-image": "^3.0.2",
17
- "@rollup/plugin-json": "^6.0.0",
18
- "@rollup/plugin-node-resolve": "^15.0.2",
19
- "@rollup/plugin-replace": "^5.0.2",
20
- "@rollup/plugin-terser": "^0.4.1",
21
- "@rollup/plugin-typescript": "^11.1.0",
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": "^9.2.0",
24
- "@types/node": "^18.16.3",
25
- "@typescript-eslint/eslint-plugin": "^5.59.2",
26
- "@typescript-eslint/parser": "^5.59.2",
27
- "autoprefixer": "10.4.14",
28
- "chalk": "5.2.0",
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.6.0",
31
- "inquirer": "9.2.0",
34
+ "figlet": "1.7.0",
35
+ "inquirer": "11.0.1",
32
36
  "live-server": "^1.2.2",
33
- "postcss": "^8.4.23",
34
- "postcss-import": "^15.1.0",
35
- "rollup": "^3.21.4",
36
- "rollup-plugin-copy": "^3.4.0",
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.3.2"
44
- },
45
- "scripts": {
46
- "help": "tspci --help",
47
- "init": "tspci init --force --path=../../pcis"
47
+ "tailwindcss": "^3.4.11"
48
48
  },
49
- "gitHead": "97b99b32afa946f3a85b3cfe6743fa7857d77091"
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();
@@ -67,6 +67,7 @@ class App implements IMSpci<PropTypes> {
67
67
  },
68
68
  } as QtiVariableJSON;
69
69
  }
70
+ oncompleted = () => { };
70
71
  }
71
72
 
72
73
  export default new App();
@@ -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).value;
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 = (this.state === null || this.state === undefined) ? undefined : { base: { integer: this.state }} as QtiVariableJSON;
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 add options: tailwind and preact (both are selected by default, for more info; keep reading).
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: "checkbox",
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 = (await askOption("What your pci identifier (typeIdentifier). this can only contain alphanumeric characters (default: myPci) ")) || "myPci";
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("Would you like to add other features?", ["tailwind css", "preact"]);
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 css")) {
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.13.2",
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`, { cwd: PACKAGE_ROOT_PATH, stdio: [0, 1, 2] });
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.error("Missing dev target name. Using IMS template");
451
+ console.log("Using IMS template");
417
452
  watchBuild(true);
418
453
  } else {
419
454
  const target = args[devIndex + 1];