@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.
@@ -4005,6 +4005,12 @@ var gobjJs = (function(exports) {
4005
4005
  * called gobj_short_name() on a null gobj ("gobj bad type"), and a
4006
4006
  * null middle segment threw a TypeError.
4007
4007
  ************************************************************/
4008
+ function list_segment_index(list, seg) {
4009
+ if (!/^[0-9]+$/.test(seg)) return -1;
4010
+ const idx = Number(seg);
4011
+ if (idx >= list.length) return -1;
4012
+ return idx;
4013
+ }
4008
4014
  function kw_find_path(gobj, kw, path, verbose) {
4009
4015
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
4010
4016
  const prefix = gobj ? `${gobj_short_name(gobj)}: ` : "";
@@ -4020,11 +4026,12 @@ var gobjJs = (function(exports) {
4020
4026
  let len = ss.length;
4021
4027
  for (let i = 0; i < len; i++) {
4022
4028
  if (is_array(kw)) {
4023
- if (!/^[0-9]+$/.test(ss[i])) {
4029
+ const idx = list_segment_index(kw, ss[i]);
4030
+ if (idx < 0) {
4024
4031
  if (verbose) log_error(`${prefix}path not found: '${path}'`);
4025
4032
  return;
4026
4033
  }
4027
- ss[i] = String(Number(ss[i]));
4034
+ ss[i] = String(idx);
4028
4035
  }
4029
4036
  if (is_prototype_segment(kw, ss[i])) {
4030
4037
  if (verbose) log_error(`${prefix}path not found: '${path}'`);
@@ -4059,8 +4066,14 @@ var gobjJs = (function(exports) {
4059
4066
  function kw_delete(gobj, kw, path) {
4060
4067
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
4061
4068
  let [path_, k] = strrchr_split(path, "`");
4062
- if (!empty_string(k)) json_object_del(kw_find_path(gobj, kw, path_, true), k);
4063
- else json_object_del(kw, path);
4069
+ if (!empty_string(k)) {
4070
+ let v = kw_find_path(gobj, kw, path_, true);
4071
+ if (is_array(v)) {
4072
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}kw_delete(): cannot delete an item of a list: '${path}'`);
4073
+ return -1;
4074
+ }
4075
+ json_object_del(v, k);
4076
+ } else json_object_del(kw, path);
4064
4077
  return 0;
4065
4078
  }
4066
4079
  /************************************************************
@@ -4416,6 +4429,14 @@ var gobjJs = (function(exports) {
4416
4429
  let len = ss.length;
4417
4430
  for (let i = 0; i < len; i++) {
4418
4431
  let key = ss[i];
4432
+ if (is_array(kw)) {
4433
+ const idx = list_segment_index(kw, key);
4434
+ if (idx < 0) {
4435
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}kw_set_dict_value(): segment '${key}' is not an index of its list: '${path}'`);
4436
+ return -1;
4437
+ }
4438
+ key = String(idx);
4439
+ }
4419
4440
  if (i === len - 1) set_own_key(kw, key, value);
4420
4441
  else {
4421
4442
  let seg = is_prototype_segment(kw, key) ? void 0 : kw[key];
@@ -5402,6 +5423,68 @@ var gobjJs = (function(exports) {
5402
5423
  /***************************************************************************
5403
5424
  *
5404
5425
  ***************************************************************************/
5426
+ /***************************************************************************
5427
+ * Markup that createElement2() inserts AS HTML, said out loud.
5428
+ *
5429
+ * createElement2() reads a string that starts with '<' as markup. That
5430
+ * decision depends on the CONTENT of the string, not on who wrote it, so
5431
+ * a value from a backend or typed by a user that starts with '<' runs as
5432
+ * html. html_markup() is the explicit way to ask for markup: the string
5433
+ * is the caller's own (an icon, an svg), never data.
5434
+ *
5435
+ * ['span', {class: 'icon'}, html_markup('<i class="yi-copy"></i>')]
5436
+ *
5437
+ * With set_strings_are_text(true) a plain string is ALWAYS text and
5438
+ * html_markup() is the only way to insert markup.
5439
+ ***************************************************************************/
5440
+ var HtmlMarkup = class {
5441
+ constructor(html) {
5442
+ this.html = html;
5443
+ Object.freeze(this);
5444
+ }
5445
+ toString() {
5446
+ return this.html;
5447
+ }
5448
+ };
5449
+ function html_markup(html) {
5450
+ if (typeof html !== "string") {
5451
+ log_error(`html_markup: not a string, type ${typeof html}`);
5452
+ return new HtmlMarkup("");
5453
+ }
5454
+ return new HtmlMarkup(html);
5455
+ }
5456
+ function is_html_markup(v) {
5457
+ return v instanceof HtmlMarkup;
5458
+ }
5459
+ function markup_fragment(markup) {
5460
+ const template = document.createElement("template");
5461
+ template.innerHTML = markup.html.trim();
5462
+ return template.content;
5463
+ }
5464
+ var __strings_are_text__ = false;
5465
+ var __markup_strings_warned__ = /* @__PURE__ */ new Set();
5466
+ /***************************************************************************
5467
+ * The mode of createElement2() for a plain string that starts with '<':
5468
+ * false (default): it is markup, as it always was.
5469
+ * true: it is TEXT; markup is asked for with html_markup().
5470
+ * An app turns it on once its own code and the libraries it mounts pass
5471
+ * every deliberate markup through html_markup(). A string that starts
5472
+ * with '<' is then logged once (a deliberate one not migrated yet, or a
5473
+ * datum that used to run as html).
5474
+ ***************************************************************************/
5475
+ function set_strings_are_text(on) {
5476
+ __strings_are_text__ = !!on;
5477
+ }
5478
+ function strings_are_text() {
5479
+ return __strings_are_text__;
5480
+ }
5481
+ function warn_markup_string(content) {
5482
+ if (__markup_strings_warned__.size >= 100) return;
5483
+ const key = content.slice(0, 80);
5484
+ if (__markup_strings_warned__.has(key)) return;
5485
+ __markup_strings_warned__.add(key);
5486
+ log_warning(`createElement2: a string that starts with '<' is TEXT (set_strings_are_text): use html_markup() if it is markup: ${JSON.stringify(key)}`);
5487
+ }
5405
5488
  function createOneHtml(htmlString) {
5406
5489
  const template = document.createElement("template");
5407
5490
  template.innerHTML = htmlString.trim();
@@ -5563,6 +5646,7 @@ var gobjJs = (function(exports) {
5563
5646
  * if string begins with '<' then
5564
5647
  * it will be converted to HTMLElement
5565
5648
  * content = createOneHtml(string)
5649
+ * | html_markup(string): markup, said out loud (any mode)
5566
5650
  * ⚠️ So a string is MARKUP when it starts with '<': never
5567
5651
  * pass DATA (a value from a backend, a name a user typed)
5568
5652
  * as a bare string, or "<img src=x onerror=...>" runs.
@@ -5572,6 +5656,8 @@ var gobjJs = (function(exports) {
5572
5656
  * appended as it is and a string is always text -- but a
5573
5657
  * list whose first item is a string is read as ONE
5574
5658
  * description (the string is its tag).
5659
+ * With set_strings_are_text(true) a plain string is
5660
+ * always text, and markup only comes in html_markup().
5575
5661
  * if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')
5576
5662
  * it will be overridden with the translation
5577
5663
  * content = translate(attrs['i18n']));
@@ -5614,19 +5700,24 @@ var gobjJs = (function(exports) {
5614
5700
  el.setAttribute("data-i18n", data_i18next);
5615
5701
  }
5616
5702
  } else el.setAttribute(attr, attrs[attr]);
5617
- if (is_string(content)) {
5703
+ if (is_html_markup(content)) el.appendChild(markup_fragment(content));
5704
+ else if (is_string(content)) {
5618
5705
  content = content.trim();
5619
- if (content.length > 0 && content[0] === "<") el.appendChild(createOneHtml(content));
5620
- else if (translate_fn && data_i18next) {
5621
- let translated = translate_fn(data_i18next);
5622
- el.textContent = translated ? translated : content;
5623
- } else el.textContent = content;
5706
+ if (content.length > 0 && content[0] === "<" && !__strings_are_text__) el.appendChild(createOneHtml(content));
5707
+ else {
5708
+ if (content.length > 0 && content[0] === "<") warn_markup_string(content);
5709
+ if (translate_fn && data_i18next) {
5710
+ let translated = translate_fn(data_i18next);
5711
+ el.textContent = translated ? translated : content;
5712
+ } else el.textContent = content;
5713
+ }
5624
5714
  } else if (is_array(content)) {
5625
5715
  if (content.length > 0) {
5626
5716
  if (is_string(content[0])) el.appendChild(createElement2(content, translate_fn));
5627
5717
  else for (let child of content) if (Array.isArray(child)) {
5628
5718
  if (child.length > 0) el.appendChild(createElement2(child, translate_fn));
5629
5719
  } else if (child instanceof Node) el.appendChild(child);
5720
+ else if (is_html_markup(child)) el.appendChild(markup_fragment(child));
5630
5721
  else if (is_string(child)) el.appendChild(document.createTextNode(child));
5631
5722
  else if (child !== null && child !== void 0 && child !== false) log_error(`createElement2: child ignored, type ${typeof child}`);
5632
5723
  }
@@ -7232,13 +7323,13 @@ var gobjJs = (function(exports) {
7232
7323
  websocket = new WebSocket(url);
7233
7324
  } catch (e) {
7234
7325
  log_error(`${gobj_short_name(gobj)}: Cannot open WebSocket to '${url}', Error: ${e.message}`);
7235
- gobj_post_event(gobj, "EV_ON_CLOSE", {
7326
+ if (gobj_post_event(gobj, "EV_ON_CLOSE", {
7236
7327
  url,
7237
7328
  ws_seq,
7238
7329
  code: 1006,
7239
7330
  reason: e.message,
7240
7331
  was_clean: false
7241
- }, gobj);
7332
+ }, gobj) < 0) set_timeout(gobj.priv.gobj_timer, next_retry(gobj));
7242
7333
  return null;
7243
7334
  }
7244
7335
  if (!websocket) {
@@ -7977,6 +8068,7 @@ var gobjJs = (function(exports) {
7977
8068
  exports.gobj_yuno_id = gobj_yuno_id;
7978
8069
  exports.gobj_yuno_name = gobj_yuno_name;
7979
8070
  exports.gobj_yuno_role = gobj_yuno_role;
8071
+ exports.html_markup = html_markup;
7980
8072
  exports.id_index_in_obj_list = id_index_in_obj_list;
7981
8073
  exports.index_in_list = index_in_list;
7982
8074
  exports.is_array = is_array;
@@ -7984,6 +8076,7 @@ var gobjJs = (function(exports) {
7984
8076
  exports.is_date = is_date;
7985
8077
  exports.is_function = is_function;
7986
8078
  exports.is_gobj = is_gobj;
8079
+ exports.is_html_markup = is_html_markup;
7987
8080
  exports.is_metadata_key = is_metadata_key;
7988
8081
  exports.is_null = is_null;
7989
8082
  exports.is_number = is_number;
@@ -8075,6 +8168,7 @@ var gobjJs = (function(exports) {
8075
8168
  exports.set_console_log_filter = set_console_log_filter;
8076
8169
  exports.set_log_callback = set_log_callback;
8077
8170
  exports.set_remote_log_functions = set_remote_log_functions;
8171
+ exports.set_strings_are_text = set_strings_are_text;
8078
8172
  exports.set_timeout = set_timeout;
8079
8173
  exports.set_timeout_periodic = set_timeout_periodic;
8080
8174
  exports.sprintf = sprintf;
@@ -8082,6 +8176,7 @@ var gobjJs = (function(exports) {
8082
8176
  exports.str_in_list = str_in_list;
8083
8177
  exports.strcasecmp = strcasecmp;
8084
8178
  exports.strcmp = strcmp;
8179
+ exports.strings_are_text = strings_are_text;
8085
8180
  exports.strncmp = strncmp;
8086
8181
  exports.strs_in_list = strs_in_list;
8087
8182
  exports.strstr = strstr;