Socket
Socket
Sign inDemoInstall

stylable

Package Overview
Dependencies
Maintainers
2
Versions
96
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

stylable - npm Package Compare versions

Comparing version 3.0.0 to 4.0.0

dist/src/cached-process-file.d.ts

6

dist/src/generator.d.ts

@@ -31,6 +31,8 @@ import { PartialObject, Pojo } from './types';

addSheet(sheet: Stylesheet, resolvedSymbols: Pojo): void;
prepareSelector(sheet: Stylesheet, selector: string | ExtendedSelector, resolvedSymbols: Pojo, stack?: Array<string | ExtendedSelector>): {
private collectCSSRuleSets(sheet, selectors, resolvedSymbols, onCollect);
private isVariant(sheet, aSelector);
prepareSelector(sheet: Stylesheet, selector: string | ExtendedSelector, resolvedSymbols: Pojo, stack?: Array<string | ExtendedSelector>, outputVariants?: boolean): {
[x: string]: Pojo<string | string[] | Pojo<string | string[]>>;
} | null;
applyMixins(aSelector: string, rules: NestedRules, mixins: any[], resolvedSymbols: Pojo, stack: Array<string | ExtendedSelector>): void;
applyMixins(sheet: Stylesheet, aSelector: string, rules: NestedRules, mixins: any[], resolvedSymbols: Pojo, stack: Array<string | ExtendedSelector>): void;
processRules(rules: NestedRules, resolvedSymbols: Pojo, sheet: Stylesheet): Pojo<string | string[] | Pojo<string | string[]>>;

@@ -37,0 +39,0 @@ scopeValue(key: string, value: string, resolvedSymbols: Pojo, sheet: Stylesheet): string;

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

var utils_1 = require("./utils");
var process_1 = require("./process");
var cssflat = require('../modules/flat-css');

@@ -59,3 +60,2 @@ var Mode;

};
//TODO: replace Pojo with "ModuleMap"
Generator.prototype.addImports = function (resolvedSymbols) {

@@ -83,4 +83,24 @@ for (var symbol in resolvedSymbols) {

};
Generator.prototype.prepareSelector = function (sheet, selector, resolvedSymbols, stack) {
Generator.prototype.collectCSSRuleSets = function (sheet, selectors, resolvedSymbols, onCollect) {
while (selectors.length) {
var selector = selectors.pop();
var selectorObject = this.prepareSelector(sheet, selector, resolvedSymbols, selectors, true);
if (!selectorObject) {
continue;
}
onCollect(selectorObject);
}
};
Generator.prototype.isVariant = function (sheet, aSelector) {
var classSelectorNameMatch = aSelector.match(/^\s*\.([\w-_]+)/); // ToDo: change catch
var classSelectorName = classSelectorNameMatch && classSelectorNameMatch[1];
var typesClass = classSelectorName && sheet.typedClasses[classSelectorName];
if (typesClass && typesClass[stylable_value_parsers_1.valueMapping.variant]) {
return true;
}
return false;
};
Generator.prototype.prepareSelector = function (sheet, selector, resolvedSymbols, stack, outputVariants) {
if (stack === void 0) { stack = []; }
if (outputVariants === void 0) { outputVariants = false; }
var rules, aSelector, processedRules;

@@ -92,3 +112,6 @@ if (typeof selector === 'string') {

if (mixins) {
this.applyMixins(aSelector, rules, mixins, resolvedSymbols, stack);
if (this.isVariant(sheet, aSelector) && outputVariants === false) {
return null;
}
this.applyMixins(sheet, aSelector, rules, mixins, resolvedSymbols, stack);
return null;

@@ -102,2 +125,5 @@ }

/* don't emit */
if (this.isVariant(sheet, aSelector) && !outputVariants) {
return null;
}
if (selector === '@namespace') {

@@ -133,13 +159,64 @@ return null;

};
Generator.prototype.applyMixins = function (aSelector, rules, mixins, resolvedSymbols, stack) {
Generator.prototype.applyMixins = function (sheet, aSelector, rules, mixins, resolvedSymbols, stack) {
var _this = this;
mixins.forEach(function (mixin) {
var mixinFunction = resolvedSymbols[mixin.type];
var cssMixin = cssflat((_a = {},
_a[aSelector] = __assign({}, rules, mixinFunction(mixin.options.map(function (option) { return value_template_1.valueTemplate(option, resolvedSymbols, _this.mode === Mode.DEV); }))),
_a));
for (var key in cssMixin) {
stack.push({ selector: key, rules: cssMixin[key] });
var cssMixin;
var mixinSymbol = mixin.type;
var _a = _this.resolver.getSymbolDefinition(sheet, mixinSymbol, resolvedSymbols), origin = _a.origin, type = _a.type, localName = _a.localName;
switch (type) {
case 'class':
var typedClass = origin.typedClasses[localName];
if (typedClass[stylable_value_parsers_1.valueMapping.variant]) {
var originResolvedSymbols_1 = _this.resolver.resolveSymbols(origin);
var variantSelector_1 = '.' + localName;
var mixedInVal_1 = [[aSelector, rules]];
process_1.walkClassPrefix(origin.cssDefinition, variantSelector_1, function (targetSelector, index) {
var targetSelectorTrim = targetSelector.trim();
var isVariantRoot = targetSelectorTrim === variantSelector_1;
_this.collectCSSRuleSets(origin, [targetSelector], originResolvedSymbols_1, function (selectorObj) {
Object.keys(selectorObj).forEach(function (selector) {
var pRules = selectorObj[selector];
var selectorWithoutVariant = selector.replace('.' + _this.scope(localName, origin.namespace), '');
if (index === 0 && isVariantRoot) {
mixedInVal_1[0][0] = aSelector + ':global(' + selectorWithoutVariant + ')';
var inRules = {};
for (var rule in mixedInVal_1[0][1]) {
if (rule === stylable_value_parsers_1.valueMapping.mixin || rule === stylable_value_parsers_1.valueMapping.extends) {
inRules[rule] = mixedInVal_1[0][1][rule];
Object.assign(inRules, pRules);
}
else {
inRules[rule] = mixedInVal_1[0][1][rule];
}
}
mixedInVal_1[0][1] = __assign({}, inRules);
}
else {
mixedInVal_1.push([aSelector + ':global(' + selectorWithoutVariant + ')', pRules]);
}
});
});
});
mixedInVal_1.reverse().forEach(function (_a) {
var selector = _a[0], rules = _a[1];
var flatValue = cssflat((_b = {}, _b[selector] = rules, _b));
for (var key in flatValue) {
stack.push({ selector: key, rules: flatValue[key] }); // ToDo: barak, why is this in reverse?
}
var _b;
});
}
break;
case 'JSExport':
var mixinFunc = origin[localName];
cssMixin = cssflat((_b = {},
_b[aSelector] = __assign({}, rules, mixinFunc(mixin.options.map(function (option) { return value_template_1.valueTemplate(option, resolvedSymbols, _this.mode === Mode.DEV); }))),
_b));
Object.keys(cssMixin).reverse().forEach(function (key) {
var mixRules = cssMixin[key];
stack.push({ selector: key, rules: mixRules });
});
break;
}
var _a;
var _b;
});

@@ -231,2 +308,12 @@ };

}
else if (sheet.typedClasses[name]) {
var _extends = sheet.typedClasses[name][stylable_value_parsers_1.valueMapping.extends];
if (_extends) {
node.before = '.' + localName;
node.name = this.scope(_extends, sheet.namespace);
}
else {
node.name = localName;
}
}
else {

@@ -249,3 +336,2 @@ //not type

Generator.prototype.handlePseudoElement = function (sheet, node, name) {
//TODO: only transform what is found
var current = sheet;

@@ -274,5 +360,12 @@ while (current) {

var typedClass = current.typedClasses[localName];
if (hasState(typedClass, name)) {
node.type = 'attribute';
node.content = current.stateAttr(name);
var stateValue = getState(typedClass, name);
if (stateValue) {
if (typeof stateValue === 'string') {
node.type = 'invalid'; // simply concat global mapped selector - ToDo: maybe change to 'selector'
node.value = stateValue;
}
else {
node.type = 'attribute';
node.content = current.stateAttr(name);
}
break;

@@ -298,6 +391,12 @@ }

exports.Generator = Generator;
function hasState(typedClass, name) {
function getState(typedClass, name) {
var states = typedClass && typedClass[stylable_value_parsers_1.valueMapping.states];
return states ? states.indexOf(name) !== -1 : false;
if (Array.isArray(states)) {
return states.indexOf(name) !== -1;
}
else if (states && utils_1.hasOwn(states, name)) {
return states[name] || true;
}
return false;
}
//# sourceMappingURL=generator.js.map

@@ -5,2 +5,4 @@ import { Pojo } from './types';

}
export declare function findImportForSymbol(imports: Import[], symbol: string): Import;
export declare function containsSymbol(_import: Import, symbol: string): boolean;
export declare class Import {

@@ -13,3 +15,2 @@ from: string;

static fromImportObject(SbFrom: string, cssImportDef: CSSImportRaw): Import | null;
containsSymbol(symbol: string): boolean;
}

@@ -5,2 +5,10 @@ "use strict";

var parseNamed = stylable_value_parsers_1.SBTypesParsers[stylable_value_parsers_1.valueMapping.named];
function findImportForSymbol(imports, symbol) {
return imports.filter(function (_import) { return containsSymbol(_import, symbol); })[0] || null;
}
exports.findImportForSymbol = findImportForSymbol;
function containsSymbol(_import, symbol) {
return symbol ? (_import.defaultExport === symbol || !!_import.named[symbol]) : false;
}
exports.containsSymbol = containsSymbol;
var Import = (function () {

@@ -15,3 +23,3 @@ function Import(from, defaultExport, named) {

Import.findImportForSymbol = function (imports, symbol) {
return imports.filter(function (_import) { return _import.containsSymbol(symbol); })[0] || null;
return imports.filter(function (_import) { return containsSymbol(_import, symbol); })[0] || null;
};

@@ -40,5 +48,2 @@ Import.fromImportObject = function (SbFrom, cssImportDef) {

};
Import.prototype.containsSymbol = function (symbol) {
return symbol ? (this.defaultExport === symbol || !!this.named[symbol]) : false;
};
return Import;

@@ -45,0 +50,0 @@ }());

@@ -1,4 +0,5 @@

export { Resolver } from "./resolver";
export { Stylesheet } from "./stylesheet";
export { Generator, DEFAULT_CONFIG, Config } from "./generator";
export { objectifyCSS, fromCSS } from "./parser";
export { fromCSS, safeParse } from "./parser";
export { cachedProcessFile, FileProcessor } from "./cached-process-file";
export { StylableMeta, process, SDecl } from "./postcss-process";
export { StylableTransformer, StylableResults } from "./stylable-transformer";
export { Diagnostics } from "./diagnostics";
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var resolver_1 = require("./resolver");
exports.Resolver = resolver_1.Resolver;
var stylesheet_1 = require("./stylesheet");
exports.Stylesheet = stylesheet_1.Stylesheet;
var generator_1 = require("./generator");
exports.Generator = generator_1.Generator;
exports.DEFAULT_CONFIG = generator_1.DEFAULT_CONFIG;
var parser_1 = require("./parser");
exports.objectifyCSS = parser_1.objectifyCSS;
exports.fromCSS = parser_1.fromCSS;
exports.safeParse = parser_1.safeParse;
var cached_process_file_1 = require("./cached-process-file");
exports.cachedProcessFile = cached_process_file_1.cachedProcessFile;
var postcss_process_1 = require("./postcss-process");
exports.process = postcss_process_1.process;
var stylable_transformer_1 = require("./stylable-transformer");
exports.StylableTransformer = stylable_transformer_1.StylableTransformer;
var diagnostics_1 = require("./diagnostics");
exports.Diagnostics = diagnostics_1.Diagnostics;
//# sourceMappingURL=index.js.map
import { CSSObject } from "./types";
import { Stylesheet } from "./stylesheet";
import * as postcss from "postcss";
export declare function cssObjectToAst(cssObject: CSSObject, sourceFile?: string): postcss.LazyResult;
export declare function stringifyCSSObject(cssObject: CSSObject): string;
export declare function objectifyCSSStylis(css: string): CSSObject;
export declare function objectifyCSS(css: string): CSSObject;
export declare function fromCSS(css: string, namespace?: string, source?: string): Stylesheet;
export declare function fromCSS(_css: string, _namespace?: string, _source?: string): void;
export declare function safeParse(css: string, options?: postcss.ProcessOptions): any;
"use strict";
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var stylable_value_parsers_1 = require("./stylable-value-parsers");
var stylesheet_1 = require("./stylesheet");
var postcss = require("postcss");
var objectify = require("../modules/post-css-objectify");
var stylis = require("stylis");
var plugin = require("../modules/plugin");
var postcssJS = require("postcss-js");

@@ -17,15 +22,13 @@ var postcssNested = require("postcss-nested");

};
stylis.set({ compress: false, lossless: true, global: false, preserve: true });
stylis.use(false);
stylis.use(plugin(stylableObjectifyConfig));
var postcssConfig = { parser: postcssJS };
var processor = postcss([postcssNested]);
function cssObjectToAst(cssObject, sourceFile) {
if (sourceFile === void 0) { sourceFile = ''; }
return processor.process(cssObject, __assign({ from: sourceFile }, postcssConfig));
}
exports.cssObjectToAst = cssObjectToAst;
function stringifyCSSObject(cssObject) {
return processor.process(cssObject, postcssConfig).css;
return cssObjectToAst(cssObject).css;
}
exports.stringifyCSSObject = stringifyCSSObject;
function objectifyCSSStylis(css) {
return stylis('', css);
}
exports.objectifyCSSStylis = objectifyCSSStylis;
function objectifyCSS(css) {

@@ -36,6 +39,11 @@ // return stylis('', css);

exports.objectifyCSS = objectifyCSS;
function fromCSS(css, namespace, source) {
return new stylesheet_1.Stylesheet(objectifyCSS(css), namespace, source);
function fromCSS(_css, _namespace, _source) {
throw "TODO: implement";
}
exports.fromCSS = fromCSS;
function safeParse(css, options) {
if (options === void 0) { options = { from: 'style.css' }; }
return safeParser(css, options);
}
exports.safeParse = safeParse;
//# sourceMappingURL=parser.js.map
import { Stylesheet } from './stylesheet';
import { Pojo } from './types';
export declare function process(sheet: Stylesheet): void;
export declare function processNamespace(strongNamespace?: string, weakNamespace?: string | string[]): string;
export declare function walkClassPrefix(cssObject: Pojo, className: string, visitor: (selector: string, index: number) => void): void;

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

var isSimpleSelector = true;
var importedElements = {};
selector_utils_1.traverseNode(ast, function (node) {

@@ -65,7 +66,30 @@ if (!checker(node)) {

}
else if (type === 'element') {
if (name.match(/^[A-Z]\w+$/)) {
importedElements[name] = true;
}
}
return undefined;
});
addImportedElements(sheet, importedElements);
addTypedClasses(sheet, selector, rules, isSimpleSelector);
}
function addImportedElements(sheet, importedElements) {
for (var element in importedElements) {
var importWithRef = import_1.Import.findImportForSymbol(sheet.imports, element);
if (importWithRef) {
mergeTypedClass(sheet, element, element, stylable_value_parsers_1.valueMapping.extends);
}
else {
// warn for component Tag selector with no reference ?
}
}
}
function addTypedClasses(sheet, selector, rules, isSimpleSelector) {
if (rules[stylable_value_parsers_1.valueMapping.variant] && selector.match(/^\.[\w]+$/)) {
if (!rules[stylable_value_parsers_1.valueMapping.extends]) {
rules = __assign({}, rules);
}
addTypedClass(sheet, selector, rules, isSimpleSelector, stylable_value_parsers_1.valueMapping.variant);
}
addTypedClass(sheet, selector, rules, isSimpleSelector, stylable_value_parsers_1.valueMapping.root);

@@ -76,15 +100,17 @@ addTypedClass(sheet, selector, rules, isSimpleSelector, stylable_value_parsers_1.valueMapping.states);

function addTypedClass(sheet, selector, rules, isSimpleSelector, typedRule) {
Array.isArray(rules) ? rules.forEach(function (rules) {
mergeTypedClass(sheet, selector, rules, isSimpleSelector, typedRule);
}) : mergeTypedClass(sheet, selector, rules, isSimpleSelector, typedRule);
var name = selector.replace('.', '');
var merge = function (rules) {
if (!utils_1.hasOwn(rules, typedRule)) {
return;
}
if (!isSimpleSelector) {
throw new Error(typedRule + ' on complex selector: ' + selector);
}
var value = stylable_value_parsers_1.SBTypesParsers[typedRule](rules[typedRule]);
mergeTypedClass(sheet, name, value, typedRule);
};
Array.isArray(rules) ? rules.forEach(merge) : merge(rules);
}
function mergeTypedClass(sheet, selector, rules, isSimpleSelector, typedRule) {
if (!utils_1.hasOwn(rules, typedRule)) {
return;
}
if (!isSimpleSelector) {
throw new Error(typedRule + ' on complex selector: ' + selector);
}
var name = selector.replace('.', '');
sheet.typedClasses[name] = __assign({}, sheet.typedClasses[name], (_a = {}, _a[typedRule] = stylable_value_parsers_1.SBTypesParsers[typedRule](rules[typedRule]), _a));
function mergeTypedClass(sheet, name, value, typedRule) {
sheet.typedClasses[name] = __assign({}, sheet.typedClasses[name], (_a = {}, _a[typedRule] = value, _a));
var _a;

@@ -118,2 +144,11 @@ }

exports.processNamespace = processNamespace;
function walkClassPrefix(cssObject, className, visitor) {
var i = 0;
for (var selector in cssObject) {
if (selector.match(new RegExp('^\s*' + className))) {
visitor(selector, i++);
}
}
}
exports.walkClassPrefix = walkClassPrefix;
//# sourceMappingURL=process.js.map

@@ -7,2 +7,3 @@ import { Stylesheet } from './stylesheet';

}
export declare type SymbolType = 'stylesheet' | 'class' | 'var' | 'JSExport' | 'not-found';
export declare class Resolver {

@@ -16,2 +17,7 @@ private zMap;

resolveSymbols(sheet: Stylesheet): Pojo<any>;
getSymbolDefinition(sheet: Stylesheet, symbol: string, resolvedSymbols?: Pojo): {
origin: any;
type: SymbolType;
localName: string;
};
}

@@ -34,3 +34,13 @@ "use strict";

var _import = typedClass ? import_1.Import.findImportForSymbol(sheet.imports, typedClass[stylable_value_parsers_1.valueMapping.extends] || "") : null;
return _import ? this.resolveModule(_import.from) : sheet;
if (_import) {
var m = this.resolveModule(_import.from);
var extendsName = typedClass[stylable_value_parsers_1.valueMapping.extends];
if (_import.defaultExport === extendsName) {
return m.default || m;
}
else {
return m[_import.named[extendsName]];
}
}
return sheet;
};

@@ -44,5 +54,19 @@ Resolver.prototype.resolveImports = function (sheet) {

var isStylesheet = stylesheet_1.Stylesheet.isStylesheet(resolved);
for (var name_1 in importDef.named) {
acc[name_1] = isStylesheet ? value_template_1.valueTemplate(resolved.vars[name_1], resolved.vars) : resolved[name_1];
if (isStylesheet) {
for (var name_1 in importDef.named) {
var importLocalName = importDef.named[name_1];
if (resolved.vars[importLocalName]) {
acc[name_1] = value_template_1.valueTemplate(resolved.vars[importLocalName], resolved.vars);
}
else if (resolved.classes[importLocalName]) {
acc[name_1] = name_1;
}
}
}
else {
for (var name_2 in importDef.named) {
var importLocalName = importDef.named[name_2];
acc[name_2] = resolved[importLocalName];
}
}
return acc;

@@ -55,2 +79,8 @@ }, {});

var symbols = this.resolveImports(sheet);
for (var className in sheet.classes) {
if (symbols[className]) {
throw Error("resolveSymbols: Name " + className + " already set");
}
symbols[className] = className;
}
for (var varName in sheet.vars) {

@@ -64,2 +94,23 @@ if (symbols[varName]) {

};
Resolver.prototype.getSymbolDefinition = function (sheet, symbol, resolvedSymbols) {
if (symbol === 'default') {
return { origin: sheet, type: 'stylesheet', localName: 'default' };
}
else if (sheet.classes[symbol]) {
return { origin: sheet, type: 'class', localName: symbol };
}
else if (sheet.vars[symbol]) {
return { origin: sheet, type: 'var', localName: symbol };
}
else {
var importDef = import_1.Import.findImportForSymbol(sheet.imports, symbol);
if (importDef) {
resolvedSymbols = resolvedSymbols || this.resolveSymbols(sheet);
var importedModule = importDef && (resolvedSymbols[importDef.from] || this.zMap[importDef.from]);
var importLocalName = importDef.defaultExport === symbol ? 'default' : importDef.named[symbol];
return stylesheet_1.Stylesheet.isStylesheet(importedModule) ? this.getSymbolDefinition(importedModule, importLocalName) : { origin: importedModule, type: 'JSExport', localName: importLocalName };
}
}
return { origin: sheet, type: 'not-found', localName: '' };
};
return Resolver;

@@ -66,0 +117,0 @@ }());

@@ -7,2 +7,3 @@ export interface SelectorAstNode {

before?: string;
value?: string;
}

@@ -13,7 +14,8 @@ export interface PseudoSelectorAstNode extends SelectorAstNode {

}
export declare type Visitor = (node: SelectorAstNode, index: number) => boolean | void;
export declare type Visitor = (node: SelectorAstNode, index: number, nodes: SelectorAstNode[]) => boolean | void;
export declare function parseSelector(selector: string): SelectorAstNode;
export declare function stringifySelector(ast: SelectorAstNode): string;
export declare function traverseNode(node: SelectorAstNode, visitor: Visitor, index?: number): boolean | void;
export declare function traverseNode(node: SelectorAstNode, visitor: Visitor, index?: number, nodes?: SelectorAstNode[]): boolean | void;
export declare function createChecker(types: Array<string | string[]>): () => (node: SelectorAstNode) => boolean;
export declare function createRootAfterSpaceChecker(): (node?: SelectorAstNode | undefined) => boolean;
export declare const createSimpleSelectorChecker: () => (node: SelectorAstNode) => boolean;

@@ -20,0 +22,0 @@ export declare function isImport(ast: SelectorAstNode): boolean;

@@ -12,8 +12,9 @@ "use strict";

exports.stringifySelector = stringifySelector;
function traverseNode(node, visitor, index) {
function traverseNode(node, visitor, index, nodes) {
if (index === void 0) { index = 0; }
if (nodes === void 0) { nodes = [node]; }
if (!node) {
return;
}
var doNext = visitor(node, index);
var doNext = visitor(node, index, nodes);
if (doNext === false) {

@@ -27,3 +28,3 @@ return false;

for (var i = 0; i < node.nodes.length; i++) {
doNext = traverseNode(node.nodes[i], visitor, i);
doNext = traverseNode(node.nodes[i], visitor, i, node.nodes);
if (doNext === true) {

@@ -59,2 +60,19 @@ continue;

exports.createChecker = createChecker;
function createRootAfterSpaceChecker() {
var hasSpacing = false;
var isValid = true;
return function (node) {
if (!node) {
return isValid;
}
if (node.type === 'spacing') {
hasSpacing = true;
}
if (node.type === 'class' && node.name === 'root' && hasSpacing) {
isValid = false;
}
return isValid;
};
}
exports.createRootAfterSpaceChecker = createRootAfterSpaceChecker;
exports.createSimpleSelectorChecker = createChecker(['selectors', 'selector', ['element', 'class']]);

@@ -61,0 +79,0 @@ function isImport(ast) {

@@ -0,5 +1,9 @@

export declare type MappedStates = {
[s: string]: string | null;
};
export interface TypedClass {
"-st-root"?: boolean;
"-st-states"?: string[];
"-st-states"?: string[] | MappedStates;
"-st-extends"?: string;
"-st-variant"?: boolean;
}

@@ -18,3 +22,8 @@ export interface MixinValue<T = any[]> {

mixin: "-st-mixin";
variant: "-st-variant";
compose: "-st-compose";
theme: "-st-theme";
};
export declare type stKeys = keyof typeof valueMapping;
export declare const stValues: string[];
export declare const STYLABLE_VALUE_MATCHER: RegExp;

@@ -24,3 +33,5 @@ export declare const STYLABLE_NAMED_MATCHER: RegExp;

"-st-root"(value: string): boolean;
"-st-states"(value: string): string[];
"-st-variant"(value: string): boolean;
"-st-theme"(value: string): boolean;
"-st-states"(value: string): MappedStates;
"-st-extends"(value: string): string;

@@ -34,2 +45,3 @@ "-st-named"(value: string): {

}[];
"-st-compose"(value: string): string[];
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var valueParser = require("postcss-value-parser");
exports.valueMapping = {

@@ -10,4 +11,8 @@ from: '-st-from',

extends: '-st-extends',
mixin: '-st-mixin'
mixin: '-st-mixin',
variant: '-st-variant',
compose: '-st-compose',
theme: '-st-theme'
};
exports.stValues = Object.keys(exports.valueMapping).map(function (key) { return exports.valueMapping[key]; });
exports.STYLABLE_VALUE_MATCHER = /^-st-/;

@@ -19,4 +24,22 @@ exports.STYLABLE_NAMED_MATCHER = new RegExp("^" + exports.valueMapping.named + "-(.+)");

},
"-st-variant": function (value) {
return value === 'false' ? false : true;
},
"-st-theme": function (value) {
return value === 'false' ? false : true;
},
"-st-states": function (value) {
return value ? value.split(',').map(function (state) { return state.trim(); }) : [];
if (!value) {
return {};
}
var mappedStates = {};
var parts = value.split(/,?([\w-]+)(\(\"([^),]*)"\))?/g);
for (var i = 0; i < parts.length; i += 4) {
var stateName = parts[i + 1];
var mapToSelector = parts[i + 3];
if (stateName) {
mappedStates[stateName] = mapToSelector ? mapToSelector.trim() : null;
}
}
return mappedStates;
},

@@ -40,77 +63,70 @@ "-st-extends": function (value) {

"-st-mixin": function (value) {
var parts = value.match(/\s*[A-Za-z$_][$_\w]*\(.*?\)\)?|\s*([A-Za-z$_][$_\w]*\s*)/g);
if (!parts || parts.join('').length !== value.replace(/\s*/, '').length) {
throw new Error(exports.valueMapping.mixin + ': not a valid mixin value: ' + value);
}
return parts.map(function (mix) {
var type, options, match;
if (mix.indexOf('(') === -1) {
type = mix.trim();
options = [];
var ast = valueParser(value);
var mixins = [];
ast.nodes.forEach(function (node) {
if (node.type === 'function') {
mixins.push({
type: node.value,
options: createOptions(node)
});
}
else if (match = mix.match(/(.*?)\((.*?\)?)\)/)) {
type = match[1].trim();
options = [];
if (match[2]) {
var args = match[2];
var isInParam = false;
var isInString = false;
var lastIndex = 0;
var lastNoneSpaceIndex = 0;
for (var i = 0; i < args.length; ++i) {
var currentChar = args[i];
if (currentChar.match(/\s/)) {
if (!isInParam) {
lastIndex = i + 1; // ignore spaces before param
}
continue;
}
switch (currentChar) {
case "\"":
if (isInParam) {
}
else {
isInParam = true;
lastIndex = i + 1;
}
isInString = true;
lastNoneSpaceIndex = i + 1;
break;
case ",":
if (isInString) {
var lastNoneSpaceChar = args[lastNoneSpaceIndex - 1];
if (lastNoneSpaceChar === "\"") {
lastNoneSpaceIndex = lastNoneSpaceIndex - 1;
}
else {
lastNoneSpaceIndex = lastNoneSpaceIndex + 1;
continue;
}
}
options.push(args.slice(lastIndex, lastNoneSpaceIndex));
isInParam = false;
isInString = false;
lastIndex = i + 1;
lastNoneSpaceIndex = i + 1;
break;
default:
isInParam = true;
lastNoneSpaceIndex = i + 1;
}
}
if (lastIndex < args.length) {
if (isInParam) {
lastNoneSpaceIndex = args[lastNoneSpaceIndex - 1] === '"' ? lastNoneSpaceIndex - 1 : lastNoneSpaceIndex;
}
options.push(args.slice(lastIndex, lastNoneSpaceIndex));
}
}
else if (node.type === 'word') {
mixins.push({
type: node.value,
options: []
});
}
else {
throw new Error('Invalid mixin call:' + mix);
else if (node.type === 'string') {
//TODO: warn
}
return { type: type, options: options };
});
return mixins;
},
"-st-compose": function (value) {
var ast = valueParser(value);
var composes = [];
ast.walk(function (node) {
if (node.type === 'function') {
}
else if (node.type === 'word') {
composes.push(node.value);
}
else if (node.type === 'string') {
//TODO: warn
}
});
return composes;
}
};
function groupValues(node) {
var grouped = [];
var current = [];
node.nodes.forEach(function (node) {
if (node.type === 'div') {
grouped.push(current);
current = [];
}
else {
current.push(node);
}
});
var last = grouped[grouped.length - 1];
if ((last && last !== current && current.length) || !last && current.length) {
grouped.push(current);
}
return grouped;
}
function createOptions(node) {
return groupValues(node).map(function (nodes) { return valueParser.stringify(nodes, function (node) {
if (node.type === 'div') {
return null;
}
else if (node.type === 'string') {
return node.value;
}
else {
return undefined;
}
}); }).filter(function (x) { return typeof x === 'string'; });
}
//# sourceMappingURL=stylable-value-parsers.js.map

@@ -6,2 +6,1 @@ export declare type Pojo<T = any> = {

export declare type CSSObject = any & object;
export declare type CSSRulesObject = any & object;
export declare function hasKeys(o: {}): boolean;
export declare const hasOwn: any;
export declare function stripQuotation(str: string): string;
export declare function filename2varname(filename: string): string;
export declare function string2varname(str: string): string;

@@ -13,2 +13,19 @@ "use strict";

exports.hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
// export function scope(name: string, namespace: string, separator: string = '-') {
// return namespace ? namespace + separator + name : name;
// }
function stripQuotation(str) {
return str.replace(/^['"]|['"]$/g, '');
}
exports.stripQuotation = stripQuotation;
function filename2varname(filename) {
return string2varname(filename.replace(/(?=.*)\.\w+$/, '').replace(/\.st$/, ''));
}
exports.filename2varname = filename2varname;
function string2varname(str) {
return str
.replace(/[^0-9a-zA-Z_]/gm, '')
.replace(/^[^a-zA-Z_]+/gm, '');
}
exports.string2varname = string2varname;
//# sourceMappingURL=utils.js.map
import { Pojo } from "./types";
export declare function valueTemplate(value: string, data: Pojo, debug?: boolean, throwCondition?: number): string;
export declare const matchValue: RegExp;
export declare function valueReplacer(value: string, data: Pojo, onMatch: (value: string, name: string, match: string) => any, debug?: boolean): string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function valueTemplate(value, data, debug, throwCondition) {
exports.matchValue = /value\((.*?)\)/g;
function valueReplacer(value, data, onMatch, debug) {
if (debug === void 0) { debug = false; }
if (throwCondition === void 0) { throwCondition = 0; }
return value.replace(/value\((.*?)\)/g, function (match, name) {
var translatedValue;
if (~name.indexOf(',')) {
var nameParts = name.split(',');
var variableName = nameParts[0].trim();
var defaultValue = nameParts[1].trim();
defaultValue = data[defaultValue] || defaultValue;
translatedValue = data[variableName] || defaultValue;
}
else {
translatedValue = data[name];
}
if (throwCondition > 10 || translatedValue === undefined) {
throw new Error('Unresolvable variable: ' + name);
}
var res = valueTemplate(translatedValue, data, debug, throwCondition + 1);
return res !== undefined ? res + (debug ? "/*" + name + "*/" : '') : match;
return value.replace(exports.matchValue, function (match, name) {
var translatedValue = onMatch(data[name], name, match);
return translatedValue !== undefined ? translatedValue + (debug ? "/*" + name + "*/" : '') : match;
});
}
exports.valueTemplate = valueTemplate;
exports.valueReplacer = valueReplacer;
//# sourceMappingURL=value-template.js.map

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

var stylesheet_1 = require("../src/stylesheet");
var chai_1 = require("chai");
var match_css_1 = require("./matchers/match-css");
var chai = require("chai");
var expect = chai.expect;
chai.use(match_css_1.matchCSSMatchers);
describe('static Generator.generate', function () {

@@ -14,3 +17,3 @@ describe('generate() - raw css string from entry', function () {

var css = generator_1.Generator.generate(sheet);
chai_1.expect(css).to.eql(['.container {\n color: black\n}']);
expect(css).to.matchCSS(['.container {\n color: black\n}']);
});

@@ -20,3 +23,3 @@ it('includes empty selectors', function () {

var css = generator_1.Generator.generate(sheet);
chai_1.expect(css).to.eql([".container {}", ".image {}"]);
expect(css).to.matchCSS([".container {}", ".image {}"]);
});

@@ -27,3 +30,3 @@ it('css from multiple sheets', function () {

var css = generator_1.Generator.generate([sheetA, sheetB]);
chai_1.expect(css).to.eql([
expect(css).to.matchCSS([
'.container {\n color: black\n}',

@@ -36,3 +39,3 @@ '.container {\n color: white\n}',

var css = generator_1.Generator.generate(sheet, new generator_1.Generator({ namespaceDivider: "__THE_DIVIDER__" }));
chai_1.expect(css).to.eql([
expect(css).to.matchCSS([
'.TheNameSpace__THE_DIVIDER__container {\n color: white\n}'

@@ -50,3 +53,3 @@ ]);

}));
chai_1.expect(css).to.eql([
expect(css).to.matchCSS([
'.TheNameSpace__THE_DIVIDER__container {\n color: white\n}'

@@ -68,4 +71,4 @@ ]);

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -81,4 +84,4 @@ it('not append imports with unknown "from" to the output', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -97,7 +100,55 @@ it('scoped typed selector that extends root', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('component/tag typed selector that extends root', function () {
it('component/tag selector with first Capital letter automatically extend reference with identical name', function () {
var sheetA = src_1.fromCSS("", "TheNameSpace");
var sheetB = src_1.fromCSS("\n :import {\n -st-from: \"./relative/path/to/sheetA.stylable.css\";\n -st-default: Container;\n } \n :import {\n -st-from: \"./relative/path/to/sheetA-re-exported.js\";\n -st-named: NamedContainer;\n } \n Container { color:red; }\n NamedContainer { color: green; }\n ", "TheGreatNameSpace");
var css = generator_1.Generator.generate([sheetB], new generator_1.Generator({
namespaceDivider: "__THE_DIVIDER__",
resolver: new resolver_1.Resolver({
"./relative/path/to/sheetA.stylable.css": sheetA,
'./relative/path/to/sheetA-re-exported.js': { NamedContainer: sheetA }
})
}));
var res = [
'.TheGreatNameSpace__THE_DIVIDER__root .TheNameSpace__THE_DIVIDER__root {\n color: red\n}',
'.TheGreatNameSpace__THE_DIVIDER__root .TheNameSpace__THE_DIVIDER__root {\n color: green\n}'
];
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('component/tag selector with first Capital letter automatically extend reference to named export', function () {
var sheetA = src_1.fromCSS("", "TheNameSpace");
var sheetB = src_1.fromCSS("\n :import {\n -st-from: \"./relative/path/to/sheetA-re-exported.js\";\n -st-named: NamedContainer as Container;\n } \n Container { color:red; }\n ", "TheGreatNameSpace");
var css = generator_1.Generator.generate([sheetB], new generator_1.Generator({
namespaceDivider: "__THE_DIVIDER__",
resolver: new resolver_1.Resolver({
'./relative/path/to/sheetA-re-exported.js': { NamedContainer: sheetA }
})
}));
var res = [
'.TheGreatNameSpace__THE_DIVIDER__root .TheNameSpace__THE_DIVIDER__root {\n color: red\n}'
];
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('component/tag selector from named import with pseudo-elements', function () {
var sheetA = src_1.fromCSS("\n .x{}\n ", "TheNameSpace");
var sheetB = src_1.fromCSS("\n :import {\n -st-from: \"./relative/path/to/sheetA-re-exported.js\";\n -st-named: NamedContainer;\n } \n NamedContainer::x { color: gold; }\n ", "TheGreatNameSpace");
var css = generator_1.Generator.generate([sheetB], new generator_1.Generator({
namespaceDivider: "__THE_DIVIDER__",
resolver: new resolver_1.Resolver({
'./relative/path/to/sheetA-re-exported.js': { NamedContainer: sheetA }
})
}));
var res = [
'.TheNameSpace__THE_DIVIDER__x {}',
'.TheGreatNameSpace__THE_DIVIDER__root .TheNameSpace__THE_DIVIDER__root .TheNameSpace__THE_DIVIDER__x {\n color: gold\n}'
];
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('component/tag selector that extends another stylesheet', function () {
var sheetA = src_1.fromCSS("", "TheNameSpace");
var sheetB = src_1.fromCSS("\n :import(\"./relative/path/to/sheetA.stylable.css\"){\n -st-default: Container;\n } \n container {\n -st-extends: Container;\n }\n ", "TheGreatNameSpace");

@@ -113,6 +164,23 @@ var css = generator_1.Generator.generate([sheetB], new generator_1.Generator({

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('component/tag typed selector that extends root with inner class targeting', function () {
it('component/tag selector with first Capital letter is overridden with -st-extends', function () {
var sheetA = src_1.fromCSS("", "SheetA");
var sheetB = src_1.fromCSS("", "SheetB");
var entrySheet = src_1.fromCSS("\n :import(\"./relative/path/to/sheetA.stylable.css\"){\n -st-default: SheetA;\n } \n :import(\"./relative/path/to/sheetB.stylable.css\"){\n -st-default: SheetB;\n } \n SheetB {\n -st-extends: SheetA;\n }\n ", "TheGreatNameSpace");
var css = generator_1.Generator.generate([entrySheet], new generator_1.Generator({
namespaceDivider: "__THE_DIVIDER__",
resolver: new resolver_1.Resolver({
"./relative/path/to/sheetA.stylable.css": sheetA,
"./relative/path/to/sheetB.stylable.css": sheetB
})
}));
var res = [
'.TheGreatNameSpace__THE_DIVIDER__root .SheetA__THE_DIVIDER__root {}',
];
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('component/tag selector that extends root with inner class targeting', function () {
var sheetA = src_1.fromCSS("\n .inner { }\n ", "TheNameSpace");

@@ -131,4 +199,4 @@ var sheetB = src_1.fromCSS("\n :import(\"./relative/path/to/sheetA.stylable.css\"){\n -st-default: Container;\n } \n container {\n -st-extends: Container;\n }\n container::inner {\n \n }\n ", "TheGreatNameSpace");

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -150,4 +218,4 @@ it('resolve and transform pseudo-element from imported type', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -172,4 +240,4 @@ it('resolve and transform pseudo-element from deeply imported type', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -193,4 +261,4 @@ it('resolve and transform pseudo-element from deeply extended type', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -215,4 +283,4 @@ it('resolve and transform pseudo-element from deeply override rather then extended type', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -234,4 +302,4 @@ it('resolve and transform pseudo-element on root - prefer inherited element to override', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -256,4 +324,4 @@ it('resolve and transform pseudo-element from deeply imported type (selector with , separator)', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -269,5 +337,31 @@ it('custom states inline', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('custom states with mapping', function () {
var sheet = src_1.fromCSS("\n .my-class { \n -st-states: my-state(\".x\"), my-other-state(\".y[data-z=\"val\"]\");\n }\n .my-class:my-state {} \n .my-class:my-other-state {}\n ", "Style");
var css = generator_1.Generator.generate([sheet], new generator_1.Generator({
namespaceDivider: "__"
}));
var res = [
'.Style__my-class {}',
'.Style__my-class.x {}',
'.Style__my-class.y[data-z="val"] {}'
];
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('custom states with mapping with space around', function () {
var sheet = src_1.fromCSS("\n .my-class { \n -st-states: my-state(\" .x \"), my-other-state(\" .y[data-z=\"val\"] \");\n }\n .my-class:my-state {} \n .my-class:my-other-state {}\n ", "Style");
var css = generator_1.Generator.generate([sheet], new generator_1.Generator({
namespaceDivider: "__"
}));
var res = [
'.Style__my-class {}',
'.Style__my-class.x {}',
'.Style__my-class.y[data-z="val"] {}'
];
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('custom states from imported type', function () {

@@ -287,4 +381,4 @@ var sheetA = src_1.fromCSS("\n .root { \n -st-states: my-state;\n }\n ", "StyleA");

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -305,7 +399,7 @@ it('custom states lookup order', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('custom states form imported type on inner pseudo-class', function () {
var sheetA = src_1.fromCSS("\n .container { \n -st-states: my-state;\n }\n ", "StyleA");
var sheetA = src_1.fromCSS("\n .container { \n\n -st-states: my-state;\n }\n ", "StyleA");
var sheetB = src_1.fromCSS("\n :import(\"./relative/path/to/sheetA.stylable.css\"){\n -st-default: SheetA;\n }\n .my-class { \n -st-extends: SheetA;\n }\n .my-class::container:my-state {}\n ", "StyleB");

@@ -323,9 +417,22 @@ var css = generator_1.Generator.generate([sheetB], new generator_1.Generator({

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});
it('TODO: custom states form imported type on inner pseudo-class on pseudo-element', function () {
var sheet0 = src_1.fromCSS("\n .root { \n -st-states: my-state;\n }\n ", "Style0");
var sheetA = src_1.fromCSS("\n :import(\"./relative/path/to/sheet0.stylable.css\"){\n -st-default: Sheet0;\n }\n .container { \n -st-extends: Sheet0;\n }\n ", "StyleA");
var sheetB = src_1.fromCSS("\n :import(\"./relative/path/to/sheetA.stylable.css\"){\n -st-default: SheetA;\n }\n .my-class { \n -st-extends: SheetA;\n }\n .my-class::container:my-state {}\n ", "StyleB");
var css = generator_1.Generator.generate([sheetB], new generator_1.Generator({
namespaceDivider: "__",
resolver: new resolver_1.Resolver({
"./relative/path/to/sheetA.stylable.css": sheetA,
"./relative/path/to/sheet0.stylable.css": sheet0
})
}));
expect(css[3]).to.equal('');
});
it('supports multiple appearances of the same css rule', function () {
var sheet = src_1.fromCSS("\n .container {\n color: black;\n color: red;\n }\n ", "''");
var css = generator_1.Generator.generate(sheet);
chai_1.expect(css[0]).to.equal('.container {\n color: black;\n color: red\n}');
expect(css[0]).to.equal('.container {\n color: black;\n color: red\n}');
});

@@ -339,3 +446,3 @@ });

}));
chai_1.expect(sheet.classes['container']).to.equal('Sheet__container');
expect(sheet.classes['container']).to.equal('Sheet__container');
});

@@ -351,4 +458,4 @@ it('should update the scoped classnames on depended stylesheet', function () {

}));
chai_1.expect(sheetA.classes['container']).to.equal('sheetA__container');
chai_1.expect(sheetB.classes['container']).to.equal('sheetB__container');
expect(sheetA.classes['container']).to.equal('sheetA__container');
expect(sheetB.classes['container']).to.equal('sheetB__container');
});

@@ -360,3 +467,3 @@ it('should update root classname evan if there is no root defined', function () {

}));
chai_1.expect(sheet.classes['root']).to.equal('Sheet__root');
expect(sheet.classes['root']).to.equal('Sheet__root');
});

@@ -374,4 +481,4 @@ });

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -386,4 +493,4 @@ it('should work with other chunks after', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -398,4 +505,4 @@ it('should work with multiple selectors inline', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -415,4 +522,4 @@ });

var res = ["@keyframes s0__name {\n from {}\n to {}\n}"];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -442,4 +549,4 @@ it('scope animation and animation name', function () {

];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -458,4 +565,4 @@ });

var res = ['@media (max-width: 300px) {\n .s0__container {}\n}'];
css.forEach(function (chunk, index) { return chai_1.expect(chunk).to.eql(res[index]); });
chai_1.expect(css.length).to.equal(res.length);
css.forEach(function (chunk, index) { return expect(chunk).to.matchCSS(res[index]); });
expect(css.length).to.equal(res.length);
});

@@ -462,0 +569,0 @@ });

@@ -11,79 +11,54 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var src_1 = require("../src");
var generator_1 = require("../src/generator");
var chai_1 = require("chai");
var stylable_test_kit_1 = require("./utils/stylable-test-kit");
describe('static Generator mixins', function () {
it('should add rules to the root selector', function () {
function mixin(options) {
return {
color: options[0]
};
}
var sheet = src_1.fromCSS("\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: MyMixin;\n }\n .container { \n -st-mixin: MyMixin(red); \n }\n ", "StyleA");
var gen = new generator_1.Generator({
namespaceDivider: "__"
});
var stack = [];
gen.prepareSelector(sheet, '.container', {
MyMixin: mixin
}, stack);
chai_1.expect(stack[0]).to.eql({
selector: '.container',
rules: {
"-st-mixin": "MyMixin(red)",
color: "red"
}
});
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.JS('./relative/path/to/mixin.js', 'MixinJS', {
default: function mixin(options) {
return {
color: options[0]
};
}
}),
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: MyMixin;\n }\n .container { \n -st-mixin: MyMixin(red); \n }\n ")
], {});
env.validate.output([
'.Main__container {\n color: red\n}'
]);
});
it('should add child selectors', function () {
function mixin(options) {
return {
":hover": {
color: options[0]
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.JS('./relative/path/to/mixin.js', 'MixinJS', {
default: function mixin(options) {
return {
':hover': {
color: options[0]
}
};
}
};
}
var sheet = src_1.fromCSS("\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: MyMixin;\n }\n .container { \n -st-mixin: MyMixin(red);\n }\n ", "StyleA");
var gen = new generator_1.Generator({
namespaceDivider: "__"
});
var stack = [];
gen.prepareSelector(sheet, '.container', {
MyMixin: mixin
}, stack);
chai_1.expect(stack).to.eql([
{
selector: '.container',
rules: {
'-st-mixin': "MyMixin(red)"
}
},
{
selector: '.container :hover',
rules: {
color: "red"
}
}
}),
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: MyMixin;\n }\n .container { \n -st-mixin: MyMixin(red); \n }\n ")
], {});
env.validate.output([
'.Main__container {}',
'.Main__container :hover {\n color: red\n}'
]);
});
it('should add extended selectors (&) in the first level', function () {
function mixin(options) {
return {
"&:hover": {
color: options[0]
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.JS('./relative/path/to/mixin.js', 'MixinJS', {
default: function mixin(options) {
return {
'&:hover': {
color: options[0]
}
};
}
};
}
var sheet = src_1.fromCSS("\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: MyMixin;\n }\n .container { \n -st-mixin: MyMixin(red);\n }\n ", "StyleA");
var gen = new generator_1.Generator({
namespaceDivider: "__"
});
var stack = [];
gen.prepareSelector(sheet, '.container', {
MyMixin: mixin
}, stack);
chai_1.expect(stack[1]).to.eql({
selector: ".container:hover",
rules: { color: "red" }
});
}),
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: MyMixin;\n }\n .container { \n -st-mixin: MyMixin(red); \n }\n ")
], {});
env.validate.output([
'.Main__container {}',
'.Main__container:hover {\n color: red\n}'
]);
});

@@ -104,23 +79,12 @@ it('should handle nested mixins', function () {

}
var sheet = src_1.fromCSS("\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: MyMixin;\n }\n .container { \n -st-mixin: MyMixin(red, 10px solid black);\n }\n ", "StyleA");
var gen = new generator_1.Generator({
namespaceDivider: "__"
});
var stack = [];
gen.prepareSelector(sheet, '.container', {
MyMixin: mixin
}, stack);
chai_1.expect(stack).to.eql([
{
selector: ".container",
rules: { "-st-mixin": "MyMixin(red, 10px solid black)" }
},
{
selector: ".container > *",
rules: { background: "red", border: "10px solid black", color: "red" }
},
{
selector: ".container > *:hover",
rules: { color: "green" }
}
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.JS('./relative/path/to/mixin.js', 'MixinJS', {
default: mixin
}),
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: MyMixin;\n }\n .container { \n -st-mixin: MyMixin(red, 10px solid black);\n }\n ")
], {});
env.validate.output([
'.Main__container {}',
'.Main__container > * {\n background: red;\n border: 10px solid black;\n color: red\n}',
'.Main__container > *:hover {\n color: green\n}'
]);

@@ -127,0 +91,0 @@ });

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

var chai_1 = require("chai");
var stylable_test_kit_1 = require("./utils/stylable-test-kit");
describe('Generator variables interpolation', function () {

@@ -75,52 +76,29 @@ it('should not output :vars selector', function () {

it('should resolve value() usage in mixin call', function () {
function mixin(options) {
return {
color: options[0],
};
}
function otherMixin(options) {
return {
backgroundColor: options[0],
};
}
function noParamsMixin() {
return {
borderColor: 'orange',
};
}
var sheet = src_1.fromCSS("\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: MyMixin;\n }\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: OtherMixin;\n }\n :import(\"./relative/path/to/mixin.js\") {\n -st-default: NoParamsMixin;\n }\n :vars {\n param: red;\n }\n .container {\n -st-mixin: MyMixin(value(param)) NoParamsMixin OtherMixin(blue);\n }\n ", "''");
var gen = new generator_1.Generator({
namespaceDivider: "__",
mode: generator_1.Mode.PROD
});
var stack = [];
gen.prepareSelector(sheet, '.container', {
MyMixin: mixin,
OtherMixin: otherMixin,
NoParamsMixin: noParamsMixin,
param: 'red',
}, stack);
chai_1.expect(stack[0]).to.eql({
selector: '.container',
rules: {
"-st-mixin": "MyMixin(value(param)) NoParamsMixin OtherMixin(blue)",
color: "red",
}
}, '.container red');
chai_1.expect(stack[1]).to.eql({
selector: '.container',
rules: {
"-st-mixin": "MyMixin(value(param)) NoParamsMixin OtherMixin(blue)",
borderColor: "orange",
}
}, '.container orange');
chai_1.expect(stack[2]).to.eql({
selector: '.container',
rules: {
"-st-mixin": "MyMixin(value(param)) NoParamsMixin OtherMixin(blue)",
backgroundColor: "blue",
}
}, '.container blue');
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.JS('./mixins.js', 'Mixins', {
mixin: function (options) {
return {
color: options[0],
};
},
otherMixin: function (options) {
return {
backgroundColor: options[0],
};
},
noParamsMixin: function () {
return {
borderColor: 'orange',
};
}
}),
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :import(\"./mixins.js\") {\n -st-named: mixin, otherMixin, noParamsMixin;\n }\n :vars {\n param: red;\n }\n .container {\n -st-mixin: mixin(value(param)) noParamsMixin otherMixin(blue);\n }\n ")
], {});
env.validate.output([
'.Main__container {\n background-color: blue\n}',
'.Main__container {\n border-color: orange\n}',
'.Main__container {\n color: red/*param*/\n}'
]); // ToDo: fix order and combine into a single CSS ruleset
});
});
//# sourceMappingURL=generator.value.spec.js.map

@@ -9,7 +9,7 @@ "use strict";

var _import = new import_1.Import('./a', 'Name', {});
chai_1.expect(_import.containsSymbol('Name')).to.equal(true);
chai_1.expect(import_1.containsSymbol(_import, 'Name')).to.equal(true);
});
it('should find named import', function () {
var _import = new import_1.Import('./a', 'Name', { "ImportedName": "LocalImport" });
chai_1.expect(_import.containsSymbol('ImportedName')).to.equal(true);
chai_1.expect(import_1.containsSymbol(_import, 'ImportedName')).to.equal(true);
});

@@ -28,4 +28,4 @@ });

chai_1.expect(_import.defaultExport).to.equal('DefaultName');
chai_1.expect(_import.containsSymbol('NamedA'), 'NamedA').to.equal(true);
chai_1.expect(_import.containsSymbol('NamedB'), 'NamedB').to.equal(true);
chai_1.expect(import_1.containsSymbol(_import, 'NamedA'), 'NamedA').to.equal(true);
chai_1.expect(import_1.containsSymbol(_import, 'NamedB'), 'NamedB').to.equal(true);
});

@@ -32,0 +32,0 @@ it('should return Import instance from import CSS definition with "from" inside definition', function () {

@@ -29,5 +29,5 @@ "use strict";

it('multiple values', function () {
var actual = objectify("\n .btn {\n box-shadow: 0, 1, 2;\n }\n ");
var actual = objectify("\n .btn {\n box-shadow: 0,1,2;\n }\n ");
var expected = {
".btn": { "boxShadow": "0, 1, 2" }
".btn": { "boxShadow": "0,1,2" }
};

@@ -210,5 +210,2 @@ chai_1.expect(actual).to.eql(expected);

});
describe('Parser (objectify stylis)', function () {
objectifyTests(parser_1.objectifyCSSStylis);
});
//# sourceMappingURL=parser.spec.js.map

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

var chai_1 = require("chai");
var stylable_test_kit_1 = require("./utils/stylable-test-kit");
describe('Resolver', function () {

@@ -17,2 +18,16 @@ describe('resolve', function () {

});
it('get the import named definition for the symbol', function () {
var sheetA = src_1.fromCSS("");
var sheetB = src_1.fromCSS("\n :import {\n -st-from: \"./path/to/thing\";\n -st-named: x;\n }\n .class {\n -st-extends: x;\n }\n ");
var resolver = new resolver_1.Resolver({ "./path/to/thing": { x: sheetA } });
chai_1.expect(resolver.resolve(sheetB, "class")).to.equal(sheetA);
});
it('get the import named definition for the symbol when default is override named import', function () {
var sheetNamed = src_1.fromCSS("");
var sheetDefault = src_1.fromCSS("");
var sheetMain = src_1.fromCSS("\n :import {\n -st-from: \"./path/to/thing\";\n -st-default: x;\n -st-named: x as y;\n }\n .classExtendDefault {\n -st-extends: x;\n }\n .classExtendNamed {\n -st-extends: y;\n }\n ");
var resolver = new resolver_1.Resolver({ "./path/to/thing": { x: sheetNamed, default: sheetDefault } });
chai_1.expect(resolver.resolve(sheetMain, "classExtendDefault")).to.equal(sheetDefault);
chai_1.expect(resolver.resolve(sheetMain, "classExtendNamed")).to.equal(sheetNamed);
});
});

@@ -28,3 +43,3 @@ describe('resolveSymbols', function () {

var resolved = new resolver_1.Resolver({ "./path": resolvedModule }).resolveSymbols(sheet);
chai_1.expect(resolved).to.eql({ name1: resolvedModule });
chai_1.expect(resolved).to.eql({ name1: resolvedModule, root: 'root' });
});

@@ -37,3 +52,3 @@ it('should handle nameless default by using the path', function () {

var resolved = new resolver_1.Resolver({ "./path": resolvedModule }).resolveSymbols(sheet);
chai_1.expect(resolved).to.eql({ './path': resolvedModule });
chai_1.expect(resolved).to.eql({ './path': resolvedModule, root: 'root' });
});

@@ -57,3 +72,3 @@ it('should resolve named symbols', function () {

});
it('should resolve stylesheets', function () {
it('should resolve stylesheet vars', function () {
var resolvedModule = new stylesheet_1.Stylesheet({

@@ -78,2 +93,23 @@ ":vars": {

});
it('should resolve named vars alias', function () {
var resolvedModule = new stylesheet_1.Stylesheet({
":vars": {
"param1": "red",
"param2": "blue",
}
});
var sheet = new stylesheet_1.Stylesheet({
":import": {
"-st-from": "./path",
"-st-named": "param1 as P1, param2 as P2",
},
":vars": {
"P3": "green",
},
}, "namespace");
var resolved = new resolver_1.Resolver({
"./path": resolvedModule,
}).resolveSymbols(sheet);
chai_1.expect(resolved).to.contain({ P1: "red", P2: "blue", P3: "green" });
});
it('should throw error on var name conflict', function () {

@@ -117,3 +153,74 @@ var resolvedModule = new stylesheet_1.Stylesheet({

});
describe('getSymbolDefinition', function () {
it('should return type "not-found" when symbol is missing', function () {
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.CSS('./main.css', 'Main', "")
], {});
var mainStylesheet = env.resolver.resolveModule('./main.css');
var symbolDef = env.resolver.getSymbolDefinition(mainStylesheet, 'missing');
chai_1.expect(symbolDef).to.eql({ origin: mainStylesheet, type: 'not-found', localName: '' });
});
it('should return class from stylesheet', function () {
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.CSS('./main.css', 'Main', "\n .classA {}\n ")
], {});
var mainStylesheet = env.resolver.resolveModule('./main.css');
var symbolDef = env.resolver.getSymbolDefinition(mainStylesheet, 'classA');
chai_1.expect(symbolDef).to.eql({ origin: mainStylesheet, type: 'class', localName: 'classA' });
});
it('should return var from stylesheet', function () {
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :vars {\n param1: green; \n }\n ")
], {});
var mainStylesheet = env.resolver.resolveModule('./main.css');
var symbolDef = env.resolver.getSymbolDefinition(mainStylesheet, 'param1');
chai_1.expect(symbolDef).to.eql({ origin: mainStylesheet, type: 'var', localName: 'param1' });
});
it('should return class from imported stylesheet', function () {
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.CSS('./style-x.css', 'StyleX', "\n .classA {}\n "),
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :import {\n -st-from: \"./style-x.css\";\n -st-named: classA as renamedClassA;\n }\n ")
], {});
var mainStylesheet = env.resolver.resolveModule('./main.css');
var symbolDef = env.resolver.getSymbolDefinition(mainStylesheet, 'renamedClassA');
var styleX = env.resolver.resolveModule('./style-x.css');
chai_1.expect(symbolDef).to.eql({ origin: styleX, type: 'class', localName: 'classA' });
});
it('should return var from imported stylesheet', function () {
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.CSS('./style-x.css', 'StyleX', "\n :vars {\n param1: green; \n }\n "),
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :import {\n -st-from: \"./style-x.css\";\n -st-named: param1 as renamedParam;\n }\n ")
], {});
var mainStylesheet = env.resolver.resolveModule('./main.css');
var symbolDef = env.resolver.getSymbolDefinition(mainStylesheet, 'renamedParam');
var styleX = env.resolver.resolveModule('./style-x.css');
chai_1.expect(symbolDef).to.eql({ origin: styleX, type: 'var', localName: 'param1' });
});
it('should return default imported stylesheet', function () {
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.CSS('./style-x.css', 'StyleX', ""),
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :import {\n -st-from: \"./style-x.css\";\n -st-default: StyleXDefault;\n }\n ")
], {});
var mainStylesheet = env.resolver.resolveModule('./main.css');
var symbolDef = env.resolver.getSymbolDefinition(mainStylesheet, 'StyleXDefault');
var styleX = env.resolver.resolveModule('./style-x.css');
chai_1.expect(symbolDef).to.eql({ origin: styleX, type: 'stylesheet', localName: 'default' });
});
it('should return symbols imported from JS module', function () {
var env = stylable_test_kit_1.defineStylableEnv([
stylable_test_kit_1.JS('./module-x.js', 'ModuleX', {
default: 'def-value',
other: 'named-value'
}),
stylable_test_kit_1.CSS('./main.css', 'Main', "\n :import {\n -st-from: \"./module-x.js\";\n -st-default: moduleXDefault;\n -st-named: other as moduleXNamed;\n }\n ")
], {});
var mainStylesheet = env.resolver.resolveModule('./main.css');
var defaultDef = env.resolver.getSymbolDefinition(mainStylesheet, 'moduleXDefault');
var namedDef = env.resolver.getSymbolDefinition(mainStylesheet, 'moduleXNamed');
var moduleX = env.resolver.resolveModule('./module-x.js');
chai_1.expect(defaultDef, 'default').to.eql({ origin: moduleX, type: 'JSExport', localName: 'default' });
chai_1.expect(namedDef, 'named').to.eql({ origin: moduleX, type: 'JSExport', localName: 'other' });
});
});
});
//# sourceMappingURL=resolver.spec.js.map

@@ -105,6 +105,27 @@ "use strict";

container: {
"-st-states": ["stateA", "stateB"]
"-st-states": {
"stateA": null,
"stateB": null
}
}
});
});
it('with mapped -st-states', function () {
var sheet = src_1.fromCSS("\n .container {\n -st-states: stateA(\".x\"), stateB, state-c(\"[x=\"y\"]\"), state-d;\n }\n ");
chai_1.expect(sheet.typedClasses).to.eql({
root: { "-st-root": true },
container: {
"-st-states": { "stateA": ".x", "stateB": null, "state-c": "[x=\"y\"]", "state-d": null }
}
});
});
it('with trim mapped -st-states', function () {
var sheet = src_1.fromCSS("\n .container {\n -st-states: stateA(\" .x \"), stateB, state-c(\" [x=\"y\"] \"), state-d;\n }\n ");
chai_1.expect(sheet.typedClasses).to.eql({
root: { "-st-root": true },
container: {
"-st-states": { "stateA": ".x", "stateB": null, "state-c": "[x=\"y\"]", "state-d": null }
}
});
});
it('with empty -st-states ', function () {

@@ -115,3 +136,3 @@ var sheet = src_1.fromCSS("\n .container {\n -st-states: ;\n }\n ");

container: {
"-st-states": []
"-st-states": {}
}

@@ -129,2 +150,11 @@ });

});
it('with auto -st-extends on imported elements with capital first letter', function () {
var sheet = src_1.fromCSS("\n :import(\"./path/to/thing\"){\n -st-default: Thing;\n }\n Thing {}\n ");
chai_1.expect(sheet.typedClasses).to.eql({
root: { "-st-root": true },
Thing: {
"-st-extends": "Thing"
}
});
});
it('with -st-mixin', function () {

@@ -154,15 +184,23 @@ var sheet = src_1.fromCSS("\n :import(\"./path/to/mixin\"){\n -st-named: MyMixin1;\n }\n .container {\n -st-mixin: MyMixin1;\n }\n ");

});
it('with -st-mixin with missing params should remove the last', function () {
var sheet = src_1.fromCSS("\n :import(\"./path/to/mixin\"){\n -st-named: MyMixin1;\n }\n .container {\n -st-mixin: MyMixin1( 300 , , , );\n }\n ");
it('with -st-mixin with missing params should remove empty args', function () {
var sheet = src_1.fromCSS("\n :import(\"./path/to/mixin\"){\n -st-named: MyMixin1;\n }\n .container {\n -st-mixin: MyMixin1( 300 , '', 400);\n }\n ");
chai_1.expect(sheet.mixinSelectors).to.eql({
".container": [
{ type: "MyMixin1", options: ["300", "", ""] }
{ type: "MyMixin1", options: ["300", "", '400'] }
]
});
});
it.skip('TODO: with -st-mixin with missing params should give an empty string value to missing arg', function () {
var sheet = src_1.fromCSS("\n :import(\"./path/to/mixin\"){\n -st-named: MyMixin1;\n }\n .container {\n -st-mixin: MyMixin1( 300 , , 400);\n }\n ");
chai_1.expect(sheet.mixinSelectors).to.eql({
".container": [
{ type: "MyMixin1", options: ["300", "", '400'] }
]
});
});
it('with -st-mixin with params normalized', function () {
var sheet = src_1.fromCSS("\n :import(\"./path/to/mixin\"){\n -st-named: MyMixin1;\n }\n .container {\n -st-mixin: MyMixin1(300, aaa, \"bbb\", \"cc,c\", \"\"ddd\"\", \"\"eee\"\", 'fff');\n }\n ");
var sheet = src_1.fromCSS("\n :import(\"./path/to/mixin\"){\n -st-named: MyMixin1;\n }\n .container {\n -st-mixin: MyMixin1(300, aaa, \"bbb\", \"cc,c\", \"'ddd'\", '\"eee\"', 'fff');\n }\n ");
chai_1.expect(sheet.mixinSelectors).to.eql({
".container": [
{ type: "MyMixin1", options: ["300", "aaa", "bbb", "cc,c", "\"ddd\"", "\"eee\"", "'fff'"] }
{ type: "MyMixin1", options: ["300", "aaa", "bbb", "cc,c", "'ddd'", "\"eee\"", "fff"] }
]

@@ -198,2 +236,15 @@ });

});
it('with -st-variant does not auto extends root', function () {
var sheet = src_1.fromCSS("\n .container {\n -st-variant: true;\n }\n ");
chai_1.expect(sheet.typedClasses.container).to.not.contain({
"-st-extends": 'root'
});
});
it('with -st-variant extends override auto root', function () {
var sheet = src_1.fromCSS("\n .container {\n -st-extends: Comp;\n -st-variant: true;\n }\n ");
chai_1.expect(sheet.typedClasses.container).to.eql({
"-st-extends": 'Comp',
"-st-variant": true
});
});
});

@@ -316,3 +367,5 @@ describe('generateStateAttribute', function () {

chai_1.expect(sheet.typedClasses[sheet.root]).to.eql({
"-st-states": ["a", "b"]
"-st-states": {
"a": null, "b": null
}
});

@@ -319,0 +372,0 @@ });

{
"name": "stylable",
"version": "3.0.0",
"version": "4.0.0",
"description": "",

@@ -22,3 +22,6 @@ "main": "./dist/src/index.js",

"@types/node": "^8.0.2",
"c3-platform": "^1.0.0",
"chai": "^4.0.2",
"deindent": "^0.1.0",
"flat": "^4.0.0",
"glob": "^7.1.2",

@@ -39,2 +42,4 @@ "mocha": "^3.4.2",

"kebab-case": "^1.0.0",
"lodash.clonedeep": "^4.5.0",
"murmurhash": "0.0.2",
"postcss": "^6.0.3",

@@ -44,2 +49,3 @@ "postcss-js": "^1.0.0",

"postcss-safe-parser": "^3.0.1",
"postcss-value-parser": "^3.3.0",
"stylis": "^3.2.3"

@@ -46,0 +52,0 @@ },

@@ -8,25 +8,1 @@ # Stylable

```
React Component Usage:
```tsx
import { SBStateless, SBComponent, Stylesheet } from "stylable/react";
const Button = SBComponent(class extends React.Component<{ text: string }, any>{
render() {
return <button cssStates={{"my-state": this.state.isMyStateActive}}>
{this.props.text}
</button>
}
}, `
.root {
background: white;
-st-states: my-state;
}
`);
```

@@ -1,4 +0,5 @@

export { Resolver } from "./resolver";
export { Stylesheet } from "./stylesheet";
export { Generator, DEFAULT_CONFIG, Config } from "./generator";
export { objectifyCSS, fromCSS } from "./parser";
export { fromCSS, safeParse } from "./parser";
export { cachedProcessFile, FileProcessor } from "./cached-process-file";
export { StylableMeta, process, SDecl } from "./postcss-process";
export { StylableTransformer, StylableResults } from "./stylable-transformer";
export { Diagnostics } from "./diagnostics";
import { CSSObject } from "./types";
import { STYLABLE_VALUE_MATCHER } from "./stylable-value-parsers";
import { Stylesheet } from "./stylesheet";
import * as postcss from "postcss";
const objectify = require("../modules/post-css-objectify");
const stylis = require("stylis");
const plugin = require("../modules/plugin");
const postcssJS = require("postcss-js");

@@ -21,5 +20,2 @@ const postcssNested = require("postcss-nested");

stylis.set({ compress: false, lossless: true, global: false, preserve: true });
stylis.use(false);
stylis.use(plugin(stylableObjectifyConfig));

@@ -29,10 +25,11 @@ const postcssConfig = { parser: postcssJS };

export function stringifyCSSObject(cssObject: CSSObject): string {
return processor.process(cssObject, postcssConfig).css;
export function cssObjectToAst(cssObject: CSSObject, sourceFile = '') {
return processor.process(cssObject, {from: sourceFile, ...postcssConfig});
}
export function objectifyCSSStylis(css: string): CSSObject {
return stylis('', css);
export function stringifyCSSObject(cssObject: CSSObject): string {
return cssObjectToAst(cssObject).css;
}
export function objectifyCSS(css: string): CSSObject {

@@ -43,5 +40,8 @@ // return stylis('', css);

export function fromCSS(css: string, namespace?: string, source?: string) {
return new Stylesheet(objectifyCSS(css), namespace, source);
export function fromCSS(_css: string, _namespace?: string, _source?: string) {
throw "TODO: implement";
}
export function safeParse(css: string, options: postcss.ProcessOptions = {from: 'style.css'}) {
return safeParser(css, options);
}

@@ -9,2 +9,3 @@ const tokenizer = require("css-selector-tokenizer");

before?: string;
value?: string;
}

@@ -17,3 +18,3 @@

export type Visitor = (node: SelectorAstNode, index: number) => boolean | void;
export type Visitor = (node: SelectorAstNode, index: number, nodes: SelectorAstNode[]) => boolean | void;

@@ -28,5 +29,5 @@ export function parseSelector(selector: string): SelectorAstNode {

export function traverseNode(node: SelectorAstNode, visitor: Visitor, index: number = 0): boolean | void {
export function traverseNode(node: SelectorAstNode, visitor: Visitor, index: number = 0, nodes: SelectorAstNode[] = [node]): boolean | void {
if (!node) { return }
let doNext = visitor(node, index);
let doNext = visitor(node, index, nodes);
if (doNext === false) { return false; }

@@ -36,3 +37,3 @@ if (doNext === true) { return true; }

for (var i = 0; i < node.nodes.length; i++) {
doNext = traverseNode(node.nodes[i], visitor, i);
doNext = traverseNode(node.nodes[i], visitor, i, node.nodes);
if (doNext === true) { continue; }

@@ -63,2 +64,17 @@ if (doNext === false) { return false; }

export function createRootAfterSpaceChecker() {
var hasSpacing = false;
var isValid = true;
return (node?: SelectorAstNode) => {
if (!node) { return isValid; }
if (node.type === 'spacing') {
hasSpacing = true;
}
if (node.type === 'class' && node.name === 'root' && hasSpacing) {
isValid = false;
}
return isValid;
}
}
export const createSimpleSelectorChecker = createChecker(['selectors', 'selector', ['element', 'class']]);

@@ -73,8 +89,8 @@

export function matchAtKeyframes(selector: string){
export function matchAtKeyframes(selector: string) {
return selector.match(/^@keyframes\s*(.*)/);
}
export function matchAtMedia(selector: string){
export function matchAtMedia(selector: string) {
return selector.match(/^@media\s*(.*)/);
}

@@ -0,5 +1,12 @@

const valueParser = require("postcss-value-parser");
export type MappedStates = { [s: string]: string | null };
//TODO: remove
export interface TypedClass {
"-st-root"?: boolean;
"-st-states"?: string[];
"-st-states"?: string[] | MappedStates;
"-st-extends"?: string;
"-st-variant"?: boolean;
}

@@ -19,5 +26,12 @@

extends: '-st-extends' as "-st-extends",
mixin: '-st-mixin' as "-st-mixin"
mixin: '-st-mixin' as "-st-mixin",
variant: '-st-variant' as "-st-variant",
compose: '-st-compose' as "-st-compose",
theme: '-st-theme' as "-st-theme"
};
export type stKeys = keyof typeof valueMapping;
export const stValues: string[] = Object.keys(valueMapping).map((key: stKeys) => valueMapping[key]);
export const STYLABLE_VALUE_MATCHER = /^-st-/;

@@ -28,6 +42,24 @@ export const STYLABLE_NAMED_MATCHER = new RegExp(`^${valueMapping.named}-(.+)`);

"-st-root"(value: string) {
return value === 'false' ? false : true
return value === 'false' ? false : true;
},
"-st-variant"(value: string) {
return value === 'false' ? false : true;
},
"-st-theme"(value: string) {
return value === 'false' ? false : true;
},
"-st-states"(value: string) {
return value ? value.split(',').map((state) => state.trim()) : [];
if (!value) {
return {};
}
const mappedStates: MappedStates = {};
const parts = value.split(/,?([\w-]+)(\(\"([^),]*)"\))?/g);
for (let i = 0; i < parts.length; i += 4) {
const stateName = parts[i + 1];
const mapToSelector = parts[i + 3];
if (stateName) {// ToDo: should check the selector has no operators and child
mappedStates[stateName] = mapToSelector ? mapToSelector.trim() : null;
}
}
return mappedStates;
},

@@ -51,77 +83,71 @@ "-st-extends"(value: string) {

const parts = value.match(/\s*[A-Za-z$_][$_\w]*\(.*?\)\)?|\s*([A-Za-z$_][$_\w]*\s*)/g);
if (!parts || parts.join('').length !== value.replace(/\s*/, '').length) {
throw new Error(valueMapping.mixin + ': not a valid mixin value: ' + value);
}
const ast = valueParser(value);
var mixins: { type: string, options: string[] }[] = [];
ast.nodes.forEach((node: any) => {
return parts.map((mix) => {
let type: string, options: string[], match;
if (node.type === 'function') {
mixins.push({
type: node.value,
options: createOptions(node)
});
} else if (node.type === 'word') {
mixins.push({
type: node.value,
options: []
})
} else if (node.type === 'string') {
//TODO: warn
}
});
if (mix.indexOf('(') === -1) {
type = mix.trim();
options = [];
} else if (match = mix.match(/(.*?)\((.*?\)?)\)/)) {
type = match[1].trim();
options = [];
if(match[2]) {
const args:string = match[2];
let isInParam = false;
let isInString = false;
let lastIndex = 0;
let lastNoneSpaceIndex = 0;
for(let i = 0; i < args.length; ++i){
const currentChar = args[i];
if(currentChar.match(/\s/)){
if(!isInParam){
lastIndex = i + 1; // ignore spaces before param
}
continue;
}
switch(currentChar) {
case `"`:
if(isInParam) {
return mixins;
} else {
isInParam = true;
lastIndex = i + 1;
}
isInString = true;
lastNoneSpaceIndex = i + 1;
break;
case `,`:
if(isInString){
const lastNoneSpaceChar = args[lastNoneSpaceIndex-1];
if(lastNoneSpaceChar === `"`){
lastNoneSpaceIndex = lastNoneSpaceIndex - 1;
} else {
lastNoneSpaceIndex = lastNoneSpaceIndex + 1;
continue;
}
}
options.push(args.slice(lastIndex, lastNoneSpaceIndex))
isInParam = false;
isInString = false;
lastIndex = i + 1;
lastNoneSpaceIndex = i + 1;
break;
default:
isInParam = true;
lastNoneSpaceIndex = i + 1;
}
}
if(lastIndex < args.length){
if(isInParam){
lastNoneSpaceIndex = args[lastNoneSpaceIndex-1] === '"' ? lastNoneSpaceIndex - 1 : lastNoneSpaceIndex
}
options.push(args.slice(lastIndex, lastNoneSpaceIndex));
}
}
} else {
throw new Error('Invalid mixin call:' + mix);
},
"-st-compose"(value: string){
const ast = valueParser(value);
const composes: string[] = [];
ast.walk((node: any)=>{
if (node.type === 'function') {
} else if (node.type === 'word') {
composes.push(node.value);
} else if (node.type === 'string') {
//TODO: warn
}
return { type, options }
});
})
return composes;
}
}
function groupValues(node: any) {
var grouped: any[] = [];
var current: any[] = [];
node.nodes.forEach((node: any) => {
if (node.type === 'div') {
grouped.push(current);
current = [];
} else {
current.push(node);
}
});
const last = grouped[grouped.length - 1];
if ((last && last !== current && current.length) || !last && current.length) {
grouped.push(current);
}
return grouped;
}
function createOptions(node: any) {
return groupValues(node).map((nodes: any) => valueParser.stringify(nodes, (node: any) => {
if (node.type === 'div') {
return null;
} else if (node.type === 'string') {
return node.value;
} else {
return undefined;
}
})).filter((x: string) => typeof x === 'string');
}
export declare type Pojo<T = any> = { [key: string]: T } & object;
export declare type PartialObject<T> = Partial<T> & object;
export declare type CSSObject = any & object;
export declare type CSSRulesObject = any & object;

@@ -13,1 +13,19 @@

export const hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
// export function scope(name: string, namespace: string, separator: string = '-') {
// return namespace ? namespace + separator + name : name;
// }
export function stripQuotation(str: string){
return str.replace(/^['"]|['"]$/g, '');
}
export function filename2varname(filename: string) {
return string2varname(filename.replace(/(?=.*)\.\w+$/, '').replace(/\.st$/, ''));
}
export function string2varname(str: string) {
return str
.replace(/[^0-9a-zA-Z_]/gm, '')
.replace(/^[^a-zA-Z_]+/gm, '')
}
import { Pojo } from "./types";
export function valueTemplate(value: string, data: Pojo, debug: boolean = false, throwCondition = 0): string {
return value.replace(/value\((.*?)\)/g, function (match: string, name: string) {
let translatedValue;
if (~name.indexOf(',')) {
const nameParts = name.split(',');
const variableName = nameParts[0].trim();
let defaultValue = nameParts[1].trim();
defaultValue = data[defaultValue] || defaultValue;
translatedValue = data[variableName] || defaultValue;
} else {
translatedValue = data[name];
}
if (throwCondition > 10 || translatedValue === undefined) { throw new Error('Unresolvable variable: ' + name) }
const res = valueTemplate(translatedValue, data, debug, throwCondition + 1);
return res !== undefined ? res + (debug ? `/*${name}*/` : '') : match;
export const matchValue = /value\((.*?)\)/g
export function valueReplacer(value: string, data: Pojo, onMatch: (value: string, name: string, match: string) => any, debug: boolean = false): string {
return value.replace(matchValue, function (match: string, name: string) {
const translatedValue = onMatch(data[name], name, match);
return translatedValue !== undefined ? translatedValue + (debug ? `/*${name}*/` : '') : match;
});
}
{
"exclude": [
"_docs",
"node_modules",
"dist",
"modules",
"**/*~~.ts"
],
"compilerOptions": {

@@ -3,0 +10,0 @@ /* Basic Options */

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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