json-renderers 1.14.1 → 1.17.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.
- package/README.md +6 -1
- package/docs/aboutSelect.html +964 -0
- package/docs/aboutTable.html +12 -0
- package/docs/dist/min.js +1577 -1063
- package/docs/dist/v14/min.js +1063 -1063
- package/docs/dist/v15/min.js +1510 -0
- package/docs/dist/v16/min.js +1576 -0
- package/docs/dist/v17/min.js +1577 -0
- package/docs/index.html +283 -79
- package/docs/select.html +33 -11
- package/docs/table/cdn.html +634 -0
- package/docs/table/index.html +607 -0
- package/docs/table/windowKs.html +332 -0
- package/docs/table/windowKsV1.html +647 -0
- package/docs/table.html +34 -11
- package/package.json +2 -2
- package/src/index.js +2 -2
- package/src/v15/guard.js +35 -0
- package/src/{v13 → v15}/index.js +11 -22
- package/src/{v11 → v15}/meta.js +1 -1
- package/src/v16/buildSpec/index.js +40 -0
- package/src/v16/guard.js +38 -0
- package/src/v16/index.js +106 -0
- package/src/{v13 → v16}/meta.js +1 -1
- package/src/v16/registerGlobal.js +27 -0
- package/src/v17/buildSpec/index.js +25 -0
- package/src/v17/getSpec.js +12 -0
- package/src/v17/guard.js +41 -0
- package/src/v17/index.js +29 -0
- package/src/{v12 → v17}/meta.js +1 -1
- package/src/v17/registerGlobal.js +28 -0
- package/src/v17/renderToDom/index.js +47 -0
- package/src/v17/spec.json +9 -0
- package/src/v17/validateConfig.js +37 -0
- package/src/v11/dataLists/fragments.json +0 -1
- package/src/v11/dataLists/index.js +0 -32
- package/src/v11/dataLists/skeleton.json +0 -38
- package/src/v11/index.js +0 -62
- package/src/v11/select/fragments.json +0 -1
- package/src/v11/select/index.js +0 -34
- package/src/v11/select/skeleton.json +0 -23
- package/src/v11/table/index.js +0 -35
- package/src/v11/table/skeleton.json +0 -47
- package/src/v12/index.js +0 -62
- package/src/v12/registerGlobal.js +0 -14
- package/src/v12/table/index.js +0 -35
- package/src/v12/table/skeleton.json +0 -47
- package/src/v13/registerGlobal.js +0 -14
- /package/src/{v13 → v15}/buildSpec/index.js +0 -0
- /package/src/{v11 → v15}/common/deriveColumnsFromData.js +0 -0
- /package/src/{v11 → v15}/registerGlobal.js +0 -0
- /package/src/{v12 → v16}/common/deriveColumnsFromData.js +0 -0
- /package/src/{v13 → v17}/common/deriveColumnsFromData.js +0 -0
package/docs/table.html
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en" class="dark">
|
|
3
|
+
|
|
3
4
|
<head>
|
|
4
5
|
<meta charset="UTF-8" />
|
|
5
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
7
|
<title>json-renderers | Table Flow</title>
|
|
7
8
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
9
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
|
-
<link
|
|
10
|
+
<link
|
|
11
|
+
href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&family=Inter:wght@300;400;500;600;700;800&display=swap"
|
|
12
|
+
rel="stylesheet" />
|
|
10
13
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
11
14
|
<script>
|
|
12
15
|
tailwind.config = {
|
|
@@ -22,16 +25,29 @@
|
|
|
22
25
|
};
|
|
23
26
|
</script>
|
|
24
27
|
<style>
|
|
25
|
-
body {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
body {
|
|
29
|
+
font-family: 'Inter', sans-serif;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
pre,
|
|
33
|
+
code {
|
|
34
|
+
font-family: 'Fira Code', monospace;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.glass {
|
|
38
|
+
background: rgba(15, 23, 42, 0.8);
|
|
39
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
40
|
+
}
|
|
28
41
|
</style>
|
|
29
42
|
</head>
|
|
43
|
+
|
|
30
44
|
<body class="bg-slate-950 text-slate-100 min-h-screen">
|
|
31
45
|
<header class="border-b border-slate-800 bg-slate-900/80 backdrop-blur sticky top-0 z-50">
|
|
32
46
|
<div class="max-w-7xl mx-auto px-4 py-3 flex items-center justify-between gap-4">
|
|
33
47
|
<div class="flex items-center gap-3">
|
|
34
|
-
<div
|
|
48
|
+
<div
|
|
49
|
+
class="w-10 h-10 rounded-xl bg-gradient-to-br from-emerald-500 via-teal-600 to-indigo-600 flex items-center justify-center font-bold text-lg">
|
|
50
|
+
📊</div>
|
|
35
51
|
<div>
|
|
36
52
|
<div class="text-base font-bold text-white">json-renderers</div>
|
|
37
53
|
<div class="text-xs text-slate-400">Table Flow Story</div>
|
|
@@ -39,15 +55,18 @@
|
|
|
39
55
|
</div>
|
|
40
56
|
<nav class="flex items-center gap-2 text-sm">
|
|
41
57
|
<a href="index.html" class="px-3 py-1.5 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200">Home</a>
|
|
42
|
-
<a href="table.html" class="px-3 py-1.5 rounded-lg bg-
|
|
43
|
-
<a href="
|
|
58
|
+
<a href="table/index.html" class="px-3 py-1.5 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200">About Table</a>
|
|
59
|
+
<a href="aboutSelect.html" class="px-3 py-1.5 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200">About Select</a>
|
|
60
|
+
<a href="table.html" class="px-3 py-1.5 rounded-lg bg-emerald-600 text-white font-semibold">Table Flow</a>
|
|
61
|
+
<a href="select.html" class="px-3 py-1.5 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-200">Select Flow</a>
|
|
44
62
|
</nav>
|
|
45
63
|
</div>
|
|
46
64
|
</header>
|
|
47
65
|
|
|
48
66
|
<main class="max-w-7xl mx-auto px-4 py-10 space-y-8">
|
|
49
67
|
<section class="glass rounded-3xl p-8">
|
|
50
|
-
<div
|
|
68
|
+
<div
|
|
69
|
+
class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-xs text-emerald-300 font-mono mb-6">
|
|
51
70
|
<span class="w-2 h-2 rounded-full bg-emerald-400 animate-pulse"></span>
|
|
52
71
|
Table / JSON to DOM
|
|
53
72
|
</div>
|
|
@@ -56,7 +75,9 @@
|
|
|
56
75
|
A table is not built by the runtime directly.
|
|
57
76
|
</h1>
|
|
58
77
|
<p class="max-w-4xl mt-5 text-lg text-slate-300">
|
|
59
|
-
The runtime asks for a table blueprint, receives JSON, and then hands that JSON to <span
|
|
78
|
+
The runtime asks for a table blueprint, receives JSON, and then hands that JSON to <span
|
|
79
|
+
class="text-emerald-300 font-mono">@keshavsoft/json-to-tag</span> so the browser can create real HTML table
|
|
80
|
+
elements.
|
|
60
81
|
</p>
|
|
61
82
|
</section>
|
|
62
83
|
|
|
@@ -126,7 +147,8 @@ target.append(...nodeList);
|
|
|
126
147
|
|
|
127
148
|
<section class="glass rounded-3xl p-5">
|
|
128
149
|
<h2 class="text-2xl font-bold text-white mb-4">Live render</h2>
|
|
129
|
-
<div class="mb-4 text-sm text-slate-300">This is the final DOM that is mounted after the JSON spec is turned into
|
|
150
|
+
<div class="mb-4 text-sm text-slate-300">This is the final DOM that is mounted after the JSON spec is turned into
|
|
151
|
+
real browser nodes.</div>
|
|
130
152
|
<div id="table-container" class="overflow-x-auto rounded-2xl border border-slate-700"></div>
|
|
131
153
|
</section>
|
|
132
154
|
</main>
|
|
@@ -169,4 +191,5 @@ target.append(...nodeList);
|
|
|
169
191
|
document.getElementById('table-container').appendChild(table);
|
|
170
192
|
</script>
|
|
171
193
|
</body>
|
|
172
|
-
|
|
194
|
+
|
|
195
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-renderers",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.3",
|
|
4
4
|
"description": "Browser DOM component renderer built on top of json-renderers-build and @keshavsoft/json-to-tag",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -41,6 +41,6 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@keshavsoft/json-to-tag": "^1.9.3",
|
|
44
|
-
"json-renderers-build": "^1.
|
|
44
|
+
"json-renderers-build": "^1.11.2"
|
|
45
45
|
}
|
|
46
46
|
}
|
package/src/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export { default } from "./
|
|
1
|
+
export * from "./v17/index.js";
|
|
2
|
+
export { default } from "./v17/index.js";
|
package/src/v15/guard.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const gaurdFunc = ({ intype, indata, intargetHtmlId, incoumns, inshowLog }) => {
|
|
2
|
+
|
|
3
|
+
if (typeof intype !== "string" || intype.trim() === "") {
|
|
4
|
+
console.error("type must be a string");
|
|
5
|
+
throw new Error("type must be a string");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (!Array.isArray(indata)) {
|
|
9
|
+
console.error("data must be an Array");
|
|
10
|
+
throw new Error("data must be an Array");
|
|
11
|
+
};
|
|
12
|
+
if (typeof intargetHtmlId !== "string" || !intargetHtmlId.trim()) {
|
|
13
|
+
console.error("targetHtmlId must be a non-empty string");
|
|
14
|
+
throw new TypeError("targetHtmlId must be a non-empty string");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!Array.isArray(incoumns)) {
|
|
18
|
+
console.error("columns must be an array");
|
|
19
|
+
throw new TypeError("columns must be an array");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof inshowLog !== "boolean") {
|
|
23
|
+
console.error("showLog must be a boolean");
|
|
24
|
+
throw new TypeError("showLog must be a boolean");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (inshowLog !== true) {
|
|
28
|
+
console.error("showLog must be true");
|
|
29
|
+
throw new TypeError("showLog must be true");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return true;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default gaurdFunc;
|
package/src/{v13 → v15}/index.js
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import registerGlobal from "./registerGlobal.js";
|
|
2
|
+
import gaurdFunc from "./guard.js";
|
|
2
3
|
|
|
3
4
|
import buildSpec from "./buildSpec/index.js";
|
|
4
5
|
|
|
@@ -16,8 +17,17 @@ const render = ({
|
|
|
16
17
|
const localTargetHtmlId = targetHtmlId;
|
|
17
18
|
const localData = data;
|
|
18
19
|
const localColumns = columns;
|
|
20
|
+
const localShowLog = showLog;
|
|
21
|
+
|
|
22
|
+
gaurdFunc({
|
|
23
|
+
intype: rawType,
|
|
24
|
+
indata: localData,
|
|
25
|
+
intargetHtmlId: localTargetHtmlId,
|
|
26
|
+
incoumns: localColumns,
|
|
27
|
+
inshowLog: localShowLog
|
|
28
|
+
});
|
|
19
29
|
|
|
20
|
-
if (
|
|
30
|
+
if (localShowLog);
|
|
21
31
|
|
|
22
32
|
// Default to table renderer
|
|
23
33
|
const content = buildSpec({
|
|
@@ -35,9 +45,6 @@ const render = ({
|
|
|
35
45
|
content instanceof NodeList ||
|
|
36
46
|
content instanceof HTMLCollection;
|
|
37
47
|
|
|
38
|
-
console.log("prepend ---------:", rawType, isCollection, container, content, localData);
|
|
39
|
-
|
|
40
|
-
|
|
41
48
|
if (isCollection) {
|
|
42
49
|
if (appendPosition === "prepend") {
|
|
43
50
|
container.prepend(...content);
|
|
@@ -53,24 +60,6 @@ const render = ({
|
|
|
53
60
|
};
|
|
54
61
|
};
|
|
55
62
|
|
|
56
|
-
// if (appendPosition === "prepend") {
|
|
57
|
-
|
|
58
|
-
// container.prepend(content);
|
|
59
|
-
// } else {
|
|
60
|
-
// if (container) container.innerHTML = "";
|
|
61
|
-
|
|
62
|
-
// console.log("showLog 5 ---------:", container, content);
|
|
63
|
-
|
|
64
|
-
// container.append(content);
|
|
65
|
-
|
|
66
|
-
// // if (content != null && typeof content[Symbol.iterator] === "function") {
|
|
67
|
-
// // container.append(...content);
|
|
68
|
-
// // } else {
|
|
69
|
-
|
|
70
|
-
// // container.append(content);
|
|
71
|
-
// // };
|
|
72
|
-
// };
|
|
73
|
-
|
|
74
63
|
if (showLog) console.log("showLog 5 :", container);
|
|
75
64
|
|
|
76
65
|
return container;
|
package/src/{v11 → v15}/meta.js
RENAMED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import jsonRenderBuild from "json-renderers-build";
|
|
2
|
+
import jsonToTag from "@keshavsoft/json-to-tag";
|
|
3
|
+
|
|
4
|
+
// --- Story of Table Render ---
|
|
5
|
+
const startFunc = ({
|
|
6
|
+
inTargetHtmlId,
|
|
7
|
+
inColumns,
|
|
8
|
+
inType = "table",
|
|
9
|
+
inData,
|
|
10
|
+
inShowLog = false
|
|
11
|
+
} = {}) => {
|
|
12
|
+
const localTargetHtmlId = inTargetHtmlId;
|
|
13
|
+
const localData = inData ?? [];
|
|
14
|
+
const localColumns = inColumns;
|
|
15
|
+
const localType = inType;
|
|
16
|
+
const localShowLog = inShowLog;
|
|
17
|
+
|
|
18
|
+
if (localShowLog) console.log("buildSpec 1 :", localTargetHtmlId, localData, localColumns);
|
|
19
|
+
|
|
20
|
+
let specAsJsonToDom = jsonRenderBuild({
|
|
21
|
+
type: localType,
|
|
22
|
+
targetHtmlId: localTargetHtmlId,
|
|
23
|
+
data: localData,
|
|
24
|
+
columns: localColumns
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
let jsonToSend = specAsJsonToDom;
|
|
28
|
+
|
|
29
|
+
const content = jsonToTag(jsonToSend);
|
|
30
|
+
|
|
31
|
+
if (localShowLog) {
|
|
32
|
+
console.log("buildSpec 2 :", jsonToSend, content);
|
|
33
|
+
console.log("buildSpec 3 :", content);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return content;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { startFunc };
|
|
40
|
+
export default startFunc;
|
package/src/v16/guard.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const guardFunc = ({ inConfig } = {}) => {
|
|
2
|
+
const localConfig = inConfig;
|
|
3
|
+
|
|
4
|
+
if (!localConfig || typeof localConfig !== "object") {
|
|
5
|
+
console.error("Config must be an object");
|
|
6
|
+
throw new TypeError("Config must be an object");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (typeof localConfig?.type !== "string") {
|
|
10
|
+
console.error("type must be string only");
|
|
11
|
+
throw new Error("type must be string only");
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
if (!Array.isArray(localConfig.data)) {
|
|
15
|
+
console.error("data must be an Array");
|
|
16
|
+
throw new TypeError("data must be an Array");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (typeof localConfig.targetHtmlId !== "string" || !localConfig.targetHtmlId.trim()) {
|
|
20
|
+
console.error("targetHtmlId must be a non-empty string");
|
|
21
|
+
throw new TypeError("targetHtmlId must be a non-empty string");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!Array.isArray(localConfig.columns)) {
|
|
25
|
+
console.error("columns must be an array");
|
|
26
|
+
throw new TypeError("columns must be an array");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (localConfig.showLog !== undefined && typeof localConfig.showLog !== "boolean") {
|
|
30
|
+
console.error("showLog must be a boolean");
|
|
31
|
+
throw new TypeError("showLog must be a boolean");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return true;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { guardFunc };
|
|
38
|
+
export default guardFunc;
|
package/src/v16/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import registerGlobal from "./registerGlobal.js";
|
|
2
|
+
import guardFunc from "./guard.js";
|
|
3
|
+
import buildSpec from "./buildSpec/index.js";
|
|
4
|
+
|
|
5
|
+
// Pure function: builds and validates the JSON configuration without touching DOM
|
|
6
|
+
const getSpec = ({
|
|
7
|
+
type = "table",
|
|
8
|
+
targetHtmlId,
|
|
9
|
+
data,
|
|
10
|
+
columns,
|
|
11
|
+
classToApply,
|
|
12
|
+
appendPosition,
|
|
13
|
+
showLog = false
|
|
14
|
+
} = {}) => {
|
|
15
|
+
const localType = type;
|
|
16
|
+
const localTargetHtmlId = targetHtmlId;
|
|
17
|
+
const localData = data;
|
|
18
|
+
const localColumns = columns;
|
|
19
|
+
const localClassToApply = classToApply;
|
|
20
|
+
const localAppendPosition = appendPosition;
|
|
21
|
+
const localShowLog = showLog;
|
|
22
|
+
|
|
23
|
+
const specJson = {
|
|
24
|
+
type: localType,
|
|
25
|
+
targetHtmlId: localTargetHtmlId,
|
|
26
|
+
data: localData,
|
|
27
|
+
columns: localColumns,
|
|
28
|
+
classToApply: localClassToApply,
|
|
29
|
+
appendPosition: localAppendPosition,
|
|
30
|
+
showLog: localShowLog
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Internal call using the in-convention
|
|
34
|
+
guardFunc({ inConfig: specJson });
|
|
35
|
+
|
|
36
|
+
return specJson;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Render function: Public API accepting clean single options object
|
|
40
|
+
const render = ({
|
|
41
|
+
type = "table",
|
|
42
|
+
targetHtmlId,
|
|
43
|
+
data,
|
|
44
|
+
columns,
|
|
45
|
+
classToApply,
|
|
46
|
+
appendPosition,
|
|
47
|
+
showLog = false
|
|
48
|
+
} = {}) => {
|
|
49
|
+
// 1. Get and validate the clean JSON specification
|
|
50
|
+
const specJson = getSpec({
|
|
51
|
+
type,
|
|
52
|
+
targetHtmlId,
|
|
53
|
+
data,
|
|
54
|
+
columns,
|
|
55
|
+
classToApply,
|
|
56
|
+
appendPosition,
|
|
57
|
+
showLog
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (specJson.showLog) console.log("showLog 1 (spec):", specJson);
|
|
61
|
+
|
|
62
|
+
// 2. Build DOM content via buildSpec
|
|
63
|
+
const content = buildSpec({
|
|
64
|
+
inTargetHtmlId: specJson.targetHtmlId,
|
|
65
|
+
inColumns: specJson.columns,
|
|
66
|
+
inData: specJson.data,
|
|
67
|
+
inType: specJson.type,
|
|
68
|
+
inShowLog: specJson.showLog
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (specJson.showLog) console.log("showLog 2 (content):", content);
|
|
72
|
+
|
|
73
|
+
const container = document.getElementById(specJson.targetHtmlId);
|
|
74
|
+
if (specJson.showLog) console.log("showLog 3 (container):", container);
|
|
75
|
+
|
|
76
|
+
if (!container) return null;
|
|
77
|
+
|
|
78
|
+
const isCollection = Array.isArray(content) ||
|
|
79
|
+
content instanceof NodeList ||
|
|
80
|
+
content instanceof HTMLCollection;
|
|
81
|
+
|
|
82
|
+
if (isCollection) {
|
|
83
|
+
if (specJson.appendPosition === "prepend") {
|
|
84
|
+
container.prepend(...content);
|
|
85
|
+
} else {
|
|
86
|
+
container.append(...content);
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
if (specJson.appendPosition === "prepend") {
|
|
90
|
+
container.prepend(content);
|
|
91
|
+
} else {
|
|
92
|
+
container.innerHTML = "";
|
|
93
|
+
container.append(content);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (specJson.showLog) console.log("showLog 4 (mounted):", container);
|
|
98
|
+
|
|
99
|
+
return container;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
registerGlobal({ render, getSpec });
|
|
103
|
+
|
|
104
|
+
export { render, getSpec, buildSpec };
|
|
105
|
+
|
|
106
|
+
export default render;
|
package/src/{v13 → v16}/meta.js
RENAMED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import meta from "./meta.js";
|
|
2
|
+
|
|
3
|
+
export const registerGlobal = (inDefinition) => {
|
|
4
|
+
const localDefinition = inDefinition;
|
|
5
|
+
|
|
6
|
+
if (typeof globalThis === "undefined" || !localDefinition) return;
|
|
7
|
+
|
|
8
|
+
globalThis.ks ??= {};
|
|
9
|
+
|
|
10
|
+
const renderFunc = typeof localDefinition === "function"
|
|
11
|
+
? localDefinition
|
|
12
|
+
: localDefinition.render;
|
|
13
|
+
|
|
14
|
+
const getSpecFunc = typeof localDefinition === "object"
|
|
15
|
+
? localDefinition.getSpec
|
|
16
|
+
: undefined;
|
|
17
|
+
|
|
18
|
+
globalThis.ks.jsonRenderers = {
|
|
19
|
+
meta,
|
|
20
|
+
renderToDom: renderFunc,
|
|
21
|
+
render: renderFunc,
|
|
22
|
+
...(getSpecFunc ? { getSpec: getSpecFunc } : {}),
|
|
23
|
+
...(typeof localDefinition === "object" ? localDefinition : {})
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default registerGlobal;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import jsonRenderBuild from "json-renderers-build";
|
|
2
|
+
|
|
3
|
+
// --- Story of Spec Build ---
|
|
4
|
+
const startFunc = ({
|
|
5
|
+
inColumns,
|
|
6
|
+
inType = "table",
|
|
7
|
+
inData,
|
|
8
|
+
inShowLog = false
|
|
9
|
+
} = {}) => {
|
|
10
|
+
const localData = inData ?? [];
|
|
11
|
+
const localColumns = inColumns;
|
|
12
|
+
const localType = inType;
|
|
13
|
+
const localShowLog = inShowLog;
|
|
14
|
+
|
|
15
|
+
const specAsJsonToDom = jsonRenderBuild({
|
|
16
|
+
type: localType,
|
|
17
|
+
data: localData,
|
|
18
|
+
columns: localColumns,
|
|
19
|
+
showLog: localShowLog
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return specAsJsonToDom;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default startFunc;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import spec from "./spec.json" with { type: "json" };
|
|
2
|
+
|
|
3
|
+
// Returns the specification object when called
|
|
4
|
+
const getSpec = () => {
|
|
5
|
+
return { ...spec };
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// Also attach properties directly to getSpec so it functions as both an object and a callable function
|
|
9
|
+
Object.assign(getSpec, spec);
|
|
10
|
+
|
|
11
|
+
export { getSpec, spec };
|
|
12
|
+
export default getSpec;
|
package/src/v17/guard.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import spec from "./spec.json" with { type: "json" };
|
|
2
|
+
|
|
3
|
+
const guardFunc = ({ inConfig } = {}) => {
|
|
4
|
+
const localConfig = inConfig;
|
|
5
|
+
|
|
6
|
+
if (!localConfig || typeof localConfig !== "object") {
|
|
7
|
+
console.error("Config must be an object");
|
|
8
|
+
throw new TypeError("Config must be an object");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Dynamic schema validation against spec.json keys and types
|
|
12
|
+
for (const key of Object.keys(spec)) {
|
|
13
|
+
// 1. All keys are compulsory
|
|
14
|
+
if (!(key in localConfig) || localConfig[key] === undefined) {
|
|
15
|
+
console.error(`Missing compulsory key: "${key}"`);
|
|
16
|
+
throw new Error(`Missing compulsory key: "${key}"`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 2. Type validation derived from spec.json
|
|
20
|
+
if (Array.isArray(spec[key])) {
|
|
21
|
+
if (!Array.isArray(localConfig[key])) {
|
|
22
|
+
console.error(`${key} must be an Array`);
|
|
23
|
+
throw new TypeError(`${key} must be an Array`);
|
|
24
|
+
}
|
|
25
|
+
} else if (typeof localConfig[key] !== typeof spec[key]) {
|
|
26
|
+
console.error(`${key} must be of type ${typeof spec[key]}`);
|
|
27
|
+
throw new TypeError(`${key} must be of type ${typeof spec[key]}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Specific business rule: targetHtmlId must be a non-empty string
|
|
32
|
+
if (typeof localConfig.targetHtmlId === "string" && !localConfig.targetHtmlId.trim()) {
|
|
33
|
+
console.error("targetHtmlId must be a non-empty string");
|
|
34
|
+
throw new TypeError("targetHtmlId must be a non-empty string");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return true;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { guardFunc };
|
|
41
|
+
export default guardFunc;
|
package/src/v17/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import registerGlobal from "./registerGlobal.js";
|
|
2
|
+
import validateConfig from "./validateConfig.js";
|
|
3
|
+
import getSpec from "./getSpec.js";
|
|
4
|
+
import buildSpec from "./buildSpec/index.js";
|
|
5
|
+
import renderToDom from "./renderToDom/index.js";
|
|
6
|
+
|
|
7
|
+
// Main orchestrator: coordinates validation, spec building, and DOM rendering
|
|
8
|
+
const render = (options = {}) => {
|
|
9
|
+
const config = validateConfig(options);
|
|
10
|
+
|
|
11
|
+
const spec = buildSpec({
|
|
12
|
+
inColumns: config.columns,
|
|
13
|
+
inData: config.data,
|
|
14
|
+
inType: config.type,
|
|
15
|
+
inShowLog: config.showLog
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return renderToDom({
|
|
19
|
+
inSpec: spec,
|
|
20
|
+
inTargetHtmlId: config.targetHtmlId,
|
|
21
|
+
inAppendPosition: config.appendPosition,
|
|
22
|
+
inShowLog: config.showLog
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
registerGlobal({ render, getSpec, validateConfig, buildSpec, renderToDom });
|
|
27
|
+
|
|
28
|
+
export { render, getSpec, validateConfig, buildSpec, renderToDom };
|
|
29
|
+
export default render;
|
package/src/{v12 → v17}/meta.js
RENAMED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import meta from "./meta.js";
|
|
2
|
+
|
|
3
|
+
export const registerGlobal = (inDefinition) => {
|
|
4
|
+
const localDefinition = inDefinition;
|
|
5
|
+
|
|
6
|
+
if (typeof globalThis === "undefined" || !localDefinition) return;
|
|
7
|
+
|
|
8
|
+
globalThis.ks ??= {};
|
|
9
|
+
|
|
10
|
+
const renderFunc = typeof localDefinition === "function"
|
|
11
|
+
? localDefinition
|
|
12
|
+
: localDefinition.render;
|
|
13
|
+
|
|
14
|
+
const getSpecFunc = typeof localDefinition === "object"
|
|
15
|
+
? localDefinition.getSpec
|
|
16
|
+
: undefined;
|
|
17
|
+
|
|
18
|
+
globalThis.ks.jsonRenderers = {
|
|
19
|
+
meta,
|
|
20
|
+
...(typeof localDefinition === "object" ? localDefinition : {}),
|
|
21
|
+
render: renderFunc,
|
|
22
|
+
renderToDom: renderFunc,
|
|
23
|
+
domMount: localDefinition?.renderToDom,
|
|
24
|
+
...(getSpecFunc ? { getSpec: getSpecFunc } : {})
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default registerGlobal;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import jsonToTag from "@keshavsoft/json-to-tag";
|
|
2
|
+
|
|
3
|
+
// --- Story of DOM Rendering and Mounting ---
|
|
4
|
+
const renderToDom = ({
|
|
5
|
+
inSpec,
|
|
6
|
+
inTargetHtmlId,
|
|
7
|
+
inAppendPosition,
|
|
8
|
+
inShowLog = false
|
|
9
|
+
} = {}) => {
|
|
10
|
+
const localSpec = inSpec;
|
|
11
|
+
const localTargetHtmlId = inTargetHtmlId;
|
|
12
|
+
const localAppendPosition = inAppendPosition;
|
|
13
|
+
const localShowLog = inShowLog;
|
|
14
|
+
|
|
15
|
+
const content = jsonToTag(localSpec);
|
|
16
|
+
|
|
17
|
+
if (localShowLog) console.log("renderToDom 1 (content):", content);
|
|
18
|
+
|
|
19
|
+
const container = document.getElementById(localTargetHtmlId);
|
|
20
|
+
if (!container) return null;
|
|
21
|
+
|
|
22
|
+
const isCollection = Array.isArray(content) ||
|
|
23
|
+
content instanceof NodeList ||
|
|
24
|
+
content instanceof HTMLCollection;
|
|
25
|
+
|
|
26
|
+
if (isCollection) {
|
|
27
|
+
if (localAppendPosition === "prepend") {
|
|
28
|
+
container.prepend(...content);
|
|
29
|
+
} else {
|
|
30
|
+
container.append(...content);
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
if (localAppendPosition === "prepend") {
|
|
34
|
+
container.prepend(content);
|
|
35
|
+
} else {
|
|
36
|
+
container.innerHTML = "";
|
|
37
|
+
container.append(content);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (localShowLog) console.log("renderToDom 2 (mounted):", container);
|
|
42
|
+
|
|
43
|
+
return container;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { renderToDom };
|
|
47
|
+
export default renderToDom;
|