@xuda.io/runtime-bundle 1.0.1440 → 1.0.1441

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.
@@ -29560,6 +29560,60 @@ func.runtime.ui.set_style = function (target, prop, value) {
29560
29560
  target_node.style[prop] = value;
29561
29561
  return target_node;
29562
29562
  };
29563
+ func.runtime.ui.normalize_external_asset_url = function (value) {
29564
+ if (typeof value !== 'string' || !value.trim()) {
29565
+ return value;
29566
+ }
29567
+
29568
+ const trimmed_value = value.trim();
29569
+ try {
29570
+ const url = new URL(trimmed_value, typeof document !== 'undefined' ? document.baseURI : 'https://xuda.ai');
29571
+ if (url.hostname === 'via.placeholder.com') {
29572
+ url.hostname = 'placehold.co';
29573
+ return url.toString();
29574
+ }
29575
+ } catch (_) {
29576
+ if (trimmed_value.startsWith('https://via.placeholder.com/') || trimmed_value.startsWith('http://via.placeholder.com/')) {
29577
+ return trimmed_value.replace('via.placeholder.com', 'placehold.co');
29578
+ }
29579
+ }
29580
+
29581
+ return value;
29582
+ };
29583
+ func.runtime.ui.normalize_svg_path_value = function (value) {
29584
+ if (typeof value !== 'string' || !value.trim()) {
29585
+ return value;
29586
+ }
29587
+
29588
+ let normalized_value = value.trim();
29589
+
29590
+ // Common AI-generated typo: path data ends with a dangling command after closepath, e.g. "...zzm".
29591
+ normalized_value = normalized_value.replace(/([zZ])+\s*[mMlLhHvVcCsSqQtTaA]\s*$/g, '$1');
29592
+
29593
+ return normalized_value;
29594
+ };
29595
+ func.runtime.ui.normalize_attr_value = function (target_or_tag, key, value) {
29596
+ if (typeof value !== 'string') {
29597
+ return value;
29598
+ }
29599
+
29600
+ const target_tag_name =
29601
+ typeof target_or_tag === 'string'
29602
+ ? target_or_tag
29603
+ : func.runtime.ui.get_first_node(target_or_tag)?.tagName || '';
29604
+ const tag_name = `${target_tag_name || ''}`.trim().toLowerCase();
29605
+ const attr_name = `${key || ''}`.trim().toLowerCase();
29606
+
29607
+ if ((tag_name === 'img' || tag_name === 'image') && ['src', 'href', 'xlink:href'].includes(attr_name)) {
29608
+ return func.runtime.ui.normalize_external_asset_url(value);
29609
+ }
29610
+
29611
+ if (tag_name === 'path' && attr_name === 'd') {
29612
+ return func.runtime.ui.normalize_svg_path_value(value);
29613
+ }
29614
+
29615
+ return value;
29616
+ };
29563
29617
  func.runtime.ui.get_attr = function (target, key) {
29564
29618
  const target_node = func.runtime.ui.get_first_node(target);
29565
29619
  return target_node?.getAttribute?.(key) ?? undefined;
@@ -29567,7 +29621,12 @@ func.runtime.ui.get_attr = function (target, key) {
29567
29621
  func.runtime.ui.set_attr = function (target, key, value) {
29568
29622
  const target_node = func.runtime.ui.get_first_node(target);
29569
29623
  if (target_node?.setAttribute) {
29570
- target_node.setAttribute(key, value);
29624
+ const normalized_value = func.runtime.ui.normalize_attr_value(target_node, key, value);
29625
+ try {
29626
+ target_node.setAttribute(key, normalized_value);
29627
+ } catch (error) {
29628
+ console.warn(`Failed to set attribute "${key}" on <${target_node.tagName?.toLowerCase?.() || 'unknown'}>`, error);
29629
+ }
29571
29630
  }
29572
29631
  return target_node || target;
29573
29632
  };
@@ -29874,7 +29933,12 @@ func.runtime.ui.create_element = function (tag_name, attr_str) {
29874
29933
  while ((match = attr_regex.exec(attr_str)) !== null) {
29875
29934
  const key = match[1];
29876
29935
  const value = match[2] !== undefined ? match[2] : (match[3] !== undefined ? match[3] : (match[4] !== undefined ? match[4] : ''));
29877
- el.setAttribute(key, value);
29936
+ const normalized_value = func.runtime.ui.normalize_attr_value(tag_name, key, value);
29937
+ try {
29938
+ el.setAttribute(key, normalized_value);
29939
+ } catch (error) {
29940
+ console.warn(`Failed to set attribute "${key}" on <${tag_name}>`, error);
29941
+ }
29878
29942
  }
29879
29943
  }
29880
29944
  return el;
@@ -29884,7 +29948,8 @@ func.runtime.ui.create_svg_element = function (element, prop, nodeP, $appendTo)
29884
29948
  let attr_str = '';
29885
29949
  for (const [key, value] of Object.entries(prop)) {
29886
29950
  if (key.substr(0, 2) !== 'xu') {
29887
- attr_str += ` ${key}="${value}" `;
29951
+ const normalized_value = func.runtime.ui.normalize_attr_value(element, key, value);
29952
+ attr_str += ` ${key}="${normalized_value}" `;
29888
29953
  }
29889
29954
  }
29890
29955
  if (element === 'svg') {
@@ -36865,66 +36930,39 @@ const create_runtime_head_element = function (doc, tag_name, attributes, asset_k
36865
36930
  return node;
36866
36931
  };
36867
36932
 
36868
- const queue_runtime_html_script_task = function (task) {
36869
- const queue =
36933
+ const get_runtime_html_script_queue = function () {
36934
+ return (
36870
36935
  func.runtime.render._html_script_queue ||
36871
36936
  (func.runtime.render._html_script_queue = {
36872
36937
  items: [],
36873
- scheduled: false,
36874
36938
  running: false,
36875
- });
36939
+ })
36940
+ );
36941
+ };
36876
36942
 
36943
+ const queue_runtime_html_script_task = function (task) {
36944
+ const queue = get_runtime_html_script_queue();
36877
36945
  queue.items.push(task);
36946
+ };
36878
36947
 
36879
- if (queue.scheduled || queue.running) {
36948
+ func.runtime.render.flush_html_script_queue = async function () {
36949
+ const queue = get_runtime_html_script_queue();
36950
+ if (queue.running || !queue.items.length) {
36880
36951
  return;
36881
36952
  }
36882
36953
 
36883
- queue.scheduled = true;
36884
-
36885
- const drain_queue = async function () {
36886
- if (queue.running) {
36887
- return;
36888
- }
36889
-
36890
- queue.running = true;
36891
- queue.scheduled = false;
36954
+ queue.running = true;
36892
36955
 
36893
- try {
36894
- while (queue.items.length) {
36895
- const next_task = queue.items.shift();
36896
- await next_task();
36897
- }
36898
- } catch (error) {
36899
- console.error(error);
36900
- } finally {
36901
- queue.running = false;
36902
- if (queue.items.length && !queue.scheduled) {
36903
- queue.scheduled = true;
36904
- schedule_runtime_html_script_queue();
36905
- }
36906
- }
36907
- };
36908
-
36909
- const schedule_runtime_html_script_queue = function () {
36910
- const win = func.runtime.platform.get_window?.();
36911
- const run_later = function () {
36912
- setTimeout(function () {
36913
- drain_queue();
36914
- }, 0);
36915
- };
36916
-
36917
- if (win?.requestAnimationFrame) {
36918
- win.requestAnimationFrame(function () {
36919
- win.requestAnimationFrame(run_later);
36920
- });
36921
- return;
36956
+ try {
36957
+ while (queue.items.length) {
36958
+ const next_task = queue.items.shift();
36959
+ await next_task();
36922
36960
  }
36923
-
36924
- run_later();
36925
- };
36926
-
36927
- schedule_runtime_html_script_queue();
36961
+ } catch (error) {
36962
+ console.error(error);
36963
+ } finally {
36964
+ queue.running = false;
36965
+ }
36928
36966
  };
36929
36967
 
36930
36968
  const upsert_runtime_head_element = async function (options) {
@@ -37464,20 +37502,30 @@ func.runtime.render.render_ui_tree = async function (SESSION_ID, $container, nod
37464
37502
  keyP,
37465
37503
  parent_nodeP,
37466
37504
  });
37505
+ const render_depth = func.runtime.render._html_script_render_depth || (func.runtime.render._html_script_render_depth = {});
37506
+ render_depth[SESSION_ID] = (render_depth[SESSION_ID] || 0) + 1;
37467
37507
 
37468
- return await func.runtime.render.render_tree(treeP, {
37469
- SESSION_ID,
37470
- $container,
37471
- parent_infoP,
37472
- paramsP,
37473
- jobNoP,
37474
- is_skeleton,
37475
- keyP,
37476
- refreshed_ds,
37477
- parent_nodeP,
37478
- check_existP,
37479
- $root_container,
37480
- });
37508
+ try {
37509
+ return await func.runtime.render.render_tree(treeP, {
37510
+ SESSION_ID,
37511
+ $container,
37512
+ parent_infoP,
37513
+ paramsP,
37514
+ jobNoP,
37515
+ is_skeleton,
37516
+ keyP,
37517
+ refreshed_ds,
37518
+ parent_nodeP,
37519
+ check_existP,
37520
+ $root_container,
37521
+ });
37522
+ } finally {
37523
+ render_depth[SESSION_ID] = Math.max((render_depth[SESSION_ID] || 1) - 1, 0);
37524
+ if (render_depth[SESSION_ID] === 0) {
37525
+ await func.runtime.render.flush_html_script_queue?.();
37526
+ delete render_depth[SESSION_ID];
37527
+ }
37528
+ }
37481
37529
  };
37482
37530
  func.runtime = func.runtime || {};
37483
37531
  func.runtime.ui = func.runtime.ui || {};