Skip to content

Instantly share code, notes, and snippets.

@yomotsu
Created June 22, 2018 19:40
Show Gist options
  • Save yomotsu/1e0d4e476db77b3c9d1621bca2daec1b to your computer and use it in GitHub Desktop.
Save yomotsu/1e0d4e476db77b3c9d1621bca2daec1b to your computer and use it in GitHub Desktop.
const path = require( 'path' );
// const fs = require( 'fs' );
const glob = require( 'glob' );
const webfontsGenerator = require( 'webfonts-generator' );
const FILE_NAME = 'icon';
const CLASS_NAME = 'Icon';
const SRC_DIR = 'src/icons';
const SCSS_DIST_DIR = 'src/scss/common';
const FONT_DIST_DIR = 'dist/assets/fonts';
const files = glob.sync( `${ SRC_DIR }/*.svg` );
const codepoints = {};
function getIconName( filename ) {
return path.basename( filename ).replace( /^u.+?-(.+)\.svg$/i, '$1' );
}
files.forEach( filename => {
const name = kebabToCamel( getIconName( filename ) );
const point = path
.basename( filename )
.split( '-' )[ 0 ]
.slice( 1 );
codepoints[ name ] = parseInt( `0x${ point }`, 16 );
} );
// function removeSvgIconfont( message ) {
// fs.unlink( `${ FONT_DIST_DIR }/Icon.svg`, error => {
// if ( error ) {
// console.log( error );
// return;
// }
// console.log( message );
// } );
// }
function done( error ) {
if ( error ) {
console.log( 'icon font build failed!', error );
} else {
// removeSvgIconfont( 'icon font build complete.' );
console.log( 'icon font build completed.' );
}
}
function kebabToCamel( string ) {
return string.replace( /-./g,
( letter ) => {
return letter.charAt( 1 ).toUpperCase();
}
);
}
const options = {
files,
dest: FONT_DIST_DIR,
fontName: FILE_NAME,
types: [ 'ttf', 'woff', 'woff2' ],
cssDest: `${ SCSS_DIST_DIR }/_icon-vars.scss`,
cssTemplate: `${ SRC_DIR }/_icon-vars.scss.hbs`,
templateOptions: {
fontName: FILE_NAME,
baseSelector: `.${ CLASS_NAME }`,
classPrefix: CLASS_NAME,
},
codepoints,
rename: function ( filename ) {
return kebabToCamel( getIconName( filename ) );
},
formatOptions: {
woff: {
clone: true,
},
},
};
webfontsGenerator( options, done );
const path = require( 'path' );
const webpack = require( 'webpack' );
const ExtractTextPlugin = require( 'extract-text-webpack-plugin' );
const VueLoaderPlugin = require( 'vue-loader/lib/plugin' );
const cssLoaders = [
{
loader: 'css-loader',
options: {
url: false,
minimize: true,
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => require( './postcss-plugins.js' ),
},
},
{
loader: 'sass-loader',
options: {
// importer: globImporter(),
includePaths: [],
},
},
];
module.exports = ( env, argv ) => {
const config = {
entry: {
'dist/assets/js/sanei.js': './src/js/index.js',
'dist/assets/css/sanei.css': './src/scss/index.scss',
},
output: {
path: path.resolve( __dirname, '../' ),
filename: '[name]',
},
module: {
rules: [
// this will apply to both plain `.js` files
// AND `<script>` blocks in `.vue` files
{
test: /\.js$/,
use: [ 'babel-loader' ],
exclude: /node_modules/,
},
{
test: /\.(css|scss)$/,
exclude: [
/node_modules/,
// ignore extracting <style> part in `.vue` files from vue-loader
( file ) => /\.vue/.test( file ),
],
use: ExtractTextPlugin.extract( {
use: cssLoaders,
} ),
},
{
test: /\.vue\.scss$/,
exclude: /node_modules/,
use: cssLoaders,
},
{
test: /\.vue$/,
loader: 'vue-loader',
exclude: [ /node_modules/ ],
options: {
esModule: true,
loaders: {
'scss': [
'vue-style-loader',
],
},
}
},
],
},
resolve: {
modules: [ 'node_modules' ],
extensions: [ '.js', '.scss' ],
},
devServer: {
host: '0.0.0.0',
port: 3000,
contentBase: path.resolve( __dirname, '../dist/' ),
publicPath: '/',
watchContentBase: true,
inline: true,
historyApiFallback: true,
noInfo: true,
},
performance: {
hints: false,
},
plugins: [
new ExtractTextPlugin( '[name]' ),
new VueLoaderPlugin(),
...(
argv.mode === 'production' ? [
new webpack.DefinePlugin( {
'process.env': {
NODE_ENV: '"production"'
}
} ),
new webpack.LoaderOptionsPlugin( {
minimize: true
} ),
] : [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
]
),
],
devtool: argv.mode === 'production' ? false : 'inline-source-map',
};
return config;
};
{
"private": true,
"scripts": {
"iconfont": "node ./build/iconfont.js",
"dev": "npm run iconfont && webpack-dev-server --mode development --config ./build/webpack.config.js --open",
"build": "npm run iconfont && webpack --mode production --config ./build/webpack.config.js"
},
"dependencies": {
"vue": "^2.5.16"
},
"browserslist": [
"ie >= 11",
"safari >= 9",
"ios >= 9",
"Android >= 4.4"
],
"devDependencies": {
"autoprefixer": "^8.6.3",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-3": "^6.24.1",
"css-loader": "^0.28.11",
"css-mqpacker": "^6.0.2",
"csswring": "^6.0.3",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"node-sass": "^4.9.0",
"postcss-flexbugs-fixes": "^3.3.1",
"postcss-loader": "^2.1.5",
"sass-loader": "^7.0.3",
"vue-loader": "^15.2.4",
"vue-style-loader": "^4.1.0",
"vue-template-compiler": "^2.5.16",
"webfonts-generator": "^0.4.0",
"webpack": "^4.12.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4"
}
}
$icons: (
{{#each codepoints}}
"{{@key}}": unquote("\"\\{{this}}\""),
{{/each}}
);
@function getIconContent( $key ) {
@each $pair in $icon {
@if nth( $pair, 1 ) == $key {
@return nth( $pair, 2 );
}
}
@return null;
}
@mixin icon( $name ) {
content: getIconContent( $name );
font-family: "{{ fontName }}";
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: middle;
display: inline-block;
}
@mixin initIcon() {
@font-face {
font-family: "{{ fontName }}";
src:
url( "../fonts/{{ fontName }}.woff2" ) format( "woff2" ),
url( "../fonts/{{ fontName }}.woff" ) format( "woff" ),
url( "../fonts/{{ fontName }}.ttf" ) format( "truetype" );
font-weight: normal;
font-style: normal;
}
[class^="{{ classPrefix }}"],
[class*=" {{ classPrefix }}"] {
font-family: "{{ fontName }}";
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: middle;
display: inline-block;
/* For With CJK Text =========== */
position: relative;
top: -0.1em;
}
{{#each codepoints}}
{{../baseSelector}}.-{{@key}}:before {
content: unquote("\"\\{{this}}\"");
}
{{/each}}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment