diff --git a/packages/nc-gui/components/project/spreadsheet/components/editColumn/FormulaOptions.vue b/packages/nc-gui/components/project/spreadsheet/components/editColumn/FormulaOptions.vue
index e1708d9851..a543a0375c 100644
--- a/packages/nc-gui/components/project/spreadsheet/components/editColumn/FormulaOptions.vue
+++ b/packages/nc-gui/components/project/spreadsheet/components/editColumn/FormulaOptions.vue
@@ -16,7 +16,7 @@
@keydown.enter.prevent="selectText"
/>
- Hint: Use $ to reference columns, e.g: $column_name$. For more, please check out
+ Hint: Use {} to reference columns, e.g: {column_name}. For more, please check out
Formulas.
@@ -97,6 +97,7 @@ import debounce from 'debounce'
import jsep from 'jsep'
import { UITypes } from 'nocodb-sdk'
import formulaList, { validations } from '../../../../../helpers/formulaList'
+import curly from '../../../../../helpers/formulaCurlyHook'
import { getWordUntilCaret, insertAtCursor } from '@/helpers'
import NcAutocompleteTree from '@/helpers/NcAutocompleteTree'
@@ -161,6 +162,7 @@ export default {
},
created() {
this.formula = { value: this.value || '' }
+ jsep.plugins.register(curly)
},
methods: {
async save() {
@@ -219,6 +221,7 @@ export default {
}
},
validateAgainstMeta(pt, arr = []) {
+ console.log('pt.type= ' + pt.type)
if (pt.type === 'CallExpression') {
if (!this.availableFunctions.includes(pt.callee.name)) {
arr.push(`'${pt.callee.name}' function is not available`)
@@ -235,11 +238,7 @@ export default {
}
pt.arguments.map(arg => this.validateAgainstMeta(arg, arr))
} else if (pt.type === 'Identifier') {
- // $column_name$ -> column_name
- const sanitizedPtName = pt.name.substring(1, pt.name.length - 1)
- if (this.meta.columns.filter(c => !this.column || this.column.id !== c.id).find(c => c.title === pt.name)) {
- arr.push(`Column '${pt.name}' needs to be wrapped by $. Try $${pt.name}$ instead`)
- } else if (this.meta.columns.filter(c => !this.column || this.column.id !== c.id).every(c => c.title !== sanitizedPtName)) {
+ if (this.meta.columns.filter(c => !this.column || this.column.id !== c.id).every(c => c.title !== pt.name)) {
arr.push(`Column '${pt.name}' is not available`)
}
} else if (pt.type === 'BinaryExpression') {
@@ -257,7 +256,7 @@ export default {
if (it.type === 'function') {
this.$set(this.formula, 'value', insertAtCursor(this.$refs.input.$el.querySelector('input'), text, len, 1))
} else if (it.type === 'column') {
- this.$set(this.formula, 'value', insertAtCursor(this.$refs.input.$el.querySelector('input'), '$' + text + '$', len))
+ this.$set(this.formula, 'value', insertAtCursor(this.$refs.input.$el.querySelector('input'), '{' + text + '}', len))
} else {
this.$set(this.formula, 'value', insertAtCursor(this.$refs.input.$el.querySelector('input'), text, len))
}
diff --git a/packages/nc-gui/helpers/formulaCurlyHook.js b/packages/nc-gui/helpers/formulaCurlyHook.js
new file mode 100644
index 0000000000..3661b088f6
--- /dev/null
+++ b/packages/nc-gui/helpers/formulaCurlyHook.js
@@ -0,0 +1,24 @@
+const OCURLY_CODE = 123; // {
+const CCURLY_CODE = 125; // }
+
+export default {
+ name: 'curly',
+ init(jsep) {
+ jsep.hooks.add('gobble-token', function gobbleCurlyLiteral(env) {
+ const { context } = env
+ if (!jsep.isIdentifierStart(context.code) && context.code === OCURLY_CODE) {
+ context.index += 1
+ let nodes = context.gobbleExpressions(CCURLY_CODE)
+ if (context.code === CCURLY_CODE) {
+ context.index += 1
+ if (nodes.length > 0) {
+ env.node = nodes[0]
+ }
+ return env.node
+ } else {
+ context.throwError('Unclosed }')
+ }
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json
index 31f19b9f86..66b60bcf64 100644
--- a/packages/nc-gui/package-lock.json
+++ b/packages/nc-gui/package-lock.json
@@ -22,7 +22,7 @@
"fix-path": "^3.0.0",
"httpsnippet": "^2.0.0",
"inflection": "^1.12.0",
- "jsep": "^0.4.0",
+ "jsep": "^1.3.6",
"material-design-icons-iconfont": "^5.0.1",
"monaco-editor": "^0.19.3",
"monaco-themes": "^0.2.5",
@@ -76,7 +76,7 @@
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
- "jsep": "^0.4.0"
+ "jsep": "^1.3.6"
},
"devDependencies": {
"@ava/typescript": "^1.1.1",
@@ -9952,9 +9952,9 @@
}
},
"node_modules/jsep": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/jsep/-/jsep-0.4.0.tgz",
- "integrity": "sha512-UDkrzhJK8hmgXeGK8WIiecc/cuW4Vnx5nnrRma7yaxK0WXlvZ4VerGrcxPzifd/CA6QdcI1hpXqr22tHKXpcQA==",
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.6.tgz",
+ "integrity": "sha512-o7fP1eZVROIChADx7HKiwGRVI0tUqgUUGhaok6DP7cMxpDeparuooREDBDeNk2G5KIB49MBSkRYsCOu4PmZ+1w==",
"engines": {
"node": ">= 10.16.0"
}
@@ -24714,9 +24714,9 @@
}
},
"jsep": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/jsep/-/jsep-0.4.0.tgz",
- "integrity": "sha512-UDkrzhJK8hmgXeGK8WIiecc/cuW4Vnx5nnrRma7yaxK0WXlvZ4VerGrcxPzifd/CA6QdcI1hpXqr22tHKXpcQA=="
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.6.tgz",
+ "integrity": "sha512-o7fP1eZVROIChADx7HKiwGRVI0tUqgUUGhaok6DP7cMxpDeparuooREDBDeNk2G5KIB49MBSkRYsCOu4PmZ+1w=="
},
"jsesc": {
"version": "2.5.2",
@@ -25389,7 +25389,7 @@
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"gh-pages": "^3.1.0",
- "jsep": "^0.4.0",
+ "jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"nyc": "^15.1.0",
"open-cli": "^6.0.1",
diff --git a/packages/nc-gui/package.json b/packages/nc-gui/package.json
index 9305f5b655..057b4ded37 100644
--- a/packages/nc-gui/package.json
+++ b/packages/nc-gui/package.json
@@ -25,7 +25,7 @@
"fix-path": "^3.0.0",
"httpsnippet": "^2.0.0",
"inflection": "^1.12.0",
- "jsep": "^0.4.0",
+ "jsep": "^1.3.6",
"material-design-icons-iconfont": "^5.0.1",
"monaco-editor": "^0.19.3",
"monaco-themes": "^0.2.5",
diff --git a/packages/nocodb-sdk/package-lock.json b/packages/nocodb-sdk/package-lock.json
index 2d1bb01701..1b51d927c4 100644
--- a/packages/nocodb-sdk/package-lock.json
+++ b/packages/nocodb-sdk/package-lock.json
@@ -10,7 +10,7 @@
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
- "jsep": "^0.4.0"
+ "jsep": "^1.3.6"
},
"devDependencies": {
"@ava/typescript": "^1.1.1",
@@ -6764,9 +6764,9 @@
}
},
"node_modules/jsep": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/jsep/-/jsep-0.4.0.tgz",
- "integrity": "sha512-UDkrzhJK8hmgXeGK8WIiecc/cuW4Vnx5nnrRma7yaxK0WXlvZ4VerGrcxPzifd/CA6QdcI1hpXqr22tHKXpcQA==",
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.6.tgz",
+ "integrity": "sha512-o7fP1eZVROIChADx7HKiwGRVI0tUqgUUGhaok6DP7cMxpDeparuooREDBDeNk2G5KIB49MBSkRYsCOu4PmZ+1w==",
"engines": {
"node": ">= 10.16.0"
}
@@ -15535,9 +15535,9 @@
}
},
"jsep": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/jsep/-/jsep-0.4.0.tgz",
- "integrity": "sha512-UDkrzhJK8hmgXeGK8WIiecc/cuW4Vnx5nnrRma7yaxK0WXlvZ4VerGrcxPzifd/CA6QdcI1hpXqr22tHKXpcQA=="
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.6.tgz",
+ "integrity": "sha512-o7fP1eZVROIChADx7HKiwGRVI0tUqgUUGhaok6DP7cMxpDeparuooREDBDeNk2G5KIB49MBSkRYsCOu4PmZ+1w=="
},
"jsesc": {
"version": "2.5.2",
diff --git a/packages/nocodb-sdk/package.json b/packages/nocodb-sdk/package.json
index 96a2dbeace..985cfa4649 100644
--- a/packages/nocodb-sdk/package.json
+++ b/packages/nocodb-sdk/package.json
@@ -44,7 +44,7 @@
},
"dependencies": {
"axios": "^0.21.1",
- "jsep": "^0.4.0"
+ "jsep": "^1.3.6"
},
"devDependencies": {
"@ava/typescript": "^1.1.1",
diff --git a/packages/nocodb-sdk/src/lib/formulaHelpers.ts b/packages/nocodb-sdk/src/lib/formulaHelpers.ts
index a1f97b20a3..1472f4fa40 100644
--- a/packages/nocodb-sdk/src/lib/formulaHelpers.ts
+++ b/packages/nocodb-sdk/src/lib/formulaHelpers.ts
@@ -1,6 +1,7 @@
import jsep from 'jsep';
import { ColumnType } from './Api';
+
export function substituteColumnIdWithAliasInFormula(
formula,
columns: ColumnType[],
@@ -23,15 +24,39 @@ export function substituteColumnIdWithAliasInFormula(
c.title === colNameOrId
);
pt.name = column?.title || ptRaw?.name || pt?.name;
- if (pt.name[0] != '$' && pt.name[pt.name.length - 1] != '$') {
- pt.name = '$' + pt.name + '$';
- }
} else if (pt.type === 'BinaryExpression') {
substituteId(pt.left, ptRaw?.left);
substituteId(pt.right, ptRaw?.right);
}
};
+ // register curly hook
+ jsep.plugins.register({
+ name: 'curly',
+ init(jsep) {
+ jsep.hooks.add('gobble-token', function gobbleCurlyLiteral(env) {
+ const OCURLY_CODE = 123; // {
+ const CCURLY_CODE = 125; // }
+ const { context } = env;
+ if (
+ !jsep.isIdentifierStart(context.code) &&
+ context.code === OCURLY_CODE
+ ) {
+ context.index += 1;
+ const nodes = context.gobbleExpressions(CCURLY_CODE);
+ if (context.code === CCURLY_CODE) {
+ context.index += 1;
+ if (nodes.length > 0) {
+ env.node = nodes[0];
+ }
+ return env.node;
+ } else {
+ context.throwError('Unclosed }');
+ }
+ }
+ });
+ },
+ } as jsep.IPlugin);
const parsedFormula = jsep(formula);
const parsedRawFormula = rawFormula && jsep(rawFormula);
substituteId(parsedFormula, parsedRawFormula);
@@ -65,7 +90,7 @@ export function jsepTreeToFormula(node) {
}
if (node.type === 'Identifier') {
- return node.name;
+ return '{' + node.name + '}';
}
if (node.type === 'Literal') {
diff --git a/packages/nocodb/package-lock.json b/packages/nocodb/package-lock.json
index 9b7f90dce5..4425d71f66 100644
--- a/packages/nocodb/package-lock.json
+++ b/packages/nocodb/package-lock.json
@@ -52,7 +52,7 @@
"ioredis-mock": "^7.1.0",
"is-docker": "^2.2.1",
"js-beautify": "^1.11.0",
- "jsep": "^0.4.0",
+ "jsep": "^1.3.6",
"json2csv": "^5.0.6",
"jsonfile": "^6.1.0",
"jsonwebtoken": "^8.5.1",
@@ -160,7 +160,7 @@
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
- "jsep": "^0.4.0"
+ "jsep": "^1.3.6"
},
"devDependencies": {
"@ava/typescript": "^1.1.1",
@@ -13834,9 +13834,9 @@
"optional": true
},
"node_modules/jsep": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/jsep/-/jsep-0.4.0.tgz",
- "integrity": "sha512-UDkrzhJK8hmgXeGK8WIiecc/cuW4Vnx5nnrRma7yaxK0WXlvZ4VerGrcxPzifd/CA6QdcI1hpXqr22tHKXpcQA==",
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.6.tgz",
+ "integrity": "sha512-o7fP1eZVROIChADx7HKiwGRVI0tUqgUUGhaok6DP7cMxpDeparuooREDBDeNk2G5KIB49MBSkRYsCOu4PmZ+1w==",
"engines": {
"node": ">= 10.16.0"
}
@@ -35846,9 +35846,9 @@
"optional": true
},
"jsep": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/jsep/-/jsep-0.4.0.tgz",
- "integrity": "sha512-UDkrzhJK8hmgXeGK8WIiecc/cuW4Vnx5nnrRma7yaxK0WXlvZ4VerGrcxPzifd/CA6QdcI1hpXqr22tHKXpcQA=="
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.6.tgz",
+ "integrity": "sha512-o7fP1eZVROIChADx7HKiwGRVI0tUqgUUGhaok6DP7cMxpDeparuooREDBDeNk2G5KIB49MBSkRYsCOu4PmZ+1w=="
},
"jsesc": {
"version": "2.5.2",
@@ -37849,7 +37849,7 @@
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"gh-pages": "^3.1.0",
- "jsep": "^0.4.0",
+ "jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"nyc": "^15.1.0",
"open-cli": "^6.0.1",
diff --git a/packages/nocodb/package.json b/packages/nocodb/package.json
index cc2cae2723..67778b1c7d 100644
--- a/packages/nocodb/package.json
+++ b/packages/nocodb/package.json
@@ -134,7 +134,7 @@
"ioredis-mock": "^7.1.0",
"is-docker": "^2.2.1",
"js-beautify": "^1.11.0",
- "jsep": "^0.4.0",
+ "jsep": "^1.3.6",
"json2csv": "^5.0.6",
"jsonfile": "^6.1.0",
"jsonwebtoken": "^8.5.1",
diff --git a/packages/nocodb/src/lib/noco/meta/helpers/formulaHelpers.ts b/packages/nocodb/src/lib/noco/meta/helpers/formulaHelpers.ts
index f49927f09c..b87441f351 100644
--- a/packages/nocodb/src/lib/noco/meta/helpers/formulaHelpers.ts
+++ b/packages/nocodb/src/lib/noco/meta/helpers/formulaHelpers.ts
@@ -14,53 +14,79 @@ export async function substituteColumnAliasWithIdInFormula(
} else if (pt.type === 'Literal') {
return;
} else if (pt.type === 'Identifier') {
- const sanitizedPtName = pt.name.substring(1, pt.name.length - 1);
- const colNameOrId = sanitizedPtName;
+ const colNameOrId = pt.name;
const column = columns.find(
c =>
c.id === colNameOrId ||
c.column_name === colNameOrId ||
c.title === colNameOrId
);
- pt.name = column.id;
+ pt.name = '{' + column.id + '}';
} else if (pt.type === 'BinaryExpression') {
await substituteId(pt.left);
await substituteId(pt.right);
}
};
-
+ // register curly hook
+ jsep.plugins.register({
+ name: 'curly',
+ init(jsep) {
+ jsep.hooks.add('gobble-token', function gobbleCurlyLiteral(env) {
+ const OCURLY_CODE = 123; // {
+ const CCURLY_CODE = 125; // }
+ const { context } = env;
+ if (
+ !jsep.isIdentifierStart(context.code) &&
+ context.code === OCURLY_CODE
+ ) {
+ context.index += 1;
+ const nodes = context.gobbleExpressions(CCURLY_CODE);
+ if (context.code === CCURLY_CODE) {
+ context.index += 1;
+ if (nodes.length > 0) {
+ env.node = nodes[0];
+ }
+ return env.node;
+ } else {
+ context.throwError('Unclosed }');
+ }
+ }
+ });
+ }
+ } as jsep.IPlugin);
const parsedFormula = jsep(formula);
await substituteId(parsedFormula);
return jsepTreeToFormula(parsedFormula);
}
-export function substituteColumnIdWithAliasInFormula(
- formula,
- columns: Column[]
-) {
- const substituteId = (pt: any) => {
- if (pt.type === 'CallExpression') {
- for (const arg of pt.arguments || []) {
- substituteId(arg);
- }
- } else if (pt.type === 'Literal') {
- return;
- } else if (pt.type === 'Identifier') {
- const colNameOrId = pt.name;
- const column = columns.find(
- c =>
- c.id === colNameOrId ||
- c.column_name === colNameOrId ||
- c.title === colNameOrId
- );
- pt.name = column.id;
- } else if (pt.type === 'BinaryExpression') {
- substituteId(pt.left);
- substituteId(pt.right);
- }
- };
-
- const parsedFormula = jsep(formula);
- substituteId(parsedFormula);
- return jsepTreeToFormula(parsedFormula);
-}
+// not in use
+// export function substituteColumnIdWithAliasInFormula(
+// formula,
+// columns: Column[]
+// ) {
+// const substituteId = (pt: any) => {
+// if (pt.type === 'CallExpression') {
+// for (const arg of pt.arguments || []) {
+// substituteId(arg);
+// }
+// } else if (pt.type === 'Literal') {
+// return;
+// } else if (pt.type === 'Identifier') {
+// const colNameOrId = pt.name;
+// const column = columns.find(
+// c =>
+// c.id === colNameOrId ||
+// c.column_name === colNameOrId ||
+// c.title === colNameOrId
+// );
+// pt.name = column.id;
+// } else if (pt.type === 'BinaryExpression') {
+// substituteId(pt.left);
+// substituteId(pt.right);
+// }
+// };
+//
+// const parsedFormula = jsep(formula);
+// substituteId(parsedFormula);
+// return jsepTreeToFormula(parsedFormula);
+// }