# Contribution Guide

`@ant-design/icons-svg` is an SVG library recommended by Ant Design official team. It offers the abstract node (essentially a plain object) to be consumed by various UI libraries or framworks.

## Project structure

```bash
.
├── README.md
├── babel.config.cjs      # babel config used by jest
├── docs
├── es                    # the output directory of typescript compiler (--module esnext)
├── gulpfile.ts           # the core gulp config
├── inline-svg            # the output directory of gulp. It contains all processed icons with the extenstion ".svg"
├── inline-namespaced-svg # the output directory of gulp. It contains all processed icons with the extenstion ".svg" and the SVG namespace (xmlns="http://www.w3.org/2000/svg")
├── jest.config.cjs
├── lib                   # the output directory of typescript compiler (--module commonjs)
├── package.json
├── plugins               # custom gulp plugins
├── scripts               # some custom scripts
├── src                   # source directory. All files in "src" are generated by gulp and compiled by tsc
├── svg                   # the raw icons directory. You can add icons here.
├── tasks/creators        # gulp tasks factory fucntions
├── templates             # some templates
├── test
├── tsconfig.build.json   # build time typescript config
├── tsconfig.json         # runtime typescript config when running "npm run generate"
├── typings.d.ts
└── utils
```

## Generate workflow

Run the command

```bash
ut generate
```

to start `gulp` workflow. See the workflow below.

```txt
1. clean (or delete) the generated or compiled files
2. run these tasks parallelly:
  2.1 copy some files to "src" dir. (e.g. helpers.ts, types.ts)
  2.2 generate abstract nodes with the theme "filled"
  2.3 generate abstract nodes with the theme "outlined"
  2.4 generate abstract nodes with the theme "twotone"
3. run these tasks parallelly:
  3.1 generate index.ts
  3.2 generate inline-svg dirctory
  3.3 generate inline-namespaced-svg dirctory
```

## Build workflow

Run the command

```bash
ut build
```

and it will use `tsc` to compile files in "src" to the output dirctories `es`、`lib`.

## How to add/modify/delete icons

### How to add icons

Make sure that the icon should obey these rules：

1. The icon should come from [Ant Design official library site](https://www.iconfont.cn/collections/detail?spm=a313x.7781069.1998910419.d9df05512&cid=9402), or be required from the community and be fitted with [the `Ant Design` icon design rules](https://ant.design/docs/spec/icon).

2. The icon should have `viewBox` attribute with the value `0 0 1024 1024`.

3. The icon should have a `64px` bleed.

Add the icon to a theme-specific fold (one of the `filled`, `outlined`, `twotone` fold) in `svg` directory.

Run the workflow commands.

```bash
# generate ".ts" files into "src" dir
ut generate

# compile files in "src" dir
ut build
```

### How to modify/delete icons

Just modify/delete the icons in the `svg` dir and run the workflow commands.

## gulp tasks

### Generate icons task

```ts
generateIcons(options: GenerateIconsOptions): () => NodeJS.ReadWriteStream
```

This task will compress all `.svg` files in specific dir by using `svgo`, and then convert them into the abstract node.

`GenerateIconsOptions`:

```ts
// gulpfile.ts

generateIcons({
  // set the icon theme
  theme: 'filled',

  // sources
  from: ['svg/filled/*.svg'],

  // output dir
  toDir: 'src/asn',

  // config of the plugin SVGO
  svgoConfig: generalConfig,

  // the collection of the transform function. See the following for details
  extraNodeTransformFactories: [
    assignAttrsAtTag('svg', { focusable: 'false' }),
    adjustViewBox
  ],

  // the serialization operation of the abstract node before applying templates. See the following for details
  stringify: JSON.stringify,

  // template
  template: iconTemplate,

  // Interpolation mapping in templates
  mapToInterpolate: ({ name, content }) => ({
    identifier: getIdentifier({ name, themeSuffix: 'Filled' }),
    content
  }),

  // output filename
  filename: ({ name }) => getIdentifier({ name, themeSuffix: 'Filled' })
});
```

#### extraNodeTransformFactories

It is an array that includes the function that process every abstract node.

```ts
interface TransformFactory {
  (options: TransformOptions): (asn: AbstractNode) => AbstractNode;
}

type TransformOptions = {
  name: string;
  theme: ThemeType;
};

interface AbstractNode {
  tag: string;
  attrs: {
    [key: string]: string;
  };
  children?: AbstractNode[];
}
```

The current config in `gulpfile.ts` is as follows.

```ts
extraNodeTransformFactories: [
  assignAttrsAtTag('svg', { focusable: 'false' }),
  adjustViewBox
]
```

`assignAttrsAtTag('svg', { focusable: 'false' })`

for each `svg` node（the `svg` XML tag）, it can assign the key-value pairs to the attributes. e.g. `focusable="false"`

`adjustViewBox`

It will adjust the view box of the icons (> antd@3.9) and remove the bleed area. (`viewBox="64 64 896 896"`)

```ts
const adjustViewBox: TransformFactory = assignAttrsAtTag('svg', ({ name }) => ({
  viewBox: includes(name, OLD_ICON_NAMES) ? '0 0 1024 1024' : '64 64 896 896'
}));
```

Note that `assignAttrsAtTag` is a help function that help to add extra attributes to the nodes.

```ts
function assignAttrsAtTag(
  tag: string,
  extraPropsOrFn:
    | Dictionary
    | ((
        options: TransformOptions & { previousAttrs: Dictionary }
      ) => Dictionary)
): TransformFactory;

type Dictionary = Record<string, string>;
```

#### Example：Add `hello="world"` for all `path` tag

```ts
extraNodeTransformFactories: [
  assignAttrsAtTag('path', { hello: 'world'})
]
```

the result is as follows

```ts
// src/asn/AccountBookFilled.ts

const AccountBookFilled: IconDefinition = {
  icon: {
    tag: 'svg',
    attrs: { viewBox: '0 0 1024 1024' },
    children: [
      {
        tag: 'path',
        attrs: {
          d:
            'M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zM648.3 426.8l-87.7 161.1h45.7c5.5 0 10 4.5 10 10v21.3c0 5.5-4.5 10-10 10h-63.4v29.7h63.4c5.5 0 10 4.5 10 10v21.3c0 5.5-4.5 10-10 10h-63.4V752c0 5.5-4.5 10-10 10h-41.3c-5.5 0-10-4.5-10-10v-51.8h-63.1c-5.5 0-10-4.5-10-10v-21.3c0-5.5 4.5-10 10-10h63.1v-29.7h-63.1c-5.5 0-10-4.5-10-10v-21.3c0-5.5 4.5-10 10-10h45.2l-88-161.1c-2.6-4.8-.9-10.9 4-13.6 1.5-.8 3.1-1.2 4.8-1.2h46c3.8 0 7.2 2.1 8.9 5.5l72.9 144.3 73.2-144.3a10 10 0 018.9-5.5h45c5.5 0 10 4.5 10 10 .1 1.7-.3 3.3-1.1 4.8z',
          hello: 'world'
        }
      }
    ]
  },
  name: 'account-book',
  theme: 'filled'
};
```

#### Example: have an access to the theme, name and even the previous attributes of the icon

```ts
extraNodeTransformFactories: [
  assignAttrsAtTag('path', ({ name, theme, previousAttrs }) => ({
    hello: `${name}-${theme}-${previousAttrs.d}`
  }))
]
```

the result is as follows

```ts
// src/asn/AccountBookFilled.ts

const AccountBookFilled: IconDefinition = {
  icon: {
    tag: 'svg',
    attrs: { viewBox: '0 0 1024 1024' },
    children: [
      {
        tag: 'path',
        attrs: {
          d:
            'M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zM648.3 426.8l-87.7 161.1h45.7c5.5 0 10 4.5 10 10v21.3c0 5.5-4.5 10-10 10h-63.4v29.7h63.4c5.5 0 10 4.5 10 10v21.3c0 5.5-4.5 10-10 10h-63.4V752c0 5.5-4.5 10-10 10h-41.3c-5.5 0-10-4.5-10-10v-51.8h-63.1c-5.5 0-10-4.5-10-10v-21.3c0-5.5 4.5-10 10-10h63.1v-29.7h-63.1c-5.5 0-10-4.5-10-10v-21.3c0-5.5 4.5-10 10-10h45.2l-88-161.1c-2.6-4.8-.9-10.9 4-13.6 1.5-.8 3.1-1.2 4.8-1.2h46c3.8 0 7.2 2.1 8.9 5.5l72.9 144.3 73.2-144.3a10 10 0 018.9-5.5h45c5.5 0 10 4.5 10 10 .1 1.7-.3 3.3-1.1 4.8z',
          hello:
            'account-book-filled-M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zM648.3 426.8l-87.7 161.1h45.7c5.5 0 10 4.5 10 10v21.3c0 5.5-4.5 10-10 10h-63.4v29.7h63.4c5.5 0 10 4.5 10 10v21.3c0 5.5-4.5 10-10 10h-63.4V752c0 5.5-4.5 10-10 10h-41.3c-5.5 0-10-4.5-10-10v-51.8h-63.1c-5.5 0-10-4.5-10-10v-21.3c0-5.5 4.5-10 10-10h63.1v-29.7h-63.1c-5.5 0-10-4.5-10-10v-21.3c0-5.5 4.5-10 10-10h45.2l-88-161.1c-2.6-4.8-.9-10.9 4-13.6 1.5-.8 3.1-1.2 4.8-1.2h46c3.8 0 7.2 2.1 8.9 5.5l72.9 144.3 73.2-144.3a10 10 0 018.9-5.5h45c5.5 0 10 4.5 10 10 .1 1.7-.3 3.3-1.1 4.8z'
        }
      }
    ]
  },
  name: 'account-book',
  theme: 'filled'
};
```
