@jesscss/plugin-js 2.0.0-alpha.5 → 2.0.0-alpha.7

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,412 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("./index.cjs");
3
+ let node_url = require("node:url");
4
+ //#region src/runtime-worker.ts
5
+ const encoder = new TextEncoder();
6
+ const decoder = new TextDecoder();
7
+ const moduleCache = /* @__PURE__ */ new Map();
8
+ const lessPluginFunctionCache = /* @__PURE__ */ new Map();
9
+ const runtimeApi = Deno.args.includes("--runtime-api=less") ? "less" : "module";
10
+ var Dimension = class {
11
+ type = "Dimension";
12
+ value;
13
+ unit;
14
+ constructor(value, unit = "") {
15
+ this.value = value;
16
+ this.unit = unit;
17
+ }
18
+ valueOf() {
19
+ return this.unit ? `${this.value}${this.unit}` : this.value;
20
+ }
21
+ toString() {
22
+ return String(this.valueOf());
23
+ }
24
+ toCSS() {
25
+ return String(this.valueOf());
26
+ }
27
+ };
28
+ var Color = class {
29
+ type = "Color";
30
+ rgb;
31
+ alpha;
32
+ constructor(rgb, alpha = 1) {
33
+ this.rgb = rgb;
34
+ this.alpha = alpha;
35
+ }
36
+ toCSS() {
37
+ const [r, g, b] = this.rgb;
38
+ return this.alpha === 1 ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${this.alpha})`;
39
+ }
40
+ };
41
+ var Quoted = class {
42
+ type = "Quoted";
43
+ quote;
44
+ value;
45
+ escaped;
46
+ constructor(quote, value, escaped = false) {
47
+ this.quote = quote || "\"";
48
+ this.value = value;
49
+ this.escaped = escaped;
50
+ }
51
+ toCSS() {
52
+ return `${this.escaped ? "~" : ""}${this.quote}${this.value}${this.quote}`;
53
+ }
54
+ };
55
+ var Anonymous = class {
56
+ type = "Anonymous";
57
+ value;
58
+ constructor(value) {
59
+ this.value = value;
60
+ }
61
+ toCSS() {
62
+ return String(this.value);
63
+ }
64
+ };
65
+ var Declaration = class {
66
+ type = "Declaration";
67
+ name;
68
+ value;
69
+ constructor(name, value) {
70
+ this.name = name;
71
+ this.value = value;
72
+ }
73
+ eval() {
74
+ return this;
75
+ }
76
+ toCSS() {
77
+ const v = this.value?.toCSS ? this.value.toCSS() : String(this.value);
78
+ return `${this.name}: ${v}`;
79
+ }
80
+ };
81
+ var DetachedRuleset = class {
82
+ type = "DetachedRuleset";
83
+ ruleset;
84
+ constructor(rules) {
85
+ this.ruleset = { rules };
86
+ }
87
+ eval() {
88
+ return this;
89
+ }
90
+ };
91
+ var Keyword = class extends Anonymous {
92
+ type = "Keyword";
93
+ };
94
+ var Value = class {
95
+ type = "Value";
96
+ value;
97
+ separator;
98
+ constructor(value, separator = ",") {
99
+ this.value = value;
100
+ this.separator = separator;
101
+ }
102
+ toCSS() {
103
+ const sep = this.separator === " " ? " " : `${this.separator} `;
104
+ return this.value.map((item) => item?.toCSS ? item.toCSS() : String(item)).join(sep);
105
+ }
106
+ };
107
+ var Expression = class extends Value {
108
+ type = "Expression";
109
+ constructor(value) {
110
+ super(value, " ");
111
+ }
112
+ };
113
+ const lessFacade = {
114
+ tree: {
115
+ Anonymous,
116
+ Color,
117
+ Declaration,
118
+ DetachedRuleset,
119
+ Dimension,
120
+ Expression,
121
+ Keyword,
122
+ Quoted,
123
+ Value
124
+ },
125
+ dimension(value, unit) {
126
+ return new Dimension(value, unit);
127
+ },
128
+ value(values, separator = ",") {
129
+ return new Value(values, separator);
130
+ },
131
+ anonymous(value) {
132
+ return new Anonymous(value);
133
+ },
134
+ color(rgb, alpha) {
135
+ return new Color(rgb, alpha);
136
+ },
137
+ quoted(quote, value, escaped = false) {
138
+ return new Quoted(quote, value, escaped);
139
+ }
140
+ };
141
+ if (runtimeApi === "less") {
142
+ globalThis.less ??= lessFacade;
143
+ globalThis.Less ??= lessFacade;
144
+ }
145
+ const isBridgeValue = (value) => value && typeof value === "object" && value.__jessBridge === true && typeof value.kind === "string";
146
+ const decodeBridgeValue = (value) => {
147
+ if (!isBridgeValue(value)) return value;
148
+ switch (value.kind) {
149
+ case "scalar": return value.value;
150
+ case "dimension": return new Dimension(value.value, value.unit ?? "");
151
+ case "color": return new Color(value.rgb, value.alpha ?? 1);
152
+ case "quoted": return new Quoted(value.quote ?? "\"", value.value, value.escaped === true);
153
+ case "keyword": return new Keyword(value.value);
154
+ case "anonymous": return new Anonymous(value.value);
155
+ case "list": return new Value((value.items ?? []).map(decodeBridgeValue), value.separator ?? ",");
156
+ case "sequence": return new Expression((value.items ?? []).map(decodeBridgeValue));
157
+ case "detached": return new DetachedRuleset((value.rules ?? []).map((decl) => {
158
+ const decoded = decodeBridgeValue(decl.value);
159
+ const cssText = decoded?.toCSS ? decoded.toCSS() : String(decoded);
160
+ return new Declaration(decl.name, new Anonymous(cssText));
161
+ }));
162
+ default: return value;
163
+ }
164
+ };
165
+ const encodeBridgeChildValue = (value) => {
166
+ const encoded = encodeBridgeValue(value);
167
+ if (isBridgeValue(encoded)) return encoded;
168
+ return {
169
+ __jessBridge: true,
170
+ kind: "scalar",
171
+ value: typeof encoded === "string" || typeof encoded === "number" || typeof encoded === "boolean" ? encoded : String(encoded)
172
+ };
173
+ };
174
+ const encodeBridgeValue = (value) => {
175
+ if (value instanceof Dimension) return {
176
+ __jessBridge: true,
177
+ kind: "dimension",
178
+ value: value.value,
179
+ unit: value.unit || void 0
180
+ };
181
+ if (value instanceof Color) return {
182
+ __jessBridge: true,
183
+ kind: "color",
184
+ rgb: value.rgb,
185
+ alpha: value.alpha
186
+ };
187
+ if (value instanceof Quoted) return {
188
+ __jessBridge: true,
189
+ kind: "quoted",
190
+ value: String(value.value),
191
+ quote: value.quote,
192
+ escaped: value.escaped
193
+ };
194
+ if (value instanceof Keyword) return {
195
+ __jessBridge: true,
196
+ kind: "keyword",
197
+ value: String(value.value)
198
+ };
199
+ if (value instanceof Anonymous) return {
200
+ __jessBridge: true,
201
+ kind: "anonymous",
202
+ value: String(value.value)
203
+ };
204
+ if (value instanceof Value || value instanceof Expression) return {
205
+ __jessBridge: true,
206
+ kind: value instanceof Expression ? "sequence" : "list",
207
+ items: value.value.map(encodeBridgeChildValue),
208
+ separator: value instanceof Expression ? void 0 : value.separator
209
+ };
210
+ return value;
211
+ };
212
+ const isJsonValue = (value) => {
213
+ try {
214
+ JSON.stringify(value);
215
+ return true;
216
+ } catch {
217
+ return false;
218
+ }
219
+ };
220
+ const send = (payload) => {
221
+ Deno.stdout.writeSync(encoder.encode(`${JSON.stringify(payload)}\n`));
222
+ };
223
+ const loadModule = async (modulePath) => {
224
+ let mod = moduleCache.get(modulePath);
225
+ if (!mod) {
226
+ mod = await import((0, node_url.pathToFileURL)(modulePath).href);
227
+ moduleCache.set(modulePath, mod);
228
+ }
229
+ const exports = [];
230
+ for (const [name, value] of Object.entries(mod)) {
231
+ if (typeof value === "function") {
232
+ exports.push({
233
+ name,
234
+ kind: "function"
235
+ });
236
+ continue;
237
+ }
238
+ if (isJsonValue(value)) exports.push({
239
+ name,
240
+ kind: "value",
241
+ value
242
+ });
243
+ }
244
+ return exports;
245
+ };
246
+ const createLegacyLessPluginRuntime = (modulePath) => {
247
+ const localFunctions = /* @__PURE__ */ new Map();
248
+ const functions = {
249
+ add(name, fn) {
250
+ if (typeof name === "string" && typeof fn === "function") localFunctions.set(name.toLowerCase(), fn);
251
+ },
252
+ addMultiple(items) {
253
+ for (const [name, fn] of Object.entries(items ?? {})) this.add(name, fn);
254
+ },
255
+ get(name) {
256
+ return localFunctions.get(String(name).toLowerCase());
257
+ }
258
+ };
259
+ const manager = {
260
+ visitors: [],
261
+ addVisitor(visitor) {
262
+ this.visitors.push(visitor);
263
+ },
264
+ addPreProcessor() {},
265
+ addPostProcessor() {},
266
+ registerPlugin(plugin) {
267
+ installPlugin(plugin);
268
+ }
269
+ };
270
+ const less = {
271
+ ...lessFacade,
272
+ functions: { functionRegistry: functions }
273
+ };
274
+ const installPlugin = (plugin) => {
275
+ if (!plugin) return;
276
+ const candidate = typeof plugin === "function" ? (() => {
277
+ try {
278
+ return new plugin();
279
+ } catch {
280
+ return plugin;
281
+ }
282
+ })() : plugin;
283
+ if (candidate && typeof candidate.install === "function") candidate.install(less, manager, functions);
284
+ };
285
+ const require = (specifier) => {
286
+ throw new Error(`Less @plugin require("${specifier}") is not supported in the Deno sandbox yet.`);
287
+ };
288
+ const registerPlugin = (plugin) => {
289
+ installPlugin(plugin);
290
+ };
291
+ return {
292
+ exports: {},
293
+ functions,
294
+ localFunctions,
295
+ manager,
296
+ require,
297
+ registerPlugin,
298
+ fileInfo: { filename: modulePath }
299
+ };
300
+ };
301
+ const loadLessPlugin = async (modulePath) => {
302
+ let functions = lessPluginFunctionCache.get(modulePath);
303
+ if (functions) return Array.from(functions.keys());
304
+ const source = await Deno.readTextFile(modulePath);
305
+ const runtime = createLegacyLessPluginRuntime(modulePath);
306
+ const module = { exports: runtime.exports };
307
+ new Function("module", "exports", "require", "registerPlugin", "functions", "tree", "less", "fileInfo", "process", source)(module, module.exports, runtime.require, runtime.registerPlugin, runtime.functions, lessFacade.tree, {
308
+ ...lessFacade,
309
+ functions: { functionRegistry: runtime.functions }
310
+ }, runtime.fileInfo, void 0);
311
+ const exported = module.exports?.default ?? module.exports;
312
+ if (typeof exported === "function" || exported && typeof exported.install === "function") runtime.registerPlugin(exported);
313
+ functions = runtime.localFunctions;
314
+ lessPluginFunctionCache.set(modulePath, functions);
315
+ return Array.from(functions.keys());
316
+ };
317
+ const invokeLessPluginFunction = async (modulePath, functionName, args) => {
318
+ let functions = lessPluginFunctionCache.get(modulePath);
319
+ if (!functions) {
320
+ await loadLessPlugin(modulePath);
321
+ functions = lessPluginFunctionCache.get(modulePath);
322
+ }
323
+ const fn = functions?.get(String(functionName).toLowerCase());
324
+ if (typeof fn !== "function") throw new Error(`Less @plugin function "${functionName}" is not registered.`);
325
+ const result = encodeBridgeValue(await fn(...args.map(decodeBridgeValue)));
326
+ if (!isJsonValue(result)) throw new Error(`Result for Less @plugin function "${functionName}" is not JSON-serializable.`);
327
+ return result;
328
+ };
329
+ const invokeExport = async (modulePath, exportName, args) => {
330
+ const mod = moduleCache.get(modulePath) ?? await import((0, node_url.pathToFileURL)(modulePath).href);
331
+ moduleCache.set(modulePath, mod);
332
+ const target = mod?.[exportName];
333
+ if (typeof target !== "function") throw new Error(`Export "${exportName}" is not callable.`);
334
+ const result = encodeBridgeValue(await target(...args.map(decodeBridgeValue)));
335
+ if (!isJsonValue(result)) throw new Error(`Result for "${exportName}" is not JSON-serializable.`);
336
+ return result;
337
+ };
338
+ const handleRequest = async (req) => {
339
+ if (!req || typeof req.id !== "number" || typeof req.type !== "string") return;
340
+ try {
341
+ if (req.type === "load") {
342
+ const exports = await loadModule(req.modulePath);
343
+ send({
344
+ id: req.id,
345
+ ok: true,
346
+ exports
347
+ });
348
+ return;
349
+ }
350
+ if (req.type === "invoke") {
351
+ const value = await invokeExport(req.modulePath, req.exportName, req.args ?? []);
352
+ send({
353
+ id: req.id,
354
+ ok: true,
355
+ value
356
+ });
357
+ return;
358
+ }
359
+ if (req.type === "loadLessPlugin") {
360
+ const functions = await loadLessPlugin(req.modulePath);
361
+ send({
362
+ id: req.id,
363
+ ok: true,
364
+ functions
365
+ });
366
+ return;
367
+ }
368
+ if (req.type === "invokeLessPluginFunction") {
369
+ const value = await invokeLessPluginFunction(req.modulePath, req.functionName, req.args ?? []);
370
+ send({
371
+ id: req.id,
372
+ ok: true,
373
+ value
374
+ });
375
+ return;
376
+ }
377
+ send({
378
+ id: req.id,
379
+ ok: false,
380
+ error: `Unknown request type "${req.type}".`
381
+ });
382
+ } catch (err) {
383
+ send({
384
+ id: req.id,
385
+ ok: false,
386
+ error: err?.message ?? String(err)
387
+ });
388
+ }
389
+ };
390
+ async function main() {
391
+ send({ type: "ready" });
392
+ let buffer = "";
393
+ for await (const chunk of Deno.stdin.readable) {
394
+ buffer += decoder.decode(chunk, { stream: true });
395
+ let idx = buffer.indexOf("\n");
396
+ while (idx >= 0) {
397
+ const line = buffer.slice(0, idx).trim();
398
+ buffer = buffer.slice(idx + 1);
399
+ idx = buffer.indexOf("\n");
400
+ if (!line) continue;
401
+ let req;
402
+ try {
403
+ req = JSON.parse(line);
404
+ } catch {
405
+ continue;
406
+ }
407
+ await handleRequest(req);
408
+ }
409
+ }
410
+ }
411
+ main();
412
+ //#endregion