Skip to content

Commit

Permalink
chore(seed-icon): change icon component, config, etc (#187)
Browse files Browse the repository at this point in the history
* chore: change width, height to span

* chore: add yaml schema

* chore: change log underline

* chore: change component template

* chore: add vite template

* chore: remove vite component, clean line

* docs: changeset

* docs: change readme

* Update strange-frogs-unite.md
  • Loading branch information
junghyeonsu authored Feb 14, 2023
1 parent 7c213d3 commit 64d5540
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 40 deletions.
18 changes: 18 additions & 0 deletions .changeset/strange-frogs-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"@seed-design/icon": minor
---

### Config

- add `vite` config template
- add `yaml schema` in config template

### Icon Component

- change component span style to `inline-flex`
- remove component props `width`, `height` and add `size` prop

### etc

- logs more detail
- update `readme`
38 changes: 38 additions & 0 deletions packages/icon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,41 @@ yarn seed-icon gen
| `componentPath` | 아이콘 컴포넌트가 저장될 경로입니다. 프로젝트 루트 기준입니다. | src/components/SeedIcon.tsx |
| `spritePath` | svg 파일이 저장될 경로입니다. 프로젝트 루트 기준입니다.Image | src/assets/sprite.svg |
| `icons` | 위 피그마 파일에서 사용되는 아이콘 이름을 추가해주세요. | [icon_add_circle_fill, icon_add_circle_regular, icon_add_circle_thin] |

## preload guide

### Vite

> vite는 svg loader를 기본적으로 제공하고 있습니다.
> 그래서 따로 설정해줘야 하는 부분이 없고, `index.html`에 아래와 같이 `sprite.svg`를 preload 해주면 됩니다.
```html
<link
rel="preload"
as="image"
type="image/svg+xml"
href="your-sprite-svg-path"
/>
```

`init`에는 `-t` 혹은 `--template` 옵션에 `vite`를 입력해서 config를 생성할 수 있습니다.

```bash
# npm
npm run seed-icon init -t vite
npm run seed-icon init --template vite

# yarn
yarn seed-icon init -t vite
yarn seed-icon init --template vite
```

그럼 `vite`프로젝트에 맞는 `icon.config.yml` 설정 파일이 생성됩니다.

### CRA, Next.js (Webpack)

todo

### Next.js 13 (Turbopack)

tood
87 changes: 63 additions & 24 deletions packages/icon/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,72 @@
#!/usr/bin/env node
import findup from "findup-sync";
import kleur from "kleur";
import { Command } from "commander";
import { Command, Option } from "commander";
import fs from "fs";
import yaml from "js-yaml";
import path from "path";
import pkg from "../package.json" assert { type: "json" };

import generateConfig from "./templates/config";
import generateComponent from "./templates/component";
import { generateDynamicConfig, generateViteConfig } from "./templates/config";
import { generateDynamicImportComponent } from "./templates/component";
import generateSprite from "./templates/sprite";
import { IconConfig } from "./types";
import { validateIcons } from "./validates/icons";

type InitTemplate = "dynamic" | "vite";

const ICON_CONFIG_FILE_NAME = "icon.config.yml";

const program = new Command();
const version = pkg.version;
const configPath = findup(ICON_CONFIG_FILE_NAME)!;
const projectPath = path.resolve(
path.dirname(findup("package.json")!),
"icon.config.yml",
ICON_CONFIG_FILE_NAME,
);
const configPath = findup("icon.config.yml")!;
const version = pkg.version;

const initCommand = new Command("init")
.alias("-i")
.description("Initialize icon.config.yml")
.action(() => {
.addOption(
new Option("-t, --template <template>", "choose template")
.choices(["dynamic", "vite"])
.default("dynamic"),
)
.action((options) => {
try {
const config = generateConfig();
fs.writeFileSync(projectPath, config);
console.log(kleur.green().underline("icon.config.yml generated!"));
console.log("");
const template = options.template as InitTemplate;

if (template === "dynamic") {
const config = generateDynamicConfig();
fs.writeFileSync(projectPath, config);
console.log(
kleur.green().underline(`⭐ ${ICON_CONFIG_FILE_NAME}`) +
kleur.green(" is created in project root!"),
);
}

if (template === "vite") {
const config = generateViteConfig();
fs.writeFileSync(projectPath, config);
console.log(
kleur.green().underline(`⭐ ${ICON_CONFIG_FILE_NAME}`) +
kleur.green(" is created in project root!"),
);

console.log(
kleur.yellow("Please add ") +
kleur
.yellow()
.bold()
.underline(
`<link rel="preload" as="image" type="image/svg+xml" href="your sprite href">`,
) +
kleur.yellow(" to your index.html if you want preload sprite.svg"),
);
}

console.log("");
} catch (e) {
console.error(e);
}
Expand All @@ -39,11 +77,13 @@ const generateCommand = new Command("generate")
.description("Generate SVG sprite and SeedIcon component")
.action(() => {
try {
console.log("");
const fileContents = yaml.load(
fs.readFileSync(configPath, "utf8"),
) as IconConfig;

const icons = fileContents.icons;
validateIcons(icons);

const spritePath = fileContents.spritePath || "src/assets/sprite.svg";
const spriteFileName = path.basename(spritePath, ".svg");
Expand All @@ -54,21 +94,21 @@ const generateCommand = new Command("generate")
const componentFileName = path.basename(componentPath, ".tsx");
const componentDir = path.dirname(componentPath);

validateIcons(icons);

const seedIconComponent = generateComponent({
const seedIconComponent = generateDynamicImportComponent({
componentFileName,
componentOutputPath: componentDir,
componentDir,
spriteFileName,
spriteOutputPath: spriteDir,
spriteDir,
version,
icons,
});

const spriteSvg = generateSprite({ icons });

const spriteOutputDir = path.resolve(spriteDir);
const iconComponentOutputDir = path.resolve(componentDir);

// create directories
if (!fs.existsSync(spriteOutputDir)) {
fs.mkdirSync(spriteOutputDir, { recursive: true });
}
Expand All @@ -77,6 +117,7 @@ const generateCommand = new Command("generate")
fs.mkdirSync(iconComponentOutputDir, { recursive: true });
}

// write files
fs.writeFileSync(
path.resolve(spriteDir, `${spriteFileName}.svg`),
spriteSvg,
Expand All @@ -86,18 +127,16 @@ const generateCommand = new Command("generate")
seedIconComponent,
);

// log
console.log(
kleur
.green()
.underline(`SVG sprite generate complete at ${spritePath}!`),
kleur.green("⭐ SVG sprite generate complete at ") +
kleur.green().bold().underline(spritePath),
);
console.log(
kleur
.green()
.underline(
`SeedIcon component generate complete at ${componentPath}!`,
),
kleur.green("⭐ SeedIcon component generate complete at ") +
kleur.green().bold().underline(`${componentPath}`),
);
console.log("");
} catch (error) {
if (error instanceof Error) {
if (error.message) {
Expand Down
27 changes: 12 additions & 15 deletions packages/icon/src/templates/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,24 @@ import { generateRelativeFilePath } from "../utils/path";

import type { IconName } from "../types";

interface ComponentInterface {
componentOutputPath: string;
interface DynamicImportComponentInterface {
componentDir: string;
componentFileName: string;
spriteOutputPath: string;
spriteDir: string;
spriteFileName: string;
version: string;
icons: IconName[];
}

export default function generate({
componentOutputPath,
export function generateDynamicImportComponent({
componentDir,
componentFileName,
spriteOutputPath,
spriteDir,
spriteFileName,
version,
icons,
}: ComponentInterface) {
const relativeSpritePath = generateRelativeFilePath(
componentOutputPath,
spriteOutputPath
);
}: DynamicImportComponentInterface) {
const relativeSpritePath = generateRelativeFilePath(componentDir, spriteDir);
const spriteUrl = relativeSpritePath.endsWith("/")
? `${relativeSpritePath}${spriteFileName}.svg`
: `${relativeSpritePath}/${spriteFileName}.svg`;
Expand All @@ -34,23 +31,23 @@ export default function generate({
export interface ${componentFileName}Props {
name: IconName;
width?: number;
height?: number;
size?: number;
className?: string;
};
const ${componentFileName}: ForwardRefRenderFunction<HTMLSpanElement, SeedIconProps> = (
{ name, className, width = 24, height = 24 },
{ name, className, size },
ref,
) => {
return (
<span
ref={ref}
style={{ display: "inline-flex", width: size, height: size }}
className={className}
data-seed-icon={name}
data-seed-icon-version="${version}"
>
<svg viewBox="0 0 24 24" width={width} height={height}>
<svg viewBox="0 0 24 24">
<use href={\`\${spriteUrl}#\${name}\`} />
</svg>
</span>
Expand Down
30 changes: 29 additions & 1 deletion packages/icon/src/templates/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import dedent from "string-dedent";

export default function generate() {
const YAML_SCHEMA_URL =
"https://raw.githubusercontent.com/daangn/karrot-ui-icon/main/schema/schema.json";

export function generateDynamicConfig() {
return dedent`
# yaml-language-server: $schema=${YAML_SCHEMA_URL}
# 아이콘 컴포넌트가 저장될 경로입니다. 프로젝트 루트 기준입니다.
# 예: src/components/SeedIcon.tsx
componentPath: src/components/SeedIcon.tsx
Expand All @@ -20,3 +25,26 @@ export default function generate() {
`;
}

export function generateViteConfig() {
return dedent`
# yaml-language-server: $schema=${YAML_SCHEMA_URL}
# 아이콘 컴포넌트가 저장될 경로입니다. 프로젝트 루트 기준입니다.
# 예: src/components/SeedIcon.tsx
componentPath: ./src/components/SeedIcon.tsx
# sprite svg 파일이 저장될 경로입니다. 프로젝트 루트 기준입니다.
# 예: src/assets/sprite.svg
spritePath: ./assets/sprite.svg
# https://www.figma.com/file/58VvezaS8z1FsIOr9KFHKW/icon?node-id=0%3A1
# 위 피그마 파일에서 사용되는 아이콘 이름을 추가해주세요.
# 예: icon_add_circle_fill | icon_add_circle_regular
icons:
- icon_add_circle_fill
- icon_add_circle_regular
- icon_add_circle_thin
`;
}

0 comments on commit 64d5540

Please sign in to comment.