Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e96c1a5d86 | |||
| 171ce40e0c | |||
| c958cc8955 | |||
| b250b2d53a | |||
| ff4d827c09 | |||
| e4738491b3 | |||
| 54f7e11b28 | |||
| 8742bde701 | |||
| 2357140c68 | |||
| c5cbeac039 | |||
| 213c0bbe3c | |||
| 050cca0866 | |||
| 2d5579078b | |||
| e3639e2407 | |||
| c2a17c7b30 | |||
| 1266838829 | |||
| 64ecb9ea84 | |||
| 93444c58db | |||
| d148d7cb1f | |||
| a89081d440 | |||
| bba65605b1 | |||
| 06b7224ed9 | |||
| 2078c727c6 | |||
| fff3e40402 | |||
| 35bcd4405f | |||
| 00b4f2ff98 | |||
| e47b5ec192 | |||
| c55a7bed78 | |||
| 164c7ceea4 | |||
| 6ab48d8def | |||
| 8ac20285f6 | |||
| 888750ec27 | |||
| 133b96a2ff | |||
| f119497312 | |||
| 62b64ecc3d | |||
| a57b6824e0 | |||
| a26633f204 | |||
| f9cce4dd02 | |||
| 16572cd848 | |||
| f98c6a5425 | |||
| fde409ace6 | |||
| 9aaace76dc | |||
| 5eb59a5302 | |||
| 10b5fcf92e | |||
| dd0144c771 | |||
| 594f1e30dd | |||
| 871acccbb1 | |||
| cd38583216 | |||
| c454d946e3 | |||
| 9cfb5ddad9 | |||
| be44246221 | |||
| 002561be94 | |||
| 3fb6687013 | |||
| f691db546e | |||
| 25b2e11dd9 | |||
| e5c39375ac | |||
| aef72870b6 | |||
| 684f1032c6 | |||
| 7840ab66a5 | |||
| 4108b8330b | |||
| 445ae12fa4 | |||
| 5cedd62d7b | |||
| 40fb115e53 | |||
| b2e2cfe56d | |||
| 037bfbf4d9 | |||
| 048f2ce7d2 | |||
| b92589a3b0 | |||
| 1c62d4c5d0 | |||
| b02e9a25ee | |||
| f1c8b2e2a2 | |||
| dbc50ac705 | |||
| c6a8fc1c04 | |||
| 42841c41a4 |
@@ -12,3 +12,4 @@ npm-debug.log
|
||||
sauce_connect.log*
|
||||
.idea
|
||||
yarn-error.log
|
||||
/handlebars-release.tgz
|
||||
|
||||
+26
-8
@@ -5,18 +5,19 @@ module.exports = function(grunt) {
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
|
||||
eslint: {
|
||||
options: {
|
||||
},
|
||||
files: [
|
||||
'*.js',
|
||||
'bench/**/*.js',
|
||||
'tasks/**/*.js',
|
||||
'lib/**/!(*.min|parser).js',
|
||||
'spec/**/!(*.amd|json2|require).js'
|
||||
'spec/**/!(*.amd|json2|require).js',
|
||||
'integration-testing/multi-nodejs-test/*.js',
|
||||
'integration-testing/webpack-test/*.js',
|
||||
'integration-testing/webpack-test/src/*.js'
|
||||
]
|
||||
},
|
||||
|
||||
clean: ['tmp', 'dist', 'lib/handlebars/compiler/parser.js'],
|
||||
clean: ['tmp', 'dist', 'lib/handlebars/compiler/parser.js', 'integration-testing/**/node_modules'],
|
||||
|
||||
copy: {
|
||||
dist: {
|
||||
@@ -166,8 +167,8 @@ module.exports = function(grunt) {
|
||||
browsers: [
|
||||
{browserName: 'chrome'},
|
||||
{browserName: 'firefox', platform: 'Linux'},
|
||||
{browserName: 'safari', version: 9, platform: 'OS X 10.11'},
|
||||
{browserName: 'safari', version: 8, platform: 'OS X 10.10'},
|
||||
// {browserName: 'safari', version: 9, platform: 'OS X 10.11'},
|
||||
// {browserName: 'safari', version: 8, platform: 'OS X 10.10'},
|
||||
{browserName: 'internet explorer', version: 11, platform: 'Windows 8.1'},
|
||||
{browserName: 'internet explorer', version: 10, platform: 'Windows 8'}
|
||||
]
|
||||
@@ -186,6 +187,20 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
|
||||
bgShell: {
|
||||
checkTypes: {
|
||||
cmd: 'npm run checkTypes',
|
||||
bg: false,
|
||||
fail: true
|
||||
},
|
||||
integrationTests: {
|
||||
cmd: './integration-testing/run-integration-tests.sh',
|
||||
bg: false,
|
||||
fail: true
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
watch: {
|
||||
scripts: {
|
||||
options: {
|
||||
@@ -201,6 +216,7 @@ module.exports = function(grunt) {
|
||||
// Build a new version of the library
|
||||
this.registerTask('build', 'Builds a distributable version of the current project', [
|
||||
'eslint',
|
||||
'bgShell:checkTypes',
|
||||
'parser',
|
||||
'node',
|
||||
'globals']);
|
||||
@@ -221,6 +237,7 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-babel');
|
||||
grunt.loadNpmTasks('grunt-bg-shell');
|
||||
grunt.loadNpmTasks('grunt-eslint');
|
||||
grunt.loadNpmTasks('grunt-saucelabs');
|
||||
grunt.loadNpmTasks('grunt-webpack');
|
||||
@@ -228,10 +245,11 @@ module.exports = function(grunt) {
|
||||
grunt.task.loadTasks('tasks');
|
||||
|
||||
grunt.registerTask('bench', ['metrics']);
|
||||
grunt.registerTask('sauce', [] /* process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : [] */);
|
||||
grunt.registerTask('sauce', process.env.SAUCE_USERNAME ? ['tests', 'connect', 'saucelabs-mocha'] : []);
|
||||
|
||||
grunt.registerTask('travis', process.env.PUBLISH ? ['default', 'sauce', 'metrics', 'publish:latest'] : ['default']);
|
||||
grunt.registerTask('travis', process.env.PUBLISH ? ['default', 'bgShell:integrationTests', 'sauce', 'metrics', 'publish:latest'] : ['default']);
|
||||
|
||||
grunt.registerTask('dev', ['clean', 'connect', 'watch']);
|
||||
grunt.registerTask('default', ['clean', 'build', 'test', 'release']);
|
||||
grunt.registerTask('integration-tests', ['default', 'bgShell:integrationTests']);
|
||||
};
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
var async = require('async'),
|
||||
var async = require('neo-async'),
|
||||
fs = require('fs'),
|
||||
zlib = require('zlib');
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "handlebars",
|
||||
"version": "4.1.0",
|
||||
"version": "4.3.5",
|
||||
"main": "handlebars.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>handlebars.js</id>
|
||||
<version>4.1.0</version>
|
||||
<version>4.3.5</version>
|
||||
<authors>handlebars.js Authors</authors>
|
||||
<licenseUrl>https://github.com/wycats/handlebars.js/blob/master/LICENSE</licenseUrl>
|
||||
<projectUrl>https://github.com/wycats/handlebars.js/</projectUrl>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "handlebars",
|
||||
"version": "4.1.0",
|
||||
"version": "4.3.5",
|
||||
"license": "MIT",
|
||||
"jspm": {
|
||||
"main": "handlebars",
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
Add a new integration test by creating a new subfolder
|
||||
|
||||
Add a file "test.sh" to that runs the test. "test.sh" should exit with a non-zero exit code
|
||||
and display an error message, if something goes wrong.
|
||||
|
||||
* An integration test should reflect real-world setups that use handlebars.
|
||||
* It should compile a minimal template and compare the output to an expected output.
|
||||
* It should use "../.." as dependency for Handlebars so that the currently built library is used.
|
||||
|
||||
Currently, integration tests are only running on Linux, especially in travis-ci.
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
"extends": "eslint:recommended",
|
||||
"globals": {
|
||||
"self": false
|
||||
},
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"rules": {
|
||||
'no-console': 'off'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
target
|
||||
package-lock.json
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "multi-nodejs-test",
|
||||
"version": "1.0.0",
|
||||
"description": "Simple integration test with all relevant NodeJS-versions.",
|
||||
"keywords": [],
|
||||
"author": "Nils Knappmeier",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"handlebars": "file:../.."
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node run-handlebars.js",
|
||||
"test-precompile": "handlebars precompile-test-template.txt.hbs"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Author: {{author}}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// This test should run successfully with node 0.10++ as long as Handlebars has been compiled before
|
||||
var assert = require('assert');
|
||||
var Handlebars = require('handlebars');
|
||||
|
||||
console.log('Testing built Handlebars with Node version ' + process.version);
|
||||
|
||||
var template = Handlebars.compile('Author: {{author}}');
|
||||
var output = template({author: 'Yehuda'});
|
||||
assert.strictEqual(output, 'Author: Yehuda');
|
||||
|
||||
console.log('Success');
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$( dirname "$( readlink -f "$0" )" )" || exit 1
|
||||
# shellcheck disable=SC1090
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||
|
||||
# This script tests with precompiler and the built distribution with multiple NodeJS version.
|
||||
# The rest of the travis-build will only work with newer NodeJS versions, because the build
|
||||
# tools don't support older versions.
|
||||
# However, the built distribution should work with older NodeJS versions as well.
|
||||
# This test is simple by design. It merely ensures, that calling Handlebars does not fail with old versions.
|
||||
# It does (almost) not test for correctness, because that is already done in the mocha-tests.
|
||||
# And it does not use any NodeJS based testing framwork to make this part independent of the Node version.
|
||||
|
||||
# A list of NodeJS versions is expected as cli-args
|
||||
echo "Handlebars should be able to run in various versions of NodeJS"
|
||||
for i in 0.10 0.12 4 5 6 7 8 9 10 11 ; do
|
||||
rm target node_modules package-lock.json -rf
|
||||
mkdir target
|
||||
nvm install "$i"
|
||||
nvm exec "$i" npm install
|
||||
nvm exec "$i" npm run test || exit 1
|
||||
nvm exec "$i" npm run test-precompile || exit 1
|
||||
|
||||
echo Success
|
||||
done
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$( dirname "$( readlink -f "$0" )" )" || exit 1
|
||||
|
||||
for i in */test.sh ; do
|
||||
(
|
||||
echo "----------------------------------------"
|
||||
echo "-- Running integration test: $i"
|
||||
echo "----------------------------------------"
|
||||
cd "$( dirname "$i" )" || exit 1
|
||||
./test.sh || exit 1
|
||||
)
|
||||
done
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"plugins": [
|
||||
"@roundingwellos/babel-plugin-handlebars-inline-precompile"
|
||||
// "istanbul"
|
||||
],
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env"
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
dist
|
||||
package-lock.json
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "webpack-babel-test",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.5.5",
|
||||
"@babel/preset-env": "^7.5.5",
|
||||
"@roundingwellos/babel-plugin-handlebars-inline-precompile": "^3.0.1",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-plugin-istanbul": "^5.2.0",
|
||||
"handlebars": "file:../..",
|
||||
"handlebars-loader": "^1.7.1",
|
||||
"nyc": "^14.1.1",
|
||||
"webpack": "^4.39.3",
|
||||
"webpack-cli": "^3.3.7"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import * as Handlebars from 'handlebars/runtime'
|
||||
import hbs from 'handlebars-inline-precompile';
|
||||
import {assertEquals} from "../../webpack-test/src/lib/assert";
|
||||
|
||||
Handlebars.registerHelper('loud', function(text) {
|
||||
return text.toUpperCase();
|
||||
});
|
||||
|
||||
const template = hbs`{{loud name}}`;
|
||||
const output = template({name: 'yehuda'})
|
||||
|
||||
assertEquals(output, 'YEHUDA')
|
||||
@@ -0,0 +1,5 @@
|
||||
export function assertEquals(actual, expected) {
|
||||
if (actual !== expected) {
|
||||
throw new Error(`Expected "${actual}" to equal "${expected}"`);
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Cleanup: package-lock and "npm ci" is not working with local dependencies
|
||||
rm dist package-lock.json -rf
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
for i in dist/*-test.js ; do
|
||||
echo "----------------------"
|
||||
echo "-- Running $i"
|
||||
echo "----------------------"
|
||||
node "$i"
|
||||
echo "Success"
|
||||
done
|
||||
@@ -0,0 +1,32 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const testFiles = fs.readdirSync('src');
|
||||
const entryPoints = {};
|
||||
testFiles
|
||||
.filter(file => file.match(/-test.js$/))
|
||||
.forEach(file => {
|
||||
entryPoints[file] = `./src/${file}`;
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
entry: entryPoints,
|
||||
output: {
|
||||
filename: '[name]',
|
||||
path: __dirname + '/dist'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: { cacheDirectory: false },
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
optimization: {
|
||||
minimize: false
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
dist
|
||||
package-lock.json
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "webpack-test",
|
||||
"description": "Various tests with Handlebars and Webpack",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"test": "node dist/main.js"
|
||||
},
|
||||
"private": true,
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"handlebars": "file:../..",
|
||||
"handlebars-loader": "^1.7.1",
|
||||
"webpack": "^4.39.3",
|
||||
"webpack-cli": "^3.3.7"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import Handlebars from 'handlebars/dist/handlebars';
|
||||
|
||||
import {assertEquals} from './lib/assert';
|
||||
|
||||
const template = Handlebars.compile('Author: {{author}}');
|
||||
assertEquals(template({author: 'Yehuda'}), 'Author: Yehuda');
|
||||
@@ -0,0 +1,6 @@
|
||||
import Handlebars from 'handlebars';
|
||||
import {assertEquals} from './lib/assert';
|
||||
|
||||
|
||||
const template = Handlebars.compile('Author: {{author}}');
|
||||
assertEquals(template({author: 'Yehuda'}), 'Author: Yehuda');
|
||||
@@ -0,0 +1,8 @@
|
||||
import {assertEquals} from './lib/assert';
|
||||
|
||||
import testTemplate from './test-template.handlebars';
|
||||
assertEquals(testTemplate({author: 'Yehuda'}).trim(), 'Author: Yehuda');
|
||||
|
||||
|
||||
const testTemplateRequire = require('./test-template.handlebars');
|
||||
assertEquals(testTemplateRequire({author: 'Yehuda'}).trim(), 'Author: Yehuda');
|
||||
@@ -0,0 +1,10 @@
|
||||
import * as HandlebarsViaImport from 'handlebars';
|
||||
const HandlebarsViaRequire = require('handlebars');
|
||||
import {assertEquals} from './lib/assert';
|
||||
|
||||
HandlebarsViaImport.registerHelper('loud', function(text) {
|
||||
return text.toUpperCase();
|
||||
});
|
||||
|
||||
const template = HandlebarsViaRequire.compile('Author: {{loud author}}');
|
||||
assertEquals(template({author: 'Yehuda'}), 'Author: YEHUDA');
|
||||
@@ -0,0 +1,6 @@
|
||||
import * as Handlebars from 'handlebars/dist/handlebars';
|
||||
|
||||
import {assertEquals} from './lib/assert';
|
||||
|
||||
const template = Handlebars.compile('Author: {{author}}');
|
||||
assertEquals(template({author: 'Yehuda'}), 'Author: Yehuda');
|
||||
@@ -0,0 +1,5 @@
|
||||
import * as Handlebars from 'handlebars';
|
||||
import {assertEquals} from './lib/assert';
|
||||
|
||||
const template = Handlebars.compile('Author: {{author}}');
|
||||
assertEquals(template({author: 'Yehuda'}), 'Author: Yehuda');
|
||||
@@ -0,0 +1,5 @@
|
||||
export function assertEquals(actual, expected) {
|
||||
if (actual !== expected) {
|
||||
throw new Error(`Expected "${actual}" to equal "${expected}"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Author: {{author}}
|
||||
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Cleanup: package-lock and "npm ci" is not working with local dependencies
|
||||
rm dist package-lock.json -rf
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
for i in dist/*-test.js ; do
|
||||
echo "----------------------"
|
||||
echo "-- Running $i"
|
||||
echo "----------------------"
|
||||
node "$i"
|
||||
echo "Success"
|
||||
done
|
||||
@@ -0,0 +1,22 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const testFiles = fs.readdirSync('src');
|
||||
const entryPoints = {};
|
||||
testFiles
|
||||
.filter(file => file.match(/-test.js$/))
|
||||
.forEach(file => {
|
||||
entryPoints[file] = `./src/${file}`;
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
entry: entryPoints,
|
||||
output: {
|
||||
filename: '[name]',
|
||||
path: __dirname + '/dist'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{test: /\.handlebars$/, loader: 'handlebars-loader'}
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -4,8 +4,9 @@ import {registerDefaultHelpers} from './helpers';
|
||||
import {registerDefaultDecorators} from './decorators';
|
||||
import logger from './logger';
|
||||
|
||||
export const VERSION = '4.1.0';
|
||||
export const COMPILER_REVISION = 7;
|
||||
export const VERSION = '4.3.5';
|
||||
export const COMPILER_REVISION = 8;
|
||||
export const LAST_COMPATIBLE_COMPILER_REVISION = 7;
|
||||
|
||||
export const REVISION_CHANGES = {
|
||||
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
|
||||
@@ -14,7 +15,8 @@ export const REVISION_CHANGES = {
|
||||
4: '== 1.x.x',
|
||||
5: '== 2.0.0-alpha.x',
|
||||
6: '>= 2.0.0-beta.1',
|
||||
7: '>= 4.0.0'
|
||||
7: '>= 4.0.0 <4.3.0',
|
||||
8: '>= 4.3.0'
|
||||
};
|
||||
|
||||
const objectType = '[object Object]';
|
||||
|
||||
@@ -24,7 +24,7 @@ export function SourceLocation(source, locInfo) {
|
||||
|
||||
export function id(token) {
|
||||
if (/^\[.*\]$/.test(token)) {
|
||||
return token.substr(1, token.length - 2);
|
||||
return token.substring(1, token.length - 1);
|
||||
} else {
|
||||
return token;
|
||||
}
|
||||
|
||||
@@ -13,13 +13,19 @@ JavaScriptCompiler.prototype = {
|
||||
// PUBLIC API: You can override these methods in a subclass to provide
|
||||
// alternative compiled forms for name lookup and buffering semantics
|
||||
nameLookup: function(parent, name/* , type*/) {
|
||||
const isEnumerable = [ this.aliasable('container.propertyIsEnumerable'), '.call(', parent, ',"constructor")'];
|
||||
|
||||
if (name === 'constructor') {
|
||||
return ['(', parent, '.propertyIsEnumerable(\'constructor\') ? ', parent, '.constructor : undefined', ')'];
|
||||
return ['(', isEnumerable, '?', _actualLookup(), ' : undefined)'];
|
||||
}
|
||||
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
||||
return [parent, '.', name];
|
||||
} else {
|
||||
return [parent, '[', JSON.stringify(name), ']'];
|
||||
return _actualLookup();
|
||||
|
||||
function _actualLookup() {
|
||||
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
||||
return [parent, '.', name];
|
||||
} else {
|
||||
return [parent, '[', JSON.stringify(name), ']'];
|
||||
}
|
||||
}
|
||||
},
|
||||
depthedLookup: function(name) {
|
||||
@@ -214,7 +220,6 @@ JavaScriptCompiler.prototype = {
|
||||
let aliasCount = 0;
|
||||
for (let alias in this.aliases) { // eslint-disable-line guard-for-in
|
||||
let node = this.aliases[alias];
|
||||
|
||||
if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) {
|
||||
varDeclarations += ', alias' + (++aliasCount) + '=' + alias;
|
||||
node.children[0] = 'alias' + aliasCount;
|
||||
@@ -311,7 +316,7 @@ JavaScriptCompiler.prototype = {
|
||||
// replace it on the stack with the result of properly
|
||||
// invoking blockHelperMissing.
|
||||
blockValue: function(name) {
|
||||
let blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
|
||||
let blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
|
||||
params = [this.contextName(0)];
|
||||
this.setupHelperArgs(name, 0, params);
|
||||
|
||||
@@ -329,7 +334,7 @@ JavaScriptCompiler.prototype = {
|
||||
// On stack, after, if lastHelper: value
|
||||
ambiguousBlockValue: function() {
|
||||
// We're being a bit cheeky and reusing the options value from the prior exec
|
||||
let blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
|
||||
let blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
|
||||
params = [this.contextName(0)];
|
||||
this.setupHelperArgs('', 0, params, true);
|
||||
|
||||
@@ -339,9 +344,9 @@ JavaScriptCompiler.prototype = {
|
||||
params.splice(1, 0, current);
|
||||
|
||||
this.pushSource([
|
||||
'if (!', this.lastHelper, ') { ',
|
||||
current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params),
|
||||
'}']);
|
||||
'if (!', this.lastHelper, ') { ',
|
||||
current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params),
|
||||
'}']);
|
||||
},
|
||||
|
||||
// [appendContent]
|
||||
@@ -622,18 +627,32 @@ JavaScriptCompiler.prototype = {
|
||||
// If the helper is not found, `helperMissing` is called.
|
||||
invokeHelper: function(paramSize, name, isSimple) {
|
||||
let nonHelper = this.popStack(),
|
||||
helper = this.setupHelper(paramSize, name),
|
||||
simple = isSimple ? [helper.name, ' || '] : '';
|
||||
helper = this.setupHelper(paramSize, name);
|
||||
|
||||
let lookup = ['('].concat(simple, nonHelper);
|
||||
if (!this.options.strict) {
|
||||
lookup.push(' || ', this.aliasable('helpers.helperMissing'));
|
||||
let possibleFunctionCalls = [];
|
||||
|
||||
if (isSimple) { // direct call to helper
|
||||
possibleFunctionCalls.push(helper.name);
|
||||
}
|
||||
// call a function from the input object
|
||||
possibleFunctionCalls.push(nonHelper);
|
||||
if (!this.options.strict) {
|
||||
possibleFunctionCalls.push(this.aliasable('container.hooks.helperMissing'));
|
||||
}
|
||||
lookup.push(')');
|
||||
|
||||
this.push(this.source.functionCall(lookup, 'call', helper.callParams));
|
||||
let functionLookupCode = ['(', this.itemsSeparatedBy(possibleFunctionCalls, '||'), ')'];
|
||||
let functionCall = this.source.functionCall(functionLookupCode, 'call', helper.callParams);
|
||||
this.push(functionCall);
|
||||
},
|
||||
|
||||
itemsSeparatedBy: function(items, separator) {
|
||||
let result = [];
|
||||
result.push(items[0]);
|
||||
for (let i = 1; i < items.length; i++) {
|
||||
result.push(separator, items[i]);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// [invokeKnownHelper]
|
||||
//
|
||||
// On stack, before: hash, inverse, program, params..., ...
|
||||
@@ -672,16 +691,16 @@ JavaScriptCompiler.prototype = {
|
||||
if (!this.options.strict) {
|
||||
lookup[0] = '(helper = ';
|
||||
lookup.push(
|
||||
' != null ? helper : ',
|
||||
this.aliasable('helpers.helperMissing')
|
||||
' != null ? helper : ',
|
||||
this.aliasable('container.hooks.helperMissing')
|
||||
);
|
||||
}
|
||||
|
||||
this.push([
|
||||
'(', lookup,
|
||||
(helper.paramsInit ? ['),(', helper.paramsInit] : []), '),',
|
||||
'(typeof helper === ', this.aliasable('"function"'), ' ? ',
|
||||
this.source.functionCall('helper', 'call', helper.callParams), ' : helper))'
|
||||
'(', lookup,
|
||||
(helper.paramsInit ? ['),(', helper.paramsInit] : []), '),',
|
||||
'(typeof helper === ', this.aliasable('"function"'), ' ? ',
|
||||
this.source.functionCall('helper', 'call', helper.callParams), ' : helper))'
|
||||
]);
|
||||
},
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ function omitLeft(body, i, multiple) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We omit the last node if it's whitespace only and not preceeded by a non-content node.
|
||||
// We omit the last node if it's whitespace only and not preceded by a non-content node.
|
||||
let original = current.value;
|
||||
current.value = current.value.replace(multiple ? (/\s+$/) : (/[ \t]+$/), '');
|
||||
current.leftStripped = current.value !== original;
|
||||
|
||||
@@ -15,3 +15,12 @@ export function registerDefaultHelpers(instance) {
|
||||
registerLookup(instance);
|
||||
registerWith(instance);
|
||||
}
|
||||
|
||||
export function moveHelperToHooks(instance, helperName, keepHelper) {
|
||||
if (instance.helpers[helperName]) {
|
||||
instance.hooks[helperName] = instance.helpers[helperName];
|
||||
if (!keepHelper) {
|
||||
delete instance.helpers[helperName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
export default function(instance) {
|
||||
instance.registerHelper('lookup', function(obj, field) {
|
||||
return obj && obj[field];
|
||||
if (!obj) {
|
||||
return obj;
|
||||
}
|
||||
if (field === 'constructor' && !obj.propertyIsEnumerable(field)) {
|
||||
return undefined;
|
||||
}
|
||||
return obj[field];
|
||||
});
|
||||
}
|
||||
|
||||
+40
-28
@@ -1,26 +1,30 @@
|
||||
import * as Utils from './utils';
|
||||
import Exception from './exception';
|
||||
import { COMPILER_REVISION, REVISION_CHANGES, createFrame } from './base';
|
||||
import {COMPILER_REVISION, createFrame, LAST_COMPATIBLE_COMPILER_REVISION, REVISION_CHANGES} from './base';
|
||||
import {moveHelperToHooks} from './helpers';
|
||||
|
||||
export function checkRevision(compilerInfo) {
|
||||
const compilerRevision = compilerInfo && compilerInfo[0] || 1,
|
||||
currentRevision = COMPILER_REVISION;
|
||||
|
||||
if (compilerRevision !== currentRevision) {
|
||||
if (compilerRevision < currentRevision) {
|
||||
const runtimeVersions = REVISION_CHANGES[currentRevision],
|
||||
compilerVersions = REVISION_CHANGES[compilerRevision];
|
||||
throw new Exception('Template was precompiled with an older version of Handlebars than the current runtime. ' +
|
||||
'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
|
||||
} else {
|
||||
// Use the embedded version info since the runtime doesn't know about this revision yet
|
||||
throw new Exception('Template was precompiled with a newer version of Handlebars than the current runtime. ' +
|
||||
'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
|
||||
}
|
||||
if (compilerRevision >= LAST_COMPATIBLE_COMPILER_REVISION && compilerRevision <= COMPILER_REVISION) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (compilerRevision < LAST_COMPATIBLE_COMPILER_REVISION) {
|
||||
const runtimeVersions = REVISION_CHANGES[currentRevision],
|
||||
compilerVersions = REVISION_CHANGES[compilerRevision];
|
||||
throw new Exception('Template was precompiled with an older version of Handlebars than the current runtime. ' +
|
||||
'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
|
||||
} else {
|
||||
// Use the embedded version info since the runtime doesn't know about this revision yet
|
||||
throw new Exception('Template was precompiled with a newer version of Handlebars than the current runtime. ' +
|
||||
'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
|
||||
}
|
||||
}
|
||||
|
||||
export function template(templateSpec, env) {
|
||||
|
||||
/* istanbul ignore next */
|
||||
if (!env) {
|
||||
throw new Exception('No environment passed to template');
|
||||
@@ -32,9 +36,12 @@ export function template(templateSpec, env) {
|
||||
templateSpec.main.decorator = templateSpec.main_d;
|
||||
|
||||
// Note: Using env.VM references rather than local var references throughout this section to allow
|
||||
// for external users to override these as psuedo-supported APIs.
|
||||
// for external users to override these as pseudo-supported APIs.
|
||||
env.VM.checkRevision(templateSpec.compiler);
|
||||
|
||||
// backwards compatibility for precompiled templates with compiler-version 7 (<4.3.0)
|
||||
const templateWasPrecompiledWithCompilerV7 = templateSpec.compiler && templateSpec.compiler[0] === 7;
|
||||
|
||||
function invokePartialWrapper(partial, context, options) {
|
||||
if (options.hash) {
|
||||
context = Utils.extend({}, context, options.hash);
|
||||
@@ -42,13 +49,15 @@ export function template(templateSpec, env) {
|
||||
options.ids[0] = true;
|
||||
}
|
||||
}
|
||||
|
||||
partial = env.VM.resolvePartial.call(this, partial, context, options);
|
||||
let result = env.VM.invokePartial.call(this, partial, context, options);
|
||||
|
||||
let optionsWithHooks = Utils.extend({}, options, {hooks: this.hooks});
|
||||
|
||||
let result = env.VM.invokePartial.call(this, partial, context, optionsWithHooks);
|
||||
|
||||
if (result == null && env.compile) {
|
||||
options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
|
||||
result = options.partials[options.name](context, options);
|
||||
result = options.partials[options.name](context, optionsWithHooks);
|
||||
}
|
||||
if (result != null) {
|
||||
if (options.indent) {
|
||||
@@ -115,15 +124,6 @@ export function template(templateSpec, env) {
|
||||
}
|
||||
return value;
|
||||
},
|
||||
merge: function(param, common) {
|
||||
let obj = param || common;
|
||||
|
||||
if (param && common && (param !== common)) {
|
||||
obj = Utils.extend({}, common, param);
|
||||
}
|
||||
|
||||
return obj;
|
||||
},
|
||||
// An empty object to use as replacement for null-contexts
|
||||
nullContext: Object.seal({}),
|
||||
|
||||
@@ -158,19 +158,28 @@ export function template(templateSpec, env) {
|
||||
|
||||
ret._setup = function(options) {
|
||||
if (!options.partial) {
|
||||
container.helpers = container.merge(options.helpers, env.helpers);
|
||||
container.helpers = Utils.extend({}, env.helpers, options.helpers);
|
||||
|
||||
if (templateSpec.usePartial) {
|
||||
container.partials = container.merge(options.partials, env.partials);
|
||||
container.partials = Utils.extend({}, env.partials, options.partials);
|
||||
}
|
||||
if (templateSpec.usePartial || templateSpec.useDecorators) {
|
||||
container.decorators = container.merge(options.decorators, env.decorators);
|
||||
container.decorators = Utils.extend({}, env.decorators, options.decorators);
|
||||
}
|
||||
|
||||
container.hooks = {};
|
||||
|
||||
let keepHelperInHelpers = options.allowCallsToHelperMissing || templateWasPrecompiledWithCompilerV7;
|
||||
moveHelperToHooks(container, 'helperMissing', keepHelperInHelpers);
|
||||
moveHelperToHooks(container, 'blockHelperMissing', keepHelperInHelpers);
|
||||
|
||||
} else {
|
||||
container.helpers = options.helpers;
|
||||
container.partials = options.partials;
|
||||
container.decorators = options.decorators;
|
||||
container.hooks = options.hooks;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ret._child = function(i, data, blockParams, depths) {
|
||||
@@ -209,6 +218,9 @@ export function wrapProgram(container, i, fn, data, declaredBlockParams, blockPa
|
||||
return prog;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is currently part of the official API, therefore implementation details should not be changed.
|
||||
*/
|
||||
export function resolvePartial(partial, context, options) {
|
||||
if (!partial) {
|
||||
if (options.name === '@partial-block') {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
const escape = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable no-console */
|
||||
import Async from 'async';
|
||||
import Async from 'neo-async';
|
||||
import fs from 'fs';
|
||||
import * as Handlebars from './handlebars';
|
||||
import {basename} from 'path';
|
||||
|
||||
Generated
+8705
File diff suppressed because it is too large
Load Diff
+14
-5
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "handlebars",
|
||||
"barename": "handlebars",
|
||||
"version": "4.1.0",
|
||||
"version": "4.3.5",
|
||||
"description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
|
||||
"homepage": "http://www.handlebarsjs.com/",
|
||||
"keywords": [
|
||||
@@ -21,7 +21,7 @@
|
||||
"node": ">=0.4.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^2.5.0",
|
||||
"neo-async": "^2.6.0",
|
||||
"optimist": "^0.6.1",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
@@ -33,10 +33,12 @@
|
||||
"babel-loader": "^5.0.0",
|
||||
"babel-runtime": "^5.1.10",
|
||||
"benchmark": "~1.0",
|
||||
"dtslint": "^0.5.5",
|
||||
"dustjs-linkedin": "^2.0.2",
|
||||
"eco": "~1.1.0-rc-3",
|
||||
"grunt": "^1.0.3",
|
||||
"grunt-babel": "^5.0.0",
|
||||
"grunt-bg-shell": "^2.3.3",
|
||||
"grunt-cli": "^1",
|
||||
"grunt-contrib-clean": "^1",
|
||||
"grunt-contrib-concat": "^1",
|
||||
@@ -46,7 +48,7 @@
|
||||
"grunt-contrib-uglify": "^1",
|
||||
"grunt-contrib-watch": "^1.1.0",
|
||||
"grunt-eslint": "^20.1.0",
|
||||
"grunt-saucelabs": "9.x",
|
||||
"grunt-saucelabs": "github:nknapp/grunt-saucelabs",
|
||||
"grunt-webpack": "^1.0.8",
|
||||
"istanbul": "^0.3.0",
|
||||
"jison": "~0.3.0",
|
||||
@@ -54,16 +56,22 @@
|
||||
"mock-stdin": "^0.3.0",
|
||||
"mustache": "^2.1.3",
|
||||
"semver": "^5.0.1",
|
||||
"typescript": "^3.4.3",
|
||||
"underscore": "^1.5.1",
|
||||
"webpack": "^1.12.6",
|
||||
"webpack-dev-server": "^1.12.1"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/handlebars.d.ts",
|
||||
"types": "types/index.d.ts",
|
||||
"browser": {
|
||||
".": "./dist/cjs/handlebars.js",
|
||||
"./runtime": "./dist/cjs/handlebars.runtime.js"
|
||||
},
|
||||
"bin": {
|
||||
"handlebars": "bin/handlebars"
|
||||
},
|
||||
"scripts": {
|
||||
"checkTypes": "dtslint types",
|
||||
"test": "grunt"
|
||||
},
|
||||
"jspm": {
|
||||
@@ -83,6 +91,7 @@
|
||||
"lib",
|
||||
"print-script",
|
||||
"release-notes.md",
|
||||
"runtime.js"
|
||||
"runtime.js",
|
||||
"types/*.d.ts"
|
||||
]
|
||||
}
|
||||
|
||||
+152
-61
@@ -2,7 +2,156 @@
|
||||
|
||||
## Development
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.0...master)
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.5...master)
|
||||
|
||||
## v4.3.5 - October 2nd, 2019
|
||||
- [#1562](https://github.com/wycats/handlebars.js/issues/1562) - Error message for syntax error missing location in 4.2.1+
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.4...v4.3.5)
|
||||
|
||||
## v4.3.4 - September 28th, 2019
|
||||
- fix: harden "propertyIsEnumerable"-check - ff4d827
|
||||
|
||||
Compatibility notes:
|
||||
- No incompatibilities are known.
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.3...v4.3.4)
|
||||
|
||||
## v4.3.3 - September 27th, 2019
|
||||
- fix test case for browsers that do not support __defineGetter__ - 8742bde
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.2...v4.3.3)
|
||||
|
||||
## v4.3.2 - September 26th, 2019
|
||||
- Use Object.prototype.propertyIsEnumerable to check for constructors - 213c0bb, #1563
|
||||
|
||||
Compatibility notes:
|
||||
- There are no breaking changes
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.1...v4.3.2)
|
||||
|
||||
## v4.3.1 - September 25th, 2019
|
||||
Fixes:
|
||||
|
||||
- do not break on precompiled templates from Handlebars >=4.0.0 <4.3.0 - 1266838, #1561
|
||||
- Ensure allowCallsToHelperMissing runtime option is optional in typings - 93444c5, 64ecb9e, #1560
|
||||
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.0...v4.3.1)
|
||||
|
||||
## v4.3.0 - September 24th, 2019
|
||||
Fixes:
|
||||
|
||||
- Security: Disallow calling "helperMissing" and "blockHelperMissing" directly - 2078c72
|
||||
- Disallow calling "helperMissing" and "blockHelperMissing" directly - 2078c72
|
||||
|
||||
Features:
|
||||
|
||||
- Add new runtime option `allowCallsToHelperMissing` to allow calling `blockHelperMissing` and `helperMissing`.
|
||||
|
||||
Breaking changes:
|
||||
|
||||
Compatibility notes:
|
||||
- Compiler revision increased - 06b7224
|
||||
- This means that template compiled with versions prior to 4.3.0 will not work with runtimes >= 4.3.0
|
||||
The increase was done because the "helperMissing" and "blockHelperMissing" are now moved from the helpers
|
||||
to the internal "container.hooks" object, so old templates will not be able to call them anymore. We suggest
|
||||
that you always recompile your templates with the latest compiler in your build pipelines.
|
||||
|
||||
- Disallow calling "helperMissing" and "blockHelperMissing" directly - 2078c72
|
||||
- Calling "helperMissing" and "blockHelperMissing" directly from a template (like in `{{blockHelperMissing}}` was
|
||||
never intended and was part of the exploits that have been revealed early in 2019
|
||||
(see https://github.com/wycats/handlebars.js/issues/1495). *It is also part of a new exploit that
|
||||
is not captured by the earlier fix.* In order to harden Handlebars against such exploits, calling thos helpers
|
||||
is now not possible anymore. *Overriding* those helpers is still possible.
|
||||
- If you really need this behavior, you can set the runtime option `allowCallsToHelperMissing` to `true` and the
|
||||
calls will again be possible
|
||||
|
||||
Both bullet points imly that Handlebars is not 100% percent compatible to 4.2.0, despite the minor version bump.
|
||||
|
||||
We consider it more important to resolve a major security issue than to maintain 100% compatibility.
|
||||
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.2.1...v4.3.0)
|
||||
|
||||
## v4.2.1 - September 20th, 2019
|
||||
Bugfixes:
|
||||
|
||||
- The "browser" property in the package.json has been updated to use the common-js builds instead of the minified UMD - c55a7be, #1553
|
||||
|
||||
Compatibility notes:
|
||||
- No compatibility issues should arise
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.2.0...v4.2.1)
|
||||
|
||||
## v4.2.0 - September 3rd, 2019
|
||||
Chore/Test:
|
||||
- Use custom `grunt-saucelab` with current sauce-connect proxy - f119497
|
||||
- Add framework for various integration tests - f9cce4d
|
||||
- Add integration test for webpack - a57b682
|
||||
|
||||
|
||||
Bugfixes:
|
||||
- [#1544](https://github.com/wycats/handlebars.js/issues/1544) - Typescript types: `knownHelpers` doesnt allow for custom helpers ([@NickCis](https://api.github.com/users/NickCis))
|
||||
- [#1534](https://github.com/wycats/handlebars.js/pull/1534) - Add typings for "Handlebars.VM.resolvePartial ([@AndrewLeedham](https://api.github.com/users/AndrewLeedham))
|
||||
|
||||
Features:
|
||||
- [#1540](https://github.com/wycats/handlebars.js/pull/1540) - added "browser"-property to package.json, resolves #1102 ([@ouijan](https://api.github.com/users/ouijan))
|
||||
|
||||
Compatibility notes:
|
||||
- The new "browser"-property should not break anything, but you can never be sure. The integration test for webpack
|
||||
shows that it works, but if it doesn't please open an issue.
|
||||
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.2-0...v4.2.0)
|
||||
|
||||
## v4.1.2-0 - August 25th, 2019
|
||||
[#1540](https://github.com/wycats/handlebars.js/pull/1540) - added browser to package.json, resolves #1102 ([@ouijan](https://api.github.com/users/ouijan))
|
||||
|
||||
Compatibility notes:
|
||||
- We are not sure if imports via webpack are still working, which is why this release is a pre-release
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.2...v4.1.2-0)
|
||||
|
||||
## v4.1.2 - April 13th, 2019
|
||||
Chore/Test:
|
||||
- [#1515](https://github.com/wycats/handlebars.js/pull/1515) - Port over linting and test for typings ([@zimmi88](https://api.github.com/users/zimmi88))
|
||||
- chore: add missing typescript dependency, add package-lock.json - 594f1e3
|
||||
- test: remove safari from saucelabs - 871accc
|
||||
|
||||
Bugfixes:
|
||||
- fix: prevent RCE through the "lookup"-helper - cd38583
|
||||
|
||||
Compatibility notes:
|
||||
|
||||
Access to the constructor of a class thought `{{lookup obj "constructor" }}` is now prohibited. This closes
|
||||
a leak that only half closed in versions 4.0.13 and 4.1.0, but it is a slight incompatibility.
|
||||
|
||||
This kind of access is not the intended use of Handlebars and leads to the vulnerability described
|
||||
in #1495. We will **not** increase the major version, because such use is not intended or documented,
|
||||
and because of the potential impact of the issue (we fear that most people won't use a new major version
|
||||
and the issue may not be resolved on many systems).
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.1...v4.1.2)
|
||||
|
||||
## v4.1.1 - March 16th, 2019
|
||||
Bugfixes:
|
||||
- fix: add "runtime.d.ts" to allow "require('handlebars/runtime')" in TypeScript - 5cedd62
|
||||
|
||||
Refactorings:
|
||||
- replace "async" with "neo-async" - 048f2ce
|
||||
- use "substring"-function instead of "substr" - 445ae12
|
||||
|
||||
Compatibility notes:
|
||||
- This is a bugfix release. There are no breaking change and no new features.
|
||||
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.1.0...v4.1.1)
|
||||
|
||||
## v4.1.0 - February 7th, 2019
|
||||
New Features
|
||||
@@ -68,64 +217,6 @@ Removed obsolete code:
|
||||
Compatibility notes:
|
||||
- No compatibility issues are to be expected
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.12...v4.0.12)
|
||||
|
||||
## v4.0.12 - September 4th, 2018
|
||||
New features:
|
||||
|
||||
- none
|
||||
|
||||
Various dependency updates
|
||||
|
||||
- [#1464](https://github.com/wycats/handlebars.js/pull/1464) - Bump versions of grunt-plugins to 1.x
|
||||
- [#1398](https://github.com/wycats/handlebars.js/pull/1398) - Chore: updated various dev dependencies
|
||||
- upgrade uglify-js - d3d3942
|
||||
- Update grunt-eslint to 20.1.0 - 7729aa9
|
||||
- Update dependencies "async" to 2.5.0 and "source-map" to 0.6.1 (73d5637)
|
||||
|
||||
Bugfixes:
|
||||
|
||||
- [components/handlebars.js#24](https://github.com/components/handlebars.js#24) Add package.json to components shim
|
||||
- Updated `source-map`-package should work better with `rollup`[#1463](https://github.com/wycats/handlebars.js/issues/1463)
|
||||
|
||||
Removed obsolete code:
|
||||
|
||||
- unnecessary check - 0ddff8b
|
||||
- Use `files` field - 69c6ca5
|
||||
- Update jsfiddle to 4.0.11 - 8947dd0
|
||||
|
||||
Compatibility notes:
|
||||
- No compatibility issues are to be expected
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.12...v4.0.12)
|
||||
|
||||
## v4.0.12 - September 4th, 2018
|
||||
New features:
|
||||
|
||||
- none
|
||||
|
||||
Various dependency updates
|
||||
|
||||
- [#1464](https://github.com/wycats/handlebars.js/pull/1464) - Bump versions of grunt-plugins to 1.x
|
||||
- [#1398](https://github.com/wycats/handlebars.js/pull/1398) - Chore: updated various dev dependencies
|
||||
- upgrade uglify-js - d3d3942
|
||||
- Update grunt-eslint to 20.1.0 - 7729aa9
|
||||
- Update dependencies "async" to 2.5.0 and "source-map" to 0.6.1 (73d5637)
|
||||
|
||||
Bugfixes:
|
||||
|
||||
- [components/handlebars.js#24](https://github.com/components/handlebars.js#24) Add package.json to components shim
|
||||
- Updated `source-map`-package should work better with `rollup`[#1463](https://github.com/wycats/handlebars.js/issues/1463)
|
||||
|
||||
Removed obsolete code:
|
||||
|
||||
- unnecessary check - 0ddff8b
|
||||
- Use `files` field - 69c6ca5
|
||||
- Update jsfiddle to 4.0.11 - 8947dd0
|
||||
|
||||
Compatibility notes:
|
||||
- No compatibility issues are to be expected
|
||||
|
||||
[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.11...v4.0.12)
|
||||
|
||||
## v4.0.11 - October 17th, 2017
|
||||
@@ -399,7 +490,7 @@ Compatibility notes:
|
||||
- Lines containing only block statements and whitespace are now removed. This matches the Mustache spec but may cause issues with code that expects whitespace to exist but would not otherwise.
|
||||
- Partials that are standalone will now indent their rendered content
|
||||
- `AST.ProgramNode`'s signature has changed.
|
||||
- Numerious methods/features removed from psuedo-API classes
|
||||
- Numerious methods/features removed from pseudo-API classes
|
||||
- `JavaScriptCompiler.register`
|
||||
- `JavaScriptCompiler.replaceStack` no longer supports non-inline replace
|
||||
- `Compiler.disassemble`
|
||||
@@ -590,7 +681,7 @@ Compatibility notes:
|
||||
## v1.0.11 / 1.0.0-rc4 - May 13 2013
|
||||
|
||||
- [#458](https://github.com/wycats/handlebars.js/issues/458) - Fix `./foo` syntax ([@jpfiset](https://github.com/jpfiset))
|
||||
- [#460](https://github.com/wycats/handlebars.js/issues/460) - Allow `:` in unescaped identifers ([@jpfiset](https://github.com/jpfiset))
|
||||
- [#460](https://github.com/wycats/handlebars.js/issues/460) - Allow `:` in unescaped identifiers ([@jpfiset](https://github.com/jpfiset))
|
||||
- [#471](https://github.com/wycats/handlebars.js/issues/471) - Create release notes (These!)
|
||||
- [#456](https://github.com/wycats/handlebars.js/issues/456) - Allow escaping of `\\`
|
||||
- [#211](https://github.com/wycats/handlebars.js/issues/211) - Fix exception in `escapeExpression`
|
||||
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
import Handlebars = require('handlebars')
|
||||
|
||||
declare module "handlebars/runtime" {
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
define(['handlebars.runtime'], function(Handlebars) {
|
||||
Handlebars = Handlebars["default"]; var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
|
||||
return templates['empty'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||
return templates['empty'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||
return "";
|
||||
},"useData":true});
|
||||
});
|
||||
|
||||
@@ -291,4 +291,36 @@ describe('Regressions', function() {
|
||||
};
|
||||
shouldCompileToWithPartials(string, [{}, {}, partials], true, 'template block partial block template');
|
||||
});
|
||||
|
||||
describe('GH-1561: 4.3.x should still work with precompiled templates from 4.0.0 <= x < 4.3.0', function() {
|
||||
|
||||
it('should compile and execute templates', function() {
|
||||
var newHandlebarsInstance = Handlebars.create();
|
||||
|
||||
registerTemplate(newHandlebarsInstance);
|
||||
newHandlebarsInstance.registerHelper('loud', function(value) {
|
||||
return value.toUpperCase();
|
||||
});
|
||||
var result = newHandlebarsInstance.templates['test.hbs']({name: 'yehuda'});
|
||||
equals(result.trim(), 'YEHUDA');
|
||||
});
|
||||
|
||||
it('should call "helperMissing" if a helper is missing', function() {
|
||||
var newHandlebarsInstance = Handlebars.create();
|
||||
|
||||
shouldThrow(function() {
|
||||
registerTemplate(newHandlebarsInstance);
|
||||
newHandlebarsInstance.templates['test.hbs']({});
|
||||
}, Handlebars.Exception, 'Missing helper: "loud"');
|
||||
});
|
||||
|
||||
// This is a only slightly modified precompiled templated from compiled with 4.2.1
|
||||
function registerTemplate(Handlebars) {
|
||||
var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
|
||||
templates['test.hbs'] = template({'compiler': [7, '>= 4.0.0'], 'main': function(container, depth0, helpers, partials, data) {
|
||||
return container.escapeExpression((helpers.loud || (depth0 && depth0.loud) || helpers.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}), (depth0 != null ? depth0.name : depth0), {'name': 'loud', 'hash': {}, 'data': data}))
|
||||
+ '\n\n';
|
||||
}, 'useData': true});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ describe('runtime', function() {
|
||||
shouldThrow(function() {
|
||||
Handlebars.template({
|
||||
main: {},
|
||||
compiler: [Handlebars.COMPILER_REVISION - 1]
|
||||
compiler: [Handlebars.LAST_COMPATIBLE_COMPILER_REVISION - 1]
|
||||
});
|
||||
}, Error, /Template was precompiled with an older version of Handlebars than the current runtime/);
|
||||
shouldThrow(function() {
|
||||
|
||||
+84
-3
@@ -2,22 +2,103 @@ describe('security issues', function() {
|
||||
describe('GH-1495: Prevent Remote Code Execution via constructor', function() {
|
||||
it('should not allow constructors to be accessed', function() {
|
||||
shouldCompileTo('{{constructor.name}}', {}, '');
|
||||
shouldCompileTo('{{lookup (lookup this "constructor") "name"}}', {}, '');
|
||||
});
|
||||
|
||||
it('should allow the "constructor" property to be accessed if it is enumerable', function() {
|
||||
shouldCompileTo('{{constructor.name}}', {'constructor': {
|
||||
'name': 'here we go'
|
||||
}}, 'here we go');
|
||||
shouldCompileTo('{{lookup (lookup this "constructor") "name"}}', {'constructor': {
|
||||
'name': 'here we go'
|
||||
}}, 'here we go');
|
||||
});
|
||||
|
||||
it('should allow prototype properties that are not constructors', function() {
|
||||
class TestClass {
|
||||
get abc() {
|
||||
function TestClass() {
|
||||
}
|
||||
|
||||
Object.defineProperty(TestClass.prototype, 'abc', {
|
||||
get: function() {
|
||||
return 'xyz';
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
shouldCompileTo('{{#with this as |obj|}}{{obj.abc}}{{/with}}',
|
||||
new TestClass(), 'xyz');
|
||||
shouldCompileTo('{{#with this as |obj|}}{{lookup obj "abc"}}{{/with}}',
|
||||
new TestClass(), 'xyz');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('GH-1558: Prevent explicit call of helperMissing-helpers', function() {
|
||||
if (!Handlebars.compile) {
|
||||
return;
|
||||
}
|
||||
|
||||
describe('without the option "allowExplicitCallOfHelperMissing"', function() {
|
||||
it('should throw an exception when calling "{{helperMissing}}" ', function() {
|
||||
shouldThrow(function() {
|
||||
var template = Handlebars.compile('{{helperMissing}}');
|
||||
template({});
|
||||
}, Error);
|
||||
});
|
||||
it('should throw an exception when calling "{{#helperMissing}}{{/helperMissing}}" ', function() {
|
||||
shouldThrow(function() {
|
||||
var template = Handlebars.compile('{{#helperMissing}}{{/helperMissing}}');
|
||||
template({});
|
||||
}, Error);
|
||||
});
|
||||
it('should throw an exception when calling "{{blockHelperMissing "abc" .}}" ', function() {
|
||||
var functionCalls = [];
|
||||
shouldThrow(function() {
|
||||
var template = Handlebars.compile('{{blockHelperMissing "abc" .}}');
|
||||
template({ fn: function() { functionCalls.push('called'); }});
|
||||
}, Error);
|
||||
equals(functionCalls.length, 0);
|
||||
});
|
||||
it('should throw an exception when calling "{{#blockHelperMissing .}}{{/blockHelperMissing}}"', function() {
|
||||
shouldThrow(function() {
|
||||
var template = Handlebars.compile('{{#blockHelperMissing .}}{{/blockHelperMissing}}');
|
||||
template({ fn: function() { return 'functionInData';}});
|
||||
}, Error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with the option "allowCallsToHelperMissing" set to true', function() {
|
||||
it('should not throw an exception when calling "{{helperMissing}}" ', function() {
|
||||
var template = Handlebars.compile('{{helperMissing}}');
|
||||
template({}, {allowCallsToHelperMissing: true});
|
||||
});
|
||||
it('should not throw an exception when calling "{{#helperMissing}}{{/helperMissing}}" ', function() {
|
||||
var template = Handlebars.compile('{{#helperMissing}}{{/helperMissing}}');
|
||||
template({}, {allowCallsToHelperMissing: true});
|
||||
});
|
||||
it('should not throw an exception when calling "{{blockHelperMissing "abc" .}}" ', function() {
|
||||
var functionCalls = [];
|
||||
var template = Handlebars.compile('{{blockHelperMissing "abc" .}}');
|
||||
template({ fn: function() { functionCalls.push('called'); }}, {allowCallsToHelperMissing: true});
|
||||
equals(functionCalls.length, 1);
|
||||
});
|
||||
it('should not throw an exception when calling "{{#blockHelperMissing .}}{{/blockHelperMissing}}"', function() {
|
||||
var template = Handlebars.compile('{{#blockHelperMissing true}}sdads{{/blockHelperMissing}}');
|
||||
template({}, {allowCallsToHelperMissing: true});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GH-1563', function() {
|
||||
it('should not allow to access constructor after overriding via __defineGetter__', function() {
|
||||
if (({}).__defineGetter__ == null || ({}).__lookupGetter__ == null) {
|
||||
return; // Browser does not support this exploit anyway
|
||||
}
|
||||
shouldCompileTo('{{__defineGetter__ "undefined" valueOf }}' +
|
||||
'{{#with __lookupGetter__ }}' +
|
||||
'{{__defineGetter__ "propertyIsEnumerable" (this.bind (this.bind 1)) }}' +
|
||||
'{{constructor.name}}' +
|
||||
'{{/with}}', {}, '');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
%{
|
||||
|
||||
function strip(start, end) {
|
||||
return yytext = yytext.substr(start, yyleng-end);
|
||||
return yytext = yytext.substring(start, yyleng - end + start);
|
||||
}
|
||||
|
||||
%}
|
||||
@@ -59,7 +59,7 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD}
|
||||
if (this.conditionStack[this.conditionStack.length-1] === 'raw') {
|
||||
return 'CONTENT';
|
||||
} else {
|
||||
yytext = yytext.substr(5, yyleng-9);
|
||||
strip(5, 9);
|
||||
return 'END_RAW_BLOCK';
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
var _ = require('underscore'),
|
||||
async = require('async'),
|
||||
async = require('neo-async'),
|
||||
metrics = require('../bench');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
var _ = require('underscore'),
|
||||
async = require('async'),
|
||||
async = require('neo-async'),
|
||||
AWS = require('aws-sdk'),
|
||||
git = require('./util/git'),
|
||||
semver = require('semver');
|
||||
@@ -66,7 +66,7 @@ module.exports = function(grunt) {
|
||||
var s3 = new AWS.S3(),
|
||||
bucket = process.env.S3_BUCKET_NAME;
|
||||
|
||||
async.forEach(_.keys(files), function(file, callback) {
|
||||
async.each(_.keys(files), function(file, callback) {
|
||||
var params = {Bucket: bucket, Key: file, Body: grunt.file.read(files[file])};
|
||||
s3.putObject(params, function(err) {
|
||||
if (err) {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
var async = require('async'),
|
||||
var async = require('neo-async'),
|
||||
git = require('./util/git'),
|
||||
semver = require('semver');
|
||||
|
||||
|
||||
+40
-11
@@ -7,9 +7,12 @@
|
||||
* - Raanan Weber <https://github.com/RaananW>
|
||||
* - Sergei Dorogin <https://github.com/evil-shrike>
|
||||
* - webbiesdk <https://github.com/webbiesdk>
|
||||
* - Andrew Leedham <https://github.com/AndrewLeedham>
|
||||
* - Nils Knappmeier <https://github.com/nknapp>
|
||||
* For full history prior to their migration to handlebars.js, please see:
|
||||
* https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/handlebars
|
||||
* https://github.com/DefinitelyTyped/DefinitelyTyped/commits/1ce60bdc07f10e0b076778c6c953271c072bc894/types/handlebars/index.d.ts
|
||||
*/
|
||||
// TypeScript Version: 2.3
|
||||
|
||||
declare namespace Handlebars {
|
||||
export interface TemplateDelegate<T = any> {
|
||||
@@ -26,6 +29,7 @@ declare namespace Handlebars {
|
||||
decorators?: { [name: string]: Function };
|
||||
data?: any;
|
||||
blockParams?: any[];
|
||||
allowCallsToHelperMissing?: boolean;
|
||||
}
|
||||
|
||||
export interface HelperOptions {
|
||||
@@ -146,6 +150,22 @@ declare namespace Handlebars {
|
||||
NullLiteral(): void;
|
||||
Hash(hash: hbs.AST.Hash): void;
|
||||
}
|
||||
|
||||
|
||||
export interface ResolvePartialOptions {
|
||||
name: string;
|
||||
helpers?: { [name: string]: Function };
|
||||
partials?: { [name: string]: HandlebarsTemplateDelegate };
|
||||
decorators?: { [name: string]: Function };
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export namespace VM {
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export function resolvePartial<T = any>(partial: HandlebarsTemplateDelegate<T> | undefined, context: any, options: ResolvePartialOptions): HandlebarsTemplateDelegate<T>;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,16 +192,7 @@ type RuntimeOptions = Handlebars.RuntimeOptions;
|
||||
interface CompileOptions {
|
||||
data?: boolean;
|
||||
compat?: boolean;
|
||||
knownHelpers?: {
|
||||
helperMissing?: boolean;
|
||||
blockHelperMissing?: boolean;
|
||||
each?: boolean;
|
||||
if?: boolean;
|
||||
unless?: boolean;
|
||||
with?: boolean;
|
||||
log?: boolean;
|
||||
lookup?: boolean;
|
||||
};
|
||||
knownHelpers?: KnownHelpers;
|
||||
knownHelpersOnly?: boolean;
|
||||
noEscape?: boolean;
|
||||
strict?: boolean;
|
||||
@@ -191,6 +202,22 @@ interface CompileOptions {
|
||||
explicitPartialContext?: boolean;
|
||||
}
|
||||
|
||||
type KnownHelpers = {
|
||||
[name in BuiltinHelperName | CustomHelperName]: boolean;
|
||||
};
|
||||
|
||||
type BuiltinHelperName =
|
||||
"helperMissing"|
|
||||
"blockHelperMissing"|
|
||||
"each"|
|
||||
"if"|
|
||||
"unless"|
|
||||
"with"|
|
||||
"log"|
|
||||
"lookup";
|
||||
|
||||
type CustomHelperName = string;
|
||||
|
||||
interface PrecompileOptions extends CompileOptions {
|
||||
srcName?: string;
|
||||
destName?: string;
|
||||
@@ -215,6 +242,8 @@ interface Logger {
|
||||
log(level: number, obj: string): void;
|
||||
}
|
||||
|
||||
type CompilerInfo = [number/* revision */, string /* versions */];
|
||||
|
||||
declare namespace hbs {
|
||||
namespace AST {
|
||||
interface Node {
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/* These test cases were imported from https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
* and includes previous contributions from the DefinitelyTyped community.
|
||||
* For full history prior to their migration to handlebars.js, please see:
|
||||
* https://github.com/DefinitelyTyped/DefinitelyTyped/commits/1ce60bdc07f10e0b076778c6c953271c072bc894/types/handlebars/handlebars-tests.ts
|
||||
*/
|
||||
|
||||
import * as Handlebars from 'handlebars';
|
||||
|
||||
const context = {
|
||||
author: { firstName: 'Alan', lastName: 'Johnson' },
|
||||
body: 'I Love Handlebars',
|
||||
comments: [{
|
||||
author: { firstName: 'Yehuda', lastName: 'Katz' },
|
||||
body: 'Me too!'
|
||||
}]
|
||||
};
|
||||
Handlebars.registerHelper('fullName', (person: typeof context.author) => {
|
||||
return person.firstName + ' ' + person.lastName;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('agree_button', function(this: any) {
|
||||
return new Handlebars.SafeString(
|
||||
'<button>I agree. I ' + this.emotion + ' ' + this.name + '</button>'
|
||||
);
|
||||
});
|
||||
|
||||
const source1 = '<p>Hello, my name is {{name}}. I am from {{hometown}}. I have ' +
|
||||
'{{kids.length}} kids:</p>' +
|
||||
'<ul>{{#kids}}<li>{{name}} is {{age}}</li>{{/kids}}</ul>';
|
||||
const template1 = Handlebars.compile(source1);
|
||||
template1({ name: "Alan", hometown: "Somewhere, TX", kids: [{name: "Jimmy", age: 12}, {name: "Sally", age: 4}]});
|
||||
|
||||
Handlebars.registerHelper('link_to', (context: typeof post) => {
|
||||
return '<a href="' + context.url + '">' + context.body + '</a>';
|
||||
});
|
||||
const post = { url: "/hello-world", body: "Hello World!" };
|
||||
const context2 = { posts: [post] };
|
||||
const source2 = '<ul>{{#posts}}<li>{{{link_to this}}}</li>{{/posts}}</ul>';
|
||||
const template2: HandlebarsTemplateDelegate<{ posts: { url: string, body: string }[] }> = Handlebars.compile(source2);
|
||||
template2(context2);
|
||||
|
||||
Handlebars.registerHelper('link_to', (title: string, context: typeof post) => {
|
||||
return '<a href="/posts' + context.url + '">' + title + '!</a>';
|
||||
});
|
||||
const context3 = { posts: [{url: '/hello-world', body: 'Hello World!'}] };
|
||||
const source3 = '<ul>{{#posts}}<li>{{{link_to "Post" this}}}</li>{{/posts}}</ul>';
|
||||
const template3 = Handlebars.compile<typeof context3>(source3);
|
||||
template3(context3);
|
||||
|
||||
const source4 = '<ul>{{#people}}<li>{{#link}}{{name}}{{/link}}</li>{{/people}}</ul>';
|
||||
Handlebars.registerHelper('link', function(this: any, context: any) {
|
||||
return '<a href="/people/' + this.id + '">' + context.fn(this) + '</a>';
|
||||
});
|
||||
const template4 = Handlebars.compile<{ people: { name: string, id: number }[] }>(source4);
|
||||
const data2 = { 'people': [
|
||||
{ 'name': 'Alan', 'id': 1 },
|
||||
{ 'name': 'Yehuda', 'id': 2 }
|
||||
]};
|
||||
template4(data2);
|
||||
|
||||
const source5 = '<ul>{{#people}}<li>{{> link}}</li>{{/people}}</ul>';
|
||||
Handlebars.registerPartial('link', '<a href="/people/{{id}}">{{name}}</a>');
|
||||
const template5 = Handlebars.compile(source5);
|
||||
const data3 = { 'people': [
|
||||
{ 'name': 'Alan', 'id': 1 },
|
||||
{ 'name': 'Yehuda', 'id': 2 }
|
||||
]};
|
||||
template5(data3);
|
||||
|
||||
const source6 = '{{#list nav}}<a href="{{url}}">{{title}}</a>{{/list}}';
|
||||
const template6 = Handlebars.compile(source6);
|
||||
Handlebars.registerHelper('list', (context, options: Handlebars.HelperOptions) => {
|
||||
let ret = "<ul>";
|
||||
for(let i=0, j=context.length; i<j; i++) {
|
||||
ret = ret + "<li>" + options.fn(context[i]) + "</li>";
|
||||
}
|
||||
return ret + "</ul>";
|
||||
});
|
||||
template6([{url:"", title:""}]);
|
||||
|
||||
|
||||
const escapedExpression = Handlebars.Utils.escapeExpression('<script>alert(\'xss\');</script>');
|
||||
|
||||
Handlebars.helpers !== undefined;
|
||||
|
||||
const parsedTmpl = Handlebars.parse('<p>Hello, my name is {{name}}.</p>', {
|
||||
srcName: "/foo/bar/baz.hbs",
|
||||
ignoreStandalone: true
|
||||
});
|
||||
|
||||
const parsedTmplWithoutOptions = Handlebars.parse('<p>Hello, my name is {{name}}.</p>');
|
||||
|
||||
// Custom partial resolution.
|
||||
const originalResolvePartial = Handlebars.VM.resolvePartial;
|
||||
Handlebars.VM.resolvePartial = <T>(partial: HandlebarsTemplateDelegate<T> | undefined, context: any, options: Handlebars.ResolvePartialOptions): HandlebarsTemplateDelegate<T> => {
|
||||
const name = options.name.replace(/my/,'your');
|
||||
// transform name.
|
||||
options.name = name;
|
||||
return originalResolvePartial(partial, context, options);
|
||||
};
|
||||
|
||||
|
||||
// #1544, allow custom helpers in knownHelpers
|
||||
Handlebars.compile('test', {
|
||||
knownHelpers: {
|
||||
each: true,
|
||||
customHelper: true
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.compile('test')({},{allowCallsToHelperMissing: true});
|
||||
|
||||
Handlebars.compile('test')({},{});
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"strictFunctionTypes": true,
|
||||
"noEmit": true,
|
||||
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"handlebars": ["."]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"extends": "dtslint/dtslint.json",
|
||||
"rules": {
|
||||
"adjacent-overload-signatures": false,
|
||||
"array-type": false,
|
||||
"arrow-return-shorthand": false,
|
||||
"ban-types": false,
|
||||
"callable-types": false,
|
||||
"comment-format": false,
|
||||
"dt-header": false,
|
||||
"eofline": false,
|
||||
"export-just-namespace": false,
|
||||
"import-spacing": false,
|
||||
"interface-name": false,
|
||||
"interface-over-type-literal": false,
|
||||
"jsdoc-format": false,
|
||||
"max-line-length": false,
|
||||
"member-access": false,
|
||||
"new-parens": false,
|
||||
"no-any-union": false,
|
||||
"no-boolean-literal-compare": false,
|
||||
"no-conditional-assignment": false,
|
||||
"no-consecutive-blank-lines": false,
|
||||
"no-construct": false,
|
||||
"no-declare-current-package": false,
|
||||
"no-duplicate-imports": false,
|
||||
"no-duplicate-variable": false,
|
||||
"no-empty-interface": false,
|
||||
"no-for-in-array": false,
|
||||
"no-inferrable-types": false,
|
||||
"no-internal-module": false,
|
||||
"no-irregular-whitespace": false,
|
||||
"no-mergeable-namespace": false,
|
||||
"no-misused-new": false,
|
||||
"no-namespace": false,
|
||||
"no-object-literal-type-assertion": false,
|
||||
"no-padding": false,
|
||||
"no-redundant-jsdoc": false,
|
||||
"no-redundant-jsdoc-2": false,
|
||||
"no-redundant-undefined": false,
|
||||
"no-reference-import": false,
|
||||
"no-relative-import-in-test": false,
|
||||
"no-self-import": false,
|
||||
"no-single-declare-module": false,
|
||||
"no-string-throw": false,
|
||||
"no-unnecessary-callback-wrapper": false,
|
||||
"no-unnecessary-class": false,
|
||||
"no-unnecessary-generics": false,
|
||||
"no-unnecessary-qualifier": false,
|
||||
"no-unnecessary-type-assertion": false,
|
||||
"no-useless-files": false,
|
||||
"no-var-keyword": false,
|
||||
"no-var-requires": false,
|
||||
"no-void-expression": false,
|
||||
"no-trailing-whitespace": false,
|
||||
"object-literal-key-quotes": false,
|
||||
"object-literal-shorthand": false,
|
||||
"one-line": false,
|
||||
"one-variable-per-declaration": false,
|
||||
"only-arrow-functions": false,
|
||||
"prefer-conditional-expression": false,
|
||||
"prefer-const": false,
|
||||
"prefer-declare-function": false,
|
||||
"prefer-for-of": false,
|
||||
"prefer-method-signature": false,
|
||||
"prefer-template": false,
|
||||
"radix": false,
|
||||
"semicolon": false,
|
||||
"space-before-function-paren": false,
|
||||
"space-within-parens": false,
|
||||
"strict-export-declare-modifiers": false,
|
||||
"trim-file": false,
|
||||
"triple-equals": false,
|
||||
"typedef-whitespace": false,
|
||||
"unified-signatures": false,
|
||||
"void-return": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user