aprog 1.8.8 → 1.8.9

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/index.js CHANGED
@@ -20,3 +20,4 @@ export {
20
20
  toKebabCaseStringPrototype, toSnakeCaseStringPrototype,
21
21
  repeatHTMLElementPrototype
22
22
  } from './src/html.js';
23
+ export { prism } from "./src/prism.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aprog",
3
- "version": "1.8.8",
3
+ "version": "1.8.9",
4
4
  "description": "Допоміжна бібліотека js",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,35 @@
1
+ /* override Prism JSON color styles */
2
+ :root {
3
+ --prism-white: #ffffff;
4
+ --prism-green: #008800;
5
+ --prism-red: #ff2800;
6
+ --prism-red-2: #C43B00;
7
+ --prism-blue-2: #1199dd;
8
+ --prism-orange: #ff8800;
9
+ --prism-violet: #881199;
10
+
11
+ /* GENERAL COLORS */
12
+ --prism-bg: #212121;
13
+ --prism-operator: #d0d0d0;
14
+ --prism-property: #A782BB;
15
+ --prism-string: #8EA765;
16
+ --prism-number: #118899;
17
+ --prism-boolean: #CC7832;
18
+ }
19
+ pre.token.block {
20
+ min-width: 100%;
21
+ width: max-content;
22
+ padding: 1rem;
23
+ color: var(--prism-property);
24
+ background-color: var(--prism-bg);
25
+ }
26
+ .token.punctuation, .token.operator { color: var(--prism-operator); }
27
+ .token.property { color: var(--prism-property); }
28
+ .token.string { color: var(--prism-string); }
29
+ .token.number { color: var(--prism-number); }
30
+ .token.boolean, .token.null { color: var(--prism-boolean); }
31
+ .token.editor {
32
+ font-weight: 700;
33
+ color: var(--prism-blue-2);
34
+ text-shadow: 0 0 6px rgba(255, 255, 255, 1);
35
+ }
package/src/prism.js ADDED
@@ -0,0 +1,172 @@
1
+ import {span} from "./aprog.js";
2
+ import "./css/prism.css";
3
+
4
+ export const prism = (text) => {
5
+ const container = document.createElement("pre");
6
+ container.className = "token block";
7
+ const stack = [];
8
+ let counter = 1;
9
+
10
+ const tokenRegex = /"(?:\\.|[^"\\])*"|true|false|null|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|[{}\[\],:]/g;
11
+ let lastIndex = 0;
12
+
13
+ const tokens = Array.from(text.matchAll(tokenRegex));
14
+
15
+ for (let i = 0; i < tokens.length; i++) {
16
+ const match = tokens[i];
17
+ const token = match[0];
18
+ const indexInText = match.index;
19
+ const nextToken = tokens[i + 1]?.[0];
20
+
21
+ if (indexInText > lastIndex) {
22
+ const between = text.slice(lastIndex, indexInText);
23
+ container.appendChild(document.createTextNode(between));
24
+ }
25
+
26
+ lastIndex = indexInText + token.length;
27
+
28
+ if (token === "{" || token === "[") {
29
+ const index = counter++;
30
+ stack.push(index);
31
+
32
+ const isEmpty = (token === "{" && nextToken === "}") || (token === "[" && nextToken === "]");
33
+
34
+ if (isEmpty) {
35
+ container.appendChild(span({
36
+ class: "token punctuation",
37
+ value: token
38
+ }));
39
+ continue;
40
+ }
41
+
42
+ const elementStart = span({
43
+ class: `token punctuation start-${index}`,
44
+ style: isEmpty ? {} : { cursor: "pointer" },
45
+ dataStart: "m",
46
+ value: isEmpty ? token : `<span class="token editor">-</span> ${token}`,
47
+ onClick: isEmpty ? null : (event) => {
48
+ const el = event.target.closest(`.start-${index}`);
49
+ const tokenType = token;
50
+
51
+ if (!el) return;
52
+
53
+ const hide = el.dataset.start === "m";
54
+ el.dataset.start = hide ? "p" : "m";
55
+ el.innerHTML = `<span class="token editor">${hide ? "+" : "-"}</span> ${tokenType}`;
56
+
57
+ let sibling = el.nextSibling;
58
+
59
+ while (sibling) {
60
+ const next = sibling.nextSibling;
61
+
62
+ if (
63
+ sibling.nodeType === 1 &&
64
+ sibling.classList.contains(`end-${index}`)
65
+ ) {
66
+ break;
67
+ }
68
+
69
+ if (sibling.nodeType === 1) {
70
+ if (hide) {
71
+ sibling.style.display = "none";
72
+ } else {
73
+ sibling.style.display = "";
74
+ }
75
+ } else if (sibling.nodeType === 3) {
76
+ if (hide) {
77
+ const span = document.createElement("span");
78
+ span.className = `__hidden-text-${index}`;
79
+ span.style.display = "none";
80
+ span.appendChild(sibling.cloneNode());
81
+ el.parentNode.insertBefore(span, sibling);
82
+ el.parentNode.removeChild(sibling);
83
+ } else {
84
+ const existing = el.parentNode.querySelector(`.__hidden-text-${index}`);
85
+ if (existing) {
86
+ const textNode = existing.firstChild;
87
+ el.parentNode.insertBefore(textNode, existing);
88
+ el.parentNode.removeChild(existing);
89
+ }
90
+ }
91
+ }
92
+
93
+ sibling = next;
94
+ }
95
+
96
+ const endNode = el.parentNode.querySelector(`.end-${index}`);
97
+ if (hide) {
98
+ const dots = document.createElement("span");
99
+ dots.className = `__dots-${index}`;
100
+ dots.textContent = " … ";
101
+ endNode.parentNode.insertBefore(dots, endNode);
102
+ } else {
103
+ const allDots = el.parentNode.querySelectorAll(`span[class*="__dots-"]`);
104
+ allDots.forEach(dot => {
105
+ const num = parseInt(dot.className.match(/__dots-(\d+)/)?.[1], 10);
106
+ if (!isNaN(num) && num >= index) dot.remove();
107
+ });
108
+
109
+ const allStarts = el.parentNode.querySelectorAll(`span[class*="start-"]`);
110
+ allStarts.forEach(startEl => {
111
+ const match = startEl.className.match(/start-(\d+)/);
112
+ const num = parseInt(match?.[1], 10);
113
+ if (!isNaN(num) && num >= index) {
114
+ startEl.dataset.start = "m";
115
+ const symbol = startEl.textContent.trim().slice(-1);
116
+ startEl.innerHTML = `<span class="token editor">-</span> ${symbol}`;
117
+ }
118
+ });
119
+ }
120
+ }
121
+ });
122
+ container.appendChild(elementStart);
123
+ } else if (token === "}" || token === "]") {
124
+ const index = stack.pop();
125
+ const elementEnd = document.createElement("span");
126
+ elementEnd.className = `token punctuation end-${index}`;
127
+ elementEnd.textContent = token;
128
+ container.appendChild(elementEnd);
129
+ } else if (token === ":") {
130
+ const el = document.createElement("span");
131
+ el.className = "token operator";
132
+ el.textContent = token;
133
+ container.appendChild(el);
134
+ } else if (token === ",") {
135
+ const el = document.createElement("span");
136
+ el.className = "token punctuation";
137
+ el.textContent = token;
138
+ container.appendChild(el);
139
+ } else if (/^"/.test(token)) {
140
+ const nextChar = text[match.index + token.length];
141
+ const content = token.slice(1, -1);
142
+ const el = document.createElement("span");
143
+ el.className = nextChar === ":" ? "token property" : "token string";
144
+ el.textContent = `"${content}"`;
145
+ container.appendChild(el);
146
+ } else if (/^-?\d/.test(token)) {
147
+ const el = document.createElement("span");
148
+ el.className = "token number";
149
+ el.textContent = token;
150
+ container.appendChild(el);
151
+ } else if (token === "true" || token === "false") {
152
+ const el = document.createElement("span");
153
+ el.className = "token boolean";
154
+ el.textContent = token;
155
+ container.appendChild(el);
156
+ } else if (token === "null") {
157
+ const el = document.createElement("span");
158
+ el.className = "token null keyword";
159
+ el.textContent = token;
160
+ container.appendChild(el);
161
+ }
162
+
163
+ lastIndex = match.index + token.length;
164
+ }
165
+
166
+ if (lastIndex < text.length) {
167
+ const remaining = text.slice(lastIndex);
168
+ container.appendChild(document.createTextNode(remaining));
169
+ }
170
+
171
+ return container;
172
+ };