UNPKG

storybook

Version:

Storybook: Develop, document, and test UI components in isolation

1,207 lines (1,165 loc) • 71.5 kB
import CJS_COMPAT_NODE_URL_ret6ivvuly from 'node:url'; import CJS_COMPAT_NODE_PATH_ret6ivvuly from 'node:path'; import CJS_COMPAT_NODE_MODULE_ret6ivvuly from "node:module"; var __filename = CJS_COMPAT_NODE_URL_ret6ivvuly.fileURLToPath(import.meta.url); var __dirname = CJS_COMPAT_NODE_PATH_ret6ivvuly.dirname(__filename); var require = CJS_COMPAT_NODE_MODULE_ret6ivvuly.createRequire(import.meta.url); // ------------------------------------------------------------ // end of CJS compatibility banner, injected by Storybook's esbuild configuration // ------------------------------------------------------------ import "../../_node-chunks/chunk-4ISTEHCM.js"; import "../../_node-chunks/chunk-CXHD3UA6.js"; import { doesStoryFileExist, fullTestProviderStore, generateStoryFile, getComponentCandidates, getStoryMetadata, getWsToken, parseStaticDir, runStoryTests, sendTelemetryError, throttle, universalTestProviderStore } from "../../_node-chunks/chunk-CUZMMOHY.js"; import "../../_node-chunks/chunk-UQRAUAGM.js"; import "../../_node-chunks/chunk-RYS45SZ5.js"; import "../../_node-chunks/chunk-JM4QTCUN.js"; import "../../_node-chunks/chunk-R3VBEOHQ.js"; import "../../_node-chunks/chunk-3LVSS6GN.js"; import { get, isStoryCreatedByAISetup } from "../../_node-chunks/chunk-UZQ7S6LH.js"; import "../../_node-chunks/chunk-ZJMC6JVU.js"; import { globalSettings } from "../../_node-chunks/chunk-JBJRWIDV.js"; import { invariant } from "../../_node-chunks/chunk-XQ72YXLB.js"; import { resolvePackageDir } from "../../_node-chunks/chunk-UHVMRW65.js"; import "../../_node-chunks/chunk-5L7EORB4.js"; import { isAbsolute, join } from "../../_node-chunks/chunk-TGEJ6REI.js"; import { require_dist } from "../../_node-chunks/chunk-XSYEGQMM.js"; import { require_picocolors } from "../../_node-chunks/chunk-BV5YQP4B.js"; import "../../_node-chunks/chunk-2E2JVUNS.js"; import { __commonJS, __require, __toESM } from "../../_node-chunks/chunk-5IHDTMLC.js"; // ../../node_modules/shell-quote/quote.js var require_quote = __commonJS({ "../../node_modules/shell-quote/quote.js"(exports, module) { "use strict"; module.exports = function(xs) { return xs.map(function(s) { return s === "" ? "''" : s && typeof s == "object" ? s.op.replace(/(.)/g, "\\$1") : /["\s\\]/.test(s) && !/'/.test(s) ? "'" + s.replace(/(['])/g, "\\$1") + "'" : /["'\s]/.test(s) ? '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"' : String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2"); }).join(" "); }; } }); // ../../node_modules/shell-quote/parse.js var require_parse = __commonJS({ "../../node_modules/shell-quote/parse.js"(exports, module) { "use strict"; var CONTROL = "(?:" + [ "\\|\\|", "\\&\\&", ";;", "\\|\\&", "\\<\\(", "\\<\\<\\<", ">>", ">\\&", "<\\&", "[&;()|<>]" ].join("|") + ")", controlRE = new RegExp("^" + CONTROL + "$"), META = "|&;()<> \\t", SINGLE_QUOTE = '"((\\\\"|[^"])*?)"', DOUBLE_QUOTE = "'((\\\\'|[^'])*?)'", hash = /^#$/, SQ = "'", DQ = '"', DS = "$", TOKEN = "", mult = 4294967296; for (i = 0; i < 4; i++) TOKEN += (mult * Math.random()).toString(16); var i, startsWithToken = new RegExp("^" + TOKEN); function matchAll(s, r) { for (var origIndex = r.lastIndex, matches = [], matchObj; matchObj = r.exec(s); ) matches.push(matchObj), r.lastIndex === matchObj.index && (r.lastIndex += 1); return r.lastIndex = origIndex, matches; } function getVar(env2, pre, key) { var r = typeof env2 == "function" ? env2(key) : env2[key]; return typeof r > "u" && key != "" ? r = "" : typeof r > "u" && (r = "$"), typeof r == "object" ? pre + TOKEN + JSON.stringify(r) + TOKEN : pre + r; } function parseInternal(string, env2, opts) { opts || (opts = {}); var BS = opts.escape || "\\", BAREWORD = "(\\" + BS + `['"` + META + `]|[^\\s'"` + META + "])+", chunker = new RegExp([ "(" + CONTROL + ")", // control chars "(" + BAREWORD + "|" + SINGLE_QUOTE + "|" + DOUBLE_QUOTE + ")+" ].join("|"), "g"), matches = matchAll(string, chunker); if (matches.length === 0) return []; env2 || (env2 = {}); var commented = !1; return matches.map(function(match) { var s = match[0]; if (!s || commented) return; if (controlRE.test(s)) return { op: s }; var quote = !1, esc = !1, out = "", isGlob = !1, i2; function parseEnvVar() { i2 += 1; var varend, varname, char = s.charAt(i2); if (char === "{") { if (i2 += 1, s.charAt(i2) === "}") throw new Error("Bad substitution: " + s.slice(i2 - 2, i2 + 1)); if (varend = s.indexOf("}", i2), varend < 0) throw new Error("Bad substitution: " + s.slice(i2)); varname = s.slice(i2, varend), i2 = varend; } else if (/[*@#?$!_-]/.test(char)) varname = char, i2 += 1; else { var slicedFromI = s.slice(i2); varend = slicedFromI.match(/[^\w\d_]/), varend ? (varname = slicedFromI.slice(0, varend.index), i2 += varend.index - 1) : (varname = slicedFromI, i2 = s.length); } return getVar(env2, "", varname); } for (i2 = 0; i2 < s.length; i2++) { var c = s.charAt(i2); if (isGlob = isGlob || !quote && (c === "*" || c === "?"), esc) out += c, esc = !1; else if (quote) c === quote ? quote = !1 : quote == SQ ? out += c : c === BS ? (i2 += 1, c = s.charAt(i2), c === DQ || c === BS || c === DS ? out += c : out += BS + c) : c === DS ? out += parseEnvVar() : out += c; else if (c === DQ || c === SQ) quote = c; else { if (controlRE.test(c)) return { op: s }; if (hash.test(c)) { commented = !0; var commentObj = { comment: string.slice(match.index + i2 + 1) }; return out.length ? [out, commentObj] : [commentObj]; } else c === BS ? esc = !0 : c === DS ? out += parseEnvVar() : out += c; } } return isGlob ? { op: "glob", pattern: out } : out; }).reduce(function(prev, arg) { return typeof arg > "u" ? prev : prev.concat(arg); }, []); } module.exports = function(s, env2, opts) { var mapped = parseInternal(s, env2, opts); return typeof env2 != "function" ? mapped : mapped.reduce(function(acc, s2) { if (typeof s2 == "object") return acc.concat(s2); var xs = s2.split(RegExp("(" + TOKEN + ".*?" + TOKEN + ")", "g")); return xs.length === 1 ? acc.concat(xs[0]) : acc.concat(xs.filter(Boolean).map(function(x) { return startsWithToken.test(x) ? JSON.parse(x.split(TOKEN)[1]) : x; })); }, []); }; } }); // ../../node_modules/shell-quote/index.js var require_shell_quote = __commonJS({ "../../node_modules/shell-quote/index.js"(exports) { "use strict"; exports.quote = require_quote(); exports.parse = require_parse(); } }); // ../../node_modules/launch-editor/editor-info/macos.js var require_macos = __commonJS({ "../../node_modules/launch-editor/editor-info/macos.js"(exports, module) { module.exports = { "/Applications/Atom.app/Contents/MacOS/Atom": "atom", "/Applications/Atom Beta.app/Contents/MacOS/Atom Beta": "/Applications/Atom Beta.app/Contents/MacOS/Atom Beta", "/Applications/Brackets.app/Contents/MacOS/Brackets": "brackets", "/Applications/Sublime Text.app/Contents/MacOS/Sublime Text": "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl", "/Applications/Sublime Text.app/Contents/MacOS/sublime_text": "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl", "/Applications/Sublime Text 2.app/Contents/MacOS/Sublime Text 2": "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl", "/Applications/Sublime Text Dev.app/Contents/MacOS/Sublime Text": "/Applications/Sublime Text Dev.app/Contents/SharedSupport/bin/subl", "/Applications/Visual Studio Code.app/Contents/MacOS/Code": "code", "/Applications/Visual Studio Code.app/Contents/MacOS/Electron": "code", "/Applications/Visual Studio Code - Insiders.app/Contents/MacOS/Code - Insiders": "code-insiders", "/Applications/Visual Studio Code - Insiders.app/Contents/MacOS/Electron": "code-insiders", "/Applications/VSCodium.app/Contents/MacOS/Electron": "codium", "/Applications/Cursor.app/Contents/MacOS/Cursor": "cursor", "/Applications/Trae.app/Contents/MacOS/Electron": "trae", "/Applications/Antigravity.app/Contents/MacOS/Electron": "antigravity", "/Applications/AppCode.app/Contents/MacOS/appcode": "/Applications/AppCode.app/Contents/MacOS/appcode", "/Applications/CLion.app/Contents/MacOS/clion": "/Applications/CLion.app/Contents/MacOS/clion", "/Applications/IntelliJ IDEA.app/Contents/MacOS/idea": "/Applications/IntelliJ IDEA.app/Contents/MacOS/idea", "/Applications/IntelliJ IDEA Ultimate.app/Contents/MacOS/idea": "/Applications/IntelliJ IDEA Ultimate.app/Contents/MacOS/idea", "/Applications/IntelliJ IDEA Community Edition.app/Contents/MacOS/idea": "/Applications/IntelliJ IDEA Community Edition.app/Contents/MacOS/idea", "/Applications/PhpStorm.app/Contents/MacOS/phpstorm": "/Applications/PhpStorm.app/Contents/MacOS/phpstorm", "/Applications/PyCharm.app/Contents/MacOS/pycharm": "/Applications/PyCharm.app/Contents/MacOS/pycharm", "/Applications/PyCharm CE.app/Contents/MacOS/pycharm": "/Applications/PyCharm CE.app/Contents/MacOS/pycharm", "/Applications/RubyMine.app/Contents/MacOS/rubymine": "/Applications/RubyMine.app/Contents/MacOS/rubymine", "/Applications/WebStorm.app/Contents/MacOS/webstorm": "/Applications/WebStorm.app/Contents/MacOS/webstorm", "/Applications/MacVim.app/Contents/MacOS/MacVim": "mvim", "/Applications/GoLand.app/Contents/MacOS/goland": "/Applications/GoLand.app/Contents/MacOS/goland", "/Applications/Rider.app/Contents/MacOS/rider": "/Applications/Rider.app/Contents/MacOS/rider", "/Applications/Zed.app/Contents/MacOS/zed": "zed" }; } }); // ../../node_modules/launch-editor/editor-info/linux.js var require_linux = __commonJS({ "../../node_modules/launch-editor/editor-info/linux.js"(exports, module) { module.exports = { atom: "atom", Brackets: "brackets", "code-insiders": "code-insiders", code: "code", vscodium: "vscodium", codium: "codium", cursor: "cursor", trae: "trae", antigravity: "antigravity", emacs: "emacs", gvim: "gvim", idea: "idea", "idea.sh": "idea", phpstorm: "phpstorm", "phpstorm.sh": "phpstorm", pycharm: "pycharm", "pycharm.sh": "pycharm", rubymine: "rubymine", "rubymine.sh": "rubymine", sublime_text: "subl", vim: "vim", webstorm: "webstorm", "webstorm.sh": "webstorm", goland: "goland", "goland.sh": "goland", rider: "rider", "rider.sh": "rider", zed: "zed" }; } }); // ../../node_modules/launch-editor/editor-info/windows.js var require_windows = __commonJS({ "../../node_modules/launch-editor/editor-info/windows.js"(exports, module) { module.exports = [ "Brackets.exe", "Code.exe", "Code - Insiders.exe", "VSCodium.exe", "Cursor.exe", "atom.exe", "sublime_text.exe", "notepad++.exe", "clion.exe", "clion64.exe", "idea.exe", "idea64.exe", "phpstorm.exe", "phpstorm64.exe", "pycharm.exe", "pycharm64.exe", "rubymine.exe", "rubymine64.exe", "webstorm.exe", "webstorm64.exe", "goland.exe", "goland64.exe", "rider.exe", "rider64.exe", "Trae.exe", "zed.exe", "Antigravity.exe" ]; } }); // ../../node_modules/launch-editor/guess.js var require_guess = __commonJS({ "../../node_modules/launch-editor/guess.js"(exports, module) { var path = __require("path"), shellQuote = require_shell_quote(), childProcess = __require("child_process"), COMMON_EDITORS_MACOS = require_macos(), COMMON_EDITORS_LINUX = require_linux(), COMMON_EDITORS_WIN = require_windows(); module.exports = function(specifiedEditor) { if (specifiedEditor) return shellQuote.parse(specifiedEditor); if (process.env.LAUNCH_EDITOR) return [process.env.LAUNCH_EDITOR]; if (process.versions.webcontainer) return [process.env.EDITOR || "code"]; try { if (process.platform === "darwin") { let output = childProcess.execSync("ps x -o comm=", { stdio: ["pipe", "pipe", "ignore"] }).toString(), processNames = Object.keys(COMMON_EDITORS_MACOS), processList = output.split(` `); for (let i = 0; i < processNames.length; i++) { let processName = processNames[i]; if (processList.includes(processName)) return [COMMON_EDITORS_MACOS[processName]]; let processNameWithoutApplications = processName.replace("/Applications", ""); if (output.indexOf(processNameWithoutApplications) !== -1) { if (processName !== COMMON_EDITORS_MACOS[processName]) return [COMMON_EDITORS_MACOS[processName]]; let runningProcess = processList.find((procName) => procName.endsWith(processNameWithoutApplications)); if (runningProcess !== void 0) return [runningProcess]; } } } else if (process.platform === "win32") { let runningProcesses = childProcess.execSync( 'powershell -NoProfile -Command "[Console]::OutputEncoding=[Text.Encoding]::UTF8;Get-CimInstance -Query \\"select executablepath from win32_process where executablepath is not null\\" | % { $_.ExecutablePath }"', { stdio: ["pipe", "pipe", "ignore"] } ).toString().split(`\r `); for (let i = 0; i < runningProcesses.length; i++) { let fullProcessPath = runningProcesses[i].trim(), shortProcessName = path.basename(fullProcessPath); if (COMMON_EDITORS_WIN.indexOf(shortProcessName) !== -1) return [fullProcessPath]; } } else if (process.platform === "linux") { let output = childProcess.execSync("ps x --no-heading -o comm --sort=comm", { stdio: ["pipe", "pipe", "ignore"] }).toString(), processNames = Object.keys(COMMON_EDITORS_LINUX); for (let i = 0; i < processNames.length; i++) { let processName = processNames[i]; if (output.indexOf(processName) !== -1) return [COMMON_EDITORS_LINUX[processName]]; } } } catch { } return process.env.VISUAL ? [process.env.VISUAL] : process.env.EDITOR ? [process.env.EDITOR] : [null]; }; } }); // ../../node_modules/launch-editor/get-args.js var require_get_args = __commonJS({ "../../node_modules/launch-editor/get-args.js"(exports, module) { var path = __require("path"); module.exports = function(editor, fileName, lineNumber, columnNumber = 1) { switch (path.basename(editor).replace(/\.(exe|cmd|bat)$/i, "")) { case "atom": case "Atom": case "Atom Beta": case "subl": case "sublime": case "sublime_text": case "wstorm": case "charm": case "zed": return [`${fileName}:${lineNumber}:${columnNumber}`]; case "notepad++": return ["-n" + lineNumber, "-c" + columnNumber, fileName]; case "vim": case "mvim": return [`+call cursor(${lineNumber}, ${columnNumber})`, fileName]; case "joe": case "gvim": return [`+${lineNumber}`, fileName]; case "emacs": case "emacsclient": return [`+${lineNumber}:${columnNumber}`, fileName]; case "rmate": case "mate": case "mine": return ["--line", lineNumber, fileName]; case "code": case "Code": case "code-insiders": case "Code - Insiders": case "codium": case "trae": case "antigravity": case "cursor": case "vscodium": case "VSCodium": return ["-r", "-g", `${fileName}:${lineNumber}:${columnNumber}`]; case "appcode": case "clion": case "clion64": case "idea": case "idea64": case "phpstorm": case "phpstorm64": case "pycharm": case "pycharm64": case "rubymine": case "rubymine64": case "webstorm": case "webstorm64": case "goland": case "goland64": case "rider": case "rider64": return ["--line", lineNumber, "--column", columnNumber, fileName]; } return process.env.LAUNCH_EDITOR ? [fileName, lineNumber, columnNumber] : [fileName]; }; } }); // ../../node_modules/launch-editor/index.js var require_launch_editor = __commonJS({ "../../node_modules/launch-editor/index.js"(exports, module) { var fs = __require("fs"), os = __require("os"), path = __require("path"), colors = require_picocolors(), childProcess = __require("child_process"), guessEditor = require_guess(), getArgumentsForPosition = require_get_args(); function wrapErrorCallback(cb) { return (fileName, errorMessage) => { console.log(), console.log( colors.red("Could not open " + path.basename(fileName) + " in the editor.") ), errorMessage && (errorMessage[errorMessage.length - 1] !== "." && (errorMessage += "."), console.log( colors.red("The editor process exited with an error: " + errorMessage) )), console.log(), cb && cb(fileName, errorMessage); }; } function isTerminalEditor(editor) { switch (editor) { case "vim": case "emacs": case "nano": return !0; } return !1; } var positionRE = /:(\d+)(:(\d+))?$/; function parseFile(file) { file.startsWith("file://") && (file = __require("url").fileURLToPath(file)); let fileName = file.replace(positionRE, ""), match = file.match(positionRE), lineNumber = match && match[1], columnNumber = match && match[3]; return { fileName, lineNumber, columnNumber }; } var _childProcess = null; function launchEditor(file, specifiedEditor, onErrorCallback) { let parsed = parseFile(file), { fileName } = parsed, { lineNumber, columnNumber } = parsed; if (!fs.existsSync(fileName)) return; typeof specifiedEditor == "function" && (onErrorCallback = specifiedEditor, specifiedEditor = void 0), onErrorCallback = wrapErrorCallback(onErrorCallback); let [editor, ...args] = guessEditor(specifiedEditor); if (!editor) { onErrorCallback(fileName, null); return; } if (process.platform === "linux" && fileName.startsWith("/mnt/") && /Microsoft/i.test(os.release()) && (fileName = path.relative("", fileName)), lineNumber) { let extraArgs = getArgumentsForPosition(editor, fileName, lineNumber, columnNumber); args.push.apply(args, extraArgs); } else args.push(fileName); if (_childProcess && isTerminalEditor(editor) && _childProcess.kill("SIGKILL"), process.platform === "win32") { let escapeCmdArgs2 = function(cmdArgs) { return cmdArgs.replace(/([&|<>,;=^])/g, "^$1"); }, doubleQuoteIfNeeded2 = function(str) { return str.includes("^") ? `^"${str}^"` : str.includes(" ") ? `"${str}"` : str; }; var escapeCmdArgs = escapeCmdArgs2, doubleQuoteIfNeeded = doubleQuoteIfNeeded2; let launchCommand = [editor, ...args.map(escapeCmdArgs2)].map(doubleQuoteIfNeeded2).join(" "); _childProcess = childProcess.exec(launchCommand, { stdio: "inherit", shell: !0 }); } else _childProcess = childProcess.spawn(editor, args, { stdio: "inherit" }); _childProcess.on("exit", function(errorCode) { _childProcess = null, errorCode && onErrorCallback(fileName, "(code " + errorCode + ")"); }), _childProcess.on("error", function(error) { let { code, message } = error; code === "ENOENT" && (message = `${message} ('${editor}' command does not exist in 'PATH')`), onErrorCallback(fileName, message); }); } module.exports = launchEditor; } }); // src/core-server/presets/common-preset.ts import { existsSync } from "node:fs"; import { readFile as readFile2 } from "node:fs/promises"; import { normalizeStories, optionalEnvToBoolean } from "storybook/internal/common"; import { JsPackageManagerFactory, getDirectoryFromWorkingDir, getPreviewBodyTemplate, getPreviewHeadTemplate, loadEnvs, removeAddon as removeAddonBase } from "storybook/internal/common"; import { StoryIndexGenerator } from "storybook/internal/core-server"; import { loadCsf } from "storybook/internal/csf-tools"; import { logger as logger5 } from "storybook/internal/node-logger"; import { telemetry as telemetry10 } from "storybook/internal/telemetry"; var import_ts_dedent = __toESM(require_dist(), 1); // src/core-server/server-channel/create-new-story-channel.ts import { CREATE_NEW_STORYFILE_REQUEST, CREATE_NEW_STORYFILE_RESPONSE } from "storybook/internal/core-events"; import { telemetry } from "storybook/internal/telemetry"; function initCreateNewStoryChannel(channel, options) { return channel.on( CREATE_NEW_STORYFILE_REQUEST, async (data) => { let result = await generateStoryFile(data.payload, options); result.success ? (channel.emit(CREATE_NEW_STORYFILE_RESPONSE, { success: !0, id: data.id, payload: { storyId: result.storyId, storyFilePath: result.storyFilePath, exportedStoryName: result.exportedStoryName }, error: null }), telemetry("create-new-story-file", { success: !0 })) : (channel.emit(CREATE_NEW_STORYFILE_RESPONSE, { success: !1, id: data.id, payload: result.errorType === "STORY_FILE_EXISTS" ? { type: "STORY_FILE_EXISTS", kind: result.kind } : void 0, error: result.error || "Unknown error occurred" }), await telemetry("create-new-story-file", { success: !1, error: result.errorType || result.error })); } ), channel; } // src/core-server/server-channel/file-search-channel.ts import { readFile } from "node:fs/promises"; import { dirname, join as join2 } from "node:path"; import { extractRenderer, getFrameworkName, getProjectRoot } from "storybook/internal/common"; import { FILE_COMPONENT_SEARCH_REQUEST, FILE_COMPONENT_SEARCH_RESPONSE } from "storybook/internal/core-events"; import { telemetry as telemetry2 } from "storybook/internal/telemetry"; // src/core-server/utils/parser/generic-parser.ts import { parser, types as t } from "storybook/internal/babel"; var GenericParser = class { /** * Parse the content of a file and return the exports * * @param content The content of the file * @returns The exports of the file */ async parse(content) { let ast = parser.parse(content, { allowImportExportEverywhere: !0, allowAwaitOutsideFunction: !0, allowNewTargetOutsideFunction: !0, allowReturnOutsideFunction: !0, allowUndeclaredExports: !0, plugins: [ // Language features "typescript", "jsx", // Latest ECMAScript features "asyncGenerators", "bigInt", "classProperties", "classPrivateProperties", "classPrivateMethods", "classStaticBlock", "dynamicImport", "exportNamespaceFrom", "logicalAssignment", "moduleStringNames", "nullishCoalescingOperator", "numericSeparator", "objectRestSpread", "optionalCatchBinding", "optionalChaining", "privateIn", "regexpUnicodeSets", "topLevelAwait", // ECMAScript proposals "asyncDoExpressions", "decimal", "decorators", "decoratorAutoAccessors", "deferredImportEvaluation", "destructuringPrivate", "doExpressions", "explicitResourceManagement", "exportDefaultFrom", "functionBind", "functionSent", "importAttributes", "importReflection", "moduleBlocks", "partialApplication", "recordAndTuple", "sourcePhaseImports", "throwExpressions" ] }), exports = []; return ast.program.body.forEach(function(node) { t.isExportNamedDeclaration(node) ? (t.isFunctionDeclaration(node.declaration) && t.isIdentifier(node.declaration.id) && exports.push({ name: node.declaration.id.name, default: !1 }), t.isClassDeclaration(node.declaration) && t.isIdentifier(node.declaration.id) && exports.push({ name: node.declaration.id.name, default: !1 }), node.declaration === null && node.specifiers.length > 0 && node.specifiers.forEach((specifier) => { t.isExportSpecifier(specifier) && t.isIdentifier(specifier.exported) && exports.push({ name: specifier.exported.name, default: !1 }); }), t.isVariableDeclaration(node.declaration) && node.declaration.declarations.forEach((declaration) => { t.isVariableDeclarator(declaration) && t.isIdentifier(declaration.id) && exports.push({ name: declaration.id.name, default: !1 }); })) : t.isExportDefaultDeclaration(node) && exports.push({ name: "default", default: !0 }); }), { exports }; } }; // src/core-server/utils/parser/index.ts function getParser(renderer) { return new GenericParser(); } // src/core-server/utils/search-files.ts var FILE_EXTENSIONS = ["js", "mjs", "cjs", "jsx", "mts", "ts", "tsx", "cts"], IGNORED_FILES = [ "**/node_modules/**", "**/*.spec.*", "**/*.test.*", "**/*.stories.*", "**/storybook-static/**" ]; async function searchFiles({ searchQuery, cwd, ignoredFiles = IGNORED_FILES, fileExtensions = FILE_EXTENSIONS }) { let { globby, isDynamicPattern } = await import("../../_node-chunks/globby-JBOYUSB4.js"), hasSearchSpecialGlobChars = isDynamicPattern(searchQuery, { cwd }), searchQueryHasExtension = /(\.[a-z]+)$/i.test(searchQuery), fileExtensionsPattern = `{${fileExtensions.join(",")}}`, globbedSearchQuery = hasSearchSpecialGlobChars ? searchQuery : searchQueryHasExtension ? [`**/*${searchQuery}*`, `**/*${searchQuery}*/**`] : [ `**/*${searchQuery}*.${fileExtensionsPattern}`, `**/*${searchQuery}*/**/*.${fileExtensionsPattern}` ]; return (await globby(globbedSearchQuery, { ignore: ignoredFiles, gitignore: !0, caseSensitiveMatch: !1, cwd, objectMode: !0 })).map((entry) => entry.path).filter((entry) => fileExtensions.some((ext) => entry.endsWith(`.${ext}`))); } // src/core-server/server-channel/file-search-channel.ts async function initFileSearchChannel(channel, options) { return channel.on( FILE_COMPONENT_SEARCH_REQUEST, async (data) => { let searchQuery = data.id; try { if (!searchQuery) return; let frameworkName = await getFrameworkName(options), rendererName = await extractRenderer(frameworkName), entries = (await searchFiles({ searchQuery, cwd: getProjectRoot() })).map(async (file) => { let parser3 = getParser(rendererName); try { let content = await readFile(join2(getProjectRoot(), file), "utf-8"), { storyFileName } = getStoryMetadata(join2(getProjectRoot(), file)), dir = dirname(file), storyFileExists = doesStoryFileExist(join2(getProjectRoot(), dir), storyFileName), info = await parser3.parse(content); return { filepath: file, exportedComponents: info.exports, storyFileExists }; } catch (e) { return telemetry2("create-new-story-file-search", { success: !1, error: `Could not parse file: ${e}` }), { filepath: file, storyFileExists: !1, exportedComponents: null }; } }); telemetry2("create-new-story-file-search", { success: !0, payload: { fileCount: entries.length } }), channel.emit(FILE_COMPONENT_SEARCH_RESPONSE, { success: !0, id: searchQuery, payload: { files: await Promise.all(entries) }, error: null }); } catch (e) { channel.emit(FILE_COMPONENT_SEARCH_RESPONSE, { success: !1, id: searchQuery ?? "", error: `An error occurred while searching for components in the project. ${e?.message}` }), telemetry2("create-new-story-file-search", { success: !1, error: `An error occurred while searching for components: ${e}` }); } } ), channel; } // src/core-server/server-channel/ghost-stories-channel.ts import { GHOST_STORIES_REQUEST, GHOST_STORIES_RESPONSE } from "storybook/internal/core-events"; import { getLastEvents, getStorybookMetadata, telemetry as telemetry3 } from "storybook/internal/telemetry"; // src/core-server/utils/wait-for-idle-vitest.ts async function waitForIdleVitest(maxWaitMs = 1800 * 1e3, pollIntervalMs = 60 * 1e3) { let deadline = Date.now() + maxWaitMs; for (; Date.now() < deadline; ) { try { let state = fullTestProviderStore.getFullState(); if (!Object.values(state).some((s) => s === "test-provider-state:running")) return !0; } catch { return !0; } await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs)); } return !1; } // src/shared/utils/ai-checklist-flags.ts import { resolve } from "node:path"; import { cache } from "storybook/internal/common"; function isProjectScopedFlag(value) { return typeof value == "object" && value !== null && "configDir" in value && typeof value.configDir == "string"; } async function readProjectScopedFlag(key, configDir) { try { let value = await cache.get(key); if (isProjectScopedFlag(value) && value.configDir === resolve(configDir)) return value; } catch { } } async function hasAiInitOptIn(configDir) { return (await readProjectScopedFlag("ai-init-opt-in", configDir))?.answer !== !1; } async function hasAiSetupRun(configDir) { return !!await readProjectScopedFlag("ai-setup-ran", configDir); } async function getAiSetupRunId(configDir) { return (await readProjectScopedFlag("ai-setup-ran", configDir))?.runId; } // src/core-server/server-channel/ghost-stories-channel.ts var SkipGhostStoriesTelemetry = class extends Error { }; function initGhostStoriesChannel(channel, options) { return channel.on(GHOST_STORIES_REQUEST, async () => { let stats = {}, aiSetupRunId = await getAiSetupRunId(options.configDir); try { await telemetry3("ghost-stories", async () => { try { let ghostRunStart = Date.now(), lastEvents = await getLastEvents(), lastInit = lastEvents?.init, lastAISetup = lastEvents?.["ai-setup"], lastSetupStoryScoringRun = lastEvents?.["ai-setup-final-scoring"], lastGhostStoriesRun = lastEvents?.["ghost-stories"]; if (!(lastAISetup ?? lastInit)) throw new SkipGhostStoriesTelemetry(); if (lastGhostStoriesRun && lastSetupStoryScoringRun.body.payload.runId === lastAISetup.body.payload.runId) throw new SkipGhostStoriesTelemetry(); let metadata = await getStorybookMetadata(options.configDir), isReactStorybook = metadata?.renderer?.includes("@storybook/react"), hasVitestAddon = !!metadata?.addons && Object.keys(metadata.addons).some( (addonKey) => addonKey.includes("@storybook/addon-vitest") ); if (!isReactStorybook || !hasVitestAddon) throw new SkipGhostStoriesTelemetry(); if (!await waitForIdleVitest()) return { stats, aiSetupRunId, runError: "Vitest busy, couldn't run ghost stories" }; let candidateAnalysisStart = Date.now(), candidatesResult = await getComponentCandidates(); if (stats.candidateAnalysisDuration = Date.now() - candidateAnalysisStart, stats.globMatchCount = candidatesResult.globMatchCount, stats.analyzedCount = candidatesResult.analyzedCount ?? 0, stats.avgComplexity = candidatesResult.avgComplexity ?? 0, stats.candidateCount = candidatesResult.candidates.length, candidatesResult.error) return stats.totalRunDuration = Date.now() - ghostRunStart, { stats, aiSetupRunId, runError: candidatesResult.error }; if (candidatesResult.candidates.length === 0) return stats.totalRunDuration = Date.now() - ghostRunStart, { stats, aiSetupRunId, runError: "No candidates found" }; let testRunResult = await runStoryTests(candidatesResult.candidates, { ghostRun: !0 }); return stats.totalRunDuration = Date.now() - ghostRunStart, stats.testRunDuration = testRunResult.duration, testRunResult.runError ? { stats, aiSetupRunId, runError: testRunResult.runError } : { stats, aiSetupRunId, results: testRunResult.summary }; } catch (error) { if (error instanceof SkipGhostStoriesTelemetry) throw error; return { stats, aiSetupRunId, runError: "Unknown error during ghost run" }; } }); } catch (error) { if (!(error instanceof SkipGhostStoriesTelemetry)) throw error; } finally { channel.emit(GHOST_STORIES_RESPONSE); } }), channel; } // src/core-server/server-channel/open-in-editor-channel.ts var import_launch_editor = __toESM(require_launch_editor(), 1); import { OPEN_IN_EDITOR_REQUEST, OPEN_IN_EDITOR_RESPONSE } from "storybook/internal/core-events"; import { telemetry as telemetry4 } from "storybook/internal/telemetry"; async function initOpenInEditorChannel(channel) { return channel.on(OPEN_IN_EDITOR_REQUEST, async (payload) => { let sendTelemetry = (data) => { telemetry4("open-in-editor", data); }; try { let { file: targetFile, line, column } = payload; if (!targetFile) throw new Error("No file was provided to open"); let location = typeof line == "number" ? `${targetFile}:${line}${typeof column == "number" ? `:${column}` : ""}` : targetFile; await new Promise((resolve2, reject) => { (0, import_launch_editor.default)(location, void 0, (_fileName, errorMessage) => { errorMessage ? reject(new Error(errorMessage)) : resolve2(); }); }), channel.emit(OPEN_IN_EDITOR_RESPONSE, { file: targetFile, line, column, error: null }), sendTelemetry({ success: !0 }); } catch (e) { let error = e?.message || "Failed to open in editor"; channel.emit(OPEN_IN_EDITOR_RESPONSE, { error, ...payload }), sendTelemetry({ success: !1, error }); } }), channel; } // src/core-server/server-channel/telemetry-channel.ts import { PREVIEW_INITIALIZED, SHARE_ISOLATE_MODE, SIDEBAR_FILTER_CHANGED, AI_PROMPT_NUDGE } from "storybook/internal/core-events"; import { telemetry as telemetry5 } from "storybook/internal/telemetry"; import { getLastEvents as getLastEvents2 } from "storybook/internal/telemetry"; import { getSessionId } from "storybook/internal/telemetry"; var makePayload = (userAgent, lastInit, sessionId) => { let payload = { userAgent, isNewUser: !1, timeSinceInit: void 0 }; return sessionId && lastInit?.body?.sessionId === sessionId && (payload.timeSinceInit = Date.now() - lastInit.timestamp, payload.isNewUser = !!lastInit.body.payload.newUser), payload; }; function initTelemetryChannel(channel) { channel.on(PREVIEW_INITIALIZED, async ({ userAgent }) => { try { let sessionId = await getSessionId(), lastEvents = await getLastEvents2(), lastInit = lastEvents.init; if (!lastEvents["preview-first-load"]) { let payload = makePayload(userAgent, lastInit, sessionId); telemetry5("preview-first-load", payload); } } catch { } }), channel.on(SHARE_ISOLATE_MODE, async () => { telemetry5("share", { action: "isolate-mode-opened" }); }), channel.on(SIDEBAR_FILTER_CHANGED, (payload) => { telemetry5("sidebar-filter", payload); }), channel.on(AI_PROMPT_NUDGE, async ({ id, origin }) => { telemetry5("ai-prompt-nudge", { id, origin }); }); } // src/core-server/utils/checklist.ts import { createFileSystemCache, resolvePathInStorybookCache } from "storybook/internal/common"; import { experimental_UniversalStore } from "storybook/internal/core-server"; import { AI_SETUP_ANALYTICS_REQUEST, GHOST_STORIES_REQUEST as GHOST_STORIES_REQUEST2, STORY_INDEX_INVALIDATED } from "storybook/internal/core-events"; import { logger } from "storybook/internal/node-logger"; import { telemetry as telemetry6 } from "storybook/internal/telemetry"; // ../../node_modules/es-toolkit/dist/predicate/isPrimitive.mjs function isPrimitive(value) { return value == null || typeof value != "object" && typeof value != "function"; } // ../../node_modules/es-toolkit/dist/predicate/isTypedArray.mjs function isTypedArray(x) { return ArrayBuffer.isView(x) && !(x instanceof DataView); } // ../../node_modules/es-toolkit/dist/object/clone.mjs function clone(obj) { if (isPrimitive(obj)) return obj; if (Array.isArray(obj) || isTypedArray(obj) || obj instanceof ArrayBuffer || typeof SharedArrayBuffer < "u" && obj instanceof SharedArrayBuffer) return obj.slice(0); let prototype = Object.getPrototypeOf(obj), Constructor = prototype.constructor; if (obj instanceof Date || obj instanceof Map || obj instanceof Set) return new Constructor(obj); if (obj instanceof RegExp) { let newRegExp = new Constructor(obj); return newRegExp.lastIndex = obj.lastIndex, newRegExp; } if (obj instanceof DataView) return new Constructor(obj.buffer.slice(0)); if (obj instanceof Error) { let newError = new Constructor(obj.message); return newError.stack = obj.stack, newError.name = obj.name, newError.cause = obj.cause, newError; } if (typeof File < "u" && obj instanceof File) return new Constructor([obj], obj.name, { type: obj.type, lastModified: obj.lastModified }); if (typeof obj == "object") { let newObject = Object.create(prototype); return Object.assign(newObject, obj); } return obj; } // ../../node_modules/es-toolkit/dist/predicate/isPlainObject.mjs function isPlainObject(value) { if (!value || typeof value != "object") return !1; let proto = Object.getPrototypeOf(value); return proto === null || proto === Object.prototype || Object.getPrototypeOf(proto) === null ? Object.prototype.toString.call(value) === "[object Object]" : !1; } // ../../node_modules/es-toolkit/dist/_internal/isUnsafeProperty.mjs function isUnsafeProperty(key) { return key === "__proto__"; } // ../../node_modules/es-toolkit/dist/object/mergeWith.mjs function mergeWith(target, source, merge2) { let sourceKeys = Object.keys(source); for (let i = 0; i < sourceKeys.length; i++) { let key = sourceKeys[i]; if (isUnsafeProperty(key)) continue; let sourceValue = source[key], targetValue = target[key], merged = merge2(targetValue, sourceValue, key, target, source); merged !== void 0 ? target[key] = merged : Array.isArray(sourceValue) ? Array.isArray(targetValue) ? target[key] = mergeWith(targetValue, sourceValue, merge2) : target[key] = mergeWith([], sourceValue, merge2) : isPlainObject(sourceValue) ? isPlainObject(targetValue) ? target[key] = mergeWith(targetValue, sourceValue, merge2) : target[key] = mergeWith({}, sourceValue, merge2) : (targetValue === void 0 || sourceValue !== void 0) && (target[key] = sourceValue); } return target; } // ../../node_modules/es-toolkit/dist/string/words.mjs var CASE_SPLIT_PATTERN = new RegExp("\\p{Lu}?\\p{Ll}+|[0-9]+|\\p{Lu}+(?!\\p{Ll})|\\p{Emoji_Presentation}|\\p{Extended_Pictographic}|\\p{L}+", "gu"); // ../../node_modules/es-toolkit/dist/object/toMerged.mjs function toMerged(target, source) { return mergeWith(clone(target), source, function mergeRecursively(targetValue, sourceValue) { if (Array.isArray(sourceValue)) return Array.isArray(targetValue) ? mergeWith(clone(targetValue), sourceValue, mergeRecursively) : mergeWith([], sourceValue, mergeRecursively); if (isPlainObject(sourceValue)) return isPlainObject(targetValue) ? mergeWith(clone(targetValue), sourceValue, mergeRecursively) : mergeWith({}, sourceValue, mergeRecursively); }); } // src/shared/checklist-store/checklistData.state.ts var initialState = { items: { accessibilityTests: { status: "open" }, aiSetup: { status: "open" }, autodocs: { status: "open" }, ciTests: { status: "open" }, controls: { status: "open" }, coverage: { status: "open" }, guidedTour: { status: "open" }, installA11y: { status: "open" }, installChromatic: { status: "open" }, installDocs: { status: "open" }, installVitest: { status: "open" }, mdxDocs: { status: "open" }, moreComponents: { status: "open" }, moreStories: { status: "open" }, onboardingSurvey: { status: "open" }, organizeStories: { status: "open" }, renderComponent: { status: "open" }, runTests: { status: "open" }, publishStorybook: { status: "open" }, shareStorybook: { status: "open" }, viewports: { status: "open" }, visualTests: { status: "open" }, whatsNewStorybook10: { status: "open" }, writeInteractions: { status: "open" } }, widget: {} }; // src/shared/checklist-store/index.ts var UNIVERSAL_CHECKLIST_STORE_OPTIONS = { id: "storybook/checklist", initialState }; // src/core-server/utils/checklist.ts async function initializeChecklist(channel, getStoryIndexGeneratorPromise, configDir) { try { let store = experimental_UniversalStore.create({ ...UNIVERSAL_CHECKLIST_STORE_OPTIONS, leader: !0 }), cache2 = createFileSystemCache({ basePath: resolvePathInStorybookCache("checklist"), ns: "storybook" }), [[userState, saveUserState], [projectState, saveProjectState]] = await Promise.all([ globalSettings().then((settings) => { let save = throttle(() => settings.save(), 1e3), state = { items: settings.value.checklist?.items ?? {}, widget: settings.value.checklist?.widget ?? {} }; return [state, ({ items = state.items, widget = state.widget }) => { settings.value.checklist = { items, widget }, save(); }]; }), cache2.get("state").then((cachedState) => [{ items: cachedState?.items ?? {} }, ({ items }) => cache2.set("state", { items })]) ]); store.setState( (value) => ({ ...toMerged(value, toMerged(userState, projectState)), loaded: !0 }) ), hasAiSetupRun(configDir).then((hasSetupRun) => { hasSetupRun && store.setState((state) => ({ ...state, aiSetupRun: !0 })); }).catch(() => { }), hasAiInitOptIn(configDir).then((hasOptedIn) => { store.setState((state) => ({ ...state, aiOptIn: hasOptedIn })); }).catch(() => { }); let isAiSetupCompleted = async () => { try { if (!await hasAiSetupRun(configDir)) return !1; let generatorPromise = getStoryIndexGeneratorPromise?.(); if (!generatorPromise) return !1; let entries = (await (await generatorPromise)?.getIndexAndStats?.())?.storyIndex?.entries; return Object.values(entries || []).some(isStoryCreatedByAISetup); } catch { return !1; } }, markAiSetupDone = async () => await isAiSetupCompleted() ? (store.getState().items.aiSetup?.status !== "done" && store.setState((state) => ({ ...state, items: { ...state.items, aiSetup: { ...state.items.aiSetup, status: "done" } } })), !0) : !1, AI_IDLE_DELAY_MS = 240 * 1e3, analyticsTimer, analyticsEmitted = !1, throttledSyncAiSetupStatus = throttle(() => markAiSetupDone().catch(() => { }), 1e3), scheduleIdleCheck = () => { !channel || analyticsEmitted || (throttledSyncAiSetupStatus(), clearTimeout(analyticsTimer), analyticsTimer = setTimeout(async () => { if (!store.getState().aiSetupRun) return; let now = Date.now(), [lastTestRun, lastSelfHealing] = await Promise.all([ get("test-run").catch(() => { }), get("ai-setup-self-healing-scoring").catch(() => { }) ]); if ([lastTestRun, lastSelfHealing].some( (e) => e && now - e.timestamp < AI_IDLE_DELAY_MS )) { scheduleIdleCheck(); return; } await markAiSetupDone(), store.getState().items.aiSetup?.status === "done" && (analyticsEmitted = !0, channel.off(STORY_INDEX_INVALIDATED, onIndexInvalidated), unsubscribeTestProvider(), channel.emit(GHOST_STORIES_REQUEST2), channel.emit(AI_SETUP_ANALYTICS_REQUEST)); }, AI_IDLE_DELAY_MS)); }; markAiSetupDone().then((detected) => { detected && scheduleIdleCheck(); }); let onIndexInvalidated = () => { analyticsEmitted || scheduleIdleCheck(); }; channel && channel.on(STORY_INDEX_INVALIDATED, onIndexInvalidated); let unsubscribeTestProvider = universalTestProviderStore.onStateChange(() => { analyticsEmitted || scheduleIdleCheck(); }); store.onStateChange((state, previousState) => { let entries = Object.entries(state.items), projectValues = {}, userValues = {}; if (entries.forEach(([id, { status, mutedAt }]) => { status === "done" ? projectValues[id] = { status } : (status === "accepted" || status === "skipped") && (userValues[id] = { status }), mutedAt && (userValues[id] = { ...userValues[id], mutedAt }); }), saveProjectState({ items: projectValues }), saveUserState({ items: userValues, widget: state.widget }), !previousState.loaded) return; let { mutedItems, statusItems } = entries.reduce( (acc, [item, { mutedAt, status }]) => { let prev = previousState.items[item]; return mutedAt !== prev?.mutedAt && acc.mutedItems.push(item), status !== prev?.status && acc.statusItems.push(item), acc; }, { mutedItems: [], statusItems: [] } ); mutedItems.length > 0 && telemetry6("onboarding-checklist-muted", { items: mutedItems, completedItems: entries.reduce((acc, [id, { status }]) => status === "done" || status === "accepted" ? acc.concat([id]) : acc, []), skippedItems: entries.reduce((acc, [id, { status }]) => status === "skipped" ? acc.concat([id]) : acc, []) }), statusItems.forEach((item) => { let { status } = state.items[item]; telemetry6("onboarding-checklist-status", { item, status }); }); }); } catch (err) { logger.error("Failed to initialize checklist"), logger.error(err); } } // src/core-server/utils/constants.ts var defaultStaticDirs = [ { from: join(resolvePackageDir("storybook"), "assets/browser"), to: "/sb-common-assets" } ], defaultFavicon = join(resolvePackageDir("storybook"), "assets/browser/favicon.svg"); // src/core-server/utils/save-story/save-story.ts import { writeFile } from "node:fs/promises"; import { basename, join as join3 } from "node:path"; import { formatFileContent } from "storybook/internal/common"; import { SAVE_STORY_REQUEST, SAVE_STORY_RESPONSE, STORY_RENDERED } from "storybook/internal/core-events"; import { storyNameFromExport, toId } from "storybook/internal/csf"; import { printCsf, readCsf } from "storybook/internal/csf-tools"; import { logger as logger2 } from "storybook/internal/node-logger"; import { isExampleStoryId, telemetry as telemetry7 } from "storybook/internal/telemetry"; // src/core-server/utils/save-story/duplicate-story-with-new-name.ts import { types as t2, traverse } from "storybook/internal/babel"; // src/core-server/utils/save-story/utils.ts var SaveStoryError = class extends Error { }; // src/core-server/utils/save-story/duplicate-story-with-new-name.ts var duplicateStoryWithNewName = (csfFile, storyName, newStoryName) => { let node = csfFile._storyExports[storyName], cloned = t2.cloneNode(node); if (!cloned) throw new SaveStoryError("cannot clone Node"); let found = !1; if (traverse(cloned, { Identifier(path) { found || path.node.name === storyName && (found = !0, path.node.name = newStoryName); }, ObjectProperty(path) { let key = path.get("key"); key.isIdentifier() && key.node.name === "args" && path.remove(); }, noScope: !0 }), !(t2.isCallExpression(cloned.init) && t2.isMemberExpression(cloned.init.callee) && t2.isIdentifier(cloned.init.callee.property) && cloned.init.callee.property.name === "story") && (t2.isArrowFunctionExpression(cloned.init) || t2.isCallExpression(cloned.init))) throw new SaveStoryError("Creating a new story based on a CSF2 story is not supported"); return traverse(csfFile._ast, { Program(path) { path.pushContainer(