consolidate on express-handlebars for web + email
Web templates were using express-hbs while email templates used express-handlebars. Change both to use express-handlebars, which also lets us share helpers between email + web templates.
This commit is contained in:
Родитель
98eb86efd2
Коммит
8a8f87e810
|
@ -42,13 +42,6 @@ async function verify(req, res) {
|
|||
req.app.locals.breaches
|
||||
);
|
||||
|
||||
if(unsafeBreachesForEmail) {
|
||||
unsafeBreachesForEmail.forEach((breach) => {
|
||||
breach.BreachDate = HBSHelpers.prettyDate(breach.BreachDate);
|
||||
breach.DataClasses = HBSHelpers.breachDataClasses(breach.DataClasses);
|
||||
});
|
||||
}
|
||||
|
||||
const unsubscribeUrl = EmailUtils.unsubscribeUrl(verifiedEmailHash);
|
||||
const serverUrl = req.app.locals.SERVER_URL;
|
||||
|
||||
|
@ -58,7 +51,7 @@ async function verify(req, res) {
|
|||
"report",
|
||||
{
|
||||
email: verifiedEmailHash.email,
|
||||
date: new Date().toLocaleString("en-US", {year: "numeric", month: "long", day: "numeric"}),
|
||||
date: HBSHelpers.prettyDate(new Date()),
|
||||
unsafeBreachesForEmail,
|
||||
TIPS,
|
||||
unsubscribeUrl,
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
"use strict";
|
||||
|
||||
|
||||
|
||||
const AppConstants = require("./app-constants");
|
||||
|
||||
const nodemailer = require("nodemailer");
|
||||
const hbs = require("nodemailer-express-handlebars");
|
||||
|
||||
const HBSHelpers = require("./hbs-helpers");
|
||||
|
||||
|
||||
const hbsOptions = {
|
||||
viewEngine: {
|
||||
extname: ".hbs",
|
||||
layoutsDir: __dirname + "/views/email/layouts",
|
||||
defaultLayout: "default_email",
|
||||
partialsDir: __dirname + "/views/email/email_partials/",
|
||||
helpers: HBSHelpers,
|
||||
},
|
||||
viewPath: __dirname + "/views/email/",
|
||||
extName: ".hbs",
|
||||
|
|
152
hbs-helpers.js
152
hbs-helpers.js
|
@ -1,87 +1,89 @@
|
|||
"use strict";
|
||||
|
||||
const HBSHelpers = {
|
||||
breachDataClasses(dataClasses) {
|
||||
if (dataClasses.constructor === Array) {
|
||||
return dataClasses.join(", ");
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
function breachDataClasses(dataClasses) {
|
||||
if (dataClasses.constructor === Array) {
|
||||
return dataClasses.join(", ");
|
||||
} else {
|
||||
return dataClasses;
|
||||
}
|
||||
}
|
||||
|
||||
prettyDate(date) {
|
||||
const jsDate = new Date(date);
|
||||
return jsDate.toLocaleDateString("en-US", {year: "numeric", month: "long", day: "numeric"});
|
||||
},
|
||||
|
||||
localeString(input) {
|
||||
return input.toLocaleString();
|
||||
},
|
||||
function prettyDate(date) {
|
||||
const jsDate = new Date(date);
|
||||
return jsDate.toLocaleDateString("en-US", {year: "numeric", month: "long", day: "numeric"});
|
||||
}
|
||||
|
||||
eachFromTo(ary, min, max, options) {
|
||||
if(!ary || ary.length === 0)
|
||||
return options.inverse(this);
|
||||
|
||||
const result = [];
|
||||
function localeString(input) {
|
||||
return input.toLocaleString();
|
||||
}
|
||||
|
||||
for (let i = min; i < max && i < ary.length; i++) {
|
||||
result.push(options.fn(ary[i], { data : { itemIndex : i } } ));
|
||||
}
|
||||
return result.join("");
|
||||
},
|
||||
|
||||
ifCompare(v1, operator, v2, options) {
|
||||
//https://stackoverflow.com/questions/28978759/length-check-in-a-handlebars-js-if-conditional
|
||||
const operators = {
|
||||
">": v1 > v2 ? true : false,
|
||||
">=": v1 >= v2 ? true : false,
|
||||
"<": v1 < v2 ? true : false,
|
||||
"<=": v1 <= v2 ? true : false,
|
||||
"===": v1 === v2 ? true : false,
|
||||
};
|
||||
if (operators.hasOwnProperty(operator)) {
|
||||
if (operators[operator]) {
|
||||
return options.fn(this);
|
||||
}
|
||||
function eachFromTo(ary, min, max, options) {
|
||||
if(!ary || ary.length === 0)
|
||||
return options.inverse(this);
|
||||
}
|
||||
return console.error(`Error: ${operator} not found`);
|
||||
},
|
||||
|
||||
breachMath(lValue, operator, rValue) {
|
||||
lValue = parseFloat(lValue);
|
||||
rValue = parseFloat(rValue);
|
||||
const returnValue = {
|
||||
"+": lValue + rValue,
|
||||
"-": lValue - rValue,
|
||||
"*": lValue * rValue,
|
||||
"/": lValue / rValue,
|
||||
"%": lValue % rValue,
|
||||
}[operator];
|
||||
if (returnValue < 10) {
|
||||
return {
|
||||
1: "one",
|
||||
2: "two",
|
||||
3: "three",
|
||||
4: "four",
|
||||
5: "five",
|
||||
6: "six",
|
||||
7: "seven",
|
||||
8: "eight",
|
||||
9: "nine",
|
||||
}[returnValue];
|
||||
}
|
||||
return returnValue;
|
||||
},
|
||||
const result = [];
|
||||
|
||||
register(hbs) {
|
||||
hbs.registerHelper("prettyDate", this.prettyDate);
|
||||
hbs.registerHelper("breachDataClasses", this.breachDataClasses);
|
||||
hbs.registerHelper("localeString", this.localeString);
|
||||
hbs.registerHelper("each_from_to", this.eachFromTo);
|
||||
hbs.registerHelper("if_compare", this.ifCompare);
|
||||
hbs.registerHelper("breachMath", this.breachMath);
|
||||
},
|
||||
for (let i = min; i < max && i < ary.length; i++) {
|
||||
result.push(options.fn(ary[i], { data : { itemIndex : i } } ));
|
||||
}
|
||||
return result.join("");
|
||||
}
|
||||
|
||||
|
||||
function ifCompare(v1, operator, v2, options) {
|
||||
//https://stackoverflow.com/questions/28978759/length-check-in-a-handlebars-js-if-conditional
|
||||
const operators = {
|
||||
">": v1 > v2 ? true : false,
|
||||
">=": v1 >= v2 ? true : false,
|
||||
"<": v1 < v2 ? true : false,
|
||||
"<=": v1 <= v2 ? true : false,
|
||||
"===": v1 === v2 ? true : false,
|
||||
};
|
||||
if (operators.hasOwnProperty(operator)) {
|
||||
if (operators[operator]) {
|
||||
return options.fn(this);
|
||||
}
|
||||
return options.inverse(this);
|
||||
}
|
||||
return console.error(`Error: ${operator} not found`);
|
||||
}
|
||||
|
||||
|
||||
function breachMath(lValue, operator, rValue) {
|
||||
lValue = parseFloat(lValue);
|
||||
rValue = parseFloat(rValue);
|
||||
const returnValue = {
|
||||
"+": lValue + rValue,
|
||||
"-": lValue - rValue,
|
||||
"*": lValue * rValue,
|
||||
"/": lValue / rValue,
|
||||
"%": lValue % rValue,
|
||||
}[operator];
|
||||
if (returnValue < 10) {
|
||||
return {
|
||||
1: "one",
|
||||
2: "two",
|
||||
3: "three",
|
||||
4: "four",
|
||||
5: "five",
|
||||
6: "six",
|
||||
7: "seven",
|
||||
8: "eight",
|
||||
9: "nine",
|
||||
}[returnValue];
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
breachDataClasses,
|
||||
prettyDate,
|
||||
localeString,
|
||||
eachFromTo,
|
||||
ifCompare,
|
||||
breachMath,
|
||||
};
|
||||
|
||||
module.exports = HBSHelpers;
|
||||
|
|
|
@ -53,7 +53,8 @@
|
|||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||
"dev": true
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.5",
|
||||
|
@ -1261,15 +1262,6 @@
|
|||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"config-chain": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz",
|
||||
"integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=",
|
||||
"requires": {
|
||||
"ini": "^1.3.4",
|
||||
"proto-list": "~1.2.1"
|
||||
}
|
||||
},
|
||||
"configstore": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
|
||||
|
@ -1813,18 +1805,6 @@
|
|||
"jsbn": "~0.1.0"
|
||||
}
|
||||
},
|
||||
"editorconfig": {
|
||||
"version": "0.13.3",
|
||||
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz",
|
||||
"integrity": "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==",
|
||||
"requires": {
|
||||
"bluebird": "^3.0.5",
|
||||
"commander": "^2.9.0",
|
||||
"lru-cache": "^3.2.0",
|
||||
"semver": "^5.1.0",
|
||||
"sigmund": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
|
@ -2345,16 +2325,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"express-hbs": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/express-hbs/-/express-hbs-1.0.4.tgz",
|
||||
"integrity": "sha1-xEgNboqfjCNQDTsaE5Txfq5FF4Y=",
|
||||
"requires": {
|
||||
"handlebars": "4.0.6",
|
||||
"js-beautify": "1.6.8",
|
||||
"readdirp": "2.1.0"
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
|
||||
|
@ -5569,17 +5539,6 @@
|
|||
"integrity": "sha512-aUnNwqMOXw3yvErjMPSQu6qIIzUmT1e5KcU1OZxRDU1g/am6mzBvcrmLAYwzmB59BHPrh5/tKaiF4OPhqRWESQ==",
|
||||
"dev": true
|
||||
},
|
||||
"js-beautify": {
|
||||
"version": "1.6.8",
|
||||
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.6.8.tgz",
|
||||
"integrity": "sha1-2hFG00QxFFMJyJvn9p7Rbo4P8H4=",
|
||||
"requires": {
|
||||
"config-chain": "~1.1.5",
|
||||
"editorconfig": "^0.13.2",
|
||||
"mkdirp": "~0.5.0",
|
||||
"nopt": "~3.0.1"
|
||||
}
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
|
||||
|
@ -5961,14 +5920,6 @@
|
|||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
|
||||
"integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz",
|
||||
"integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=",
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
|
||||
|
@ -6489,14 +6440,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
|
||||
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
|
||||
"requires": {
|
||||
"abbrev": "1"
|
||||
}
|
||||
},
|
||||
"normalize-package-data": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
|
||||
|
@ -7526,11 +7469,6 @@
|
|||
"sisteransi": "^0.1.1"
|
||||
}
|
||||
},
|
||||
"proto-list": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
||||
"integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk="
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz",
|
||||
|
@ -7552,7 +7490,8 @@
|
|||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
|
||||
"dev": true
|
||||
},
|
||||
"pstree.remy": {
|
||||
"version": "1.1.0",
|
||||
|
@ -7689,6 +7628,7 @@
|
|||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
|
||||
"integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"minimatch": "^3.0.2",
|
||||
|
@ -8105,7 +8045,8 @@
|
|||
"semver": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
|
||||
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA=="
|
||||
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
|
||||
"dev": true
|
||||
},
|
||||
"semver-diff": {
|
||||
"version": "2.1.0",
|
||||
|
@ -8163,7 +8104,8 @@
|
|||
"set-immediate-shim": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
|
||||
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
|
||||
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
|
||||
"dev": true
|
||||
},
|
||||
"set-value": {
|
||||
"version": "2.0.0",
|
||||
|
@ -8234,11 +8176,6 @@
|
|||
"integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
|
||||
"dev": true
|
||||
},
|
||||
"sigmund": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
|
||||
"integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA="
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"dompurify": "^1.0.4",
|
||||
"dotenv": "^5.0.1",
|
||||
"express": "^4.16.2",
|
||||
"express-hbs": "^1.0.4",
|
||||
"express-handlebars": "^3.0.0",
|
||||
"git-rev-sync": "^1.12.0",
|
||||
"got": "^8.3.1",
|
||||
"hbs": "^4.0.1",
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
const AppConstants = require("./app-constants");
|
||||
|
||||
const express = require("express");
|
||||
const hbs = require("express-hbs");
|
||||
const exphbs = require("express-handlebars");
|
||||
const helmet = require("helmet");
|
||||
const sessions = require("client-sessions");
|
||||
|
||||
|
@ -63,13 +63,14 @@ app.use(helmet.contentSecurityPolicy({
|
|||
}));
|
||||
app.use(express.static("public"));
|
||||
|
||||
app.engine("hbs", hbs.express4({
|
||||
app.engine("hbs", exphbs({
|
||||
extname: ".hbs",
|
||||
layoutsDir: __dirname + "/views/layouts",
|
||||
defaultLayout: "default",
|
||||
partialsDir: __dirname + "/views/partials",
|
||||
helpers: HBSHelpers,
|
||||
}));
|
||||
app.set("view engine", "hbs");
|
||||
app.set("views", __dirname + "/views");
|
||||
HBSHelpers.register(hbs);
|
||||
|
||||
const cookie = {httpOnly: true, secureProxy: true};
|
||||
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
</td>
|
||||
<td valign="top" style="vertical-align: top; padding-top:10px;">
|
||||
<p style="padding: 0px 0px 5px 0px; margin: 0px; color: #333333; margin: 0px; font-weight: 600; font-size: 16px;">{{ Title }} Breach</p>
|
||||
<p style="padding: 0px 0px 5px 0px; margin: 0px; color: #333333; font-weight: 600;">Breach Date:<span style="font-weight:300; padding-left: 5px; color: #5d5d5d">{{ BreachDate }}</span></p>
|
||||
<p style="padding: 0px 0px 5px 0px; margin: 0px; color: #333333; font-weight: 600;">Breach Date:<span style="font-weight:300; padding-left: 5px; color: #5d5d5d">{{prettyDate BreachDate }}</span></p>
|
||||
<p style="padding: 0px 0px 5px 0px; margin: 0px; color: #333333; font-weight: 600;">Compromised Accounts:<span style="font-weight:300; padding-left: 5px; color: #5d5d5d">{{ PwnCount }}</span></p>
|
||||
<p style="padding: 0px 0px 5px 0px; margin: 0px; color: #333333; font-weight: 600;">Compromised Data:<span style="font-weight:300; padding-left: 5px; color: #5d5d5d">{{ DataClasses }}</span></p>
|
||||
{{#if DataClasses }}
|
||||
<p style="padding: 0px 0px 5px 0px; margin: 0px; color: #333333; font-weight: 600;">Compromised Data:<span style="font-weight:300; padding-left: 5px; color: #5d5d5d">{{breachDataClasses DataClasses }}</span></p>
|
||||
{{/if}}
|
||||
<p style="padding: 0px 0px 5px 0px; margin: 0px; font-weight: 300; color: #5d5d5d;">{{ Description }}</p>
|
||||
<br />
|
||||
</td>
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
{{#if_compare foundBreaches.length ">=" 1}}
|
||||
{{#ifCompare foundBreaches.length ">=" 1}}
|
||||
<div class="compromised-accounts">
|
||||
<div class="section-wrapper">
|
||||
<!--show first 4 breaches-->
|
||||
{{#each_from_to foundBreaches 0 4 }}
|
||||
{{#eachFromTo foundBreaches 0 4 }}
|
||||
<div class="half listings">
|
||||
{{> breach_listing }}
|
||||
</div>
|
||||
{{/each_from_to}}
|
||||
{{/eachFromTo}}
|
||||
<!--display "Show More" button and show remaining breaches onclick if foundBreaches.length > 4-->
|
||||
{{#if_compare foundBreaches.length ">" 4}}
|
||||
{{#ifCompare foundBreaches.length ">" 4}}
|
||||
<div id="additional-breaches" class="section-wrapper">
|
||||
{{#each_from_to foundBreaches 4 foundBreaches.length }}
|
||||
{{#eachFromTo foundBreaches 4 foundBreaches.length }}
|
||||
<div class="half listings">
|
||||
{{> breach_listing }}
|
||||
</div>
|
||||
{{/each_from_to}}
|
||||
{{/eachFromTo}}
|
||||
</div>
|
||||
<button id="show-additional-breaches" class="button transparent-button">Show More</button>
|
||||
{{> hibp_attribution }}
|
||||
{{/if_compare}}
|
||||
{{/ifCompare}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if_compare}}
|
||||
{{/ifCompare}}
|
||||
|
|
|
@ -7,25 +7,26 @@
|
|||
<h3 id="found-breaches" class="section-headline">This might be a problem</h3>
|
||||
{{#if featuredBreach}}
|
||||
{{#if userAccountCompromised}}
|
||||
{{#if_compare foundBreaches.length ">" 1}} <!-- checking for additional "non-featured" breaches (is foundBreaches.length > 1) -->
|
||||
<p>Your accounts appear in the <span class="bold">{{ featuredBreach.Title }}</span> breach, as well as <span class="bold">{{ breachMath foundBreaches.length "-" 1 }}</span> other breach{{#if_compare foundBreaches.length ">" 2}}es{{/if_compare}}.</p>
|
||||
{{#ifCompare foundBreaches.length ">" 1}} <!-- checking for additional "non-featured" breaches (is foundBreaches.length > 1) -->
|
||||
<p>Your accounts appear in the <span class="bold">{{ featuredBreach.Title }}</span> breach, as well as <span class="bold">{{ breachMath foundBreaches.length "-" 1 }}</span> other breach{{#ifCompare foundBreaches.length ">" 2}}es{{/ifCompare}}.</p>
|
||||
{{else}}
|
||||
<p>Your account appears in the <span class="bold">{{ featuredBreach.Title }}</span> breach, but does not appear in any other known breaches.</p>
|
||||
</section><!--closes half.scan-results-content-left-->
|
||||
<section class="half order-last">
|
||||
{{> featured_breach}}
|
||||
{{/if_compare}}
|
||||
</div>
|
||||
{{/ifCompare}}
|
||||
{{else}} <!--#if !userAccountCompromised -->
|
||||
{{#if_compare foundBreaches.length ">=" 1}} <!-- user has breached accounts (foundBreaches.length > 0) but wasn't compromised in the 'featuredBreach' -->
|
||||
<p>Your account did not appear in the <span class="bold">{{ featuredBreach.Title }}</span> breach, but it did appear in <span class="bold">{{ breachMath foundBreaches.length "-" 0 }}</span> other breach{{#if_compare foundBreaches.length ">" 1}}es{{/if_compare}}.</p>
|
||||
{{/if_compare}}
|
||||
{{#ifCompare foundBreaches.length ">=" 1}} <!-- user has breached accounts (foundBreaches.length > 0) but wasn't compromised in the 'featuredBreach' -->
|
||||
<p>Your account did not appear in the <span class="bold">{{ featuredBreach.Title }}</span> breach, but it did appear in <span class="bold">{{ breachMath foundBreaches.length "-" 0 }}</span> other breach{{#ifCompare foundBreaches.length ">" 1}}es{{/ifCompare}}.</p>
|
||||
{{/ifCompare}}
|
||||
{{/if}}
|
||||
{{else}} <!--#if !featuredBreach-->
|
||||
{{#if_compare foundBreaches.length "===" 1}}
|
||||
{{#ifCompare foundBreaches.length "===" 1}}
|
||||
<p>Your account was compromised in the following breach.</p>
|
||||
{{else}}
|
||||
<p>Your accounts were compromised in the following breaches.</p>
|
||||
{{/if_compare}}
|
||||
{{/ifCompare}}
|
||||
{{/if}}<!--/#if featuredBreach-->
|
||||
</section><!--.half.scan-results-content-left // or closes .half.order-last (Line 15)-->
|
||||
{{> compromised_accounts }}
|
||||
|
|
Загрузка…
Ссылка в новой задаче