@proscom/gulp-svgr
Advanced tools
Comparing version 0.1.2 to 0.1.3
238
index.js
@@ -20,24 +20,40 @@ const { default: svgr } = require('@svgr/core'); | ||
async function createAggregatedFile(name, icons, aggregations) { | ||
const aggregation = aggregations[0]; | ||
function getDefaultIcon(name, icons) { | ||
return icons[icons.length - 1]; | ||
} | ||
async function createAggregatedFile(name, icons, options) { | ||
const aggregation = options.aggregate[0]; | ||
const defaultIconFn = options.aggregateDefault || getDefaultIcon; | ||
const defaultIcon = defaultIconFn(name, icons); | ||
const renderIconImport = ([, componentName]) => { | ||
// language=JSX Harmony | ||
return `import ${componentName} from './${componentName}';`; | ||
}; | ||
const renderIcon = (componentName) => { | ||
return `<${componentName} {...props} />;`; | ||
}; | ||
const renderIconCase = ([variant, componentName]) => { | ||
return ` | ||
case '${variant}': | ||
return ${renderIcon(componentName)}; | ||
`; | ||
}; | ||
const defaultIconRendered = defaultIcon && defaultIcon[1] ? renderIcon(defaultIcon[1]) : 'null'; | ||
// language=JSX Harmony | ||
const content = ` | ||
import React from 'react'; | ||
${icons.map(([, componentName]) => { | ||
// language=JSX Harmony | ||
return `import ${componentName} from './${componentName}';`; | ||
}).join('\n')} | ||
${icons.map(renderIconImport).join('\n')} | ||
export default function ${name}({ ${aggregation}, ...props }) { | ||
switch (${aggregation}) { | ||
${icons.map(([variant, componentName]) => { | ||
// language=JSX Harmony | ||
return ` | ||
case '${variant}': | ||
return <${componentName} {...props} />; | ||
`; | ||
}).join('\n')} | ||
${icons.map(renderIconCase).join('\n')} | ||
default: | ||
return null; | ||
return ${defaultIconRendered}; | ||
} | ||
@@ -47,3 +63,3 @@ } | ||
${name}.variations = { | ||
${aggregation}: [${icons.map(icon => `'${icon[0]}'`).join(',')}] | ||
${aggregation}: [${icons.map((icon) => `'${icon[0]}'`).join(',')}] | ||
}; | ||
@@ -56,6 +72,9 @@ `; | ||
async function createAllIconsFile(icons) { | ||
const content = icons.map(icon => ( | ||
// language=JSX Harmony | ||
`export { default as ${icon.name} } from './${icon.path}';` | ||
)).join('\n'); | ||
const content = icons | ||
.map( | ||
(icon) => | ||
// language=JSX Harmony | ||
`export { default as ${icon.name} } from './${icon.path}';` | ||
) | ||
.join('\n'); | ||
@@ -66,3 +85,8 @@ return prettify(content); | ||
module.exports = function gulpSvgr(options) { | ||
const { svgr: svgrOptions, aggregate, createIndex, extension = 'jsx' } = options; | ||
const { | ||
svgr: svgrOptions, | ||
aggregate, | ||
createIndex, | ||
extension = 'jsx' | ||
} = options; | ||
@@ -73,94 +97,116 @@ const allIcons = []; | ||
if (aggregate && !Array.isArray(aggregate)) { | ||
throw new PluginError(PLUGIN_NAME, '\'aggregate\' should be an array'); | ||
throw new PluginError(PLUGIN_NAME, "'aggregate' should be an array"); | ||
} | ||
if (aggregate && aggregate.length > 1) { | ||
throw new PluginError(PLUGIN_NAME, `Aggregating by multiple dimensions is not supported. Got '${aggregate.join(',')}'`); | ||
throw new PluginError( | ||
PLUGIN_NAME, | ||
`Aggregating by multiple dimensions is not supported. Got '${aggregate.join( | ||
',' | ||
)}'` | ||
); | ||
} | ||
return through.obj(async function(file, encoding, callback) { | ||
if (file.isNull()) { | ||
return callback(null, file); | ||
} | ||
return through.obj( | ||
async function (file, encoding, callback) { | ||
if (file.isNull()) { | ||
return callback(null, file); | ||
} | ||
if (file.isStream()) { | ||
this.emit( | ||
'error', | ||
new PluginError(PLUGIN_NAME, 'Streams not supported!') | ||
); | ||
} else if (file.isBuffer()) { | ||
const fileContent = file.contents.toString(); | ||
const iconPath = file.relative.split(/[\/\\]/); | ||
iconPath[iconPath.length - 1] = file.stem; | ||
iconPath.unshift('Icon'); | ||
const iconName = camelcase(iconPath, { pascalCase: true }); | ||
if (file.isStream()) { | ||
this.emit( | ||
'error', | ||
new PluginError(PLUGIN_NAME, 'Streams not supported!') | ||
); | ||
} else if (file.isBuffer()) { | ||
const fileContent = file.contents.toString(); | ||
const iconPath = file.relative.split(/[\/\\]/); | ||
iconPath[iconPath.length - 1] = file.stem; | ||
iconPath.unshift('Icon'); | ||
const iconName = camelcase(iconPath, { pascalCase: true }); | ||
if (aggregate) { | ||
// Group icons by aggregator | ||
const basePath = iconPath.slice(0, iconPath.length - 1); | ||
const baseIcon = camelcase(basePath, { pascalCase: true }); | ||
if (!baseIconsMap[baseIcon]) { | ||
baseIconsMap[baseIcon] = { | ||
path: basePath.slice(1), | ||
icons: [] | ||
}; | ||
if (aggregate) { | ||
// Group icons by aggregator | ||
const basePath = iconPath.slice(0, iconPath.length - 1); | ||
const baseIcon = camelcase(basePath, { pascalCase: true }); | ||
if (!baseIconsMap[baseIcon]) { | ||
baseIconsMap[baseIcon] = { | ||
path: basePath.slice(1), | ||
icons: [] | ||
}; | ||
} | ||
baseIconsMap[baseIcon].icons.push([file.stem, iconName]); | ||
} | ||
baseIconsMap[baseIcon].icons.push([file.stem, iconName]); | ||
} | ||
const jsCode = await svgr( | ||
fileContent, | ||
svgrOptions, | ||
{ componentName: iconName } | ||
); | ||
const jsCode = await svgr(fileContent, svgrOptions, { | ||
componentName: iconName | ||
}); | ||
const newFile = file.clone({ contents: false }); | ||
newFile.contents = Buffer.from(jsCode, 'utf-8'); | ||
newFile.path = path.join(path.dirname(file.path), `${ iconName }.${ extension }`); | ||
this.push(newFile); | ||
const newFile = file.clone({ contents: false }); | ||
newFile.contents = Buffer.from(jsCode, 'utf-8'); | ||
newFile.path = path.join( | ||
path.dirname(file.path), | ||
`${iconName}.${extension}` | ||
); | ||
this.push(newFile); | ||
allIcons.push({ | ||
name: iconName, | ||
path: `${ iconPath.slice(1).join('/') }/${ iconName }` | ||
}); | ||
callback(null); | ||
} else { | ||
this.emit('error', new PluginError(PLUGIN_NAME, 'Unknown file type')); | ||
} | ||
}, async function(cb) { | ||
if (aggregate) { | ||
// Do not save normal files | ||
allIcons.length = 0; | ||
// Save aggregated files | ||
for (const [iconName, info] of Object.entries(baseIconsMap)) { | ||
const combined = await createAggregatedFile(iconName, info.icons, aggregate); | ||
const filename = 'index.' + extension; | ||
const newFile = new Vinyl({ | ||
cwd: '', | ||
base: null, | ||
path: path.join(...info.path, filename), | ||
contents: Buffer.from(combined, 'utf-8') | ||
}); | ||
this.push(newFile); | ||
allIcons.push({ | ||
name: iconName, | ||
path: info.path.join('/') | ||
path: `${iconPath.slice(1).join('/')}/${iconName}` | ||
}); | ||
callback(null); | ||
} else { | ||
this.emit('error', new PluginError(PLUGIN_NAME, 'Unknown file type')); | ||
} | ||
} | ||
}, | ||
async function (cb) { | ||
if (aggregate) { | ||
// Do not save normal files | ||
allIcons.length = 0; | ||
if (createIndex) { | ||
// Создаем общий файл со списком всех иконок | ||
const allIconsCombined = await createAllIconsFile(allIcons) | ||
this.push(new Vinyl({ | ||
cwd: '', | ||
base: null, | ||
path: typeof createIndex === 'string' ? createIndex : 'index.' + extension, | ||
contents: Buffer.from(allIconsCombined, 'utf-8') | ||
})); | ||
// Save aggregated files | ||
for (const [iconName, info] of Object.entries(baseIconsMap)) { | ||
const combined = await createAggregatedFile( | ||
iconName, | ||
info.icons, | ||
options | ||
); | ||
const filename = 'index.' + extension; | ||
const newFile = new Vinyl({ | ||
cwd: '', | ||
base: null, | ||
path: path.join(...info.path, filename), | ||
contents: Buffer.from(combined, 'utf-8') | ||
}); | ||
this.push(newFile); | ||
allIcons.push({ | ||
name: iconName, | ||
path: info.path.join('/') | ||
}); | ||
} | ||
} | ||
if (createIndex) { | ||
allIcons.sort((a, b) => { | ||
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0; | ||
}); | ||
// Создаем общий файл со списком всех иконок | ||
const allIconsCombined = await createAllIconsFile(allIcons); | ||
this.push( | ||
new Vinyl({ | ||
cwd: '', | ||
base: null, | ||
path: | ||
typeof createIndex === 'string' | ||
? createIndex | ||
: 'index.' + extension, | ||
contents: Buffer.from(allIconsCombined, 'utf-8') | ||
}) | ||
); | ||
} | ||
cb(); | ||
} | ||
cb(); | ||
}); | ||
); | ||
}; |
{ | ||
"name": "@proscom/gulp-svgr", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"description": "Allows to run svgr as a gulp task", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -36,2 +36,6 @@ # `@proscom/gulp-svgr` | ||
aggregate: ['size'], | ||
// You can pass a function to determine which | ||
// icon to render when no aggregation matches props. | ||
// Default behavior is to render the last icon | ||
aggregateDefault: (name, icons) => icons[icons.length - 1], | ||
// Creates index.jsx file containing all the icons | ||
@@ -38,0 +42,0 @@ createIndex: true, |
9313
178
91