Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 .changeset/tired-paths-take.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-directives-plugin": minor
---

Added support for custom directives like "use something"
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "react-directives-plugin",
"version": "1.0.0",
"description": "Minimal open-source stack to help you ship an open-source package in TS",
"description": "Vite plugin that allows you to add react directives to files behind the scenes",
"scripts": {
"build": "pnpm run --filter=\"./packages/**/*\" build",
"build:watch": "pnpm build && pnpm run --filter=\"./packages/**/*\" --parallel build --watch",
Expand Down Expand Up @@ -39,4 +39,4 @@
"pnpm": ">=10.6.5",
"node": ">=20.0.0"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
{
"name": "react-directives-plugin",
"version": "1.0.0",
"description": "Minimal open-source stack to help you ship an open-source package in TS",
"main": "./dist/index.cjs",
"description": "Vite plugin that allows you to add react directives to files behind the scenes",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"type": "module",
Expand All @@ -13,11 +12,6 @@
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"import": "./dist/index.cjs",
"require": "./dist/index.cjs"
}
}
},
Expand All @@ -40,9 +34,7 @@
"bugs": {
"url": "https://github.com/forge-42/react-directives-plugin/issues"
},
"files": [
"dist"
],
"files": ["dist"],
"homepage": "https://github.com/forge-42/react-directives-plugin#readme",
"publishConfig": {
"provenance": true
Expand Down Expand Up @@ -72,4 +64,4 @@
"@babel/types": "^7.26.10",
"picomatch": "^4.0.2"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import traverse from "@babel/traverse"
export const trav =
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
typeof (traverse as any).default !== "undefined"
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
? ((traverse as any).default as typeof import("@babel/traverse").default)
? // biome-ignore lint/suspicious/noExplicitAny: <explanation>
((traverse as any).default as typeof import("@babel/traverse").default)
: traverse

export const gen =
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
typeof (generate as any).default !== "undefined"
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
? ((generate as any).default as typeof import("@babel/generator").default)
? // biome-ignore lint/suspicious/noExplicitAny: <explanation>
((generate as any).default as typeof import("@babel/generator").default)
: generate
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import type { Plugin } from "vite"
import { transformCode } from "./transformer"

// This is your packages entry point, everything exported from here will be accessible to the end-user.
export const reactDirectives = (props?: {
export interface ReactDirectivesPluginOptions {
"use strict"?: string[]
"use server"?: string[]
"use client"?: string[]
[key: `use ${string}`]: string[] | undefined
}

// This is your packages entry point, everything exported from here will be accessible to the end-user.
export const reactDirectives = (
props?: ReactDirectivesPluginOptions
// biome-ignore lint/suspicious/noExplicitAny: Avoid issues with vite-plugin types
}): any => {
const { "use client": useClient = [], "use server": useServer = [], "use strict": useStrict = [] } = props || {}
): any => {
return {
name: "react-directives-plugin",
enforce: "pre",
transform(code, id) {
return transformCode(code, id, {
useClient,
useServer,
useStrict,
})
return transformCode(code, id, props)
},
} satisfies Plugin
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: ["**/*.js"],
useServer: [],
useStrict: [],
"use client": ["**/*.js"],
"use server": [],
"use strict": [],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -64,9 +64,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: ["*/.ts", "**/*.js"],
useServer: [],
useStrict: [],
"use client": ["*/.ts", "**/*.js"],
"use server": [],
"use strict": [],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -79,9 +79,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: [],
useServer: ["*/.ts", "**/*.ts"],
useStrict: [],
"use client": [],
"use server": ["*/.ts", "**/*.ts"],
"use strict": [],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -94,9 +94,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: [],
useServer: ["**/*.js"],
useStrict: [],
"use client": [],
"use server": ["**/*.js"],
"use strict": [],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -110,9 +110,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.server.js"
const result = transformCode(code, id, {
useClient: [],
useServer: ["**/*.server.js"],
useStrict: [],
"use client": [],
"use server": ["**/*.server.js"],
"use strict": [],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -125,9 +125,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: [],
useServer: ["*/.ts", "**/*.js"],
useStrict: [],
"use client": [],
"use server": ["*/.ts", "**/*.js"],
"use strict": [],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -140,9 +140,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: [],
useServer: ["*/.ts", "**/*.ts"],
useStrict: [],
"use client": [],
"use server": ["*/.ts", "**/*.ts"],
"use strict": [],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -156,9 +156,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: [],
useServer: [],
useStrict: ["*/.ts", "**/*.ts"],
"use client": [],
"use server": [],
"use strict": ["*/.ts", "**/*.ts"],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -171,9 +171,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: [],
useServer: [],
useStrict: ["**/*.js"],
"use client": [],
"use server": [],
"use strict": ["**/*.js"],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -186,9 +186,9 @@ describe("transformCode", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: [],
useServer: [],
useStrict: ["*/.ts", "**/*.js"],
"use client": [],
"use server": [],
"use strict": ["*/.ts", "**/*.js"],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand All @@ -197,13 +197,31 @@ describe("transformCode", () => {
`)
)
})

it("should add random directive with multiple matchers", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
"use client": [],
"use server": [],
"use strict": ["*/.ts", "**/*.js"],
"use potato": ["*/.ts", "**/*.js"],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
"use potato";
"use strict";
const a = 1;
`)
)
})
it("should not add strict directive with multiple matchers if they don't match", () => {
const code = "const a = 1;"
const id = "C://path/to/file/test.js"
const result = transformCode(code, id, {
useClient: [],
useServer: [],
useStrict: ["*/.ts", "**/*.ts"],
"use client": [],
"use server": [],
"use strict": ["*/.ts", "**/*.ts"],
})
expect(removeWhitespace(result.code)).toMatch(
removeWhitespace(`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { types as Babel } from "@babel/core"
import type { ParseResult } from "@babel/parser"
import picomatch from "picomatch"
import type { ReactDirectivesPluginOptions } from "."
import { gen, parse, t } from "./babel"

const transform = (ast: ParseResult<Babel.File>, directivesToAdd: string[]) => {
Expand Down Expand Up @@ -37,32 +38,18 @@ export function addReactDirectives(code: string, directivesToAdd: string[], id:
}
}

export const transformCode = (
code: string,
id: string,
{
useClient,
useServer,
useStrict,
}: {
useClient: string[]
useServer: string[]
useStrict: string[]
export const transformCode = (code: string, id: string, directives?: ReactDirectivesPluginOptions) => {
if (!directives) {
return { code }
}
) => {
const directivesToAdd = []
const clientMatcher = picomatch(useClient)
const serverMatcher = picomatch(useServer)
const strictMatcher = picomatch(useStrict)
if (clientMatcher(id)) {
directivesToAdd.push("use client")
}
if (serverMatcher(id)) {
directivesToAdd.push("use server")
}
if (strictMatcher(id)) {
directivesToAdd.push("use strict")
for (const [key, value] of Object.entries(directives)) {
const matcher = picomatch(value)
if (matcher(id)) {
directivesToAdd.push(key)
}
}

if (!directivesToAdd.length) {
return { code }
}
Expand Down
Loading
Loading