@yuneta/gobj-js 7.26.2 → 7.26.3

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.
@@ -5404,6 +5404,68 @@
5404
5404
  /***************************************************************************
5405
5405
  *
5406
5406
  ***************************************************************************/
5407
+ /***************************************************************************
5408
+ * Markup that createElement2() inserts AS HTML, said out loud.
5409
+ *
5410
+ * createElement2() reads a string that starts with '<' as markup. That
5411
+ * decision depends on the CONTENT of the string, not on who wrote it, so
5412
+ * a value from a backend or typed by a user that starts with '<' runs as
5413
+ * html. html_markup() is the explicit way to ask for markup: the string
5414
+ * is the caller's own (an icon, an svg), never data.
5415
+ *
5416
+ * ['span', {class: 'icon'}, html_markup('<i class="yi-copy"></i>')]
5417
+ *
5418
+ * With set_strings_are_text(true) a plain string is ALWAYS text and
5419
+ * html_markup() is the only way to insert markup.
5420
+ ***************************************************************************/
5421
+ var HtmlMarkup = class {
5422
+ constructor(html) {
5423
+ this.html = html;
5424
+ Object.freeze(this);
5425
+ }
5426
+ toString() {
5427
+ return this.html;
5428
+ }
5429
+ };
5430
+ function html_markup(html) {
5431
+ if (typeof html !== "string") {
5432
+ log_error(`html_markup: not a string, type ${typeof html}`);
5433
+ return new HtmlMarkup("");
5434
+ }
5435
+ return new HtmlMarkup(html);
5436
+ }
5437
+ function is_html_markup(v) {
5438
+ return v instanceof HtmlMarkup;
5439
+ }
5440
+ function markup_fragment(markup) {
5441
+ const template = document.createElement("template");
5442
+ template.innerHTML = markup.html.trim();
5443
+ return template.content;
5444
+ }
5445
+ var __strings_are_text__ = false;
5446
+ var __markup_strings_warned__ = /* @__PURE__ */ new Set();
5447
+ /***************************************************************************
5448
+ * The mode of createElement2() for a plain string that starts with '<':
5449
+ * false (default): it is markup, as it always was.
5450
+ * true: it is TEXT; markup is asked for with html_markup().
5451
+ * An app turns it on once its own code and the libraries it mounts pass
5452
+ * every deliberate markup through html_markup(). A string that starts
5453
+ * with '<' is then logged once (a deliberate one not migrated yet, or a
5454
+ * datum that used to run as html).
5455
+ ***************************************************************************/
5456
+ function set_strings_are_text(on) {
5457
+ __strings_are_text__ = !!on;
5458
+ }
5459
+ function strings_are_text() {
5460
+ return __strings_are_text__;
5461
+ }
5462
+ function warn_markup_string(content) {
5463
+ if (__markup_strings_warned__.size >= 100) return;
5464
+ const key = content.slice(0, 80);
5465
+ if (__markup_strings_warned__.has(key)) return;
5466
+ __markup_strings_warned__.add(key);
5467
+ log_warning(`createElement2: a string that starts with '<' is TEXT (set_strings_are_text): use html_markup() if it is markup: ${JSON.stringify(key)}`);
5468
+ }
5407
5469
  function createOneHtml(htmlString) {
5408
5470
  const template = document.createElement("template");
5409
5471
  template.innerHTML = htmlString.trim();
@@ -5565,6 +5627,7 @@
5565
5627
  * if string begins with '<' then
5566
5628
  * it will be converted to HTMLElement
5567
5629
  * content = createOneHtml(string)
5630
+ * | html_markup(string): markup, said out loud (any mode)
5568
5631
  * ⚠️ So a string is MARKUP when it starts with '<': never
5569
5632
  * pass DATA (a value from a backend, a name a user typed)
5570
5633
  * as a bare string, or "<img src=x onerror=...>" runs.
@@ -5574,6 +5637,8 @@
5574
5637
  * appended as it is and a string is always text -- but a
5575
5638
  * list whose first item is a string is read as ONE
5576
5639
  * description (the string is its tag).
5640
+ * With set_strings_are_text(true) a plain string is
5641
+ * always text, and markup only comes in html_markup().
5577
5642
  * if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')
5578
5643
  * it will be overridden with the translation
5579
5644
  * content = translate(attrs['i18n']));
@@ -5616,19 +5681,24 @@
5616
5681
  el.setAttribute("data-i18n", data_i18next);
5617
5682
  }
5618
5683
  } else el.setAttribute(attr, attrs[attr]);
5619
- if (is_string(content)) {
5684
+ if (is_html_markup(content)) el.appendChild(markup_fragment(content));
5685
+ else if (is_string(content)) {
5620
5686
  content = content.trim();
5621
- if (content.length > 0 && content[0] === "<") el.appendChild(createOneHtml(content));
5622
- else if (translate_fn && data_i18next) {
5623
- let translated = translate_fn(data_i18next);
5624
- el.textContent = translated ? translated : content;
5625
- } else el.textContent = content;
5687
+ if (content.length > 0 && content[0] === "<" && !__strings_are_text__) el.appendChild(createOneHtml(content));
5688
+ else {
5689
+ if (content.length > 0 && content[0] === "<") warn_markup_string(content);
5690
+ if (translate_fn && data_i18next) {
5691
+ let translated = translate_fn(data_i18next);
5692
+ el.textContent = translated ? translated : content;
5693
+ } else el.textContent = content;
5694
+ }
5626
5695
  } else if (is_array(content)) {
5627
5696
  if (content.length > 0) {
5628
5697
  if (is_string(content[0])) el.appendChild(createElement2(content, translate_fn));
5629
5698
  else for (let child of content) if (Array.isArray(child)) {
5630
5699
  if (child.length > 0) el.appendChild(createElement2(child, translate_fn));
5631
5700
  } else if (child instanceof Node) el.appendChild(child);
5701
+ else if (is_html_markup(child)) el.appendChild(markup_fragment(child));
5632
5702
  else if (is_string(child)) el.appendChild(document.createTextNode(child));
5633
5703
  else if (child !== null && child !== void 0 && child !== false) log_error(`createElement2: child ignored, type ${typeof child}`);
5634
5704
  }
@@ -7979,6 +8049,7 @@
7979
8049
  exports.gobj_yuno_id = gobj_yuno_id;
7980
8050
  exports.gobj_yuno_name = gobj_yuno_name;
7981
8051
  exports.gobj_yuno_role = gobj_yuno_role;
8052
+ exports.html_markup = html_markup;
7982
8053
  exports.id_index_in_obj_list = id_index_in_obj_list;
7983
8054
  exports.index_in_list = index_in_list;
7984
8055
  exports.is_array = is_array;
@@ -7986,6 +8057,7 @@
7986
8057
  exports.is_date = is_date;
7987
8058
  exports.is_function = is_function;
7988
8059
  exports.is_gobj = is_gobj;
8060
+ exports.is_html_markup = is_html_markup;
7989
8061
  exports.is_metadata_key = is_metadata_key;
7990
8062
  exports.is_null = is_null;
7991
8063
  exports.is_number = is_number;
@@ -8077,6 +8149,7 @@
8077
8149
  exports.set_console_log_filter = set_console_log_filter;
8078
8150
  exports.set_log_callback = set_log_callback;
8079
8151
  exports.set_remote_log_functions = set_remote_log_functions;
8152
+ exports.set_strings_are_text = set_strings_are_text;
8080
8153
  exports.set_timeout = set_timeout;
8081
8154
  exports.set_timeout_periodic = set_timeout_periodic;
8082
8155
  exports.sprintf = sprintf;
@@ -8084,6 +8157,7 @@
8084
8157
  exports.str_in_list = str_in_list;
8085
8158
  exports.strcasecmp = strcasecmp;
8086
8159
  exports.strcmp = strcmp;
8160
+ exports.strings_are_text = strings_are_text;
8087
8161
  exports.strncmp = strncmp;
8088
8162
  exports.strs_in_list = strs_in_list;
8089
8163
  exports.strstr = strstr;