@stylable/core
Advanced tools
Comparing version 5.4.1-rc.1 to 5.5.0
@@ -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 |
"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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1215303
21936
0
Updated@tokey/imports-parser@^0.1.2
Updatedpostcss@^8.4.20