@yuneta/gobj-ui 7.23.194 → 7.23.196

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.
@@ -0,0 +1,53 @@
1
+ /****************************************************************************
2
+ * table_cell_text.js
3
+ *
4
+ * What a treedb table cell hands Tabulator.
5
+ *
6
+ * Tabulator assigns a formatter's STRING result with `innerHTML`
7
+ * (only its own `plaintext` formatter escapes), so a record's text
8
+ * returned as a string is parsed as markup: `a<b and c>d` showed
9
+ * as `ad`, and a field holding `<img src=x onerror=...>` ran it in
10
+ * the operator's browser (M31 of the 2026-09-21 review). Record
11
+ * data goes in as a TEXT NODE, and a cell built around it as DOM,
12
+ * never as an HTML string with the data interpolated.
13
+ *
14
+ * Pure but for the `document` it is handed, so it is tested
15
+ * without one.
16
+ *
17
+ * Copyright (c) 2026, ArtGins.
18
+ * All Rights Reserved.
19
+ ****************************************************************************/
20
+
21
+ /************************************************************
22
+ * A value shown as text, whatever characters it holds
23
+ ************************************************************/
24
+ function cell_text(value, doc = globalThis.document)
25
+ {
26
+ if(value === null || value === undefined) {
27
+ return "";
28
+ }
29
+ return doc.createTextNode(String(value));
30
+ }
31
+
32
+ /************************************************************
33
+ * The hook cell, as a createElement2 spec: the row id is an
34
+ * attribute VALUE, never text spliced into markup (an id holding
35
+ * a `"` cut the attribute and lost the rest of the id)
36
+ ************************************************************/
37
+ function hook_cell_spec(row_id, col_id, items, title, title_key)
38
+ {
39
+ return ['a', {
40
+ class: 'HOOK_CELL hook_cell',
41
+ title: title,
42
+ 'data-i18n-title': title_key,
43
+ 'aria-label': title,
44
+ 'data-i18n-aria-label': title_key,
45
+ 'data-row_id': String(row_id),
46
+ 'data-col_id': String(col_id)
47
+ }, [
48
+ ['span', {class: 'icon yi-eye'}],
49
+ ['u', {class: 'HOOK_CELL_COUNT'}, `[ ${items} ]`]
50
+ ]];
51
+ }
52
+
53
+ export {cell_text, hook_cell_spec};
@@ -0,0 +1,39 @@
1
+ import {describe, it, expect} from "vitest";
2
+ import {cell_text, hook_cell_spec} from "./table_cell_text.js";
3
+
4
+ /* A document double: the library has no DOM test (see yui_clipboard.test.js) */
5
+ const doc = {
6
+ createTextNode: (text) => ({nodeType: 3, textContent: text})
7
+ };
8
+
9
+ describe("table_cell_text", () => {
10
+
11
+ it("record text is a text node, markup included", () => {
12
+ /* M31: Tabulator puts a string through innerHTML */
13
+ const node = cell_text("limit a<b and c>d", doc);
14
+ expect(node.nodeType).toBe(3);
15
+ expect(node.textContent).toBe("limit a<b and c>d");
16
+ expect(cell_text('<img src=x onerror=alert(1)>', doc).textContent)
17
+ .toBe('<img src=x onerror=alert(1)>');
18
+ });
19
+
20
+ it("numbers and booleans are shown as text too, nothing is empty", () => {
21
+ expect(cell_text(0, doc).textContent).toBe("0");
22
+ expect(cell_text(false, doc).textContent).toBe("false");
23
+ expect(cell_text(null, doc)).toBe("");
24
+ expect(cell_text(undefined, doc)).toBe("");
25
+ });
26
+
27
+ it("the hook cell carries the row id whole, quote included", () => {
28
+ const spec = hook_cell_spec(
29
+ 'es"madrid', "users", 3, "ver registros enlazados", "show linked records"
30
+ );
31
+ expect(spec[0]).toBe("a");
32
+ expect(spec[1]["data-row_id"]).toBe('es"madrid');
33
+ expect(spec[1]["data-col_id"]).toBe("users");
34
+ expect(spec[1].title).toBe("ver registros enlazados");
35
+ expect(spec[1]["aria-label"]).toBe("ver registros enlazados");
36
+ expect(spec[1]["data-i18n-title"]).toBe("show linked records");
37
+ expect(spec[1]["data-i18n-aria-label"]).toBe("show linked records");
38
+ });
39
+ });