@pikacss/integration 0.0.32 → 0.0.34
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/dist/index.cjs +332 -217
- package/dist/index.d.cts +32 -25
- package/dist/index.d.mts +32 -25
- package/dist/index.mjs +334 -218
- package/package.json +15 -8
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { statSync } from "node:fs";
|
|
2
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
-
import { createEngine, defineEnginePlugin,
|
|
4
|
-
import {
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { createEngine, defineEnginePlugin, log } from "@pikacss/core";
|
|
4
|
+
import { computed, signal } from "alien-signals";
|
|
5
|
+
import { globbyStream } from "globby";
|
|
5
6
|
import { klona } from "klona";
|
|
6
7
|
import { isPackageExists } from "local-pkg";
|
|
7
8
|
import MagicString from "magic-string";
|
|
8
|
-
import micromatch from "micromatch";
|
|
9
9
|
import { dirname, isAbsolute, join, relative, resolve } from "pathe";
|
|
10
|
-
import { debounce } from "perfect-debounce";
|
|
11
10
|
|
|
12
11
|
export * from "@pikacss/core"
|
|
13
12
|
|
|
@@ -15,6 +14,7 @@ export * from "@pikacss/core"
|
|
|
15
14
|
function createEventHook() {
|
|
16
15
|
const listeners = /* @__PURE__ */ new Set();
|
|
17
16
|
function trigger(payload) {
|
|
17
|
+
if (listeners.size === 0) return;
|
|
18
18
|
listeners.forEach((listener) => listener(payload));
|
|
19
19
|
}
|
|
20
20
|
function off(listener) {
|
|
@@ -103,9 +103,11 @@ function generateVueDeclaration(ctx) {
|
|
|
103
103
|
];
|
|
104
104
|
}
|
|
105
105
|
async function generateOverloadContent(ctx) {
|
|
106
|
+
log.debug("Generating TypeScript overload content");
|
|
106
107
|
const paramsLines = [];
|
|
107
108
|
const fnsLines = [];
|
|
108
109
|
const usages = [...ctx.usages.values()].flat();
|
|
110
|
+
log.debug(`Processing ${usages.length} style usages for overload generation`);
|
|
109
111
|
for (let i = 0; i < usages.length; i++) {
|
|
110
112
|
const usage = usages[i];
|
|
111
113
|
try {
|
|
@@ -139,6 +141,7 @@ async function generateOverloadContent(ctx) {
|
|
|
139
141
|
];
|
|
140
142
|
}
|
|
141
143
|
async function generateTsCodegenContent(ctx) {
|
|
144
|
+
log.debug("Generating TypeScript code generation content");
|
|
142
145
|
const lines = [
|
|
143
146
|
`// Auto-generated by ${ctx.currentPackageName}`,
|
|
144
147
|
`import type { CSSProperty, CSSSelectors, DefineAutocomplete, Properties, StyleDefinition, StyleItem } from \'${ctx.currentPackageName}\'`,
|
|
@@ -160,257 +163,370 @@ async function generateTsCodegenContent(ctx) {
|
|
|
160
163
|
lines.push(...generateGlobalDeclaration(ctx));
|
|
161
164
|
lines.push(...generateVueDeclaration(ctx));
|
|
162
165
|
lines.push(...await generateOverloadContent(ctx));
|
|
166
|
+
log.debug("TypeScript code generation content completed");
|
|
163
167
|
return lines.join("\n");
|
|
164
168
|
}
|
|
165
169
|
|
|
166
170
|
//#endregion
|
|
167
171
|
//#region src/ctx.ts
|
|
168
|
-
function
|
|
169
|
-
const
|
|
170
|
-
let matched = RE.exec(code);
|
|
171
|
-
while (matched != null) {
|
|
172
|
-
const fnName = matched[1];
|
|
173
|
-
const start = matched.index;
|
|
174
|
-
let end = start + fnName.length;
|
|
175
|
-
let depth = 1;
|
|
176
|
-
let inString = false;
|
|
177
|
-
while (depth > 0) {
|
|
178
|
-
end++;
|
|
179
|
-
if (inString === false && code[end] === "(") depth++;
|
|
180
|
-
else if (inString === false && code[end] === ")") depth--;
|
|
181
|
-
else if (inString === false && (code[end] === "'" || code[end] === "\"")) inString = code[end];
|
|
182
|
-
else if (inString === code[end]) inString = false;
|
|
183
|
-
}
|
|
184
|
-
const snippet = code.slice(start, end + 1);
|
|
185
|
-
result.push({
|
|
186
|
-
fnName,
|
|
187
|
-
start,
|
|
188
|
-
end,
|
|
189
|
-
snippet
|
|
190
|
-
});
|
|
191
|
-
matched = RE.exec(code);
|
|
192
|
-
}
|
|
193
|
-
return result;
|
|
194
|
-
}
|
|
195
|
-
const ESCAPE_REPLACE_RE = /[.*+?^${}()|[\]\\/]/g;
|
|
196
|
-
function createFnUtils(fnName) {
|
|
197
|
-
const available = {
|
|
198
|
-
normal: new Set([fnName]),
|
|
199
|
-
forceString: new Set([
|
|
200
|
-
`${fnName}.str`,
|
|
201
|
-
`${fnName}['str']`,
|
|
202
|
-
`${fnName}["str"]`,
|
|
203
|
-
`${fnName}[\`str\`]`
|
|
204
|
-
]),
|
|
205
|
-
forceArray: new Set([
|
|
206
|
-
`${fnName}.arr`,
|
|
207
|
-
`${fnName}['arr']`,
|
|
208
|
-
`${fnName}["arr"]`,
|
|
209
|
-
`${fnName}[\`arr\`]`
|
|
210
|
-
]),
|
|
211
|
-
forceInline: new Set([
|
|
212
|
-
`${fnName}.inl`,
|
|
213
|
-
`${fnName}['inl']`,
|
|
214
|
-
`${fnName}["inl"]`,
|
|
215
|
-
`${fnName}[\`inl\`]`
|
|
216
|
-
]),
|
|
217
|
-
normalPreview: new Set([`${fnName}p`]),
|
|
218
|
-
forceStringPreview: new Set([
|
|
219
|
-
`${fnName}p.str`,
|
|
220
|
-
`${fnName}p['str']`,
|
|
221
|
-
`${fnName}p["str"]`,
|
|
222
|
-
`${fnName}p[\`str\`]`
|
|
223
|
-
]),
|
|
224
|
-
forceArrayPreview: new Set([
|
|
225
|
-
`${fnName}p.arr`,
|
|
226
|
-
`${fnName}p['arr']`,
|
|
227
|
-
`${fnName}p["arr"]`,
|
|
228
|
-
`${fnName}p[\`arr\`]`
|
|
229
|
-
]),
|
|
230
|
-
forceInlinePreview: new Set([
|
|
231
|
-
`${fnName}p.inl`,
|
|
232
|
-
`${fnName}p['inl']`,
|
|
233
|
-
`${fnName}p["inl"]`,
|
|
234
|
-
`${fnName}p[\`inl\`]`
|
|
235
|
-
])
|
|
236
|
-
};
|
|
172
|
+
function usePaths({ cwd: _cwd, cssCodegen, tsCodegen }) {
|
|
173
|
+
const cwd = signal(_cwd);
|
|
237
174
|
return {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
isForceInline: (fnName$1) => available.forceInline.has(fnName$1) || available.forceInlinePreview.has(fnName$1),
|
|
242
|
-
isPreview: (fnName$1) => available.normalPreview.has(fnName$1) || available.forceStringPreview.has(fnName$1) || available.forceArrayPreview.has(fnName$1) || available.forceInlinePreview.has(fnName$1),
|
|
243
|
-
RE: new RegExp(`\\b(${Object.values(available).flatMap((s) => [...s].map((f) => `(${f.replace(ESCAPE_REPLACE_RE, "\\$&")})`)).join("|")})\\(`, "g")
|
|
175
|
+
cwd,
|
|
176
|
+
cssCodegenFilepath: computed(() => isAbsolute(cssCodegen) ? resolve(cssCodegen) : join(cwd(), cssCodegen)),
|
|
177
|
+
tsCodegenFilepath: computed(() => tsCodegen === false ? null : isAbsolute(tsCodegen) ? resolve(tsCodegen) : join(cwd(), tsCodegen))
|
|
244
178
|
};
|
|
245
179
|
}
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
180
|
+
function useConfig({ cwd, tsCodegenFilepath, currentPackageName, autoCreateConfig, configOrPath, scan }) {
|
|
181
|
+
const RE_VALID_CONFIG_EXT = /\.(?:js|cjs|mjs|ts|cts|mts)$/;
|
|
182
|
+
const specificConfigPath = computed(() => {
|
|
183
|
+
if (typeof configOrPath === "string" && RE_VALID_CONFIG_EXT.test(configOrPath)) return isAbsolute(configOrPath) ? configOrPath : join(cwd(), configOrPath);
|
|
184
|
+
return null;
|
|
250
185
|
});
|
|
251
|
-
|
|
252
|
-
|
|
186
|
+
async function findFirstExistingConfigPath() {
|
|
187
|
+
const _cwd = cwd();
|
|
188
|
+
const _specificConfigPath = specificConfigPath();
|
|
189
|
+
if (_specificConfigPath != null && statSync(_specificConfigPath, { throwIfNoEntry: false })?.isFile()) return _specificConfigPath;
|
|
190
|
+
const stream = globbyStream("**/{pika,pikacss}.config.{js,cjs,mjs,ts,cts,mts}", { ignore: scan.exclude });
|
|
191
|
+
for await (const entry of stream) return join(_cwd, entry);
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
253
194
|
const inlineConfig = typeof configOrPath === "object" ? configOrPath : null;
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
"mts"
|
|
262
|
-
].map((ext) => `${name}.config.${ext}`)).map((name) => join(cwd, name))];
|
|
263
|
-
const targetREs = target.map((t) => micromatch.makeRe(t));
|
|
264
|
-
const needToTransform = (id) => targetREs.some((re) => re.test(id));
|
|
265
|
-
const ctx = {
|
|
266
|
-
cwd,
|
|
267
|
-
currentPackageName,
|
|
268
|
-
fnName,
|
|
269
|
-
fnUtils: createFnUtils(fnName),
|
|
270
|
-
transformedFormat,
|
|
271
|
-
devCssFilepath,
|
|
272
|
-
tsCodegenFilepath,
|
|
273
|
-
hasVue: isPackageExists("vue", { paths: [cwd] }),
|
|
274
|
-
usages: /* @__PURE__ */ new Map(),
|
|
275
|
-
hooks: {
|
|
276
|
-
styleUpdated: createEventHook(),
|
|
277
|
-
tsCodegenUpdated: createEventHook()
|
|
278
|
-
},
|
|
279
|
-
loadConfig: async () => {
|
|
280
|
-
if (inlineConfig != null) return {
|
|
281
|
-
config: klona(inlineConfig),
|
|
282
|
-
file: null
|
|
283
|
-
};
|
|
284
|
-
let resolvedConfigPath = configSources.find((path) => {
|
|
285
|
-
const stat = statSync(path, { throwIfNoEntry: false });
|
|
286
|
-
return stat != null && stat.isFile();
|
|
287
|
-
});
|
|
288
|
-
if (resolvedConfigPath == null) {
|
|
289
|
-
if (autoCreateConfig === false) return {
|
|
290
|
-
config: null,
|
|
195
|
+
async function _loadConfig() {
|
|
196
|
+
try {
|
|
197
|
+
log.debug("Loading engine config");
|
|
198
|
+
if (inlineConfig != null) {
|
|
199
|
+
log.debug("Using inline config");
|
|
200
|
+
return {
|
|
201
|
+
config: klona(inlineConfig),
|
|
291
202
|
file: null
|
|
292
203
|
};
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
204
|
+
}
|
|
205
|
+
let resolvedConfigPath$1 = await findFirstExistingConfigPath();
|
|
206
|
+
const _cwd = cwd();
|
|
207
|
+
if (resolvedConfigPath$1 == null) {
|
|
208
|
+
if (autoCreateConfig === false) {
|
|
209
|
+
log.warn("Config file not found and autoCreateConfig is false");
|
|
210
|
+
return {
|
|
211
|
+
config: null,
|
|
212
|
+
file: null
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
resolvedConfigPath$1 = join(_cwd, specificConfigPath() ?? "pika.config.js");
|
|
216
|
+
await mkdir(dirname(resolvedConfigPath$1), { recursive: true }).catch(() => {});
|
|
217
|
+
const _tsCodegenFilepath = tsCodegenFilepath();
|
|
218
|
+
const relativeTsCodegenFilepath = _tsCodegenFilepath == null ? null : `./${relative(dirname(resolvedConfigPath$1), _tsCodegenFilepath)}`;
|
|
219
|
+
await writeFile(resolvedConfigPath$1, [
|
|
220
|
+
...relativeTsCodegenFilepath == null ? [] : [`/// <reference path="${relativeTsCodegenFilepath}" />`],
|
|
297
221
|
`import { defineEngineConfig } from '${currentPackageName}'`,
|
|
298
|
-
...relativeTsCodegenFilepath == null ? [] : [`/** @type {import('${relativeTsCodegenFilepath}')} */`],
|
|
299
222
|
"",
|
|
300
223
|
"export default defineEngineConfig({",
|
|
301
224
|
" // Add your PikaCSS engine config here",
|
|
302
225
|
"})"
|
|
303
226
|
].join("\n"));
|
|
304
227
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
228
|
+
log.info(`Using config file: ${resolvedConfigPath$1}`);
|
|
229
|
+
const { createJiti } = await import("jiti");
|
|
230
|
+
const jiti = createJiti(import.meta.url, { interopDefault: true });
|
|
231
|
+
const content = await readFile(resolvedConfigPath$1, "utf-8");
|
|
232
|
+
const config = (await jiti.evalModule(content, {
|
|
233
|
+
id: resolvedConfigPath$1,
|
|
234
|
+
forceTranspile: true
|
|
235
|
+
})).default;
|
|
309
236
|
return {
|
|
310
237
|
config: klona(config),
|
|
311
|
-
file: resolvedConfigPath
|
|
238
|
+
file: resolvedConfigPath$1
|
|
312
239
|
};
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
240
|
+
} catch (error) {
|
|
241
|
+
log.error(`Failed to load config file: ${error.message}`, error);
|
|
242
|
+
return {
|
|
243
|
+
config: null,
|
|
244
|
+
file: null
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const resolvedConfig = signal(inlineConfig);
|
|
249
|
+
const resolvedConfigPath = signal(null);
|
|
250
|
+
async function loadConfig() {
|
|
251
|
+
const result = await _loadConfig();
|
|
252
|
+
resolvedConfig(result.config);
|
|
253
|
+
resolvedConfigPath(result.file);
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
resolvedConfig,
|
|
258
|
+
resolvedConfigPath,
|
|
259
|
+
loadConfig
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function useTransform({ cwd, scan, fnName, usages, engine, transformedFormat, triggerStyleUpdated, triggerTsCodegenUpdated }) {
|
|
263
|
+
const ESCAPE_REPLACE_RE = /[.*+?^${}()|[\]\\/]/g;
|
|
264
|
+
function createFnUtils(fnName$1) {
|
|
265
|
+
const available = {
|
|
266
|
+
normal: new Set([fnName$1]),
|
|
267
|
+
forceString: new Set([
|
|
268
|
+
`${fnName$1}.str`,
|
|
269
|
+
`${fnName$1}['str']`,
|
|
270
|
+
`${fnName$1}["str"]`,
|
|
271
|
+
`${fnName$1}[\`str\`]`
|
|
272
|
+
]),
|
|
273
|
+
forceArray: new Set([
|
|
274
|
+
`${fnName$1}.arr`,
|
|
275
|
+
`${fnName$1}['arr']`,
|
|
276
|
+
`${fnName$1}["arr"]`,
|
|
277
|
+
`${fnName$1}[\`arr\`]`
|
|
278
|
+
]),
|
|
279
|
+
forceInline: new Set([
|
|
280
|
+
`${fnName$1}.inl`,
|
|
281
|
+
`${fnName$1}['inl']`,
|
|
282
|
+
`${fnName$1}["inl"]`,
|
|
283
|
+
`${fnName$1}[\`inl\`]`
|
|
284
|
+
]),
|
|
285
|
+
normalPreview: new Set([`${fnName$1}p`]),
|
|
286
|
+
forceStringPreview: new Set([
|
|
287
|
+
`${fnName$1}p.str`,
|
|
288
|
+
`${fnName$1}p['str']`,
|
|
289
|
+
`${fnName$1}p["str"]`,
|
|
290
|
+
`${fnName$1}p[\`str\`]`
|
|
291
|
+
]),
|
|
292
|
+
forceArrayPreview: new Set([
|
|
293
|
+
`${fnName$1}p.arr`,
|
|
294
|
+
`${fnName$1}p['arr']`,
|
|
295
|
+
`${fnName$1}p["arr"]`,
|
|
296
|
+
`${fnName$1}p[\`arr\`]`
|
|
297
|
+
]),
|
|
298
|
+
forceInlinePreview: new Set([
|
|
299
|
+
`${fnName$1}p.inl`,
|
|
300
|
+
`${fnName$1}p['inl']`,
|
|
301
|
+
`${fnName$1}p["inl"]`,
|
|
302
|
+
`${fnName$1}p[\`inl\`]`
|
|
303
|
+
])
|
|
304
|
+
};
|
|
305
|
+
return {
|
|
306
|
+
isNormal: (fnName$2) => available.normal.has(fnName$2) || available.normalPreview.has(fnName$2),
|
|
307
|
+
isForceString: (fnName$2) => available.forceString.has(fnName$2) || available.forceStringPreview.has(fnName$2),
|
|
308
|
+
isForceArray: (fnName$2) => available.forceArray.has(fnName$2) || available.forceArrayPreview.has(fnName$2),
|
|
309
|
+
isForceInline: (fnName$2) => available.forceInline.has(fnName$2) || available.forceInlinePreview.has(fnName$2),
|
|
310
|
+
isPreview: (fnName$2) => available.normalPreview.has(fnName$2) || available.forceStringPreview.has(fnName$2) || available.forceArrayPreview.has(fnName$2) || available.forceInlinePreview.has(fnName$2),
|
|
311
|
+
RE: new RegExp(`\\b(${Object.values(available).flatMap((s) => [...s].map((f) => `(${f.replace(ESCAPE_REPLACE_RE, "\\$&")})`)).join("|")})\\(`, "g")
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
const fnUtils = createFnUtils(fnName);
|
|
315
|
+
function findFunctionCalls(code) {
|
|
316
|
+
const RE = fnUtils.RE;
|
|
317
|
+
const result = [];
|
|
318
|
+
let matched = RE.exec(code);
|
|
319
|
+
while (matched != null) {
|
|
320
|
+
const fnName$1 = matched[1];
|
|
321
|
+
const start = matched.index;
|
|
322
|
+
let end = start + fnName$1.length;
|
|
323
|
+
let depth = 1;
|
|
324
|
+
let inString = false;
|
|
325
|
+
while (depth > 0) {
|
|
326
|
+
end++;
|
|
327
|
+
if (inString === false && code[end] === "(") depth++;
|
|
328
|
+
else if (inString === false && code[end] === ")") depth--;
|
|
329
|
+
else if (inString === false && (code[end] === "'" || code[end] === "\"")) inString = code[end];
|
|
330
|
+
else if (inString === code[end]) inString = false;
|
|
345
331
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
transformed.update(fnCall.start, fnCall.end + 1, transformedContent);
|
|
376
|
-
}
|
|
377
|
-
ctx.usages.set(id, usages);
|
|
378
|
-
ctx.hooks.styleUpdated.trigger();
|
|
379
|
-
ctx.hooks.tsCodegenUpdated.trigger();
|
|
380
|
-
return {
|
|
381
|
-
code: transformed.toString(),
|
|
382
|
-
map: transformed.generateMap({ hires: true })
|
|
332
|
+
const snippet = code.slice(start, end + 1);
|
|
333
|
+
result.push({
|
|
334
|
+
fnName: fnName$1,
|
|
335
|
+
start,
|
|
336
|
+
end,
|
|
337
|
+
snippet
|
|
338
|
+
});
|
|
339
|
+
matched = RE.exec(code);
|
|
340
|
+
}
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
343
|
+
async function transform(code, id) {
|
|
344
|
+
const _engine = engine();
|
|
345
|
+
if (_engine == null) return null;
|
|
346
|
+
try {
|
|
347
|
+
log.debug(`Transforming file: ${id}`);
|
|
348
|
+
usages.delete(id);
|
|
349
|
+
const functionCalls = findFunctionCalls(code);
|
|
350
|
+
if (functionCalls.length === 0) return;
|
|
351
|
+
log.debug(`Found ${functionCalls.length} style function calls in ${id}`);
|
|
352
|
+
const usageList = [];
|
|
353
|
+
const transformed = new MagicString(code);
|
|
354
|
+
for (const fnCall of functionCalls) {
|
|
355
|
+
const argsStr = `[${fnCall.snippet.slice(fnCall.fnName.length + 1, -1)}]`;
|
|
356
|
+
const args = new Function(`return ${argsStr}`)();
|
|
357
|
+
const names = await _engine.use(...args);
|
|
358
|
+
const usage = {
|
|
359
|
+
atomicStyleIds: names,
|
|
360
|
+
params: args
|
|
383
361
|
};
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
362
|
+
usageList.push(usage);
|
|
363
|
+
let transformedContent;
|
|
364
|
+
if (fnUtils.isNormal(fnCall.fnName)) transformedContent = transformedFormat === "array" ? `[${names.map((n) => `'${n}'`).join(", ")}]` : transformedFormat === "string" ? `'${names.join(" ")}'` : names.join(" ");
|
|
365
|
+
else if (fnUtils.isForceString(fnCall.fnName)) transformedContent = `'${names.join(" ")}'`;
|
|
366
|
+
else if (fnUtils.isForceArray(fnCall.fnName)) transformedContent = `[${names.map((n) => `'${n}'`).join(", ")}]`;
|
|
367
|
+
else if (fnUtils.isForceInline(fnCall.fnName)) transformedContent = names.join(" ");
|
|
368
|
+
else throw new Error(`Unexpected function name: ${fnCall.fnName}`);
|
|
369
|
+
transformed.update(fnCall.start, fnCall.end + 1, transformedContent);
|
|
387
370
|
}
|
|
371
|
+
usages.set(id, usageList);
|
|
372
|
+
triggerStyleUpdated();
|
|
373
|
+
triggerTsCodegenUpdated();
|
|
374
|
+
log.debug(`Transformed ${usageList.length} style usages in ${id}`);
|
|
375
|
+
return {
|
|
376
|
+
code: transformed.toString(),
|
|
377
|
+
map: transformed.generateMap({ hires: true })
|
|
378
|
+
};
|
|
379
|
+
} catch (error) {
|
|
380
|
+
log.error(`Failed to transform code (${join(cwd(), id)}): ${error.message}`, error);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
transformFilter: scan,
|
|
386
|
+
transform
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function createCtx(options) {
|
|
390
|
+
const { cwd, cssCodegenFilepath, tsCodegenFilepath } = usePaths(options);
|
|
391
|
+
const { resolvedConfig, resolvedConfigPath, loadConfig } = useConfig({
|
|
392
|
+
...options,
|
|
393
|
+
cwd,
|
|
394
|
+
tsCodegenFilepath
|
|
395
|
+
});
|
|
396
|
+
const usages = /* @__PURE__ */ new Map();
|
|
397
|
+
const engine = signal(null);
|
|
398
|
+
const hooks = {
|
|
399
|
+
styleUpdated: createEventHook(),
|
|
400
|
+
tsCodegenUpdated: createEventHook()
|
|
401
|
+
};
|
|
402
|
+
const { transformFilter, transform } = useTransform({
|
|
403
|
+
...options,
|
|
404
|
+
cwd,
|
|
405
|
+
usages,
|
|
406
|
+
engine,
|
|
407
|
+
triggerStyleUpdated: () => hooks.styleUpdated.trigger(),
|
|
408
|
+
triggerTsCodegenUpdated: () => hooks.tsCodegenUpdated.trigger()
|
|
409
|
+
});
|
|
410
|
+
const ctx = {
|
|
411
|
+
currentPackageName: options.currentPackageName,
|
|
412
|
+
fnName: options.fnName,
|
|
413
|
+
transformedFormat: options.transformedFormat,
|
|
414
|
+
get cwd() {
|
|
415
|
+
return cwd();
|
|
416
|
+
},
|
|
417
|
+
set cwd(v) {
|
|
418
|
+
cwd(v);
|
|
388
419
|
},
|
|
389
|
-
|
|
390
|
-
|
|
420
|
+
get cssCodegenFilepath() {
|
|
421
|
+
return cssCodegenFilepath();
|
|
422
|
+
},
|
|
423
|
+
get tsCodegenFilepath() {
|
|
424
|
+
return tsCodegenFilepath();
|
|
425
|
+
},
|
|
426
|
+
get hasVue() {
|
|
427
|
+
return isPackageExists("vue", { paths: [cwd()] });
|
|
428
|
+
},
|
|
429
|
+
get resolvedConfig() {
|
|
430
|
+
return resolvedConfig();
|
|
431
|
+
},
|
|
432
|
+
get resolvedConfigPath() {
|
|
433
|
+
return resolvedConfigPath();
|
|
434
|
+
},
|
|
435
|
+
loadConfig,
|
|
436
|
+
usages,
|
|
437
|
+
hooks,
|
|
438
|
+
get engine() {
|
|
439
|
+
const _engine = engine();
|
|
440
|
+
if (_engine == null) throw new Error("Engine is not initialized yet");
|
|
441
|
+
return _engine;
|
|
442
|
+
},
|
|
443
|
+
transformFilter,
|
|
444
|
+
transform: async (code, id) => {
|
|
445
|
+
await ctx.setupPromise;
|
|
446
|
+
return transform(code, id);
|
|
447
|
+
},
|
|
448
|
+
getCssCodegenContent: async () => {
|
|
449
|
+
await ctx.setupPromise;
|
|
450
|
+
log.debug("Generating CSS code");
|
|
391
451
|
const atomicStyleIds = [...new Set([...ctx.usages.values()].flatMap((i) => [...new Set(i.flatMap((i$1) => i$1.atomicStyleIds))]))];
|
|
452
|
+
log.debug(`Collecting ${atomicStyleIds.length} atomic style IDs`);
|
|
392
453
|
return [
|
|
393
454
|
`/* Auto-generated by ${ctx.currentPackageName} */`,
|
|
394
|
-
await ctx.engine.renderPreflights(
|
|
395
|
-
await ctx.engine.renderAtomicStyles(
|
|
455
|
+
await ctx.engine.renderPreflights(true),
|
|
456
|
+
await ctx.engine.renderAtomicStyles(true, { atomicStyleIds })
|
|
396
457
|
].join("\n").trim();
|
|
397
458
|
},
|
|
398
459
|
getTsCodegenContent: async () => {
|
|
399
|
-
|
|
460
|
+
await ctx.setupPromise;
|
|
461
|
+
if (ctx.tsCodegenFilepath == null) return null;
|
|
400
462
|
return await generateTsCodegenContent(ctx);
|
|
401
463
|
},
|
|
402
|
-
|
|
403
|
-
|
|
464
|
+
writeCssCodegenFile: async () => {
|
|
465
|
+
await ctx.setupPromise;
|
|
466
|
+
const content = await ctx.getCssCodegenContent();
|
|
404
467
|
if (content == null) return;
|
|
405
|
-
await
|
|
406
|
-
|
|
407
|
-
|
|
468
|
+
await mkdir(dirname(ctx.cssCodegenFilepath), { recursive: true }).catch(() => {});
|
|
469
|
+
log.debug(`Writing CSS code generation file: ${ctx.cssCodegenFilepath}`);
|
|
470
|
+
await writeFile(ctx.cssCodegenFilepath, content);
|
|
471
|
+
},
|
|
472
|
+
writeTsCodegenFile: async () => {
|
|
473
|
+
await ctx.setupPromise;
|
|
474
|
+
if (ctx.tsCodegenFilepath == null) return;
|
|
408
475
|
const content = await ctx.getTsCodegenContent();
|
|
409
|
-
if (
|
|
476
|
+
if (content == null) return;
|
|
477
|
+
await mkdir(dirname(ctx.tsCodegenFilepath), { recursive: true }).catch(() => {});
|
|
478
|
+
log.debug(`Writing TypeScript code generation file: ${ctx.tsCodegenFilepath}`);
|
|
410
479
|
await writeFile(ctx.tsCodegenFilepath, content);
|
|
411
|
-
},
|
|
480
|
+
},
|
|
481
|
+
fullyCssCodegen: async () => {
|
|
482
|
+
await ctx.setupPromise;
|
|
483
|
+
log.debug("Starting full CSS code generation scan");
|
|
484
|
+
const stream = globbyStream(options.scan.include, { ignore: options.scan.exclude });
|
|
485
|
+
let fileCount = 0;
|
|
486
|
+
const _cwd = cwd();
|
|
487
|
+
for await (const entry of stream) {
|
|
488
|
+
const code = await readFile(join(_cwd, entry), "utf-8");
|
|
489
|
+
await ctx.transform(code, entry);
|
|
490
|
+
fileCount++;
|
|
491
|
+
}
|
|
492
|
+
log.debug(`Scanned ${fileCount} files for style collection`);
|
|
493
|
+
await ctx.writeCssCodegenFile();
|
|
494
|
+
},
|
|
495
|
+
setupPromise: null,
|
|
496
|
+
setup: () => {
|
|
497
|
+
ctx.setupPromise = setup().catch((error) => {
|
|
498
|
+
log.error(`Failed to setup integration context: ${error.message}`, error);
|
|
499
|
+
}).then(() => {
|
|
500
|
+
ctx.setupPromise = null;
|
|
501
|
+
});
|
|
502
|
+
return ctx.setupPromise;
|
|
503
|
+
}
|
|
412
504
|
};
|
|
413
|
-
|
|
505
|
+
async function setup() {
|
|
506
|
+
log.debug("Setting up integration context");
|
|
507
|
+
usages.clear();
|
|
508
|
+
hooks.styleUpdated.listeners.clear();
|
|
509
|
+
hooks.tsCodegenUpdated.listeners.clear();
|
|
510
|
+
engine(null);
|
|
511
|
+
await loadConfig();
|
|
512
|
+
const devPlugin = defineEnginePlugin({
|
|
513
|
+
name: "@pikacss/integration:dev",
|
|
514
|
+
preflightUpdated: () => hooks.styleUpdated.trigger(),
|
|
515
|
+
atomicStyleAdded: () => hooks.styleUpdated.trigger(),
|
|
516
|
+
autocompleteConfigUpdated: () => hooks.tsCodegenUpdated.trigger()
|
|
517
|
+
});
|
|
518
|
+
try {
|
|
519
|
+
const config = resolvedConfig() ?? {};
|
|
520
|
+
config.plugins = config.plugins ?? [];
|
|
521
|
+
config.plugins.unshift(devPlugin);
|
|
522
|
+
log.debug("Creating engine with loaded/default config");
|
|
523
|
+
engine(await createEngine(config));
|
|
524
|
+
} catch (error) {
|
|
525
|
+
log.error(`Failed to create engine: ${error.message}. Falling back to default config.`, error);
|
|
526
|
+
engine(await createEngine({ plugins: [devPlugin] }));
|
|
527
|
+
}
|
|
528
|
+
log.debug("Integration context setup successfully");
|
|
529
|
+
}
|
|
414
530
|
return ctx;
|
|
415
531
|
}
|
|
416
532
|
|