xcratch-create 1.0.1 → 1.2.0

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/bin/create.js CHANGED
@@ -1,28 +1,25 @@
1
1
  #!/usr/bin/env node
2
- 'use strict'
3
2
 
4
- const path = require('path');
5
- const replace = require('replace-in-file');
6
- const fs = require('fs-extra');
7
- const admZip = require('adm-zip');
8
- const projectJson = require('../package.json');
3
+ import path from 'path';
4
+ import { replaceInFile } from 'replace-in-file';
5
+ import fs from 'fs-extra';
6
+ import AdmZip from 'adm-zip';
7
+ import projectJson from '../package.json' assert { type: 'json' };
8
+
9
+ const __dirname = path.dirname(new URL(import.meta.url).pathname);
9
10
 
10
11
  function getArgs() {
11
12
  const args = {};
12
13
  process.argv
13
- .slice(2, process.argv.length)
14
+ .slice(2) // Start from the third argument (ignoring Node and script path)
14
15
  .forEach(arg => {
15
- if (arg.slice(0, 2) === '--') {
16
- // long arg
17
- const longArg = arg.split('=');
18
- const longArgFlag = longArg[0].slice(2, longArg[0].length);
19
- const longArgValue = longArg.length > 1 ? longArg[1] : true;
20
- args[longArgFlag] = longArgValue;
21
- }
22
- else if (arg[0] === '-') {
23
- // flags
24
- const flags = arg.slice(1, arg.length).split('');
25
- flags.forEach(flag => {
16
+ if (arg.startsWith('--')) {
17
+ // Long argument (e.g., --account=my-account)
18
+ const [longArgFlag, ...rest] = arg.slice(2).split('=');
19
+ args[longArgFlag] = rest.join('=') || true; // Handle arguments with and without values
20
+ } else if (arg.startsWith('-')) {
21
+ // Flags (e.g., -abc becomes args.a = args.b = args.c = true)
22
+ arg.slice(1).split('').forEach(flag => {
26
23
  args[flag] = true;
27
24
  });
28
25
  }
@@ -32,85 +29,97 @@ function getArgs() {
32
29
 
33
30
  const args = getArgs();
34
31
 
35
- if (args['version'] || args['V']) {
32
+ // Check for version request
33
+ if (args.version || args.V) {
36
34
  process.stdout.write(`v${projectJson.version}\n`);
37
- process.exit(0);
35
+ process.exit(0); // Exit successfully after displaying version
38
36
  }
39
37
 
40
- if (!args['account']) {
38
+ // Validate required arguments
39
+ if (!args.account) {
41
40
  process.stderr.write('"--account=<github account>" is not set\n');
42
- process.exit(1);
41
+ process.exit(1); // Exit with an error code
43
42
  }
44
- const account = args['account'];
43
+ const account = args.account;
45
44
 
46
- if (!args['repo']) {
45
+ if (!args.repo) {
47
46
  process.stderr.write('"--repo=<github repository>" is not set\n');
48
47
  process.exit(1);
49
48
  }
50
- const repo = args['repo'];
49
+ const repo = args.repo;
51
50
 
52
- if (!args['extensionID']) {
51
+ if (!args.extensionID) {
53
52
  process.stderr.write('"--extensionID=<extension ID>" is not set\n');
54
53
  process.exit(1);
55
54
  }
56
- const extensionID = args['extensionID'];
55
+ const extensionID = args.extensionID;
57
56
 
58
- if (!args['extensionName']) {
57
+ if (!args.extensionName) {
59
58
  process.stderr.write('"--extensionName=<extension name>" is not set\n');
60
59
  process.exit(1);
61
60
  }
62
- const extensionName = args['extensionName'];
61
+ const extensionName = args.extensionName;
63
62
 
64
- const outputDir = args['out'] ?
65
- path.resolve(process.cwd(), args['out']) :
66
- path.resolve(process.cwd(), repo);
63
+ // Determine output directory
64
+ const outputDir = args.out
65
+ ? path.resolve(process.cwd(), args.out)
66
+ : path.resolve(process.cwd(), repo);
67
67
 
68
- /**
69
- * Fetch template files
70
- *
71
- */
68
+ // Fetch the project template
72
69
  async function fetchTemplate() {
73
- fs.copySync(path.resolve(__dirname, '../template'), outputDir);
70
+ try {
71
+ await fs.copy(path.resolve(__dirname, '../template'), outputDir);
72
+ } catch (error) {
73
+ console.error('Error fetching template:', error);
74
+ process.exit(1);
75
+ }
74
76
  }
75
77
 
78
+ // Replacement options for template files
76
79
  const options = {
77
- files: [
78
- './**/*',
79
- ],
80
+ files: ['./**/*'], // Target all files in the output directory
80
81
  from: [
81
82
  /<<account>>/g,
82
83
  /<<repo>>/g,
83
84
  /<<extensionID>>/g,
84
85
  /<<extensionName>>/g,
85
86
  ],
86
- to: [
87
- account,
88
- repo,
89
- extensionID,
90
- extensionName,
91
- ],
87
+ to: [account, repo, extensionID, extensionName],
92
88
  };
93
89
 
90
+ // Customize the template with provided arguments
94
91
  async function resetRepo() {
95
- process.chdir(outputDir);
96
- fs.renameSync('dot_gitignore', '.gitignore');
97
92
  try {
98
- const results = await replace(options)
99
- console.log('Replacement results:', results);
100
- }
101
- catch (error) {
102
- console.error('Error occurred:', error);
103
- }
104
- try {
105
- const zip = new admZip();
93
+ process.chdir(outputDir); // Change working directory to the output directory
94
+
95
+ // Rename .gitignore file
96
+ await fs.rename('dot_gitignore', '.gitignore');
97
+
98
+ // Replace placeholders in template files
99
+ await replaceInFile(options);
100
+
101
+ // Zip the example project directory
102
+ const zip = new AdmZip();
106
103
  const examplePath = path.resolve(outputDir, 'projects/example');
107
104
  zip.addLocalFolder(examplePath);
108
105
  zip.writeZip(path.resolve(outputDir, 'projects/example.sb3'));
109
- fs.rm(examplePath, {recursive:true, force:true});
106
+
107
+ // Remove the original example directory
108
+ await fs.rm(examplePath, { recursive: true, force: true });
109
+
110
+ console.log(`Scaffolding project created at: ${outputDir}`);
111
+
110
112
  } catch (error) {
111
113
  console.error('Error occurred:', error);
114
+ process.exit(1);
112
115
  }
113
116
  }
114
117
 
118
+ // Execute the setup process
115
119
  fetchTemplate()
116
- .then(() => resetRepo());
120
+ .then(resetRepo)
121
+ .catch(error => {
122
+ console.error('Error during setup:', error);
123
+ process.exit(1);
124
+ });
125
+
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "xcratch-create",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "Support tool to create new extension for Xcratch",
5
+ "type": "module",
5
6
  "bin": {
6
7
  "xcratch-create": "./bin/create.js"
7
8
  },
@@ -27,8 +28,8 @@
27
28
  },
28
29
  "homepage": "https://github.com/xcratch/xcratch-create#readme",
29
30
  "dependencies": {
30
- "adm-zip": "^0.5.10",
31
- "fs-extra": "^11.2.0",
32
- "replace-in-file": "^7.1.0"
31
+ "adm-zip": "^0.5.16",
32
+ "fs-extra": "^11.3.0",
33
+ "replace-in-file": "^8.3.0"
33
34
  }
34
35
  }
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ testEnvironment: 'node',
3
+ transform: {
4
+ '^.+\\.jsx?$': 'babel-jest'
5
+ },
6
+ setupFilesAfterEnv: ['./test/setup-test.js'],
7
+ moduleNameMapper: {
8
+ '\\.(png|jpg|jpeg|gif|svg)$': '<rootDir>/test/mocks/fileMock.js'
9
+ },
10
+ testMatch: ['**/test/unit/**/*.test.js'],
11
+ };
@@ -1,36 +1,36 @@
1
1
  {
2
2
  "name": "<<repo>>",
3
3
  "version": "0.0.0",
4
+ "description": "extension for Xcratch",
4
5
  "scripts": {
5
6
  "setup-dev": "node ./scripts/setup-dev.mjs",
6
7
  "build": "rollup -c ./scripts/rollup.config.mjs",
7
8
  "watch": "rollup -c ./scripts/rollup.config.mjs --watch",
8
- "test": "mocha"
9
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
9
10
  },
10
11
  "devDependencies": {
11
- "@babel/core": "^7.24.0",
12
- "@babel/eslint-parser": "^7.23.10",
13
- "@babel/plugin-transform-react-jsx": "^7.23.4",
14
- "@babel/plugin-transform-runtime": "^7.24.0",
15
- "@babel/preset-env": "^7.24.0",
16
- "@babel/preset-react": "^7.23.3",
17
- "@babel/register": "^7.23.7",
12
+ "@babel/core": "^7.26.9",
13
+ "@babel/eslint-parser": "^7.26.8",
14
+ "@babel/plugin-transform-react-jsx": "^7.25.9",
15
+ "@babel/plugin-transform-runtime": "^7.26.9",
16
+ "@babel/preset-env": "^7.26.9",
17
+ "@babel/preset-react": "^7.26.3",
18
+ "@babel/register": "^7.25.9",
18
19
  "@rollup/plugin-babel": "^6.0.4",
19
- "@rollup/plugin-commonjs": "^25.0.7",
20
+ "@rollup/plugin-commonjs": "^28.0.2",
20
21
  "@rollup/plugin-image": "^3.0.3",
21
22
  "@rollup/plugin-json": "^6.1.0",
22
23
  "@rollup/plugin-multi-entry": "^6.0.1",
23
- "@rollup/plugin-node-resolve": "^15.2.3",
24
- "chai": "^5.1.0",
25
- "core-js": "^3.36.0",
24
+ "@rollup/plugin-node-resolve": "^16.0.0",
25
+ "core-js": "^3.40.0",
26
26
  "eslint": "^8.57.0",
27
- "eslint-config-scratch": "^9.0.8",
28
- "eslint-plugin-import": "^2.29.1",
29
- "eslint-plugin-mocha": "^10.4.1",
30
- "fs-extra": "^11.2.0",
31
- "mocha": "^10.3.0",
32
- "rollup": "^4.12.1",
33
- "rollup-plugin-node-globals": "^1.4.0",
27
+ "eslint-config-scratch": "^9.0.9",
28
+ "eslint-plugin-import": "^2.31.0",
29
+ "eslint-plugin-jest": "^27.6.3",
30
+ "fs-extra": "^11.3.0",
31
+ "jest": "^29.7.0",
32
+ "jest-environment-jsdom": "^29.7.0",
33
+ "rollup": "^4.34.7",
34
34
  "rollup-plugin-polyfill-node": "^0.13.0"
35
35
  }
36
- }
36
+ }
@@ -4,7 +4,6 @@ import fs from 'fs-extra';
4
4
  import babel from '@rollup/plugin-babel';
5
5
  import commonjs from '@rollup/plugin-commonjs';
6
6
  import nodeResolve from '@rollup/plugin-node-resolve';
7
- import nodeGlobals from 'rollup-plugin-node-globals';
8
7
  import nodePolifills from 'rollup-plugin-polyfill-node';
9
8
  import importImage from '@rollup/plugin-image';
10
9
  import multi from '@rollup/plugin-multi-entry';
@@ -28,11 +27,10 @@ const rollupOptions = {
28
27
  multi(),
29
28
  importImage(),
30
29
  commonjs(),
31
- nodeGlobals(),
32
30
  nodePolifills(),
33
31
  nodeResolve({
34
32
  browser: true,
35
- preferBuiltins: true,
33
+ preferBuiltins: false,
36
34
  modulePaths: [
37
35
  path.resolve(process.cwd(), './node_modules'),
38
36
  ],
@@ -57,10 +55,8 @@ const rollupOptions = {
57
55
  babelHelpers: 'runtime',
58
56
  plugins: [
59
57
  '@babel/plugin-transform-react-jsx',
60
- [
61
- "@babel/plugin-transform-runtime",
62
- { "regenerator": true }
63
- ]
58
+ ["@babel/plugin-transform-runtime",
59
+ { "regenerator": true }]
64
60
  ],
65
61
  }),
66
62
  ],
@@ -76,8 +72,7 @@ const rollupOptions = {
76
72
  },
77
73
  buildDelay: 500,
78
74
  },
79
- external: [
80
- ],
75
+ external: [],
81
76
  }
82
77
 
83
78
  export default rollupOptions;
@@ -8,8 +8,13 @@ module.exports = {
8
8
  process: true
9
9
  },
10
10
  rules: {
11
+ // BEGIN: these caused trouble after upgrading eslint-plugin-react from 7.24.0 to 7.33.2
12
+ 'react/forbid-prop-types': 'off',
13
+ 'react/no-unknown-property': 'off',
14
+ // END: these caused trouble after upgrading eslint-plugin-react from 7.24.0 to 7.33.2
15
+ 'no-warning-comments': 'off',
11
16
  'import/no-mutable-exports': 'error',
12
- // 'import/no-commonjs': 'error',
17
+ 'import/no-commonjs': 'error',
13
18
  'import/no-amd': 'error',
14
19
  'import/no-nodejs-modules': 'error',
15
20
  'react/jsx-no-literals': 'error',
@@ -17,8 +22,19 @@ module.exports = {
17
22
  allowParens: true
18
23
  }]
19
24
  },
25
+ overrides: [
26
+ {
27
+ files: ['**/.eslintrc.js'],
28
+ env: {
29
+ node: true
30
+ },
31
+ rules: {
32
+ 'import/no-commonjs': 'off'
33
+ }
34
+ }
35
+ ],
20
36
  settings: {
21
- react: {
37
+ 'react': {
22
38
  version: '16.2' // Prevent 16.3 lifecycle method errors
23
39
  }
24
40
  }
@@ -34,6 +34,7 @@ const entry = {
34
34
  id: '<<extensionID>>.entry.description'
35
35
  });
36
36
  },
37
+ tags: [],
37
38
  featured: true,
38
39
  disabled: false,
39
40
  bluetoothRequired: false,
@@ -1,7 +1,6 @@
1
1
  import BlockType from '../../extension-support/block-type';
2
2
  import ArgumentType from '../../extension-support/argument-type';
3
3
  import Cast from '../../util/cast';
4
- import log from '../../util/log';
5
4
  import translations from './translations.json';
6
5
  import blockIcon from './block-icon.png';
7
6
 
@@ -138,7 +137,7 @@ class ExtensionBlocks {
138
137
  doIt (args) {
139
138
  const statement = Cast.toString(args.SCRIPT);
140
139
  const func = new Function(`return (${statement})`);
141
- log.log(`doIt: ${statement}`);
140
+ console.log(`doIt: ${statement}`);
142
141
  return func.call(this);
143
142
  }
144
143
  }
@@ -1,11 +1,11 @@
1
1
  module.exports = {
2
2
  root: true,
3
- plugins: ["mocha"],
4
- extends: ["plugin:mocha/recommended"],
3
+ plugins: ["jest"],
4
+ extends: ["plugin:jest/recommended"],
5
5
  env: {
6
6
  browser: true,
7
7
  es6: true,
8
- mocha: true,
8
+ "jest/globals": true,
9
9
  },
10
10
  parserOptions: {
11
11
  sourceType: "module",
@@ -0,0 +1 @@
1
+ module.exports = 'test-file-stub';
@@ -1,4 +1,2 @@
1
- require.extensions[".png"] = function () {
2
- return null;
3
- };
4
-
1
+ // Jest automatically handles require extensions through moduleNameMapper in jest.config.js
2
+ // This file is still used for any additional test setup
@@ -1,5 +1,3 @@
1
- import { describe, it } from "mocha";
2
- import { expect } from "chai";
3
1
  import { blockClass } from "../../src/vm/extensions/block/index.js";
4
2
 
5
3
  describe("blockClass", () => {
@@ -8,14 +6,15 @@ describe("blockClass", () => {
8
6
  return msg.default;
9
7
  }
10
8
  };
11
- it("should create an instance of blockClass", () => {
9
+
10
+ test("should create an instance of blockClass", () => {
12
11
  const block = new blockClass(runtime);
13
- expect(block).to.be.an.instanceOf(blockClass);
12
+ expect(block).toBeInstanceOf(blockClass);
14
13
  });
15
14
 
16
- it("doIt('3 + 4') should return 7", () => {
15
+ test("doIt('3 + 4') should return 7", () => {
17
16
  const block = new blockClass(runtime);
18
17
  const result = block.doIt({SCRIPT: "3 + 4"});
19
- expect(result).to.equal(7);
18
+ expect(result).toBe(7);
20
19
  });
21
20
  });
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- require: ["@babel/register", "./test/setup-test.js"],
3
- spec: "test/unit/**/*.test.js",
4
- };