chaincss 2.1.29 → 2.1.31
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 +397 -65
- package/dist/browser.js +3398 -0
- package/dist/cli/index.js +312 -375
- package/dist/compiler/btt.d.ts +11 -72
- package/dist/compiler/component-generator.d.ts +10 -0
- package/dist/compiler/index.js +198 -331
- package/dist/compiler/recipe.d.ts +35 -0
- package/dist/compiler/scanner.d.ts +5 -0
- package/dist/compiler/timeline.d.ts +29 -0
- package/dist/index.js +253 -397
- package/dist/plugins/vite.js +110 -186
- package/index.html +41 -0
- package/package.json +8 -7
- package/src/browser.ts +9 -0
- package/src/compiler/btt.ts +126 -901
- package/src/compiler/component-generator.ts +87 -0
- package/src/compiler/recipe.ts +145 -0
- package/src/compiler/scanner.ts +46 -0
- package/src/compiler/timeline.ts +128 -0
package/dist/plugins/vite.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import fs6 from "fs";
|
|
3
3
|
import path5 from "path";
|
|
4
4
|
import crypto4 from "crypto";
|
|
5
|
-
import
|
|
5
|
+
import chalk from "chalk";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
7
7
|
|
|
8
8
|
// src/core/constants.ts
|
|
@@ -332,9 +332,7 @@ function formatCSS(css, minify = false) {
|
|
|
332
332
|
var currentLogLevel = process.env.DEBUG ? "debug" : "info";
|
|
333
333
|
|
|
334
334
|
// src/compiler/btt.ts
|
|
335
|
-
import fs2 from "fs";
|
|
336
335
|
import https from "https";
|
|
337
|
-
import chalk from "chalk";
|
|
338
336
|
|
|
339
337
|
// src/compiler/commonProps.ts
|
|
340
338
|
var COMMON_CSS_PROPERTIES = [
|
|
@@ -417,7 +415,7 @@ var COMMON_CSS_PROPERTIES = [
|
|
|
417
415
|
"z-index"
|
|
418
416
|
];
|
|
419
417
|
|
|
420
|
-
// src/compiler/
|
|
418
|
+
// src/compiler/timeline.ts
|
|
421
419
|
var styleHistory = [];
|
|
422
420
|
var styleChanges = [];
|
|
423
421
|
var timelineEnabled = false;
|
|
@@ -428,22 +426,13 @@ function takeSnapshot(selector, styles, source) {
|
|
|
428
426
|
const existing = styleHistory.find((s) => s.selector === selector && s.hash === hash);
|
|
429
427
|
if (existing) return existing.id;
|
|
430
428
|
const id = `snapshot_${currentSnapshotId++}`;
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
selector,
|
|
435
|
-
styles: { ...styles },
|
|
436
|
-
source,
|
|
437
|
-
hash
|
|
438
|
-
};
|
|
439
|
-
styleHistory.push(snapshot);
|
|
440
|
-
const previousSnapshot = styleHistory.slice(-2)[0];
|
|
441
|
-
if (previousSnapshot && previousSnapshot.selector === selector) {
|
|
429
|
+
styleHistory.push({ id, timestamp: Date.now(), selector, styles: { ...styles }, source, hash });
|
|
430
|
+
const previous = styleHistory[styleHistory.length - 2];
|
|
431
|
+
if (previous && previous.selector === selector) {
|
|
442
432
|
for (const [key, value] of Object.entries(styles)) {
|
|
443
|
-
|
|
444
|
-
if (!(key in previousSnapshot.styles)) {
|
|
433
|
+
if (!(key in previous.styles)) {
|
|
445
434
|
styleChanges.push({
|
|
446
|
-
id: `change_${Date.now()}_${Math.random()}`,
|
|
435
|
+
id: `change_${Date.now()}_${Math.random().toString(36).slice(2)}`,
|
|
447
436
|
timestamp: Date.now(),
|
|
448
437
|
selector,
|
|
449
438
|
property: key,
|
|
@@ -451,26 +440,26 @@ function takeSnapshot(selector, styles, source) {
|
|
|
451
440
|
newValue: value,
|
|
452
441
|
type: "add"
|
|
453
442
|
});
|
|
454
|
-
} else if (JSON.stringify(
|
|
443
|
+
} else if (JSON.stringify(previous.styles[key]) !== JSON.stringify(value)) {
|
|
455
444
|
styleChanges.push({
|
|
456
|
-
id: `change_${Date.now()}_${Math.random()}`,
|
|
445
|
+
id: `change_${Date.now()}_${Math.random().toString(36).slice(2)}`,
|
|
457
446
|
timestamp: Date.now(),
|
|
458
447
|
selector,
|
|
459
448
|
property: key,
|
|
460
|
-
oldValue,
|
|
449
|
+
oldValue: previous.styles[key],
|
|
461
450
|
newValue: value,
|
|
462
451
|
type: "modify"
|
|
463
452
|
});
|
|
464
453
|
}
|
|
465
454
|
}
|
|
466
|
-
for (const [key] of Object.entries(
|
|
455
|
+
for (const [key] of Object.entries(previous.styles)) {
|
|
467
456
|
if (!(key in styles)) {
|
|
468
457
|
styleChanges.push({
|
|
469
|
-
id: `change_${Date.now()}_${Math.random()}`,
|
|
458
|
+
id: `change_${Date.now()}_${Math.random().toString(36).slice(2)}`,
|
|
470
459
|
timestamp: Date.now(),
|
|
471
460
|
selector,
|
|
472
461
|
property: key,
|
|
473
|
-
oldValue:
|
|
462
|
+
oldValue: previous.styles[key],
|
|
474
463
|
newValue: void 0,
|
|
475
464
|
type: "remove"
|
|
476
465
|
});
|
|
@@ -479,20 +468,47 @@ function takeSnapshot(selector, styles, source) {
|
|
|
479
468
|
}
|
|
480
469
|
return id;
|
|
481
470
|
}
|
|
471
|
+
function isTimelineEnabled() {
|
|
472
|
+
return timelineEnabled;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// src/compiler/scanner.ts
|
|
476
|
+
import fs2 from "fs";
|
|
477
|
+
function scanFileForStyles(filePath, optimizer, source = null) {
|
|
478
|
+
const errors = [];
|
|
479
|
+
let foundCount = 0;
|
|
480
|
+
try {
|
|
481
|
+
const content = source !== null ? source : fs2.readFileSync(filePath, "utf8");
|
|
482
|
+
if (!content || content.trim().length === 0) return { foundCount: 0, errors };
|
|
483
|
+
const styleRegex = /(?:chain|smartChain|\$)\(((?:[^()]|\([^()]*\))*)\)/g;
|
|
484
|
+
let match;
|
|
485
|
+
while ((match = styleRegex.exec(content)) !== null) {
|
|
486
|
+
try {
|
|
487
|
+
const styleBody = match[1].trim();
|
|
488
|
+
const cleanBody = styleBody.replace(/^['"\`]|['"\`]$/g, "");
|
|
489
|
+
if (cleanBody && optimizer && typeof optimizer.trackStyles === "function") {
|
|
490
|
+
optimizer.trackStyles([{ selectors: { "&": cleanBody } }]);
|
|
491
|
+
foundCount++;
|
|
492
|
+
}
|
|
493
|
+
} catch (parseError) {
|
|
494
|
+
errors.push(parseError);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
} catch (err) {
|
|
498
|
+
errors.push(err);
|
|
499
|
+
}
|
|
500
|
+
return { foundCount, errors };
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// src/compiler/btt.ts
|
|
482
504
|
var enableSourceComments = true;
|
|
483
505
|
function getSourceLocation() {
|
|
484
506
|
if (!enableSourceComments) return null;
|
|
485
507
|
const stack = new Error().stack;
|
|
486
508
|
if (!stack) return null;
|
|
487
|
-
const
|
|
488
|
-
for (let i = 0; i < stackLines.length; i++) {
|
|
489
|
-
const line = stackLines[i];
|
|
509
|
+
for (const line of stack.split("\n")) {
|
|
490
510
|
const match = line.match(/([^/]+\.chain\.js):(\d+):\d+/);
|
|
491
|
-
if (match) {
|
|
492
|
-
const fileName = match[1];
|
|
493
|
-
const lineNumber = match[2];
|
|
494
|
-
return `${fileName}:${lineNumber}`;
|
|
495
|
-
}
|
|
511
|
+
if (match) return `${match[1]}:${match[2]}`;
|
|
496
512
|
}
|
|
497
513
|
return null;
|
|
498
514
|
}
|
|
@@ -529,9 +545,7 @@ var fetchWithHttps = (url) => {
|
|
|
529
545
|
});
|
|
530
546
|
};
|
|
531
547
|
var loadCSSProperties = async () => {
|
|
532
|
-
if (chains.cachedValidProperties
|
|
533
|
-
return chains.cachedValidProperties;
|
|
534
|
-
}
|
|
548
|
+
if (chains.cachedValidProperties?.length > 0) return chains.cachedValidProperties;
|
|
535
549
|
try {
|
|
536
550
|
const url = "https://raw.githubusercontent.com/mdn/data/main/css/properties.json";
|
|
537
551
|
let data;
|
|
@@ -545,14 +559,9 @@ var loadCSSProperties = async () => {
|
|
|
545
559
|
data = await fetchWithHttps(url);
|
|
546
560
|
}
|
|
547
561
|
const allProperties = Object.keys(data);
|
|
548
|
-
|
|
549
|
-
allProperties.forEach((prop) => {
|
|
550
|
-
const baseProp = prop.replace(/^-(webkit|moz|ms|o)-/, "");
|
|
551
|
-
baseProperties.add(baseProp);
|
|
552
|
-
});
|
|
553
|
-
chains.cachedValidProperties = Array.from(baseProperties).sort();
|
|
562
|
+
chains.cachedValidProperties = allProperties.map((p) => p.replace(/^-(webkit|moz|ms|o)-/, "")).filter((v, i, a) => a.indexOf(v) === i).sort();
|
|
554
563
|
return chains.cachedValidProperties;
|
|
555
|
-
} catch
|
|
564
|
+
} catch {
|
|
556
565
|
chains.cachedValidProperties = COMMON_CSS_PROPERTIES;
|
|
557
566
|
return chains.cachedValidProperties;
|
|
558
567
|
}
|
|
@@ -563,11 +572,8 @@ var chains = {
|
|
|
563
572
|
classMap: {},
|
|
564
573
|
atomicStats: null,
|
|
565
574
|
async initializeProperties() {
|
|
566
|
-
if (this.cachedValidProperties
|
|
567
|
-
|
|
568
|
-
}
|
|
569
|
-
const properties = await loadCSSProperties();
|
|
570
|
-
this.cachedValidProperties = properties;
|
|
575
|
+
if (this.cachedValidProperties?.length > 0) return;
|
|
576
|
+
this.cachedValidProperties = await loadCSSProperties();
|
|
571
577
|
},
|
|
572
578
|
getCachedProperties() {
|
|
573
579
|
return this.cachedValidProperties;
|
|
@@ -584,21 +590,13 @@ function processAtRule(rule, parentSelectors = null) {
|
|
|
584
590
|
output = `@media ${rule.query} {
|
|
585
591
|
`;
|
|
586
592
|
if (rule.styles && typeof rule.styles === "object") {
|
|
587
|
-
let
|
|
588
|
-
for (const prop in rule.styles) {
|
|
589
|
-
const kebabKey = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
590
|
-
ruleBody += ` ${kebabKey}: ${rule.styles[prop]};
|
|
593
|
+
let body = "";
|
|
594
|
+
for (const prop in rule.styles) body += ` ${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${rule.styles[prop]};
|
|
591
595
|
`;
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
if (enableSourceComments && sourceLocation) {
|
|
597
|
-
output += ` /* Generated from: ${sourceLocation} */
|
|
598
|
-
`;
|
|
599
|
-
}
|
|
600
|
-
output += ` ${selector} {
|
|
601
|
-
${ruleBody} }
|
|
596
|
+
if (body.trim()) {
|
|
597
|
+
const sel = parentSelectors?.length ? parentSelectors.join(", ") : ".unknown-selector";
|
|
598
|
+
output += ` ${sel} {
|
|
599
|
+
${body} }
|
|
602
600
|
`;
|
|
603
601
|
}
|
|
604
602
|
}
|
|
@@ -611,11 +609,8 @@ ${ruleBody} }
|
|
|
611
609
|
output += ` ${step} {
|
|
612
610
|
`;
|
|
613
611
|
for (const prop in rule.steps[step]) {
|
|
614
|
-
if (prop !== "selectors") {
|
|
615
|
-
const kebabKey = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
616
|
-
output += ` ${kebabKey}: ${rule.steps[step][prop]};
|
|
612
|
+
if (prop !== "selectors") output += ` ${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${rule.steps[step][prop]};
|
|
617
613
|
`;
|
|
618
|
-
}
|
|
619
614
|
}
|
|
620
615
|
output += " }\n";
|
|
621
616
|
}
|
|
@@ -624,17 +619,11 @@ ${ruleBody} }
|
|
|
624
619
|
case "font-face":
|
|
625
620
|
output = "@font-face {\n";
|
|
626
621
|
for (const prop in rule.properties) {
|
|
627
|
-
if (prop !== "selectors") {
|
|
628
|
-
const kebabKey = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
629
|
-
output += ` ${kebabKey}: ${rule.properties[prop]};
|
|
622
|
+
if (prop !== "selectors") output += ` ${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${rule.properties[prop]};
|
|
630
623
|
`;
|
|
631
|
-
}
|
|
632
624
|
}
|
|
633
625
|
output += "}\n";
|
|
634
626
|
break;
|
|
635
|
-
default:
|
|
636
|
-
output = "";
|
|
637
|
-
break;
|
|
638
627
|
}
|
|
639
628
|
return output;
|
|
640
629
|
}
|
|
@@ -646,25 +635,20 @@ var compile = (obj) => {
|
|
|
646
635
|
if (!obj.hasOwnProperty(key)) continue;
|
|
647
636
|
const element = obj[key];
|
|
648
637
|
if (element && element.variants && typeof element.compileAll === "function") {
|
|
649
|
-
|
|
650
|
-
const recipeOutput = element.compileAll(cleanKey);
|
|
651
|
-
cssString += recipeOutput + "\n";
|
|
638
|
+
cssString += element.compileAll(key.includes("_") ? key.split("_").pop() : key) + "\n";
|
|
652
639
|
continue;
|
|
653
640
|
}
|
|
654
|
-
if (!element
|
|
641
|
+
if (!element?.selectors?.[0]) continue;
|
|
655
642
|
const selectorKey = element.selectors.join(",");
|
|
656
643
|
if (processedSelectors.has(selectorKey)) continue;
|
|
657
644
|
processedSelectors.add(selectorKey);
|
|
658
645
|
collected.push(element);
|
|
659
646
|
const sourceLocation = getSourceLocation();
|
|
660
|
-
let elementCSS = "";
|
|
661
|
-
|
|
662
|
-
if (timelineEnabled) {
|
|
647
|
+
let elementCSS = "", subRulesCSS = "";
|
|
648
|
+
if (isTimelineEnabled()) {
|
|
663
649
|
const styles = {};
|
|
664
650
|
for (const prop in element) {
|
|
665
|
-
if (!["selectors", "atRules", "hover", "nestedRules", "use", "nest", "themes"].includes(prop))
|
|
666
|
-
styles[prop] = element[prop];
|
|
667
|
-
}
|
|
651
|
+
if (!["selectors", "atRules", "hover", "nestedRules", "use", "nest", "themes"].includes(prop)) styles[prop] = element[prop];
|
|
668
652
|
}
|
|
669
653
|
takeSnapshot(element.selectors[0], styles, sourceLocation || "unknown");
|
|
670
654
|
}
|
|
@@ -674,41 +658,25 @@ var compile = (obj) => {
|
|
|
674
658
|
if (prop.startsWith("_") || !element.hasOwnProperty(prop)) continue;
|
|
675
659
|
const value = element[prop];
|
|
676
660
|
if (value === void 0 || value === null) continue;
|
|
677
|
-
|
|
678
|
-
elementCSS += ` ${kebabKey}: ${value};
|
|
661
|
+
elementCSS += ` ${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${value};
|
|
679
662
|
`;
|
|
680
663
|
}
|
|
681
|
-
if (elementCSS.trim()) {
|
|
682
|
-
let block = `${element.selectors.join(", ")} {
|
|
664
|
+
if (elementCSS.trim()) cssString += addSourceComment(`${element.selectors.join(", ")} {
|
|
683
665
|
${elementCSS}}
|
|
684
|
-
|
|
685
|
-
cssString += addSourceComment(block, sourceLocation);
|
|
686
|
-
}
|
|
666
|
+
`, sourceLocation);
|
|
687
667
|
if (element.hover && typeof element.hover === "object") {
|
|
688
|
-
let
|
|
689
|
-
for (const
|
|
690
|
-
const hKebab = hProp.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
691
|
-
hoverBody += ` ${hKebab}: ${element.hover[hProp]};
|
|
692
|
-
`;
|
|
693
|
-
}
|
|
694
|
-
if (hoverBody) {
|
|
695
|
-
let block = `${element.selectors.join(", ")}:hover {
|
|
696
|
-
${hoverBody}}
|
|
668
|
+
let hb = "";
|
|
669
|
+
for (const hp in element.hover) hb += ` ${hp.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${element.hover[hp]};
|
|
697
670
|
`;
|
|
698
|
-
|
|
699
|
-
|
|
671
|
+
if (hb) cssString += addSourceComment(`${element.selectors.join(", ")}:hover {
|
|
672
|
+
${hb}}
|
|
673
|
+
`, sourceLocation);
|
|
700
674
|
}
|
|
701
675
|
for (const prop in element) {
|
|
702
676
|
if ((prop.startsWith(".") || prop.startsWith("&")) && typeof element[prop] === "object") {
|
|
703
|
-
const
|
|
704
|
-
const
|
|
705
|
-
|
|
706
|
-
cssString += compile({
|
|
707
|
-
[subSelector]: {
|
|
708
|
-
selectors: [subSelector],
|
|
709
|
-
...subElement
|
|
710
|
-
}
|
|
711
|
-
}) + "\n";
|
|
677
|
+
const parentSel = element.selectors[0];
|
|
678
|
+
const subSel = prop.startsWith("&") ? prop.replace("&", parentSel) : `${parentSel} ${prop}`;
|
|
679
|
+
cssString += compile({ [subSel]: { selectors: [subSel], ...element[prop] } }) + "\n";
|
|
712
680
|
}
|
|
713
681
|
}
|
|
714
682
|
if (element.atRules && Array.isArray(element.atRules)) {
|
|
@@ -719,25 +687,21 @@ ${hoverBody}}
|
|
|
719
687
|
if (element.themes && Array.isArray(element.themes)) {
|
|
720
688
|
element.themes.forEach((theme) => {
|
|
721
689
|
if (theme.styles) {
|
|
722
|
-
let
|
|
723
|
-
for (const
|
|
724
|
-
if (
|
|
725
|
-
|
|
726
|
-
themeCSS += ` ${tKebab}: ${theme.styles[tProp]};
|
|
690
|
+
let tc = "";
|
|
691
|
+
for (const tp in theme.styles) {
|
|
692
|
+
if (tp === "selectors") continue;
|
|
693
|
+
tc += ` ${tp.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${theme.styles[tp]};
|
|
727
694
|
`;
|
|
728
695
|
}
|
|
729
|
-
if (
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
`;
|
|
733
|
-
subRulesCSS += addSourceComment(block, sourceLocation);
|
|
734
|
-
}
|
|
696
|
+
if (tc) subRulesCSS += addSourceComment(`${theme.styles.selectors?.join(", ") || element.selectors.join(", ")} {
|
|
697
|
+
${tc}}
|
|
698
|
+
`, sourceLocation);
|
|
735
699
|
}
|
|
736
700
|
});
|
|
737
701
|
}
|
|
738
702
|
cssString += subRulesCSS;
|
|
739
703
|
}
|
|
740
|
-
if (atomicOptimizer
|
|
704
|
+
if (atomicOptimizer?.options.enabled) {
|
|
741
705
|
const result = atomicOptimizer.optimize(collected);
|
|
742
706
|
chains.cssOutput = result.css;
|
|
743
707
|
return result.css;
|
|
@@ -745,48 +709,8 @@ ${themeCSS}}
|
|
|
745
709
|
chains.cssOutput = cssString.trim();
|
|
746
710
|
return chains.cssOutput;
|
|
747
711
|
};
|
|
748
|
-
function scanFileForStyles(filePath, optimizer, source = null) {
|
|
749
|
-
const errors = [];
|
|
750
|
-
let foundCount = 0;
|
|
751
|
-
try {
|
|
752
|
-
const content = source !== null ? source : fs2.readFileSync(filePath, "utf8");
|
|
753
|
-
if (!content || content.trim().length === 0) {
|
|
754
|
-
return { foundCount: 0, errors };
|
|
755
|
-
}
|
|
756
|
-
const styleRegex = /(?:chain|\$)\(((?:[^()]|\([^()]*\))*)\)/g;
|
|
757
|
-
let match;
|
|
758
|
-
while ((match = styleRegex.exec(content)) !== null) {
|
|
759
|
-
try {
|
|
760
|
-
const styleBody = match[1].trim();
|
|
761
|
-
const cleanBody = styleBody.replace(/^['"`]|['"`]$/g, "");
|
|
762
|
-
if (cleanBody) {
|
|
763
|
-
if (optimizer && typeof optimizer.trackStyles === "function") {
|
|
764
|
-
optimizer.trackStyles([{ selectors: { "&": cleanBody } }]);
|
|
765
|
-
}
|
|
766
|
-
foundCount++;
|
|
767
|
-
}
|
|
768
|
-
} catch (parseError) {
|
|
769
|
-
errors.push(parseError);
|
|
770
|
-
if (process.env.DEBUG) {
|
|
771
|
-
console.error(`[Scanner] Parse error in ${filePath}:`, parseError);
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
if (foundCount > 0 && process.env.DEBUG) {
|
|
776
|
-
console.log(chalk.magenta(`[Scanner] Found ${foundCount} styles in ${filePath}`));
|
|
777
|
-
}
|
|
778
|
-
} catch (err) {
|
|
779
|
-
errors.push(err);
|
|
780
|
-
if (process.env.DEBUG) {
|
|
781
|
-
console.error(`[Scanner] Error processing ${filePath}:`, err);
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
return { foundCount, errors };
|
|
785
|
-
}
|
|
786
712
|
chains.initializeProperties().catch((err) => {
|
|
787
|
-
if (process.env.DEBUG)
|
|
788
|
-
console.error("Failed to load CSS properties:", err.message);
|
|
789
|
-
}
|
|
713
|
+
if (process.env.DEBUG) console.error("Failed to load CSS properties:", err.message);
|
|
790
714
|
});
|
|
791
715
|
|
|
792
716
|
// src/compiler/atomic-optimizer.ts
|
|
@@ -2719,7 +2643,7 @@ var ChainCSSCompiler = class {
|
|
|
2719
2643
|
if (oldest) {
|
|
2720
2644
|
this.styleCache.delete(oldest);
|
|
2721
2645
|
if (this.config.verbose) {
|
|
2722
|
-
console.log(
|
|
2646
|
+
console.log(chalk.gray(` \u{1F9F9} Cache evicted: ${oldest.slice(0, 8)}...`));
|
|
2723
2647
|
}
|
|
2724
2648
|
}
|
|
2725
2649
|
}
|
|
@@ -2739,7 +2663,7 @@ var ChainCSSCompiler = class {
|
|
|
2739
2663
|
console.log(` \u2514\u2500 Processed ${processedCount} chain() styles from ${id.split("/").pop()}`);
|
|
2740
2664
|
}
|
|
2741
2665
|
} catch (error) {
|
|
2742
|
-
console.error(
|
|
2666
|
+
console.error(chalk.red(` \u274C Error compiling source ${id}: ${error}`));
|
|
2743
2667
|
}
|
|
2744
2668
|
}
|
|
2745
2669
|
/**
|
|
@@ -2764,7 +2688,7 @@ var ChainCSSCompiler = class {
|
|
|
2764
2688
|
}
|
|
2765
2689
|
} catch (err) {
|
|
2766
2690
|
if (this.config.verbose) {
|
|
2767
|
-
console.warn(
|
|
2691
|
+
console.warn(chalk.yellow(` \u26A0\uFE0F Failed to parse style body: ${input.substring(0, 100)}...`));
|
|
2768
2692
|
}
|
|
2769
2693
|
}
|
|
2770
2694
|
return {};
|
|
@@ -2973,7 +2897,7 @@ var ChainCSSCompiler = class {
|
|
|
2973
2897
|
if (this.atomicOptimizer) this.atomicOptimizer.reset();
|
|
2974
2898
|
this.accumulatedCSS = "";
|
|
2975
2899
|
if (!this.config.silent) {
|
|
2976
|
-
console.log(
|
|
2900
|
+
console.log(chalk.blue("\n\u{1F50D} Phase 1: Scanning & Usage Analysis..."));
|
|
2977
2901
|
}
|
|
2978
2902
|
const BATCH_SIZE = PERFORMANCE.BATCH_SIZE || 10;
|
|
2979
2903
|
const errors = [];
|
|
@@ -2998,7 +2922,7 @@ var ChainCSSCompiler = class {
|
|
|
2998
2922
|
}
|
|
2999
2923
|
} catch (err) {
|
|
3000
2924
|
if (this.config.verbose) {
|
|
3001
|
-
console.warn(
|
|
2925
|
+
console.warn(chalk.yellow(` \u26A0\uFE0F Scanning fallback for ${path5.basename(file)}`));
|
|
3002
2926
|
}
|
|
3003
2927
|
const result = scanFileForStyles(file, this.atomicOptimizer);
|
|
3004
2928
|
if (result.errors.length > 0) {
|
|
@@ -3009,14 +2933,14 @@ var ChainCSSCompiler = class {
|
|
|
3009
2933
|
});
|
|
3010
2934
|
await Promise.allSettled(batchPromises);
|
|
3011
2935
|
if (this.config.verbose && i % (BATCH_SIZE * 5) === 0) {
|
|
3012
|
-
console.log(
|
|
2936
|
+
console.log(chalk.gray(` \u{1F4CA} Processed ${Math.min(i + BATCH_SIZE, components.length)}/${components.length} files`));
|
|
3013
2937
|
}
|
|
3014
2938
|
}
|
|
3015
2939
|
if (errors.length > 0 && this.config.verbose) {
|
|
3016
|
-
console.warn(
|
|
2940
|
+
console.warn(chalk.yellow(` \u26A0\uFE0F ${errors.length} scanning errors occurred`));
|
|
3017
2941
|
}
|
|
3018
2942
|
if (!this.config.silent) {
|
|
3019
|
-
console.log(
|
|
2943
|
+
console.log(chalk.blue("\n\u{1F3D7}\uFE0F Phase 2: Generating Component Styles..."));
|
|
3020
2944
|
}
|
|
3021
2945
|
const publicDir = path5.resolve(process.cwd(), "public");
|
|
3022
2946
|
const manifestDir = path5.resolve(process.cwd(), ".chaincss", "manifest");
|
|
@@ -3047,7 +2971,7 @@ var ChainCSSCompiler = class {
|
|
|
3047
2971
|
const result = this.compileStyle(name, style);
|
|
3048
2972
|
if (this.config.verbose) {
|
|
3049
2973
|
const className2 = Object.values(result.classMap)[0];
|
|
3050
|
-
console.log(
|
|
2974
|
+
console.log(chalk.gray(` \u{1F4DD} ${name} \u2192 ${className2 || "(empty)"}`));
|
|
3051
2975
|
}
|
|
3052
2976
|
const className = Object.values(result.classMap)[0];
|
|
3053
2977
|
if (className) {
|
|
@@ -3073,21 +2997,21 @@ var ChainCSSCompiler = class {
|
|
|
3073
2997
|
}
|
|
3074
2998
|
processedComponents++;
|
|
3075
2999
|
if (this.config.verbose) {
|
|
3076
|
-
console.log(
|
|
3000
|
+
console.log(chalk.green(` \u2728 ${baseName} \u2192 ${path5.relative(process.cwd(), classFilePath)}`));
|
|
3077
3001
|
}
|
|
3078
3002
|
}
|
|
3079
3003
|
} catch (error) {
|
|
3080
|
-
console.error(
|
|
3004
|
+
console.error(chalk.red(` \u274C Failed to process ${baseName}: ${error.message}`));
|
|
3081
3005
|
}
|
|
3082
3006
|
}
|
|
3083
3007
|
if (!this.config.silent) {
|
|
3084
|
-
console.log(
|
|
3008
|
+
console.log(chalk.blue("\n\u{1F30D} Phase 3: Finalizing Global Assets..."));
|
|
3085
3009
|
}
|
|
3086
3010
|
const finalAtomicCSS = this.atomicOptimizer ? this.atomicOptimizer.generateAtomicCSS() : "";
|
|
3087
3011
|
const globalCssPath = path5.join(publicDir, "global.css");
|
|
3088
3012
|
fs6.writeFileSync(globalCssPath, formatCSS(finalAtomicCSS, this.config.output.minify));
|
|
3089
3013
|
if (this.config.verbose) {
|
|
3090
|
-
console.log(
|
|
3014
|
+
console.log(chalk.blue(` \u{1F4E6} Global CSS \u2192 ${path5.relative(process.cwd(), globalCssPath)} (${finalAtomicCSS.length} bytes)`));
|
|
3091
3015
|
}
|
|
3092
3016
|
const manifestData = {
|
|
3093
3017
|
version: VERSION,
|
|
@@ -3099,25 +3023,25 @@ var ChainCSSCompiler = class {
|
|
|
3099
3023
|
const manifestPath = path5.join(manifestDir, "manifest.json");
|
|
3100
3024
|
fs6.writeFileSync(manifestPath, JSON.stringify(manifestData, null, 2));
|
|
3101
3025
|
if (this.config.verbose) {
|
|
3102
|
-
console.log(
|
|
3026
|
+
console.log(chalk.blue(` \u{1F4E6} Manifest \u2192 ${path5.relative(process.cwd(), manifestPath)}`));
|
|
3103
3027
|
}
|
|
3104
3028
|
if (!this.config.silent) {
|
|
3105
|
-
console.log(
|
|
3029
|
+
console.log(chalk.green(`
|
|
3106
3030
|
\u2705 Build Complete!`));
|
|
3107
|
-
console.log(
|
|
3108
|
-
console.log(
|
|
3109
|
-
console.log(
|
|
3110
|
-
console.log(
|
|
3031
|
+
console.log(chalk.gray(` \u{1F4C1} Components processed: ${processedComponents}`));
|
|
3032
|
+
console.log(chalk.gray(` \u{1F4C1} Class files generated: ${generatedClassFiles.length}`));
|
|
3033
|
+
console.log(chalk.gray(` \u{1F4C1} Global CSS: ${path5.relative(process.cwd(), globalCssPath)}`));
|
|
3034
|
+
console.log(chalk.gray(` \u{1F4C1} Manifest: ${path5.relative(process.cwd(), manifestPath)}`));
|
|
3111
3035
|
if (this.atomicOptimizer) {
|
|
3112
3036
|
const atomicCount = Object.keys(this.atomicOptimizer.atomicMap).length;
|
|
3113
3037
|
const stats = this.atomicOptimizer.getStats();
|
|
3114
|
-
console.log(
|
|
3038
|
+
console.log(chalk.cyan(`
|
|
3115
3039
|
\u{1F4CA} Optimization Stats:`));
|
|
3116
|
-
console.log(
|
|
3117
|
-
console.log(
|
|
3118
|
-
console.log(
|
|
3040
|
+
console.log(chalk.gray(` Atomic Rules: ${atomicCount}`));
|
|
3041
|
+
console.log(chalk.gray(` Total Styles: ${stats.totalStyles}`));
|
|
3042
|
+
console.log(chalk.gray(` Unique Properties: ${stats.uniqueProperties}`));
|
|
3119
3043
|
if (stats.savings) {
|
|
3120
|
-
console.log(
|
|
3044
|
+
console.log(chalk.green(` CSS Savings: ${stats.savings}`));
|
|
3121
3045
|
}
|
|
3122
3046
|
}
|
|
3123
3047
|
}
|
package/index.html
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>ChainCSS Vanilla JS</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<div id="app"></div>
|
|
8
|
+
<script type="module">
|
|
9
|
+
import { chain, injectChainStyles } from 'chaincss';
|
|
10
|
+
|
|
11
|
+
const heading = chain()
|
|
12
|
+
.fs(48)
|
|
13
|
+
.fw(800)
|
|
14
|
+
.textGradient(['#6366f1', '#06b6d4'])
|
|
15
|
+
.$el('heading');
|
|
16
|
+
|
|
17
|
+
const button = chain()
|
|
18
|
+
.display('inline-flex')
|
|
19
|
+
.px(28)
|
|
20
|
+
.py(14)
|
|
21
|
+
.bg('#6366f1')
|
|
22
|
+
.color('white')
|
|
23
|
+
.rounded(12)
|
|
24
|
+
.border('none')
|
|
25
|
+
.cursor('pointer')
|
|
26
|
+
.hover().bg('#4f46e5').transform('translateY(-2px)').end()
|
|
27
|
+
.$el('btn');
|
|
28
|
+
|
|
29
|
+
// Inject styles
|
|
30
|
+
injectChainStyles({ heading, button });
|
|
31
|
+
|
|
32
|
+
// Build UI
|
|
33
|
+
document.getElementById('app').innerHTML = `
|
|
34
|
+
<h1 class="${heading.selectors[0]}">Hello ChainCSS!</h1>
|
|
35
|
+
<button class="${button.selectors[0]}" onclick="alert('Clicked!')">
|
|
36
|
+
Vanilla JS Button
|
|
37
|
+
</button>
|
|
38
|
+
`;
|
|
39
|
+
</script>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chaincss",
|
|
3
|
-
"version": "2.1.
|
|
4
|
-
"description": "ChainCSS - The first CSS-in-JS library with true auto-detection mixed mode. Zero runtime by default, dynamic when you need it.",
|
|
3
|
+
"version": "2.1.31",
|
|
4
|
+
"description": "ChainCSS v3.0 - The first CSS-in-JS library with true auto-detection mixed mode. Zero runtime by default, dynamic when you need it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -33,14 +33,15 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
|
-
"build": "npm run build:clean && npm run build:types && npm run build:core && npm run build:cli && npm run build:plugins && npm run build:runtime && npm run build:compiler",
|
|
36
|
+
"build": "npm run build:clean && npm run build:types && npm run build:core && npm run build:cli && npm run build:plugins && npm run build:runtime && npm run build:browser && npm run build:compiler",
|
|
37
37
|
"build:clean": "rm -rf dist",
|
|
38
38
|
"build:types": "tsc -p tsconfig.build.json",
|
|
39
|
-
"build:core": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --
|
|
40
|
-
"build:cli": "esbuild src/cli/index.ts --bundle --platform=node --format=esm --outfile=dist/cli/index.js --
|
|
41
|
-
"build:plugins": "esbuild src/plugins/vite.ts --bundle --platform=node --format=esm --outfile=dist/plugins/vite.js --
|
|
39
|
+
"build:core": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --packages=external",
|
|
40
|
+
"build:cli": "esbuild src/cli/index.ts --bundle --platform=node --format=esm --outfile=dist/cli/index.js --packages=external && chmod +x dist/cli/index.js",
|
|
41
|
+
"build:plugins": "esbuild src/plugins/vite.ts --bundle --platform=node --format=esm --outfile=dist/plugins/vite.js --packages=external && esbuild src/plugins/webpack.ts --bundle --platform=node --format=esm --outfile=dist/plugins/webpack.js --packages=external",
|
|
42
42
|
"build:runtime": "esbuild src/runtime/index.ts --bundle --platform=browser --format=esm --outfile=dist/runtime/index.js --external:react --external:react-dom --external:vue --external:svelte",
|
|
43
|
-
"build:
|
|
43
|
+
"build:browser": "esbuild src/browser.ts --bundle --platform=browser --format=esm --outfile=dist/browser.js --external:react --external:react-dom --external:vue --external:svelte",
|
|
44
|
+
"build:compiler": "esbuild src/compiler/index.ts --bundle --platform=node --format=esm --outfile=dist/compiler/index.js --packages=external",
|
|
44
45
|
"dev": "tsc -w",
|
|
45
46
|
"prepublishOnly": "npm run build",
|
|
46
47
|
"test": "vitest run",
|
package/src/browser.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Lightweight browser-only entry for vanilla JS
|
|
2
|
+
// No React, Vue, Svelte, HMR, or Node.js deps
|
|
3
|
+
export { chain, createChain, enableDebug, setTokenContext, getTokenContext } from './compiler/Chain.js';
|
|
4
|
+
export { $, $t, chain as runtimeChain, setManifest, setTokens } from './runtime/Chain.js';
|
|
5
|
+
export { smartChain, buildChain, runtimeChain as smartRuntimeChain } from './core/smart-chain.js';
|
|
6
|
+
export { shorthandMap, macros, getAvailableShorthands } from './compiler/shorthands.js';
|
|
7
|
+
export { animationPresets, createAnimation, getAnimationPreset, getAnimationPresetNames } from './compiler/animations.js';
|
|
8
|
+
export { helpers } from './compiler/helpers.js';
|
|
9
|
+
export { injectChainStyles, inspectSplit } from './runtime/index.js';
|