eos-icons
Version:
The iconic and open source font made for EOS Design System.
669 lines (621 loc) • 19.4 kB
JavaScript
module.exports = function (grunt) {
const { compareFolders } = require('./scripts/md-name-checker')
const {
combineIconsModels,
showMissingOutlinedFiles
} = require('./scripts/combine-eos-icons')
const {
checkForMissingModelsOrIcons,
checkModelKeys,
outlinedModelsChecker,
outlineModelsAndSvgTest,
missingOutlinedModelsChecker
} = require('./scripts/models-checker')
const { createNewModel } = require('./scripts/models-creation')
const {
checkSvgName,
renameSvgTo,
deleteDuplicateSvg,
writeDuplicateSvgsTheme
} = require('./scripts/svg-checker')
const duplicatedIcons = require('./scripts/duplicated_icons.json')
const {
eosMdIconsDifferences,
downloadMaterialIconsList
} = require('./scripts/eos-md-icons-log-differences')
const { downloadMDFile } = require('./scripts/download-svg')
const {
jsFileFromJSON,
readFilesNameInFolder
} = require('./scripts/utilities')
// Append path to your svg below
// EOS-set and MD svg path
const srcEosSet = ['svg/*.svg', 'svg/material/*.svg']
const srcEosSetOutlined = ['temp/*.svg', 'temp/material/*.svg']
grunt.initConfig({
webfont: {
icons: {
src: srcEosSet,
dest: 'dist/fonts',
destCss: 'dist/css',
destScss: 'dist/css',
destLess: 'dist/css',
options: {
font: 'eos-icons',
syntax: 'bootstrap',
version: '1.0.0',
ligatures: true,
normalize: true,
types: 'woff2,woff,ttf,svg,eot',
metadata: 'something here',
templateOptions: {
baseClass: 'eos-icons',
classPrefix: 'eos-',
template: 'templates/css-template.css',
iconsStyles: false
},
stylesheets: ['less', 'scss', 'css'],
destHtml: 'dist/',
htmlDemoTemplate: 'templates/index-template.html',
htmlDemoFilename: 'index',
customOutputs: [
{
template: 'templates/glyph-list-template.json',
dest: 'dist/js/glyph-list.json'
}
]
}
},
outlined: {
src: srcEosSetOutlined,
dest: 'dist/fonts/',
destCss: 'dist/css/',
destScss: 'dist/css/',
destLess: 'dist/css/',
options: {
font: 'eos-icons-outlined',
syntax: 'bootstrap',
version: '1.0.0',
ligatures: true,
normalize: true,
types: 'woff2,woff,ttf,svg,eot',
metadata: 'something here',
templateOptions: {
baseClass: 'eos-icons-outlined',
classPrefix: 'eos-',
template: 'templates/css-template.css',
iconsStyles: false
},
stylesheets: ['less', 'scss', 'css']
}
}
},
svgmin: {
options: {
plugins: [
'removeDoctype',
'removeXMLProcInst',
'removeComments',
'removeMetadata',
'removeEditorsNSData',
'cleanupAttrs',
'inlineStyles',
'cleanupIDs',
'removeUselessDefs',
'removeUnknownsAndDefaults',
'removeNonInheritableGroupAttrs',
'removeUselessStrokeAndFill',
{ removeDimensions: true },
{ removeViewBox: false },
'cleanupEnableBackground',
'removeHiddenElems',
'removeEmptyText',
{ moveElemsAttrsToGroup: false },
{ moveGroupAttrsToElems: false },
{ convertPathData: false },
{ convertTransform: false },
'removeEmptyAttrs',
'removeEmptyContainers',
'removeUnusedNS',
'removeTitle',
'removeDesc',
'removeScriptElement',
'removeStyleElement',
'removeOffCanvasPaths',
{ mergePaths: false },
{ convertShapeToPath: false },
{
removeFill: {
type: 'perItem',
name: 'removeFillHeightWidth',
description:
'Removes the Fill, Height and Width attr from the <svg> <path> element',
fn: function (item) {
if (item.isElem('svg')) {
item.removeAttr('fill')
item.removeAttr('height')
item.removeAttr('width')
}
}
}
},
{
removeUnusedPath: {
type: 'perItem',
name: 'removeUnusedPath',
description: 'Removes the removeUnusedPath',
fn: function (item) {
if (item.isElem('path') && item.attrs.fill) {
if (item.attrs.fill.value === 'none') {
return !item.isElem('path')
}
}
}
}
},
{
removeRectFillNone: {
type: 'perItem',
name: 'removeRectIfFillNone',
description: 'Removes <rect> element if Fill is none',
fn: function (item) {
if (item.isElem('rect') && item.attrs.fill) {
if (item.attrs.fill.value === 'none') {
return !item.isElem('rect')
}
}
}
}
}
]
},
dist: {
files: [
{
expand: true,
cwd: 'svg/material',
src: '*.svg',
dest: 'svg/material',
ext: '.svg',
extDot: 'first'
},
{
expand: true,
cwd: 'svg-outlined/material',
src: '*.svg',
dest: 'svg-outlined/material',
ext: '.svg',
extDot: 'first'
}
]
}
},
concat: {
dist: {
src: ['templates/css-webfont.css'],
dest: 'templates/css-template.css'
}
},
replace: {
replace_metadata: {
src: ['dist/fonts/eos-icons.svg'],
overwrite: true,
replacements: [
{
from: /<metadata>(.|\n)*?<\/metadata>/,
to: '<metadata>Created by EOS Design System</metadata>'
}
]
}
},
coffee: {
files: './scripts/eos-md-icons-log-differences',
tasks: ['coffee']
},
copy: {
outlined: {
expand: true,
dest: 'temp',
cwd: 'svg-outlined',
src: '**/*'
},
demosFilesJS: {
expand: true,
cwd: 'scripts/demos',
src: '*.js',
dest: './dist/js/'
},
demoFilesHTML: {
expand: true,
cwd: 'scripts/demos',
src: '*.html',
dest: './dist/'
}
},
clean: {
tempFolder: {
src: './temp'
},
icons: {
expand: true,
cwd: './svg/material/',
src: duplicatedIcons.filled.map((ele) => `${ele}.svg`)
},
iconsOutlined: {
expand: true,
cwd: './svg-outlined/material/',
src: duplicatedIcons.outlined.map((ele) => `${ele}.svg`)
},
models: {
expand: true,
cwd: './models/material/',
src: duplicatedIcons.filled.map((ele) => `${ele}.json`)
},
dist: {
src: './dist/'
},
hidden: {
src: ['./svg/**/.DS_Store', './models/**/.DS_Store']
}
}
})
grunt.registerTask('checkMissingModelsOutlined', async function () {
const done = this.async()
outlineModelsAndSvgTest({
normalSvgs: '/svg',
outlinedSvgs: '/svg-outlined'
}).then((data) => {
const { difference } = data
if (difference.length) {
console.log(
'\x1b[33m%s\x1b[0m',
`⚠️ === WARNING === ⚠️ \n${
difference.length
} SVG missing: we found the outlined version of # ${difference.map(
(ele) => ele
)} # but not the SVG inside /svg. \n Please make sure to generate the filled version before adding the outlined one.`
)
process.exit(1)
} else {
console.log('✅ No extra outlined icons were found.')
done()
}
})
})
/* Looks into the models and svg folders and finds the differences */
grunt.registerTask('checkMissingModelandSVG', function () {
const done = this.async()
checkForMissingModelsOrIcons({
modelsSrc: '/models',
mdModelsSrc: '/models/material',
mdIconsSrc: '/svg/material',
iconsSrc: '/svg',
animatedSrc: '/animated-svg'
}).then(async (data) => {
const {
SVGsMissingModelsEOS,
SVGsMissingModelsMd,
ModelsMissingSVGsEos,
ModelsMissingSVGsMd
} = data
const SVGsMissingModels = [
...SVGsMissingModelsMd,
...SVGsMissingModelsEOS
]
let ModelsMissingSVGs
if (
SVGsMissingModels.length ||
ModelsMissingSVGsEos.length ||
ModelsMissingSVGsMd.length
) {
if (SVGsMissingModels.length) {
console.log(
`⚠️ ${
SVGsMissingModels.length
} SVG missing: we found models # ${SVGsMissingModels.map(
(ele) => ele
)} # but not the SVG inside /svg.`
)
process.exit(1)
}
if (ModelsMissingSVGsEos.length || ModelsMissingSVGsMd.length) {
ModelsMissingSVGs = ModelsMissingSVGsEos
console.log(
`⚠️ ${
ModelsMissingSVGs.length
} EOS model missing: we found the SVG # ${ModelsMissingSVGs.map(
(ele) => ele
)} # but not the model inside /models. Please create one below.`
)
/* If any model is missing, send it to be created. */
await createNewModel({
ModelsMissingSVGs,
modelsSrc: './models'
}).then(async () => {
if (ModelsMissingSVGsMd.length) {
ModelsMissingSVGs = ModelsMissingSVGsMd
console.log(
`⚠️ ${
ModelsMissingSVGs.length
} MD Model missing: we found the SVG # ${ModelsMissingSVGs.map(
(ele) => ele
)} # but not the model inside ./models/material. Please create one below.`
)
/* If any model is missing, send it to be created. */
await createNewModel({
ModelsMissingSVGs,
modelsSrc: './models/material'
}).then(done)
}
})
}
} else {
console.log(
'✅ All SVGs have their corresponding model and vice versa.'
)
done()
}
})
})
/* Find duplictes name between our icons and MD icon set. */
grunt.registerTask('findDuplicateNames', function () {
const done = this.async()
const mdRepo = '/svg/material'
const eosRepo = '/svg'
const eosModelsSrc = '/models'
const mdModelsSrc = '/models/material'
compareFolders({ mdRepo, eosRepo, eosModelsSrc, mdModelsSrc }).then(
async (result) => {
const {
duplicatedEOSicon,
duplicatedMDicon,
duplicatedIconsList
} = result
if (duplicatedEOSicon.length) {
console.log(duplicatedEOSicon)
for await (const icon of duplicatedEOSicon) {
console.log(
`⚠️ An icon with the name ${icon}.svg already exits in svg/material. Please rename this new icon below:`
)
await renameSvgTo(icon, eosRepo, mdRepo).then(done)
}
} else if (duplicatedMDicon.length) {
for await (const icon of duplicatedMDicon) {
console.log(
`⚠️ An icon with the name ${icon}.svg already exits svg/. Please rename this new icon below:`
)
await renameSvgTo(icon, mdRepo, eosRepo).then(done)
}
} else if (duplicatedIconsList.length) {
for await (const icon of duplicatedIconsList) {
console.log(`${icon}`)
await deleteDuplicateSvg(icon).then()
}
done()
} else {
console.log('✅ No duplicated SVG file found in EOS and MD folder.')
done()
}
}
)
})
/* Combine all the models into a single file */
grunt.registerTask('combineAllIconsModels', async function () {
const done = this.async()
return combineIconsModels({
targetDirEos: 'models/',
targetDirMd: 'models/material/',
destDir: 'dist/js/eos-icons.json'
}).then(done)
})
/* compare MD icons in our repo and MD officical website Download MD svgs and create models */
grunt.registerTask('importMdIcons', async function () {
const done = this.async()
const targetDir = '/svg/material'
await downloadMaterialIconsList()
.then(
eosMdIconsDifferences({
targetDirMd: targetDir,
duplicatedIconsList: duplicatedIcons.filled
}).then(async (res) => {
if (res.answer === 'Yes') {
const iconList = [...res.iconsList]
/* Download MD svgs and create models */
await downloadMDFile(iconList, targetDir).then()
done()
} else {
done()
}
})
)
.then()
})
/* Import outlined MD icons */
grunt.registerTask('importOutlinedMdIcons', async function () {
const done = this.async()
const targetDir = '/svg-outlined/material'
await downloadMaterialIconsList()
.then(
eosMdIconsDifferences({
targetDirMd: targetDir,
duplicatedIconsList: [
...duplicatedIcons.filled,
...duplicatedIcons.outlined
]
}).then(async (res) => {
if (res.answer === 'Yes') {
const iconList = [...res.iconsList]
/* Download MD svgs and create models */
await downloadMDFile(iconList, targetDir).then()
done()
} else {
done()
}
})
)
.then()
})
/* Checks for each models to make sure it has all the properties we expect. */
grunt.registerTask('checkModelKeysTask', async function () {
const done = this.async()
return checkModelKeys('/models', '/models/material').then((result) => {
if (!result.length) return done()
console.log(
`🚫 The following errors need fixing: \n\n ${result.map((ele) => ele)}`
)
// If any of the results includes the missing dateOutlined propriety, add it.
if (result.map((ele) => ele.includes('Found hasOutlined'))) {
console.log(
'\n\n⚠️ To fix the missing dateOutlined property: grunt fixOutlinedProps'
)
}
})
})
grunt.registerTask('fixOutlinedProps', async function () {
const done = this.async()
try {
grunt.task.run(['outlinedModelsChecker', 'eosIconsOutlineModels'])
} catch (error) {
console.error('ERROR: fixOutlinedProps(): ', error)
} finally {
done()
}
})
grunt.registerTask('clearDuplicatesSVGs', async function () {
const done = this.async()
try {
const mdIcons = readFilesNameInFolder('/svg/material')
await writeDuplicateSvgsTheme(mdIcons)
} catch (error) {
console.error('ERROR: clearDuplicatesSVGs(): ', error)
} finally {
done()
}
})
// Handle MD Icons Outline model
grunt.registerTask('outlinedModelsChecker', async function () {
const done = this.async()
return outlinedModelsChecker({
outlineSvgDir: '/svg-outlined/material',
modelsFolder: '/models/material'
}).then(done)
})
// Handle missing MD Icons Outlined icons model
grunt.registerTask('missingOutlinedModelsChecker', async function () {
const done = this.async()
return missingOutlinedModelsChecker({
outlineSvgDir: '/svg-outlined/material',
modelsFolder: '/models/material'
}).then(done)
})
// Handle EOS Icons Outline model
grunt.registerTask('eosIconsOutlineModels', async function () {
const done = this.async()
return outlinedModelsChecker({
outlineSvgDir: '/svg-outlined',
modelsFolder: '/models'
}).then(done)
})
// Temporaty folder mix
grunt.registerTask('temp_svg_collection', async function () {
const done = this.async()
showMissingOutlinedFiles({
outlineSvgDir: './svg-outlined',
normalSvgDir: './svg',
tempFolder: './temp'
}).then((data) => {
console.log(data)
showMissingOutlinedFiles({
outlineSvgDir: './svg-outlined/material',
normalSvgDir: './svg/material',
tempFolder: './temp/material'
}).then((data) => {
console.log(data)
done()
})
})
})
grunt.registerTask('jsFromJSON', async function () {
const done = this.async()
jsFileFromJSON('./dist/js/eos-icons.json', './dist/js/eos-icons.js').then(
done
)
})
/* Checks for SVGs names returns the one with a wrong naming convention */
grunt.registerTask('checkNameConvention', async function () {
const done = this.async()
const mdDir = '/svg/material'
const eosDir = '/svg'
checkSvgName({ mdDir, eosDir }).then(async (result) => {
const { eosIconsNew, mdIconsMdNew } = result
if (eosIconsNew.length || mdIconsMdNew.length) {
if (eosIconsNew.length) {
for await (const icon of eosIconsNew) {
console.log(
`⚠️ ${icon}.svg is not matching our naming convention, please rename it below:`
)
await renameSvgTo(icon, eosDir, mdDir)
}
process.exit(1)
}
if (mdIconsMdNew.length) {
for await (const icon of mdIconsMdNew) {
console.log(
`⚠️ ${icon}.svg is not matching our naming convention, please rename it below:`
)
await renameSvgTo(icon, mdDir, eosDir).then(done)
}
}
} else {
console.log('✅ All SVGs have correct naming convention.')
done()
}
})
})
grunt.loadNpmTasks('grunt-webfont')
grunt.loadNpmTasks('grunt-svgmin')
grunt.loadNpmTasks('grunt-contrib-copy')
grunt.loadNpmTasks('grunt-contrib-concat')
grunt.loadNpmTasks('grunt-contrib-clean')
grunt.loadNpmTasks('grunt-text-replace')
grunt.registerTask('cleanSvg', ['svgmin'])
grunt.registerTask('clean:all', [
'clean:hidden',
'clean:dist',
'clean:icons',
'clean:iconsOutlined',
'clean:models',
'clean:tempFolder'
])
grunt.registerTask('build', [
'findDuplicateNames',
'clean:all',
'missingOutlinedModelsChecker',
'concat',
'copy:outlined',
'temp_svg_collection',
'webfont:icons',
'webfont:outlined',
'replace',
'combineAllIconsModels',
'clean:tempFolder',
'jsFromJSON',
'copy:demosFilesJS',
'copy:demoFilesHTML'
])
grunt.registerTask('test', [
'importMdIcons',
'importOutlinedMdIcons',
'fixOutlinedProps',
'findDuplicateNames',
'checkNameConvention',
'checkModelKeysTask',
'checkMissingModelandSVG',
'outlinedModelsChecker',
'eosIconsOutlineModels',
'checkMissingModelsOutlined',
'cleanSvg',
'clearDuplicatesSVGs'
])
grunt.registerTask('default', ['test', 'build'])
}