Updated dependencies and linted

This commit is contained in:
n1474335 2017-07-24 13:49:16 +00:00
parent 58361e58f8
commit a61df0832f
17 changed files with 3591 additions and 1651 deletions

View File

@ -52,6 +52,9 @@
"no-trailing-spaces": "warn",
"eol-last": "error",
"func-call-spacing": "error",
//"key-spacing": ["warn", {
// "mode": "minimum"
//}],
"indent": ["error", 4, {
"ArrayExpression": "first",
"SwitchCase": 1

4834
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -31,36 +31,36 @@
"bugs": "https://github.com/gchq/CyberChef/issues",
"devDependencies": {
"babel-core": "^6.24.0",
"babel-loader": "^6.4.0",
"babel-loader": "^7.1.1",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.2.2",
"css-loader": "^0.27.3",
"babel-preset-env": "^1.6.0",
"css-loader": "^0.28.4",
"exports-loader": "^0.6.4",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.10.1",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^0.11.2",
"grunt": ">=0.4.5",
"grunt-accessibility": "~5.0.0",
"grunt-chmod": "~1.1.1",
"grunt-contrib-clean": "~1.0.0",
"grunt-contrib-clean": "~1.1.0",
"grunt-contrib-copy": "~1.0.0",
"grunt-eslint": "^19.0.0",
"grunt-exec": "~1.0.1",
"grunt-eslint": "^20.0.0",
"grunt-exec": "~2.0.0",
"grunt-execute": "^0.2.2",
"grunt-jsdoc": "^2.1.0",
"grunt-webpack": "^2.0.1",
"html-webpack-plugin": "^2.28.0",
"grunt-webpack": "^3.0.2",
"html-webpack-plugin": "^2.29.0",
"imports-loader": "^0.7.1",
"ink-docstrap": "^1.1.4",
"jsdoc-babel": "^0.3.0",
"less": "^2.7.2",
"less-loader": "^4.0.3",
"less-loader": "^4.0.5",
"postcss-css-variables": "^0.7.0",
"postcss-import": "^10.0.0",
"postcss-loader": "^2.0.5",
"style-loader": "^0.15.0",
"style-loader": "^0.18.2",
"url-loader": "^0.5.8",
"web-resource-inliner": "^4.1.0",
"webpack": "^2.2.1"
"webpack": "^3.3.0"
},
"dependencies": {
"bootstrap": "^3.3.7",
@ -68,15 +68,15 @@
"bootstrap-switch": "^3.3.4",
"crypto-api": "^0.6.2",
"crypto-js": "^3.1.9-1",
"diff": "^3.2.0",
"diff": "^3.3.0",
"escodegen": "^1.8.1",
"esmangle": "^1.0.1",
"esprima": "^3.1.3",
"exif-parser": "^0.1.9",
"esprima": "^4.0.0",
"exif-parser": "^0.1.12",
"google-code-prettify": "^1.0.5",
"jquery": "^3.1.1",
"jsbn": "^1.1.0",
"jsrsasign": "7.1.3",
"jsrsasign": "8.0.3",
"lodash": "^4.17.4",
"moment": "^2.17.1",
"moment-timezone": "^0.5.11",
@ -86,7 +86,7 @@
"vkbeautify": "^0.99.1",
"xmldom": "^0.1.27",
"xpath": "0.0.24",
"zlibjs": "^0.2.0"
"zlibjs": "^0.3.1"
},
"scripts": {
"build": "grunt prod",

View File

@ -293,7 +293,7 @@ const Utils = {
* Utils.escapeRegex("[example]");
*/
escapeRegex: function(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
return str.replace(/([.*+?^=!:${}()|[\]/\\])/g, "\\$1");
},
@ -592,7 +592,7 @@ const Utils = {
i = 0;
if (removeNonAlphChars) {
const re = new RegExp("[^" + alphabet.replace(/[\[\]\\\-^$]/g, "\\$&") + "]", "g");
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
data = data.replace(re, "");
}
@ -810,7 +810,7 @@ const Utils = {
"`": "`"
};
return str.replace(/[&<>"'\/`]/g, function (match) {
return str.replace(/[&<>"'/`]/g, function (match) {
return HTML_CHARS[match];
});
},

View File

@ -228,19 +228,19 @@ const Code = {
}
code = code
// Create newlines after ;
.replace(/;/g, ";\n")
// Create newlines after { and around }
.replace(/{/g, "{\n")
.replace(/}/g, "\n}\n")
// Remove carriage returns
.replace(/\r/g, "")
// Remove all indentation
.replace(/^\s+/g, "")
.replace(/\n\s+/g, "\n")
// Remove trailing spaces
.replace(/\s*$/g, "")
.replace(/\n{/g, "{");
// Create newlines after ;
.replace(/;/g, ";\n")
// Create newlines after { and around }
.replace(/{/g, "{\n")
.replace(/}/g, "\n}\n")
// Remove carriage returns
.replace(/\r/g, "")
// Remove all indentation
.replace(/^\s+/g, "")
.replace(/\n\s+/g, "\n")
// Remove trailing spaces
.replace(/\s*$/g, "")
.replace(/\n{/g, "{");
// Indent
let i = 0,
@ -265,27 +265,27 @@ const Code = {
}
code = code
// Add strategic spaces
.replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ")
.replace(/\s*<([=]?)\s*/g, " <$1 ")
.replace(/\s*>([=]?)\s*/g, " >$1 ")
.replace(/([^+])\+([^+=])/g, "$1 + $2")
.replace(/([^-])-([^-=])/g, "$1 - $2")
.replace(/([^*])\*([^*=])/g, "$1 * $2")
.replace(/([^/])\/([^/=])/g, "$1 / $2")
.replace(/\s*,\s*/g, ", ")
.replace(/\s*{/g, " {")
.replace(/}\n/g, "}\n\n")
// Hacky horribleness
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n $3")
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3")
.replace(/else\s*\n([^{])/gim, "else\n $1")
.replace(/else\s+([^{])/gim, "else $1")
// Remove strategic spaces
.replace(/\s+;/g, ";")
.replace(/\{\s+\}/g, "{}")
.replace(/\[\s+\]/g, "[]")
.replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1");
// Add strategic spaces
.replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ")
.replace(/\s*<([=]?)\s*/g, " <$1 ")
.replace(/\s*>([=]?)\s*/g, " >$1 ")
.replace(/([^+])\+([^+=])/g, "$1 + $2")
.replace(/([^-])-([^-=])/g, "$1 - $2")
.replace(/([^*])\*([^*=])/g, "$1 * $2")
.replace(/([^/])\/([^/=])/g, "$1 / $2")
.replace(/\s*,\s*/g, ", ")
.replace(/\s*{/g, " {")
.replace(/}\n/g, "}\n\n")
// Hacky horribleness
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n $3")
.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3")
.replace(/else\s*\n([^{])/gim, "else\n $1")
.replace(/else\s+([^{])/gim, "else $1")
// Remove strategic spaces
.replace(/\s+;/g, ";")
.replace(/\{\s+\}/g, "{}")
.replace(/\[\s+\]/g, "[]")
.replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1");
// Replace preserved tokens
const ptokens = /###preservedToken(\d+)###/g;

View File

@ -144,8 +144,9 @@ const HTML = {
}
if (removeLineBreaks) {
input = input.replace(/^\s*\n/, "") // first line
.replace(/(\n\s*){2,}/g, "\n"); // all others
input = input
.replace(/^\s*\n/, "") // first line
.replace(/(\n\s*){2,}/g, "\n"); // all others
}
return input;

View File

@ -125,30 +125,30 @@ const HTTP = {
}
return fetch(url, config)
.then(r => {
if (r.status === 0 && r.type === "opaque") {
return "Error: Null response. Try setting the connection mode to CORS.";
}
if (showResponseMetadata) {
let headers = "";
for (let pair of r.headers.entries()) {
headers += " " + pair[0] + ": " + pair[1] + "\n";
.then(r => {
if (r.status === 0 && r.type === "opaque") {
return "Error: Null response. Try setting the connection mode to CORS.";
}
return r.text().then(b => {
return "####\n Status: " + r.status + " " + r.statusText +
"\n Exposed headers:\n" + headers + "####\n\n" + b;
});
}
return r.text();
})
.catch(e => {
return e.toString() +
"\n\nThis error could be caused by one of the following:\n" +
" - An invalid URL\n" +
" - Making a request to an insecure resource (HTTP) from a secure source (HTTPS)\n" +
" - Making a cross-origin request to a server which does not support CORS\n";
});
if (showResponseMetadata) {
let headers = "";
for (let pair of r.headers.entries()) {
headers += " " + pair[0] + ": " + pair[1] + "\n";
}
return r.text().then(b => {
return "####\n Status: " + r.status + " " + r.statusText +
"\n Exposed headers:\n" + headers + "####\n\n" + b;
});
}
return r.text();
})
.catch(e => {
return e.toString() +
"\n\nThis error could be caused by one of the following:\n" +
" - An invalid URL\n" +
" - Making a request to an insecure resource (HTTP) from a secure source (HTTPS)\n" +
" - Making a cross-origin request to a server which does not support CORS\n";
});
},
};

View File

@ -1,4 +1,4 @@
import esprima from "esprima";
import * as esprima from "esprima";
import escodegen from "escodegen";
import esmangle from "esmangle";
@ -62,7 +62,7 @@ const JS = {
tolerant: parseTolerant
};
result = esprima.parse(input, options);
result = esprima.parseScript(input, options);
return JSON.stringify(result, null, 2);
},
@ -104,7 +104,7 @@ const JS = {
AST;
try {
AST = esprima.parse(input, {
AST = esprima.parseScript(input, {
range: true,
tokens: true,
comment: true
@ -142,7 +142,7 @@ const JS = {
*/
runMinify: function(input, args) {
let result = "",
AST = esprima.parse(input),
AST = esprima.parseScript(input),
optimisedAST = esmangle.optimize(AST, null),
mangledAST = esmangle.mangle(optimisedAST);

View File

@ -27,52 +27,49 @@ const PublicKey = {
* @returns {string}
*/
runParseX509: function (input, args) {
let cert = new r.X509(),
inputFormat = args[0];
if (!input.length) {
return "No input";
}
let cert = new r.X509(),
inputFormat = args[0];
switch (inputFormat) {
case "DER Hex":
input = input.replace(/\s/g, "");
cert.hex = input;
cert.pem = r.KJUR.asn1.ASN1Util.getPEMStringFromHex(input, "CERTIFICATE");
cert.readCertHex(input);
break;
case "PEM":
cert.hex = r.X509.pemToHex(input);
cert.pem = input;
cert.readCertPEM(input);
break;
case "Base64":
cert.hex = Utils.toHex(Utils.fromBase64(input, null, "byteArray"), "");
cert.pem = r.KJUR.asn1.ASN1Util.getPEMStringFromHex(cert.hex, "CERTIFICATE");
cert.readCertHex(Utils.toHex(Utils.fromBase64(input, null, "byteArray"), ""));
break;
case "Raw":
cert.hex = Utils.toHex(Utils.strToByteArray(input), "");
cert.pem = r.KJUR.asn1.ASN1Util.getPEMStringFromHex(cert.hex, "CERTIFICATE");
cert.readCertHex(Utils.toHex(Utils.strToByteArray(input), ""));
break;
default:
throw "Undefined input format";
}
let version = r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 0, 0]),
sn = cert.getSerialNumberHex(),
algorithm = r.KJUR.asn1.x509.OID.oid2name(r.KJUR.asn1.ASN1Util.oidHexToInt(r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 2, 0]))),
let sn = cert.getSerialNumberHex(),
issuer = cert.getIssuerString(),
notBefore = cert.getNotBefore(),
notAfter = cert.getNotAfter(),
subject = cert.getSubjectString(),
pkAlgorithm = r.KJUR.asn1.x509.OID.oid2name(r.KJUR.asn1.ASN1Util.oidHexToInt(r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 6, 0, 0]))),
pk = r.X509.getPublicKeyFromCertPEM(cert.pem),
pk = cert.getPublicKey(),
pkFields = [],
pkStr = "",
certSigAlg = r.KJUR.asn1.x509.OID.oid2name(r.KJUR.asn1.ASN1Util.oidHexToInt(r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [1, 0]))),
certSig = r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [2]).substr(2),
sig = cert.getSignatureValueHex(),
sigStr = "",
extensions = r.ASN1HEX.dump(r.ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 7]));
extensions = cert.getInfo().split("X509v3 Extensions:\n")[1].split("signature")[0];
window.cert = cert;
window.r = r;
// Public Key fields
pkFields.push({
key: "Algorithm",
value: pk.type
});
if (pk.type === "EC") { // ECDSA
pkFields.push({
key: "Curve Name",
@ -123,21 +120,6 @@ const PublicKey = {
});
}
// Signature fields
let breakoutSig = false;
try {
breakoutSig = r.ASN1HEX.dump(certSig).indexOf("SEQUENCE") === 0;
} catch (err) {
// Error processing signature, output without further breakout
}
if (breakoutSig) { // DSA or ECDSA
sigStr = " r: " + PublicKey._formatByteStr(r.ASN1HEX.getDecendantHexVByNthList(certSig, 0, [0]), 16, 18) + "\n" +
" s: " + PublicKey._formatByteStr(r.ASN1HEX.getDecendantHexVByNthList(certSig, 0, [1]), 16, 18) + "\n";
} else { // RSA or unknown
sigStr = " Signature: " + PublicKey._formatByteStr(certSig, 16, 18) + "\n";
}
// Format Public Key fields
for (let i = 0; i < pkFields.length; i++) {
pkStr += " " + pkFields[i].key + ":" +
@ -148,31 +130,45 @@ const PublicKey = {
);
}
// Signature fields
let breakoutSig = false;
try {
breakoutSig = r.ASN1HEX.dump(sig).indexOf("SEQUENCE") === 0;
} catch (err) {
// Error processing signature, output without further breakout
}
if (breakoutSig) { // DSA or ECDSA
sigStr = " r: " + PublicKey._formatByteStr(r.ASN1HEX.getV(sig, 4), 16, 18) + "\n" +
" s: " + PublicKey._formatByteStr(r.ASN1HEX.getV(sig, 48), 16, 18);
} else { // RSA or unknown
sigStr = " Signature: " + PublicKey._formatByteStr(sig, 16, 18);
}
let issuerStr = PublicKey._formatDnStr(issuer, 2),
nbDate = PublicKey._formatDate(notBefore),
naDate = PublicKey._formatDate(notAfter),
nbDate = PublicKey._formatDate(cert.getNotBefore()),
naDate = PublicKey._formatDate(cert.getNotAfter()),
subjectStr = PublicKey._formatDnStr(subject, 2);
const output = "Version: " + (parseInt(version, 16) + 1) + " (0x" + version + ")\n" +
"Serial number: " + new r.BigInteger(sn, 16).toString() + " (0x" + sn + ")\n" +
"Algorithm ID: " + algorithm + "\n" +
"Validity\n" +
" Not Before: " + nbDate + " (dd-mm-yy hh:mm:ss) (" + notBefore + ")\n" +
" Not After: " + naDate + " (dd-mm-yy hh:mm:ss) (" + notAfter + ")\n" +
"Issuer\n" +
issuerStr +
"Subject\n" +
subjectStr +
"Public Key\n" +
" Algorithm: " + pkAlgorithm + "\n" +
pkStr +
"Certificate Signature\n" +
" Algorithm: " + certSigAlg + "\n" +
sigStr +
"\nExtensions (parsed ASN.1)\n" +
extensions;
return `Version: ${cert.version} (0x${Utils.hex(cert.version - 1)})
Serial number: ${new r.BigInteger(sn, 16).toString()} (0x${sn})
Algorithm ID: ${cert.getSignatureAlgorithmField()}
Validity
Not Before: ${nbDate} (dd-mm-yy hh:mm:ss) (${cert.getNotBefore()})
Not After: ${naDate} (dd-mm-yy hh:mm:ss) (${cert.getNotAfter()})
Issuer
${issuerStr}
Subject
${subjectStr}
Public Key
${pkStr.slice(0, -1)}
Certificate Signature
Algorithm: ${cert.getSignatureAlgorithmName()}
${sigStr}
return output;
Extensions
${extensions}`;
},
@ -192,7 +188,9 @@ const PublicKey = {
// Add footer so that the KEYUTIL function works
input = input + "-----END CERTIFICATE-----";
}
return r.KEYUTIL.getHexFromPEM(input);
let cert = new r.X509();
cert.readCertPEM(input);
return cert.hex;
},
@ -270,7 +268,7 @@ const PublicKey = {
*/
_formatDnStr: function(dnStr, indent) {
let output = "",
fields = dnStr.split(",/|"),
fields = dnStr.substr(1).replace(/([^\\])\//g, "$1$1/").split(/[^\\]\//),
maxKeyLen = 0,
key,
value,
@ -295,7 +293,7 @@ const PublicKey = {
output += Utils.padLeft(str, indent + str.length, " ");
}
return output;
return output.slice(0, -1);
},
@ -347,24 +345,6 @@ const PublicKey = {
export default PublicKey;
/**
* Overwrite X509.hex2dn function so as to join RDNs with a string which can be split on without
* causing problems later (I hope).
*
* @param {string} hDN - Hex DN string
* @returns {string}
*/
r.X509.hex2dn = function(hDN) {
let s = "";
const a = r.ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
for (let i = 0; i < a.length; i++) {
const hRDN = r.ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
s = s + ",/|" + r.X509.hex2rdn(hRDN);
}
return s;
};
/**
* Overwrite DN attribute lookup in jsrasign library with a much more complete version from
* https://github.com/nfephp-org/nfephp/blob/master/libs/Common/Certificate/Oids.php

View File

@ -61,7 +61,7 @@ const QuotedPrintable = {
* @returns {byteArray}
*/
runFrom: function (input, args) {
const str = input.replace(/\=(?:\r?\n|$)/g, "");
const str = input.replace(/=(?:\r?\n|$)/g, "");
return QuotedPrintable.mimeDecode(str);
},
@ -73,7 +73,7 @@ const QuotedPrintable = {
* @returns {byteArray}
*/
mimeDecode: function(str) {
let encodedBytesCount = (str.match(/\=[\da-fA-F]{2}/g) || []).length,
let encodedBytesCount = (str.match(/=[\da-fA-F]{2}/g) || []).length,
bufferLength = str.length - encodedBytesCount * 2,
chr, hex,
buffer = new Array(bufferLength),
@ -219,21 +219,21 @@ const QuotedPrintable = {
result += line;
pos += line.length;
continue;
} else if (line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t\.,!\?][^ \t\.,!\?]*$/))) {
} else if (line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t.,!?][^ \t.,!?]*$/))) {
// truncate to nearest space
line = line.substr(0, line.length - (match[0].length - 1));
} else if (line.substr(-1) === "\r") {
line = line.substr(0, line.length - 1);
} else {
if (line.match(/\=[\da-f]{0,2}$/i)) {
if (line.match(/=[\da-f]{0,2}$/i)) {
// push incomplete encoding sequences to the next line
if ((match = line.match(/\=[\da-f]{0,1}$/i))) {
if ((match = line.match(/=[\da-f]{0,1}$/i))) {
line = line.substr(0, line.length - match[0].length);
}
// ensure that utf-8 sequences are not split
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/\=[\da-f]{2}$/ig))) {
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/=[\da-f]{2}$/ig))) {
code = parseInt(match[0].substr(1, 2), 16);
if (code < 128) {
break;
@ -250,7 +250,7 @@ const QuotedPrintable = {
}
if (pos + line.length < len && line.substr(-1) !== "\n") {
if (line.length === 76 && line.match(/\=[\da-f]{2}$/i)) {
if (line.length === 76 && line.match(/=[\da-f]{2}$/i)) {
line = line.substr(0, line.length - 3);
} else if (line.length === 76) {
line = line.substr(0, line.length - 1);

View File

@ -476,16 +476,16 @@ const StrUtils = {
const splitInput = input.split(delimiter);
return splitInput
.filter((line, lineIndex) => {
lineIndex += 1;
.filter((line, lineIndex) => {
lineIndex += 1;
if (number < 0) {
return lineIndex <= splitInput.length + number;
} else {
return lineIndex <= number;
}
})
.join(delimiter);
if (number < 0) {
return lineIndex <= splitInput.length + number;
} else {
return lineIndex <= number;
}
})
.join(delimiter);
},
@ -504,16 +504,16 @@ const StrUtils = {
const splitInput = input.split(delimiter);
return splitInput
.filter((line, lineIndex) => {
lineIndex += 1;
.filter((line, lineIndex) => {
lineIndex += 1;
if (number < 0) {
return lineIndex > -number;
} else {
return lineIndex > splitInput.length - number;
}
})
.join(delimiter);
if (number < 0) {
return lineIndex > -number;
} else {
return lineIndex > splitInput.length - number;
}
})
.join(delimiter);
},

View File

@ -127,7 +127,7 @@ const URL_ = {
.replace(/\(/g, "%28")
.replace(/\)/g, "%29")
.replace(/\*/g, "%2A")
.replace(/\-/g, "%2D")
.replace(/-/g, "%2D")
.replace(/\./g, "%2E")
.replace(/_/g, "%5F")
.replace(/~/g, "%7E");

View File

@ -14,12 +14,12 @@ const CyberChef = module.exports = {
bake: function(input, recipeConfig) {
this.chef = new Chef();
return this.chef.bake(
input,
recipeConfig,
{},
0,
false
);
input,
recipeConfig,
{},
0,
false
);
}
};

View File

@ -183,9 +183,9 @@ ControlsWaiter.prototype.generateStateUrl = function(includeRecipe, includeInput
];
const hash = params
.filter(v => v)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join("&");
.filter(v => v)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join("&");
if (hash) {
return `${link}#${hash}`;
@ -288,7 +288,7 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() {
// Add recipes to select
const savedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
JSON.parse(localStorage.savedRecipes) : [];
for (i = 0; i < savedRecipes.length; i++) {
const opt = document.createElement("option");
@ -310,7 +310,7 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() {
ControlsWaiter.prototype.loadDeleteClick = function() {
const id = parseInt(document.getElementById("load-name").value, 10);
const rawSavedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
JSON.parse(localStorage.savedRecipes) : [];
const savedRecipes = rawSavedRecipes.filter(r => r.id !== id);
@ -325,7 +325,7 @@ ControlsWaiter.prototype.loadDeleteClick = function() {
ControlsWaiter.prototype.loadNameChange = function(e) {
const el = e.target;
const savedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : [];
JSON.parse(localStorage.savedRecipes) : [];
const id = parseInt(el.value, 10);
const recipe = savedRecipes.find(r => r.id === id);

View File

@ -493,13 +493,14 @@ HighlighterWaiter.prototype.highlight = function(textarea, highlighter, pos) {
//if (colour) cssClass += "-"+colour;
// Remove HTML tags
text = text.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/\n/g, "&#10;")
// Convert placeholders to tags
.replace(startPlaceholderRegex, "<span class=\""+cssClass+"\">")
.replace(endPlaceholderRegex, "</span>") + "&nbsp;";
text = text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/\n/g, "&#10;")
// Convert placeholders to tags
.replace(startPlaceholderRegex, "<span class=\""+cssClass+"\">")
.replace(endPlaceholderRegex, "</span>") + "&nbsp;";
// Adjust width to allow for scrollbars
highlighter.style.width = textarea.clientWidth + "px";

View File

@ -46,8 +46,7 @@ import Chef from "../src/core/Chef.js";
{},
0,
false
)
.then(function(result) {
).then(function(result) {
const ret = {
test: test,
status: null,

View File

@ -73,11 +73,11 @@ TestRegister.addTests([
"",
"Make: SONY",
"Model: DSC-H5",
"XResolution: 72",
"YResolution: 72",
"XResolution: 70",
"YResolution: 70",
"ResolutionUnit: 2",
"Software: Pictomio 1.2.31.0",
"ModifyDate: 2010:07:04 23:31:13",
"ModifyDate: 1278286273",
"ExposureTime: 0.008",
"FNumber: 3.7",
"ExposureProgram: 3",