@onlook/storybook-plugin 0.4.0-beta.10 → 0.4.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { E as EnvContainmentOptions, a as EnvContainmentSubstitution, O as OnlookPluginOptions, e as envContainmentPlugin, s as storybookOnlookPlugin } from './storybook-onlook-plugin-CigILdDb.js';
1
+ export { E as EnvContainmentOptions, a as EnvContainmentSubstitution, O as OnlookPluginOptions, e as envContainmentPlugin, s as storybookOnlookPlugin } from './storybook-onlook-plugin-B9Eo_OIq.js';
2
2
  import { Plugin } from 'vite';
3
3
  import { Indexer } from 'storybook/internal/types';
4
4
 
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from 'node:module';
2
- import path6, { dirname, join, relative } from 'path';
2
+ import path7, { dirname, join, relative } from 'path';
3
3
  import crypto, { createHash } from 'crypto';
4
- import fs4, { existsSync } from 'fs';
4
+ import fs5, { existsSync } from 'fs';
5
5
  import { fileURLToPath } from 'url';
6
6
  import generateModule from '@babel/generator';
7
7
  import { parse } from '@babel/parser';
@@ -61,7 +61,7 @@ function envContainmentPlugin(options) {
61
61
  const resolveOutcomes = /* @__PURE__ */ new Map();
62
62
  const roots = /* @__PURE__ */ new Set([normalizeSlashes(process.cwd())]);
63
63
  const matchTarget = (absPath) => {
64
- const norm = normalizeSlashes(path6.normalize(absPath));
64
+ const norm = normalizeSlashes(path7.normalize(absPath));
65
65
  for (const rel of byModule.keys()) {
66
66
  for (const root of roots) {
67
67
  const target = `${root}/${rel}`;
@@ -96,10 +96,10 @@ function envContainmentPlugin(options) {
96
96
  if (source.startsWith("\0")) return null;
97
97
  const cleaned = stripQuery(source);
98
98
  let direct = null;
99
- if (path6.isAbsolute(cleaned)) {
99
+ if (path7.isAbsolute(cleaned)) {
100
100
  direct = cleaned;
101
101
  } else if (importer && (cleaned.startsWith("./") || cleaned.startsWith("../"))) {
102
- direct = path6.resolve(path6.dirname(stripQuery(importer)), cleaned);
102
+ direct = path7.resolve(path7.dirname(stripQuery(importer)), cleaned);
103
103
  }
104
104
  if (direct) {
105
105
  const rel = matchTarget(direct);
@@ -108,7 +108,7 @@ function envContainmentPlugin(options) {
108
108
  }
109
109
  if (!specifierMightMatch(cleaned)) return null;
110
110
  if (typeof this.resolve !== "function") return null;
111
- const importerDir = importer ? path6.dirname(stripQuery(importer)) : "";
111
+ const importerDir = importer ? path7.dirname(stripQuery(importer)) : "";
112
112
  const outcomeKey = `${importerDir}|${source}`;
113
113
  const memoized = resolveOutcomes.get(outcomeKey);
114
114
  if (memoized !== void 0) return memoized;
@@ -328,7 +328,7 @@ function componentLocPlugin(options = {}) {
328
328
  sourceFilename: filepath
329
329
  });
330
330
  let mutated = false;
331
- const relativePath = path6.relative(root, filepath);
331
+ const relativePath = path7.relative(root, filepath);
332
332
  traverse(ast, {
333
333
  JSXElement(nodePath) {
334
334
  const opening = nodePath.node.openingElement;
@@ -387,9 +387,9 @@ function fastRefreshTolerantExportsPlugin() {
387
387
  }
388
388
  };
389
389
  }
390
- var CACHE_DIR = path6.join(process.cwd(), ".storybook-cache");
391
- var SCREENSHOTS_DIR = path6.join(CACHE_DIR, "screenshots");
392
- var MANIFEST_PATH = path6.join(CACHE_DIR, "manifest.json");
390
+ var CACHE_DIR = path7.join(process.cwd(), ".storybook-cache");
391
+ var SCREENSHOTS_DIR = path7.join(CACHE_DIR, "screenshots");
392
+ var MANIFEST_PATH = path7.join(CACHE_DIR, "manifest.json");
393
393
  var VIEWPORT_WIDTH = 1920;
394
394
  var VIEWPORT_HEIGHT = 1080;
395
395
  var MIN_COMPONENT_WIDTH = 420;
@@ -397,30 +397,30 @@ var MIN_COMPONENT_HEIGHT = 280;
397
397
 
398
398
  // src/utils/fileSystem/fileSystem.ts
399
399
  function ensureCacheDirectories() {
400
- if (!fs4.existsSync(CACHE_DIR)) {
401
- fs4.mkdirSync(CACHE_DIR, { recursive: true });
400
+ if (!fs5.existsSync(CACHE_DIR)) {
401
+ fs5.mkdirSync(CACHE_DIR, { recursive: true });
402
402
  }
403
- if (!fs4.existsSync(SCREENSHOTS_DIR)) {
404
- fs4.mkdirSync(SCREENSHOTS_DIR, { recursive: true });
403
+ if (!fs5.existsSync(SCREENSHOTS_DIR)) {
404
+ fs5.mkdirSync(SCREENSHOTS_DIR, { recursive: true });
405
405
  }
406
406
  }
407
407
  function computeFileHash(filePath) {
408
- if (!fs4.existsSync(filePath)) {
408
+ if (!fs5.existsSync(filePath)) {
409
409
  return "";
410
410
  }
411
- const content = fs4.readFileSync(filePath, "utf-8");
411
+ const content = fs5.readFileSync(filePath, "utf-8");
412
412
  return crypto.createHash("sha256").update(content).digest("hex");
413
413
  }
414
414
  function loadManifest() {
415
- if (fs4.existsSync(MANIFEST_PATH)) {
416
- const content = fs4.readFileSync(MANIFEST_PATH, "utf-8");
415
+ if (fs5.existsSync(MANIFEST_PATH)) {
416
+ const content = fs5.readFileSync(MANIFEST_PATH, "utf-8");
417
417
  return JSON.parse(content);
418
418
  }
419
419
  return { stories: {} };
420
420
  }
421
421
  function saveManifest(manifest) {
422
422
  ensureCacheDirectories();
423
- fs4.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2));
423
+ fs5.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2));
424
424
  }
425
425
  function updateManifest(storyId, sourcePath, fileHash, boundingBox) {
426
426
  const manifest = loadManifest();
@@ -510,8 +510,8 @@ async function getBrowser() {
510
510
  return browserPromise;
511
511
  }
512
512
  function getScreenshotPath(storyId, theme) {
513
- const storyDir = path6.join(SCREENSHOTS_DIR, storyId);
514
- return path6.join(storyDir, `${theme}.png`);
513
+ const storyDir = path7.join(SCREENSHOTS_DIR, storyId);
514
+ return path7.join(storyDir, `${theme}.png`);
515
515
  }
516
516
  async function captureScreenshotBuffer(storyId, theme, width = VIEWPORT_WIDTH, height = VIEWPORT_HEIGHT, storybookUrl = "http://localhost:6006", timeoutMs = 3e4) {
517
517
  const browser = await getBrowser();
@@ -598,9 +598,9 @@ async function captureScreenshotBuffer(storyId, theme, width = VIEWPORT_WIDTH, h
598
598
  async function generateScreenshot(storyId, theme, storybookUrl = "http://localhost:6006", timeoutMs = 3e4) {
599
599
  try {
600
600
  ensureCacheDirectories();
601
- const storyDir = path6.join(SCREENSHOTS_DIR, storyId);
602
- if (!fs4.existsSync(storyDir)) {
603
- fs4.mkdirSync(storyDir, { recursive: true });
601
+ const storyDir = path7.join(SCREENSHOTS_DIR, storyId);
602
+ if (!fs5.existsSync(storyDir)) {
603
+ fs5.mkdirSync(storyDir, { recursive: true });
604
604
  }
605
605
  const screenshotPath = getScreenshotPath(storyId, theme);
606
606
  const { buffer, boundingBox } = await captureScreenshotBuffer(
@@ -611,7 +611,7 @@ async function generateScreenshot(storyId, theme, storybookUrl = "http://localho
611
611
  storybookUrl,
612
612
  timeoutMs
613
613
  );
614
- fs4.writeFileSync(screenshotPath, buffer);
614
+ fs5.writeFileSync(screenshotPath, buffer);
615
615
  return { path: screenshotPath, boundingBox };
616
616
  } catch (error) {
617
617
  console.error(`Error generating screenshot for ${storyId} (${theme}):`, error);
@@ -719,7 +719,7 @@ async function fetchStorybookIndex() {
719
719
  }
720
720
  function getStoriesForFile(filePath) {
721
721
  if (!cachedIndex) return [];
722
- const fileName = path6.basename(filePath);
722
+ const fileName = path7.basename(filePath);
723
723
  return Object.values(cachedIndex.entries).filter((entry) => entry.type === "story" && entry.importPath.endsWith(fileName)).map((entry) => entry.id);
724
724
  }
725
725
  async function regenerateScreenshotsForFiles(files) {
@@ -891,13 +891,115 @@ function softStoryRerenderPlugin() {
891
891
  preview.onStoriesChanged({ importFn: newModule.importFn });
892
892
  }
893
893
  });`;
894
- const out = code.replace(pattern, (_match, quote, path7) => {
895
- return replacement.replace("$QUOTE$$PATH$$QUOTE$", `${quote}${path7}${quote}`);
894
+ const out = code.replace(pattern, (_match, quote, path8) => {
895
+ return replacement.replace("$QUOTE$$PATH$$QUOTE$", `${quote}${path8}${quote}`);
896
896
  });
897
897
  return out === code ? null : { code: out, map: null };
898
898
  }
899
899
  };
900
900
  }
901
+ var TSCONFIG_CANDIDATES = ["tsconfig.json", "tsconfig.app.json", "tsconfig.base.json"];
902
+ function resolveTsconfigAliases(root) {
903
+ try {
904
+ const config = readTsconfigAliasConfig(root);
905
+ if (!config) return [];
906
+ const base = path7.resolve(root, config.baseUrl ?? ".");
907
+ const aliases = [];
908
+ for (const [key, targets] of Object.entries(config.paths)) {
909
+ const target = targets[0];
910
+ if (!target) continue;
911
+ if (key.endsWith("/*") && target.endsWith("/*")) {
912
+ const findPrefix = key.slice(0, -1);
913
+ const targetDir = path7.resolve(base, target.slice(0, -2));
914
+ aliases.push({
915
+ find: new RegExp(`^${escapeRegExp(findPrefix)}`),
916
+ replacement: `${targetDir}/`
917
+ });
918
+ } else if (!key.includes("*") && !target.includes("*")) {
919
+ aliases.push({
920
+ find: new RegExp(`^${escapeRegExp(key)}$`),
921
+ replacement: path7.resolve(base, target)
922
+ });
923
+ }
924
+ }
925
+ return aliases.sort((a, b) => b.find.source.length - a.find.source.length);
926
+ } catch {
927
+ return [];
928
+ }
929
+ }
930
+ function readTsconfigAliasConfig(root) {
931
+ for (const candidate of TSCONFIG_CANDIDATES) {
932
+ const abs = path7.join(root, candidate);
933
+ let text;
934
+ try {
935
+ text = fs5.readFileSync(abs, "utf-8");
936
+ } catch {
937
+ continue;
938
+ }
939
+ let parsed;
940
+ try {
941
+ parsed = JSON.parse(stripJsonComments(text));
942
+ } catch {
943
+ continue;
944
+ }
945
+ const paths = parsed.compilerOptions?.paths;
946
+ if (paths && typeof paths === "object" && Object.keys(paths).length > 0) {
947
+ const baseUrl = parsed.compilerOptions?.baseUrl;
948
+ return typeof baseUrl === "string" ? { baseUrl, paths } : { paths };
949
+ }
950
+ }
951
+ return null;
952
+ }
953
+ function escapeRegExp(value) {
954
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
955
+ }
956
+ function stripJsonComments(text) {
957
+ let out = "";
958
+ let inString = false;
959
+ let inLine = false;
960
+ let inBlock = false;
961
+ for (let i = 0; i < text.length; i++) {
962
+ const c = text.charAt(i);
963
+ const next = text.charAt(i + 1);
964
+ if (inLine) {
965
+ if (c === "\n") {
966
+ inLine = false;
967
+ out += c;
968
+ }
969
+ continue;
970
+ }
971
+ if (inBlock) {
972
+ if (c === "*" && next === "/") {
973
+ inBlock = false;
974
+ i++;
975
+ }
976
+ continue;
977
+ }
978
+ if (inString) {
979
+ out += c;
980
+ if (c === "\\") {
981
+ out += next;
982
+ i++;
983
+ } else if (c === '"') {
984
+ inString = false;
985
+ }
986
+ continue;
987
+ }
988
+ if (c === '"') {
989
+ inString = true;
990
+ out += c;
991
+ } else if (c === "/" && next === "/") {
992
+ inLine = true;
993
+ i++;
994
+ } else if (c === "/" && next === "*") {
995
+ inBlock = true;
996
+ i++;
997
+ } else {
998
+ out += c;
999
+ }
1000
+ }
1001
+ return out;
1002
+ }
901
1003
  function findGitRoot(startPath) {
902
1004
  let currentPath = startPath;
903
1005
  while (currentPath !== dirname(currentPath)) {
@@ -924,8 +1026,8 @@ var manifestCache = null;
924
1026
  var manifestHash = null;
925
1027
  function readManifestFromDisk(filePath) {
926
1028
  try {
927
- if (!fs4.existsSync(filePath)) return null;
928
- const raw = fs4.readFileSync(filePath, "utf-8");
1029
+ if (!fs5.existsSync(filePath)) return null;
1030
+ const raw = fs5.readFileSync(filePath, "utf-8");
929
1031
  const hash = createHash("sha1").update(raw).digest("hex");
930
1032
  const manifest = JSON.parse(raw);
931
1033
  return { manifest, hash };
@@ -968,10 +1070,10 @@ var TAILWIND_ENTRY_CANDIDATES = [
968
1070
  var TAILWIND_DIRECTIVE_PATTERN = /@import\s+['"](?:tailwindcss|tailwindcss\/.+)['"]|@tailwind\s+(?:base|components|utilities)/;
969
1071
  function detectTailwindEntryCss(cwd) {
970
1072
  for (const rel of TAILWIND_ENTRY_CANDIDATES) {
971
- const abs = path6.join(cwd, rel);
1073
+ const abs = path7.join(cwd, rel);
972
1074
  try {
973
- if (!fs4.existsSync(abs)) continue;
974
- const head = fs4.readFileSync(abs, "utf-8").slice(0, 2048);
1075
+ if (!fs5.existsSync(abs)) continue;
1076
+ const head = fs5.readFileSync(abs, "utf-8").slice(0, 2048);
975
1077
  if (TAILWIND_DIRECTIVE_PATTERN.test(head)) return abs;
976
1078
  } catch {
977
1079
  }
@@ -1099,7 +1201,7 @@ var serveMetadataAndScreenshots = (req, res, next) => {
1099
1201
  return;
1100
1202
  }
1101
1203
  if (req.url?.startsWith("/screenshots/")) {
1102
- const screenshotPath = path6.join(
1204
+ const screenshotPath = path7.join(
1103
1205
  process.cwd(),
1104
1206
  ".storybook-cache",
1105
1207
  req.url.replace("/screenshots/", "screenshots/")
@@ -1108,11 +1210,11 @@ var serveMetadataAndScreenshots = (req, res, next) => {
1108
1210
  const storyId = urlParts[0];
1109
1211
  const themeFile = urlParts[1];
1110
1212
  const theme = themeFile?.replace(".png", "");
1111
- if (fs4.existsSync(screenshotPath)) {
1213
+ if (fs5.existsSync(screenshotPath)) {
1112
1214
  res.setHeader("Content-Type", "image/png");
1113
1215
  res.setHeader("Access-Control-Allow-Origin", "*");
1114
1216
  res.setHeader("Cache-Control", "public, max-age=3600");
1115
- fs4.createReadStream(screenshotPath).pipe(res);
1217
+ fs5.createReadStream(screenshotPath).pipe(res);
1116
1218
  return;
1117
1219
  }
1118
1220
  if (storyId && theme && (theme === "light" || theme === "dark")) {
@@ -1120,16 +1222,16 @@ var serveMetadataAndScreenshots = (req, res, next) => {
1120
1222
  `[STORYBOOK_PLUGIN] Generating screenshot on-demand: ${storyId}/${theme}`
1121
1223
  );
1122
1224
  captureScreenshotBuffer(storyId, theme).then(({ buffer }) => {
1123
- const storyDir = path6.join(
1225
+ const storyDir = path7.join(
1124
1226
  process.cwd(),
1125
1227
  ".storybook-cache",
1126
1228
  "screenshots",
1127
1229
  storyId
1128
1230
  );
1129
- if (!fs4.existsSync(storyDir)) {
1130
- fs4.mkdirSync(storyDir, { recursive: true });
1231
+ if (!fs5.existsSync(storyDir)) {
1232
+ fs5.mkdirSync(storyDir, { recursive: true });
1131
1233
  }
1132
- fs4.writeFileSync(screenshotPath, buffer);
1234
+ fs5.writeFileSync(screenshotPath, buffer);
1133
1235
  res.setHeader("Content-Type", "image/png");
1134
1236
  res.setHeader("Access-Control-Allow-Origin", "*");
1135
1237
  res.setHeader("Cache-Control", "public, max-age=3600");
@@ -1203,10 +1305,20 @@ function storybookOnlookPlugin(options = {}) {
1203
1305
  repoRoot,
1204
1306
  hmr: hmrOverride ?? null
1205
1307
  });
1308
+ const aliasEntries = options.resolveAliases === false ? [] : resolveTsconfigAliases(process.cwd());
1309
+ if (aliasEntries.length > 0) {
1310
+ console.log("[STORYBOOK_PLUGIN] Resolved tsconfig path aliases", {
1311
+ count: aliasEntries.length,
1312
+ aliases: aliasEntries.map((a) => a.find.source)
1313
+ });
1314
+ }
1206
1315
  const mainPlugin = {
1207
1316
  name: "storybook-onlook-plugin",
1208
1317
  config() {
1209
1318
  return {
1319
+ ...aliasEntries.length > 0 && {
1320
+ resolve: { alias: aliasEntries }
1321
+ },
1210
1322
  server: {
1211
1323
  // HMR override applies only when the caller explicitly opts in
1212
1324
  // (typically: Storybook fronted over HTTPS by a reverse proxy).
@@ -1227,7 +1339,7 @@ function storybookOnlookPlugin(options = {}) {
1227
1339
  configureServer(server) {
1228
1340
  console.log("[STORYBOOK_PLUGIN] Configuring server middleware");
1229
1341
  server.middlewares.use(serveMetadataAndScreenshots);
1230
- const cachedManifestPath = path6.join(
1342
+ const cachedManifestPath = path7.join(
1231
1343
  process.cwd(),
1232
1344
  ".storybook-cache",
1233
1345
  "manifest.json"
@@ -1246,7 +1358,7 @@ function storybookOnlookPlugin(options = {}) {
1246
1358
  server.watcher.on("change", scheduleRefresh);
1247
1359
  const storyGlobs = options.storyGlobs ?? ["**/*.stories.@(js|jsx|mjs|ts|tsx|mdx)"];
1248
1360
  const resolvedStoryGlobs = storyGlobs.map(
1249
- (glob) => path6.isAbsolute(glob) ? glob : path6.join(process.cwd(), glob)
1361
+ (glob) => path7.isAbsolute(glob) ? glob : path7.join(process.cwd(), glob)
1250
1362
  );
1251
1363
  if (resolvedStoryGlobs.length > 0) {
1252
1364
  server.watcher.add(resolvedStoryGlobs);
@@ -1257,7 +1369,7 @@ function storybookOnlookPlugin(options = {}) {
1257
1369
  const tailwindEntryPath = (() => {
1258
1370
  if (options.tailwindEntryCss === false) return null;
1259
1371
  if (typeof options.tailwindEntryCss === "string") {
1260
- return path6.isAbsolute(options.tailwindEntryCss) ? options.tailwindEntryCss : path6.join(process.cwd(), options.tailwindEntryCss);
1372
+ return path7.isAbsolute(options.tailwindEntryCss) ? options.tailwindEntryCss : path7.join(process.cwd(), options.tailwindEntryCss);
1261
1373
  }
1262
1374
  return detectTailwindEntryCss(process.cwd());
1263
1375
  })();
@@ -1273,13 +1385,13 @@ function storybookOnlookPlugin(options = {}) {
1273
1385
  });
1274
1386
  server.watcher.on("add", (file) => {
1275
1387
  if (!/\.tsx?$/.test(file)) return;
1276
- const dir = path6.dirname(file);
1388
+ const dir = path7.dirname(file);
1277
1389
  const isNewDir = !seenDirs.has(dir);
1278
1390
  seenDirs.add(dir);
1279
1391
  if (!watcherReady || !isNewDir) return;
1280
1392
  try {
1281
1393
  const now = /* @__PURE__ */ new Date();
1282
- fs4.utimesSync(tailwindEntryPath, now, now);
1394
+ fs5.utimesSync(tailwindEntryPath, now, now);
1283
1395
  console.log("[STORYBOOK_PLUGIN] Tailwind rescan for new dir", {
1284
1396
  dir,
1285
1397
  entry: tailwindEntryPath
@@ -1304,7 +1416,7 @@ function storybookOnlookPlugin(options = {}) {
1304
1416
  configurePreviewServer(server) {
1305
1417
  console.log("[STORYBOOK_PLUGIN] Configuring preview server middleware");
1306
1418
  server.middlewares.use(serveMetadataAndScreenshots);
1307
- refreshManifest(path6.join(process.cwd(), ".storybook-cache", "manifest.json"));
1419
+ refreshManifest(path7.join(process.cwd(), ".storybook-cache", "manifest.json"));
1308
1420
  },
1309
1421
  handleHotUpdate: handleStoryFileChange
1310
1422
  };
@@ -1,4 +1,4 @@
1
- import { O as OnlookPluginOptions } from '../storybook-onlook-plugin-CigILdDb.js';
1
+ import { O as OnlookPluginOptions } from '../storybook-onlook-plugin-B9Eo_OIq.js';
2
2
  import 'vite';
3
3
 
4
4
  declare function pluginOptionsFromPresetOptions(options: Record<string, unknown> | undefined): OnlookPluginOptions;
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import crypto, { createHash } from 'crypto';
3
- import fs4, { existsSync } from 'fs';
4
- import path6, { dirname, join, relative } from 'path';
3
+ import fs5, { existsSync } from 'fs';
4
+ import path7, { dirname, join, relative } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import generateModule from '@babel/generator';
7
7
  import { parse } from '@babel/parser';
@@ -36,7 +36,7 @@ function componentLocPlugin(options = {}) {
36
36
  sourceFilename: filepath
37
37
  });
38
38
  let mutated = false;
39
- const relativePath = path6.relative(root, filepath);
39
+ const relativePath = path7.relative(root, filepath);
40
40
  traverse(ast, {
41
41
  JSXElement(nodePath) {
42
42
  const opening = nodePath.node.openingElement;
@@ -114,7 +114,7 @@ function envContainmentPlugin(options) {
114
114
  const resolveOutcomes = /* @__PURE__ */ new Map();
115
115
  const roots = /* @__PURE__ */ new Set([normalizeSlashes(process.cwd())]);
116
116
  const matchTarget = (absPath) => {
117
- const norm = normalizeSlashes(path6.normalize(absPath));
117
+ const norm = normalizeSlashes(path7.normalize(absPath));
118
118
  for (const rel of byModule.keys()) {
119
119
  for (const root of roots) {
120
120
  const target = `${root}/${rel}`;
@@ -149,10 +149,10 @@ function envContainmentPlugin(options) {
149
149
  if (source.startsWith("\0")) return null;
150
150
  const cleaned = stripQuery(source);
151
151
  let direct = null;
152
- if (path6.isAbsolute(cleaned)) {
152
+ if (path7.isAbsolute(cleaned)) {
153
153
  direct = cleaned;
154
154
  } else if (importer && (cleaned.startsWith("./") || cleaned.startsWith("../"))) {
155
- direct = path6.resolve(path6.dirname(stripQuery(importer)), cleaned);
155
+ direct = path7.resolve(path7.dirname(stripQuery(importer)), cleaned);
156
156
  }
157
157
  if (direct) {
158
158
  const rel = matchTarget(direct);
@@ -161,7 +161,7 @@ function envContainmentPlugin(options) {
161
161
  }
162
162
  if (!specifierMightMatch(cleaned)) return null;
163
163
  if (typeof this.resolve !== "function") return null;
164
- const importerDir = importer ? path6.dirname(stripQuery(importer)) : "";
164
+ const importerDir = importer ? path7.dirname(stripQuery(importer)) : "";
165
165
  const outcomeKey = `${importerDir}|${source}`;
166
166
  const memoized = resolveOutcomes.get(outcomeKey);
167
167
  if (memoized !== void 0) return memoized;
@@ -264,9 +264,9 @@ function fastRefreshTolerantExportsPlugin() {
264
264
  }
265
265
  };
266
266
  }
267
- var CACHE_DIR = path6.join(process.cwd(), ".storybook-cache");
268
- var SCREENSHOTS_DIR = path6.join(CACHE_DIR, "screenshots");
269
- var MANIFEST_PATH = path6.join(CACHE_DIR, "manifest.json");
267
+ var CACHE_DIR = path7.join(process.cwd(), ".storybook-cache");
268
+ var SCREENSHOTS_DIR = path7.join(CACHE_DIR, "screenshots");
269
+ var MANIFEST_PATH = path7.join(CACHE_DIR, "manifest.json");
270
270
  var VIEWPORT_WIDTH = 1920;
271
271
  var VIEWPORT_HEIGHT = 1080;
272
272
  var MIN_COMPONENT_WIDTH = 420;
@@ -274,30 +274,30 @@ var MIN_COMPONENT_HEIGHT = 280;
274
274
 
275
275
  // src/utils/fileSystem/fileSystem.ts
276
276
  function ensureCacheDirectories() {
277
- if (!fs4.existsSync(CACHE_DIR)) {
278
- fs4.mkdirSync(CACHE_DIR, { recursive: true });
277
+ if (!fs5.existsSync(CACHE_DIR)) {
278
+ fs5.mkdirSync(CACHE_DIR, { recursive: true });
279
279
  }
280
- if (!fs4.existsSync(SCREENSHOTS_DIR)) {
281
- fs4.mkdirSync(SCREENSHOTS_DIR, { recursive: true });
280
+ if (!fs5.existsSync(SCREENSHOTS_DIR)) {
281
+ fs5.mkdirSync(SCREENSHOTS_DIR, { recursive: true });
282
282
  }
283
283
  }
284
284
  function computeFileHash(filePath) {
285
- if (!fs4.existsSync(filePath)) {
285
+ if (!fs5.existsSync(filePath)) {
286
286
  return "";
287
287
  }
288
- const content = fs4.readFileSync(filePath, "utf-8");
288
+ const content = fs5.readFileSync(filePath, "utf-8");
289
289
  return crypto.createHash("sha256").update(content).digest("hex");
290
290
  }
291
291
  function loadManifest() {
292
- if (fs4.existsSync(MANIFEST_PATH)) {
293
- const content = fs4.readFileSync(MANIFEST_PATH, "utf-8");
292
+ if (fs5.existsSync(MANIFEST_PATH)) {
293
+ const content = fs5.readFileSync(MANIFEST_PATH, "utf-8");
294
294
  return JSON.parse(content);
295
295
  }
296
296
  return { stories: {} };
297
297
  }
298
298
  function saveManifest(manifest) {
299
299
  ensureCacheDirectories();
300
- fs4.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2));
300
+ fs5.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2));
301
301
  }
302
302
  function updateManifest(storyId, sourcePath, fileHash, boundingBox) {
303
303
  const manifest = loadManifest();
@@ -387,8 +387,8 @@ async function getBrowser() {
387
387
  return browserPromise;
388
388
  }
389
389
  function getScreenshotPath(storyId, theme) {
390
- const storyDir = path6.join(SCREENSHOTS_DIR, storyId);
391
- return path6.join(storyDir, `${theme}.png`);
390
+ const storyDir = path7.join(SCREENSHOTS_DIR, storyId);
391
+ return path7.join(storyDir, `${theme}.png`);
392
392
  }
393
393
  async function captureScreenshotBuffer(storyId, theme, width = VIEWPORT_WIDTH, height = VIEWPORT_HEIGHT, storybookUrl = "http://localhost:6006", timeoutMs = 3e4) {
394
394
  const browser = await getBrowser();
@@ -475,9 +475,9 @@ async function captureScreenshotBuffer(storyId, theme, width = VIEWPORT_WIDTH, h
475
475
  async function generateScreenshot(storyId, theme, storybookUrl = "http://localhost:6006", timeoutMs = 3e4) {
476
476
  try {
477
477
  ensureCacheDirectories();
478
- const storyDir = path6.join(SCREENSHOTS_DIR, storyId);
479
- if (!fs4.existsSync(storyDir)) {
480
- fs4.mkdirSync(storyDir, { recursive: true });
478
+ const storyDir = path7.join(SCREENSHOTS_DIR, storyId);
479
+ if (!fs5.existsSync(storyDir)) {
480
+ fs5.mkdirSync(storyDir, { recursive: true });
481
481
  }
482
482
  const screenshotPath = getScreenshotPath(storyId, theme);
483
483
  const { buffer, boundingBox } = await captureScreenshotBuffer(
@@ -488,7 +488,7 @@ async function generateScreenshot(storyId, theme, storybookUrl = "http://localho
488
488
  storybookUrl,
489
489
  timeoutMs
490
490
  );
491
- fs4.writeFileSync(screenshotPath, buffer);
491
+ fs5.writeFileSync(screenshotPath, buffer);
492
492
  return { path: screenshotPath, boundingBox };
493
493
  } catch (error) {
494
494
  console.error(`Error generating screenshot for ${storyId} (${theme}):`, error);
@@ -596,7 +596,7 @@ async function fetchStorybookIndex() {
596
596
  }
597
597
  function getStoriesForFile(filePath) {
598
598
  if (!cachedIndex) return [];
599
- const fileName = path6.basename(filePath);
599
+ const fileName = path7.basename(filePath);
600
600
  return Object.values(cachedIndex.entries).filter((entry) => entry.type === "story" && entry.importPath.endsWith(fileName)).map((entry) => entry.id);
601
601
  }
602
602
  async function regenerateScreenshotsForFiles(files) {
@@ -884,13 +884,115 @@ function softStoryRerenderPlugin() {
884
884
  preview.onStoriesChanged({ importFn: newModule.importFn });
885
885
  }
886
886
  });`;
887
- const out = code.replace(pattern, (_match, quote, path7) => {
888
- return replacement.replace("$QUOTE$$PATH$$QUOTE$", `${quote}${path7}${quote}`);
887
+ const out = code.replace(pattern, (_match, quote, path8) => {
888
+ return replacement.replace("$QUOTE$$PATH$$QUOTE$", `${quote}${path8}${quote}`);
889
889
  });
890
890
  return out === code ? null : { code: out, map: null };
891
891
  }
892
892
  };
893
893
  }
894
+ var TSCONFIG_CANDIDATES = ["tsconfig.json", "tsconfig.app.json", "tsconfig.base.json"];
895
+ function resolveTsconfigAliases(root) {
896
+ try {
897
+ const config = readTsconfigAliasConfig(root);
898
+ if (!config) return [];
899
+ const base = path7.resolve(root, config.baseUrl ?? ".");
900
+ const aliases = [];
901
+ for (const [key, targets] of Object.entries(config.paths)) {
902
+ const target = targets[0];
903
+ if (!target) continue;
904
+ if (key.endsWith("/*") && target.endsWith("/*")) {
905
+ const findPrefix = key.slice(0, -1);
906
+ const targetDir = path7.resolve(base, target.slice(0, -2));
907
+ aliases.push({
908
+ find: new RegExp(`^${escapeRegExp(findPrefix)}`),
909
+ replacement: `${targetDir}/`
910
+ });
911
+ } else if (!key.includes("*") && !target.includes("*")) {
912
+ aliases.push({
913
+ find: new RegExp(`^${escapeRegExp(key)}$`),
914
+ replacement: path7.resolve(base, target)
915
+ });
916
+ }
917
+ }
918
+ return aliases.sort((a, b) => b.find.source.length - a.find.source.length);
919
+ } catch {
920
+ return [];
921
+ }
922
+ }
923
+ function readTsconfigAliasConfig(root) {
924
+ for (const candidate of TSCONFIG_CANDIDATES) {
925
+ const abs = path7.join(root, candidate);
926
+ let text;
927
+ try {
928
+ text = fs5.readFileSync(abs, "utf-8");
929
+ } catch {
930
+ continue;
931
+ }
932
+ let parsed;
933
+ try {
934
+ parsed = JSON.parse(stripJsonComments(text));
935
+ } catch {
936
+ continue;
937
+ }
938
+ const paths = parsed.compilerOptions?.paths;
939
+ if (paths && typeof paths === "object" && Object.keys(paths).length > 0) {
940
+ const baseUrl = parsed.compilerOptions?.baseUrl;
941
+ return typeof baseUrl === "string" ? { baseUrl, paths } : { paths };
942
+ }
943
+ }
944
+ return null;
945
+ }
946
+ function escapeRegExp(value) {
947
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
948
+ }
949
+ function stripJsonComments(text) {
950
+ let out = "";
951
+ let inString = false;
952
+ let inLine = false;
953
+ let inBlock = false;
954
+ for (let i = 0; i < text.length; i++) {
955
+ const c = text.charAt(i);
956
+ const next = text.charAt(i + 1);
957
+ if (inLine) {
958
+ if (c === "\n") {
959
+ inLine = false;
960
+ out += c;
961
+ }
962
+ continue;
963
+ }
964
+ if (inBlock) {
965
+ if (c === "*" && next === "/") {
966
+ inBlock = false;
967
+ i++;
968
+ }
969
+ continue;
970
+ }
971
+ if (inString) {
972
+ out += c;
973
+ if (c === "\\") {
974
+ out += next;
975
+ i++;
976
+ } else if (c === '"') {
977
+ inString = false;
978
+ }
979
+ continue;
980
+ }
981
+ if (c === '"') {
982
+ inString = true;
983
+ out += c;
984
+ } else if (c === "/" && next === "/") {
985
+ inLine = true;
986
+ i++;
987
+ } else if (c === "/" && next === "*") {
988
+ inBlock = true;
989
+ i++;
990
+ } else {
991
+ out += c;
992
+ }
993
+ }
994
+ return out;
995
+ }
894
996
  function findGitRoot(startPath) {
895
997
  let currentPath = startPath;
896
998
  while (currentPath !== dirname(currentPath)) {
@@ -917,8 +1019,8 @@ var manifestCache = null;
917
1019
  var manifestHash = null;
918
1020
  function readManifestFromDisk(filePath) {
919
1021
  try {
920
- if (!fs4.existsSync(filePath)) return null;
921
- const raw = fs4.readFileSync(filePath, "utf-8");
1022
+ if (!fs5.existsSync(filePath)) return null;
1023
+ const raw = fs5.readFileSync(filePath, "utf-8");
922
1024
  const hash = createHash("sha1").update(raw).digest("hex");
923
1025
  const manifest = JSON.parse(raw);
924
1026
  return { manifest, hash };
@@ -961,10 +1063,10 @@ var TAILWIND_ENTRY_CANDIDATES = [
961
1063
  var TAILWIND_DIRECTIVE_PATTERN = /@import\s+['"](?:tailwindcss|tailwindcss\/.+)['"]|@tailwind\s+(?:base|components|utilities)/;
962
1064
  function detectTailwindEntryCss(cwd) {
963
1065
  for (const rel of TAILWIND_ENTRY_CANDIDATES) {
964
- const abs = path6.join(cwd, rel);
1066
+ const abs = path7.join(cwd, rel);
965
1067
  try {
966
- if (!fs4.existsSync(abs)) continue;
967
- const head = fs4.readFileSync(abs, "utf-8").slice(0, 2048);
1068
+ if (!fs5.existsSync(abs)) continue;
1069
+ const head = fs5.readFileSync(abs, "utf-8").slice(0, 2048);
968
1070
  if (TAILWIND_DIRECTIVE_PATTERN.test(head)) return abs;
969
1071
  } catch {
970
1072
  }
@@ -1092,7 +1194,7 @@ var serveMetadataAndScreenshots = (req, res, next) => {
1092
1194
  return;
1093
1195
  }
1094
1196
  if (req.url?.startsWith("/screenshots/")) {
1095
- const screenshotPath = path6.join(
1197
+ const screenshotPath = path7.join(
1096
1198
  process.cwd(),
1097
1199
  ".storybook-cache",
1098
1200
  req.url.replace("/screenshots/", "screenshots/")
@@ -1101,11 +1203,11 @@ var serveMetadataAndScreenshots = (req, res, next) => {
1101
1203
  const storyId = urlParts[0];
1102
1204
  const themeFile = urlParts[1];
1103
1205
  const theme = themeFile?.replace(".png", "");
1104
- if (fs4.existsSync(screenshotPath)) {
1206
+ if (fs5.existsSync(screenshotPath)) {
1105
1207
  res.setHeader("Content-Type", "image/png");
1106
1208
  res.setHeader("Access-Control-Allow-Origin", "*");
1107
1209
  res.setHeader("Cache-Control", "public, max-age=3600");
1108
- fs4.createReadStream(screenshotPath).pipe(res);
1210
+ fs5.createReadStream(screenshotPath).pipe(res);
1109
1211
  return;
1110
1212
  }
1111
1213
  if (storyId && theme && (theme === "light" || theme === "dark")) {
@@ -1113,16 +1215,16 @@ var serveMetadataAndScreenshots = (req, res, next) => {
1113
1215
  `[STORYBOOK_PLUGIN] Generating screenshot on-demand: ${storyId}/${theme}`
1114
1216
  );
1115
1217
  captureScreenshotBuffer(storyId, theme).then(({ buffer }) => {
1116
- const storyDir = path6.join(
1218
+ const storyDir = path7.join(
1117
1219
  process.cwd(),
1118
1220
  ".storybook-cache",
1119
1221
  "screenshots",
1120
1222
  storyId
1121
1223
  );
1122
- if (!fs4.existsSync(storyDir)) {
1123
- fs4.mkdirSync(storyDir, { recursive: true });
1224
+ if (!fs5.existsSync(storyDir)) {
1225
+ fs5.mkdirSync(storyDir, { recursive: true });
1124
1226
  }
1125
- fs4.writeFileSync(screenshotPath, buffer);
1227
+ fs5.writeFileSync(screenshotPath, buffer);
1126
1228
  res.setHeader("Content-Type", "image/png");
1127
1229
  res.setHeader("Access-Control-Allow-Origin", "*");
1128
1230
  res.setHeader("Cache-Control", "public, max-age=3600");
@@ -1196,10 +1298,20 @@ function storybookOnlookPlugin(options = {}) {
1196
1298
  repoRoot,
1197
1299
  hmr: hmrOverride ?? null
1198
1300
  });
1301
+ const aliasEntries = options.resolveAliases === false ? [] : resolveTsconfigAliases(process.cwd());
1302
+ if (aliasEntries.length > 0) {
1303
+ console.log("[STORYBOOK_PLUGIN] Resolved tsconfig path aliases", {
1304
+ count: aliasEntries.length,
1305
+ aliases: aliasEntries.map((a) => a.find.source)
1306
+ });
1307
+ }
1199
1308
  const mainPlugin = {
1200
1309
  name: "storybook-onlook-plugin",
1201
1310
  config() {
1202
1311
  return {
1312
+ ...aliasEntries.length > 0 && {
1313
+ resolve: { alias: aliasEntries }
1314
+ },
1203
1315
  server: {
1204
1316
  // HMR override applies only when the caller explicitly opts in
1205
1317
  // (typically: Storybook fronted over HTTPS by a reverse proxy).
@@ -1220,7 +1332,7 @@ function storybookOnlookPlugin(options = {}) {
1220
1332
  configureServer(server) {
1221
1333
  console.log("[STORYBOOK_PLUGIN] Configuring server middleware");
1222
1334
  server.middlewares.use(serveMetadataAndScreenshots);
1223
- const cachedManifestPath = path6.join(
1335
+ const cachedManifestPath = path7.join(
1224
1336
  process.cwd(),
1225
1337
  ".storybook-cache",
1226
1338
  "manifest.json"
@@ -1239,7 +1351,7 @@ function storybookOnlookPlugin(options = {}) {
1239
1351
  server.watcher.on("change", scheduleRefresh);
1240
1352
  const storyGlobs = options.storyGlobs ?? ["**/*.stories.@(js|jsx|mjs|ts|tsx|mdx)"];
1241
1353
  const resolvedStoryGlobs = storyGlobs.map(
1242
- (glob) => path6.isAbsolute(glob) ? glob : path6.join(process.cwd(), glob)
1354
+ (glob) => path7.isAbsolute(glob) ? glob : path7.join(process.cwd(), glob)
1243
1355
  );
1244
1356
  if (resolvedStoryGlobs.length > 0) {
1245
1357
  server.watcher.add(resolvedStoryGlobs);
@@ -1250,7 +1362,7 @@ function storybookOnlookPlugin(options = {}) {
1250
1362
  const tailwindEntryPath = (() => {
1251
1363
  if (options.tailwindEntryCss === false) return null;
1252
1364
  if (typeof options.tailwindEntryCss === "string") {
1253
- return path6.isAbsolute(options.tailwindEntryCss) ? options.tailwindEntryCss : path6.join(process.cwd(), options.tailwindEntryCss);
1365
+ return path7.isAbsolute(options.tailwindEntryCss) ? options.tailwindEntryCss : path7.join(process.cwd(), options.tailwindEntryCss);
1254
1366
  }
1255
1367
  return detectTailwindEntryCss(process.cwd());
1256
1368
  })();
@@ -1266,13 +1378,13 @@ function storybookOnlookPlugin(options = {}) {
1266
1378
  });
1267
1379
  server.watcher.on("add", (file) => {
1268
1380
  if (!/\.tsx?$/.test(file)) return;
1269
- const dir = path6.dirname(file);
1381
+ const dir = path7.dirname(file);
1270
1382
  const isNewDir = !seenDirs.has(dir);
1271
1383
  seenDirs.add(dir);
1272
1384
  if (!watcherReady || !isNewDir) return;
1273
1385
  try {
1274
1386
  const now = /* @__PURE__ */ new Date();
1275
- fs4.utimesSync(tailwindEntryPath, now, now);
1387
+ fs5.utimesSync(tailwindEntryPath, now, now);
1276
1388
  console.log("[STORYBOOK_PLUGIN] Tailwind rescan for new dir", {
1277
1389
  dir,
1278
1390
  entry: tailwindEntryPath
@@ -1297,7 +1409,7 @@ function storybookOnlookPlugin(options = {}) {
1297
1409
  configurePreviewServer(server) {
1298
1410
  console.log("[STORYBOOK_PLUGIN] Configuring preview server middleware");
1299
1411
  server.middlewares.use(serveMetadataAndScreenshots);
1300
- refreshManifest(path6.join(process.cwd(), ".storybook-cache", "manifest.json"));
1412
+ refreshManifest(path7.join(process.cwd(), ".storybook-cache", "manifest.json"));
1301
1413
  },
1302
1414
  handleHotUpdate: handleStoryFileChange
1303
1415
  };
@@ -1324,7 +1436,8 @@ var OPTION_KEY_MAP = {
1324
1436
  storyGlobs: true,
1325
1437
  tailwindEntryCss: true,
1326
1438
  envContainment: true,
1327
- moduleLoadCatchAll: true
1439
+ moduleLoadCatchAll: true,
1440
+ resolveAliases: true
1328
1441
  };
1329
1442
  var OPTION_KEYS = Object.keys(OPTION_KEY_MAP);
1330
1443
  function pluginOptionsFromPresetOptions(options) {
@@ -55,6 +55,7 @@ type OnlookPluginOptions = {
55
55
  tailwindEntryCss?: string | false;
56
56
  envContainment?: EnvContainmentOptions;
57
57
  moduleLoadCatchAll?: boolean;
58
+ resolveAliases?: boolean;
58
59
  };
59
60
  declare function storybookOnlookPlugin(options?: OnlookPluginOptions): PluginOption[];
60
61
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlook/storybook-plugin",
3
- "version": "0.4.0-beta.10",
3
+ "version": "0.4.0-beta.11",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "onlook-storybook": "./dist/cli/index.js"