@cssfn/cssfn
Advanced tools
Comparing version 2.0.10 to 2.0.11
@@ -9,3 +9,3 @@ import { | ||
// internals: | ||
import { flat, isFinalSelector, isFinalStyleMap, } from './utilities.js'; | ||
import { flat, isFinalSelector, isStyle, isFinalStyleMap, } from './utilities.js'; | ||
import { mergeSelectors, } from './mergeSelectors.js'; | ||
@@ -65,2 +65,8 @@ // processors: | ||
}; | ||
const parseSelectorsFromString = (selectorString) => { | ||
const selectorGroup = parseSelectors(selectorString); | ||
if (!selectorGroup) | ||
throw Error(`parse selector error: ${selectorString}`); | ||
return selectorGroup; | ||
}; | ||
const finalizeSelector = (style, symbolProp) => { | ||
@@ -81,8 +87,3 @@ const ruleData = style.get(symbolProp); // get existing prop (if any) | ||
const selectorGroup = ((selectorGroupByRuleType.get(0 /* RuleType.SelectorRule */) ?? []) // take only the SelectorRule(s) | ||
.flatMap((selectorString) => { | ||
const selectorGroup = parseSelectors(selectorString); | ||
if (!selectorGroup) | ||
throw Error(`parse selector error: ${selectorString}`); | ||
return selectorGroup; | ||
})); | ||
.flatMap(parseSelectorsFromString)); | ||
// merge selectors: | ||
@@ -136,2 +137,17 @@ const mergedSelectors = mergeSelectors(selectorGroup, options); | ||
}; | ||
const containsOnlyParentSelector = (styles) => { | ||
// conditions: | ||
if (!isStyle(styles)) | ||
return undefined; // not a CssStyle object => ignore | ||
if (Object.keys(styles).length) | ||
return undefined; // has any props => ignore | ||
const symbolProps = Object.getOwnPropertySymbols(styles); | ||
if (symbolProps.length !== 1) | ||
return undefined; // not exactly one nested_prop => ignore | ||
const symbolProp = symbolProps[0]; | ||
const [selector, nestedStyles] = styles[symbolProp]; | ||
if (selector !== '&') | ||
return undefined; // not a parentSelector => ignore | ||
return nestedStyles ?? null; // if `undefined` => convert to `null` to make different than *`undefined` means not_found* | ||
}; | ||
export const mergeParent = (style) => { | ||
@@ -143,11 +159,20 @@ let needToReorderOtherSymbolProps = false; | ||
/* move the CssProps and (nested)Rules from only_parentSelector to current style */ | ||
const [, styles] = style.get(symbolProp); | ||
const mergedParentStyles = (isFinalStyleMap(styles) ? styles : mergeStyles(styles)); | ||
if (mergedParentStyles) { | ||
if (!needToReorderOtherSymbolProps) { | ||
/* if mergedParentStyles has any (nested) Rule => all (nested) Rule in current style need to rearrange to preserve the order */ | ||
if (hasRuleKeys(mergedParentStyles.keys())) | ||
needToReorderOtherSymbolProps = true; | ||
let [, styles] = style.get(symbolProp); | ||
if (!!styles && (styles !== true)) { | ||
// efficiently dealing with *deep nested* only_parentSelector: | ||
let deepStyles = undefined; | ||
while ((deepStyles = containsOnlyParentSelector(styles)) !== undefined) { | ||
styles = deepStyles; | ||
} // while | ||
if (!!styles && (styles !== true)) { | ||
const mergedParentStyles = (isFinalStyleMap(styles) ? styles : mergeStyles(styles)); | ||
if (mergedParentStyles) { | ||
if (!needToReorderOtherSymbolProps) { | ||
/* if mergedParentStyles has any (nested) Rule => all (nested) Rule in current style need to rearrange to preserve the order */ | ||
if (hasRuleKeys(mergedParentStyles.keys())) | ||
needToReorderOtherSymbolProps = true; | ||
} // if | ||
mergeLiteral(style, mergedParentStyles); // merge into current style | ||
} // if | ||
} // if | ||
mergeLiteral(style, mergedParentStyles); // merge into current style | ||
} // if | ||
@@ -154,0 +179,0 @@ style.delete(symbolProp); // merged => delete source |
import type { SingleOrDeepArray } from '@cssfn/types'; | ||
import type { CssFinalStyleMap, CssStyleCollection, CssSelectorOptions, CssRawSelector, CssFinalSelector, CssScopeName } from '@cssfn/css-types'; | ||
import type { CssStyle, CssFinalStyleMap, CssStyleCollection, CssSelectorOptions, CssRawSelector, CssFinalSelector, CssScopeName } from '@cssfn/css-types'; | ||
export { camelCase, } from 'camel-case'; | ||
@@ -12,4 +12,5 @@ export { pascalCase, } from 'pascal-case'; | ||
export declare const isFinalSelector: (selector: CssRawSelector | CssFinalSelector) => selector is string; | ||
export declare const isStyle: (style: CssStyleCollection | CssFinalStyleMap) => style is CssStyle; | ||
export declare const isFinalStyleMap: (style: CssStyleCollection | CssFinalStyleMap) => style is CssFinalStyleMap; | ||
export declare const normalizeSelectorOptions: <TDefaultOptions extends CssSelectorOptions>(options: CssSelectorOptions | undefined, defaultOptions: TDefaultOptions) => TDefaultOptions; | ||
export declare const generateId: (styleSheetId: string, scopeName: CssScopeName) => string; |
@@ -24,6 +24,7 @@ // other libs: | ||
export const isFinalSelector = (selector) => (typeof (selector) === 'string'); | ||
export const isStyle = (style) => ((!!style && (style !== true)) | ||
&& | ||
(Object.getPrototypeOf(style) === Object.prototype)); | ||
export const isFinalStyleMap = (style) => ((!!style && (style !== true)) | ||
&& | ||
(typeof (style) === 'object') | ||
&& | ||
(Object.getPrototypeOf(style) === Map.prototype)); | ||
@@ -30,0 +31,0 @@ export const normalizeSelectorOptions = (options, defaultOptions) => { |
{ | ||
"name": "@cssfn/cssfn", | ||
"version": "2.0.10", | ||
"version": "2.0.11", | ||
"description": "Writes, imports, and exports css stylesheets as javascript modules.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -59,2 +59,3 @@ // cssfn: | ||
isFinalSelector, | ||
isStyle, | ||
isFinalStyleMap, | ||
@@ -131,2 +132,7 @@ } from './utilities.js' | ||
const parseSelectorsFromString = (selectorString: CssSelector): SelectorGroup => { | ||
const selectorGroup = parseSelectors(selectorString); | ||
if (!selectorGroup) throw Error(`parse selector error: ${selectorString}`); | ||
return selectorGroup; | ||
} | ||
const finalizeSelector = (style: (CssRuleMap & CssFinalRuleMap), symbolProp: symbol): CssFinalSelector|null => { | ||
@@ -160,7 +166,3 @@ const ruleData = (style as CssRuleMap|CssFinalRuleMap).get(symbolProp); // get existing prop (if any) | ||
(selectorGroupByRuleType.get(RuleType.SelectorRule) ?? []) // take only the SelectorRule(s) | ||
.flatMap((selectorString) => { | ||
const selectorGroup = parseSelectors(selectorString); | ||
if (!selectorGroup) throw Error(`parse selector error: ${selectorString}`); | ||
return selectorGroup; | ||
}) | ||
.flatMap(parseSelectorsFromString) | ||
); | ||
@@ -232,2 +234,16 @@ // merge selectors: | ||
} | ||
const containsOnlyParentSelector = (styles: CssStyleCollection|CssFinalStyleMap): CssStyleCollection => { | ||
// conditions: | ||
if (!isStyle(styles)) return undefined; // not a CssStyle object => ignore | ||
if (Object.keys(styles).length) return undefined; // has any props => ignore | ||
const symbolProps = Object.getOwnPropertySymbols(styles); | ||
if (symbolProps.length !== 1) return undefined; // not exactly one nested_prop => ignore | ||
const symbolProp = symbolProps[0]; | ||
const [selector, nestedStyles] = styles[symbolProp]; | ||
if (selector !== '&') return undefined; // not a parentSelector => ignore | ||
return nestedStyles ?? null; // if `undefined` => convert to `null` to make different than *`undefined` means not_found* | ||
} | ||
export const mergeParent = (style: CssStyleMap): void => { | ||
@@ -242,15 +258,27 @@ let needToReorderOtherSymbolProps = false; | ||
const [, styles] = (style as CssRuleMap|CssFinalRuleMap).get(symbolProp)!; | ||
const mergedParentStyles = (isFinalStyleMap(styles) ? styles : mergeStyles(styles)) as (CssStyleMap|null); | ||
if (mergedParentStyles) { | ||
if (!needToReorderOtherSymbolProps) { | ||
/* if mergedParentStyles has any (nested) Rule => all (nested) Rule in current style need to rearrange to preserve the order */ | ||
if (hasRuleKeys(mergedParentStyles.keys())) needToReorderOtherSymbolProps = true; | ||
} // if | ||
let [, styles] = (style as CssRuleMap|CssFinalRuleMap).get(symbolProp)!; | ||
if (!!styles && (styles !== true)) { | ||
// efficiently dealing with *deep nested* only_parentSelector: | ||
let deepStyles : CssStyleCollection = undefined; | ||
while((deepStyles = containsOnlyParentSelector(styles)) !== undefined) { | ||
styles = deepStyles; | ||
} // while | ||
mergeLiteral(style, mergedParentStyles); // merge into current style | ||
if (!!styles && (styles !== true)) { | ||
const mergedParentStyles = (isFinalStyleMap(styles) ? styles : mergeStyles(styles)) as (CssStyleMap|null); | ||
if (mergedParentStyles) { | ||
if (!needToReorderOtherSymbolProps) { | ||
/* if mergedParentStyles has any (nested) Rule => all (nested) Rule in current style need to rearrange to preserve the order */ | ||
if (hasRuleKeys(mergedParentStyles.keys())) needToReorderOtherSymbolProps = true; | ||
} // if | ||
mergeLiteral(style, mergedParentStyles); // merge into current style | ||
} // if | ||
} // if | ||
} // if | ||
style.delete(symbolProp); // merged => delete source | ||
style.delete(symbolProp); // merged => delete source | ||
} | ||
@@ -257,0 +285,0 @@ else if (needToReorderOtherSymbolProps) { |
@@ -7,2 +7,3 @@ // cssfn: | ||
import type { | ||
CssStyle, | ||
CssFinalStyleMap, | ||
@@ -59,7 +60,10 @@ CssStyleCollection, | ||
export const isStyle = (style: CssStyleCollection|CssFinalStyleMap): style is CssStyle => ( | ||
(!!style && (style !== true)) | ||
&& | ||
(Object.getPrototypeOf(style) === Object.prototype) | ||
); | ||
export const isFinalStyleMap = (style: CssStyleCollection|CssFinalStyleMap): style is CssFinalStyleMap => ( | ||
(!!style && (style !== true)) | ||
&& | ||
(typeof(style) === 'object') | ||
&& | ||
(Object.getPrototypeOf(style) === Map.prototype) | ||
@@ -66,0 +70,0 @@ ); |
561126
15680