Bugfix: Email addressparser

Cleanup vendor scripts
This commit is contained in:
djmaze 2020-08-12 11:49:40 +02:00
parent aaf4933b0a
commit a8ef5ec75b
11 changed files with 651 additions and 968 deletions

View file

@ -75,23 +75,23 @@ Things might work in Edge 15-18, Firefox 47-62 and Chrome 54-68 due to one polyf
|js/* |1.14.0 |native |gzip 1.14 |gzip |
|----------- |--------: |--------: |--------: |--------: |
|admin.js |2.130.942 |1.133.275 | 485.481 | 274.632 |
|app.js |4.184.455 |2.844.189 | 932.725 | 664.075 |
|admin.js |2.130.942 |1.130.247 | 485.481 | 273.277 |
|app.js |4.184.455 |2.840.968 | 932.725 | 662.061 |
|boot.js | 671.522 | 44.029 | 169.502 | 15.460 |
|libs.js | 647.614 | 431.049 | 194.728 | 132.315 |
|libs.js | 647.614 | 426.949 | 194.728 | 131.409 |
|polyfills.js | 325.834 | 0 | 71.825 | 0 |
|TOTAL js |7.960.367 |4.452.542 |1.854.261 |1.086.482 |
|TOTAL js |7.960.367 |4.442.193 |1.854.261 |1.082.207 |
|js/min/* |1.14.0 |native |gzip 1.14 |gzip |
|--------------- |--------: |--------: |--------: |--------: |
|admin.min.js | 252.147 | 153.095 | 73.657 | 43.734 |
|app.min.js | 511.202 | 378.695 |140.462 | 99.511 |
|admin.min.js | 252.147 | 152.759 | 73.657 | 43.564 |
|app.min.js | 511.202 | 378.335 |140.462 | 99.341 |
|boot.min.js | 66.007 | 5.589 | 22.567 | 2.333 |
|libs.min.js | 572.545 | 387.636 |176.720 |122.519 |
|libs.min.js | 572.545 | 385.139 |176.720 |121.907 |
|polyfills.min.js | 32.452 | 0 | 11.312 | 0 |
|TOTAL js/min |1.434.353 | 925.015 |424.718 |268.097 |
|TOTAL js/min |1.434.353 | 921.822 |424.718 |267.145 |
509.338 bytes (156.621 gzip) is not much, but it feels faster.
512.531 bytes (157.573 gzip) is not much, but it feels faster.
|css/* |1.14.0 |native |

View file

@ -7,19 +7,15 @@ import { Mime } from 'Common/Mime';
const
$ = jQuery,
$div = $('<div></div>'),
isArray = Array.isArray;
var htmlspecialchars = ((de,se,gt,lt,sq,dq,bt) => {
return (str, quote_style = 3, double_encode = true) => {
str = (''+str)
.replace(double_encode?de:se,'&amp;')
.replace(gt,'&lt;')
.replace(lt,'&gt;')
.replace(bt,'&#x60;');
if (quote_style & 1) { str = str.replace(sq,'&#x27;'); }
return (quote_style & 2) ? str.replace(dq,'&quot;') : str;
};
})(/&/g,/&(?![\w#]+;)/gi,/</g,/>/g,/'/g,/"/g,/`/g);
isArray = Array.isArray,
htmlmap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;'
},
htmlspecialchars = str => (''+str).replace(/[&<>"']/g, m => htmlmap[m]);
/**
* @param {*} value
@ -89,15 +85,13 @@ export function simpleQueryParser(queryString) {
* @returns {string}
*/
export function fakeMd5(len = 32) {
const line = '0123456789abcdefghijklmnopqrstuvwxyz',
lineLen = line.length;
const line = '0123456789abcdefghijklmnopqrstuvwxyz';
len = pInt(len);
let result = '';
while (result.length < len) {
result += line.substr(Math.round(Math.random() * lineLen), 1);
}
while (len--)
result += line.substr(Math.round(Math.random() * 36), 1);
return result;
}

22
dev/External/ko.js vendored
View file

@ -747,35 +747,33 @@ ko.bindingHandlers.emailsTags = {
$el = $(element),
fValue = fValueAccessor(),
fAllBindings = fAllBindingsAccessor(),
fAutoCompleteSource = fAllBindings.autoCompleteSource || null,
inputDelimiters = [',', ';', '\n'],
fFocusCallback = (value) => {
if (fValue && fValue.focused) {
fValue.focused(!!value);
}
};
inputDelimiters = [',', ';', '\n'];
$el.inputosaurus({
parseOnBlur: true,
allowDragAndDrop: true,
focusCallback: fFocusCallback,
focusCallback: value => {
if (fValue && fValue.focused) {
fValue.focused(!!value);
}
},
inputDelimiters: inputDelimiters,
autoCompleteSource: fAutoCompleteSource,
splitHook: (value) => {
autoCompleteSource: fAllBindings.autoCompleteSource || null,
splitHook: value => {
const v = value.trim();
if (v && inputDelimiters.includes(v.substr(-1))) {
return EmailModel.splitEmailLine(value);
}
return null;
},
parseHook: (input) =>
parseHook: input =>
input.map(inputValue => {
const values = EmailModel.parseEmailLine(inputValue);
return values.length ? values : inputValue;
}).flat(Infinity).map(
item => (item.toLine ? [item.toLine(false), item] : [item, null])
),
change: (event) => {
change: event => {
$el.data('EmailsTagsValue', event.target.value);
fValue(event.target.value);
}

View file

@ -1,4 +1,4 @@
import { encodeHtml, isNonEmptyArray } from 'Common/Utils';
import { encodeHtml } from 'Common/Utils';
'use strict';
@ -64,12 +64,10 @@ function _handleAddress(tokens) {
comment: [],
group: [],
text: []
// Filter out <addresses>, (comments) and regular text
};
for (var i = 0, len = tokens.length; i < len; i++) {
var token = tokens[i];
// Filter out <addresses>, (comments) and regular text
tokens.forEach(token => {
if (token.type === 'operator') {
switch (token.value) {
case '<':
@ -85,12 +83,10 @@ function _handleAddress(tokens) {
default:
state = 'text';
}
} else {
if (token.value) {
data[state].push(token.value);
}
} else if (token.value) {
data[state].push(token.value);
}
}
});
// If there is no text but a comment, replace the two
if (!data.text.length && data.comment.length) {
@ -108,25 +104,25 @@ function _handleAddress(tokens) {
} else {
// If no address was found, try to detect one from regular text
if (!data.address.length && data.text.length) {
for (var _i = data.text.length - 1; _i >= 0; _i--) {
if (data.text[_i].match(/^[^@\s]+@[^@\s]+$/)) {
data.address = data.text.splice(_i, 1);
var i = data.text.length;
while (i--) {
if (data.text[i].match(/^[^@\s]+@[^@\s]+$/)) {
data.address = data.text.splice(i, 1);
break;
}
}
var _regexHandler = function _regexHandler(address) {
if (!data.address.length) {
data.address = [address.trim()];
return ' ';
}
return address;
};
// still no address
if (!data.address.length) {
for (var _i2 = data.text.length - 1; _i2 >= 0; _i2--) {
data.text[_i2] = data.text[_i2].replace(/\s*\b[^@\s]+@[^@\s]+\b\s*/, _regexHandler).trim();
i = data.text.length;
while (i--) {
data.text[i] = data.text[i].replace(/\s*\b[^@\s]+@[^@\s]+\b\s*/, address => {
if (!data.address.length) {
data.address = [address.trim()];
return '';
}
return address.trim();
});
if (data.address.length) {
break;
}
@ -202,8 +198,8 @@ class Tokenizer
}
tokenize() {
var list = [], i = this.str.length;
while (i--) this.checkChar(this.str[i]);
var list = [];
[...this.str].forEach(c => this.checkChar(c));
this.list.forEach(node => {
node.value = (node.value || '').toString().trim();
@ -420,7 +416,7 @@ class EmailModel {
static splitEmailLine(line) {
const parsedResult = addressparser(line);
if (isNonEmptyArray(parsedResult)) {
if (parsedResult.length) {
const result = [];
let exists = false;
parsedResult.forEach((item) => {
@ -443,7 +439,7 @@ class EmailModel {
static parseEmailLine(line) {
const parsedResult = addressparser(line);
if (isNonEmptyArray(parsedResult)) {
if (parsedResult.length) {
return parsedResult.map(item =>
item.address ? new EmailModel(item.address.replace(/^[<]+(.*)[>]+$/g, '$1'), item.name || '') : null
).filter(value => !!value);
@ -463,7 +459,7 @@ class EmailModel {
}
const result = addressparser(emailAddress);
if (isNonEmptyArray(result) && result[0]) {
if (result.length) {
this.name = result[0].name || '';
this.email = result[0].address || '';
this.clearDuplicateName();

View file

@ -1401,7 +1401,7 @@ class ComposePopupView extends AbstractViewNext {
}
});
this.addAttachmentEnabled(true).dragAndDropEnabled(oJua.isDragAndDropSupported());
this.addAttachmentEnabled(true).dragAndDropEnabled(true);
} else {
this.addAttachmentEnabled(false).dragAndDropEnabled(false);
}

View file

@ -18,7 +18,7 @@
*/
(function($) {
($ => {
var inputosaurustext = {
@ -39,22 +39,12 @@
// the value tags are created on the fly when an inputDelimiter is detected
inputDelimiters : [',', ';'],
// this separator is used to rejoin all input items back to the value of the original <input>
outputDelimiter : ',',
allowDuplicates : false,
allowDragAndDrop : true,
focusCallback : null,
parseOnBlur : false,
// optional wrapper for widget
wrapperElement : null,
width : null,
// simply passing an autoComplete source (array, string or function) will instantiate autocomplete functionality
autoCompleteSource : '',
@ -65,17 +55,14 @@
// the array of tag names is passed and expected to be returned as an array after manipulation
parseHook : null,
elementHook : null,
// define a placeholder to display when the input is empty
placeholder: null
splitHook : null
},
_create: function() {
var widget = this,
els = {},
o = widget.options,
placeholder = o.placeholder || this.element.attr('placeholder') || null;
placeholder = this.element.attr('placeholder') || null;
this._chosenValues = [];
@ -85,7 +72,7 @@
if (this.options.allowDragAndDrop)
{
els.ul.droppable({
'drop': function(event, ui) {
'drop': (event, ui) => {
ui.draggable.addClass('inputosaurus-dropped');
els.input.val(ui.draggable.data('inputosaurus-value'));
@ -106,9 +93,9 @@
els.origInputCont = $('<li class="inputosaurus-input-hidden inputosaurus-required"></li>');
els.lastEdit = '';
els.input.on('focus', function () {
els.input.on('focus', () => {
widget._focusTrigger(true);
}).on('blur', function () {
}).on('blur', () => {
widget._focusTrigger(false);
});
@ -116,21 +103,15 @@
if (placeholder) {
o.placeholder = placeholder;
els.input.attr('placeholder', o.placeholder);
if (o.width) {
els.input.css('min-width', o.width - 50);
}
}
o.wrapperElement && o.wrapperElement.append(els.ul);
this.element.replaceWith(o.wrapperElement || els.ul);
this.element.replaceWith(els.ul);
els.origInputCont.append(this.element).hide();
els.inputCont.append(els.input);
els.ul.append(els.inputCont);
els.ul.append(els.origInputCont);
o.width && els.ul.css('width', o.width);
this.elements = els;
widget._attachEvents();
@ -148,13 +129,10 @@
_focusTrigger : function (bValue) {
var widget = this;
window.clearTimeout(this._focusTriggerTimer);
this._focusTriggerTimer = window.setTimeout(function () {
clearTimeout(this._focusTriggerTimer);
this._focusTriggerTimer = setTimeout(() => {
widget.elements.ul[!bValue ? 'removeClass' : 'addClass']('inputosaurus-focused');
if (widget.options.focusCallback)
{
widget.options.focusCallback(bValue);
}
widget.options.focusCallback(bValue);
}, 10);
},
@ -169,7 +147,7 @@
source : this.options.autoCompleteSource,
minLength : 1,
autoFocus : true,
select : function(ev, ui){
select : (ev, ui) => {
ev.preventDefault();
widget.elements.input.val(ui.item.value);
widget.parseInput();
@ -190,9 +168,7 @@
}
}
},
focus: function () {
return false;
}
focus: () => false
});
}
},
@ -210,12 +186,6 @@
}
},
/*_closeAutoCompleteMenu : function() {
if(this.options.autoCompleteSource){
this.elements.input.autocomplete('close');
}
},*/
parseInput : function(ev) {
var widget = (ev && ev.data.widget) || this,
val,
@ -226,11 +196,7 @@
val = widget.elements.input.val();
if (val) {
if ($.isFunction(widget.options.splitHook)) {
hook = widget.options.splitHook(val);
} else {
delimiterFound = widget._containsDelimiter(val);
}
hook = widget.options.splitHook(val);
}
if (hook) {
@ -246,15 +212,13 @@
values.push(val);
}
$.isFunction(widget.options.parseHook) && (values = widget.options.parseHook(values));
values = widget.options.parseHook(values);
if(values.length){
widget._setChosen(values);
widget.elements.input.val('');
widget._resizeInput();
}
widget._resetPlaceholder();
},
_inputFocus : function(ev) {
@ -284,7 +248,7 @@
// reposition autoComplete menu as <ul> grows and shrinks vertically
if(widget.options.autoCompleteSource){
setTimeout(function(){widget._autoCompleteMenuPosition.call(widget);}, 200);
setTimeout(()=>widget._autoCompleteMenuPosition.call(widget), 200);
}
},
@ -297,7 +261,7 @@
var widget = (ev && ev.data.widget) || this;
inputosaurustext.fakeSpan.text(widget.elements.input.val());
// window.setTimeout(function () {
// setTimeout(function () {
var txtWidth = 25 + inputosaurustext.fakeSpan.width();
txtWidth = txtWidth > 50 ? txtWidth : 50;
txtWidth = txtWidth < 500 ? txtWidth : 500;
@ -305,18 +269,6 @@
// }, 1);
},
// resets placeholder on representative input
_resetPlaceholder: function () {
var placeholder = this.options.placeholder,
input = this.elements.input,
width = this.options.width || 'inherit';
if (placeholder && this.element.val().length === 0) {
input.attr('placeholder', placeholder).css('min-width', width - 50)
}else {
input.attr('placeholder', '').css('min-width', 'inherit')
}
},
// if our input contains no value and backspace has been pressed, select the last tag
_inputBackspace : function(ev) {
var widget = (ev && ev.data.widget) || this,
@ -349,7 +301,7 @@
next = false
;
$.each(widget._chosenValues, function(i,v) {
$.each(widget._chosenValues, (i,v) => {
if (v.key === tagKey)
{
tagName = v.value;
@ -369,15 +321,13 @@
$li.after(widget.elements.inputCont);
widget.elements.input.val(tagName);
window.setTimeout(function () {
widget.elements.input.select();
}, 100);
setTimeout(() => widget.elements.input.select(), 100);
widget._removeTag(ev);
widget._resizeInput(ev);
},
_tagKeypress : function(ev) {
_tagKeypress : ev => {
var widget = ev.data.widget;
switch(ev.which){
@ -439,7 +389,7 @@
var found = false;
$.each(this.options.inputDelimiters, function(k,v) {
$.each(this.options.inputDelimiters, (k,v) => {
if(tagStr.indexOf(v) !== -1){
found = v;
}
@ -455,7 +405,7 @@
return false;
}
$.each(valArr, function(k,a) {
$.each(valArr, (k,a) => {
var v = '', exists = false,
lastIndex = -1,
obj = {
@ -466,7 +416,7 @@
v = $.trim(a[0]);
$.each(self._chosenValues, function(kk, vv) {
$.each(self._chosenValues, (kk, vv) => {
if (vv.value === self.elements.lastEdit)
{
lastIndex = kk;
@ -475,7 +425,7 @@
vv.value === v && (exists = true);
});
if(v !== '' && a && a[1] && (!exists || self.options.allowDuplicates)){
if(v !== '' && a && a[1] && !exists){
obj.key = 'mi_' + Math.random().toString( 16 ).slice( 2, 10 );
obj.value = v;
@ -505,11 +455,10 @@
},
_buildValue : function() {
var widget = this,
value = '';
var value = '';
$.each(this._chosenValues, function(k,v) {
value += value.length ? widget.options.outputDelimiter + v.value : v.value;
$.each(this._chosenValues, (k,v) => {
value += value.length ? ',' + v.value : v.value;
});
return value;
@ -542,14 +491,10 @@
$li.draggable({
'revert': 'invalid',
'revertDuration': 200,
'start': function(event, ui) {
ui.helper.__widget = widget;
}
'start': (event, ui) => ui.helper.__widget = widget
});
}
$.isFunction(this.options.elementHook) && (this.options.elementHook($li, obj));
return $li;
}
},
@ -559,7 +504,7 @@
this.elements.ul.find('li:not(.inputosaurus-required)').remove();
$.each(this._chosenValues, function(k, v) {
$.each(this._chosenValues, (k, v) => {
var el = self._createTag(v.value, v.key, v.obj);
if (el) {
self.elements.ul.find('li.inputosaurus-input').before(el);
@ -573,7 +518,7 @@
widget = (ev && ev.data.widget) || this;
$.each(widget._chosenValues, function(k,v) {
$.each(widget._chosenValues, (k,v) => {
if(key === v.key){
indexFound = k;
}
@ -584,9 +529,7 @@
widget._setValue(widget._buildValue());
$(ev.currentTarget).closest('li').remove();
window.setTimeout(function () {
widget.elements.input.focus();
}, 100);
setTimeout(() => widget.elements.input.focus(), 100);
},
_removeDraggedTag : function ($li) {
@ -596,7 +539,7 @@
indexFound = false
;
$.each(widget._chosenValues, function(k,v) {
$.each(widget._chosenValues, (k,v) => {
if (key === v.key) {
indexFound = k;
@ -634,12 +577,10 @@
}
},
_tagFocus : function(ev) {
$(ev.currentTarget).parent()[ev.type === 'focusout' ? 'removeClass' : 'addClass']('inputosaurus-selected');
},
_tagFocus : ev => $(ev.currentTarget).parent()[ev.type === 'focusout' ? 'removeClass' : 'addClass']('inputosaurus-selected'),
refresh : function() {
var delim = this.options.outputDelimiter,
var delim = ',',
val = this.element.val(),
values = [];
@ -659,7 +600,7 @@
if (values.length) {
this._chosenValues = [];
$.isFunction(this.options.parseHook) && (values = this.options.parseHook(values));
values = this.options.parseHook(values);
this._setChosen(values);
this._renderTags();

1067
vendors/jua/jua.js vendored

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -44,7 +44,11 @@
// parse and assign shortcut
function assignKey(key, scope, method){
var keys = getKeys(key), mods;
key = key.replace(/\s/g, '');
var keys = key.split(','), mods;
if ((keys[keys.length - 1]) == '') {
keys[keys.length - 2] += ',';
}
if (method === undefined) {
method = scope;
scope = 'all';
@ -56,12 +60,12 @@
mods = [];
key = keys[i].split('+');
if (key.length > 1){
mods = getMods(key);
mods = key.slice(0, key.length - 1);
mods.forEach((mod, mi) => mods[mi] = _MODIFIERS[mod]);
key = [key[key.length-1]];
}
// convert to keycode and...
key = key[0];
key = code(key);
key = code(key[0]);
// ...store handler
if (!(key in _handlers)) _handlers[key] = [];
@ -78,25 +82,7 @@
// initialize key.<modifier> to false
for(k in _MODIFIERS) assignKey[k] = false;
// set current scope (default 'all')
const
setScope = scope => { _scope = scope || 'all' },
getScope = () => _scope || 'all',
// abstract key logic for assign and unassign
getKeys = key => {
key = key.replace(/\s/g, '');
var keys = key.split(',');
if ((keys[keys.length - 1]) == '') {
keys[keys.length - 2] += ',';
}
return keys;
},
// abstract mods logic for assign and unassign
getMods = key => {
var mods = key.slice(0, key.length - 1);
mods.forEach((mod, mi) => mods[mi] = _MODIFIERS[mod]);
return mods;
};
const getScope = () => _scope || 'all';
// set the handlers globally on document
document.addEventListener('keydown', event => {
@ -170,7 +156,7 @@
// set window.key and window.key.set/get, and the default filter
global.key = assignKey;
global.key.setScope = setScope;
global.key.setScope = scope => { _scope = scope || 'all' };
global.key.getScope = getScope;
global.key.filter = event => {
var tagName = event.target.tagName;

263
vendors/qr.js/qr.js vendored
View file

@ -20,10 +20,6 @@
16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
];
// Default MIME type.
var DEFAULT_MIME = 'image/png';
// MIME used to initiate a browser download prompt when `qr.save` is called.
var DOWNLOAD_MIME = 'image/octet-stream';
// There are four elements per version. The first two indicate the number of blocks, then the
// data width, and finally the ECC width.
var ECC_BLOCKS = [
@ -131,8 +127,6 @@
0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5,
0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69
];
// Mode for node.js file system file writes.
var WRITE_MODE = parseInt('0666', 8);
// Private variables
// -----------------
@ -153,16 +147,10 @@
var frameBuffer = [];
// Fixed part of the image.
var frameMask = [];
// File system within the node.js environment.
var fs;
// Constructor for `img` elements in the node.js environment.
var Image;
// Indicates whether or not this script is running in node.js.
var inNode = false;
// Generator polynomial.
var polynomial = [];
// Save the previous value of the `qr` variable.
var previousQr = root.qr;
// Data input buffer.
var stringBuffer = [];
// Version for the data.
@ -173,92 +161,14 @@
// Private functions
// -----------------
// Create a new canvas using `document.createElement` unless script is running in node.js, in
// which case the `canvas` module is used.
function createCanvas() {
return inNode ? new Canvas() : root.document.createElement('canvas');
}
// Create a new image using `document.createElement` unless script is running in node.js, in
// which case the `canvas` module is used.
function createImage() {
return inNode ? new Image() : root.document.createElement('img');
}
// Force the canvas image to be downloaded in the browser.
// Optionally, a `callback` function can be specified which will be called upon completed. Since
// this is not an asynchronous operation, this is merely convenient and helps simplify the
// calling code.
function download(cvs, data, callback) {
var mime = data.mime || DEFAULT_MIME;
root.location.href = cvs.toDataURL(mime).replace(mime, DOWNLOAD_MIME);
if (typeof callback === 'function') callback();
}
// Normalize the `data` that is provided to the main API.
function normalizeData(data) {
const normalizeData = data => {
if (typeof data === 'string') data = { value: data };
return data || {};
}
// Asynchronously write the data of the rendered canvas to a given file path.
function writeFile(cvs, data, callback) {
if (typeof data.path !== 'string') {
return callback(new TypeError('Invalid path type: ' + typeof data.path));
}
var fd, buff;
// Write the buffer to the open file stream once both prerequisites are met.
function writeBuffer() {
fs.write(fd, buff, 0, buff.length, 0, function (error) {
fs.close(fd);
callback(error);
});
}
// Create a buffer of the canvas' data.
cvs.toBuffer(function (error, _buff) {
if (error) return callback(error);
buff = _buff;
if (fd) {
writeBuffer();
}
});
// Open a stream for the file to be written.
fs.open(data.path, 'w', WRITE_MODE, function (error, _fd) {
if (error) return callback(error);
fd = _fd;
if (buff) {
writeBuffer();
}
});
}
// Write the data of the rendered canvas to a given file path.
function writeFileSync(cvs, data) {
if (typeof data.path !== 'string') {
throw new TypeError('Invalid path type: ' + typeof data.path);
}
var buff = cvs.toBuffer();
var fd = fs.openSync(data.path, 'w', WRITE_MODE);
try {
fs.writeSync(fd, buff, 0, buff.length, 0);
} finally {
fs.closeSync(fd);
}
}
},
// Set bit to indicate cell in frame is immutable (symmetric around diagonal).
function setMask(x, y) {
setMask = (x, y) => {
var bit;
if (x > y) {
@ -274,11 +184,11 @@
bit += x;
frameMask[bit] = 1;
}
},
// Enter alignment pattern. Foreground colour to frame, background to mask. Frame will be merged
// with mask later.
function addAlignment(x, y) {
addAlignment = (x, y) => {
var i;
frameBuffer[x + width * y] = 1;
@ -296,21 +206,21 @@
setMask(x - i, y - 1);
setMask(x + i, y + 1);
}
}
},
// Exponentiation mod N.
function modN(x) {
modN = x => {
while (x >= 255) {
x -= 255;
x = (x >> 8) + (x & 255);
}
return x;
}
},
// Calculate and append `ecc` data to the `data` block. If block is in the string buffer the
// indices to buffers are used.
function appendData(data, dataLength, ecc, eccLength) {
appendData = (data, dataLength, ecc, eccLength) => {
var bit, i, j;
for (i = 0; i < eccLength; i++) {
@ -334,10 +244,10 @@
stringBuffer[ecc + eccLength - 1] = bit === 255 ? 0 :
GALOIS_EXPONENT[modN(bit + polynomial[0])];
}
}
},
// Check mask since symmetricals use half.
function isMasked(x, y) {
isMasked = (x, y) => {
var bit;
if (x > y) {
@ -352,10 +262,10 @@
bit += x;
return frameMask[bit] === 1;
}
},
// Apply the selected mask out of the 8 options.
function applyMask(mask) {
applyMask = mask => {
var x, y, r3x, r3y;
switch (mask) {
@ -463,11 +373,11 @@
break;
}
}
},
// Using the table for the length of each run, calculate the amount of bad image. Long runs or
// those that look like finders are called twice; once for X and Y.
function getBadRuns(length) {
getBadRuns = length => {
var badRuns = 0;
var i;
@ -492,10 +402,10 @@
}
return badRuns;
}
},
// Calculate how bad the masked image is (e.g. blocks, imbalance, runs, or finders).
function checkBadness() {
checkBadness = () => {
var b, b1, bad, big, bw, count, h, x, y;
bad = bw = count = 0;
@ -566,10 +476,10 @@
}
return bad;
}
},
// Generate the encoded QR image for the string provided.
function generateFrame(str) {
generateFrame = str => {
var i, j, k, m, t, v, x, y;
// Find the smallest version that fits the string.
@ -975,13 +885,13 @@
// Finally, return the image data.
return frameBuffer;
}
};
// qr.js setup
// -----------
// Build the publicly exposed API.
var qr = {
root.qr = {
// Constants
// ---------
@ -992,12 +902,13 @@
// QR functions
// ------------
// Generate the QR code using the data provided and render it on to a `<canvas>` element.
// Generate the QR code using the data provided and render it on to a `<canvas>` element before
// returning its data URI.
// If no `<canvas>` element is specified in the argument provided a new one will be created and
// used.
// ECC (error correction capacity) determines how many intential errors are contained in the QR
// code.
canvas: function(data) {
toDataURL: data => {
data = normalizeData(data);
// Module size of the generated QR code (i.e. 1-10).
@ -1006,7 +917,7 @@
size *= 25;
// `<canvas>` element used to render the QR code.
var cvs = data.canvas || createCanvas();
var cvs = inNode ? new Canvas() : document.createElement('canvas');
// Retreive the 2D context of the canvas.
var c2d = cvs.getContext('2d');
// Ensure the canvas has the correct dimensions.
@ -1047,131 +958,9 @@
}
}
return cvs;
},
// Generate the QR code using the data provided and render it on to a `<img>` element.
// If no `<img>` element is specified in the argument provided a new one will be created and
// used.
// ECC (error correction capacity) determines how many intential errors are contained in the QR
// code.
image: function(data) {
data = normalizeData(data);
// `<canvas>` element only which the QR code is rendered.
var cvs = this.canvas(data);
// `<img>` element used to display the QR code.
var img = data.image || createImage();
// Apply the QR code to `img`.
img.src = cvs.toDataURL(data.mime || DEFAULT_MIME);
img.height = cvs.height;
img.width = cvs.width;
return img;
},
// Generate the QR code using the data provided and render it on to a `<canvas>` element and
// save it as an image file.
// If no `<canvas>` element is specified in the argument provided a new one will be created and
// used.
// ECC (error correction capacity) determines how many intential errors are contained in the QR
// code.
// If called in a browser the `path` property/argument is ignored and will simply prompt the
// user to choose a location and file name. However, if called within node.js the file will be
// saved to specified path.
// A `callback` function must be provided which will be called once the saving process has
// started. If an error occurs it will be passed as the first argument to this function,
// otherwise this argument will be `null`.
save: function(data, path, callback) {
data = normalizeData(data);
switch (typeof path) {
case 'function':
callback = path;
path = null;
break;
case 'string':
data.path = path;
break;
}
// Callback function is required.
if (typeof callback !== 'function') {
throw new TypeError('Invalid callback type: ' + typeof callback);
}
var completed = false;
// `<canvas>` element only which the QR code is rendered.
var cvs = this.canvas(data);
// Simple function to try and ensure that the `callback` function is only called once.
function done(error) {
if (!completed) {
completed = true;
callback(error);
}
}
if (inNode) {
writeFile(cvs, data, done);
} else {
download(cvs, data, done);
}
},
// Generate the QR code using the data provided and render it on to a `<canvas>` element and
// save it as an image file.
// If no `<canvas>` element is specified in the argument provided a new one will be created and
// used.
// ECC (error correction capacity) determines how many intential errors are contained in the QR
// code.
// If called in a browser the `path` property/argument is ignored and will simply prompt the
// user to choose a location and file name. However, if called within node.js the file will be
// saved to specified path.
saveSync: function(data, path) {
data = normalizeData(data);
if (typeof path === 'string') data.path = path;
// `<canvas>` element only which the QR code is rendered.
var cvs = this.canvas(data);
if (inNode) {
writeFileSync(cvs, data);
} else {
download(cvs, data);
}
},
// Generate the QR code using the data provided and render it on to a `<canvas>` element before
// returning its data URI.
// If no `<canvas>` element is specified in the argument provided a new one will be created and
// used.
// ECC (error correction capacity) determines how many intential errors are contained in the QR
// code.
toDataURL: function(data) {
data = normalizeData(data);
return this.canvas(data).toDataURL(data.mime || DEFAULT_MIME);
},
// Utility functions
// -----------------
// Run qr.js in *noConflict* mode, returning the `qr` variable to its previous owner.
// Returns a reference to `qr`.
noConflict: function() {
root.qr = previousQr;
return this;
return cvs.toDataURL('image/png');
}
};
// Support
// -------
root.qr = qr;
})(this);

File diff suppressed because one or more lines are too long