@budibase/string-templates 3.2.5 → 3.2.6

Sign up to get free protection for your applications and to get access to all the features.
package/dist/iife.mjs ADDED
@@ -0,0 +1 @@
1
+ !function(){const s={};try{if(process)return process.env=Object.assign({},process.env),void Object.assign(process.env,s)}catch(s){}globalThis.process={env:s}}();const s=s=>`(function(){\n${s}\n})();`;export{s as iifeWrapper};
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@budibase/string-templates",
3
- "version": "3.2.5",
3
+ "version": "3.2.6",
4
4
  "description": "Handlebars wrapper for Budibase templating.",
5
5
  "main": "dist/bundle.cjs",
6
6
  "module": "dist/bundle.mjs",
7
- "types": "src/index.ts",
7
+ "types": "dist/index.d.ts",
8
8
  "license": "MPL-2.0",
9
9
  "exports": {
10
10
  ".": {
@@ -12,12 +12,8 @@
12
12
  "import": "./dist/bundle.mjs"
13
13
  },
14
14
  "./package.json": "./package.json",
15
- "./iife": "./src/iife.js"
15
+ "./iife": "./dist/iife.mjs"
16
16
  },
17
- "files": [
18
- "dist",
19
- "src"
20
- ],
21
17
  "scripts": {
22
18
  "build": "tsc --emitDeclarationOnly && rollup -c",
23
19
  "dev": "rollup -cw",
@@ -48,5 +44,5 @@
48
44
  "ts-jest": "29.1.1",
49
45
  "typescript": "5.5.2"
50
46
  },
51
- "gitHead": "c1ee7b00e6687d588565b3d74ee24084a8d1ceab"
47
+ "gitHead": "4b9c088e1a3550a500613b3f24a15d046689abe3"
52
48
  }
@@ -1,131 +0,0 @@
1
- import { getJsHelperList } from "../helpers"
2
-
3
- function getLayers(fullBlock: string): string[] {
4
- let layers = []
5
- while (fullBlock.length) {
6
- const start = fullBlock.lastIndexOf("("),
7
- end = fullBlock.indexOf(")")
8
- let layer: string
9
- if (start === -1 || end === -1) {
10
- layer = fullBlock.trim()
11
- fullBlock = ""
12
- } else {
13
- const untrimmed = fullBlock.substring(start, end + 1)
14
- layer = untrimmed.substring(1, untrimmed.length - 1).trim()
15
- fullBlock =
16
- fullBlock.slice(0, start) +
17
- fullBlock.slice(start + untrimmed.length + 1, fullBlock.length)
18
- }
19
- layers.push(layer)
20
- }
21
- return layers
22
- }
23
-
24
- function getVariable(variableName: string) {
25
- if (!variableName || typeof variableName !== "string") {
26
- return variableName
27
- }
28
- // it is an array
29
- const arrayOrObject = [",", "{", ":"]
30
- let contains = false
31
- arrayOrObject.forEach(char => {
32
- if (variableName.includes(char)) {
33
- contains = true
34
- }
35
- })
36
- if (variableName.startsWith("[") && contains) {
37
- return variableName
38
- }
39
- // it is just a number
40
- if (!isNaN(parseFloat(variableName))) {
41
- return variableName
42
- }
43
- if (variableName.startsWith("'") || variableName.startsWith('"')) {
44
- return variableName
45
- }
46
- // extract variable
47
- return `$("${variableName}")`
48
- }
49
-
50
- function buildList(parts: string[], value: any) {
51
- function build() {
52
- return parts
53
- .map((part: string) =>
54
- part.startsWith("helper") ? part : getVariable(part)
55
- )
56
- .join(", ")
57
- }
58
- if (!value) {
59
- return parts.length > 1 ? `${build()}` : build()
60
- } else {
61
- return parts.length === 0 ? value : `${build()}, ${value}`
62
- }
63
- }
64
-
65
- function splitBySpace(layer: string) {
66
- const parts: string[] = []
67
- let started = null,
68
- endChar = null,
69
- last = 0
70
- function add(str: string) {
71
- const startsWith = ["]"]
72
- while (startsWith.indexOf(str.substring(0, 1)) !== -1) {
73
- str = str.substring(1, str.length)
74
- }
75
- if (str.length > 0) {
76
- parts.push(str.trim())
77
- }
78
- }
79
- const continuationChars = ["[", "'", '"']
80
- for (let index = 0; index < layer.length; index++) {
81
- const char = layer[index]
82
- if (continuationChars.indexOf(char) !== -1 && started == null) {
83
- started = index
84
- endChar = char === "[" ? "]" : char
85
- } else if (
86
- char === endChar &&
87
- started != null &&
88
- layer[index + 1] !== "."
89
- ) {
90
- add(layer.substring(started, index + 1))
91
- started = null
92
- endChar = null
93
- last = index + 1
94
- } else if (started == null && char === " ") {
95
- add(layer.substring(last, index))
96
- last = index
97
- }
98
- }
99
- if (
100
- (!layer.startsWith("[") || parts.length === 0) &&
101
- last !== layer.length - 1
102
- ) {
103
- add(layer.substring(last, layer.length))
104
- }
105
- return parts
106
- }
107
-
108
- export function convertHBSBlock(block: string, blockNumber: number) {
109
- const braceLength = block[2] === "{" ? 3 : 2
110
- block = block.substring(braceLength, block.length - braceLength).trim()
111
- const layers = getLayers(block)
112
-
113
- let value = null
114
- const list = getJsHelperList()
115
- for (let layer of layers) {
116
- const parts = splitBySpace(layer)
117
- if (value || parts.length > 1 || list[parts[0]]) {
118
- // first of layer should always be the helper
119
- const [helper] = parts.splice(0, 1)
120
- if (list[helper]) {
121
- value = `helpers.${helper}(${buildList(parts, value)})`
122
- }
123
- }
124
- // no helpers
125
- else {
126
- value = getVariable(parts[0])
127
- }
128
- }
129
- // split by space will remove square brackets
130
- return { variable: `var${blockNumber}`, value }
131
- }
package/src/errors.ts DELETED
@@ -1,20 +0,0 @@
1
- export class JsTimeoutError extends Error {
2
- static message = "Timed out while executing JS"
3
- static code = "JS_TIMEOUT_ERROR"
4
- code: string = JsTimeoutError.code
5
-
6
- constructor() {
7
- super(JsTimeoutError.message)
8
- }
9
- }
10
-
11
- export class UserScriptError extends Error {
12
- static code = "USER_SCRIPT_ERROR"
13
- code: string = UserScriptError.code
14
-
15
- constructor(readonly userScriptError: Error) {
16
- super(
17
- `error while running user-supplied JavaScript: ${userScriptError.toString()}`
18
- )
19
- }
20
- }
@@ -1,36 +0,0 @@
1
- import Handlebars from "handlebars"
2
-
3
- export default class Helper {
4
- private name: any
5
- private fn: any
6
- private useValueFallback: boolean
7
-
8
- constructor(name: string, fn: any, useValueFallback = true) {
9
- this.name = name
10
- this.fn = fn
11
- this.useValueFallback = useValueFallback
12
- }
13
-
14
- register(handlebars: typeof Handlebars) {
15
- // wrap the function so that no helper can cause handlebars to break
16
- handlebars.registerHelper(
17
- this.name,
18
- (value: any, info: { data: { root: {} } }) => {
19
- let context = {}
20
- if (info && info.data && info.data.root) {
21
- context = info.data.root
22
- }
23
- const result = this.fn(value, context)
24
- if (result == null) {
25
- return this.useValueFallback ? value : null
26
- } else {
27
- return result
28
- }
29
- }
30
- )
31
- }
32
-
33
- unregister(handlebars: { unregisterHelper: any }) {
34
- handlebars.unregisterHelper(this.name)
35
- }
36
- }
@@ -1,41 +0,0 @@
1
- export const HelperFunctionBuiltin = [
2
- "#if",
3
- "#unless",
4
- "#each",
5
- "#with",
6
- "lookup",
7
- "log",
8
- "blockHelperMissing",
9
- "each",
10
- "helperMissing",
11
- "if",
12
- "unless",
13
- "log",
14
- "lookup",
15
- "with",
16
- ]
17
-
18
- /**
19
- * full list of supported helpers can be found here:
20
- * https://github.com/Budibase/handlebars-helpers
21
- */
22
- export const EXTERNAL_FUNCTION_COLLECTIONS = [
23
- "math",
24
- "array",
25
- "number",
26
- "url",
27
- "string",
28
- "comparison",
29
- "object",
30
- "regex",
31
- "uuid",
32
- ]
33
-
34
- export const HelperFunctionNames = {
35
- OBJECT: "object",
36
- ALL: "all",
37
- LITERAL: "literal",
38
- JS: "js",
39
- }
40
-
41
- export const LITERAL_MARKER = "%LITERAL%"
@@ -1,133 +0,0 @@
1
- import dayjs from "dayjs"
2
-
3
- import dayjsDurationPlugin from "dayjs/plugin/duration"
4
- import dayjsAdvancedFormatPlugin from "dayjs/plugin/advancedFormat"
5
- import dayjsIsoWeekPlugin from "dayjs/plugin/isoWeek"
6
- import dayjsWeekYearPlugin from "dayjs/plugin/weekYear"
7
- import dayjsWeekOfYearPlugin from "dayjs/plugin/weekOfYear"
8
- import dayjsRelativeTimePlugin from "dayjs/plugin/relativeTime"
9
- import dayjsUtcPlugin from "dayjs/plugin/utc"
10
- import dayjsTimezonePlugin from "dayjs/plugin/timezone"
11
-
12
- dayjs.extend(dayjsDurationPlugin)
13
- dayjs.extend(dayjsAdvancedFormatPlugin)
14
- dayjs.extend(dayjsIsoWeekPlugin)
15
- dayjs.extend(dayjsWeekYearPlugin)
16
- dayjs.extend(dayjsWeekOfYearPlugin)
17
- dayjs.extend(dayjsRelativeTimePlugin)
18
- dayjs.extend(dayjsUtcPlugin)
19
- dayjs.extend(dayjsTimezonePlugin)
20
-
21
- /**
22
- * This file was largely taken from the helper-date package - we did this for two reasons:
23
- * 1. It made use of both moment of date.js - this caused some weird bugs with some relatively simple
24
- * syntax and didn't offer much in return.
25
- * 2. Replacing moment with dayjs helps massively reduce bundle size.
26
- * The original package can be found here:
27
- * https://github.com/helpers/helper-date
28
- */
29
-
30
- function isOptions(val: any) {
31
- return typeof val === "object" && typeof val.hash === "object"
32
- }
33
-
34
- function isApp(thisArg: any) {
35
- return (
36
- typeof thisArg === "object" &&
37
- typeof thisArg.options === "object" &&
38
- typeof thisArg.app === "object"
39
- )
40
- }
41
-
42
- function getContext(thisArg: any, locals: any, options: any) {
43
- if (isOptions(thisArg)) {
44
- return getContext({}, locals, thisArg)
45
- }
46
- // ensure args are in the correct order
47
- if (isOptions(locals)) {
48
- return getContext(thisArg, options, locals)
49
- }
50
- const appContext = isApp(thisArg) ? thisArg.context : {}
51
- options = options || {}
52
-
53
- // if "options" is not handlebars options, merge it onto locals
54
- if (!isOptions(options)) {
55
- locals = Object.assign({}, locals, options)
56
- }
57
- // merge handlebars root data onto locals if specified on the hash
58
- if (isOptions(options) && options.hash.root === true) {
59
- locals = Object.assign({}, options.data.root, locals)
60
- }
61
- let context = Object.assign({}, appContext, locals, options.hash)
62
- if (!isApp(thisArg)) {
63
- context = Object.assign({}, thisArg, context)
64
- }
65
- if (isApp(thisArg) && thisArg.view && thisArg.view.data) {
66
- context = Object.assign({}, context, thisArg.view.data)
67
- }
68
- return context
69
- }
70
-
71
- function initialConfig(str: any, pattern: any, options?: any) {
72
- if (isOptions(pattern)) {
73
- options = pattern
74
- pattern = null
75
- }
76
-
77
- if (isOptions(str)) {
78
- options = str
79
- pattern = null
80
- str = null
81
- }
82
- return { str, pattern, options }
83
- }
84
-
85
- function setLocale(this: any, str: any, pattern: any, options?: any) {
86
- // if options is null then it'll get updated here
87
- const config = initialConfig(str, pattern, options)
88
- const defaults = { lang: "en", date: new Date(config.str) }
89
- // for now don't allow this to be configurable, don't pass in options
90
- const opts = getContext(this, defaults, {})
91
-
92
- // set the language to use
93
- dayjs.locale(opts.lang || opts.language)
94
- }
95
-
96
- export const date = (str: any, pattern: any, options: any) => {
97
- const config = initialConfig(str, pattern, options)
98
-
99
- // if no args are passed, return a formatted date
100
- if (config.str == null && config.pattern == null) {
101
- dayjs.locale("en")
102
- return dayjs().format("MMMM DD, YYYY")
103
- }
104
-
105
- setLocale(config.str, config.pattern, config.options)
106
-
107
- let date = dayjs(new Date(config.str))
108
- if (typeof config.options === "string") {
109
- date =
110
- config.options.toLowerCase() === "utc"
111
- ? date.utc()
112
- : date.tz(config.options)
113
- } else {
114
- date = date.tz(dayjs.tz.guess())
115
- }
116
- if (config.pattern === "") {
117
- return date.toISOString()
118
- }
119
- return date.format(config.pattern)
120
- }
121
-
122
- export const duration = (str: any, pattern: any, format: any) => {
123
- const config = initialConfig(str, pattern)
124
-
125
- setLocale(config.str, config.pattern)
126
-
127
- const duration = dayjs.duration(config.str, config.pattern)
128
- if (format && !isOptions(format)) {
129
- return duration.format(format)
130
- } else {
131
- return duration.humanize()
132
- }
133
- }
@@ -1,57 +0,0 @@
1
- // @ts-ignore we don't have types for it
2
- import helpers from "@budibase/handlebars-helpers"
3
-
4
- import { date, duration } from "./date"
5
- import {
6
- HelperFunctionBuiltin,
7
- EXTERNAL_FUNCTION_COLLECTIONS,
8
- } from "./constants"
9
- import Handlebars from "handlebars"
10
-
11
- const ADDED_HELPERS = {
12
- date: date,
13
- duration: duration,
14
- }
15
-
16
- export const externalCollections = EXTERNAL_FUNCTION_COLLECTIONS
17
- export const addedHelpers = ADDED_HELPERS
18
-
19
- export function registerAll(handlebars: typeof Handlebars) {
20
- for (let [name, helper] of Object.entries(ADDED_HELPERS)) {
21
- handlebars.registerHelper(name, helper)
22
- }
23
- let externalNames = []
24
- for (let collection of EXTERNAL_FUNCTION_COLLECTIONS) {
25
- // collect information about helper
26
- let hbsHelperInfo = helpers[collection]()
27
- for (let entry of Object.entries(hbsHelperInfo)) {
28
- const name = entry[0]
29
- // skip built-in functions and ones seen already
30
- if (
31
- HelperFunctionBuiltin.indexOf(name) !== -1 ||
32
- externalNames.indexOf(name) !== -1
33
- ) {
34
- continue
35
- }
36
- externalNames.push(name)
37
- }
38
- // attach it to our handlebars instance
39
- helpers[collection]({
40
- handlebars,
41
- })
42
- }
43
- // add date external functionality
44
- externalHelperNames = externalNames.concat(Object.keys(ADDED_HELPERS))
45
- }
46
-
47
- export function unregisterAll(handlebars: typeof Handlebars) {
48
- for (let name of Object.keys(ADDED_HELPERS)) {
49
- handlebars.unregisterHelper(name)
50
- }
51
- for (let name of externalHelperNames) {
52
- handlebars.unregisterHelper(name)
53
- }
54
- externalHelperNames = []
55
- }
56
-
57
- export let externalHelperNames: any[] = []
@@ -1,103 +0,0 @@
1
- import Helper from "./Helper"
2
- import Handlebars from "handlebars"
3
- import * as externalHandlebars from "./external"
4
- import { processJS } from "./javascript"
5
- import {
6
- HelperFunctionNames,
7
- HelperFunctionBuiltin,
8
- LITERAL_MARKER,
9
- } from "./constants"
10
-
11
- export { getJsHelperList } from "./list"
12
-
13
- const HTML_SWAPS = {
14
- "<": "&lt;",
15
- ">": "&gt;",
16
- }
17
-
18
- function isObject(value: string | any[]) {
19
- if (value == null || typeof value !== "object") {
20
- return false
21
- }
22
- return (
23
- value.toString() === "[object Object]" ||
24
- (value.length > 0 && typeof value[0] === "object")
25
- )
26
- }
27
-
28
- const HELPERS = [
29
- // external helpers
30
- new Helper(HelperFunctionNames.OBJECT, (value: any) => {
31
- return new Handlebars.SafeString(JSON.stringify(value))
32
- }),
33
- // javascript helper
34
- new Helper(HelperFunctionNames.JS, processJS, false),
35
- // this help is applied to all statements
36
- new Helper(
37
- HelperFunctionNames.ALL,
38
- (value: string, inputs: { __opts: any }) => {
39
- const { __opts } = inputs
40
- if (isObject(value)) {
41
- return new Handlebars.SafeString(JSON.stringify(value))
42
- }
43
- // null/undefined values produce bad results
44
- if (__opts && __opts.onlyFound && value == null) {
45
- return __opts.input
46
- }
47
- if (value == null || typeof value !== "string") {
48
- return value == null ? "" : value
49
- }
50
- // TODO: check, this should always be false
51
- if (value && (value as any).string) {
52
- value = (value as any).string
53
- }
54
- let text: any = value
55
- if (__opts && __opts.escapeNewlines) {
56
- text = value.replace(/\n/g, "\\n")
57
- }
58
- text = new Handlebars.SafeString(text.replace(/&amp;/g, "&"))
59
- if (text == null || typeof text !== "string") {
60
- return text
61
- }
62
- return text.replace(/[<>]/g, (tag: string) => {
63
- return HTML_SWAPS[tag as keyof typeof HTML_SWAPS] || tag
64
- })
65
- }
66
- ),
67
- // adds a note for post-processor
68
- new Helper(HelperFunctionNames.LITERAL, (value: any) => {
69
- if (value === undefined) {
70
- return ""
71
- }
72
- const type = typeof value
73
- const outputVal = type === "object" ? JSON.stringify(value) : value
74
- return `{{${LITERAL_MARKER} ${type}-${outputVal}}}`
75
- }),
76
- ]
77
-
78
- export function HelperNames() {
79
- return Object.values(HelperFunctionNames).concat(
80
- HelperFunctionBuiltin,
81
- externalHandlebars.externalHelperNames
82
- )
83
- }
84
-
85
- export function registerMinimum(handlebars: typeof Handlebars) {
86
- for (let helper of HELPERS) {
87
- helper.register(handlebars)
88
- }
89
- }
90
-
91
- export function registerAll(handlebars: typeof Handlebars) {
92
- registerMinimum(handlebars)
93
- // register imported helpers
94
- externalHandlebars.registerAll(handlebars)
95
- }
96
-
97
- export function unregisterAll(handlebars: any) {
98
- for (let helper of HELPERS) {
99
- helper.unregister(handlebars)
100
- }
101
- // unregister all imported helpers
102
- externalHandlebars.unregisterAll(handlebars)
103
- }