Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ladle plugin #728

Merged
merged 16 commits into from
Jul 22, 2024
Merged
1 change: 0 additions & 1 deletion .bun-version

This file was deleted.

3 changes: 1 addition & 2 deletions .github/workflows/ci-bun.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: '.bun-version'
- run: bun upgrade --canary
- name: Install dependencies
run: bun install --ignore-scripts --frozen-lockfile
- name: Run formatter, linter, import sorter
Expand Down
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
2 changes: 1 addition & 1 deletion packages/knip/src/binaries/resolvers/bun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import parseArgs from 'minimist';
import type { Resolver } from '../types.js';
import { tryResolveFilePath } from '../util.js';

const commands = ['add', 'create', 'init', 'install', 'link', 'pm', 'remove', 'run', 'test', 'update'];
const commands = ['add', 'create', 'init', 'install', 'link', 'pm', 'remove', 'run', 'test', 'update', 'upgrade'];

export const resolve: Resolver = (_binary, args, { manifestScriptNames, cwd, fromArgs }) => {
const parsed = parseArgs(args);
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
50 changes: 50 additions & 0 deletions packages/knip/src/plugins/ladle/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { EnablerPatterns } from '#p/types/config.js';
import type { IsPluginEnabled, Plugin, ResolveConfig, ResolveEntryPaths } from '#p/types/plugins.js';
import { toAbsolute } from '#p/util/path.js';
import { hasDependency, load } from '#p/util/plugin.js';
import { toEntryPattern } from '../../util/protocols.js';
import { resolveConfig as resolveVitestConfig } from '../vitest/index.js';
import type { LadleConfig } from './types.js';

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

const title = 'Ladle';

const enablers: EnablerPatterns = ['@ladle/react'];

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

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

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

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

const resolveEntryPaths: ResolveEntryPaths<LadleConfig> = (localConfig, options) => {
const localStories = typeof localConfig.stories === 'string' ? [localConfig.stories] : localConfig.stories;
const viteConfig = localConfig.viteConfig ? [toAbsolute(localConfig.viteConfig, options.cwd)] : [];
const patterns = [...restEntry, ...(localStories ?? stories), ...viteConfig];
return patterns.map(toEntryPattern);
};

const resolveConfig: ResolveConfig<LadleConfig> = async (localConfig, options) => {
if (localConfig.viteConfig) {
const viteConfigPath = toAbsolute(localConfig.viteConfig, options.cwd);
const viteConfig = await load(viteConfigPath);
return resolveVitestConfig(viteConfig, options);
}
return [];
};

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;
};
30 changes: 30 additions & 0 deletions packages/knip/test/plugins/ladle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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']['react-dom']);
assert(issues.devDependencies['package.json']['@types/react-dom']);
assert(issues.binaries['package.json']['ladle']);
assert(issues.unlisted['.ladle/vite.config.ts']['vite']);

assert.deepEqual(counters, {
...baseCounters,
binaries: 1,
dependencies: 1,
devDependencies: 1,
unlisted: 1,
processed: 5,
total: 5,
});
});
Loading