Compare commits

..

2 Commits

Author SHA1 Message Date
Nils Knappmeier 0d5c691f36 v4.2.2 2019-10-02 22:12:55 +02:00
Nils Knappmeier ea1ae7c19f Update release notes 2019-10-02 22:12:17 +02:00
39 changed files with 190 additions and 7029 deletions
+19 -7
View File
@@ -1,11 +1,25 @@
module.exports = {
"extends": ["eslint:recommended","plugin:compat/recommended"],
"extends": "eslint:recommended",
"globals": {
"self": false
},
"env": {
"node": true,
"es6": true
"node": true
},
"ecmaFeatures": {
// Enabling features that can be implemented without polyfills. Want to avoid polyfills at this time.
"arrowFunctions": true,
"blockBindings": true,
"defaultParams": true,
"destructuring": true,
"modules": true,
"objectLiteralComputedProperties": true,
"objectLiteralDuplicateProperties": true,
"objectLiteralShorthandMethods": true,
"objectLiteralShorthandProperties": true,
"restParams": true,
"spread": true,
"templateStrings": true
},
"rules": {
// overrides eslint:recommended defaults
@@ -110,8 +124,6 @@ module.exports = {
"no-var": "warn"
},
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 6,
"ecmaFeatures": {}
"sourceType": "module"
}
}
}
+1 -2
View File
@@ -90,7 +90,6 @@ Handlebars utilizes the [release yeoman generator][generator-release] to perform
A full release may be completed with the following:
```
npm ci
yo release
npm publish
yo release:publish components handlebars.js dist/components/
@@ -105,7 +104,7 @@ in those places still point to the latest version
* [The npm-package](https://www.npmjs.com/package/handlebars) (check latest-tag)
* [The bower package](https://github.com/components/handlebars.js) (check the package.json)
* [The AWS S3 Bucket](https://s3.amazonaws.com/builds.handlebarsjs.com) (check latest-tag)
* [The AWS S3 Bucket](http://builds.handlebarsjs.com.s3.amazonaws.com/) (check latest-tag)
* [RubyGems](https://rubygems.org/gems/handlebars-source)
When everything is OK, the handlebars site needs to be updated to point to the new version numbers. The jsfiddle link should be updated to point to the most recent distribution for all instances in our documentation.
+1 -1
View File
@@ -239,7 +239,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-bg-shell');
grunt.loadNpmTasks('grunt-eslint');
grunt.loadNpmTasks('@knappi/grunt-saucelabs');
grunt.loadNpmTasks('grunt-saucelabs');
grunt.loadNpmTasks('grunt-webpack');
grunt.task.loadTasks('tasks');
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "handlebars",
"version": "4.5.2",
"version": "4.2.2",
"main": "handlebars.js",
"license": "MIT",
"dependencies": {}
+1 -1
View File
@@ -2,7 +2,7 @@
<package>
<metadata>
<id>handlebars.js</id>
<version>4.5.2</version>
<version>4.2.2</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 -1
View File
@@ -1,6 +1,6 @@
{
"name": "handlebars",
"version": "4.5.2",
"version": "4.2.2",
"license": "MIT",
"jspm": {
"main": "handlebars",
-28
View File
@@ -16,34 +16,6 @@ var ast = Handlebars.parse(myTemplate);
Handlebars.precompile(ast);
```
### Parsing
There are two primary APIs that are used to parse an existing template into the AST:
#### parseWithoutProcessing
`Handlebars.parseWithoutProcessing` is the primary mechanism to turn a raw template string into the Handlebars AST described in this document. No processing is done on the resulting AST which makes this ideal for codemod (for source to source transformation) tooling.
Example:
```js
let ast = Handlebars.parseWithoutProcessing(myTemplate);
```
#### parse
`Handlebars.parse` will parse the template with `parseWithoutProcessing` (see above) then it will update the AST to strip extraneous whitespace. The whitespace stripping functionality handles two distinct situations:
* Removes whitespace around dynamic statements that are on a line by themselves (aka "stand alone")
* Applies "whitespace control" characters (i.e. `~`) by truncating the `ContentStatement` `value` property appropriately (e.g. `\n\n{{~foo}}` would have a `ContentStatement` with a `value` of `''`)
`Handlebars.parse` is used internally by `Handlebars.precompile` and `Handlebars.compile`.
Example:
```js
let ast = Handlebars.parse(myTemplate);
```
### Basic
+1 -2
View File
@@ -2,7 +2,7 @@ import runtime from './handlebars.runtime';
// Compiler imports
import AST from './handlebars/compiler/ast';
import { parser as Parser, parse, parseWithoutProcessing } from './handlebars/compiler/base';
import { parser as Parser, parse } from './handlebars/compiler/base';
import { Compiler, compile, precompile } from './handlebars/compiler/compiler';
import JavaScriptCompiler from './handlebars/compiler/javascript-compiler';
import Visitor from './handlebars/compiler/visitor';
@@ -25,7 +25,6 @@ function create() {
hb.JavaScriptCompiler = JavaScriptCompiler;
hb.Parser = Parser;
hb.parse = parse;
hb.parseWithoutProcessing = parseWithoutProcessing;
return hb;
}
+3 -5
View File
@@ -4,9 +4,8 @@ import {registerDefaultHelpers} from './helpers';
import {registerDefaultDecorators} from './decorators';
import logger from './logger';
export const VERSION = '4.5.2';
export const COMPILER_REVISION = 8;
export const LAST_COMPATIBLE_COMPILER_REVISION = 7;
export const VERSION = '4.2.2';
export const COMPILER_REVISION = 7;
export const REVISION_CHANGES = {
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
@@ -15,8 +14,7 @@ export const REVISION_CHANGES = {
4: '== 1.x.x',
5: '== 2.0.0-alpha.x',
6: '>= 2.0.0-beta.1',
7: '>= 4.0.0 <4.3.0',
8: '>= 4.3.0'
7: '>= 4.0.0'
};
const objectType = '[object Object]';
+2 -10
View File
@@ -8,7 +8,7 @@ export { parser };
let yy = {};
extend(yy, Helpers);
export function parseWithoutProcessing(input, options) {
export function parse(input, options) {
// Just return if an already-compiled AST was passed in.
if (input.type === 'Program') { return input; }
@@ -19,14 +19,6 @@ export function parseWithoutProcessing(input, options) {
return new yy.SourceLocation(options && options.srcName, locInfo);
};
let ast = parser.parse(input);
return ast;
}
export function parse(input, options) {
let ast = parseWithoutProcessing(input, options);
let strip = new WhitespaceControl(options);
return strip.accept(ast);
return strip.accept(parser.parse(input));
}
+25 -45
View File
@@ -13,19 +13,13 @@ 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 ['(', isEnumerable, '?', _actualLookup(), ' : undefined)'];
return ['(', parent, '.propertyIsEnumerable(\'constructor\') ? ', parent, '.constructor : undefined', ')'];
}
return _actualLookup();
function _actualLookup() {
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
return [parent, '.', name];
} else {
return [parent, '[', JSON.stringify(name), ']'];
}
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
return [parent, '.', name];
} else {
return [parent, '[', JSON.stringify(name), ']'];
}
},
depthedLookup: function(name) {
@@ -220,6 +214,7 @@ 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;
@@ -316,7 +311,7 @@ JavaScriptCompiler.prototype = {
// replace it on the stack with the result of properly
// invoking blockHelperMissing.
blockValue: function(name) {
let blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'),
let blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
params = [this.contextName(0)];
this.setupHelperArgs(name, 0, params);
@@ -334,7 +329,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('container.hooks.blockHelperMissing'),
let blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
params = [this.contextName(0)];
this.setupHelperArgs('', 0, params, true);
@@ -344,9 +339,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]
@@ -543,7 +538,7 @@ JavaScriptCompiler.prototype = {
if (this.hash) {
this.hashes.push(this.hash);
}
this.hash = {values: {}, types: [], contexts: [], ids: []};
this.hash = {values: [], types: [], contexts: [], ids: []};
},
popHash: function() {
let hash = this.hash;
@@ -627,32 +622,18 @@ 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);
helper = this.setupHelper(paramSize, name),
simple = isSimple ? [helper.name, ' || '] : '';
let possibleFunctionCalls = [];
if (isSimple) { // direct call to helper
possibleFunctionCalls.push(helper.name);
}
// call a function from the input object
possibleFunctionCalls.push(nonHelper);
let lookup = ['('].concat(simple, nonHelper);
if (!this.options.strict) {
possibleFunctionCalls.push(this.aliasable('container.hooks.helperMissing'));
lookup.push(' || ', this.aliasable('helpers.helperMissing'));
}
lookup.push(')');
let functionLookupCode = ['(', this.itemsSeparatedBy(possibleFunctionCalls, '||'), ')'];
let functionCall = this.source.functionCall(functionLookupCode, 'call', helper.callParams);
this.push(functionCall);
this.push(this.source.functionCall(lookup, 'call', helper.callParams));
},
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..., ...
@@ -691,16 +672,16 @@ JavaScriptCompiler.prototype = {
if (!this.options.strict) {
lookup[0] = '(helper = ';
lookup.push(
' != null ? helper : ',
this.aliasable('container.hooks.helperMissing')
' != null ? helper : ',
this.aliasable('helpers.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))'
]);
},
@@ -1091,7 +1072,6 @@ JavaScriptCompiler.prototype = {
setupHelperArgs: function(helper, paramSize, params, useRegister) {
let options = this.setupParams(helper, paramSize, params);
options.loc = JSON.stringify(this.source.currentLocation);
options = this.objectLiteral(options);
if (useRegister) {
this.useRegister('options');
@@ -1151,7 +1131,7 @@ function strictLookup(requireTerminal, compiler, parts, type) {
}
if (requireTerminal) {
return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ', ', JSON.stringify(compiler.source.currentLocation), ' )'];
return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')'];
} else {
return stack;
}
+2 -13
View File
@@ -1,18 +1,13 @@
const errorProps = ['description', 'fileName', 'lineNumber', 'endLineNumber', 'message', 'name', 'number', 'stack'];
const errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
function Exception(message, node) {
let loc = node && node.loc,
line,
endLineNumber,
column,
endColumn;
column;
if (loc) {
line = loc.start.line;
endLineNumber = loc.end.line;
column = loc.start.column;
endColumn = loc.end.column;
message += ' - ' + line + ':' + column;
}
@@ -32,7 +27,6 @@ function Exception(message, node) {
try {
if (loc) {
this.lineNumber = line;
this.endLineNumber = endLineNumber;
// Work around issue under safari where we can't directly set the column value
/* istanbul ignore next */
@@ -41,13 +35,8 @@ function Exception(message, node) {
value: column,
enumerable: true
});
Object.defineProperty(this, 'endColumn', {
value: endColumn,
enumerable: true
});
} else {
this.column = column;
this.endColumn = endColumn;
}
}
} catch (nop) {
-9
View File
@@ -15,12 +15,3 @@ 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];
}
}
}
-10
View File
@@ -49,16 +49,6 @@ export default function(instance) {
execIteration(i, i, i === context.length - 1);
}
}
} else if (global.Symbol && context[global.Symbol.iterator]) {
const newContext = [];
const iterator = context[global.Symbol.iterator]();
for (let it = iterator.next(); !it.done; it = iterator.next()) {
newContext.push(it.value);
}
context = newContext;
for (let j = context.length; i < j; i++) {
execIteration(i, i, i === context.length - 1);
}
} else {
let priorKey;
+1 -4
View File
@@ -1,9 +1,7 @@
import { isEmpty, isFunction } from '../utils';
import Exception from '../exception';
import {isEmpty, isFunction} from '../utils';
export default function(instance) {
instance.registerHelper('if', function(conditional, options) {
if (arguments.length != 2) { throw new Exception('#if requires exactly one argument');}
if (isFunction(conditional)) { conditional = conditional.call(this); }
// Default behavior is to render the positive path if the value is truthy and not empty.
@@ -17,7 +15,6 @@ export default function(instance) {
});
instance.registerHelper('unless', function(conditional, options) {
if (arguments.length != 2) { throw new Exception('#unless requires exactly one argument');}
return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
});
}
+1 -1
View File
@@ -3,7 +3,7 @@ export default function(instance) {
if (!obj) {
return obj;
}
if (String(field) === 'constructor' && !obj.propertyIsEnumerable(field)) {
if (field === 'constructor' && !obj.propertyIsEnumerable(field)) {
return undefined;
}
return obj[field];
+1 -3
View File
@@ -1,9 +1,7 @@
import { appendContextPath, blockParams, createFrame, isEmpty, isFunction } from '../utils';
import Exception from '../exception';
import {appendContextPath, blockParams, createFrame, isEmpty, isFunction} from '../utils';
export default function(instance) {
instance.registerHelper('with', function(context, options) {
if (arguments.length != 2) { throw new Exception('#with requires exactly one argument');}
if (isFunction(context)) { context = context.call(this); }
let fn = options.fn;
+30 -39
View File
@@ -1,30 +1,26 @@
import * as Utils from './utils';
import Exception from './exception';
import {COMPILER_REVISION, createFrame, LAST_COMPATIBLE_COMPILER_REVISION, REVISION_CHANGES} from './base';
import {moveHelperToHooks} from './helpers';
import { COMPILER_REVISION, REVISION_CHANGES, createFrame } from './base';
export function checkRevision(compilerInfo) {
const compilerRevision = compilerInfo && compilerInfo[0] || 1,
currentRevision = COMPILER_REVISION;
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] + ').');
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] + ').');
}
}
}
export function template(templateSpec, env) {
/* istanbul ignore next */
if (!env) {
throw new Exception('No environment passed to template');
@@ -39,9 +35,6 @@ export function template(templateSpec, env) {
// 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);
@@ -49,15 +42,13 @@ export function template(templateSpec, env) {
options.ids[0] = true;
}
}
partial = env.VM.resolvePartial.call(this, partial, context, options);
let optionsWithHooks = Utils.extend({}, options, {hooks: this.hooks});
let result = env.VM.invokePartial.call(this, partial, context, optionsWithHooks);
let result = env.VM.invokePartial.call(this, partial, context, options);
if (result == null && env.compile) {
options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
result = options.partials[options.name](context, optionsWithHooks);
result = options.partials[options.name](context, options);
}
if (result != null) {
if (options.indent) {
@@ -79,9 +70,9 @@ export function template(templateSpec, env) {
// Just add water
let container = {
strict: function(obj, name, loc) {
if (!obj || !(name in obj)) {
throw new Exception('"' + name + '" not defined in ' + obj, { loc: loc });
strict: function(obj, name) {
if (!(name in obj)) {
throw new Exception('"' + name + '" not defined in ' + obj);
}
return obj[name];
},
@@ -124,6 +115,15 @@ 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,28 +158,19 @@ export function template(templateSpec, env) {
ret._setup = function(options) {
if (!options.partial) {
container.helpers = Utils.extend({}, env.helpers, options.helpers);
container.helpers = container.merge(options.helpers, env.helpers);
if (templateSpec.usePartial) {
container.partials = Utils.extend({}, env.partials, options.partials);
container.partials = container.merge(options.partials, env.partials);
}
if (templateSpec.usePartial || templateSpec.useDecorators) {
container.decorators = Utils.extend({}, env.decorators, options.decorators);
container.decorators = container.merge(options.decorators, env.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) {
-1
View File
@@ -1,4 +1,3 @@
const escape = {
'&': '&amp;',
'<': '&lt;',
+69 -182
View File
@@ -1,88 +1,9 @@
{
"name": "handlebars",
"version": "4.5.0",
"version": "4.1.2-0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@babel/runtime": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz",
"integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==",
"dev": true,
"requires": {
"regenerator-runtime": "^0.13.2"
}
},
"@knappi/grunt-saucelabs": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@knappi/grunt-saucelabs/-/grunt-saucelabs-9.0.2.tgz",
"integrity": "sha512-PHnusXA+begWFgZS084ZAC8kT7FNRvvJIWg5FOqusRjr4LSe++RIk2HRULAQ8Dx+6HiKJiQXzrAsDagKh3k1pw==",
"dev": true,
"requires": {
"@knappi/sauce-tunnel": "^2.5.0",
"colors": "~1.1.2",
"lodash": "^4.17.11",
"q": "~1.4.1",
"requestretry": "~1.9.0",
"saucelabs": "^1.5.0"
},
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
"q": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
"integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
"dev": true
}
}
},
"@knappi/sauce-tunnel": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@knappi/sauce-tunnel/-/sauce-tunnel-2.5.0.tgz",
"integrity": "sha512-8f60HrHH4SRHOspcVLbN0gpDiBYLQjmZCXwmqibhzJDHGaD/fflPpdUD2kJJyeioydcf1T0xfpbMcJW0dLjpnw==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
"request": "^2.88.0",
"split": "^1.0.1"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"@types/parsimmon": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@types/parsimmon/-/parsimmon-1.10.0.tgz",
@@ -330,12 +251,6 @@
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
"dev": true
},
"ast-metadata-inferer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.1.1.tgz",
"integrity": "sha512-hc9w8Qrgg9Lf9iFcZVhNjUnhrd2BBpTlyCnegPVvCe6O0yMrF57a6Cmh7k+xUsfUOMh9wajOL5AsGOBNEyTCcw==",
"dev": true
},
"ast-traverse": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ast-traverse/-/ast-traverse-0.1.1.tgz",
@@ -847,17 +762,6 @@
"pako": "~0.2.0"
}
},
"browserslist": {
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.2.tgz",
"integrity": "sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001004",
"electron-to-chromium": "^1.3.295",
"node-releases": "^1.1.38"
}
},
"buffer": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
@@ -957,18 +861,6 @@
}
}
},
"caniuse-db": {
"version": "1.0.30001005",
"resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001005.tgz",
"integrity": "sha512-MSRfm2N6FRDSpAJ00ipCuFe0CNink5JJOFzl4S7fLSBJdowhGq3uMxzkWGTjvvReo1PuWfK5YYJydJJ+9mJebw==",
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001005",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001005.tgz",
"integrity": "sha512-g78miZm1Z5njjYR216a5812oPiLgV1ssndgGxITHWUopmjUrCswMisA0a2kSB7a0vZRox6JOKhM51+efmYN8Mg==",
"dev": true
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@@ -1785,12 +1677,6 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
"dev": true
},
"electron-to-chromium": {
"version": "1.3.296",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.296.tgz",
"integrity": "sha512-s5hv+TSJSVRsxH190De66YHb50pBGTweT9XGWYu/LMR20KX6TsjFzObo36CjVAzM+PUeeKSBRtm/mISlCzeojQ==",
"dev": true
},
"emojis-list": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
@@ -2111,35 +1997,6 @@
}
}
},
"eslint-plugin-compat": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.3.0.tgz",
"integrity": "sha512-QCgYy3pZ+zH10dkBJus1xER0359h1UhJjufhQRqp9Owm6BEoLZeSqxf2zINwL1OGao9Yc96xPYIW3nQj5HUryg==",
"dev": true,
"requires": {
"@babel/runtime": "^7.4.5",
"ast-metadata-inferer": "^0.1.1",
"browserslist": "^4.6.3",
"caniuse-db": "^1.0.30000977",
"lodash.memoize": "4.1.2",
"mdn-browser-compat-data": "^0.0.84",
"semver": "^6.1.2"
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
},
"eslint-plugin-es5": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-es5/-/eslint-plugin-es5-1.4.1.tgz",
"integrity": "sha512-kktkmkF2O7pnSZYgrMiYMbt3wCKRIiXePwILv8USDG95YgP0PzhIxSIROLLKmiQQ/Z6LuhDGWTHK04gnbXBvkg==",
"dev": true
},
"eslint-scope": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
@@ -3846,6 +3703,33 @@
}
}
},
"grunt-saucelabs": {
"version": "github:nknapp/grunt-saucelabs#5b9b7150e66051dbf68e9212fbb89561e447e855",
"from": "github:nknapp/grunt-saucelabs",
"dev": true,
"requires": {
"colors": "~1.1.2",
"lodash": "^4.17.11",
"q": "~1.4.1",
"requestretry": "~1.9.0",
"sauce-tunnel": "github:nknapp/sauce-tunnel",
"saucelabs": "^1.5.0"
},
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
"q": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
"integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
"dev": true
}
}
},
"grunt-webpack": {
"version": "1.0.18",
"resolved": "https://registry.npmjs.org/grunt-webpack/-/grunt-webpack-1.0.18.tgz",
@@ -5202,12 +5086,6 @@
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=",
"dev": true
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
"dev": true
},
"longest": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
@@ -5299,15 +5177,6 @@
"pretty-bytes": "^1.0.0"
}
},
"mdn-browser-compat-data": {
"version": "0.0.84",
"resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-0.0.84.tgz",
"integrity": "sha512-fAznuGNaQMQiWLVf+gyp33FaABTglYWqMT7JqvH+4RZn2UQPD12gbMqxwP9m0lj8AAbNpu5/kD6n4Ox1SOffpw==",
"dev": true,
"requires": {
"extend": "3.0.2"
}
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -5710,23 +5579,6 @@
}
}
},
"node-releases": {
"version": "1.1.39",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.39.tgz",
"integrity": "sha512-8MRC/ErwNCHOlAFycy9OPca46fQYUjbJRDcZTHVWIGXIjYLM73k70vv3WkYutVnM4cCo4hE0MqBVVZjP6vjISA==",
"dev": true,
"requires": {
"semver": "^6.3.0"
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
},
"nomnom": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/nomnom/-/nomnom-0.4.3.tgz",
@@ -6851,12 +6703,6 @@
"through": "~2.3.8"
}
},
"regenerator-runtime": {
"version": "0.13.3",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
"integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
"dev": true
},
"regex-cache": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
@@ -7174,6 +7020,47 @@
"integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=",
"dev": true
},
"sauce-tunnel": {
"version": "github:nknapp/sauce-tunnel#746744c71b9bec69ca612e751e7121f61a37d489",
"from": "github:nknapp/sauce-tunnel",
"dev": true,
"requires": {
"chalk": "^2.4.2",
"request": "^2.88.0",
"split": "^1.0.1"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"saucelabs": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz",
+2 -4
View File
@@ -1,7 +1,7 @@
{
"name": "handlebars",
"barename": "handlebars",
"version": "4.5.2",
"version": "4.2.2",
"description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
"homepage": "http://www.handlebarsjs.com/",
"keywords": [
@@ -29,7 +29,6 @@
"uglify-js": "^3.1.4"
},
"devDependencies": {
"@knappi/grunt-saucelabs": "^9.0.2",
"aws-sdk": "^2.1.49",
"babel-loader": "^5.0.0",
"babel-runtime": "^5.1.10",
@@ -37,8 +36,6 @@
"dtslint": "^0.5.5",
"dustjs-linkedin": "^2.0.2",
"eco": "~1.1.0-rc-3",
"eslint-plugin-compat": "^3.3.0",
"eslint-plugin-es5": "^1.4.1",
"grunt": "^1.0.3",
"grunt-babel": "^5.0.0",
"grunt-bg-shell": "^2.3.3",
@@ -51,6 +48,7 @@
"grunt-contrib-uglify": "^1",
"grunt-contrib-watch": "^1.1.0",
"grunt-eslint": "^20.1.0",
"grunt-saucelabs": "github:nknapp/grunt-saucelabs",
"grunt-webpack": "^1.0.8",
"istanbul": "^0.3.0",
"jison": "~0.3.0",
+3 -155
View File
@@ -2,165 +2,13 @@
## Development
[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.2...master)
[Commits](https://github.com/wycats/handlebars.js/compare/v4.2.2...master)
## v4.5.2 - November 13th, 2019
# Bugfixes
- fix: use String(field) in lookup when checking for "constructor" - d541378
- test: add fluent API for testing Handlebars - c2ac79c
Compatibility notes:
- no incompatibility are to be expected
[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.1...v4.5.2)
## v4.5.1 - October 29th, 2019
Bugfixs
- fix: move "eslint-plugin-compat" to devDependencies - 5e9d17f (#1589)
Compatibility notes:
- No compatibility issues are to be expected
[Commits](https://github.com/wycats/handlebars.js/compare/v4.5.0...v4.5.1)
## v4.5.0 - October 28th, 2019
Features / Improvements
- Add method Handlebars.parseWithoutProcessing (#1584) - 62ed3c2
- add guard to if & unless helpers (#1549)
- show source location for the strict lookup exceptions - feb60f8
Bugfixes:
- Use objects for hash value tracking - 7fcf9d2
Chore:
- Resolve deprecation warning message from eslint while running eslint (#1586) - 7052e88
- chore: add eslint-plugin-compat and eslint-plugin-es5 - 088e618
Compatibility notes:
- No compatibility issues are to be expected
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.5...v4.5.0)
## v4.4.5 - October 20th, 2019
Bugfixes:
- Contents of raw-blocks must be matched with non-eager regex-matching - 8d5530e, #1579
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.4...v4.4.5)
## v4.4.4 - October 20th, 2019
Bugfixes:
- fix: prevent zero length tokens in raw-blocks (#1577, #1578) - f1752fe
Chore:
- chore: link to s3 bucket with https, add "npm ci" to build instructions - 0b593bf
Compatibility notes:
- no compatibility issues are expected
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.3...v4.4.4)
## v4.4.3 - October 8th, 2019
Bugfixes
Typings:
- add missing type fields to AST typings and add tests for them - 0440af2
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.2...v4.4.3)
## v4.4.2 - October 2nd, 2019
- chore: fix grunt-saucelabs dependency - b7eada0
[Commits](https://github.com/wycats/handlebars.js/compare/v4.4.1...v4.4.2)
## v4.4.1 - October 2nd, 2019
## v4.2.2 - 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.4.0...v4.4.1)
## v4.4.0 - September 29th, 2019
- Added support for iterable objects in {{#each}} helper (#1557) - cf7545e
[Commits](https://github.com/wycats/handlebars.js/compare/v4.3.4...v4.4.0)
## 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)
[Commits](https://github.com/wycats/handlebars.js/compare/v4.2.1...v4.2.2)
## v4.2.1 - September 20th, 2019
Bugfixes:
+2 -8
View File
@@ -1,20 +1,14 @@
{
"extends": [
"../.eslintrc.js",
"plugin:es5/no-es2015"
],
"plugins": [
"es5"
],
"globals": {
"CompilerContext": true,
"Handlebars": true,
"handlebarsEnv": true,
"shouldCompileTo": true,
"shouldCompileToWithPartials": true,
"shouldThrow": true,
"expectTemplate": true,
"compileWithPartials": true,
"console": true,
"require": true,
"suite": true,
-105
View File
@@ -123,40 +123,6 @@ describe('ast', function() {
});
});
describe('whitespace control', function() {
describe('parse', function() {
it('mustache', function() {
var ast = Handlebars.parse(' {{~comment~}} ');
equals(ast.body[0].value, '');
equals(ast.body[2].value, '');
});
it('block statements', function() {
var ast = Handlebars.parse(' {{# comment~}} \nfoo\n {{~/comment}}');
equals(ast.body[0].value, '');
equals(ast.body[1].program.body[0].value, 'foo');
});
});
describe('parseWithoutProcessing', function() {
it('mustache', function() {
var ast = Handlebars.parseWithoutProcessing(' {{~comment~}} ');
equals(ast.body[0].value, ' ');
equals(ast.body[2].value, ' ');
});
it('block statements', function() {
var ast = Handlebars.parseWithoutProcessing(' {{# comment~}} \nfoo\n {{~/comment}}');
equals(ast.body[0].value, ' ');
equals(ast.body[1].program.body[0].value, ' \nfoo\n ');
});
});
});
describe('standalone flags', function() {
describe('mustache', function() {
it('does not mark mustaches as standalone', function() {
@@ -165,54 +131,6 @@ describe('ast', function() {
equals(!!ast.body[2].value, true);
});
});
describe('blocks - parseWithoutProcessing', function() {
it('block mustaches', function() {
var ast = Handlebars.parseWithoutProcessing(' {{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} '),
block = ast.body[1];
equals(ast.body[0].value, ' ');
equals(block.program.body[0].value, ' \nfoo\n ');
equals(block.inverse.body[0].value, ' \n bar \n ');
equals(ast.body[2].value, ' ');
});
it('initial block mustaches', function() {
var ast = Handlebars.parseWithoutProcessing('{{# comment}} \nfoo\n {{/comment}}'),
block = ast.body[0];
equals(block.program.body[0].value, ' \nfoo\n ');
});
it('mustaches with children', function() {
var ast = Handlebars.parseWithoutProcessing('{{# comment}} \n{{foo}}\n {{/comment}}'),
block = ast.body[0];
equals(block.program.body[0].value, ' \n');
equals(block.program.body[1].path.original, 'foo');
equals(block.program.body[2].value, '\n ');
});
it('nested block mustaches', function() {
var ast = Handlebars.parseWithoutProcessing('{{#foo}} \n{{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} \n{{/foo}}'),
body = ast.body[0].program.body,
block = body[1];
equals(body[0].value, ' \n');
equals(block.program.body[0].value, ' \nfoo\n ');
equals(block.inverse.body[0].value, ' \n bar \n ');
});
it('column 0 block mustaches', function() {
var ast = Handlebars.parseWithoutProcessing('test\n{{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} '),
block = ast.body[1];
equals(ast.body[0].omit, undefined);
equals(block.program.body[0].value, ' \nfoo\n ');
equals(block.inverse.body[0].value, ' \n bar \n ');
equals(ast.body[2].value, ' ');
});
});
describe('blocks', function() {
it('marks block mustaches as standalone', function() {
var ast = Handlebars.parse(' {{# comment}} \nfoo\n {{else}} \n bar \n {{/comment}} '),
@@ -286,18 +204,6 @@ describe('ast', function() {
equals(ast.body[2].value, '');
});
});
describe('partials - parseWithoutProcessing', function() {
it('simple partial', function() {
var ast = Handlebars.parseWithoutProcessing('{{> partial }} ');
equals(ast.body[1].value, ' ');
});
it('indented partial', function() {
var ast = Handlebars.parseWithoutProcessing(' {{> partial }} ');
equals(ast.body[0].value, ' ');
equals(ast.body[1].indent, '');
equals(ast.body[2].value, ' ');
});
});
describe('partials', function() {
it('marks partial as standalone', function() {
var ast = Handlebars.parse('{{> partial }} ');
@@ -317,17 +223,6 @@ describe('ast', function() {
equals(ast.body[1].omit, undefined);
});
});
describe('comments - parseWithoutProcessing', function() {
it('simple comment', function() {
var ast = Handlebars.parseWithoutProcessing('{{! comment }} ');
equals(ast.body[1].value, ' ');
});
it('indented comment', function() {
var ast = Handlebars.parseWithoutProcessing(' {{! comment }} ');
equals(ast.body[0].value, ' ');
equals(ast.body[2].value, ' ');
});
});
describe('comments', function() {
it('marks comment as standalone', function() {
var ast = Handlebars.parse('{{! comment }} ');
-31
View File
@@ -254,37 +254,6 @@ describe('builtin helpers', function() {
template({});
}, handlebarsEnv.Exception, 'Must pass iterator to #each');
});
if (global.Symbol && global.Symbol.iterator) {
it('each on iterable', function() {
function Iterator(arr) {
this.arr = arr;
this.index = 0;
}
Iterator.prototype.next = function() {
var value = this.arr[this.index];
var done = this.index === this.arr.length;
if (!done) {
this.index++;
}
return { value: value, done: done };
};
function Iterable(arr) {
this.arr = arr;
}
Iterable.prototype[global.Symbol.iterator] = function() {
return new Iterator(this.arr);
};
var string = '{{#each goodbyes}}{{text}}! {{/each}}cruel {{world}}!';
var goodbyes = new Iterable([{text: 'goodbye'}, {text: 'Goodbye'}, {text: 'GOODBYE'}]);
var goodbyesEmpty = new Iterable([]);
var hash = {goodbyes: goodbyes, world: 'world'};
shouldCompileTo(string, hash, 'goodbye! Goodbye! GOODBYE! cruel world!',
'each with array argument iterates over the contents when not empty');
shouldCompileTo(string, {goodbyes: goodbyesEmpty, world: 'world'}, 'cruel world!',
'each with array argument ignores the contents when empty');
});
}
});
describe('#log', function() {
+1 -1
View File
@@ -9,7 +9,7 @@ var filename = 'dist/handlebars.js';
if (global.minimizedTest) {
filename = 'dist/handlebars.min.js';
}
var distHandlebars = fs.readFileSync(require.resolve('../../' + filename), 'utf-8');
var distHandlebars = fs.readFileSync(require.resolve(`../../${filename}`), 'utf-8');
vm.runInThisContext(distHandlebars, filename);
global.CompilerContext = {
+3 -83
View File
@@ -1,6 +1,4 @@
var global = (function() {
return this;
}());
var global = (function() { return this; }());
var AssertError;
if (Error.captureStackTrace) {
@@ -18,16 +16,10 @@ if (Error.captureStackTrace) {
AssertError = Error;
}
/**
* @deprecated Use "expectTemplate(template)...toCompileTo(output)" instead
*/
global.shouldCompileTo = function(string, hashOrArray, expected, message) {
shouldCompileToWithPartials(string, hashOrArray, false, expected, message);
};
/**
* @deprecated Use "expectTemplate(template)...toCompileTo(output)" instead
*/
global.shouldCompileToWithPartials = function shouldCompileToWithPartials(string, hashOrArray, partials, expected, message) {
var result = compileWithPartials(string, hashOrArray, partials);
if (result !== expected) {
@@ -35,9 +27,6 @@ global.shouldCompileToWithPartials = function shouldCompileToWithPartials(string
}
};
/**
* @deprecated Use "expectTemplate(template)...toCompileTo(output)" instead
*/
global.compileWithPartials = function(string, hashOrArray, partials) {
var template,
ary,
@@ -47,8 +36,8 @@ global.compileWithPartials = function(string, hashOrArray, partials) {
delete hashOrArray.hash;
} else if (Object.prototype.toString.call(hashOrArray) === '[object Array]') {
ary = [];
ary.push(hashOrArray[0]); // input
ary.push({helpers: hashOrArray[1], partials: hashOrArray[2]});
ary.push(hashOrArray[0]);
ary.push({ helpers: hashOrArray[1], partials: hashOrArray[2] });
options = typeof hashOrArray[3] === 'object' ? hashOrArray[3] : {compat: hashOrArray[3]};
if (hashOrArray[4] != null) {
options.data = !!hashOrArray[4];
@@ -86,72 +75,3 @@ global.shouldThrow = function(callback, type, msg) {
throw new AssertError('It failed to throw', shouldThrow);
}
};
global.expectTemplate = function(templateAsString) {
return new HandlebarsTestBench(templateAsString);
};
function HandlebarsTestBench(templateAsString) {
this.templateAsString = templateAsString;
this.helpers = {};
this.partials = {};
this.input = {};
this.message = 'Template' + templateAsString + ' does not evaluate to expected output';
this.compileOptions = {};
this.runtimeOptions = {};
}
HandlebarsTestBench.prototype.withInput = function(input) {
this.input = input;
return this;
};
HandlebarsTestBench.prototype.withHelper = function(name, helperFunction) {
this.helpers[name] = helperFunction;
return this;
};
HandlebarsTestBench.prototype.withPartial = function(name, partialAsString) {
this.partials[name] = partialAsString;
return this;
};
HandlebarsTestBench.prototype.withCompileOptions = function(compileOptions) {
this.compileOptions = compileOptions;
return this;
};
HandlebarsTestBench.prototype.withRuntimeOptions = function(runtimeOptions) {
this.runtimeOptions = runtimeOptions;
return this;
};
HandlebarsTestBench.prototype.withMessage = function(message) {
this.message = message;
return this;
};
HandlebarsTestBench.prototype.toCompileTo = function(expectedOutputAsString) {
var self = this;
var compile = Object.keys(this.partials).length > 0
? CompilerContext.compileWithPartial
: CompilerContext.compile;
var combinedRuntimeOptions = {};
Object.keys(this.runtimeOptions).forEach(function(key) {
combinedRuntimeOptions[key] = self.runtimeOptions[key];
});
combinedRuntimeOptions.helpers = this.helpers;
combinedRuntimeOptions.partials = this.partials;
var template = compile(this.templateAsString, this.compileOptions);
var output = template(this.input, combinedRuntimeOptions);
if (output !== expectedOutputAsString) {
// Error message formatted so that IntelliJ-Idea shows "diff"-button
// https://stackoverflow.com/a/10945655/4251384
throw new AssertError(this.message + '\nexpected:' + expectedOutputAsString + 'but was:' + output);
}
};
+1 -1
View File
@@ -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":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
return templates['empty'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) {
return "";
},"useData":true});
});
+7 -102
View File
@@ -28,43 +28,14 @@ describe('helpers', function() {
'raw block helper gets raw content');
});
describe('raw block parsing (with identity helper-function)', function() {
function runWithIdentityHelper(template, expected) {
var helpers = {
identity: function(options) {
it('helper for nested raw block gets raw content', function() {
var string = '{{{{a}}}} {{{{b}}}} {{{{/b}}}} {{{{/a}}}}';
var helpers = {
a: function(options) {
return options.fn();
}
};
shouldCompileTo(template, [{}, helpers], expected);
}
it('helper for nested raw block gets raw content', function() {
runWithIdentityHelper('{{{{identity}}}} {{{{b}}}} {{{{/b}}}} {{{{/identity}}}}', ' {{{{b}}}} {{{{/b}}}} ');
});
it('helper for nested raw block works with empty content', function() {
runWithIdentityHelper('{{{{identity}}}}{{{{/identity}}}}', '');
});
xit('helper for nested raw block works if nested raw blocks are broken', function() {
// This test was introduced in 4.4.4, but it was not the actual problem that lead to the patch release
// The test is deactivated, because in 3.x this template cases an exception and it also does not work in 4.4.3
// If anyone can make this template work without breaking everything else, then go for it,
// but for now, this is just a known bug, that will be documented.
runWithIdentityHelper('{{{{identity}}}} {{{{a}}}} {{{{ {{{{/ }}}} }}}} {{{{/identity}}}}', ' {{{{a}}}} {{{{ {{{{/ }}}} }}}} ');
});
it('helper for nested raw block closes after first matching close', function() {
runWithIdentityHelper('{{{{identity}}}}abc{{{{/identity}}}} {{{{identity}}}}abc{{{{/identity}}}}', 'abc abc');
});
it('helper for nested raw block throw exception when with missing closing braces', function() {
var string = '{{{{a}}}} {{{{/a';
shouldThrow(function() {
Handlebars.compile(string)();
});
});
}
};
shouldCompileTo(string, [{}, helpers], ' {{{{b}}}} {{{{/b}}}} ', 'raw block helper should get nested raw block as raw content');
});
it('helper block with identical context', function() {
@@ -766,70 +737,4 @@ describe('helpers', function() {
shouldCompileTo('{{#if bar}}{{else goodbyes as |value|}}{{value}}{{/if}}{{value}}', [hash, helpers], '1foo');
});
});
describe('built-in helpers malformed arguments ', function() {
it('if helper - too few arguments', function() {
var template = CompilerContext.compile('{{#if}}{{/if}}');
shouldThrow(function() {
template({});
}, undefined, /#if requires exactly one argument/);
});
it('if helper - too many arguments, string', function() {
var template = CompilerContext.compile('{{#if test "string"}}{{/if}}');
shouldThrow(function() {
template({});
}, undefined, /#if requires exactly one argument/);
});
it('if helper - too many arguments, undefined', function() {
var template = CompilerContext.compile('{{#if test undefined}}{{/if}}');
shouldThrow(function() {
template({});
}, undefined, /#if requires exactly one argument/);
});
it('if helper - too many arguments, null', function() {
var template = CompilerContext.compile('{{#if test null}}{{/if}}');
shouldThrow(function() {
template({});
}, undefined, /#if requires exactly one argument/);
});
it('unless helper - too few arguments', function() {
var template = CompilerContext.compile('{{#unless}}{{/unless}}');
shouldThrow(function() {
template({});
}, undefined, /#unless requires exactly one argument/);
});
it('unless helper - too many arguments', function() {
var template = CompilerContext.compile('{{#unless test null}}{{/unless}}');
shouldThrow(function() {
template({});
}, undefined, /#unless requires exactly one argument/);
});
it('with helper - too few arguments', function() {
var template = CompilerContext.compile('{{#with}}{{/with}}');
shouldThrow(function() {
template({});
}, undefined, /#with requires exactly one argument/);
});
it('with helper - too many arguments', function() {
var template = CompilerContext.compile('{{#with test "string"}}{{/with}}');
shouldThrow(function() {
template({});
}, undefined, /#with requires exactly one argument/);
});
});
});
-43
View File
@@ -291,47 +291,4 @@ 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});
}
});
it('should allow hash with protected array names', function() {
var obj = {array: [1], name: 'John'};
var helpers = {
helpa: function(options) {
return options.hash.length;
}
};
shouldCompileTo('{{helpa length="foo"}}', [obj, helpers], 'foo');
});
});
+1 -1
View File
@@ -21,7 +21,7 @@ describe('runtime', function() {
shouldThrow(function() {
Handlebars.template({
main: {},
compiler: [Handlebars.LAST_COMPATIBLE_COMPILER_REVISION - 1]
compiler: [Handlebars.COMPILER_REVISION - 1]
});
}, Error, /Template was precompiled with an older version of Handlebars than the current runtime/);
shouldThrow(function() {
+3 -94
View File
@@ -1,26 +1,11 @@
describe('security issues', function() {
describe('GH-1495: Prevent Remote Code Execution via constructor', function() {
it('should not allow constructors to be accessed', function() {
expectTemplate('{{lookup (lookup this "constructor") "name"}}')
.withInput({})
.toCompileTo('');
expectTemplate('{{constructor.name}}')
.withInput({})
.toCompileTo('');
shouldCompileTo('{{constructor.name}}', {}, '');
shouldCompileTo('{{lookup (lookup this "constructor") "name"}}', {}, '');
});
it('GH-1603: should not allow constructors to be accessed (lookup via toString)', function() {
expectTemplate('{{lookup (lookup this (list "constructor")) "name"}}')
.withInput({})
.withHelper('list', function(element) {
return [element];
})
.toCompileTo('');
});
it('should allow the "constructor" property to be accessed if it is enumerable', function() {
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');
@@ -29,13 +14,6 @@ describe('security issues', function() {
}}, 'here we go');
});
it('should allow the "constructor" property to be accessed if it is enumerable', function() {
shouldCompileTo('{{lookup (lookup this "constructor") "name"}}', {'constructor': {
'name': 'here we go'
}}, 'here we go');
});
it('should allow prototype properties that are not constructors', function() {
function TestClass() {
}
@@ -54,73 +32,4 @@ describe('security issues', function() {
});
});
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}}', {}, '');
});
});
});
-19
View File
@@ -95,25 +95,6 @@ describe('strict', function() {
};
equals(template({}, {helpers: helpers}), 'success');
});
it('should show error location on missing property lookup', function() {
shouldThrow(function() {
var template = CompilerContext.compile('\n\n\n {{hello}}', {strict: true});
template({});
}, Exception, '"hello" not defined in [object Object] - 4:5');
});
it('should error contains correct location properties on missing property lookup', function() {
try {
var template = CompilerContext.compile('\n\n\n {{hello}}', {strict: true});
template({});
} catch (error) {
equals(error.lineNumber, 4);
equals(error.endLineNumber, 4);
equals(error.column, 5);
equals(error.endColumn, 10);
}
});
});
describe('assume objects', function() {
-5
View File
@@ -441,9 +441,4 @@ describe('Tokenizer', function() {
result = tokenize('{{else foo as |bar baz|}}');
shouldMatchTokens(result, ['OPEN_INVERSE_CHAIN', 'ID', 'OPEN_BLOCK_PARAMS', 'ID', 'ID', 'CLOSE_BLOCK_PARAMS', 'CLOSE']);
});
it('tokenizes raw blocks', function() {
var result = tokenize('{{{{a}}}} abc {{{{/a}}}} aaa {{{{a}}}} abc {{{{/a}}}}');
shouldMatchTokens(result, ['OPEN_RAW_BLOCK', 'ID', 'CLOSE_RAW_BLOCK', 'CONTENT', 'END_RAW_BLOCK', 'CONTENT', 'OPEN_RAW_BLOCK', 'ID', 'CLOSE_RAW_BLOCK', 'CONTENT', 'END_RAW_BLOCK']);
});
});
+1 -1
View File
@@ -63,7 +63,7 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD}
return 'END_RAW_BLOCK';
}
}
<raw>[^\x00]+?/("{{{{") { return 'CONTENT'; }
<raw>[^\x00]*?/("{{{{") { return 'CONTENT'; }
<com>[\s\S]*?"--"{RIGHT_STRIP}?"}}" {
this.popState();
+1 -1
View File
@@ -39,7 +39,7 @@ content
};
rawBlock
: openRawBlock content* END_RAW_BLOCK -> yy.prepareRawBlock($1, $2, $3, @$)
: openRawBlock content+ END_RAW_BLOCK -> yy.prepareRawBlock($1, $2, $3, @$)
;
openRawBlock
+5 -37
View File
@@ -29,7 +29,6 @@ declare namespace Handlebars {
decorators?: { [name: string]: Function };
data?: any;
blockParams?: any[];
allowCallsToHelperMissing?: boolean;
}
export interface HelperOptions {
@@ -47,8 +46,8 @@ declare namespace Handlebars {
}
export interface ParseOptions {
srcName?: string;
ignoreStandalone?: boolean;
srcName?: string,
ignoreStandalone?: boolean
}
export function registerHelper(name: string, fn: HelperDelegate): void;
@@ -66,9 +65,9 @@ declare namespace Handlebars {
export function K(): void;
export function createFrame(object: any): any;
export function blockParams(obj: any[], ids: any[]): any[];
export function Exception(message: string): void;
export function log(level: number, obj: any): void;
export function parse(input: string, options?: ParseOptions): hbs.AST.Program;
export function parseWithoutProcessing(input: string, options?: ParseOptions): hbs.AST.Program;
export function compile<T = any>(input: any, options?: CompileOptions): HandlebarsTemplateDelegate<T>;
export function precompile(input: any, options?: PrecompileOptions): TemplateSpecification;
export function template<T = any>(precompilation: TemplateSpecification): HandlebarsTemplateDelegate<T>;
@@ -86,20 +85,6 @@ declare namespace Handlebars {
export function noConflict(): typeof Handlebars;
export class Exception {
constructor(message: string, node?: hbs.AST.Node);
description: string;
fileName: string;
lineNumber?: any;
endLineNumber?: any;
message: string;
name: string;
number: number;
stack?: string;
column?: any;
endColumn?: any;
}
export class SafeString {
constructor(str: string);
toString(): string;
@@ -284,7 +269,6 @@ declare namespace hbs {
interface Statement extends Node {}
interface MustacheStatement extends Statement {
type: 'MustacheStatement';
path: PathExpression | Literal;
params: Expression[];
hash: Hash;
@@ -295,7 +279,6 @@ declare namespace hbs {
interface Decorator extends MustacheStatement { }
interface BlockStatement extends Statement {
type: 'BlockStatement';
path: PathExpression;
params: Expression[];
hash: Hash;
@@ -309,7 +292,6 @@ declare namespace hbs {
interface DecoratorBlock extends BlockStatement { }
interface PartialStatement extends Statement {
type: 'PartialStatement';
name: PathExpression | SubExpression;
params: Expression[];
hash: Hash;
@@ -318,7 +300,6 @@ declare namespace hbs {
}
interface PartialBlockStatement extends Statement {
type: 'PartialBlockStatement';
name: PathExpression | SubExpression;
params: Expression[];
hash: Hash;
@@ -328,13 +309,11 @@ declare namespace hbs {
}
interface ContentStatement extends Statement {
type: 'ContentStatement';
value: string;
original: StripFlags;
}
interface CommentStatement extends Statement {
type: 'CommentStatement';
value: string;
strip: StripFlags;
}
@@ -342,14 +321,12 @@ declare namespace hbs {
interface Expression extends Node {}
interface SubExpression extends Expression {
type: 'SubExpression';
path: PathExpression;
params: Expression[];
hash: Hash;
}
interface PathExpression extends Expression {
type: 'PathExpression';
data: boolean;
depth: number;
parts: string[];
@@ -358,38 +335,29 @@ declare namespace hbs {
interface Literal extends Expression {}
interface StringLiteral extends Literal {
type: 'StringLiteral';
value: string;
original: string;
}
interface BooleanLiteral extends Literal {
type: 'BooleanLiteral';
value: boolean;
original: boolean;
}
interface NumberLiteral extends Literal {
type: 'NumberLiteral';
value: number;
original: number;
}
interface UndefinedLiteral extends Literal {
type: 'UndefinedLiteral';
}
interface UndefinedLiteral extends Literal {}
interface NullLiteral extends Literal {
type: 'NullLiteral';
}
interface NullLiteral extends Literal {}
interface Hash extends Node {
type: 'Hash';
pairs: HashPair[];
}
interface HashPair extends Node {
type: 'HashPair';
key: string;
value: Expression;
}
+1 -134
View File
@@ -97,7 +97,7 @@ Handlebars.VM.resolvePartial = <T>(partial: HandlebarsTemplateDelegate<T> | unde
// transform name.
options.name = name;
return originalResolvePartial(partial, context, options);
};
}
// #1544, allow custom helpers in knownHelpers
@@ -107,136 +107,3 @@ Handlebars.compile('test', {
customHelper: true
}
});
Handlebars.compile('test')({},{allowCallsToHelperMissing: true});
Handlebars.compile('test')({},{});
const allthings = {} as hbs.AST.MustacheStatement |
hbs.AST.BlockStatement |
hbs.AST.PartialStatement |
hbs.AST.PartialBlockStatement |
hbs.AST.ContentStatement |
hbs.AST.CommentStatement |
hbs.AST.SubExpression |
hbs.AST.PathExpression |
hbs.AST.StringLiteral |
hbs.AST.BooleanLiteral |
hbs.AST.NumberLiteral |
hbs.AST.UndefinedLiteral |
hbs.AST.NullLiteral |
hbs.AST.Hash |
hbs.AST.HashPair;
switch(allthings.type) {
case "MustacheStatement":
let mustacheStatement: hbs.AST.MustacheStatement;
mustacheStatement = allthings;
break;
case "BlockStatement":
let blockStatement: hbs.AST.BlockStatement;
blockStatement = allthings;
break;
case "PartialStatement":
let partialStatement: hbs.AST.PartialStatement;
partialStatement = allthings;
break;
case "PartialBlockStatement":
let partialBlockStatement: hbs.AST.PartialBlockStatement;
partialBlockStatement = allthings;
break;
case "ContentStatement":
let ContentStatement: hbs.AST.ContentStatement;
ContentStatement = allthings;
break;
case "CommentStatement":
let CommentStatement: hbs.AST.CommentStatement;
CommentStatement = allthings;
break;
case "SubExpression":
let SubExpression: hbs.AST.SubExpression;
SubExpression = allthings;
break;
case "PathExpression":
let PathExpression: hbs.AST.PathExpression;
PathExpression = allthings;
break;
case "StringLiteral":
let StringLiteral: hbs.AST.StringLiteral;
StringLiteral = allthings;
break;
case "BooleanLiteral":
let BooleanLiteral: hbs.AST.BooleanLiteral;
BooleanLiteral = allthings;
break;
case "NumberLiteral":
let NumberLiteral: hbs.AST.NumberLiteral;
NumberLiteral = allthings;
break;
case "UndefinedLiteral":
let UndefinedLiteral: hbs.AST.UndefinedLiteral;
UndefinedLiteral = allthings;
break;
case "NullLiteral":
let NullLiteral: hbs.AST.NullLiteral;
NullLiteral = allthings;
break;
case "Hash":
let Hash: hbs.AST.Hash;
Hash = allthings;
break;
case "HashPair":
let HashPair: hbs.AST.HashPair;
HashPair = allthings;
break;
default:
break;
}
function testParseWithoutProcessing() {
const parsedTemplate: hbs.AST.Program = Handlebars.parseWithoutProcessing('<p>Hello, my name is {{name}}.</p>', {
srcName: "/foo/bar/baz.hbs",
});
const parsedTemplateWithoutOptions: hbs.AST.Program = Handlebars.parseWithoutProcessing('<p>Hello, my name is {{name}}.</p>');
}
function testExceptionTypings() {
// Test exception constructor with a single argument - message.
let exception: Handlebars.Exception = new Handlebars.Exception('message');
// Fields
let message: string = exception.message;
let lineNumber: number = exception.lineNumber;
let column: number = exception.column;
let endLineNumber: number = exception.endLineNumber;
let endColumn: number = exception.endColumn;
let description = exception.description;
let name: string = exception.name;
let fileName: string = exception.fileName;
let stack: string | undefined = exception.stack;
}
function testExceptionWithNodeTypings() {
// Test exception constructor with both arguments.
const exception: Handlebars.Exception = new Handlebars.Exception('message', {
type: 'MustacheStatement',
loc: {
source: 'source',
start: { line: 1, column: 5 },
end: { line: 10, column: 2 }
}
});
// Fields
let message: string = exception.message;
let lineNumber: number = exception.lineNumber;
let column: number = exception.column;
let endLineNumber: number = exception.endLineNumber;
let endColumn: number = exception.endColumn;
let description = exception.description;
let name: string = exception.name;
let fileName: string = exception.fileName;
let stack: string | undefined = exception.stack;
}
-5839
View File
File diff suppressed because it is too large Load Diff