@microflash/spritely
Advanced tools
Sorry, the diff of this file is not supported yet
+3
-3
| { | ||
| "name": "@microflash/spritely", | ||
| "version": "1.2.7", | ||
| "version": "1.2.8", | ||
| "description": "A handy Node.js CLI to generate SVG sprites", | ||
| "preferGlobal": true, | ||
| "bin": { | ||
| "spritely": "./bin/spritely.js" | ||
| "spritely": "./bin/spritely" | ||
| }, | ||
| "devDependencies": { | ||
| "dependencies": { | ||
| "cheerio": "^1.0.0-rc.3", | ||
@@ -11,0 +11,0 @@ "commander": "^5.1.0", |
-125
| #!/usr/bin/env node | ||
| const path = require('path') | ||
| const fs = require('fs-extra') | ||
| const program = require('commander') | ||
| const cheerio = require('cheerio') | ||
| const klaw = require('klaw') | ||
| const pkg = require('../package.json') | ||
| program | ||
| .name(`spritely ${pkg.version}`) | ||
| .version(pkg.version) | ||
| program | ||
| .option('-i, --input [input]', 'specify input directory (default: current directory)') | ||
| .option('-o, --output [output]', 'specify output file (default: "sprites.svg")') | ||
| .option('-r, --recursive [recursive]', 'enable recursive traversal of input directory (default: false)') | ||
| .option('-v, --viewbox [viewbox]', 'specify viewBox attribute (detected automatically, if not specified)') | ||
| .option('-p, --prefix [prefix]', 'specify prefix for id attribute for symbols (default: none)') | ||
| .option('-n, --normalize [normalize]', 'toggle whitespace normalization (default: true)') | ||
| .option('-q, --quiet', 'disable verbose output') | ||
| .parse(process.argv) | ||
| const SOURCE_FOLDER = program.input || '.' | ||
| const OUTPUT_FILE = program.output || 'sprites.svg' | ||
| const RECURSIVE = program.recursive || false | ||
| const ID_PREFIX = program.prefix || '' | ||
| const VIEWBOX = program.viewbox || null | ||
| const PARSER_OPTIONS = { | ||
| normalizeWhitespace: program.normalize || true | ||
| } | ||
| const QUIET = program.quiet || false | ||
| const log = message => { | ||
| if (!QUIET) console.log(message) | ||
| } | ||
| const getSvgElement = content => { | ||
| const $ = cheerio.load(content, PARSER_OPTIONS) | ||
| return $('svg').first() | ||
| } | ||
| const getViewbox = content => { | ||
| const svgContent = getSvgElement(content) | ||
| return VIEWBOX || svgContent.attr('viewbox') || svgContent.attr('viewBox') | ||
| } | ||
| const getPreserveAspectRatio = content => { | ||
| const svgContent = getSvgElement(content) | ||
| return svgContent.attr('preserveaspectratio') || svgContent.attr('preserveAspectRatio') | ||
| } | ||
| const generateSymbolId = fileName => (ID_PREFIX + fileName).replace(' ', '-') | ||
| const generateAttributesString = attributes => { | ||
| return Object.keys(attributes).reduce((acc, key) => { | ||
| const value = attributes[key] | ||
| return value ? `${acc} ${key}="${value}"` : acc | ||
| }, '') | ||
| } | ||
| const getSvgContent = content => getSvgElement(content).html() | ||
| const generateSymbol = (content, attributes) => `<symbol${generateAttributesString(attributes)}>${getSvgContent(content)}</symbol>` | ||
| const wrapFile = (fileName, content) => { | ||
| const attributes = { | ||
| viewBox: getViewbox(content), | ||
| id: generateSymbolId(fileName), | ||
| preserveAspectRatio: getPreserveAspectRatio(content) | ||
| } | ||
| log(`Process "${fileName}" (viewBox "${attributes.viewBox}")...`) | ||
| return generateSymbol(content, attributes) | ||
| } | ||
| const processFile = file => { | ||
| const filePath = path.resolve(SOURCE_FOLDER, file) | ||
| const fileName = path.basename(file, path.extname(file)) | ||
| const wrapContent = wrapFile.bind(null, fileName) | ||
| return fs.readFile(filePath, 'utf8').then(wrapContent) | ||
| } | ||
| const removeOutputFile = () => fs.remove(OUTPUT_FILE) | ||
| const readSourceDirectory = d => { | ||
| return !RECURSIVE | ||
| ? fs.readdir(SOURCE_FOLDER) | ||
| : new Promise((resolve, reject) => { | ||
| const files = [] | ||
| klaw(SOURCE_FOLDER) | ||
| .on('data', ({ path, stats }) => { if (stats.isFile()) files.push(path) }) | ||
| .on('end', () => resolve(files)) | ||
| .on('error', (err, item) => reject(err, item)) | ||
| }) | ||
| } | ||
| const processFiles = files => { | ||
| const processedFiles = files.filter(filterSvgFile).map(processFile) | ||
| return Promise.all(processedFiles) | ||
| } | ||
| const filterSvgFile = file => path.extname(file) === '.svg' | ||
| const getSpriteContent = contents => `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true">${contents.join('')}</svg>` | ||
| const writeOutputFile = content => fs.writeFile(OUTPUT_FILE, content, 'utf8') | ||
| const conclude = () => log(`File "${OUTPUT_FILE}" successfully generated.`) | ||
| const rethrowErrors = err => { | ||
| throw err | ||
| } | ||
| removeOutputFile() | ||
| .then(readSourceDirectory) | ||
| .then(processFiles) | ||
| .then(getSpriteContent) | ||
| .then(writeOutputFile) | ||
| .then(conclude) | ||
| .catch(rethrowErrors) |
Empty package
Supply chain riskPackage does not contain any code. It may be removed, is name squatting, or the result of a faulty package publish.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
0
-100%1
-66.67%9117
-0.08%5
Infinity%0
-100%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added