Quick addition of a duration helper which can be used to create relative humanized date strings.
This commit is contained in:
parent
620fc8c72f
commit
a86b6db772
|
@ -5,18 +5,31 @@ const fs = require("fs")
|
||||||
const doctrine = require("doctrine")
|
const doctrine = require("doctrine")
|
||||||
const marked = require("marked")
|
const marked = require("marked")
|
||||||
|
|
||||||
const DIRECTORY = fs.existsSync("node_modules") ? "." : ".."
|
|
||||||
|
|
||||||
const FILENAME = `${DIRECTORY}/manifest.json`
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* full list of supported helpers can be found here:
|
* full list of supported helpers can be found here:
|
||||||
* https://github.com/helpers/handlebars-helpers
|
* https://github.com/budibase/handlebars-helpers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const DIRECTORY = fs.existsSync("node_modules") ? "." : ".."
|
||||||
const COLLECTIONS = ["math", "array", "number", "url", "string", "comparison"]
|
const COLLECTIONS = ["math", "array", "number", "url", "string", "comparison"]
|
||||||
|
const FILENAME = `${DIRECTORY}/manifest.json`
|
||||||
const outputJSON = {}
|
const outputJSON = {}
|
||||||
|
const ADDED_HELPERS = {
|
||||||
|
date: {
|
||||||
|
date: {
|
||||||
|
args: ["datetime", "format"],
|
||||||
|
numArgs: 2,
|
||||||
|
example: '{{date now "DD-MM-YYYY"}} -> 21-01-2021',
|
||||||
|
description: "Format a date using moment.js date formatting.",
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
args: ["time", "durationType"],
|
||||||
|
numArgs: 2,
|
||||||
|
example: '{{duration timeLeft "seconds"}} -> a few seconds',
|
||||||
|
description: "Produce a humanized duration left/until given an amount of time and the type of time measurement."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function fixSpecialCases(name, obj) {
|
function fixSpecialCases(name, obj) {
|
||||||
const args = obj.args
|
const args = obj.args
|
||||||
|
@ -134,15 +147,15 @@ function run() {
|
||||||
}
|
}
|
||||||
outputJSON[collection] = collectionInfo
|
outputJSON[collection] = collectionInfo
|
||||||
}
|
}
|
||||||
// add the date helper
|
// add extra helpers
|
||||||
outputJSON["date"] = {
|
for (let [collectionName, collection] of Object.entries(ADDED_HELPERS)) {
|
||||||
date: {
|
let input = collection
|
||||||
args: ["datetime", "format"],
|
if (outputJSON[collectionName]) {
|
||||||
numArgs: 2,
|
input = Object.assign(outputJSON[collectionName], collection)
|
||||||
example: '{{date now "DD-MM-YYYY"}}',
|
|
||||||
description: "Format a date using moment.js date formatting.",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
outputJSON[collectionName] = input
|
||||||
|
}
|
||||||
|
|
||||||
// convert all markdown to HTML
|
// convert all markdown to HTML
|
||||||
for (let collection of Object.values(outputJSON)) {
|
for (let collection of Object.values(outputJSON)) {
|
||||||
for (let helper of Object.values(collection)) {
|
for (let helper of Object.values(collection)) {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
const dayjs = require("dayjs")
|
const dayjs = require("dayjs")
|
||||||
|
dayjs.extend(require("dayjs/plugin/duration"))
|
||||||
|
dayjs.extend(require("dayjs/plugin/advancedFormat"))
|
||||||
|
dayjs.extend(require("dayjs/plugin/relativeTime"))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file was largely taken from the helper-date package - we did this for two reasons:
|
* This file was largely taken from the helper-date package - we did this for two reasons:
|
||||||
|
@ -50,7 +53,7 @@ function getContext(thisArg, locals, options) {
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function dateHelper(str, pattern, options) {
|
function initialSteps(str, pattern, options) {
|
||||||
if (isOptions(pattern)) {
|
if (isOptions(pattern)) {
|
||||||
options = pattern
|
options = pattern
|
||||||
pattern = null
|
pattern = null
|
||||||
|
@ -61,6 +64,21 @@ module.exports = function dateHelper(str, pattern, options) {
|
||||||
pattern = null
|
pattern = null
|
||||||
str = null
|
str = null
|
||||||
}
|
}
|
||||||
|
return {str, pattern, options}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLocale(str, pattern, options) {
|
||||||
|
// if options is null then it'll get updated here
|
||||||
|
({str, pattern, options} = initialSteps(str, pattern, options))
|
||||||
|
const defaults = { lang: "en", date: new Date(str) }
|
||||||
|
const opts = getContext(this, defaults, options)
|
||||||
|
|
||||||
|
// set the language to use
|
||||||
|
dayjs.locale(opts.lang || opts.language)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.date = (str, pattern, options) => {
|
||||||
|
({str, pattern, options} = initialSteps(str, pattern, options))
|
||||||
|
|
||||||
// if no args are passed, return a formatted date
|
// if no args are passed, return a formatted date
|
||||||
if (str == null && pattern == null) {
|
if (str == null && pattern == null) {
|
||||||
|
@ -68,11 +86,20 @@ module.exports = function dateHelper(str, pattern, options) {
|
||||||
return dayjs().format("MMMM DD, YYYY")
|
return dayjs().format("MMMM DD, YYYY")
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaults = { lang: "en", date: new Date(str) }
|
setLocale(str, pattern, options)
|
||||||
const opts = getContext(this, defaults, options)
|
|
||||||
|
|
||||||
// set the language to use
|
|
||||||
dayjs.locale(opts.lang || opts.language)
|
|
||||||
|
|
||||||
return dayjs(new Date(str)).format(pattern)
|
return dayjs(new Date(str)).format(pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports.duration = (str, pattern, format) => {
|
||||||
|
({str, pattern} = initialSteps(str, pattern))
|
||||||
|
|
||||||
|
setLocale(str, pattern)
|
||||||
|
|
||||||
|
const duration = dayjs.duration(str, pattern)
|
||||||
|
if (!isOptions(format)) {
|
||||||
|
return duration.format(format)
|
||||||
|
} else {
|
||||||
|
return duration.humanize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const helpers = require("@budibase/handlebars-helpers")
|
const helpers = require("@budibase/handlebars-helpers")
|
||||||
const dateHelper = require("./date")
|
const { date, duration } = require("./date")
|
||||||
const { HelperFunctionBuiltin } = require("./constants")
|
const { HelperFunctionBuiltin } = require("./constants")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,10 +18,15 @@ const EXTERNAL_FUNCTION_COLLECTIONS = [
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
const DATE_NAME = "date"
|
const ADDED_HELPERS = {
|
||||||
|
"date": date,
|
||||||
|
"duration": duration,
|
||||||
|
}
|
||||||
|
|
||||||
exports.registerAll = handlebars => {
|
exports.registerAll = handlebars => {
|
||||||
handlebars.registerHelper(DATE_NAME, dateHelper)
|
for (let [name, helper] of Object.entries(ADDED_HELPERS)) {
|
||||||
|
handlebars.registerHelper(name, helper)
|
||||||
|
}
|
||||||
let externalNames = []
|
let externalNames = []
|
||||||
for (let collection of EXTERNAL_FUNCTION_COLLECTIONS) {
|
for (let collection of EXTERNAL_FUNCTION_COLLECTIONS) {
|
||||||
// collect information about helper
|
// collect information about helper
|
||||||
|
@ -43,12 +48,13 @@ exports.registerAll = handlebars => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// add date external functionality
|
// add date external functionality
|
||||||
externalNames.push(DATE_NAME)
|
exports.externalHelperNames = externalNames.concat(Object.keys(ADDED_HELPERS))
|
||||||
exports.externalHelperNames = externalNames
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.unregisterAll = handlebars => {
|
exports.unregisterAll = handlebars => {
|
||||||
handlebars.unregisterHelper(DATE_NAME)
|
for (let name of Object.keys(ADDED_HELPERS)) {
|
||||||
|
handlebars.unregisterHelper(name)
|
||||||
|
}
|
||||||
for (let name of module.exports.externalHelperNames) {
|
for (let name of module.exports.externalHelperNames) {
|
||||||
handlebars.unregisterHelper(name)
|
handlebars.unregisterHelper(name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,6 +318,17 @@ describe("Cover a few complex use cases", () => {
|
||||||
expect(validity).toBe(true)
|
expect(validity).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("test a very complex duration output", async () => {
|
||||||
|
const currentTime = new Date(1612432082000).toISOString(),
|
||||||
|
eventTime = new Date(1612432071000).toISOString()
|
||||||
|
const input = `{{duration ( subtract (date currentTime "X")(date eventTime "X")) "seconds"}}`
|
||||||
|
const output = await processString(input, {
|
||||||
|
currentTime,
|
||||||
|
eventTime,
|
||||||
|
})
|
||||||
|
expect(output).toBe("a few seconds")
|
||||||
|
})
|
||||||
|
|
||||||
it("should confirm a bunch of invalid strings", () => {
|
it("should confirm a bunch of invalid strings", () => {
|
||||||
const invalids = ["{{ awd )", "{{ awdd () ", "{{ awdwad ", "{{ awddawd }"]
|
const invalids = ["{{ awd )", "{{ awdd () ", "{{ awdwad ", "{{ awddawd }"]
|
||||||
for (let invalid of invalids) {
|
for (let invalid of invalids) {
|
||||||
|
|
Loading…
Reference in New Issue