diff --git a/package-lock.json b/package-lock.json index 675f3d66..8734841e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "query-builder", - "version": "1.27.1", + "version": "1.28.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "query-builder", - "version": "1.27.1", + "version": "1.28.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index dae31acd..957b5f51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "query-builder", - "version": "1.27.1", + "version": "1.28.0", "description": "Introduces new user interfaces for building queries in Roam", "main": "./build/main.js", "author": { diff --git a/src/utils/conditionToDatalog.ts b/src/utils/conditionToDatalog.ts index 509c2dec..41621e06 100644 --- a/src/utils/conditionToDatalog.ts +++ b/src/utils/conditionToDatalog.ts @@ -21,6 +21,13 @@ type ConditionToDatalog = (condition: Condition) => DatalogClause[]; const INPUT_REGEX = /^:in /; +const isRegex = (str: string) => /^\/.+\/(i)?$/.test(str); +const regexRePatternValue = (str: string) => { + const isCaseInsensitive = str.endsWith("/i"); + return isCaseInsensitive + ? `"(?i)${str.slice(1, -2).replace(/\\/g, "\\\\")}"` + : `"${str.slice(1, -1).replace(/\\/g, "\\\\")}"`; +}; const getTitleDatalog = ({ source, target, @@ -100,7 +107,8 @@ const getTitleDatalog = ({ }, ]; } - if (target.startsWith("/") && target.endsWith("/")) { + if (isRegex(target)) { + const rePattern = regexRePatternValue(target); return [ { type: "data-pattern", @@ -116,7 +124,7 @@ const getTitleDatalog = ({ arguments: [ { type: "constant", - value: `"${target.slice(1, -1).replace(/\\/g, "\\\\")}"`, + value: rePattern, }, ], binding: { @@ -388,37 +396,88 @@ const translator: Record = { isVariable: true, }, "with text": { - callback: ({ source, target }) => [ - { - type: "or-clause", - clauses: [ + callback: ({ source, target }) => { + if (isRegex(target)) { + const rePattern = regexRePatternValue(target); + return [ { - type: "data-pattern", + type: "or-clause", + clauses: [ + { + type: "data-pattern", + arguments: [ + { type: "variable", value: source }, + { type: "constant", value: ":block/string" }, + { type: "variable", value: `${source}-String` }, + ], + }, + { + type: "data-pattern", + arguments: [ + { type: "variable", value: source }, + { type: "constant", value: ":node/title" }, + { type: "variable", value: `${source}-String` }, + ], + }, + ], + }, + { + type: "fn-expr", + fn: "re-pattern", arguments: [ - { type: "variable", value: source }, - { type: "constant", value: ":block/string" }, + { + type: "constant", + value: rePattern, + }, + ], + binding: { + type: "bind-scalar", + variable: { type: "variable", value: `${target}-regex` }, + }, + }, + { + type: "pred-expr", + pred: "re-find", + arguments: [ + { type: "variable", value: `${target}-regex` }, { type: "variable", value: `${source}-String` }, ], }, + ]; + } else { + return [ + { + type: "or-clause", + clauses: [ + { + type: "data-pattern", + arguments: [ + { type: "variable", value: source }, + { type: "constant", value: ":block/string" }, + { type: "variable", value: `${source}-String` }, + ], + }, + { + type: "data-pattern", + arguments: [ + { type: "variable", value: source }, + { type: "constant", value: ":node/title" }, + { type: "variable", value: `${source}-String` }, + ], + }, + ], + }, { - type: "data-pattern", + type: "pred-expr", + pred: "clojure.string/includes?", arguments: [ - { type: "variable", value: source }, - { type: "constant", value: ":node/title" }, { type: "variable", value: `${source}-String` }, + { type: "constant", value: `"${normalizePageTitle(target)}"` }, ], }, - ], - }, - { - type: "pred-expr", - pred: "clojure.string/includes?", - arguments: [ - { type: "variable", value: `${source}-String` }, - { type: "constant", value: `"${normalizePageTitle(target)}"` }, - ], - }, - ], + ]; + } + }, placeholder: "Enter any text", }, "created by": {