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

@stylable/core

Package Overview
Dependencies
Maintainers
6
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 5.4.1-rc.1 to 5.5.0

44

dist/features/st-custom-state.d.ts

@@ -1,3 +0,8 @@

import { parsePseudoStates, transformPseudoClassToCustomState, createBooleanStateClassName, createStateWithParamClassName, systemValidators, validationErrors as sysValidationErrors, resolveStateParam } from '../helpers/custom-state';
import { parsePseudoStates, transformPseudoClassToCustomState, createBooleanStateClassName, createStateWithParamClassName, systemValidators, validationErrors as sysValidationErrors, resolveStateParam, isTemplateState } from '../helpers/custom-state';
export declare const diagnostics: {
MISSING_TYPE_OR_TEMPLATE: {
(name: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("..").DiagnosticSeverity;
};
UNKNOWN_STATE_TYPE: {

@@ -48,2 +53,37 @@ (name: string, type: string): import("../diagnostics").DiagnosticBase;

};
TEMPLATE_MISSING_PLACEHOLDER: {
(state: string, template: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("..").DiagnosticSeverity;
};
TEMPLATE_MULTI_PARAMETERS: {
(state: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("..").DiagnosticSeverity;
};
TEMPLATE_MISSING_PARAMETER: {
(state: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("..").DiagnosticSeverity;
};
UNSUPPORTED_MULTI_SELECTOR: {
(state: string, finalSelector: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("..").DiagnosticSeverity;
};
UNSUPPORTED_COMPLEX_SELECTOR: {
(state: string, finalSelector: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("..").DiagnosticSeverity;
};
INVALID_SELECTOR: {
(state: string, finalSelector: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("..").DiagnosticSeverity;
};
UNSUPPORTED_INITIAL_SELECTOR: {
(state: string, finalSelector: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("..").DiagnosticSeverity;
};
};

@@ -56,3 +96,3 @@ export declare const hooks: import("./feature").FeatureHooks<import("./feature").NodeTypes>;

};
export { parsePseudoStates, transformPseudoClassToCustomState, delimiters, createBooleanStateClassName, createStateWithParamClassName, systemValidators, sysValidationErrors, resolveStateParam, };
export { parsePseudoStates, transformPseudoClassToCustomState, delimiters, createBooleanStateClassName, createStateWithParamClassName, systemValidators, sysValidationErrors, resolveStateParam, isTemplateState, };
//# sourceMappingURL=st-custom-state.d.ts.map

3

dist/features/st-custom-state.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveStateParam = exports.sysValidationErrors = exports.systemValidators = exports.createStateWithParamClassName = exports.createBooleanStateClassName = exports.delimiters = exports.transformPseudoClassToCustomState = exports.parsePseudoStates = exports.hooks = exports.diagnostics = void 0;
exports.isTemplateState = exports.resolveStateParam = exports.sysValidationErrors = exports.systemValidators = exports.createStateWithParamClassName = exports.createBooleanStateClassName = exports.delimiters = exports.transformPseudoClassToCustomState = exports.parsePseudoStates = exports.hooks = exports.diagnostics = void 0;
const feature_1 = require("./feature");

@@ -13,2 +13,3 @@ const custom_state_1 = require("../helpers/custom-state");

Object.defineProperty(exports, "resolveStateParam", { enumerable: true, get: function () { return custom_state_1.resolveStateParam; } });
Object.defineProperty(exports, "isTemplateState", { enumerable: true, get: function () { return custom_state_1.isTemplateState; } });
exports.diagnostics = {

@@ -15,0 +16,0 @@ ...custom_state_1.stateDiagnostics,

@@ -7,4 +7,9 @@ import type * as postcss from 'postcss';

export interface MappedStates {
[s: string]: StateParsedValue | string | null;
[s: string]: StateParsedValue | string | TemplateStateParsedValue | null;
}
export interface TemplateStateParsedValue {
type: 'template';
template: string;
params: [StateParsedValue];
}
export interface StateParsedValue {

@@ -24,2 +29,7 @@ type: string;

export declare const stateDiagnostics: {
MISSING_TYPE_OR_TEMPLATE: {
(name: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("../diagnostics").DiagnosticSeverity;
};
UNKNOWN_STATE_TYPE: {

@@ -70,2 +80,37 @@ (name: string, type: string): import("../diagnostics").DiagnosticBase;

};
TEMPLATE_MISSING_PLACEHOLDER: {
(state: string, template: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("../diagnostics").DiagnosticSeverity;
};
TEMPLATE_MULTI_PARAMETERS: {
(state: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("../diagnostics").DiagnosticSeverity;
};
TEMPLATE_MISSING_PARAMETER: {
(state: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("../diagnostics").DiagnosticSeverity;
};
UNSUPPORTED_MULTI_SELECTOR: {
(state: string, finalSelector: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("../diagnostics").DiagnosticSeverity;
};
UNSUPPORTED_COMPLEX_SELECTOR: {
(state: string, finalSelector: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("../diagnostics").DiagnosticSeverity;
};
INVALID_SELECTOR: {
(state: string, finalSelector: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("../diagnostics").DiagnosticSeverity;
};
UNSUPPORTED_INITIAL_SELECTOR: {
(state: string, finalSelector: string): import("../diagnostics").DiagnosticBase;
code: string;
severity: import("../diagnostics").DiagnosticSeverity;
};
};

@@ -107,2 +152,3 @@ export declare function parsePseudoStates(value: string, decl: postcss.Declaration, diagnostics: Diagnostics): MappedStates;

export declare function transformPseudoClassToCustomState(states: MappedStates, meta: StylableMeta, name: string, node: PseudoClass, namespace: string, resolver: StylableResolver, diagnostics: Diagnostics, rule?: postcss.Rule): void;
export declare function isTemplateState(state: MappedStates[string]): state is TemplateStateParsedValue;
export declare function createBooleanStateClassName(stateName: string, namespace: string): string;

@@ -109,0 +155,0 @@ export declare function createStateWithParamClassName(stateName: string, namespace: string, param: string): string;

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

Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveStateParam = exports.createStateWithParamClassName = exports.createBooleanStateClassName = exports.transformPseudoClassToCustomState = exports.validateStateArgument = exports.validateRuleStateDefinition = exports.systemValidators = exports.validationErrors = exports.parsePseudoStates = exports.stateDiagnostics = exports.stateWithParamDelimiter = exports.booleanStateDelimiter = exports.stateMiddleDelimiter = void 0;
exports.resolveStateParam = exports.createStateWithParamClassName = exports.createBooleanStateClassName = exports.isTemplateState = exports.transformPseudoClassToCustomState = exports.validateStateArgument = exports.validateRuleStateDefinition = exports.systemValidators = exports.validationErrors = exports.parsePseudoStates = exports.stateDiagnostics = exports.stateWithParamDelimiter = exports.booleanStateDelimiter = exports.stateMiddleDelimiter = void 0;
const postcss_value_parser_1 = __importDefault(require("postcss-value-parser"));

@@ -21,2 +21,3 @@ const cssesc_1 = __importDefault(require("cssesc"));

exports.stateDiagnostics = {
MISSING_TYPE_OR_TEMPLATE: (0, diagnostics_1.createDiagnosticReporter)('08000', 'error', (name) => `pseudo-state "${name}" missing type or template`),
UNKNOWN_STATE_TYPE: (0, diagnostics_1.createDiagnosticReporter)('08002', 'error', (name, type) => `pseudo-state "${name}" defined with unknown type: "${type}"`),

@@ -34,2 +35,9 @@ TOO_MANY_STATE_TYPES: (0, diagnostics_1.createDiagnosticReporter)('08003', 'error', (name, types) => `pseudo-state "${name}(${types.join(', ')})" definition must be of a single type`),

].join('\n')),
TEMPLATE_MISSING_PLACEHOLDER: (0, diagnostics_1.createDiagnosticReporter)('08011', 'warning', (state, template) => `pseudo-state "${state}" template "${template}" is missing a placeholder, use "$0" to set the parameter insertion place`),
TEMPLATE_MULTI_PARAMETERS: (0, diagnostics_1.createDiagnosticReporter)('08012', 'error', (state) => `pseudo-state "${state}" template only supports a single parameter`),
TEMPLATE_MISSING_PARAMETER: (0, diagnostics_1.createDiagnosticReporter)('08013', 'error', (state) => `pseudo-state "${state}" template expected a parameter definition`),
UNSUPPORTED_MULTI_SELECTOR: (0, diagnostics_1.createDiagnosticReporter)('08014', 'error', (state, finalSelector) => `pseudo-state "${state}" resulted in an unsupported multi selector "${finalSelector}"`),
UNSUPPORTED_COMPLEX_SELECTOR: (0, diagnostics_1.createDiagnosticReporter)('08015', 'error', (state, finalSelector) => `pseudo-state "${state}" resulted in an unsupported complex selector "${finalSelector}"`),
INVALID_SELECTOR: (0, diagnostics_1.createDiagnosticReporter)('08016', 'error', (state, finalSelector) => `pseudo-state "${state}" resulted in an invalid selector "${finalSelector}"`),
UNSUPPORTED_INITIAL_SELECTOR: (0, diagnostics_1.createDiagnosticReporter)('08017', 'error', (state, finalSelector) => `pseudo-state "${state}" result cannot start with a type or universal selector "${finalSelector}"`),
};

@@ -70,3 +78,3 @@ // parse

function resolveBooleanState(mappedStates, stateDefinition) {
const currentState = mappedStates[stateDefinition.type];
const currentState = mappedStates[stateDefinition.value];
if (!currentState) {

@@ -80,5 +88,6 @@ mappedStates[stateDefinition.value] = null; // add boolean state

function resolveStateType(stateDefinition, mappedStates, stateDefault, diagnostics, decl) {
if (stateDefinition.type === 'function' && stateDefinition.nodes.length === 0) {
const stateName = stateDefinition.value;
if (stateDefinition.nodes.length === 0) {
resolveBooleanState(mappedStates, stateDefinition);
diagnostics.report(exports.stateDiagnostics.NO_STATE_TYPE_GIVEN(stateDefinition.value), {
diagnostics.report(exports.stateDiagnostics.NO_STATE_TYPE_GIVEN(stateName), {
node: decl,

@@ -89,41 +98,124 @@ word: decl.value,

}
if (stateDefinition.nodes.length > 1) {
diagnostics.report(exports.stateDiagnostics.TOO_MANY_STATE_TYPES(stateDefinition.value, (0, value_1.listOptions)(stateDefinition)), {
const { paramType, argsFirstNode, argsFullValue } = collectStateArgsDef(stateDefinition.nodes);
if (!paramType) {
diagnostics.report(exports.stateDiagnostics.MISSING_TYPE_OR_TEMPLATE(stateName), {
node: decl,
word: decl.value,
});
return;
}
const paramType = stateDefinition.nodes[0];
const stateType = {
type: paramType.value,
arguments: [],
defaultValue: postcss_value_parser_1.default
.stringify(stateDefault)
.trim(),
};
if (isCustomMapping(stateDefinition)) {
mappedStates[stateDefinition.value] = stateType.type.trim().replace(/\\["']/g, '"');
if ((paramType === null || paramType === void 0 ? void 0 : paramType.type) === 'string') {
defineTemplateState(stateName, paramType, argsFirstNode, argsFullValue, mappedStates, diagnostics, decl);
}
else if (typeof stateType === 'object' && stateType.type === 'boolean') {
else {
if (argsFullValue.length > 1) {
diagnostics.report(exports.stateDiagnostics.TOO_MANY_STATE_TYPES(stateName, argsFirstNode.map((argNode) => argNode ? postcss_value_parser_1.default.stringify(argNode) : '')), {
node: decl,
word: decl.value,
});
}
defineParamState(stateName, paramType, stateDefault, mappedStates, diagnostics, stateDefinition, decl);
}
}
function defineTemplateState(stateName, templateDef, argsFirstNode, argsFullValue, mappedStates, diagnostics, decl) {
const template = (0, string_1.stripQuotation)(postcss_value_parser_1.default.stringify(templateDef));
if (argsFullValue.length === 1) {
// simple template with no params
mappedStates[stateName] = template.trim().replace(/\\["']/g, '"');
}
else if (argsFullValue.length === 2) {
// single parameter template
if (!template.includes('$0')) {
diagnostics.report(exports.stateDiagnostics.TEMPLATE_MISSING_PLACEHOLDER(stateName, template), {
node: decl,
word: template,
});
}
const paramFullDef = argsFullValue[1];
const paramTypeDef = argsFirstNode[1];
if (!paramTypeDef) {
diagnostics.report(exports.stateDiagnostics.TEMPLATE_MISSING_PARAMETER(stateName), {
node: decl,
});
return;
}
const param = createStateParamDef(stateName + ' parameter', paramTypeDef, paramFullDef.splice(paramFullDef.indexOf(paramTypeDef) + 1), diagnostics, decl);
if (!param) {
// UNKNOWN_STATE_TYPE reported in createStateParamDef
return;
}
const templateStateType = {
type: 'template',
template,
params: [param],
};
mappedStates[stateName] = templateStateType;
}
else {
// unsupported multiple params
diagnostics.report(exports.stateDiagnostics.TEMPLATE_MULTI_PARAMETERS(stateName), {
node: decl,
});
}
}
function defineParamState(stateName, paramType, stateDefault, mappedStates, diagnostics, stateDefinition, decl) {
if (paramType.value === 'boolean') {
// explicit boolean // ToDo: remove support
resolveBooleanState(mappedStates, stateDefinition);
return;
}
else if (paramType.type === 'function' && stateType.type in exports.systemValidators) {
if (paramType.nodes.length > 0) {
resolveArguments(paramType, stateType, stateDefinition.value, diagnostics, decl);
else {
const stateParamDef = createStateParamDef(stateName, paramType, stateDefault, diagnostics, decl);
if (stateParamDef) {
mappedStates[stateName] = stateParamDef;
}
mappedStates[stateDefinition.value] = stateType;
}
else if (stateType.type in exports.systemValidators) {
mappedStates[stateDefinition.value] = stateType;
}
function createStateParamDef(stateName, typeDef, stateDefault, diagnostics, decl) {
const type = typeDef.value;
if (type in exports.systemValidators && (typeDef.type === 'function' || typeDef.type === 'word')) {
const stateType = {
type,
arguments: [],
defaultValue: postcss_value_parser_1.default
.stringify(stateDefault)
.trim(),
};
if (typeDef.type === 'function' && typeDef.nodes.length > 0) {
resolveArguments(typeDef, stateType, stateName, diagnostics, decl);
}
return stateType;
}
else {
diagnostics.report(exports.stateDiagnostics.UNKNOWN_STATE_TYPE(stateDefinition.value, paramType.value), {
const srcValue = postcss_value_parser_1.default.stringify(typeDef);
diagnostics.report(exports.stateDiagnostics.UNKNOWN_STATE_TYPE(stateName, srcValue), {
node: decl,
word: paramType.value,
word: srcValue,
});
return;
}
}
function isCustomMapping(stateDefinition) {
return stateDefinition.nodes.length === 1 && stateDefinition.nodes[0].type === 'string';
function collectStateArgsDef(nodes) {
const argsFullValue = [];
const argsFirstNode = [];
let collectedArg = [];
let firstActualValue = undefined;
for (const node of nodes) {
if (node.type === 'div') {
argsFullValue.push(collectedArg);
argsFirstNode.push(firstActualValue);
collectedArg = [];
firstActualValue = undefined;
}
else {
collectedArg.push(node);
if (!firstActualValue && node.type !== 'space' && node.type !== 'comment') {
firstActualValue = node;
}
}
}
if (collectedArg.length) {
argsFullValue.push(collectedArg);
argsFirstNode.push(firstActualValue);
}
const paramType = argsFirstNode[0];
return { paramType, argsFullValue, argsFirstNode };
}

@@ -339,7 +431,8 @@ function resolveArguments(paramType, stateType, name, diagnostics, decl) {

if (state && typeof state === 'object') {
const { errors } = validateStateArgument(state, meta, state.defaultValue || '', resolver, diagnostics, parentRule, true, !!state.defaultValue);
const stateParam = isTemplateState(state) ? state.params[0] : state;
const { errors } = validateStateArgument(stateParam, meta, stateParam.defaultValue || '', resolver, diagnostics, parentRule, true, !!stateParam.defaultValue);
if (errors) {
rule.walkDecls((decl) => {
if (decl.prop === `-st-states`) {
diagnostics.report(exports.stateDiagnostics.DEFAULT_PARAM_FAILS_VALIDATION(stateName, state.defaultValue || '', errors), {
diagnostics.report(exports.stateDiagnostics.DEFAULT_PARAM_FAILS_VALIDATION(stateName, stateParam.defaultValue || '', errors), {
node: decl,

@@ -387,2 +480,3 @@ word: decl.value,

(0, selector_1.convertToClass)(node).value = createBooleanStateClassName(name, namespace);
delete node.nodes;
}

@@ -392,9 +486,18 @@ else if (typeof stateDef === 'string') {

(0, selector_1.convertToInvalid)(node).value = stateDef;
delete node.nodes;
}
else if (typeof stateDef === 'object') {
resolveStateValue(meta, resolver, diagnostics, rule, node, stateDef, name, namespace);
if (isTemplateState(stateDef)) {
convertTemplateState(meta, resolver, diagnostics, rule, node, stateDef, name);
}
else {
resolveStateValue(meta, resolver, diagnostics, rule, node, stateDef, name, namespace);
}
}
delete node.nodes;
}
exports.transformPseudoClassToCustomState = transformPseudoClassToCustomState;
function isTemplateState(state) {
return !!state && typeof state === 'object' && state.type === 'template';
}
exports.isTemplateState = isTemplateState;
function createBooleanStateClassName(stateName, namespace) {

@@ -416,7 +519,21 @@ const escapedNamespace = (0, cssesc_1.default)(namespace, { isIdentifier: true });

exports.resolveStateParam = resolveStateParam;
function resolveStateValue(meta, resolver, diagnostics, rule, node, stateDef, name, namespace) {
function convertTemplateState(meta, resolver, diagnostics, rule, node, stateParamDef, name) {
const paramStateDef = stateParamDef.params[0];
const resolvedParam = getParamInput(meta, resolver, diagnostics, rule, node, paramStateDef, name);
validateParam(meta, resolver, diagnostics, rule, paramStateDef, resolvedParam, name);
const strippedParam = (0, string_1.stripQuotation)(resolvedParam);
transformMappedStateWithParam({
stateName: name,
template: stateParamDef.template,
param: strippedParam,
node,
rule,
diagnostics,
});
}
function getParamInput(meta, resolver, diagnostics, rule, node, stateParamDef, name) {
const inputValue = node.nodes && node.nodes.length ? (0, selector_1.stringifySelector)(node.nodes) : ``;
let actualParam = resolveParam(meta, resolver, diagnostics, rule, inputValue ? inputValue : stateDef.defaultValue);
if (rule && !inputValue && !stateDef.defaultValue) {
diagnostics.report(exports.stateDiagnostics.NO_STATE_ARGUMENT_GIVEN(name, stateDef.type), {
const resolvedParam = resolveParam(meta, resolver, diagnostics, rule, inputValue ? inputValue : stateParamDef.defaultValue);
if (rule && !inputValue && !stateParamDef.defaultValue) {
diagnostics.report(exports.stateDiagnostics.NO_STATE_ARGUMENT_GIVEN(name, stateParamDef.type), {
node: rule,

@@ -426,6 +543,9 @@ word: name,

}
const validator = exports.systemValidators[stateDef.type];
return resolvedParam;
}
function validateParam(meta, resolver, diagnostics, rule, stateParamDef, resolvedParam, name) {
const validator = exports.systemValidators[stateParamDef.type];
let stateParamOutput;
try {
stateParamOutput = validator.validate(actualParam, stateDef.arguments, resolveParam.bind(null, meta, resolver, diagnostics, rule), false, true);
stateParamOutput = validator.validate(resolvedParam, stateParamDef.arguments, resolveParam.bind(null, meta, resolver, diagnostics, rule), false, true);
}

@@ -436,15 +556,68 @@ catch (e) {

if (stateParamOutput !== undefined) {
if (stateParamOutput.res !== actualParam) {
actualParam = stateParamOutput.res;
if (stateParamOutput.res !== resolvedParam) {
resolvedParam = stateParamOutput.res;
}
if (rule && stateParamOutput.errors) {
diagnostics.report(exports.stateDiagnostics.FAILED_STATE_VALIDATION(name, actualParam, stateParamOutput.errors), {
diagnostics.report(exports.stateDiagnostics.FAILED_STATE_VALIDATION(name, resolvedParam, stateParamOutput.errors), {
node: rule,
word: actualParam,
word: resolvedParam,
});
}
}
const strippedParam = (0, string_1.stripQuotation)(actualParam);
}
function resolveStateValue(meta, resolver, diagnostics, rule, node, stateParamDef, name, namespace) {
const resolvedParam = getParamInput(meta, resolver, diagnostics, rule, node, stateParamDef, name);
validateParam(meta, resolver, diagnostics, rule, stateParamDef, resolvedParam, name);
const strippedParam = (0, string_1.stripQuotation)(resolvedParam);
(0, selector_1.convertToClass)(node).value = createStateWithParamClassName(name, namespace, strippedParam);
delete node.nodes;
}
function transformMappedStateWithParam({ stateName, template, param, node, rule, diagnostics, }) {
const targetSelectorStr = template.replace(/\$0/g, param);
const selectorAst = (0, selector_1.parseSelectorWithCache)(targetSelectorStr, { clone: true });
if (selectorAst.length > 1) {
if (rule) {
diagnostics.report(exports.stateDiagnostics.UNSUPPORTED_MULTI_SELECTOR(stateName, targetSelectorStr), {
node: rule,
});
}
return;
}
else {
const firstSelector = selectorAst[0].nodes.find(({ type }) => type !== 'comment');
if ((firstSelector === null || firstSelector === void 0 ? void 0 : firstSelector.type) === 'type' || (firstSelector === null || firstSelector === void 0 ? void 0 : firstSelector.type) === 'universal') {
if (rule) {
diagnostics.report(exports.stateDiagnostics.UNSUPPORTED_INITIAL_SELECTOR(stateName, targetSelectorStr), {
node: rule,
});
}
return;
}
let unexpectedSelector = undefined;
for (const node of selectorAst[0].nodes) {
if (node.type === 'combinator' || node.type === 'invalid') {
unexpectedSelector = node;
break;
}
}
if (unexpectedSelector) {
if (rule) {
switch (unexpectedSelector.type) {
case 'combinator':
diagnostics.report(exports.stateDiagnostics.UNSUPPORTED_COMPLEX_SELECTOR(stateName, targetSelectorStr), {
node: rule,
});
break;
case 'invalid':
diagnostics.report(exports.stateDiagnostics.INVALID_SELECTOR(stateName, targetSelectorStr), {
node: rule,
});
break;
}
}
return;
}
}
(0, selector_1.convertToSelector)(node).nodes = selectorAst[0].nodes;
}
function resolveParam(meta, resolver, diagnostics, rule, nodeContent) {

@@ -451,0 +624,0 @@ const defaultStringValue = '';

@@ -6,3 +6,3 @@ export { safeParse } from './parser';

export { STSymbol, STGlobal, STCustomSelector, STCustomState, CSSCustomProperty } from './features';
export type { MappedStates, StateParsedValue } from './helpers/custom-state';
export type { MappedStates, StateParsedValue, TemplateStateParsedValue } from './helpers/custom-state';
export { murmurhash3_32_gc } from './murmurhash';

@@ -9,0 +9,0 @@ export { cssParse } from './parser';

import type * as postcss from 'postcss';
export declare function isAsset(url: string): boolean;
export declare function isRelativeNativeCss(fullPath: string): boolean;
export declare function makeAbsolute(resourcePath: string, rootContext: string, moduleContext: string): string;
export declare function makeAbsolute(host: {
join: (...paths: string[]) => string;
isAbsolute: (path: string) => boolean;
}, resourcePath: string, rootContext: string, moduleContext: string): string;
export declare function fixRelativeUrls(ast: postcss.Root, originPath: string, targetPath: string): void;
export declare function assureRelativeUrlPrefix(url: string): string;
//# sourceMappingURL=stylable-assets.d.ts.map

@@ -36,4 +36,4 @@ "use strict";

exports.isRelativeNativeCss = isRelativeNativeCss;
function makeAbsolute(resourcePath, rootContext, moduleContext) {
const isAbs = path_1.default.isAbsolute(resourcePath);
function makeAbsolute(host, resourcePath, rootContext, moduleContext) {
const isAbs = host.isAbsolute(resourcePath);
let abs;

@@ -44,3 +44,3 @@ if (isExternal(resourcePath) || resourcePath.startsWith('~')) {

else if (isAbs && resourcePath.startsWith('/')) {
abs = path_1.default.join(rootContext, resourcePath);
abs = host.join(rootContext, resourcePath);
}

@@ -51,3 +51,3 @@ else if (isAbs) {

else {
abs = path_1.default.join(moduleContext, resourcePath);
abs = host.join(moduleContext, resourcePath);
}

@@ -54,0 +54,0 @@ return abs;

{
"name": "@stylable/core",
"version": "5.4.1-rc.1",
"version": "5.5.0",
"description": "CSS for Components",

@@ -14,4 +14,4 @@ "main": "dist/index.js",

"dependencies": {
"@tokey/css-selector-parser": "^0.6.0",
"@tokey/imports-parser": "^0.1.0",
"@tokey/css-selector-parser": "^0.6.1",
"@tokey/imports-parser": "^0.1.2",
"balanced-match": "^2.0.0",

@@ -25,3 +25,3 @@ "css-selector-tokenizer": "^0.8.0",

"lodash.clonedeepwith": "^4.5.0",
"postcss": "^8.4.19",
"postcss": "^8.4.20",
"postcss-js": "^4.0.0",

@@ -28,0 +28,0 @@ "postcss-nested": "^6.0.0",

@@ -14,2 +14,3 @@ import { createFeature } from './feature';

resolveStateParam,
isTemplateState,
} from '../helpers/custom-state';

@@ -39,2 +40,3 @@

resolveStateParam,
isTemplateState,
};
import type * as postcss from 'postcss';
import postcssValueParser from 'postcss-value-parser';
import postcssValueParser, {
type Node as ValueNode,
type FunctionNode,
} from 'postcss-value-parser';
import cssesc from 'cssesc';
import type { PseudoClass } from '@tokey/css-selector-parser';
import type { PseudoClass, SelectorNode } from '@tokey/css-selector-parser';
import { createDiagnosticReporter, Diagnostics } from '../diagnostics';

@@ -11,2 +14,3 @@ import {

convertToInvalid,
convertToSelector,
} from './selector';

@@ -23,4 +27,9 @@ import { groupValues, listOptions } from './value';

export interface MappedStates {
[s: string]: StateParsedValue | string | null;
[s: string]: StateParsedValue | string | TemplateStateParsedValue | null;
}
export interface TemplateStateParsedValue {
type: 'template';
template: string;
params: [StateParsedValue];
}
export interface StateParsedValue {

@@ -43,2 +52,7 @@ type: string;

export const stateDiagnostics = {
MISSING_TYPE_OR_TEMPLATE: createDiagnosticReporter(
'08000',
'error',
(name: string) => `pseudo-state "${name}" missing type or template`
),
UNKNOWN_STATE_TYPE: createDiagnosticReporter(

@@ -104,2 +118,42 @@ '08002',

),
TEMPLATE_MISSING_PLACEHOLDER: createDiagnosticReporter(
'08011',
'warning',
(state: string, template: string) =>
`pseudo-state "${state}" template "${template}" is missing a placeholder, use "$0" to set the parameter insertion place`
),
TEMPLATE_MULTI_PARAMETERS: createDiagnosticReporter(
'08012',
'error',
(state: string) => `pseudo-state "${state}" template only supports a single parameter`
),
TEMPLATE_MISSING_PARAMETER: createDiagnosticReporter(
'08013',
'error',
(state: string) => `pseudo-state "${state}" template expected a parameter definition`
),
UNSUPPORTED_MULTI_SELECTOR: createDiagnosticReporter(
'08014',
'error',
(state: string, finalSelector: string) =>
`pseudo-state "${state}" resulted in an unsupported multi selector "${finalSelector}"`
),
UNSUPPORTED_COMPLEX_SELECTOR: createDiagnosticReporter(
'08015',
'error',
(state: string, finalSelector: string) =>
`pseudo-state "${state}" resulted in an unsupported complex selector "${finalSelector}"`
),
INVALID_SELECTOR: createDiagnosticReporter(
'08016',
'error',
(state: string, finalSelector: string) =>
`pseudo-state "${state}" resulted in an invalid selector "${finalSelector}"`
),
UNSUPPORTED_INITIAL_SELECTOR: createDiagnosticReporter(
'08017',
'error',
(state: string, finalSelector: string) =>
`pseudo-state "${state}" result cannot start with a type or universal selector "${finalSelector}"`
),
};

@@ -135,3 +189,9 @@

if (stateDefinition.type === 'function') {
resolveStateType(stateDefinition, mappedStates, stateDefault, diagnostics, decl);
resolveStateType(
stateDefinition as FunctionNode,
mappedStates,
stateDefault,
diagnostics,
decl
);
} else if (stateDefinition.type === 'word') {

@@ -147,3 +207,3 @@ resolveBooleanState(mappedStates, stateDefinition);

function resolveBooleanState(mappedStates: MappedStates, stateDefinition: ParsedValue) {
const currentState = mappedStates[stateDefinition.type];
const currentState = mappedStates[stateDefinition.value];
if (!currentState) {

@@ -156,3 +216,3 @@ mappedStates[stateDefinition.value] = null; // add boolean state

function resolveStateType(
stateDefinition: ParsedValue,
stateDefinition: FunctionNode,
mappedStates: MappedStates,

@@ -163,6 +223,7 @@ stateDefault: ParsedValue[],

) {
if (stateDefinition.type === 'function' && stateDefinition.nodes.length === 0) {
const stateName = stateDefinition.value;
if (stateDefinition.nodes.length === 0) {
resolveBooleanState(mappedStates, stateDefinition);
diagnostics.report(stateDiagnostics.NO_STATE_TYPE_GIVEN(stateDefinition.value), {
diagnostics.report(stateDiagnostics.NO_STATE_TYPE_GIVEN(stateName), {
node: decl,

@@ -174,50 +235,186 @@ word: decl.value,

}
const { paramType, argsFirstNode, argsFullValue } = collectStateArgsDef(stateDefinition.nodes);
if (stateDefinition.nodes.length > 1) {
diagnostics.report(
stateDiagnostics.TOO_MANY_STATE_TYPES(
stateDefinition.value,
listOptions(stateDefinition)
),
{
node: decl,
word: decl.value,
}
if (!paramType) {
diagnostics.report(stateDiagnostics.MISSING_TYPE_OR_TEMPLATE(stateName), {
node: decl,
});
return;
}
if (paramType?.type === 'string') {
defineTemplateState(
stateName,
paramType,
argsFirstNode,
argsFullValue,
mappedStates,
diagnostics,
decl
);
} else {
if (argsFullValue.length > 1) {
diagnostics.report(
stateDiagnostics.TOO_MANY_STATE_TYPES(
stateName,
argsFirstNode.map((argNode) =>
argNode ? postcssValueParser.stringify(argNode) : ''
)
),
{
node: decl,
word: decl.value,
}
);
}
defineParamState(
stateName,
paramType,
stateDefault,
mappedStates,
diagnostics,
stateDefinition,
decl
);
}
}
function defineTemplateState(
stateName: string,
templateDef: postcssValueParser.StringNode,
argsFirstNode: (postcssValueParser.Node | undefined)[],
argsFullValue: postcssValueParser.Node[][],
mappedStates: MappedStates,
diagnostics: Diagnostics,
decl: postcss.Declaration
) {
const template = stripQuotation(postcssValueParser.stringify(templateDef));
if (argsFullValue.length === 1) {
// simple template with no params
mappedStates[stateName] = template.trim().replace(/\\["']/g, '"');
} else if (argsFullValue.length === 2) {
// single parameter template
if (!template.includes('$0')) {
diagnostics.report(stateDiagnostics.TEMPLATE_MISSING_PLACEHOLDER(stateName, template), {
node: decl,
word: template,
});
}
const paramType = stateDefinition.nodes[0];
const stateType: StateParsedValue = {
type: paramType.value,
arguments: [],
defaultValue: postcssValueParser
.stringify(stateDefault as postcssValueParser.Node[])
.trim(),
};
const paramFullDef = argsFullValue[1];
const paramTypeDef = argsFirstNode[1];
if (!paramTypeDef) {
diagnostics.report(stateDiagnostics.TEMPLATE_MISSING_PARAMETER(stateName), {
node: decl,
});
return;
}
const param = createStateParamDef(
stateName + ' parameter',
paramTypeDef,
paramFullDef.splice(paramFullDef.indexOf(paramTypeDef) + 1),
diagnostics,
decl
);
if (!param) {
// UNKNOWN_STATE_TYPE reported in createStateParamDef
return;
}
if (isCustomMapping(stateDefinition)) {
mappedStates[stateDefinition.value] = stateType.type.trim().replace(/\\["']/g, '"');
} else if (typeof stateType === 'object' && stateType.type === 'boolean') {
const templateStateType: TemplateStateParsedValue = {
type: 'template',
template,
params: [param],
};
mappedStates[stateName] = templateStateType;
} else {
// unsupported multiple params
diagnostics.report(stateDiagnostics.TEMPLATE_MULTI_PARAMETERS(stateName), {
node: decl,
});
}
}
function defineParamState(
stateName: string,
paramType: postcssValueParser.Node,
stateDefault: ParsedValue[],
mappedStates: MappedStates,
diagnostics: Diagnostics,
stateDefinition: FunctionNode,
decl: postcss.Declaration
) {
if (paramType.value === 'boolean') {
// explicit boolean // ToDo: remove support
resolveBooleanState(mappedStates, stateDefinition);
return;
} else if (paramType.type === 'function' && stateType.type in systemValidators) {
if (paramType.nodes.length > 0) {
resolveArguments(paramType, stateType, stateDefinition.value, diagnostics, decl);
} else {
const stateParamDef = createStateParamDef(
stateName,
paramType,
stateDefault,
diagnostics,
decl
);
if (stateParamDef) {
mappedStates[stateName] = stateParamDef;
}
mappedStates[stateDefinition.value] = stateType;
} else if (stateType.type in systemValidators) {
mappedStates[stateDefinition.value] = stateType;
}
}
function createStateParamDef(
stateName: string,
typeDef: postcssValueParser.Node,
stateDefault: ParsedValue[],
diagnostics: Diagnostics,
decl: postcss.Declaration
): StateParsedValue | undefined {
const type = typeDef.value;
if (type in systemValidators && (typeDef.type === 'function' || typeDef.type === 'word')) {
const stateType: StateParsedValue = {
type,
arguments: [],
defaultValue: postcssValueParser
.stringify(stateDefault as postcssValueParser.Node[])
.trim(),
};
if (typeDef.type === 'function' && typeDef.nodes.length > 0) {
resolveArguments(typeDef, stateType, stateName, diagnostics, decl);
}
return stateType;
} else {
diagnostics.report(
stateDiagnostics.UNKNOWN_STATE_TYPE(stateDefinition.value, paramType.value),
{
node: decl,
word: paramType.value,
const srcValue = postcssValueParser.stringify(typeDef);
diagnostics.report(stateDiagnostics.UNKNOWN_STATE_TYPE(stateName, srcValue), {
node: decl,
word: srcValue,
});
return;
}
}
function collectStateArgsDef(nodes: ValueNode[]) {
const argsFullValue: ValueNode[][] = [];
const argsFirstNode: Array<ValueNode | undefined> = [];
let collectedArg: ValueNode[] = [];
let firstActualValue: ValueNode | undefined = undefined;
for (const node of nodes) {
if (node.type === 'div') {
argsFullValue.push(collectedArg);
argsFirstNode.push(firstActualValue);
collectedArg = [];
firstActualValue = undefined;
} else {
collectedArg.push(node);
if (!firstActualValue && node.type !== 'space' && node.type !== 'comment') {
firstActualValue = node;
}
);
}
}
if (collectedArg.length) {
argsFullValue.push(collectedArg);
argsFirstNode.push(firstActualValue);
}
const paramType = argsFirstNode[0];
return { paramType, argsFullValue, argsFirstNode };
}
function isCustomMapping(stateDefinition: ParsedValue) {
return stateDefinition.nodes.length === 1 && stateDefinition.nodes[0].type === 'string';
}
function resolveArguments(

@@ -527,6 +724,7 @@ paramType: ParsedValue,

if (state && typeof state === 'object') {
const stateParam = isTemplateState(state) ? state.params[0] : state;
const { errors } = validateStateArgument(
state,
stateParam,
meta,
state.defaultValue || '',
stateParam.defaultValue || '',
resolver,

@@ -536,3 +734,3 @@ diagnostics,

true,
!!state.defaultValue
!!stateParam.defaultValue
);

@@ -545,3 +743,3 @@ if (errors) {

stateName,
state.defaultValue || '',
stateParam.defaultValue || '',
errors

@@ -620,10 +818,18 @@ ),

convertToClass(node).value = createBooleanStateClassName(name, namespace);
delete node.nodes;
} else if (typeof stateDef === 'string') {
// simply concat global mapped selector - ToDo: maybe change to 'selector'
convertToInvalid(node).value = stateDef;
delete node.nodes;
} else if (typeof stateDef === 'object') {
resolveStateValue(meta, resolver, diagnostics, rule, node, stateDef, name, namespace);
if (isTemplateState(stateDef)) {
convertTemplateState(meta, resolver, diagnostics, rule, node, stateDef, name);
} else {
resolveStateValue(meta, resolver, diagnostics, rule, node, stateDef, name, namespace);
}
}
delete node.nodes;
}
export function isTemplateState(state: MappedStates[string]): state is TemplateStateParsedValue {
return !!state && typeof state === 'object' && state.type === 'template';
}

@@ -651,4 +857,35 @@ export function createBooleanStateClassName(stateName: string, namespace: string) {

}
function convertTemplateState(
meta: StylableMeta,
resolver: StylableResolver,
diagnostics: Diagnostics,
rule: postcss.Rule | undefined,
node: PseudoClass,
stateParamDef: TemplateStateParsedValue,
name: string
) {
const paramStateDef = stateParamDef.params[0];
const resolvedParam = getParamInput(
meta,
resolver,
diagnostics,
rule,
node,
paramStateDef,
name
);
function resolveStateValue(
validateParam(meta, resolver, diagnostics, rule, paramStateDef, resolvedParam, name);
const strippedParam = stripQuotation(resolvedParam);
transformMappedStateWithParam({
stateName: name,
template: stateParamDef.template,
param: strippedParam,
node,
rule,
diagnostics,
});
}
function getParamInput(
meta: StylableMeta,

@@ -659,8 +896,7 @@ resolver: StylableResolver,

node: PseudoClass,
stateDef: StateParsedValue,
name: string,
namespace: string
stateParamDef: StateParsedValue,
name: string
) {
const inputValue = node.nodes && node.nodes.length ? stringifySelector(node.nodes) : ``;
let actualParam = resolveParam(
const resolvedParam = resolveParam(
meta,

@@ -670,7 +906,7 @@ resolver,

rule,
inputValue ? inputValue : stateDef.defaultValue
inputValue ? inputValue : stateParamDef.defaultValue
);
if (rule && !inputValue && !stateDef.defaultValue) {
diagnostics.report(stateDiagnostics.NO_STATE_ARGUMENT_GIVEN(name, stateDef.type), {
if (rule && !inputValue && !stateParamDef.defaultValue) {
diagnostics.report(stateDiagnostics.NO_STATE_ARGUMENT_GIVEN(name, stateParamDef.type), {
node: rule,

@@ -680,10 +916,20 @@ word: name,

}
return resolvedParam;
}
function validateParam(
meta: StylableMeta,
resolver: StylableResolver,
diagnostics: Diagnostics,
rule: postcss.Rule | undefined,
stateParamDef: StateParsedValue,
resolvedParam: string,
name: string
) {
const validator = systemValidators[stateParamDef.type];
const validator = systemValidators[stateDef.type];
let stateParamOutput: StateResult | undefined;
try {
stateParamOutput = validator.validate(
actualParam,
stateDef.arguments,
resolvedParam,
stateParamDef.arguments,
resolveParam.bind(null, meta, resolver, diagnostics, rule),

@@ -698,4 +944,4 @@ false,

if (stateParamOutput !== undefined) {
if (stateParamOutput.res !== actualParam) {
actualParam = stateParamOutput.res;
if (stateParamOutput.res !== resolvedParam) {
resolvedParam = stateParamOutput.res;
}

@@ -707,3 +953,3 @@

name,
actualParam,
resolvedParam,
stateParamOutput.errors

@@ -713,3 +959,3 @@ ),

node: rule,
word: actualParam,
word: resolvedParam,
}

@@ -719,7 +965,107 @@ );

}
}
function resolveStateValue(
meta: StylableMeta,
resolver: StylableResolver,
diagnostics: Diagnostics,
rule: postcss.Rule | undefined,
node: PseudoClass,
stateParamDef: StateParsedValue,
name: string,
namespace: string
) {
const resolvedParam = getParamInput(
meta,
resolver,
diagnostics,
rule,
node,
stateParamDef,
name
);
const strippedParam = stripQuotation(actualParam);
validateParam(meta, resolver, diagnostics, rule, stateParamDef, resolvedParam, name);
const strippedParam = stripQuotation(resolvedParam);
convertToClass(node).value = createStateWithParamClassName(name, namespace, strippedParam);
delete node.nodes;
}
function transformMappedStateWithParam({
stateName,
template,
param,
node,
rule,
diagnostics,
}: {
stateName: string;
template: string;
param: string;
node: PseudoClass;
rule?: postcss.Rule;
diagnostics: Diagnostics;
}) {
const targetSelectorStr = template.replace(/\$0/g, param);
const selectorAst = parseSelectorWithCache(targetSelectorStr, { clone: true });
if (selectorAst.length > 1) {
if (rule) {
diagnostics.report(
stateDiagnostics.UNSUPPORTED_MULTI_SELECTOR(stateName, targetSelectorStr),
{
node: rule,
}
);
}
return;
} else {
const firstSelector = selectorAst[0].nodes.find(({ type }) => type !== 'comment');
if (firstSelector?.type === 'type' || firstSelector?.type === 'universal') {
if (rule) {
diagnostics.report(
stateDiagnostics.UNSUPPORTED_INITIAL_SELECTOR(stateName, targetSelectorStr),
{
node: rule,
}
);
}
return;
}
let unexpectedSelector: undefined | SelectorNode = undefined;
for (const node of selectorAst[0].nodes) {
if (node.type === 'combinator' || node.type === 'invalid') {
unexpectedSelector = node;
break;
}
}
if (unexpectedSelector) {
if (rule) {
switch (unexpectedSelector.type) {
case 'combinator':
diagnostics.report(
stateDiagnostics.UNSUPPORTED_COMPLEX_SELECTOR(
stateName,
targetSelectorStr
),
{
node: rule,
}
);
break;
case 'invalid':
diagnostics.report(
stateDiagnostics.INVALID_SELECTOR(stateName, targetSelectorStr),
{
node: rule,
}
);
break;
}
}
return;
}
}
convertToSelector(node).nodes = selectorAst[0].nodes;
}
function resolveParam(

@@ -726,0 +1072,0 @@ meta: StylableMeta,

@@ -13,3 +13,3 @@ export { safeParse } from './parser';

export { STSymbol, STGlobal, STCustomSelector, STCustomState, CSSCustomProperty } from './features';
export type { MappedStates, StateParsedValue } from './helpers/custom-state';
export type { MappedStates, StateParsedValue, TemplateStateParsedValue } from './helpers/custom-state';
export { murmurhash3_32_gc } from './murmurhash';

@@ -16,0 +16,0 @@ export { cssParse } from './parser';

@@ -35,4 +35,12 @@ import path from 'path';

export function makeAbsolute(resourcePath: string, rootContext: string, moduleContext: string) {
const isAbs = path.isAbsolute(resourcePath);
export function makeAbsolute(
host: {
join: (...paths: string[]) => string;
isAbsolute: (path: string) => boolean;
},
resourcePath: string,
rootContext: string,
moduleContext: string
) {
const isAbs = host.isAbsolute(resourcePath);
let abs: string;

@@ -42,7 +50,7 @@ if (isExternal(resourcePath) || resourcePath.startsWith('~')) {

} else if (isAbs && resourcePath.startsWith('/')) {
abs = path.join(rootContext, resourcePath);
abs = host.join(rootContext, resourcePath);
} else if (isAbs) {
abs = resourcePath;
} else {
abs = path.join(moduleContext, resourcePath);
abs = host.join(moduleContext, resourcePath);
}

@@ -49,0 +57,0 @@ return abs;

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