feat(nunjucks): init @lowdefy/nunjucks package

This commit is contained in:
Sam Tolmay 2020-10-07 13:48:46 +02:00
parent 816ef63c5d
commit 93f7dd79e4
12 changed files with 325 additions and 3 deletions

62
.pnp.js generated
View File

@ -50,6 +50,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"name": "@lowdefy/layout",
"reference": "workspace:packages/layout"
},
{
"name": "@lowdefy/nunjucks",
"reference": "workspace:packages/nunjucks"
},
{
"name": "@lowdefy/renderer",
"reference": "workspace:packages/renderer"
@ -77,6 +81,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@lowdefy/helpers", ["workspace:packages/helpers"]],
["@lowdefy/layout", ["workspace:packages/layout"]],
["@lowdefy/lowdefy", ["workspace:."]],
["@lowdefy/nunjucks", ["workspace:packages/nunjucks"]],
["@lowdefy/poc-express", ["workspace:packages/express"]],
["@lowdefy/renderer", ["workspace:packages/renderer"]],
["@lowdefy/serializer", ["workspace:packages/serializer"]],
@ -3751,6 +3756,23 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"linkType": "SOFT",
}]
]],
["@lowdefy/nunjucks", [
["workspace:packages/nunjucks", {
"packageLocation": "./packages/nunjucks/",
"packageDependencies": [
["@lowdefy/nunjucks", "workspace:packages/nunjucks"],
["@babel/cli", "virtual:10c70c57b8c041994c932fbc6065790a1801b95ea6f8bb47c7334c5a9a57ca5035df7a515298306323a03d95e4c0d72d9488454f45837690b0620ca3a249c7f5#npm:7.11.6"],
["@babel/core", "npm:7.11.6"],
["@babel/preset-env", "virtual:10c70c57b8c041994c932fbc6065790a1801b95ea6f8bb47c7334c5a9a57ca5035df7a515298306323a03d95e4c0d72d9488454f45837690b0620ca3a249c7f5#npm:7.11.5"],
["@lowdefy/type", "workspace:packages/type"],
["babel-jest", "virtual:dc086c2784eb23a46dc07fa9ec3a3b376e693ea14441b30b9d9ab2ee39c177169123288242a40e296e2dd681a1cce35ee32919388c9b6f1a58c0a512bc095c93#npm:26.5.2"],
["jest", "npm:26.5.2"],
["nunjucks", "npm:3.2.2"],
["nunjucks-date-filter", "npm:0.1.1"]
],
"linkType": "SOFT",
}]
]],
["@lowdefy/poc-express", [
["workspace:packages/express", {
"packageLocation": "./packages/express/",
@ -5257,6 +5279,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"linkType": "HARD",
}]
]],
["a-sync-waterfall", [
["npm:1.0.1", {
"packageLocation": "./.yarn/cache/a-sync-waterfall-npm-1.0.1-f6b6b49568-da11585ce7.zip/node_modules/a-sync-waterfall/",
"packageDependencies": [
["a-sync-waterfall", "npm:1.0.1"]
],
"linkType": "HARD",
}]
]],
["abab", [
["npm:2.0.5", {
"packageLocation": "./.yarn/cache/abab-npm-2.0.5-ae8d5b629e-a42b91bd9d.zip/node_modules/abab/",
@ -7597,6 +7628,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["commander", "npm:4.1.1"]
],
"linkType": "HARD",
}],
["npm:5.1.0", {
"packageLocation": "./.yarn/cache/commander-npm-5.1.0-7e939e7832-d16141ea7f.zip/node_modules/commander/",
"packageDependencies": [
["commander", "npm:5.1.0"]
],
"linkType": "HARD",
}]
]],
["comment-json", [
@ -14773,6 +14811,30 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"linkType": "HARD",
}]
]],
["nunjucks", [
["npm:3.2.2", {
"packageLocation": "./.yarn/cache/nunjucks-npm-3.2.2-810aaf7ac6-ad7ac5ab62.zip/node_modules/nunjucks/",
"packageDependencies": [
["nunjucks", "npm:3.2.2"],
["a-sync-waterfall", "npm:1.0.1"],
["asap", "npm:2.0.6"],
["chokidar", "npm:3.4.2"],
["commander", "npm:5.1.0"]
],
"linkType": "HARD",
}]
]],
["nunjucks-date-filter", [
["npm:0.1.1", {
"packageLocation": "./.yarn/cache/nunjucks-date-filter-npm-0.1.1-434e2afa95-45663784cf.zip/node_modules/nunjucks-date-filter/",
"packageDependencies": [
["nunjucks-date-filter", "npm:0.1.1"],
["moment", "npm:2.29.1"],
["nunjucks", "npm:3.2.2"]
],
"linkType": "HARD",
}]
]],
["nwsapi", [
["npm:2.2.0", {
"packageLocation": "./.yarn/cache/nwsapi-npm-2.2.0-8f05590043-fb0f05113a.zip/node_modules/nwsapi/",

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -5,6 +5,9 @@ packageExtensions:
'@apollographql/apollo-tools@*':
dependencies:
graphql: '*'
'nunjucks-date-filter@*':
dependencies:
'nunjucks': '*'
'rc-animate@*':
dependencies:
'react-dom': '*'

View File

@ -0,0 +1,13 @@
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "12",
"esmodules": true
}
}
]
]
}

View File

@ -0,0 +1,19 @@
module.exports = {
// Automatically clear mock calls and instances between every test
clearMocks: true,
// The directory where Jest should output its coverage files
coverageDirectory: 'coverage',
// An array of regexp pattern strings used to skip coverage collection
coveragePathIgnorePatterns: ['/node_modules/', '/dist/'],
// A list of reporter names that Jest uses when writing coverage reports
coverageReporters: ['text'],
// The test environment that will be used for testing
testEnvironment: 'node',
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
};

View File

@ -0,0 +1,44 @@
{
"name": "@lowdefy/nunjucks",
"version": "1.0.0",
"licence": "Apache-2.0",
"description": "",
"homepage": "https://lowdefy.com",
"bugs": {
"url": "https://github.com/lowdefy/lowdefy/issues"
},
"contributors": [
{
"name": "Sam Tolmay",
"url": "https://github.com/SamTolmay"
},
{
"name": "Gerrie van Wyk",
"url": "https://github.com/Gervwyk"
}
],
"repository": {
"type": "git",
"url": "https://github.com/lowdefy/lowdefy.git"
},
"main": "dist/nunjucks.js",
"scripts": {
"build": "babel src --out-dir dist",
"test": "jest --coverage",
"prepare": "yarn build",
"prepublishOnly": "yarn build",
"npm-publish": "npm publish --access public"
},
"dependencies": {
"@lowdefy/type": "1.0.1",
"nunjucks": "3.2.2",
"nunjucks-date-filter": "0.1.1"
},
"devDependencies": {
"@babel/cli": "7.11.6",
"@babel/core": "7.11.6",
"@babel/preset-env": "7.11.5",
"babel-jest": "26.5.2",
"jest": "26.5.2"
}
}

View File

@ -0,0 +1,54 @@
import nunjucks from 'nunjucks';
import dateFilter from 'nunjucks-date-filter';
import type from '@lowdefy/type';
// dateFilter.setDefaultFormat('YYYY-MM-DD');
export const nunjucksEnv = new nunjucks.Environment();
nunjucksEnv.addFilter('date', dateFilter);
const nunjucksTemplates = {};
// slow
export const nunjucksString = (templateString, value) => {
if (type.isPrimitive(value)) {
return nunjucksEnv.renderString(templateString, { value });
}
return nunjucksEnv.renderString(templateString, value);
};
export const validNunjucksString = (templateString, returnError = false) => {
try {
nunjucksString(templateString, {});
return true;
} catch (e) {
if (returnError) {
return { name: e.name, message: e.message };
}
return false;
}
};
// fast
// test with memoization
// this method compiles a nunjucks string only if the client has not compiled the same string before.
export const nunjucksFunction = (templateString) => {
// template was already compiled
if (type.isFunction(nunjucksTemplates[templateString])) {
return nunjucksTemplates[templateString];
}
if (type.isString(templateString)) {
const template = nunjucks.compile(templateString, nunjucksEnv);
// execute once to throw catch template errors
template.render({});
nunjucksTemplates[templateString] = (value) => {
if (type.isPrimitive(value)) {
return template.render({ value });
}
return template.render(value);
};
} else {
// for non string types like booleans or objects
nunjucksTemplates[templateString] = () => templateString;
}
return nunjucksTemplates[templateString];
};

View File

@ -0,0 +1,72 @@
import { nunjucksString, nunjucksFunction, validNunjucksString } from '../src/nunjucks';
test('nunjucksString - string parsing', () => {
expect(nunjucksString('$ {{value}}', '100')).toEqual('$ 100');
expect(nunjucksString('$ {{value}}', 46.6)).toEqual('$ 46.6');
expect(nunjucksString('{{value}} is a boolean', true)).toEqual('true is a boolean');
});
test('nunjucksFunction - string parsing, string value', () => {
const temp = nunjucksFunction('$ {{value}}');
expect(temp('100')).toEqual('$ 100');
expect(temp(100)).toEqual('$ 100');
expect(temp(true)).toEqual('$ true');
});
test('nunjucksFunction - string parsing, object value', () => {
const temp = nunjucksFunction('$ {{ cost }}');
expect(temp({ cost: '100' })).toEqual('$ 100');
expect(temp({ cost: 100 })).toEqual('$ 100');
expect(temp({ cost: true })).toEqual('$ true');
});
test('nunjucksString - errors', () => {
expect(() => {
nunjucksString('{% if a %}', {});
}).toThrowErrorMatchingInlineSnapshot(`
"(unknown path)
parseIf: expected elif, else, or endif, got end of file"
`);
});
test('nunjucksFunction - errors', () => {
expect(() => {
nunjucksFunction('{% if a %}');
}).toThrowErrorMatchingInlineSnapshot(`
"(unknown path)
parseIf: expected elif, else, or endif, got end of file"
`);
});
test('validNunjucksString - {% if %} single line', () => {
expect(validNunjucksString('{% if $state.name %} true {% endif %}')).toEqual(true);
expect(validNunjucksString('{% if $state.name %}')).toEqual(false);
});
test('validNunjucksString - {% if %} return error', () => {
expect(validNunjucksString('{% if $state.name %} true {% endif %}', true)).toEqual(true);
expect(validNunjucksString('{% if $state.name %}', true)).toMatchInlineSnapshot(`
Object {
"message": "(unknown path)
parseIf: expected elif, else, or endif, got end of file",
"name": "Template render error",
}
`);
});
test('nunjucksFunction - non-string template', () => {
const bool = nunjucksFunction(true);
expect(bool('100')).toEqual(true);
const number = nunjucksFunction(100);
expect(number('100')).toEqual(100);
const obj = nunjucksFunction({ x: 1 });
expect(obj('100')).toEqual({ x: 1 });
});
test('nunjucksFunction - memoization', () => {
const func1 = nunjucksFunction('$ {{value}}');
expect(func1('100')).toEqual('$ 100');
const memo = nunjucksFunction('$ {{value}}');
expect(memo('100')).toEqual('$ 100');
expect(memo).toBe(func1);
});

View File

@ -2963,6 +2963,21 @@ __metadata:
languageName: unknown
linkType: soft
"@lowdefy/nunjucks@workspace:packages/nunjucks":
version: 0.0.0-use.local
resolution: "@lowdefy/nunjucks@workspace:packages/nunjucks"
dependencies:
"@babel/cli": 7.11.6
"@babel/core": 7.11.6
"@babel/preset-env": 7.11.5
"@lowdefy/type": 1.0.1
babel-jest: 26.5.2
jest: 26.5.2
nunjucks: 3.2.2
nunjucks-date-filter: 0.1.1
languageName: unknown
linkType: soft
"@lowdefy/poc-express@workspace:packages/express":
version: 0.0.0-use.local
resolution: "@lowdefy/poc-express@workspace:packages/express"
@ -4295,6 +4310,13 @@ __metadata:
languageName: node
linkType: hard
"a-sync-waterfall@npm:^1.0.0":
version: 1.0.1
resolution: "a-sync-waterfall@npm:1.0.1"
checksum: da11585ce7067691fa27ce2c4b731dfb632b090cfe32decb8a6f6e9b2cd6150353a5d78f1eb4555d4a9f8849eb66f443b34f3324dd0099badf208aea335be7f4
languageName: node
linkType: hard
"abab@npm:^2.0.3":
version: 2.0.5
resolution: "abab@npm:2.0.5"
@ -5034,7 +5056,7 @@ __metadata:
languageName: node
linkType: hard
"asap@npm:^2.0.0, asap@npm:~2.0.3":
"asap@npm:^2.0.0, asap@npm:^2.0.3, asap@npm:~2.0.3":
version: 2.0.6
resolution: "asap@npm:2.0.6"
checksum: 3d314f8c598b625a98347bacdba609d4c889c616ca5d8ea65acaae8050ab8b7aa6630df2cfe9856c20b260b432adf2ee7a65a1021f268ef70408c70f809e3a39
@ -5991,7 +6013,7 @@ __metadata:
languageName: node
linkType: hard
"chokidar@npm:^3.2.2":
"chokidar@npm:^3.2.2, chokidar@npm:^3.3.0":
version: 3.4.2
resolution: "chokidar@npm:3.4.2"
dependencies:
@ -6274,6 +6296,13 @@ __metadata:
languageName: node
linkType: hard
"commander@npm:^5.1.0":
version: 5.1.0
resolution: "commander@npm:5.1.0"
checksum: d16141ea7f580945156fb8a06de2834c4647c7d9d3732ebd4534ab8e0b7c64747db301e18f2b840f28ea8fef51f7a8d6178e674b45a21931f0b65ff1c7f476b3
languageName: node
linkType: hard
"comment-json@npm:^2.2.0":
version: 2.4.2
resolution: "comment-json@npm:2.4.2"
@ -12247,7 +12276,7 @@ fsevents@^1.2.7:
languageName: node
linkType: hard
"moment@npm:^2.24.0, moment@npm:^2.25.3":
"moment@npm:^2.24.0, moment@npm:^2.25.3, moment@npm:^2.9.0":
version: 2.29.1
resolution: "moment@npm:2.29.1"
checksum: 86729013febf7160de5b93da69273dd304d674b0224f9544b3abd09a87671ddd2cdd57598261ce57588910d63747ffd5590965e83c790d8bf327083c0e0a06e0
@ -12726,6 +12755,32 @@ fsevents@^1.2.7:
languageName: node
linkType: hard
"nunjucks-date-filter@npm:0.1.1":
version: 0.1.1
resolution: "nunjucks-date-filter@npm:0.1.1"
dependencies:
moment: ^2.9.0
checksum: 45663784cf45758ac05bcd0e796e332b96601e934f95782cdf0a712e1ace14712b49dcbed750a986bd5706608d08edbad3588d66a9d436a036c7e0032ebb30e2
languageName: node
linkType: hard
"nunjucks@npm:*, nunjucks@npm:3.2.2":
version: 3.2.2
resolution: "nunjucks@npm:3.2.2"
dependencies:
a-sync-waterfall: ^1.0.0
asap: ^2.0.3
chokidar: ^3.3.0
commander: ^5.1.0
dependenciesMeta:
chokidar:
optional: true
bin:
nunjucks-precompile: bin/precompile
checksum: ad7ac5ab621d30375ae8bd5e2f1fa4c87e652079179b63a8dc6d0fdb483ab283ba042f38675553a56db606a1accec19c1aade37b2e437520ab4e398b5f1dfbdd
languageName: node
linkType: hard
"nwsapi@npm:^2.2.0":
version: 2.2.0
resolution: "nwsapi@npm:2.2.0"