UNPKG

@stylable/core

Version:

CSS for Components

256 lines 9.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StylableResolver = exports.isInPath = exports.resolverWarnings = void 0; const stylable_value_parsers_1 = require("./stylable-value-parsers"); exports.resolverWarnings = { UNKNOWN_IMPORTED_FILE(path) { return `cannot resolve imported file: "${path}"`; }, UNKNOWN_IMPORTED_SYMBOL(name, path) { return `cannot resolve imported symbol "${name}" from stylesheet "${path}"`; }, }; function isInPath(extendPath, { symbol: { name: name1 }, meta: { source: source1 } }) { return extendPath.find(({ symbol: { name }, meta: { source } }) => { return name1 === name && source === source1; }); } exports.isInPath = isInPath; class StylableResolver { constructor(fileProcessor, requireModule) { this.fileProcessor = fileProcessor; this.requireModule = requireModule; } resolveImported(imported, name) { const { context, from } = imported; let symbol; if (from.match(/\.css$/)) { let meta; try { meta = this.fileProcessor.process(from, false, context); symbol = !name ? meta.mappedSymbols[meta.root] : meta.mappedSymbols[name]; } catch (e) { return null; } return { _kind: 'css', symbol, meta }; } else { let _module; try { _module = this.requireModule(this.fileProcessor.resolvePath(from)); } catch { return null; } symbol = !name ? _module.default || _module : _module[name]; return { _kind: 'js', symbol, meta: null }; } } resolveImport(importSymbol) { const name = importSymbol.type === 'named' ? importSymbol.name : ''; return this.resolveImported(importSymbol.import, name); } resolve(maybeImport) { if (!maybeImport || maybeImport._kind !== 'import') { if (maybeImport && maybeImport._kind !== 'var' && maybeImport._kind !== 'cssVar') { if (maybeImport.alias && !maybeImport[stylable_value_parsers_1.valueMapping.extends]) { maybeImport = maybeImport.alias; } else if (maybeImport[stylable_value_parsers_1.valueMapping.extends]) { maybeImport = maybeImport[stylable_value_parsers_1.valueMapping.extends]; } else { return null; } } else { return null; } } if (!maybeImport || maybeImport._kind !== 'import') { return null; } return this.resolveImport(maybeImport); } deepResolve(maybeImport, path = []) { let resolved = this.resolve(maybeImport); while (resolved && resolved._kind === 'css' && resolved.symbol && resolved.symbol._kind === 'import') { resolved = this.resolve(resolved.symbol); } if (resolved && resolved.symbol && resolved.meta && (resolved.symbol._kind === 'class' || resolved.symbol._kind === 'element') && resolved.symbol.alias && !resolved.symbol[stylable_value_parsers_1.valueMapping.extends]) { if (path.includes(resolved.symbol)) { return { _kind: 'css', symbol: resolved.symbol, meta: resolved.meta }; } path.push(resolved.symbol); return this.deepResolve(resolved.symbol.alias, path); } return resolved; } resolveSymbolOrigin(symbol, meta, path = []) { if (!symbol || !meta) { return null; } if (symbol._kind === 'element' || symbol._kind === 'class') { if (path.includes(symbol)) { return { meta, symbol, _kind: 'css' }; } path.push(symbol); const isAliasOnly = symbol.alias && !symbol[stylable_value_parsers_1.valueMapping.extends]; return isAliasOnly ? this.resolveSymbolOrigin(symbol.alias, meta, path) : { meta, symbol, _kind: 'css' }; } else if (symbol._kind === 'cssVar') { if (path.includes(symbol)) { return { meta, symbol, _kind: 'css' }; } } else if (symbol._kind === 'import') { const resolved = this.resolveImport(symbol); if (resolved && resolved.symbol && resolved._kind === 'css') { return this.resolveSymbolOrigin(resolved.symbol, resolved.meta, path); } else { return null; } } return null; } resolveClass(meta, symbol) { return this.resolveName(meta, symbol, false); } resolveName(meta, symbol, isElement) { const type = isElement ? 'element' : 'class'; let finalSymbol; let finalMeta; if (symbol._kind === type) { finalSymbol = symbol; finalMeta = meta; } else if (symbol._kind === 'import') { const resolved = this.deepResolve(symbol); if (resolved && resolved._kind === 'css' && resolved.symbol) { if (resolved.symbol._kind === 'class' || resolved.symbol._kind === 'element') { finalSymbol = resolved.symbol; finalMeta = resolved.meta; } else { // TODO: warn } } else { // TODO: warn } } else { // TODO: warn } if (finalMeta && finalSymbol) { return { _kind: 'css', symbol: finalSymbol, meta: finalMeta, }; } else { return null; } } resolveElement(meta, symbol) { return this.resolveName(meta, symbol, true); } resolveExtends(meta, className, isElement = false, transformer, reportError) { const bucket = isElement ? meta.elements : meta.classes; const customSelector = isElement ? null : meta.customSelectors[':--' + className]; if (!bucket[className] && !customSelector) { return []; } if (customSelector && transformer) { const parsed = transformer.resolveSelectorElements(meta, customSelector); if (parsed.length === 1) { return parsed[0][parsed[0].length - 1].resolved; } else { return []; } } let current = { _kind: 'css', symbol: bucket[className], meta, }; const extendPath = []; while (current === null || current === void 0 ? void 0 : current.symbol) { if (isInPath(extendPath, current)) { break; } extendPath.push(current); const parent = current.symbol[stylable_value_parsers_1.valueMapping.extends] || current.symbol.alias; if (parent) { if (parent._kind === 'import') { const res = this.resolve(parent); if (res && res._kind === 'css' && res.symbol && (res.symbol._kind === 'element' || res.symbol._kind === 'class')) { const { _kind, meta, symbol } = res; current = { _kind, meta, symbol, }; } else { if (reportError) { reportError(res, parent, extendPath, meta, className, isElement); } break; } } else { current = { _kind: 'css', symbol: parent, meta }; } } else { break; } } return extendPath; } validateImports(meta, diagnostics) { for (const importObj of meta.imports) { const resolvedImport = this.resolveImported(importObj, ''); if (!resolvedImport) { // warn about unknown imported files const fromDecl = importObj.rule.nodes && importObj.rule.nodes.find((decl) => decl.type === 'decl' && decl.prop === stylable_value_parsers_1.valueMapping.from); if (fromDecl) { diagnostics.warn(fromDecl, exports.resolverWarnings.UNKNOWN_IMPORTED_FILE(importObj.fromRelative), { word: importObj.fromRelative }); } } else if (resolvedImport._kind === 'css') { // warn about unknown named imported symbols for (const name in importObj.named) { const origName = importObj.named[name]; const resolvedSymbol = this.resolveImported(importObj, origName); const namedDecl = importObj.rule.nodes && importObj.rule.nodes.find((decl) => decl.type === 'decl' && decl.prop === stylable_value_parsers_1.valueMapping.named); if (!resolvedSymbol.symbol && namedDecl) { diagnostics.warn(namedDecl, exports.resolverWarnings.UNKNOWN_IMPORTED_SYMBOL(origName, importObj.fromRelative), { word: origName }); } } } } } } exports.StylableResolver = StylableResolver; //# sourceMappingURL=stylable-resolver.js.map