silverbullet/lib/builtin_query_functions.ts

125 lines
3.3 KiB
TypeScript
Raw Normal View History

2024-02-29 22:23:05 +08:00
import type { FunctionMap } from "../plug-api/types.ts";
2024-07-27 17:03:42 +08:00
import { niceDate, niceTime, safeTime } from "./dates.ts";
export const builtinFunctions: FunctionMap = {
2024-03-02 18:01:52 +08:00
// String functions
contains(str: unknown, substr: unknown) {
if (typeof str !== "string") {
throw new Error("contains(): str is not a string");
}
if (typeof substr !== "string") {
throw new Error("contains(): substr is not a string");
}
return str.includes(substr);
},
replace(
str: unknown,
...replacementPairs: unknown[]
) {
if (typeof str !== "string") {
throw new Error("replace(): str is not a string");
}
2024-02-23 20:47:27 +08:00
if (replacementPairs.length % 2 !== 0) {
throw new Error(
"replace(): requires an even number of replacement arguments",
2024-02-23 20:47:27 +08:00
);
}
let ret = str;
2024-02-23 20:47:27 +08:00
for (let i = 0; i < replacementPairs.length; i += 2) {
let match = replacementPairs[i];
2024-02-23 20:47:27 +08:00
const replace = replacementPairs[i + 1];
match = Array.isArray(match)
? new RegExp(match[0], (match[1] ?? "") + "g")
2024-02-23 20:47:27 +08:00
: match;
if (typeof match !== "string" && (!(match instanceof RegExp))) {
throw new Error(
`replace(): match is not a string or regexp`,
);
}
if (typeof replace !== "string") {
throw new Error(
`replace(): replace is not a string`,
);
}
ret = ret.replaceAll(match, replace);
2024-02-23 20:47:27 +08:00
}
return ret;
},
json: (v: unknown) => {
return JSON.stringify(v);
},
niceDate: (ts: unknown) => {
if (
typeof ts !== "string" && typeof ts !== "number" && !(ts instanceof Date)
) {
throw new Error("niceDate(): ts is not a valid date");
}
const date = new Date(ts);
if (isNaN(date.getTime())) {
throw new Error("niceDate(): ts is not a valid date");
}
return niceDate(new Date(ts));
},
escapeRegexp: (ts: unknown) => {
if (typeof ts !== "string") {
throw new Error("escapeRegexp(): ts is not a string");
}
return ts.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
},
// Legacy name: don't use
escape: (handlebarsExpr: string) => {
return `{{${handlebarsExpr}}}`;
},
escapeDirective: (directiveText: unknown) => {
return `{{${directiveText}}}`;
},
2024-03-02 18:01:52 +08:00
today() {
return niceDate(new Date());
},
time: () => niceTime(new Date()),
2024-07-27 17:03:42 +08:00
safeTime: () => safeTime(new Date()),
tomorrow: () => {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
return niceDate(tomorrow);
},
yesterday: () => {
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
return niceDate(yesterday);
},
lastWeek: () => {
const lastWeek = new Date();
lastWeek.setDate(lastWeek.getDate() - 7);
return niceDate(lastWeek);
},
nextWeek: () => {
const nextWeek = new Date();
nextWeek.setDate(nextWeek.getDate() + 7);
return niceDate(nextWeek);
},
weekStart: (startOnMonday = true) => {
const d = new Date();
const day = d.getDay();
let diff = d.getDate() - day;
if (startOnMonday) {
diff += day == 0 ? -6 : 1;
}
return niceDate(new Date(d.setDate(diff)));
},
// List functions
count: <T>(list: T[]) => {
return list.length;
},
at: <T>(list: T[], index: number) => {
return list[index];
},
};