qrcode.react
Advanced tools
Comparing version 0.9.3 to 1.0.0
@@ -0,1 +1,10 @@ | ||
## [1.0.0] - 2019-11-08 | ||
### Added | ||
- Support for embedding image into QR Code. | ||
### Changed | ||
- Remove `PropTypes` in production environments. | ||
## [0.9.3] - 2019-02-17 | ||
@@ -2,0 +11,0 @@ |
188
lib/index.js
@@ -7,4 +7,6 @@ 'use strict'; | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } | ||
@@ -24,2 +26,4 @@ | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
@@ -29,4 +33,2 @@ | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -42,3 +44,6 @@ | ||
var ErrorCorrectLevel = require('qr.js/lib/ErrorCorrectLevel'); // Convert from UTF-16, forcing the use of byte-mode encoding in our QR Code. | ||
var ErrorCorrectLevel = require('qr.js/lib/ErrorCorrectLevel'); // TODO: pull this off of the QRCode class type so it matches. | ||
// Convert from UTF-16, forcing the use of byte-mode encoding in our QR Code. | ||
// This allows us to encode Hanji, Kanji, emoji, etc. Ideally we'd do more | ||
@@ -48,4 +53,2 @@ // detection and not resort to byte-mode if possible, but we're trading off | ||
// Based on http://jonisalonen.com/2012/from-utf-16-to-utf-8-in-javascript/ | ||
function convertStr(str) { | ||
@@ -88,3 +91,3 @@ var out = ''; | ||
}; | ||
var PROP_TYPES = { | ||
var PROP_TYPES = process.env.NODE_ENV !== 'production' ? { | ||
value: PropTypes.string.isRequired, | ||
@@ -95,6 +98,19 @@ size: PropTypes.number, | ||
fgColor: PropTypes.string, | ||
includeMargin: PropTypes.bool | ||
}; | ||
var MARGIN_SIZE = 4; | ||
includeMargin: PropTypes.bool, | ||
imageSettings: PropTypes.shape({ | ||
src: PropTypes.string.isRequired, | ||
height: PropTypes.number.isRequired, | ||
width: PropTypes.number.isRequired, | ||
excavate: PropTypes.bool, | ||
x: PropTypes.number, | ||
y: PropTypes.number | ||
}) | ||
} : {}; | ||
var MARGIN_SIZE = 4; // This is *very* rough estimate of max amount of QRCode allowed to be covered. | ||
// It is "wrong" in a lot of ways (area is a terrible way to estimate, it | ||
// really should be number of modules covered), but if for some reason we don't | ||
// get an explicit height or width, I'd rather default to something than throw. | ||
var DEFAULT_IMG_SCALE = 0.1; | ||
function generatePath(modules) { | ||
@@ -139,2 +155,61 @@ var margin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
return ops.join(''); | ||
} // We could just do this in generatePath, except that we want to support | ||
// non-Path2D canvas, so we need to keep it an explicit step. | ||
function excavateModules(modules, excavation) { | ||
return modules.slice().map(function (row, y) { | ||
if (y < excavation.y || y >= excavation.y + excavation.h) { | ||
return row; | ||
} | ||
return row.map(function (cell, x) { | ||
if (x < excavation.x || x >= excavation.x + excavation.w) { | ||
return cell; | ||
} | ||
return false; | ||
}); | ||
}); | ||
} | ||
function getImageSettings(props, cells) { | ||
var imageSettings = props.imageSettings, | ||
size = props.size, | ||
includeMargin = props.includeMargin; | ||
if (imageSettings == null) { | ||
return null; | ||
} | ||
var margin = includeMargin ? MARGIN_SIZE : 0; | ||
var numCells = cells.length + margin * 2; | ||
var defaultSize = Math.floor(size * DEFAULT_IMG_SCALE); | ||
var scale = numCells / size; | ||
var w = (imageSettings.width || defaultSize) * scale; | ||
var h = (imageSettings.height || defaultSize) * scale; | ||
var x = imageSettings.x == null ? cells.length / 2 - w / 2 : imageSettings.x * scale; | ||
var y = imageSettings.y == null ? cells.length / 2 - h / 2 : imageSettings.y * scale; | ||
var excavation = null; | ||
if (imageSettings.excavate) { | ||
var floorX = Math.floor(x); | ||
var floorY = Math.floor(y); | ||
var ceilW = Math.ceil(w + x - floorX); | ||
var ceilH = Math.ceil(h + y - floorY); | ||
excavation = { | ||
x: floorX, | ||
y: floorY, | ||
w: ceilW, | ||
h: ceilH | ||
}; | ||
} | ||
return { | ||
x: x, | ||
y: y, | ||
h: h, | ||
w: w, | ||
excavation: excavation | ||
}; | ||
} // For canvas we're going to switch our drawing mode based on whether or not | ||
@@ -175,4 +250,16 @@ // the environment supports Path2D. We only need the constructor to be | ||
_defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "_canvas", void 0); | ||
_defineProperty(_assertThisInitialized(_this), "_canvas", void 0); | ||
_defineProperty(_assertThisInitialized(_this), "_image", void 0); | ||
_defineProperty(_assertThisInitialized(_this), "state", { | ||
imgLoaded: false | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "handleImageLoad", function () { | ||
_this.setState({ | ||
imgLoaded: true | ||
}); | ||
}); | ||
return _this; | ||
@@ -200,3 +287,4 @@ } | ||
fgColor = _this$props.fgColor, | ||
includeMargin = _this$props.includeMargin; // We'll use type===-1 to force QRCode to automatically pick the best type | ||
includeMargin = _this$props.includeMargin, | ||
imageSettings = _this$props.imageSettings; // We'll use type===-1 to force QRCode to automatically pick the best type | ||
@@ -222,3 +310,10 @@ var qrcode = new QRCodeImpl(-1, ErrorCorrectLevel[level]); | ||
var margin = includeMargin ? MARGIN_SIZE : 0; | ||
var numCells = cells.length + margin * 2; // We're going to scale this so that the number of drawable units | ||
var numCells = cells.length + margin * 2; | ||
var calculatedImageSettings = getImageSettings(this.props, cells); | ||
if (imageSettings != null && calculatedImageSettings != null) { | ||
if (calculatedImageSettings.excavation != null) { | ||
cells = excavateModules(cells, calculatedImageSettings.excavation); | ||
} | ||
} // We're going to scale this so that the number of drawable units | ||
// matches the number of cells. This avoids rounding issues, but does | ||
@@ -228,2 +323,3 @@ // result in some potentially unwanted single pixel issues between | ||
var pixelRatio = window.devicePixelRatio || 1; | ||
@@ -250,2 +346,6 @@ canvas.height = canvas.width = size * pixelRatio; | ||
} | ||
if (this.state.imgLoaded && this._image && calculatedImageSettings != null) { | ||
ctx.drawImage(this._image, calculatedImageSettings.x + margin, calculatedImageSettings.y + margin, calculatedImageSettings.w, calculatedImageSettings.h); | ||
} | ||
} | ||
@@ -266,3 +366,4 @@ } | ||
includeMargin = _this$props2.includeMargin, | ||
otherProps = _objectWithoutProperties(_this$props2, ["value", "size", "level", "bgColor", "fgColor", "style", "includeMargin"]); | ||
imageSettings = _this$props2.imageSettings, | ||
otherProps = _objectWithoutProperties(_this$props2, ["value", "size", "level", "bgColor", "fgColor", "style", "includeMargin", "imageSettings"]); | ||
@@ -274,10 +375,26 @@ var canvasStyle = _objectSpread({ | ||
return React.createElement("canvas", _extends({ | ||
var img = null; | ||
var imgSrc = imageSettings && imageSettings.src; | ||
if (imageSettings != null && imgSrc != null) { | ||
img = React.createElement("img", { | ||
src: imgSrc, | ||
style: { | ||
display: 'none' | ||
}, | ||
onLoad: this.handleImageLoad, | ||
ref: function ref(_ref) { | ||
return _this2._image = _ref; | ||
} | ||
}); | ||
} | ||
return React.createElement(React.Fragment, null, React.createElement("canvas", _extends({ | ||
style: canvasStyle, | ||
height: size, | ||
width: size, | ||
ref: function ref(_ref) { | ||
return _this2._canvas = _ref; | ||
ref: function ref(_ref2) { | ||
return _this2._canvas = _ref2; | ||
} | ||
}, otherProps)); | ||
}, otherProps)), img); | ||
} | ||
@@ -291,3 +408,5 @@ }]); | ||
_defineProperty(QRCodeCanvas, "propTypes", PROP_TYPES); | ||
if (process.env.NODE_ENV !== 'production') { | ||
QRCodeCanvas.propTypes = PROP_TYPES; | ||
} | ||
@@ -315,3 +434,4 @@ var QRCodeSVG = | ||
includeMargin = _this$props3.includeMargin, | ||
otherProps = _objectWithoutProperties(_this$props3, ["value", "size", "level", "bgColor", "fgColor", "includeMargin"]); // We'll use type===-1 to force QRCode to automatically pick the best type | ||
imageSettings = _this$props3.imageSettings, | ||
otherProps = _objectWithoutProperties(_this$props3, ["value", "size", "level", "bgColor", "fgColor", "includeMargin", "imageSettings"]); // We'll use type===-1 to force QRCode to automatically pick the best type | ||
@@ -328,3 +448,21 @@ | ||
var margin = includeMargin ? MARGIN_SIZE : 0; // Drawing strategy: instead of a rect per module, we're going to create a | ||
var margin = includeMargin ? MARGIN_SIZE : 0; | ||
var numCells = cells.length + margin * 2; | ||
var calculatedImageSettings = getImageSettings(this.props, cells); | ||
var image = null; | ||
if (imageSettings != null && calculatedImageSettings != null) { | ||
if (calculatedImageSettings.excavation != null) { | ||
cells = excavateModules(cells, calculatedImageSettings.excavation); | ||
} | ||
image = React.createElement("image", { | ||
xlinkHref: imageSettings.src, | ||
height: calculatedImageSettings.h, | ||
width: calculatedImageSettings.w, | ||
x: calculatedImageSettings.x + margin, | ||
y: calculatedImageSettings.y + margin, | ||
preserveAspectRatio: "none" | ||
}); | ||
} // Drawing strategy: instead of a rect per module, we're going to create a | ||
// single path for the dark modules and layer that on top of a light rect, | ||
@@ -336,4 +474,4 @@ // for a total of 2 DOM nodes. We pay a bit more in string concat but that's | ||
var fgPath = generatePath(cells, margin); | ||
var numCells = cells.length + margin * 2; | ||
return React.createElement("svg", _extends({ | ||
@@ -350,3 +488,3 @@ shapeRendering: "crispEdges", | ||
d: fgPath | ||
})); | ||
}), image); | ||
} | ||
@@ -360,3 +498,5 @@ }]); | ||
_defineProperty(QRCodeSVG, "propTypes", PROP_TYPES); | ||
if (process.env.NODE_ENV !== 'production') { | ||
QRCodeSVG.propTypes = PROP_TYPES; | ||
} | ||
@@ -363,0 +503,0 @@ var QRCode = function QRCode(props) { |
{ | ||
"name": "qrcode.react", | ||
"version": "0.9.3", | ||
"version": "1.0.0", | ||
"description": "React component to generate QR codes", | ||
@@ -15,3 +15,3 @@ "keywords": [ | ||
"lint": "eslint .", | ||
"pretty": "prettier --write {*,.*}.{js,json} **/*.{js,json}", | ||
"pretty": "prettier --write '{*,.*}.{js,json}' '**/*.{js,json}'", | ||
"prepublish": "flow && make clean && make all", | ||
@@ -32,2 +32,3 @@ "prepublish-docs": "make clean && make all", | ||
"dependencies": { | ||
"loose-envify": "^1.4.0", | ||
"prop-types": "^15.6.0", | ||
@@ -49,10 +50,10 @@ "qr.js": "0.0.0" | ||
"babel-loader": "^8.0.0", | ||
"eslint": "^5.4.0", | ||
"eslint-config-prettier": "^3.0.1", | ||
"eslint-plugin-flowtype": "^3.2.0", | ||
"eslint": "^6.6.0", | ||
"eslint-config-prettier": "^6.5.0", | ||
"eslint-plugin-flowtype": "^4.3.0", | ||
"eslint-plugin-prettier": "^3.0.0", | ||
"eslint-plugin-react": "^7.6.1", | ||
"flow-bin": "^0.89.0", | ||
"flow-bin": "^0.111.3", | ||
"gh-pages": "^2.0.1", | ||
"prettier": "^1.1.0", | ||
"prettier": "1.19.0", | ||
"react": "^16.2.0", | ||
@@ -62,3 +63,8 @@ "react-dom": "^16.2.0", | ||
"webpack-cli": "^3.1.2" | ||
}, | ||
"browserify": { | ||
"transform": [ | ||
"loose-envify" | ||
] | ||
} | ||
} |
@@ -34,3 +34,15 @@ # qrcode.react | ||
`includeMargin` | `boolean` | `false` | ||
`imageSettings` | `object` (see below) | | ||
### `imageSettings` | ||
field | type | default value | ||
-----------|----------------------|-------------- | ||
`src` | `string` | | ||
`x` | `number` | none, will center | ||
`y` | `number` | none, will center | ||
`height` | `number` | 10% of `size` | ||
`width` | `number` | 10% of `size` | ||
`excavate` | `boolean` | `false` | ||
## Custom Styles | ||
@@ -37,0 +49,0 @@ |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
25841
405
1
57
4
6
+ Addedloose-envify@^1.4.0