@formfeed/engine 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +19 -7
- package/index.js +19 -7
- package/package.json +1 -1
package/index.cjs
CHANGED
|
@@ -270,6 +270,7 @@ function toDate(value, tz) {
|
|
|
270
270
|
function escapeHtml(value) {
|
|
271
271
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
272
272
|
}
|
|
273
|
+
var isNamedArgs = (v) => !!v && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date);
|
|
273
274
|
var str = (v) => v === void 0 || v === null ? "" : String(v);
|
|
274
275
|
var opt = (v, fallback) => v === void 0 || v === null || v === "" ? fallback : v;
|
|
275
276
|
var wordsByLang = {
|
|
@@ -304,7 +305,7 @@ var formatHelpers = [
|
|
|
304
305
|
name: "number",
|
|
305
306
|
doc: {
|
|
306
307
|
signature: "number(value, decimals?, locale?)",
|
|
307
|
-
description: "Formats a number with grouping and
|
|
308
|
+
description: "Formats a number with grouping. With decimals, exactly that many (rounded half away from zero); without, the decimals the number has, at most three, so 1234.5 \u2192 1.234,5 and 2.34567 \u2192 2,346. Use number(0) for whole numbers.",
|
|
308
309
|
example: "{{ qty | number(2) }} \u2192 1.234,00",
|
|
309
310
|
category: "format"
|
|
310
311
|
},
|
|
@@ -398,15 +399,26 @@ var formatHelpers = [
|
|
|
398
399
|
{
|
|
399
400
|
name: "round",
|
|
400
401
|
doc: {
|
|
401
|
-
signature: "round(value, decimals = 0)",
|
|
402
|
-
description: "Rounds half away from zero.",
|
|
403
|
-
example: "{{ 2.345 | round(2) }} gives 2.35",
|
|
402
|
+
signature: "round(value, decimals = 0, method = 'common')",
|
|
403
|
+
description: "Rounds to the given decimals, as Jinja2's round does: 'common' rounds half away from zero, 'floor' always down and 'ceil' always up.",
|
|
404
|
+
example: "{{ 2.345 | round(2) }} gives 2.35, {{ 2.349 | round(2, 'floor') }} gives 2.34",
|
|
404
405
|
category: "format"
|
|
405
406
|
},
|
|
406
|
-
|
|
407
|
+
// `round(2, method='floor')` (Jinja2) and `round: 2, method: 'floor'` (Liquid) arrive as a
|
|
408
|
+
// trailing object, as does a Handlebars hash
|
|
409
|
+
fn: (_ctx, value, ...args) => {
|
|
407
410
|
const n = toNumber(value);
|
|
408
|
-
|
|
409
|
-
|
|
411
|
+
if (Number.isNaN(n)) return "";
|
|
412
|
+
const named = args.find(isNamedArgs) ?? {};
|
|
413
|
+
const [decimals, method] = args.filter((a) => !isNamedArgs(a));
|
|
414
|
+
const places = Number(opt(decimals, opt(named["precision"], opt(named["decimals"], 0))));
|
|
415
|
+
const how = String(opt(method, opt(named["method"], "common")));
|
|
416
|
+
const f = 10 ** places;
|
|
417
|
+
const scaled = Number((Math.abs(n) * f).toPrecision(15));
|
|
418
|
+
if (how === "floor") return (n < 0 ? -Math.ceil(scaled) : Math.floor(scaled)) / f;
|
|
419
|
+
if (how === "ceil") return (n < 0 ? -Math.floor(scaled) : Math.ceil(scaled)) / f;
|
|
420
|
+
if (how !== "common") throw new Error(`round: method must be 'common', 'floor' or 'ceil', not '${how}'`);
|
|
421
|
+
return Math.round(scaled + Number.EPSILON) / f * Math.sign(n);
|
|
410
422
|
}
|
|
411
423
|
},
|
|
412
424
|
{
|
package/index.js
CHANGED
|
@@ -140,6 +140,7 @@ function toDate(value, tz) {
|
|
|
140
140
|
function escapeHtml(value) {
|
|
141
141
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
142
142
|
}
|
|
143
|
+
var isNamedArgs = (v) => !!v && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date);
|
|
143
144
|
var str = (v) => v === void 0 || v === null ? "" : String(v);
|
|
144
145
|
var opt = (v, fallback) => v === void 0 || v === null || v === "" ? fallback : v;
|
|
145
146
|
var wordsByLang = {
|
|
@@ -174,7 +175,7 @@ var formatHelpers = [
|
|
|
174
175
|
name: "number",
|
|
175
176
|
doc: {
|
|
176
177
|
signature: "number(value, decimals?, locale?)",
|
|
177
|
-
description: "Formats a number with grouping and
|
|
178
|
+
description: "Formats a number with grouping. With decimals, exactly that many (rounded half away from zero); without, the decimals the number has, at most three, so 1234.5 \u2192 1.234,5 and 2.34567 \u2192 2,346. Use number(0) for whole numbers.",
|
|
178
179
|
example: "{{ qty | number(2) }} \u2192 1.234,00",
|
|
179
180
|
category: "format"
|
|
180
181
|
},
|
|
@@ -268,15 +269,26 @@ var formatHelpers = [
|
|
|
268
269
|
{
|
|
269
270
|
name: "round",
|
|
270
271
|
doc: {
|
|
271
|
-
signature: "round(value, decimals = 0)",
|
|
272
|
-
description: "Rounds half away from zero.",
|
|
273
|
-
example: "{{ 2.345 | round(2) }} gives 2.35",
|
|
272
|
+
signature: "round(value, decimals = 0, method = 'common')",
|
|
273
|
+
description: "Rounds to the given decimals, as Jinja2's round does: 'common' rounds half away from zero, 'floor' always down and 'ceil' always up.",
|
|
274
|
+
example: "{{ 2.345 | round(2) }} gives 2.35, {{ 2.349 | round(2, 'floor') }} gives 2.34",
|
|
274
275
|
category: "format"
|
|
275
276
|
},
|
|
276
|
-
|
|
277
|
+
// `round(2, method='floor')` (Jinja2) and `round: 2, method: 'floor'` (Liquid) arrive as a
|
|
278
|
+
// trailing object, as does a Handlebars hash
|
|
279
|
+
fn: (_ctx, value, ...args) => {
|
|
277
280
|
const n = toNumber(value);
|
|
278
|
-
|
|
279
|
-
|
|
281
|
+
if (Number.isNaN(n)) return "";
|
|
282
|
+
const named = args.find(isNamedArgs) ?? {};
|
|
283
|
+
const [decimals, method] = args.filter((a) => !isNamedArgs(a));
|
|
284
|
+
const places = Number(opt(decimals, opt(named["precision"], opt(named["decimals"], 0))));
|
|
285
|
+
const how = String(opt(method, opt(named["method"], "common")));
|
|
286
|
+
const f = 10 ** places;
|
|
287
|
+
const scaled = Number((Math.abs(n) * f).toPrecision(15));
|
|
288
|
+
if (how === "floor") return (n < 0 ? -Math.ceil(scaled) : Math.floor(scaled)) / f;
|
|
289
|
+
if (how === "ceil") return (n < 0 ? -Math.floor(scaled) : Math.ceil(scaled)) / f;
|
|
290
|
+
if (how !== "common") throw new Error(`round: method must be 'common', 'floor' or 'ceil', not '${how}'`);
|
|
291
|
+
return Math.round(scaled + Number.EPSILON) / f * Math.sign(n);
|
|
280
292
|
}
|
|
281
293
|
},
|
|
282
294
|
{
|