@yuneta/gobj-js 7.26.2 → 7.26.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.
@@ -4003,6 +4003,12 @@ function set_own_key(obj, key, value) {
4003
4003
  * called gobj_short_name() on a null gobj ("gobj bad type"), and a
4004
4004
  * null middle segment threw a TypeError.
4005
4005
  ************************************************************/
4006
+ function list_segment_index(list, seg) {
4007
+ if (!/^[0-9]+$/.test(seg)) return -1;
4008
+ const idx = Number(seg);
4009
+ if (idx >= list.length) return -1;
4010
+ return idx;
4011
+ }
4006
4012
  function kw_find_path(gobj, kw, path, verbose) {
4007
4013
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
4008
4014
  const prefix = gobj ? `${gobj_short_name(gobj)}: ` : "";
@@ -4018,11 +4024,12 @@ function kw_find_path(gobj, kw, path, verbose) {
4018
4024
  let len = ss.length;
4019
4025
  for (let i = 0; i < len; i++) {
4020
4026
  if (is_array(kw)) {
4021
- if (!/^[0-9]+$/.test(ss[i])) {
4027
+ const idx = list_segment_index(kw, ss[i]);
4028
+ if (idx < 0) {
4022
4029
  if (verbose) log_error(`${prefix}path not found: '${path}'`);
4023
4030
  return;
4024
4031
  }
4025
- ss[i] = String(Number(ss[i]));
4032
+ ss[i] = String(idx);
4026
4033
  }
4027
4034
  if (is_prototype_segment(kw, ss[i])) {
4028
4035
  if (verbose) log_error(`${prefix}path not found: '${path}'`);
@@ -4057,8 +4064,14 @@ function strrchr_split(str, char) {
4057
4064
  function kw_delete(gobj, kw, path) {
4058
4065
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
4059
4066
  let [path_, k] = strrchr_split(path, "`");
4060
- if (!empty_string(k)) json_object_del(kw_find_path(gobj, kw, path_, true), k);
4061
- else json_object_del(kw, path);
4067
+ if (!empty_string(k)) {
4068
+ let v = kw_find_path(gobj, kw, path_, true);
4069
+ if (is_array(v)) {
4070
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}kw_delete(): cannot delete an item of a list: '${path}'`);
4071
+ return -1;
4072
+ }
4073
+ json_object_del(v, k);
4074
+ } else json_object_del(kw, path);
4062
4075
  return 0;
4063
4076
  }
4064
4077
  /************************************************************
@@ -4414,6 +4427,14 @@ function kw_set_dict_value(gobj, kw, path, value) {
4414
4427
  let len = ss.length;
4415
4428
  for (let i = 0; i < len; i++) {
4416
4429
  let key = ss[i];
4430
+ if (is_array(kw)) {
4431
+ const idx = list_segment_index(kw, key);
4432
+ if (idx < 0) {
4433
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}kw_set_dict_value(): segment '${key}' is not an index of its list: '${path}'`);
4434
+ return -1;
4435
+ }
4436
+ key = String(idx);
4437
+ }
4417
4438
  if (i === len - 1) set_own_key(kw, key, value);
4418
4439
  else {
4419
4440
  let seg = is_prototype_segment(kw, key) ? void 0 : kw[key];
@@ -5400,6 +5421,68 @@ function safeSrc(url) {
5400
5421
  /***************************************************************************
5401
5422
  *
5402
5423
  ***************************************************************************/
5424
+ /***************************************************************************
5425
+ * Markup that createElement2() inserts AS HTML, said out loud.
5426
+ *
5427
+ * createElement2() reads a string that starts with '<' as markup. That
5428
+ * decision depends on the CONTENT of the string, not on who wrote it, so
5429
+ * a value from a backend or typed by a user that starts with '<' runs as
5430
+ * html. html_markup() is the explicit way to ask for markup: the string
5431
+ * is the caller's own (an icon, an svg), never data.
5432
+ *
5433
+ * ['span', {class: 'icon'}, html_markup('<i class="yi-copy"></i>')]
5434
+ *
5435
+ * With set_strings_are_text(true) a plain string is ALWAYS text and
5436
+ * html_markup() is the only way to insert markup.
5437
+ ***************************************************************************/
5438
+ var HtmlMarkup = class {
5439
+ constructor(html) {
5440
+ this.html = html;
5441
+ Object.freeze(this);
5442
+ }
5443
+ toString() {
5444
+ return this.html;
5445
+ }
5446
+ };
5447
+ function html_markup(html) {
5448
+ if (typeof html !== "string") {
5449
+ log_error(`html_markup: not a string, type ${typeof html}`);
5450
+ return new HtmlMarkup("");
5451
+ }
5452
+ return new HtmlMarkup(html);
5453
+ }
5454
+ function is_html_markup(v) {
5455
+ return v instanceof HtmlMarkup;
5456
+ }
5457
+ function markup_fragment(markup) {
5458
+ const template = document.createElement("template");
5459
+ template.innerHTML = markup.html.trim();
5460
+ return template.content;
5461
+ }
5462
+ var __strings_are_text__ = false;
5463
+ var __markup_strings_warned__ = /* @__PURE__ */ new Set();
5464
+ /***************************************************************************
5465
+ * The mode of createElement2() for a plain string that starts with '<':
5466
+ * false (default): it is markup, as it always was.
5467
+ * true: it is TEXT; markup is asked for with html_markup().
5468
+ * An app turns it on once its own code and the libraries it mounts pass
5469
+ * every deliberate markup through html_markup(). A string that starts
5470
+ * with '<' is then logged once (a deliberate one not migrated yet, or a
5471
+ * datum that used to run as html).
5472
+ ***************************************************************************/
5473
+ function set_strings_are_text(on) {
5474
+ __strings_are_text__ = !!on;
5475
+ }
5476
+ function strings_are_text() {
5477
+ return __strings_are_text__;
5478
+ }
5479
+ function warn_markup_string(content) {
5480
+ if (__markup_strings_warned__.size >= 100) return;
5481
+ const key = content.slice(0, 80);
5482
+ if (__markup_strings_warned__.has(key)) return;
5483
+ __markup_strings_warned__.add(key);
5484
+ log_warning(`createElement2: a string that starts with '<' is TEXT (set_strings_are_text): use html_markup() if it is markup: ${JSON.stringify(key)}`);
5485
+ }
5403
5486
  function createOneHtml(htmlString) {
5404
5487
  const template = document.createElement("template");
5405
5488
  template.innerHTML = htmlString.trim();
@@ -5561,6 +5644,7 @@ parent: document.body
5561
5644
  * if string begins with '<' then
5562
5645
  * it will be converted to HTMLElement
5563
5646
  * content = createOneHtml(string)
5647
+ * | html_markup(string): markup, said out loud (any mode)
5564
5648
  * ⚠️ So a string is MARKUP when it starts with '<': never
5565
5649
  * pass DATA (a value from a backend, a name a user typed)
5566
5650
  * as a bare string, or "<img src=x onerror=...>" runs.
@@ -5570,6 +5654,8 @@ parent: document.body
5570
5654
  * appended as it is and a string is always text -- but a
5571
5655
  * list whose first item is a string is read as ONE
5572
5656
  * description (the string is its tag).
5657
+ * With set_strings_are_text(true) a plain string is
5658
+ * always text, and markup only comes in html_markup().
5573
5659
  * if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')
5574
5660
  * it will be overridden with the translation
5575
5661
  * content = translate(attrs['i18n']));
@@ -5612,19 +5698,24 @@ function createElement2(description, translate_fn) {
5612
5698
  el.setAttribute("data-i18n", data_i18next);
5613
5699
  }
5614
5700
  } else el.setAttribute(attr, attrs[attr]);
5615
- if (is_string(content)) {
5701
+ if (is_html_markup(content)) el.appendChild(markup_fragment(content));
5702
+ else if (is_string(content)) {
5616
5703
  content = content.trim();
5617
- if (content.length > 0 && content[0] === "<") el.appendChild(createOneHtml(content));
5618
- else if (translate_fn && data_i18next) {
5619
- let translated = translate_fn(data_i18next);
5620
- el.textContent = translated ? translated : content;
5621
- } else el.textContent = content;
5704
+ if (content.length > 0 && content[0] === "<" && !__strings_are_text__) el.appendChild(createOneHtml(content));
5705
+ else {
5706
+ if (content.length > 0 && content[0] === "<") warn_markup_string(content);
5707
+ if (translate_fn && data_i18next) {
5708
+ let translated = translate_fn(data_i18next);
5709
+ el.textContent = translated ? translated : content;
5710
+ } else el.textContent = content;
5711
+ }
5622
5712
  } else if (is_array(content)) {
5623
5713
  if (content.length > 0) {
5624
5714
  if (is_string(content[0])) el.appendChild(createElement2(content, translate_fn));
5625
5715
  else for (let child of content) if (Array.isArray(child)) {
5626
5716
  if (child.length > 0) el.appendChild(createElement2(child, translate_fn));
5627
5717
  } else if (child instanceof Node) el.appendChild(child);
5718
+ else if (is_html_markup(child)) el.appendChild(markup_fragment(child));
5628
5719
  else if (is_string(child)) el.appendChild(document.createTextNode(child));
5629
5720
  else if (child !== null && child !== void 0 && child !== false) log_error(`createElement2: child ignored, type ${typeof child}`);
5630
5721
  }
@@ -7230,13 +7321,13 @@ function setup_websocket(gobj) {
7230
7321
  websocket = new WebSocket(url);
7231
7322
  } catch (e) {
7232
7323
  log_error(`${gobj_short_name(gobj)}: Cannot open WebSocket to '${url}', Error: ${e.message}`);
7233
- gobj_post_event(gobj, "EV_ON_CLOSE", {
7324
+ if (gobj_post_event(gobj, "EV_ON_CLOSE", {
7234
7325
  url,
7235
7326
  ws_seq,
7236
7327
  code: 1006,
7237
7328
  reason: e.message,
7238
7329
  was_clean: false
7239
- }, gobj);
7330
+ }, gobj) < 0) set_timeout(gobj.priv.gobj_timer, next_retry(gobj));
7240
7331
  return null;
7241
7332
  }
7242
7333
  if (!websocket) {
@@ -7814,6 +7905,6 @@ function register_c_ievent_cli() {
7814
7905
  return create_gclass(GCLASS_NAME);
7815
7906
  }
7816
7907
  //#endregion
7817
- export { GObj, SDATA, SDATAAUTHZ, SDATACM, SDATACM2, SDATADF, SDATAPM, SDATAPM0, SDATA_END, SDataDesc, YUNETA_VERSION, __yuno__, build_command_response, build_path, build_stats_response, clean_name, clear_timeout, cmp_two_simple_json, command_parser, createElement2, createOneHtml, create_json_record, create_template_record, current_timestamp, data_type_t, db_list_persistent_attrs, db_load_persistent_attrs, db_remove_persistent_attrs, db_save_persistent_attrs, debounce, delete_from_list, duplicate_objects, empty_json, empty_string, escapeHtml, event_flag_t, flat2json, flat_apply, flat_diff, flat_key_join, flat_key_split, gclass_add_ev_action, gclass_add_event_type, gclass_add_state, gclass_check_fsm, gclass_create, gclass_event_type, gclass_find_by_name, gclass_flag_t, gclass_unregister, getPositionRelativeToBody, get_function_name, get_now, gobj_bottom_gobj, gobj_change_parent, gobj_change_state, gobj_command, gobj_create, gobj_create2, gobj_create_default_service, gobj_create_pure_child, gobj_create_service, gobj_create_volatil, gobj_create_yuno, gobj_current_state, gobj_default_service, gobj_deliver_posted_events, gobj_destroy, gobj_find_child, gobj_find_gobj, gobj_find_service, gobj_find_subscribings, gobj_find_subscriptions, gobj_flag_t, gobj_full_name, gobj_gclass_name, gobj_get_gclass_trace_level, gobj_get_gclass_trace_level2, gobj_get_gclass_trace_no_level, gobj_get_global_trace_level, gobj_get_global_trace_no_level, gobj_global_trace_level, gobj_global_trace_no_level, gobj_has_attr, gobj_has_event, gobj_has_output_event, gobj_hsdata, gobj_is_destroying, gobj_is_playing, gobj_is_pure_child, gobj_is_running, gobj_is_service, gobj_is_volatil, gobj_list_persistent_attrs, gobj_list_subscriptions, gobj_load_persistent_attrs, gobj_match_children, gobj_match_children_tree, gobj_match_gobj, gobj_name, gobj_parent, gobj_pause, gobj_play, gobj_post_event, gobj_posted_events_size, gobj_publish_event, gobj_read_attr, gobj_read_attrs, gobj_read_bool_attr, gobj_read_integer_attr, gobj_read_pointer_attr, gobj_read_str_attr, gobj_remove_persistent_attrs, gobj_repr_global_trace_levels, gobj_reset_volatil_attrs, gobj_save_persistent_attrs, gobj_search_path, gobj_send_event, gobj_services, gobj_set_bottom_gobj, gobj_set_deep_trace, gobj_set_gclass_no_trace, gobj_set_gclass_trace, gobj_set_global_no_trace, gobj_set_global_no_trace2, gobj_set_global_trace, gobj_set_global_trace2, gobj_set_gobj_no_trace, gobj_set_gobj_trace, gobj_set_trace_machine_format, gobj_short_name, gobj_start, gobj_start_children, gobj_start_tree, gobj_start_up, gobj_stats, gobj_stop, gobj_stop_children, gobj_stop_tree, gobj_subscribe_event, gobj_trace_level, gobj_trace_machine_format, gobj_trace_no_level, gobj_unsubscribe_event, gobj_unsubscribe_list, gobj_walk_gobj_children, gobj_walk_gobj_children_tree, gobj_write_attr, gobj_write_attrs, gobj_write_bool_attr, gobj_write_integer_attr, gobj_write_str_attr, gobj_yuno, gobj_yuno_id, gobj_yuno_name, gobj_yuno_role, id_index_in_obj_list, index_in_list, is_array, is_boolean, is_date, is_function, is_gobj, is_metadata_key, is_null, is_number, is_object, is_private_key, is_pure_number, is_secret_name, is_string, jdb_delete, jdb_get, jdb_get_by_idx, jdb_get_topic, jdb_init, jdb_update, json2flat, json_array_append, json_array_append_new, json_array_extend, json_array_remove, json_array_size, json_deep_copy, json_is_identical, json_mask_secrets, json_object_del, json_object_get, json_object_set, json_object_set_new, json_object_size, json_object_update, json_object_update_existing, json_object_update_missing, json_size, jwt2json, jwtDecode, kw_clone_by_keys, kw_clone_by_not_keys, kw_collect, kw_delete, kw_find_json_in_list, kw_find_path, kw_flag_t, kw_get_bool, kw_get_dict, kw_get_dict_value, kw_get_int, kw_get_list, kw_get_local_storage_value, kw_get_pointer, kw_get_real, kw_get_str, kw_has_key, kw_match_simple, kw_pop, kw_remove_local_storage_value, kw_select, kw_set_dict_value, kw_set_local_storage_value, kw_set_subdict_value, kwid_collect, kwid_find_one_record, kwid_get_ids, kwid_match_id, kwid_new_dict, kwid_new_list, list2options, load_json_file, log_debug, log_error, log_info, log_warning, mask_secrets_inline, msg_iev_get_msg_type, msg_iev_get_stack, msg_iev_push_stack, msg_iev_read_key, msg_iev_set_msg_type, msg_iev_write_key, node_uuid, parseBoolean, parseSVG, refresh_language, register_c_ievent_cli, register_c_timer, register_c_yuno, safeSrc, sdata_flag_t, send_http_json_post, set_console_log_enabled, set_console_log_filter, set_log_callback, set_remote_log_functions, set_timeout, set_timeout_periodic, sprintf, stats_parser, str_in_list, strcasecmp, strcmp, strncmp, strs_in_list, strstr, template_get_field_desc, timeTracker, trace_json, trace_json_masked, trace_level_t, trace_msg, treedb_decoder_fkey, treedb_decoder_hook, treedb_encoder_fkey, treedb_get_field_desc, treedb_hook_data_size, vsprintf, walk_type_t };
7908
+ export { GObj, SDATA, SDATAAUTHZ, SDATACM, SDATACM2, SDATADF, SDATAPM, SDATAPM0, SDATA_END, SDataDesc, YUNETA_VERSION, __yuno__, build_command_response, build_path, build_stats_response, clean_name, clear_timeout, cmp_two_simple_json, command_parser, createElement2, createOneHtml, create_json_record, create_template_record, current_timestamp, data_type_t, db_list_persistent_attrs, db_load_persistent_attrs, db_remove_persistent_attrs, db_save_persistent_attrs, debounce, delete_from_list, duplicate_objects, empty_json, empty_string, escapeHtml, event_flag_t, flat2json, flat_apply, flat_diff, flat_key_join, flat_key_split, gclass_add_ev_action, gclass_add_event_type, gclass_add_state, gclass_check_fsm, gclass_create, gclass_event_type, gclass_find_by_name, gclass_flag_t, gclass_unregister, getPositionRelativeToBody, get_function_name, get_now, gobj_bottom_gobj, gobj_change_parent, gobj_change_state, gobj_command, gobj_create, gobj_create2, gobj_create_default_service, gobj_create_pure_child, gobj_create_service, gobj_create_volatil, gobj_create_yuno, gobj_current_state, gobj_default_service, gobj_deliver_posted_events, gobj_destroy, gobj_find_child, gobj_find_gobj, gobj_find_service, gobj_find_subscribings, gobj_find_subscriptions, gobj_flag_t, gobj_full_name, gobj_gclass_name, gobj_get_gclass_trace_level, gobj_get_gclass_trace_level2, gobj_get_gclass_trace_no_level, gobj_get_global_trace_level, gobj_get_global_trace_no_level, gobj_global_trace_level, gobj_global_trace_no_level, gobj_has_attr, gobj_has_event, gobj_has_output_event, gobj_hsdata, gobj_is_destroying, gobj_is_playing, gobj_is_pure_child, gobj_is_running, gobj_is_service, gobj_is_volatil, gobj_list_persistent_attrs, gobj_list_subscriptions, gobj_load_persistent_attrs, gobj_match_children, gobj_match_children_tree, gobj_match_gobj, gobj_name, gobj_parent, gobj_pause, gobj_play, gobj_post_event, gobj_posted_events_size, gobj_publish_event, gobj_read_attr, gobj_read_attrs, gobj_read_bool_attr, gobj_read_integer_attr, gobj_read_pointer_attr, gobj_read_str_attr, gobj_remove_persistent_attrs, gobj_repr_global_trace_levels, gobj_reset_volatil_attrs, gobj_save_persistent_attrs, gobj_search_path, gobj_send_event, gobj_services, gobj_set_bottom_gobj, gobj_set_deep_trace, gobj_set_gclass_no_trace, gobj_set_gclass_trace, gobj_set_global_no_trace, gobj_set_global_no_trace2, gobj_set_global_trace, gobj_set_global_trace2, gobj_set_gobj_no_trace, gobj_set_gobj_trace, gobj_set_trace_machine_format, gobj_short_name, gobj_start, gobj_start_children, gobj_start_tree, gobj_start_up, gobj_stats, gobj_stop, gobj_stop_children, gobj_stop_tree, gobj_subscribe_event, gobj_trace_level, gobj_trace_machine_format, gobj_trace_no_level, gobj_unsubscribe_event, gobj_unsubscribe_list, gobj_walk_gobj_children, gobj_walk_gobj_children_tree, gobj_write_attr, gobj_write_attrs, gobj_write_bool_attr, gobj_write_integer_attr, gobj_write_str_attr, gobj_yuno, gobj_yuno_id, gobj_yuno_name, gobj_yuno_role, html_markup, id_index_in_obj_list, index_in_list, is_array, is_boolean, is_date, is_function, is_gobj, is_html_markup, is_metadata_key, is_null, is_number, is_object, is_private_key, is_pure_number, is_secret_name, is_string, jdb_delete, jdb_get, jdb_get_by_idx, jdb_get_topic, jdb_init, jdb_update, json2flat, json_array_append, json_array_append_new, json_array_extend, json_array_remove, json_array_size, json_deep_copy, json_is_identical, json_mask_secrets, json_object_del, json_object_get, json_object_set, json_object_set_new, json_object_size, json_object_update, json_object_update_existing, json_object_update_missing, json_size, jwt2json, jwtDecode, kw_clone_by_keys, kw_clone_by_not_keys, kw_collect, kw_delete, kw_find_json_in_list, kw_find_path, kw_flag_t, kw_get_bool, kw_get_dict, kw_get_dict_value, kw_get_int, kw_get_list, kw_get_local_storage_value, kw_get_pointer, kw_get_real, kw_get_str, kw_has_key, kw_match_simple, kw_pop, kw_remove_local_storage_value, kw_select, kw_set_dict_value, kw_set_local_storage_value, kw_set_subdict_value, kwid_collect, kwid_find_one_record, kwid_get_ids, kwid_match_id, kwid_new_dict, kwid_new_list, list2options, load_json_file, log_debug, log_error, log_info, log_warning, mask_secrets_inline, msg_iev_get_msg_type, msg_iev_get_stack, msg_iev_push_stack, msg_iev_read_key, msg_iev_set_msg_type, msg_iev_write_key, node_uuid, parseBoolean, parseSVG, refresh_language, register_c_ievent_cli, register_c_timer, register_c_yuno, safeSrc, sdata_flag_t, send_http_json_post, set_console_log_enabled, set_console_log_filter, set_log_callback, set_remote_log_functions, set_strings_are_text, set_timeout, set_timeout_periodic, sprintf, stats_parser, str_in_list, strcasecmp, strcmp, strings_are_text, strncmp, strs_in_list, strstr, template_get_field_desc, timeTracker, trace_json, trace_json_masked, trace_level_t, trace_msg, treedb_decoder_fkey, treedb_decoder_hook, treedb_encoder_fkey, treedb_get_field_desc, treedb_hook_data_size, vsprintf, walk_type_t };
7818
7909
 
7819
7910
  //# sourceMappingURL=gobj-js.es.js.map