pulse-js-framework 1.7.16 → 1.7.18

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/README.md CHANGED
@@ -163,6 +163,12 @@ pulse test --create <name> # Generate test file
163
163
  pulse doctor # Run project diagnostics
164
164
  pulse doctor --verbose # Detailed diagnostics
165
165
 
166
+ # Creating .pulse Files
167
+ pulse new <name> # Create component (src/components/<Name>.pulse)
168
+ pulse new <name> --type page # Create page (src/pages/<Name>.pulse)
169
+ pulse new <name> --type layout # Create layout (src/layouts/<Name>.pulse)
170
+ pulse new <name> --props # Include props section
171
+
166
172
  # Scaffolding
167
173
  pulse scaffold component <name> # Generate component
168
174
  pulse scaffold page <name> # Generate page
package/cli/help.js CHANGED
@@ -66,6 +66,40 @@ Merges with existing package.json if present.`,
66
66
  ]
67
67
  },
68
68
 
69
+ new: {
70
+ name: 'new',
71
+ summary: 'Create a new .pulse file',
72
+ usage: 'pulse new <name> [options]',
73
+ description: `
74
+ Creates a new .pulse file with a component template. This is a shorthand for
75
+ "pulse scaffold component/page/layout" that makes it quick to create new
76
+ Pulse components from the command line.
77
+
78
+ File types:
79
+ - component: Reusable UI component (default)
80
+ - page: Page component with routing support
81
+ - layout: Layout component with slots`,
82
+ arguments: [
83
+ { name: '<name>', description: 'Name of the component (PascalCase recommended)' }
84
+ ],
85
+ options: [
86
+ { flag: '--type, -t <type>', description: 'Type: component, page, layout (default: component)' },
87
+ { flag: '--dir, -d <path>', description: 'Output directory (default: based on type)' },
88
+ { flag: '--force, -f', description: 'Overwrite existing files' },
89
+ { flag: '--props', description: 'Include props section' },
90
+ { flag: '--no-state', description: 'Skip state section' },
91
+ { flag: '--no-style', description: 'Skip style section' }
92
+ ],
93
+ examples: [
94
+ { cmd: 'pulse new Button', desc: 'Create src/components/Button.pulse' },
95
+ { cmd: 'pulse new Dashboard --type page', desc: 'Create src/pages/Dashboard.pulse' },
96
+ { cmd: 'pulse new Admin --type layout', desc: 'Create src/layouts/Admin.pulse' },
97
+ { cmd: 'pulse new Modal --props', desc: 'Create component with props section' },
98
+ { cmd: 'pulse new Card -d src/ui', desc: 'Create in custom directory' },
99
+ { cmd: 'pulse new Header --no-style', desc: 'Create without style block' }
100
+ ]
101
+ },
102
+
69
103
  dev: {
70
104
  name: 'dev',
71
105
  summary: 'Start development server',
@@ -505,7 +539,7 @@ function showGeneralHelp() {
505
539
  'Development': ['dev', 'build', 'preview'],
506
540
  'Code Quality': ['compile', 'lint', 'format', 'analyze'],
507
541
  'Testing': ['test', 'doctor'],
508
- 'Scaffolding': ['scaffold', 'docs'],
542
+ 'Scaffolding': ['new', 'scaffold', 'docs'],
509
543
  'Release': ['release'],
510
544
  'Mobile': ['mobile'],
511
545
  'Information': ['version', 'help']
package/cli/index.js CHANGED
@@ -24,6 +24,7 @@ const commands = {
24
24
  version: showVersion,
25
25
  create: createProject,
26
26
  init: initProject,
27
+ new: newPulseFile,
27
28
  dev: runDev,
28
29
  build: runBuild,
29
30
  preview: runPreview,
@@ -73,7 +74,9 @@ const commandAliases = {
73
74
  'scaffod': 'scaffold',
74
75
  'scafflod': 'scaffold',
75
76
  'doc': 'docs',
76
- 'dcos': 'docs'
77
+ 'dcos': 'docs',
78
+ 'nwe': 'new',
79
+ 'enw': 'new'
77
80
  };
78
81
 
79
82
  /**
@@ -683,6 +686,80 @@ async function runScaffoldCmd(args) {
683
686
  await runScaffold(args);
684
687
  }
685
688
 
689
+ /**
690
+ * Create a new .pulse file
691
+ * Usage: pulse new <name> [options]
692
+ * Options:
693
+ * --type, -t <type> Type: component, page, layout (default: component)
694
+ * --dir, -d <path> Output directory (default: src/components or based on type)
695
+ * --force, -f Overwrite existing files
696
+ * --props Include props section
697
+ * --no-state Skip state section
698
+ * --no-style Skip style section
699
+ */
700
+ async function newPulseFile(args) {
701
+ const { options, patterns } = parseArgs(args);
702
+ const name = patterns[0];
703
+
704
+ if (!name) {
705
+ log.error('Please provide a name for the .pulse file.');
706
+ log.info(`
707
+ Usage: pulse new <name> [options]
708
+
709
+ Options:
710
+ --type, -t <type> Type: component, page, layout (default: component)
711
+ --dir, -d <path> Output directory
712
+ --force, -f Overwrite existing files
713
+ --props Include props section
714
+ --no-state Skip state section
715
+ --no-style Skip style section
716
+
717
+ Examples:
718
+ pulse new Button Create src/components/Button.pulse
719
+ pulse new Dashboard --type page Create src/pages/Dashboard.pulse
720
+ pulse new Admin --type layout Create src/layouts/Admin.pulse
721
+ pulse new Modal --props Create component with props section
722
+ pulse new Card -d src/ui Create in custom directory
723
+ `);
724
+ process.exit(1);
725
+ }
726
+
727
+ // Determine type
728
+ const type = options.type || options.t || 'component';
729
+ const validTypes = ['component', 'page', 'layout'];
730
+
731
+ if (!validTypes.includes(type)) {
732
+ log.error(`Invalid type: ${type}`);
733
+ log.info(`Valid types: ${validTypes.join(', ')}`);
734
+ process.exit(1);
735
+ }
736
+
737
+ // Map type to scaffold type and delegate
738
+ const { runScaffold } = await import('./scaffold.js');
739
+
740
+ // Build args for scaffold command
741
+ const scaffoldArgs = [type, name];
742
+
743
+ // Pass through options
744
+ if (options.dir || options.d) {
745
+ scaffoldArgs.push('--dir', options.dir || options.d);
746
+ }
747
+ if (options.force || options.f) {
748
+ scaffoldArgs.push('--force');
749
+ }
750
+ if (options.props) {
751
+ scaffoldArgs.push('--props');
752
+ }
753
+ if (options.state === false) {
754
+ scaffoldArgs.push('--no-state');
755
+ }
756
+ if (options.style === false) {
757
+ scaffoldArgs.push('--no-style');
758
+ }
759
+
760
+ await runScaffold(scaffoldArgs);
761
+ }
762
+
686
763
  /**
687
764
  * Run docs command
688
765
  */
package/cli/release.js CHANGED
@@ -350,14 +350,15 @@ function updateDocsChangelog(newVersion, title, changes) {
350
350
  }
351
351
 
352
352
  /**
353
- * Escape HTML entities
353
+ * Escape HTML entities and convert backticks to <code> tags
354
354
  */
355
355
  function escapeHtml(str) {
356
356
  return str
357
357
  .replace(/&/g, '&amp;')
358
358
  .replace(/</g, '&lt;')
359
359
  .replace(/>/g, '&gt;')
360
- .replace(/"/g, '&quot;');
360
+ .replace(/"/g, '&quot;')
361
+ .replace(/`([^`]+)`/g, '<code>$1</code>');
361
362
  }
362
363
 
363
364
  /**
@@ -247,6 +247,10 @@ export function resolveImportPath(fromFile, importPath) {
247
247
 
248
248
  /**
249
249
  * Parse CLI arguments into options and file patterns
250
+ * Supports:
251
+ * - Boolean flags: --verbose, -v
252
+ * - Value options: --dir /path, -d /path
253
+ * - Negation: --no-state
250
254
  * @param {string[]} args - Command line arguments
251
255
  * @returns {{ options: object, patterns: string[] }}
252
256
  */
@@ -254,15 +258,33 @@ export function parseArgs(args) {
254
258
  const options = {};
255
259
  const patterns = [];
256
260
 
261
+ // Options that take a value (not boolean)
262
+ const valueOptions = new Set([
263
+ 'dir', 'd', 'output', 'o', 'type', 't', 'format', 'f', 'filter', 'timeout', 'title', 'from'
264
+ ]);
265
+
257
266
  for (let i = 0; i < args.length; i++) {
258
267
  const arg = args[i];
259
- if (arg.startsWith('--')) {
268
+ if (arg.startsWith('--no-')) {
269
+ // Negation: --no-state -> state: false
270
+ const key = arg.slice(5);
271
+ options[key] = false;
272
+ } else if (arg.startsWith('--')) {
260
273
  const key = arg.slice(2);
261
- // Boolean flags - don't consume next argument
262
- options[key] = true;
274
+ // Check if this option takes a value
275
+ if (valueOptions.has(key) && i + 1 < args.length && !args[i + 1].startsWith('-')) {
276
+ options[key] = args[++i];
277
+ } else {
278
+ options[key] = true;
279
+ }
263
280
  } else if (arg.startsWith('-') && arg.length === 2) {
264
281
  const key = arg.slice(1);
265
- options[key] = true;
282
+ // Check if this option takes a value
283
+ if (valueOptions.has(key) && i + 1 < args.length && !args[i + 1].startsWith('-')) {
284
+ options[key] = args[++i];
285
+ } else {
286
+ options[key] = true;
287
+ }
266
288
  } else {
267
289
  patterns.push(arg);
268
290
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulse-js-framework",
3
- "version": "1.7.16",
3
+ "version": "1.7.18",
4
4
  "description": "A declarative DOM framework with CSS selector-based structure and reactive pulsations",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/runtime/index.js CHANGED
@@ -1,27 +1,89 @@
1
1
  /**
2
2
  * Pulse Runtime - Main exports
3
+ *
4
+ * Core modules are re-exported here for convenience.
5
+ * Development-only modules (devtools, hmr) should be imported directly
6
+ * from their respective paths to enable tree-shaking in production.
3
7
  */
4
8
 
9
+ // Core reactivity
5
10
  export * from './pulse.js';
11
+
12
+ // DOM creation and manipulation
6
13
  export * from './dom.js';
14
+
15
+ // Routing
7
16
  export * from './router.js';
17
+
18
+ // State management
8
19
  export * from './store.js';
9
- export * from './native.js';
10
- export * from './logger.js';
11
- export * from './a11y.js';
20
+
21
+ // Context API
12
22
  export * from './context.js';
23
+
24
+ // Async primitives (useAsync, useResource, usePolling)
25
+ export * from './async.js';
26
+
27
+ // Form handling (useForm, useField, validators)
28
+ export * from './form.js';
29
+
30
+ // HTTP client
31
+ export * from './http.js';
32
+
33
+ // WebSocket client
13
34
  export * from './websocket.js';
35
+
36
+ // GraphQL client
14
37
  export * from './graphql.js';
38
+
39
+ // Server-side rendering
15
40
  export * from './ssr.js';
16
41
 
42
+ // Accessibility utilities
43
+ export * from './a11y.js';
44
+
45
+ // Native mobile bridge
46
+ export * from './native.js';
47
+
48
+ // Logging
49
+ export * from './logger.js';
50
+
51
+ // Security utilities (XSS prevention, URL sanitization)
52
+ export * from './utils.js';
53
+
54
+ // Error classes
55
+ export * from './errors.js';
56
+
57
+ // LRU Cache
58
+ export * from './lru-cache.js';
59
+
60
+ // DOM Adapter (for SSR/testing)
61
+ export * from './dom-adapter.js';
62
+
63
+ // Default exports for namespace imports
17
64
  export { default as PulseCore } from './pulse.js';
18
65
  export { default as PulseDOM } from './dom.js';
19
66
  export { default as PulseRouter } from './router.js';
20
67
  export { default as PulseStore } from './store.js';
21
- export { default as PulseNative } from './native.js';
22
- export { default as PulseLogger } from './logger.js';
23
- export { default as PulseA11y } from './a11y.js';
24
68
  export { default as PulseContext } from './context.js';
69
+ export { default as PulseAsync } from './async.js';
70
+ export { default as PulseForm } from './form.js';
71
+ export { default as PulseHttp } from './http.js';
25
72
  export { default as PulseWebSocket } from './websocket.js';
26
73
  export { default as PulseGraphQL } from './graphql.js';
27
74
  export { default as PulseSSR } from './ssr.js';
75
+ export { default as PulseA11y } from './a11y.js';
76
+ export { default as PulseNative } from './native.js';
77
+ export { default as PulseLogger } from './logger.js';
78
+
79
+ // Note: The following modules are intentionally NOT re-exported here
80
+ // to enable tree-shaking. Import them directly when needed:
81
+ //
82
+ // Development tools (adds overhead, use only in dev):
83
+ // import { enableDevTools, trackedPulse } from 'pulse-js-framework/runtime/devtools';
84
+ //
85
+ // HMR utilities (Vite/webpack integration):
86
+ // import { createHMRContext } from 'pulse-js-framework/runtime/hmr';
87
+ //
88
+ // Lite build (minimal ~5KB bundle):
89
+ // import { pulse, effect, el, mount } from 'pulse-js-framework/runtime/lite';