@navikt/aksel
Version:
Aksel command line interface. Codemods and other utilities for Aksel users.
219 lines (218 loc) • 9.72 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = transformer;
const lineterminator_1 = require("../../../utils/lineterminator");
const headingSizeMap = {
small: "xsmall",
medium: "small",
large: "medium",
};
const bodySizeMap = {
small: "small",
medium: "medium",
large: "large",
};
const boxMarginMap = {
small: "space-12",
medium: "space-16",
large: "space-16",
};
function transformer(file, api) {
var _a;
const j = api.jscodeshift;
const root = j(file.source);
let localListName = "List";
let hasListImport = false;
let dsReactImportPath = null;
let localHeadingName = "Heading";
let hasHeadingImport = false;
let localBodyShortName = "BodyShort";
let hasBodyShortImport = false;
let localBoxName = "Box";
let hasBoxImport = false;
// Find the local name for List import
root.find(j.ImportDeclaration).forEach((path) => {
var _a, _b;
if (path.node.source.value === "@navikt/ds-react") {
dsReactImportPath = path;
(_a = path.node.specifiers) === null || _a === void 0 ? void 0 : _a.forEach((specifier) => {
var _a, _b, _c, _d;
if (specifier.type === "ImportSpecifier") {
if (specifier.imported.name === "List") {
localListName = ((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) || "List";
hasListImport = true;
}
if (specifier.imported.name === "Heading") {
localHeadingName = ((_b = specifier.local) === null || _b === void 0 ? void 0 : _b.name) || "Heading";
hasHeadingImport = true;
}
if (specifier.imported.name === "BodyShort") {
localBodyShortName = ((_c = specifier.local) === null || _c === void 0 ? void 0 : _c.name) || "BodyShort";
hasBodyShortImport = true;
}
if (specifier.imported.name === "Box") {
localBoxName = ((_d = specifier.local) === null || _d === void 0 ? void 0 : _d.name) || "Box";
hasBoxImport = true;
}
}
});
}
else if (path.node.source.value === "@navikt/ds-react/List") {
(_b = path.node.specifiers) === null || _b === void 0 ? void 0 : _b.forEach((specifier) => {
var _a;
if (specifier.type === "ImportSpecifier") {
if (specifier.imported.name === "List") {
localListName = ((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) || "List";
hasListImport = true;
}
}
});
}
});
if (!hasListImport) {
return root.toSource((0, lineterminator_1.getLineTerminator)(file.source));
}
const newImports = new Set();
root
.find(j.JSXElement, {
openingElement: { name: { name: localListName } },
})
.forEach((path) => {
var _a, _b;
const attributes = path.node.openingElement.attributes;
const titleAttr = attributes.find((attr) => attr.type === "JSXAttribute" && attr.name.name === "title");
const descAttr = attributes.find((attr) => attr.type === "JSXAttribute" && attr.name.name === "description");
if (attributes.some((attr) => attr.type === "JSXAttribute" &&
attr.name.name === "data-aksel-migrated-v8")) {
return;
}
const headingTagAttr = attributes.find((attr) => attr.type === "JSXAttribute" && attr.name.name === "headingTag");
const sizeAttr = attributes.find((attr) => attr.type === "JSXAttribute" && attr.name.name === "size");
// Extract values
const titleValue = titleAttr === null || titleAttr === void 0 ? void 0 : titleAttr.value;
const descValue = descAttr === null || descAttr === void 0 ? void 0 : descAttr.value;
let sizeValue = "medium";
if (sizeAttr && ((_a = sizeAttr.value) === null || _a === void 0 ? void 0 : _a.type) === "StringLiteral") {
sizeValue = sizeAttr.value.value;
}
let headingAs = "h3";
if (headingTagAttr && ((_b = headingTagAttr.value) === null || _b === void 0 ? void 0 : _b.type) === "StringLiteral") {
headingAs = headingTagAttr.value.value;
}
// Separate attributes
const listAttributes = [
j.jsxAttribute(j.jsxIdentifier("data-aksel-migrated-v8")),
];
const divAttributes = [];
attributes.forEach((attr) => {
if (attr.type !== "JSXAttribute") {
// Spread attributes or others -> move to div
divAttributes.push(attr);
return;
}
const name = attr.name.name;
if (name === "title" ||
name === "description" ||
name === "headingTag") {
// Handled separately
return;
}
if (name === "size" ||
name === "as" ||
name === "aria-label" ||
name === "aria-labelledby") {
listAttributes.push(attr);
}
else {
divAttributes.push(attr);
}
});
const newNodes = [];
// Create Heading
if (titleValue) {
if (!hasHeadingImport) {
newImports.add("Heading");
}
const headingAttrs = [
j.jsxAttribute(j.jsxIdentifier("as"), j.stringLiteral(headingAs)),
];
const mappedSize = headingSizeMap[sizeValue];
if (mappedSize) {
headingAttrs.push(j.jsxAttribute(j.jsxIdentifier("size"), j.stringLiteral(mappedSize)));
}
let children = [];
if (titleValue.type === "StringLiteral") {
children = [j.jsxText(titleValue.value)];
}
else if (titleValue.type === "JSXExpressionContainer") {
children = [titleValue];
}
const heading = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier(localHeadingName), headingAttrs), j.jsxClosingElement(j.jsxIdentifier(localHeadingName)), children);
newNodes.push(heading);
}
// Create BodyShort
if (descValue) {
if (!hasBodyShortImport) {
newImports.add("BodyShort");
}
const bodyAttrs = [];
const mappedSize = bodySizeMap[sizeValue];
if (mappedSize && mappedSize !== "medium") {
bodyAttrs.push(j.jsxAttribute(j.jsxIdentifier("size"), j.stringLiteral(mappedSize)));
}
let children = [];
if (descValue.type === "StringLiteral") {
children = [j.jsxText(descValue.value)];
}
else if (descValue.type === "JSXExpressionContainer") {
children = [descValue];
}
const body = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier(localBodyShortName), bodyAttrs), j.jsxClosingElement(j.jsxIdentifier(localBodyShortName)), children);
newNodes.push(body);
}
// Create Box
if (!hasBoxImport) {
newImports.add("Box");
}
const boxAttrs = [
j.jsxAttribute(j.jsxIdentifier("marginBlock"), j.stringLiteral(boxMarginMap[sizeValue] || "space-16")),
j.jsxAttribute(j.jsxIdentifier("asChild")),
];
// Reconstruct List element
const newList = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier(localListName), listAttributes), path.node.closingElement, path.node.children);
const box = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier(localBoxName), boxAttrs), j.jsxClosingElement(j.jsxIdentifier(localBoxName)), [newList]);
newNodes.push(box);
// Wrap in div
if (newNodes.length === 1 && divAttributes.length === 0) {
j(path).replaceWith(newNodes[0]);
}
else {
const div = j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier("div"), divAttributes), j.jsxClosingElement(j.jsxIdentifier("div")), newNodes);
j(path).replaceWith(div);
}
});
// Add imports
if (newImports.size > 0) {
if (dsReactImportPath) {
const existingSpecifiers = new Set((_a = dsReactImportPath.node.specifiers) === null || _a === void 0 ? void 0 : _a.map((specifier) => { var _a; return (_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name; }));
newImports.forEach((imp) => {
var _a;
if (!existingSpecifiers.has(imp)) {
(_a = dsReactImportPath.node.specifiers) === null || _a === void 0 ? void 0 : _a.push(j.importSpecifier(j.identifier(imp)));
}
});
}
else {
const specifiers = Array.from(newImports).map((imp) => j.importSpecifier(j.identifier(imp)));
const newImportDecl = j.importDeclaration(specifiers, j.stringLiteral("@navikt/ds-react"));
const lastImport = root.find(j.ImportDeclaration).at(-1);
if (lastImport.length > 0) {
lastImport.insertAfter(newImportDecl);
}
else {
root.get().node.program.body.unshift(newImportDecl);
}
}
}
return root.toSource((0, lineterminator_1.getLineTerminator)(file.source));
}