@emasoft/svg-matrix 1.0.16 → 1.0.17

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@emasoft/svg-matrix",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "description": "Arbitrary-precision matrix, vector and affine transformation library for JavaScript using decimal.js",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -9,7 +9,11 @@
9
9
  "test:browser": "node test/browser-verify.mjs",
10
10
  "test:playwright": "node test/playwright-diagnose.js",
11
11
  "ci-test": "npm ci && npm test",
12
- "prepublishOnly": "npm test",
12
+ "version:sync": "node scripts/version-sync.js",
13
+ "version:check": "node scripts/version-sync.js --check",
14
+ "preversion": "npm run version:sync",
15
+ "version": "node scripts/version-sync.js && git add src/index.js package-lock.json",
16
+ "prepublishOnly": "npm run version:check && npm test",
13
17
  "postinstall": "node scripts/postinstall.js || true"
14
18
  },
15
19
  "repository": {
@@ -137,7 +137,7 @@ ${c.cyan}${B.v}${c.reset}${R(` ${c.green}${B.dot} Transforms3D${c.reset} 3D af
137
137
  ${c.cyan}${B.v}${c.reset}${R('')}${c.cyan}${B.v}${c.reset}
138
138
  ${c.cyan}${B.v}${hr}${B.v}${c.reset}
139
139
  ${c.cyan}${B.v}${c.reset}${R('')}${c.cyan}${B.v}${c.reset}
140
- ${c.cyan}${B.v}${c.reset}${R(` ${c.yellow}New in v1.0.16:${c.reset}`)}${c.cyan}${B.v}${c.reset}
140
+ ${c.cyan}${B.v}${c.reset}${R(` ${c.yellow}New in v1.0.17:${c.reset}`)}${c.cyan}${B.v}${c.reset}
141
141
  ${c.cyan}${B.v}${c.reset}${R(` ${c.green}${B.dot}${c.reset} Enhanced CLI help: svg-matrix <command> --help`)}${c.cyan}${B.v}${c.reset}
142
142
  ${c.cyan}${B.v}${c.reset}${R(` ${c.green}${B.dot}${c.reset} High-precision Bezier circle/ellipse approximation`)}${c.cyan}${B.v}${c.reset}
143
143
  ${c.cyan}${B.v}${c.reset}${R(` ${c.green}${B.dot}${c.reset} E2E verification always enabled for precision`)}${c.cyan}${B.v}${c.reset}
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @fileoverview Version synchronization script for @emasoft/svg-matrix
4
+ * Ensures all version references in the codebase match package.json.
5
+ *
6
+ * This script:
7
+ * 1. Reads the canonical version from package.json
8
+ * 2. Updates src/index.js (VERSION constant and @version jsdoc)
9
+ * 3. Can optionally update package-lock.json
10
+ * 4. Validates that all versions are in sync
11
+ *
12
+ * Usage:
13
+ * node scripts/version-sync.js # Sync versions
14
+ * node scripts/version-sync.js --check # Check only (exit 1 if mismatch)
15
+ * node scripts/version-sync.js --help # Show help
16
+ *
17
+ * @module scripts/version-sync
18
+ * @license MIT
19
+ */
20
+
21
+ import { readFileSync, writeFileSync } from 'fs';
22
+ import { fileURLToPath } from 'url';
23
+ import { dirname, join } from 'path';
24
+
25
+ const __dirname = dirname(fileURLToPath(import.meta.url));
26
+ const ROOT = join(__dirname, '..');
27
+
28
+ // ANSI colors for output
29
+ const colors = process.env.NO_COLOR !== undefined ? {
30
+ reset: '', red: '', green: '', yellow: '', cyan: '', dim: '', bright: '',
31
+ } : {
32
+ reset: '\x1b[0m', red: '\x1b[31m', green: '\x1b[32m',
33
+ yellow: '\x1b[33m', cyan: '\x1b[36m', dim: '\x1b[2m', bright: '\x1b[1m',
34
+ };
35
+
36
+ /**
37
+ * Read the canonical version from package.json
38
+ * @returns {string} Version string
39
+ */
40
+ function getPackageVersion() {
41
+ const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'));
42
+ return pkg.version;
43
+ }
44
+
45
+ /**
46
+ * Get version from src/index.js VERSION constant
47
+ * @returns {string|null} Version string or null if not found
48
+ */
49
+ function getIndexVersion() {
50
+ const content = readFileSync(join(ROOT, 'src', 'index.js'), 'utf8');
51
+ const match = content.match(/export const VERSION = ['"]([^'"]+)['"]/);
52
+ return match ? match[1] : null;
53
+ }
54
+
55
+ /**
56
+ * Get @version from src/index.js jsdoc
57
+ * @returns {string|null} Version string or null if not found
58
+ */
59
+ function getIndexJsDocVersion() {
60
+ const content = readFileSync(join(ROOT, 'src', 'index.js'), 'utf8');
61
+ const match = content.match(/@version\s+(\S+)/);
62
+ return match ? match[1] : null;
63
+ }
64
+
65
+ /**
66
+ * Get version from package-lock.json root
67
+ * @returns {string|null} Version string or null if not found
68
+ */
69
+ function getLockfileVersion() {
70
+ try {
71
+ const lock = JSON.parse(readFileSync(join(ROOT, 'package-lock.json'), 'utf8'));
72
+ return lock.version;
73
+ } catch {
74
+ return null;
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Update src/index.js VERSION constant
80
+ * @param {string} version - New version
81
+ * @returns {boolean} True if updated
82
+ */
83
+ function updateIndexVersion(version) {
84
+ const filePath = join(ROOT, 'src', 'index.js');
85
+ let content = readFileSync(filePath, 'utf8');
86
+ const original = content;
87
+
88
+ // Update VERSION constant
89
+ content = content.replace(
90
+ /export const VERSION = ['"][^'"]+['"]/,
91
+ `export const VERSION = '${version}'`
92
+ );
93
+
94
+ // Update @version in jsdoc
95
+ content = content.replace(
96
+ /@version\s+\S+/,
97
+ `@version ${version}`
98
+ );
99
+
100
+ if (content !== original) {
101
+ writeFileSync(filePath, content, 'utf8');
102
+ return true;
103
+ }
104
+ return false;
105
+ }
106
+
107
+ /**
108
+ * Update package-lock.json version
109
+ * @param {string} version - New version
110
+ * @returns {boolean} True if updated
111
+ */
112
+ function updateLockfileVersion(version) {
113
+ const filePath = join(ROOT, 'package-lock.json');
114
+ try {
115
+ const lock = JSON.parse(readFileSync(filePath, 'utf8'));
116
+ const original = JSON.stringify(lock);
117
+
118
+ lock.version = version;
119
+ if (lock.packages && lock.packages['']) {
120
+ lock.packages[''].version = version;
121
+ }
122
+
123
+ const updated = JSON.stringify(lock, null, 2) + '\n';
124
+ if (updated !== original) {
125
+ writeFileSync(filePath, updated, 'utf8');
126
+ return true;
127
+ }
128
+ } catch {
129
+ // Lockfile might not exist
130
+ }
131
+ return false;
132
+ }
133
+
134
+ /**
135
+ * Check if all versions are in sync
136
+ * @returns {{inSync: boolean, versions: Object}}
137
+ */
138
+ function checkVersions() {
139
+ const pkgVersion = getPackageVersion();
140
+ const indexVersion = getIndexVersion();
141
+ const jsDocVersion = getIndexJsDocVersion();
142
+ const lockVersion = getLockfileVersion();
143
+
144
+ const versions = {
145
+ 'package.json': pkgVersion,
146
+ 'src/index.js (VERSION)': indexVersion,
147
+ 'src/index.js (@version)': jsDocVersion,
148
+ 'package-lock.json': lockVersion,
149
+ };
150
+
151
+ const inSync = indexVersion === pkgVersion &&
152
+ jsDocVersion === pkgVersion &&
153
+ (lockVersion === null || lockVersion === pkgVersion);
154
+
155
+ return { inSync, versions, canonical: pkgVersion };
156
+ }
157
+
158
+ /**
159
+ * Main function
160
+ */
161
+ function main() {
162
+ const args = process.argv.slice(2);
163
+
164
+ if (args.includes('--help') || args.includes('-h')) {
165
+ console.log(`
166
+ ${colors.bright}version-sync.js${colors.reset} - Synchronize version numbers across the codebase
167
+
168
+ ${colors.cyan}Usage:${colors.reset}
169
+ node scripts/version-sync.js Sync all versions to package.json
170
+ node scripts/version-sync.js --check Check only (exit 1 if mismatch)
171
+ node scripts/version-sync.js --help Show this help
172
+
173
+ ${colors.cyan}Files updated:${colors.reset}
174
+ - src/index.js (VERSION constant)
175
+ - src/index.js (@version jsdoc)
176
+ - package-lock.json (if present)
177
+ `);
178
+ process.exit(0);
179
+ }
180
+
181
+ const checkOnly = args.includes('--check');
182
+ const { inSync, versions, canonical } = checkVersions();
183
+
184
+ console.log(`${colors.bright}Version Check${colors.reset}`);
185
+ console.log(`${colors.dim}${'─'.repeat(50)}${colors.reset}`);
186
+
187
+ for (const [file, version] of Object.entries(versions)) {
188
+ const status = version === canonical
189
+ ? `${colors.green}OK${colors.reset}`
190
+ : version === null
191
+ ? `${colors.yellow}N/A${colors.reset}`
192
+ : `${colors.red}MISMATCH${colors.reset}`;
193
+ console.log(` ${file.padEnd(30)} ${(version || 'N/A').padEnd(12)} ${status}`);
194
+ }
195
+
196
+ console.log(`${colors.dim}${'─'.repeat(50)}${colors.reset}`);
197
+ console.log(` Canonical version: ${colors.cyan}${canonical}${colors.reset}`);
198
+
199
+ if (inSync) {
200
+ console.log(`\n${colors.green}All versions are in sync.${colors.reset}`);
201
+ process.exit(0);
202
+ }
203
+
204
+ if (checkOnly) {
205
+ console.log(`\n${colors.red}Version mismatch detected!${colors.reset}`);
206
+ console.log(`Run ${colors.cyan}node scripts/version-sync.js${colors.reset} to fix.`);
207
+ process.exit(1);
208
+ }
209
+
210
+ // Sync versions
211
+ console.log(`\n${colors.yellow}Syncing versions...${colors.reset}`);
212
+
213
+ let updated = 0;
214
+ if (updateIndexVersion(canonical)) {
215
+ console.log(` ${colors.green}Updated${colors.reset} src/index.js`);
216
+ updated++;
217
+ }
218
+ if (updateLockfileVersion(canonical)) {
219
+ console.log(` ${colors.green}Updated${colors.reset} package-lock.json`);
220
+ updated++;
221
+ }
222
+
223
+ if (updated > 0) {
224
+ console.log(`\n${colors.green}Synced ${updated} file(s) to version ${canonical}${colors.reset}`);
225
+ } else {
226
+ console.log(`\n${colors.green}All files already in sync.${colors.reset}`);
227
+ }
228
+ }
229
+
230
+ main();
package/src/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * SVG path conversion, and 2D/3D affine transformations using Decimal.js.
6
6
  *
7
7
  * @module @emasoft/svg-matrix
8
- * @version 1.0.16
8
+ * @version 1.0.17
9
9
  * @license MIT
10
10
  *
11
11
  * @example
@@ -58,7 +58,7 @@ Decimal.set({ precision: 80 });
58
58
  * Library version
59
59
  * @constant {string}
60
60
  */
61
- export const VERSION = '1.0.16';
61
+ export const VERSION = '1.0.17';
62
62
 
63
63
  /**
64
64
  * Default precision for path output (decimal places)