@jackens/nnn 2026.9.7 → 2026.9.28
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 +1099 -0
- package/nnn.d.ts +164 -243
- package/nnn.js +81 -114
- package/package.json +2 -13
- package/readme.md +0 -1541
package/nnn.js
CHANGED
|
@@ -50,51 +50,78 @@ var _c = (node, splitter = DEFAULT_SPLITTER, prefix = "", flatten = false) => {
|
|
|
50
50
|
return out.join(flatten ? ";" : "");
|
|
51
51
|
};
|
|
52
52
|
var c = (node, splitter = DEFAULT_SPLITTER) => _c(node, splitter);
|
|
53
|
-
// src/nnn/createEscape.ts
|
|
54
|
-
var createEscape = (escapeFn) => (template, ...values) => String.raw(template, ...values.map(escapeFn));
|
|
55
53
|
// src/nnn/createTokenizer.ts
|
|
56
|
-
var
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
54
|
+
var ROOT = "root";
|
|
55
|
+
var createTokenizer = (decorator, ...specs) => {
|
|
56
|
+
const compiled = specs.map(([metadata, pattern, options]) => ({
|
|
57
|
+
metadata,
|
|
58
|
+
pattern: pattern instanceof RegExp ? new RegExp(pattern.source, pattern.sticky ? pattern.flags : pattern.flags.replace("g", "") + "g") : pattern,
|
|
59
|
+
states: [options?.in ?? ROOT].flat(),
|
|
60
|
+
pop: options?.pop ?? false,
|
|
61
|
+
push: options?.push
|
|
62
|
+
}));
|
|
63
|
+
const find = (pattern, code, position) => {
|
|
64
|
+
if (typeof pattern === "string") {
|
|
65
|
+
const index = pattern.length > 0 ? code.indexOf(pattern, position) : -1;
|
|
66
|
+
return [index, pattern];
|
|
67
|
+
}
|
|
68
|
+
pattern.lastIndex = position;
|
|
69
|
+
for (let match = pattern.exec(code);match != null; match = pattern.exec(code)) {
|
|
70
|
+
if (match[0].length > 0) {
|
|
71
|
+
return [match.index, match[0]];
|
|
73
72
|
}
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
bestIndex = index;
|
|
77
|
-
bestChunk = chunk;
|
|
73
|
+
if (pattern.sticky) {
|
|
74
|
+
break;
|
|
78
75
|
}
|
|
76
|
+
pattern.lastIndex = match.index + 1;
|
|
79
77
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
return [-1, ""];
|
|
79
|
+
};
|
|
80
|
+
return (code) => {
|
|
81
|
+
const result = [];
|
|
82
|
+
const stack = [ROOT];
|
|
83
|
+
const cache = compiled.map(() => ({ from: -1, index: -1, chunk: "" }));
|
|
84
|
+
let position = 0;
|
|
85
|
+
while (position < code.length) {
|
|
86
|
+
const state = stack.at(-1);
|
|
87
|
+
let best = -1;
|
|
88
|
+
let bestIndex = Infinity;
|
|
89
|
+
let bestChunk = "";
|
|
90
|
+
compiled.forEach(({ pattern, states }, i) => {
|
|
91
|
+
if (!states.includes(state)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const cached = cache[i];
|
|
95
|
+
const isValid = cached.from >= 0 && (pattern instanceof RegExp && pattern.sticky ? cached.from === position : cached.from <= position && (cached.index < 0 || cached.index >= position));
|
|
96
|
+
if (!isValid) {
|
|
97
|
+
[cached.index, cached.chunk] = find(pattern, code, position);
|
|
98
|
+
cached.from = position;
|
|
99
|
+
}
|
|
100
|
+
if (cached.index >= 0 && (cached.index < bestIndex || cached.index === bestIndex && cached.chunk.length > bestChunk.length)) {
|
|
101
|
+
best = i;
|
|
102
|
+
bestIndex = cached.index;
|
|
103
|
+
bestChunk = cached.chunk;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
if (best < 0) {
|
|
107
|
+
result.push(decorator(code.slice(position)));
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
const { metadata, pop, push } = compiled[best];
|
|
111
|
+
if (bestIndex > position) {
|
|
112
|
+
result.push(decorator(code.slice(position, bestIndex)));
|
|
113
|
+
}
|
|
114
|
+
result.push(decorator(bestChunk, metadata));
|
|
115
|
+
position = bestIndex + bestChunk.length;
|
|
116
|
+
if (pop && stack.length > 1) {
|
|
117
|
+
stack.pop();
|
|
118
|
+
}
|
|
119
|
+
if (push != null) {
|
|
120
|
+
stack.push(push);
|
|
83
121
|
}
|
|
84
|
-
result.push(decorator(bestChunk, bestMetadata));
|
|
85
|
-
code = code.slice(bestIndex + bestChunk.length);
|
|
86
|
-
} else {
|
|
87
|
-
result.push(decorator(code));
|
|
88
|
-
break;
|
|
89
122
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
};
|
|
93
|
-
// src/nnn/csvParse.ts
|
|
94
|
-
var MAIN_PATTERN = /\n|(?<!")("(?:[^"]|"")*")(?!")/g;
|
|
95
|
-
var csvParse = (csv, separator = ",") => {
|
|
96
|
-
const linePattern = new RegExp(`${separator}|(?<!")\\s*"((?:[^"]|"")*)"\\s*(?!")`, "g");
|
|
97
|
-
return csv.replace(/\r/g, "").replace(/\n+$/, "").replace(MAIN_PATTERN, (_, chunk) => chunk ?? "\r").split("\r").map((line) => line.replace(linePattern, (_, chunk) => chunk == null ? "\r" : chunk.replace(/""/g, '"')).split("\r"));
|
|
123
|
+
return result;
|
|
124
|
+
};
|
|
98
125
|
};
|
|
99
126
|
// src/nnn/h.ts
|
|
100
127
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
@@ -153,45 +180,6 @@ var _h = (createElement, tagOrNode, ...args) => {
|
|
|
153
180
|
var h = _h.bind(null, (tag) => document.createElement(tag));
|
|
154
181
|
var s = _h.bind(null, (tag) => document.createElementNS("http://www.w3.org/2000/svg", tag));
|
|
155
182
|
var svgUse = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
|
|
156
|
-
|
|
157
|
-
// src/nnn/fixPlTypography.ts
|
|
158
|
-
var TAGS_TO_SKIP = [
|
|
159
|
-
"IFRAME",
|
|
160
|
-
"NOSCRIPT",
|
|
161
|
-
"PRE",
|
|
162
|
-
"SCRIPT",
|
|
163
|
-
"STYLE",
|
|
164
|
-
"TEXTAREA"
|
|
165
|
-
];
|
|
166
|
-
var fixPlTypography = (node) => {
|
|
167
|
-
const queue = [node];
|
|
168
|
-
while (queue.length > 0) {
|
|
169
|
-
const node0 = queue.shift();
|
|
170
|
-
if (node0 instanceof Element) {
|
|
171
|
-
node0.childNodes.forEach((childNode) => {
|
|
172
|
-
if (childNode instanceof Text) {
|
|
173
|
-
queue.push(childNode);
|
|
174
|
-
} else if (childNode instanceof Element && !TAGS_TO_SKIP.includes(childNode.tagName)) {
|
|
175
|
-
queue.push(childNode);
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
} else if (node0 instanceof Text) {
|
|
179
|
-
const nodeValue = node0.nodeValue?.trim?.();
|
|
180
|
-
if (nodeValue != null) {
|
|
181
|
-
let previousNode = node0;
|
|
182
|
-
nodeValue.split(/(\s|\(|„)([aiouwz—]\s)/gi).forEach((chunk, i) => {
|
|
183
|
-
i %= 3;
|
|
184
|
-
const currentNode = i === 2 ? h("span", { style: "white-space:nowrap" }, chunk) : document.createTextNode(i === 1 ? chunk : chunk.replace(/(\/(?=[^/\s])|\.(?=[^\s]))/g, "$1"));
|
|
185
|
-
if (node0.parentNode != null) {
|
|
186
|
-
node0.parentNode.insertBefore(currentNode, previousNode.nextSibling);
|
|
187
|
-
}
|
|
188
|
-
previousNode = currentNode;
|
|
189
|
-
});
|
|
190
|
-
node0.parentNode?.removeChild(node0);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
183
|
// src/nnn/monokai.ts
|
|
196
184
|
var monokai = {
|
|
197
185
|
":root$$monokai": {
|
|
@@ -270,6 +258,14 @@ var monokai = {
|
|
|
270
258
|
string: "#ffd866"
|
|
271
259
|
}
|
|
272
260
|
}
|
|
261
|
+
},
|
|
262
|
+
"@media print$$monokai": {
|
|
263
|
+
pre: {
|
|
264
|
+
"background-color": "white"
|
|
265
|
+
},
|
|
266
|
+
":root": {
|
|
267
|
+
"--bg": "white"
|
|
268
|
+
}
|
|
273
269
|
}
|
|
274
270
|
};
|
|
275
271
|
// src/nnn/nanolightTs.ts
|
|
@@ -285,7 +281,12 @@ var NUMBER = "number";
|
|
|
285
281
|
var OPERATOR = "operator";
|
|
286
282
|
var PUNCTUATION = "punctuation";
|
|
287
283
|
var STRING = "string";
|
|
288
|
-
var
|
|
284
|
+
var ROOT2 = "root";
|
|
285
|
+
var TEMPLATE = "template";
|
|
286
|
+
var nanolightTs = /* @__PURE__ */ createTokenizer((chunk, name) => name != null ? ["span", { class: name }, chunk] : chunk, [COMMENT, /\/\*[\s\S]*?(?:\*\/|$)/], [COMMENT, /\/\/.*/], [STRING, /"(?:[^"\\\n]|\\[\s\S])*"?/], [STRING, /'(?:[^'\\\n]|\\[\s\S])*'?/], [STRING, /`(?:[^`\\$]|\\[\s\S]|\$(?!\{))*(?:`|$)/], [STRING, /`(?:[^`\\$]|\\[\s\S]|\$(?!\{))*(?=\$\{)/, { push: TEMPLATE }], [STRING, /(?:[^`\\$]|\\[\s\S]|\$(?!\{))*(?:`|$)/y, { in: TEMPLATE, pop: true }], [STRING, /(?:[^`\\$]|\\[\s\S]|\$(?!\{))+(?=\$\{)/y, { in: TEMPLATE }], [PUNCTUATION, "${", { in: TEMPLATE, push: ROOT2 }], [
|
|
287
|
+
STRING,
|
|
288
|
+
/(?<=(?:^|[!%&(*+,\-:;<=>?[^{|}~]|\b(?:await|case|delete|do|else|in|instanceof|new|of|return|throw|typeof|void|yield))\s*)\/(?![*/])(?:[^\\/[\n]|\\.|\[(?:[^\\\]\n]|\\.)*\]?)+\/[dgimsuvy]*/
|
|
289
|
+
], [NUMBER, /0b[01_]+/], [NUMBER, /0o[01234567_]+/], [NUMBER, /0x[\dabcdef_]+/], [NUMBER, /\d[\d_]*(\.[\d_]+)?(e[+-]?[\d_]+)?/], [OPERATOR, "!"], [OPERATOR, "!="], [OPERATOR, "!=="], [OPERATOR, "%"], [OPERATOR, "%="], [OPERATOR, "&&"], [OPERATOR, "&&="], [OPERATOR, "&"], [OPERATOR, "&="], [OPERATOR, "*"], [OPERATOR, "**"], [OPERATOR, "**="], [OPERATOR, "*="], [OPERATOR, "+"], [OPERATOR, "++"], [OPERATOR, "+="], [OPERATOR, "-"], [OPERATOR, "--"], [OPERATOR, "-="], [OPERATOR, "..."], [OPERATOR, "/"], [OPERATOR, "/="], [OPERATOR, ":"], [OPERATOR, "<"], [OPERATOR, "<<"], [OPERATOR, "<<="], [OPERATOR, "<="], [OPERATOR, "="], [OPERATOR, "=="], [OPERATOR, "==="], [OPERATOR, "=>"], [OPERATOR, ">"], [OPERATOR, ">="], [OPERATOR, ">>"], [OPERATOR, ">>="], [OPERATOR, ">>>"], [OPERATOR, ">>>="], [OPERATOR, "?"], [OPERATOR, "??"], [OPERATOR, "??="], [OPERATOR, "^"], [OPERATOR, "^="], [OPERATOR, "|"], [OPERATOR, "|="], [OPERATOR, "||"], [OPERATOR, "||="], [OPERATOR, "~"], [OPERATOR, "~="], [OPERATOR, /(?<=\s):/], [PUNCTUATION, "("], [PUNCTUATION, ")"], [PUNCTUATION, ","], [PUNCTUATION, "."], [PUNCTUATION, ":"], [PUNCTUATION, ";"], [PUNCTUATION, "?."], [PUNCTUATION, "["], [PUNCTUATION, "]"], [PUNCTUATION, "{", { push: ROOT2 }], [PUNCTUATION, "}", { pop: true }], [KEYWORD1, "as"], [KEYWORD1, "async"], [KEYWORD1, "await"], [KEYWORD1, "break"], [KEYWORD1, "case"], [KEYWORD1, "catch"], [KEYWORD1, "class"], [KEYWORD1, "const"], [KEYWORD1, "continue"], [KEYWORD1, "debugger"], [KEYWORD1, "default"], [KEYWORD1, "delete"], [KEYWORD1, "do"], [KEYWORD1, "else"], [KEYWORD1, "export"], [KEYWORD1, "extends"], [KEYWORD1, "finally"], [KEYWORD1, "for"], [KEYWORD1, "from"], [KEYWORD1, "function"], [KEYWORD1, "function*"], [KEYWORD1, "goto"], [KEYWORD1, "if"], [KEYWORD1, "import"], [KEYWORD1, "in"], [KEYWORD1, "instanceof"], [KEYWORD1, "is"], [KEYWORD1, "keyof"], [KEYWORD1, "let"], [KEYWORD1, "new"], [KEYWORD1, "of"], [KEYWORD1, "package"], [KEYWORD1, "return"], [KEYWORD1, "super"], [KEYWORD1, "switch"], [KEYWORD1, "this"], [KEYWORD1, "throw"], [KEYWORD1, "try"], [KEYWORD1, "type"], [KEYWORD1, "typeof"], [KEYWORD1, "var"], [KEYWORD1, "void"], [KEYWORD1, "while"], [KEYWORD1, "with"], [KEYWORD1, "yield"], [KEYWORD1, "yield*"], [KEYWORD2, "false"], [KEYWORD2, "Infinity"], [KEYWORD2, "NaN"], [KEYWORD2, "null"], [KEYWORD2, "true"], [KEYWORD2, "undefined"], [KEYWORD3, "any"], [KEYWORD3, "bigint"], [KEYWORD3, "boolean"], [KEYWORD3, "eval"], [KEYWORD3, "number"], [KEYWORD3, "string"], [KEYWORD3, "symbol"], [KEYWORD3, "unknown"], [IDENTIFIER1, /[\p{Lu}_$][\p{Lu}\d_$]*/u], [IDENTIFIER2, /[\p{L}_$][\p{L}\d_$]*(?=[(`])/u], [IDENTIFIER3, /\p{Lu}[\p{L}\d_$]*/u], [IDENTIFIER4, /[\p{L}_$][\p{L}\d_$]*/u]);
|
|
289
290
|
// src/nnn/rwd.ts
|
|
290
291
|
var rwd = (root, selector, cellWidthPx, cellHeightPx, ...specs) => {
|
|
291
292
|
const main = root[selector] ??= {};
|
|
@@ -310,47 +311,13 @@ var rwd = (root, selector, cellWidthPx, cellHeightPx, ...specs) => {
|
|
|
310
311
|
node.height = `${cellHeightPx * height}px`;
|
|
311
312
|
}
|
|
312
313
|
};
|
|
313
|
-
// src/nnn/uuidV1.ts
|
|
314
|
-
var ZEROS = /* @__PURE__ */ "0".repeat(16);
|
|
315
|
-
var counter = 0;
|
|
316
|
-
var uuidV1 = (date = new Date, node = Math.random().toString(16).slice(2)) => {
|
|
317
|
-
const time = ZEROS + (1e4 * (+date + 12219292800000)).toString(16);
|
|
318
|
-
counter = counter + 1 & 16383;
|
|
319
|
-
return time.slice(-8).concat("-", time.slice(-12, -8), -1, time.slice(-15, -12), "-", (8 | counter >> 12).toString(16), (ZEROS + (counter & 4095).toString(16)).slice(-3), "-", (ZEROS + node).slice(-12));
|
|
320
|
-
};
|
|
321
|
-
// src/nnn/vivify.ts
|
|
322
|
-
var ARRAY_INDEX_REGEXP = /^(0|[1-9]\d*)$/;
|
|
323
|
-
var isObject = (ref) => typeof ref === "object";
|
|
324
|
-
var getTarget = (parent, parentKey, key) => parent[parentKey] ??= typeof key === "string" && ARRAY_INDEX_REGEXP.test(key) ? [] : {};
|
|
325
|
-
var _vivify = (parent, parentKey) => new Proxy(parent, {
|
|
326
|
-
get(_, key) {
|
|
327
|
-
const target = getTarget(parent, parentKey, key);
|
|
328
|
-
const value = target[key];
|
|
329
|
-
return typeof key === "string" && isObject(target) && (value == null || isObject(value)) ? _vivify(target, key) : value;
|
|
330
|
-
},
|
|
331
|
-
set(_, key, value) {
|
|
332
|
-
const target = getTarget(parent, parentKey, key);
|
|
333
|
-
target[key] = value;
|
|
334
|
-
return true;
|
|
335
|
-
},
|
|
336
|
-
deleteProperty(_, key) {
|
|
337
|
-
const target = getTarget(parent, parentKey, key);
|
|
338
|
-
return delete target[key];
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
var vivify = (ref) => _vivify({ _: ref }, "_");
|
|
342
314
|
export {
|
|
343
315
|
c,
|
|
344
|
-
createEscape,
|
|
345
316
|
createTokenizer,
|
|
346
|
-
csvParse,
|
|
347
|
-
fixPlTypography,
|
|
348
317
|
h,
|
|
349
318
|
monokai,
|
|
350
319
|
nanolightTs,
|
|
351
320
|
rwd,
|
|
352
321
|
s,
|
|
353
|
-
svgUse
|
|
354
|
-
uuidV1,
|
|
355
|
-
vivify
|
|
322
|
+
svgUse
|
|
356
323
|
};
|
package/package.json
CHANGED
|
@@ -1,31 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jackens/nnn",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.28",
|
|
4
4
|
"description": "Jackens’ JavaScript helpers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CSS-in-JS",
|
|
7
|
-
"CSV parse",
|
|
8
|
-
"DOM",
|
|
9
7
|
"HyperScript",
|
|
10
8
|
"JS-to-CSS",
|
|
11
9
|
"Monokai",
|
|
12
10
|
"RWD",
|
|
13
11
|
"Responsive Web Design",
|
|
14
12
|
"SVG",
|
|
15
|
-
"autovivify",
|
|
16
|
-
"c",
|
|
17
|
-
"escape",
|
|
18
|
-
"h",
|
|
19
13
|
"highlight",
|
|
20
14
|
"nanolight",
|
|
21
15
|
"nnn",
|
|
22
16
|
"tokenize",
|
|
23
|
-
"tokenizer"
|
|
24
|
-
"typography",
|
|
25
|
-
"uuid",
|
|
26
|
-
"uuid1",
|
|
27
|
-
"uuidV1",
|
|
28
|
-
"vivify"
|
|
17
|
+
"tokenizer"
|
|
29
18
|
],
|
|
30
19
|
"license": "MIT",
|
|
31
20
|
"author": "Jackens",
|