tw-merge
Version:
Merge CSS utility classes without style conflicts - small and zero config
157 lines (125 loc) • 3.57 kB
text/typescript
import { CONSTANTS, TOP_CONFLICT_RULE } from "./data";
import { GenerationState } from "./generation-state";
import { GenerateTailwindRuleSetOptions } from "./types";
function orderByPriority(_targets: string[]): string[] {
const targets = [..._targets];
let seenTargets = [];
let i = 0;
while (i < targets.length) {
const target = targets[i] as string;
const seenIndex = seenTargets.findIndex((t) => target.startsWith(t));
if (seenIndex >= 0) {
const [t] = targets.splice(i, 1);
targets.splice(seenIndex, 0, t as string);
return orderByPriority(targets);
}
seenTargets.push(target);
i++;
continue;
}
return targets;
}
function orderSimpleTargets(targets: string[]) {
return orderByPriority(targets.sort());
}
function objectFitPositionToConstantName(value: string) {
return {
fit: "OBJECT_FIT",
position: "BG_AND_OBJECT_POSITION",
}[value];
}
export function generateFile(
state: GenerationState,
{
importPath = "merge-utility",
exportName = "tailwindRuleSet",
}: GenerateTailwindRuleSetOptions
) {
let file = "";
// imports
file += "import {\n RuleSet,\n ";
file += state.imports.join(",\n ");
file += `\n} from '${importPath}'\n`;
// constants
state.constants.forEach((constant) => {
file += `\nconst ${constant} = "${CONSTANTS[constant]}"`;
});
if (state.constants.length > 0) file += "\n";
// header
file += `\nexport const ${exportName}: RuleSet = [`;
// top conflict rules
if (state.topConflictRule.length > 0) {
file += `\n conflictRule({\n`;
state.topConflictRule.forEach((rule) => {
file += ` '${rule}': '${TOP_CONFLICT_RULE[rule]}',\n`;
});
file += ` }),`;
}
// flex direction wrap unique rules
// TODO
// flex basis grow shrink conflict rule
// TODO
// text align size unique rules
// TODO
// bg unique rules
// TODO
// scroll unique rules
// TODO
// top unique rules
if (state.topUniqueRules.length > 0) {
file += "\n ...uniqueRules([";
state.topUniqueRules.forEach((rule) => {
file += `\n ${rule},`;
});
file += "\n ]),";
}
// align content unique rule
// TODO
// list style position unique rule
// TODO
// text decoration style unique rule
// TODO
// border style unique rule
// TODO
// divide style unique rule
// TODO
// outline style unique rule
// TODO
// shadow unique rule
// TODO
// font weight unique rule
// TODO
// top simple rule
if (state.topSimpleRule.length > 0) {
file += "\n simpleRule(";
const targets = orderSimpleTargets(state.topSimpleRule);
file += `\n '${targets.join("|")}'`;
file += "\n ),";
}
// top simple rule by type
if (state.topSimpleRuleByType.length > 0) {
file += "\n simpleRule(";
const targets = orderSimpleTargets(state.topSimpleRuleByType);
file += `\n '${targets.join("|")}'`;
file += "\n ),";
}
// border cardinal rule
// TODO
// xy cardinal rules
if (state.xyCardinalRules.length > 0) {
file += `\n ...cardinalRules('${state.xyCardinalRules.join("|")}'),`;
}
// trbl cardinal rules
// TODO
// object fit position unique rules
if (state.objectFitPositionUniqueRules.length > 0) {
file += `\n ...uniqueRules([${state.objectFitPositionUniqueRules
.map(objectFitPositionToConstantName)
.join(", ")}], { prefix: 'object' }),`;
}
// arbitrary rule
if (state.arbitraryRule) file += "\n arbitraryRule(),";
// footer
file += "\n]\n";
return file;
}