Add more theme stuff, add a smidge of content
This commit is contained in:
6
public/js/feather/bin/.eslintrc.json
Normal file
6
public/js/feather/bin/.eslintrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"rules": {
|
||||
"import/no-extraneous-dependencies": "off",
|
||||
"no-console": "off"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`builds object correctly 1`] = `
|
||||
Object {
|
||||
"icon1": "<line x1=\\"23\\" y1=\\"1\\" x2=\\"1\\" y2=\\"23\\"></line><line x1=\\"1\\" y1=\\"1\\" x2=\\"23\\" y2=\\"23\\"></line>",
|
||||
"icon2": "<circle cx=\\"12\\" cy=\\"12\\" r=\\"11\\"></circle>",
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +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>"`;
|
||||
@@ -0,0 +1,10 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`optimizes SVG correctly 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\"><line x1=\\"23\\" y1=\\"1\\" x2=\\"1\\" y2=\\"23\\"/><line x1=\\"1\\" y1=\\"1\\" x2=\\"23\\" y2=\\"23\\"/></svg>"`;
|
||||
|
||||
exports[`rejects when passed unparsable SVG string 1`] = `
|
||||
[Error: Error in parsing SVG: Unclosed root tag
|
||||
Line: 0
|
||||
Column: 10
|
||||
Char: ]
|
||||
`;
|
||||
17
public/js/feather/bin/__tests__/build-icons-object.test.js
Normal file
17
public/js/feather/bin/__tests__/build-icons-object.test.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/* eslint-env jest */
|
||||
import buildIconsObject from '../build-icons-object';
|
||||
|
||||
const SVG_FILES = {
|
||||
'icon1.svg':
|
||||
'<svg\n xmlns="http://www.w3.org/2000/svg"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n>\n <line x1="23" y1="1" x2="1" y2="23" />\n <line x1="1" y1="1" x2="23" y2="23" />\n</svg>',
|
||||
'icon2.svg':
|
||||
'<svg\n xmlns="http://www.w3.org/2000/svg"\n width="24"\n height="24"\n viewBox="0 0 24 24"\n>\n <circle cx="12" cy="12" r="11" />\n</svg>',
|
||||
};
|
||||
|
||||
function getSvg(svgFile) {
|
||||
return SVG_FILES[svgFile];
|
||||
}
|
||||
|
||||
test('builds object correctly', () => {
|
||||
expect(buildIconsObject(Object.keys(SVG_FILES), getSvg)).toMatchSnapshot();
|
||||
});
|
||||
12
public/js/feather/bin/__tests__/build-sprite-string.test.js
Normal file
12
public/js/feather/bin/__tests__/build-sprite-string.test.js
Normal file
@@ -0,0 +1,12 @@
|
||||
/* eslint-env jest */
|
||||
import buildSpriteString from '../build-sprite-string';
|
||||
|
||||
const icons = {
|
||||
icon1:
|
||||
'<line x1="23" y1="1" x2="1" y2="23"></line><line x1="1" y1="1" x2="23" y2="23"></line>',
|
||||
icon2: '<circle cx="12" cy="12" r="11"></circle>',
|
||||
};
|
||||
|
||||
test('builds sprite correctly', () => {
|
||||
expect(buildSpriteString(icons)).toMatchSnapshot();
|
||||
});
|
||||
15
public/js/feather/bin/__tests__/optimize-svg.test.js
Normal file
15
public/js/feather/bin/__tests__/optimize-svg.test.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-env jest */
|
||||
import optimizeSvg from '../optimize-svg';
|
||||
|
||||
test('optimizes SVG correctly', () => {
|
||||
const SVG =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>Title</title><line x1="23" y1="1" x2="1" y2="23" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><line x1="1" y1="1" x2="23" y2="23" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/></svg>';
|
||||
|
||||
expect(optimizeSvg(SVG)).resolves.toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('rejects when passed unparsable SVG string', () => {
|
||||
const UNPARSABLE_SVG = '<svg></svg';
|
||||
|
||||
expect(optimizeSvg(UNPARSABLE_SVG)).rejects.toMatchSnapshot();
|
||||
});
|
||||
19
public/js/feather/bin/build-icons-json.js
Normal file
19
public/js/feather/bin/build-icons-json.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
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}...`);
|
||||
|
||||
const svgFiles = fs
|
||||
.readdirSync(IN_DIR)
|
||||
.filter(file => path.extname(file) === '.svg');
|
||||
|
||||
const getSvg = svgFile => fs.readFileSync(path.join(IN_DIR, svgFile));
|
||||
|
||||
const icons = buildIconsObject(svgFiles, getSvg);
|
||||
|
||||
fs.writeFileSync(OUT_FILE, JSON.stringify(icons));
|
||||
35
public/js/feather/bin/build-icons-object.js
Normal file
35
public/js/feather/bin/build-icons-object.js
Normal file
@@ -0,0 +1,35 @@
|
||||
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 filenames.
|
||||
* @param {Function} getSvg - A function that returns the contents of an SVG file given a filename.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function buildIconsObject(svgFiles, getSvg) {
|
||||
return svgFiles
|
||||
.map(svgFile => {
|
||||
const name = path.basename(svgFile, '.svg');
|
||||
const svg = getSvg(svgFile);
|
||||
const contents = getSvgContents(svg);
|
||||
return { name, contents };
|
||||
})
|
||||
.reduce((icons, icon) => {
|
||||
icons[icon.name] = icon.contents;
|
||||
return icons;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get contents between opening and closing `<svg>` tags.
|
||||
* @param {string} svg
|
||||
* @returns {string}
|
||||
*/
|
||||
function getSvgContents(svg) {
|
||||
const $ = cheerio.load(svg);
|
||||
return minify($('svg').html(), { collapseWhitespace: true });
|
||||
}
|
||||
|
||||
export default buildIconsObject;
|
||||
26
public/js/feather/bin/build-sprite-string.js
Normal file
26
public/js/feather/bin/build-sprite-string.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import DEFAULT_ATTRS from '../src/default-attrs.json';
|
||||
|
||||
/**
|
||||
* 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 `<svg xmlns="${DEFAULT_ATTRS.xmlns}"><defs>${symbols}</defs></svg>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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="${DEFAULT_ATTRS.viewBox}">${contents}</symbol>`;
|
||||
}
|
||||
|
||||
export default buildSpriteString;
|
||||
10
public/js/feather/bin/build-sprite.js
Normal file
10
public/js/feather/bin/build-sprite.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import icons from '../dist/icons.json';
|
||||
import buildSpriteString from './build-sprite-string';
|
||||
|
||||
const OUT_FILE = path.resolve(__dirname, '../dist/feather-sprite.svg');
|
||||
|
||||
console.log(`Building ${OUT_FILE}...`);
|
||||
|
||||
fs.writeFileSync(OUT_FILE, buildSpriteString(icons));
|
||||
13
public/js/feather/bin/build-svgs.js
Normal file
13
public/js/feather/bin/build-svgs.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import icons from '../src/icons';
|
||||
|
||||
const OUT_DIR = path.resolve(__dirname, '../dist/icons');
|
||||
|
||||
console.log(`Building SVGs in ${OUT_DIR}...`);
|
||||
|
||||
Object.keys(icons).forEach(name => {
|
||||
const svg = icons[name].toSvg();
|
||||
|
||||
fs.writeFileSync(path.join(OUT_DIR, `${name}.svg`), svg);
|
||||
});
|
||||
22
public/js/feather/bin/build.sh
Executable file
22
public/js/feather/bin/build.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Create dist directory
|
||||
npx rimraf dist
|
||||
mkdir dist
|
||||
|
||||
# Build icons.json
|
||||
npx babel-node bin/build-icons-json.js
|
||||
|
||||
# Build SVG sprite
|
||||
npx babel-node bin/build-sprite.js
|
||||
|
||||
# Create dist/icons directory
|
||||
npx rimraf dist/icons
|
||||
mkdir dist/icons
|
||||
|
||||
# Build SVG icons
|
||||
npx babel-node bin/build-svgs.js
|
||||
|
||||
# Build JavaScript library
|
||||
npx webpack --output-filename feather.js --mode development
|
||||
npx webpack --output-filename feather.min.js --mode production
|
||||
50
public/js/feather/bin/optimize-svg.js
Normal file
50
public/js/feather/bin/optimize-svg.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import Svgo from 'svgo';
|
||||
import cheerio from 'cheerio';
|
||||
|
||||
import DEFAULT_ATTRS from '../src/default-attrs.json';
|
||||
|
||||
/**
|
||||
* Optimize SVG string.
|
||||
* @param {string} svg - An SVG string.
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
function optimizeSvg(svg) {
|
||||
return svgo(svg).then(setAttrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run SVGO on SVG string.
|
||||
* @param {string} svg - An SVG string.
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
function svgo(svg) {
|
||||
const s = new Svgo({
|
||||
plugins: [
|
||||
{ convertShapeToPath: false },
|
||||
{ mergePaths: false },
|
||||
{ removeAttrs: { attrs: '(fill|stroke.*)' } },
|
||||
{ removeTitle: true },
|
||||
],
|
||||
});
|
||||
|
||||
return new Promise(resolve => {
|
||||
s.optimize(svg, ({ data }) => resolve(data));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default attributes on SVG.
|
||||
* @param {string} svg - An SVG string.
|
||||
* @returns {string}
|
||||
*/
|
||||
function setAttrs(svg) {
|
||||
const $ = cheerio.load(svg);
|
||||
|
||||
Object.keys(DEFAULT_ATTRS).forEach(key =>
|
||||
$('svg').attr(key, DEFAULT_ATTRS[key]),
|
||||
);
|
||||
|
||||
return $('body').html();
|
||||
}
|
||||
|
||||
export default optimizeSvg;
|
||||
17
public/js/feather/bin/optimize-svgs.js
Normal file
17
public/js/feather/bin/optimize-svgs.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import optimizeSvg from './optimize-svg';
|
||||
|
||||
const IN_DIR = path.resolve(__dirname, '../icons');
|
||||
|
||||
console.log(`Optimizing SVGs in ${IN_DIR}...`);
|
||||
|
||||
fs.readdirSync(IN_DIR)
|
||||
.filter(file => path.extname(file) === '.svg')
|
||||
.forEach(svgFile => {
|
||||
const svg = fs.readFileSync(path.join(IN_DIR, svgFile));
|
||||
optimizeSvg(svg).then(svg =>
|
||||
fs.writeFileSync(path.join(IN_DIR, svgFile), svg),
|
||||
);
|
||||
});
|
||||
6
public/js/feather/bin/setup.sh
Executable file
6
public/js/feather/bin/setup.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
npm install --legacy-peer-deps
|
||||
npm run build
|
||||
npm run test:coverage
|
||||
npm run lint
|
||||
Reference in New Issue
Block a user