@storybook/codemod
Version:
A collection of codemod scripts written with JSCodeshift
396 lines (387 loc) • 18.4 kB
JavaScript
import CJS_COMPAT_NODE_URL_9127jrv5ql from 'node:url';
import CJS_COMPAT_NODE_PATH_9127jrv5ql from 'node:path';
import CJS_COMPAT_NODE_MODULE_9127jrv5ql from "node:module";
var __filename = CJS_COMPAT_NODE_URL_9127jrv5ql.fileURLToPath(import.meta.url);
var __dirname = CJS_COMPAT_NODE_PATH_9127jrv5ql.dirname(__filename);
var require = CJS_COMPAT_NODE_MODULE_9127jrv5ql.createRequire(import.meta.url);
// ------------------------------------------------------------
// end of CJS compatibility banner, injected by Storybook's esbuild configuration
// ------------------------------------------------------------
// src/index.ts
import { readdirSync } from "node:fs";
import { rename as renameAsync } from "node:fs/promises";
import { extname as extname2, join as join2 } from "node:path";
import { resolvePackageDir } from "storybook/internal/common";
import { sync as spawnSync } from "cross-spawn";
// ../../../node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs
var _lazyMatch = () => {
var __lib__ = (() => {
var m = Object.defineProperty, V = Object.getOwnPropertyDescriptor, G = Object.getOwnPropertyNames, T = Object.prototype.hasOwnProperty, q = (r, e) => {
for (var n in e) m(r, n, { get: e[n], enumerable: !0 });
}, H = (r, e, n, a) => {
if (e && typeof e == "object" || typeof e == "function") for (let t of G(e)) !T.call(r, t) && t !== n && m(r, t, { get: () => e[t], enumerable: !(a = V(e, t)) || a.enumerable });
return r;
}, J = (r) => H(m({}, "__esModule", { value: !0 }), r), w = {};
q(w, { default: () => re });
var A = (r) => Array.isArray(r), d = (r) => typeof r == "function", Q = (r) => r.length === 0, W = (r) => typeof r == "number", K = (r) => typeof r == "object" && r !== null, X = (r) => r instanceof RegExp, b = (r) => typeof r == "string", h = (r) => r === void 0, Y = (r) => {
let e = /* @__PURE__ */ new Map();
return (n) => {
let a = e.get(n);
if (a) return a;
let t = r(n);
return e.set(n, t), t;
};
}, rr = (r, e, n = {}) => {
let a = { cache: {}, input: r, index: 0, indexMax: 0, options: n, output: [] };
if (v(e)(a) && a.index === r.length) return a.output;
throw new Error(`Failed to parse at index ${a.indexMax}`);
}, i = (r, e) => A(r) ? er(r, e) : b(r) ? ar(r, e) : nr(r, e), er = (r, e) => {
let n = {};
for (let a of r) {
if (a.length !== 1) throw new Error(`Invalid character: "${a}"`);
let t = a.charCodeAt(0);
n[t] = !0;
}
return (a) => {
let t = a.index, o = a.input;
for (; a.index < o.length && o.charCodeAt(a.index) in n; ) a.index += 1;
let u = a.index;
if (u > t) {
if (!h(e) && !a.options.silent) {
let s = a.input.slice(t, u), c = d(e) ? e(s, o, String(t)) : e;
h(c) || a.output.push(c);
}
a.indexMax = Math.max(a.indexMax, a.index);
}
return !0;
};
}, nr = (r, e) => {
let n = r.source, a = r.flags.replace(/y|$/, "y"), t = new RegExp(n, a);
return g((o) => {
t.lastIndex = o.index;
let u = t.exec(o.input);
if (u) {
if (!h(e) && !o.options.silent) {
let s = d(e) ? e(...u, o.input, String(o.index)) : e;
h(s) || o.output.push(s);
}
return o.index += u[0].length, o.indexMax = Math.max(o.indexMax, o.index), !0;
} else return !1;
});
}, ar = (r, e) => (n) => {
if (n.input.startsWith(r, n.index)) {
if (!h(e) && !n.options.silent) {
let t = d(e) ? e(r, n.input, String(n.index)) : e;
h(t) || n.output.push(t);
}
return n.index += r.length, n.indexMax = Math.max(n.indexMax, n.index), !0;
} else return !1;
}, C = (r, e, n, a) => {
let t = v(r);
return g(_(M((o) => {
let u = 0;
for (; u < n; ) {
let s = o.index;
if (!t(o) || (u += 1, o.index === s)) break;
}
return u >= e;
})));
}, tr = (r, e) => C(r, 0, 1), f = (r, e) => C(r, 0, 1 / 0), x = (r, e) => {
let n = r.map(v);
return g(_(M((a) => {
for (let t = 0, o = n.length; t < o; t++) if (!n[t](a)) return !1;
return !0;
})));
}, l = (r, e) => {
let n = r.map(v);
return g(_((a) => {
for (let t = 0, o = n.length; t < o; t++) if (n[t](a)) return !0;
return !1;
}));
}, M = (r, e = !1) => {
let n = v(r);
return (a) => {
let t = a.index, o = a.output.length, u = n(a);
return (!u || e) && (a.index = t, a.output.length !== o && (a.output.length = o)), u;
};
}, _ = (r, e) => v(r), g = /* @__PURE__ */ (() => {
let r = 0;
return (e) => {
let n = v(e), a = r += 1;
return (t) => {
var o;
if (t.options.memoization === !1) return n(t);
let u = t.index, s = (o = t.cache)[a] || (o[a] = /* @__PURE__ */ new Map()), c = s.get(u);
if (c === !1) return !1;
if (W(c)) return t.index = c, !0;
if (c) return t.index = c.index, c.output?.length && t.output.push(...c.output), !0;
{
let Z = t.output.length;
if (n(t)) {
let D = t.index, U = t.output.length;
if (U > Z) {
let ee = t.output.slice(Z, U);
s.set(u, { index: D, output: ee });
} else s.set(u, D);
return !0;
} else return s.set(u, !1), !1;
}
};
};
})(), E = (r) => {
let e;
return (n) => (e || (e = v(r())), e(n));
}, v = Y((r) => {
if (d(r)) return Q(r) ? E(r) : r;
if (b(r) || X(r)) return i(r);
if (A(r)) return x(r);
if (K(r)) return l(Object.values(r));
throw new Error("Invalid rule");
}), P = "abcdefghijklmnopqrstuvwxyz", ir = (r) => {
let e = "";
for (; r > 0; ) {
let n = (r - 1) % 26;
e = P[n] + e, r = Math.floor((r - 1) / 26);
}
return e;
}, O = (r) => {
let e = 0;
for (let n = 0, a = r.length; n < a; n++) e = e * 26 + P.indexOf(r[n]) + 1;
return e;
}, S = (r, e) => {
if (e < r) return S(e, r);
let n = [];
for (; r <= e; ) n.push(r++);
return n;
}, or = (r, e, n) => S(r, e).map((a) => String(a).padStart(n, "0")), R = (r, e) => S(O(r), O(e)).map(ir), p = (r) => r, z = (r) => ur((e) => rr(e, r, { memoization: !1 }).join("")), ur = (r) => {
let e = {};
return (n) => e[n] ?? (e[n] = r(n));
}, sr = i(/^\*\*\/\*$/, ".*"), cr = i(/^\*\*\/(\*)?([ a-zA-Z0-9._-]+)$/, (r, e, n) => `.*${e ? "" : "(?:^|/)"}${n.replaceAll(".", "\\.")}`), lr = i(/^\*\*\/(\*)?([ a-zA-Z0-9._-]*)\{([ a-zA-Z0-9._-]+(?:,[ a-zA-Z0-9._-]+)*)\}$/, (r, e, n, a) => `.*${e ? "" : "(?:^|/)"}${n.replaceAll(".", "\\.")}(?:${a.replaceAll(",", "|").replaceAll(".", "\\.")})`), y = i(/\\./, p), pr = i(/[$.*+?^(){}[\]\|]/, (r) => `\\${r}`), vr = i(/./, p), hr = i(/^(?:!!)*!(.*)$/, (r, e) => `(?!^${L(e)}$).*?`), dr = i(/^(!!)+/, ""), fr = l([hr, dr]), xr = i(/\/(\*\*\/)+/, "(?:/.+/|/)"), gr = i(/^(\*\*\/)+/, "(?:^|.*/)"), mr = i(/\/(\*\*)$/, "(?:/.*|$)"), _r = i(/\*\*/, ".*"), j = l([xr, gr, mr, _r]), Sr = i(/\*\/(?!\*\*\/)/, "[^/]*/"), yr = i(/\*/, "[^/]*"), N = l([Sr, yr]), k = i("?", "[^/]"), $r = i("[", p), wr = i("]", p), Ar = i(/[!^]/, "^/"), br = i(/[a-z]-[a-z]|[0-9]-[0-9]/i, p), Cr = i(/[$.*+?^(){}[\|]/, (r) => `\\${r}`), Mr = i(/[^\]]/, p), Er = l([y, Cr, br, Mr]), B = x([$r, tr(Ar), f(Er), wr]), Pr = i("{", "(?:"), Or = i("}", ")"), Rr = i(/(\d+)\.\.(\d+)/, (r, e, n) => or(+e, +n, Math.min(e.length, n.length)).join("|")), zr = i(/([a-z]+)\.\.([a-z]+)/, (r, e, n) => R(e, n).join("|")), jr = i(/([A-Z]+)\.\.([A-Z]+)/, (r, e, n) => R(e.toLowerCase(), n.toLowerCase()).join("|").toUpperCase()), Nr = l([Rr, zr, jr]), I = x([Pr, Nr, Or]), kr = i("{", "(?:"), Br = i("}", ")"), Ir = i(",", "|"), Fr = i(/[$.*+?^(){[\]\|]/, (r) => `\\${r}`), Lr = i(/[^}]/, p), Zr = E(() => F), Dr = l([j, N, k, B, I, Zr, y, Fr, Ir, Lr]), F = x([kr, f(Dr), Br]), Ur = f(l([sr, cr, lr, fr, j, N, k, B, I, F, y, pr, vr])), Vr = Ur, Gr = z(Vr), L = Gr, Tr = i(/\\./, p), qr = i(/./, p), Hr = i(/\*\*\*+/, "*"), Jr = i(/([^/{[(!])\*\*/, (r, e) => `${e}*`), Qr = i(/(^|.)\*\*(?=[^*/)\]}])/, (r, e) => `${e}*`), Wr = f(l([Tr, Hr, Jr, Qr, qr])), Kr = Wr, Xr = z(Kr), Yr = Xr, $ = (r, e) => {
let n = Array.isArray(r) ? r : [r];
if (!n.length) return !1;
let a = n.map($.compile), t = n.every((s) => /(\/(?:\*\*)?|\[\/\])$/.test(s)), o = e.replace(/[\\\/]+/g, "/").replace(/\/$/, t ? "/" : "");
return a.some((s) => s.test(o));
};
$.compile = (r) => new RegExp(`^${L(Yr(r))}$`, "s");
var re = $;
return J(w);
})();
return __lib__.default || __lib__;
}, _match, zeptomatch = (path, pattern) => (_match || (_match = _lazyMatch(), _lazyMatch = null), _match(path, pattern)), _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
function normalizeWindowsPath(input = "") {
return input && input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
}
var _UNC_REGEX = /^[/\\]{2}/, _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/, _DRIVE_LETTER_RE = /^[A-Za-z]:$/, _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/, _EXTNAME_RE = /.(\.[^./]+|\.)$/, _PATH_ROOT_RE = /^[/\\]|^[a-zA-Z]:[/\\]/, sep = "/", normalize = function(path) {
if (path.length === 0)
return ".";
path = normalizeWindowsPath(path);
let isUNCPath = path.match(_UNC_REGEX), isPathAbsolute = isAbsolute(path), trailingSeparator = path[path.length - 1] === "/";
return path = normalizeString(path, !isPathAbsolute), path.length === 0 ? isPathAbsolute ? "/" : trailingSeparator ? "./" : "." : (trailingSeparator && (path += "/"), _DRIVE_LETTER_RE.test(path) && (path += "/"), isUNCPath ? isPathAbsolute ? `//${path}` : `//./${path}` : isPathAbsolute && !isAbsolute(path) ? `/${path}` : path);
}, join = function(...segments) {
let path = "";
for (let seg of segments)
if (seg)
if (path.length > 0) {
let pathTrailing = path[path.length - 1] === "/", segLeading = seg[0] === "/";
pathTrailing && segLeading ? path += seg.slice(1) : path += pathTrailing || segLeading ? seg : `/${seg}`;
} else
path += seg;
return normalize(path);
};
function cwd() {
return typeof process < "u" && typeof process.cwd == "function" ? process.cwd().replace(/\\/g, "/") : "/";
}
var resolve = function(...arguments_) {
arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
let resolvedPath = "", resolvedAbsolute = !1;
for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
let path = index >= 0 ? arguments_[index] : cwd();
!path || path.length === 0 || (resolvedPath = `${path}/${resolvedPath}`, resolvedAbsolute = isAbsolute(path));
}
return resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute), resolvedAbsolute && !isAbsolute(resolvedPath) ? `/${resolvedPath}` : resolvedPath.length > 0 ? resolvedPath : ".";
};
function normalizeString(path, allowAboveRoot) {
let res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, char = null;
for (let index = 0; index <= path.length; ++index) {
if (index < path.length)
char = path[index];
else {
if (char === "/")
break;
char = "/";
}
if (char === "/") {
if (!(lastSlash === index - 1 || dots === 1)) if (dots === 2) {
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
if (res.length > 2) {
let lastSlashIndex = res.lastIndexOf("/");
lastSlashIndex === -1 ? (res = "", lastSegmentLength = 0) : (res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/")), lastSlash = index, dots = 0;
continue;
} else if (res.length > 0) {
res = "", lastSegmentLength = 0, lastSlash = index, dots = 0;
continue;
}
}
allowAboveRoot && (res += res.length > 0 ? "/.." : "..", lastSegmentLength = 2);
} else
res.length > 0 ? res += `/${path.slice(lastSlash + 1, index)}` : res = path.slice(lastSlash + 1, index), lastSegmentLength = index - lastSlash - 1;
lastSlash = index, dots = 0;
} else char === "." && dots !== -1 ? ++dots : dots = -1;
}
return res;
}
var isAbsolute = function(p) {
return _IS_ABSOLUTE_RE.test(p);
}, toNamespacedPath = function(p) {
return normalizeWindowsPath(p);
}, extname = function(p) {
if (p === "..") return "";
let match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
return match && match[1] || "";
}, relative = function(from, to) {
let _from = resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/"), _to = resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0])
return _to.join("/");
let _fromCopy = [..._from];
for (let segment of _fromCopy) {
if (_to[0] !== segment)
break;
_from.shift(), _to.shift();
}
return [..._from.map(() => ".."), ..._to].join("/");
}, dirname = function(p) {
let segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
return segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0]) && (segments[0] += "/"), segments.join("/") || (isAbsolute(p) ? "/" : ".");
}, format = function(p) {
let ext = p.ext ? p.ext.startsWith(".") ? p.ext : `.${p.ext}` : "", segments = [p.root, p.dir, p.base ?? (p.name ?? "") + ext].filter(
Boolean
);
return normalizeWindowsPath(
p.root ? resolve(...segments) : segments.join("/")
);
}, basename = function(p, extension) {
let segments = normalizeWindowsPath(p).split("/"), lastSegment = "";
for (let i = segments.length - 1; i >= 0; i--) {
let val = segments[i];
if (val) {
lastSegment = val;
break;
}
}
return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;
}, parse = function(p) {
let root = _PATH_ROOT_RE.exec(p)?.[0]?.replace(/\\/g, "/") || "", base = basename(p), extension = extname(base);
return {
root,
dir: dirname(p),
base,
ext: extension,
name: base.slice(0, base.length - extension.length)
};
}, matchesGlob = (path, pattern) => zeptomatch(pattern, normalize(path)), _path = {
__proto__: null,
basename,
dirname,
extname,
format,
isAbsolute,
join,
matchesGlob,
normalize,
normalizeString,
parse,
relative,
resolve,
sep,
toNamespacedPath
};
// ../../../node_modules/pathe/dist/index.mjs
var delimiter = globalThis.process?.platform === "win32" ? ";" : ":", _platforms = { posix: void 0, win32: void 0 }, mix = (del = delimiter) => new Proxy(_path, {
get(_, prop) {
return prop === "delimiter" ? del : prop === "posix" ? posix : prop === "win32" ? win32 : _platforms[prop] || _path[prop];
}
}), posix = mix(":"), win32 = mix(";");
// src/index.ts
import { glob as tinyglobby } from "tinyglobby";
// src/lib/utils.ts
import { camelCase, upperFirst } from "es-toolkit/string";
function jscodeshiftToPrettierParser(parser) {
let parserMap = {
babylon: "babel",
flow: "flow",
ts: "typescript",
tsx: "typescript"
};
return parser && parserMap[parser] || "babel";
}
// src/index.ts
var TRANSFORM_DIR = join2(resolvePackageDir("@storybook/codemod"), "dist", "transforms");
function listCodemods() {
return readdirSync(TRANSFORM_DIR).filter((fname) => fname.endsWith(".js")).map((fname) => fname.slice(0, -3));
}
async function renameFile(file, from, to, { logger }) {
let newFile = file.replace(from, to);
return logger.log(`Rename: ${file} ${newFile}`), renameAsync(file, newFile);
}
async function runCodemod(codemod, {
glob,
logger,
dryRun,
rename,
parser
}) {
if (!listCodemods().includes(codemod))
throw new Error(`Unknown codemod ${codemod}. Run --list for options.`);
let renameParts = null;
if (rename && (renameParts = rename.split(":"), renameParts.length !== 2))
throw new Error(`Codemod rename: expected format "from:to", got "${rename}"`);
let inferredParser = parser;
if (!parser) {
let extension = extname2(glob).slice(1);
jscodeshiftToPrettierParser(extension) !== "babel" && (inferredParser = extension);
}
let files = await tinyglobby([normalize(glob), "!**/node_modules", "!**/dist"]), extensions = new Set(files.map((file) => extname2(file).slice(1))), commaSeparatedExtensions = Array.from(extensions).join(",");
if (logger.step(`Applying ${codemod}: ${files.length} files`), files.length === 0) {
logger.step(`No matching files for glob: ${glob}`);
return;
}
if (!dryRun && files.length > 0) {
let parserArgs = inferredParser ? ["--parser", inferredParser] : [], result = spawnSync(
"node",
[
join2(resolvePackageDir("jscodeshift"), "bin", "jscodeshift"),
// this makes sure codeshift doesn't transform our own source code with babel
// which is faster, and also makes sure the user won't see babel messages such as:
// [BABEL] Note: The code generator has deoptimised the styling of repo/node_modules/prettier/index.js as it exceeds the max of 500KB.
"--no-babel",
`--extensions=${commaSeparatedExtensions}`,
"--fail-on-error",
"-t",
`${TRANSFORM_DIR}/${codemod}.js`,
...parserArgs,
...files
],
{
stdio: "inherit"
}
);
if (codemod === "mdx-to-csf" && result.status === 1)
logger.log(
"The codemod was not able to transform the files mentioned above. We have renamed the files to .mdx.broken. Please check the files and rename them back to .mdx after you have either manually transformed them to mdx + csf or fixed the issues so that the codemod can transform them."
);
else if (result.status === 1) {
logger.log("Skipped renaming because of errors.");
return;
}
}
if (renameParts) {
let [from, to] = renameParts;
logger.step(`Renaming ${rename}: ${files.length} files`), await Promise.all(
files.map((file) => renameFile(file, new RegExp(`${from}$`), to, { logger }))
);
}
}
export {
listCodemods,
runCodemod
};