@jackens/nnn 2026.9.30 → 2026.11.16

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.
Files changed (4) hide show
  1. package/README.md +219 -600
  2. package/nnn.d.ts +26 -88
  3. package/nnn.js +135 -270
  4. package/package.json +14 -10
package/nnn.js CHANGED
@@ -1,304 +1,174 @@
1
- // src/nnn/c.ts
1
+ // src/c.ts
2
2
  var DEFAULT_SPLITTER = "$$";
3
- var combinePrefixAndName = (prefix, name) => {
4
- const prefixes = prefix === "" ? [""] : prefix.split(",");
5
- const names = name.split(",");
6
- const combined = [];
7
- for (const p of prefixes) {
8
- for (const n of names) {
9
- combined.push(p + n);
3
+ var OPENING_BRACKETS = "([";
4
+ var CLOSING_BRACKETS = ")]";
5
+ var scan = (selector, onChar) => {
6
+ let depth = 0;
7
+ let quote = "";
8
+ for (const char of selector) {
9
+ if (quote !== "") {
10
+ if (char === quote) {
11
+ quote = "";
12
+ }
13
+ } else if (char === '"' || char === "'") {
14
+ quote = char;
15
+ } else if (OPENING_BRACKETS.includes(char)) {
16
+ ++depth;
17
+ } else if (CLOSING_BRACKETS.includes(char)) {
18
+ --depth;
19
+ }
20
+ onChar(char, quote === "" && depth === 0);
21
+ }
22
+ };
23
+ var splitSelectorList = (selectorList) => {
24
+ const selectors = [""];
25
+ scan(selectorList, (char, topLevel) => {
26
+ if (topLevel && char === ",") {
27
+ selectors.push("");
28
+ } else {
29
+ selectors[selectors.length - 1] += char;
30
+ }
31
+ });
32
+ return selectors.map((selector, index) => (index === 0 ? selector : selector.trimStart()).trimEnd());
33
+ };
34
+ var nestSelector = (parent, selector) => {
35
+ let nested = "";
36
+ let ampersandFound = false;
37
+ scan(selector, (char, topLevel) => {
38
+ if (char === "&" && topLevel) {
39
+ nested += parent;
40
+ ampersandFound = true;
41
+ } else {
42
+ nested += char;
43
+ }
44
+ });
45
+ return ampersandFound ? nested : parent + selector;
46
+ };
47
+ var stripSplitter = (key, splitter) => {
48
+ const splitterIndex = splitter === "" ? -1 : key.indexOf(splitter);
49
+ return splitterIndex < 0 ? key : key.slice(0, splitterIndex);
50
+ };
51
+ var cProperties = (node, splitter, prefix) => {
52
+ const out = [];
53
+ for (const [key, value] of Object.entries(node)) {
54
+ if (value != null) {
55
+ const name = prefix + stripSplitter(key, splitter);
56
+ if (typeof value === "object") {
57
+ out.push(...cProperties(value, splitter, name));
58
+ } else {
59
+ out.push(`${name}:${value}`);
60
+ }
10
61
  }
11
62
  }
12
- return combined.join(",");
63
+ return out;
13
64
  };
14
- var _c = (node, splitter = DEFAULT_SPLITTER, prefix = "", flatten = false) => {
65
+ var cRules = (node, splitter, selectors) => {
15
66
  const out = [];
16
- let buffer = [];
67
+ let declarations = [];
17
68
  const flush = () => {
18
- if (buffer.length === 0) {
19
- return;
69
+ if (declarations.length > 0) {
70
+ out.push(selectors.length === 0 ? `${declarations.join(";")};` : `${selectors.join(",")}{${declarations.join(";")}}`);
71
+ declarations = [];
20
72
  }
21
- out.push(prefix === "" ? buffer.join(";") : `${prefix}{${buffer.join(";")}}`);
22
- buffer = [];
23
73
  };
24
- for (const [rawKey, value] of Object.entries(node)) {
74
+ for (const [key, value] of Object.entries(node)) {
25
75
  if (value == null) {
26
76
  continue;
27
77
  }
28
- const splitterIndex = rawKey.indexOf(splitter);
29
- const name = splitterIndex < 0 ? rawKey : rawKey.slice(0, splitterIndex);
30
- if (typeof value === "number" || typeof value === "string") {
31
- if (flatten) {
32
- out.push(`${prefix + name}:${value}`);
33
- } else {
34
- buffer.push(`${name}:${value}`);
35
- }
36
- continue;
37
- }
38
- if (flatten) {
39
- out.push(_c(value, splitter, prefix + name, true));
78
+ const name = stripSplitter(key, splitter);
79
+ if (typeof value !== "object") {
80
+ declarations.push(`${name}:${value}`);
40
81
  continue;
41
82
  }
42
83
  flush();
43
- if (prefix === "" && (name === ":root" || name[0] === "@")) {
44
- out.push(`${name}{${_c(value, splitter, "", name === ":root")}}`);
84
+ if (name[0] === "@") {
85
+ out.push(`${name}{${cRules(value, splitter, selectors)}}`);
86
+ } else if (selectors.length === 0 && name === ":root") {
87
+ out.push(`:root{${cProperties(value, splitter, "").join(";")}}`);
45
88
  } else {
46
- out.push(_c(value, splitter, combinePrefixAndName(prefix, name), false));
89
+ const alternatives = splitSelectorList(name);
90
+ const parents = selectors.length === 0 ? [""] : selectors;
91
+ out.push(cRules(value, splitter, parents.flatMap((parent) => alternatives.map((selector) => nestSelector(parent, selector)))));
47
92
  }
48
93
  }
49
94
  flush();
50
- return out.join(flatten ? ";" : "");
95
+ const css = out.join("");
96
+ return css.endsWith(";") ? css.slice(0, -1) : css;
51
97
  };
52
- var c = (node, splitter = DEFAULT_SPLITTER) => _c(node, splitter);
53
- // src/nnn/createLexer.ts
54
- var ROOT = "root";
55
- var createLexer = (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]];
72
- }
73
- if (pattern.sticky) {
74
- break;
75
- }
76
- pattern.lastIndex = match.index + 1;
77
- }
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);
121
- }
98
+ var c = (node, splitter = DEFAULT_SPLITTER) => cRules(node, splitter, []);
99
+ // src/h.ts
100
+ var SVG_NS = "http://www.w3.org/2000/svg";
101
+ var NAMESPACES = {
102
+ xlink: "http://www.w3.org/1999/xlink",
103
+ xml: "http://www.w3.org/XML/1998/namespace",
104
+ xmlns: "http://www.w3.org/2000/xmlns/"
105
+ };
106
+ var isPlainObject = (value) => {
107
+ if (typeof value !== "object" || value == null) {
108
+ return false;
109
+ }
110
+ const prototype = Object.getPrototypeOf(value);
111
+ return prototype === Object.prototype || prototype == null;
112
+ };
113
+ var setAttribute = (element, name, value) => {
114
+ if (value == null) {
115
+ return;
116
+ }
117
+ const indexOfColon = name.indexOf(":");
118
+ const namespace = indexOfColon < 0 ? undefined : NAMESPACES[name.slice(0, indexOfColon)];
119
+ if (namespace == null) {
120
+ if (value === false) {
121
+ element.removeAttribute(name);
122
+ } else {
123
+ element.setAttribute(name, value === true ? "" : String(value));
122
124
  }
123
- return result;
124
- };
125
+ } else if (value === false) {
126
+ element.removeAttributeNS(namespace, name.slice(indexOfColon + 1));
127
+ } else {
128
+ element.setAttributeNS(namespace, name, value === true ? "" : String(value));
129
+ }
125
130
  };
126
- // src/nnn/h.ts
127
- var XLINK_NS = "http://www.w3.org/1999/xlink";
128
- var _h = (createElement, tagOrNode, ...args) => {
131
+ var hyperscript = (createElement, tagOrNode, ...args) => {
129
132
  const node = typeof tagOrNode === "string" ? createElement(tagOrNode) : tagOrNode;
130
- args.forEach((arg) => {
131
- let child = null;
133
+ for (const arg of args) {
132
134
  if (arg instanceof Node) {
133
- child = arg;
135
+ node.appendChild(arg);
134
136
  } else if (Array.isArray(arg)) {
135
- child = _h(createElement, ...arg);
137
+ node.appendChild(hyperscript(createElement, ...arg));
136
138
  } else if (typeof arg === "string" || typeof arg === "number") {
137
- child = document.createTextNode(arg);
138
- } else if (typeof arg === "object" && arg != null) {
139
+ node.appendChild(document.createTextNode(String(arg)));
140
+ } else if (arg != null) {
139
141
  for (const name in arg) {
140
142
  const value = arg[name];
141
143
  if (name[0] === "$") {
142
144
  const name1 = name.slice(1);
143
- if (typeof value === "object" && value != null && !Array.isArray(value)) {
145
+ if (isPlainObject(value)) {
144
146
  Object.assign(node[name1] ??= {}, value);
145
147
  } else {
146
148
  node[name1] = value;
147
149
  }
148
150
  } else if (node instanceof Element) {
149
- const indexOfColon = name.indexOf(":");
150
- if (indexOfColon >= 0) {
151
- const nsKey = name.slice(0, indexOfColon);
152
- if (nsKey === "xlink") {
153
- const basename = name.slice(indexOfColon + 1);
154
- if (value === true) {
155
- node.setAttributeNS(XLINK_NS, basename, "");
156
- } else if (value === false) {
157
- node.removeAttributeNS(XLINK_NS, basename);
158
- } else {
159
- node.setAttributeNS(XLINK_NS, basename, "" + value);
160
- }
161
- }
162
- } else {
163
- if (value === true) {
164
- node.setAttribute(name, "");
165
- } else if (value === false) {
166
- node.removeAttribute(name);
167
- } else {
168
- node.setAttribute(name, "" + value);
169
- }
170
- }
151
+ setAttribute(node, name, value);
171
152
  }
172
153
  }
173
154
  }
174
- if (child != null) {
175
- node.appendChild(child);
176
- }
177
- });
155
+ }
178
156
  return node;
179
157
  };
180
- var h = _h.bind(null, (tag) => document.createElement(tag));
181
- var s = _h.bind(null, (tag) => document.createElementNS("http://www.w3.org/2000/svg", tag));
182
- var svgUse = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
183
- // src/nnn/monokai.ts
184
- var monokai = {
185
- ":root$$monokai": {
186
- "--": {
187
- bg: "#faf4f2",
188
- fg: "#29242a",
189
- comment: "#918c8e",
190
- identifier: {
191
- 1: "#7058be",
192
- 2: "#269d69",
193
- 3: "#1c8ca8",
194
- 4: "#29242a"
195
- },
196
- keyword: {
197
- 1: "#e14775",
198
- 2: "#7058be",
199
- 3: "#1c8ca8"
200
- },
201
- number: "#7058be",
202
- operator: "#e14775",
203
- punctuation: "#918c8e",
204
- regexp: "#e16032",
205
- string: "#cc7a0a"
206
- }
207
- },
208
- pre$$monokai: {
209
- "background-color": "var(--bg)",
210
- color: "var(--fg)",
211
- margin: 0,
212
- padding: "1em",
213
- overflow: "visible",
214
- " code": {
215
- "font-family": '"Source Code Pro"',
216
- padding: 0
217
- }
218
- },
219
- "code>span.$$monokai": {
220
- bg: { color: "var(--bg)" },
221
- fg: { color: "var(--fg)" },
222
- comment: { color: "var(--comment)" },
223
- identifier: {
224
- 1: { color: "var(--identifier1)" },
225
- 2: { color: "var(--identifier2)" },
226
- 3: { color: "var(--identifier3)" },
227
- 4: { color: "var(--identifier4)" }
228
- },
229
- keyword: {
230
- 1: { color: "var(--keyword1)" },
231
- 2: { color: "var(--keyword2)" },
232
- 3: { color: "var(--keyword3)" }
233
- },
234
- number: { color: "var(--number)" },
235
- operator: { color: "var(--operator)" },
236
- punctuation: { color: "var(--punctuation)" },
237
- regexp: { color: "var(--regexp)" },
238
- string: { color: "var(--string)" }
239
- },
240
- "@media only screen and (prefers-color-scheme: dark)$$monokai": {
241
- ":root": {
242
- "--": {
243
- bg: "#2d2a2e",
244
- fg: "#fcfcfa",
245
- comment: "#727072",
246
- identifier: {
247
- 1: "#ae81ff",
248
- 2: "#a9dc76",
249
- 3: "#66d9ef",
250
- 4: "#fcfcfa"
251
- },
252
- keyword: {
253
- 1: "#ff6188",
254
- 2: "#ae81ff",
255
- 3: "#66d9ef"
256
- },
257
- number: "#ae81ff",
258
- operator: "#ff6188",
259
- punctuation: "#727072",
260
- regexp: "#fc9867",
261
- string: "#ffd866"
262
- }
263
- }
264
- },
265
- "@media print$$monokai": {
266
- pre: {
267
- "background-color": "white"
268
- },
269
- ":root": {
270
- "--bg": "white"
158
+ var h = hyperscript.bind(null, (tag) => document.createElement(tag));
159
+ var s = hyperscript.bind(null, (tag) => document.createElementNS(SVG_NS, tag));
160
+ var svgUse = (id, ...args) => s("svg", ["use", { href: "#" + id }], ...args);
161
+ // src/rwd.ts
162
+ var isPositiveInteger = (value) => Number.isInteger(value) && value > 0;
163
+ var rwd = (root, selector, cellWidthPx, cellHeightPx, ...specs) => {
164
+ if (!(cellWidthPx > 0 && cellHeightPx > 0 && Number.isFinite(cellWidthPx) && Number.isFinite(cellHeightPx))) {
165
+ throw new RangeError(`rwd: cell size must be positive: ${cellWidthPx}×${cellHeightPx}`);
166
+ }
167
+ for (const [columns, width = 1, height = 1] of specs) {
168
+ if (!isPositiveInteger(columns) || !isPositiveInteger(width) || !isPositiveInteger(height) || width > columns) {
169
+ throw new RangeError(`rwd: invalid spec: [${columns}, ${width}, ${height}]`);
271
170
  }
272
171
  }
273
- };
274
- // src/nnn/nanolightTs.ts
275
- var COMMENT = "comment";
276
- var IDENTIFIER1 = "identifier1";
277
- var IDENTIFIER2 = "identifier2";
278
- var IDENTIFIER3 = "identifier3";
279
- var IDENTIFIER4 = "identifier4";
280
- var KEYWORD1 = "keyword1";
281
- var KEYWORD2 = "keyword2";
282
- var KEYWORD3 = "keyword3";
283
- var NUMBER = "number";
284
- var OPERATOR = "operator";
285
- var PUNCTUATION = "punctuation";
286
- var REGEXP = "regexp";
287
- var STRING = "string";
288
- var ROOT2 = "root";
289
- var TEMPLATE = "template";
290
- var REGEXP_BODY = "regexpBody";
291
- var REGEXP_FLAGS = "regexpFlags";
292
- var REGEXP_GROUP_NAME = "regexpGroupName";
293
- var REGEXP_SET = "regexpSet";
294
- var REGEXP_SET_NEGATION = "regexpSetNegation";
295
- var nanolightTs = /* @__PURE__ */ createLexer((chunk, name) => name != null ? ["span", { class: name }, chunk] : chunk, [COMMENT, /^#!.*/], [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 }], [
296
- REGEXP,
297
- /(?<=(?:^|[!%&(*,:;<=>?[^{|}~]|(?<!\+)\+|(?<!-)-|(?<!\.)\b(?:await|case|delete|do|else|in|instanceof|new|of|return|throw|typeof|void|yield))\s*)\/(?![*/])(?=(?:[^\\/[\n]|\\.|\[(?:[^\\\]\n]|\\.)*\])+\/)=?/,
298
- { push: REGEXP_BODY }
299
- ], [REGEXP, /\/(?=[dgimsuvy])/y, { in: REGEXP_BODY, pop: true, push: REGEXP_FLAGS }], [REGEXP, /\/(?![dgimsuvy])/y, { in: REGEXP_BODY, pop: true }], [KEYWORD1, /[dgimsuvy]+/y, { in: REGEXP_FLAGS, pop: true }], [IDENTIFIER2, /\\[1-9]\d*|\\k<[\p{L}_$][\p{L}\d_$]*>/uy, { in: REGEXP_BODY }], [KEYWORD1, /\\[bB]/y, { in: REGEXP_BODY }], [KEYWORD3, /\\[dDsSwW]|\\[pP]\{[\w=]*\}/y, { in: [REGEXP_BODY, REGEXP_SET] }], [KEYWORD2, /\\(?:c[A-Za-z]|x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|.)/uy, { in: [REGEXP_BODY, REGEXP_SET] }], [KEYWORD1, /[$^]/y, { in: REGEXP_BODY }], [KEYWORD3, ".", { in: REGEXP_BODY }], [OPERATOR, /(?:[*+?]|\{\d+(?:,\d*)?\})\??/y, { in: REGEXP_BODY }], [OPERATOR, "|", { in: REGEXP_BODY }], [PUNCTUATION, /\((?:\?(?:[:=!]|<[=!]))?/y, { in: REGEXP_BODY }], [PUNCTUATION, /\(\?<(?=[\p{L}_$][\p{L}\d_$]*>)/uy, { in: REGEXP_BODY, push: REGEXP_GROUP_NAME }], [IDENTIFIER2, /[\p{L}_$][\p{L}\d_$]*/uy, { in: REGEXP_GROUP_NAME }], [PUNCTUATION, ">", { in: REGEXP_GROUP_NAME, pop: true }], [PUNCTUATION, ")", { in: REGEXP_BODY }], [PUNCTUATION, /\[(?!\^)/y, { in: REGEXP_BODY, push: REGEXP_SET }], [PUNCTUATION, /\[(?=\^)/y, { in: REGEXP_BODY, push: REGEXP_SET_NEGATION }], [OPERATOR, "^", { in: REGEXP_SET_NEGATION, pop: true, push: REGEXP_SET }], [OPERATOR, /(?<!(?<!\\)\[\^?)-(?!\])/y, { in: REGEXP_SET }], [PUNCTUATION, "]", { in: REGEXP_SET, pop: true }], [REGEXP, /[^\\/[()|?*+{^$.\n]+/uy, { in: REGEXP_BODY }], [REGEXP, /[^\\\]\-\n]+/uy, { in: REGEXP_SET }], [REGEXP, /[^\n]/uy, { in: [REGEXP_BODY, REGEXP_SET] }], [NUMBER, /0b[01_]+n?/i], [NUMBER, /0o[0-7_]+n?/i], [NUMBER, /0x[\da-f_]+n?/i], [NUMBER, /(?:\d[\d_]*(?:\.[\d_]+)?|\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?n?/i], [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, /\?\.(?!\d)/], [PUNCTUATION, "["], [PUNCTUATION, "]"], [PUNCTUATION, "{", { push: ROOT2 }], [PUNCTUATION, "}", { pop: true }], [IDENTIFIER2, /(?<=(?<!\.)\.)\p{Ll}[\p{L}\d_$]*(?=[(`])/u], [IDENTIFIER4, /(?<=(?<!\.)\.)\p{Ll}[\p{L}\d_$]*/u], [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"], [IDENTIFIER2, /@[\p{L}_$][\p{L}\d_$]*/u], [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]);
300
- // src/nnn/rwd.ts
301
- var rwd = (root, selector, cellWidthPx, cellHeightPx, ...specs) => {
302
172
  const main = root[selector] ??= {};
303
173
  main["box-sizing"] = "border-box";
304
174
  main.display = "block";
@@ -306,27 +176,22 @@ var rwd = (root, selector, cellWidthPx, cellHeightPx, ...specs) => {
306
176
  main.width = "100%";
307
177
  main.height = `${cellHeightPx}px`;
308
178
  specs.sort(([a], [b]) => a - b);
309
- for (let [maxWidth, width, height] of specs) {
310
- const atRule = `@media(min-width:${cellWidthPx * maxWidth}px)`;
311
- const node = maxWidth === 1 ? main : (root[atRule] ??= {})[selector] ??= {};
312
- width ??= 1;
313
- height ??= 1;
179
+ for (const [columns, width = 1, height = 1] of specs) {
180
+ const atRule = `@media(min-width:${cellWidthPx * columns}px)`;
181
+ const node = columns === 1 ? main : (root[atRule] ??= {})[selector] ??= {};
314
182
  let gcd = 100 * width;
315
- let tmp = maxWidth;
183
+ let tmp = columns;
316
184
  while (tmp > 0) {
317
185
  [gcd, tmp] = [tmp, gcd % tmp];
318
186
  }
319
187
  const widthOverGcd = 100 * width / gcd;
320
- node.width = maxWidth === gcd ? `${widthOverGcd}%` : `calc(${widthOverGcd}% / ${maxWidth / gcd})`;
188
+ node.width = columns === gcd ? `${widthOverGcd}%` : `calc(${widthOverGcd}% / ${columns / gcd})`;
321
189
  node.height = `${cellHeightPx * height}px`;
322
190
  }
323
191
  };
324
192
  export {
325
193
  c,
326
- createLexer,
327
194
  h,
328
- monokai,
329
- nanolightTs,
330
195
  rwd,
331
196
  s,
332
197
  svgUse
package/package.json CHANGED
@@ -1,25 +1,29 @@
1
1
  {
2
2
  "name": "@jackens/nnn",
3
- "version": "2026.9.30",
3
+ "version": "2026.11.16",
4
4
  "description": "Jackens’ JavaScript helpers.",
5
5
  "keywords": [
6
6
  "CSS-in-JS",
7
- "highlight",
8
7
  "HyperScript",
9
8
  "JS-to-CSS",
10
- "lexer",
11
- "Monokai",
12
- "nanolight",
13
9
  "nnn",
14
10
  "Responsive Web Design",
15
- "RWD",
16
- "SVG",
17
- "tokenize",
18
- "tokenizer"
11
+ "RWD"
19
12
  ],
20
13
  "license": "MIT",
21
14
  "author": "Jackens",
22
15
  "type": "module",
23
16
  "main": "nnn.js",
24
- "types": "nnn.d.ts"
17
+ "types": "nnn.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./nnn.d.ts",
21
+ "default": "./nnn.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "nnn.d.ts",
26
+ "nnn.js"
27
+ ],
28
+ "sideEffects": false
25
29
  }