├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .husky └── pre-commit ├── .nvmrc ├── .prettierrc.js ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README-CN.md ├── README.md ├── docs ├── index.html ├── package.json ├── public │ ├── _headers │ ├── favicon.svg │ ├── pwa-192x192.png │ ├── pwa-512x512.png │ └── safari-pinned-tab.svg ├── src │ ├── App.vue │ ├── auto-imports.d.ts │ ├── components.d.ts │ ├── components │ │ ├── Dropdown.vue │ │ ├── Footer.vue │ │ ├── GitBadge.vue │ │ ├── IconInfo.vue │ │ ├── LangSwitcher.vue │ │ ├── Message.vue │ │ ├── Navbar.vue │ │ ├── RandomIcon.vue │ │ ├── Sidebar.vue │ │ ├── ToggleTheme.vue │ │ └── ToolSidebar.vue │ ├── composables │ │ ├── dark.ts │ │ ├── index.ts │ │ └── locale.ts │ ├── i18n │ │ ├── index.ts │ │ └── translations │ │ │ ├── en.yml │ │ │ └── zh.yml │ ├── icons.ts │ ├── layouts │ │ ├── default.vue │ │ └── docs.vue │ ├── main.ts │ ├── modules │ │ ├── README.md │ │ ├── i18n.ts │ │ ├── nprogress.ts │ │ ├── pinia.ts │ │ └── pwa.ts │ ├── pages │ │ ├── [...locale].vue │ │ ├── docs.md │ │ └── zh │ │ │ └── docs.md │ ├── shims.d.ts │ ├── stores │ │ ├── icon.ts │ │ └── site.ts │ ├── styles │ │ ├── main.css │ │ └── markdown.css │ └── types.ts ├── tsconfig.json ├── unocss.config.ts └── vite.config.ts ├── iconpacks └── index.js ├── package.json ├── package ├── .gitignore ├── build │ └── rollup.config.js ├── index.html ├── package.json ├── src │ ├── App.vue │ ├── components │ │ └── Icon.ts │ ├── index.ts │ ├── main.ts │ ├── shims-vue.d.ts │ ├── styles │ │ ├── animation.css │ │ ├── flip.css │ │ ├── icon.css │ │ └── index.ts │ ├── utils │ │ └── index.ts │ └── vite-env.d.ts ├── tsconfig.json ├── types │ └── icons.d.ts ├── vite.config.ts └── yarn.lock ├── scripts ├── build.js ├── download.sh ├── release.sh ├── svgo.js ├── tasks.js ├── templates.js ├── update.sh └── utils.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | iconpacks/ 3 | package/icons/ 4 | package/build/ 5 | *dist/ 6 | docs/src/auto-imports.d.ts 7 | docs/src/components.d.ts 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: "vue-eslint-parser", 3 | parserOptions: { 4 | parser: "@typescript-eslint/parser", // Specifies the ESLint parser 5 | ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features 6 | sourceType: "module", // Allows for the use of imports 7 | ecmaFeatures: { 8 | // Allows for the parsing of JSX 9 | jsx: true 10 | } 11 | }, 12 | extends: [ 13 | "plugin:vue/vue3-recommended", 14 | "plugin:@typescript-eslint/recommended", 15 | "plugin:prettier/recommended" 16 | ], 17 | rules: { 18 | "@typescript-eslint/no-explicit-any": "off", 19 | "@typescript-eslint/ban-ts-comment": "off", 20 | "@typescript-eslint/no-var-requires": "off", 21 | "@typescript-eslint/no-unused-vars": "off", 22 | "@typescript-eslint/ban-types": "off", 23 | "@typescript-eslint/no-empty-interface": "off", 24 | "vue/require-default-prop": "off", 25 | "vue/require-prop-types": "off", 26 | "vue/multi-word-component-names": "off" 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | iconpacks/*/ 2 | *.zip 3 | dist/ 4 | 5 | # vscode settings 6 | .vscode 7 | 8 | # Logs 9 | logs 10 | *.log 11 | npm-debug.log* 12 | 13 | # Dependency directory 14 | node_modules 15 | 16 | # Optional npm cache directory 17 | .npm 18 | 19 | # Others 20 | .DS_Store 21 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint-staged 5 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v16 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: "none" 3 | }; 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [v1.0.0-rc3](https://github.com/Renovamen/oh-vue-icons/compare/1.0.0-rc2...v1.0.0-rc3) (2022-04-24) 4 | 5 | ### Bug Fixes 6 | 7 | - correct `vue-demi` version [#21](https://github.com/Renovamen/oh-vue-icons/issues/21) ([9220f4d](https://github.com/Renovamen/oh-vue-icons/commit/9220f4d76585849739af5885cd05db6e65770d3b)) 8 | 9 | ### Features 10 | 11 | - **iconpacks:** bump iconpacks: 12 | 13 | - [academicons](https://github.com/jpswalsh/academicons) (v1.9.2) 14 | - [Bootstrap Icons](https://github.com/twbs/icons) (v1.8.1) 15 | - [Flag Icons](https://github.com/lipis/flag-icon-css) (v6.2.0) 16 | - [Heroicons](https://github.com/tailwindlabs/heroicons) (v1.0.6) 17 | - [Material Design icons](https://github.com/google/material-design-icons) 18 | - [Octicons](https://github.com/primer/octicons) (v17.0.0) 19 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v6.19.0) 20 | - [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (v11.11.0) 21 | 22 | 23 | ## [v1.0.0-rc2](https://github.com/Renovamen/oh-vue-icons/compare/v1.0.0-rc1...1.0.0-rc2) (2022-01-27) 24 | 25 | ### Features 26 | 27 | - export type `CustomizeIconType` ([90da087](https://github.com/Renovamen/oh-vue-icons/commit/90da0871e8869e9b6ae2c19bfe01c33a7dfe0ac5)) ([#18](https://github.com/Renovamen/oh-vue-icons/issues/18), [#19](https://github.com/Renovamen/oh-vue-icons/pull/19)), which can be imported by 28 | 29 | ```js 30 | import type { CustomizeIconType } from "oh-vue-icons"; 31 | ``` 32 | 33 | - **iconpacks:** bump iconpacks ([d0a76db](https://github.com/Renovamen/oh-vue-icons/commit/d0a76dbf0886e99e790a759ae4ed6aa043954ed1)) 34 | - [academicons](https://github.com/jpswalsh/academicons) 35 | - [Bootstrap Icons](https://github.com/twbs/icons) (v1.7.2) 36 | - [Flag Icons](https://github.com/lipis/flag-icon-css) (v6.0.3) 37 | - [gameicons](https://github.com/game-icons/icons) 38 | - [Heroicons](https://github.com/tailwindlabs/heroicons) (v1.0.5) 39 | - [Ionicons](https://ionicons.com/) (v6.0.1) 40 | - [Material Design icons](https://github.com/google/material-design-icons) 41 | - [Octicons](https://github.com/primer/octicons) (v16.3.0) 42 | - [PrimeIcons](https://github.com/primefaces/primeicons) (v5.0.1-SNAPSHOT) 43 | - [Pixelarticons](https://github.com/halfmage/pixelarticons) (v1.5.0) 44 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v6.7.0) 45 | - [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (v11.8.0) 46 | 47 | 48 | 49 | ## [1.0.0-rc1](https://github.com/Renovamen/oh-vue-icons/compare/v0.4.7...v1.0.0-rc1) (2021-10-14) 50 | 51 | ### BREAKING CHANGES 52 | 53 | - import paths have changed: 54 | 55 | Vue 3: 56 | 57 | ```diff 58 | - import OhVueIcon from "oh-vue-icons/dist/v3/icon.es"; 59 | + import { OhVueIcon, addIcons } from "oh-vue-icons"; 60 | 61 | - OhVueIcon.add(FaFlag) 62 | + addIcons(FaFlag) 63 | ``` 64 | 65 | Vue 2: 66 | 67 | ```diff 68 | - import OhVueIcon from "oh-vue-icons"; 69 | + import { OhVueIcon, addIcons } from "oh-vue-icons"; 70 | 71 | - OhVueIcon.add(FaFlag) 72 | + addIcons(FaFlag) 73 | ``` 74 | 75 | - [`@vue/composition-api`](https://github.com/vuejs/composition-api) is needed for Vue 2, [@nuxtjs/composition-api](https://github.com/nuxt-community/composition-api) is needed for Nuxt 2. 76 | 77 | ### Features 78 | 79 | - **iconpacks:** bump iconpacks ([78cc148](https://github.com/Renovamen/oh-vue-icons/commit/78cc148d5684d371c3cf571a7835210960f84af0)) 80 | - [Bootstrap Icons](https://github.com/twbs/icons) (v1.5.0) 81 | - [Font Awesome 5](https://github.com/FortAwesome/Font-Awesome) (v5.15.4) 82 | - [Heroicons](https://github.com/tailwindlabs/heroicons) (v1.0.4) 83 | - [Octicons](https://github.com/primer/octicons) (v16.0.0) 84 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v5.18.0) 85 | - [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (v11.6.0) 86 | 87 | 88 | ## [0.4.7](https://github.com/Renovamen/oh-vue-icons/compare/v0.4.6...v0.4.7) (2021-08-02) 89 | 90 | ### Features 91 | 92 | - **iconpacks:** upgrade iconpacks ([dedff0b](https://github.com/Renovamen/oh-vue-icons/commit/dedff0bc3a2fa754cb9c4536449259241d468aab)): 93 | - [Heroicons](https://github.com/tailwindlabs/heroicons) (v1.0.3) 94 | - [Octicons](https://github.com/primer/octicons) (v15.0.0) 95 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v5.8.1) 96 | - [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (v11.6.0) 97 | - [Weather Icons](https://github.com/erikflowers/weather-icons) 98 | 99 | 100 | ## [0.4.6](https://github.com/Renovamen/oh-vue-icons/compare/v0.4.5...v0.4.6) (2021-07-25) 101 | 102 | ### Features 103 | 104 | - **iconpacks**: upgrade iconpacks ([9235fb9](https://github.com/Renovamen/oh-vue-icons/commit/9235fb97fb198502024bc431ca679866e9f0d6b9)): 105 | - [Bootstrap Icons](https://github.com/twbs/icons) (v1.5.0) 106 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v5.7.0) 107 | - [Octicons](https://github.com/primer/octicons) (v14.2.2) 108 | - [Cryptocurrency Icons](https://github.com/spothq/cryptocurrency-icons) (v0.18.0) 109 | 110 | 111 | ## [0.4.5](https://github.com/Renovamen/oh-vue-icons/compare/v0.4.4...v0.4.5) (2021-07-18) 112 | 113 | ### Bug Fixes 114 | 115 | - fix [#15](https://github.com/Renovamen/oh-vue-icons/issues/15) 116 | 117 | 118 | ## ~~[0.4.4](https://github.com/Renovamen/oh-vue-icons/compare/v0.4.3...v0.4.4) (2021-07-11)~~ 119 | 120 | **This version has been DEPRECATED (see [#15](https://github.com/Renovamen/oh-vue-icons/issues/15)), use v0.4.5 or above instead.** 121 | 122 | ### Features 123 | 124 | - **iconpack:** upgrade ([d04ddde](https://github.com/Renovamen/oh-vue-icons/commit/d04ddde68bc4fb88fc4c09b6b552ee45a0f930cc)): 125 | - [Cryptocurrency Icons](https://github.com/spothq/cryptocurrency-icons) (v0.17.2) 126 | - [gameicons](https://github.com/game-icons/icons) 127 | - [Heroicons](https://github.com/tailwindlabs/heroicons) (v1.0.2) 128 | - [Material Design icons](https://github.com/google/material-design-icons) (v4.0.0) 129 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v5.6.0) 130 | - [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (v11.5.0) 131 | 132 | 133 | ## [0.4.3](https://github.com/Renovamen/oh-vue-icons/compare/v0.4.2...v0.4.3) (2021-05-08) 134 | 135 | ### Features 136 | 137 | - **iconpack:** upgrade ([7026e84](https://github.com/Renovamen/oh-vue-icons/commit/7026e84c62209ee01a7b64ee1851bb3ea55779ad)): 138 | - [Heroicons](https://github.com/tailwindlabs/heroicons) (v1.0.1): 8 new icons 139 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v4.22.0): 31 new icons, 12 updated icons 140 | - [academicons](https://github.com/jpswalsh/academicons): 2 updated icons 141 | 142 | 143 | ## [0.4.2](https://github.com/Renovamen/oh-vue-icons/compare/v0.4.1...v0.4.2) (2021-04-14) 144 | 145 | ### Features 146 | 147 | - **iconpacks:** add [Material Design Icons](https://github.com/google/material-design-icons) ([#8](https://github.com/Renovamen/oh-vue-icons/issues/8)) ([b46accc](https://github.com/Renovamen/oh-vue-icons/commit/b46accc1f4a46fa804343f984647917355dd2b07)) 148 | - **iconpack:** upgrade ([01ed58a](https://github.com/Renovamen/oh-vue-icons/commit/01ed58a2092a5b10a93fb52b1f6c9f1d18d58816)): 149 | - [academicons](https://github.com/jpswalsh/academicons): 2 updated icons 150 | - [Heroicons](https://github.com/tailwindlabs/heroicons) (v1.0.0): 2 updated icons 151 | - [Octicons](https://github.com/primer/octicons) (v13.0.0): 10 new icons, 3 fixed icons 152 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v4.19.0): 7 new icons, 6 updated icons 153 | - [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (v11.4.0): 4 new icons, 1 updated icon 154 | 155 | 156 | ## [0.4.1](https://github.com/Renovamen/oh-vue-icons/compare/v0.3.1...v0.4.1) (2021-03-29) 157 | 158 | ### BREAKING CHANGES 159 | 160 | - expand data argument to remove need of array whem import icons ([c32a79b](https://github.com/Renovamen/oh-vue-icons/commit/c32a79b3a2d846b5c3aa5b490751d638e2c1db3b)) ([#10](https://github.com/Renovamen/oh-vue-icons/pull/10)) 161 | - use rollup to bundle the component in esm format ([4a31c95](https://github.com/Renovamen/oh-vue-icons/commit/4a31c9522854c7306b8f6fdfb3bf3fbdca5b24e9)) ([#9](https://github.com/Renovamen/oh-vue-icons/issues/9)) 162 | - import paths have changed: 163 | 164 | Icons: 165 | 166 | ```diff 167 | - OhVueIcon.add([FaFlag, RiZhihuFill]); 168 | + OhVueIcon.add(FaFlag, RiZhihuFill); 169 | ``` 170 | 171 | Vue 3: 172 | 173 | ```diff 174 | - import OhVueIcon from "oh-vue-icons/dist/v3/icon.umd.min"; 175 | + import OhVueIcon from "oh-vue-icons/dist/v3/icon.es"; 176 | ``` 177 | 178 | 179 | ## [0.3.1](https://github.com/Renovamen/oh-vue-icons/compare/v0.3.0...v0.3.1) (2021-03-26) 180 | 181 | ### Features 182 | 183 | - **iconpack:** upgrade [Bootstrap Icons](https://github.com/twbs/icons) (17 updated icons) ([5118f11](https://github.com/Renovamen/oh-vue-icons/commit/5118f1115855a5c1d625a07b4cda51a0ace6875d)) 184 | - **animation:** add `float` animation ([6d514cb](https://github.com/Renovamen/oh-vue-icons/commit/6d514cbee5d806002d6c453f5d3d0d6ba1aa598a)) 185 | 186 | 187 | ## [0.3.0](https://github.com/Renovamen/oh-vue-icons/compare/v0.2.2...v0.3.0) (2021-03-24) 188 | 189 | ### Features 190 | 191 | - add typescript supports ([#6](https://github.com/Renovamen/oh-vue-icons/issues/6)) ([24b9c3b](https://github.com/Renovamen/oh-vue-icons/commit/24b9c3b70971604bf816739f33f2f129abef82bd)) 192 | 193 | ### BREAKING CHANGES 194 | 195 | - import paths have changed: 196 | 197 | Vue 2: 198 | 199 | ```diff 200 | - import OhVueIcon from "oh-vue-icons/components/icon"; 201 | + import OhVueIcon from "oh-vue-icons"; 202 | ``` 203 | 204 | Vue 2 SSR: 205 | 206 | ```diff 207 | + import OhVueIcon from "oh-vue-icons/dist-css/v2/icon.umd.min"; 208 | + import 'oh-vue-icons/dist-css/v2/icon.css' 209 | ``` 210 | 211 | Vue 3: 212 | 213 | ```diff 214 | - import OhVueIcon from "oh-vue-icons/components/icon-v3"; 215 | + import OhVueIcon from "oh-vue-icons/dist/v3/icon.umd.min"; 216 | ``` 217 | 218 | Vue 3 SSR: 219 | 220 | ```diff 221 | + import OhVueIcon from "oh-vue-icons/dist-css/v3/icon.umd.min"; 222 | + import 'oh-vue-icons/dist-css/v3/icon.css' 223 | ``` 224 | 225 | 226 | ## [0.2.2](https://github.com/Renovamen/oh-vue-icons/compare/v0.2.1...v0.2.2) (2021-03-22) 227 | 228 | ### Features 229 | 230 | - **iconpack:** add [CoreUI Icons](https://github.com/coreui/coreui-icons) ([#5](https://github.com/Renovamen/oh-vue-icons/issues/5)) ([ad8434d](https://github.com/Renovamen/oh-vue-icons/commit/ad8434d0c26b7ac5bfbbda0f4862082bfc2324ad)), [Ionicons](https://ionicons.com/) ([#7](https://github.com/Renovamen/oh-vue-icons/issues/7)) ([3bce239](https://github.com/Renovamen/oh-vue-icons/commit/3bce239385fae7855817059ab5c6537f91420f99)), [PrimeIcons](https://github.com/primefaces/primeicons) ([#4](https://github.com/Renovamen/oh-vue-icons/issues/4)) ([5733e7c](https://github.com/Renovamen/oh-vue-icons/commit/5733e7cccf9c3e3b86be8f3ae35c200d2b03b518)) and [Heroicons](https://github.com/tailwindlabs/heroicons) ([697c391](https://github.com/Renovamen/oh-vue-icons/commit/697c3916ef7684f0589151d0ae82cc7777ba66b8)) 231 | - **iconpack:** upgrade ([91e597b](https://github.com/Renovamen/oh-vue-icons/commit/91e597bbc24774f9eb44c7348b1ed7d44c9ef8eb)): 232 | - [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (v11.2.0): 7 more icons, 1 updated icon 233 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v4.12.0): 41 more icons, 31 updated icons 234 | - [Font Awesome 5](https://github.com/FortAwesome/Font-Awesome) (v5.15.3): 1 updated icon 235 | 236 | 237 | ## [0.2.1](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.11...v0.2.1) (2021-03-14) 238 | 239 | ### BREAKING CHANGES 240 | 241 | - support Vue 3 🎉 ([d58e037](https://github.com/Renovamen/oh-vue-icons/commit/d58e037485ad48bd1a245adc0937714d101f2249)) 242 | - import path for Vue 2 has changed: 243 | 244 | ```diff 245 | - import OhVueIcon from "oh-vue-icons/components/Icon"; 246 | + import OhVueIcon from "oh-vue-icons/components/icon"; 247 | ``` 248 | 249 | ### Features 250 | 251 | - **iconpack:** upgrade: 252 | - [Pixelarticons](https://github.com/halfmage/pixelarticons) (v1.4.0): 9 more icons, 1 fixed icon ([4b9de36](https://github.com/Renovamen/oh-vue-icons/commit/4b9de361376158e62a19db60928f27c5946c163a)) 253 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v4.13.0): 32 more icons, 5 updated icons ([5f85208](https://github.com/Renovamen/oh-vue-icons/commit/5f85208cb7057e63f0ac97e481dd330a13facf09)) 254 | 255 | 256 | ## [0.1.11](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.10...v0.1.11) (2021-02-27) 257 | 258 | ### Bug Fixes 259 | 260 | - remove `core-js` from dependencies ([#3](https://github.com/Renovamen/oh-vue-icons/issues/3)) ([0213f03](https://github.com/Renovamen/oh-vue-icons/commit/0213f0336cfdd40e3d2d8f9fe1ecd2be8b842308)) 261 | 262 | 263 | ## [0.1.10](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.9...v0.1.10) (2021-02-25) 264 | 265 | ### Features 266 | 267 | - **iconpack:** upgrade ([f805e3d](https://github.com/Renovamen/oh-vue-icons/commit/f805e3d5dd53ae72ac29e1e5b06ce7cc9e9d45d6)): 268 | - [Bootstrap Icons](https://github.com/twbs/icons) (v1.4.0): 60 more icons 269 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v4.12.0): 49 more icons 270 | - [Weather Icons](https://github.com/erikflowers/weather-icons) (v2.0.12): fix 1 icon 271 | 272 | 273 | ## [0.1.9](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.8...v0.1.9) (2021-02-13) 274 | 275 | ### Features 276 | 277 | - **iconpack:** add [Line Awesome](https://icons8.com/line-awesome) ([#2](https://github.com/Renovamen/oh-vue-icons/issues/2)) ([d1cb04a](https://github.com/Renovamen/oh-vue-icons/commit/d1cb04ab9ee47d1ba7df649017c4141a8a23f02e)), [Pixelarticons](https://github.com/halfmage/pixelarticons) ([530a591](https://github.com/Renovamen/oh-vue-icons/commit/530a591c28223a9e0e524f09178178dc07599a38)) and [VSCode Icons](https://github.com/vscode-icons/vscode-icons) ([279991a](https://github.com/Renovamen/oh-vue-icons/commit/279991a3ae344252283c80138d2f2f9619564490)) 278 | - **iconpack:** upgrade ([eb263a4](https://github.com/Renovamen/oh-vue-icons/commit/eb263a461c3456107995e6576cfc8add28ff9190)): 279 | - [Bootstrap Icons](https://github.com/twbs/icons) (v1.3.0): 64 more icons 280 | - [Cryptocurrency Icons](https://github.com/spothq/cryptocurrency-icons) (v0.17.1): 26 more icons 281 | - [Octicons](https://github.com/primer/octicons) (v12.0.0): 3 more icons 282 | - [Simple Icons](https://github.com/simple-icons/simple-icons) (v4.10.0): 238 more icons 283 | 284 | 285 | ## [0.1.8](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.7...v0.1.8) (2021-02-02) 286 | 287 | ### Features 288 | 289 | - **iconpack**: add [Octicons](https://github.com/primer/octicons) ([b381719](https://github.com/Renovamen/oh-vue-icons/commit/b381719cddc9196b2824e3b2a99445115a38bc5c)) 290 | - **animation**: support adjusting animation speed, add `flash` animation ([e8ecf8f](https://github.com/Renovamen/oh-vue-icons/commit/e8ecf8fb672bedaf3370758b9833df69b3cca2ee)) 291 | 292 | 293 | ## [0.1.7](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.6...v0.1.7) (2021-01-05) 294 | 295 | ### Bug Fixes 296 | 297 | - fix tree shaking problems (which occured due to the code sructure change in v0.1.5) ([3507656](https://github.com/Renovamen/oh-vue-icons/commit/3507656076e533c20da09f01d565b3ac2d95f696)) 298 | 299 | ### Features 300 | 301 | - **iconpack**: add [Bootstrap Icons](https://github.com/twbs/icons) ([#1](https://github.com/Renovamen/oh-vue-icons/issues/1)) ([3b213fc](https://github.com/Renovamen/oh-vue-icons/commit/3b213fcd7f050b59ec80c63700ab42fbffa6e8b0)), [Flag Icons](https://github.com/lipis/flag-icon-css) ([02cc01a](https://github.com/Renovamen/oh-vue-icons/commit/02cc01a86a8d749540b1c92b16dedda82741a54c)) and [Pokemon Icons](https://github.com/TheArtificial/pokemon-icons) ([2473310](https://github.com/Renovamen/oh-vue-icons/commit/2473310b433045ae9894ade447a16de05b9ad9c2)) 302 | 303 | 304 | ## [0.1.6](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.5...v0.1.6) (2021-01-03) 305 | 306 | ### Features 307 | 308 | - add support to colorful icons ([7167a45](https://github.com/Renovamen/oh-vue-icons/commit/7167a45db2ce061cf96e83e2648e4200f33eebd8)) 309 | - support customizing icon fill color ([a19a142](https://github.com/Renovamen/oh-vue-icons/commit/a19a1425be02a33ed36dcd68cd62dede8cf93803)) 310 | - **iconpack**: add [Flat Color Icons](https://github.com/icons8/flat-color-icons) ([7167a45](https://github.com/Renovamen/oh-vue-icons/commit/7167a45db2ce061cf96e83e2648e4200f33eebd8)), [Cryptocurrency Icons](https://github.com/spothq/cryptocurrency-icons) ([ff909bf](https://github.com/Renovamen/oh-vue-icons/commit/ff909bf7f370ae38b963b6b82e5d7c8d336037e6)), [Simple Icons](https://github.com/simple-icons/simple-icons) ([87e0512](https://github.com/Renovamen/oh-vue-icons/commit/87e0512e2944c640456e16cacd05e759a4132b6f)) and [Weather Icons](https://github.com/erikflowers/weather-icons) ([4f9e4d1](https://github.com/Renovamen/oh-vue-icons/commit/4f9e4d1b0a13b6ed265366552d57b1d0473f16f5)) 311 | - **animation**: add `wrench`, `ring` and `pulse` animations ([2bdb1e6](https://github.com/Renovamen/oh-vue-icons/commit/2bdb1e60d01b92772c011fafcb47b3be32892319)) 312 | 313 | ### Chore 314 | 315 | - change the prefix of gameicons to 'gi' ([287852b](https://github.com/Renovamen/oh-vue-icons/commit/287852b605ce76695c761c9215dc7aece4e07812)) 316 | 317 | 318 | ## [0.1.5](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.2...v0.1.5) (2020-12-25) 319 | 320 | ### Features 321 | 322 | - **iconpack**: add [gameicons](https://github.com/game-icons/icons) ([1fb8dc1](https://github.com/Renovamen/oh-vue-icons/commit/1fb8dc130915f3c982e38fc1657c6332d36e43e2)) 323 | 324 | ### BREAKING CHANGES 325 | 326 | - change the way of importing icons ([40d37d2](https://github.com/Renovamen/oh-vue-icons/commit/40d37d2bcaeb71c70bfc416c18425d99a004a59f)) 327 | 328 | 329 | ## [0.1.2](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.1...v0.1.2) (2020-12-06) 330 | 331 | ### Features 332 | 333 | - resize some of the icons for better and more consistent user experience ([6caf2e2](https://github.com/Renovamen/oh-vue-icons/commit/6caf2e2091524a39f76ac5ae38ff7f53a165f7fa)) 334 | 335 | 336 | ## [0.1.1](https://github.com/Renovamen/oh-vue-icons/compare/v0.1.0...v0.1.1) (2020-12-06) 337 | 338 | ### Bug Fixes 339 | 340 | - upgrade some packages to generate svgs correctly ([0e37e60](https://github.com/Renovamen/oh-vue-icons/commit/0e37e60b509b6744d54839fdc03767b1ed038277)) 341 | 342 | ### Features 343 | 344 | - support importing a whole given icon pack ([cb3e137](https://github.com/Renovamen/oh-vue-icons/commit/cb3e1373ab2f76cb7ef95454e205bcb1396ab9dc)) 345 | 346 | 347 | ## [0.1.0](https://github.com/Renovamen/oh-vue-icons/compare/19c8c9d74ebf5a23c5dc34aace3b2807b06c9a9a...v0.1.0) (2020-12-04) 348 | 349 | ### Features 350 | 351 | - **iconpack**: add [Font Awesome 5](https://github.com/FortAwesome/Font-Awesome), [Remix Icon](https://github.com/Remix-Design/RemixIcon) and [academicons](https://github.com/jpswalsh/academicons) ([fbc2c5b](https://github.com/Renovamen/oh-vue-icons/commit/fbc2c5bcfb4a3c014c949553f279654756f2c862)) 352 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guides 2 | 3 | ## Development 4 | 5 | ### Install Dependencies 6 | 7 | Clone the repo and install dependencies: 8 | 9 | ```bash 10 | yarn 11 | ``` 12 | 13 | ### Icons 14 | 15 | Fetch icon sources: 16 | 17 | ```bash 18 | yarn download -f 19 | ``` 20 | 21 | This script would download icon packs as zip files from their Github repositories. Although it could be achieved more easily via "git submodule", too many submodules brings git too much loads and reduces its speed. 22 | 23 | Then, re-generate files under `package/icons` automatically: 24 | 25 | ```bash 26 | yarn icons 27 | ``` 28 | 29 | ### Dev 30 | 31 | ```bash 32 | yarn dev 33 | ``` 34 | 35 | ### Build 36 | 37 | ```bash 38 | yarn build 39 | ``` 40 | 41 | 42 |   43 | 44 | ## Website 45 | 46 | The source code of the website is under folder [`docs`](docs), built with [Vitesse](https://github.com/antfu/vitesse). 47 | 48 | Start developing: 49 | 50 | ```bash 51 | yarn docs 52 | ``` 53 | 54 | Generate static files: 55 | 56 | ```bash 57 | yarn build:docs 58 | ``` 59 | 60 | 61 |   62 | 63 | ## License 64 | 65 | By contributing to `oh-vue-icons`, you agree that your contributions will be licensed under its [MIT license](LICENSE). 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020-present Xiaohan Zou (@Renovamen) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | ----------------------------------------------------------------------------- 24 | 25 | oh-vue-icons is using the part of the following codes with the following licenses: 26 | 27 | MIT License 28 | Copyright (c) 2016–Present GU Yiling 29 | vue-awesome: https://github.com/Justineo/vue-awesome 30 | License: https://github.com/Justineo/vue-awesome/blob/master/LICENSE 31 | 32 | MIT License 33 | Copyright 2018 kamijin_fanta 34 | React Icons: https://github.com/react-icons/react-icons 35 | License: https://github.com/react-icons/react-icons/blob/master/LICENSE 36 | -------------------------------------------------------------------------------- /README-CN.md: -------------------------------------------------------------------------------- 1 | # Oh, Vue Icons! 2 | 3 | [![npm](https://img.shields.io/npm/v/oh-vue-icons.svg?style=flat-square)](https://www.npmjs.com/package/oh-vue-icons) ![downloads](https://img.shields.io/npm/dw/oh-vue-icons.svg?style=flat-square) [![license](https://img.shields.io/badge/License-MIT-green?style=flat-square)](LICENSE) 4 | 5 | [English](README.md) | **中文说明** 6 | 7 | `oh-vue-icons` 是一个能让你在 [Vue](https://vuejs.org/) 中轻松从多个流行图标库中引入 SVG 图标的组件。 8 | 9 | 10 |   11 | 12 | ## 特性 13 | 14 | - 支持 Vue 2 和 3 15 | - 支持 tree-shaking,因此你能够仅引入你需要的图标从而减小打包体积 16 | - 支持来自 [20 个流行的图标库](#支持的图标库)的 30000+ 个图标 17 | 18 | 19 |   20 | 21 | ## 支持的图标库 22 | 23 | 目前支持以下 20 个图标库: 24 | 25 | | 图标库 | 前缀 | 协议 | 图标数量 | 26 | | ------------------------------------------------------------- | ------ | ------------------------------------------------------------- | ---------- | 27 | | [academicons](https://github.com/jpswalsh/academicons) | `ai` | [SIL OFL 1.1](http://scripts.sil.org/OFL) | 149 | 28 | | [Bootstrap Icons](https://github.com/twbs/icons) | `bi` | [MIT](https://github.com/twbs/icons/blob/main/LICENSE.md) | 1668 | 29 | | [CoreUI Icons Free](https://github.com/coreui/coreui-icons) (Colorful) | `co` | [CC BY 4.0 License](https://github.com/coreui/coreui-icons/blob/master/LICENSE) | 1575 | 30 | | [Cryptocurrency Icons](https://github.com/spothq/cryptocurrency-icons) (Colorful) | `ci` | [CC0 1.0 Universal](https://github.com/spothq/cryptocurrency-icons/blob/master/LICENSE.md) | 942 | 31 | | [Font Awesome 5 Free](https://github.com/FortAwesome/Font-Awesome) | `fa` | [CC BY 4.0](https://github.com/FortAwesome/Font-Awesome/blob/master/LICENSE.txt) | 1610 | 32 | | [Flat Color Icons](https://github.com/icons8/flat-color-icons) (Colorful) | `fc` | [MIT / Good Boy](https://github.com/icons8/flat-color-icons/blob/master/LICENSE.md) | 329 | 33 | | [Flag Icon](https://github.com/lipis/flag-icon-css) (Colorful)| `fi` | [MIT](https://github.com/lipis/flag-icon-css/blob/master/LICENSE) | 530 | 34 | | [gameicons](https://github.com/game-icons/icons) | `gi` | [CC BY 3.0](https://github.com/game-icons/icons/blob/master/license.txt) | 4052 | 35 | | [Heroicons](https://github.com/tailwindlabs/heroicons) | `hi` | [MIT](https://github.com/tailwindlabs/heroicons/blob/master/LICENSE) | 460 | 36 | | [Ionicons](https://github.com/ionic-team/ionicons) | `io` | [MIT](https://github.com/ionic-team/ionicons/blob/master/LICENSE) | 1332 | 37 | | [Line Awesome](https://github.com/icons8/line-awesome) | `la` | [MIT / Good Boy](https://github.com/icons8/line-awesome/blob/master/LICENSE.md) | 1544 | 38 | | [Material Design icons](https://github.com/google/material-design-icons) | `md` | [Apache 2.0](https://github.com/google/material-design-icons/blob/master/LICENSE) | 10537 | 39 | | [Octicons](https://github.com/primer/octicons) | `oi` | [MIT](https://github.com/primer/octicons/blob/main/LICENSE) | 259 | 40 | | [Pokemon Icons](https://github.com/TheArtificial/pokemon-icons) (Colorful)| `pi` | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | 1453 | 41 | | [PrimeIcons](https://github.com/primefaces/primeicons) | `pr` | [MIT](https://github.com/primefaces/primeicons/blob/master/LICENSE) | 238 | 42 | | [Pixelarticons](https://github.com/halfmage/pixelarticons) | `px` | [MIT](https://github.com/halfmage/pixelarticons/blob/master/LICENSE) | 460 | 43 | | [Remix Icon](https://github.com/Remix-Design/RemixIcon) | `ri` | [Apache 2.0](https://github.com/Remix-Design/RemixIcon/blob/master/License) | 2271 | 44 | | [Simple Icons](https://github.com/simple-icons/simple-icons) | `si` | [CC0 1.0 Universal](https://github.com/simple-icons/simple-icons/blob/develop/LICENSE.md) | 2233 | 45 | | [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (Colorful) | `vi` | [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) | 1125 | 46 | | [Weather Icons](https://github.com/erikflowers/weather-icons) | `wi` | [SIL OFL 1.1](http://scripts.sil.org/OFL) | 219 | 47 | 48 | 49 |   50 | 51 | ## 文档 52 | 53 | 在[这里](https://oh-vue-icons.js.org/zh/)查找图标和查看文档。 54 | 55 | 56 |   57 | 58 | ## 安装 59 | 60 | ```bash 61 | yarn add oh-vue-icons 62 | # 或 63 | npm install oh-vue-icons 64 | ``` 65 | 66 | 使用 Vue 2 时,还需要安装 `@vue/composition-api`: 67 | 68 | ```bash 69 | yarn add @vue/composition-api -D 70 | ``` 71 | 72 | 如果用的是 [Nuxt 2](https://nuxtjs.org/),则需要安装的是 `@nuxtjs/composition-api`: 73 | 74 | ```bash 75 | yarn add @nuxtjs/composition-api -D 76 | ``` 77 | 78 | 然后把 `@nuxtjs/composition-api/module` 加到你的 `nuxt.config.js` 文件的 `buildModules` 项中,更多细节见[这里](https://composition-api.nuxtjs.org/getting-started/setup)。 79 | 80 | 81 |   82 | 83 | ## 引入 84 | 85 | ### 全局引入 86 | 87 | 首先需要在 `main.js` 中引入 `oh-vue-icons`。你可以只引入你需要的图标从而减小打包体积。 88 | 89 | 90 | #### Vue 3 91 | 92 | ```js 93 | // main.js 94 | import { createApp } from "vue"; 95 | import App from "./App.vue"; 96 | 97 | import { OhVueIcon, addIcons } from "oh-vue-icons"; 98 | import { FaFlag, RiZhihuFill } from "oh-vue-icons/icons"; 99 | 100 | addIcons(FaFlag, RiZhihuFill); 101 | 102 | const app = createApp(App); 103 | app.component("v-icon", OhVueIcon); 104 | app.mount("#app"); 105 | ``` 106 | 107 | 如果你并不在意打包体积,并希望引入某个图标库的所有图标,你可以: 108 | 109 | ```js 110 | // main.js 111 | // 引入 Font Awesome 112 | import * as FaIcons from 'oh-vue-icons/icons/fa' 113 | 114 | const Fa = Object.values({ ...FaIcons }) 115 | OhVueIcon.add(...Fa); 116 | ``` 117 | 118 | 119 | #### Vue 2 120 | 121 | ```js 122 | // main.js 123 | import Vue from "vue"; 124 | import App from "./App.vue"; 125 | 126 | import { OhVueIcon, addIcons } from "oh-vue-icons"; 127 | import { FaFlag, RiZhihuFill } from "oh-vue-icons/icons"; 128 | 129 | addIcons(FaFlag, RiZhihuFill); 130 | 131 | Vue.component("v-icon", OhVueIcon); 132 | 133 | new Vue({ 134 | render: h => h(App) 135 | }).$mount("#app"); 136 | ``` 137 | 138 | 139 |   140 | 141 | ### 局部引入 142 | 143 | ```js 144 | import OhVueIcon from "oh-vue-icons"; 145 | 146 | export default { 147 | components: { 148 | "v-icon": OhVueIcon 149 | } 150 | }; 151 | ``` 152 | 153 | 154 |   155 | 156 | ## 用法 157 | 158 | 通过 `name` prop 来指定图标名,`name` prop 值需要使用**短横线隔开式**命名: 159 | 160 | ```html 161 | 167 | ``` 168 | 169 | 对于 [Font Awesome 5](https://fontawesome.com/),来自 `regular` 包的图标的 `name` prop 值的前缀为 `fa-regular-` 而不是 `fa-`,如 `fa-regular-flag`。而 `solid` 和 `brands` 包的图标前缀均为 `fa-`,如 `fa-beer` 和 `fa-github`。 170 | 171 | [文档](https://oh-vue-icons.js.org/zh/docs#基本用法)中有更多的用法。 172 | 173 | 174 |   175 | 176 | ## Props 177 | 178 | | 名称 | 描述 | 类型 | 接受值 | 默认值 | 179 | | ----------- | ---------------------| --------- | ------------------------------------------------------------- | -------------- | 180 | | `scale` | 图标大小 | `number` | / | `1` | 181 | | `animation` | 动画类型 | `string` | `wrench` / `ring` / `pulse` / `spin` / `spin-pulse` / `flash` / `float` | / | 182 | | `speed` | 动画速度 | `string` | `slow` / `fast` | / | 183 | | `hover` | 仅在被 hover 时启用动画 | `boolean` | `true` / `false` | `false` | 184 | | `flip` | 翻转类型 | `string` | `vertical` / `horizontal` / `both` | / | 185 | | `fill` | 图标的填充颜色 | `string` | 颜色名称或十六进制颜色代码 | `currentColor` | 186 | | `label` | 图标的 lable | `string` | / | / | 187 | | `title` | 图标的 title | `string` | / | / | 188 | | `inverse` | 把图标变成白色 | `boolean` | `true` / `false` | `false` | 189 | 190 | [文档](https://oh-vue-icons.js.org/zh/docs#示例)中有一些示例。 191 | 192 | 193 |   194 | 195 | ## Nuxt 196 | 197 | 当使用 Nuxt.js 时,需要按照 [Nuxt 文档](https://nuxtjs.org/docs/2.x/directory-structure/plugins)中的方式,将 `oh-vue-icons` 注册为一个插件。 198 | 199 | 然后需要在 `nuxt.config.js` 的 `build.transpile` 项中添加 `oh-vue-icons`(具体解释见[这里](https://nuxtjs.org/docs/2.x/directory-structure/plugins)): 200 | 201 | ```js 202 | export default { 203 | // ... 204 | build: { 205 | transpile: ['oh-vue-icons'] 206 | } 207 | } 208 | ``` 209 | 210 | 为了仅在客户端(client-side)渲染该组件,需要把组件包裹在 `` 标签里: 211 | 212 | ```html 213 | 221 | ``` 222 | 223 | 224 |   225 | 226 | ## Vite 227 | 228 | 使用 [Vite](https://cn.vitejs.dev/) 作为打包工具时,建议在预构建中排除 `oh-vue-icons`(具体讨论见 [#20](https://github.com/Renovamen/oh-vue-icons/issues/20)): 229 | 230 | ```js 231 | // vite.config.js 232 | 233 | export default { 234 | // ... 235 | optimizeDeps: { 236 | exclude: ["oh-vue-icons/icons"] 237 | } 238 | } 239 | ``` 240 | 241 | 当使用 Vite 的[服务端渲染(SSR)](https://cn.vitejs.dev/guide/ssr.html)功能时(例如 [VuePress](https://v2.vuepress.vuejs.org/zh/)、[Vite SSG](https://github.com/antfu/vite-ssg) 等),需要将 `oh-vue-icons` 加入 `ssr.noExternal` 项(具体解释见[这里](https://cn.vitejs.dev/guide/ssr.html#ssr-externals)): 242 | 243 | ```js 244 | // vite.config.js 245 | 246 | export default { 247 | // ... 248 | ssr: { 249 | noExternal: ["oh-vue-icons"] 250 | } 251 | } 252 | ``` 253 | 254 | 255 |   256 | 257 | ## 贡献 258 | 259 | 欢迎贡献,这里是[贡献指南](CONTRIBUTING.md)。 260 | 261 | 262 |   263 | 264 | ## 致谢 265 | 266 | - 本项目受到了 [vue-awesome](https://github.com/Justineo/vue-awesome) 和 [react-icons](https://github.com/react-icons/react-icons) 的启发并借鉴了它们的部分代码 267 | - [文档网站](https://oh-vue-icons.js.org)由 [Vitesse](https://github.com/antfu/vitesse) 驱动,部署在 [Netlify](https://www.netlify.com/) 上 268 | 269 | 270 |   271 | 272 | ## 开源协议 273 | 274 | 本项目使用 [MIT](LICENSE) 开源协议。图标来自于[其他项目](#支持的图标库),所以还需要参考这些项目的开源协议。 275 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Oh, Vue Icons! 2 | 3 | [![npm](https://img.shields.io/npm/v/oh-vue-icons.svg?style=flat-square)](https://www.npmjs.com/package/oh-vue-icons) ![downloads](https://img.shields.io/npm/dw/oh-vue-icons.svg?style=flat-square) [![license](https://img.shields.io/badge/License-MIT-green?style=flat-square)](LICENSE) 4 | 5 | **English** | [中文说明](README-CN.md) 6 | 7 | A [Vue](https://vuejs.org/) component for including inline SVG icons from different popular icon packs easily. 8 | 9 | 10 |   11 | 12 | ## Features 13 | 14 | - Works for both Vue 2 & 3 15 | - Supports tree-shaking: only import the icons you want 16 | - 30000+ icons from 20 popular icon packs, see [here](#supported-icon-packs) 17 | 18 | 19 |   20 | 21 | ## Supported Icon Packs 22 | 23 | Now the following 20 icon packs are supported: 24 | 25 | | Icon Pack | Prefix | License | Counts | 26 | | ------------------------------------------------------------- | ------ | ------------------------------------------------------------- | ---------- | 27 | | [academicons](https://github.com/jpswalsh/academicons) | `ai` | [SIL OFL 1.1](http://scripts.sil.org/OFL) | 149 | 28 | | [Bootstrap Icons](https://github.com/twbs/icons) | `bi` | [MIT](https://github.com/twbs/icons/blob/main/LICENSE.md) | 1668 | 29 | | [CoreUI Icons Free](https://github.com/coreui/coreui-icons) (Colorful) | `co` | [CC BY 4.0 License](https://github.com/coreui/coreui-icons/blob/master/LICENSE) | 1575 | 30 | | [Cryptocurrency Icons](https://github.com/spothq/cryptocurrency-icons) (Colorful) | `ci` | [CC0 1.0 Universal](https://github.com/spothq/cryptocurrency-icons/blob/master/LICENSE.md) | 942 | 31 | | [Font Awesome 5 Free](https://github.com/FortAwesome/Font-Awesome) | `fa` | [CC BY 4.0](https://github.com/FortAwesome/Font-Awesome/blob/master/LICENSE.txt) | 1610 | 32 | | [Flat Color Icons](https://github.com/icons8/flat-color-icons) (Colorful) | `fc` | [MIT / Good Boy](https://github.com/icons8/flat-color-icons/blob/master/LICENSE.md) | 329 | 33 | | [Flag Icon](https://github.com/lipis/flag-icon-css) (Colorful)| `fi` | [MIT](https://github.com/lipis/flag-icon-css/blob/master/LICENSE) | 530 | 34 | | [gameicons](https://github.com/game-icons/icons) | `gi` | [CC BY 3.0](https://github.com/game-icons/icons/blob/master/license.txt) | 4052 | 35 | | [Heroicons](https://github.com/tailwindlabs/heroicons) | `hi` | [MIT](https://github.com/tailwindlabs/heroicons/blob/master/LICENSE) | 460 | 36 | | [Ionicons](https://github.com/ionic-team/ionicons) | `io` | [MIT](https://github.com/ionic-team/ionicons/blob/master/LICENSE) | 1332 | 37 | | [Line Awesome](https://github.com/icons8/line-awesome) | `la` | [MIT / Good Boy](https://github.com/icons8/line-awesome/blob/master/LICENSE.md) | 1544 | 38 | | [Material Design icons](https://github.com/google/material-design-icons) | `md` | [Apache 2.0](https://github.com/google/material-design-icons/blob/master/LICENSE) | 10537 | 39 | | [Octicons](https://github.com/primer/octicons) | `oi` | [MIT](https://github.com/primer/octicons/blob/main/LICENSE) | 259 | 40 | | [Pokemon Icons](https://github.com/TheArtificial/pokemon-icons) (Colorful)| `pi` | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | 1453 | 41 | | [PrimeIcons](https://github.com/primefaces/primeicons) | `pr` | [MIT](https://github.com/primefaces/primeicons/blob/master/LICENSE) | 238 | 42 | | [Pixelarticons](https://github.com/halfmage/pixelarticons) | `px` | [MIT](https://github.com/halfmage/pixelarticons/blob/master/LICENSE) | 460 | 43 | | [Remix Icon](https://github.com/Remix-Design/RemixIcon) | `ri` | [Apache 2.0](https://github.com/Remix-Design/RemixIcon/blob/master/License) | 2271 | 44 | | [Simple Icons](https://github.com/simple-icons/simple-icons) | `si` | [CC0 1.0 Universal](https://github.com/simple-icons/simple-icons/blob/develop/LICENSE.md) | 2233 | 45 | | [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (Colorful) | `vi` | [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) | 1125 | 46 | | [Weather Icons](https://github.com/erikflowers/weather-icons) | `wi` | [SIL OFL 1.1](http://scripts.sil.org/OFL) | 219 | 47 | 48 | 49 |   50 | 51 | ## Documentation 52 | 53 | Search for icons and view the documentation [here](https://oh-vue-icons.js.org). 54 | 55 | 56 |   57 | 58 | ## Installation 59 | 60 | ```bash 61 | yarn add oh-vue-icons 62 | # or 63 | npm install oh-vue-icons 64 | ``` 65 | 66 | For Vue 2, you'll also need `@vue/composition-api`: 67 | 68 | ```bash 69 | yarn add @vue/composition-api -D 70 | ``` 71 | 72 | Or if you are using [Nuxt 2](https://nuxtjs.org/), you'll need `@nuxtjs/composition-api` instead: 73 | 74 | ```bash 75 | yarn add @nuxtjs/composition-api -D 76 | ``` 77 | 78 | then add `@nuxtjs/composition-api/module` to the `buildModules` option in your `nuxt.config.js`, see [here](https://composition-api.nuxtjs.org/getting-started/setup) for details. 79 | 80 | 81 |   82 | 83 | ## Import 84 | 85 | ### Global Import 86 | 87 | Import `oh-vue-icons` and install it into Vue in `main.js`. You can only import the icons you need to reduce the bundle size. 88 | 89 | From `v1.x`, this library works for both Vue 2 & 3 within a single package. 90 | 91 | 92 | #### Vue 3 93 | 94 | ```js 95 | // main.js 96 | import { createApp } from "vue"; 97 | import App from "./App.vue"; 98 | 99 | import { OhVueIcon, addIcons } from "oh-vue-icons"; 100 | import { FaFlag, RiZhihuFill } from "oh-vue-icons/icons"; 101 | 102 | addIcons(FaFlag, RiZhihuFill); 103 | 104 | const app = createApp(App); 105 | app.component("v-icon", OhVueIcon); 106 | app.mount("#app"); 107 | ``` 108 | 109 | If you don't care about the bundle size and want to import a whole icon pack, you may should: 110 | 111 | ```js 112 | // main.js 113 | // import Font Awesome 114 | import * as FaIcons from "oh-vue-icons/icons/fa"; 115 | 116 | const Fa = Object.values({ ...FaIcons }); 117 | addIcons(...Fa); 118 | ``` 119 | 120 | 121 | #### Vue 2 122 | 123 | ```js 124 | // main.js 125 | import Vue from "vue"; 126 | import App from "./App.vue"; 127 | 128 | import { OhVueIcon, addIcons } from "oh-vue-icons"; 129 | import { FaFlag, RiZhihuFill } from "oh-vue-icons/icons"; 130 | 131 | addIcons(FaFlag, RiZhihuFill); 132 | 133 | Vue.component("v-icon", OhVueIcon); 134 | 135 | new Vue({ 136 | render: h => h(App) 137 | }).$mount("#app"); 138 | ``` 139 | 140 | 141 |   142 | 143 | ### Local Import 144 | 145 | ```js 146 | import OhVueIcon from "oh-vue-icons"; 147 | 148 | export default { 149 | components: { 150 | "v-icon": OhVueIcon 151 | } 152 | }; 153 | ``` 154 | 155 | 156 |   157 | 158 | ## Usage 159 | 160 | The icon names should be passed using **kebab-case**. 161 | 162 | ```html 163 | 169 | ``` 170 | 171 | For [Font Awesome 5](https://fontawesome.com/) icons, icons from `regular` pack have name prop values like `fa-regular-flag`. Icons from `solid` and `brands` pack have name prop values like `fa-beer` and `fa-github`. 172 | 173 | See the [documentation](https://oh-vue-icons.js.orgdocs#basic-usage) for more about the usage. 174 | 175 | 176 |   177 | 178 | ## Props 179 | 180 | | Name | Description | Type | Accepted Values | Default value | 181 | | ----------- | ---------------------------------------- | --------- | ------------------------------------------------------------- | -------------- | 182 | | `scale` | Icon size | `number` | / | `1` | 183 | | `animation` | Type of animation | `string` | `wrench` / `ring` / `pulse` / `spin` / `spin-pulse` / `flash` / `float` | / | 184 | | `speed` | Animation speed | `string` | `slow` / `fast` | / | 185 | | `hover` | Enable animation only when being hovered | `boolean` | `true` / `false` | `false` | 186 | | `flip` | Used to flip icon | `string` | `vertical` / `horizontal` / `both` | / | 187 | | `fill` | Fill color of icon | `string` | HEX color code or color name | `currentColor` | 188 | | `label` | Icon lable | `string` | / | / | 189 | | `title` | Icon title | `string` | / | / | 190 | | `inverse` | Make icon color white? | `boolean` | `true` / `false` | `false` | 191 | 192 | Some examples could be found in the [documentation](https://oh-vue-icons.js.orgdocs#examples). 193 | 194 | 195 |   196 | 197 | ## Nuxt 198 | 199 | When using Nuxt, you need to register `oh-vue-icons` as a plugin following [Nuxt's documentation](https://nuxtjs.org/docs/directory-structure/plugins#vue-plugins). 200 | 201 | It should be noted that, `oh-vue-icons` should be added to the `build.transpile` option in your `nuxt.config.js` (see [here](https://nuxtjs.org/docs/directory-structure/plugins/#es6-plugins) for details): 202 | 203 | ```js 204 | export default { 205 | // ... 206 | build: { 207 | transpile: ["oh-vue-icons"] 208 | } 209 | } 210 | ``` 211 | 212 | To render the icon component only on client-side, you may need to wrap it in a `` tag: 213 | 214 | ```html 215 | 223 | ``` 224 | 225 | 226 |   227 | 228 | ## Vite 229 | 230 | When using [Vite](https://vitejs.dev/), it is suggested to exclude `oh-vue-icons` from pre-bundling (see [#20](https://github.com/Renovamen/oh-vue-icons/issues/20) for details): 231 | 232 | ```js 233 | // vite.config.js 234 | 235 | export default { 236 | // ... 237 | optimizeDeps: { 238 | exclude: ["oh-vue-icons/icons"] 239 | } 240 | } 241 | ``` 242 | 243 | When using Vite's [Server-Side Rendering (SSR)](https://vitejs.dev/guide/ssr.html) support ([VuePress](https://v2.vuepress.vuejs.org/), [Vite SSG](https://github.com/antfu/vite-ssg), etc.), `oh-vue-icons` should be added to the `ssr.noExternal` option (see [here](https://vitejs.dev/guide/ssr.html#ssr-externals) for details): 244 | 245 | ```js 246 | // vite.config.js 247 | 248 | export default { 249 | // ... 250 | ssr: { 251 | noExternal: ["oh-vue-icons"] 252 | } 253 | } 254 | ``` 255 | 256 | 257 |   258 | 259 | ## Contributing 260 | 261 | Contributions are welcomed, see the [contribution guides](CONTRIBUTING.md). 262 | 263 | 264 |   265 | 266 | ## Acknowledgements 267 | 268 | - This project is inspired by and based on [vue-awesome](https://github.com/Justineo/vue-awesome) and [react-icons](https://github.com/react-icons/react-icons) 269 | - The [website](https://oh-vue-icons.js.org) is built with [Vitesse](https://github.com/antfu/vitesse) and hosted on [Netlify](https://www.netlify.com/) 270 | 271 | 272 |   273 | 274 | ## License 275 | 276 | This project is [MIT](LICENSE) licensed. Icons are taken from [other projects](#supported-icon-packs), so check the license of each accordingly. 277 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "vite-ssg build", 7 | "dev": "vite --port 3333 --open", 8 | "preview": "vite preview", 9 | "preview-https": "serve dist", 10 | "typecheck": "vue-tsc --noEmit" 11 | }, 12 | "dependencies": { 13 | "@vueuse/core": "^8.2.6", 14 | "@vueuse/head": "^0.7.6", 15 | "camelcase": "^6.3.0", 16 | "copy-text-to-clipboard": "^3.0.1", 17 | "nprogress": "^0.2.0", 18 | "oh-vue-icons-npm": "npm:oh-vue-icons@1.0.0-rc3", 19 | "pinia": "^2.0.13", 20 | "prism-theme-vars": "^0.2.2", 21 | "vue": "^3.2.33", 22 | "vue-demi": "^0.12.5", 23 | "vue-i18n": "^9.1.9", 24 | "vue-router": "^4.0.14", 25 | "vue-slider-component": "^4.0.0-beta.5", 26 | "vue3-swatches": "^1.0.7" 27 | }, 28 | "devDependencies": { 29 | "@intlify/vite-plugin-vue-i18n": "^4.0.0", 30 | "@types/markdown-it-link-attributes": "^3.0.1", 31 | "@types/nprogress": "^0.2.0", 32 | "@vitejs/plugin-vue": "^2.3.1", 33 | "critters": "^0.0.16", 34 | "cross-env": "^7.0.3", 35 | "https-localhost": "^4.7.1", 36 | "markdown-it-link-attributes": "^4.0.0", 37 | "markdown-it-prism": "^2.2.4", 38 | "typescript": "^4.6.3", 39 | "unocss": "^0.31.5", 40 | "unplugin-auto-import": "^0.7.1", 41 | "unplugin-vue-components": "^0.19.3", 42 | "vite": "^2.9.5", 43 | "vite-plugin-inspect": "^0.5.0", 44 | "vite-plugin-md": "^0.12.4", 45 | "vite-plugin-pages": "^0.23.0", 46 | "vite-plugin-pwa": "^0.11.13", 47 | "vite-plugin-vue-layouts": "^0.6.0", 48 | "vite-ssg": "^0.19.2", 49 | "vite-ssg-sitemap": "^0.2.3", 50 | "vue-tsc": "^0.34.7" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /docs/public/_headers: -------------------------------------------------------------------------------- 1 | /assets/* 2 | cache-control: max-age=31536000 3 | cache-control: immutable 4 | -------------------------------------------------------------------------------- /docs/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/public/pwa-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Renovamen/oh-vue-icons/931fa2161005df3aa68263bec469ea001cac1971/docs/public/pwa-192x192.png -------------------------------------------------------------------------------- /docs/public/pwa-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Renovamen/oh-vue-icons/931fa2161005df3aa68263bec469ea001cac1971/docs/public/pwa-512x512.png -------------------------------------------------------------------------------- /docs/public/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 46 | -------------------------------------------------------------------------------- /docs/src/auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by 'unplugin-auto-import' 2 | // We suggest you to commit this file into source control 3 | declare global { 4 | const $: typeof import('vue/macros')['$'] 5 | const $$: typeof import('vue/macros')['$$'] 6 | const $computed: typeof import('vue/macros')['$computed'] 7 | const $customRef: typeof import('vue/macros')['$customRef'] 8 | const $ref: typeof import('vue/macros')['$ref'] 9 | const $shallowRef: typeof import('vue/macros')['$shallowRef'] 10 | const $toRef: typeof import('vue/macros')['$toRef'] 11 | const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] 12 | const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] 13 | const computed: typeof import('vue')['computed'] 14 | const computedAsync: typeof import('@vueuse/core')['computedAsync'] 15 | const computedEager: typeof import('@vueuse/core')['computedEager'] 16 | const computedInject: typeof import('@vueuse/core')['computedInject'] 17 | const computedWithControl: typeof import('@vueuse/core')['computedWithControl'] 18 | const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] 19 | const controlledRef: typeof import('@vueuse/core')['controlledRef'] 20 | const createApp: typeof import('vue')['createApp'] 21 | const createEventHook: typeof import('@vueuse/core')['createEventHook'] 22 | const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] 23 | const createInjectionState: typeof import('@vueuse/core')['createInjectionState'] 24 | const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn'] 25 | const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] 26 | const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn'] 27 | const customRef: typeof import('vue')['customRef'] 28 | const debouncedRef: typeof import('@vueuse/core')['debouncedRef'] 29 | const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] 30 | const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] 31 | const defineComponent: typeof import('vue')['defineComponent'] 32 | const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] 33 | const effectScope: typeof import('vue')['effectScope'] 34 | const EffectScope: typeof import('vue')['EffectScope'] 35 | const extendRef: typeof import('@vueuse/core')['extendRef'] 36 | const getCurrentInstance: typeof import('vue')['getCurrentInstance'] 37 | const getCurrentScope: typeof import('vue')['getCurrentScope'] 38 | const h: typeof import('vue')['h'] 39 | const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] 40 | const inject: typeof import('vue')['inject'] 41 | const isDefined: typeof import('@vueuse/core')['isDefined'] 42 | const isReadonly: typeof import('vue')['isReadonly'] 43 | const isRef: typeof import('vue')['isRef'] 44 | const logicAnd: typeof import('@vueuse/core')['logicAnd'] 45 | const logicNot: typeof import('@vueuse/core')['logicNot'] 46 | const logicOr: typeof import('@vueuse/core')['logicOr'] 47 | const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] 48 | const markRaw: typeof import('vue')['markRaw'] 49 | const nextTick: typeof import('vue')['nextTick'] 50 | const onActivated: typeof import('vue')['onActivated'] 51 | const onBeforeMount: typeof import('vue')['onBeforeMount'] 52 | const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] 53 | const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] 54 | const onClickOutside: typeof import('@vueuse/core')['onClickOutside'] 55 | const onDeactivated: typeof import('vue')['onDeactivated'] 56 | const onErrorCaptured: typeof import('vue')['onErrorCaptured'] 57 | const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke'] 58 | const onLongPress: typeof import('@vueuse/core')['onLongPress'] 59 | const onMounted: typeof import('vue')['onMounted'] 60 | const onRenderTracked: typeof import('vue')['onRenderTracked'] 61 | const onRenderTriggered: typeof import('vue')['onRenderTriggered'] 62 | const onScopeDispose: typeof import('vue')['onScopeDispose'] 63 | const onServerPrefetch: typeof import('vue')['onServerPrefetch'] 64 | const onStartTyping: typeof import('@vueuse/core')['onStartTyping'] 65 | const onUnmounted: typeof import('vue')['onUnmounted'] 66 | const onUpdated: typeof import('vue')['onUpdated'] 67 | const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] 68 | const provide: typeof import('vue')['provide'] 69 | const reactify: typeof import('@vueuse/core')['reactify'] 70 | const reactifyObject: typeof import('@vueuse/core')['reactifyObject'] 71 | const reactive: typeof import('vue')['reactive'] 72 | const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed'] 73 | const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit'] 74 | const reactivePick: typeof import('@vueuse/core')['reactivePick'] 75 | const readonly: typeof import('vue')['readonly'] 76 | const ref: typeof import('vue')['ref'] 77 | const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] 78 | const refDebounced: typeof import('@vueuse/core')['refDebounced'] 79 | const refDefault: typeof import('@vueuse/core')['refDefault'] 80 | const refThrottled: typeof import('@vueuse/core')['refThrottled'] 81 | const refWithControl: typeof import('@vueuse/core')['refWithControl'] 82 | const resolveComponent: typeof import('vue')['resolveComponent'] 83 | const shallowReactive: typeof import('vue')['shallowReactive'] 84 | const shallowReadonly: typeof import('vue')['shallowReadonly'] 85 | const shallowRef: typeof import('vue')['shallowRef'] 86 | const syncRef: typeof import('@vueuse/core')['syncRef'] 87 | const syncRefs: typeof import('@vueuse/core')['syncRefs'] 88 | const templateRef: typeof import('@vueuse/core')['templateRef'] 89 | const throttledRef: typeof import('@vueuse/core')['throttledRef'] 90 | const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] 91 | const toRaw: typeof import('vue')['toRaw'] 92 | const toReactive: typeof import('@vueuse/core')['toReactive'] 93 | const toRef: typeof import('vue')['toRef'] 94 | const toRefs: typeof import('vue')['toRefs'] 95 | const triggerRef: typeof import('vue')['triggerRef'] 96 | const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] 97 | const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] 98 | const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] 99 | const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] 100 | const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted'] 101 | const unref: typeof import('vue')['unref'] 102 | const unrefElement: typeof import('@vueuse/core')['unrefElement'] 103 | const until: typeof import('@vueuse/core')['until'] 104 | const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] 105 | const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] 106 | const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] 107 | const useAttrs: typeof import('vue')['useAttrs'] 108 | const useBase64: typeof import('@vueuse/core')['useBase64'] 109 | const useBattery: typeof import('@vueuse/core')['useBattery'] 110 | const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] 111 | const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel'] 112 | const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] 113 | const useCached: typeof import('@vueuse/core')['useCached'] 114 | const useClamp: typeof import('@vueuse/core')['useClamp'] 115 | const useClipboard: typeof import('@vueuse/core')['useClipboard'] 116 | const useColorMode: typeof import('@vueuse/core')['useColorMode'] 117 | const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] 118 | const useCounter: typeof import('@vueuse/core')['useCounter'] 119 | const useCssModule: typeof import('vue')['useCssModule'] 120 | const useCssVar: typeof import('@vueuse/core')['useCssVar'] 121 | const useCssVars: typeof import('vue')['useCssVars'] 122 | const useCycleList: typeof import('@vueuse/core')['useCycleList'] 123 | const useDark: typeof import('@vueuse/core')['useDark'] 124 | const useDateFormat: typeof import('@vueuse/core')['useDateFormat'] 125 | const useDebounce: typeof import('@vueuse/core')['useDebounce'] 126 | const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] 127 | const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] 128 | const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] 129 | const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] 130 | const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] 131 | const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] 132 | const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] 133 | const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] 134 | const useDraggable: typeof import('@vueuse/core')['useDraggable'] 135 | const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] 136 | const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] 137 | const useElementHover: typeof import('@vueuse/core')['useElementHover'] 138 | const useElementSize: typeof import('@vueuse/core')['useElementSize'] 139 | const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] 140 | const useEventBus: typeof import('@vueuse/core')['useEventBus'] 141 | const useEventListener: typeof import('@vueuse/core')['useEventListener'] 142 | const useEventSource: typeof import('@vueuse/core')['useEventSource'] 143 | const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper'] 144 | const useFavicon: typeof import('@vueuse/core')['useFavicon'] 145 | const useFetch: typeof import('@vueuse/core')['useFetch'] 146 | const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess'] 147 | const useFocus: typeof import('@vueuse/core')['useFocus'] 148 | const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin'] 149 | const useFps: typeof import('@vueuse/core')['useFps'] 150 | const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] 151 | const useGamepad: typeof import('@vueuse/core')['useGamepad'] 152 | const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] 153 | const useHead: typeof import('@vueuse/head')['useHead'] 154 | const useI18n: typeof import('vue-i18n')['useI18n'] 155 | const useIdle: typeof import('@vueuse/core')['useIdle'] 156 | const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll'] 157 | const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] 158 | const useInterval: typeof import('@vueuse/core')['useInterval'] 159 | const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] 160 | const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] 161 | const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] 162 | const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] 163 | const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] 164 | const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] 165 | const useMediaControls: typeof import('@vueuse/core')['useMediaControls'] 166 | const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery'] 167 | const useMemoize: typeof import('@vueuse/core')['useMemoize'] 168 | const useMemory: typeof import('@vueuse/core')['useMemory'] 169 | const useMounted: typeof import('@vueuse/core')['useMounted'] 170 | const useMouse: typeof import('@vueuse/core')['useMouse'] 171 | const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement'] 172 | const useMousePressed: typeof import('@vueuse/core')['useMousePressed'] 173 | const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver'] 174 | const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage'] 175 | const useNetwork: typeof import('@vueuse/core')['useNetwork'] 176 | const useNow: typeof import('@vueuse/core')['useNow'] 177 | const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination'] 178 | const useOnline: typeof import('@vueuse/core')['useOnline'] 179 | const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] 180 | const useParallax: typeof import('@vueuse/core')['useParallax'] 181 | const usePermission: typeof import('@vueuse/core')['usePermission'] 182 | const usePointer: typeof import('@vueuse/core')['usePointer'] 183 | const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] 184 | const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] 185 | const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] 186 | const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] 187 | const useRafFn: typeof import('@vueuse/core')['useRafFn'] 188 | const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] 189 | const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] 190 | const useRoute: typeof import('vue-router')['useRoute'] 191 | const useRouter: typeof import('vue-router')['useRouter'] 192 | const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea'] 193 | const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] 194 | const useScroll: typeof import('@vueuse/core')['useScroll'] 195 | const useScrollLock: typeof import('@vueuse/core')['useScrollLock'] 196 | const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage'] 197 | const useShare: typeof import('@vueuse/core')['useShare'] 198 | const useSlots: typeof import('vue')['useSlots'] 199 | const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] 200 | const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis'] 201 | const useStorage: typeof import('@vueuse/core')['useStorage'] 202 | const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync'] 203 | const useStyleTag: typeof import('@vueuse/core')['useStyleTag'] 204 | const useSwipe: typeof import('@vueuse/core')['useSwipe'] 205 | const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] 206 | const useTextSelection: typeof import('@vueuse/core')['useTextSelection'] 207 | const useThrottle: typeof import('@vueuse/core')['useThrottle'] 208 | const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] 209 | const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] 210 | const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] 211 | const useTimeout: typeof import('@vueuse/core')['useTimeout'] 212 | const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] 213 | const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll'] 214 | const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] 215 | const useTitle: typeof import('@vueuse/core')['useTitle'] 216 | const useToggle: typeof import('@vueuse/core')['useToggle'] 217 | const useTransition: typeof import('@vueuse/core')['useTransition'] 218 | const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] 219 | const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] 220 | const useVibrate: typeof import('@vueuse/core')['useVibrate'] 221 | const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] 222 | const useVModel: typeof import('@vueuse/core')['useVModel'] 223 | const useVModels: typeof import('@vueuse/core')['useVModels'] 224 | const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] 225 | const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] 226 | const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] 227 | const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] 228 | const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] 229 | const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] 230 | const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] 231 | const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] 232 | const watch: typeof import('vue')['watch'] 233 | const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] 234 | const watchDebounced: typeof import('@vueuse/core')['watchDebounced'] 235 | const watchEffect: typeof import('vue')['watchEffect'] 236 | const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable'] 237 | const watchOnce: typeof import('@vueuse/core')['watchOnce'] 238 | const watchPausable: typeof import('@vueuse/core')['watchPausable'] 239 | const watchThrottled: typeof import('@vueuse/core')['watchThrottled'] 240 | const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] 241 | const whenever: typeof import('@vueuse/core')['whenever'] 242 | } 243 | export {} 244 | -------------------------------------------------------------------------------- /docs/src/components.d.ts: -------------------------------------------------------------------------------- 1 | // generated by unplugin-vue-components 2 | // We suggest you to commit this file into source control 3 | // Read more: https://github.com/vuejs/vue-next/pull/3399 4 | import '@vue/runtime-core' 5 | 6 | declare module '@vue/runtime-core' { 7 | export interface GlobalComponents { 8 | Dropdown: typeof import('./components/Dropdown.vue')['default'] 9 | Footer: typeof import('./components/Footer.vue')['default'] 10 | GitBadge: typeof import('./components/GitBadge.vue')['default'] 11 | IconInfo: typeof import('./components/IconInfo.vue')['default'] 12 | LangSwitcher: typeof import('./components/LangSwitcher.vue')['default'] 13 | Message: typeof import('./components/Message.vue')['default'] 14 | Navbar: typeof import('./components/Navbar.vue')['default'] 15 | RandomIcon: typeof import('./components/RandomIcon.vue')['default'] 16 | RouterLink: typeof import('vue-router')['RouterLink'] 17 | RouterView: typeof import('vue-router')['RouterView'] 18 | Sidebar: typeof import('./components/Sidebar.vue')['default'] 19 | ToggleTheme: typeof import('./components/ToggleTheme.vue')['default'] 20 | ToolSidebar: typeof import('./components/ToolSidebar.vue')['default'] 21 | } 22 | } 23 | 24 | export {} 25 | -------------------------------------------------------------------------------- /docs/src/components/Dropdown.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 46 | 47 | 54 | -------------------------------------------------------------------------------- /docs/src/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 30 | -------------------------------------------------------------------------------- /docs/src/components/GitBadge.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 26 | -------------------------------------------------------------------------------- /docs/src/components/IconInfo.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 86 | 87 | 92 | -------------------------------------------------------------------------------- /docs/src/components/LangSwitcher.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 29 | -------------------------------------------------------------------------------- /docs/src/components/Message.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 59 | 60 | 70 | -------------------------------------------------------------------------------- /docs/src/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 54 | -------------------------------------------------------------------------------- /docs/src/components/RandomIcon.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 41 | -------------------------------------------------------------------------------- /docs/src/components/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 77 | 78 | 90 | -------------------------------------------------------------------------------- /docs/src/components/ToggleTheme.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 31 | -------------------------------------------------------------------------------- /docs/src/components/ToolSidebar.vue: -------------------------------------------------------------------------------- 1 | 121 | 122 | 179 | 180 | 196 | -------------------------------------------------------------------------------- /docs/src/composables/dark.ts: -------------------------------------------------------------------------------- 1 | // these APIs are auto-imported from @vueuse/core 2 | export const isDark = useDark(); 3 | export const toggleDark = useToggle(isDark); 4 | -------------------------------------------------------------------------------- /docs/src/composables/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./dark"; 2 | export * from "./locale"; 3 | -------------------------------------------------------------------------------- /docs/src/composables/locale.ts: -------------------------------------------------------------------------------- 1 | export const localePath = (path: string) => { 2 | const { locale } = useI18n(); 3 | const prefix = locale.value === "en" ? "" : `/${locale.value}`; 4 | return `${prefix}${path[0] === "/" ? "" : "/"}${path}`; 5 | }; 6 | 7 | export const switchLocalePath = (toLocale: string) => { 8 | const { locale } = useI18n(); 9 | const route = useRoute(); 10 | 11 | const basePath = 12 | locale.value === "en" 13 | ? route.path 14 | : route.path.replace(`/${locale.value}`, ""); 15 | 16 | const toPath = toLocale === "en" ? basePath : `/${toLocale}${basePath}`; 17 | return toPath; 18 | }; 19 | -------------------------------------------------------------------------------- /docs/src/i18n/index.ts: -------------------------------------------------------------------------------- 1 | const SUPPORT_LOCALES = { 2 | en: { 3 | name: "English", 4 | icon: "fi-square-gb" 5 | }, 6 | zh: { 7 | name: "简体中文", 8 | icon: "fi-square-cn" 9 | } 10 | }; 11 | 12 | export default SUPPORT_LOCALES; 13 | -------------------------------------------------------------------------------- /docs/src/i18n/translations/en.yml: -------------------------------------------------------------------------------- 1 | tagline: A Vue component for including inline SVG icons from different popular iconpacks easily. 2 | nav: 3 | icons: Icons 4 | docs: Docs 5 | language: Language 6 | github: 7 | repo: Repository 8 | changelog: Changelog 9 | toolbar: 10 | scale: Scale 11 | color: Color 12 | animation: Animation 13 | animSpeed: Animation Speed 14 | flip: Flip 15 | -------------------------------------------------------------------------------- /docs/src/i18n/translations/zh.yml: -------------------------------------------------------------------------------- 1 | tagline: 一个能让你在 Vue 中轻松从多个流行图标库中引入 SVG 图标的组件 2 | nav: 3 | icons: 图标 4 | docs: 文档 5 | language: 选择语言 6 | github: 7 | repo: 查看源码 8 | changelog: 更新日志 9 | toolbar: 10 | scale: 大小 11 | color: 颜色 12 | animation: 动画类型 13 | animSpeed: 动画速度 14 | flip: 翻转类型 15 | -------------------------------------------------------------------------------- /docs/src/icons.ts: -------------------------------------------------------------------------------- 1 | const icons = [ 2 | { 3 | id: "ai", 4 | name: "academicons" 5 | }, 6 | { 7 | id: "bi", 8 | name: "Bootstrap Icons" 9 | }, 10 | { 11 | id: "co", 12 | name: "CoreUI Icons", 13 | multiColor: true 14 | }, 15 | { 16 | id: "ci", 17 | name: "Crypto Icons", 18 | multiColor: true 19 | }, 20 | { 21 | id: "fa", 22 | name: "Font Awesome" 23 | }, 24 | { 25 | id: "fc", 26 | name: "Flat Color Icons", 27 | multiColor: true 28 | }, 29 | { 30 | id: "fi", 31 | name: "Flag Icon", 32 | multiColor: true 33 | }, 34 | { 35 | id: "gi", 36 | name: "gameicons" 37 | }, 38 | { 39 | id: "hi", 40 | name: "Heroicons" 41 | }, 42 | { 43 | id: "io", 44 | name: "Ionicons" 45 | }, 46 | { 47 | id: "la", 48 | name: "Line Awesome" 49 | }, 50 | { 51 | id: "md", 52 | name: "Material Design icons" 53 | }, 54 | { 55 | id: "oi", 56 | name: "Octicons" 57 | }, 58 | { 59 | id: "pi", 60 | name: "Pokemon Icons", 61 | multiColor: true, 62 | website: "https://theartificial.github.io/pokemon-icons/" 63 | }, 64 | { 65 | id: "pr", 66 | name: "PrimeIcons" 67 | }, 68 | { 69 | id: "px", 70 | name: "Pixelarticons" 71 | }, 72 | { 73 | id: "ri", 74 | name: "Remix Icon" 75 | }, 76 | { 77 | id: "si", 78 | name: "Simple Icons" 79 | }, 80 | { 81 | id: "vi", 82 | name: "VSCode Icons", 83 | multiColor: true 84 | }, 85 | { 86 | id: "wi", 87 | name: "Weather Icons" 88 | } 89 | ]; 90 | 91 | export default icons; 92 | -------------------------------------------------------------------------------- /docs/src/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /docs/src/layouts/docs.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 52 | -------------------------------------------------------------------------------- /docs/src/main.ts: -------------------------------------------------------------------------------- 1 | import { ViteSSG } from "vite-ssg"; 2 | import { setupLayouts } from "virtual:generated-layouts"; 3 | import App from "./App.vue"; 4 | import generatedRoutes from "~pages"; 5 | 6 | import "@unocss/reset/tailwind.css"; 7 | import "./styles/main.css"; 8 | import "uno.css"; 9 | 10 | import { OhVueIcon, addIcons } from "oh-vue-icons-npm"; 11 | import * as AllIcons from "oh-vue-icons-npm/icons"; 12 | 13 | addIcons(...Object.values({ ...AllIcons })); 14 | addIcons( 15 | { 16 | name: "baidu", 17 | width: 23.868, 18 | height: 26, 19 | d: "M3.613 13.701c2.827-.608 2.442-3.986 2.357-4.725-.138-1.139-1.477-3.128-3.296-2.971C.386 6.21.052 9.515.052 9.515c-.309 1.528.74 4.793 3.561 4.186zm3.002 5.875c-.083.238-.268.846-.107 1.375.315 1.187 1.346 1.24 1.346 1.24h1.48v-3.619H7.749c-.713.213-1.057.767-1.134 1.004zM8.86 8.035c1.562 0 2.823-1.797 2.823-4.019C11.683 1.796 10.421 0 8.86 0 7.301 0 6.036 1.796 6.036 4.016c0 2.222 1.265 4.019 2.824 4.019zm6.724.265c2.087.271 3.429-1.956 3.695-3.644.272-1.686-1.074-3.644-2.552-3.98-1.48-.339-3.329 2.032-3.497 3.578-.2 1.89.271 3.778 2.354 4.046zm5.114 9.923s-3.229-2.498-5.113-5.198c-2.555-3.981-6.185-2.361-7.399-.337-1.209 2.024-3.093 3.305-3.36 3.644-.271.334-3.9 2.293-3.095 5.871.806 3.576 3.635 3.508 3.635 3.508s2.085.205 4.504-.336c2.42-.537 4.503.134 4.503.134s5.652 1.893 7.199-1.751c1.545-3.645-.874-5.535-.874-5.535zm-9.671 5.423H7.352c-1.587-.316-2.219-1.4-2.299-1.584-.078-.188-.528-1.059-.29-2.539.686-2.219 2.642-2.379 2.642-2.379h1.956V14.74l1.666.025v8.881zm6.844-.025h-4.229c-1.639-.423-1.716-1.587-1.716-1.587v-4.677l1.716-.027v4.203c.104.447.661.529.661.529h1.742v-4.705h1.825v6.264zm5.986-12.486c0-.808-.671-3.239-3.159-3.239-2.492 0-2.825 2.295-2.825 3.917 0 1.548.131 3.71 3.227 3.641 3.096-.068 2.757-3.507 2.757-4.319z" 20 | }, 21 | { 22 | name: "webpack", 23 | width: 1200, 24 | height: 1200, 25 | paths: [ 26 | { 27 | fill: "#8ED6FB", 28 | d: "M1035.6 879.3l-418.1 236.5V931.6L878 788.3l157.6 91zm28.6-25.9V358.8l-153 88.3V765l153 88.4zm-901.5 25.9l418.1 236.5V931.6L320.3 788.3l-157.6 91zm-28.6-25.9V358.8l153 88.3V765l-153 88.4zM152 326.8L580.8 84.2v178.1L306.1 413.4l-2.1 1.2-152-87.8zm894.3 0L617.5 84.2v178.1l274.7 151.1 2.1 1.2 152-87.8z" 29 | }, 30 | { 31 | fill: "#1C78C0", 32 | d: "M580.8 889.7l-257-141.3v-280l257 148.4v272.9zm36.7 0l257-141.3v-280l-257 148.4v272.9zm-18.3-283.6zM341.2 436l258-141.9 258 141.9-258 149-258-149z" 33 | } 34 | ] 35 | }, 36 | { 37 | name: "vue", 38 | width: 256, 39 | height: 221, 40 | polygons: [ 41 | { 42 | fill: "#41B883", 43 | points: "0,0 128,220.8 256,0 204.8,0 128,132.48 50.56,0 0,0" 44 | }, 45 | { 46 | fill: "#35495E", 47 | points: "50.56,0 128,133.12 204.8,0 157.44,0 128,51.2 97.92,0 50.56,0" 48 | } 49 | ] 50 | }, 51 | { 52 | name: "html5-c", 53 | width: 512, 54 | height: 512, 55 | raw: '' 56 | }, 57 | { 58 | name: "oh-vue-icons", 59 | width: 32, 60 | height: 32, 61 | raw: `` 62 | } 63 | ); 64 | 65 | const routes = setupLayouts(generatedRoutes); 66 | 67 | // https://github.com/antfu/vite-ssg 68 | export const createApp = ViteSSG( 69 | App, 70 | { routes, base: import.meta.env.BASE_URL }, 71 | (ctx) => { 72 | // install all modules under `modules/` 73 | Object.values(import.meta.globEager("./modules/*.ts")).forEach((i) => 74 | i.install?.(ctx) 75 | ); 76 | ctx.app.component("VIcon", OhVueIcon); 77 | } 78 | ); 79 | -------------------------------------------------------------------------------- /docs/src/modules/README.md: -------------------------------------------------------------------------------- 1 | ## Modules 2 | 3 | A custom user module system. Place a `.ts` file with the following template, it will be installed automatically. 4 | 5 | ```ts 6 | import { type UserModule } from '~/types' 7 | 8 | export const install: UserModule = ({ app, router, isClient }) => { 9 | // do something 10 | } 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/src/modules/i18n.ts: -------------------------------------------------------------------------------- 1 | import { createI18n } from "vue-i18n"; 2 | import type { UserModule } from "~/types"; 3 | 4 | // Import i18n resources 5 | // https://vitejs.dev/guide/features.html#glob-import 6 | // 7 | // Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite 8 | const messages = Object.fromEntries( 9 | Object.entries(import.meta.globEager("../i18n/translations/*.y(a)?ml")).map( 10 | ([key, value]) => [ 11 | key 12 | .split("/") 13 | .at(-1) 14 | ?.replace(/\.ya?ml$/, ""), 15 | value.default 16 | ] 17 | ) 18 | ); 19 | 20 | export const install: UserModule = ({ app }) => { 21 | const i18n = createI18n({ 22 | legacy: false, 23 | locale: "en", 24 | messages 25 | }); 26 | 27 | app.use(i18n); 28 | }; 29 | -------------------------------------------------------------------------------- /docs/src/modules/nprogress.ts: -------------------------------------------------------------------------------- 1 | import NProgress from "nprogress"; 2 | import { type UserModule } from "~/types"; 3 | 4 | export const install: UserModule = ({ isClient, router }) => { 5 | if (isClient) { 6 | router.beforeEach((to, from) => { 7 | if (to.path !== from.path) NProgress.start(); 8 | }); 9 | router.afterEach(() => { 10 | NProgress.done(); 11 | }); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /docs/src/modules/pinia.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from "pinia"; 2 | import { type UserModule } from "~/types"; 3 | 4 | // Setup Pinia 5 | // https://pinia.esm.dev/ 6 | export const install: UserModule = ({ isClient, initialState, app }) => { 7 | const pinia = createPinia(); 8 | app.use(pinia); 9 | // Refer to 10 | // https://github.com/antfu/vite-ssg/blob/main/README.md#state-serialization 11 | // for other serialization strategies. 12 | if (isClient) pinia.state.value = initialState.pinia || {}; 13 | else initialState.pinia = pinia.state.value; 14 | }; 15 | -------------------------------------------------------------------------------- /docs/src/modules/pwa.ts: -------------------------------------------------------------------------------- 1 | import { type UserModule } from "~/types"; 2 | 3 | // https://github.com/antfu/vite-plugin-pwa#automatic-reload-when-new-content-available 4 | export const install: UserModule = ({ isClient, router }) => { 5 | if (!isClient) return; 6 | 7 | router.isReady().then(async () => { 8 | const { registerSW } = await import("virtual:pwa-register"); 9 | registerSW({ immediate: true }); 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /docs/src/pages/[...locale].vue: -------------------------------------------------------------------------------- 1 | 101 | 102 | 184 | -------------------------------------------------------------------------------- /docs/src/pages/docs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Docs - Oh, Vue Icons! 3 | --- 4 | 5 | ## Features 6 | 7 | - Works for both Vue 2 & 3 8 | - Supports tree-shaking: only import the icons you want 9 | - 30000+ icons from 20 popular icon packs, see [here](#supported-icon-packs) 10 | 11 | 12 | ## Supported Icon Packs 13 | 14 | Now the following 20 icon packs are supported: 15 | 16 | | Icon Pack | Prefix | License | Counts | 17 | | ------------------------------------------------------------- | ------ | ------------------------------------------------------------- | ---------- | 18 | | [academicons](https://github.com/jpswalsh/academicons) | `ai` | [SIL OFL 1.1](http://scripts.sil.org/OFL) | 149 | 19 | | [Bootstrap Icons](https://github.com/twbs/icons) | `bi` | [MIT](https://github.com/twbs/icons/blob/main/LICENSE.md) | 1668 | 20 | | [CoreUI Icons Free](https://github.com/coreui/coreui-icons) (Colorful) | `co` | [CC BY 4.0 License](https://github.com/coreui/coreui-icons/blob/master/LICENSE) | 1575 | 21 | | [Cryptocurrency Icons](https://github.com/spothq/cryptocurrency-icons) (Colorful) | `ci` | [CC0 1.0 Universal](https://github.com/spothq/cryptocurrency-icons/blob/master/LICENSE.md) | 942 | 22 | | [Font Awesome 5 Free](https://github.com/FortAwesome/Font-Awesome) | `fa` | [CC BY 4.0](https://github.com/FortAwesome/Font-Awesome/blob/master/LICENSE.txt) | 1610 | 23 | | [Flat Color Icons](https://github.com/icons8/flat-color-icons) (Colorful) | `fc` | [MIT / Good Boy](https://github.com/icons8/flat-color-icons/blob/master/LICENSE.md) | 329 | 24 | | [Flag Icon](https://github.com/lipis/flag-icon-css) (Colorful)| `fi` | [MIT](https://github.com/lipis/flag-icon-css/blob/master/LICENSE) | 530 | 25 | | [gameicons](https://github.com/game-icons/icons) | `gi` | [CC BY 3.0](https://github.com/game-icons/icons/blob/master/license.txt) | 4052 | 26 | | [Heroicons](https://github.com/tailwindlabs/heroicons) | `hi` | [MIT](https://github.com/tailwindlabs/heroicons/blob/master/LICENSE) | 460 | 27 | | [Ionicons](https://github.com/ionic-team/ionicons) | `io` | [MIT](https://github.com/ionic-team/ionicons/blob/master/LICENSE) | 1332 | 28 | | [Line Awesome](https://github.com/icons8/line-awesome) | `la` | [MIT / Good Boy](https://github.com/icons8/line-awesome/blob/master/LICENSE.md) | 1544 | 29 | | [Material Design icons](https://github.com/google/material-design-icons) | `md` | [Apache 2.0](https://github.com/google/material-design-icons/blob/master/LICENSE) | 10537 | 30 | | [Octicons](https://github.com/primer/octicons) | `oi` | [MIT](https://github.com/primer/octicons/blob/main/LICENSE) | 259 | 31 | | [Pokemon Icons](https://github.com/TheArtificial/pokemon-icons) (Colorful)| `pi` | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | 1453 | 32 | | [PrimeIcons](https://github.com/primefaces/primeicons) | `pr` | [MIT](https://github.com/primefaces/primeicons/blob/master/LICENSE) | 238 | 33 | | [Pixelarticons](https://github.com/halfmage/pixelarticons) | `px` | [MIT](https://github.com/halfmage/pixelarticons/blob/master/LICENSE) | 460 | 34 | | [Remix Icon](https://github.com/Remix-Design/RemixIcon) | `ri` | [Apache 2.0](https://github.com/Remix-Design/RemixIcon/blob/master/License) | 2271 | 35 | | [Simple Icons](https://github.com/simple-icons/simple-icons) | `si` | [CC0 1.0 Universal](https://github.com/simple-icons/simple-icons/blob/develop/LICENSE.md) | 2233 | 36 | | [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (Colorful) | `vi` | [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) | 1125 | 37 | | [Weather Icons](https://github.com/erikflowers/weather-icons) | `wi` | [SIL OFL 1.1](http://scripts.sil.org/OFL) | 219 | 38 | 39 | 40 | ## Installation 41 | 42 | ```bash 43 | yarn add oh-vue-icons 44 | # or 45 | npm install oh-vue-icons 46 | ``` 47 | 48 | For Vue 2, you'll also need `@vue/composition-api`: 49 | 50 | ```bash 51 | yarn add @vue/composition-api -D 52 | ``` 53 | 54 | Or if you are using [Nuxt 2](https://nuxtjs.org/), you'll need `@nuxtjs/composition-api` instead: 55 | 56 | ```bash 57 | yarn add @nuxtjs/composition-api -D 58 | ``` 59 | 60 | then add `@nuxtjs/composition-api/module` to the `buildModules` option in your `nuxt.config.js`, see [here](https://composition-api.nuxtjs.org/getting-started/setup) for details. 61 | 62 | 63 | ## Import 64 | 65 | ### Global Import 66 | 67 | Import `oh-vue-icons` and install it into Vue in `main.js`. You can choose to only import the icons you use to reduce bundle size. 68 | 69 | 70 | #### Vue 3 71 | 72 | ```js 73 | // main.js 74 | import { createApp } from "vue"; 75 | import App from "./App.vue"; 76 | 77 | import { OhVueIcon, addIcons } from "oh-vue-icons"; 78 | import { FaFlag, RiZhihuFill } from "oh-vue-icons/icons"; 79 | 80 | addIcons(FaFlag, RiZhihuFill); 81 | 82 | const app = createApp(App); 83 | app.component("v-icon", OhVueIcon); 84 | app.mount("#app"); 85 | ``` 86 | 87 | If you don't care about the bundle size and want to import a whole icon pack, you may should: 88 | 89 | ```js 90 | // main.js 91 | // import Font Awesome 92 | import * as FaIcons from "oh-vue-icons/icons/fa"; 93 | 94 | const Fa = Object.values({ ...FaIcons }); 95 | addIcons(...Fa); 96 | ``` 97 | 98 | 99 | #### Vue 2 100 | 101 | ```js 102 | // main.js 103 | import Vue from "vue"; 104 | import App from "./App.vue"; 105 | 106 | import { OhVueIcon, addIcons } from "oh-vue-icons"; 107 | import { FaFlag, RiZhihuFill } from "oh-vue-icons/icons"; 108 | 109 | addIcons(FaFlag, RiZhihuFill); 110 | 111 | Vue.component("v-icon", OhVueIcon); 112 | 113 | new Vue({ 114 | render: h => h(App) 115 | }).$mount("#app"); 116 | ``` 117 | 118 | 119 | ### Local Import 120 | 121 | ```js 122 | import OhVueIcon from "oh-vue-icons"; 123 | 124 | export default { 125 | components: { 126 | "v-icon": OhVueIcon 127 | } 128 | }; 129 | ``` 130 | 131 | 132 | ## Basic Usage 133 | 134 | The icon names should be passed using **kebab-case**. 135 | 136 |

137 | 138 | 139 | 140 | 141 |

142 | 143 | ```html 144 | 152 | ``` 153 | 154 | 155 | ## Props 156 | 157 | | Name | Description | Type | Accepted Values | Default value | 158 | | ----------- | ---------------------------------------- | --------- | ------------------------------------------------------------- | -------------- | 159 | | `scale` | Icon size | `number` | / | `1` | 160 | | `animation` | Type of animation | `string` | `wrench` / `ring` / `pulse` / `spin` / `spin-pulse` / `flash` / `float` | / | 161 | | `speed` | Animation speed | `string` | `slow` / `fast` | / | 162 | | `hover` | Enable animation only when being hovered | `boolean` | `true` / `false` | `false` | 163 | | `flip` | Used to flip icon | `string` | `vertical` / `horizontal` / `both` | / | 164 | | `fill` | Fill color of icon | `string` | HEX color code or color name | `currentColor` | 165 | | `label` | Icon lable | `string` | / | / | 166 | | `title` | Icon title | `string` | / | / | 167 | | `inverse` | Make icon color white? | `boolean` | `true` / `false` | `false` | 168 | 169 | 170 | ## Examples 171 | 172 | ### Scale 173 | 174 | Use prop `scale: number | string` to specify the icon size: 175 | 176 |

177 | 178 | 179 | 180 | 181 | 182 | 183 |

184 | 185 | ```html 186 | 187 | 188 | 189 | 190 | 191 | 192 | ``` 193 | 194 | ### Animations 195 | 196 | Use `animation: string` to enablle animations: 197 | 198 |

199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 |

207 | 208 | ```html 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | ``` 217 | 218 | Use `hover: boolean` to enable the animation only when the icon is hoverd: 219 | 220 |

221 | 222 | ```html 223 | 224 | ``` 225 | 226 | Use `speed: string` to control the animation speed: 227 | 228 |

229 | Slow: , 230 | Normal: , 231 | Fast: 232 |

233 | 234 | ```html 235 | 236 | 237 | 238 | ``` 239 | 240 | ### Flip 241 | 242 | Use `flip: string` to mirror an icon: 243 | 244 | - `vertical`: mirrors an icon vertically 245 | - `horizontal`: mirrors icon horizontally 246 | - `both`: mirrors icon vertically and horizontally 247 | 248 |

249 | 250 | 251 | 252 |

253 | 254 | ```html 255 | 256 | 257 | 258 | ``` 259 | 260 | ### Fill 261 | 262 | Set fill color for icons via prop `fill: string`: 263 | 264 |

265 | 266 | 267 | 268 |

269 | 270 | ```html 271 | 272 | 273 | 274 | ``` 275 | 276 | 277 | ### Stacked Icons 278 | 279 | Stack your icons easily jusy like in Font Awesome, even more powerful. 280 | 281 |

282 | 283 | 284 | 285 | 286 |

287 | 288 | ```html 289 | 290 | 291 | 292 | 293 | ``` 294 | 295 | You can also make it animated: 296 | 297 |

298 | 299 | 300 | 301 | 302 |

303 | 304 | ```html 305 | 306 | 307 | 308 | 309 | ``` 310 | 311 | 312 | ### Inverse 313 | 314 | Use `inverse: boolean` to make the color of icon white (`#fff`), which is **invalid on multi-color icons**: 315 | 316 |

317 | 318 | 319 | 320 | 321 |

322 | 323 | ```html 324 | 325 | 326 | 327 | 328 | ``` 329 | 330 | 331 | ### Label 332 | 333 | Specify prop `label: string` to set the `aria-label` for the icon if provided. 334 | 335 |

336 | 337 | ```html 338 | 339 | ``` 340 | 341 | ### Title 342 | 343 | Specify prop `title: string` to add a `` tag for the icon. 344 | 345 | <p><v-icon name="fa-vuejs" title="Vue.js"></v-icon></p> 346 | 347 | ```html 348 | <v-icon name="fa-vuejs" title="Vue.js" /> 349 | ``` 350 | 351 | ## Advanced Usage 352 | 353 | ### Custom icons 354 | 355 | You can register your own icons: 356 | 357 | ```js 358 | OhVueIcon.add({ 359 | name: 'baidu', 360 | width: 23.868, 361 | height: 26, 362 | d: 'M3.613 13.701c2.827-.608 2.442-3.986 2.357-4.725-.138-1.139-1.477-3.128-3.296-2.971C.386 6.21.052 9.515.052 9.515c-.309 1.528.74 4.793 3.561 4.186zm3.002 5.875c-.083.238-.268.846-.107 1.375.315 1.187 1.346 1.24 1.346 1.24h1.48v-3.619H7.749c-.713.213-1.057.767-1.134 1.004zM8.86 8.035c1.562 0 2.823-1.797 2.823-4.019C11.683 1.796 10.421 0 8.86 0 7.301 0 6.036 1.796 6.036 4.016c0 2.222 1.265 4.019 2.824 4.019zm6.724.265c2.087.271 3.429-1.956 3.695-3.644.272-1.686-1.074-3.644-2.552-3.98-1.48-.339-3.329 2.032-3.497 3.578-.2 1.89.271 3.778 2.354 4.046zm5.114 9.923s-3.229-2.498-5.113-5.198c-2.555-3.981-6.185-2.361-7.399-.337-1.209 2.024-3.093 3.305-3.36 3.644-.271.334-3.9 2.293-3.095 5.871.806 3.576 3.635 3.508 3.635 3.508s2.085.205 4.504-.336c2.42-.537 4.503.134 4.503.134s5.652 1.893 7.199-1.751c1.545-3.645-.874-5.535-.874-5.535zm-9.671 5.423H7.352c-1.587-.316-2.219-1.4-2.299-1.584-.078-.188-.528-1.059-.29-2.539.686-2.219 2.642-2.379 2.642-2.379h1.956V14.74l1.666.025v8.881zm6.844-.025h-4.229c-1.639-.423-1.716-1.587-1.716-1.587v-4.677l1.716-.027v4.203c.104.447.661.529.661.529h1.742v-4.705h1.825v6.264zm5.986-12.486c0-.808-.671-3.239-3.159-3.239-2.492 0-2.825 2.295-2.825 3.917 0 1.548.131 3.71 3.227 3.641 3.096-.068 2.757-3.507 2.757-4.319z' 363 | }) 364 | ``` 365 | 366 | <p><v-icon name="baidu"></v-icon></p> 367 | 368 | ```html 369 | <v-icon name="baidu" /> 370 | ``` 371 | 372 | ### Multi-color icons 373 | 374 | Register icons in more advanced ways to unleash the full power of SVG: 375 | 376 | ```js 377 | OhVueIcon.add( 378 | { 379 | name: 'webpack', 380 | width: 1200, 381 | height: 1200, 382 | paths: [ 383 | { 384 | fill: '#8ED6FB', 385 | d: 'M1035.6 879.3l-418.1 236.5V931.6L878 788.3l157.6 91zm28.6-25.9V358.8l-153 88.3V765l153 88.4zm-901.5 25.9l418.1 236.5V931.6L320.3 788.3l-157.6 91zm-28.6-25.9V358.8l153 88.3V765l-153 88.4zM152 326.8L580.8 84.2v178.1L306.1 413.4l-2.1 1.2-152-87.8zm894.3 0L617.5 84.2v178.1l274.7 151.1 2.1 1.2 152-87.8z' 386 | }, 387 | { 388 | fill: '#1C78C0', 389 | d: 'M580.8 889.7l-257-141.3v-280l257 148.4v272.9zm36.7 0l257-141.3v-280l-257 148.4v272.9zm-18.3-283.6zM341.2 436l258-141.9 258 141.9-258 149-258-149z' 390 | } 391 | ] 392 | }, 393 | { 394 | name: 'vue', 395 | width: 256, 396 | height: 221, 397 | polygons: [ 398 | { 399 | fill: '#41B883', 400 | points: '0,0 128,220.8 256,0 204.8,0 128,132.48 50.56,0 0,0' 401 | }, 402 | { 403 | fill: '#35495E', 404 | points: '50.56,0 128,133.12 204.8,0 157.44,0 128,51.2 97.92,0 50.56,0' 405 | } 406 | ] 407 | }, 408 | { 409 | name: 'html5-c', 410 | width: 512, 411 | height: 512, 412 | raw: '<path fill="#E34F26" d="M71,460 L30,0 481,0 440,460 255,512"/><path fill="#EF652A" d="M256,472 L405,431 440,37 256,37"/><path fill="#EBEBEB" d="M256,208 L181,208 176,150 256,150 256,94 255,94 114,94 115,109 129,265 256,265zM256,355 L255,355 192,338 188,293 158,293 132,293 139,382 255,414 256,414z"/><path fill="#FFF" d="M255,208 L255,265 325,265 318,338 255,355 255,414 371,382 372,372 385,223 387,208 371,208zM255,94 L255,129 255,150 255,150 392,150 392,150 392,150 393,138 396,109 397,94z"/>' 413 | } 414 | ) 415 | ``` 416 | 417 | <p> 418 | <v-icon name="webpack"></v-icon> 419 | <v-icon name="vue"></v-icon> 420 | <v-icon name="html5-c"></v-icon> 421 | </p> 422 | 423 | ```html 424 | <v-icon name="webpack" /> <v-icon name="vue" /> <v-icon name="html5-c" /> 425 | ``` 426 | 427 | 428 | ## Nuxt 429 | 430 | When using Nuxt, you need to register `oh-vue-icons` as a plugin following [Nuxt's documentation](https://nuxtjs.org/docs/directory-structure/plugins#vue-plugins). 431 | 432 | It should be noted that, `oh-vue-icons` should be added to the `build.transpile` option in your `nuxt.config.js` (see [here](https://nuxtjs.org/docs/directory-structure/plugins/#es6-plugins) for details): 433 | 434 | ```js 435 | // nuxt.config.js 436 | 437 | export default { 438 | // ... 439 | build: { 440 | transpile: ["oh-vue-icons"] 441 | } 442 | } 443 | ``` 444 | 445 | To render the icon component only on client-side, you may need to wrap it in a `<client-only>` tag: 446 | 447 | ```html 448 | <template> 449 | <div> 450 | <client-only> 451 | <v-icon name="fa-flag" /> 452 | <v-icon name="ri-zhihu-fill" /> 453 | </client-only> 454 | </div> 455 | </template> 456 | ``` 457 | 458 | 459 | ## Vite 460 | 461 | When using [Vite](https://vitejs.dev/), it is suggested to exclude `oh-vue-icons` from pre-bundling (see [#20](https://github.com/Renovamen/oh-vue-icons/issues/20) for details): 462 | 463 | ```js 464 | // vite.config.js 465 | 466 | export default { 467 | // ... 468 | optimizeDeps: { 469 | exclude: ["oh-vue-icons/icons"] 470 | } 471 | } 472 | ``` 473 | 474 | When using Vite's [Server-Side Rendering (SSR)](https://vitejs.dev/guide/ssr.html) support ([VuePress](https://v2.vuepress.vuejs.org/), [Vite SSG](https://github.com/antfu/vite-ssg), etc.), `oh-vue-icons` should be added to the `ssr.noExternal` option (see [here](https://vitejs.dev/guide/ssr.html#ssr-externals) for details): 475 | 476 | ```js 477 | // vite.config.js 478 | 479 | export default { 480 | // ... 481 | ssr: { 482 | noExternal: ["oh-vue-icons"] 483 | } 484 | } 485 | ``` 486 | 487 | 488 | ## Migrate from v0.x to v1.x 489 | 490 | From `v1.x`, this library works for both Vue 2 & 3 within a single package. 491 | 492 | 493 | ### Vue 3 494 | 495 | ```diff 496 | - import OhVueIcon from "oh-vue-icons/dist/v3/icon.es"; 497 | + import { OhVueIcon, addIcons } from "oh-vue-icons"; 498 | 499 | - OhVueIcon.add(FaFlag) 500 | + addIcons(FaFlag) 501 | ``` 502 | 503 | 504 | ### Vue 2 505 | 506 | ```diff 507 | - import OhVueIcon from "oh-vue-icons"; 508 | + import { OhVueIcon, addIcons } from "oh-vue-icons"; 509 | 510 | - OhVueIcon.add(FaFlag) 511 | + addIcons(FaFlag) 512 | ``` 513 | 514 | And you need to have `@vue/composition-api` installed, see [here](#installation). 515 | 516 | 517 | ### Nuxt 2 518 | 519 | You need to install and enable `@nuxtjs/composition-api`, see [here](#installation). 520 | 521 | 522 | 523 | ## Acknowledgements 524 | 525 | - This project is inspired by and based on [vue-awesome](https://github.com/Justineo/vue-awesome) and [react-icons](https://github.com/react-icons/react-icons) 526 | 527 | - This website is built with [Vitesse](https://github.com/antfu/vitesse) and hosted on [Netlify](https://www.netlify.com/) 528 | 529 | 530 | ## License 531 | 532 | This project is [MIT](https://github.com/Renovamen/oh-vue-icons/blob/master/LICENSE) licensed. Icons are taken from [other projects](#supported-icon-packs), so check the license of each accordingly. 533 | -------------------------------------------------------------------------------- /docs/src/pages/zh/docs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 文档 - Oh, Vue Icons! 3 | --- 4 | 5 | ## 特性 6 | 7 | - 支持 Vue 2 和 3 8 | - 支持 tree-shaking,因此你能够仅引入你需要的图标从而减小打包体积 9 | - 支持来自 [20 个流行的图标库](#支持的图标库)的 30000+ 个图标 10 | 11 | 12 | ## 支持的图标库 13 | 14 | 目前支持以下 20 个图标库: 15 | 16 | | 图标库 | 前缀 | 协议 | 图标数量 | 17 | | ------------------------------------------------------------- | ------ | ------------------------------------------------------------- | ---------- | 18 | | [academicons](https://github.com/jpswalsh/academicons) | `ai` | [SIL OFL 1.1](http://scripts.sil.org/OFL) | 149 | 19 | | [Bootstrap Icons](https://github.com/twbs/icons) | `bi` | [MIT](https://github.com/twbs/icons/blob/main/LICENSE.md) | 1668 | 20 | | [CoreUI Icons Free](https://github.com/coreui/coreui-icons) (Colorful) | `co` | [CC BY 4.0 License](https://github.com/coreui/coreui-icons/blob/master/LICENSE) | 1575 | 21 | | [Cryptocurrency Icons](https://github.com/spothq/cryptocurrency-icons) (Colorful) | `ci` | [CC0 1.0 Universal](https://github.com/spothq/cryptocurrency-icons/blob/master/LICENSE.md) | 942 | 22 | | [Font Awesome 5 Free](https://github.com/FortAwesome/Font-Awesome) | `fa` | [CC BY 4.0](https://github.com/FortAwesome/Font-Awesome/blob/master/LICENSE.txt) | 1610 | 23 | | [Flat Color Icons](https://github.com/icons8/flat-color-icons) (Colorful) | `fc` | [MIT / Good Boy](https://github.com/icons8/flat-color-icons/blob/master/LICENSE.md) | 329 | 24 | | [Flag Icon](https://github.com/lipis/flag-icon-css) (Colorful)| `fi` | [MIT](https://github.com/lipis/flag-icon-css/blob/master/LICENSE) | 530 | 25 | | [gameicons](https://github.com/game-icons/icons) | `gi` | [CC BY 3.0](https://github.com/game-icons/icons/blob/master/license.txt) | 4052 | 26 | | [Heroicons](https://github.com/tailwindlabs/heroicons) | `hi` | [MIT](https://github.com/tailwindlabs/heroicons/blob/master/LICENSE) | 460 | 27 | | [Ionicons](https://github.com/ionic-team/ionicons) | `io` | [MIT](https://github.com/ionic-team/ionicons/blob/master/LICENSE) | 1332 | 28 | | [Line Awesome](https://github.com/icons8/line-awesome) | `la` | [MIT / Good Boy](https://github.com/icons8/line-awesome/blob/master/LICENSE.md) | 1544 | 29 | | [Material Design icons](https://github.com/google/material-design-icons) | `md` | [Apache 2.0](https://github.com/google/material-design-icons/blob/master/LICENSE) | 10537 | 30 | | [Octicons](https://github.com/primer/octicons) | `oi` | [MIT](https://github.com/primer/octicons/blob/main/LICENSE) | 259 | 31 | | [Pokemon Icons](https://github.com/TheArtificial/pokemon-icons) (Colorful)| `pi` | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | 1453 | 32 | | [PrimeIcons](https://github.com/primefaces/primeicons) | `pr` | [MIT](https://github.com/primefaces/primeicons/blob/master/LICENSE) | 238 | 33 | | [Pixelarticons](https://github.com/halfmage/pixelarticons) | `px` | [MIT](https://github.com/halfmage/pixelarticons/blob/master/LICENSE) | 460 | 34 | | [Remix Icon](https://github.com/Remix-Design/RemixIcon) | `ri` | [Apache 2.0](https://github.com/Remix-Design/RemixIcon/blob/master/License) | 2271 | 35 | | [Simple Icons](https://github.com/simple-icons/simple-icons) | `si` | [CC0 1.0 Universal](https://github.com/simple-icons/simple-icons/blob/develop/LICENSE.md) | 2233 | 36 | | [VSCode Icons](https://github.com/vscode-icons/vscode-icons) (Colorful) | `vi` | [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) | 1125 | 37 | | [Weather Icons](https://github.com/erikflowers/weather-icons) | `wi` | [SIL OFL 1.1](http://scripts.sil.org/OFL) | 219 | 38 | 39 | 40 | ## 安装 41 | 42 | ```bash 43 | yarn add oh-vue-icons 44 | # 或 45 | npm install oh-vue-icons 46 | ``` 47 | 48 | 使用 Vue 2 时,还需要安装 `@vue/composition-api`: 49 | 50 | ```bash 51 | yarn add @vue/composition-api -D 52 | ``` 53 | 54 | 如果用的是 [Nuxt 2](https://nuxtjs.org/),则需要安装的是 `@nuxtjs/composition-api`: 55 | 56 | ```bash 57 | yarn add @nuxtjs/composition-api -D 58 | ``` 59 | 60 | 然后把 `@nuxtjs/composition-api/module` 加到你的 `nuxt.config.js` 文件的 `buildModules` 项中,更多细节见[这里](https://composition-api.nuxtjs.org/getting-started/setup)。 61 | 62 | 63 | ## 引入 64 | 65 | ### 全局引入 66 | 67 | 首先需要在 `main.js` 中引入 `oh-vue-icons`。你可以只引入你需要的图标从而减小打包体积。 68 | 69 | 70 | #### Vue 3 71 | 72 | ```js 73 | // main.js 74 | import { createApp } from "vue"; 75 | import App from "./App.vue"; 76 | 77 | import { OhVueIcon, addIcons } from "oh-vue-icons"; 78 | import { FaFlag, RiZhihuFill } from "oh-vue-icons/icons"; 79 | 80 | addIcons(FaFlag, RiZhihuFill); 81 | 82 | const app = createApp(App); 83 | app.component("v-icon", OhVueIcon); 84 | app.mount("#app"); 85 | ``` 86 | 87 | 如果你并不在意打包体积,并希望引入某个图标库的所有图标,你可以: 88 | 89 | ```js 90 | // main.js 91 | // 引入 Font Awesome 92 | import * as FaIcons from 'oh-vue-icons/icons/fa' 93 | 94 | const Fa = Object.values({ ...FaIcons }) 95 | OhVueIcon.add(...Fa); 96 | ``` 97 | 98 | 99 | #### Vue 2 100 | 101 | ```js 102 | // main.js 103 | import Vue from "vue"; 104 | import App from "./App.vue"; 105 | 106 | import { OhVueIcon, addIcons } from "oh-vue-icons"; 107 | import { FaFlag, RiZhihuFill } from "oh-vue-icons/icons"; 108 | 109 | addIcons(FaFlag, RiZhihuFill); 110 | 111 | Vue.component("v-icon", OhVueIcon); 112 | 113 | new Vue({ 114 | render: h => h(App) 115 | }).$mount("#app"); 116 | ``` 117 | 118 | 119 | ### 局部引入 120 | 121 | ```js 122 | import OhVueIcon from "oh-vue-icons"; 123 | 124 | export default { 125 | components: { 126 | "v-icon": OhVueIcon 127 | } 128 | }; 129 | ``` 130 | 131 | 132 | ## 基本用法 133 | 134 | 通过 `name` prop 来指定图标名,`name` prop 值需要使用**短横线隔开式**命名: 135 | 136 | <p> 137 | <v-icon name="bi-music-player"></v-icon> 138 | <v-icon name="fc-globe"></v-icon> 139 | <v-icon name="oi-repo-pull"></v-icon> 140 | <v-icon name="vi-file-type-gridsome"></v-icon> 141 | </p> 142 | 143 | ```html 144 | <template> 145 | <div> 146 | <v-icon name="bi-music-player" /> 147 | <v-icon name="fc-globe" /> 148 | <v-icon name="oi-repo-pull" /> 149 | <v-icon name="vi-file-type-gridsome" /> 150 | </div> 151 | </template> 152 | ``` 153 | 154 | 155 | ## Props 156 | 157 | | 名称 | 描述 | 类型 | 接受值 | 默认值 | 158 | | ----------- | ---------------------| --------- | ------------------------------------------------------------- | -------------- | 159 | | `scale` | 图标大小 | `number` | / | `1` | 160 | | `animation` | 动画类型 | `string` | `wrench` / `ring` / `pulse` / `spin` / `spin-pulse` / `flash` / `float` | / | 161 | | `speed` | 动画速度 | `string` | `slow` / `fast` | / | 162 | | `hover` | 仅在被 hover 时启用动画 | `boolean` | `true` / `false` | `false` | 163 | | `flip` | 翻转类型 | `string` | `vertical` / `horizontal` / `both` | / | 164 | | `fill` | 图标的填充颜色 | `string` | 颜色名称或十六进制颜色代码 | `currentColor` | 165 | | `label` | 图标的 lable | `string` | / | / | 166 | | `title` | 图标的 title | `string` | / | / | 167 | | `inverse` | 把图标变成白色 | `boolean` | `true` / `false` | `false` | 168 | 169 | 170 | ## 示例 171 | 172 | ### 图标大小 173 | 174 | 使用 `scale: number | string` prop 来调整图标大小: 175 | 176 | <p> 177 | <v-icon name="fa-gamepad" scale="1.5"></v-icon> 178 | <v-icon name="ri-folder-music-fill" scale="2"></v-icon> 179 | <v-icon name="ai-overleaf" scale="2.5"></v-icon> 180 | <v-icon name="si-gatsby" scale="3"></v-icon> 181 | <v-icon name="wi-day-sunny-overcast" scale="3.5"></v-icon> 182 | <v-icon name="gi-ancient-sword" scale="4"></v-icon> 183 | </p> 184 | 185 | ```html 186 | <v-icon name="fa-gamepad" scale="1.5"/> 187 | <v-icon name="ri-folder-music-fill" scale="2"/> 188 | <v-icon name="ai-overleaf" scale="2.5"/> 189 | <v-icon name="si-gatsby" scale="3"/> 190 | <v-icon name="wi-day-sunny-overcast" scale="3.5"/> 191 | <v-icon name="gi-ancient-sword" scale="4"/> 192 | ``` 193 | 194 | ### 图标动画 195 | 196 | 使用 `animation: string` 来指定动画类型: 197 | 198 | <p> 199 | <v-icon name="ri-refresh-line" animation="spin"></v-icon> 200 | <v-icon name="fa-spinner" animation="spin-pulse"></v-icon> 201 | <v-icon name="la-tools-solid" animation="wrench"></v-icon> 202 | <v-icon name="fa-regular-bell" animation="ring"></v-icon> 203 | <v-icon name="ri-heart-pulse-line" animation="pulse"></v-icon> 204 | <v-icon name="bi-lightning" animation="flash"></v-icon> 205 | <v-icon name="ri-sailboat-line" animation="float"></v-icon> 206 | </p> 207 | 208 | ```html 209 | <v-icon name="ri-refresh-line" animation="spin" /> 210 | <v-icon name="fa-spinner" animation="spin-pulse" /> 211 | <v-icon name="la-tools-solid" animation="wrench" /> 212 | <v-icon name="fa-regular-bell" animation="ring" /> 213 | <v-icon name="ri-heart-pulse-line" animation="pulse" /> 214 | <v-icon name="bi-lightning" animation="flash" /> 215 | <v-icon name="ri-sailboat-line" animation="float" /> 216 | ``` 217 | 218 | 使用 `hover: boolean` 来仅在图标被 hover 时启用动画: 219 | 220 | <p><v-icon name="ri-refresh-line" animation="spin" hover></v-icon></p> 221 | 222 | ```html 223 | <v-icon name="ri-refresh-line" animation="spin" hover /> 224 | ``` 225 | 226 | 使用 `speed: string` 来控制动画的速度: 227 | 228 | <p> 229 | 慢:<v-icon name="ri-refresh-line" animation="spin" speed="slow"></v-icon>, 230 | 正常:<v-icon name="ri-refresh-line" animation="spin"></v-icon>, 231 | 快:<v-icon name="ri-refresh-line" animation="spin" speed="fast"></v-icon> 232 | </p> 233 | 234 | ```html 235 | <v-icon name="ri-refresh-line" animation="spin" speed="slow" /> 236 | <v-icon name="ri-refresh-line" animation="spin" /> 237 | <v-icon name="ri-refresh-line" animation="spin" speed="fast" /> 238 | ``` 239 | 240 | ### 图标翻转 241 | 242 | 使用 `flip: string` 来翻转图标: 243 | 244 | - `vertical`:垂直翻转 245 | - `horizontal`:水平翻转 246 | - `both`:垂直 + 水平翻转 247 | 248 | <p> 249 | <v-icon name="ri-playstation-line" flip="vertical"></v-icon> 250 | <v-icon name="si-internetexplorer" flip="horizontal"></v-icon> 251 | <v-icon name="ai-google-scholar" flip="both"></v-icon> 252 | </p> 253 | 254 | ```html 255 | <v-icon name="ri-playstation-line" flip="vertical" /> 256 | <v-icon name="si-internetexplorer" flip="horizontal" /> 257 | <v-icon name="ai-google-scholar" flip="both" /> 258 | ``` 259 | 260 | ### 填充颜色 261 | 262 | 使用 `fill: string` 来指定图标的填充颜色: 263 | 264 | <p> 265 | <v-icon name="fa-thermometer-empty" fill="green"></v-icon> 266 | <v-icon name="fa-thermometer-half" fill="orange"></v-icon> 267 | <v-icon name="fa-thermometer-full" fill="red"></v-icon> 268 | </p> 269 | 270 | ```html 271 | <v-icon name="fa-thermometer-empty" fill="green" /> 272 | <v-icon name="fa-thermometer-half" fill="orange" /> 273 | <v-icon name="fa-thermometer-full" fill="red" /> 274 | ``` 275 | 276 | ### 堆叠图标 277 | 278 | 类似于 Font Awesome 中的 `fa-stack`,但功能更强大一些: 279 | 280 | <p> 281 | <v-icon label="No Photo"> 282 | <v-icon name="fa-camera"></v-icon> 283 | <v-icon name="fa-ban" scale="2" fill="#fC644d"></v-icon> 284 | </v-icon> 285 | </p> 286 | 287 | ```html 288 | <v-icon label="No Photos"> 289 | <v-icon name="fa-camera" /> 290 | <v-icon name="fa-ban" scale="2" fill="#fC644d" /> 291 | </v-icon> 292 | ``` 293 | 294 | 堆叠的图标也可以加动画: 295 | 296 | <p> 297 | <v-icon label="No Photo" animation="wrench"> 298 | <v-icon name="fa-camera"></v-icon> 299 | <v-icon name="fa-ban" scale="2" fill="#fC644d"></v-icon> 300 | </v-icon> 301 | </p> 302 | 303 | ```html 304 | <v-icon label="No Photos" animation="wrench"> 305 | <v-icon name="fa-camera" /> 306 | <v-icon name="fa-ban" scale="2" fill="#fC644d" /> 307 | </v-icon> 308 | ``` 309 | 310 | ### 颜色反转 311 | 312 | 使用 `inverse: boolean` 来把图标变成白色 (`#fff`),**不适用于彩色图标**: 313 | 314 | <p> 315 | <v-icon label="Wechat Logo"> 316 | <v-icon name="fa-square" scale="1.5" fill="#57C181"></v-icon> 317 | <v-icon name="si-wechat" inverse></v-icon> 318 | </v-icon> 319 | </p> 320 | 321 | ```html 322 | <v-icon label="Wechat Logo"> 323 | <v-icon name="fa-square" scale="1.5" fill="#57C181" /> 324 | <v-icon name="si-wechat" inverse /> 325 | </v-icon> 326 | ``` 327 | 328 | ### Label 329 | 330 | 使用 `label: string` 来设置图标的 `aria-label`: 331 | 332 | <p><v-icon name="fa-code" label="Source Code"></v-icon></p> 333 | 334 | ```html 335 | <v-icon name="fa-code" label="Source Code" /> 336 | ``` 337 | 338 | ### Title 339 | 340 | 使用 `title: string` 给图标加上 `<title>` 标签: 341 | 342 | <p><v-icon name="fa-vuejs" title="Vue.js"></v-icon></p> 343 | 344 | ```html 345 | <v-icon name="fa-vuejs" title="Vue.js" /> 346 | ``` 347 | 348 | 349 | ## 进阶用法 350 | 351 | ### 自定义图标 352 | 353 | 注册自定义的图标: 354 | 355 | ```js 356 | OhVueIcon.add({ 357 | name: 'baidu', 358 | width: 23.868, 359 | height: 26, 360 | d: 'M3.613 13.701c2.827-.608 2.442-3.986 2.357-4.725-.138-1.139-1.477-3.128-3.296-2.971C.386 6.21.052 9.515.052 9.515c-.309 1.528.74 4.793 3.561 4.186zm3.002 5.875c-.083.238-.268.846-.107 1.375.315 1.187 1.346 1.24 1.346 1.24h1.48v-3.619H7.749c-.713.213-1.057.767-1.134 1.004zM8.86 8.035c1.562 0 2.823-1.797 2.823-4.019C11.683 1.796 10.421 0 8.86 0 7.301 0 6.036 1.796 6.036 4.016c0 2.222 1.265 4.019 2.824 4.019zm6.724.265c2.087.271 3.429-1.956 3.695-3.644.272-1.686-1.074-3.644-2.552-3.98-1.48-.339-3.329 2.032-3.497 3.578-.2 1.89.271 3.778 2.354 4.046zm5.114 9.923s-3.229-2.498-5.113-5.198c-2.555-3.981-6.185-2.361-7.399-.337-1.209 2.024-3.093 3.305-3.36 3.644-.271.334-3.9 2.293-3.095 5.871.806 3.576 3.635 3.508 3.635 3.508s2.085.205 4.504-.336c2.42-.537 4.503.134 4.503.134s5.652 1.893 7.199-1.751c1.545-3.645-.874-5.535-.874-5.535zm-9.671 5.423H7.352c-1.587-.316-2.219-1.4-2.299-1.584-.078-.188-.528-1.059-.29-2.539.686-2.219 2.642-2.379 2.642-2.379h1.956V14.74l1.666.025v8.881zm6.844-.025h-4.229c-1.639-.423-1.716-1.587-1.716-1.587v-4.677l1.716-.027v4.203c.104.447.661.529.661.529h1.742v-4.705h1.825v6.264zm5.986-12.486c0-.808-.671-3.239-3.159-3.239-2.492 0-2.825 2.295-2.825 3.917 0 1.548.131 3.71 3.227 3.641 3.096-.068 2.757-3.507 2.757-4.319z' 361 | }) 362 | ``` 363 | 364 | <p><v-icon name="baidu"></v-icon></p> 365 | 366 | ```html 367 | <v-icon name="baidu" /> 368 | ``` 369 | 370 | ### 自定义彩色图标 371 | 372 | ```js 373 | OhVueIcon.add( 374 | { 375 | name: 'webpack', 376 | width: 1200, 377 | height: 1200, 378 | paths: [ 379 | { 380 | fill: '#8ED6FB', 381 | d: 'M1035.6 879.3l-418.1 236.5V931.6L878 788.3l157.6 91zm28.6-25.9V358.8l-153 88.3V765l153 88.4zm-901.5 25.9l418.1 236.5V931.6L320.3 788.3l-157.6 91zm-28.6-25.9V358.8l153 88.3V765l-153 88.4zM152 326.8L580.8 84.2v178.1L306.1 413.4l-2.1 1.2-152-87.8zm894.3 0L617.5 84.2v178.1l274.7 151.1 2.1 1.2 152-87.8z' 382 | }, 383 | { 384 | fill: '#1C78C0', 385 | d: 'M580.8 889.7l-257-141.3v-280l257 148.4v272.9zm36.7 0l257-141.3v-280l-257 148.4v272.9zm-18.3-283.6zM341.2 436l258-141.9 258 141.9-258 149-258-149z' 386 | } 387 | ] 388 | }, 389 | { 390 | name: 'vue', 391 | width: 256, 392 | height: 221, 393 | polygons: [ 394 | { 395 | fill: '#41B883', 396 | points: '0,0 128,220.8 256,0 204.8,0 128,132.48 50.56,0 0,0' 397 | }, 398 | { 399 | fill: '#35495E', 400 | points: '50.56,0 128,133.12 204.8,0 157.44,0 128,51.2 97.92,0 50.56,0' 401 | } 402 | ] 403 | }, 404 | { 405 | name: 'html5-c', 406 | width: 512, 407 | height: 512, 408 | raw: '<path fill="#E34F26" d="M71,460 L30,0 481,0 440,460 255,512"/><path fill="#EF652A" d="M256,472 L405,431 440,37 256,37"/><path fill="#EBEBEB" d="M256,208 L181,208 176,150 256,150 256,94 255,94 114,94 115,109 129,265 256,265zM256,355 L255,355 192,338 188,293 158,293 132,293 139,382 255,414 256,414z"/><path fill="#FFF" d="M255,208 L255,265 325,265 318,338 255,355 255,414 371,382 372,372 385,223 387,208 371,208zM255,94 L255,129 255,150 255,150 392,150 392,150 392,150 393,138 396,109 397,94z"/>' 409 | } 410 | ) 411 | ``` 412 | 413 | <p> 414 | <v-icon name="webpack"></v-icon> 415 | <v-icon name="vue"></v-icon> 416 | <v-icon name="html5-c"></v-icon> 417 | </p> 418 | 419 | ```html 420 | <v-icon name="webpack" /> <v-icon name="vue" /> <v-icon name="html5-c" /> 421 | ``` 422 | 423 | 424 | ## Nuxt 425 | 426 | 当使用 Nuxt.js 时,需要按照 [Nuxt 文档](https://nuxtjs.org/docs/2.x/directory-structure/plugins)中的方式,将 `oh-vue-icons` 注册为一个插件。 427 | 428 | 然后需要在 `nuxt.config.js` 的 `build.transpile` 项中添加 `oh-vue-icons`(具体解释见[这里](https://nuxtjs.org/docs/2.x/directory-structure/plugins)): 429 | 430 | ```js 431 | export default { 432 | // ... 433 | build: { 434 | transpile: ['oh-vue-icons'] 435 | } 436 | } 437 | ``` 438 | 439 | 为了仅在客户端(client-side)渲染该组件,需要把组件包裹在 `<client-only>` 标签里: 440 | 441 | ```html 442 | <template> 443 | <div> 444 | <client-only> 445 | <v-icon name="fa-flag" /> 446 | <v-icon name="ri-zhihu-fill" /> 447 | </client-only> 448 | </div> 449 | </template> 450 | ``` 451 | 452 | 453 | ## Vite 454 | 455 | 使用 [Vite](https://cn.vitejs.dev/) 作为打包工具时,建议在预构建中排除 `oh-vue-icons`(具体讨论见 [#20](https://github.com/Renovamen/oh-vue-icons/issues/20)): 456 | 457 | ```js 458 | // vite.config.js 459 | 460 | export default { 461 | // ... 462 | optimizeDeps: { 463 | exclude: ["oh-vue-icons/icons"] 464 | } 465 | } 466 | ``` 467 | 468 | 当使用 Vite 的[服务端渲染(SSR)](https://cn.vitejs.dev/guide/ssr.html)功能时(例如 [VuePress](https://v2.vuepress.vuejs.org/zh/)、[Vite SSG](https://github.com/antfu/vite-ssg) 等),需要将 `oh-vue-icons` 加入 `ssr.noExternal` 项(具体解释见[这里](https://cn.vitejs.dev/guide/ssr.html#ssr-externals)): 469 | 470 | ```js 471 | // vite.config.js 472 | 473 | export default { 474 | // ... 475 | ssr: { 476 | noExternal: ["oh-vue-icons"] 477 | } 478 | } 479 | ``` 480 | 481 | 482 | ## 从 v0.x 迁移到 v1.x 483 | 484 | ### Vue 3 485 | 486 | ```diff 487 | - import OhVueIcon from "oh-vue-icons/dist/v3/icon.es"; 488 | + import { OhVueIcon, addIcons } from "oh-vue-icons"; 489 | 490 | - OhVueIcon.add(FaFlag) 491 | + addIcons(FaFlag) 492 | ``` 493 | 494 | 495 | ### Vue 2 496 | 497 | ```diff 498 | - import OhVueIcon from "oh-vue-icons"; 499 | + import { OhVueIcon, addIcons } from "oh-vue-icons"; 500 | 501 | - OhVueIcon.add(FaFlag) 502 | + addIcons(FaFlag) 503 | ``` 504 | 505 | 同时你还需要安装 `@vue/composition-api`,见[这里](#安装)。 506 | 507 | 508 | ### Nuxt 2 509 | 510 | 需要安装 `@nuxtjs/composition-api`,见[这里](#安装)。 511 | 512 | 513 | 514 | ## 致谢 515 | 516 | - 本项目受到了 [vue-awesome](https://github.com/Justineo/vue-awesome) 和 [react-icons](https://github.com/react-icons/react-icons) 的启发并借鉴了它们的部分代码 517 | 518 | - 本站由 [Vitesse](https://github.com/antfu/vitesse) 驱动,部署在 [Netlify](https://www.netlify.com/) 上 519 | 520 | 521 | ## 开源协议 522 | 523 | 本项目使用 [MIT](https://github.com/Renovamen/oh-vue-icons/blob/master/LICENSE) 开源协议。图标来自于[其他项目](#支持的图标库),所以还需要参考这些项目的开源协议。 524 | -------------------------------------------------------------------------------- /docs/src/shims.d.ts: -------------------------------------------------------------------------------- 1 | declare interface Window { 2 | // extend the window 3 | } 4 | 5 | // with vite-plugin-md, markdowns can be treat as Vue components 6 | declare module "*.md" { 7 | import { type DefineComponent } from "vue"; 8 | const component: DefineComponent<{}, {}, any>; 9 | export default component; 10 | } 11 | 12 | declare module "*.vue" { 13 | import { type DefineComponent } from "vue"; 14 | const component: DefineComponent<{}, {}, any>; 15 | export default component; 16 | } 17 | -------------------------------------------------------------------------------- /docs/src/stores/icon.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | 3 | const flipOptions = ["normal", "horizontal", "vertical", "both"]; 4 | 5 | export const useIconStore = defineStore("icon", () => { 6 | const state = reactive({ 7 | size: 2.4, 8 | color: "#222F3D", 9 | animation: null as string | null, 10 | flip: "normal", 11 | animSpeed: "normal" 12 | }); 13 | 14 | const setSize = (value: number) => { 15 | state.size = value; 16 | }; 17 | 18 | const setColor = (value: string) => { 19 | state.color = value; 20 | }; 21 | 22 | const setAnimation = (value: string) => { 23 | state.animation = state.animation === value ? null : value; 24 | }; 25 | 26 | const setAnimSpeed = (value: string) => { 27 | state.animSpeed = value; 28 | }; 29 | 30 | const setFlip = () => { 31 | const currentIndex = flipOptions.indexOf(state.flip); 32 | const nextIndex = (currentIndex + 1) % flipOptions.length; 33 | state.flip = flipOptions[nextIndex]; 34 | }; 35 | 36 | return { 37 | state, 38 | setSize, 39 | setColor, 40 | setAnimation, 41 | setAnimSpeed, 42 | setFlip 43 | }; 44 | }); 45 | -------------------------------------------------------------------------------- /docs/src/stores/site.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from "pinia"; 2 | 3 | export const useSiteStore = defineStore("site", () => { 4 | const sidebar = ref(false); 5 | 6 | const toggleSidebar = (value: boolean) => { 7 | sidebar.value = value; 8 | }; 9 | 10 | return { 11 | sidebar, 12 | toggleSidebar 13 | }; 14 | }); 15 | -------------------------------------------------------------------------------- /docs/src/styles/main.css: -------------------------------------------------------------------------------- 1 | @import './markdown.css'; 2 | 3 | html, 4 | body, 5 | #app, 6 | main { 7 | height: 100%; 8 | margin: 0; 9 | padding: 0; 10 | } 11 | 12 | html.dark { 13 | @apply bg-gray-800; 14 | } 15 | 16 | #nprogress { 17 | pointer-events: none; 18 | } 19 | 20 | #nprogress .bar { 21 | background: rgb(13,148,136); 22 | opacity: 0.75; 23 | position: fixed; 24 | z-index: 1031; 25 | top: 0; 26 | left: 0; 27 | width: 100%; 28 | height: 2px; 29 | } 30 | -------------------------------------------------------------------------------- /docs/src/styles/markdown.css: -------------------------------------------------------------------------------- 1 | /* https://github.com/antfu/prism-theme-vars */ 2 | @import 'prism-theme-vars/base.css'; 3 | 4 | .prose { 5 | --prism-font-family: 'DM Mono', monospace; 6 | max-width: 675px !important; 7 | } 8 | 9 | .prose img { 10 | @apply w-full; 11 | } 12 | 13 | .prose pre[class*="language-"] { 14 | @apply border border-gray-300 rounded; 15 | } 16 | .dark .prose pre[class*="language-"] { 17 | @apply border-gray-600; 18 | } 19 | 20 | .prose thead { 21 | @apply bg-gray-100; 22 | } 23 | .dark .prose thead { 24 | @apply bg-gray-700; 25 | } 26 | 27 | .prose td, 28 | .prose th { 29 | border: 1px solid #d1d5db !important; 30 | } 31 | .dark .prose td, 32 | .dark .prose th { 33 | border: 1px solid #4b5563 !important; 34 | } 35 | 36 | html:not(.dark) .prose { 37 | --prism-foreground: #393a34; 38 | --prism-background: #fbfbfb; 39 | --prism-comment: #a0ada0; 40 | --prism-string: #b56959; 41 | --prism-literal: #2f8a89; 42 | --prism-number: #296aa3; 43 | --prism-keyword: #1c6b48; 44 | --prism-function: #6c7834; 45 | --prism-boolean: #1c6b48; 46 | --prism-constant: #a65e2b; 47 | --prism-deleted: #a14f55; 48 | --prism-class: #2993a3; 49 | --prism-builtin: #ab5959; 50 | --prism-property: #b58451; 51 | --prism-namespace: #b05a78; 52 | --prism-punctuation: #8e8f8b; 53 | --prism-decorator: #bd8f8f; 54 | --prism-regex: #ab5e3f; 55 | --prism-json-property: #698c96; 56 | } 57 | 58 | html.dark .prose { 59 | --prism-selector: #eeeeee; 60 | --prism-symbol: #888888; 61 | --prism-foreground: #d4cfbf; 62 | --prism-background: #151515; 63 | --prism-comment: #758575; 64 | --prism-string: #d48372; 65 | --prism-literal: #429988; 66 | --prism-keyword: #4d9375; 67 | --prism-boolean: #1c6b48; 68 | --prism-number: #6394bf; 69 | --prism-variable: #c2b36e; 70 | --prism-function: #a1b567; 71 | --prism-deleted: #a14f55; 72 | --prism-class: #54b1bf; 73 | --prism-builtin: #e0a569; 74 | --prism-property: #dd8e6e; 75 | --prism-namespace: #db889a; 76 | --prism-punctuation: #858585; 77 | --prism-decorator: #bd8f8f; 78 | --prism-regex: #ab5e3f; 79 | --prism-json-property: #6b8b9e; 80 | --prism-line-number: #888888; 81 | --prism-line-number-gutter: #eeeeee; 82 | --prism-line-highlight-background: #444444; 83 | --prism-selection-background: #444444; 84 | } 85 | -------------------------------------------------------------------------------- /docs/src/types.ts: -------------------------------------------------------------------------------- 1 | import { type ViteSSGContext } from "vite-ssg"; 2 | 3 | export type UserModule = (ctx: ViteSSGContext) => void; 4 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "module": "ESNext", 5 | "target": "ESNext", 6 | "lib": ["DOM", "ESNext"], 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "jsx": "preserve", 10 | "skipLibCheck": true, 11 | "moduleResolution": "node", 12 | "resolveJsonModule": true, 13 | "noUnusedLocals": true, 14 | "strictNullChecks": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "types": [ 17 | "vite/client", 18 | "vue/ref-macros", 19 | "vite-plugin-pages/client", 20 | "vite-plugin-vue-layouts/client" 21 | ], 22 | "paths": { 23 | "~/*": ["src/*"] 24 | } 25 | }, 26 | "exclude": ["dist", "node_modules", "cypress"] 27 | } 28 | -------------------------------------------------------------------------------- /docs/unocss.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | presetAttributify, 4 | presetTypography, 5 | presetUno, 6 | presetWebFonts, 7 | transformerDirectives, 8 | transformerVariantGroup 9 | } from "unocss"; 10 | 11 | export default defineConfig({ 12 | shortcuts: [ 13 | [ 14 | "sidebar-li", 15 | "leading-9 list-none cursor-pointer ml-0 px-4 hover:text-blue-600 dark:hover:text-blue-400" 16 | ], 17 | [ 18 | "tool-btn", 19 | "h-8 border border-solid border-gray-500 outline-none rounded hover:bg-gray-100 dark:(border-gray-400 hover:bg-gray-700)" 20 | ], 21 | ["tool-title", "m-3 ml-0 mr-4 text-left"], 22 | ["tool-section", "p-2 mx-2"], 23 | ["hide-on-mobile", "hidden lg:block"], 24 | ["show-on-mobile", "block lg:hidden"], 25 | ["homepage", "max-w-home xl:max-w-home-xl"] 26 | ], 27 | rules: [ 28 | ["max-w-home-xl", { "max-width": "750px" }], 29 | ["max-w-home", { "max-width": "500px" }] 30 | ], 31 | presets: [ 32 | presetUno(), 33 | presetAttributify(), 34 | presetTypography(), 35 | presetWebFonts({ 36 | fonts: { 37 | sans: "Kumbh Sans:400,500,700", 38 | mono: "DM Mono" 39 | } 40 | }) 41 | ], 42 | transformers: [transformerDirectives(), transformerVariantGroup()], 43 | safelist: "prose prose-sm m-auto text-left dark:text-gray-100".split(" ") 44 | }); 45 | -------------------------------------------------------------------------------- /docs/vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { defineConfig } from "vite"; 3 | import Vue from "@vitejs/plugin-vue"; 4 | import Pages from "vite-plugin-pages"; 5 | import generateSitemap from "vite-ssg-sitemap"; 6 | import Layouts from "vite-plugin-vue-layouts"; 7 | import Components from "unplugin-vue-components/vite"; 8 | import AutoImport from "unplugin-auto-import/vite"; 9 | import Markdown from "vite-plugin-md"; 10 | import { VitePWA } from "vite-plugin-pwa"; 11 | import VueI18n from "@intlify/vite-plugin-vue-i18n"; 12 | import Inspect from "vite-plugin-inspect"; 13 | import Prism from "markdown-it-prism"; 14 | import LinkAttributes from "markdown-it-link-attributes"; 15 | import Unocss from "unocss/vite"; 16 | 17 | const markdownWrapperClasses = 18 | "prose prose-sm m-auto text-left dark:text-gray-100"; 19 | 20 | export default defineConfig({ 21 | resolve: { 22 | alias: { 23 | "~/": `${path.resolve(__dirname, "src")}/` 24 | } 25 | }, 26 | 27 | // @ts-ignore:next-line 28 | ssr: { 29 | noExternal: ["oh-vue-icons-npm"] 30 | }, 31 | 32 | plugins: [ 33 | Vue({ 34 | include: [/\.vue$/, /\.md$/], 35 | reactivityTransform: true 36 | }), 37 | 38 | // https://github.com/hannoeru/vite-plugin-pages 39 | Pages({ 40 | extensions: ["vue", "md"], 41 | extendRoute: (route) => { 42 | if (route.component.endsWith(".md")) { 43 | route.meta = { layout: "docs" }; 44 | } 45 | } 46 | }), 47 | 48 | // https://github.com/JohnCampionJr/vite-plugin-vue-layouts 49 | Layouts(), 50 | 51 | // https://github.com/antfu/unplugin-auto-import 52 | AutoImport({ 53 | imports: [ 54 | "vue", 55 | "vue-router", 56 | "vue-i18n", 57 | "vue/macros", 58 | "@vueuse/head", 59 | "@vueuse/core" 60 | ], 61 | dts: "src/auto-imports.d.ts" 62 | }), 63 | 64 | // https://github.com/antfu/unplugin-vue-components 65 | Components({ 66 | // allow auto load markdown components under `./src/components/` 67 | extensions: ["vue", "md"], 68 | // allow auto import and register components used in markdown 69 | include: [/\.vue$/, /\.vue\?vue/, /\.md$/], 70 | dts: "src/components.d.ts" 71 | }), 72 | 73 | // https://github.com/antfu/unocss 74 | // see unocss.config.ts for config 75 | Unocss(), 76 | 77 | // https://github.com/antfu/vite-plugin-md 78 | // Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite 79 | Markdown({ 80 | wrapperClasses: markdownWrapperClasses, 81 | headEnabled: true, 82 | markdownItSetup(md) { 83 | // https://prismjs.com/ 84 | md.use(Prism); 85 | md.use(LinkAttributes, { 86 | matcher: (link: string) => /^https?:\/\//.test(link), 87 | attrs: { 88 | target: "_blank", 89 | rel: "noopener" 90 | } 91 | }); 92 | } 93 | }), 94 | 95 | // https://github.com/antfu/vite-plugin-pwa 96 | VitePWA({ 97 | registerType: "autoUpdate", 98 | includeAssets: ["favicon.svg", "safari-pinned-tab.svg"], 99 | manifest: { 100 | name: "Vitesse", 101 | short_name: "Vitesse", 102 | theme_color: "#ffffff", 103 | icons: [ 104 | { 105 | src: "/pwa-192x192.png", 106 | sizes: "192x192", 107 | type: "image/png" 108 | }, 109 | { 110 | src: "/pwa-512x512.png", 111 | sizes: "512x512", 112 | type: "image/png" 113 | }, 114 | { 115 | src: "/pwa-512x512.png", 116 | sizes: "512x512", 117 | type: "image/png", 118 | purpose: "any maskable" 119 | } 120 | ] 121 | } 122 | }), 123 | 124 | // https://github.com/intlify/bundle-tools/tree/main/packages/vite-plugin-vue-i18n 125 | VueI18n({ 126 | runtimeOnly: true, 127 | compositionOnly: true, 128 | include: [path.resolve(__dirname, "src/i18n/translations/**")] 129 | }), 130 | 131 | // https://github.com/antfu/vite-plugin-inspect 132 | // Visit http://localhost:3333/__inspect/ to see the inspector 133 | Inspect() 134 | ], 135 | 136 | // https://github.com/antfu/vite-ssg 137 | ssgOptions: { 138 | script: "async", 139 | formatting: "minify", 140 | onFinished() { 141 | generateSitemap(); 142 | }, 143 | includedRoutes() { 144 | return ["/", "/docs", "/zh/", "/zh/docs"]; 145 | } 146 | } 147 | }); 148 | -------------------------------------------------------------------------------- /iconpacks/index.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = { 4 | icons: [ 5 | { 6 | id: "ai", 7 | name: "academicons", 8 | downloadFileName: "academicons", 9 | downloadURL: "https://github.com/jpswalsh/academicons/archive/refs/heads/master.zip", 10 | contents: [ 11 | { 12 | files: path.resolve(__dirname, "academicons/svg/*.svg"), 13 | formatter: (name) => `Ai${name}`, 14 | prefix: (name) => `ai-${name}`, 15 | scale: 1.17 16 | }, 17 | ], 18 | projectUrl: "https://github.com/jpswalsh/academicons", 19 | website: "https://jpswalsh.github.io/academicons/", 20 | license: "SIL OFL 1.1", 21 | licenseUrl: "http://scripts.sil.org/OFL" 22 | }, 23 | { 24 | id: "bi", 25 | name: "Bootstrap Icons", 26 | downloadFileName: "bootstrap-icons", 27 | downloadURL: "https://github.com/twbs/icons/archive/refs/heads/main.zip", 28 | contents: [ 29 | { 30 | files: path.resolve(__dirname, "bootstrap-icons/icons/*.svg"), 31 | formatter: (name) => `Bi${name}`, 32 | prefix: (name) => `bi-${name}`, 33 | scale: 1.2 34 | }, 35 | ], 36 | projectUrl: "https://github.com/twbs/icons", 37 | website: "https://icons.getbootstrap.com/", 38 | license: "MIT", 39 | licenseUrl: "https://opensource.org/licenses/MIT" 40 | }, 41 | { 42 | id: "ci", 43 | name: "Crypto Icons", 44 | downloadFileName: "cryptocurrency-icons", 45 | downloadURL: "https://github.com/spothq/cryptocurrency-icons/archive/refs/heads/master.zip", 46 | contents: [ 47 | { 48 | files: path.resolve(__dirname, "cryptocurrency-icons/svg/black/*.svg"), 49 | formatter: (name) => `Ci${name}`, 50 | prefix: (name) => `ci-${name}`, 51 | scale: 1.2 52 | }, 53 | { 54 | files: path.resolve(__dirname, "cryptocurrency-icons/svg/color/*.svg"), 55 | formatter: (name) => `CiColor${name}`, 56 | prefix: (name) => `ci-color-${name}`, 57 | scale: 1.2 58 | } 59 | ], 60 | multiColor: true, 61 | projectUrl: "https://github.com/spothq/cryptocurrency-icons", 62 | website: "http://cryptoicons.co/", 63 | license: "CC0 1.0 Universal", 64 | licenseUrl: "https://creativecommons.org/publicdomain/zero/1.0/" 65 | }, 66 | { 67 | id: "co", 68 | name: "CoreUI Icons", 69 | downloadFileName: "coreui-icons", 70 | downloadURL: "https://github.com/coreui/coreui-icons/archive/refs/heads/master.zip", 71 | contents: [ 72 | { 73 | files: path.resolve(__dirname, "coreui-icons/svg/*/*.svg"), 74 | formatter: (name) => `Co${name}`, 75 | prefix: (name) => `co-${name}`, 76 | raw: (name) => name.substr(4), 77 | scale: 1.2 78 | } 79 | ], 80 | multiColor: true, 81 | projectUrl: "https://github.com/coreui/coreui-icons", 82 | website: "https://icons.coreui.io/icons/", 83 | license: "CC BY 4.0", 84 | licenseUrl: "https://creativecommons.org/licenses/by/4.0/" 85 | }, 86 | { 87 | id: "fa", 88 | name: "Font Awesome", 89 | downloadFileName: "fontawesome", 90 | downloadURL: "https://github.com/FortAwesome/Font-Awesome/archive/refs/heads/master.zip", 91 | contents: [ 92 | { 93 | files: path.resolve( 94 | __dirname, 95 | "fontawesome/svgs/+(brands|solid)/*.svg" 96 | ), 97 | formatter: (name) => `Fa${name}`, 98 | prefix: (name) => `fa-${name}`, 99 | scale: 1.17 100 | }, 101 | { 102 | files: path.resolve(__dirname, "fontawesome/svgs/regular/*.svg"), 103 | formatter: (name) => `FaRegular${name}`, 104 | prefix: (name) => `fa-regular-${name}`, 105 | scale: 1.17 106 | }, 107 | ], 108 | projectUrl: "https://github.com/FortAwesome/Font-Awesome", 109 | website: "https://fontawesome.com/", 110 | license: "CC BY 4.0 License", 111 | licenseUrl: "https://creativecommons.org/licenses/by/4.0/" 112 | }, 113 | { 114 | id: "fc", 115 | name: "Flat Color Icons", 116 | downloadFileName: "flat-color-icons", 117 | downloadURL: "https://github.com/icons8/flat-color-icons/archive/refs/heads/master.zip", 118 | contents: [ 119 | { 120 | files: path.resolve(__dirname, "flat-color-icons/svg/*.svg"), 121 | formatter: (name) => `Fc${name}`, 122 | prefix: (name) => `fc-${name}` 123 | }, 124 | ], 125 | multiColor: true, 126 | projectUrl: "https://github.com/icons8/flat-color-icons", 127 | website: "https://icons8.com/icons/color", 128 | license: "MIT / Good Boy", 129 | licenseUrl: "https://github.com/icons8/flat-color-icons/blob/master/LICENSE.md" 130 | }, 131 | { 132 | id: "fi", 133 | name: "Flag Icon", 134 | downloadFileName: "flag-icon", 135 | downloadURL: "https://github.com/lipis/flag-icons/archive/refs/heads/main.zip", 136 | contents: [ 137 | { 138 | files: path.resolve(__dirname, "flag-icon/flags/4x3/*.svg"), 139 | formatter: (name) => `Fi${name}`, 140 | prefix: (name) => `fi-${name}` 141 | }, 142 | { 143 | files: path.resolve(__dirname, "flag-icon/flags/1x1/*.svg"), 144 | formatter: (name) => `FiSquare${name}`, 145 | prefix: (name) => `fi-square-${name}`, 146 | scale: 1.33 147 | } 148 | ], 149 | multiColor: true, 150 | projectUrl: "https://github.com/lipis/flag-icon-css", 151 | website: "https://flagicons.lipis.dev/", 152 | license: "MIT", 153 | licenseUrl: "https://opensource.org/licenses/MIT" 154 | }, 155 | { 156 | id: "gi", 157 | name: "gameicons", 158 | downloadFileName: "gameicons", 159 | downloadURL: "https://game-icons.net/archives/svg/zip/000000/transparent/game-icons.net.svg.zip", 160 | contents: [ 161 | { 162 | files: path.resolve(__dirname, "gameicons/000000/transparent/1x1/*/*.svg"), 163 | formatter: (name) => `Gi${name}`, 164 | prefix: (name) => `gi-${name}`, 165 | scale: 1.14 166 | }, 167 | ], 168 | projectUrl: "https://github.com/game-icons/icons", 169 | website: "https://game-icons.net/", 170 | license: "CC BY 3.0", 171 | licenseUrl: "https://creativecommons.org/licenses/by/3.0/" 172 | }, 173 | { 174 | id: "hi", 175 | name: "Heroicons", 176 | downloadFileName: "heroicons", 177 | downloadURL: "https://github.com/tailwindlabs/heroicons/archive/refs/heads/master.zip", 178 | contents: [ 179 | { 180 | files: path.resolve(__dirname, "heroicons/optimized/outline/*.svg"), 181 | formatter: (name) => `Hi${name}`, 182 | prefix: (name) => `hi-${name}` 183 | }, 184 | { 185 | files: path.resolve(__dirname, "heroicons/optimized/solid/*.svg"), 186 | formatter: (name) => `HiSolid${name}`, 187 | prefix: (name) => `hi-solid-${name}` 188 | } 189 | ], 190 | projectUrl: "https://github.com/tailwindlabs/heroicons", 191 | website: "https://heroicons.com/", 192 | license: "MIT", 193 | licenseUrl: "https://opensource.org/licenses/MIT" 194 | }, 195 | { 196 | id: "io", 197 | name: "Ionicons", 198 | downloadFileName: "ionicons", 199 | downloadURL: "https://github.com/ionic-team/ionicons/archive/refs/heads/main.zip", 200 | contents: [ 201 | { 202 | files: path.resolve(__dirname, "ionicons/src/svg/*.svg"), 203 | formatter: (name) => `Io${name}`, 204 | prefix: (name) => `io-${name}` 205 | }, 206 | ], 207 | projectUrl: "https://github.com/ionic-team/ionicons", 208 | website: "https://ionicons.com/", 209 | license: "MIT", 210 | licenseUrl: "https://opensource.org/licenses/MIT" 211 | }, 212 | { 213 | id: "la", 214 | name: "Line Awesome", 215 | downloadFileName: "line-awesome", 216 | downloadURL: "https://github.com/icons8/line-awesome/archive/refs/heads/master.zip", 217 | contents: [ 218 | { 219 | files: path.resolve(__dirname, "line-awesome/svg/*.svg"), 220 | formatter: (name) => `La${name}`, 221 | prefix: (name) => `la-${name}` 222 | }, 223 | ], 224 | projectUrl: "https://github.com/icons8/line-awesome", 225 | website: "https://icons8.com/line-awesome", 226 | license: "MIT / Good Boy", 227 | licenseUrl: "https://github.com/icons8/line-awesome/blob/master/LICENSE.md" 228 | }, 229 | { 230 | id: "md", 231 | name: "Material Design icons", 232 | downloadFileName: "material-design-icons", 233 | downloadURL: "https://github.com/google/material-design-icons/archive/refs/heads/master.zip", 234 | contents: [ 235 | { 236 | files: path.resolve(__dirname, "material-design-icons/src/*/*/*/24px.svg"), 237 | formatter: (name) => `Md${name}`, 238 | nameFromPath: (file) => { 239 | const match = file.match(/material-design-icons\/src\/(.*?)\/(.*?)\/(.*?)\/24px.svg/); 240 | let name = match[2].replace(/_/g, ""); 241 | const style = match[3].replace(/materialicons/g, ""); 242 | if (style !== "") name = `${name}-${style}`; 243 | return name; 244 | }, 245 | prefix: (name) => `md-${name}`, 246 | scale: 0.96 247 | }, 248 | ], 249 | projectUrl: "https://github.com/google/material-design-icons", 250 | website: "http://google.github.io/material-design-icons/", 251 | license: "Apache License Version 2.0", 252 | licenseUrl: "http://www.apache.org/licenses/" 253 | }, 254 | { 255 | id: "oi", 256 | name: "Octicons", 257 | downloadFileName: "octicons", 258 | downloadURL: "https://github.com/primer/octicons/archive/refs/heads/main.zip", 259 | contents: [ 260 | { 261 | files: path.resolve(__dirname, "octicons/icons/*-16.svg"), 262 | formatter: (name) => `Oi${name}`, 263 | prefix: (name) => `oi-${name}`, 264 | raw: (name) => name.slice(0, -3), 265 | scale: 1.2 266 | }, 267 | ], 268 | projectUrl: "https://github.com/primer/octicons", 269 | website: "https://primer.style/octicons/", 270 | license: "MIT", 271 | licenseUrl: "https://opensource.org/licenses/MIT" 272 | }, 273 | { 274 | id: "pi", 275 | name: "Pokemon Icons", 276 | downloadFileName: "pokemon-icons", 277 | downloadURL: "https://github.com/TheArtificial/pokemon-icons/archive/refs/heads/master.zip", 278 | contents: [ 279 | { 280 | files: path.resolve(__dirname, "pokemon-icons/_icons/SVG/*.svg"), 281 | formatter: (name) => `Pi${name}`, 282 | prefix: (name) => `pi-${name}`, 283 | raw: (name) => name.substr(4), 284 | scale: 1.17 285 | } 286 | ], 287 | multiColor: true, 288 | projectUrl: "https://github.com/TheArtificial/pokemon-icons", 289 | website: "https://theartificial.github.io/pokemon-icons/", 290 | license: "CC BY 4.0", 291 | licenseUrl: "https://creativecommons.org/licenses/by/4.0/" 292 | }, 293 | { 294 | id: "pr", 295 | name: "PrimeIcons", 296 | downloadFileName: "primeicons", 297 | downloadURL: "https://github.com/primefaces/primeicons/archive/refs/heads/master.zip", 298 | contents: [ 299 | { 300 | files: path.resolve(__dirname, "primeicons/raw-svg/*.svg"), 301 | formatter: (name) => `Pr${name}`, 302 | prefix: (name) => `pr-${name}`, 303 | scale: 0.9 304 | } 305 | ], 306 | projectUrl: "https://github.com/primefaces/primeicons", 307 | website: "https://www.primefaces.org/primeng/showcase/#/icons", 308 | license: "MIT", 309 | licenseUrl: "https://opensource.org/licenses/MIT" 310 | }, 311 | { 312 | id: "px", 313 | name: "Pixelarticons", 314 | downloadFileName: "pixelarticons", 315 | downloadURL: "https://github.com/halfmage/pixelarticons/archive/refs/heads/master.zip", 316 | contents: [ 317 | { 318 | files: path.resolve(__dirname, "pixelarticons/svg/*.svg"), 319 | formatter: (name) => `Px${name}`, 320 | prefix: (name) => `px-${name}`, 321 | scale: 1.15 322 | } 323 | ], 324 | projectUrl: "https://github.com/halfmage/pixelarticons", 325 | website: "https://pixelarticons.com/", 326 | license: "MIT", 327 | licenseUrl: "https://opensource.org/licenses/MIT" 328 | }, 329 | { 330 | id: "ri", 331 | name: "Remix Icon", 332 | downloadFileName: "remixicon", 333 | downloadURL: "https://github.com/Remix-Design/RemixIcon/archive/refs/heads/master.zip", 334 | contents: [ 335 | { 336 | files: path.resolve(__dirname, "remixicon/icons/*/*.svg"), 337 | formatter: (name) => `Ri${name}`, 338 | prefix: (name) => `ri-${name}` 339 | } 340 | ], 341 | projectUrl: "https://github.com/Remix-Design/RemixIcon", 342 | website: "https://remixicon.com/", 343 | license: "Apache License Version 2.0", 344 | licenseUrl: "http://www.apache.org/licenses/" 345 | }, 346 | { 347 | id: "si", 348 | name: "Simple Icons", 349 | downloadFileName: "simple-icons", 350 | downloadURL: "https://github.com/simple-icons/simple-icons/archive/refs/heads/develop.zip", 351 | contents: [ 352 | { 353 | files: path.resolve(__dirname, "simple-icons/icons/*.svg"), 354 | formatter: (name) => `Si${name}`, 355 | prefix: (name) => `si-${name}`, 356 | scale: 1.25 357 | }, 358 | ], 359 | projectUrl: "https://github.com/simple-icons/simple-icons", 360 | website: "https://simpleicons.org/", 361 | license: "CC0 1.0 Universal", 362 | licenseUrl: "https://creativecommons.org/publicdomain/zero/1.0/" 363 | }, 364 | { 365 | id: "vi", 366 | name: "VSCode Icons", 367 | downloadFileName: "vscode-icons", 368 | downloadURL: "https://github.com/vscode-icons/vscode-icons/archive/refs/heads/master.zip", 369 | contents: [ 370 | { 371 | files: path.resolve(__dirname, "vscode-icons/icons/*.svg"), 372 | formatter: (name) => `Vi${name}`, 373 | prefix: (name) => `vi-${name}`, 374 | scale: 1.04 375 | }, 376 | ], 377 | multiColor: true, 378 | projectUrl: "https://github.com/vscode-icons/vscode-icons", 379 | website: "https://marketplace.visualstudio.com/items?itemName=vscode-icons-team.vscode-icons", 380 | license: "CC BY-SA 4.0", 381 | licenseUrl: "https://creativecommons.org/licenses/by-sa/4.0/" 382 | }, 383 | { 384 | id: "wi", 385 | name: "Weather Icons", 386 | downloadFileName: "weather-icons", 387 | downloadURL: "https://github.com/erikflowers/weather-icons/archive/refs/heads/master.zip", 388 | contents: [ 389 | { 390 | files: path.resolve(__dirname, "weather-icons/svg/*.svg") 391 | }, 392 | ], 393 | projectUrl: "https://github.com/erikflowers/weather-icons", 394 | website: "https://erikflowers.github.io/weather-icons/", 395 | license: "SIL OFL 1.1", 396 | licenseUrl: "http://scripts.sil.org/OFL" 397 | } 398 | ] 399 | } 400 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "package", 5 | "docs" 6 | ], 7 | "scripts": { 8 | "build": "yarn workspace oh-vue-icons run build", 9 | "build:demo": "yarn workspace oh-vue-icons build:demo", 10 | "build:docs": "yarn workspace docs run build", 11 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", 12 | "dev": "yarn workspace oh-vue-icons run dev", 13 | "docs": "yarn workspace docs run dev", 14 | "download": "bash ./scripts/download.sh", 15 | "icons": "node scripts/build.js", 16 | "lint": "eslint --ext .js,.ts,.tsx,.vue ./", 17 | "prepare": "husky install", 18 | "release": "bash ./scripts/release.sh" 19 | }, 20 | "lint-staged": { 21 | "*.{js,ts,tsx,vue}": [ 22 | "eslint --fix --ext .js,.ts,.tsx,.vue ./" 23 | ], 24 | "package.json": [ 25 | "sort-package-json" 26 | ] 27 | }, 28 | "devDependencies": { 29 | "@typescript-eslint/eslint-plugin": "^5.20.0", 30 | "@typescript-eslint/parser": "^5.20.0", 31 | "camelcase": "^6.3.0", 32 | "cheerio": "^1.0.0-rc.10", 33 | "eslint": "^8.14.0", 34 | "eslint-config-prettier": "^8.5.0", 35 | "eslint-plugin-prettier": "^4.0.0", 36 | "eslint-plugin-vue": "^8.7.1", 37 | "glob-promise": "^4.2.2", 38 | "husky": "^7.0.4", 39 | "lint-staged": "^12.4.0", 40 | "prettier": "^2.6.2", 41 | "rimraf": "^3.0.2", 42 | "sort-package-json": "^1.55.0", 43 | "svgo": "^1.3.2", 44 | "typescript": "^4.6.3" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /package/.gitignore: -------------------------------------------------------------------------------- 1 | icons 2 | demo_dist 3 | -------------------------------------------------------------------------------- /package/build/rollup.config.js: -------------------------------------------------------------------------------- 1 | import analyze from "rollup-plugin-analyzer"; 2 | import postcss from "rollup-plugin-postcss"; 3 | import dts from "rollup-plugin-dts"; 4 | import esbuild from "rollup-plugin-esbuild"; 5 | 6 | const EMPTY_FILE_ID = "__rollup_empty__"; 7 | 8 | const ingoreCSS = { 9 | name: "ignore-css", 10 | resolveId: (source) => { 11 | if (source.endsWith(".css")) { 12 | return EMPTY_FILE_ID; 13 | } 14 | return null; 15 | }, 16 | load: (id) => { 17 | return id === EMPTY_FILE_ID ? "" : null; 18 | } 19 | }; 20 | 21 | const base = { 22 | input: "src/index.ts", 23 | plugins: [ 24 | esbuild(), 25 | postcss(), 26 | analyze({ summaryOnly: true, hideDeps: true }) 27 | ], 28 | external: ["vue-demi"] 29 | }; 30 | 31 | const config = [ 32 | Object.assign({}, base, { 33 | output: { 34 | file: "dist/index.mjs", 35 | format: "es", 36 | sourcemap: true 37 | } 38 | }), 39 | Object.assign({}, base, { 40 | output: { 41 | file: "dist/index.cjs", 42 | format: "cjs", 43 | sourcemap: true 44 | } 45 | }), 46 | { 47 | input: "src/index.ts", 48 | plugins: [ingoreCSS, dts()], 49 | output: { 50 | file: "dist/index.d.ts", 51 | format: "es" 52 | } 53 | } 54 | ]; 55 | 56 | export default config; 57 | -------------------------------------------------------------------------------- /package/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html lang="en"> 3 | <head> 4 | <meta charset="UTF-8" /> 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 | <title>Demo Vue 3 - Oh, Vue Icons! 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oh-vue-icons", 3 | "version": "1.0.0-rc3", 4 | "description": "Include inline SVG icons from different popular icon packs in Vue 2 & 3 easily.", 5 | "keywords": [ 6 | "icons", 7 | "vue", 8 | "vue3", 9 | "font awesome", 10 | "remix icon", 11 | "bootstrap icons", 12 | "line awesome", 13 | "octions", 14 | "simple icons", 15 | "heroicons", 16 | "material design icons", 17 | "ionicons" 18 | ], 19 | "homepage": "https://oh-vue-icons.js.org", 20 | "bugs": { 21 | "url": "https://github.com/Renovamen/oh-vue-icons/issues" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/Renovamen/oh-vue-icons" 26 | }, 27 | "license": "MIT", 28 | "author": "Renovamen ", 29 | "main": "dist/index.cjs", 30 | "module": "dist/index.mjs", 31 | "types": "dist/index.d.ts", 32 | "files": [ 33 | "dist", 34 | "icons", 35 | "types" 36 | ], 37 | "scripts": { 38 | "build": "rollup --config ./build/rollup.config.js", 39 | "build:demo": "vue-tsc --noEmit && vite build", 40 | "dev": "vite", 41 | "serve": "vite preview" 42 | }, 43 | "dependencies": { 44 | "vue-demi": "^0.12.5" 45 | }, 46 | "devDependencies": { 47 | "@vitejs/plugin-vue": "^2.3.1", 48 | "postcss": "^8.4.12", 49 | "rollup": "^2.70.2", 50 | "rollup-plugin-analyzer": "^4.0.0", 51 | "rollup-plugin-dts": "^4.2.1", 52 | "rollup-plugin-esbuild": "^4.9.1", 53 | "rollup-plugin-postcss": "^4.0.2", 54 | "typescript": "^4.6.3", 55 | "vite": "^2.9.5", 56 | "vue": "^3.2.33", 57 | "vue-tsc": "^0.34.10" 58 | }, 59 | "peerDependencies": { 60 | "@vue/composition-api": "^1.0.0-rc.1", 61 | "vue": "^2.0.0 || >=3.0.0" 62 | }, 63 | "peerDependenciesMeta": { 64 | "@vue/composition-api": { 65 | "optional": true 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /package/src/App.vue: -------------------------------------------------------------------------------- 1 | 66 | 67 | 74 | -------------------------------------------------------------------------------- /package/src/components/Icon.ts: -------------------------------------------------------------------------------- 1 | import { 2 | defineComponent, 3 | reactive, 4 | computed, 5 | onMounted, 6 | onUpdated, 7 | toRefs, 8 | ref, 9 | h, 10 | isVue2 11 | } from "vue-demi"; 12 | import type { CustomizeIconType, ObjType } from "../../types/icons"; 13 | import utils from "../utils"; 14 | 15 | type IconsType = { 16 | [key: string]: CustomizeIconType; 17 | }; 18 | 19 | const icons: IconsType = {}; 20 | 21 | const register = (data: CustomizeIconType): void => { 22 | const { name, paths = [], d, polygons = [], points } = data; 23 | 24 | if (d) paths.push({ d }); 25 | if (points) polygons.push({ points }); 26 | 27 | icons[name] = Object.assign({}, data, { 28 | paths, 29 | polygons 30 | }); 31 | 32 | if (!icons[name].minX) icons[name].minX = 0; 33 | if (!icons[name].minY) icons[name].minY = 0; 34 | }; 35 | 36 | const addIcons = (...data: CustomizeIconType[]): void => { 37 | for (const icon of data) register(icon); 38 | }; 39 | 40 | const listIcons = (): IconsType => { 41 | return icons; 42 | }; 43 | 44 | const OhVueIcon = defineComponent({ 45 | name: "OhVueIcon", 46 | 47 | props: { 48 | name: { 49 | type: String, 50 | validator: (val: string): boolean => { 51 | if (val && !(val in icons)) { 52 | console.warn( 53 | `Invalid prop: prop "name" is referring to an unregistered icon "${val}".\n` + 54 | `Please make sure you have imported this icon before using it.` 55 | ); 56 | return false; 57 | } 58 | return true; 59 | } 60 | }, 61 | title: String, 62 | fill: String, 63 | scale: { 64 | type: [Number, String], 65 | default: 1 66 | }, 67 | animation: { 68 | validator: (val: string): boolean => { 69 | return [ 70 | "spin", 71 | "spin-pulse", 72 | "wrench", 73 | "ring", 74 | "pulse", 75 | "flash", 76 | "float" 77 | ].includes(val); 78 | } 79 | }, 80 | hover: Boolean, 81 | flip: { 82 | validator: (val: string): boolean => { 83 | return ["horizontal", "vertical", "both"].includes(val); 84 | } 85 | }, 86 | speed: { 87 | validator: (val: string): boolean => { 88 | return val === "fast" || val === "slow"; 89 | } 90 | }, 91 | label: String, 92 | inverse: Boolean 93 | }, 94 | 95 | setup(props) { 96 | const children = ref([] as any[]); 97 | 98 | const state = reactive({ 99 | outerScale: 1.2, 100 | x: null as number | null, 101 | y: null as number | null 102 | }); 103 | 104 | const childrenState = reactive({ 105 | width: 0, 106 | height: 0 107 | }); 108 | 109 | const normalizedScale = computed(() => { 110 | const scale = Number(props.scale); 111 | if (isNaN(scale) || scale <= 0) { 112 | console.warn(`Invalid prop: prop "scale" should be a number over 0.`); 113 | return state.outerScale; 114 | } 115 | return scale * state.outerScale; 116 | }); 117 | 118 | const klass = computed(() => { 119 | const classes = { 120 | "ov-icon": true, 121 | "ov-inverse": props.inverse, 122 | "ov-flip-horizontal": props.flip === "horizontal", 123 | "ov-flip-vertical": props.flip === "vertical", 124 | "ov-flip-both": props.flip === "both", 125 | "ov-spin": props.animation === "spin", 126 | "ov-spin-pulse": props.animation === "spin-pulse", 127 | "ov-wrench": props.animation === "wrench", 128 | "ov-ring": props.animation === "ring", 129 | "ov-pulse": props.animation === "pulse", 130 | "ov-flash": props.animation === "flash", 131 | "ov-float": props.animation === "float", 132 | "ov-hover": props.hover, 133 | "ov-fast": props.speed === "fast", 134 | "ov-slow": props.speed === "slow" 135 | }; 136 | return classes; 137 | }); 138 | 139 | const icon = computed((): CustomizeIconType | null => { 140 | if (props.name) return icons[props.name]; 141 | return null; 142 | }); 143 | 144 | const box = computed((): string => { 145 | if (icon.value) { 146 | return `${icon.value.minX} ${icon.value.minY} ${icon.value.width} ${icon.value.height}`; 147 | } 148 | return `0 0 ${width.value} ${height.value}`; 149 | }); 150 | 151 | const ratio = computed((): number => { 152 | if (!icon.value) return 1; 153 | 154 | const { width, height } = icon.value; 155 | return Math.max(width, height) / 16; 156 | }); 157 | 158 | const width = computed((): number => { 159 | return ( 160 | childrenState.width || 161 | (icon.value && 162 | (icon.value.width / ratio.value) * normalizedScale.value) || 163 | 0 164 | ); 165 | }); 166 | 167 | const height = computed((): number => { 168 | return ( 169 | childrenState.height || 170 | (icon.value && 171 | (icon.value.height / ratio.value) * normalizedScale.value) || 172 | 0 173 | ); 174 | }); 175 | 176 | const style = computed(() => { 177 | if (normalizedScale.value === 1) return false; 178 | return { 179 | fontSize: normalizedScale.value + "em" 180 | }; 181 | }); 182 | 183 | const raw = computed((): string | null => { 184 | // Generates unique id for each icon's SVG element with ID 185 | if (!icon.value || !icon.value.raw) return null; 186 | 187 | const ids: { [key: string]: string } = {}; 188 | let raw = icon.value.raw; 189 | 190 | raw = raw.replace( 191 | /\s(?:xml:)?id=(["']?)([^"')\s]+)\1/g, 192 | (match: any, quote: string, id: string) => { 193 | const uniqueId = utils.getID("vat-"); 194 | ids[id] = uniqueId; 195 | return ` id="${uniqueId}"`; 196 | } 197 | ); 198 | raw = raw.replace( 199 | /#(?:([^'")\s]+)|xpointer\(id\((['"]?)([^')]+)\2\)\))/g, 200 | (match: any, rawId: string, _: string, pointerId: string) => { 201 | const id = rawId || pointerId; 202 | if (!id || !ids[id]) return match; 203 | return `#${ids[id]}`; 204 | } 205 | ); 206 | return raw; 207 | }); 208 | 209 | const attribs = computed((): any => { 210 | if (!icon.value || !icon.value.attr) return {}; 211 | return icon.value.attr; 212 | }); 213 | 214 | const updateStack = () => { 215 | if (!props.name && props.name !== null && children.value.length === 0) { 216 | console.warn(`Invalid prop: prop "name" is required.`); 217 | return; 218 | } 219 | 220 | if (icon.value) return; 221 | 222 | let width = 0, 223 | height = 0; 224 | 225 | children.value.forEach((child: any) => { 226 | child.outerScale = normalizedScale.value; 227 | 228 | width = Math.max(width, child.width); 229 | height = Math.max(height, child.height); 230 | }); 231 | 232 | childrenState.width = width; 233 | childrenState.height = height; 234 | 235 | children.value.forEach((child: any) => { 236 | child.x = (width - child.width) / 2; 237 | child.y = (height - child.height) / 2; 238 | }); 239 | }; 240 | 241 | onMounted(() => { 242 | updateStack(); 243 | }); 244 | 245 | onUpdated(() => { 246 | updateStack(); 247 | }); 248 | 249 | return { 250 | ...toRefs(state), 251 | children, 252 | icon, 253 | klass, 254 | style, 255 | width, 256 | height, 257 | box, 258 | attribs, 259 | raw 260 | }; 261 | }, 262 | 263 | created() { 264 | const parent = this.$parent as any; 265 | if (parent && parent.children) parent.children.push(this); 266 | }, 267 | 268 | render() { 269 | const attrs = Object.assign( 270 | { 271 | role: this.$attrs.role || (this.label || this.title ? "img" : null), 272 | "aria-label": this.label || null, 273 | "aria-hidden": !(this.label || this.title), 274 | width: this.width, 275 | height: this.height, 276 | viewBox: this.box 277 | }, 278 | this.attribs 279 | ) as any; 280 | 281 | if ((this.attribs as ObjType).stroke) 282 | attrs.stroke = this.fill ? this.fill : "currentColor"; 283 | else attrs.fill = this.fill ? this.fill : "currentColor"; 284 | 285 | if (this.x) attrs.x = (this.x as number).toString(); 286 | if (this.y) attrs.y = (this.y as number).toString(); 287 | 288 | let options = { 289 | class: this.klass, 290 | style: this.style 291 | } as any; 292 | 293 | if (isVue2) { 294 | options.attrs = attrs; 295 | } else { 296 | options = Object.assign(options, attrs); 297 | } 298 | 299 | if (this.raw) { 300 | const html = this.title 301 | ? `${utils.escapeHTML(this.title)}${this.raw}` 302 | : this.raw; 303 | 304 | if (isVue2) { 305 | options.domProps = { innerHTML: html }; 306 | } else { 307 | options.innerHTML = html; 308 | } 309 | } 310 | 311 | const content = this.title 312 | ? [h("title", this.title as string)] 313 | : ([] as any[]); 314 | 315 | const svgAttrs = (name: string, value: ObjType, i: number) => { 316 | if (isVue2) { 317 | return h(name, { 318 | attrs: value, 319 | key: `${name}-${i}` 320 | }); 321 | } else { 322 | return h(name, { 323 | ...value, 324 | key: `${name}-${i}` 325 | }); 326 | } 327 | }; 328 | 329 | return h( 330 | "svg", 331 | options, 332 | this.raw 333 | ? undefined 334 | : content.concat([ 335 | this.$slots.default 336 | ? isVue2 337 | ? this.$slots.default 338 | : // @ts-ignore: this.$slots.default() is only used in Vue3 339 | this.$slots.default() 340 | : this.icon 341 | ? [ 342 | ...((this.icon as CustomizeIconType).paths as ObjType[]).map( 343 | (path: ObjType, i: number) => svgAttrs("path", path, i) 344 | ), 345 | ...( 346 | (this.icon as CustomizeIconType).polygons as ObjType[] 347 | ).map((polygon: ObjType, i: number) => 348 | svgAttrs("polygon", polygon, i) 349 | ) 350 | ] 351 | : [] 352 | ]) 353 | ); 354 | } 355 | }); 356 | 357 | export { OhVueIcon, addIcons, listIcons }; 358 | -------------------------------------------------------------------------------- /package/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { CustomizeIconType } from "../types/icons"; 2 | 3 | export type { CustomizeIconType }; 4 | export * from "./components/Icon"; 5 | import "./styles"; 6 | -------------------------------------------------------------------------------- /package/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import App from "./App.vue"; 3 | import { OhVueIcon, addIcons } from "."; 4 | 5 | import { 6 | FaFlag, 7 | FcLinux, 8 | BiBattery, 9 | BiBatteryHalf, 10 | BiBatteryFull, 11 | FaCamera, 12 | FaBan, 13 | FaSquare, 14 | SiWechat, 15 | RiRefreshLine, 16 | FaSpinner, 17 | GiPiercingSword, 18 | FaRegularBell, 19 | RiHeartPulseLine, 20 | BiLightning, 21 | HiAcademicCap, 22 | RiSailboatLine 23 | } from "../icons"; 24 | 25 | addIcons( 26 | FaFlag, 27 | FcLinux, 28 | BiBattery, 29 | BiBatteryHalf, 30 | BiBatteryFull, 31 | FaCamera, 32 | FaBan, 33 | FaSquare, 34 | SiWechat, 35 | RiRefreshLine, 36 | FaSpinner, 37 | GiPiercingSword, 38 | FaRegularBell, 39 | RiHeartPulseLine, 40 | BiLightning, 41 | HiAcademicCap, 42 | RiSailboatLine 43 | ); 44 | 45 | addIcons({ 46 | name: "baidu", 47 | width: 23.868, 48 | height: 26, 49 | d: "M3.613 13.701c2.827-.608 2.442-3.986 2.357-4.725-.138-1.139-1.477-3.128-3.296-2.971C.386 6.21.052 9.515.052 9.515c-.309 1.528.74 4.793 3.561 4.186zm3.002 5.875c-.083.238-.268.846-.107 1.375.315 1.187 1.346 1.24 1.346 1.24h1.48v-3.619H7.749c-.713.213-1.057.767-1.134 1.004zM8.86 8.035c1.562 0 2.823-1.797 2.823-4.019C11.683 1.796 10.421 0 8.86 0 7.301 0 6.036 1.796 6.036 4.016c0 2.222 1.265 4.019 2.824 4.019zm6.724.265c2.087.271 3.429-1.956 3.695-3.644.272-1.686-1.074-3.644-2.552-3.98-1.48-.339-3.329 2.032-3.497 3.578-.2 1.89.271 3.778 2.354 4.046zm5.114 9.923s-3.229-2.498-5.113-5.198c-2.555-3.981-6.185-2.361-7.399-.337-1.209 2.024-3.093 3.305-3.36 3.644-.271.334-3.9 2.293-3.095 5.871.806 3.576 3.635 3.508 3.635 3.508s2.085.205 4.504-.336c2.42-.537 4.503.134 4.503.134s5.652 1.893 7.199-1.751c1.545-3.645-.874-5.535-.874-5.535zm-9.671 5.423H7.352c-1.587-.316-2.219-1.4-2.299-1.584-.078-.188-.528-1.059-.29-2.539.686-2.219 2.642-2.379 2.642-2.379h1.956V14.74l1.666.025v8.881zm6.844-.025h-4.229c-1.639-.423-1.716-1.587-1.716-1.587v-4.677l1.716-.027v4.203c.104.447.661.529.661.529h1.742v-4.705h1.825v6.264zm5.986-12.486c0-.808-.671-3.239-3.159-3.239-2.492 0-2.825 2.295-2.825 3.917 0 1.548.131 3.71 3.227 3.641 3.096-.068 2.757-3.507 2.757-4.319z" 50 | }); 51 | 52 | const app = createApp(App); 53 | app.component("VIcon", OhVueIcon); 54 | app.mount("#app"); 55 | -------------------------------------------------------------------------------- /package/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.vue" { 2 | import { DefineComponent } from "vue"; 3 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 4 | const component: DefineComponent<{}, {}, any>; 5 | export default component; 6 | } 7 | -------------------------------------------------------------------------------- /package/src/styles/animation.css: -------------------------------------------------------------------------------- 1 | /* ---------------- spin ---------------- */ 2 | .ov-spin:not(.ov-hover), 3 | .ov-spin.ov-hover:hover, 4 | .ov-parent.ov-hover:hover > .ov-spin { 5 | animation: ov-spin 1s linear infinite; 6 | } 7 | 8 | .ov-spin:not(.ov-hover).ov-fast, 9 | .ov-spin.ov-hover.ov-fast:hover, 10 | .ov-parent.ov-hover:hover > .ov-spin.ov-fast { 11 | animation: ov-spin 0.7s linear infinite; 12 | } 13 | 14 | .ov-spin:not(.ov-hover).ov-slow, 15 | .ov-spin.ov-hover.ov-slow:hover, 16 | .ov-parent.ov-hover:hover > .ov-spin.ov-slow { 17 | animation: ov-spin 2s linear infinite; 18 | } 19 | 20 | /* ---------------- spin-pulse ---------------- */ 21 | 22 | .ov-spin-pulse:not(.ov-hover), 23 | .ov-spin-pulse.ov-hover:hover, 24 | .ov-parent.ov-hover:hover > .ov-spin-pulse { 25 | animation: ov-spin 1s infinite steps(8); 26 | } 27 | 28 | .ov-spin-pulse:not(.ov-hover).ov-fast, 29 | .ov-spin-pulse.ov-hover.ov-fast:hover, 30 | .ov-parent.ov-hover:hover > .ov-spin-pulse.ov-fast { 31 | animation: ov-spin 0.7s infinite steps(8); 32 | } 33 | 34 | .ov-spin-pulse:not(.ov-hover).ov-slow, 35 | .ov-spin-pulse.ov-hover.ov-slow:hover, 36 | .ov-parent.ov-hover:hover > .ov-spin-pulse.ov-slow { 37 | animation: ov-spin 2s infinite steps(8); 38 | } 39 | 40 | @keyframes ov-spin { 41 | 0% { 42 | transform: rotate(0deg); 43 | } 44 | 100% { 45 | transform: rotate(360deg); 46 | } 47 | } 48 | 49 | /* ---------------- wrench ---------------- */ 50 | .ov-wrench:not(.ov-hover), 51 | .ov-wrench.ov-hover:hover, 52 | .ov-parent.ov-hover:hover > .ov-wrench { 53 | animation: ov-wrench 2.5s ease infinite; 54 | } 55 | 56 | .ov-wrench:not(.ov-hover).ov-fast, 57 | .ov-wrench.ov-hover.ov-fast:hover, 58 | .ov-parent.ov-hover:hover > .ov-wrench.ov-fast { 59 | animation: ov-wrench 1.2s ease infinite; 60 | } 61 | 62 | .ov-wrench:not(.ov-hover).ov-slow, 63 | .ov-wrench.ov-hover.ov-slow:hover, 64 | .ov-parent.ov-hover:hover > .ov-wrench.ov-slow { 65 | animation: ov-wrench 3.7s ease infinite; 66 | } 67 | 68 | @keyframes ov-wrench { 69 | 0% { 70 | transform: rotate(-12deg); 71 | } 72 | 73 | 8% { 74 | transform: rotate(12deg); 75 | } 76 | 77 | 10%, 28%, 30%, 48%, 50%, 68% { 78 | transform: rotate(24deg); 79 | } 80 | 81 | 18%, 20%, 38%, 40%, 58%, 60% { 82 | transform: rotate(-24deg); 83 | } 84 | 85 | 75%, 100% { 86 | transform: rotate(0deg); 87 | } 88 | } 89 | 90 | /* ---------------- ring ---------------- */ 91 | .ov-ring:not(.ov-hover), 92 | .ov-ring.ov-hover:hover, 93 | .ov-parent.ov-hover:hover > .ov-ring { 94 | animation: ov-ring 2s ease infinite; 95 | } 96 | 97 | .ov-ring:not(.ov-hover).ov-fast, 98 | .ov-ring.ov-hover.ov-fast:hover, 99 | .ov-parent.ov-hover:hover > .ov-ring.ov-fast { 100 | animation: ov-ring 1s ease infinite; 101 | } 102 | 103 | .ov-ring:not(.ov-hover).ov-slow, 104 | .ov-ring.ov-hover.ov-slow:hover, 105 | .ov-parent.ov-hover:hover > .ov-ring.ov-slow { 106 | animation: ov-ring 3s ease infinite; 107 | } 108 | 109 | @keyframes ov-ring { 110 | 0% { 111 | transform: rotate(-15deg); 112 | } 113 | 114 | 2% { 115 | transform: rotate(15deg); 116 | } 117 | 118 | 4%, 12% { 119 | transform: rotate(-18deg); 120 | } 121 | 122 | 6% { 123 | transform: rotate(18deg); 124 | } 125 | 126 | 8% { 127 | transform: rotate(-22deg); 128 | } 129 | 130 | 10% { 131 | transform: rotate(22deg); 132 | } 133 | 134 | 12% { 135 | transform: rotate(-18deg); 136 | } 137 | 138 | 14% { 139 | transform: rotate(18deg); 140 | } 141 | 142 | 16% { 143 | transform: rotate(-12deg); 144 | } 145 | 146 | 18% { 147 | transform: rotate(12deg); 148 | } 149 | 150 | 20%, 100% { 151 | transform: rotate(0deg); 152 | } 153 | } 154 | 155 | /* ---------------- pulse ---------------- */ 156 | .ov-pulse:not(.ov-hover), 157 | .ov-pulse.ov-hover:hover, 158 | .ov-parent.ov-hover:hover > .ov-pulse { 159 | animation: ov-pulse 2s linear infinite; 160 | } 161 | 162 | .ov-pulse:not(.ov-hover).ov-fast, 163 | .ov-pulse.ov-hover.ov-fast:hover, 164 | .ov-parent.ov-hover:hover > .ov-pulse.ov-fast { 165 | animation: ov-pulse 1s linear infinite; 166 | } 167 | 168 | .ov-pulse:not(.ov-hover).ov-slow, 169 | .ov-pulse.ov-hover.ov-slow:hover, 170 | .ov-parent.ov-hover:hover > .ov-pulse.ov-slow { 171 | animation: ov-pulse 3s linear infinite; 172 | } 173 | 174 | @keyframes ov-pulse { 175 | 0% { 176 | transform: scale(1.1); 177 | } 178 | 179 | 50% { 180 | transform: scale(0.8); 181 | } 182 | 183 | 100% { 184 | transform: scale(1.1); 185 | } 186 | } 187 | 188 | /* ---------------- flash ---------------- */ 189 | .ov-flash:not(.ov-hover), 190 | .ov-flash.ov-hover:hover, 191 | .ov-parent.ov-hover:hover > .ov-flash { 192 | animation: ov-flash 2s ease infinite; 193 | } 194 | 195 | .ov-flash:not(.ov-hover).ov-fast, 196 | .ov-flash.ov-hover.ov-fast:hover, 197 | .ov-parent.ov-hover:hover > .ov-flash.ov-fast { 198 | animation: ov-flash 1s ease infinite; 199 | } 200 | 201 | .ov-flash:not(.ov-hover).ov-slow, 202 | .ov-flash.ov-hover.ov-slow:hover, 203 | .ov-parent.ov-hover:hover > .ov-flash.ov-slow { 204 | animation: ov-flash 3s ease infinite; 205 | } 206 | 207 | @keyframes ov-flash { 208 | 0%, 100%, 50%{ 209 | opacity: 1; 210 | } 211 | 25%, 75%{ 212 | opacity: 0; 213 | } 214 | } 215 | 216 | /* ---------------- float ---------------- */ 217 | .ov-float:not(.ov-hover), 218 | .ov-float.ov-hover:hover, 219 | .ov-parent.ov-hover:hover > .ov-float { 220 | animation: ov-float 2s linear infinite; 221 | } 222 | 223 | .ov-float:not(.ov-hover).ov-fast, 224 | .ov-float.ov-hover.ov-fast:hover, 225 | .ov-parent.ov-hover:hover > .ov-float.ov-fast { 226 | animation: ov-float 1s linear infinite; 227 | } 228 | 229 | .ov-float:not(.ov-hover).ov-slow, 230 | .ov-float.ov-hover.ov-slow:hover, 231 | .ov-parent.ov-hover:hover > .ov-float.ov-slow { 232 | animation: ov-float 3s linear infinite; 233 | } 234 | 235 | @keyframes ov-float { 236 | 0%, 100% { 237 | transform: translateY(-3px); 238 | } 239 | 50% { 240 | transform: translateY(3px); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /package/src/styles/flip.css: -------------------------------------------------------------------------------- 1 | .ov-flip-horizontal { 2 | transform: scale(-1, 1); 3 | } 4 | 5 | .ov-flip-vertical { 6 | transform: scale(1, -1); 7 | } 8 | 9 | .ov-flip-both { 10 | transform: scale(-1, -1); 11 | } 12 | 13 | .ov-inverse { 14 | color: #fff; 15 | } 16 | -------------------------------------------------------------------------------- /package/src/styles/icon.css: -------------------------------------------------------------------------------- 1 | .ov-icon { 2 | display: inline-block; 3 | overflow: visible; 4 | vertical-align: -0.2em; 5 | } 6 | -------------------------------------------------------------------------------- /package/src/styles/index.ts: -------------------------------------------------------------------------------- 1 | import "./icon.css"; 2 | import "./animation.css"; 3 | import "./flip.css"; 4 | -------------------------------------------------------------------------------- /package/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | const ESCAPE_MAP: { [key: string]: string } = { 2 | "<": "<", 3 | ">": ">", 4 | '"': """, 5 | "'": "'", 6 | "&": "&" 7 | }; 8 | 9 | const escapeHTML = (html: string): string => { 10 | return html.replace(/[<>"&]/g, (c) => ESCAPE_MAP[c] || c); 11 | }; 12 | 13 | let id_count = 0; 14 | 15 | const getID = (prefix: string): string => { 16 | return prefix + id_count++; 17 | }; 18 | 19 | export default { 20 | escapeHTML, 21 | getID 22 | }; 23 | -------------------------------------------------------------------------------- /package/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /package/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "strict": true, 7 | "jsx": "preserve", 8 | "sourceMap": true, 9 | "resolveJsonModule": true, 10 | "esModuleInterop": true, 11 | "lib": ["esnext", "dom"], 12 | "baseUrl": "src", 13 | "paths": { 14 | "@/*": ["*"] 15 | } 16 | }, 17 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] 18 | } 19 | -------------------------------------------------------------------------------- /package/types/icons.d.ts: -------------------------------------------------------------------------------- 1 | export interface IconType { 2 | name: string; 3 | minX: number; 4 | minY: number; 5 | width: number; 6 | height: number; 7 | raw: string; 8 | attr?: ObjType; 9 | } 10 | 11 | export interface CustomizeIconType { 12 | name: string; 13 | width: number; 14 | height: number; 15 | minX?: number; 16 | minY?: number; 17 | raw?: string; 18 | attr?: ObjType; 19 | points?: string; 20 | polygons?: ObjType[]; 21 | d?: string; 22 | paths?: ObjType[]; 23 | } 24 | 25 | export interface ObjType { 26 | [key: string]: string; 27 | } 28 | -------------------------------------------------------------------------------- /package/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import vue from "@vitejs/plugin-vue"; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()], 7 | build: { 8 | outDir: "demo_dist" 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /scripts/build.js: -------------------------------------------------------------------------------- 1 | const performance = require("perf_hooks").performance; 2 | const path = require("path"); 3 | const { icons } = require("../iconpacks"); 4 | const task = require("./tasks"); 5 | 6 | async function runTask(name, fn) { 7 | const start = performance.now(); 8 | console.log(`----------------- ${name} -----------------`); 9 | await fn(); 10 | const end = performance.now(); 11 | console.log(`${name}: `, Math.floor(end - start) / 1000, "sec\n\n"); 12 | } 13 | 14 | async function main() { 15 | try { 16 | const DIST = path.resolve(__dirname, "../package/icons"); 17 | const ASSETS = path.resolve(__dirname, "../assets"); 18 | 19 | await runTask("Initialize", async () => { 20 | await task.dirInit(DIST, ASSETS); 21 | }); 22 | await runTask("Write icons", async () => { 23 | for (const icon of icons) { 24 | await task.writeIconModule(icon, DIST, ASSETS); 25 | } 26 | }); 27 | console.log("done"); 28 | } catch (e) { 29 | console.error(e); 30 | process.exit(1); 31 | } 32 | } 33 | 34 | main(); 35 | -------------------------------------------------------------------------------- /scripts/download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ICONPATH="./iconpacks" 4 | ICONJSON="${ICONPATH}/index.js" 5 | 6 | # -------------------------------------------------------------------- 7 | # Handle force download (-f) option 8 | # -------------------------------------------------------------------- 9 | 10 | while getopts "f" arg 11 | do 12 | case $arg in 13 | f) 14 | echo "Force downloading all iconpacks..." 15 | # delete all exist iconpacks 16 | find $ICONPATH ! -name 'index.js' -depth 1 -exec rm -r {} + 17 | ;; 18 | ?) 19 | exit 1 20 | ;; 21 | esac 22 | done 23 | 24 | 25 | # -------------------------------------------------------------------- 26 | # Extract download URLs and file names from $ICONJSON 27 | # -------------------------------------------------------------------- 28 | 29 | declare -a urlList=() 30 | declare -a fileNameList=() 31 | 32 | while read line 33 | do 34 | # Extract download URL 35 | result=$(echo $line | sed 's/downloadURL: "\(.*\)",/\1/g') 36 | 37 | if [ "$result" != "$line" ] 38 | then 39 | urlList[${#urlList[@]}]=$result 40 | fi 41 | 42 | # Extract download file name 43 | result=$(echo $line | sed 's/downloadFileName: "\(.*\)",/\1/g') 44 | 45 | if [ "$result" != "$line" ] 46 | then 47 | fileNameList[${#fileNameList[@]}]=$result 48 | fi 49 | done < $ICONJSON 50 | 51 | 52 | # -------------------------------------------------------------------- 53 | # Download iconpacks from Github 54 | 55 | # This could be done via "git submodule". However, too many submodules 56 | # brings git too much loads and reduces its speed. So here I download 57 | # iconpacks' zip files from their Github repos directly. 58 | # -------------------------------------------------------------------- 59 | 60 | download() { 61 | url=$1 62 | filePath="${ICONPATH}/$2.zip" 63 | folderPath="${ICONPATH}/$2" 64 | 65 | if [ ! -d "$folderPath" ]; then 66 | if [ ! -f "$filePath" ]; then 67 | echo "Downloading ${url} to ${filePath}" 68 | wget -O $filePath $url 69 | fi 70 | 71 | echo "Extracting ${filePath} to ${folderPath}" 72 | 73 | if [ "$2" == "gameicons" ] # hard code for gameicons 74 | then 75 | oldFolferName="icons" 76 | else 77 | oldFolferName=$(unzip -Z -1 ${filePath} | head -1) 78 | fi 79 | 80 | unzip -qq $filePath -d $ICONPATH 81 | mv "${ICONPATH}/${oldFolferName}" $folderPath 82 | fi 83 | } 84 | 85 | for (( i = 0; i < ${#urlList[@]}; i++ )) do 86 | download ${urlList[i]} ${fileNameList[i]} 87 | done 88 | -------------------------------------------------------------------------------- /scripts/release.sh: -------------------------------------------------------------------------------- 1 | # download iconpacks 2 | yarn download -f 3 | 4 | # generate icon files 5 | yarn icons 6 | 7 | # build lib 8 | yarn build 9 | 10 | # publish to npm 11 | cd package 12 | npm publish 13 | -------------------------------------------------------------------------------- /scripts/svgo.js: -------------------------------------------------------------------------------- 1 | const SVGO = require("svgo"); 2 | 3 | const svgo = new SVGO({ 4 | plugins: [ 5 | { 6 | cleanupAttrs: true 7 | }, 8 | { 9 | removeDoctype: true 10 | }, 11 | { 12 | removeXMLProcInst: true 13 | }, 14 | { 15 | removeXMLNS: true 16 | }, 17 | { 18 | removeComments: true 19 | }, 20 | { 21 | removeMetadata: true 22 | }, 23 | { 24 | removeTitle: true 25 | }, 26 | { 27 | removeDesc: true 28 | }, 29 | { 30 | removeUselessDefs: true 31 | }, 32 | { 33 | removeEditorsNSData: true 34 | }, 35 | { 36 | removeEmptyAttrs: true 37 | }, 38 | { 39 | removeHiddenElems: true 40 | }, 41 | { 42 | removeEmptyText: true 43 | }, 44 | { 45 | removeEmptyContainers: true 46 | }, 47 | { 48 | removeViewBox: false 49 | }, 50 | { 51 | cleanupEnableBackground: true 52 | }, 53 | { 54 | convertStyleToAttrs: true 55 | }, 56 | { 57 | convertColors: true 58 | }, 59 | { 60 | convertPathData: true 61 | }, 62 | { 63 | convertTransform: true 64 | }, 65 | { 66 | removeUnknownsAndDefaults: true 67 | }, 68 | { 69 | removeNonInheritableGroupAttrs: true 70 | }, 71 | { 72 | removeUselessStrokeAndFill: true 73 | }, 74 | { 75 | removeUnusedNS: true 76 | }, 77 | { 78 | cleanupIDs: true 79 | }, 80 | { 81 | cleanupNumericValues: true 82 | }, 83 | { 84 | moveElemsAttrsToGroup: true 85 | }, 86 | { 87 | moveGroupAttrsToElems: true 88 | }, 89 | { 90 | collapseGroups: true 91 | }, 92 | { 93 | removeRasterImages: false 94 | }, 95 | { 96 | mergePaths: true 97 | }, 98 | { 99 | convertShapeToPath: true 100 | }, 101 | { 102 | sortAttrs: true 103 | }, 104 | { 105 | removeDimensions: true 106 | }, 107 | { 108 | removeAttrs: { 109 | elemSeparator: "^", 110 | attrs: [ 111 | "data.*", 112 | "version", 113 | "svg^aria-label", 114 | "svg^class", 115 | "xmlns:xlink" 116 | ] 117 | } 118 | }, 119 | { 120 | removeOffCanvasPaths: true 121 | } 122 | ] 123 | }); 124 | 125 | module.exports = svgo; 126 | -------------------------------------------------------------------------------- /scripts/tasks.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const fs = require("fs").promises; 3 | const camelcase = require("camelcase"); 4 | const rimraf = require("rimraf"); 5 | 6 | const svgo = require("./svgo"); 7 | const { icons } = require("../iconpacks"); 8 | const { getIconFiles, convertSVG /* writeSVG */ } = require("./utils"); 9 | const { 10 | autoGenerateTemplate, 11 | packageJsonTemplate, 12 | iconDataTemplate, 13 | tsDefTemplate, 14 | tsDefImportTemplate 15 | } = require("./templates"); 16 | 17 | const ignore = (err) => { 18 | if (err.code === "EEXIST") return; 19 | throw err; 20 | }; 21 | 22 | const excludes = ["fa-font-awesome-logo-full"]; 23 | 24 | async function dirInit(DIST, ASSETS) { 25 | rimraf.sync(DIST); 26 | await fs.mkdir(DIST, { recursive: true }).catch(ignore); 27 | 28 | // rimraf.sync(ASSETS); 29 | // await fs.mkdir(ASSETS, { recursive: true }).catch(ignore); 30 | 31 | const write = (filePath, str) => 32 | fs.writeFile(path.resolve(DIST, filePath), str, "utf8").catch(ignore); 33 | 34 | for (const icon of icons) { 35 | await fs.mkdir(path.resolve(DIST, icon.id)).catch(ignore); 36 | await write(`${icon.id}/index.js`, autoGenerateTemplate); 37 | await write(`${icon.id}/index.d.ts`, tsDefImportTemplate); 38 | await write(`${icon.id}/package.json`, packageJsonTemplate); 39 | } 40 | 41 | await write("index.js", autoGenerateTemplate); 42 | await write("index.d.ts", autoGenerateTemplate); 43 | } 44 | 45 | async function writeIconModule(icon, DIST, ASSETS) { 46 | const entryModule = `export * from "./${icon.id}";\n`; 47 | await fs.appendFile(path.resolve(DIST, "index.js"), entryModule, "utf8"); 48 | await fs.appendFile(path.resolve(DIST, "index.d.ts"), entryModule, "utf8"); 49 | 50 | // const svgDir = path.resolve(ASSETS, `${icon.id}`); 51 | // rimraf.sync(svgDir); 52 | // await fs.mkdir(svgDir, { recursive: true }).catch(ignore); 53 | 54 | const exists = new Set(); // for removing duplicate 55 | var iconNum = 0; 56 | 57 | for (const content of icon.contents) { 58 | const files = await getIconFiles(content); 59 | for (const file of files) { 60 | const svgStrRaw = await fs.readFile(file, "utf8"); 61 | const svgStr = await svgo 62 | .optimize(svgStrRaw) 63 | .then((result) => result.data); 64 | 65 | const name = 66 | (content.nameFromPath && content.nameFromPath(file)) || 67 | path 68 | .basename(file, path.extname(file)) 69 | .replace(/_/g, "-") 70 | .replace(/\$/g, ""); 71 | 72 | const rawName = (content.raw && content.raw(name)) || name; 73 | const prefixName = (content.prefix && content.prefix(rawName)) || rawName; 74 | const prefix = prefixName.replace(`-${rawName}`, ""); 75 | 76 | if (excludes.includes(prefixName)) continue; 77 | 78 | const pascalName = camelcase(rawName, { pascalCase: true }); 79 | const prefixPascalName = 80 | (content.formatter && content.formatter(pascalName)) || pascalName; 81 | if (exists.has(prefixPascalName)) continue; // remove duplicate 82 | exists.add(prefixPascalName); 83 | 84 | const iconData = await convertSVG( 85 | content.scale, 86 | prefixName, 87 | prefix, 88 | svgStr 89 | ); 90 | 91 | await fs.appendFile( 92 | path.resolve(DIST, `${icon.id}/index.js`), 93 | iconDataTemplate(prefixPascalName, iconData), 94 | "utf8" 95 | ); 96 | 97 | await fs.appendFile( 98 | path.resolve(DIST, `${icon.id}/index.d.ts`), 99 | tsDefTemplate(prefixPascalName), 100 | "utf8" 101 | ); 102 | 103 | // await writeSVG(svgDir, iconData); 104 | 105 | exists.add(file); 106 | } 107 | iconNum += files.length; 108 | } 109 | 110 | console.log(`- ${iconNum} icons from ${icon.name} done`); 111 | } 112 | 113 | module.exports = { 114 | dirInit, 115 | writeIconModule 116 | }; 117 | -------------------------------------------------------------------------------- /scripts/templates.js: -------------------------------------------------------------------------------- 1 | const autoGenerateTemplate = "// THIS FILE IS AUTO GENERATED\n"; 2 | 3 | const packageJsonTemplate = 4 | JSON.stringify( 5 | { 6 | sideEffects: false, 7 | module: "./index.js" 8 | }, 9 | null, 10 | 2 11 | ) + "\n"; 12 | 13 | const tsDefImportTemplate = `${autoGenerateTemplate}import { IconType } from "../../types/icons";\n`; 14 | 15 | const tsDefTemplate = (name) => { 16 | return `export declare const ${name}: IconType;\n`; 17 | }; 18 | 19 | const iconDataTemplate = (name, data) => { 20 | return `export const ${name} = ${JSON.stringify(data)};\n`; 21 | }; 22 | 23 | module.exports = { 24 | autoGenerateTemplate, 25 | packageJsonTemplate, 26 | iconDataTemplate, 27 | tsDefTemplate, 28 | tsDefImportTemplate 29 | }; 30 | -------------------------------------------------------------------------------- /scripts/update.sh: -------------------------------------------------------------------------------- 1 | for dir in ./iconpacks/* 2 | do 3 | if [ -d $dir ] && [ ! $dir = "./iconpacks/gameicons" ] 4 | then 5 | echo Updating $dir ... 6 | 7 | if [ $dir = "./iconpacks/bootstrap-icons" ] || [ $dir = "./iconpacks/octicons" ] 8 | then 9 | (cd $dir && git pull origin main) 10 | else 11 | (cd $dir && git pull origin master) 12 | fi 13 | fi 14 | done 15 | -------------------------------------------------------------------------------- /scripts/utils.js: -------------------------------------------------------------------------------- 1 | const glob = require("glob-promise"); 2 | const path = require("path"); 3 | const fs = require("fs").promises; 4 | const cheerio = require("cheerio"); 5 | 6 | const attrToString = (attr) => { 7 | let str = ""; 8 | for (let key in attr) str += ` ${key}="${attr[key]}"`; 9 | return str; 10 | }; 11 | 12 | const fillAttrWhiteList = ["hi"]; 13 | 14 | const cleanAttr = (attr, prefix) => { 15 | if (attr.fill && !fillAttrWhiteList.includes(prefix)) delete attr.fill; 16 | delete attr.viewBox; 17 | return attr; 18 | }; 19 | 20 | async function getIconFiles(content) { 21 | let files = await glob(content.files); 22 | files = files.sort(function (a, b) { 23 | const namea = a.substr(a.lastIndexOf("/") + 1), 24 | nameb = b.substr(b.lastIndexOf("/") + 1); 25 | return namea.localeCompare(nameb); 26 | }); 27 | return files; 28 | } 29 | 30 | async function convertSVG(scale, name, prefix, svg) { 31 | const $ = cheerio.load(svg, { 32 | xmlMode: true, 33 | xml: { 34 | normalizeWhitespace: true 35 | } 36 | }); 37 | 38 | let attr = $("svg")[0].attribs; 39 | 40 | const viewbox = attr["viewBox"].split(" "); 41 | const initW = Number(viewbox[2]), 42 | initH = Number(viewbox[3]); 43 | attr = cleanAttr(attr, prefix); 44 | 45 | if (!scale) scale = 1; 46 | const width = Number( 47 | (initW > initH ? initW * scale : initH * scale).toFixed(3) 48 | ); 49 | const height = Number( 50 | (initW > initH ? initW * scale : initH * scale).toFixed(3) 51 | ); 52 | 53 | const minX = Number((-(width - initW) / 2).toFixed(3)); 54 | const minY = Number((-(height - initH) / 2).toFixed(3)); 55 | 56 | const raw = svg.match(/(.*?)<\/svg>/)[2]; 57 | 58 | const data = { 59 | name: name, 60 | minX: minX, 61 | minY: minY, 62 | width: width, 63 | height: height, 64 | raw: raw 65 | }; 66 | if (JSON.stringify(attr) !== "{}") data.attr = attr; 67 | return data; 68 | } 69 | 70 | async function writeSVG(dir, icon) { 71 | const filePath = path.resolve(dir, `${icon.name}.svg`); 72 | const attr = icon.attr ? attrToString(icon.attr) : ""; 73 | const svg = `${icon.raw}`; 74 | await fs.writeFile(filePath, svg); 75 | } 76 | 77 | module.exports = { 78 | getIconFiles, 79 | convertSVG, 80 | writeSVG 81 | }; 82 | --------------------------------------------------------------------------------