@jxsuite/compiler 0.18.0 → 0.19.0
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/compiler.js +111 -111
- package/package.json +1 -1
- package/src/shared.js +95 -22
package/package.json
CHANGED
package/src/shared.js
CHANGED
|
@@ -488,10 +488,45 @@ export function compileStyles(doc, mediaQueries = {}, projectStyle = null) {
|
|
|
488
488
|
// everything else on body. Project-level style is implicitly :root, so a
|
|
489
489
|
// flat object like { "--bg": "#000", "margin": "0" } is the expected format.
|
|
490
490
|
if (projectStyle && typeof projectStyle === "object") {
|
|
491
|
+
function emitProjectRules(
|
|
492
|
+
/** @type {string} */ selector,
|
|
493
|
+
/** @type {Record<string, any>} */ obj,
|
|
494
|
+
) {
|
|
495
|
+
const props = toCSSText(/** @type {any} */ (obj));
|
|
496
|
+
if (props) rules.push(`${selector} { ${props} }`);
|
|
497
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
498
|
+
if (val === null || typeof val !== "object" || Array.isArray(val)) continue;
|
|
499
|
+
if (key.startsWith("@")) {
|
|
500
|
+
const query = key.startsWith("@--")
|
|
501
|
+
? (mediaQueries[key.slice(1)] ?? key.slice(1))
|
|
502
|
+
: key.slice(1);
|
|
503
|
+
const mProps = toCSSText(/** @type {any} */ (val));
|
|
504
|
+
if (mProps) rules.push(`@media ${query} { ${selector} { ${mProps} } }`);
|
|
505
|
+
for (const [sel, sub] of Object.entries(/** @type {Record<string, any>} */ (val))) {
|
|
506
|
+
if (sub === null || typeof sub !== "object" || Array.isArray(sub)) continue;
|
|
507
|
+
if (sel.startsWith("@")) continue;
|
|
508
|
+
const resolved = sel.startsWith("&")
|
|
509
|
+
? sel.replace("&", selector)
|
|
510
|
+
: sel.startsWith(":") || sel.startsWith(".") || sel.startsWith("[")
|
|
511
|
+
? `${selector}${sel}`
|
|
512
|
+
: `${selector} ${sel}`;
|
|
513
|
+
const subProps = toCSSText(/** @type {any} */ (sub));
|
|
514
|
+
if (subProps) rules.push(`@media ${query} { ${resolved} { ${subProps} } }`);
|
|
515
|
+
}
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const resolved = key.startsWith("&")
|
|
519
|
+
? key.replace("&", selector)
|
|
520
|
+
: key.startsWith(":") || key.startsWith(".") || key.startsWith("[")
|
|
521
|
+
? `${selector}${key}`
|
|
522
|
+
: `${selector} ${key}`;
|
|
523
|
+
emitProjectRules(resolved, val);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
491
527
|
for (const [key, val] of Object.entries(projectStyle)) {
|
|
492
528
|
if (key.startsWith(":") || key.startsWith(".") || key.startsWith("[")) {
|
|
493
|
-
|
|
494
|
-
rules.push(`${key} { ${toCSSText(/** @type {any} */ (val))} }`);
|
|
529
|
+
emitProjectRules(key, /** @type {any} */ (val));
|
|
495
530
|
} else if (
|
|
496
531
|
val !== null &&
|
|
497
532
|
typeof val === "object" &&
|
|
@@ -499,10 +534,9 @@ export function compileStyles(doc, mediaQueries = {}, projectStyle = null) {
|
|
|
499
534
|
!key.startsWith("@") &&
|
|
500
535
|
!key.startsWith("--")
|
|
501
536
|
) {
|
|
502
|
-
|
|
503
|
-
rules.push(`${key} { ${toCSSText(/** @type {any} */ (val))} }`);
|
|
537
|
+
emitProjectRules(key, val);
|
|
504
538
|
} else if (key.startsWith("@")) {
|
|
505
|
-
// @media block
|
|
539
|
+
// @media block at top level
|
|
506
540
|
const query = key.startsWith("@--")
|
|
507
541
|
? (mediaQueries[key.slice(1)] ?? key.slice(1))
|
|
508
542
|
: key.slice(1);
|
|
@@ -541,6 +575,47 @@ export function compileStyles(doc, mediaQueries = {}, projectStyle = null) {
|
|
|
541
575
|
return `<style>\n${rules.join("\n")}\n</style>`;
|
|
542
576
|
}
|
|
543
577
|
|
|
578
|
+
/**
|
|
579
|
+
* Recursively emit CSS rules for a nested element selector.
|
|
580
|
+
*
|
|
581
|
+
* @param {string} selector
|
|
582
|
+
* @param {Record<string, any>} obj
|
|
583
|
+
* @param {string[]} rules
|
|
584
|
+
* @param {Record<string, any>} mediaQueries
|
|
585
|
+
*/
|
|
586
|
+
function emitNestedElement(selector, obj, rules, mediaQueries) {
|
|
587
|
+
const props = toCSSText(/** @type {any} */ (obj));
|
|
588
|
+
if (props) rules.push(`${selector} { ${props} }`);
|
|
589
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
590
|
+
if (val === null || typeof val !== "object" || Array.isArray(val)) continue;
|
|
591
|
+
if (key.startsWith("@")) {
|
|
592
|
+
const query = key.startsWith("@--")
|
|
593
|
+
? (mediaQueries[key.slice(1)] ?? key.slice(1))
|
|
594
|
+
: key.slice(1);
|
|
595
|
+
const mProps = toCSSText(/** @type {any} */ (val));
|
|
596
|
+
if (mProps) rules.push(`@media ${query} { ${selector} { ${mProps} } }`);
|
|
597
|
+
for (const [sel, sub] of Object.entries(/** @type {Record<string, any>} */ (val))) {
|
|
598
|
+
if (sub === null || typeof sub !== "object" || Array.isArray(sub)) continue;
|
|
599
|
+
if (sel.startsWith("@")) continue;
|
|
600
|
+
const resolved = sel.startsWith("&")
|
|
601
|
+
? sel.replace("&", selector)
|
|
602
|
+
: sel.startsWith(":") || sel.startsWith(".") || sel.startsWith("[")
|
|
603
|
+
? `${selector}${sel}`
|
|
604
|
+
: `${selector} ${sel}`;
|
|
605
|
+
const subProps = toCSSText(/** @type {any} */ (sub));
|
|
606
|
+
if (subProps) rules.push(`@media ${query} { ${resolved} { ${subProps} } }`);
|
|
607
|
+
}
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
const resolved = key.startsWith("&")
|
|
611
|
+
? key.replace("&", selector)
|
|
612
|
+
: key.startsWith(":") || key.startsWith(".") || key.startsWith("[")
|
|
613
|
+
? `${selector}${key}`
|
|
614
|
+
: `${selector} ${key}`;
|
|
615
|
+
emitNestedElement(resolved, val, rules, mediaQueries);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
544
619
|
/**
|
|
545
620
|
* @param {any} def
|
|
546
621
|
* @param {string[]} rules
|
|
@@ -590,34 +665,32 @@ export function collectStyles(
|
|
|
590
665
|
}
|
|
591
666
|
|
|
592
667
|
for (const [prop, val] of Object.entries(def.style)) {
|
|
668
|
+
if (val === null || typeof val !== "object" || Array.isArray(val)) continue;
|
|
593
669
|
if (prop.startsWith("@")) {
|
|
594
670
|
const query = prop.startsWith("@--")
|
|
595
671
|
? (mediaQueries[prop.slice(1)] ?? prop.slice(1))
|
|
596
672
|
: prop.slice(1);
|
|
597
673
|
rules.push(`@media ${query} { ${selector} { ${toCSSText(/** @type {any} */ (val))} } }`);
|
|
598
674
|
for (const [sel, nestedRules] of Object.entries(/** @type {Record<string, any>} */ (val))) {
|
|
599
|
-
if (
|
|
600
|
-
!(
|
|
601
|
-
sel.startsWith(":") ||
|
|
602
|
-
sel.startsWith(".") ||
|
|
603
|
-
sel.startsWith("&") ||
|
|
604
|
-
sel.startsWith("[")
|
|
605
|
-
)
|
|
606
|
-
)
|
|
675
|
+
if (nestedRules === null || typeof nestedRules !== "object" || Array.isArray(nestedRules))
|
|
607
676
|
continue;
|
|
608
|
-
|
|
677
|
+
if (sel.startsWith("@")) continue;
|
|
678
|
+
const resolved = sel.startsWith("&")
|
|
679
|
+
? sel.replace("&", selector)
|
|
680
|
+
: sel.startsWith(":") || sel.startsWith(".") || sel.startsWith("[")
|
|
681
|
+
? `${selector}${sel}`
|
|
682
|
+
: `${selector} ${sel}`;
|
|
609
683
|
rules.push(
|
|
610
684
|
`@media ${query} { ${resolved} { ${toCSSText(/** @type {any} */ (nestedRules))} } }`,
|
|
611
685
|
);
|
|
612
686
|
}
|
|
613
|
-
} else
|
|
614
|
-
prop.startsWith("
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
rules.push(`${resolved} { ${toCSSText(/** @type {any} */ (val))} }`);
|
|
687
|
+
} else {
|
|
688
|
+
const resolved = prop.startsWith("&")
|
|
689
|
+
? prop.replace("&", selector)
|
|
690
|
+
: prop.startsWith(":") || prop.startsWith(".") || prop.startsWith("[")
|
|
691
|
+
? `${selector}${prop}`
|
|
692
|
+
: `${selector} ${prop}`;
|
|
693
|
+
emitNestedElement(resolved, val, rules, mediaQueries);
|
|
621
694
|
}
|
|
622
695
|
}
|
|
623
696
|
}
|