@stylable/core
Advanced tools
Comparing version 5.4.0 to 5.4.1-rc.1
@@ -66,4 +66,5 @@ import type { ImportSymbol } from './st-import'; | ||
export declare function get(meta: StylableMeta, name: string): CSSVarSymbol | undefined; | ||
export declare function getRuntimeTypedDefinitionNames(meta: StylableMeta): string[]; | ||
export declare function getTransformedName({ symbol, meta }: CSSResolve<CSSVarSymbol>): string; | ||
export declare function scopeCSSVar(resolver: StylableResolver, meta: StylableMeta, symbolName: string): string; | ||
//# sourceMappingURL=css-custom-property.d.ts.map |
@@ -29,3 +29,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.scopeCSSVar = exports.getTransformedName = exports.get = exports.hooks = exports.diagnostics = void 0; | ||
exports.scopeCSSVar = exports.getTransformedName = exports.getRuntimeTypedDefinitionNames = exports.get = exports.hooks = exports.diagnostics = void 0; | ||
const feature_1 = require("./feature"); | ||
@@ -53,3 +53,6 @@ const STSymbol = __importStar(require("./st-symbol")); | ||
metaInit({ meta }) { | ||
plugable_record_1.plugableRecord.set(meta.data, dataKey, { stCustomGlobalProperty: {} }); | ||
plugable_record_1.plugableRecord.set(meta.data, dataKey, { | ||
stCustomGlobalProperty: {}, | ||
typedDefinitions: {}, | ||
}); | ||
}, | ||
@@ -77,2 +80,3 @@ analyzeInit(context) { | ||
analyzeAtRule({ context, atRule }) { | ||
var _a; | ||
const isStylable = context.meta.type === 'stylable'; | ||
@@ -88,4 +92,5 @@ if (atRule.name === `property`) { | ||
} | ||
const { stCustomGlobalProperty, typedDefinitions } = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); | ||
// handle conflict with deprecated `@st-global-custom-property` | ||
if (plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey).stCustomGlobalProperty[name]) { | ||
if (stCustomGlobalProperty[name]) { | ||
global = true; | ||
@@ -101,2 +106,7 @@ } | ||
(0, css_custom_property_1.validateAtProperty)(atRule, context.diagnostics); | ||
// save reference to runtime definitions | ||
if (atRule.nodes) { | ||
(_a = typedDefinitions[name]) !== null && _a !== void 0 ? _a : (typedDefinitions[name] = []); | ||
typedDefinitions[name].push(atRule); | ||
} | ||
} | ||
@@ -285,2 +295,7 @@ else if (atRule.name === `st-global-custom-property` && isStylable) { | ||
} | ||
function getRuntimeTypedDefinitionNames(meta) { | ||
const { typedDefinitions } = plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey); | ||
return Object.keys(typedDefinitions); | ||
} | ||
exports.getRuntimeTypedDefinitionNames = getRuntimeTypedDefinitionNames; | ||
function getTransformedName({ symbol, meta }) { | ||
@@ -287,0 +302,0 @@ return symbol.global ? symbol.name : (0, css_custom_property_1.generateScopedCSSVar)(meta.namespace, symbol.name.slice(2)); |
@@ -37,2 +37,3 @@ import type { StylableMeta } from '../stylable-meta'; | ||
isScoped: boolean; | ||
originalNode: postcss.AtRule | postcss.Rule; | ||
}) => boolean; | ||
@@ -43,5 +44,12 @@ }) => void; | ||
node: T['IMMUTABLE_SELECTOR']; | ||
topSelectorIndex: number; | ||
rule: postcss.Rule; | ||
originalNode: postcss.AtRule | postcss.Rule; | ||
walkContext: SelectorNodeContext; | ||
}) => SelectorWalkReturn; | ||
analyzeSelectorDone: (options: { | ||
context: FeatureContext; | ||
rule: postcss.Rule; | ||
originalNode: postcss.AtRule | postcss.Rule; | ||
}) => SelectorWalkReturn; | ||
analyzeDeclaration: (options: { | ||
@@ -48,0 +56,0 @@ context: FeatureContext; |
@@ -17,2 +17,5 @@ "use strict"; | ||
}, | ||
analyzeSelectorDone() { | ||
/**/ | ||
}, | ||
analyzeDeclaration() { | ||
@@ -19,0 +22,0 @@ /**/ |
@@ -52,2 +52,3 @@ "use strict"; | ||
isScoped: false, | ||
originalNode: atRule, | ||
}); | ||
@@ -54,0 +55,0 @@ const analyzed = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); |
import type { StylableMeta } from '../stylable-meta'; | ||
import type { SelectorNode, ImmutablePseudoClass, SelectorList, PseudoClass } from '@tokey/css-selector-parser'; | ||
import type { SelectorNode, ImmutableSelectorNode, SelectorList, PseudoClass } from '@tokey/css-selector-parser'; | ||
import type * as postcss from 'postcss'; | ||
export declare const diagnostics: { | ||
@@ -11,6 +12,7 @@ UNSUPPORTED_MULTI_SELECTOR_IN_GLOBAL: { | ||
export declare const hooks: import("./feature").FeatureHooks<{ | ||
IMMUTABLE_SELECTOR: ImmutablePseudoClass; | ||
IMMUTABLE_SELECTOR: ImmutableSelectorNode; | ||
}>; | ||
export declare function getGlobalRules(meta: StylableMeta): postcss.Rule[]; | ||
export declare function unwrapPseudoGlobals(selectorAst: SelectorList): PseudoClass[]; | ||
export declare function addGlobals(meta: StylableMeta, selectorAst: SelectorNode[]): void; | ||
//# sourceMappingURL=st-global.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.addGlobals = exports.unwrapPseudoGlobals = exports.hooks = exports.diagnostics = void 0; | ||
exports.addGlobals = exports.unwrapPseudoGlobals = exports.getGlobalRules = exports.hooks = exports.diagnostics = void 0; | ||
const feature_1 = require("./feature"); | ||
@@ -15,17 +15,64 @@ const plugable_record_1 = require("../helpers/plugable-record"); | ||
metaInit({ meta }) { | ||
plugable_record_1.plugableRecord.set(meta.data, dataKey, {}); | ||
plugable_record_1.plugableRecord.set(meta.data, dataKey, { rules: new Map() }); | ||
}, | ||
analyzeSelectorNode({ context, node, rule }) { | ||
var _a; | ||
if (node.value !== `global`) { | ||
analyzeSelectorNode({ context, node, topSelectorIndex, rule, originalNode }) { | ||
var _a, _b, _c; | ||
var _d, _e; | ||
const { rules } = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); | ||
if (node.type === 'selector' || node.type === 'combinator' || node.type === 'comment') { | ||
return; | ||
} | ||
if (node.nodes && ((_a = node.nodes) === null || _a === void 0 ? void 0 : _a.length) > 1) { | ||
context.diagnostics.report(exports.diagnostics.UNSUPPORTED_MULTI_SELECTOR_IN_GLOBAL(), { | ||
node: rule, | ||
word: (0, selector_1.stringifySelector)(node.nodes), | ||
if (!rules.has(originalNode)) { | ||
rules.set(originalNode, { | ||
isGlobal: true, | ||
checkedRule: rule, | ||
topLevelSelectorsFlags: [], | ||
}); | ||
} | ||
return selector_1.walkSelector.skipNested; | ||
const ruleData = rules.get(originalNode); | ||
if (node.type === 'pseudo_class' && node.value === `global`) { | ||
// mark selector as global only if it isn't set | ||
(_a = (_d = ruleData.topLevelSelectorsFlags)[topSelectorIndex]) !== null && _a !== void 0 ? _a : (_d[topSelectorIndex] = true); | ||
if (node.nodes && ((_b = node.nodes) === null || _b === void 0 ? void 0 : _b.length) > 1) { | ||
context.diagnostics.report(exports.diagnostics.UNSUPPORTED_MULTI_SELECTOR_IN_GLOBAL(), { | ||
node: rule, | ||
word: (0, selector_1.stringifySelector)(node.nodes), | ||
}); | ||
} | ||
return selector_1.walkSelector.skipNested; | ||
} | ||
else if (node.type === 'universal' || (node.type === 'type' && !(0, selector_1.isCompRoot)(node.value))) { | ||
// mark selector as global only if it isn't set | ||
(_c = (_e = ruleData.topLevelSelectorsFlags)[topSelectorIndex]) !== null && _c !== void 0 ? _c : (_e[topSelectorIndex] = true); | ||
} | ||
else { | ||
// mark selector as local if it has a local selector | ||
ruleData.topLevelSelectorsFlags[topSelectorIndex] = false; | ||
} | ||
return; | ||
}, | ||
analyzeSelectorDone({ context, originalNode }) { | ||
const { rules } = plugable_record_1.plugableRecord.getUnsafe(context.meta.data, dataKey); | ||
const data = rules.get(originalNode); | ||
if (!data) { | ||
return; | ||
} | ||
// require at least one global selector in rule selectors | ||
if (!data.topLevelSelectorsFlags.find((isGlobal) => isGlobal)) { | ||
data.isGlobal = false; | ||
return; | ||
} | ||
// rule is global if it doesn't have any local parents | ||
let parent = originalNode.parent; | ||
while (parent) { | ||
const parentData = rules.get(parent); | ||
if (parentData) { | ||
// quick resolution: parent calculated first | ||
data.isGlobal = parentData.isGlobal; | ||
break; | ||
} | ||
// keep searching | ||
parent = parent.parent; | ||
} | ||
}, | ||
transformInit({ context }) { | ||
@@ -47,2 +94,13 @@ context.meta.globals = {}; | ||
// API | ||
function getGlobalRules(meta) { | ||
const { rules } = plugable_record_1.plugableRecord.getUnsafe(meta.data, dataKey); | ||
const globalRules = []; | ||
for (const [rule, { isGlobal, checkedRule }] of rules) { | ||
if (isGlobal && checkedRule === rule && rule.type === 'rule') { | ||
globalRules.push(rule); | ||
} | ||
} | ||
return globalRules; | ||
} | ||
exports.getGlobalRules = getGlobalRules; | ||
function unwrapPseudoGlobals(selectorAst) { | ||
@@ -49,0 +107,0 @@ const collectedGlobals = []; |
@@ -74,3 +74,3 @@ import { FeatureContext } from './feature'; | ||
UNKNOWN_IMPORTED_FILE: { | ||
(path: string): import("../diagnostics").DiagnosticBase; | ||
(path: string, error?: unknown): import("../diagnostics").DiagnosticBase; | ||
code: string; | ||
@@ -77,0 +77,0 @@ severity: import("../diagnostics").DiagnosticSeverity; |
@@ -61,3 +61,3 @@ "use strict"; | ||
UNKNOWN_IMPORTED_SYMBOL: (0, diagnostics_2.createDiagnosticReporter)('05015', 'error', (name, path) => `cannot resolve imported symbol "${name}" from stylesheet "${path}"`), | ||
UNKNOWN_IMPORTED_FILE: (0, diagnostics_2.createDiagnosticReporter)('05016', 'error', (path) => `cannot resolve imported file: "${path}"`), | ||
UNKNOWN_IMPORTED_FILE: (0, diagnostics_2.createDiagnosticReporter)('05016', 'error', (path, error) => `cannot resolve imported file: "${path}"${error ? `\nFailed with:\n${error}` : ''}`), | ||
UNKNOWN_TYPED_IMPORT: (0, diagnostics_2.createDiagnosticReporter)('05018', 'error', (type) => `Unknown type import "${type}"`), | ||
@@ -122,2 +122,3 @@ NO_DEFAULT_EXPORT: (0, diagnostics_2.createDiagnosticReporter)('05020', 'error', (path) => `Native CSS files have no default export. Imported file: "${path}"`), | ||
validateImports(context); | ||
calcCssDepth(context); | ||
}, | ||
@@ -142,2 +143,9 @@ }); | ||
exports.StylablePublicApi = StylablePublicApi; | ||
function calcCssDepth(context) { | ||
let cssDepth = 0; | ||
const deepDependencies = (0, import_1.tryCollectImportsDeep)(context.resolver, context.meta, new Set(), ({ depth }) => { | ||
cssDepth = Math.max(cssDepth, depth); | ||
}, 1); | ||
context.meta.transformCssDepth = { cssDepth, deepDependencies }; | ||
} | ||
function isImportStatement(node) { | ||
@@ -207,8 +215,8 @@ return ((node.type === `atrule` && node.name === `st-import`) || | ||
for (const importObj of imports) { | ||
const resolvedImport = context.resolver.resolveImported(importObj, ''); | ||
if (!resolvedImport) { | ||
const entity = context.resolver.getModule(importObj); | ||
if (!entity.value) { | ||
// warn about unknown imported files | ||
const fromDecl = importObj.rule.nodes && | ||
importObj.rule.nodes.find((decl) => decl.type === 'decl' && decl.prop === exports.PseudoImportDecl.FROM); | ||
context.diagnostics.report(exports.diagnostics.UNKNOWN_IMPORTED_FILE(importObj.request), { | ||
context.diagnostics.report(exports.diagnostics.UNKNOWN_IMPORTED_FILE(importObj.request, getErrorText(entity)), { | ||
node: fromDecl || importObj.rule, | ||
@@ -218,7 +226,8 @@ word: importObj.request, | ||
} | ||
else if (resolvedImport._kind === 'css') { | ||
else if (entity.kind === 'css') { | ||
const meta = entity.value; | ||
// propagate some native CSS diagnostics to st-import | ||
if (resolvedImport.meta.type === 'css') { | ||
if (meta.type === 'css') { | ||
let foundUnsupportedNativeImport = false; | ||
for (const report of resolvedImport.meta.diagnostics.reports) { | ||
for (const report of meta.diagnostics.reports) { | ||
if (report.code === '05021') { | ||
@@ -237,3 +246,3 @@ foundUnsupportedNativeImport = true; | ||
// report unsupported native CSS default import | ||
if (resolvedImport.meta.type !== 'stylable' && importObj.defaultExport) { | ||
if (meta.type !== 'stylable' && importObj.defaultExport) { | ||
context.diagnostics.report(exports.diagnostics.NO_DEFAULT_EXPORT(importObj.request), { | ||
@@ -255,4 +264,21 @@ node: importObj.rule, | ||
} | ||
else if (entity.kind === 'js') { | ||
// TODO: add diagnostics for JS imports (typeof checks) | ||
} | ||
} | ||
} | ||
function getErrorText(res) { | ||
if ('error' in res) { | ||
const { error } = res; | ||
if (typeof error === 'object' && error) { | ||
return 'details' in error | ||
? String(error.details) | ||
: 'message' in error | ||
? String(error.message) | ||
: String(error); | ||
} | ||
return String(error); | ||
} | ||
return ''; | ||
} | ||
//# sourceMappingURL=st-import.js.map |
@@ -48,2 +48,3 @@ "use strict"; | ||
isScoped: true, | ||
originalNode: atRule, | ||
}); | ||
@@ -50,0 +51,0 @@ context.meta.scopes.push(atRule); |
import { Diagnostics } from '../diagnostics'; | ||
import type { Imported } from '../features'; | ||
import { Root, Rule, AtRule } from 'postcss'; | ||
import type { Stylable } from '../stylable'; | ||
import type { StylableMeta } from '../stylable-meta'; | ||
import type * as postcss from 'postcss'; | ||
import type { StylableResolver } from '../stylable-resolver'; | ||
export declare const parseImportMessages: { | ||
@@ -93,4 +93,10 @@ ST_IMPORT_STAR: { | ||
type ImportPatch = Partial<Pick<Imported, 'defaultExport' | 'named' | 'keyframes'>> & Pick<Imported, 'request'>; | ||
export declare function tryCollectImportsDeep(stylable: Stylable, meta: StylableMeta, imports?: Set<string>): Set<string>; | ||
type ImportEvent = { | ||
context: string; | ||
request: string; | ||
resolved: string; | ||
depth: number; | ||
}; | ||
export declare function tryCollectImportsDeep(resolver: StylableResolver, meta: StylableMeta, imports?: Set<string>, onImport?: undefined | ((e: ImportEvent) => void), depth?: number): Set<string>; | ||
export {}; | ||
//# sourceMappingURL=import.d.ts.map |
@@ -434,12 +434,13 @@ "use strict"; | ||
} | ||
function tryCollectImportsDeep(stylable, meta, imports = new Set()) { | ||
function tryCollectImportsDeep(resolver, meta, imports = new Set(), onImport = undefined, depth = 0) { | ||
for (const { context, request } of meta.getImportStatements()) { | ||
try { | ||
const resolved = stylable.resolver.resolvePath(context, request); | ||
const resolved = resolver.resolvePath(context, request); | ||
onImport === null || onImport === void 0 ? void 0 : onImport({ context, request, resolved, depth }); | ||
if (!imports.has(resolved)) { | ||
imports.add(resolved); | ||
tryCollectImportsDeep(stylable, stylable.analyze(resolved), imports); | ||
tryCollectImportsDeep(resolver, resolver.analyze(resolved), imports, onImport, depth + 1); | ||
} | ||
} | ||
catch (e) { | ||
catch { | ||
/** */ | ||
@@ -446,0 +447,0 @@ } |
@@ -5,3 +5,3 @@ export { safeParse } from './parser'; | ||
export { validateDefaultConfig } from './stylable'; | ||
export { STCustomSelector, STCustomState } from './features'; | ||
export { STSymbol, STGlobal, STCustomSelector, STCustomState, CSSCustomProperty } from './features'; | ||
export type { MappedStates, StateParsedValue } from './helpers/custom-state'; | ||
@@ -12,3 +12,3 @@ export { murmurhash3_32_gc } from './murmurhash'; | ||
export { nativePseudoClasses, nativePseudoElements, knownPseudoClassesWithNestedSelectors, } from './native-reserved-lists'; | ||
export { isAsset, makeAbsolute, isRelativeNativeCss } from './stylable-assets'; | ||
export { isAsset, makeAbsolute, isRelativeNativeCss, fixRelativeUrls } from './stylable-assets'; | ||
export { namespace, namespaceDelimiter } from './helpers/namespace'; | ||
@@ -15,0 +15,0 @@ export { emitDiagnostics, DiagnosticsMode, EmitDiagnosticsContext, reportDiagnostic, } from './report-diagnostic'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.tryCollectImportsDeep = exports.getAstNodeAt = exports.createCustomValue = exports.packageNamespaceFactory = exports.createStylableFileProcessor = exports.cachedProcessFile = exports.StylableResolver = exports.reportDiagnostic = exports.emitDiagnostics = exports.namespaceDelimiter = exports.namespace = exports.isRelativeNativeCss = exports.makeAbsolute = exports.isAsset = exports.knownPseudoClassesWithNestedSelectors = exports.nativePseudoElements = exports.nativePseudoClasses = exports.cssParse = exports.murmurhash3_32_gc = exports.STCustomState = exports.STCustomSelector = exports.validateDefaultConfig = exports.transformerDiagnostics = exports.StylableTransformer = exports.StylableProcessor = exports.processorDiagnostics = exports.safeParse = void 0; | ||
exports.tryCollectImportsDeep = exports.getAstNodeAt = exports.createCustomValue = exports.packageNamespaceFactory = exports.createStylableFileProcessor = exports.cachedProcessFile = exports.StylableResolver = exports.reportDiagnostic = exports.emitDiagnostics = exports.namespaceDelimiter = exports.namespace = exports.fixRelativeUrls = exports.isRelativeNativeCss = exports.makeAbsolute = exports.isAsset = exports.knownPseudoClassesWithNestedSelectors = exports.nativePseudoElements = exports.nativePseudoClasses = exports.cssParse = exports.murmurhash3_32_gc = exports.CSSCustomProperty = exports.STCustomState = exports.STCustomSelector = exports.STGlobal = exports.STSymbol = exports.validateDefaultConfig = exports.transformerDiagnostics = exports.StylableTransformer = exports.StylableProcessor = exports.processorDiagnostics = exports.safeParse = void 0; | ||
var parser_1 = require("./parser"); | ||
@@ -15,4 +15,7 @@ Object.defineProperty(exports, "safeParse", { enumerable: true, get: function () { return parser_1.safeParse; } }); | ||
var features_1 = require("./features"); | ||
Object.defineProperty(exports, "STSymbol", { enumerable: true, get: function () { return features_1.STSymbol; } }); | ||
Object.defineProperty(exports, "STGlobal", { enumerable: true, get: function () { return features_1.STGlobal; } }); | ||
Object.defineProperty(exports, "STCustomSelector", { enumerable: true, get: function () { return features_1.STCustomSelector; } }); | ||
Object.defineProperty(exports, "STCustomState", { enumerable: true, get: function () { return features_1.STCustomState; } }); | ||
Object.defineProperty(exports, "CSSCustomProperty", { enumerable: true, get: function () { return features_1.CSSCustomProperty; } }); | ||
var murmurhash_1 = require("./murmurhash"); | ||
@@ -30,2 +33,3 @@ Object.defineProperty(exports, "murmurhash3_32_gc", { enumerable: true, get: function () { return murmurhash_1.murmurhash3_32_gc; } }); | ||
Object.defineProperty(exports, "isRelativeNativeCss", { enumerable: true, get: function () { return stylable_assets_1.isRelativeNativeCss; } }); | ||
Object.defineProperty(exports, "fixRelativeUrls", { enumerable: true, get: function () { return stylable_assets_1.fixRelativeUrls; } }); | ||
var namespace_1 = require("./helpers/namespace"); | ||
@@ -32,0 +36,0 @@ Object.defineProperty(exports, "namespace", { enumerable: true, get: function () { return namespace_1.namespace; } }); |
@@ -15,2 +15,6 @@ import type * as postcss from 'postcss'; | ||
urls: string[]; | ||
transformCssDepth: { | ||
cssDepth: number; | ||
deepDependencies: Set<string>; | ||
} | undefined; | ||
transformDiagnostics: Diagnostics | null; | ||
@@ -17,0 +21,0 @@ transformedScopes: Record<string, SelectorList> | null; |
@@ -20,5 +20,6 @@ import type * as postcss from 'postcss'; | ||
private collectUrls; | ||
protected handleRule(rule: postcss.Rule, { isScoped, reportUnscoped }: { | ||
protected handleRule(rule: postcss.Rule, { isScoped, reportUnscoped, originalNode, }: { | ||
isScoped: boolean; | ||
reportUnscoped: boolean; | ||
originalNode?: postcss.AtRule | postcss.Rule; | ||
}): boolean; | ||
@@ -25,0 +26,0 @@ } |
@@ -58,5 +58,6 @@ "use strict"; | ||
handleAtRules(root) { | ||
const analyzeRule = (rule, { isScoped }) => { | ||
const analyzeRule = (rule, { isScoped, originalNode, }) => { | ||
return this.handleRule(rule, { | ||
isScoped, | ||
originalNode, | ||
reportUnscoped: false, | ||
@@ -148,5 +149,6 @@ }); | ||
} | ||
handleRule(rule, { isScoped, reportUnscoped }) { | ||
handleRule(rule, { isScoped, reportUnscoped, originalNode = rule, }) { | ||
const selectorAst = (0, selector_1.parseSelectorWithCache)(rule.selector); | ||
let locallyScoped = isScoped; | ||
let topSelectorIndex = -1; | ||
(0, selector_1.walkSelector)(selectorAst, (node, ...nodeContext) => { | ||
@@ -158,3 +160,15 @@ const [index, nodes, parents] = nodeContext; | ||
locallyScoped = isScoped; | ||
topSelectorIndex++; | ||
} | ||
const walkSkip = features_2.STGlobal.hooks.analyzeSelectorNode({ | ||
context: this, | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
}); | ||
if (walkSkip !== undefined) { | ||
return walkSkip; | ||
} | ||
if (node.type === 'pseudo_class') { | ||
@@ -165,3 +179,5 @@ if (node.value === 'import') { | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
@@ -174,14 +190,8 @@ }); | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
}); | ||
} | ||
else if (node.value === `global`) { | ||
return features_2.STGlobal.hooks.analyzeSelectorNode({ | ||
context: this, | ||
node, | ||
rule, | ||
walkContext: nodeContext, | ||
}); | ||
} | ||
else if (node.value.startsWith('--')) { | ||
@@ -202,3 +212,5 @@ // ToDo: move to css-class feature | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
@@ -221,3 +233,5 @@ }); | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
@@ -261,2 +275,7 @@ }); | ||
}); | ||
features_2.STGlobal.hooks.analyzeSelectorDone({ | ||
context: this, | ||
rule, | ||
originalNode, | ||
}); | ||
return locallyScoped; | ||
@@ -263,0 +282,0 @@ } |
@@ -68,3 +68,4 @@ import type { FileProcessor } from './cached-process-file'; | ||
constructor(fileProcessor: FileProcessor<StylableMeta>, requireModule: (resolvedPath: string) => any, moduleResolver: ModuleResolver, cache?: StylableResolverCache | undefined); | ||
private getModule; | ||
getModule({ context, request }: Imported): CachedModuleEntity; | ||
analyze(filePath: string): StylableMeta; | ||
resolvePath(directoryPath: string, request: string): string; | ||
@@ -71,0 +72,0 @@ resolveImported(imported: Imported, name: string, subtype?: 'mappedSymbols' | 'mappedKeyframes' | STSymbol.Namespaces): CSSResolve | JSResolve | null; |
@@ -71,2 +71,5 @@ "use strict"; | ||
} | ||
analyze(filePath) { | ||
return this.fileProcessor.process(filePath); | ||
} | ||
resolvePath(directoryPath, request) { | ||
@@ -73,0 +76,0 @@ var _a, _b, _c; |
{ | ||
"name": "@stylable/core", | ||
"version": "5.4.0", | ||
"version": "5.4.1-rc.1", | ||
"description": "CSS for Components", | ||
@@ -20,3 +20,3 @@ "main": "dist/index.js", | ||
"deindent": "^0.1.0", | ||
"enhanced-resolve": "^5.10.0", | ||
"enhanced-resolve": "^5.12.0", | ||
"is-vendor-prefixed": "^4.0.0", | ||
@@ -23,0 +23,0 @@ "lodash.clonedeep": "^4.5.0", |
@@ -67,2 +67,3 @@ import { createFeature, FeatureContext } from './feature'; | ||
stCustomGlobalProperty: Record<string, CSSVarSymbol>; | ||
typedDefinitions: Record<string, postcss.AtRule[]>; | ||
}>('custom-property'); | ||
@@ -76,3 +77,6 @@ | ||
metaInit({ meta }) { | ||
plugableRecord.set(meta.data, dataKey, { stCustomGlobalProperty: {} }); | ||
plugableRecord.set(meta.data, dataKey, { | ||
stCustomGlobalProperty: {}, | ||
typedDefinitions: {}, | ||
}); | ||
}, | ||
@@ -114,4 +118,8 @@ analyzeInit(context) { | ||
} | ||
const { stCustomGlobalProperty, typedDefinitions } = plugableRecord.getUnsafe( | ||
context.meta.data, | ||
dataKey | ||
); | ||
// handle conflict with deprecated `@st-global-custom-property` | ||
if (plugableRecord.getUnsafe(context.meta.data, dataKey).stCustomGlobalProperty[name]) { | ||
if (stCustomGlobalProperty[name]) { | ||
global = true; | ||
@@ -127,2 +135,7 @@ } | ||
validateAtProperty(atRule, context.diagnostics); | ||
// save reference to runtime definitions | ||
if (atRule.nodes) { | ||
typedDefinitions[name] ??= []; | ||
typedDefinitions[name].push(atRule); | ||
} | ||
} else if (atRule.name === `st-global-custom-property` && isStylable) { | ||
@@ -334,2 +347,7 @@ analyzeDeprecatedStGlobalCustomProperty(context, atRule); | ||
} | ||
export function getRuntimeTypedDefinitionNames(meta: StylableMeta) { | ||
const { typedDefinitions } = plugableRecord.getUnsafe(meta.data, dataKey); | ||
return Object.keys(typedDefinitions); | ||
} | ||
export function getTransformedName({ symbol, meta }: CSSResolve<CSSVarSymbol>) { | ||
@@ -336,0 +354,0 @@ return symbol.global ? symbol.name : generateScopedCSSVar(meta.namespace, symbol.name.slice(2)); |
@@ -40,3 +40,6 @@ import type { StylableMeta } from '../stylable-meta'; | ||
atRule: postcss.AtRule; | ||
analyzeRule: (rule: postcss.Rule, options: { isScoped: boolean }) => boolean; | ||
analyzeRule: ( | ||
rule: postcss.Rule, | ||
options: { isScoped: boolean; originalNode: postcss.AtRule | postcss.Rule } | ||
) => boolean; | ||
}) => void; | ||
@@ -46,5 +49,12 @@ analyzeSelectorNode: (options: { | ||
node: T['IMMUTABLE_SELECTOR']; | ||
topSelectorIndex: number; | ||
rule: postcss.Rule; | ||
originalNode: postcss.AtRule | postcss.Rule; // used by rules generated from at-rules | ||
walkContext: SelectorNodeContext; | ||
}) => SelectorWalkReturn; | ||
analyzeSelectorDone: (options: { | ||
context: FeatureContext; | ||
rule: postcss.Rule; | ||
originalNode: postcss.AtRule | postcss.Rule; // used by rules generated from at-rules | ||
}) => SelectorWalkReturn; | ||
analyzeDeclaration: (options: { context: FeatureContext; decl: postcss.Declaration }) => void; | ||
@@ -101,2 +111,5 @@ analyzeDone: (context: FeatureContext) => void; | ||
}, | ||
analyzeSelectorDone() { | ||
/**/ | ||
}, | ||
analyzeDeclaration() { | ||
@@ -103,0 +116,0 @@ /**/ |
@@ -46,2 +46,3 @@ import { plugableRecord } from '../helpers/plugable-record'; | ||
isScoped: false, | ||
originalNode: atRule, | ||
}); | ||
@@ -48,0 +49,0 @@ const analyzed = plugableRecord.getUnsafe(context.meta.data, dataKey); |
@@ -8,2 +8,3 @@ import { createFeature } from './feature'; | ||
flattenFunctionalSelector, | ||
isCompRoot, | ||
} from '../helpers/selector'; | ||
@@ -13,3 +14,3 @@ import type { StylableMeta } from '../stylable-meta'; | ||
SelectorNode, | ||
ImmutablePseudoClass, | ||
ImmutableSelectorNode, | ||
SelectorList, | ||
@@ -19,4 +20,14 @@ PseudoClass, | ||
import { createDiagnosticReporter } from '../diagnostics'; | ||
import type * as postcss from 'postcss'; | ||
const dataKey = plugableRecord.key<Record<string, true>>('globals'); | ||
const dataKey = plugableRecord.key<{ | ||
rules: Map< | ||
postcss.Rule | postcss.AtRule, | ||
{ | ||
isGlobal: boolean; | ||
checkedRule: postcss.AtRule | postcss.Rule; | ||
topLevelSelectorsFlags: boolean[]; | ||
} | ||
>; | ||
}>('globals'); | ||
@@ -33,18 +44,63 @@ export const diagnostics = { | ||
export const hooks = createFeature<{ IMMUTABLE_SELECTOR: ImmutablePseudoClass }>({ | ||
export const hooks = createFeature<{ IMMUTABLE_SELECTOR: ImmutableSelectorNode }>({ | ||
metaInit({ meta }) { | ||
plugableRecord.set(meta.data, dataKey, {}); | ||
plugableRecord.set(meta.data, dataKey, { rules: new Map() }); | ||
}, | ||
analyzeSelectorNode({ context, node, rule }) { | ||
if (node.value !== `global`) { | ||
analyzeSelectorNode({ context, node, topSelectorIndex, rule, originalNode }) { | ||
const { rules } = plugableRecord.getUnsafe(context.meta.data, dataKey); | ||
if (node.type === 'selector' || node.type === 'combinator' || node.type === 'comment') { | ||
return; | ||
} | ||
if (node.nodes && node.nodes?.length > 1) { | ||
context.diagnostics.report(diagnostics.UNSUPPORTED_MULTI_SELECTOR_IN_GLOBAL(), { | ||
node: rule, | ||
word: stringifySelector(node.nodes), | ||
if (!rules.has(originalNode)) { | ||
rules.set(originalNode, { | ||
isGlobal: true, | ||
checkedRule: rule, | ||
topLevelSelectorsFlags: [], | ||
}); | ||
} | ||
return walkSelector.skipNested; | ||
const ruleData = rules.get(originalNode)!; | ||
if (node.type === 'pseudo_class' && node.value === `global`) { | ||
// mark selector as global only if it isn't set | ||
ruleData.topLevelSelectorsFlags[topSelectorIndex] ??= true; | ||
if (node.nodes && node.nodes?.length > 1) { | ||
context.diagnostics.report(diagnostics.UNSUPPORTED_MULTI_SELECTOR_IN_GLOBAL(), { | ||
node: rule, | ||
word: stringifySelector(node.nodes), | ||
}); | ||
} | ||
return walkSelector.skipNested; | ||
} else if (node.type === 'universal' || (node.type === 'type' && !isCompRoot(node.value))) { | ||
// mark selector as global only if it isn't set | ||
ruleData.topLevelSelectorsFlags[topSelectorIndex] ??= true; | ||
} else { | ||
// mark selector as local if it has a local selector | ||
ruleData.topLevelSelectorsFlags[topSelectorIndex] = false; | ||
} | ||
return; | ||
}, | ||
analyzeSelectorDone({ context, originalNode }) { | ||
const { rules } = plugableRecord.getUnsafe(context.meta.data, dataKey); | ||
const data = rules.get(originalNode); | ||
if (!data) { | ||
return; | ||
} | ||
// require at least one global selector in rule selectors | ||
if (!data.topLevelSelectorsFlags.find((isGlobal) => isGlobal)) { | ||
data.isGlobal = false; | ||
return; | ||
} | ||
// rule is global if it doesn't have any local parents | ||
let parent: postcss.Container | postcss.Document | undefined = originalNode.parent; | ||
while (parent) { | ||
const parentData = rules.get(parent as postcss.Rule); | ||
if (parentData) { | ||
// quick resolution: parent calculated first | ||
data.isGlobal = parentData.isGlobal; | ||
break; | ||
} | ||
// keep searching | ||
parent = parent.parent; | ||
} | ||
}, | ||
transformInit({ context }) { | ||
@@ -68,2 +124,13 @@ context.meta.globals = {}; | ||
export function getGlobalRules(meta: StylableMeta) { | ||
const { rules } = plugableRecord.getUnsafe(meta.data, dataKey); | ||
const globalRules: postcss.Rule[] = []; | ||
for (const [rule, { isGlobal, checkedRule }] of rules) { | ||
if (isGlobal && checkedRule === rule && rule.type === 'rule') { | ||
globalRules.push(rule); | ||
} | ||
} | ||
return globalRules; | ||
} | ||
export function unwrapPseudoGlobals(selectorAst: SelectorList) { | ||
@@ -70,0 +137,0 @@ const collectedGlobals: PseudoClass[] = []; |
@@ -5,3 +5,8 @@ import { createFeature, FeatureContext, FeatureTransformContext } from './feature'; | ||
import { plugableRecord } from '../helpers/plugable-record'; | ||
import { parseStImport, parsePseudoImport, parseImportMessages } from '../helpers/import'; | ||
import { | ||
parseStImport, | ||
parsePseudoImport, | ||
parseImportMessages, | ||
tryCollectImportsDeep, | ||
} from '../helpers/import'; | ||
import { validateCustomPropertyName } from '../helpers/css-custom-property'; | ||
@@ -14,2 +19,3 @@ import type { StylableMeta } from '../stylable-meta'; | ||
import type { Stylable } from '../stylable'; | ||
import type { CachedModuleEntity } from '../stylable-resolver'; | ||
@@ -95,3 +101,4 @@ export interface ImportSymbol { | ||
'error', | ||
(path: string) => `cannot resolve imported file: "${path}"` | ||
(path: string, error?: unknown) => | ||
`cannot resolve imported file: "${path}"${error ? `\nFailed with:\n${error}` : ''}` | ||
), | ||
@@ -175,2 +182,3 @@ UNKNOWN_TYPED_IMPORT: createDiagnosticReporter( | ||
validateImports(context); | ||
calcCssDepth(context); | ||
}, | ||
@@ -195,2 +203,16 @@ }); | ||
function calcCssDepth(context: FeatureTransformContext) { | ||
let cssDepth = 0; | ||
const deepDependencies = tryCollectImportsDeep( | ||
context.resolver, | ||
context.meta, | ||
new Set(), | ||
({ depth }) => { | ||
cssDepth = Math.max(cssDepth, depth); | ||
}, | ||
1 | ||
); | ||
context.meta.transformCssDepth = { cssDepth, deepDependencies }; | ||
} | ||
function isImportStatement(node: postcss.ChildNode): node is postcss.Rule | postcss.AtRule { | ||
@@ -273,5 +295,4 @@ return ( | ||
for (const importObj of imports) { | ||
const resolvedImport = context.resolver.resolveImported(importObj, ''); | ||
if (!resolvedImport) { | ||
const entity = context.resolver.getModule(importObj); | ||
if (!entity.value) { | ||
// warn about unknown imported files | ||
@@ -284,11 +305,15 @@ const fromDecl = | ||
context.diagnostics.report(diagnostics.UNKNOWN_IMPORTED_FILE(importObj.request), { | ||
node: fromDecl || importObj.rule, | ||
word: importObj.request, | ||
}); | ||
} else if (resolvedImport._kind === 'css') { | ||
context.diagnostics.report( | ||
diagnostics.UNKNOWN_IMPORTED_FILE(importObj.request, getErrorText(entity)), | ||
{ | ||
node: fromDecl || importObj.rule, | ||
word: importObj.request, | ||
} | ||
); | ||
} else if (entity.kind === 'css') { | ||
const meta = entity.value; | ||
// propagate some native CSS diagnostics to st-import | ||
if (resolvedImport.meta.type === 'css') { | ||
if (meta.type === 'css') { | ||
let foundUnsupportedNativeImport = false; | ||
for (const report of resolvedImport.meta.diagnostics.reports) { | ||
for (const report of meta.diagnostics.reports) { | ||
if (report.code === '05021') { | ||
@@ -307,3 +332,3 @@ foundUnsupportedNativeImport = true; | ||
// report unsupported native CSS default import | ||
if (resolvedImport.meta.type !== 'stylable' && importObj.defaultExport) { | ||
if (meta.type !== 'stylable' && importObj.defaultExport) { | ||
context.diagnostics.report(diagnostics.NO_DEFAULT_EXPORT(importObj.request), { | ||
@@ -331,4 +356,21 @@ node: importObj.rule, | ||
} | ||
} else if (entity.kind === 'js') { | ||
// TODO: add diagnostics for JS imports (typeof checks) | ||
} | ||
} | ||
} | ||
function getErrorText(res: CachedModuleEntity) { | ||
if ('error' in res) { | ||
const { error } = res; | ||
if (typeof error === 'object' && error) { | ||
return 'details' in error | ||
? String(error.details) | ||
: 'message' in error | ||
? String(error.message) | ||
: String(error); | ||
} | ||
return String(error); | ||
} | ||
return ''; | ||
} |
@@ -34,2 +34,3 @@ import { createFeature } from './feature'; | ||
isScoped: true, | ||
originalNode: atRule, | ||
} | ||
@@ -36,0 +37,0 @@ ); |
@@ -9,3 +9,2 @@ import path from 'path'; | ||
import type { ParsedValue } from '../types'; | ||
import type { Stylable } from '../stylable'; | ||
import type { StylableMeta } from '../stylable-meta'; | ||
@@ -17,2 +16,3 @@ import type * as postcss from 'postcss'; | ||
} from 'postcss-value-parser'; | ||
import type { StylableResolver } from '../stylable-resolver'; | ||
@@ -585,16 +585,32 @@ export const parseImportMessages = { | ||
type ImportEvent = { | ||
context: string; | ||
request: string; | ||
resolved: string; | ||
depth: number; | ||
}; | ||
export function tryCollectImportsDeep( | ||
stylable: Stylable, | ||
resolver: StylableResolver, | ||
meta: StylableMeta, | ||
imports = new Set<string>() | ||
imports = new Set<string>(), | ||
onImport: undefined | ((e: ImportEvent) => void) = undefined, | ||
depth = 0 | ||
) { | ||
for (const { context, request } of meta.getImportStatements()) { | ||
try { | ||
const resolved = stylable.resolver.resolvePath(context, request); | ||
const resolved = resolver.resolvePath(context, request); | ||
onImport?.({ context, request, resolved, depth }); | ||
if (!imports.has(resolved)) { | ||
imports.add(resolved); | ||
tryCollectImportsDeep(stylable, stylable.analyze(resolved), imports); | ||
tryCollectImportsDeep( | ||
resolver, | ||
resolver.analyze(resolved), | ||
imports, | ||
onImport, | ||
depth + 1 | ||
); | ||
} | ||
} catch (e) { | ||
} catch { | ||
/** */ | ||
@@ -601,0 +617,0 @@ } |
@@ -12,3 +12,3 @@ export { safeParse } from './parser'; | ||
export { validateDefaultConfig } from './stylable'; | ||
export { STCustomSelector, STCustomState } from './features'; | ||
export { STSymbol, STGlobal, STCustomSelector, STCustomState, CSSCustomProperty } from './features'; | ||
export type { MappedStates, StateParsedValue } from './helpers/custom-state'; | ||
@@ -23,3 +23,3 @@ export { murmurhash3_32_gc } from './murmurhash'; | ||
} from './native-reserved-lists'; | ||
export { isAsset, makeAbsolute, isRelativeNativeCss } from './stylable-assets'; | ||
export { isAsset, makeAbsolute, isRelativeNativeCss, fixRelativeUrls } from './stylable-assets'; | ||
export { namespace, namespaceDelimiter } from './helpers/namespace'; | ||
@@ -26,0 +26,0 @@ export { |
@@ -52,2 +52,3 @@ import type * as postcss from 'postcss'; | ||
public urls: string[] = []; | ||
public transformCssDepth: { cssDepth: number; deepDependencies: Set<string> } | undefined; | ||
public transformDiagnostics: Diagnostics | null = null; | ||
@@ -54,0 +55,0 @@ public transformedScopes: Record<string, SelectorList> | null = null; |
@@ -96,5 +96,12 @@ import type * as postcss from 'postcss'; | ||
protected handleAtRules(root: postcss.Root) { | ||
const analyzeRule = (rule: postcss.Rule, { isScoped }: { isScoped: boolean }) => { | ||
const analyzeRule = ( | ||
rule: postcss.Rule, | ||
{ | ||
isScoped, | ||
originalNode, | ||
}: { isScoped: boolean; originalNode: postcss.AtRule | postcss.Rule } | ||
) => { | ||
return this.handleRule(rule, { | ||
isScoped, | ||
originalNode, | ||
reportUnscoped: false, | ||
@@ -193,3 +200,11 @@ }); | ||
rule: postcss.Rule, | ||
{ isScoped, reportUnscoped }: { isScoped: boolean; reportUnscoped: boolean } | ||
{ | ||
isScoped, | ||
reportUnscoped, | ||
originalNode = rule, | ||
}: { | ||
isScoped: boolean; | ||
reportUnscoped: boolean; | ||
originalNode?: postcss.AtRule | postcss.Rule; | ||
} | ||
) { | ||
@@ -199,3 +214,3 @@ const selectorAst = parseSelectorWithCache(rule.selector); | ||
let locallyScoped = isScoped; | ||
let topSelectorIndex = -1; | ||
walkSelector(selectorAst, (node, ...nodeContext) => { | ||
@@ -207,4 +222,17 @@ const [index, nodes, parents] = nodeContext; | ||
locallyScoped = isScoped; | ||
topSelectorIndex++; | ||
} | ||
const walkSkip = STGlobal.hooks.analyzeSelectorNode({ | ||
context: this, | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
}); | ||
if (walkSkip !== undefined) { | ||
return walkSkip; | ||
} | ||
if (node.type === 'pseudo_class') { | ||
@@ -215,3 +243,5 @@ if (node.value === 'import') { | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
@@ -223,12 +253,7 @@ }); | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
}); | ||
} else if (node.value === `global`) { | ||
return STGlobal.hooks.analyzeSelectorNode({ | ||
context: this, | ||
node, | ||
rule, | ||
walkContext: nodeContext, | ||
}); | ||
} else if (node.value.startsWith('--')) { | ||
@@ -247,3 +272,5 @@ // ToDo: move to css-class feature | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
@@ -266,3 +293,5 @@ }); | ||
node, | ||
topSelectorIndex, | ||
rule, | ||
originalNode, | ||
walkContext: nodeContext, | ||
@@ -316,3 +345,7 @@ }); | ||
}); | ||
STGlobal.hooks.analyzeSelectorDone({ | ||
context: this, | ||
rule, | ||
originalNode, | ||
}); | ||
return locallyScoped; | ||
@@ -319,0 +352,0 @@ } |
@@ -122,3 +122,3 @@ import type { FileProcessor } from './cached-process-file'; | ||
) {} | ||
private getModule({ context, request }: Imported): CachedModuleEntity { | ||
public getModule({ context, request }: Imported): CachedModuleEntity { | ||
let entity: CachedModuleEntity; | ||
@@ -173,2 +173,5 @@ let resolvedPath: string | undefined; | ||
} | ||
public analyze(filePath: string) { | ||
return this.fileProcessor.process(filePath); | ||
} | ||
public resolvePath(directoryPath: string, request: string): string { | ||
@@ -318,3 +321,2 @@ const key = cacheKey(directoryPath, request); | ||
} | ||
public resolveSymbols(meta: StylableMeta, diagnostics: Diagnostics) { | ||
@@ -321,0 +323,0 @@ const resolvedSymbols: MetaResolvedSymbols = { |
@@ -125,3 +125,2 @@ import isVendorPrefixed from 'is-vendor-prefixed'; | ||
private getResolvedSymbols: ReturnType<typeof createSymbolResolverWithCache>; | ||
constructor(options: TransformerOptions) { | ||
@@ -128,0 +127,0 @@ this.diagnostics = options.diagnostics; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1185052
21325
1
Updatedenhanced-resolve@^5.12.0