Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/knip/fixtures/plugins/ladle/.ladle/components.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { type GlobalProvider } from "@ladle/react";
import React from "react";

// For details see https://ladle.dev/docs/providers
export const Provider: GlobalProvider = ({ children }) => <div>{children}</div>;
6 changes: 6 additions & 0 deletions packages/knip/fixtures/plugins/ladle/.ladle/config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// For details see https://ladle.dev/docs/config
/** @type {import('@ladle/react').UserConfig} */
export default {
stories: "app/**/*.stories.{tsx,mdx}",
viteConfig: "./.ladle/vite.config.ts",
};
7 changes: 7 additions & 0 deletions packages/knip/fixtures/plugins/ladle/.ladle/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from "vite";

export default defineConfig({
server: {
open: false,
},
});
39 changes: 39 additions & 0 deletions packages/knip/fixtures/plugins/ladle/app/basic.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export const Hello = () => <h2>Simple Story</h2>;

export const Responsive = () => {
return (
<>
<div
style={{
width: '100',
background: '#000',
color: '#FFF',
padding: '32px 32px',
border: '1px solid black',
fontFamily: 'arial',
fontSize: 28,
}}
>
Header
</div>
<button
style={{
padding: '16px 102px',
fontFamily: 'arial',
fontSize: 22,
margin: 32,
borderRadius: 8,
color: '#174291',
border: '2px solid #174291',
background: '#FFF',
}}
>
Ladle v4
</button>
</>
);
};
Responsive.meta = {
width: 'xsmall',
};

37 changes: 37 additions & 0 deletions packages/knip/fixtures/plugins/ladle/app/control.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { Story } from "@ladle/react";

export const Controls: Story<{
label: string;
disabled: boolean;
count: number;
colors: string[];
variant: string;
size: string;
}> = ({ count, disabled, label, colors, variant, size }) => (
<>
<p>Count: {count}</p>
<p>Disabled: {disabled ? "yes" : "no"}</p>
<p>Label: {label}</p>
<p>Colors: {colors.join(",")}</p>
<p>Variant: {variant}</p>
<p>Size: {size}</p>
</>
);

Controls.args = {
label: "Hello world",
disabled: false,
count: 2,
colors: ["Red", "Blue"],
};
Controls.argTypes = {
variant: {
options: ["primary", "secondary"],
control: { type: "radio" },
defaultValue: "primary",
},
size: {
options: ["small", "medium", "big", "huuuuge"],
control: { type: "select" },
},
};
19 changes: 19 additions & 0 deletions packages/knip/fixtures/plugins/ladle/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "@fixtures/ladle",
"type": "module",
"scripts": {
"dev": "ladle serve --port 4123",
"build": "ladle build"
},
"dependencies": {
"@ladle/react": "*",
"react": "*",
"react-dom": "*"
},
"devDependencies": {
"@types/node": "*",
"@types/react": "*",
"@types/react-dom": "*",
"typescript": "*"
}
}
20 changes: 20 additions & 0 deletions packages/knip/fixtures/plugins/ladle/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"]
}
4 changes: 4 additions & 0 deletions packages/knip/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,10 @@
"title": "Jest plugin configuration (https://knip.dev/reference/plugins/jest)",
"$ref": "#/definitions/plugin"
},
"ladle": {
"title": "ladle plugin configuration (https://knip.dev/reference/plugins/ladle)",
"$ref": "#/definitions/plugin"
},
"lefthook": {
"title": "lefthook plugin configuration (https://knip.dev/reference/plugins/lefthook)",
"$ref": "#/definitions/plugin"
Expand Down
1 change: 1 addition & 0 deletions packages/knip/src/ConfigurationValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ const pluginsSchema = z.object({
'graphql-codegen': pluginSchema,
husky: pluginSchema,
jest: pluginSchema,
ladle: pluginSchema,
lefthook: pluginSchema,
'lint-staged': pluginSchema,
linthtml: pluginSchema,
Expand Down
1 change: 1 addition & 0 deletions packages/knip/src/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export { default as githubActions } from './github-actions/index.js';
export { default as graphqlCodegen } from './graphql-codegen/index.js';
export { default as husky } from './husky/index.js';
export { default as jest } from './jest/index.js';
export { default as ladle } from './ladle/index.js';
export { default as lefthook } from './lefthook/index.js';
export { default as linthtml } from './linthtml/index.js';
export { default as lintStaged } from './lint-staged/index.js';
Expand Down
43 changes: 43 additions & 0 deletions packages/knip/src/plugins/ladle/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { EnablerPatterns } from '#p/types/config.js';
import type { IsPluginEnabled, Plugin, ResolveConfig, ResolveEntryPaths } from '#p/types/plugins.js';
import { hasDependency, load } from '#p/util/plugin.js';
import type { LadleConfig } from './types.js';
import { toEntryPattern } from '../../util/protocols.js';
import { resolveConfig as resolveVitestConfig } from '../vitest/index.js';

// https://ladle.dev/docs/config

const title = 'ladle';

const enablers: EnablerPatterns = [/^@ladle\//];

const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);

const config = ['.ladle/config.{mjs,js,ts}'];

const stories: string[] = ['src/**/*.stories.{js,jsx,ts,tsx,mdx}'];
const restEntry: string[] = ['.ladle/components.{js,jsx,ts,tsx}'];
const entry: string[] = [...restEntry, ...stories];

const project = ['.ladle/**/*.{js,jsx,ts,tsx}'];

const resolveEntryPaths: ResolveEntryPaths<LadleConfig> = async localConfig => {
const localStories = typeof localConfig.stories === 'string' ? [localConfig.stories] : localConfig.stories;
const patterns = [...restEntry, ...(localStories ?? stories)];

return patterns.map(toEntryPattern);
};

const resolveConfig: ResolveConfig<LadleConfig> = async (localConfig, options) =>
localConfig.viteConfig ? resolveVitestConfig(await load(localConfig.viteConfig), options) : [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please expand it a bit and use something like join(options.configFileDir, localConfig.viteConfig) so that it is resolved relative the Ladle config file dir.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh never mind, now I read https://ladle.dev/docs/config/#viteconfig and see that the path should be absolute anyway (wasn't clear from the fixture).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, just the example uses an absolute path, I could not find something in the documentation stating that is has to be absolute.

I think it would be great to support both, so I now check if the path is already absolute and if not, I join it with options.cwd. (I did not check before what's inside options, so helpful 🤣 ).

At least on my machine with our config it now works like a charm :)


export default {
title,
enablers,
isEnabled,
config,
entry,
project,
resolveEntryPaths,
resolveConfig,
} satisfies Plugin;
4 changes: 4 additions & 0 deletions packages/knip/src/plugins/ladle/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type LadleConfig = {
stories?: string | string[];
viteConfig?: string;
};
31 changes: 31 additions & 0 deletions packages/knip/test/plugins/ladle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { test } from 'bun:test';
import assert from 'node:assert/strict';
import { main } from '../../src/index.js';
import { resolve } from '../../src/util/path.js';
import baseArguments from '../helpers/baseArguments.js';
import baseCounters from '../helpers/baseCounters.js';

const cwd = resolve('fixtures/plugins/ladle');

test('Find dependencies with the ladle plugin', async () => {
const { issues, counters } = await main({
...baseArguments,
cwd,
});

assert(issues.dependencies['package.json']['@ladle/react']);
assert(issues.dependencies['package.json']['react']);
assert(issues.dependencies['package.json']['react-dom']);
assert(issues.devDependencies['package.json']['@types/react']);
assert(issues.devDependencies['package.json']['@types/react-dom']);
assert(issues.binaries['package.json']['ladle']);

assert.deepEqual(counters, {
...baseCounters,
binaries: 1,
dependencies: 3,
devDependencies: 2,
processed: 0,
total: 0,
});
});