Skip to content

Commit

Permalink
Merge pull request #60 from bywhitebird/59-create-the-storybook-plugi…
Browse files Browse the repository at this point in the history
…n-for-kaz

59 create the storybook plugin for kaz
  • Loading branch information
arthur-fontaine authored Oct 27, 2023
2 parents 32cc57f + ec158b0 commit 1aae0f5
Show file tree
Hide file tree
Showing 23 changed files with 6,112 additions and 1,107 deletions.
3 changes: 3 additions & 0 deletions apps/kaz-playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,8 @@
"react-dom": "^18.0.0",
"tailwindcss": "^3.0.24",
"zod": "^3.21.4"
},
"devDependencies": {
"encoding": "^0.1.13"
}
}
33 changes: 33 additions & 0 deletions examples/simple-kazam-project/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { join, dirname } from "path";

/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/
function getAbsolutePath(value) {
return dirname(require.resolve(join(value, "package.json")));
}

/** @type { import('@storybook/react-vite').StorybookConfig } */
const config = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
getAbsolutePath("@storybook/addon-links"),
getAbsolutePath("@storybook/addon-essentials"),
getAbsolutePath("@storybook/addon-onboarding"),
getAbsolutePath("@storybook/addon-interactions"),
],
framework: {
// @ts-ignore
name: getAbsolutePath("@whitebird/storybook-plugin-kaz-react-vite"),
options: {},
},
docs: {
autodocs: "tag",
},
core: {
// @ts-ignore
builder: getAbsolutePath('@storybook/builder-vite'),
},
};
export default config;
14 changes: 14 additions & 0 deletions examples/simple-kazam-project/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/** @type { import('@storybook/react').Preview } */
const preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};

export default preview;
23 changes: 20 additions & 3 deletions examples/simple-kazam-project/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,26 @@
"name": "simple-kazam-project",
"version": "0.0.0",
"private": true,
"scripts": {
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"devDependencies": {
"kazam": "workspace:*",
"@storybook/addon-essentials": "^7.5.1",
"@storybook/addon-interactions": "^7.5.1",
"@storybook/addon-links": "^7.5.1",
"@storybook/addon-onboarding": "^1.0.8",
"@storybook/blocks": "^7.5.1",
"@storybook/react": "^7.5.1",
"@storybook/react-vite": "^7.5.1",
"@storybook/testing-library": "^0.2.2",
"@whitebird/kazam-parser-kaz": "workspace:*",
"@whitebird/kazam-transformer-react": "workspace:*",
"@whitebird/kazam-parser-kaz": "workspace:*"
"@whitebird/storybook-plugin-kaz-react-vite": "workspace:*",
"kazam": "workspace:*",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"storybook": "^7.5.1"
}
}
}
8 changes: 6 additions & 2 deletions examples/simple-kazam-project/src/components/Button.kaz
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
- prop buttonText: string = "Button"
- prop callback: () => void = () => console.log('Button clicked')
- prop callback: () => void = () => {
console.log('Button clicked')
}
- prop color: string = "red"

div() {
button(
type="submit",
on:click={callback}
on:click={callback},
style={`background-color: ${color}; color: white`}
) {
${buttonText}
}
Expand Down
22 changes: 22 additions & 0 deletions examples/simple-kazam-project/src/stories/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { StoryObj } from '@storybook/react'

import Button from '../components/Button.kaz'

export default {
title: 'Example/Button',
component: Button,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
callback: { action: 'clicked' },
},
}

export const Primary: StoryObj = {
args: {
buttonText: 'Button',
color: 'red',
},
}
7 changes: 7 additions & 0 deletions examples/simple-kazam-project/src/types/kaz-shim.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
declare module '*.kaz' {
import type { ComponentType } from 'react'

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const component: ComponentType<any>
export default component
}
11 changes: 11 additions & 0 deletions examples/simple-kazam-project/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Default",
"extends": "@whitebird/tsconfig/node.json",
"compilerOptions": {
"outDir": "dist",
"jsx": "react-jsx"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"@antfu/eslint-config": "0.43.1"
},
"patchedDependencies": {
"[email protected]": "patches/[email protected]"
"[email protected]": "patches/[email protected]",
"@storybook/[email protected]": "patches/@[email protected]"
}
}
}
12 changes: 12 additions & 0 deletions packages/storybook-plugin-kaz-react-vite/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# @whitebird/kazam-parser-base

## 0.1.0

### Minor Changes

- 4fd3da1: Initial release

### Patch Changes

- Updated dependencies [4fd3da1]
- @whitebird/kazam-transformer-base@0.1.0
5 changes: 5 additions & 0 deletions packages/storybook-plugin-kaz-react-vite/build.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineBuildConfig } from 'unbuild'

export default defineBuildConfig({
declaration: true,
})
36 changes: 36 additions & 0 deletions packages/storybook-plugin-kaz-react-vite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@whitebird/storybook-plugin-kaz-react-vite",
"type": "module",
"version": "0.1.0",
"license": "MIT",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./preset": {
"types": "./dist/preset.d.ts",
"require": "./dist/preset.cjs"
},
"./package.json": "./package.json"
},
"main": "./dist/index.cjs",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "unbuild",
"lint": "eslint .",
"lint:fix": "eslint . --fix"
},
"dependencies": {
"@storybook/react-vite": "^7.5.1",
"@whitebird/kazam-parser-kaz": "workspace:*",
"@whitebird/kazam-transformer-react": "workspace:*",
"kazam": "workspace:*"
},
"devDependencies": {
"@types/node": "^18.11.9"
}
}
1 change: 1 addition & 0 deletions packages/storybook-plugin-kaz-react-vite/preset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./dist/preset')
1 change: 1 addition & 0 deletions packages/storybook-plugin-kaz-react-vite/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {}
17 changes: 17 additions & 0 deletions packages/storybook-plugin-kaz-react-vite/src/preset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { StorybookConfig } from '@storybook/react-vite'
import { viteFinal as reactViteFinal } from '@storybook/react-vite/preset'

import { viteKazReactPlugin } from './vite-kaz-react-plugin'

export * from '@storybook/react-vite/preset'

export const viteFinal: StorybookConfig['viteFinal'] = async (config, options) => {
if (reactViteFinal !== undefined)
config = await reactViteFinal(config, options)

const { plugins = [] } = config

plugins.unshift(viteKazReactPlugin())

return config
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import * as path from 'node:path'

import { ParserKaz } from '@whitebird/kazam-parser-kaz'
import { TransformerReact } from '@whitebird/kazam-transformer-react'
import * as kazam from 'kazam'
import type { Plugin } from 'vite'

export const viteKazReactPlugin = (): Plugin => {
const KAZ_REACT_SUFFIX = '?kaz-react'

const kazComponents: string[] = []
let kazamGenerationResult: Awaited<ReturnType<typeof kazam.generate>>[0] | undefined
let rootDir: string | undefined

return {
name: 'vite-kaz-react',

enforce: 'pre',

resolveId(source, importer) {
if (importer?.endsWith('/index.html'))
rootDir = importer.slice(0, -'index.html'.length)

if (source.endsWith('.kaz')) {
const componentPath = path.join(path.dirname(importer ?? ''), source)

kazComponents.push(componentPath)
return `${componentPath}.tsx${KAZ_REACT_SUFFIX}`
}

return null
},

async load(id) {
// As we provide only one config, kazam.generate will return only one output
if (id.endsWith(KAZ_REACT_SUFFIX)) {
if (rootDir === undefined)
throw new Error('rootDir is undefined')

kazamGenerationResult ??= await kazam.generate({
rootDir,
input: kazComponents,
output: rootDir,
parsers: [ParserKaz],
transformers: [TransformerReact],
}).then(([output]) => output)

if (kazamGenerationResult === undefined)
throw new Error('kazamGenerationResult is undefined')

const kazComponentId = id.slice(0, -`.tsx${KAZ_REACT_SUFFIX}`.length)
const kazComponentFilename = path.basename(kazComponentId)

const output = kazamGenerationResult.get(kazComponentFilename)?.content

if (output === undefined)
throw new Error(`Could not find output for ${kazComponentId}`)

return output
}

return null
},

handleHotUpdate({ file, server, modules }) {
if (file.endsWith('.kaz')) {
kazamGenerationResult = undefined

return [
...(server.moduleGraph.getModulesByFile(`${file}.tsx`) ?? []),
...modules,
]
}

return modules
},
}
}
10 changes: 10 additions & 0 deletions packages/storybook-plugin-kaz-react-vite/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Default",
"extends": "@whitebird/tsconfig/node.json",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const autoImport = (tagName: string) =>
if (componentPath === undefined)
return

yield * _(transformService.addImport('namedImport', {
yield * _(transformService.addImport('defaultImport', {
name: tagName,
path: `./${path.relative(
path.dirname(metadata.filePath),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import * as path from 'node:path'

import { Effect, pipe } from 'effect'

import { TransformService } from '../../transform-service'
Expand Down Expand Up @@ -34,14 +32,9 @@ export const handleKaz: Handle<'ast', string>
Exclude<typeof kaz.instructions[number], { $type: 'ImportInstruction' | 'PropInstruction' }>[]
)

const metadata = yield * _(transformService.getMetadata())
const componentName = path.basename(metadata.componentName, path.extname(metadata.componentName))

return yield * _(pipe(
String.prototype.concat(
'export const ',
componentName,
' = (',
'export default (',
props.length > 0
? `{ ${propsDeclaration} }: { ${propsType} }`
: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const handlePropInstruction: Handle<'propInstruction', {
declaration: String.prototype.concat(
propInstruction.name.$value,
propInstruction.defaultValue !== undefined
? ` = ${transformService.transformExpression(propInstruction.defaultValue.expression)}`
? ` = ${yield * _(transformService.transformExpression(propInstruction.defaultValue.expression))}`
: '',
),
type: String.prototype.concat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function formatTsxForClient(
return `
import ReactDOM from 'react-dom/client';
${tsx}
${tsx.replace('export default', 'const Index =')}
const root = ReactDOM.createRoot(
document.getElementById('root')
Expand Down
16 changes: 16 additions & 0 deletions patches/@[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
diff --git a/package.json b/package.json
index 53cb6051f09b624d4c54bfb4a6b388531b90ac88..4fcf4772164a0a2566f1677f1afe6fac4e6a30a9 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,11 @@
},
"./package.json": "./package.json"
},
+ "typesVersions": {
+ "*": {
+ "preset": ["./dist/preset.d.ts"]
+ }
+ },
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
Loading

0 comments on commit 1aae0f5

Please sign in to comment.