pulse-js-framework 1.7.2 → 1.7.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.
package/cli/build.js CHANGED
@@ -185,28 +185,104 @@ function readRuntimeFile(filename) {
185
185
 
186
186
  /**
187
187
  * Minify JavaScript code (simple minification)
188
- * String-aware: preserves content inside string literals
188
+ * String and regex-aware: preserves content inside string and regex literals
189
189
  */
190
190
  export function minifyJS(code) {
191
- // Extract strings to protect them from minification
192
- const strings = [];
193
- const placeholder = '\x00STR';
194
-
195
- // Replace strings with placeholders (handles ", ', and ` with escape sequences)
196
- const withPlaceholders = code.replace(
197
- /(["'`])(?:\\.|(?!\1)[^\\])*\1/g,
198
- (match) => {
199
- strings.push(match);
200
- return placeholder + (strings.length - 1) + '\x00';
191
+ // Extract strings and regexes to protect them from minification
192
+ const preserved = [];
193
+ const placeholder = '\x00PRE';
194
+
195
+ // State machine to properly handle strings and regexes
196
+ let result = '';
197
+ let i = 0;
198
+
199
+ while (i < code.length) {
200
+ const char = code[i];
201
+ const next = code[i + 1];
202
+
203
+ // Skip single-line comments
204
+ if (char === '/' && next === '/') {
205
+ while (i < code.length && code[i] !== '\n') i++;
206
+ continue;
201
207
  }
202
- );
203
208
 
204
- // Apply minification to non-string parts
205
- let minified = withPlaceholders
206
- // Remove single-line comments
207
- .replace(/\/\/.*$/gm, '')
208
- // Remove multi-line comments
209
- .replace(/\/\*[\s\S]*?\*\//g, '')
209
+ // Skip multi-line comments
210
+ if (char === '/' && next === '*') {
211
+ i += 2;
212
+ while (i < code.length - 1 && !(code[i] === '*' && code[i + 1] === '/')) i++;
213
+ i += 2;
214
+ continue;
215
+ }
216
+
217
+ // Handle string literals
218
+ if (char === '"' || char === "'" || char === '`') {
219
+ const quote = char;
220
+ let str = char;
221
+ i++;
222
+ while (i < code.length) {
223
+ const c = code[i];
224
+ str += c;
225
+ if (c === '\\' && i + 1 < code.length) {
226
+ i++;
227
+ str += code[i];
228
+ } else if (c === quote) {
229
+ break;
230
+ }
231
+ i++;
232
+ }
233
+ i++;
234
+ preserved.push(str);
235
+ result += placeholder + (preserved.length - 1) + '\x00';
236
+ continue;
237
+ }
238
+
239
+ // Handle regex literals (after = : ( , [ ! & | ? ; { or keywords)
240
+ if (char === '/') {
241
+ // Look back to determine if this is a regex
242
+ const lookback = result.slice(-20).trim();
243
+ const isRegexContext = lookback === '' ||
244
+ /[=:(\[,!&|?;{]$/.test(lookback) ||
245
+ /\breturn$/.test(lookback) ||
246
+ /\bthrow$/.test(lookback) ||
247
+ /\btypeof$/.test(lookback);
248
+
249
+ if (isRegexContext && next !== '/' && next !== '*') {
250
+ let regex = char;
251
+ i++;
252
+ let inCharClass = false;
253
+ while (i < code.length) {
254
+ const c = code[i];
255
+ regex += c;
256
+ if (c === '\\' && i + 1 < code.length) {
257
+ i++;
258
+ regex += code[i];
259
+ } else if (c === '[') {
260
+ inCharClass = true;
261
+ } else if (c === ']') {
262
+ inCharClass = false;
263
+ } else if (c === '/' && !inCharClass) {
264
+ // End of regex, collect flags
265
+ i++;
266
+ while (i < code.length && /[gimsuvy]/.test(code[i])) {
267
+ regex += code[i];
268
+ i++;
269
+ }
270
+ break;
271
+ }
272
+ i++;
273
+ }
274
+ preserved.push(regex);
275
+ result += placeholder + (preserved.length - 1) + '\x00';
276
+ continue;
277
+ }
278
+ }
279
+
280
+ result += char;
281
+ i++;
282
+ }
283
+
284
+ // Apply minification to non-preserved parts
285
+ let minified = result
210
286
  // Remove leading/trailing whitespace per line
211
287
  .split('\n')
212
288
  .map(line => line.trim())
@@ -214,7 +290,7 @@ export function minifyJS(code) {
214
290
  .join('\n')
215
291
  // Collapse multiple newlines
216
292
  .replace(/\n{2,}/g, '\n')
217
- // Remove spaces around operators (simple)
293
+ // Remove spaces around operators
218
294
  .replace(/\s*([{};,:])\s*/g, '$1')
219
295
  .replace(/\s*=\s*/g, '=')
220
296
  .replace(/\s*\(\s*/g, '(')
@@ -223,10 +299,10 @@ export function minifyJS(code) {
223
299
  .replace(/\s+/g, ' ')
224
300
  .trim();
225
301
 
226
- // Restore strings
302
+ // Restore preserved strings and regexes
227
303
  minified = minified.replace(
228
304
  new RegExp(placeholder.replace('\x00', '\\x00') + '(\\d+)\\x00', 'g'),
229
- (_, index) => strings[parseInt(index)]
305
+ (_, index) => preserved[parseInt(index)]
230
306
  );
231
307
 
232
308
  return minified;
package/cli/dev.js CHANGED
@@ -128,7 +128,10 @@ export async function startDevServer(args) {
128
128
  });
129
129
 
130
130
  if (result.success) {
131
- res.writeHead(200, { 'Content-Type': 'application/javascript' });
131
+ res.writeHead(200, {
132
+ 'Content-Type': 'application/javascript',
133
+ 'Cache-Control': 'no-cache, no-store, must-revalidate'
134
+ });
132
135
  res.end(result.code);
133
136
  } else {
134
137
  res.writeHead(500, { 'Content-Type': 'text/plain' });
@@ -146,7 +149,10 @@ export async function startDevServer(args) {
146
149
  if (pathname.endsWith('.js') || pathname.endsWith('.mjs')) {
147
150
  if (existsSync(filePath)) {
148
151
  const content = readFileSync(filePath, 'utf-8');
149
- res.writeHead(200, { 'Content-Type': 'application/javascript' });
152
+ res.writeHead(200, {
153
+ 'Content-Type': 'application/javascript',
154
+ 'Cache-Control': 'no-cache, no-store, must-revalidate'
155
+ });
150
156
  res.end(content);
151
157
  return;
152
158
  }
@@ -164,7 +170,10 @@ export async function startDevServer(args) {
164
170
  });
165
171
 
166
172
  if (result.success) {
167
- res.writeHead(200, { 'Content-Type': 'application/javascript' });
173
+ res.writeHead(200, {
174
+ 'Content-Type': 'application/javascript',
175
+ 'Cache-Control': 'no-cache, no-store, must-revalidate'
176
+ });
168
177
  res.end(result.code);
169
178
  } else {
170
179
  res.writeHead(500, { 'Content-Type': 'text/plain' });
@@ -183,7 +192,10 @@ export async function startDevServer(args) {
183
192
  const modulePath = join(root, '..', 'pulse', pathname.replace('/node_modules/pulse-js-framework/', ''));
184
193
  if (existsSync(modulePath)) {
185
194
  const content = readFileSync(modulePath, 'utf-8');
186
- res.writeHead(200, { 'Content-Type': 'application/javascript' });
195
+ res.writeHead(200, {
196
+ 'Content-Type': 'application/javascript',
197
+ 'Cache-Control': 'no-cache, no-store, must-revalidate'
198
+ });
187
199
  res.end(content);
188
200
  return;
189
201
  }
@@ -203,7 +215,10 @@ export async function startDevServer(args) {
203
215
  for (const runtimePath of possiblePaths) {
204
216
  if (existsSync(runtimePath)) {
205
217
  const content = readFileSync(runtimePath, 'utf-8');
206
- res.writeHead(200, { 'Content-Type': 'application/javascript' });
218
+ res.writeHead(200, {
219
+ 'Content-Type': 'application/javascript',
220
+ 'Cache-Control': 'no-cache, no-store, must-revalidate'
221
+ });
207
222
  res.end(content);
208
223
  return;
209
224
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulse-js-framework",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
4
4
  "description": "A declarative DOM framework with CSS selector-based structure and reactive pulsations",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -52,6 +52,9 @@
52
52
  },
53
53
  "./runtime/lru-cache": "./runtime/lru-cache.js",
54
54
  "./runtime/utils": "./runtime/utils.js",
55
+ "./runtime/async": "./runtime/async.js",
56
+ "./runtime/form": "./runtime/form.js",
57
+ "./runtime/devtools": "./runtime/devtools.js",
55
58
  "./compiler": {
56
59
  "types": "./types/index.d.ts",
57
60
  "default": "./compiler/index.js"
@@ -80,7 +83,7 @@
80
83
  "LICENSE"
81
84
  ],
82
85
  "scripts": {
83
- "test": "npm run test:compiler && npm run test:sourcemap && npm run test:pulse && npm run test:dom && npm run test:router && npm run test:store && npm run test:hmr && npm run test:lint && npm run test:format && npm run test:analyze && npm run test:lru-cache && npm run test:utils && npm run test:docs",
86
+ "test": "npm run test:compiler && npm run test:sourcemap && npm run test:pulse && npm run test:dom && npm run test:router && npm run test:store && npm run test:hmr && npm run test:lint && npm run test:format && npm run test:analyze && npm run test:lru-cache && npm run test:utils && npm run test:docs && npm run test:async && npm run test:form && npm run test:devtools",
84
87
  "test:compiler": "node test/compiler.test.js",
85
88
  "test:sourcemap": "node test/sourcemap.test.js",
86
89
  "test:pulse": "node test/pulse.test.js",
@@ -94,6 +97,9 @@
94
97
  "test:lru-cache": "node test/lru-cache.test.js",
95
98
  "test:utils": "node test/utils.test.js",
96
99
  "test:docs": "node test/docs.test.js",
100
+ "test:async": "node test/async.test.js",
101
+ "test:form": "node test/form.test.js",
102
+ "test:devtools": "node test/devtools.test.js",
97
103
  "build:netlify": "node scripts/build-netlify.js",
98
104
  "version": "node scripts/sync-version.js",
99
105
  "docs": "node cli/index.js dev docs"