Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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/dull-ducks-give.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"flowbite-react": patch
---

Search for `<ThemeInit />` in the project and warn if it's not found instead of warning all the time
2 changes: 1 addition & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@
"prepack": "clean-package",
"prepare": "bun run generate-metadata",
"prepublishOnly": "bun run build",
"test": "bun test scripts && vitest",
"test": "bun test scripts src/cli src/helpers && vitest",
"test:coverage": "vitest run --coverage",
"typecheck": "tsc --noEmit"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/scripts/generate-metadata.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { describe, expect, it } from "bun:test";
import { extractClassList, extractDependencyList } from "./generate-metadata";

describe("extractClassList", () => {
Expand Down
17 changes: 17 additions & 0 deletions packages/ui/src/cli/commands/build.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from "fs/promises";
import { allowedExtensions, automaticClassGenerationMessage, classListFilePath, excludeDirs } from "../consts";
import { buildClassList } from "../utils/build-class-list";
import { createInitLogger } from "../utils/create-init-logger";
import { extractComponentImports } from "../utils/extract-component-imports";
import { findFiles } from "../utils/find-files";
import { getConfig } from "../utils/get-config";
Expand All @@ -13,11 +14,24 @@ export async function build() {
try {
const config = await getConfig();
await setupInit(config);
const initLogger = createInitLogger(config);

const importedComponents: string[] = [];

if (config.components.length) {
console.warn(automaticClassGenerationMessage);

if (initLogger.isCustomConfig) {
const files = await findFiles({
patterns: allowedExtensions.map((ext) => `**/*${ext}`),
excludeDirs,
});

for (const file of files) {
const content = await fs.readFile(file, "utf-8");
initLogger.check(file, content);
}
}
} else {
const files = await findFiles({
patterns: allowedExtensions.map((ext) => `**/*${ext}`),
Expand All @@ -27,13 +41,16 @@ export async function build() {
for (const file of files) {
const content = await fs.readFile(file, "utf-8");
const components = extractComponentImports(content);
initLogger.check(file, content);

if (components.length) {
importedComponents.push(...components);
}
}
}

initLogger.log();

const classList = buildClassList({
components: config.components.length ? config.components : [...new Set(importedComponents)],
dark: config.dark,
Expand Down
26 changes: 18 additions & 8 deletions packages/ui/src/cli/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
initJsxFilePath,
} from "../consts";
import { buildClassList } from "../utils/build-class-list";
import { createInitLogger } from "../utils/create-init-logger";
import { extractComponentImports } from "../utils/extract-component-imports";
import { findFiles } from "../utils/find-files";
import { getClassList } from "../utils/get-class-list";
Expand All @@ -25,6 +26,7 @@ export async function dev() {
await setupOutputDirectory();
let config = await getConfig();
await setupInit(config);
const initLogger = createInitLogger(config);

if (config.components.length) {
console.warn(automaticClassGenerationMessage);
Expand All @@ -42,12 +44,15 @@ export async function dev() {
for (const file of files) {
const content = await fs.readFile(file, "utf-8");
const componentImports = extractComponentImports(content);
initLogger.check(file, content);

if (componentImports.length) {
importedComponentsMap[file] = componentImports;
}
}

initLogger.log();

const newImportedComponents = [...new Set(Object.values(importedComponentsMap).flat())];
const newClassList = buildClassList({
components: config.components.length ? config.components : newImportedComponents,
Expand All @@ -63,9 +68,19 @@ export async function dev() {

// watch for changes
async function handleChange(path: string, eventName: "change" | "unlink") {
if ([configFilePath, initFilePath, initJsxFilePath].includes(path)) {
config = await getConfig();
await setupInit(config);
initLogger.config = config;
}
if (path === gitIgnoreFilePath) {
await setupGitIgnore();
}

if (eventName === "change") {
const content = await fs.readFile(path, "utf-8");
const componentImports = extractComponentImports(content);
initLogger.check(path, content);

if (componentImports.length) {
importedComponentsMap[path] = componentImports;
Expand All @@ -75,17 +90,12 @@ export async function dev() {
}
if (eventName === "unlink") {
delete importedComponentsMap[path];
initLogger.checkedMap.delete(path);
}

const newImportedComponents = [...new Set(Object.values(importedComponentsMap).flat())];
initLogger.log();

if ([configFilePath, initFilePath, initJsxFilePath].includes(path)) {
config = await getConfig();
await setupInit(config);
}
if (path === gitIgnoreFilePath) {
await setupGitIgnore();
}
const newImportedComponents = [...new Set(Object.values(importedComponentsMap).flat())];

const newClassList = buildClassList({
components: config.components.length ? config.components : newImportedComponents,
Expand Down
37 changes: 3 additions & 34 deletions packages/ui/src/cli/commands/setup-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,18 @@ import { klona } from "klona/json";
import { isEqual } from "../../helpers/is-equal";
import { COMPONENT_TO_CLASS_LIST_MAP } from "../../metadata/class-list";
import { configFilePath } from "../consts";
import { createConfig, type Config } from "../utils/create-config";
import { getTailwindVersion } from "../utils/get-tailwind-version";

export interface Config {
$schema: string;
components: string[];
dark: boolean;
path: string;
prefix: string;
rsc: boolean;
tsx: boolean;
version: 3 | 4;
}

/**
* Sets up the `.flowbite-react/config.json` file in the project.
*
* This function creates or updates the configuration file with default values and validates existing configurations.
*/
export async function setupConfig(): Promise<Config> {
const defaultConfig: Config = {
$schema: "https://unpkg.com/flowbite-react/schema.json",
components: [],
dark: true,
path: "src/components",
// TODO: infer from project
prefix: "",
rsc: true,
tsx: true,
const defaultConfig = createConfig({
version: await getTailwindVersion(),
};
});
const writeTimeout = 10;

try {
Expand Down Expand Up @@ -102,19 +84,6 @@ export async function setupConfig(): Promise<Config> {
setTimeout(() => fs.writeFile(configFilePath, JSON.stringify(newConfig, null, 2)), writeTimeout);
}

if (
newConfig.dark !== defaultConfig.dark ||
newConfig.prefix !== defaultConfig.prefix ||
newConfig.version !== defaultConfig.version
) {
// TODO: search for <ThemeInit /> in the project and warn if it's not found
console.info(
`\n[!] Custom values detected in ${configFilePath}, render <ThemeInit /> at root level of your app to sync runtime with node config values.`,
`\n[!] Otherwise, your app will use the default values instead of your custom configuration.`,
`\n[!] Example: In case of custom 'prefix' or 'version', the app will not display the correct class names.`,
);
}

return newConfig;
} catch (error) {
if (error instanceof Error && error.message.includes("ENOENT")) {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/cli/commands/setup-init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { namedTypes } from "ast-types";
import { parse } from "recast";
import { initFilePath, initJsxFilePath } from "../consts";
import { compareNodes } from "../utils/compare-nodes";
import type { Config } from "./setup-config";
import type { Config } from "../utils/create-config";

/**
* Sets up the `.flowbite-react/init.tsx` file in the project.
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/cli/utils/add-import.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { describe, expect, it } from "bun:test";
import { addImport } from "./add-import";

describe("addImport", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/cli/utils/add-plugin.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { describe, expect, it } from "bun:test";
import { addPlugin } from "./add-plugin";

describe("addPlugin", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/cli/utils/add-to-config.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from "bun:test";
import * as recast from "recast";
import { describe, expect, it } from "vitest";
import { addToConfig } from "./add-to-config";

describe("addToConfig", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/cli/utils/compare-nodes.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from "bun:test";
import { parse } from "recast";
import { describe, expect, it } from "vitest";
import { compareNodes } from "./compare-nodes";

describe("compareNodes", () => {
Expand Down
24 changes: 24 additions & 0 deletions packages/ui/src/cli/utils/create-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export interface Config {
$schema: string;
components: string[];
dark: boolean;
path: string;
prefix: string;
rsc: boolean;
tsx: boolean;
version: 3 | 4;
}

export function createConfig(input: Partial<Config> = {}): Config {
return {
$schema: input.$schema ?? "https://unpkg.com/flowbite-react/schema.json",
components: input.components ?? [],
dark: input.dark ?? true,
path: input.path ?? "src/components",
// TODO: infer from project
prefix: input.prefix ?? "",
rsc: input.rsc ?? true,
tsx: input.tsx ?? true,
version: input.version ?? 4,
};
}
Loading
Loading