@yuneta/gobj-ui 7.19.3 → 7.20.0
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/README.md +26 -3
- package/dist/gobj-ui.cjs.js +256 -30
- package/dist/gobj-ui.es.js +256 -30
- package/package.json +1 -1
- package/src/c_yui_json.css +38 -1
- package/src/c_yui_json.js +226 -16
- package/src/c_yui_shell.js +18 -1
- package/src/json_view_helpers.js +32 -2
- package/src/json_view_helpers.test.js +42 -0
- package/src/yui_icons.css +13 -0
package/dist/gobj-ui.es.js
CHANGED
|
@@ -1462,7 +1462,7 @@ function navigate_to(gobj, route, depth, no_drain) {
|
|
|
1462
1462
|
if (!empty_string(t.event)) gobj_publish_event(gobj, t.event, t.kw || {});
|
|
1463
1463
|
};
|
|
1464
1464
|
let config = gobj_read_attr(gobj, "config") || {};
|
|
1465
|
-
let prev = priv.stages && priv.stages.main && priv.stages.main.active_route || gobj_read_attr(gobj, "default_route") || config.shell && config.shell.stages && config.shell.stages.main && config.shell.stages.main.default_route || "/";
|
|
1465
|
+
let prev = gobj_read_attr(gobj, "current_route") || priv.stages && priv.stages.main && priv.stages.main.active_route || gobj_read_attr(gobj, "default_route") || config.shell && config.shell.stages && config.shell.stages.main && config.shell.stages.main.default_route || "/";
|
|
1466
1466
|
let redirect = t.redirect;
|
|
1467
1467
|
if (redirect === "stay") {
|
|
1468
1468
|
if (gobj_read_attr(gobj, "use_hash")) {
|
|
@@ -10411,6 +10411,39 @@ function format_epoch(value) {
|
|
|
10411
10411
|
if (isNaN(d.getTime())) return null;
|
|
10412
10412
|
return d.toLocaleString();
|
|
10413
10413
|
}
|
|
10414
|
+
/************************************************************
|
|
10415
|
+
* The text view's payload: the document as text, indented
|
|
10416
|
+
* four characters, cut at `max_chars`.
|
|
10417
|
+
*
|
|
10418
|
+
* Returns {text, capped}. `capped` is what the caller
|
|
10419
|
+
* announces under the dump — a cut that is not announced
|
|
10420
|
+
* reads as a document that ends there.
|
|
10421
|
+
************************************************************/
|
|
10422
|
+
function json_text_dump(root, max_chars) {
|
|
10423
|
+
let text;
|
|
10424
|
+
try {
|
|
10425
|
+
text = JSON.stringify(root, null, 4);
|
|
10426
|
+
} catch (e) {
|
|
10427
|
+
return {
|
|
10428
|
+
text: "",
|
|
10429
|
+
capped: false,
|
|
10430
|
+
error: String(e)
|
|
10431
|
+
};
|
|
10432
|
+
}
|
|
10433
|
+
if (text === void 0) return {
|
|
10434
|
+
text: "",
|
|
10435
|
+
capped: false,
|
|
10436
|
+
error: "not representable as JSON"
|
|
10437
|
+
};
|
|
10438
|
+
if (typeof max_chars === "number" && max_chars > 0 && text.length > max_chars) return {
|
|
10439
|
+
text: text.slice(0, max_chars),
|
|
10440
|
+
capped: true
|
|
10441
|
+
};
|
|
10442
|
+
return {
|
|
10443
|
+
text,
|
|
10444
|
+
capped: false
|
|
10445
|
+
};
|
|
10446
|
+
}
|
|
10414
10447
|
//#endregion
|
|
10415
10448
|
//#region src/c_yui_json.js
|
|
10416
10449
|
/***********************************************************************
|
|
@@ -10439,9 +10472,19 @@ function format_epoch(value) {
|
|
|
10439
10472
|
* Only expanded containers are materialised in the DOM, so the tree
|
|
10440
10473
|
* stays bounded no matter how large the source document is.
|
|
10441
10474
|
*
|
|
10475
|
+
* TWO VIEWS over the same working document, chosen by the `view_mode`
|
|
10476
|
+
* attr ("tree" | "text") and switched from the toolbar: the lazy tree
|
|
10477
|
+
* above, and the raw `JSON.stringify(…, 4)` dump of what is currently
|
|
10478
|
+
* loaded. The text view is what you reach for to read a document as
|
|
10479
|
+
* it is written, to select a slab of it, or to search it with the
|
|
10480
|
+
* browser's own Ctrl+F; it shows the `__collapsed__` sentinels
|
|
10481
|
+
* verbatim, because that is honestly what the client holds. The
|
|
10482
|
+
* tree-only controls (search, expand/collapse) hide with the tree.
|
|
10483
|
+
*
|
|
10442
10484
|
* DOM is self-describing (UPPER_SNAKE logical classes): JSON_VIEWER /
|
|
10443
|
-
* JSON_TOOLBAR / JSON_SEARCH /
|
|
10444
|
-
*
|
|
10485
|
+
* JSON_TOOLBAR / JSON_SEARCH / JSON_VIEW_MODE / JSON_TREE / JSON_TEXT /
|
|
10486
|
+
* JSON_TEXT_BODY / JSON_ROW / JSON_KEY / JSON_VALUE / JSON_SUMMARY /
|
|
10487
|
+
* JSON_COLLAPSED / JSON_TIME.
|
|
10445
10488
|
*
|
|
10446
10489
|
* Copyright (c) 2026, ArtGins.
|
|
10447
10490
|
* All Rights Reserved.
|
|
@@ -10451,6 +10494,7 @@ function format_epoch(value) {
|
|
|
10451
10494
|
***************************************************************/
|
|
10452
10495
|
var GCLASS_NAME$10 = "C_YUI_JSON";
|
|
10453
10496
|
var MAX_RENDER_ROWS = 5e3;
|
|
10497
|
+
var MAX_TEXT_CHARS = 2e6;
|
|
10454
10498
|
/***************************************************************
|
|
10455
10499
|
* Data
|
|
10456
10500
|
***************************************************************/
|
|
@@ -10458,6 +10502,7 @@ var attrs_table$10 = [
|
|
|
10458
10502
|
SDATA(data_type_t.DTP_POINTER, "subscriber", 0, null, "Subscriber of output events"),
|
|
10459
10503
|
SDATA(data_type_t.DTP_STRING, "title", 0, "", "Optional header title (i18n key)"),
|
|
10460
10504
|
SDATA(data_type_t.DTP_JSON, "json_data", 0, null, "Initial JSON to render (usually already collapsed)"),
|
|
10505
|
+
SDATA(data_type_t.DTP_STRING, "view_mode", 0, "tree", "View: 'tree' (lazy tree) or 'text' (raw JSON dump)"),
|
|
10461
10506
|
SDATA(data_type_t.DTP_POINTER, "$container", 0, null, "HTMLElement root, mounted by the parent"),
|
|
10462
10507
|
SDATA_END()
|
|
10463
10508
|
];
|
|
@@ -10468,7 +10513,13 @@ var PRIVATE_DATA$10 = {
|
|
|
10468
10513
|
errors: null,
|
|
10469
10514
|
search: "",
|
|
10470
10515
|
$tree: null,
|
|
10471
|
-
$
|
|
10516
|
+
$text: null,
|
|
10517
|
+
$text_body: null,
|
|
10518
|
+
$search: null,
|
|
10519
|
+
$search_ctl: null,
|
|
10520
|
+
$expand_btn: null,
|
|
10521
|
+
$collapse_btn: null,
|
|
10522
|
+
$mode_btn: null
|
|
10472
10523
|
};
|
|
10473
10524
|
var __gclass__$10 = null;
|
|
10474
10525
|
/******************************
|
|
@@ -10486,6 +10537,7 @@ function mt_create$10(gobj) {
|
|
|
10486
10537
|
let json_data = gobj_read_attr(gobj, "json_data");
|
|
10487
10538
|
if (json_data !== null && json_data !== void 0) priv.root = json_deep_copy(json_data);
|
|
10488
10539
|
build_ui$9(gobj);
|
|
10540
|
+
apply_view_mode(gobj);
|
|
10489
10541
|
let subscriber = gobj_read_pointer_attr(gobj, "subscriber");
|
|
10490
10542
|
if (!subscriber) subscriber = gobj_parent(gobj);
|
|
10491
10543
|
gobj_subscribe_event(gobj, null, {}, subscriber);
|
|
@@ -10494,7 +10546,7 @@ function mt_create$10(gobj) {
|
|
|
10494
10546
|
* Framework Method: Start
|
|
10495
10547
|
***************************************************************/
|
|
10496
10548
|
function mt_start$10(gobj) {
|
|
10497
|
-
|
|
10549
|
+
render_view(gobj);
|
|
10498
10550
|
}
|
|
10499
10551
|
/***************************************************************
|
|
10500
10552
|
* Framework Method: Stop
|
|
@@ -10521,22 +10573,38 @@ function build_ui$9(gobj) {
|
|
|
10521
10573
|
class: "C_YUI_JSON JSON_VIEWER view-card",
|
|
10522
10574
|
style: "height:100%; display:flex; flex-direction:column;"
|
|
10523
10575
|
},
|
|
10524
|
-
[
|
|
10525
|
-
|
|
10526
|
-
|
|
10527
|
-
|
|
10528
|
-
|
|
10529
|
-
|
|
10530
|
-
|
|
10531
|
-
|
|
10532
|
-
|
|
10533
|
-
|
|
10534
|
-
|
|
10535
|
-
|
|
10576
|
+
[
|
|
10577
|
+
[
|
|
10578
|
+
"div",
|
|
10579
|
+
{ class: "JSON_TOOLBAR is-flex-grow-0" },
|
|
10580
|
+
[$toolbar]
|
|
10581
|
+
],
|
|
10582
|
+
[
|
|
10583
|
+
"div",
|
|
10584
|
+
{
|
|
10585
|
+
class: "JSON_TREE is-flex-grow-1",
|
|
10586
|
+
style: "flex:1 1 auto; min-height:0; overflow:auto;"
|
|
10587
|
+
},
|
|
10588
|
+
[]
|
|
10589
|
+
],
|
|
10590
|
+
[
|
|
10591
|
+
"div",
|
|
10592
|
+
{
|
|
10593
|
+
class: "JSON_TEXT is-flex-grow-1 is-hidden",
|
|
10594
|
+
style: "flex:1 1 auto; min-height:0; overflow:auto;"
|
|
10595
|
+
},
|
|
10596
|
+
[]
|
|
10597
|
+
]
|
|
10598
|
+
]
|
|
10536
10599
|
]);
|
|
10537
10600
|
gobj_write_attr(gobj, "$container", $container);
|
|
10538
10601
|
priv.$tree = $container.querySelector(".JSON_TREE");
|
|
10602
|
+
priv.$text = $container.querySelector(".JSON_TEXT");
|
|
10539
10603
|
priv.$search = $container.querySelector(".JSON_SEARCH");
|
|
10604
|
+
priv.$search_ctl = $container.querySelector(".JSON_SEARCH_CONTROL");
|
|
10605
|
+
priv.$expand_btn = $container.querySelector(".EV_EXPAND_ALL");
|
|
10606
|
+
priv.$collapse_btn = $container.querySelector(".EV_COLLAPSE_ALL");
|
|
10607
|
+
priv.$mode_btn = $container.querySelector(".JSON_VIEW_MODE");
|
|
10540
10608
|
refresh_language($container, t);
|
|
10541
10609
|
}
|
|
10542
10610
|
/************************************************************
|
|
@@ -10550,10 +10618,17 @@ function destroy_ui$5(gobj) {
|
|
|
10550
10618
|
gobj_write_attr(gobj, "$container", null);
|
|
10551
10619
|
}
|
|
10552
10620
|
priv.$tree = null;
|
|
10621
|
+
priv.$text = null;
|
|
10622
|
+
priv.$text_body = null;
|
|
10553
10623
|
priv.$search = null;
|
|
10624
|
+
priv.$search_ctl = null;
|
|
10625
|
+
priv.$expand_btn = null;
|
|
10626
|
+
priv.$collapse_btn = null;
|
|
10627
|
+
priv.$mode_btn = null;
|
|
10554
10628
|
}
|
|
10555
10629
|
/************************************************************
|
|
10556
|
-
* Toolbar: search +
|
|
10630
|
+
* Toolbar: search + tree/text switch + expand-all /
|
|
10631
|
+
* collapse-all / copy
|
|
10557
10632
|
************************************************************/
|
|
10558
10633
|
function make_toolbar$2(gobj) {
|
|
10559
10634
|
let title = gobj_read_str_attr(gobj, "title");
|
|
@@ -10582,7 +10657,7 @@ function make_toolbar$2(gobj) {
|
|
|
10582
10657
|
let $search_control = createElement2([
|
|
10583
10658
|
"div",
|
|
10584
10659
|
{
|
|
10585
|
-
class: "control has-icons-left",
|
|
10660
|
+
class: "control has-icons-left JSON_SEARCH_CONTROL",
|
|
10586
10661
|
style: "max-width:22em;"
|
|
10587
10662
|
},
|
|
10588
10663
|
[$search_input, [
|
|
@@ -10594,6 +10669,7 @@ function make_toolbar$2(gobj) {
|
|
|
10594
10669
|
attach_clear($search_control, $search_input);
|
|
10595
10670
|
left_items.push($search_control);
|
|
10596
10671
|
let right_items = [
|
|
10672
|
+
view_mode_button(gobj),
|
|
10597
10673
|
icon_button(gobj, "yi-chevron-right", "EV_EXPAND_ALL", "expand loaded"),
|
|
10598
10674
|
icon_button(gobj, "yi-chevron-right", "EV_COLLAPSE_ALL", "collapse all"),
|
|
10599
10675
|
icon_button(gobj, "yi-copy", "EV_COPY_ALL", "copy json")
|
|
@@ -10650,6 +10726,122 @@ function icon_button(gobj, icon, event_name, label_key) {
|
|
|
10650
10726
|
];
|
|
10651
10727
|
}
|
|
10652
10728
|
/************************************************************
|
|
10729
|
+
* The tree/text switch.
|
|
10730
|
+
*
|
|
10731
|
+
* It shows the view it takes you TO — the `code` glyph while the
|
|
10732
|
+
* tree is on screen, the `sitemap` glyph while the text is — and
|
|
10733
|
+
* sends EV_SET_VIEW_MODE with no mode, which the action reads as
|
|
10734
|
+
* "toggle". apply_view_mode() keeps the icon and its i18n keys in
|
|
10735
|
+
* step with the attr.
|
|
10736
|
+
************************************************************/
|
|
10737
|
+
function view_mode_button(gobj) {
|
|
10738
|
+
return [
|
|
10739
|
+
"button",
|
|
10740
|
+
{
|
|
10741
|
+
class: "button JSON_VIEW_MODE",
|
|
10742
|
+
style: "width:2.5em;",
|
|
10743
|
+
title: t("text view"),
|
|
10744
|
+
"data-i18n-title": "text view",
|
|
10745
|
+
"aria-label": t("text view"),
|
|
10746
|
+
"data-i18n-aria-label": "text view"
|
|
10747
|
+
},
|
|
10748
|
+
[[
|
|
10749
|
+
"span",
|
|
10750
|
+
{ class: "icon" },
|
|
10751
|
+
[["i", { class: "yi-code" }]]
|
|
10752
|
+
]],
|
|
10753
|
+
{ click: function(evt) {
|
|
10754
|
+
evt.stopPropagation();
|
|
10755
|
+
gobj_send_event(gobj, "EV_SET_VIEW_MODE", {}, gobj);
|
|
10756
|
+
} }
|
|
10757
|
+
];
|
|
10758
|
+
}
|
|
10759
|
+
/************************************************************
|
|
10760
|
+
* The current view, normalised. Anything but "text" is the tree.
|
|
10761
|
+
************************************************************/
|
|
10762
|
+
function current_view_mode(gobj) {
|
|
10763
|
+
return gobj_read_str_attr(gobj, "view_mode") === "text" ? "text" : "tree";
|
|
10764
|
+
}
|
|
10765
|
+
/************************************************************
|
|
10766
|
+
* Show the chrome of the current view and hide the other's.
|
|
10767
|
+
************************************************************/
|
|
10768
|
+
function apply_view_mode(gobj) {
|
|
10769
|
+
let priv = gobj.priv;
|
|
10770
|
+
let text_mode = current_view_mode(gobj) === "text";
|
|
10771
|
+
if (priv.$tree) priv.$tree.classList.toggle("is-hidden", text_mode);
|
|
10772
|
+
if (priv.$text) priv.$text.classList.toggle("is-hidden", !text_mode);
|
|
10773
|
+
[
|
|
10774
|
+
priv.$search_ctl,
|
|
10775
|
+
priv.$expand_btn,
|
|
10776
|
+
priv.$collapse_btn
|
|
10777
|
+
].forEach(function($el) {
|
|
10778
|
+
if ($el) $el.classList.toggle("is-hidden", text_mode);
|
|
10779
|
+
});
|
|
10780
|
+
if (priv.$mode_btn) {
|
|
10781
|
+
let icon = text_mode ? "yi-sitemap" : "yi-code";
|
|
10782
|
+
let key = text_mode ? "tree view" : "text view";
|
|
10783
|
+
let $i = priv.$mode_btn.querySelector("i");
|
|
10784
|
+
if ($i) $i.className = icon;
|
|
10785
|
+
priv.$mode_btn.setAttribute("data-i18n-title", key);
|
|
10786
|
+
priv.$mode_btn.setAttribute("data-i18n-aria-label", key);
|
|
10787
|
+
priv.$mode_btn.setAttribute("title", t(key));
|
|
10788
|
+
priv.$mode_btn.setAttribute("aria-label", t(key));
|
|
10789
|
+
}
|
|
10790
|
+
}
|
|
10791
|
+
/************************************************************
|
|
10792
|
+
* Render whichever view is current.
|
|
10793
|
+
************************************************************/
|
|
10794
|
+
function render_view(gobj) {
|
|
10795
|
+
if (current_view_mode(gobj) === "text") render_text(gobj);
|
|
10796
|
+
else render_tree(gobj);
|
|
10797
|
+
}
|
|
10798
|
+
/************************************************************
|
|
10799
|
+
* Render the text view: the whole loaded document, verbatim.
|
|
10800
|
+
*
|
|
10801
|
+
* Unlike the tree, nothing here is lazy — what the client holds is
|
|
10802
|
+
* what it prints, `__collapsed__` sentinels included. Over
|
|
10803
|
+
* MAX_TEXT_CHARS the dump is cut and the cut is announced.
|
|
10804
|
+
************************************************************/
|
|
10805
|
+
function render_text(gobj) {
|
|
10806
|
+
let priv = gobj.priv;
|
|
10807
|
+
let $text = priv.$text;
|
|
10808
|
+
if (!$text) return;
|
|
10809
|
+
let scroll_top = $text.scrollTop;
|
|
10810
|
+
$text.textContent = "";
|
|
10811
|
+
priv.$text_body = null;
|
|
10812
|
+
if (priv.root === null || priv.root === void 0) {
|
|
10813
|
+
$text.appendChild(createElement2([
|
|
10814
|
+
"div",
|
|
10815
|
+
{
|
|
10816
|
+
class: "JSON_EMPTY has-text-grey p-3",
|
|
10817
|
+
"data-i18n": "no data"
|
|
10818
|
+
},
|
|
10819
|
+
"no data"
|
|
10820
|
+
]));
|
|
10821
|
+
return;
|
|
10822
|
+
}
|
|
10823
|
+
let dump = json_text_dump(priv.root, MAX_TEXT_CHARS);
|
|
10824
|
+
if (dump.error) log_error(`${GCLASS_NAME$10}: cannot dump the document as text: ${dump.error}`);
|
|
10825
|
+
let $pre = createElement2([
|
|
10826
|
+
"pre",
|
|
10827
|
+
{ class: "JSON_TEXT_BODY" },
|
|
10828
|
+
[]
|
|
10829
|
+
]);
|
|
10830
|
+
$pre.textContent = dump.text;
|
|
10831
|
+
$text.appendChild($pre);
|
|
10832
|
+
priv.$text_body = $pre;
|
|
10833
|
+
if (dump.capped) $text.appendChild(createElement2([
|
|
10834
|
+
"div",
|
|
10835
|
+
{
|
|
10836
|
+
class: "JSON_CAPPED has-text-warning p-2",
|
|
10837
|
+
"data-i18n": "text truncated; collapse some branches"
|
|
10838
|
+
},
|
|
10839
|
+
"text truncated; collapse some branches"
|
|
10840
|
+
]));
|
|
10841
|
+
refresh_language($text, t);
|
|
10842
|
+
$text.scrollTop = scroll_top;
|
|
10843
|
+
}
|
|
10844
|
+
/************************************************************
|
|
10653
10845
|
* Re-render the whole tree from priv.root + priv.expanded.
|
|
10654
10846
|
*
|
|
10655
10847
|
* Only expanded containers are walked, so the DOM size is
|
|
@@ -10980,7 +11172,7 @@ function ac_set_json(gobj, event, kw, src) {
|
|
|
10980
11172
|
priv.expanded.clear();
|
|
10981
11173
|
priv.pending.clear();
|
|
10982
11174
|
priv.errors.clear();
|
|
10983
|
-
|
|
11175
|
+
render_view(gobj);
|
|
10984
11176
|
return 0;
|
|
10985
11177
|
}
|
|
10986
11178
|
/************************************************************
|
|
@@ -10995,7 +11187,7 @@ function ac_subtree_loaded(gobj, event, kw, src) {
|
|
|
10995
11187
|
priv.pending.delete(path);
|
|
10996
11188
|
priv.errors.delete(path);
|
|
10997
11189
|
if (path) priv.expanded.add(path);
|
|
10998
|
-
|
|
11190
|
+
render_view(gobj);
|
|
10999
11191
|
return 0;
|
|
11000
11192
|
}
|
|
11001
11193
|
/************************************************************
|
|
@@ -11007,7 +11199,7 @@ function ac_subtree_error(gobj, event, kw, src) {
|
|
|
11007
11199
|
priv.pending.delete(path);
|
|
11008
11200
|
priv.errors.set(path, kw.error || "error");
|
|
11009
11201
|
log_error(`${GCLASS_NAME$10}: subtree load failed at '${path}': ${kw.error || ""}`);
|
|
11010
|
-
|
|
11202
|
+
render_view(gobj);
|
|
11011
11203
|
return 0;
|
|
11012
11204
|
}
|
|
11013
11205
|
/************************************************************
|
|
@@ -11018,7 +11210,7 @@ function ac_toggle_node(gobj, event, kw, src) {
|
|
|
11018
11210
|
let path = kw.path || "";
|
|
11019
11211
|
if (priv.expanded.has(path)) priv.expanded.delete(path);
|
|
11020
11212
|
else priv.expanded.add(path);
|
|
11021
|
-
|
|
11213
|
+
render_view(gobj);
|
|
11022
11214
|
return 0;
|
|
11023
11215
|
}
|
|
11024
11216
|
/************************************************************
|
|
@@ -11031,7 +11223,7 @@ function ac_expand_collapsed(gobj, event, kw, src) {
|
|
|
11031
11223
|
if (priv.pending.has(path)) return 0;
|
|
11032
11224
|
priv.pending.add(path);
|
|
11033
11225
|
priv.errors.delete(path);
|
|
11034
|
-
|
|
11226
|
+
render_view(gobj);
|
|
11035
11227
|
gobj_publish_event(gobj, "EV_EXPAND_PATH", {
|
|
11036
11228
|
path,
|
|
11037
11229
|
size: kw.size
|
|
@@ -11044,7 +11236,7 @@ function ac_expand_collapsed(gobj, event, kw, src) {
|
|
|
11044
11236
|
function ac_search$1(gobj, event, kw, src) {
|
|
11045
11237
|
let priv = gobj.priv;
|
|
11046
11238
|
priv.search = (kw.text || "").trim().toLowerCase();
|
|
11047
|
-
|
|
11239
|
+
render_view(gobj);
|
|
11048
11240
|
return 0;
|
|
11049
11241
|
}
|
|
11050
11242
|
/************************************************************
|
|
@@ -11062,7 +11254,7 @@ function ac_expand_all$1(gobj, event, kw, src) {
|
|
|
11062
11254
|
paths.forEach(function(p) {
|
|
11063
11255
|
priv.expanded.add(p);
|
|
11064
11256
|
});
|
|
11065
|
-
|
|
11257
|
+
render_view(gobj);
|
|
11066
11258
|
return 0;
|
|
11067
11259
|
}
|
|
11068
11260
|
/************************************************************
|
|
@@ -11070,7 +11262,7 @@ function ac_expand_all$1(gobj, event, kw, src) {
|
|
|
11070
11262
|
************************************************************/
|
|
11071
11263
|
function ac_collapse_all$1(gobj, event, kw, src) {
|
|
11072
11264
|
gobj.priv.expanded.clear();
|
|
11073
|
-
|
|
11265
|
+
render_view(gobj);
|
|
11074
11266
|
return 0;
|
|
11075
11267
|
}
|
|
11076
11268
|
/************************************************************
|
|
@@ -11079,7 +11271,12 @@ function ac_collapse_all$1(gobj, event, kw, src) {
|
|
|
11079
11271
|
function ac_copy_all(gobj, event, kw, src) {
|
|
11080
11272
|
let priv = gobj.priv;
|
|
11081
11273
|
if (priv.root === null || priv.root === void 0) return 0;
|
|
11082
|
-
let
|
|
11274
|
+
let dump = json_text_dump(priv.root, 0);
|
|
11275
|
+
if (dump.error) {
|
|
11276
|
+
log_error(`${GCLASS_NAME$10}: cannot copy the document: ${dump.error}`);
|
|
11277
|
+
return -1;
|
|
11278
|
+
}
|
|
11279
|
+
let text = dump.text;
|
|
11083
11280
|
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(text).catch(function(e) {
|
|
11084
11281
|
log_error(`${GCLASS_NAME$10}: clipboard write failed: ${e}`);
|
|
11085
11282
|
});
|
|
@@ -11087,6 +11284,23 @@ function ac_copy_all(gobj, event, kw, src) {
|
|
|
11087
11284
|
return 0;
|
|
11088
11285
|
}
|
|
11089
11286
|
/************************************************************
|
|
11287
|
+
* EV_SET_VIEW_MODE { mode } — "tree" | "text".
|
|
11288
|
+
*
|
|
11289
|
+
* With no mode it toggles, which is what the toolbar button sends.
|
|
11290
|
+
************************************************************/
|
|
11291
|
+
function ac_set_view_mode(gobj, event, kw, src) {
|
|
11292
|
+
let mode = kw.mode;
|
|
11293
|
+
if (mode === void 0 || mode === null || mode === "") mode = current_view_mode(gobj) === "text" ? "tree" : "text";
|
|
11294
|
+
else if (mode !== "tree" && mode !== "text") {
|
|
11295
|
+
log_error(`${GCLASS_NAME$10}: unknown view_mode '${mode}'`);
|
|
11296
|
+
return -1;
|
|
11297
|
+
}
|
|
11298
|
+
gobj_write_attr(gobj, "view_mode", mode);
|
|
11299
|
+
apply_view_mode(gobj);
|
|
11300
|
+
render_view(gobj);
|
|
11301
|
+
return 0;
|
|
11302
|
+
}
|
|
11303
|
+
/************************************************************
|
|
11090
11304
|
* EV_LANGUAGE_CHANGED — re-translate chrome + re-render
|
|
11091
11305
|
************************************************************/
|
|
11092
11306
|
function ac_language_changed$3(gobj, event, kw, src) {
|
|
@@ -11095,8 +11309,9 @@ function ac_language_changed$3(gobj, event, kw, src) {
|
|
|
11095
11309
|
if ($container) {
|
|
11096
11310
|
refresh_language($container, t);
|
|
11097
11311
|
if (priv.$search) priv.$search.setAttribute("placeholder", t("search"));
|
|
11312
|
+
apply_view_mode(gobj);
|
|
11098
11313
|
}
|
|
11099
|
-
|
|
11314
|
+
render_view(gobj);
|
|
11100
11315
|
return 0;
|
|
11101
11316
|
}
|
|
11102
11317
|
/************************************************************
|
|
@@ -11116,7 +11331,7 @@ function ac_hide$6(gobj, event, kw, src) {
|
|
|
11116
11331
|
* EV_REFRESH
|
|
11117
11332
|
************************************************************/
|
|
11118
11333
|
function ac_refresh$4(gobj, event, kw, src) {
|
|
11119
|
-
|
|
11334
|
+
render_view(gobj);
|
|
11120
11335
|
return 0;
|
|
11121
11336
|
}
|
|
11122
11337
|
/***************************
|
|
@@ -11142,6 +11357,11 @@ function create_gclass$10(gclass_name) {
|
|
|
11142
11357
|
ac_set_json,
|
|
11143
11358
|
"ST_READY"
|
|
11144
11359
|
],
|
|
11360
|
+
[
|
|
11361
|
+
"EV_SET_VIEW_MODE",
|
|
11362
|
+
ac_set_view_mode,
|
|
11363
|
+
null
|
|
11364
|
+
],
|
|
11145
11365
|
[
|
|
11146
11366
|
"EV_LANGUAGE_CHANGED",
|
|
11147
11367
|
ac_language_changed$3,
|
|
@@ -11208,6 +11428,11 @@ function create_gclass$10(gclass_name) {
|
|
|
11208
11428
|
ac_copy_all,
|
|
11209
11429
|
null
|
|
11210
11430
|
],
|
|
11431
|
+
[
|
|
11432
|
+
"EV_SET_VIEW_MODE",
|
|
11433
|
+
ac_set_view_mode,
|
|
11434
|
+
null
|
|
11435
|
+
],
|
|
11211
11436
|
[
|
|
11212
11437
|
"EV_LANGUAGE_CHANGED",
|
|
11213
11438
|
ac_language_changed$3,
|
|
@@ -11239,6 +11464,7 @@ function create_gclass$10(gclass_name) {
|
|
|
11239
11464
|
["EV_EXPAND_ALL", 0],
|
|
11240
11465
|
["EV_COLLAPSE_ALL", 0],
|
|
11241
11466
|
["EV_COPY_ALL", 0],
|
|
11467
|
+
["EV_SET_VIEW_MODE", 0],
|
|
11242
11468
|
["EV_LANGUAGE_CHANGED", 0],
|
|
11243
11469
|
["EV_REFRESH", 0],
|
|
11244
11470
|
["EV_SHOW", 0],
|
package/package.json
CHANGED
package/src/c_yui_json.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/***********************************************************************
|
|
2
2
|
* c_yui_json.css
|
|
3
3
|
*
|
|
4
|
-
* Styling for C_YUI_JSON (lazy JSON tree viewer).
|
|
4
|
+
* Styling for C_YUI_JSON (lazy JSON tree viewer + raw text view).
|
|
5
5
|
* Monospace tree, type-coloured leaves, dark-aware.
|
|
6
6
|
* No transitions/animations by design (lib-yui convention).
|
|
7
7
|
*
|
|
@@ -151,6 +151,43 @@
|
|
|
151
151
|
opacity: 0.7;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
/*
|
|
155
|
+
* Text view: the same document as a raw dump, monospace like the tree.
|
|
156
|
+
*/
|
|
157
|
+
.C_YUI_JSON .JSON_TEXT {
|
|
158
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
159
|
+
font-size: 1em;
|
|
160
|
+
line-height: 1.5;
|
|
161
|
+
padding: 0.25rem 0.5rem;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.C_YUI_JSON .JSON_TEXT_BODY {
|
|
165
|
+
margin: 0;
|
|
166
|
+
padding: 0;
|
|
167
|
+
background: none;
|
|
168
|
+
color: inherit;
|
|
169
|
+
font-family: inherit;
|
|
170
|
+
font-size: inherit;
|
|
171
|
+
line-height: inherit;
|
|
172
|
+
/* `pre`, NOT `pre-wrap`: the indentation IS the structure here, and
|
|
173
|
+
* a wrapped continuation line restarts at column 0 and lies about
|
|
174
|
+
* the depth of everything under it — on a phone that is most of the
|
|
175
|
+
* document. Long lines scroll sideways inside .JSON_TEXT (which
|
|
176
|
+
* owns the overflow), never on the page body. */
|
|
177
|
+
white-space: pre;
|
|
178
|
+
/* And the <pre> must GROW to its longest line: as a plain block it
|
|
179
|
+
* takes the container's width, its text spills out of a box that
|
|
180
|
+
* reports no overflow, and .JSON_TEXT gets no scroll range to
|
|
181
|
+
* offer — the tail of every long line is simply unreachable.
|
|
182
|
+
* `min-width: 100%` keeps it filling the container when the
|
|
183
|
+
* document is narrower. */
|
|
184
|
+
width: max-content;
|
|
185
|
+
min-width: 100%;
|
|
186
|
+
/* The dump is there to be read AND taken: a plain <pre> in some
|
|
187
|
+
* host stylesheets is unselectable chrome. */
|
|
188
|
+
user-select: text;
|
|
189
|
+
}
|
|
190
|
+
|
|
154
191
|
/*
|
|
155
192
|
* Disable any transition a host stylesheet might inject.
|
|
156
193
|
*/
|