@linaria/react
Version:
Blazing fast zero-runtime CSS in JS library
310 lines (309 loc) • 11.2 kB
JavaScript
"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