@jqhtml/core 2.3.54 → 2.3.61

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/dist/index.js CHANGED
@@ -634,7 +634,9 @@ function process_instructions(instructions, target, context, slots) {
634
634
  if (el) {
635
635
  const element = $(el);
636
636
  el.removeAttribute('data-tid');
637
- apply_attributes(element, tagData.attrs, context);
637
+ // Bind to the component whose template wrote this element, which for
638
+ // spliced content is not the component being rendered.
639
+ apply_attributes(element, tagData.attrs, tagData.context);
638
640
  }
639
641
  }
640
642
  // Third pass: initialize and boot components in parallel
@@ -660,6 +662,16 @@ function process_instruction_to_html(instruction, html, tagElements, components,
660
662
  // Raw HTML/text - no escaping, as requested
661
663
  html.push(instruction);
662
664
  }
665
+ else if (Array.isArray(instruction)) {
666
+ if (instruction[0] !== '_content' || !Array.isArray(instruction[1])) {
667
+ return;
668
+ }
669
+ // Content written in another template renders in that template's component.
670
+ const definer = instruction[2] || context;
671
+ for (const item of instruction[1]) {
672
+ process_instruction_to_html(item, html, tagElements, components, definer, slots);
673
+ }
674
+ }
663
675
  else if ('tag' in instruction) {
664
676
  // HTML tag
665
677
  process_tag_to_html(instruction, html, tagElements, components, context);
@@ -856,11 +868,22 @@ function process_rawtag_to_html(instruction, html) {
856
868
  }
857
869
  }
858
870
  html.push('>');
859
- // Add raw content - escape HTML entities but preserve whitespace
860
- const escaped_content = rawContent
861
- .replace(/&/g, '&')
862
- .replace(/</g, '&lt;')
863
- .replace(/>/g, '&gt;');
871
+ // Add raw content, preserving whitespace.
872
+ //
873
+ // <textarea> holds text and nothing else, so everything is escaped.
874
+ //
875
+ // <pre> holds phrasing content - <pre><code> is the standard code-block idiom - so
876
+ // markup the author wrote is passed through. A '<' that does not begin a tag is
877
+ // still escaped, which is what the HTML tokenizer itself does with a stray '<' and
878
+ // keeps code samples such as "if (a < b)" rendering as written. Interpolated
879
+ // values are escaped by the compiler before they reach this point.
880
+ const is_raw_html_content = tagName.toLowerCase() === 'pre';
881
+ const escaped_content = is_raw_html_content
882
+ ? rawContent.replace(/<(?![a-zA-Z/!?])/g, '&lt;')
883
+ : rawContent
884
+ .replace(/&/g, '&amp;')
885
+ .replace(/</g, '&lt;')
886
+ .replace(/>/g, '&gt;');
864
887
  html.push(escaped_content);
865
888
  // Close tag
866
889
  html.push(`</${tagName}>`);
@@ -1532,6 +1555,11 @@ class Load_Coordinator {
1532
1555
  }
1533
1556
  if (!uncacheable_property) {
1534
1557
  uncacheable_property = key;
1558
+ // This package compiles with strictNullChecks off, and without it
1559
+ // TypeScript will not narrow a discriminated union by its boolean
1560
+ // discriminant - so `serialized` is still the full Serialize_Result
1561
+ // here even though `ok` has been ruled out above. The cast states
1562
+ // what the control flow already guarantees.
1535
1563
  uncacheable_reason = serialized.reason;
1536
1564
  }
1537
1565
  return { key: null, uncacheable_property, uncacheable_reason };
@@ -1819,7 +1847,7 @@ Load_Coordinator._registry = new Map();
1819
1847
  const class_registry = Object.create(null);
1820
1848
  // Markers for serialized class instances (unique to avoid collisions with user data)
1821
1849
  // Replaced at build time by rollup (see rollup.config.js).
1822
- const CORE_VERSION = '2.3.54';
1850
+ const CORE_VERSION = '2.3.61';
1823
1851
  const CLASS_MARKER = '__jqhtml_class__';
1824
1852
  const PROPS_MARKER = '__jqhtml_props__';
1825
1853
  /**
@@ -3828,10 +3856,10 @@ class Jqhtml_Component {
3828
3856
  // Create a content function that invokes child slots
3829
3857
  // When parent calls content('slotName'), it invokes the child's slot function
3830
3858
  const childSlots = instructions._slots;
3831
- const contentFunction = (slotName, data) => {
3859
+ const contentFunction = (slotName, ...slotArgs) => {
3832
3860
  if (childSlots[slotName] && typeof childSlots[slotName] === 'function') {
3833
- // Invoke the slot function with data parameter
3834
- const [slotInstructions, slotContext] = childSlots[slotName](data);
3861
+ // Invoke the slot function with everything content() was given
3862
+ const [slotInstructions, slotContext] = childSlots[slotName](...slotArgs);
3835
3863
  // Return in render function format: [instructions, context]
3836
3864
  // The template expression handler expects this format
3837
3865
  return [slotInstructions, slotContext];
@@ -3856,12 +3884,11 @@ class Jqhtml_Component {
3856
3884
  instructions = [];
3857
3885
  }
3858
3886
  }
3859
- // Flatten any nested content instructions before processing
3860
- // Instructions may contain ['_content', [...]] markers from content() calls
3861
- const flattenedInstructions = this._flatten_instructions(instructions);
3862
- // Process instructions to generate DOM
3887
+ // Process instructions to generate DOM. ['_content', ...] markers from
3888
+ // content() are handled by the processor, which renders them in the
3889
+ // component that wrote them.
3863
3890
  // This kicks off child component boots but doesn't wait for them
3864
- process_instructions(flattenedInstructions, this.$, this);
3891
+ process_instructions(instructions, this.$, this);
3865
3892
  }
3866
3893
  // Don't update ready state here - let phases complete in order
3867
3894
  this._update_debug_attrs();
@@ -4953,11 +4980,21 @@ class Jqhtml_Component {
4953
4980
  }
4954
4981
  /**
4955
4982
  * Find closest ancestor component matching selector
4983
+ *
4984
+ * A bare component name - a plain identifier starting with a capital letter,
4985
+ * such as 'Parent_Dashboard' - is treated as the component-name class
4986
+ * selector '.Parent_Dashboard'. Components carry a CSS class for every name
4987
+ * in their prototype chain, so a base class name matches its subclasses too.
4988
+ * Every other selector ('.Foo', '#id', '[attr]', 'div > .Component') is
4989
+ * passed to jQuery unchanged.
4956
4990
  */
4957
4991
  closest(selector) {
4992
+ const search = Jqhtml_Component.COMPONENT_NAME_PATTERN.test(selector)
4993
+ ? `.${selector}`
4994
+ : selector;
4958
4995
  let current = this.$.parent();
4959
4996
  while (current.length > 0) {
4960
- if (current.is(selector)) {
4997
+ if (current.is(search)) {
4961
4998
  const comp = current.data('_component');
4962
4999
  if (comp instanceof Jqhtml_Component) {
4963
5000
  return comp;
@@ -5011,26 +5048,6 @@ class Jqhtml_Component {
5011
5048
  _generate_cid() {
5012
5049
  return uid();
5013
5050
  }
5014
- /**
5015
- * Flatten instruction array - converts ['_content', [...]] markers to flat array
5016
- * Recursively flattens nested content from content() calls
5017
- */
5018
- _flatten_instructions(instructions) {
5019
- const result = [];
5020
- for (const instruction of instructions) {
5021
- // Check if this is a _content marker: ['_content', [...]]
5022
- if (Array.isArray(instruction) && instruction[0] === '_content' && Array.isArray(instruction[1])) {
5023
- // Recursively flatten the content instructions
5024
- const contentInstructions = this._flatten_instructions(instruction[1]);
5025
- result.push(...contentInstructions);
5026
- }
5027
- else {
5028
- // Regular instruction - keep as is
5029
- result.push(instruction);
5030
- }
5031
- }
5032
- return result;
5033
- }
5034
5051
  _apply_css_classes() {
5035
5052
  const hierarchy = this.constructor.get_class_hierarchy();
5036
5053
  // If component name differs from class name, add component name to hierarchy
@@ -5254,6 +5271,8 @@ class Jqhtml_Component {
5254
5271
  }
5255
5272
  // Static properties
5256
5273
  Jqhtml_Component.__jqhtml_component = true; // Marker for unified register() detection
5274
+ // A bare component name, as accepted by closest() in place of a class selector
5275
+ Jqhtml_Component.COMPONENT_NAME_PATTERN = /^[A-Z][A-Za-z0-9_]*$/;
5257
5276
 
5258
5277
  /**
5259
5278
  * JQHTML v2 Template Renderer
@@ -6150,7 +6169,7 @@ function init(jQuery, config) {
6150
6169
  }
6151
6170
  }
6152
6171
  // Version - will be replaced during build with actual version from package.json
6153
- const version = '2.3.54';
6172
+ const version = '2.3.61';
6154
6173
  // Default export with all functionality
6155
6174
  const jqhtml = {
6156
6175
  // Core