mirror of
https://github.com/feathericons/feather.git
synced 2023-08-10 21:13:24 +03:00
Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
dc3c0cc47e | |||
d5ba74d93b | |||
c978b1cb4e | |||
bd129d9dcf | |||
90133ea33e | |||
1a210808c5 | |||
400f34afc2 | |||
1da9dd43b2 | |||
6e7693e6da | |||
32810336ec | |||
e374f72cb6 | |||
28e74c6e2b | |||
3183ae1ef6 | |||
703b1a7882 | |||
9dffc53b3a | |||
741ac5632c | |||
ad3c8a94d0 | |||
76f29d8565 | |||
23b17b9c55 | |||
1d3283d81d | |||
5031cacbdd | |||
894dcfd6a6 | |||
765985a5e3 | |||
87f272275a | |||
17fb9c99a9 | |||
9167bfc36d | |||
fb0ae8054e | |||
d2369242f1 | |||
d33cb6ecf9 | |||
b22f3b4515 | |||
94531bbe7c | |||
a3527829b8 | |||
e697b3a927 | |||
920bd45776 | |||
cbd3c6184b |
13
.babelrc
13
.babelrc
@ -1,4 +1,13 @@
|
||||
{
|
||||
"presets": ["es2015"],
|
||||
"plugins": ["transform-object-rest-spread"]
|
||||
"presets": [
|
||||
[
|
||||
"env",
|
||||
{
|
||||
"targets": {
|
||||
"browsers": ["last 2 versions"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"stage-2"
|
||||
]
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
dist
|
||||
dist
|
||||
coverage
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ node_modules
|
||||
dist
|
||||
sandbox
|
||||
stash
|
||||
coverage
|
@ -8,7 +8,10 @@ node_js: 8
|
||||
before_script:
|
||||
- npm prune
|
||||
script:
|
||||
- npm start
|
||||
- npm run all
|
||||
after_success:
|
||||
- npx codecov
|
||||
- npx babel-node ./bin/sync-algolia.js
|
||||
deploy:
|
||||
provider: script
|
||||
skip_cleanup: true
|
||||
|
61
README.md
61
README.md
@ -1,9 +1,11 @@
|
||||
# Feather
|
||||
|
||||
[](https://travis-ci.org/feathericons/feather)
|
||||
[](https://npm-stat.com/charts.html?package=feather-icons&from=2017-06-01)
|
||||
[](https://travis-ci.org/feathericons/feather)
|
||||
[](https://codecov.io/gh/feathericons/feather)
|
||||
[](https://www.npmjs.com/package/feather-icons)
|
||||
[](https://www.npmjs.com/package/feather-icons)
|
||||
[](https://cdnjs.com/libraries/feather-icons)
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=G6CPFZ6PQRZW8&lc=US&item_name=Feather&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted)
|
||||
|
||||
## What is Feather?
|
||||
|
||||
@ -25,7 +27,7 @@ npm install feather-icons
|
||||
|
||||
* [Quick Start](#quick-start)
|
||||
* [Usage](#usage)
|
||||
* [Client-side](#client-side)
|
||||
* [Client-side JavaScript](#client-side-javascript)
|
||||
* [Node](#node)
|
||||
* [SVG Sprite](#svg-sprite)
|
||||
* [API Reference](#api-reference)
|
||||
@ -67,7 +69,7 @@ At its core, Feather is a collection of [SVG](https://svgontheweb.com/#svg) file
|
||||
|
||||
The following are additional ways you can use Feather.
|
||||
|
||||
### Client-side
|
||||
### Client-side JavaScript
|
||||
|
||||
#### 1. Install
|
||||
|
||||
@ -168,40 +170,58 @@ feather.icons.x.toSvg({ class: 'foo bar', 'stroke-width': 1, color: 'red' })
|
||||
See the [API Reference](#api-reference) for more information about the available properties and methods of the `feather` object.
|
||||
|
||||
### SVG Sprite
|
||||
A SVG Sprite is also provided, which can be used as following:
|
||||
|
||||
#### 1. Install
|
||||
|
||||
> **Note:** If you intend to use Feather with a CDN, you can skip this installation step.
|
||||
|
||||
Install with [npm](https://docs.npmjs.com/getting-started/what-is-npm).
|
||||
|
||||
```
|
||||
npm install feather-icons --save
|
||||
```
|
||||
|
||||
Or just copy [`feather-sprite.svg`](https://unpkg.com/feather-icons/dist/feather-sprite.svg) into your project directory.
|
||||
|
||||
#### 2. Use
|
||||
|
||||
In your HTML, you can include an icon like so:
|
||||
|
||||
```html
|
||||
<svg class="feather feather-[iconName]"
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<use xlink:href="feather-sprite.svg#[iconName]"/>
|
||||
<use xlink:href="path/to/feather-sprite.svg#circle"/>
|
||||
</svg>
|
||||
```
|
||||
Where `iconName` is the name of the icon you want to display.
|
||||
|
||||
Same result but using a CSS class:
|
||||
> **Note:** `circle` in the above example can be replaced with any valid icon name. See the complete list of icon names at [feathericons.com](https://feathericons.com).
|
||||
|
||||
However, this markup can be simplified using a simple CSS class to avoid repetition of SVG attributes between icons.
|
||||
|
||||
```css
|
||||
.feather {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: currentColor;
|
||||
stroke-width: 2;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
stroke: currentColor;
|
||||
stroke-width: 2;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
fill: none;
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<svg class="feather feather-[iconName]">
|
||||
<use xlink:href="feather-sprite.svg#[iconName]"/>
|
||||
<svg class="feather">
|
||||
<use xlink:href="path/to/dist/feather-sprite.svg#circle"/>
|
||||
</svg>
|
||||
```
|
||||
Prefer using CSS classes to keep things organized.
|
||||
|
||||
## API Reference
|
||||
|
||||
@ -235,6 +255,8 @@ feather.icons.x.toString()
|
||||
// '<line ... /><line ... />'
|
||||
```
|
||||
|
||||
> **Note:** `x` in the above example can be replaced with any valid icon name. See the complete list of icon names at [feathericons.com](https://feathericons.com). Icons with multi-word names (e.g. `arrow-right`) **cannot** be accessed using dot notation (e.g. `feather.icons.x`). Instead, use bracket notation (e.g. `feather.icons['arrow-right']`).
|
||||
|
||||
[View Source](https://github.com/colebemis/feather/blob/master/src/icons.js)
|
||||
|
||||
---
|
||||
@ -355,7 +377,6 @@ feather.toSvg('circle', { class: 'foo bar' })
|
||||
## Roadmap
|
||||
|
||||
- [ ] Write icon design guidelines
|
||||
- [ ] Track code coverage
|
||||
- [ ] Improve SVG accessibility
|
||||
- [ ] Handle usage of custom icons
|
||||
- [ ] Add usage examples
|
||||
|
6
bin/.eslintrc.json
Normal file
6
bin/.eslintrc.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"rules": {
|
||||
"import/no-extraneous-dependencies": "off",
|
||||
"no-console": "off"
|
||||
}
|
||||
}
|
@ -1,14 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`builds sprite correctly 1`] = `
|
||||
"<svg xmlns=\\"http://www.w3.org/2000/svg\\">
|
||||
<defs>
|
||||
<symbol id=\\"icon1\\" viewBox=\\"0 0 24 24\\">
|
||||
<line x1=\\"23\\" y1=\\"1\\" x2=\\"1\\" y2=\\"23\\"></line><line x1=\\"1\\" y1=\\"1\\" x2=\\"23\\" y2=\\"23\\"></line>
|
||||
</symbol>
|
||||
<symbol id=\\"icon2\\" viewBox=\\"0 0 24 24\\">
|
||||
<circle cx=\\"12\\" cy=\\"12\\" r=\\"11\\"></circle>
|
||||
</symbol>
|
||||
</defs>
|
||||
</svg>"
|
||||
`;
|
||||
exports[`builds sprite correctly 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\"><defs><symbol id=\\"icon1\\" viewBox=\\"0 0 24 24\\"><line x1=\\"23\\" y1=\\"1\\" x2=\\"1\\" y2=\\"23\\"></line><line x1=\\"1\\" y1=\\"1\\" x2=\\"23\\" y2=\\"23\\"></line></symbol><symbol id=\\"icon2\\" viewBox=\\"0 0 24 24\\"><circle cx=\\"12\\" cy=\\"12\\" r=\\"11\\"></circle></symbol></defs></svg>"`;
|
||||
|
@ -6,7 +6,7 @@ import buildIconsObject from './build-icons-object';
|
||||
const IN_DIR = path.resolve(__dirname, '../icons');
|
||||
const OUT_FILE = path.resolve(__dirname, '../dist/icons.json');
|
||||
|
||||
console.log(`Building ${OUT_FILE}`); // eslint-disable-line no-console
|
||||
console.log(`Building ${OUT_FILE}...`);
|
||||
|
||||
const svgFiles = fs
|
||||
.readdirSync(IN_DIR)
|
||||
|
@ -1,12 +1,11 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import path from 'path';
|
||||
import cheerio from 'cheerio';
|
||||
import { minify } from 'html-minifier';
|
||||
|
||||
/**
|
||||
* Build an object in the format: `{ <name>: <contents> }`.
|
||||
* @param {string[]} svgFiles - A list of file names.
|
||||
* @param {Function} getSvg - A function that returns the contents of an SVG file.
|
||||
* @param {string[]} svgFiles - A list of filenames.
|
||||
* @param {Function} getSvg - A function that returns the contents of an SVG file given a filename.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function buildIconsObject(svgFiles, getSvg) {
|
||||
@ -26,6 +25,7 @@ function buildIconsObject(svgFiles, getSvg) {
|
||||
/**
|
||||
* Get contents between opening and closing `<svg>` tags.
|
||||
* @param {string} svg
|
||||
* @returns {string}
|
||||
*/
|
||||
function getSvgContents(svg) {
|
||||
const $ = cheerio.load(svg);
|
||||
|
@ -1,30 +1,28 @@
|
||||
import defaultAttrs from '../src/default-attrs.json';
|
||||
|
||||
const svgStartTag = `<svg xmlns="${defaultAttrs.xmlns}">\n<defs>\n`;
|
||||
const svgEndTag = '</defs>\n</svg>';
|
||||
import DEFAULT_ATTRS from '../src/default-attrs.json';
|
||||
|
||||
/**
|
||||
* Renders the inner sprites as SVG Symbols
|
||||
* @param {object} icons the icons object
|
||||
* @returns {string} the rendered string with SVG symbols
|
||||
* Build an SVG sprite string containing SVG symbols.
|
||||
* @param {Object} icons
|
||||
* @returns {string}
|
||||
*/
|
||||
function buildSpriteString(icons) {
|
||||
const symbols = Object.keys(icons)
|
||||
.map(icon => toSvgSymbol(icon, icons[icon]))
|
||||
.join('');
|
||||
|
||||
return svgStartTag + symbols + svgEndTag;
|
||||
return `<svg xmlns="${DEFAULT_ATTRS.xmlns}"><defs>${symbols}</defs></svg>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a SVG symbol tag
|
||||
* @param {string} name The name of the icon
|
||||
* @param {string} contents The contents of the icon
|
||||
* @returns {string} the rendered SVG symbol
|
||||
* Create an SVG symbol string.
|
||||
* @param {string} name - Icon name
|
||||
* @param {string} contents - SVG contents
|
||||
* @returns {string}
|
||||
*/
|
||||
function toSvgSymbol(name, contents) {
|
||||
return `<symbol id="${name}" viewBox="${defaultAttrs.viewBox}">
|
||||
${contents}\n</symbol>\n`;
|
||||
return `<symbol id="${name}" viewBox="${DEFAULT_ATTRS.viewBox}">${
|
||||
contents
|
||||
}</symbol>`;
|
||||
}
|
||||
|
||||
export default buildSpriteString;
|
||||
|
@ -3,12 +3,8 @@ import path from 'path';
|
||||
import icons from '../dist/icons.json';
|
||||
import buildSpriteString from './build-sprite-string';
|
||||
|
||||
const sprite = buildSpriteString(icons);
|
||||
|
||||
const OUT_FILE = path.resolve(__dirname, '../dist/feather-sprite.svg');
|
||||
|
||||
console.log(`Building ${OUT_FILE}`); // eslint-disable-line no-console
|
||||
console.log(`Building ${OUT_FILE}...`);
|
||||
|
||||
fs.writeFile(OUT_FILE, sprite, err => {
|
||||
if (err) throw err;
|
||||
});
|
||||
fs.writeFileSync(OUT_FILE, buildSpriteString(icons));
|
||||
|
@ -4,7 +4,7 @@ import icons from '../src/icons';
|
||||
|
||||
const OUT_DIR = path.resolve(__dirname, '../dist/icons');
|
||||
|
||||
console.log(`Building SVGs in ${OUT_DIR}`); // eslint-disable-line no-console
|
||||
console.log(`Building SVGs in ${OUT_DIR}...`);
|
||||
|
||||
Object.keys(icons).forEach(name => {
|
||||
const svg = icons[name].toSvg();
|
||||
|
14
bin/build.sh
14
bin/build.sh
@ -1,15 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Process SVG files
|
||||
./node_modules/.bin/babel-node bin/process-svgs.js
|
||||
|
||||
# Create dist directory
|
||||
./node_modules/.bin/rimraf dist
|
||||
mkdir dist
|
||||
|
||||
# Build icons.json
|
||||
./node_modules/.bin/babel-node bin/build-icons-json.js
|
||||
|
||||
# Build SVG sprite
|
||||
./node_modules/.bin/babel-node bin/build-sprite.js
|
||||
|
||||
# Create dist/icons directory
|
||||
./node_modules/.bin/rimraf dist/icons
|
||||
mkdir dist/icons
|
||||
|
||||
# Build SVG icons
|
||||
./node_modules/.bin/babel-node bin/build-svgs.js
|
||||
|
||||
./node_modules/.bin/webpack --output-filename feather.js
|
||||
./node_modules/.bin/webpack --output-filename feather.min.js -p
|
||||
# Build JavaScript library
|
||||
./node_modules/.bin/webpack --output-filename feather.js --mode development
|
||||
./node_modules/.bin/webpack --output-filename feather.min.js --mode production
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import Svgo from 'svgo';
|
||||
import cheerio from 'cheerio';
|
||||
import { format } from 'prettier';
|
||||
|
@ -5,7 +5,7 @@ import processSvg from './process-svg';
|
||||
|
||||
const IN_DIR = path.resolve(__dirname, '../icons');
|
||||
|
||||
console.log(`Processing SVGs in ${IN_DIR}`); // eslint-disable-line no-console
|
||||
console.log(`Processing SVGs in ${IN_DIR}...`);
|
||||
|
||||
fs
|
||||
.readdirSync(IN_DIR)
|
||||
|
36
bin/sync-algolia.js
Normal file
36
bin/sync-algolia.js
Normal file
@ -0,0 +1,36 @@
|
||||
import algolia from 'algoliasearch';
|
||||
import icons from '../dist/icons.json';
|
||||
import tags from '../src/tags.json';
|
||||
|
||||
const ALGOLIA_APP_ID = '5EEOG744D0';
|
||||
|
||||
if (
|
||||
process.env.TRAVIS_PULL_REQUEST === 'false' &&
|
||||
process.env.TRAVIS_BRANCH === 'master'
|
||||
) {
|
||||
console.log('Syncing Algolia records...');
|
||||
syncAlgolia();
|
||||
} else {
|
||||
console.log('Skipped Algolia sync.');
|
||||
}
|
||||
|
||||
function syncAlgolia() {
|
||||
const client = algolia(ALGOLIA_APP_ID, process.env.ALGOLIA_ADMIN_KEY);
|
||||
|
||||
const index = client.initIndex('icons');
|
||||
|
||||
const records = Object.keys(icons).map(name => ({
|
||||
name,
|
||||
tags: tags[name] || [],
|
||||
}));
|
||||
|
||||
index.clearIndex((err, content) => {
|
||||
if (err) throw err;
|
||||
console.log(content);
|
||||
|
||||
index.addObjects(records, (err, content) => {
|
||||
if (err) throw err;
|
||||
console.log(content);
|
||||
});
|
||||
});
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
module.exports = {
|
||||
extends: ['@commitlint/config-angular'],
|
||||
extends: ['@commitlint/config-conventional'],
|
||||
rules: {
|
||||
'subject-case': 'sentence-case',
|
||||
'scope-case': [0],
|
||||
'subject-case': [2, 'always', 'sentence-case'],
|
||||
'header-max-length': [0],
|
||||
},
|
||||
};
|
||||
|
8842
package-lock.json
generated
8842
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@ -7,10 +7,11 @@
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "npm-run-all --sequential build lint test",
|
||||
"all": "npm-run-all --sequential build lint test:coverage",
|
||||
"build": "./bin/build.sh",
|
||||
"lint": "eslint .",
|
||||
"test": "jest",
|
||||
"test": "jest --watch",
|
||||
"test:coverage": "jest --coverage",
|
||||
"cm": "git-cz",
|
||||
"precommit": "lint-staged",
|
||||
"commitmsg": "commitlint --edit"
|
||||
@ -20,20 +21,25 @@
|
||||
"path": "cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"jest": {
|
||||
"collectCoverageFrom": [
|
||||
"src/**/*.js"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.5"
|
||||
"classnames": "^2.2.5",
|
||||
"core-js": "^2.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^5.2.5",
|
||||
"@commitlint/config-angular": "^5.1.1",
|
||||
"@commitlint/config-conventional": "^6.1.3",
|
||||
"algoliasearch": "^3.27.1",
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-register": "^6.24.1",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"babel-preset-stage-2": "^6.24.1",
|
||||
"cheerio": "^1.0.0-rc.2",
|
||||
"commitizen": "^2.9.6",
|
||||
"core-js": "^2.5.3",
|
||||
"cz-conventional-changelog": "^2.1.0",
|
||||
"eslint": "^4.15.0",
|
||||
"eslint-config-airbnb-base": "^12.1.0",
|
||||
@ -49,7 +55,8 @@
|
||||
"rimraf": "^2.6.2",
|
||||
"semantic-release": "^12.2.2",
|
||||
"svgo": "^0.7.2",
|
||||
"webpack": "^3.10.0"
|
||||
"webpack": "^4.8.3",
|
||||
"webpack-cli": "^2.1.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
3
src/__tests__/__snapshots__/replace.node.test.js.snap
Normal file
3
src/__tests__/__snapshots__/replace.node.test.js.snap
Normal file
@ -0,0 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`throws an error when run in node environment 1`] = `"\`feather.replace()\` only works in a browser environment."`;
|
@ -1,5 +1,5 @@
|
||||
/* eslint-env jest */
|
||||
import feather from '../..';
|
||||
import feather from '../index';
|
||||
|
||||
test('has correct properties', () => {
|
||||
expect(feather).toHaveProperty('icons');
|
||||
|
10
src/__tests__/replace.node.test.js
Normal file
10
src/__tests__/replace.node.test.js
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @jest-environment node
|
||||
*/
|
||||
|
||||
/* eslint-env jest */
|
||||
import replace from '../replace';
|
||||
|
||||
test('throws an error when run in node environment', () => {
|
||||
expect(replace).toThrowErrorMatchingSnapshot();
|
||||
});
|
@ -1,25 +0,0 @@
|
||||
import path from 'path';
|
||||
|
||||
export default {
|
||||
entry: [
|
||||
'core-js/fn/array/from',
|
||||
'core-js/fn/object/assign',
|
||||
'core-js/fn/set',
|
||||
path.resolve(__dirname, 'src/index.js'),
|
||||
],
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
libraryTarget: 'umd',
|
||||
library: 'feather',
|
||||
},
|
||||
devtool: 'source-map',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
23
webpack.config.js
Normal file
23
webpack.config.js
Normal file
@ -0,0 +1,23 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: ['core-js/fn/array/from', path.resolve(__dirname, 'src/index.js')],
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
libraryTarget: 'umd',
|
||||
library: 'feather',
|
||||
// Prevents webpack from referencing `window` in the UMD build
|
||||
// Source: https://git.io/vppgU
|
||||
globalObject: "typeof self !== 'undefined' ? self : this",
|
||||
},
|
||||
devtool: 'source-map',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
Reference in New Issue
Block a user