diff --git a/gulpfile.mjs b/gulpfile.mjs index fb54f96..af31cdc 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -1,5 +1,4 @@ import gulp from 'gulp'; -import rename from 'gulp-rename'; import { deleteAsync } from 'del'; gulp.task('remove-server', async () => await deleteAsync(['build/server'])); @@ -13,14 +12,10 @@ function copyAssets(assetsDir) { () => gulp.src('./node_modules/@formio/core/dist/formio.core.min.js').pipe(gulp.dest(assetsDir)), () => gulp.src('./node_modules/fast-json-patch/dist/fast-json-patch.min.js').pipe(gulp.dest(assetsDir)), () => gulp.src('./node_modules/nunjucks/browser/nunjucks.min.js').pipe(gulp.dest(assetsDir)), - () => gulp.src('./node_modules/nunjucks-date-filter/index.js').pipe(rename('nunjucks-date-filter.js')).pipe(gulp.dest(assetsDir)), - () => gulp.src('./src/core/deps/assets/*.html').pipe(gulp.dest(assetsDir)) + () => gulp.src('./src/core/deps/assets/*').pipe(gulp.dest(assetsDir)) ) } gulp.task('copy-assets-build', copyAssets('build/core/deps/assets')); gulp.task('prebuild', async () => deleteAsync(['build'])) gulp.task('postbuild', gulp.parallel('copy-assets-build', 'remove-server')); - -gulp.task('pretest', copyAssets('src/core/deps/assets')); -gulp.task('posttest', async () => await deleteAsync(['src/core/deps/assets/*.js'])); \ No newline at end of file diff --git a/package.json b/package.json index 01fdcd6..a17cd5a 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,6 @@ "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", "eslint-plugin-promise": "^6.0.0", "gulp": "^4.0.2", - "gulp-rename": "^2.0.0", "husky": ">=6", "lint-staged": ">=10", "mocha": "^10.2.0", diff --git a/src/core/__tests__/ContextBuilder.test.ts b/src/core/__tests__/ContextBuilder.test.ts index fe07ba5..90a70ff 100644 --- a/src/core/__tests__/ContextBuilder.test.ts +++ b/src/core/__tests__/ContextBuilder.test.ts @@ -40,6 +40,13 @@ describe('Test ContextBuilder', () => { expect(result).to.equal('Hello World'); }); + it(`should evaluate code with nunjucks['lib']`, () => { + const result = context.evalSync( + `var nlib = nunjucks["lib"]; var date = moment.utc('2024-08-01T13:03:26.208Z'); nlib.isFunction(date['add']);`, + ); + expect(result).to.equal(true); + }); + it('should evaluate code with injectable depencies', () => { const context = ContextBuilder.fromDefaultIsolate() .withInjectedDependency('function sum(x, y) { return x + y }') diff --git a/src/core/deps/assets/nunjucks-date-filter.js b/src/core/deps/assets/nunjucks-date-filter.js new file mode 100644 index 0000000..4b324da --- /dev/null +++ b/src/core/deps/assets/nunjucks-date-filter.js @@ -0,0 +1,57 @@ +/* global nunjucks, moment */ +/** + * nunjucks-date-filter + * https://github.com/piwi/nunjucks-date-filter + * + * Copyright (c) 2015 Pierre Cassat + * Licensed under the Apache 2.0 license. + */ + +var nlib = nunjucks['lib']; +// default default format (ISO 8601) +var dateFilterDefaultFormat = null; + +// a date filter for Nunjucks +// usage: {{ my_date | date(format) }} +// see: +function dateFilter(date, format) { + var result; + var errs = []; + var args = []; + var obj; + Array.prototype.push.apply(args, arguments); + try { + obj = moment.utc(date); + } catch (err) { + errs.push(err); + } + if (obj) { + try { + if (obj[format] && nlib.isFunction(obj[format])) { + result = obj[format].apply(obj, args.slice(2)); + } else { + if (dateFilterDefaultFormat !== null) { + result = obj.format(format || dateFilterDefaultFormat); + } else { + result = obj.format(format); + } + } + } catch (err) { + errs.push(err); + } + } + + if (errs.length) { + return errs.join('\n'); + } + return result; +} + +dateFilter.setDefaultFormat = function (format) { + dateFilterDefaultFormat = format; +}; +dateFilter.install = function (env, customName) { + (env || nunjucks.configure()).addFilter(customName || 'date', dateFilter); +}; + +dateFilter; diff --git a/src/core/deps/nunjucks.ts b/src/core/deps/nunjucks.ts index 99230f0..ee2cb5a 100644 --- a/src/core/deps/nunjucks.ts +++ b/src/core/deps/nunjucks.ts @@ -1,35 +1,37 @@ import fs from 'fs'; import path from 'path'; -export const nunjucksCode = fs.readFileSync(path.join(__dirname, './assets/nunjucks.min.js'), 'utf8'); -export const nunjucksDateFilterCode = fs.readFileSync(path.join(__dirname, './assets/nunjucks-date-filter.js'), 'utf8') - // Remove 'use strict' and require statements - .replace(`'use strict';`, '') - .replace(/^.+require.+$/gm, '') - // Remove module.exports - .replace(`module.exports = dateFilter;`, '') - .replaceAll(`module.exports.`, ''); +export const nunjucksCode = fs.readFileSync( + path.join(__dirname, './assets/nunjucks.min.js'), + 'utf8', +); +export const nunjucksDateFilterCode = fs.readFileSync( + path.join(__dirname, './assets/nunjucks-date-filter.js'), + 'utf8', +); // Strip away macros and escape breakout attempts. const sanitize = (input: any) => { - if (!input) { - throw new Error('Input is required for sanitize fn'); - } - return input - .replace(/{{(.*(\.constructor|\]\().*)}}/g, '{% raw %}{{$1}}{% endraw %}') + if (!input) { + throw new Error('Input is required for sanitize fn'); + } + return input.replace( + /{{(.*(\.constructor|\]\().*)}}/g, + '{% raw %}{{$1}}{% endraw %}', + ); }; // Unescape HTML sequences const unescape = (str: any) => { - if (!str) { - throw new Error('Input is required for unescape fn'); - } - return str - .replace(/</g , '<') - .replace(/>/g , '>') - .replace(/"/g , '\"') - .replace(/'/g , '\'') - .replace(/&/g , '&') + if (!str) { + throw new Error('Input is required for unescape fn'); + } + return str + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, "'") + .replace(/&/g, '&'); }; export const nunjucksEnvironmentCode = ` diff --git a/src/core/evaluateProcess.ts b/src/core/evaluateProcess.ts index 8e1bbbf..d47bac7 100644 --- a/src/core/evaluateProcess.ts +++ b/src/core/evaluateProcess.ts @@ -31,6 +31,7 @@ export type EvaluateProcessorsOptions = { form: any; submission: any; scope?: any; + config?: any; token?: string; timeout?: number; additionalDeps?: string[]; @@ -46,6 +47,7 @@ export async function evaluateProcess({ submission, timeout = globalTimeout, scope = {}, + config = {}, token = '', additionalDeps = [], }: EvaluateProcessorsOptions): Promise { @@ -57,6 +59,7 @@ export async function evaluateProcess({ data: serializedSubmission.data, scope: scope, config: { + ...config, server: true, token, }, @@ -96,6 +99,7 @@ export async function evaluateProcessMocked( data: submission.data, scope: options.scope || {}, config: { + ...(options.config || {}), server: true, token: options.token || '', }, diff --git a/yarn.lock b/yarn.lock index e14bad7..19727c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2680,11 +2680,6 @@ gulp-cli@^2.2.0: v8flags "^3.2.0" yargs "^7.1.0" -gulp-rename@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz#9bbc3962b0c0f52fc67cd5eaff6c223ec5b9cf6c" - integrity sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ== - gulp@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz#543651070fd0f6ab0a0650c6a3e6ff5a7cb09caa"