@jqhtml/core 2.3.61 → 2.3.64

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * JQHTML Core v2.3.61
2
+ * JQHTML Core v2.3.64
3
3
  * (c) 2025 JQHTML Team
4
4
  * Released under the MIT License
5
5
  */
@@ -204,6 +204,21 @@ class LifecycleManager {
204
204
  }
205
205
  }
206
206
 
207
+ /**
208
+ * The one rule for "is this name a component?"
209
+ *
210
+ * An optional SINGLE leading underscore, then a capital letter, then letters,
211
+ * digits and underscores. The underscore prefix is a namespace reserved for
212
+ * framework-provided components (`_Root_Layout`) so they cannot collide with
213
+ * application components. Two or more leading underscores are not a component
214
+ * name; a lower-case first letter after the optional underscore is an HTML tag.
215
+ */
216
+ const COMPONENT_NAME_PATTERN = /^_?[A-Z][A-Za-z0-9_]*$/;
217
+ const COMPONENT_NAME_RULE = 'must start with a capital letter, optionally preceded by a single underscore';
218
+ function is_component_name(name) {
219
+ return COMPONENT_NAME_PATTERN.test(name);
220
+ }
221
+
207
222
  /**
208
223
  * JQHTML v2 Component Registry
209
224
  *
@@ -250,9 +265,9 @@ function register_component(nameOrClass, component_class, template) {
250
265
  if (!component_class) {
251
266
  throw new Error('Component class is required when registering by name');
252
267
  }
253
- // Validate component name starts with capital letter
254
- if (!/^[A-Z]/.test(name)) {
255
- throw new Error(`Component name '${name}' must start with a capital letter. Convention is First_Letter_With_Underscores.`);
268
+ // Validate component name against the shared rule
269
+ if (!is_component_name(name)) {
270
+ throw new Error(`Component name '${name}' ${COMPONENT_NAME_RULE}. Convention is First_Letter_With_Underscores.`);
256
271
  }
257
272
  component_classes.set(name, component_class);
258
273
  // If template provided, register it
@@ -321,9 +336,9 @@ function register_template(template_def) {
321
336
  if (!name) {
322
337
  throw new Error('Template must have a name property');
323
338
  }
324
- // Validate template name starts with capital letter
325
- if (!/^[A-Z]/.test(name)) {
326
- throw new Error(`Template name '${name}' must start with a capital letter. Convention is First_Letter_With_Underscores.`);
339
+ // Validate template name against the shared rule
340
+ if (!is_component_name(name)) {
341
+ throw new Error(`Template name '${name}' ${COMPONENT_NAME_RULE}. Convention is First_Letter_With_Underscores.`);
327
342
  }
328
343
  // Check for duplicate registration
329
344
  if (component_templates.has(name)) {
@@ -1852,7 +1867,7 @@ Load_Coordinator._registry = new Map();
1852
1867
  const class_registry = Object.create(null);
1853
1868
  // Markers for serialized class instances (unique to avoid collisions with user data)
1854
1869
  // Replaced at build time by rollup (see rollup.config.js).
1855
- const CORE_VERSION = '2.3.61';
1870
+ const CORE_VERSION = '2.3.64';
1856
1871
  const CLASS_MARKER = '__jqhtml_class__';
1857
1872
  const PROPS_MARKER = '__jqhtml_props__';
1858
1873
  /**
@@ -4987,7 +5002,8 @@ class Jqhtml_Component {
4987
5002
  * Find closest ancestor component matching selector
4988
5003
  *
4989
5004
  * A bare component name - a plain identifier starting with a capital letter,
4990
- * such as 'Parent_Dashboard' - is treated as the component-name class
5005
+ * optionally preceded by a single underscore, such as 'Parent_Dashboard' or
5006
+ * '_Root_Layout' - is treated as the component-name class
4991
5007
  * selector '.Parent_Dashboard'. Components carry a CSS class for every name
4992
5008
  * in their prototype chain, so a base class name matches its subclasses too.
4993
5009
  * Every other selector ('.Foo', '#id', '[attr]', 'div > .Component') is
@@ -5064,14 +5080,16 @@ class Jqhtml_Component {
5064
5080
  // Add component name at the beginning (most specific)
5065
5081
  classesToAdd.unshift(this.args._component_name);
5066
5082
  }
5067
- // Filter out private classes (starting with _) and invalid class names
5083
+ // Filter out private/mangled classes (starting with _) and invalid class names.
5084
+ // A component name with the reserved single-underscore prefix (_Root_Layout)
5085
+ // is public and is kept - see component-name.ts.
5068
5086
  const publicClasses = classesToAdd.filter(className => {
5069
5087
  // Guard against undefined, null, or non-string values
5070
5088
  if (!className || typeof className !== 'string') {
5071
5089
  console.warn('[JQHTML] Filtered out invalid class name:', className);
5072
5090
  return false;
5073
5091
  }
5074
- return !className.startsWith('_');
5092
+ return !className.startsWith('_') || is_component_name(className);
5075
5093
  });
5076
5094
  if (publicClasses.length > 0) {
5077
5095
  this.$.addClass(publicClasses.join(' '));
@@ -5277,7 +5295,7 @@ class Jqhtml_Component {
5277
5295
  // Static properties
5278
5296
  Jqhtml_Component.__jqhtml_component = true; // Marker for unified register() detection
5279
5297
  // A bare component name, as accepted by closest() in place of a class selector
5280
- Jqhtml_Component.COMPONENT_NAME_PATTERN = /^[A-Z][A-Za-z0-9_]*$/;
5298
+ Jqhtml_Component.COMPONENT_NAME_PATTERN = COMPONENT_NAME_PATTERN;
5281
5299
 
5282
5300
  /**
5283
5301
  * JQHTML v2 Template Renderer
@@ -5799,16 +5817,20 @@ function init_jquery_plugin(jQuery) {
5799
5817
  catch (error) {
5800
5818
  console.warn('[JQHTML] Error stopping existing component during replacement:', error);
5801
5819
  }
5802
- // Remove component classes (any class starting with capital letter, except BEM classes)
5820
+ // Remove component classes (any class starting with a capital letter, or a
5821
+ // component name with the reserved underscore prefix - except BEM classes)
5803
5822
  const classes = element.attr('class');
5804
5823
  if (classes) {
5805
5824
  const classList = classes.split(/\s+/);
5806
5825
  const nonComponentClasses = classList.filter((cls) => {
5807
5826
  // Keep class if:
5808
5827
  // 1. It's empty
5809
- // 2. It doesn't start with a capital letter
5828
+ // 2. It is neither capital-first nor a component name (see component-name.ts)
5810
5829
  // 3. It's a BEM-style class (contains __) - these persist across reinitialization
5811
- return !cls || cls[0] !== cls[0].toUpperCase() || cls[0] === cls[0].toLowerCase() || cls.includes('__');
5830
+ if (!cls || cls.includes('__'))
5831
+ return true;
5832
+ const capital_first = cls[0] === cls[0].toUpperCase() && cls[0] !== cls[0].toLowerCase();
5833
+ return !capital_first && !is_component_name(cls);
5812
5834
  });
5813
5835
  element.attr('class', nonComponentClasses.join(' '));
5814
5836
  }
@@ -6174,7 +6196,7 @@ function init(jQuery, config) {
6174
6196
  }
6175
6197
  }
6176
6198
  // Version - will be replaced during build with actual version from package.json
6177
- const version = '2.3.61';
6199
+ const version = '2.3.64';
6178
6200
  // Default export with all functionality
6179
6201
  const jqhtml = {
6180
6202
  // Core
@@ -6310,5 +6332,5 @@ if (typeof window !== 'undefined' && !window.jqhtml) {
6310
6332
  }
6311
6333
  }
6312
6334
 
6313
- export { Jqhtml_Component, LifecycleManager as Jqhtml_LifecycleManager, Jqhtml_Local_Storage, LifecycleManager, Load_Coordinator, applyDebugDelay, boot, clear_preload_data, configure, create_component, jqhtml as default, devWarn, escape_html, escape_html_nl2br, extract_slots, get_captured_data, get_component_class, get_component_names, get_config, get_registered_templates, get_template, get_template_by_class, handleComponentError, has_component, init, init_jquery_plugin, isSequentialProcessing, list_components, logDataChange, logDispatch, logInstruction, logLifecycle, process_instructions, register, register_cache_class, register_component, register_template, render_template, set_preload_data, start_data_capture, stop_data_capture, version };
6335
+ export { COMPONENT_NAME_PATTERN, COMPONENT_NAME_RULE, Jqhtml_Component, LifecycleManager as Jqhtml_LifecycleManager, Jqhtml_Local_Storage, LifecycleManager, Load_Coordinator, applyDebugDelay, boot, clear_preload_data, configure, create_component, jqhtml as default, devWarn, escape_html, escape_html_nl2br, extract_slots, get_captured_data, get_component_class, get_component_names, get_config, get_registered_templates, get_template, get_template_by_class, handleComponentError, has_component, init, init_jquery_plugin, isSequentialProcessing, is_component_name, list_components, logDataChange, logDispatch, logInstruction, logLifecycle, process_instructions, register, register_cache_class, register_component, register_template, render_template, set_preload_data, start_data_capture, stop_data_capture, version };
6314
6336
  //# sourceMappingURL=jqhtml-core.esm.js.map