Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@stylable/core

Package Overview
Dependencies
Maintainers
5
Versions
218
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@stylable/core - npm Package Compare versions

Comparing version 2.4.0 to 2.4.1-alpha.0

4

cjs/functions.d.ts

@@ -20,3 +20,3 @@ import postcss from 'postcss';

export declare function resolveArgumentsValue(options: Record<string, string>, transformer: StylableTransformer, meta: StylableMeta, diagnostics: Diagnostics, node: postcss.Node, variableOverride?: Record<string, string>, path?: string[], cssVarsMapping?: Record<string, string>): Record<string, string>;
export declare function processDeclarationValue(resolver: StylableResolver, value: string, meta: StylableMeta, node: postcss.Node, variableOverride?: Record<string, string> | null, valueHook?: replaceValueHook, diagnostics?: Diagnostics, passedThrough?: string[], cssVarsMapping?: Record<string, string>, args?: string[]): {
export declare function processDeclarationValue(resolver: StylableResolver, value: string, meta: StylableMeta, node?: postcss.Node, variableOverride?: Record<string, string> | null, valueHook?: replaceValueHook, diagnostics?: Diagnostics, passedThrough?: string[], cssVarsMapping?: Record<string, string>, args?: string[]): {
topLevelType: any;

@@ -26,3 +26,3 @@ outputValue: string;

};
export declare function evalDeclarationValue(resolver: StylableResolver, value: string, meta: StylableMeta, node: postcss.Node, variableOverride?: Record<string, string> | null, valueHook?: replaceValueHook, diagnostics?: Diagnostics, passedThrough?: string[], cssVarsMapping?: Record<string, string>, args?: string[]): string;
export declare function evalDeclarationValue(resolver: StylableResolver, value: string, meta: StylableMeta, node?: postcss.Node, variableOverride?: Record<string, string> | null, valueHook?: replaceValueHook, diagnostics?: Diagnostics, passedThrough?: string[], cssVarsMapping?: Record<string, string>, args?: string[]): string;
//# sourceMappingURL=functions.d.ts.map

@@ -31,2 +31,3 @@ "use strict";

function processDeclarationValue(resolver, value, meta, node, variableOverride, valueHook, diagnostics, passedThrough = [], cssVarsMapping, args = []) {
diagnostics = node ? diagnostics : undefined;
const customValues = custom_values_1.resolveCustomValues(meta, resolver);

@@ -57,3 +58,3 @@ const parsedValue = valueParser(value);

const { outputValue, topLevelType, typeError } = resolved;
if (diagnostics) {
if (diagnostics && node) {
const argsAsString = parsedArgs.join(', ');

@@ -87,3 +88,3 @@ if (typeError) {

: resolvedVarSymbol._kind;
if (diagnostics) {
if (diagnostics && node) {
diagnostics.warn(node, exports.functionWarnings.CANNOT_USE_AS_VALUE(errorKind, varName), { word: varName });

@@ -93,3 +94,3 @@ }

}
else if (resolvedVar._kind === 'js' && diagnostics) {
else if (resolvedVar._kind === 'js' && diagnostics && node) {
// ToDo: provide actual exported id (default/named as x)

@@ -105,3 +106,3 @@ diagnostics.warn(node, exports.functionWarnings.CANNOT_USE_JS_AS_VALUE(varName), {

});
if (namedDecl && diagnostics) {
if (namedDecl && diagnostics && node) {
// ToDo: provide actual exported id (default/named as x)

@@ -112,3 +113,3 @@ diagnostics.error(node, exports.functionWarnings.CANNOT_FIND_IMPORTED_VAR(varName), { word: varName });

}
else if (diagnostics) {
else if (diagnostics && node) {
diagnostics.warn(node, exports.functionWarnings.UNKNOWN_VAR(varName), {

@@ -148,3 +149,3 @@ word: varName

parsedNode.resolvedValue = stringifyFunction(value, parsedNode);
if (diagnostics) {
if (diagnostics && node) {
diagnostics.warn(node, exports.functionWarnings.FAIL_TO_EXECUTE_FORMATTER(parsedNode.resolvedValue, error.message), { word: node.value });

@@ -169,3 +170,3 @@ }

}
else if (diagnostics) {
else if (diagnostics && node) {
parsedNode.resolvedValue = stringifyFunction(value, parsedNode);

@@ -222,3 +223,3 @@ diagnostics.warn(node, exports.functionWarnings.UNKNOWN_FORMATTER(value), {

cyclicChain.push(refUniqID);
if (diagnostics) {
if (diagnostics && node) {
diagnostics.warn(node, exports.functionWarnings.CYCLIC_VALUE(cyclicChain), {

@@ -225,0 +226,0 @@ word: refUniqID

@@ -288,5 +288,3 @@ "use strict";

const param = nodeContent || defaultStringValue;
return rule
? functions_1.evalDeclarationValue(resolver, param, meta, rule, undefined, undefined, diagnostics)
: param;
return functions_1.evalDeclarationValue(resolver, param, meta, rule, undefined, undefined, diagnostics);
}

@@ -293,0 +291,0 @@ function createBooleanStateClassName(stateName, namespace) {

import postcss from 'postcss';
import { ClassSymbol, ElementSymbol } from './stylable-meta';
import { CSSResolve } from './stylable-resolver';
export interface SelectorAstNode {

@@ -31,4 +33,15 @@ type: string;

operator?: string;
value?: string;
nodes: Array<Partial<SelectorAstNode>>;
}
export interface SelectorChunk2 {
type: string;
operator?: string;
value?: string;
nodes: SelectorAstNode[];
before?: string;
}
export declare function mergeChunks(chunks: SelectorChunk2[][]): any;
export declare function separateChunks2(selectorNode: SelectorAstNode): SelectorChunk2[][];
export declare function getOriginDefinition(resolved: Array<CSSResolve<ClassSymbol | ElementSymbol>>): CSSResolve<ClassSymbol | ElementSymbol>;
export declare function separateChunks(selectorNode: SelectorAstNode): SelectorChunk[][];

@@ -40,3 +53,3 @@ export declare function filterChunkNodesByType(chunk: SelectorChunk, typeOptions: string[]): Array<Partial<SelectorAstNode>>;

export declare function isCompRoot(name: string): RegExpMatchArray | null;
export declare function createWarningRule(extendedNode: string, scopedExtendedNode: string, extendedFile: string, extendingNode: string, scopedExtendingNode: string, extendingFile: string): postcss.Rule;
export declare function createWarningRule(extendedNode: string, scopedExtendedNode: string, extendedFile: string, extendingNode: string, scopedExtendingNode: string, extendingFile: string, useScoped?: boolean): postcss.Rule;
//# sourceMappingURL=selector-utils.d.ts.map

@@ -7,2 +7,3 @@ "use strict";

const postcss_1 = __importDefault(require("postcss"));
const stylable_value_parsers_1 = require("./stylable-value-parsers");
const tokenizer = require('css-selector-tokenizer');

@@ -118,2 +119,60 @@ function parseSelector(selector) {

exports.isNodeMatch = isNodeMatch;
function mergeChunks(chunks) {
const ast = { type: 'selectors', nodes: [] };
let i = 0;
for (const selectorChunks of chunks) {
ast.nodes[i] = { type: 'selector', nodes: [] };
for (const chunk of selectorChunks) {
if (chunk.type !== 'selector') {
ast.nodes[i].nodes.push(chunk);
}
else {
ast.nodes[i].before = chunk.before;
}
for (const node of chunk.nodes) {
ast.nodes[i].nodes.push(node);
}
}
i++;
}
return ast;
}
exports.mergeChunks = mergeChunks;
function separateChunks2(selectorNode) {
const selectors = [];
selectorNode.nodes.map(({ nodes, before }) => {
selectors.push([{ type: 'selector', nodes: [], before }]);
nodes.forEach(node => {
if (node.type === 'operator') {
const chunks = selectors[selectors.length - 1];
chunks.push(Object.assign(Object.assign({}, node), { nodes: [] }));
}
else if (node.type === 'spacing') {
const chunks = selectors[selectors.length - 1];
chunks.push(Object.assign(Object.assign({}, node), { nodes: [] }));
}
else {
const chunks = selectors[selectors.length - 1];
chunks[chunks.length - 1].nodes.push(node);
}
});
});
return selectors;
}
exports.separateChunks2 = separateChunks2;
function getOriginDefinition(resolved) {
for (const r of resolved) {
const { symbol } = r;
if (symbol._kind === 'class' || symbol._kind === 'element') {
if (symbol.alias && !symbol[stylable_value_parsers_1.valueMapping.extends]) {
continue;
}
else {
return r;
}
}
}
return resolved[0];
}
exports.getOriginDefinition = getOriginDefinition;
function separateChunks(selectorNode) {

@@ -134,3 +193,3 @@ const selectors = [];

const chunks = selectors[selectors.length - 1];
chunks.push({ type: node.type, nodes: [] });
chunks.push({ type: node.type, value: node.value, nodes: [] });
}

@@ -240,7 +299,7 @@ else {

exports.isCompRoot = isCompRoot;
function createWarningRule(extendedNode, scopedExtendedNode, extendedFile, extendingNode, scopedExtendingNode, extendingFile) {
function createWarningRule(extendedNode, scopedExtendedNode, extendedFile, extendingNode, scopedExtendingNode, extendingFile, useScoped = false) {
// tslint:disable-next-line:max-line-length
const message = `"class extending component '.${extendingNode} => ${scopedExtendingNode}' in stylesheet '${extendingFile}' was set on a node that does not extend '.${extendedNode} => ${scopedExtendedNode}' from stylesheet '${extendedFile}'" !important`;
return postcss_1.default.rule({
selector: `.${extendingNode}:not(.${extendedNode})::before`,
selector: `.${useScoped ? scopedExtendingNode : extendingNode}:not(.${useScoped ? scopedExtendedNode : extendedNode})::before`,
nodes: [

@@ -247,0 +306,0 @@ postcss_1.default.decl({

import { FileProcessor } from './cached-process-file';
import { Diagnostics } from './diagnostics';
import { Imported } from './stylable-meta';
import { ClassSymbol, ElementSymbol, Imported } from './stylable-meta';
import { ImportSymbol, StylableMeta, StylableSymbol } from './stylable-processor';

@@ -10,5 +10,5 @@ import { StylableTransformer } from './stylable-transformer';

};
export interface CSSResolve {
export interface CSSResolve<T extends StylableSymbol = StylableSymbol> {
_kind: 'css';
symbol: StylableSymbol;
symbol: T;
meta: StylableMeta;

@@ -25,13 +25,13 @@ }

constructor(fileProcessor: FileProcessor<StylableMeta>, requireModule: (modulePath: string) => any);
resolveImported(imported: Imported, name: string): CSSResolve | JSResolve | null;
resolveImport(importSymbol: ImportSymbol): CSSResolve | JSResolve | null;
resolveImported(imported: Imported, name: string): CSSResolve<StylableSymbol> | JSResolve | null;
resolveImport(importSymbol: ImportSymbol): CSSResolve<StylableSymbol> | JSResolve | null;
resolve(maybeImport: StylableSymbol | undefined): CSSResolve | JSResolve | null;
deepResolve(maybeImport: StylableSymbol | undefined, path?: StylableSymbol[]): CSSResolve | JSResolve | null;
resolveSymbolOrigin(symbol: StylableSymbol | undefined, meta: StylableMeta, path?: StylableSymbol[]): CSSResolve | null;
resolveClass(meta: StylableMeta, symbol: StylableSymbol): CSSResolve | null;
resolveClass(meta: StylableMeta, symbol: StylableSymbol): CSSResolve<StylableSymbol> | null;
resolveName(meta: StylableMeta, symbol: StylableSymbol, isElement: boolean): CSSResolve | null;
resolveElement(meta: StylableMeta, symbol: StylableSymbol): CSSResolve | null;
resolveExtends(meta: StylableMeta, className: string, isElement?: boolean, transformer?: StylableTransformer): CSSResolve[];
resolveElement(meta: StylableMeta, symbol: StylableSymbol): CSSResolve<StylableSymbol> | null;
resolveExtends(meta: StylableMeta, className: string, isElement?: boolean, transformer?: StylableTransformer, reportError?: (res: CSSResolve | JSResolve | null, extend: ImportSymbol | ClassSymbol | ElementSymbol, extendPath: Array<CSSResolve<ClassSymbol | ElementSymbol>>, meta: StylableMeta, className: string, isElement: boolean) => void): Array<CSSResolve<ClassSymbol | ElementSymbol>>;
validateImports(meta: StylableMeta, diagnostics: Diagnostics): void;
}
//# sourceMappingURL=stylable-resolver.d.ts.map

@@ -6,4 +6,8 @@ "use strict";

exports.resolverWarnings = {
UNKNOWN_IMPORTED_FILE(path) { return `cannot resolve imported file: "${path}"`; },
UNKNOWN_IMPORTED_SYMBOL(name, path) { return `cannot resolve imported symbol "${name}" in stylesheet "${path}"`; }
UNKNOWN_IMPORTED_FILE(path) {
return `cannot resolve imported file: "${path}"`;
},
UNKNOWN_IMPORTED_SYMBOL(name, path) {
return `cannot resolve imported symbol "${name}" from stylesheet "${path}"`;
}
};

@@ -37,5 +41,3 @@ class StylableResolver {

}
symbol = !name ?
_module.default || _module :
_module[name];
symbol = !name ? _module.default || _module : _module[name];
return { _kind: 'js', symbol, meta: null };

@@ -45,5 +47,3 @@ }

resolveImport(importSymbol) {
const name = importSymbol.type === 'named' ?
importSymbol.name :
'';
const name = importSymbol.type === 'named' ? importSymbol.name : '';
return this.resolveImported(importSymbol.import, name);

@@ -168,3 +168,3 @@ }

}
resolveExtends(meta, className, isElement = false, transformer) {
resolveExtends(meta, className, isElement = false, transformer, reportError) {
const bucket = isElement ? meta.elements : meta.classes;

@@ -198,3 +198,3 @@ const type = isElement ? 'element' : 'class';

}
const res = this.resolve(extend);
const res = this.resolve(extend) || { _kind: 'css', symbol: extend, meta };
if (res &&

@@ -208,2 +208,5 @@ res._kind === 'css' &&

else {
if (reportError) {
reportError(res, extend, extendPath, meta, className, isElement);
}
break;

@@ -210,0 +213,0 @@ }

import postcss from 'postcss';
import { FileProcessor } from './cached-process-file';
import { Diagnostics } from './diagnostics';
import { SelectorAstNode } from './selector-utils';
import { ClassSymbol, StylableMeta, StylableSymbol } from './stylable-processor';
import { SelectorAstNode, SelectorChunk2 } from './selector-utils';
import { ClassSymbol, ElementSymbol, StylableMeta, StylableSymbol } from './stylable-processor';
import { CSSResolve, StylableResolver } from './stylable-resolver';

@@ -10,3 +10,3 @@ export interface ResolvedElement {

type: string;
resolved: CSSResolve[];
resolved: Array<CSSResolve<ClassSymbol | ElementSymbol>>;
}

@@ -79,2 +79,3 @@ export interface KeyFrameWithNode {

mode: EnvMode;
private metaParts;
constructor(options: TransformerOptions);

@@ -97,5 +98,5 @@ transform(meta: StylableMeta): StylableResults;

applyRootScoping(meta: StylableMeta, selectorAst: SelectorAstNode): void;
scopeRule(meta: StylableMeta, rule: postcss.Rule, classesExport?: Record<string, string>): string;
scopeRule(meta: StylableMeta, rule: postcss.Rule, _classesExport?: Record<string, string>): string;
handleClass(meta: StylableMeta, node: SelectorAstNode, name: string, classesExport?: Record<string, string>, rule?: postcss.Rule, originMeta?: StylableMeta): CSSResolve;
handleElement(meta: StylableMeta, node: SelectorAstNode, name: string, originMeta?: StylableMeta): CSSResolve | {
handleElement(meta: StylableMeta, node: SelectorAstNode, name: string, originMeta?: StylableMeta): CSSResolve<StylableSymbol> | {
meta: StylableMeta;

@@ -106,6 +107,41 @@ symbol: StylableSymbol;

scope(name: string, namespace: string, delimiter?: string): string;
exportClasses(meta: StylableMeta): Record<string, string>;
getPartExports(resolved: Array<CSSResolve<ClassSymbol | ElementSymbol>>): string[];
scopeSelector2(originMeta: StylableMeta, selector: string, _classesExport?: Record<string, string>, _calcPaths?: boolean, rule?: postcss.Rule): {
selector: string;
elements: ResolvedElement[][];
};
scopeSelectorAst(context: ScopeSelectorContext): SelectorAstNode;
private handleChunkNode;
private handleCustomSelector;
private scopeClassNode;
private resolveMetaParts;
private addDevRules;
private resetTransformProperties;
}
export declare function removeSTDirective(root: postcss.Root): void;
interface ScopeSelectorContext {
originMeta: StylableMeta;
selectorAst: SelectorAstNode;
rule: postcss.Rule;
additionalSelectors?: Array<() => void>;
selectorIndex?: number;
metaParts?: MetaParts;
chunks?: SelectorChunk2[];
chunk?: SelectorChunk2;
node?: SelectorAstNode;
elements?: any[];
_currentAnchor?: any;
currentAnchor?: {
type: 'class' | 'element' | 'pseudo-element';
name: string;
resolved: Array<CSSResolve<ClassSymbol | ElementSymbol>>;
};
transformGlobals?: boolean;
}
interface MetaParts {
class: Record<string, Array<CSSResolve<ClassSymbol | ElementSymbol>>>;
element: Record<string, Array<CSSResolve<ClassSymbol | ElementSymbol>>>;
}
export {};
//# sourceMappingURL=stylable-transformer.d.ts.map

@@ -8,2 +8,3 @@ "use strict";

const path_1 = require("path");
const postcss_1 = __importDefault(require("postcss"));
const custom_values_1 = require("./custom-values");

@@ -18,2 +19,3 @@ const functions_1 = require("./functions");

const stylable_value_parsers_1 = require("./stylable-value-parsers");
const USE_SCOPE_SELECTOR_2 = true;
const isVendorPrefixed = require('is-vendor-prefixed');

@@ -54,2 +56,3 @@ const valueParser = require('postcss-value-parser');

constructor(options) {
this.metaParts = new WeakMap();
this.diagnostics = options.diagnostics;

@@ -107,5 +110,15 @@ this.delimiter = options.delimiter || '__';

});
if (USE_SCOPE_SELECTOR_2) {
if (this.mode === 'development') {
this.addDevRules(meta);
}
}
ast.walkRules((rule) => stylable_mixins_1.appendMixins(this, rule, meta, variableOverride || {}, cssVarsMapping, path));
if (metaExports) {
this.exportRootClass(meta, metaExports.classes);
if (USE_SCOPE_SELECTOR_2) {
Object.assign(metaExports.classes, this.exportClasses(meta));
}
else {
this.exportRootClass(meta, metaExports.classes);
}
this.exportLocalVars(meta, metaExports.stVars, variableOverride);

@@ -157,3 +170,2 @@ this.exportKeyframes(keyframeMapping, metaExports.keyframes);

const resolved = this.resolver.deepResolve(extend);
const found = stylable_utils_1.findRule(meta.ast, '.' + classSymbol.name);
if (resolved && resolved._kind === 'css' && resolved.symbol) {

@@ -166,3 +178,4 @@ if (resolved.symbol._kind === 'class') {

else {
if (!!found) {
const found = stylable_utils_1.findRule(meta.ast, '.' + classSymbol.name);
if (found) {
this.diagnostics.error(found, exports.transformerWarnings.IMPORT_ISNT_EXTENDABLE(), { word: found.value });

@@ -172,11 +185,14 @@ }

}
else if (found && resolved) {
if (!resolved.symbol) {
this.diagnostics.error(found, exports.transformerWarnings.CANNOT_EXTEND_UNKNOWN_SYMBOL(found.value), { word: found.value });
else if (resolved) {
const found = stylable_utils_1.findRule(meta.ast, '.' + classSymbol.name);
if (found) {
if (!resolved.symbol) {
this.diagnostics.error(found, exports.transformerWarnings.CANNOT_EXTEND_UNKNOWN_SYMBOL(found.value), { word: found.value });
}
else {
this.diagnostics.error(found, exports.transformerWarnings.CANNOT_EXTEND_JS(), {
word: found.value
});
}
}
else {
this.diagnostics.error(found, exports.transformerWarnings.CANNOT_EXTEND_JS(), {
word: found.value
});
}
}

@@ -293,3 +309,8 @@ }

resolveSelectorElements(meta, selector) {
return this.scopeSelector(meta, selector, undefined, true).elements;
if (USE_SCOPE_SELECTOR_2) {
return this.scopeSelector2(meta, selector, undefined, true).elements;
}
else {
return this.scopeSelector(meta, selector, undefined, true).elements;
}
}

@@ -427,4 +448,9 @@ scopeSelector(originMeta, selector, classesExport, calcPaths = false, rule) {

}
scopeRule(meta, rule, classesExport) {
return this.scopeSelector(meta, rule.selector, classesExport, false, rule).selector;
scopeRule(meta, rule, _classesExport) {
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;
}
}

@@ -611,2 +637,308 @@ handleClass(meta, node, name, classesExport, rule, originMeta) {

}
exportClasses(meta) {
const locals = {};
const metaParts = this.resolveMetaParts(meta);
for (const [localName, resolved] of Object.entries(metaParts.class)) {
const exportedClasses = this.getPartExports(resolved);
locals[localName] = exportedClasses.join(' ');
}
return locals;
}
/* None alias symbol */
getPartExports(resolved) {
const exportedClasses = [];
let first = true;
for (const { meta, symbol } of resolved) {
if (!first && symbol[stylable_value_parsers_1.valueMapping.root]) {
break;
}
first = false;
if (symbol.alias && !symbol[stylable_value_parsers_1.valueMapping.extends]) {
continue;
}
exportedClasses.push(this.scope(symbol.name, meta.namespace));
}
return exportedClasses;
}
scopeSelector2(originMeta, selector, _classesExport, _calcPaths = false, rule) {
const context = {
originMeta,
selectorAst: selector_utils_1.parseSelector(selector),
rule: rule || postcss_1.default.rule({ selector }),
_currentAnchor: null,
elements: [],
get currentAnchor() {
return this._currentAnchor;
},
set currentAnchor(c) {
if (this.selectorIndex !== undefined && this.selectorIndex !== -1) {
this.elements[this.selectorIndex].push(c);
}
this._currentAnchor = c;
}
};
return {
selector: selector_utils_1.stringifySelector(this.scopeSelectorAst(context)),
elements: context.elements
};
}
scopeSelectorAst(context) {
const { originMeta, selectorAst } = context;
// split selectors to chunks: .a.b .c:hover, a .c:hover -> [[[.a.b], [.c:hover]], [[.a], [.c:hover]]]
const selectorListChunks = selector_utils_1.separateChunks2(selectorAst);
// resolve meta classes and elements
context.metaParts = this.resolveMetaParts(originMeta);
// set stylesheet root as the global anchor
context.currentAnchor = context.currentAnchor || {
name: originMeta.root,
type: 'class',
resolved: context.metaParts.class[originMeta.root]
};
context.selectorIndex = -1;
// used to add additional selector (used in custom selector flow)
context.additionalSelectors = [];
context.elements = [];
// loop over selectors
for (const selectorChunks of selectorListChunks) {
context.elements.push([]);
context.selectorIndex++;
context.chunks = selectorChunks;
// loop over chunks
for (const chunk of selectorChunks) {
context.chunk = chunk;
// loop over each node in a chunk
for (const node of chunk.nodes) {
context.node = node;
// transfrom node
this.handleChunkNode(context);
}
}
}
const outputAst = selector_utils_1.mergeChunks(selectorListChunks);
context.additionalSelectors.forEach(addSelector => outputAst.nodes.push(addSelector()));
return outputAst;
}
handleChunkNode(context) {
const { node, metaParts, originMeta, transformGlobals } = context;
const { type, name } = node;
if (type === 'class') {
const resolved = metaParts.class[name] || [
// used to scope classes from js mixins
{ _kind: 'css', meta: originMeta, symbol: { _kind: 'class', name } }
];
context.currentAnchor = { name, type: 'class', resolved };
const { symbol, meta } = selector_utils_1.getOriginDefinition(resolved);
this.scopeClassNode(symbol, meta, node, originMeta);
}
else if (type === 'element') {
const resolved = metaParts.element[name] || [
// provides resolution for native elements
{ _kind: 'css', meta: originMeta, symbol: { _kind: 'element', name } }
];
context.currentAnchor = { name, type: 'element', resolved };
// native node does not resolve e.g. div
if (resolved && resolved.length > 1) {
const { symbol, meta } = selector_utils_1.getOriginDefinition(resolved);
this.scopeClassNode(symbol, meta, node, originMeta);
}
}
else if (type === 'pseudo-element') {
const len = context.currentAnchor.resolved.length;
const lookupStartingPoint = len === 1 /* no extends */ ? 0 : 1;
let resolved;
for (let i = lookupStartingPoint; i < len; i++) {
const { symbol, meta } = context.currentAnchor.resolved[i];
if (!symbol[stylable_value_parsers_1.valueMapping.root]) {
// debugger
continue;
}
const customSelector = meta.customSelectors[':--' + name];
if (customSelector) {
this.handleCustomSelector(customSelector, meta, context, name, node);
return;
}
const requestedPart = meta.classes[name];
if (symbol.alias || !requestedPart) {
// skip alias since thay cannot add parts
continue;
}
resolved = this.resolveMetaParts(meta).class[name];
// first definition of a part in the extends/alias chain
context.currentAnchor = {
name,
type: 'pseudo-element',
resolved
};
const resolvedPart = selector_utils_1.getOriginDefinition(resolved);
node.before = resolvedPart.symbol[stylable_value_parsers_1.valueMapping.root] ? '' : ' ';
this.scopeClassNode(resolvedPart.symbol, resolvedPart.meta, node, originMeta);
break;
}
if (!resolved) {
// first definition of a part in the extends/alias chain
context.currentAnchor = {
name,
type: 'pseudo-element',
resolved: []
};
if (native_reserved_lists_1.nativePseudoElements.indexOf(name) === -1 && !isVendorPrefixed(name)) {
this.diagnostics.warn(context.rule, exports.transformerWarnings.UNKNOWN_PSEUDO_ELEMENT(name), {
word: name
});
}
}
}
else if (type === 'pseudo-class') {
let found = false;
for (const { symbol, meta } of context.currentAnchor.resolved) {
const states = symbol[stylable_value_parsers_1.valueMapping.states];
if (states && states.hasOwnProperty(name)) {
found = true;
pseudo_states_1.setStateToNode(states, meta, name, node, meta.namespace, this.resolver, this.diagnostics, context.rule);
break;
}
}
if (!found && native_reserved_lists_1.nativePseudoClasses.indexOf(name) === -1 && !isVendorPrefixed(name)) {
this.diagnostics.warn(context.rule, pseudo_states_1.stateErrors.UNKNOWN_STATE_USAGE(name), {
word: name
});
}
}
else if (type === 'nested-pseudo-class') {
if (name === 'global') {
// :global(.a) -> .a
if (transformGlobals) {
node.type = 'selector';
}
}
else {
this.scopeSelectorAst(Object.assign(Object.assign({}, context), { selectorAst: {
type: 'selectors',
name: `${name}`,
nodes: node.nodes
} }));
}
}
else if (type === 'invalid' && node.value === '&') {
if ( /* maybe should be currentAnchor meta */originMeta.parent) {
const origin = originMeta.mappedSymbols[originMeta.root];
context.currentAnchor = {
name: origin.name,
type: 'class',
resolved: context.metaParts.class[origin.name]
};
}
}
}
handleCustomSelector(customSelector, meta, context, name, node) {
const selectorListChunks = selector_utils_1.separateChunks2(selector_utils_1.parseSelector(customSelector));
const hasSingleSelector = selectorListChunks.length === 1;
removeFirstRootInEachSelectorChunk(selectorListChunks, meta);
const internalContext = {
originMeta: meta,
selectorAst: selector_utils_1.mergeChunks(selectorListChunks),
rule: context.rule,
_currentAnchor: null,
elements: [],
get currentAnchor() {
return this._currentAnchor;
},
set currentAnchor(c) {
if (this.selectorIndex !== undefined && this.selectorIndex !== -1) {
// context.currentAnchor = c
this.elements[this.selectorIndex].push(c);
}
this._currentAnchor = c;
}
};
const customAstSelectors = this.scopeSelectorAst(internalContext).nodes;
customAstSelectors.forEach(trimLeftSelectorAst);
if (hasSingleSelector && internalContext.currentAnchor) {
// context.currentAnchor = internalContext.currentAnchor;
context.currentAnchor = {
name,
type: 'pseudo-element',
resolved: internalContext.currentAnchor.resolved
};
}
else {
// unknown context due to multiple selectors
// context.currentAnchor = anyElementAnchor(meta);
context.currentAnchor = {
name,
type: 'pseudo-element',
resolved: anyElementAnchor(meta).resolved
};
}
Object.assign(node, customAstSelectors[0]);
// first one handled inline above
for (let i = 1; i < customAstSelectors.length; i++) {
const selectorNode = context.selectorAst.nodes[context.selectorIndex];
const nodeIndex = selectorNode.nodes.indexOf(node);
context.additionalSelectors.push(lazyCreateSelector(customAstSelectors[i], selectorNode, nodeIndex));
}
}
scopeClassNode(symbol, meta, node, originMeta) {
if (symbol[stylable_value_parsers_1.valueMapping.global]) {
const globalMappedNodes = symbol[stylable_value_parsers_1.valueMapping.global];
node.type = 'selector';
node.nodes = globalMappedNodes;
this.addGlobalsToMeta(globalMappedNodes, originMeta);
}
else {
node.type = 'class';
node.name = this.scope(symbol.name, meta.namespace);
}
}
resolveMetaParts(meta) {
let metaParts = this.metaParts.get(meta);
if (!metaParts) {
const resolvedClasses = {};
for (const className of Object.keys(meta.classes)) {
resolvedClasses[className] = this.resolver.resolveExtends(meta, className, false, this, (res, extend) => {
const decl = stylable_utils_1.findRule(meta.ast, '.' + className);
if (decl) {
if (res && res._kind === 'js') {
this.diagnostics.error(decl, exports.transformerWarnings.CANNOT_EXTEND_JS(), {
word: decl.value
});
}
else if (res && !res.symbol) {
this.diagnostics.error(decl, exports.transformerWarnings.CANNOT_EXTEND_UNKNOWN_SYMBOL(extend.name), { word: decl.value });
}
else {
this.diagnostics.error(decl, exports.transformerWarnings.IMPORT_ISNT_EXTENDABLE(), { word: decl.value });
}
}
else {
if (meta.classes[className] && meta.classes[className].alias) {
meta.ast.walkRules(new RegExp('\\.' + className), rule => {
this.diagnostics.error(rule, exports.transformerWarnings.UNKNOWN_IMPORT_ALIAS(className), { word: className });
return false;
});
}
}
});
}
const resolvedElements = {};
for (const k of Object.keys(meta.elements)) {
resolvedElements[k] = this.resolver.resolveExtends(meta, k, true, this);
}
metaParts = { class: resolvedClasses, element: resolvedElements };
this.metaParts.set(meta, metaParts);
}
return metaParts;
}
addDevRules(meta) {
const metaParts = this.resolveMetaParts(meta);
for (const [className, resolved] of Object.entries(metaParts.class)) {
if (resolved.length > 1) {
meta.outputAst.walkRules('.' + this.scope(className, meta.namespace), rule => {
const a = resolved[0];
const b = resolved[1];
rule.after(selector_utils_1.createWarningRule(b.symbol.name, this.scope(b.symbol.name, b.meta.namespace), path_1.basename(b.meta.source), a.symbol.name, this.scope(a.symbol.name, a.meta.namespace), path_1.basename(a.meta.source), true));
});
}
}
}
resetTransformProperties(meta) {

@@ -688,2 +1020,38 @@ meta.globals = {};

}
function removeFirstRootInEachSelectorChunk(selectorListChunks, meta) {
selectorListChunks.forEach(selectorChunks => {
selectorChunks[0].nodes = selectorChunks[0].nodes.filter(({ type, name }) => {
return !(type === 'class' && name === meta.root);
});
});
}
function trimLeftSelectorAst(n, i = 0) {
if (n) {
if (n.type === 'spacing') {
n.value = '';
}
n.before = '';
trimLeftSelectorAst(n.nodes && n.nodes[0], i + 1);
if (i === 0) {
n.before = ' ';
}
}
}
function anyElementAnchor(meta) {
return {
type: 'element',
name: '*',
resolved: [{ _kind: 'css', meta, symbol: { _kind: 'element', name: '*' } }]
};
}
function lazyCreateSelector(customElementChunk, selectorNode, nodeIndex) {
if (nodeIndex === -1) {
throw new Error('not supported inside nested classes');
}
return () => {
const clone = lodash_clonedeep_1.default(selectorNode);
clone.nodes[nodeIndex].nodes = customElementChunk.nodes;
return clone;
};
}
//# sourceMappingURL=stylable-transformer.js.map

@@ -18,3 +18,3 @@ import postcss from 'postcss';

export declare function findDeclaration(importNode: Imported, test: any): postcss.Declaration;
export declare function findRule(root: postcss.Root, selector: string, test?: any): any;
export declare function findRule(root: postcss.Root, selector: string, test?: any): null | postcss.Declaration;
export declare function getDeclStylable(decl: SDecl): DeclStylableProps;

@@ -21,0 +21,0 @@ export declare function getSourcePath(root: postcss.Root, diagnostics: Diagnostics): string;

@@ -217,2 +217,3 @@ "use strict";

exports.findDeclaration = findDeclaration;
// TODO: What is this?
function findRule(root, selector, test = (statement) => statement.prop === stylable_value_parsers_1.valueMapping.extends) {

@@ -219,0 +220,0 @@ let found = null;

{
"name": "@stylable/core",
"version": "2.4.0",
"version": "2.4.1-alpha.0",
"description": "CSS for Components",

@@ -47,3 +47,3 @@ "main": "./cjs/index.js",

"license": "BSD-3-Clause",
"gitHead": "8eff3a9c749f71d4f9a5578e3b57be6034ef1435"
"gitHead": "d6d3e197927e688d6db4a831fb4285ad4c418df3"
}

@@ -75,3 +75,3 @@ import postcss from 'postcss';

meta: StylableMeta,
node: postcss.Node,
node?: postcss.Node,
variableOverride?: Record<string, string> | null,

@@ -83,3 +83,4 @@ valueHook?: replaceValueHook,

args: string[] = []
): { topLevelType: any; outputValue: string; typeError: Error } {
): { topLevelType: any; outputValue: string; typeError: Error } {
diagnostics = node ? diagnostics : undefined;
const customValues = resolveCustomValues(meta, resolver);

@@ -142,3 +143,3 @@ const parsedValue = valueParser(value);

if (diagnostics) {
if (diagnostics && node) {
const argsAsString = parsedArgs.join(', ');

@@ -195,3 +196,3 @@ if (typeError) {

: resolvedVarSymbol._kind;
if (diagnostics) {
if (diagnostics && node) {
diagnostics.warn(

@@ -207,3 +208,3 @@ node,

}
} else if (resolvedVar._kind === 'js' && diagnostics) {
} else if (resolvedVar._kind === 'js' && diagnostics && node) {
// ToDo: provide actual exported id (default/named as x)

@@ -222,3 +223,3 @@ diagnostics.warn(

});
if (namedDecl && diagnostics) {
if (namedDecl && diagnostics && node) {
// ToDo: provide actual exported id (default/named as x)

@@ -232,3 +233,3 @@ diagnostics.error(

}
} else if (diagnostics) {
} else if (diagnostics && node) {
diagnostics.warn(node, functionWarnings.UNKNOWN_VAR(varName), {

@@ -270,3 +271,3 @@ word: varName

parsedNode.resolvedValue = stringifyFunction(value, parsedNode);
if (diagnostics) {
if (diagnostics && node) {
diagnostics.warn(

@@ -295,3 +296,3 @@ node,

parsedNode.resolvedValue = stringifyFunction(value, parsedNode);
} else if (diagnostics) {
} else if (diagnostics && node) {
parsedNode.resolvedValue = stringifyFunction(value, parsedNode);

@@ -344,3 +345,3 @@ diagnostics.warn(node, functionWarnings.UNKNOWN_FORMATTER(value), {

meta: StylableMeta,
node: postcss.Node,
node?: postcss.Node,
variableOverride?: Record<string, string> | null,

@@ -371,3 +372,3 @@ valueHook?: replaceValueHook,

diagnostics: Diagnostics | undefined,
node: postcss.Node,
node: postcss.Node | undefined,
value: string,

@@ -378,3 +379,3 @@ parsedNode: ParsedValue

cyclicChain.push(refUniqID);
if (diagnostics) {
if (diagnostics && node) {
diagnostics.warn(node, functionWarnings.CYCLIC_VALUE(cyclicChain), {

@@ -381,0 +382,0 @@ word: refUniqID

@@ -440,6 +440,3 @@ import postcss from 'postcss';

const param = nodeContent || defaultStringValue;
return rule
? evalDeclarationValue(resolver, param, meta, rule, undefined, undefined, diagnostics)
: param;
return evalDeclarationValue(resolver, param, meta, rule, undefined, undefined, diagnostics);
}

@@ -446,0 +443,0 @@

import postcss from 'postcss';
import { ClassSymbol, ElementSymbol } from './stylable-meta';
import { CSSResolve } from './stylable-resolver';
import { valueMapping } from './stylable-value-parsers';
const tokenizer = require('css-selector-tokenizer');

@@ -148,5 +151,69 @@

operator?: string;
value?: string;
nodes: Array<Partial<SelectorAstNode>>;
}
export interface SelectorChunk2 {
type: string;
operator?: string;
value?: string;
nodes: SelectorAstNode[];
before?: string;
}
export function mergeChunks(chunks: SelectorChunk2[][]) {
const ast: any = { type: 'selectors', nodes: [] };
let i = 0;
for (const selectorChunks of chunks) {
ast.nodes[i] = { type: 'selector', nodes: [] };
for (const chunk of selectorChunks) {
if (chunk.type !== 'selector') {
ast.nodes[i].nodes.push(chunk);
} else {
ast.nodes[i].before = chunk.before;
}
for (const node of chunk.nodes) {
ast.nodes[i].nodes.push(node);
}
}
i++;
}
return ast;
}
export function separateChunks2(selectorNode: SelectorAstNode) {
const selectors: SelectorChunk2[][] = [];
selectorNode.nodes.map(({ nodes, before }) => {
selectors.push([{ type: 'selector', nodes: [], before }]);
nodes.forEach(node => {
if (node.type === 'operator') {
const chunks = selectors[selectors.length - 1];
chunks.push({ ...node, nodes: [] });
} else if (node.type === 'spacing') {
const chunks = selectors[selectors.length - 1];
chunks.push({ ...node, nodes: [] });
} else {
const chunks = selectors[selectors.length - 1];
chunks[chunks.length - 1].nodes.push(node);
}
});
});
return selectors;
}
export function getOriginDefinition(resolved: Array<CSSResolve<ClassSymbol | ElementSymbol>>) {
for (const r of resolved) {
const { symbol } = r;
if (symbol._kind === 'class' || symbol._kind === 'element') {
if (symbol.alias && !symbol[valueMapping.extends]) {
continue;
} else {
return r;
}
}
}
return resolved[0];
}
export function separateChunks(selectorNode: SelectorAstNode) {

@@ -165,3 +232,3 @@ const selectors: SelectorChunk[][] = [];

const chunks = selectors[selectors.length - 1];
chunks.push({ type: node.type, nodes: [] });
chunks.push({ type: node.type, value: node.value, nodes: [] });
} else {

@@ -295,3 +362,4 @@ const chunks = selectors[selectors.length - 1];

scopedExtendingNode: string,
extendingFile: string
extendingFile: string,
useScoped = false
) {

@@ -301,3 +369,5 @@ // tslint:disable-next-line:max-line-length

return postcss.rule({
selector: `.${extendingNode}:not(.${extendedNode})::before`,
selector: `.${useScoped ? scopedExtendingNode : extendingNode}:not(.${
useScoped ? scopedExtendedNode : extendedNode
})::before`,
nodes: [

@@ -304,0 +374,0 @@ postcss.decl({

import { FileProcessor } from './cached-process-file';
import { Diagnostics } from './diagnostics';
import { Imported } from './stylable-meta';
import { ClassSymbol, ElementSymbol, Imported } from './stylable-meta';
import { ImportSymbol, StylableMeta, StylableSymbol } from './stylable-processor';

@@ -10,10 +10,14 @@ import { StylableTransformer } from './stylable-transformer';

export const resolverWarnings = {
UNKNOWN_IMPORTED_FILE(path: string) { return `cannot resolve imported file: "${path}"`; },
UNKNOWN_IMPORTED_SYMBOL(name: string, path: string) { return `cannot resolve imported symbol "${name}" in stylesheet "${path}"`; }
UNKNOWN_IMPORTED_FILE(path: string) {
return `cannot resolve imported file: "${path}"`;
},
UNKNOWN_IMPORTED_SYMBOL(name: string, path: string) {
return `cannot resolve imported symbol "${name}" from stylesheet "${path}"`;
}
};
/* tslint:enable:max-line-length */
export interface CSSResolve {
export interface CSSResolve<T extends StylableSymbol = StylableSymbol> {
_kind: 'css';
symbol: StylableSymbol;
symbol: T;
meta: StylableMeta;

@@ -53,5 +57,3 @@ }

}
symbol = !name ?
_module.default || _module :
_module[name];
symbol = !name ? _module.default || _module : _module[name];

@@ -62,5 +64,3 @@ return { _kind: 'js', symbol, meta: null } as JSResolve;

public resolveImport(importSymbol: ImportSymbol) {
const name = importSymbol.type === 'named' ?
importSymbol.name :
'';
const name = importSymbol.type === 'named' ? importSymbol.name : '';
return this.resolveImported(importSymbol.import, name);

@@ -195,4 +195,12 @@ }

isElement: boolean = false,
transformer?: StylableTransformer
): CSSResolve[] {
transformer?: StylableTransformer,
reportError?: (
res: CSSResolve | JSResolve | null,
extend: ImportSymbol | ClassSymbol | ElementSymbol,
extendPath: Array<CSSResolve<ClassSymbol | ElementSymbol>>,
meta: StylableMeta,
className: string,
isElement: boolean
) => void
): Array<CSSResolve<ClassSymbol | ElementSymbol>> {
const bucket = isElement ? meta.elements : meta.classes;

@@ -216,3 +224,3 @@ const type = isElement ? 'element' : 'class';

const extendPath = [];
const extendPath: Array<CSSResolve<ClassSymbol | ElementSymbol>> = [];
const resolvedClass = this.resolveName(meta, bucket[className], isElement);

@@ -226,3 +234,3 @@

) {
let current = resolvedClass;
let current = resolvedClass as CSSResolve<ClassSymbol | ElementSymbol>;
let extend = resolvedClass.symbol[valueMapping.extends] || resolvedClass.symbol.alias;

@@ -235,3 +243,3 @@

}
const res = this.resolve(extend);
const res = this.resolve(extend) || { _kind: 'css', symbol: extend, meta };
if (

@@ -243,5 +251,8 @@ res &&

) {
current = res;
current = res as CSSResolve<ClassSymbol | ElementSymbol>;
extend = res.symbol[valueMapping.extends] || res.symbol.alias;
} else {
if (reportError) {
reportError(res, extend, extendPath, meta, className, isElement);
}
break;

@@ -260,4 +271,7 @@ }

// warn about unknown imported files
const fromDecl = importObj.rule.nodes &&
importObj.rule.nodes.find(decl => decl.type === 'decl' && decl.prop === valueMapping.from);
const fromDecl =
importObj.rule.nodes &&
importObj.rule.nodes.find(
decl => decl.type === 'decl' && decl.prop === valueMapping.from
);

@@ -268,5 +282,5 @@ if (fromDecl) {

resolverWarnings.UNKNOWN_IMPORTED_FILE(importObj.fromRelative),
{ word: importObj.fromRelative });
{ word: importObj.fromRelative }
);
}
} else if (resolvedImport._kind === 'css') {

@@ -277,4 +291,7 @@ // warn about unknown named imported symbols

const resolvedSymbol = this.resolveImported(importObj, origName);
const namedDecl = importObj.rule.nodes &&
importObj.rule.nodes.find(decl => decl.type === 'decl' && decl.prop === valueMapping.named);
const namedDecl =
importObj.rule.nodes &&
importObj.rule.nodes.find(
decl => decl.type === 'decl' && decl.prop === valueMapping.named
);

@@ -284,4 +301,8 @@ if (!resolvedSymbol!.symbol && namedDecl) {

namedDecl,
resolverWarnings.UNKNOWN_IMPORTED_SYMBOL(origName, importObj.fromRelative),
{ word: origName });
resolverWarnings.UNKNOWN_IMPORTED_SYMBOL(
origName,
importObj.fromRelative
),
{ word: origName }
);
}

@@ -288,0 +309,0 @@ }

@@ -8,9 +8,22 @@ import cloneDeep from 'lodash.clonedeep';

import { evalDeclarationValue, processDeclarationValue } from './functions';
import { nativePseudoElements, reservedKeyFrames } from './native-reserved-lists';
import { transformPseudoStateSelector, validateStateDefinition } from './pseudo-states';
import {
nativePseudoClasses,
nativePseudoElements,
reservedKeyFrames
} from './native-reserved-lists';
import {
setStateToNode,
stateErrors,
transformPseudoStateSelector,
validateStateDefinition
} from './pseudo-states';
import {
createWarningRule,
getOriginDefinition,
isChildOfAtRule,
mergeChunks,
parseSelector,
SelectorAstNode,
SelectorChunk2,
separateChunks2,
stringifySelector,

@@ -32,2 +45,4 @@ traverseNode

const USE_SCOPE_SELECTOR_2 = true;
const isVendorPrefixed = require('is-vendor-prefixed');

@@ -39,3 +54,3 @@ const valueParser = require('postcss-value-parser');

type: string;
resolved: CSSResolve[];
resolved: Array<CSSResolve<ClassSymbol | ElementSymbol>>;
}

@@ -145,2 +160,4 @@

public mode: EnvMode;
private metaParts = new WeakMap<StylableMeta, MetaParts>();
constructor(options: TransformerOptions) {

@@ -230,3 +247,7 @@ this.diagnostics = options.diagnostics;

});
if (USE_SCOPE_SELECTOR_2) {
if (this.mode === 'development') {
this.addDevRules(meta);
}
}
ast.walkRules((rule: SRule) =>

@@ -237,3 +258,7 @@ appendMixins(this, rule, meta, variableOverride || {}, cssVarsMapping, path)

if (metaExports) {
this.exportRootClass(meta, metaExports.classes);
if (USE_SCOPE_SELECTOR_2) {
Object.assign(metaExports.classes, this.exportClasses(meta));
} else {
this.exportRootClass(meta, metaExports.classes);
}
this.exportLocalVars(meta, metaExports.stVars, variableOverride);

@@ -313,3 +338,2 @@ this.exportKeyframes(keyframeMapping, metaExports.keyframes);

const resolved = this.resolver.deepResolve(extend);
const found = findRule(meta.ast, '.' + classSymbol.name);
if (resolved && resolved._kind === 'css' && resolved.symbol) {

@@ -321,3 +345,4 @@ if (resolved.symbol._kind === 'class') {

} else {
if (!!found) {
const found = findRule(meta.ast, '.' + classSymbol.name);
if (found) {
this.diagnostics.error(

@@ -330,13 +355,20 @@ found,

}
} else if (found && resolved) {
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
});
} 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
}
);
}
}

@@ -484,3 +516,7 @@ }

public resolveSelectorElements(meta: StylableMeta, selector: string): ResolvedElement[][] {
return this.scopeSelector(meta, selector, undefined, true).elements;
if (USE_SCOPE_SELECTOR_2) {
return this.scopeSelector2(meta, selector, undefined, true).elements;
} else {
return this.scopeSelector(meta, selector, undefined, true).elements;
}
}

@@ -666,5 +702,9 @@ public scopeSelector(

rule: postcss.Rule,
classesExport?: Record<string, string>
_classesExport?: Record<string, string>
): string {
return this.scopeSelector(meta, rule.selector, classesExport, false, rule).selector;
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;
}
}

@@ -896,2 +936,381 @@ public handleClass(

}
public exportClasses(meta: StylableMeta) {
const locals: Record<string, string> = {};
const metaParts = this.resolveMetaParts(meta);
for (const [localName, resolved] of Object.entries(metaParts.class)) {
const exportedClasses = this.getPartExports(resolved);
locals[localName] = exportedClasses.join(' ');
}
return locals;
}
/* None alias symbol */
public getPartExports(resolved: Array<CSSResolve<ClassSymbol | ElementSymbol>>) {
const exportedClasses = [];
let first = true;
for (const { meta, symbol } of resolved) {
if (!first && symbol[valueMapping.root]) {
break;
}
first = false;
if (symbol.alias && !symbol[valueMapping.extends]) {
continue;
}
exportedClasses.push(this.scope(symbol.name, meta.namespace));
}
return exportedClasses;
}
public scopeSelector2(
originMeta: StylableMeta,
selector: string,
_classesExport?: Record<string, string>,
_calcPaths = false,
rule?: postcss.Rule
): { selector: string; elements: ResolvedElement[][] } {
const context: ScopeSelectorContext = {
originMeta,
selectorAst: parseSelector(selector),
rule: rule || postcss.rule({ selector }),
_currentAnchor: null,
elements: [],
get currentAnchor() {
return this._currentAnchor;
},
set currentAnchor(c) {
if (this.selectorIndex !== undefined && this.selectorIndex !== -1) {
this.elements![this.selectorIndex!]!.push(c!);
}
this._currentAnchor = c;
}
};
return {
selector: stringifySelector(this.scopeSelectorAst(context)),
elements: context.elements!
};
}
public scopeSelectorAst(context: ScopeSelectorContext): SelectorAstNode {
const { originMeta, selectorAst } = context;
// split selectors to chunks: .a.b .c:hover, a .c:hover -> [[[.a.b], [.c:hover]], [[.a], [.c:hover]]]
const selectorListChunks = separateChunks2(selectorAst);
// resolve meta classes and elements
context.metaParts = this.resolveMetaParts(originMeta);
// set stylesheet root as the global anchor
context.currentAnchor = context.currentAnchor || {
name: originMeta.root,
type: 'class',
resolved: context.metaParts.class[originMeta.root]
};
context.selectorIndex = -1;
// used to add additional selector (used in custom selector flow)
context.additionalSelectors = [];
context.elements = [];
// loop over selectors
for (const selectorChunks of selectorListChunks) {
context.elements.push([]);
context.selectorIndex++;
context.chunks = selectorChunks;
// loop over chunks
for (const chunk of selectorChunks) {
context.chunk = chunk;
// loop over each node in a chunk
for (const node of chunk.nodes) {
context.node = node;
// transfrom node
this.handleChunkNode(context as Required<ScopeSelectorContext>);
}
}
}
const outputAst = mergeChunks(selectorListChunks);
context.additionalSelectors.forEach(addSelector => outputAst.nodes.push(addSelector()));
return outputAst;
}
private handleChunkNode(context: Required<ScopeSelectorContext>) {
const { node, metaParts, originMeta, transformGlobals } = context;
const { type, name } = node;
if (type === 'class') {
const resolved = metaParts.class[name] || [
// used to scope classes from js mixins
{ _kind: 'css', meta: originMeta, symbol: { _kind: 'class', name } }
];
context.currentAnchor = { name, type: 'class', resolved };
const { symbol, meta } = getOriginDefinition(resolved);
this.scopeClassNode(symbol, meta, node, originMeta);
} else if (type === 'element') {
const resolved = metaParts.element[name] || [
// provides resolution for native elements
{ _kind: 'css', meta: originMeta, symbol: { _kind: 'element', name } }
];
context.currentAnchor = { name, type: 'element', resolved };
// native node does not resolve e.g. div
if (resolved && resolved.length > 1) {
const { symbol, meta } = getOriginDefinition(resolved);
this.scopeClassNode(symbol, meta, node, originMeta);
}
} else if (type === 'pseudo-element') {
const len = context.currentAnchor.resolved.length;
const lookupStartingPoint = len === 1 /* no extends */ ? 0 : 1;
let resolved: Array<CSSResolve<ClassSymbol | ElementSymbol>> | undefined;
for (let i = lookupStartingPoint; i < len; i++) {
const { symbol, meta } = context.currentAnchor.resolved[i];
if (!symbol[valueMapping.root]) {
// debugger
continue;
}
const customSelector = meta.customSelectors[':--' + name];
if (customSelector) {
this.handleCustomSelector(customSelector, meta, context, name, node);
return;
}
const requestedPart = meta.classes[name];
if (symbol.alias || !requestedPart) {
// skip alias since thay cannot add parts
continue;
}
resolved = this.resolveMetaParts(meta).class[name];
// first definition of a part in the extends/alias chain
context.currentAnchor = {
name,
type: 'pseudo-element',
resolved
};
const resolvedPart = getOriginDefinition(resolved);
node.before = resolvedPart.symbol[valueMapping.root] ? '' : ' ';
this.scopeClassNode(resolvedPart.symbol, resolvedPart.meta, node, originMeta);
break;
}
if (!resolved) {
// first definition of a part in the extends/alias chain
context.currentAnchor = {
name,
type: 'pseudo-element',
resolved: []
};
if (nativePseudoElements.indexOf(name) === -1 && !isVendorPrefixed(name)) {
this.diagnostics.warn(
context.rule,
transformerWarnings.UNKNOWN_PSEUDO_ELEMENT(name),
{
word: name
}
);
}
}
} else if (type === 'pseudo-class') {
let found = false;
for (const { symbol, meta } of context.currentAnchor.resolved) {
const states = symbol[valueMapping.states];
if (states && states.hasOwnProperty(name)) {
found = true;
setStateToNode(
states,
meta,
name,
node,
meta.namespace,
this.resolver,
this.diagnostics,
context.rule
);
break;
}
}
if (!found && nativePseudoClasses.indexOf(name) === -1 && !isVendorPrefixed(name)) {
this.diagnostics.warn(context.rule, stateErrors.UNKNOWN_STATE_USAGE(name), {
word: name
});
}
} else if (type === 'nested-pseudo-class') {
if (name === 'global') {
// :global(.a) -> .a
if (transformGlobals) {
node.type = 'selector';
}
} else {
this.scopeSelectorAst({
...context,
selectorAst: {
type: 'selectors',
name: `${name}`,
nodes: node.nodes
}
});
}
} else if (type === 'invalid' && node.value === '&') {
if (/* maybe should be currentAnchor meta */ originMeta.parent) {
const origin = originMeta.mappedSymbols[originMeta.root] as ClassSymbol;
context.currentAnchor = {
name: origin.name,
type: 'class',
resolved: context.metaParts.class[origin.name]
};
}
}
}
private handleCustomSelector(
customSelector: string,
meta: StylableMeta,
context: Required<ScopeSelectorContext>,
name: string,
node: SelectorAstNode
) {
const selectorListChunks = separateChunks2(parseSelector(customSelector));
const hasSingleSelector = selectorListChunks.length === 1;
removeFirstRootInEachSelectorChunk(selectorListChunks, meta);
const internalContext: ScopeSelectorContext = {
originMeta: meta,
selectorAst: mergeChunks(selectorListChunks),
rule: context.rule,
_currentAnchor: null,
elements: [],
get currentAnchor() {
return this._currentAnchor;
},
set currentAnchor(c) {
if (this.selectorIndex !== undefined && this.selectorIndex !== -1) {
// context.currentAnchor = c
this.elements![this.selectorIndex!]!.push(c!);
}
this._currentAnchor = c;
}
};
const customAstSelectors = this.scopeSelectorAst(internalContext).nodes;
customAstSelectors.forEach(trimLeftSelectorAst);
if (hasSingleSelector && internalContext.currentAnchor) {
// context.currentAnchor = internalContext.currentAnchor;
context.currentAnchor = {
name,
type: 'pseudo-element',
resolved: internalContext.currentAnchor.resolved
};
} else {
// unknown context due to multiple selectors
// context.currentAnchor = anyElementAnchor(meta);
context.currentAnchor = {
name,
type: 'pseudo-element',
resolved: anyElementAnchor(meta).resolved
};
}
Object.assign(node, customAstSelectors[0]);
// first one handled inline above
for (let i = 1; i < customAstSelectors.length; i++) {
const selectorNode = context.selectorAst.nodes[context.selectorIndex];
const nodeIndex = selectorNode.nodes.indexOf(node);
context.additionalSelectors.push(
lazyCreateSelector(customAstSelectors[i], selectorNode, nodeIndex)
);
}
}
private scopeClassNode(symbol: any, meta: any, node: any, originMeta: any) {
if (symbol[valueMapping.global]) {
const globalMappedNodes = symbol[valueMapping.global];
node.type = 'selector';
node.nodes = globalMappedNodes;
this.addGlobalsToMeta(globalMappedNodes!, originMeta);
} else {
node.type = 'class';
node.name = this.scope(symbol.name, meta.namespace);
}
}
private resolveMetaParts(meta: StylableMeta): MetaParts {
let metaParts = this.metaParts.get(meta);
if (!metaParts) {
const resolvedClasses: Record<
string,
Array<CSSResolve<ClassSymbol | ElementSymbol>>
> = {};
for (const className of Object.keys(meta.classes)) {
resolvedClasses[className] = this.resolver.resolveExtends(
meta,
className,
false,
this,
(res, extend) => {
const decl = findRule(meta.ast, '.' + className);
if (decl) {
if (res && res._kind === 'js') {
this.diagnostics.error(
decl,
transformerWarnings.CANNOT_EXTEND_JS(),
{
word: decl.value
}
);
} else if (res && !res.symbol) {
this.diagnostics.error(
decl,
transformerWarnings.CANNOT_EXTEND_UNKNOWN_SYMBOL(extend.name),
{ word: decl.value }
);
} else {
this.diagnostics.error(
decl,
transformerWarnings.IMPORT_ISNT_EXTENDABLE(),
{ word: decl.value }
);
}
} else {
if (meta.classes[className] && meta.classes[className].alias) {
meta.ast.walkRules(new RegExp('\\.' + className), rule => {
this.diagnostics.error(
rule,
transformerWarnings.UNKNOWN_IMPORT_ALIAS(className),
{ word: className }
);
return false;
});
}
}
}
);
}
const resolvedElements: Record<
string,
Array<CSSResolve<ClassSymbol | ElementSymbol>>
> = {};
for (const k of Object.keys(meta.elements)) {
resolvedElements[k] = this.resolver.resolveExtends(meta, k, true, this);
}
metaParts = { class: resolvedClasses, element: resolvedElements };
this.metaParts.set(meta, metaParts);
}
return metaParts!;
}
private addDevRules(meta: StylableMeta) {
const metaParts = this.resolveMetaParts(meta);
for (const [className, resolved] of Object.entries(metaParts.class)) {
if (resolved.length > 1) {
meta.outputAst!.walkRules('.' + this.scope(className, meta.namespace), rule => {
const a = resolved[0];
const b = resolved[1];
rule.after(
createWarningRule(
b.symbol.name,
this.scope(b.symbol.name, b.meta.namespace),
basename(b.meta.source),
a.symbol.name,
this.scope(a.symbol.name, a.meta.namespace),
basename(a.meta.source),
true
)
);
});
}
}
}
private resetTransformProperties(meta: StylableMeta) {

@@ -978,1 +1397,77 @@ meta.globals = {};

}
function removeFirstRootInEachSelectorChunk(
selectorListChunks: SelectorChunk2[][],
meta: StylableMeta
) {
selectorListChunks.forEach(selectorChunks => {
selectorChunks[0].nodes = selectorChunks[0].nodes.filter(({ type, name }) => {
return !(type === 'class' && name === meta.root);
});
});
}
function trimLeftSelectorAst(n: SelectorAstNode, i = 0) {
if (n) {
if (n.type === 'spacing') {
n.value = '';
}
n.before = '';
trimLeftSelectorAst(n.nodes && n.nodes[0], i + 1);
if (i === 0) {
n.before = ' ';
}
}
}
function anyElementAnchor(
meta: StylableMeta
): { type: 'class' | 'element'; name: string; resolved: Array<CSSResolve<ElementSymbol>> } {
return {
type: 'element',
name: '*',
resolved: [{ _kind: 'css', meta, symbol: { _kind: 'element', name: '*' } }]
};
}
function lazyCreateSelector(
customElementChunk: SelectorAstNode,
selectorNode: SelectorAstNode,
nodeIndex: number
) {
if (nodeIndex === -1) {
throw new Error('not supported inside nested classes');
}
return () => {
const clone = cloneDeep(selectorNode);
clone.nodes[nodeIndex].nodes = customElementChunk.nodes;
return clone;
};
}
interface ScopeSelectorContext {
originMeta: StylableMeta;
selectorAst: SelectorAstNode;
rule: postcss.Rule;
additionalSelectors?: Array<() => void>;
selectorIndex?: number;
metaParts?: MetaParts;
chunks?: SelectorChunk2[];
chunk?: SelectorChunk2;
node?: SelectorAstNode;
// TODO: maybe collect elements with better api and not getter setter
elements?: any[];
_currentAnchor?: any;
currentAnchor?: {
type: 'class' | 'element' | 'pseudo-element';
name: string;
resolved: Array<CSSResolve<ClassSymbol | ElementSymbol>>;
};
transformGlobals?: boolean;
}
interface MetaParts {
class: Record<string, Array<CSSResolve<ClassSymbol | ElementSymbol>>>;
element: Record<string, Array<CSSResolve<ClassSymbol | ElementSymbol>>>;
}

@@ -281,2 +281,3 @@ import cloneDeep from 'lodash.clonedeep';

// TODO: What is this?
export function findRule(

@@ -286,3 +287,3 @@ root: postcss.Root,

test: any = (statement: any) => statement.prop === valueMapping.extends
) {
): null | postcss.Declaration {
let found: any = null;

@@ -289,0 +290,0 @@ root.walkRules(selector, rule => {

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc