@stylable/core
Advanced tools
Comparing version 4.0.0-alpha.10 to 4.0.0
{ | ||
"name": "@stylable/core", | ||
"version": "4.0.0-alpha.10", | ||
"version": "4.0.0", | ||
"description": "CSS for Components", | ||
"main": "./cjs/index.js", | ||
"types": "./cjs/index.d.ts", | ||
"main": "dist/index.js", | ||
"scripts": { | ||
"clean": "rimraf ./cjs", | ||
"build": "ts-build ./src --cjs", | ||
"test": "mocha \"./test/**/*.spec.ts\"", | ||
"start": "webpack serve", | ||
"prepack": "yarn build" | ||
"test": "mocha \"./dist/test/**/*.spec.js\"", | ||
"start": "webpack serve" | ||
}, | ||
@@ -23,4 +19,3 @@ "dependencies": { | ||
"lodash.clonedeepwith": "^4.5.0", | ||
"murmurhash": "^2.0.0", | ||
"postcss": "^8.2.4", | ||
"postcss": "^8.2.6", | ||
"postcss-js": "^3.0.3", | ||
@@ -30,9 +25,10 @@ "postcss-nested": "^5.0.3", | ||
"postcss-selector-matches": "^4.0.0", | ||
"postcss-value-parser": "^4.1.0" | ||
"postcss-value-parser": "^4.1.0", | ||
"toky": "^0.1.0" | ||
}, | ||
"files": [ | ||
"cjs", | ||
"dist", | ||
"!dist/test", | ||
"src", | ||
"test-utils.js", | ||
"test-utils.d.ts" | ||
"!*/tsconfig.{json,tsbuildinfo}" | ||
], | ||
@@ -48,4 +44,3 @@ "engines": { | ||
"author": "Wix.com", | ||
"license": "BSD-3-Clause", | ||
"gitHead": "73175a1223e30b7900e26953215abbf9ae297937" | ||
"license": "BSD-3-Clause" | ||
} |
@@ -0,0 +0,0 @@ # @stylable/core |
@@ -0,0 +0,0 @@ export type processFn<T> = (fullpath: string, content: string) => T; |
@@ -7,3 +7,3 @@ import path from 'path'; | ||
import { createDefaultResolver } from './module-resolver'; | ||
import { Diagnostics } from './diagnostics'; | ||
import type { Diagnostics } from './diagnostics'; | ||
@@ -27,6 +27,3 @@ export interface StylableInfrastructure { | ||
let resolvePath = (context: string | undefined = projectRoot, moduleId: string) => { | ||
if (!path.isAbsolute(moduleId) && !moduleId.startsWith('.')) { | ||
moduleId = resolveModule(context, moduleId); | ||
} | ||
return moduleId; | ||
return path.isAbsolute(moduleId) ? moduleId : resolveModule(context, moduleId); | ||
}; | ||
@@ -33,0 +30,0 @@ |
import { extract, parseWithComments } from 'jest-docblock'; | ||
import { StylableMeta, StylableSymbol } from './stylable-meta'; | ||
import type { StylableMeta, StylableSymbol } from './stylable-meta'; | ||
@@ -4,0 +4,0 @@ export interface CssDoc { |
import cloneDeepWith from 'lodash.clonedeepwith'; | ||
import postcssValueParser from 'postcss-value-parser'; | ||
import { StylableMeta } from './stylable-meta'; | ||
import { StylableResolver } from './stylable-resolver'; | ||
import type { StylableMeta } from './stylable-meta'; | ||
import type { StylableResolver } from './stylable-resolver'; | ||
import { getFormatterArgs, getNamedArgs, getStringValue } from './stylable-value-parsers'; | ||
import { ParsedValue } from './types'; | ||
import type { ParsedValue } from './types'; | ||
@@ -8,0 +8,0 @@ export interface Box<Type extends string, Value extends any> { |
@@ -1,2 +0,2 @@ | ||
import * as postcss from 'postcss'; | ||
import type * as postcss from 'postcss'; | ||
@@ -3,0 +3,0 @@ export type DiagnosticType = 'error' | 'warning'; |
import { dirname, relative } from 'path'; | ||
import postcssValueParser from 'postcss-value-parser'; | ||
import * as postcss from 'postcss'; | ||
import type * as postcss from 'postcss'; | ||
import { resolveCustomValues } from './custom-values'; | ||
import { Diagnostics } from './diagnostics'; | ||
import type { Diagnostics } from './diagnostics'; | ||
import { isCssNativeFunction } from './native-reserved-lists'; | ||
import { assureRelativeUrlPrefix } from './stylable-assets'; | ||
import { StylableMeta } from './stylable-processor'; | ||
import { CSSResolve, JSResolve, StylableResolver } from './stylable-resolver'; | ||
import { replaceValueHook, StylableTransformer } from './stylable-transformer'; | ||
import type { StylableMeta } from './stylable-processor'; | ||
import type { CSSResolve, JSResolve, StylableResolver } from './stylable-resolver'; | ||
import type { replaceValueHook, StylableTransformer } from './stylable-transformer'; | ||
import { isCSSVarProp } from './stylable-utils'; | ||
@@ -18,3 +18,3 @@ import { | ||
} from './stylable-value-parsers'; | ||
import { ParsedValue } from './types'; | ||
import type { ParsedValue } from './types'; | ||
import { stripQuotation } from './utils'; | ||
@@ -21,0 +21,0 @@ |
@@ -25,4 +25,6 @@ export { safeParse } from './parser'; | ||
export * from './visit-meta-css-dependencies'; | ||
export * from './murmurhash'; | ||
export * from './timed-cache'; | ||
import * as pseudoStates from './pseudo-states'; | ||
export { pseudoStates }; |
import { dirname } from 'path'; | ||
import deindent from 'deindent'; | ||
import { MinimalFS } from './cached-process-file'; | ||
import type { MinimalFS } from './cached-process-file'; | ||
@@ -5,0 +5,0 @@ export interface File { |
@@ -5,4 +5,4 @@ // importing the factory directly, as we feed it our own fs, and don't want graceful-fs to be implicitly imported | ||
import { ModuleResolver } from './types'; | ||
import { MinimalFS } from './cached-process-file'; | ||
import type { ModuleResolver } from './types'; | ||
import type { MinimalFS } from './cached-process-file'; | ||
@@ -23,3 +23,3 @@ const resolverContext = {}; | ||
throw new Error( | ||
`Stylable does not support browser field 'false' values. ${request} resolved to 'false'` | ||
`Stylable does not support browser field 'false' values. ${request} resolved to 'false' from ${directoryPath}` | ||
); | ||
@@ -26,0 +26,0 @@ } |
@@ -97,2 +97,3 @@ // MDN reference: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes | ||
export const nativeFunctionsDic = { | ||
annotation: true, | ||
attr: true, | ||
@@ -102,3 +103,6 @@ blur: true, | ||
calc: true, | ||
'character-variant': true, | ||
circle: true, | ||
clamp: true, | ||
'conic-gradient': true, | ||
constant: true, | ||
@@ -112,2 +116,3 @@ contrast: true, | ||
env: true, | ||
'fit-content': true, | ||
format: true, | ||
@@ -122,2 +127,3 @@ grayscale: true, | ||
invert: true, | ||
leader: true, | ||
'linear-gradient': true, | ||
@@ -127,4 +133,7 @@ local: true, | ||
matrix3d: true, | ||
max: true, | ||
min: true, | ||
minmax: true, | ||
opacity: true, | ||
ornaments: true, | ||
paint: true, | ||
@@ -139,2 +148,3 @@ path: true, | ||
'repeating-radial-gradient': true, | ||
'repeating-conic-gradient': true, | ||
rgb: true, | ||
@@ -148,3 +158,2 @@ rgba: true, | ||
saturate: true, | ||
sepia: true, | ||
scale: true, | ||
@@ -155,5 +164,10 @@ scale3d: true, | ||
scaleZ: true, | ||
sepia: true, | ||
skew: true, | ||
skewX: true, | ||
skewY: true, | ||
steps: true, | ||
styleset: true, | ||
stylistic: true, | ||
swash: true, | ||
symbols: true, | ||
@@ -160,0 +174,0 @@ translate: true, |
@@ -5,3 +5,3 @@ import postcss, { ProcessOptions, Root } from 'postcss'; | ||
import safeParser from 'postcss-safe-parser'; | ||
import { CSSObject } from './types'; | ||
import type { CSSObject } from './types'; | ||
@@ -8,0 +8,0 @@ const processor = postcss([postcssNested()]); |
@@ -1,25 +0,15 @@ | ||
import * as postcss from 'postcss'; | ||
import type * as postcss from 'postcss'; | ||
import postcssValueParser from 'postcss-value-parser'; | ||
import isVendorPrefixed from 'is-vendor-prefixed'; | ||
import { Diagnostics } from './diagnostics'; | ||
import type { Diagnostics } from './diagnostics'; | ||
import { evalDeclarationValue } from './functions'; | ||
import { nativePseudoClasses } from './native-reserved-lists'; | ||
import { SelectorAstNode } from './selector-utils'; | ||
import type { SelectorAstNode } from './selector-utils'; | ||
import { StateResult, systemValidators } from './state-validators'; | ||
import { | ||
ClassSymbol, | ||
ElementSymbol, | ||
SRule, | ||
StylableMeta, | ||
StylableSymbol, | ||
} from './stylable-processor'; | ||
import { StylableResolver } from './stylable-resolver'; | ||
import type { SRule, StylableMeta } from './stylable-processor'; | ||
import type { StylableResolver } from './stylable-resolver'; | ||
import { isValidClassName } from './stylable-utils'; | ||
import { groupValues, listOptions, MappedStates } from './stylable-value-parsers'; | ||
import { valueMapping } from './stylable-value-parsers'; | ||
import { ParsedValue, StateParsedValue } from './types'; | ||
import type { ParsedValue, StateParsedValue } from './types'; | ||
import { stripQuotation } from './utils'; | ||
const { hasOwnProperty } = Object.prototype; | ||
export const stateMiddleDelimiter = '-'; | ||
@@ -268,83 +258,2 @@ export const booleanStateDelimiter = '--'; | ||
export function transformPseudoStateSelector( | ||
meta: StylableMeta, | ||
node: SelectorAstNode, | ||
name: string, | ||
symbol: StylableSymbol | null, | ||
origin: StylableMeta, | ||
originSymbol: ClassSymbol | ElementSymbol, | ||
resolver: StylableResolver, | ||
diagnostics: Diagnostics, | ||
rule?: postcss.Rule | ||
) { | ||
let current = meta; | ||
let currentSymbol = symbol; | ||
if (originSymbol && symbol !== originSymbol) { | ||
current = origin; | ||
currentSymbol = originSymbol; | ||
} | ||
let found = false; | ||
while (current && currentSymbol) { | ||
if (currentSymbol._kind === 'class' || currentSymbol._kind === 'element') { | ||
const states = currentSymbol[valueMapping.states]; | ||
const extend = currentSymbol[valueMapping.extends]; | ||
const alias = currentSymbol.alias; | ||
if (states && hasOwnProperty.call(states, name)) { | ||
found = true; | ||
setStateToNode( | ||
states, | ||
meta, | ||
name, | ||
node, | ||
current.namespace, | ||
resolver, | ||
diagnostics, | ||
rule | ||
); | ||
break; | ||
} else if (extend) { | ||
if ( | ||
current.mappedSymbols[extend.name] && | ||
current.mappedSymbols[extend.name]._kind !== 'import' | ||
) { | ||
const nextCurrentSymbol = current.mappedSymbols[extend.name]; | ||
if (currentSymbol === nextCurrentSymbol) { | ||
break; | ||
} | ||
currentSymbol = nextCurrentSymbol; | ||
} else { | ||
const next = resolver.resolve(extend); | ||
if (next && next.meta) { | ||
currentSymbol = next.symbol; | ||
current = next.meta; | ||
} else { | ||
break; | ||
} | ||
} | ||
} else if (alias) { | ||
const next = resolver.resolve(alias); | ||
if (next && next.meta) { | ||
currentSymbol = next.symbol; | ||
current = next.meta; | ||
} else { | ||
break; | ||
} | ||
} else { | ||
break; | ||
} | ||
} else { | ||
break; | ||
} | ||
} | ||
if (!found && rule) { | ||
if (!nativePseudoClasses.includes(name) && !isVendorPrefixed(name)) { | ||
diagnostics.warn(rule, stateErrors.UNKNOWN_STATE_USAGE(name), { word: name }); | ||
} | ||
} | ||
return meta; | ||
} | ||
export function setStateToNode( | ||
@@ -351,0 +260,0 @@ states: MappedStates, |
@@ -1,2 +0,2 @@ | ||
import { StylableMeta } from './stylable-processor'; | ||
import type { StylableMeta } from './stylable-processor'; | ||
@@ -8,5 +8,9 @@ export interface EmitDiagnosticsContext { | ||
export type DiagnosticsMode = 'auto' | 'strict' | 'loose'; | ||
/** | ||
* Helper function to report diagnostics for every diagnosticsMode | ||
*/ | ||
function reportDiagnostic( | ||
ctx: EmitDiagnosticsContext, | ||
diagnosticsMode: 'auto' | 'strict' | 'loose', | ||
diagnosticsMode: DiagnosticsMode, | ||
{ message, type }: { message: string; type: 'warning' | 'error' } | ||
@@ -30,10 +34,10 @@ ) { | ||
meta: StylableMeta, | ||
diagnosticsMode: 'auto' | 'strict' | 'loose' | ||
diagnosticsMode: DiagnosticsMode | ||
) { | ||
meta.diagnostics?.reports.forEach((diagnostic) => { | ||
reportDiagnostic(ctx, diagnosticsMode, diagnostic); | ||
}); | ||
meta.transformDiagnostics?.reports.forEach((diagnostic) => { | ||
reportDiagnostic(ctx, diagnosticsMode, diagnostic); | ||
}); | ||
meta.diagnostics?.reports.forEach((diagnostic) => | ||
reportDiagnostic(ctx, diagnosticsMode, diagnostic) | ||
); | ||
meta.transformDiagnostics?.reports.forEach((diagnostic) => | ||
reportDiagnostic(ctx, diagnosticsMode, diagnostic) | ||
); | ||
} |
@@ -1,3 +0,3 @@ | ||
import hash from 'murmurhash'; | ||
import { processNamespace } from './stylable-processor'; | ||
import { murmurhash3_32_gc } from './murmurhash'; | ||
import type { processNamespace } from './stylable-processor'; | ||
@@ -25,3 +25,3 @@ export function packageNamespaceFactory( | ||
namespace + | ||
hash.v3( | ||
murmurhash3_32_gc( | ||
hashSalt + config.name + '@' + normalizeVersion(config.version) + '/' + fromRoot | ||
@@ -28,0 +28,0 @@ ) |
import * as postcss from 'postcss'; | ||
import cssSelectorTokenizer from 'css-selector-tokenizer'; | ||
import { ClassSymbol, ElementSymbol } from './stylable-meta'; | ||
import { CSSResolve } from './stylable-resolver'; | ||
import type { ClassSymbol, ElementSymbol } from './stylable-meta'; | ||
import type { CSSResolve } from './stylable-resolver'; | ||
import { valueMapping } from './stylable-value-parsers'; | ||
@@ -6,0 +6,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { StateArguments } from './types'; | ||
import type { StateArguments } from './types'; | ||
@@ -3,0 +3,0 @@ export interface StateResult { |
import path from 'path'; | ||
import * as postcss from 'postcss'; | ||
import type * as postcss from 'postcss'; | ||
import isUrl from 'is-url-superb'; | ||
import cssSelectorTokenizer from 'css-selector-tokenizer'; | ||
import { ParsedValue } from './types'; | ||
import type { ParsedValue } from './types'; | ||
@@ -7,0 +7,0 @@ const { parseValues, stringifyValues } = cssSelectorTokenizer; |
@@ -1,4 +0,4 @@ | ||
import * as postcss from 'postcss'; | ||
import { Diagnostics } from './diagnostics'; | ||
import { SelectorAstNode, SelectorChunk2 } from './selector-utils'; | ||
import type * as postcss from 'postcss'; | ||
import type { Diagnostics } from './diagnostics'; | ||
import type { SelectorAstNode, SelectorChunk2 } from './selector-utils'; | ||
import { getSourcePath } from './stylable-utils'; | ||
@@ -70,4 +70,4 @@ import { MappedStates, MixinValue, valueMapping } from './stylable-value-parsers'; | ||
keyframes: Record<string, string>; | ||
rule: postcss.Rule; | ||
fromRelative: string; | ||
rule: postcss.Rule | postcss.AtRule; | ||
request: string; | ||
context: string; | ||
@@ -74,0 +74,0 @@ } |
@@ -7,6 +7,6 @@ import { dirname } from 'path'; | ||
import { fixRelativeUrls } from './stylable-assets'; | ||
import { ImportSymbol } from './stylable-meta'; | ||
import { RefedMixin, SRule, StylableMeta } from './stylable-processor'; | ||
import { CSSResolve } from './stylable-resolver'; | ||
import { StylableTransformer } from './stylable-transformer'; | ||
import type { ImportSymbol } from './stylable-meta'; | ||
import type { RefedMixin, SRule, StylableMeta } from './stylable-processor'; | ||
import type { CSSResolve } from './stylable-resolver'; | ||
import type { StylableTransformer } from './stylable-transformer'; | ||
import { createSubsetAst, isValidDeclaration, mergeRules } from './stylable-utils'; | ||
@@ -13,0 +13,0 @@ import { valueMapping, mixinDeclRegExp } from './stylable-value-parsers'; |
@@ -1,5 +0,6 @@ | ||
import hash from 'murmurhash'; | ||
import { murmurhash3_32_gc } from './murmurhash'; | ||
import path from 'path'; | ||
import * as postcss from 'postcss'; | ||
import postcssValueParser from 'postcss-value-parser'; | ||
import { tokenizeImports } from 'toky'; | ||
import { Diagnostics } from './diagnostics'; | ||
@@ -119,2 +120,14 @@ import { | ||
}, | ||
NO_ST_IMPORT_IN_NESTED_SCOPE() { | ||
return `cannot use "@st-import" inside of nested scope`; | ||
}, | ||
ST_IMPORT_STAR() { | ||
return '@st-import * is not supported'; | ||
}, | ||
ST_IMPORT_EMPTY_FROM() { | ||
return '@st-import must specify a valid "from" string value'; | ||
}, | ||
INVALID_ST_IMPORT_FORMAT(errors: string[]) { | ||
return `Invalid @st-import format:\n - ${errors.join('\n - ')}`; | ||
}, | ||
NO_KEYFRAMES_IN_ST_SCOPE() { | ||
@@ -142,2 +155,3 @@ return `cannot use "@keyframes" inside of "@st-scope"`; | ||
protected meta!: StylableMeta; | ||
protected dirContext!: string; | ||
constructor( | ||
@@ -150,2 +164,4 @@ protected diagnostics = new Diagnostics(), | ||
this.dirContext = path.dirname(this.meta.source); | ||
this.handleAtRules(root); | ||
@@ -182,22 +198,6 @@ | ||
this.meta.scopes.forEach((atRule) => { | ||
const scopingRule = postcss.rule({ selector: atRule.params }) as SRule; | ||
this.handleRule(scopingRule, true); | ||
validateScopingSelector(atRule, scopingRule, this.diagnostics); | ||
stubs.forEach((s) => s && s.remove()); | ||
if (scopingRule.selector) { | ||
atRule.walkRules((rule) => { | ||
const scopedRule = rule.clone({ | ||
selector: scopeSelector(scopingRule.selector, rule.selector, false) | ||
.selector, | ||
}); | ||
(scopedRule as SRule).stScopeSelector = atRule.params; | ||
rule.replaceWith(scopedRule); | ||
}); | ||
} | ||
this.meta.scopes.forEach((scope) => this.handleScope(scope)); | ||
atRule.replaceWith(atRule.nodes || []); | ||
}); | ||
stubs.forEach((s) => s && s.remove()); | ||
return this.meta; | ||
@@ -270,2 +270,16 @@ } | ||
break; | ||
case 'st-import': | ||
if (atRule.parent?.type !== 'root') { | ||
this.diagnostics.warn( | ||
atRule, | ||
processorWarnings.NO_ST_IMPORT_IN_NESTED_SCOPE() | ||
); | ||
atRule.remove(); | ||
} else { | ||
const _import = this.handleStImport(atRule); | ||
this.meta.imports.push(_import); | ||
this.addImportSymbols(_import); | ||
} | ||
break; | ||
case 'st-global-custom-property': { | ||
@@ -345,3 +359,3 @@ const cssVarsByComma = atRule.params.split(','); | ||
traverseNode(rule.selectorAst, (node, _index, _nodes) => { | ||
traverseNode(rule.selectorAst, (node, index, nodes) => { | ||
if (node.type === 'selector') { | ||
@@ -363,5 +377,5 @@ locallyScoped = false; | ||
const _import = this.handleImport(rule); | ||
this.meta.imports.push(_import); | ||
this.addImportSymbols(_import); | ||
const imported = this.handleImport(rule); | ||
this.meta.imports.push(imported); | ||
this.addImportSymbols(imported); | ||
return false; | ||
@@ -405,3 +419,3 @@ } else { | ||
} else if (locallyScoped === false && !inStScope) { | ||
if (this.checkForScopedNodeAfter(rule, _nodes, _index) === false) { | ||
if (this.checkForScopedNodeAfter(rule, nodes, index) === false) { | ||
this.diagnostics.warn(rule, processorWarnings.UNSCOPED_CLASS(name), { | ||
@@ -419,3 +433,3 @@ word: name, | ||
if (locallyScoped === false && !inStScope) { | ||
if (this.checkForScopedNodeAfter(rule, _nodes, _index) === false) { | ||
if (this.checkForScopedNodeAfter(rule, nodes, index) === false) { | ||
this.diagnostics.warn(rule, processorWarnings.UNSCOPED_ELEMENT(name), { | ||
@@ -543,3 +557,3 @@ word: name, | ||
import: importDef, | ||
context: path.dirname(this.meta.source), | ||
context: this.dirContext, | ||
}; | ||
@@ -554,3 +568,3 @@ } | ||
import: importDef, | ||
context: path.dirname(this.meta.source), | ||
context: this.dirContext, | ||
}; | ||
@@ -783,3 +797,47 @@ }); | ||
} | ||
protected handleStImport(atRule: postcss.AtRule) { | ||
const importObj: Imported = { | ||
defaultExport: '', | ||
from: '', | ||
request: '', | ||
named: {}, | ||
rule: atRule, | ||
context: this.dirContext, | ||
keyframes: {}, | ||
}; | ||
const imports = tokenizeImports(`import ${atRule.params}`, '[', ']', true)[0]; | ||
if (imports && imports.star) { | ||
this.diagnostics.error(atRule, processorWarnings.ST_IMPORT_STAR()); | ||
} else { | ||
importObj.defaultExport = imports.defaultName || ''; | ||
setImportObjectFrom(imports.from || '', this.dirContext, importObj); | ||
if (imports.tagged?.keyframes) { | ||
// importObj.keyframes = imports.tagged?.keyframes; | ||
for (const [impName, impAsName] of Object.entries(imports.tagged.keyframes)) { | ||
importObj.keyframes[impAsName] = impName; | ||
} | ||
} | ||
if (imports.named) { | ||
for (const [impName, impAsName] of Object.entries(imports.named)) { | ||
importObj.named[impAsName] = impName; | ||
} | ||
} | ||
if (imports.errors.length) { | ||
this.diagnostics.error( | ||
atRule, | ||
processorWarnings.INVALID_ST_IMPORT_FORMAT(imports.errors) | ||
); | ||
} else if (!imports.from?.trim()) { | ||
this.diagnostics.error(atRule, processorWarnings.ST_IMPORT_EMPTY_FROM()); | ||
} | ||
} | ||
atRule.remove(); | ||
return importObj; | ||
} | ||
protected handleImport(rule: postcss.Rule) { | ||
@@ -790,7 +848,7 @@ let fromExists = false; | ||
from: '', | ||
fromRelative: '', | ||
request: '', | ||
named: {}, | ||
keyframes: {}, | ||
rule, | ||
context: path.dirname(this.meta.source), | ||
context: this.dirContext, | ||
}; | ||
@@ -810,14 +868,3 @@ | ||
if (!path.isAbsolute(importPath) && !importPath.startsWith('.')) { | ||
// 3rd party request | ||
importObj.fromRelative = importPath; | ||
importObj.from = importPath; | ||
} else { | ||
importObj.fromRelative = importPath; | ||
const dirPath = path.dirname(this.meta.source); | ||
importObj.from = | ||
path.posix && path.posix.isAbsolute(dirPath) // browser has no posix methods | ||
? path.posix.resolve(dirPath, importPath) | ||
: path.resolve(dirPath, importPath); | ||
} | ||
setImportObjectFrom(importPath, this.dirContext, importObj); | ||
fromExists = true; | ||
@@ -866,4 +913,34 @@ break; | ||
} | ||
private handleScope(atRule: postcss.AtRule) { | ||
const scopingRule = postcss.rule({ selector: atRule.params }) as SRule; | ||
this.handleRule(scopingRule, true); | ||
validateScopingSelector(atRule, scopingRule, this.diagnostics); | ||
if (scopingRule.selector) { | ||
atRule.walkRules((rule) => { | ||
const scopedRule = rule.clone({ | ||
selector: scopeSelector(scopingRule.selector, rule.selector, false).selector, | ||
}); | ||
(scopedRule as SRule).stScopeSelector = atRule.params; | ||
rule.replaceWith(scopedRule); | ||
}); | ||
} | ||
atRule.replaceWith(atRule.nodes || []); | ||
} | ||
} | ||
function setImportObjectFrom(importPath: string, dirPath: string, importObj: Imported) { | ||
if (!path.isAbsolute(importPath) && !importPath.startsWith('.')) { | ||
importObj.request = importPath; | ||
importObj.from = importPath; | ||
} else { | ||
importObj.request = importPath; | ||
importObj.from = | ||
path.posix && path.posix.isAbsolute(dirPath) // browser has no posix methods | ||
? path.posix.resolve(dirPath, importPath) | ||
: path.resolve(dirPath, importPath); | ||
} | ||
} | ||
export function validateScopingSelector( | ||
@@ -887,3 +964,3 @@ atRule: postcss.AtRule, | ||
export function processNamespace(namespace: string, source: string) { | ||
return namespace + hash.v3(source); // .toString(36); | ||
return namespace + murmurhash3_32_gc(source); // .toString(36); | ||
} | ||
@@ -890,0 +967,0 @@ |
@@ -1,6 +0,6 @@ | ||
import { FileProcessor } from './cached-process-file'; | ||
import { Diagnostics } from './diagnostics'; | ||
import { ClassSymbol, ElementSymbol, Imported } from './stylable-meta'; | ||
import { ImportSymbol, StylableMeta, StylableSymbol } from './stylable-processor'; | ||
import { StylableTransformer } from './stylable-transformer'; | ||
import type { FileProcessor } from './cached-process-file'; | ||
import type { Diagnostics } from './diagnostics'; | ||
import type { ClassSymbol, ElementSymbol, Imported } from './stylable-meta'; | ||
import type { ImportSymbol, StylableMeta, StylableSymbol } from './stylable-processor'; | ||
import type { StylableTransformer } from './stylable-transformer'; | ||
import { valueMapping } from './stylable-value-parsers'; | ||
@@ -17,2 +17,9 @@ | ||
export type JsModule = { | ||
default?: unknown; | ||
[key: string]: unknown; | ||
}; | ||
export type CachedModule = StylableMeta | JsModule | null; | ||
export type StylableResolverCache = Map<string, StylableMeta | JsModule | null>; | ||
export interface CSSResolve<T extends StylableSymbol = StylableSymbol> { | ||
@@ -39,33 +46,59 @@ _kind: 'css'; | ||
// this is a safe cache key delimiter for all OS; | ||
const safePathDelimiter = ';:'; | ||
export class StylableResolver { | ||
constructor( | ||
protected fileProcessor: FileProcessor<StylableMeta>, | ||
protected requireModule: (modulePath: string) => any | ||
protected requireModule: (modulePath: string) => any, | ||
protected cache?: StylableResolverCache | ||
) {} | ||
public resolveImported(imported: Imported, name: string) { | ||
const { context, from } = imported; | ||
let symbol: StylableSymbol; | ||
private getModule({ context, from }: Imported): CachedModule { | ||
const key = `${context}${safePathDelimiter}${from}`; | ||
if (this.cache?.has(key)) { | ||
return this.cache.get(key)!; | ||
} | ||
let res; | ||
if (from.match(/\.css$/)) { | ||
let meta; | ||
try { | ||
meta = this.fileProcessor.process(from, false, context); | ||
symbol = !name | ||
? meta.mappedSymbols[meta.root] | ||
: meta.mappedSymbols[name] || meta.mappedKeyframes[name]; | ||
res = this.fileProcessor.process(from, false, context); | ||
} catch (e) { | ||
return null; | ||
res = null; | ||
} | ||
return { _kind: 'css', symbol, meta } as CSSResolve; | ||
} else { | ||
let _module; | ||
try { | ||
_module = this.requireModule(this.fileProcessor.resolvePath(from)); | ||
res = this.requireModule(this.fileProcessor.resolvePath(from, context)); | ||
} catch { | ||
return null; | ||
res = null; | ||
} | ||
symbol = !name ? _module.default || _module : _module[name]; | ||
} | ||
this.cache?.set(key, res); | ||
return res; | ||
} | ||
return { _kind: 'js', symbol, meta: null } as JSResolve; | ||
public resolveImported( | ||
imported: Imported, | ||
name: string, | ||
subtype: 'mappedSymbols' | 'mappedKeyframes' = 'mappedSymbols' | ||
): CSSResolve | JSResolve | null { | ||
const res = this.getModule(imported); | ||
if (res === null) { | ||
return null; | ||
} | ||
if (imported.from.match(/\.css$/)) { | ||
const meta = res as StylableMeta; | ||
return { | ||
_kind: 'css', | ||
symbol: !name ? meta.mappedSymbols[meta.root] : meta[subtype][name], | ||
meta, | ||
}; | ||
} else { | ||
const jsModule = res as JsModule; | ||
return { | ||
_kind: 'js', | ||
symbol: !name ? jsModule.default || jsModule : jsModule[name], | ||
meta: null, | ||
}; | ||
} | ||
} | ||
@@ -108,3 +141,7 @@ public resolveImport(importSymbol: ImportSymbol) { | ||
while (current.symbol?.import) { | ||
const res = this.resolveImported(current.symbol.import, current.symbol.name); | ||
const res = this.resolveImported( | ||
current.symbol.import, | ||
current.symbol.name, | ||
'mappedKeyframes' | ||
); | ||
if (res?._kind === 'css' && res.symbol?._kind === 'keyframes') { | ||
@@ -322,4 +359,4 @@ const { meta, symbol } = res; | ||
fromDecl, | ||
resolverWarnings.UNKNOWN_IMPORTED_FILE(importObj.fromRelative), | ||
{ word: importObj.fromRelative } | ||
resolverWarnings.UNKNOWN_IMPORTED_FILE(importObj.request), | ||
{ word: importObj.request } | ||
); | ||
@@ -341,6 +378,3 @@ } | ||
namedDecl, | ||
resolverWarnings.UNKNOWN_IMPORTED_SYMBOL( | ||
origName, | ||
importObj.fromRelative | ||
), | ||
resolverWarnings.UNKNOWN_IMPORTED_SYMBOL(origName, importObj.request), | ||
{ word: origName } | ||
@@ -347,0 +381,0 @@ ); |
@@ -7,5 +7,5 @@ import { basename } from 'path'; | ||
import { FileProcessor } from './cached-process-file'; | ||
import type { FileProcessor } from './cached-process-file'; | ||
import { unbox } from './custom-values'; | ||
import { Diagnostics } from './diagnostics'; | ||
import type { Diagnostics } from './diagnostics'; | ||
import { evalDeclarationValue, processDeclarationValue } from './functions'; | ||
@@ -17,9 +17,4 @@ import { | ||
} from './native-reserved-lists'; | ||
import { setStateToNode, stateErrors, validateStateDefinition } from './pseudo-states'; | ||
import { | ||
setStateToNode, | ||
stateErrors, | ||
transformPseudoStateSelector, | ||
validateStateDefinition, | ||
} from './pseudo-states'; | ||
import { | ||
createWarningRule, | ||
@@ -37,3 +32,3 @@ getOriginDefinition, | ||
import { appendMixins } from './stylable-mixins'; | ||
import { | ||
import type { | ||
ClassSymbol, | ||
@@ -46,3 +41,3 @@ ElementSymbol, | ||
} from './stylable-processor'; | ||
import { CSSResolve, JSResolve, StylableResolver } from './stylable-resolver'; | ||
import { CSSResolve, StylableResolverCache, StylableResolver } from './stylable-resolver'; | ||
import { findRule, generateScopedCSSVar, getDeclStylable, isCSSVarProp } from './stylable-utils'; | ||
@@ -52,3 +47,2 @@ import { valueMapping } from './stylable-value-parsers'; | ||
const { hasOwnProperty } = Object.prototype; | ||
const USE_SCOPE_SELECTOR_2 = true; | ||
@@ -114,2 +108,3 @@ export interface ResolvedElement { | ||
mode?: EnvMode; | ||
resolverCache?: StylableResolverCache; | ||
} | ||
@@ -162,3 +157,7 @@ | ||
this.postProcessor = options.postProcessor; | ||
this.resolver = new StylableResolver(options.fileProcessor, options.requireModule); | ||
this.resolver = new StylableResolver( | ||
options.fileProcessor, | ||
options.requireModule, | ||
options.resolverCache | ||
); | ||
this.mode = options.mode || 'production'; | ||
@@ -198,3 +197,3 @@ } | ||
} | ||
rule.selector = this.scopeRule(meta, rule, metaExports && metaExports.classes); | ||
rule.selector = this.scopeRule(meta, rule); | ||
}); | ||
@@ -247,6 +246,4 @@ | ||
if (USE_SCOPE_SELECTOR_2) { | ||
if (!mixinTransform && meta.outputAst && this.mode === 'development') { | ||
this.addDevRules(meta); | ||
} | ||
if (!mixinTransform && meta.outputAst && this.mode === 'development') { | ||
this.addDevRules(meta); | ||
} | ||
@@ -258,7 +255,3 @@ ast.walkRules((rule) => | ||
if (metaExports) { | ||
if (USE_SCOPE_SELECTOR_2) { | ||
Object.assign(metaExports.classes, this.exportClasses(meta)); | ||
} else { | ||
this.exportRootClass(meta, metaExports.classes); | ||
} | ||
Object.assign(metaExports.classes, this.exportClasses(meta)); | ||
this.exportLocalVars(meta, metaExports.stVars, variableOverride); | ||
@@ -300,99 +293,2 @@ this.exportKeyframes(keyframeMapping, metaExports.keyframes); | ||
} | ||
public exportRootClass(meta: StylableMeta, classesExport: Record<string, string>) { | ||
const classExports: Record<string, string> = {}; | ||
this.handleClass( | ||
meta, | ||
{ | ||
type: 'class', | ||
name: meta.mappedSymbols[meta.root].name, | ||
nodes: [], | ||
}, | ||
meta.mappedSymbols[meta.root].name, | ||
classExports | ||
); | ||
classesExport[meta.root] = classExports[meta.mappedSymbols[meta.root].name]; | ||
} | ||
public exportClass( | ||
meta: StylableMeta, | ||
name: string, | ||
classSymbol: ClassSymbol, | ||
metaExports?: Record<string, string> | ||
) { | ||
const scopedName = this.scope(name, meta.namespace); | ||
if (metaExports && !metaExports[name]) { | ||
const extend = classSymbol ? classSymbol[valueMapping.extends] : undefined; | ||
let exportedClasses = scopedName; | ||
if (extend && extend !== classSymbol) { | ||
let finalSymbol; | ||
let finalName; | ||
let finalMeta; | ||
if (extend._kind === 'class') { | ||
finalSymbol = extend; | ||
finalName = extend.name; | ||
finalMeta = meta; | ||
} else if (extend._kind === 'import') { | ||
const resolved = this.resolver.deepResolve(extend); | ||
if (resolved && resolved._kind === 'css' && resolved.symbol) { | ||
if (resolved.symbol._kind === 'class') { | ||
finalSymbol = resolved.symbol; | ||
finalName = resolved.symbol.name; | ||
finalMeta = resolved.meta; | ||
} else { | ||
const found = findRule(meta.ast, '.' + classSymbol.name); | ||
if (found) { | ||
this.diagnostics.error( | ||
found, | ||
transformerWarnings.IMPORT_ISNT_EXTENDABLE(), | ||
{ word: found.value } | ||
); | ||
} | ||
} | ||
} else if (resolved) { | ||
const found = findRule(meta.ast, '.' + classSymbol.name); | ||
if (found) { | ||
if (!resolved.symbol) { | ||
this.diagnostics.error( | ||
found, | ||
transformerWarnings.CANNOT_EXTEND_UNKNOWN_SYMBOL(found.value), | ||
{ word: found.value } | ||
); | ||
} else { | ||
this.diagnostics.error( | ||
found, | ||
transformerWarnings.CANNOT_EXTEND_JS(), | ||
{ | ||
word: found.value, | ||
} | ||
); | ||
} | ||
} | ||
} | ||
} | ||
if (finalSymbol && finalName && finalMeta && !finalSymbol[valueMapping.root]) { | ||
const classExports: Record<string, string> = {}; | ||
this.handleClass( | ||
finalMeta, | ||
{ type: 'class', name: finalName, nodes: [] }, | ||
finalName, | ||
classExports | ||
); | ||
if (classExports[finalName]) { | ||
exportedClasses += ' ' + classExports[finalName]; | ||
} else { | ||
console.error( | ||
`something went wrong when exporting '${finalName}', ` + | ||
`please file an issue in stylable. With specific use case` | ||
); | ||
} | ||
} | ||
} | ||
metaExports[name] = exportedClasses; | ||
} | ||
return scopedName; | ||
} | ||
public scopeKeyframes(ast: postcss.Root, meta: StylableMeta) { | ||
@@ -513,415 +409,7 @@ ast.walkAtRules(/keyframes$/, (atRule) => { | ||
public resolveSelectorElements(meta: StylableMeta, selector: string): ResolvedElement[][] { | ||
if (USE_SCOPE_SELECTOR_2) { | ||
return this.scopeSelector2(meta, selector, undefined, true).elements; | ||
} else { | ||
return this.scopeSelector(meta, selector, undefined, true).elements; | ||
} | ||
return this.scopeSelector(meta, selector).elements; | ||
} | ||
public scopeSelector( | ||
originMeta: StylableMeta, | ||
selector: string, | ||
classesExport?: Record<string, string>, | ||
calcPaths = false, | ||
rule?: postcss.Rule | ||
): ScopedSelectorResults { | ||
let meta = originMeta; | ||
let current = meta; | ||
let symbol: StylableSymbol | null = null; | ||
let nestedSymbol: StylableSymbol | null; | ||
let originSymbol: ClassSymbol | ElementSymbol; | ||
const selectorAst = parseSelector(selector); | ||
const addedSelectors: AdditionalSelector[] = []; | ||
const elements = selectorAst.nodes.map((selectorNode) => { | ||
const selectorElements: ResolvedElement[] = []; | ||
traverseNode(selectorNode, (node) => { | ||
const { name, type } = node; | ||
if ( | ||
calcPaths && | ||
(type === 'class' || type === 'element' || type === 'pseudo-element') | ||
) { | ||
selectorElements.push({ | ||
name, | ||
type, | ||
resolved: this.resolver.resolveExtends( | ||
current, | ||
name, | ||
type === 'element', | ||
this | ||
), | ||
}); | ||
} | ||
if (type === 'selector' || type === 'spacing' || type === 'operator') { | ||
if (nestedSymbol) { | ||
symbol = nestedSymbol; | ||
nestedSymbol = null; | ||
} else { | ||
meta = originMeta; | ||
current = originMeta; | ||
symbol = originMeta.classes[originMeta.root]; | ||
originSymbol = symbol; | ||
} | ||
} else if (type === 'class') { | ||
const next = this.handleClass( | ||
current, | ||
node, | ||
name, | ||
classesExport, | ||
rule, | ||
originMeta | ||
); | ||
originSymbol = current.classes[name]; | ||
symbol = next.symbol; | ||
current = next.meta; | ||
} else if (type === 'element') { | ||
const next = this.handleElement(current, node, name, originMeta); | ||
originSymbol = current.elements[name]; | ||
symbol = next.symbol; | ||
current = next.meta; | ||
} else if (type === 'pseudo-element') { | ||
const next = this.handlePseudoElement( | ||
current, | ||
node, | ||
name, | ||
selectorNode, | ||
addedSelectors, | ||
rule, | ||
originMeta | ||
); | ||
originSymbol = current.classes[name]; | ||
meta = current; | ||
symbol = next.symbol; | ||
current = next.meta; | ||
} else if (type === 'pseudo-class') { | ||
current = transformPseudoStateSelector( | ||
current, | ||
node, | ||
name, | ||
symbol, | ||
meta, | ||
originSymbol, | ||
this.resolver, | ||
this.diagnostics, | ||
rule | ||
); | ||
} else if (type === 'nested-pseudo-class') { | ||
if (name === 'global') { | ||
// node.type = 'selector'; | ||
return true; | ||
} | ||
nestedSymbol = symbol; | ||
} else if (type === 'invalid' && node.value === '&' && current.parent) { | ||
const origin = current.mappedSymbols[current.root]; | ||
const next = this.handleClass( | ||
current, | ||
{ | ||
type: 'class', | ||
nodes: [], | ||
name: origin.name, | ||
}, | ||
origin.name, | ||
undefined, | ||
undefined, | ||
originMeta | ||
); | ||
originSymbol = current.classes[origin.name]; | ||
symbol = next.symbol; | ||
current = next.meta; | ||
} | ||
/* do nothing */ | ||
return undefined; | ||
}); | ||
return selectorElements; | ||
}); | ||
this.addAdditionalSelectors(addedSelectors, selectorAst); | ||
return { | ||
current, | ||
symbol, | ||
selectorAst, | ||
elements, | ||
selector: stringifySelector(selectorAst), | ||
}; | ||
public scopeRule(meta: StylableMeta, rule: postcss.Rule): string { | ||
return this.scopeSelector(meta, rule.selector, rule).selector; | ||
} | ||
public addAdditionalSelectors( | ||
addedSelectors: AdditionalSelector[], | ||
selectorAst: SelectorAstNode | ||
) { | ||
addedSelectors.forEach((s) => { | ||
const clone = cloneDeep(s.selectorNode); | ||
const i = s.selectorNode.nodes.indexOf(s.node); | ||
if (i === -1) { | ||
throw new Error('not supported inside nested classes'); | ||
} else { | ||
clone.nodes[i].value = s.customElementChunk; | ||
} | ||
selectorAst.nodes.push(clone); | ||
}); | ||
} | ||
public applyRootScoping(meta: StylableMeta, selectorAst: SelectorAstNode) { | ||
const scopedRoot = | ||
(meta.mappedSymbols[meta.root] as ClassSymbol)[valueMapping.global] || | ||
this.scope(meta.root, meta.namespace); | ||
selectorAst.nodes.forEach((selector) => { | ||
const first = selector.nodes[0]; | ||
/* This finds a transformed or non transform global selector */ | ||
if ( | ||
first && | ||
(first.type === 'selector' || first.type === 'nested-pseudo-class') && | ||
first.name === 'global' | ||
) { | ||
return; | ||
} | ||
// -st-global can make anther global inside root | ||
if (first && first.nodes === scopedRoot) { | ||
return; | ||
} | ||
if (first && first.before && first.before === '.' + scopedRoot) { | ||
return; | ||
} | ||
if (first && first.type === 'invalid' && first.value === '&') { | ||
return; | ||
} | ||
if (!first || first.name !== scopedRoot) { | ||
selector.nodes = [ | ||
typeof scopedRoot !== 'string' | ||
? { type: 'selector', nodes: scopedRoot, name: 'global' } | ||
: { type: 'class', name: scopedRoot, nodes: [] }, | ||
{ type: 'spacing', value: ' ', name: '', nodes: [] }, | ||
...selector.nodes, | ||
]; | ||
} | ||
}); | ||
} | ||
public scopeRule( | ||
meta: StylableMeta, | ||
rule: postcss.Rule, | ||
_classesExport?: Record<string, string> | ||
): string { | ||
if (USE_SCOPE_SELECTOR_2) { | ||
return this.scopeSelector2(meta, rule.selector, undefined, false, rule).selector; | ||
} else { | ||
return this.scopeSelector(meta, rule.selector, _classesExport, false, rule).selector; | ||
} | ||
} | ||
public handleClass( | ||
meta: StylableMeta, | ||
node: SelectorAstNode, | ||
name: string, | ||
classesExport?: Record<string, string>, | ||
rule?: postcss.Rule, | ||
originMeta?: StylableMeta | ||
): CSSResolve { | ||
const symbol = meta.classes[name]; | ||
const extend = symbol ? symbol[valueMapping.extends] : undefined; | ||
if (!extend && symbol && symbol.alias) { | ||
let next = this.resolver.deepResolve(symbol.alias); | ||
if (next && next._kind === 'css' && next.symbol && next.symbol._kind === 'class') { | ||
const globalMappedNodes = next.symbol[valueMapping.global]; | ||
if (globalMappedNodes) { | ||
node.before = ''; | ||
node.type = 'selector'; | ||
node.nodes = globalMappedNodes; | ||
this.addGlobalsToMeta(globalMappedNodes, originMeta); | ||
} else { | ||
node.name = this.exportClass( | ||
next.meta, | ||
next.symbol.name, | ||
next.symbol, | ||
classesExport | ||
); | ||
} | ||
if (next.symbol[valueMapping.extends]) { | ||
next = this.resolver.deepResolve(next.symbol[valueMapping.extends]); | ||
if (next && next._kind === 'css') { | ||
return next; | ||
} | ||
} else { | ||
return next; | ||
} | ||
} else if (rule) { | ||
this.diagnostics.error(rule, transformerWarnings.UNKNOWN_IMPORT_ALIAS(name), { | ||
word: symbol.alias.name, | ||
}); | ||
} | ||
} | ||
let scopedName = ''; | ||
let globalScopedSelector = ''; | ||
const globalMappedNodes = symbol && symbol[valueMapping.global]; | ||
if (globalMappedNodes) { | ||
globalScopedSelector = stringifySelector({ | ||
type: 'selector', | ||
name: '', | ||
nodes: globalMappedNodes, | ||
}); | ||
} else { | ||
scopedName = this.exportClass(meta, name, symbol, classesExport); | ||
} | ||
if (globalScopedSelector) { | ||
node.before = ''; | ||
node.type = 'selector'; | ||
node.nodes = symbol[valueMapping.global] || []; | ||
this.addGlobalsToMeta(globalMappedNodes!, originMeta); | ||
} else { | ||
node.name = scopedName; | ||
} | ||
const next = this.resolver.deepResolve(extend); | ||
if (next && next._kind === 'css' && next.symbol && next.symbol._kind === 'class') { | ||
if (this.mode === 'development' && rule && (rule as SRule).selectorType === 'class') { | ||
rule.after( | ||
createWarningRule( | ||
next.symbol.name, | ||
this.scope(next.symbol.name, next.meta.namespace), | ||
basename(next.meta.source), | ||
name, | ||
this.scope(symbol.name, meta.namespace), | ||
basename(meta.source) | ||
) | ||
); | ||
} | ||
return next; | ||
} | ||
// local | ||
if (extend && extend._kind === 'class') { | ||
if (extend === symbol && extend.alias) { | ||
const next = this.resolver.deepResolve(extend.alias); | ||
if (next && next._kind === 'css' && next.symbol) { | ||
return next; | ||
} | ||
} | ||
} | ||
return { _kind: 'css', meta, symbol }; | ||
} | ||
public handleElement( | ||
meta: StylableMeta, | ||
node: SelectorAstNode, | ||
name: string, | ||
originMeta?: StylableMeta | ||
) { | ||
const tRule = meta.elements[name] as StylableSymbol; | ||
const extend = tRule ? meta.mappedSymbols[name] : undefined; | ||
const next = this.resolver.deepResolve(extend); | ||
if (next && next._kind === 'css' && next.symbol) { | ||
if (next.symbol._kind === 'class' && next.symbol[valueMapping.global]) { | ||
node.before = ''; | ||
node.type = 'selector'; | ||
node.nodes = next.symbol[valueMapping.global] || []; | ||
this.addGlobalsToMeta(node.nodes, originMeta); | ||
} else { | ||
node.type = 'class'; | ||
node.name = this.scope(next.symbol.name, next.meta.namespace); | ||
} | ||
// node.name = (next.symbol as ClassSymbol)[valueMapping.global] || | ||
// this.scope(next.symbol.name, next.meta.namespace); | ||
return next; | ||
} | ||
return { meta, symbol: tRule }; | ||
} | ||
public handlePseudoElement( | ||
meta: StylableMeta, | ||
node: SelectorAstNode, | ||
name: string, | ||
selectorNode: SelectorAstNode, | ||
addedSelectors: AdditionalSelector[], | ||
rule?: postcss.Rule, | ||
originMeta?: StylableMeta | ||
): CSSResolve { | ||
let next: JSResolve | CSSResolve | null; | ||
const customSelector = meta.customSelectors[':--' + name]; | ||
if (customSelector) { | ||
const rootRes = this.scopeSelector(meta, '.root', {}, false); | ||
const res = this.scopeSelector(meta, customSelector, {}, false); | ||
const rootEg = new RegExp('^\\s*' + rootRes.selector.replace(/\./, '\\.') + '\\s*'); | ||
const selectors = res.selectorAst.nodes.map((sel) => | ||
stringifySelector(sel).trim().replace(rootEg, '') | ||
); | ||
if (selectors[0]) { | ||
node.type = 'invalid'; /*just take it */ | ||
node.before = ' '; | ||
node.value = selectors[0]; | ||
} | ||
for (let i = 1 /*start from second one*/; i < selectors.length; i++) { | ||
addedSelectors.push({ | ||
selectorNode, | ||
node, | ||
customElementChunk: selectors[i], | ||
}); | ||
} | ||
if (res.selectorAst.nodes.length === 1 && res.symbol) { | ||
return { _kind: 'css', meta: res.current, symbol: res.symbol }; | ||
} | ||
// this is an error mode fallback | ||
return { | ||
_kind: 'css', | ||
meta, | ||
symbol: { _kind: 'element', name: '*' }, | ||
}; | ||
} | ||
// find if the current symbol exists in the initial meta; | ||
let symbol = meta.mappedSymbols[name]; | ||
let current = meta; | ||
while (!symbol) { | ||
// go up the root extends path and find first symbol | ||
const root = current.mappedSymbols[current.root] as ClassSymbol; | ||
next = this.resolver.deepResolve(root[valueMapping.extends]); | ||
if (next && next._kind === 'css') { | ||
current = next.meta; | ||
symbol = next.meta.mappedSymbols[name]; | ||
} else { | ||
break; | ||
} | ||
} | ||
if (symbol) { | ||
if (symbol._kind === 'class') { | ||
node.type = 'class'; | ||
node.before = symbol[valueMapping.root] ? '' : ' '; | ||
next = this.resolver.deepResolve(symbol); | ||
if (symbol[valueMapping.global]) { | ||
node.type = 'selector'; | ||
node.nodes = symbol[valueMapping.global] || []; | ||
this.addGlobalsToMeta(node.nodes, originMeta); | ||
} else { | ||
if (symbol.alias && !symbol[valueMapping.extends]) { | ||
if (next && next.meta && next.symbol) { | ||
node.name = this.scope(next.symbol.name, next.meta.namespace); | ||
} else { | ||
// TODO: maybe warn on un resolved alias | ||
} | ||
} else { | ||
node.name = this.scope(symbol.name, current.namespace); | ||
} | ||
} | ||
if (next && next._kind === 'css') { | ||
return next; | ||
} | ||
} | ||
} else if (rule) { | ||
if (!nativePseudoElements.includes(name) && !isVendorPrefixed(name)) { | ||
this.diagnostics.warn(rule, transformerWarnings.UNKNOWN_PSEUDO_ELEMENT(name), { | ||
word: name, | ||
}); | ||
} | ||
} | ||
return { _kind: 'css', meta: current, symbol }; | ||
} | ||
public scope(name: string, namespace: string, delimiter: string = this.delimiter) { | ||
@@ -955,7 +443,5 @@ return namespace ? namespace + delimiter + name : name; | ||
} | ||
public scopeSelector2( | ||
public scopeSelector( | ||
originMeta: StylableMeta, | ||
selector: string, | ||
_classesExport?: Record<string, string>, | ||
_calcPaths = false, | ||
rule?: postcss.Rule | ||
@@ -1194,3 +680,2 @@ ): { selector: string; elements: ResolvedElement[][]; targetSelectorAst: SelectorAstNode } { | ||
} | ||
private handleCustomSelector( | ||
@@ -1342,38 +827,2 @@ customSelector: string, | ||
export function removeSTDirective(root: postcss.Root) { | ||
const toRemove: postcss.Node[] = []; | ||
root.walkRules((rule: postcss.Rule) => { | ||
if (rule.nodes && rule.nodes.length === 0) { | ||
toRemove.push(rule); | ||
return; | ||
} | ||
rule.walkDecls((decl: postcss.Declaration) => { | ||
if (decl.prop.startsWith('-st-')) { | ||
toRemove.push(decl); | ||
} | ||
}); | ||
if (rule.raws) { | ||
rule.raws = { | ||
after: '\n', | ||
}; | ||
} | ||
}); | ||
if (root.raws) { | ||
root.raws = {}; | ||
} | ||
function removeRecursiveUpIfEmpty(node: postcss.Node) { | ||
const parent = node.parent; | ||
node.remove(); | ||
if (parent && parent.nodes && parent.nodes.length === 0) { | ||
removeRecursiveUpIfEmpty(parent); | ||
} | ||
} | ||
toRemove.forEach((node) => { | ||
removeRecursiveUpIfEmpty(node); | ||
}); | ||
} | ||
function validateScopes(transformer: StylableTransformer, meta: StylableMeta) { | ||
@@ -1380,0 +829,0 @@ const transformedScopes: Record<string, SelectorChunk2[][]> = {}; |
@@ -5,4 +5,4 @@ import cloneDeep from 'lodash.clonedeep'; | ||
import replaceRuleSelector from 'postcss-selector-matches/dist/replaceRuleSelector'; | ||
import { Diagnostics } from './diagnostics'; | ||
import { | ||
import type { Diagnostics } from './diagnostics'; | ||
import type { | ||
DeclStylableProps, | ||
@@ -24,5 +24,5 @@ Imported, | ||
} from './selector-utils'; | ||
import { ImportSymbol } from './stylable-meta'; | ||
import type { ImportSymbol } from './stylable-meta'; | ||
import { valueMapping, mixinDeclRegExp } from './stylable-value-parsers'; | ||
import { StylableResolver } from './stylable-resolver'; | ||
import type { StylableResolver } from './stylable-resolver'; | ||
@@ -29,0 +29,0 @@ export const CUSTOM_SELECTOR_RE = /:--[\w-]+/g; |
@@ -1,2 +0,2 @@ | ||
import * as postcss from 'postcss'; | ||
import type * as postcss from 'postcss'; | ||
import postcssValueParser, { | ||
@@ -6,6 +6,6 @@ ParsedValue as PostCSSParsedValue, | ||
} from 'postcss-value-parser'; | ||
import { Diagnostics } from './diagnostics'; | ||
import type { Diagnostics } from './diagnostics'; | ||
import { processPseudoStates } from './pseudo-states'; | ||
import { parseSelector } from './selector-utils'; | ||
import { ParsedValue, StateParsedValue } from './types'; | ||
import type { ParsedValue, StateParsedValue } from './types'; | ||
@@ -74,3 +74,2 @@ export const valueParserWarnings = { | ||
export const mixinDeclRegExp = new RegExp(`(${valueMapping.mixin})|(${valueMapping.partialMixin})`); | ||
@@ -135,3 +134,7 @@ | ||
}, | ||
'-st-named'(value: string, node: postcss.Declaration, diagnostics: Diagnostics) { | ||
'-st-named'( | ||
value: string, | ||
node: postcss.Declaration | postcss.AtRule, | ||
diagnostics: Diagnostics | ||
) { | ||
const namedMap: Record<string, string> = {}; | ||
@@ -201,3 +204,3 @@ const keyframesMap: Record<string, string> = {}; | ||
key: keyof typeof buckets = 'namedMap', | ||
node: postcss.Declaration, | ||
node: postcss.Declaration | postcss.AtRule, | ||
diagnostics: Diagnostics | ||
@@ -204,0 +207,0 @@ ) { |
@@ -1,2 +0,2 @@ | ||
import { FileProcessor, MinimalFS } from './cached-process-file'; | ||
import type { FileProcessor, MinimalFS } from './cached-process-file'; | ||
import { createInfrastructure } from './create-infra-structure'; | ||
@@ -6,3 +6,3 @@ import { Diagnostics } from './diagnostics'; | ||
import { processNamespace, StylableMeta, StylableProcessor } from './stylable-processor'; | ||
import { StylableResolver } from './stylable-resolver'; | ||
import { StylableResolverCache, StylableResolver } from './stylable-resolver'; | ||
import { | ||
@@ -14,4 +14,4 @@ StylableResults, | ||
} from './stylable-transformer'; | ||
import { TimedCacheOptions } from './timed-cache'; | ||
import { IStylableOptimizer, ModuleResolver } from './types'; | ||
import type { TimedCacheOptions } from './timed-cache'; | ||
import type { IStylableOptimizer, ModuleResolver } from './types'; | ||
@@ -34,7 +34,11 @@ export interface StylableConfig { | ||
resolveNamespace?: typeof processNamespace; | ||
/** @deprecated use resolverCache instead */ | ||
timedCacheOptions?: Omit<TimedCacheOptions, 'createKey'>; | ||
resolveModule?: ModuleResolver; | ||
cssParser?: CssParser; | ||
resolverCache?: StylableResolverCache; | ||
} | ||
export type CreateProcessorOptions = Pick<StylableConfig, 'resolveNamespace'>; | ||
export class Stylable { | ||
@@ -61,3 +65,4 @@ public static create(config: StylableConfig) { | ||
config.resolveModule, | ||
config.cssParser | ||
config.cssParser, | ||
config.resolverCache | ||
); | ||
@@ -80,8 +85,6 @@ } | ||
public resolveNamespace?: typeof processNamespace, | ||
protected timedCacheOptions: Omit<TimedCacheOptions, 'createKey'> = { | ||
timeout: 1, | ||
useTimer: true, | ||
}, | ||
protected timedCacheOptions?: Omit<TimedCacheOptions, 'createKey'>, | ||
protected resolveModule?: ModuleResolver, | ||
protected cssParser: CssParser = safeParse | ||
protected cssParser: CssParser = safeParse, | ||
protected resolverCache?: StylableResolverCache | ||
) { | ||
@@ -102,2 +105,18 @@ const { fileProcessor, resolvePath } = createInfrastructure( | ||
} | ||
public initCache() { | ||
this.resolverCache = new Map(); | ||
} | ||
public createResolver({ | ||
requireModule, | ||
resolverCache, | ||
}: Pick<StylableConfig, 'requireModule' | 'resolverCache'>) { | ||
return new StylableResolver( | ||
this.fileProcessor, | ||
requireModule || this.requireModule, | ||
resolverCache || this.resolverCache | ||
); | ||
} | ||
public createProcessor({ resolveNamespace }: CreateProcessorOptions = {}) { | ||
return new StylableProcessor(new Diagnostics(), resolveNamespace || this.resolveNamespace); | ||
} | ||
public createTransformer(options: Partial<TransformerOptions> = {}) { | ||
@@ -111,2 +130,3 @@ return new StylableTransformer({ | ||
replaceValueHook: this.hooks.replaceValueHook, | ||
resolverCache: this.resolverCache, | ||
mode: this.mode, | ||
@@ -121,14 +141,12 @@ ...options, | ||
resourcePath?: string, | ||
options: Partial<TransformerOptions> = {} | ||
options: Partial<TransformerOptions> = {}, | ||
processorOptions: CreateProcessorOptions = {} | ||
): StylableResults { | ||
if (typeof meta === 'string') { | ||
// TODO: refactor to use fileProcessor | ||
// meta = this.fileProcessor.processContent(meta, resourcePath + ''); | ||
const root = this.cssParser(meta, { from: resourcePath }); | ||
meta = new StylableProcessor(undefined, this.resolveNamespace).process(root); | ||
meta = this.createProcessor(processorOptions).process( | ||
this.cssParser(meta, { from: resourcePath }) | ||
); | ||
} | ||
const transformer = this.createTransformer(options); | ||
this.fileProcessor.add(meta.source, meta); | ||
return transformer.transform(meta); | ||
@@ -135,0 +153,0 @@ } |
@@ -0,0 +0,0 @@ export interface TimedCacheOptions { |
@@ -1,5 +0,5 @@ | ||
import * as postcss from 'postcss'; | ||
import { Box } from './custom-values'; | ||
import { StylableMeta } from './stylable-meta'; | ||
import { StylableExports, StylableResults } from './stylable-transformer'; | ||
import type * as postcss from 'postcss'; | ||
import type { Box } from './custom-values'; | ||
import type { StylableMeta } from './stylable-meta'; | ||
import type { StylableExports, StylableResults } from './stylable-transformer'; | ||
@@ -6,0 +6,0 @@ export type PartialObject<T> = Partial<T> & object; |
@@ -0,0 +0,0 @@ // export function scope(name: string, namespace: string, separator: string = '-') { |
@@ -1,4 +0,4 @@ | ||
import { StylableMeta } from './stylable-meta'; | ||
import { Imported } from './stylable-processor'; | ||
import { StylableResolver } from './stylable-resolver'; | ||
import type { StylableMeta } from './stylable-meta'; | ||
import type { Imported } from './stylable-processor'; | ||
import type { StylableResolver } from './stylable-resolver'; | ||
@@ -5,0 +5,0 @@ export function visitMetaCSSDependenciesBFS( |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
153
0
685016
11791
2
+ Addedtoky@^0.1.0
+ Addedtoky@0.1.0(transitive)
- Removedmurmurhash@^2.0.0
- Removedmurmurhash@2.0.1(transitive)
Updatedpostcss@^8.2.6