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
226 changes: 21 additions & 205 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Ionic Angular Collect Icons
# @rdlabo/ionic-angular-collect-icons

**Documentation:** [Read the full documentation](https://docs.rdlabo.dev/projects/ionic-angular-collect-icons)
<!-- rdlabo-docs-omit -->
[![npm version](https://badge.fury.io/js/@rdlabo%2Fionic-angular-collect-icons.svg)](https://badge.fury.io/js/@rdlabo%2Fionic-angular-collect-icons)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
<!-- /rdlabo-docs-omit -->

## What is this?

Expand All @@ -18,223 +21,36 @@ This project is based [ionic-team/ionic-angular-standalone-codemods](https://git
- Node.js >= 20
- ionicons >= 6.0.0

## Initialize

```bash
npm install @rdlabo/ionic-angular-collect-icons --save-dev
```
## Quick start

### 🤖 Automatic Configuration
After [Installation](#installation), initialize `addIcons` and collect icons before production builds:

```bash
npx @rdlabo/ionic-angular-collect-icons --initialize true
```

### 📝 Manual Configuration
Details: [Initialize](./docs/initialize.md) and [Usage](./docs/usage.md).

#### 1. Run the CLI
## Installation

```bash
npx @rdlabo/ionic-angular-collect-icons
```

This will generate `src/use-icons.ts`.

#### 2. Import the generated file in your `main.ts` ( or `app.config.ts` ) file:

```diff
+ import { addIcons } from 'ionicons';
+ import * as allIcons from 'ionicons/icons';
+ import * as useIcons from '../use-icons';

if (environment.production) {
enableProdMode();
}

+ addIcons(environment.production ? useIcons : allIcons);
```

#### 3. Remove other `addIcons` calls in class constructor

```diff
@Component(/* ... */)
export class ExampleComponent {
constructor() {
- addIcons(useIcons);
}
}
```

## Usage

```bash
npx @rdlabo/ionic-angular-collect-icons
```

### Let's automate run

It is inefficient to run commands each time before running a production build, so put them in an npm script to automate the process. Example:

```diff
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
+ "prebuild": "npx @rdlabo/ionic-angular-collect-icons",
```

> [!WARNING]
> This method cannot be used for production builds without using the npm script.

## Optional

### --dry-run [boolean]

If you want to see what changes would be made without actually writing them to files, set `true`. The default is `false`.

```bash
npx @rdlabo/ionic-angular-collect-icons --dry-run true
```

### --interactive [boolean]

If you want to set all CLI option using the prompts, set `true`. This can be used to check only the results in a Dry run.
The default is `false`.

```bash
npx @rdlabo/ionic-angular-collect-icons --interactive true
```

### --initialize [boolean]

If you want to initialize `addIcons` automatically, you can use the `--initialize` flag. The default is `false`. The CLI add lines:

```diff
+ import { addIcons } from 'ionicons';
+ import * as allIcons from 'ionicons/icons';
+ import * as useIcons from '../use-icons';

if (environment.production) {
enableProdMode();
}

+ addIcons(environment.production ? useIcons : allIcons);
```

the CLI will add lines at the file that has `enableProdMode()`. Of course, it can also be set manually.

And remove other `addIcons` calls in class constructor.

```diff
@Component(/* ... */)
export class ExampleComponent {
constructor() {
- addIcons(useIcons);
}
}
```

```bash
npx @rdlabo/ionic-angular-collect-icons --initialize true
```

### --project-path [string]

If you want to specify the path to the project, you can use the `--project-path` flag. The default is the current directory.

```bash
npx @rdlabo/ionic-angular-collect-icons --project-path /path/to/project
```

Target files are under the `src` directory from the specified path.

- path/to/project + `src/**/*.ts`
- path/to/project + `src/**/*.html`

### --icon-path [string]

Default create file is (path/to/project +) `src/use-icons.ts`. If you want to specify the file name, you can use the `--icon-path` flag.

```bash
npx @rdlabo/ionic-angular-collect-icons --icon-path src/other-use-icons.ts
```

## FAQ

- Can run addIcons in main.ts?

Yes. Please check this issue: https://github.com/ionic-team/ionic-framework/issues/28445#issuecomment-1789028722

> You're more than welcome to register them in main.ts or app.component.ts. You can then use them anywhere in your application. However, the initial bundle size may increase because the icons need to be loaded up front.

- Support Unit Test?

Unit test at ChromeHeadless don't read `main.ts`. So, you need to add `addIcons` in each test, or add `addIcons` in `src/test.ts`.

- Support binding icon name?

No, and we do not plan to support this program. For example, this kind of code is difficult to follow until it is displayed.

```ts
@Component({
selector: "app-example",
template: ` <ion-icon [name]="iconName"></ion-icon> `,
})
export class ExampleComponent {
iconName = "add";

ionViewWillEnter() {
setTimeout(() => {
this.iconName = "remove";
}, 1000);
}
}
```

If you are doing this kind of complex processing, please import manually.

Alternatively, if you have a limited number of icons you're binding to, you can add a block in your template as a "hint."

```html
<!-- This is a trick to get ionic-angular-collect-icons
to include the icons, but it will never render. -->
@if(false) {
<ion-icon name="home"></ion-icon>
<ion-icon name="people"></ion-icon>
}
npm install @rdlabo/ionic-angular-collect-icons --save-dev
```

It's not ideal, but it will help to maintain the automation.

- Why not addIcons in each component?

This is to minimize diffs by libraries. I did not like to have every component change on every run. I wanted to keep the diff as small as possible.

## Developing

1. Clone this repository.
2. Run `npm install` to install dependencies
3. Run `npm run dev` to start the dev server, this will watch for changes and rebuild the project
4. Run `npm run start` to start the CLI and test the code mods

### Testing

This project uses [Vitest](https://vitest.dev/) for unit testing.

| Command | Description |
| -------------------- | --------------------------- |
| `npm run test` | Run all tests |
| `npm run test:watch` | Run all tests in watch mode |
| `npm run coverage` | Run tests with coverage |
## Documentation

### Formatting
Start with [Installation](#installation), then [Initialize](./docs/initialize.md) and [Usage](./docs/usage.md).

This project uses [Prettier](https://prettier.io/) for code formatting.
- [Initialize](./docs/initialize.md) — wire `addIcons` automatically or by hand.
- [Usage](./docs/usage.md) — run the collector before production builds.
- [CLI Options](./docs/options.md) — `--dry-run`, `--initialize`, paths.
- [FAQ](./docs/faq.md) — tests, binding, and `main.ts`.

Run `npm run fmt` to format all files in the project.
<!-- rdlabo-docs-omit -->
**Full documentation:** [https://docs.rdlabo.dev/projects/ionic-angular-collect-icons](https://docs.rdlabo.dev/projects/ionic-angular-collect-icons)

### Additional Resources
## License

- [Typescript AST Explorer](https://ts-ast-viewer.com/)
- [ts-morph API Docs](https://ts-morph.com/)
- [Clack Prompts Docs](https://github.com/natemoo-re/clack/tree/main/packages/prompts#readme)
This project is licensed under the [MIT License](./LICENSE).
<!-- /rdlabo-docs-omit -->
35 changes: 35 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Developing

This project is a TypeScript CLI built on top of `ts-morph` and `clack`. It is designed for local development workflows and is published to npm as `@rdlabo/ionic-angular-collect-icons`.

## Setup

1. Clone the repository.
2. Install dependencies:

```bash
npm install
```

## Common commands

| Command | Description |
| -------------------- | ----------------------------------------- |
| `npm run dev` | Build and watch for changes |
| `npm run start` | Run the CLI against the local source |
| `npm run test` | Run all Vitest tests |
| `npm run test:watch` | Run tests in watch mode |
| `npm run coverage` | Run tests with coverage |
| `npm run lint` | Run ESLint |
| `npm run fmt` | Format files with Prettier |
| `npm run build` | Build the `dist/` output for both CJS/ESM |

## Useful resources

- [TypeScript AST Explorer](https://ts-ast-explorer.com/)
- [ts-morph API Docs](https://ts-morph.com/)
- [Clack Prompts Docs](https://github.com/natemoo-re/clack/tree/main/packages/prompts#readme)

## Contributing

Contributions are welcome. Please run `npm run fmt`, `npm run lint`, and `npm test` before opening a pull request.
48 changes: 48 additions & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
- Can run addIcons in main.ts?

Yes. Please check this issue: https://github.com/ionic-team/ionic-framework/issues/28445#issuecomment-1789028722

> You're more than welcome to register them in main.ts or app.component.ts. You can then use them anywhere in your application. However, the initial bundle size may increase because the icons need to be loaded up front.

- Support Unit Test?

Unit test at ChromeHeadless don't read `main.ts`. So, you need to add `addIcons` in each test, or add `addIcons` in `src/test.ts`.

- Support binding icon name?

No, and we do not plan to support this program. For example, this kind of code is difficult to follow until it is displayed.

```ts
@Component({
selector: 'app-example',
template: ` <ion-icon [name]="iconName"></ion-icon> `,
})
export class ExampleComponent {
iconName = 'add';

ionViewWillEnter() {
setTimeout(() => {
this.iconName = 'remove';
}, 1000);
}
}
```

If you are doing this kind of complex processing, please import manually.

Alternatively, if you have a limited number of icons you're binding to, you can add a block in your template as a "hint."

```html
<!-- This is a trick to get ionic-angular-collect-icons
to include the icons, but it will never render. -->
@if(false) {
<ion-icon name="home"></ion-icon>
<ion-icon name="people"></ion-icon>
}
```

It's not ideal, but it will help to maintain the automation.

- Why not addIcons in each component?

This is to minimize diffs by libraries. I did not like to have every component change on every run. I wanted to keep the diff as small as possible.
46 changes: 46 additions & 0 deletions docs/initialize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
Install the CLI and wire `addIcons`. See also [Usage](./usage.md).

```bash
npm install @rdlabo/ionic-angular-collect-icons --save-dev
```

### 🤖 Automatic Configuration

```bash
npx @rdlabo/ionic-angular-collect-icons --initialize true
```

### 📝 Manual Configuration

#### 1. Run the CLI

```bash
npx @rdlabo/ionic-angular-collect-icons
```

This will generate `src/use-icons.ts`.

#### 2. Import the generated file in your `main.ts` ( or `app.config.ts` ) file:

```diff
+ import { addIcons } from 'ionicons';
+ import * as allIcons from 'ionicons/icons';
+ import * as useIcons from './use-icons';

if (environment.production) {
enableProdMode();
}

+ addIcons(environment.production ? useIcons : allIcons);
```

#### 3. Remove other `addIcons` calls in class constructor

```diff
@Component(/* ... */)
export class ExampleComponent {
constructor() {
- addIcons(useIcons);
}
}
```
Loading
Loading