Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

babel-plugin-inline-react-svg

Package Overview
Dependencies
Maintainers
3
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

babel-plugin-inline-react-svg - npm Package Compare versions

Comparing version 0.5.2 to 0.5.3

.travis.yml

10

lib/fileExistsWithCaseSync.js
Object.defineProperty(exports, "__esModule", {
value: true
value: true
});

@@ -10,6 +10,6 @@ exports['default'] = fileExistsWithCaseSync;

function fileExistsWithCaseSync(filepath) {
var dir = path.dirname(filepath);
if (dir === '/' || dir === '.') return true;
var filenames = fs.readdirSync(dir);
return filenames.indexOf(path.basename(filepath)) !== -1;
var dir = path.dirname(filepath);
if (dir === '/' || dir === '.') return true;
var filenames = fs.readdirSync(dir);
return filenames.indexOf(path.basename(filepath)) !== -1;
}

@@ -19,5 +19,5 @@ Object.defineProperty(exports, "__esModule", {

var _resolveFrom = require('resolve-from');
var _resolve = require('resolve');
var _resolveFrom2 = _interopRequireDefault(_resolveFrom);
var _resolve2 = _interopRequireDefault(_resolve);

@@ -50,2 +50,75 @@ var _optimize = require('./optimize');

var t = _ref.types;
function applyPlugin(importIdentifier, importPath, path, state) {
var _state$opts = state.opts,
ignorePattern = _state$opts.ignorePattern,
caseSensitive = _state$opts.caseSensitive;
var file = state.file;
if (ignorePattern) {
// Only set the ignoreRegex once:
ignoreRegex = ignoreRegex || new RegExp(ignorePattern);
// Test if we should ignore this:
if (ignoreRegex.test(importPath)) {
return;
}
}
// This plugin only applies for SVGs:
if ((0, _path.extname)(importPath) === '.svg') {
var iconPath = state.file.opts.filename;
var svgPath = _resolve2['default'].sync(importPath, { basedir: (0, _path.dirname)(iconPath) });
if (caseSensitive && !(0, _fileExistsWithCaseSync2['default'])(svgPath)) {
throw new Error('File path didn\'t match case of file on disk: ' + String(svgPath));
}
if (!svgPath) {
throw new Error('File path does not exist: ' + String(importPath));
}
var rawSource = (0, _fs.readFileSync)(svgPath, 'utf8');
var optimizedSource = state.opts.svgo === false ? rawSource : (0, _optimize2['default'])(rawSource, state.opts.svgo);
var escapeSvgSource = (0, _escapeBraces2['default'])(optimizedSource);
var parsedSvgAst = (0, _babylon.parse)(escapeSvgSource, {
sourceType: 'module',
plugins: ['jsx']
});
(0, _babelTraverse2['default'])(parsedSvgAst, (0, _transformSvg2['default'])(t));
var svgCode = _babelTraverse2['default'].removeProperties(parsedSvgAst.program.body[0].expression);
var opts = {
SVG_NAME: importIdentifier,
SVG_CODE: svgCode
};
// Move props off of element and into defaultProps
if (svgCode.openingElement.attributes.length > 1) {
var keepProps = [];
var defaultProps = [];
svgCode.openingElement.attributes.forEach(function (prop) {
if (prop.type === 'JSXSpreadAttribute') {
keepProps.push(prop);
} else {
defaultProps.push(t.objectProperty(t.identifier(prop.name.name), prop.value));
}
});
svgCode.openingElement.attributes = keepProps;
opts.SVG_DEFAULT_PROPS_CODE = t.objectExpression(defaultProps);
}
if (opts.SVG_DEFAULT_PROPS_CODE) {
var svgReplacement = buildSvgWithDefaults(opts);
path.replaceWithMultiple(svgReplacement);
} else {
var _svgReplacement = buildSvg(opts);
path.replaceWith(_svgReplacement);
}
file.get('ensureReact')();
file.set('ensureReact', function () {});
}
}
return {

@@ -56,14 +129,12 @@ visitor: {

function enter(_ref2, _ref3) {
var scope = _ref2.scope;
var node = _ref2.node;
var scope = _ref2.scope,
node = _ref2.node;
var file = _ref3.file;
if (!scope.hasBinding('React')) {
(function () {
var reactImportDeclaration = t.importDeclaration([t.importDefaultSpecifier(t.identifier('React'))], t.stringLiteral('react'));
var reactImportDeclaration = t.importDeclaration([t.importDefaultSpecifier(t.identifier('React'))], t.stringLiteral('react'));
file.set('ensureReact', function () {
node.body.unshift(reactImportDeclaration);
});
})();
file.set('ensureReact', function () {
node.body.unshift(reactImportDeclaration);
});
} else {

@@ -77,73 +148,20 @@ file.set('ensureReact', function () {});

},
ImportDeclaration: function () {
function ImportDeclaration(path, state) {
var importPath = path.node.source.value;
var _state$opts = state.opts;
var ignorePattern = _state$opts.ignorePattern;
var caseSensitive = _state$opts.caseSensitive;
var file = state.file;
CallExpression: function () {
function CallExpression(path, state) {
var node = path.node;
if (ignorePattern) {
// Only set the ignoreRegex once:
ignoreRegex = ignoreRegex || new RegExp(ignorePattern);
// Test if we should ignore this:
if (ignoreRegex.test(importPath)) {
return;
}
var filePath = node.arguments.length > 0 && node.arguments[0].value;
if (node.callee.name === 'require' && t.isVariableDeclarator(path.parent)) {
applyPlugin(path.parent.id, filePath, path.parentPath.parentPath, state);
}
// This plugin only applies for SVGs:
if ((0, _path.extname)(importPath) === '.svg') {
// We only support the import default specifier, so let's use that identifier:
var importIdentifier = path.node.specifiers[0].local;
var iconPath = state.file.opts.filename;
var svgPath = (0, _resolveFrom2['default'])((0, _path.dirname)(iconPath), importPath);
if (caseSensitive && !(0, _fileExistsWithCaseSync2['default'])(svgPath)) {
throw new Error('File path didn\'t match case of file on disk: ' + String(svgPath));
}
var rawSource = (0, _fs.readFileSync)(svgPath, 'utf8');
var optimizedSource = state.opts.svgo === false ? rawSource : (0, _optimize2['default'])(rawSource, state.opts.svgo);
}
var escapeSvgSource = (0, _escapeBraces2['default'])(optimizedSource);
return CallExpression;
}(),
ImportDeclaration: function () {
function ImportDeclaration(path, state) {
var node = path.node;
var parsedSvgAst = (0, _babylon.parse)(escapeSvgSource, {
sourceType: 'module',
plugins: ['jsx']
});
(0, _babelTraverse2['default'])(parsedSvgAst, (0, _transformSvg2['default'])(t));
var svgCode = _babelTraverse2['default'].removeProperties(parsedSvgAst.program.body[0].expression);
var opts = {
SVG_NAME: importIdentifier,
SVG_CODE: svgCode
};
// Move props off of element and into defaultProps
if (svgCode.openingElement.attributes.length > 1) {
(function () {
var keepProps = [];
var defaultProps = [];
svgCode.openingElement.attributes.forEach(function (prop) {
if (prop.type === 'JSXSpreadAttribute') {
keepProps.push(prop);
} else {
defaultProps.push(t.objectProperty(t.identifier(prop.name.name), prop.value));
}
});
svgCode.openingElement.attributes = keepProps;
opts.SVG_DEFAULT_PROPS_CODE = t.objectExpression(defaultProps);
})();
}
if (opts.SVG_DEFAULT_PROPS_CODE) {
var svgReplacement = buildSvgWithDefaults(opts);
path.replaceWithMultiple(svgReplacement);
} else {
var _svgReplacement = buildSvg(opts);
path.replaceWith(_svgReplacement);
}
file.get('ensureReact')();
if (node.specifiers.length > 0) {
applyPlugin(node.specifiers[0].local, node.source.value, path, state);
}

@@ -150,0 +168,0 @@ }

@@ -5,3 +5,3 @@ Object.defineProperty(exports, "__esModule", {

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

@@ -36,2 +36,3 @@ exports['default'] = optimize;

if (typeof opts.plugins === 'undefined' || Array.isArray(opts.plugins) && opts.plugins.length === 0) {
/* eslint no-param-reassign: 1 */
opts.plugins = [].concat(essentialPlugins);

@@ -60,2 +61,3 @@ return;

// and update state
/* eslint no-param-reassign: 1 */
state[k] = true;

@@ -75,3 +77,3 @@ }

function optimize(content) {
var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

@@ -78,0 +80,0 @@ validateAndFix(opts);

@@ -21,4 +21,7 @@ Object.defineProperty(exports, "__esModule", {

JSXAttribute: function () {
function JSXAttribute(path) {
if (t.isJSXNamespacedName(path.node.name)) {
function JSXAttribute(_ref) {
var node = _ref.node;
var originalName = node.name;
if (t.isJSXNamespacedName(originalName)) {
// converts

@@ -28,4 +31,4 @@ // <svg xmlns:xlink="asdf">

// <svg xmlnsXlink="asdf">
path.node.name = t.jSXIdentifier((0, _camelize.namespaceToCamel)(path.node.name.namespace.name, path.node.name.name.name));
} else if (t.isJSXIdentifier(path.node.name)) {
node.name = t.jSXIdentifier((0, _camelize.namespaceToCamel)(originalName.namespace.name, originalName.name.name));
} else if (t.isJSXIdentifier(originalName)) {
// converts

@@ -35,4 +38,4 @@ // <tag class="blah blah1"/>

// <tag className="blah blah1"/>
if (path.node.name.name === 'class') {
path.node.name.name = 'className';
if (originalName.name === 'class') {
originalName.name = 'className';
}

@@ -44,10 +47,8 @@

// <tag style={{textAlign: 'center', width: '50px'}}>
if (path.node.name.name === 'style') {
(function () {
var csso = (0, _cssToObj2['default'])(path.node.value.value);
var properties = Object.keys(csso).map(function (prop) {
return t.objectProperty(t.identifier((0, _camelize.hyphenToCamel)(prop)), t.stringLiteral(csso[prop]));
});
path.node.value = t.jSXExpressionContainer(t.objectExpression(properties));
})();
if (originalName.name === 'style') {
var csso = (0, _cssToObj2['default'])(node.value.value);
var properties = Object.keys(csso).map(function (prop) {
return t.objectProperty(t.identifier((0, _camelize.hyphenToCamel)(prop)), t.stringLiteral(csso[prop]));
});
node.value = t.jSXExpressionContainer(t.objectExpression(properties));
}

@@ -59,5 +60,7 @@

// <svg strokeWidth="5">
// don't convert any custom data-* attributes
if (!path.node.name.name.startsWith('data-')) {
path.node.name.name = (0, _camelize.hyphenToCamel)(path.node.name.name);
// don't convert any custom data-* or aria-* attributes just wrap in quotes
if (/^data-|^aria-/.test(originalName.name)) {
originalName.name = '\'' + String(originalName.name) + '\'';
} else {
originalName.name = (0, _camelize.hyphenToCamel)(originalName.name);
}

@@ -77,6 +80,10 @@ }

JSXOpeningElement: function () {
function JSXOpeningElement(path) {
if (path.node.name.name.toLowerCase() === 'svg') {
function JSXOpeningElement(_ref2) {
var _ref2$node = _ref2.node,
name = _ref2$node.name,
attributes = _ref2$node.attributes;
if (name.name.toLowerCase() === 'svg') {
// add spread props
path.node.attributes.push(t.jSXSpreadAttribute(t.identifier('props')));
attributes.push(t.jSXSpreadAttribute(t.identifier('props')));
}

@@ -83,0 +90,0 @@ }

{
"name": "babel-plugin-inline-react-svg",
"version": "0.5.2",
"version": "0.5.3",
"description": "A babel plugin that optimizes and inlines SVGs for your react components.",
"main": "lib/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"sanity": "babel-node test/sanity.js",
"test": "npm run tests-only",
"pretests-only": "npm run build",
"tests-only": "babel-node test/sanity.js",
"build": "babel src --out-dir lib",
"lint": "eslint src/",
"prepublish": "npm run build"
"prepublish": "npm run build",
"pretest": "npm run lint"
},

@@ -31,21 +33,21 @@ "repository": {

"devDependencies": {
"babel-cli": "^6.14.0",
"babel-core": "^6.14.0",
"babel-preset-airbnb": "^2.0.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-preset-airbnb": "^2.5.1",
"babel-preset-react": "^6.24.1",
"eslint": "^3.5.0",
"eslint-config-airbnb": "^11.1.0",
"eslint-plugin-import": "^1.15.0",
"eslint-plugin-jsx-a11y": "^2.2.2",
"eslint-plugin-react": "^6.2.2",
"eslint": "^4.19.1",
"eslint-config-airbnb": "^17.0.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.10.0",
"react": "^15.3.1"
},
"dependencies": {
"babel-template": "^6.15.0",
"babel-traverse": "^6.15.0",
"babylon": "^6.10.0",
"babel-template": "^6.26.0",
"babel-traverse": "^6.26.0",
"babylon": "^6.18.0",
"lodash.isplainobject": "^4.0.6",
"resolve-from": "^2.0.0",
"svgo": "^0.7.0"
"resolve": "^1.8.1",
"svgo": "^0.7.2"
}
}

@@ -11,3 +11,3 @@ # babel-plugin-inline-react-svg

const MyComponent = () => <CloseSvg />;
const MyComponent = () => <CloseSVG />;
```

@@ -21,3 +21,3 @@

const MyComponent = () => <CloseSvg />;
const MyComponent = () => <CloseSVG />;
```

@@ -24,0 +24,0 @@

import { transformFile } from 'babel-core';
import fs from 'fs';
import path from 'path';
function assertReactImport(result) {
const match = result.code.match(/import React from 'react'/);
const match = result.code.match(/import React from 'react'/g);
if (!match) {

@@ -9,7 +11,13 @@ throw new Error('no React import found');

if (match.length !== 1) {
throw new Error('more or less than one match found');
throw new Error(`more or less than one match found: ${match}\n${result.code}`);
}
}
transformFile('test/fixtures/test.jsx', {
function validateDefaultProps(result) {
if (!(/'data-name':/g).test(result.code)) {
throw new Error('data-* props need to be quoted');
}
}
transformFile('test/fixtures/test-import.jsx', {
babelrc: false,

@@ -23,6 +31,7 @@ presets: ['react'],

assertReactImport(result);
console.log('test/fixtures/test.jsx', result.code);
validateDefaultProps(result);
console.log('test/fixtures/test-import.jsx', result.code);
});
transformFile('test/fixtures/test-no-react.jsx', {
transformFile('test/fixtures/test-multiple-svg.jsx', {
babelrc: false,

@@ -35,22 +44,40 @@ presets: ['react'],

if (err) throw err;
console.log('test/fixtures/test-no-react.jsx', result.code);
assertReactImport(result);
validateDefaultProps(result);
console.log('test/fixtures/test-multiple-svg.jsx', result.code);
});
transformFile('test/fixtures/test-case-sensitive.jsx', {
transformFile('test/fixtures/test-no-react.jsx', {
babelrc: false,
presets: ['react'],
plugins: [
['../../src/index', {
caseSensitive: true,
}],
'../../src/index',
],
}, (err) => {
if (err && err.message.indexOf('match case') !== -1) {
console.log('test/fixtures/test-case-sensitive.jsx', 'Test passed: Expected case sensitive error was thrown');
} else {
throw new Error("Test failed: Expected case sensitive error wasn't thrown");
}
}, (err, result) => {
if (err) throw err;
console.log('test/fixtures/test-no-react.jsx', result.code);
assertReactImport(result);
validateDefaultProps(result);
});
if (fs.existsSync(path.resolve('./PACKAGE.JSON'))) {
transformFile('test/fixtures/test-case-sensitive.jsx', {
babelrc: false,
presets: ['react'],
plugins: [
['../../src/index', {
caseSensitive: true,
}],
],
}, (err) => {
if (err && err.message.indexOf('match case') !== -1) {
console.log('test/fixtures/test-case-sensitive.jsx', 'Test passed: Expected case sensitive error was thrown');
} else {
throw new Error("Test failed: Expected case sensitive error wasn't thrown");
}
});
} else {
console.log('# SKIP: case-sensitive check; on a case-sensitive filesystem');
}
transformFile('test/fixtures/test-no-svg-or-react.js', {

@@ -69,1 +96,22 @@ babelrc: false,

});
transformFile('test/fixtures/test-import.jsx', {
presets: ['airbnb'],
plugins: [
'../../src/index',
],
}, (err1, importResult) => {
if (err1) throw err1;
console.log('test/fixtures/test-import.jsx', importResult.code);
transformFile('test/fixtures/test-require.jsx', {
presets: ['airbnb'],
plugins: [
'../../src/index',
],
}, (err2, requireResult) => {
if (err2) throw err2;
if (importResult.code !== requireResult.code) {
throw new Error('Test failed: Import and require tests don\'t match');
}
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc