@zenuml/core 3.32.2 → 3.32.4

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.
@@ -0,0 +1,76 @@
1
+ # Running Cypress Tests Locally
2
+
3
+ This document explains how to run Cypress tests locally on your machine, with a focus on ensuring color profiles match those used in GitHub Actions for consistent visual testing results.
4
+
5
+ ## Running Tests
6
+
7
+ You can run Cypress tests using the following commands:
8
+
9
+ - Run all tests headlessly:
10
+
11
+ ```bash
12
+ pnpm cy
13
+ ```
14
+
15
+ - Run a specific test file:
16
+
17
+ ```bash
18
+ pnpm cypress run --spec "cypress/e2e/smoke.spec.js"
19
+ ```
20
+
21
+ ## Color Profile Configuration
22
+
23
+ ### Why Color Profiles Matter
24
+
25
+ Visual regression tests in Cypress compare screenshots pixel-by-pixel. Different color profiles can cause the same UI to render with slightly different colors, leading to false test failures. To match the GitHub Actions environment, we use the sRGB color profile.
26
+
27
+ ### Automatic Configuration
28
+
29
+ Our Cypress configuration automatically forces the sRGB color profile when running tests. This is configured in `cypress/plugins/index.js` with the following code:
30
+
31
+ ```javascript
32
+ on("before:browser:launch", (browser = {}, launchOptions) => {
33
+ if (browser.family === "chromium" && browser.name !== "electron") {
34
+ launchOptions.args.push("--force-color-profile=srgb");
35
+ }
36
+ });
37
+ ```
38
+
39
+ ### Configuring macOS Color Profile
40
+
41
+ For the most consistent results, you should also configure your macOS system to use the sRGB color profile:
42
+
43
+ 1. Open System Preferences (or System Settings on newer macOS versions)
44
+ 2. Go to "Displays"
45
+ 3. Select the "Color" tab
46
+ 4. Click "Calibrate" to open the Display Calibrator Assistant
47
+ 5. Follow the wizard and when prompted for a color profile, select "sRGB"
48
+ 6. Complete the calibration and save the profile
49
+
50
+ Alternatively, you can directly select an existing sRGB profile:
51
+
52
+ 1. Open System Preferences > Displays > Color
53
+ 2. From the list of color profiles, select "sRGB IEC61966-2.1" or a similar sRGB profile
54
+ 3. Click "Apply"
55
+
56
+ ## Troubleshooting Visual Test Failures
57
+
58
+ If you encounter visual test failures despite using the sRGB profile:
59
+
60
+ 1. Check that your display brightness is set to a consistent level
61
+ 2. Ensure you're using the same browser version as GitHub Actions (Chrome)
62
+ 3. Verify that your OS theme/appearance settings match the CI environment (light mode is recommended)
63
+ 4. If necessary, adjust the threshold in the image snapshot configuration:
64
+
65
+ ```javascript
66
+ cy.document().toMatchImageSnapshot({
67
+ imageConfig: { threshold: 0.012 }, // Increase this value if needed
68
+ capture: "viewport",
69
+ });
70
+ ```
71
+
72
+ ## Additional Resources
73
+
74
+ - [Cypress Image Snapshot Documentation](https://github.com/jaredpalmer/cypress-image-snapshot)
75
+ - [Chrome Command Line Switches](https://peter.sh/experiments/chromium-command-line-switches/)
76
+ - [macOS Color Management Guide](https://support.apple.com/guide/mac-help/calibrate-your-display-mchlp2920/mac)
@@ -0,0 +1,35 @@
1
+ import js from "@eslint/js";
2
+ import globals from "globals";
3
+ import reactHooks from "eslint-plugin-react-hooks";
4
+ import reactRefresh from "eslint-plugin-react-refresh";
5
+ import tseslint from "typescript-eslint";
6
+ import eslintConfigPrettier from "eslint-config-prettier/flat";
7
+
8
+ export default tseslint.config(
9
+ { ignores: ["dist"] },
10
+ {
11
+ extends: [
12
+ js.configs.recommended,
13
+ ...tseslint.configs.recommended,
14
+ eslintConfigPrettier,
15
+ ],
16
+ files: ["**/*.{ts,tsx}"],
17
+ languageOptions: {
18
+ ecmaVersion: 2020,
19
+ globals: globals.browser,
20
+ },
21
+ plugins: {
22
+ "react-hooks": reactHooks,
23
+ "react-refresh": reactRefresh,
24
+ },
25
+ rules: {
26
+ ...reactHooks.configs.recommended.rules,
27
+ "react-refresh/only-export-components": [
28
+ "warn",
29
+ { allowConstantExport: true },
30
+ ],
31
+ "@typescript-eslint/no-unsafe-function-type": "off",
32
+ "@typescript-eslint/no-explicit-any": "off",
33
+ },
34
+ },
35
+ );
package/index.html CHANGED
@@ -1,6 +1,9 @@
1
1
  <!doctype html>
2
- <html>
2
+ <html lang="en">
3
3
  <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
4
7
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
5
8
  <link
6
9
  rel="preload stylesheet"
@@ -16,9 +19,6 @@
16
19
  /* font-family: "Kalam", serif;*/
17
20
  /*}*/
18
21
  </style>
19
- <meta charset="utf-8" />
20
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
21
- <meta name="viewport" content="width=device-width,initial-scale=1.0" />
22
22
  <link
23
23
  rel="stylesheet"
24
24
  href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/default.min.css"
@@ -34,10 +34,14 @@
34
34
  />
35
35
  <title>ZenUML Core Demo</title>
36
36
  <style>
37
+ body {
38
+ margin: 0;
39
+ }
37
40
  .CodeMirror {
38
41
  /* Set height, width, borders, and global font properties here */
39
42
  font-family: monospace;
40
43
  font-size: 13px;
44
+ height: 100vh;
41
45
  }
42
46
 
43
47
  .zenuml .CodeMirror .CodeMirror-cursor {
@@ -62,14 +66,7 @@
62
66
  }
63
67
  </style>
64
68
  </head>
65
-
66
69
  <body>
67
- <noscript>
68
- <strong
69
- >We're sorry but vue-sequence doesn't work properly without JavaScript
70
- enabled. Please enable it to continue.</strong
71
- >
72
- </noscript>
73
70
  <div class="m-1 grid grid-cols-6" id="diagram1">
74
71
  <div class="col-span-2">
75
72
  <textarea
@@ -121,6 +118,6 @@
121
118
  editor.setValue(savedCode);
122
119
  }
123
120
  </script>
124
- <script type="module" src="./src/main.ts"></script>
121
+ <script type="module" src="/src/main.tsx"></script>
125
122
  </body>
126
123
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenuml/core",
3
- "version": "3.32.2",
3
+ "version": "3.32.4",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -11,9 +11,9 @@
11
11
  "preview": "vite preview --port 8080 --host",
12
12
  "build:site": "vite build",
13
13
  "build:gh-pages": "vite build --mode gh-pages",
14
- "build": "vite build -c vite.config.lib.js",
14
+ "build": "vite build -c vite.config.lib.ts",
15
15
  "test": "vitest",
16
- "cy": "cypress run",
16
+ "cy": "cypress install & cypress run",
17
17
  "cy:update": "cypress run --env updateSnapshots=true",
18
18
  "cy:open": "cypress open",
19
19
  "cy:smoke": "cypress run --spec cypress/e2e/smoke.spec.js",
@@ -25,7 +25,7 @@
25
25
  "antlr:clear": "rm -rf src/generated-parser/*",
26
26
  "antlr:lexer": "java -Duser.dir=$(pwd)/src/g4 -cp $(pwd)/antlr/antlr-4.11.1-complete.jar org.antlr.v4.Tool -o ./src/generated-parser -Dlanguage=JavaScript sequenceLexer.g4",
27
27
  "antlr:parser": "java -Duser.dir=$(pwd)/src/g4 -cp $(pwd)/antlr/antlr-4.11.1-complete.jar org.antlr.v4.Tool -o ./src/generated-parser -Dlanguage=JavaScript sequenceParser.g4",
28
- "eslint": "eslint --fix --ext .js,.ts,.vue src",
28
+ "eslint": "eslint --fix --ext .js,.ts,.tsx,.jsx src",
29
29
  "prettier": "prettier --write --ignore-unknown \"src/**/*.{js,ts,vue,json,htm,html}\"",
30
30
  "git:branch:clean:gone": "git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d",
31
31
  "git:branch:clean:merged": "git branch --merged|egrep -v \"(\\*|master|main|dev|skip_branch_name)\" | xargs git branch -d",
@@ -39,87 +39,80 @@
39
39
  "types": "./types/index.d.ts",
40
40
  "lint-staged": {
41
41
  "**/*": "prettier --write --ignore-unknown",
42
- "*.{js,ts,vue,json,htm,html}": "eslint --fix"
42
+ "*.{js,ts,tsx,jsx,json,htm,html}": "eslint --fix"
43
+ },
44
+ "engines": {
45
+ "node": ">=20"
46
+ },
47
+ "postcss": {
48
+ "plugins": {
49
+ "tailwindcss": {},
50
+ "autoprefixer": {}
51
+ }
52
+ },
53
+ "pnpm": {
54
+ "overrides": {
55
+ "react": "^19.0.0",
56
+ "react-dom": "^19.0.0"
57
+ }
43
58
  },
44
59
  "dependencies": {
45
- "@headlessui-float/vue": "^0.14.0",
46
- "@headlessui/tailwindcss": "^0.2.0",
47
- "@headlessui/vue": "^1.7.16",
48
- "@types/assert": "^1.5.6",
49
- "@types/ramda": "^0.28.20",
50
- "@vue/compat": "^3.2.45",
60
+ "@floating-ui/react": "^0.27.8",
61
+ "@headlessui/react": "^2.2.1",
62
+ "@headlessui/tailwindcss": "^0.2.2",
51
63
  "antlr4": "~4.11.0",
52
- "color-string": "^1.5.5",
53
- "dom-to-image-more": "^2.13.0",
54
- "dompurify": "^3.1.5",
55
- "file-saver": "^2.0.5",
64
+ "class-variance-authority": "^0.7.1",
65
+ "clsx": "^2.1.1",
66
+ "color-string": "^2.0.1",
67
+ "dompurify": "^3.2.5",
56
68
  "highlight.js": "^10.7.3",
57
- "html-to-image": "^1.11.3",
58
- "lodash": "^4.17.21",
59
- "marked": "^4.0.10",
69
+ "html-to-image": "^1.11.13",
70
+ "immer": "^10.1.1",
71
+ "jotai": "^2.12.2",
72
+ "marked": "^4.3.0",
60
73
  "pino": "^8.8.0",
61
- "postcss": "^8.4.31",
74
+ "radash": "^12.1.0",
62
75
  "ramda": "^0.28.0",
63
- "tailwindcss": "^3.4.17",
64
- "vue": "^3.2.45",
65
- "vuex": "^4.1.0"
76
+ "react": "^19.0.0",
77
+ "react-dom": "^19.0.0",
78
+ "tailwind-merge": "^3.1.0",
79
+ "tailwindcss": "^3.4.17"
66
80
  },
67
81
  "devDependencies": {
68
- "@babel/eslint-parser": "^7.19.1",
69
- "@babel/preset-env": "^7.20.2",
82
+ "@eslint/js": "^9.21.0",
83
+ "@testing-library/jest-dom": "^6.6.3",
84
+ "@testing-library/react": "^16.3.0",
70
85
  "@types/antlr4": "~4.11.2",
71
- "@types/color-string": "^1.5.2",
72
- "@types/jest": "^29.5.14",
86
+ "@types/color-string": "^1.5.5",
87
+ "@types/highlight.js": "10",
73
88
  "@types/jsdom": "^21.1.7",
74
- "@types/lodash": "^4.14.191",
75
- "@types/node": "latest",
76
- "@typescript-eslint/eslint-plugin": "^6.7.4",
77
- "@typescript-eslint/parser": "^6.7.4",
78
- "@vitejs/plugin-vue": "^4.0.0",
79
- "@vitest/coverage-v8": "^2.1.5",
80
- "@vue/compiler-dom": "^3.3.8",
81
- "@vue/compiler-sfc": "^3.2.45",
82
- "@vue/test-utils": "^2.2.7",
83
- "autoprefixer": "^10.4.13",
84
- "concurrently": "^7.6.0",
85
- "cypress": "^10.11.0",
89
+ "@types/marked": "^4.3.2",
90
+ "@types/node": "^22.14.0",
91
+ "@types/ramda": "^0.28.20",
92
+ "@types/react": "^19.0.10",
93
+ "@types/react-dom": "^19.0.4",
94
+ "@vitejs/plugin-react": "^4.3.4",
95
+ "autoprefixer": "^10.4.21",
96
+ "cypress": "^14.3.2",
86
97
  "cypress-plugin-snapshots": "^1.4.4",
87
- "eslint": "^8.30.0",
88
- "eslint-config-prettier": "^9.0.0",
89
- "eslint-plugin-html": "^7.1.0",
90
- "eslint-plugin-prettier": "^5.0.0",
91
- "eslint-plugin-vue": "^9.17.0",
92
- "global-jsdom": "^8.6.0",
93
- "husky": "^8.0.3",
94
- "jsdom": "^20.0.3",
95
- "less": "^4.1.3",
96
- "less-loader": "^11.1.3",
97
- "lint-staged": "^14.0.1",
98
- "prettier": "^3.0.3",
99
- "regenerator-runtime": "^0.13.11",
100
- "sass": "^1.57.0",
101
- "svg-url-loader": "^6.0.0",
102
- "terser-webpack-plugin": "^3.1.0",
103
- "ts-node": "^10.9.1",
104
- "typescript": "^5.6.3",
105
- "vite": "^4.5.6",
106
- "vite-plugin-css-injected-by-js": "^2.2.0",
107
- "vite-svg-loader": "^4.0.0",
108
- "vitest": "^2.1.5"
109
- },
110
- "postcss": {
111
- "plugins": {
112
- "tailwindcss": {},
113
- "autoprefixer": {}
114
- }
115
- },
116
- "browserslist": [
117
- "last 2 years"
118
- ],
119
- "engines": {
120
- "node": ">=12.0.0"
121
- },
122
- "volta": {
123
- "node": "18.12.1"
98
+ "eslint": "^9.21.0",
99
+ "eslint-config-prettier": "^10.1.1",
100
+ "eslint-plugin-react-hooks": "^5.1.0",
101
+ "eslint-plugin-react-refresh": "^0.4.19",
102
+ "globals": "^15.15.0",
103
+ "husky": "^9.1.7",
104
+ "jsdom": "^26.1.0",
105
+ "less": "^4.3.0",
106
+ "lint-staged": "^15.5.1",
107
+ "postcss": "^8.5.3",
108
+ "prettier": "3.5.3",
109
+ "sass": "^1.86.3",
110
+ "typescript": "~5.7.2",
111
+ "typescript-eslint": "^8.24.1",
112
+ "vite": "^6.2.0",
113
+ "vite-plugin-css-injected-by-js": "^3.5.2",
114
+ "vite-plugin-svgr": "^4.3.0",
115
+ "vite-svg-loader": "^5.1.0",
116
+ "vitest": "^3.1.1"
124
117
  }
125
118
  }
@@ -0,0 +1,31 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "ES2020",
5
+ "useDefineForClassFields": true,
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
8
+ "skipLibCheck": true,
9
+ "paths": {
10
+ "@/*": ["./src/*"]
11
+ },
12
+ "allowJs": true,
13
+ "types": ["vitest/globals", "@testing-library/jest-dom"],
14
+
15
+ /* Bundler mode */
16
+ "moduleResolution": "bundler",
17
+ "allowImportingTsExtensions": true,
18
+ "isolatedModules": true,
19
+ "moduleDetection": "force",
20
+ "noEmit": true,
21
+ "jsx": "react-jsx",
22
+
23
+ /* Linting */
24
+ "strict": true,
25
+ "noUnusedLocals": true,
26
+ "noUnusedParameters": true,
27
+ "noFallthroughCasesInSwitch": true,
28
+ "noUncheckedSideEffectImports": true
29
+ },
30
+ "include": ["src"]
31
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2022",
5
+ "lib": ["ES2023"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "isolatedModules": true,
13
+ "moduleDetection": "force",
14
+ "noEmit": true,
15
+
16
+ /* Linting */
17
+ "strict": true,
18
+ "noUnusedLocals": true,
19
+ "noUnusedParameters": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "noUncheckedSideEffectImports": true
22
+ },
23
+ "include": ["vite.config.ts"]
24
+ }
@@ -1,9 +1,9 @@
1
- /* eslint-env es6 */
1
+ /* eslint-env node */
2
2
  import { resolve } from "path";
3
3
  import { defineConfig } from "vite";
4
- import createVuePlugin from "@vitejs/plugin-vue";
4
+ import react from "@vitejs/plugin-react";
5
5
  import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
6
- import svgLoader from "vite-svg-loader";
6
+ import svgr from "vite-plugin-svgr";
7
7
  import { readFileSync } from "fs";
8
8
 
9
9
  // Read version from package.json
@@ -15,17 +15,17 @@ export default defineConfig({
15
15
  build: {
16
16
  // https://vitejs.dev/guide/build.html#library-mode
17
17
  lib: {
18
- entry: resolve(__dirname, "src/core.ts"),
18
+ entry: resolve(__dirname, "src/core.tsx"),
19
19
  // https://vitejs.dev/config/build-options.html#build-lib
20
20
  // the exposed global variable and is required when formats includes 'umd' or 'iife'.
21
21
  name: "ZenUML",
22
22
  fileName: "zenuml",
23
23
  },
24
+ sourcemap: true,
24
25
  rollupOptions: {
25
26
  output: [
26
27
  {
27
28
  format: "esm",
28
- sourcemap: true,
29
29
  // https://rollupjs.org/guide/en/#outputentryfilenames
30
30
  // It will use the file name in `build.lib.entry` without extension as `[name]` if `[name].xxx.yyy` is provided.
31
31
  // So we hard code as zenuml. We may consider rename `core.ts` to `zenuml.ts`.
@@ -36,7 +36,6 @@ export default defineConfig({
36
36
  {
37
37
  name: "zenuml", // it is the global variable name representing your bundle. https://rollupjs.org/guide/en/#outputname
38
38
  format: "umd",
39
- sourcemap: true,
40
39
  entryFileNames: `zenuml.js`,
41
40
  },
42
41
  ],
@@ -44,23 +43,10 @@ export default defineConfig({
44
43
  },
45
44
  resolve: {
46
45
  alias: {
47
- vue: "@vue/compat",
48
46
  "@": resolve(__dirname, "./src"),
49
47
  },
50
48
  },
51
- plugins: [
52
- svgLoader(),
53
- createVuePlugin({
54
- template: {
55
- compilerOptions: {
56
- compatConfig: {
57
- MODE: 2,
58
- },
59
- },
60
- },
61
- }),
62
- cssInjectedByJsPlugin(),
63
- ],
49
+ plugins: [svgr(), react(), cssInjectedByJsPlugin()],
64
50
  define: {
65
51
  "process.env.NODE_ENV": '"production"',
66
52
  "process.env.VITE_VERSION": JSON.stringify(packageJson.version),
@@ -1,9 +1,9 @@
1
- import { resolve } from "path";
2
1
  import { defineConfig } from "vite";
3
- import createVuePlugin from "@vitejs/plugin-vue";
2
+ import react from "@vitejs/plugin-react";
3
+ import { resolve } from "path";
4
4
  import { execSync } from "child_process";
5
- import svgLoader from "vite-svg-loader";
6
5
  import { readFileSync } from "fs";
6
+ import svgr from "vite-plugin-svgr";
7
7
 
8
8
  process.env.VITE_APP_GIT_HASH = process.env.DOCKER
9
9
  ? ""
@@ -12,7 +12,6 @@ process.env.VITE_APP_GIT_BRANCH = process.env.DOCKER
12
12
  ? ""
13
13
  : execSync("git branch --show-current").toString().trim();
14
14
 
15
- // Read version from package.json
16
15
  const packageJson = JSON.parse(
17
16
  readFileSync(resolve(__dirname, "package.json"), "utf-8"),
18
17
  );
@@ -28,7 +27,6 @@ function getCypressHtmlFiles() {
28
27
  }
29
28
 
30
29
  const cypressHtmlFiles = getCypressHtmlFiles();
31
- console.log(cypressHtmlFiles);
32
30
 
33
31
  export default defineConfig(({ mode }) => ({
34
32
  base: mode === "gh-pages" ? "/zenuml-core/" : "/",
@@ -39,27 +37,22 @@ export default defineConfig(({ mode }) => ({
39
37
  },
40
38
  resolve: {
41
39
  alias: {
42
- vue: "@vue/compat",
43
40
  "@": resolve(__dirname, "./src"),
44
41
  },
45
42
  },
46
- plugins: [
47
- createVuePlugin({
48
- template: {
49
- compilerOptions: {
50
- compatConfig: {
51
- MODE: 2,
52
- },
53
- },
54
- },
55
- }),
56
- svgLoader(),
57
- ],
43
+ plugins: [svgr(), react()],
58
44
  define: {
59
45
  "process.env.NODE_ENV": JSON.stringify(mode),
60
46
  "process.env.VITE_BUILD_TIME": JSON.stringify(new Date().toISOString()),
61
47
  "process.env.VITE_VERSION": JSON.stringify(packageJson.version),
62
48
  },
49
+ css: {
50
+ preprocessorOptions: {
51
+ scss: {
52
+ api: "modern-compiler",
53
+ },
54
+ },
55
+ },
63
56
  test: {
64
57
  // used by vitest: https://vitest.dev/guide/#configuring-vitest
65
58
  environment: "jsdom",
@@ -68,8 +61,6 @@ export default defineConfig(({ mode }) => ({
68
61
  coverage: {
69
62
  provider: "v8", // or 'v8'
70
63
  },
71
- deps: {
72
- inline: ["@vue/test-utils"],
73
- },
64
+ setupFiles: resolve(__dirname, "test/setup.ts"),
74
65
  },
75
66
  }));