Skip to content

Commit

Permalink
fix: correctly load the storybook preview annotation (#726)
Browse files Browse the repository at this point in the history
<!---
☝️ PR title should follow conventional commits
(https://conventionalcommits.org)
-->

### 🔗 Linked issue

Fixes #718.

<!-- If it resolves an open issue, please link the issue here. For
example "Resolves #123" -->

### ❓ Type of change

<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply. -->

- [ ] 📖 Documentation (updates to the documentation or readme)
- [ ] 🐞 Bug fix (a non-breaking change that fixes an issue)
- [ ] 👌 Enhancement (improving an existing functionality)
- [ ] ✨ New feature (a non-breaking change that adds functionality)
- [ ] 🧹 Chore (updates to the build process or auxiliary tools and
libraries)
- [ ] ⚠️ Breaking change (fix or feature that would cause existing
functionality to change)

### 📚 Description


<!-- Describe your changes in detail -->
<!-- Why is this change required? What problem does it solve? -->
  • Loading branch information
tobiasdiez authored Aug 3, 2024
1 parent c83508a commit 07f2995
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 19 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dev": "pnpm run --filter=./playground/** dev",
"dev:prepare": "pnpm run --recursive --filter=./packages/* --parallel dev:prepare && pnpm run prepare",
"dev:build": "pnpm run --filter=./playground/** build",
"playground:storybook:dev": "pnpm run --filter=./playground/** storybook",
"playground:storybook:build": "cd playground && pnpm run build-storybook",
"playground:storybook:publish": "chromatic --exit-zero-on-changes --build-script-name playground:storybook:build --project-token=chpt_d7cf5e98426e11e",
"example:starter:dev": "pnpm run --filter=./examples/starter/** examples/starter dev",
Expand Down
4 changes: 2 additions & 2 deletions packages/storybook-addon/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"@storybook/vue3": "^8.2.7",
"@storybook/vue3-vite": "^8.2.7",
"json-stable-stringify": "^1.1.1",
"mlly": "^1.7.1",
"ofetch": "^1.3.4",
"pathe": "^1.1.2",
"unctx": "^2.3.1",
Expand All @@ -88,8 +89,7 @@
"typescript": "5.5.4",
"unbuild": "2.0.0",
"nuxt": "3.12.4",
"vue": "3.4.35",
"vite": "5.3.5"
"vue": "3.4.35"
},
"publishConfig": {
"access": "public"
Expand Down
103 changes: 89 additions & 14 deletions packages/storybook-addon/src/preset.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { dirname, join, resolve } from 'node:path'
import { dirname, join } from 'node:path'
import { fileURLToPath, pathToFileURL } from 'node:url'
import { createRequire } from 'node:module'
import { resolve, normalize } from 'pathe'
import { resolvePath } from 'mlly'

import type { PresetProperty } from '@storybook/types'
import type { PresetProperty, PreviewAnnotation } from '@storybook/types'
import {
type UserConfig as ViteConfig,
mergeConfig,
Expand Down Expand Up @@ -212,14 +214,92 @@ export const core: PresetProperty<'core', StorybookConfig> = async (
renderer: await getPackageDir('@storybook/vue3'),
}
}

export interface Resolver {
/**
* Resolves the given path segments to an absolute path, using the provided base path.
*
* The resulting path is normalized, and trailing slashes are removed unless the path gets resolved to the root directory.
*
* @param path A sequence of paths or path segments.
* @throws {TypeError} if any of the arguments is not a string.
*/
resolve(...path: string[]): string
/**
* Asynchronously resolves a module path to a local file path, using the provided base path.
*
* @param id - The identifier or path of the module to resolve.
* @returns A promise to resolve to the file path, or `null` if the module could not be resolved.
*/
resolveModule(
id: string,
options?: { paths?: string[] },
): Promise<string | null>
}
/**
* Creates a resolver that can resolve paths and modules relative to a base path.
*
* @example
* ```js
* const resolver = createResolver(import.meta.url)
* const path = resolver.resolve('preview')
* const modulePath = await resolver.resolveModule('module-name')
* ```
*
* @param base - The base path to resolve paths and modules relative to.
* @returns A resolver object.
*/
function createResolver(base: string | URL): Resolver {
if (!base) {
throw new Error('`base` argument is missing for createResolver(base)!')
}

base = base.toString()
if (base.startsWith('file://')) {
base = dirname(fileURLToPath(base))
}

return {
resolve: (...path) => resolve(base, ...path),
async resolveModule(id, options) {
const paths = options?.paths ?? [base]
paths.concat([base as string])
return await resolvePath(id, { url: paths }).catch(() => null)
},
}
}

/**
* This is needed to correctly load the `preview.js` file,
* see https://github.com/storybookjs/storybook/blob/main/docs/contribute/framework.md#4-author-the-framework-itself
*/
export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (
entry = [],
) => {
return [...entry, resolve(packageDir, 'preview')]
export const previewAnnotations = async (
entry: PreviewAnnotation[] = [],
): Promise<PreviewAnnotation[]> => {
const resolver = createResolver(import.meta.url)

// Problem: Storybook does not correctly resolve some modules to an absolute path to the correct deep path in node_modules.
// Solution:
// We need to make sure that they are resolved as dependencies of this package, since they are not installed in the root.
// We need to use bare here otherwise storybook will strip the absolute path, leading to a wrong import
// https://github.com/storybookjs/storybook/blob/3590a1cade2fe24608b3ce0246d5d58692c89883/code/builders/builder-vite/src/utils/process-preview-annotation.ts#L30-L35
return [
...entry.map((entry) => {
// Handle @storybook/vue3
if (typeof entry === 'string' && entry.includes('vue3')) {
return {
bare: normalize(entry),
absolute: '',
}
} else {
return entry
}
}),
{
bare: resolver.resolve('preview'),
absolute: '',
},
]
}

export const viteFinal: StorybookConfig['viteFinal'] = async (
Expand Down Expand Up @@ -263,17 +343,12 @@ export const viteFinal: StorybookConfig['viteFinal'] = async (
return finalViteConfig
}

async function getPackageDir(frameworkPackageName: string) {
async function getPackageDir(packageName: string) {
try {
const require = createRequire(import.meta.url)
const packageDir = dirname(
require.resolve(join(frameworkPackageName, 'package.json'), {
paths: [process.cwd()],
}),
)
return packageDir
return dirname(require.resolve(join(packageName, 'package.json')))
} catch (e) {
throw new Error(`Cannot find ${frameworkPackageName}`, { cause: e })
throw new Error(`Cannot find ${packageName}`, { cause: e })
}
}

Expand Down
9 changes: 6 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 07f2995

Please sign in to comment.