UNPKG

@linaria/react

Version:

Blazing fast zero-runtime CSS in JS library

310 lines (309 loc) 11.2 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/processors/styled.ts var styled_exports = {}; __export(styled_exports, { default: () => StyledProcessor }); module.exports = __toCommonJS(styled_exports); var import_fs = require("fs"); var import_path = require("path"); var import_processor_utils = require("@wyw-in-js/processor-utils"); var import_shared = require("@wyw-in-js/shared"); var import_minimatch = require("minimatch"); var import_react_html_attributes = __toESM(require("react-html-attributes")); var import_resolve = require("resolve"); var isNotNull = (x) => x !== null; var allTagsSet = /* @__PURE__ */ new Set([...import_react_html_attributes.default.elements.html, import_react_html_attributes.default.elements.svg]); var singleQuotedStringLiteral = (value) => ({ type: "StringLiteral", value, extra: { rawValue: value, raw: `'${value}'` } }); var StyledProcessor = class extends import_processor_utils.TaggedTemplateProcessor { component; #variableIdx = 0; #variablesCache = /* @__PURE__ */ new Map(); constructor(params, ...args) { (0, import_processor_utils.validateParams)( params, ["callee", "*", "..."], import_processor_utils.TaggedTemplateProcessor.SKIP ); (0, import_processor_utils.validateParams)( params, ["callee", ["call", "member"], ["template", "call"]], "Invalid usage of `styled` tag" ); const [tag, tagOp, template] = params; if (template[0] === "call") { throw import_processor_utils.TaggedTemplateProcessor.SKIP; } super([tag, template], ...args); let component; if (tagOp[0] === "call" && tagOp.length === 2) { const value = tagOp[1]; if (value.kind === import_shared.ValueType.FUNCTION) { component = "FunctionalComponent"; } else if (value.kind === import_shared.ValueType.CONST) { component = typeof value.value === "string" ? value.value : void 0; } else { if (value.importedFrom?.length) { const selfPkg = (0, import_shared.findPackageJSON)(".", this.context.filename); const isSomeMatched = value.importedFrom.some((importedFrom) => { const importedPkg = ( // If package.json is not found, assume it's a local package (0, import_shared.findPackageJSON)(importedFrom, this.context.filename) ?? selfPkg ); if (importedPkg) { const packageJSON = JSON.parse((0, import_fs.readFileSync)(importedPkg, "utf8")); const mask = packageJSON?.linaria?.components; if (importedPkg === selfPkg && mask === void 0) { return true; } if (mask) { const packageDir = (0, import_path.dirname)(importedPkg); const fullMask = (0, import_path.join)(packageDir, mask).replace( /\\/g, import_path.posix.sep ); try { const fileWithComponent = (0, import_resolve.sync)(importedFrom, { basedir: (0, import_path.dirname)(this.context.filename), extensions: this.options.extensions }); return (0, import_minimatch.minimatch)(fileWithComponent, fullMask); } catch (e) { console.warn( `Can't resolve ${importedFrom} from ${this.context.filename}. If ${value.source} is another styled component, it should be resolvable with default Node.js resolver. If it's not, please exclude it from the linaria.components mask in package.json.` ); return false; } } } return false; }); if (!isSomeMatched) { component = { node: value.ex, nonLinaria: true, source: value.source }; } } if (component === void 0) { component = { node: value.ex, source: value.source }; this.dependencies.push(value); } } } if (tagOp[0] === "member") { [, component] = tagOp; } if (!component) { throw new Error("Invalid usage of `styled` tag"); } this.component = component; } get asSelector() { return `.${this.className}`; } get value() { const t = this.astService; const extendsNode = typeof this.component === "string" || this.component.nonLinaria ? null : this.component.node.name; return t.objectExpression([ t.objectProperty( t.stringLiteral("displayName"), t.stringLiteral(this.displayName) ), t.objectProperty( t.stringLiteral("__wyw_meta"), t.objectExpression([ t.objectProperty( t.stringLiteral("className"), t.stringLiteral(this.className) ), t.objectProperty( t.stringLiteral("extends"), extendsNode ? t.callExpression(t.identifier(extendsNode), []) : t.nullLiteral() ) ]) ) ]); } get tagExpression() { const t = this.astService; return t.callExpression(this.callee, [this.tagExpressionArgument]); } get tagExpressionArgument() { const t = this.astService; if (typeof this.component === "string") { if (this.component === "FunctionalComponent") { return t.arrowFunctionExpression([], t.blockStatement([])); } return singleQuotedStringLiteral(this.component); } return t.callExpression(t.identifier(this.component.node.name), []); } addInterpolation(node, precedingCss, source, unit = "") { const id = this.getVariableId(source, unit, precedingCss); this.interpolations.push({ id, node, source, unit }); return id; } doEvaltimeReplacement() { this.replacer(this.value, false); } doRuntimeReplacement() { const t = this.astService; const props = this.getProps(); this.replacer( t.callExpression(this.tagExpression, [this.getTagComponentProps(props)]), true ); } extractRules(valueCache, cssText, loc) { const rules = {}; let selector = `.${this.className}`; let value = typeof this.component === "string" || this.component.nonLinaria ? null : valueCache.get(this.component.node.name); while ((0, import_shared.hasEvalMeta)(value)) { selector += `.${value.__wyw_meta.className}`; value = value.__wyw_meta.extends; } rules[selector] = { cssText, className: this.className, displayName: this.displayName, start: loc?.start ?? null }; return rules; } toString() { const res = (arg) => `${this.tagSourceCode()}(${arg})\`\u2026\``; if (typeof this.component === "string") { if (this.component === "FunctionalComponent") { return res("() => {\u2026}"); } return res(`'${this.component}'`); } return res(this.component.source); } getCustomVariableId(source, unit, precedingCss) { const context = this.getVariableContext(source, unit, precedingCss); const customSlugFn = this.options.variableNameSlug; if (!customSlugFn) { return void 0; } return typeof customSlugFn === "function" ? customSlugFn(context) : (0, import_processor_utils.buildSlug)(customSlugFn, { ...context }); } getProps() { const propsObj = { name: this.displayName, class: this.className, propsAsIs: typeof this.component !== "string" || !allTagsSet.has(this.component) }; if (this.interpolations.length) { propsObj.vars = {}; this.interpolations.forEach(({ id, unit, node }) => { const items = [this.astService.callExpression(node, [])]; if (unit) { items.push(this.astService.stringLiteral(unit)); } propsObj.vars[id] = items; }); } return propsObj; } getTagComponentProps(props) { const t = this.astService; const propExpressions = Object.entries(props).map(([key, value]) => { if (value === void 0) { return null; } const keyNode = t.identifier(key); if (value === null) { return t.objectProperty(keyNode, t.nullLiteral()); } if (typeof value === "string") { return t.objectProperty(keyNode, t.stringLiteral(value)); } if (typeof value === "boolean") { return t.objectProperty(keyNode, t.booleanLiteral(value)); } const vars = Object.entries(value).map(([propName, propValue]) => { return t.objectProperty( t.stringLiteral(propName), t.arrayExpression(propValue) ); }); return t.objectProperty(keyNode, t.objectExpression(vars)); }).filter(isNotNull); return t.objectExpression(propExpressions); } getVariableContext(source, unit, precedingCss) { const getIndex = () => { return this.#variableIdx++; }; return { componentName: this.displayName, componentSlug: this.slug, get index() { return getIndex(); }, precedingCss, processor: this.constructor.name, source, unit, valueSlug: (0, import_shared.slugify)(source + unit) }; } getVariableId(source, unit, precedingCss) { const value = source + unit; if (!this.#variablesCache.has(value)) { const id = this.getCustomVariableId(source, unit, precedingCss); if (id) { return (0, import_processor_utils.toValidCSSIdentifier)(id); } const context = this.getVariableContext(source, unit, precedingCss); this.#variablesCache.set(value, `${this.slug}-${context.index}`); } return this.#variablesCache.get(value); } }; //# sourceMappingURL=styled.js.map