Skip to content

Commit

Permalink
Merge pull request #62 from oktaysenkan/feat/type-generation
Browse files Browse the repository at this point in the history
feat(core): implement type generation
  • Loading branch information
oktaysenkan authored Jan 7, 2025
2 parents b00ffff + 6a3a299 commit e002b74
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 1 deletion.
20 changes: 20 additions & 0 deletions .changeset/hot-jokes-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@monicon/icon-loader": minor
"@monicon/core": minor
"@monicon/esbuild": minor
"@monicon/loader": minor
"@monicon/metro": minor
"@monicon/native": minor
"@monicon/nuxt": minor
"@monicon/qwik": minor
"@monicon/react": minor
"@monicon/rollup": minor
"@monicon/rspack": minor
"@monicon/svelte": minor
"@monicon/typescript-config": minor
"@monicon/vite": minor
"@monicon/vue": minor
"@monicon/webpack": minor
---

implement type generation
1 change: 1 addition & 0 deletions apps/docs/pages/troubleshooting/_meta.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default {
typescript: "TypeScript",
monorepo: "Monorepo",
"module-resolution": "Module Resolution",
"bundle-size": "Bundle Size",
Expand Down
27 changes: 27 additions & 0 deletions apps/docs/pages/troubleshooting/typescript.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# TypeScript

Monicon uses TypeScript to generate types for the icons. To enable TypeScript type definitions for your icons, add the following configuration to your `tsconfig.json` file:

```json filename="tsconfig.json" copy {2}
{
"include": [".monicon/*.d.ts"]
}
```

You can also use the `typesFileName` option to specify the name of the file to output the types to. If you want to disable the types file, you can set the `generateTypes` option to `false`.

```ts filename="apps/vite-react/vite.config.ts" copy {9,10}
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import monicon from "@monicon/vite";

export default defineConfig({
plugins: [
react(),
monicon({
typesFileName: "types",
generateTypes: true,
}),
],
});
```
2 changes: 1 addition & 1 deletion apps/vite-react/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
"include": ["src", ".monicon/*.d.ts"]
}
73 changes: 73 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ export type MoniconOptions = {
* @default process.cwd()
*/
root?: string;
/**
* Whether to generate the types file.
*
* @default true
*/
generateTypes?: boolean;
/**
* The name of the file to output the types to.
*
* @default "types"
*/
typesFileName?: string;
};

export type Icon = {
Expand All @@ -69,6 +81,8 @@ const defaultOptions: Required<MoniconOptions> = {
collections: [],
customCollections: {},
root: process.cwd(),
generateTypes: true,
typesFileName: "types",
};

export const getResolveAlias = () => {
Expand Down Expand Up @@ -102,6 +116,14 @@ export const getIconsFilePath = (opts?: MoniconOptions) => {
);
};

const getTypesFilePath = (opts?: MoniconOptions) => {
const options: Required<MoniconOptions> = { ...defaultOptions, ...opts };

const autoGeneratedPath = getAutoGeneratedPath(options.root);

return path.resolve(autoGeneratedPath, `${options.typesFileName}.d.ts`);
};

export const transformIcon = (svg: string) => {
const svgObject = parseSync(svg);

Expand Down Expand Up @@ -205,9 +227,60 @@ export const loadIcons = async (opts?: MoniconOptions) => {

writeIcons(loadedIcons, outputPath, options.type);

if (options.generateTypes) {
const typesOutputPath = getTypesFilePath(options);

const iconNames = Object.keys(loadedIcons);

writeTypes(iconNames, typesOutputPath);
}

return loadedIcons;
};

const writeTypes = (iconNames: string[], outputPath: string) => {
const iconNamesAsCode = iconNames.map((name) => `\n\t| "${name}"`).join("");

const code = `// This file is automatically generated by Monicon. Do not edit this file directly.
import "@monicon/icon-loader";
declare module "@monicon/icon-loader" {
export type MoniconIconName = ${iconNamesAsCode};
export type MoniconProps = {
/**
* The name of the icon to render.
*
* @example "mdi:home"
*
* For TypeScript users, you must check below for more information.
*
* @link https://monicon-docs.vercel.app/troubleshooting/typescript
*/
name: MoniconIconName;
/**
* The size of the icon.
*
* @default collection's view box size
*/
size?: number;
/**
* The color of the icon.
*
* @default "currentColor"
*/
color?: string;
/**
* The stroke width of the icon. This feature is only available for limited icon collections.
*/
strokeWidth?: number;
};
}
`;

fs.writeFileSync(outputPath, code);
};

const writeIcons = (
icons: Record<string, Icon>,
outputPath: string,
Expand Down
22 changes: 22 additions & 0 deletions packages/icon-loader/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,31 @@ import { parseSync, stringify } from "svgson";
import icons from "@monicon/runtime";

export type MoniconProps = {
/**
* The name of the icon to render.
*
* @example "mdi:home"
*
* For TypeScript users, you must check below for more information.
*
* @link https://monicon-docs.vercel.app/troubleshooting/typescript
*/
name: string;
/**
* The size of the icon.
*
* @default collection's view box size
*/
size?: number;
/**
* The color of the icon.
*
* @default "currentColor"
*/
color?: string;
/**
* The stroke width of the icon. This feature is only available for limited icon collections.
*/
strokeWidth?: number;
};

Expand Down

0 comments on commit e002b74

Please sign in to comment.