Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 95c890ed88 |
+1
-1
@@ -116,7 +116,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"files": ["tests/bench/**/*.js"],
|
"files": ["tests/bench/**/*.mjs"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-console": "off"
|
"no-console": "off"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://swc.rs/schema.json",
|
||||||
|
"module": {
|
||||||
|
"type": "commonjs",
|
||||||
|
"importInterop": "swc"
|
||||||
|
},
|
||||||
|
"sourceMaps": "inline"
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import { loadTemplates, cli } from '../lib/precompiler.js';
|
import { createRequire } from 'node:module';
|
||||||
import yargs from 'yargs';
|
import yargs from 'yargs';
|
||||||
|
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
const Precompiler = require('../dist/cjs/precompiler');
|
||||||
|
|
||||||
const parser = yargs(process.argv.slice(2))
|
const parser = yargs(process.argv.slice(2))
|
||||||
.usage('Precompile handlebar templates.\nUsage: $0 [template|directory]...')
|
.usage('Precompile handlebar templates.\nUsage: $0 [template|directory]...')
|
||||||
.help(false)
|
.help(false)
|
||||||
@@ -16,6 +19,23 @@ const parser = yargs(process.argv.slice(2))
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'Source Map File',
|
description: 'Source Map File',
|
||||||
})
|
})
|
||||||
|
.option('a', {
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Exports amd style (require.js)',
|
||||||
|
alias: 'amd',
|
||||||
|
})
|
||||||
|
.option('c', {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Exports CommonJS style, path to Handlebars module',
|
||||||
|
alias: 'commonjs',
|
||||||
|
default: null,
|
||||||
|
})
|
||||||
|
.option('h', {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Path to handlebar.js (only valid for amd-style)',
|
||||||
|
alias: 'handlebarPath',
|
||||||
|
default: '',
|
||||||
|
})
|
||||||
.option('k', {
|
.option('k', {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'Known helpers',
|
description: 'Known helpers',
|
||||||
@@ -97,7 +117,7 @@ const argv = parser.parseSync();
|
|||||||
argv.files = argv._;
|
argv.files = argv._;
|
||||||
delete argv._;
|
delete argv._;
|
||||||
|
|
||||||
loadTemplates(argv, function (err, opts) {
|
Precompiler.loadTemplates(argv, function (err, opts) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
@@ -107,7 +127,7 @@ loadTemplates(argv, function (err, opts) {
|
|||||||
} else {
|
} else {
|
||||||
// cli() is async (returns a Promise), so errors would become unhandled
|
// cli() is async (returns a Promise), so errors would become unhandled
|
||||||
// rejections. Re-throw via nextTick to surface them as uncaught exceptions.
|
// rejections. Re-throw via nextTick to surface them as uncaught exceptions.
|
||||||
Promise.resolve(cli(opts)).catch((error) => {
|
Promise.resolve(Precompiler.cli(opts)).catch((error) => {
|
||||||
process.nextTick(() => {
|
process.nextTick(() => {
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
import Handlebars from './lib/index.js';
|
|
||||||
import fs from 'fs';
|
|
||||||
|
|
||||||
// Read the basic.js test file and extract test cases
|
|
||||||
// For now, manually define a set of representative test cases
|
|
||||||
const tests = [];
|
|
||||||
|
|
||||||
function T(template, input, expected, opts) {
|
|
||||||
tests.push({
|
|
||||||
template,
|
|
||||||
input: input ?? {},
|
|
||||||
expected,
|
|
||||||
compileOpts: opts?.compile ?? {},
|
|
||||||
runtimeOpts: opts?.runtime ?? {},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============ basic.js equivalents ============
|
|
||||||
const g = (t, i, e, co, ro) => T(t, i, e, { compile: co, runtime: ro });
|
|
||||||
|
|
||||||
g('{{foo}}', { foo: 'foo' }, 'foo');
|
|
||||||
g('\\{{foo}}', { foo: 'food' }, '{{foo}}');
|
|
||||||
g('content \\{{foo}}', { foo: 'food' }, 'content {{foo}}');
|
|
||||||
g('\\\\{{foo}}', { foo: 'food' }, '\\food');
|
|
||||||
g('\\\\ {{foo}}', { foo: 'food' }, '\\\\ food');
|
|
||||||
g(
|
|
||||||
'Goodbye\n{{cruel}}\n{{world}}!',
|
|
||||||
{ cruel: 'cruel', world: 'world' },
|
|
||||||
'Goodbye\ncruel\nworld!'
|
|
||||||
);
|
|
||||||
g('{{.}}{{length}}', 'bye', 'bye3');
|
|
||||||
g('Goodbye\n{{cruel}}\n{{world.bar}}!', undefined, 'Goodbye\n\n!');
|
|
||||||
g(
|
|
||||||
'{{! Goodbye}}Goodbye\n{{cruel}}\n{{world}}!',
|
|
||||||
{ cruel: 'cruel', world: 'world' },
|
|
||||||
'Goodbye\ncruel\nworld!'
|
|
||||||
);
|
|
||||||
g(' {{~! comment ~}} blah', {}, 'blah');
|
|
||||||
g(' {{~!-- long-comment --~}} blah', {}, 'blah');
|
|
||||||
g(' {{! comment ~}} blah', {}, ' blah');
|
|
||||||
g(' {{~! comment}} blah', {}, ' blah');
|
|
||||||
g('{{#if foo}}foo{{/if}}', { foo: true }, 'foo');
|
|
||||||
g('{{#if foo}}foo{{else}}bar{{/if}}', { foo: false }, 'bar');
|
|
||||||
g('{{#unless foo}}bar{{/unless}}', { foo: false }, 'bar');
|
|
||||||
g('{{#with foo}}{{bar}}{{/with}}', { foo: { bar: 'baz' } }, 'baz');
|
|
||||||
g('{{#each items}}{{this}}{{/each}}', { items: ['a', 'b', 'c'] }, 'abc');
|
|
||||||
g('{{#each items}}{{@index}}{{/each}}', { items: ['a', 'b'] }, '01');
|
|
||||||
g('<b>{{foo}}</b>', { foo: '&' }, '<b>&</b>');
|
|
||||||
g('{{{foo}}}', { foo: '<b>' }, '<b>');
|
|
||||||
g('{{foo.bar}}', { foo: { bar: 'baz' } }, 'baz');
|
|
||||||
g('{{foo/bar}}', { foo: { bar: 'baz' } }, 'baz');
|
|
||||||
g('{{../foo}}', {}, ''); // depth at root = empty
|
|
||||||
g('{{{foo}}}', { foo: '&' }, '&');
|
|
||||||
|
|
||||||
// ============ blocks.js equivalents ============
|
|
||||||
g(
|
|
||||||
'{{#list people}}{{firstName}} {{lastName}}\n{{/list}}',
|
|
||||||
{
|
|
||||||
people: [
|
|
||||||
{ firstName: 'Yehuda', lastName: 'Katz' },
|
|
||||||
{ firstName: 'Carl', lastName: 'Lerche' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
'Yehuda Katz\nCarl Lerche\n'
|
|
||||||
);
|
|
||||||
g(
|
|
||||||
'{{#list people}}{{../prefix}} {{firstName}}\n{{/list}}',
|
|
||||||
{ people: [{ firstName: 'Yehuda' }, { firstName: 'Carl' }], prefix: 'Mr' },
|
|
||||||
'Mr Yehuda\nMr Carl\n'
|
|
||||||
);
|
|
||||||
g(
|
|
||||||
'{{#each people as |person|}}{{person}}\n{{/each}}',
|
|
||||||
{ people: ['Yehuda', 'Carl'] },
|
|
||||||
'Yehuda\nCarl\n'
|
|
||||||
);
|
|
||||||
|
|
||||||
// ============ builtins.js equivalents ============
|
|
||||||
g(
|
|
||||||
'{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!',
|
|
||||||
{ goodbye: true, world: 'world' },
|
|
||||||
'GOODBYE cruel world!'
|
|
||||||
);
|
|
||||||
g(
|
|
||||||
'{{#if goodbye}}GOODBYE {{/if}}cruel {{world}}!',
|
|
||||||
{ goodbye: false, world: 'world' },
|
|
||||||
'cruel world!'
|
|
||||||
);
|
|
||||||
g('{{lookup foo "bar"}}', { foo: { bar: 'val' } }, 'val');
|
|
||||||
g(
|
|
||||||
'{{#each items as |value key|}}{{key}}:{{value}},{{/each}}',
|
|
||||||
{ items: { a: 1, b: 2 } },
|
|
||||||
'a:1,b:2,'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write output
|
|
||||||
const results = tests.map((t, i) => {
|
|
||||||
let result,
|
|
||||||
error = null;
|
|
||||||
try {
|
|
||||||
const env = Handlebars.create();
|
|
||||||
const compiled = env.compile(t.template, t.compileOpts);
|
|
||||||
result = compiled(t.input, t.runtimeOpts);
|
|
||||||
} catch (e) {
|
|
||||||
error = e.message;
|
|
||||||
result = null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
i,
|
|
||||||
template: t.template,
|
|
||||||
input: JSON.stringify(t.input),
|
|
||||||
expected: t.expected,
|
|
||||||
result,
|
|
||||||
error,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.writeFileSync('/tmp/golden_results.json', JSON.stringify(results, null, 2));
|
|
||||||
console.log(`Generated ${results.length} golden results`);
|
|
||||||
const failures = results.filter((r) => r.result !== r.expected);
|
|
||||||
if (failures.length) {
|
|
||||||
console.log(`\nFAILURES (${failures.length}):`);
|
|
||||||
failures.forEach((f) =>
|
|
||||||
console.log(
|
|
||||||
` [${f.i}] "${f.template}" expected="${f.expected}" got="${f.result}" error="${f.error}"`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
+5
-9
@@ -5,18 +5,14 @@ import {
|
|||||||
Visitor,
|
Visitor,
|
||||||
} from '@handlebars/parser';
|
} from '@handlebars/parser';
|
||||||
|
|
||||||
import runtime from './handlebars.runtime.js';
|
import runtime from './handlebars.runtime';
|
||||||
|
|
||||||
// Compiler imports
|
// Compiler imports
|
||||||
import AST from './handlebars/compiler/ast.js';
|
import AST from './handlebars/compiler/ast';
|
||||||
import {
|
import { Compiler, compile, precompile } from './handlebars/compiler/compiler';
|
||||||
Compiler,
|
import JavaScriptCompiler from './handlebars/compiler/javascript-compiler';
|
||||||
compile,
|
|
||||||
precompile,
|
|
||||||
} from './handlebars/compiler/compiler.js';
|
|
||||||
import JavaScriptCompiler from './handlebars/compiler/javascript-compiler.js';
|
|
||||||
|
|
||||||
import noConflict from './handlebars/no-conflict.js';
|
import noConflict from './handlebars/no-conflict';
|
||||||
|
|
||||||
let _create = runtime.create;
|
let _create = runtime.create;
|
||||||
function create() {
|
function create() {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Exception } from '@handlebars/parser';
|
import { Exception } from '@handlebars/parser';
|
||||||
import * as base from './handlebars/base.js';
|
import * as base from './handlebars/base';
|
||||||
|
|
||||||
// Each of these augment the Handlebars object. No need to setup here.
|
// Each of these augment the Handlebars object. No need to setup here.
|
||||||
// (This is done to easily share code between module systems and browser envs)
|
// (This is done to easily share code between commonjs and browse envs)
|
||||||
import SafeString from './handlebars/safe-string.js';
|
import SafeString from './handlebars/safe-string';
|
||||||
import * as Utils from './handlebars/utils.js';
|
import * as Utils from './handlebars/utils';
|
||||||
import * as runtime from './handlebars/runtime.js';
|
import * as runtime from './handlebars/runtime';
|
||||||
|
|
||||||
import noConflict from './handlebars/no-conflict.js';
|
import noConflict from './handlebars/no-conflict';
|
||||||
|
|
||||||
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
|
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
|
||||||
function create() {
|
function create() {
|
||||||
@@ -37,15 +37,4 @@ noConflict(inst);
|
|||||||
|
|
||||||
inst['default'] = inst;
|
inst['default'] = inst;
|
||||||
|
|
||||||
// Named re-exports for CJS interop.
|
|
||||||
// See the comment in lib/index.js for the full explanation. In short:
|
|
||||||
// require('handlebars/runtime').COMPILER_REVISION must be directly accessible
|
|
||||||
// for tools like handlebars-loader that compare compiler and runtime revisions.
|
|
||||||
export {
|
|
||||||
VERSION,
|
|
||||||
COMPILER_REVISION,
|
|
||||||
LAST_COMPATIBLE_COMPILER_REVISION,
|
|
||||||
REVISION_CHANGES,
|
|
||||||
} from './handlebars/base.js';
|
|
||||||
|
|
||||||
export default inst;
|
export default inst;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Exception } from '@handlebars/parser';
|
import { Exception } from '@handlebars/parser';
|
||||||
import { createFrame, extend, toString } from './utils.js';
|
import { createFrame, extend, toString } from './utils';
|
||||||
import { registerDefaultHelpers } from './helpers.js';
|
import { registerDefaultHelpers } from './helpers';
|
||||||
import { registerDefaultDecorators } from './decorators.js';
|
import { registerDefaultDecorators } from './decorators';
|
||||||
import logger from './logger.js';
|
import logger from './logger';
|
||||||
import { resetLoggedProperties } from './internal/proto-access.js';
|
import { resetLoggedProperties } from './internal/proto-access';
|
||||||
|
|
||||||
export const VERSION = '4.7.7';
|
export const VERSION = '4.7.7';
|
||||||
export const COMPILER_REVISION = 8;
|
export const COMPILER_REVISION = 8;
|
||||||
|
|||||||
@@ -1,5 +1,56 @@
|
|||||||
import { isArray } from '../utils.js';
|
/* global define */
|
||||||
import { SourceNode } from '#source-node';
|
import { isArray } from '../utils';
|
||||||
|
|
||||||
|
let SourceNode;
|
||||||
|
|
||||||
|
try {
|
||||||
|
/* v8 ignore next */
|
||||||
|
if (typeof define !== 'function' || !define.amd) {
|
||||||
|
// We don't support this in AMD environments. For these environments, we assume that
|
||||||
|
// they are running on the browser and thus have no need for the source-map library.
|
||||||
|
// The variable indirection prevents bundlers from statically resolving and bundling
|
||||||
|
// source-map (which requires Node-built-ins). The stub SourceNode below handles
|
||||||
|
// browser/bundled usage. Bundlers may emit a "Critical dependency" warning — this
|
||||||
|
// is expected and harmless.
|
||||||
|
let mod = 'source-map';
|
||||||
|
let SourceMap = require(mod);
|
||||||
|
SourceNode = SourceMap.SourceNode;
|
||||||
|
}
|
||||||
|
// oxlint-disable-next-line no-unused-vars -- Babel 5 requires named catch param
|
||||||
|
} catch (err) {
|
||||||
|
/* NOP */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* v8 ignore next -- tested but not covered due to dist build */
|
||||||
|
if (!SourceNode) {
|
||||||
|
SourceNode = function (line, column, srcFile, chunks) {
|
||||||
|
this.src = '';
|
||||||
|
if (chunks) {
|
||||||
|
this.add(chunks);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/* v8 ignore next */
|
||||||
|
SourceNode.prototype = {
|
||||||
|
add: function (chunks) {
|
||||||
|
if (isArray(chunks)) {
|
||||||
|
chunks = chunks.join('');
|
||||||
|
}
|
||||||
|
this.src += chunks;
|
||||||
|
},
|
||||||
|
prepend: function (chunks) {
|
||||||
|
if (isArray(chunks)) {
|
||||||
|
chunks = chunks.join('');
|
||||||
|
}
|
||||||
|
this.src = chunks + this.src;
|
||||||
|
},
|
||||||
|
toStringWithSourceMap: function () {
|
||||||
|
return { code: this.toString() };
|
||||||
|
},
|
||||||
|
toString: function () {
|
||||||
|
return this.src;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function castChunk(chunk, codeGen, loc) {
|
function castChunk(chunk, codeGen, loc) {
|
||||||
if (isArray(chunk)) {
|
if (isArray(chunk)) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Exception } from '@handlebars/parser';
|
import { Exception } from '@handlebars/parser';
|
||||||
import { isArray, indexOf, extend } from '../utils.js';
|
import { isArray, indexOf, extend } from '../utils';
|
||||||
import AST from './ast.js';
|
import AST from './ast';
|
||||||
|
|
||||||
const slice = [].slice;
|
const slice = [].slice;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Exception } from '@handlebars/parser';
|
import { Exception } from '@handlebars/parser';
|
||||||
import { COMPILER_REVISION, REVISION_CHANGES } from '../base.js';
|
import { COMPILER_REVISION, REVISION_CHANGES } from '../base';
|
||||||
import { isArray } from '../utils.js';
|
import { isArray } from '../utils';
|
||||||
import CodeGen from './code-gen.js';
|
import CodeGen from './code-gen';
|
||||||
|
|
||||||
function Literal(value) {
|
function Literal(value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
@@ -164,12 +164,10 @@ JavaScriptCompiler.prototype = {
|
|||||||
|
|
||||||
let { programs, decorators } = this.context;
|
let { programs, decorators } = this.context;
|
||||||
for (i = 0, l = programs.length; i < l; i++) {
|
for (i = 0, l = programs.length; i < l; i++) {
|
||||||
if (programs[i]) {
|
ret[i] = programs[i];
|
||||||
ret[i] = programs[i];
|
if (decorators[i]) {
|
||||||
if (decorators[i]) {
|
ret[i + '_d'] = decorators[i];
|
||||||
ret[i + '_d'] = decorators[i];
|
ret.useDecorators = true;
|
||||||
ret.useDecorators = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -836,8 +834,8 @@ JavaScriptCompiler.prototype = {
|
|||||||
let existing = this.matchExistingProgram(child);
|
let existing = this.matchExistingProgram(child);
|
||||||
|
|
||||||
if (existing == null) {
|
if (existing == null) {
|
||||||
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
|
// Placeholder to prevent name conflicts for nested children
|
||||||
let index = this.context.programs.length;
|
let index = this.context.programs.push('') - 1;
|
||||||
child.index = index;
|
child.index = index;
|
||||||
child.name = 'program' + index;
|
child.name = 'program' + index;
|
||||||
this.context.programs[index] = compiler.compile(
|
this.context.programs[index] = compiler.compile(
|
||||||
@@ -1175,34 +1173,20 @@ function strictLookup(requireTerminal, compiler, parts, startPartIndex, type) {
|
|||||||
stack = compiler.nameLookup(stack, parts[i], type);
|
stack = compiler.nameLookup(stack, parts[i], type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!requireTerminal) {
|
if (requireTerminal) {
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startPartIndex > len) {
|
|
||||||
// Compat mode already consumed all parts via depthedLookup; the stack
|
|
||||||
// holds the resolved value, not an object to look the property up on.
|
|
||||||
// Use container.strictLookup to traverse depths with a strict error on miss.
|
|
||||||
return [
|
return [
|
||||||
compiler.aliasable('container.strictLookup'),
|
compiler.aliasable('container.strict'),
|
||||||
'(depths, ',
|
'(',
|
||||||
|
stack,
|
||||||
|
', ',
|
||||||
compiler.quotedString(parts[len]),
|
compiler.quotedString(parts[len]),
|
||||||
', ',
|
', ',
|
||||||
JSON.stringify(compiler.source.currentLocation),
|
JSON.stringify(compiler.source.currentLocation),
|
||||||
' )',
|
' )',
|
||||||
];
|
];
|
||||||
|
} else {
|
||||||
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
|
||||||
compiler.aliasable('container.strict'),
|
|
||||||
'(',
|
|
||||||
stack,
|
|
||||||
', ',
|
|
||||||
compiler.quotedString(parts[len]),
|
|
||||||
', ',
|
|
||||||
JSON.stringify(compiler.source.currentLocation),
|
|
||||||
' )',
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default JavaScriptCompiler;
|
export default JavaScriptCompiler;
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
import { isArray } from '../utils.js';
|
|
||||||
|
|
||||||
// Lightweight stub for browser environments where the source-map package
|
|
||||||
// (which depends on Node.js built-ins) is not available.
|
|
||||||
export function SourceNode(line, column, srcFile, chunks) {
|
|
||||||
this.src = '';
|
|
||||||
if (chunks) {
|
|
||||||
this.add(chunks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SourceNode.prototype = {
|
|
||||||
add(chunks) {
|
|
||||||
if (isArray(chunks)) {
|
|
||||||
chunks = chunks.join('');
|
|
||||||
}
|
|
||||||
this.src += chunks;
|
|
||||||
},
|
|
||||||
prepend(chunks) {
|
|
||||||
if (isArray(chunks)) {
|
|
||||||
chunks = chunks.join('');
|
|
||||||
}
|
|
||||||
this.src = chunks + this.src;
|
|
||||||
},
|
|
||||||
toStringWithSourceMap() {
|
|
||||||
return { code: this.toString() };
|
|
||||||
},
|
|
||||||
toString() {
|
|
||||||
return this.src;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { SourceNode } from 'source-map';
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import registerInline from './decorators/inline.js';
|
import registerInline from './decorators/inline';
|
||||||
|
|
||||||
export function registerDefaultDecorators(instance) {
|
export function registerDefaultDecorators(instance) {
|
||||||
registerInline(instance);
|
registerInline(instance);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { extend } from '../utils.js';
|
import { extend } from '../utils';
|
||||||
|
|
||||||
export default function (instance) {
|
export default function (instance) {
|
||||||
instance.registerDecorator(
|
instance.registerDecorator(
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import registerBlockHelperMissing from './helpers/block-helper-missing.js';
|
import registerBlockHelperMissing from './helpers/block-helper-missing';
|
||||||
import registerEach from './helpers/each.js';
|
import registerEach from './helpers/each';
|
||||||
import registerHelperMissing from './helpers/helper-missing.js';
|
import registerHelperMissing from './helpers/helper-missing';
|
||||||
import registerIf from './helpers/if.js';
|
import registerIf from './helpers/if';
|
||||||
import registerLog from './helpers/log.js';
|
import registerLog from './helpers/log';
|
||||||
import registerLookup from './helpers/lookup.js';
|
import registerLookup from './helpers/lookup';
|
||||||
import registerWith from './helpers/with.js';
|
import registerWith from './helpers/with';
|
||||||
|
|
||||||
export function registerDefaultHelpers(instance) {
|
export function registerDefaultHelpers(instance) {
|
||||||
registerBlockHelperMissing(instance);
|
registerBlockHelperMissing(instance);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { isArray } from '../utils.js';
|
import { isArray } from '../utils';
|
||||||
|
|
||||||
export default function (instance) {
|
export default function (instance) {
|
||||||
instance.registerHelper('blockHelperMissing', function (context, options) {
|
instance.registerHelper('blockHelperMissing', function (context, options) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Exception } from '@handlebars/parser';
|
import { Exception } from '@handlebars/parser';
|
||||||
import { createFrame, isArray, isFunction, isMap, isSet } from '../utils.js';
|
import { createFrame, isArray, isFunction, isMap, isSet } from '../utils';
|
||||||
|
|
||||||
export default function (instance) {
|
export default function (instance) {
|
||||||
instance.registerHelper('each', function (context, options) {
|
instance.registerHelper('each', function (context, options) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Exception } from '@handlebars/parser';
|
import { Exception } from '@handlebars/parser';
|
||||||
import { isEmpty, isFunction } from '../utils.js';
|
import { isEmpty, isFunction } from '../utils';
|
||||||
|
|
||||||
export default function (instance) {
|
export default function (instance) {
|
||||||
instance.registerHelper('if', function (conditional, options) {
|
instance.registerHelper('if', function (conditional, options) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Exception } from '@handlebars/parser';
|
import { Exception } from '@handlebars/parser';
|
||||||
import { isEmpty, isFunction } from '../utils.js';
|
import { isEmpty, isFunction } from '../utils';
|
||||||
|
|
||||||
export default function (instance) {
|
export default function (instance) {
|
||||||
instance.registerHelper('with', function (context, options) {
|
instance.registerHelper('with', function (context, options) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { extend } from '../utils.js';
|
import { extend } from '../utils';
|
||||||
import logger from '../logger.js';
|
import logger from '../logger';
|
||||||
|
|
||||||
const loggedProperties = Object.create(null);
|
const loggedProperties = Object.create(null);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { indexOf } from './utils.js';
|
import { indexOf } from './utils';
|
||||||
|
|
||||||
let logger = {
|
let logger = {
|
||||||
methodMap: ['debug', 'info', 'warn', 'error'],
|
methodMap: ['debug', 'info', 'warn', 'error'],
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { Exception } from '@handlebars/parser';
|
import { Exception } from '@handlebars/parser';
|
||||||
import * as Utils from './utils.js';
|
import * as Utils from './utils';
|
||||||
import {
|
import {
|
||||||
COMPILER_REVISION,
|
COMPILER_REVISION,
|
||||||
createFrame,
|
createFrame,
|
||||||
LAST_COMPATIBLE_COMPILER_REVISION,
|
LAST_COMPATIBLE_COMPILER_REVISION,
|
||||||
REVISION_CHANGES,
|
REVISION_CHANGES,
|
||||||
} from './base.js';
|
} from './base';
|
||||||
import { moveHelperToHooks } from './helpers.js';
|
import { moveHelperToHooks } from './helpers';
|
||||||
import { wrapHelper } from './internal/wrapHelper.js';
|
import { wrapHelper } from './internal/wrapHelper';
|
||||||
import {
|
import {
|
||||||
createProtoAccessControl,
|
createProtoAccessControl,
|
||||||
resultIsAllowed,
|
resultIsAllowed,
|
||||||
} from './internal/proto-access.js';
|
} from './internal/proto-access';
|
||||||
|
|
||||||
export function checkRevision(compilerInfo) {
|
export function checkRevision(compilerInfo) {
|
||||||
const compilerRevision = (compilerInfo && compilerInfo[0]) || 1,
|
const compilerRevision = (compilerInfo && compilerInfo[0]) || 1,
|
||||||
@@ -116,22 +116,6 @@ export function template(templateSpec, env) {
|
|||||||
}
|
}
|
||||||
return container.lookupProperty(obj, name);
|
return container.lookupProperty(obj, name);
|
||||||
},
|
},
|
||||||
strictLookup: function (depths, name, loc) {
|
|
||||||
const len = depths.length;
|
|
||||||
let depth;
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
const d = depths[i];
|
|
||||||
if (
|
|
||||||
d &&
|
|
||||||
(typeof d === 'object' || typeof d === 'function') &&
|
|
||||||
name in d
|
|
||||||
) {
|
|
||||||
depth = d;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return container.strict(depth, name, loc);
|
|
||||||
},
|
|
||||||
lookupProperty: function (parent, propertyName) {
|
lookupProperty: function (parent, propertyName) {
|
||||||
if (Utils.isMap(parent)) {
|
if (Utils.isMap(parent)) {
|
||||||
return parent.get(propertyName);
|
return parent.get(propertyName);
|
||||||
|
|||||||
+23
-44
@@ -1,46 +1,25 @@
|
|||||||
import handlebars from './handlebars.js';
|
// USAGE:
|
||||||
import { PrintVisitor, print } from '@handlebars/parser';
|
// var handlebars = require('handlebars');
|
||||||
|
/* eslint-disable no-var */
|
||||||
|
|
||||||
handlebars.PrintVisitor = PrintVisitor;
|
// var local = handlebars.create();
|
||||||
handlebars.print = print;
|
|
||||||
|
|
||||||
// Named exports for CJS interop.
|
var handlebars = require('../dist/cjs/handlebars')['default'];
|
||||||
//
|
|
||||||
// When Node.js (v22+) runs require() on an ESM module, it returns the module
|
var parser = require('@handlebars/parser');
|
||||||
// namespace object — only named exports become direct properties. Without these,
|
handlebars.PrintVisitor = parser.PrintVisitor;
|
||||||
// require('handlebars') would return { default: inst } and calls like
|
handlebars.print = parser.print;
|
||||||
// Handlebars.precompile() or Handlebars.COMPILER_REVISION would be undefined.
|
|
||||||
//
|
module.exports = handlebars;
|
||||||
// Tools like handlebars-loader rely on these being directly accessible via
|
|
||||||
// require('handlebars').create(), require('handlebars').COMPILER_REVISION, etc.
|
// Publish a Node.js require() handler for .handlebars and .hbs files
|
||||||
export const {
|
function extension(module, filename) {
|
||||||
create,
|
var fs = require('fs');
|
||||||
compile,
|
var templateString = fs.readFileSync(filename, 'utf8');
|
||||||
precompile,
|
module.exports = handlebars.compile(templateString);
|
||||||
parse,
|
}
|
||||||
parseWithoutProcessing,
|
/* v8 ignore next 4 */
|
||||||
COMPILER_REVISION,
|
if (typeof require !== 'undefined' && require.extensions) {
|
||||||
LAST_COMPATIBLE_COMPILER_REVISION,
|
require.extensions['.handlebars'] = extension;
|
||||||
REVISION_CHANGES,
|
require.extensions['.hbs'] = extension;
|
||||||
VERSION,
|
}
|
||||||
AST,
|
|
||||||
Compiler,
|
|
||||||
JavaScriptCompiler,
|
|
||||||
Parser,
|
|
||||||
Visitor,
|
|
||||||
SafeString,
|
|
||||||
Exception,
|
|
||||||
Utils,
|
|
||||||
escapeExpression,
|
|
||||||
VM,
|
|
||||||
template,
|
|
||||||
log,
|
|
||||||
registerHelper,
|
|
||||||
unregisterHelper,
|
|
||||||
registerPartial,
|
|
||||||
unregisterPartial,
|
|
||||||
registerDecorator,
|
|
||||||
unregisterDecorator,
|
|
||||||
} = handlebars;
|
|
||||||
export { PrintVisitor, print };
|
|
||||||
export default handlebars;
|
|
||||||
|
|||||||
+45
-16
@@ -1,11 +1,11 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import Async from 'neo-async';
|
import Async from 'neo-async';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import Handlebars from './handlebars.js';
|
import Handlebars from './handlebars';
|
||||||
import { basename } from 'path';
|
import { basename } from 'path';
|
||||||
import { SourceMapConsumer, SourceNode } from 'source-map';
|
import { SourceMapConsumer, SourceNode } from 'source-map';
|
||||||
|
|
||||||
export function loadTemplates(opts, callback) {
|
module.exports.loadTemplates = function (opts, callback) {
|
||||||
loadStrings(opts, function (err, strings) {
|
loadStrings(opts, function (err, strings) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
@@ -20,7 +20,7 @@ export function loadTemplates(opts, callback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
function loadStrings(opts, callback) {
|
function loadStrings(opts, callback) {
|
||||||
let strings = arrayCast(opts.string),
|
let strings = arrayCast(opts.string),
|
||||||
@@ -152,7 +152,7 @@ function loadFiles(opts, callback) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cli(opts) {
|
module.exports.cli = async function (opts) {
|
||||||
if (opts.version) {
|
if (opts.version) {
|
||||||
console.log(Handlebars.VERSION);
|
console.log(Handlebars.VERSION);
|
||||||
return;
|
return;
|
||||||
@@ -176,7 +176,12 @@ export async function cli(opts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Force simple mode if we have only one template and it's unnamed.
|
// Force simple mode if we have only one template and it's unnamed.
|
||||||
if (opts.templates.length === 1 && !opts.templates[0].name) {
|
if (
|
||||||
|
!opts.amd &&
|
||||||
|
!opts.commonjs &&
|
||||||
|
opts.templates.length === 1 &&
|
||||||
|
!opts.templates[0].name
|
||||||
|
) {
|
||||||
opts.simple = true;
|
opts.simple = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +200,17 @@ export async function cli(opts) {
|
|||||||
|
|
||||||
let output = new SourceNode();
|
let output = new SourceNode();
|
||||||
if (!opts.simple) {
|
if (!opts.simple) {
|
||||||
output.add('(function() {\n');
|
if (opts.amd) {
|
||||||
|
output.add(
|
||||||
|
"define(['" +
|
||||||
|
opts.handlebarPath +
|
||||||
|
'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];'
|
||||||
|
);
|
||||||
|
} else if (opts.commonjs) {
|
||||||
|
output.add('var Handlebars = require("' + opts.commonjs + '");');
|
||||||
|
} else {
|
||||||
|
output.add('(function() {\n');
|
||||||
|
}
|
||||||
output.add(' var template = Handlebars.template, templates = ');
|
output.add(' var template = Handlebars.template, templates = ');
|
||||||
if (opts.namespace) {
|
if (opts.namespace) {
|
||||||
output.add(opts.namespace);
|
output.add(opts.namespace);
|
||||||
@@ -238,6 +253,9 @@ export async function cli(opts) {
|
|||||||
throw new Handlebars.Exception('Name missing for template');
|
throw new Handlebars.Exception('Name missing for template');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts.amd && !multiple) {
|
||||||
|
output.add('return ');
|
||||||
|
}
|
||||||
output.add([
|
output.add([
|
||||||
objectName,
|
objectName,
|
||||||
"['",
|
"['",
|
||||||
@@ -251,7 +269,14 @@ export async function cli(opts) {
|
|||||||
|
|
||||||
// Output the content
|
// Output the content
|
||||||
if (!opts.simple) {
|
if (!opts.simple) {
|
||||||
output.add('})();');
|
if (opts.amd) {
|
||||||
|
if (multiple) {
|
||||||
|
output.add(['return ', objectName, ';\n']);
|
||||||
|
}
|
||||||
|
output.add('});');
|
||||||
|
} else if (!opts.commonjs) {
|
||||||
|
output.add('})();');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.map) {
|
if (opts.map) {
|
||||||
@@ -262,7 +287,7 @@ export async function cli(opts) {
|
|||||||
output.map = output.map + '';
|
output.map = output.map + '';
|
||||||
|
|
||||||
if (opts.min) {
|
if (opts.min) {
|
||||||
output = await minify(output, opts.map);
|
output = minify(output, opts.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.map) {
|
if (opts.map) {
|
||||||
@@ -275,7 +300,7 @@ export async function cli(opts) {
|
|||||||
} else {
|
} else {
|
||||||
console.log(output);
|
console.log(output);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function arrayCast(value) {
|
function arrayCast(value) {
|
||||||
value = value != null ? value : [];
|
value = value != null ? value : [];
|
||||||
@@ -288,25 +313,29 @@ function arrayCast(value) {
|
|||||||
/**
|
/**
|
||||||
* Run uglify to minify the compiled template, if uglify exists in the dependencies.
|
* Run uglify to minify the compiled template, if uglify exists in the dependencies.
|
||||||
*
|
*
|
||||||
|
* We are using `require` instead of `import` here, because es6-modules do not allow
|
||||||
|
* dynamic imports and uglify-js is an optional dependency. Since we are inside NodeJS here, this
|
||||||
|
* should not be a problem.
|
||||||
|
*
|
||||||
* @param {string} output the compiled template
|
* @param {string} output the compiled template
|
||||||
* @param {string} sourceMapFile the file to write the source map to.
|
* @param {string} sourceMapFile the file to write the source map to.
|
||||||
*/
|
*/
|
||||||
async function minify(output, sourceMapFile) {
|
function minify(output, sourceMapFile) {
|
||||||
let uglify;
|
|
||||||
try {
|
try {
|
||||||
uglify = await import('uglify-js');
|
// Try to resolve uglify-js in order to see if it does exist
|
||||||
// Handle both default and named exports
|
require.resolve('uglify-js');
|
||||||
uglify = uglify.default || uglify;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code !== 'ERR_MODULE_NOT_FOUND' && e.code !== 'MODULE_NOT_FOUND') {
|
if (e.code !== 'MODULE_NOT_FOUND') {
|
||||||
|
// Something else seems to be wrong
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
// it does not exist!
|
||||||
console.error(
|
console.error(
|
||||||
'Code minimization is disabled due to missing uglify-js dependency'
|
'Code minimization is disabled due to missing uglify-js dependency'
|
||||||
);
|
);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
return uglify.minify(output.code, {
|
return require('uglify-js').minify(output.code, {
|
||||||
sourceMap: {
|
sourceMap: {
|
||||||
content: output.map,
|
content: output.map,
|
||||||
url: sourceMapFile,
|
url: sourceMapFile,
|
||||||
|
|||||||
Generated
+3648
-18
File diff suppressed because it is too large
Load Diff
+22
-25
@@ -16,40 +16,26 @@
|
|||||||
"url": "https://github.com/handlebars-lang/handlebars.js.git"
|
"url": "https://github.com/handlebars-lang/handlebars.js.git"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"handlebars": "bin/handlebars.js"
|
"handlebars": "bin/handlebars.mjs"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"bin",
|
"bin",
|
||||||
"dist/*.js",
|
"dist/*.js",
|
||||||
|
"dist/cjs/**/*.js",
|
||||||
"lib",
|
"lib",
|
||||||
"release-notes.md",
|
"release-notes.md",
|
||||||
"runtime.js",
|
"runtime.js",
|
||||||
"types/*.d.ts",
|
"types/*.d.ts",
|
||||||
"runtime.d.ts"
|
"runtime.d.ts"
|
||||||
],
|
],
|
||||||
"type": "module",
|
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
|
"browser": "./dist/cjs/handlebars.js",
|
||||||
"types": "types/index.d.ts",
|
"types": "types/index.d.ts",
|
||||||
"imports": {
|
|
||||||
"#source-node": {
|
|
||||||
"node": "./lib/handlebars/compiler/source-node.node.js",
|
|
||||||
"default": "./lib/handlebars/compiler/source-node.browser.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"types": "./types/index.d.ts",
|
|
||||||
"default": "./lib/index.js"
|
|
||||||
},
|
|
||||||
"./runtime": {
|
|
||||||
"types": "./runtime.d.ts",
|
|
||||||
"default": "./lib/handlebars.runtime.js"
|
|
||||||
},
|
|
||||||
"./package.json": "./package.json"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "node --input-type=module -e \"import fs from 'fs';fs.rmSync('dist',{recursive:true,force:true});fs.rmSync('tmp',{recursive:true,force:true})\"",
|
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true});require('fs').rmSync('tmp',{recursive:true,force:true})\"",
|
||||||
"build": "npm run clean && rspack build",
|
"build:cjs": "swc lib --out-dir dist/cjs --strip-leading-paths --ignore \"**/index.js\"",
|
||||||
|
"build:bundles": "rspack build",
|
||||||
|
"build": "npm run clean && npm run build:cjs && npm run build:bundles",
|
||||||
"release": "npm run build",
|
"release": "npm run build",
|
||||||
"publish:aws": "npm run build && npm run test:tasks && node tasks/publish-to-aws.js",
|
"publish:aws": "npm run build && npm run test:tasks && node tasks/publish-to-aws.js",
|
||||||
"format": "oxfmt --write . && oxlint --fix .",
|
"format": "oxfmt --write . && oxlint --fix .",
|
||||||
@@ -66,14 +52,14 @@
|
|||||||
"test:browser-smoke": "playwright test --config tests/browser/playwright.config.js",
|
"test:browser-smoke": "playwright test --config tests/browser/playwright.config.js",
|
||||||
"test:serve": "npx serve -l 9999 .",
|
"test:serve": "npx serve -l 9999 .",
|
||||||
"test:integration": "npm run build && ./tests/integration/run-integration-tests.sh",
|
"test:integration": "npm run build && ./tests/integration/run-integration-tests.sh",
|
||||||
"bench": "node tests/bench/perf.js",
|
"bench": "node tests/bench/perf.mjs",
|
||||||
"bench:compare": "node tests/bench/compare.js",
|
"bench:compare": "node tests/bench/compare.mjs",
|
||||||
"bench:size": "node tests/bench/size.js",
|
"bench:size": "node tests/bench/size.mjs",
|
||||||
"--- combined tasks ---": "",
|
"--- combined tasks ---": "",
|
||||||
"check-before-pull-request": "concurrently --kill-others-on-fail npm:lint npm:test"
|
"check-before-pull-request": "concurrently --kill-others-on-fail npm:lint npm:test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@handlebars/parser": "^2.2.2",
|
"@handlebars/parser": "^2.1.0",
|
||||||
"neo-async": "^2.6.2",
|
"neo-async": "^2.6.2",
|
||||||
"source-map": "^0.7.6",
|
"source-map": "^0.7.6",
|
||||||
"yargs": "^18.0.0"
|
"yargs": "^18.0.0"
|
||||||
@@ -83,6 +69,8 @@
|
|||||||
"@playwright/test": "^1.58.2",
|
"@playwright/test": "^1.58.2",
|
||||||
"@rspack/cli": "^1.7.8",
|
"@rspack/cli": "^1.7.8",
|
||||||
"@rspack/core": "^1.7.8",
|
"@rspack/core": "^1.7.8",
|
||||||
|
"@swc/cli": "^0.8.0",
|
||||||
|
"@swc/core": "^1.15.18",
|
||||||
"@vitest/browser": "^4.0.18",
|
"@vitest/browser": "^4.0.18",
|
||||||
"@vitest/browser-playwright": "^4.0.18",
|
"@vitest/browser-playwright": "^4.0.18",
|
||||||
"@vitest/coverage-v8": "^4.0.18",
|
"@vitest/coverage-v8": "^4.0.18",
|
||||||
@@ -128,5 +116,14 @@
|
|||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"jspm": {
|
||||||
|
"main": "handlebars",
|
||||||
|
"directories": {
|
||||||
|
"lib": "dist/cjs"
|
||||||
|
},
|
||||||
|
"buildConfig": {
|
||||||
|
"minify": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-38
@@ -1,14 +1,8 @@
|
|||||||
import { rspack } from '@rspack/core';
|
const { rspack } = require('@rspack/core');
|
||||||
import path from 'path';
|
const path = require('path');
|
||||||
import fs from 'fs';
|
const fs = require('fs');
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const pkg = require('./package.json');
|
||||||
const __dirname = path.dirname(__filename);
|
|
||||||
|
|
||||||
const pkg = JSON.parse(
|
|
||||||
fs.readFileSync(path.resolve(__dirname, 'package.json'), 'utf8')
|
|
||||||
);
|
|
||||||
const license = fs.readFileSync(path.resolve(__dirname, 'LICENSE'), 'utf8');
|
const license = fs.readFileSync(path.resolve(__dirname, 'LICENSE'), 'utf8');
|
||||||
const banner = `/*!
|
const banner = `/*!
|
||||||
|
|
||||||
@@ -35,11 +29,28 @@ function createConfig(entry, filename, minimize) {
|
|||||||
filename,
|
filename,
|
||||||
library: {
|
library: {
|
||||||
name: 'Handlebars',
|
name: 'Handlebars',
|
||||||
type: 'self',
|
type: 'umd',
|
||||||
export: 'default',
|
export: 'default',
|
||||||
},
|
},
|
||||||
|
globalObject: 'this',
|
||||||
clean: false,
|
clean: false,
|
||||||
},
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: {
|
||||||
|
loader: 'builtin:swc-loader',
|
||||||
|
options: {
|
||||||
|
jsc: {
|
||||||
|
parser: { syntax: 'ecmascript' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
minimize,
|
minimize,
|
||||||
minimizer: minimize
|
minimizer: minimize
|
||||||
@@ -60,38 +71,12 @@ function createConfig(entry, filename, minimize) {
|
|||||||
: [],
|
: [],
|
||||||
},
|
},
|
||||||
plugins,
|
plugins,
|
||||||
resolve: {
|
|
||||||
extensions: ['.js', '.json'],
|
|
||||||
mainFields: ['main'],
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
resolve: {
|
|
||||||
fullySpecified: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
use: {
|
|
||||||
loader: 'builtin:swc-loader',
|
|
||||||
options: {
|
|
||||||
jsc: {
|
|
||||||
parser: { syntax: 'ecmascript' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
target: ['web', 'browserslist'],
|
target: ['web', 'browserslist'],
|
||||||
devtool: false,
|
devtool: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default [
|
module.exports = [
|
||||||
createConfig('./lib/handlebars.js', 'handlebars.js', false),
|
createConfig('./lib/handlebars.js', 'handlebars.js', false),
|
||||||
createConfig('./lib/handlebars.runtime.js', 'handlebars.runtime.js', false),
|
createConfig('./lib/handlebars.runtime.js', 'handlebars.runtime.js', false),
|
||||||
createConfig('./lib/handlebars.js', 'handlebars.min.js', true),
|
createConfig('./lib/handlebars.js', 'handlebars.min.js', true),
|
||||||
|
|||||||
Vendored
+2
-3
@@ -1,4 +1,3 @@
|
|||||||
import Handlebars from 'handlebars';
|
import Handlebars = require('handlebars');
|
||||||
|
|
||||||
declare const runtime: typeof Handlebars;
|
declare module 'handlebars/runtime' {}
|
||||||
export default runtime;
|
|
||||||
|
|||||||
+3
-3
@@ -1,3 +1,3 @@
|
|||||||
import runtime from './lib/handlebars.runtime.js';
|
// Create a simple path alias to allow browserify to resolve
|
||||||
|
// the runtime on a supported path.
|
||||||
export default runtime;
|
module.exports = require('./dist/cjs/handlebars.runtime')['default'];
|
||||||
|
|||||||
Vendored
+3
-6
@@ -1,10 +1,7 @@
|
|||||||
import './common.js';
|
require('./common');
|
||||||
|
|
||||||
import fs from 'fs';
|
var fs = require('fs'),
|
||||||
import vm from 'vm';
|
vm = require('vm');
|
||||||
import { createRequire } from 'module';
|
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
|
||||||
|
|
||||||
global.Handlebars = 'no-conflict';
|
global.Handlebars = 'no-conflict';
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-3
@@ -1,7 +1,6 @@
|
|||||||
import './common.js';
|
require('./common');
|
||||||
import Handlebars from '../../lib/index.js';
|
|
||||||
|
|
||||||
global.Handlebars = Handlebars;
|
global.Handlebars = require('../../lib');
|
||||||
|
|
||||||
global.CompilerContext = {
|
global.CompilerContext = {
|
||||||
compile: function (template, options) {
|
compile: function (template, options) {
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
define(['handlebars.runtime'], function(Handlebars) {
|
||||||
|
Handlebars = Handlebars["default"]; var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
|
||||||
|
return templates['bom'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "a";
|
||||||
|
},"useData":true});
|
||||||
|
});
|
||||||
@@ -0,0 +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 "";
|
||||||
|
},"useData":true});
|
||||||
|
});
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
define(["handlebars.runtime"],function(e){var t=(e=e.default).template;return(e.templates=e.templates||{}).empty=t({compiler:[8,">= 4.3.0"],main:function(e,t,a,n,r){return""},useData:!0})});
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
define(['handlebars.runtime'], function(Handlebars) {
|
||||||
|
Handlebars = Handlebars["default"]; var template = Handlebars.template, templates = CustomNamespace.templates = CustomNamespace.templates || {};
|
||||||
|
return templates['empty'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "";
|
||||||
|
},"useData":true});
|
||||||
|
});
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "";
|
||||||
|
},"useData":true}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
(function() {
|
(function() {
|
||||||
var template = Handlebars.template, templates = CustomNamespace.templates = CustomNamespace.templates || {};
|
var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
|
||||||
templates['empty'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
templates['empty'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
return "";
|
return "";
|
||||||
},"useData":true});
|
},"useData":true});
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
define(['handlebars.runtime'], function(Handlebars) {
|
||||||
|
Handlebars = Handlebars["default"]; var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
|
||||||
|
templates['firstTemplate'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "<div>1</div>";
|
||||||
|
},"useData":true});
|
||||||
|
templates['secondTemplate'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "<div>2</div>";
|
||||||
|
},"useData":true});
|
||||||
|
return templates;
|
||||||
|
});
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
define(['handlebars.runtime'], function(Handlebars) {
|
||||||
|
Handlebars = Handlebars["default"]; var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
|
||||||
|
return templates['artifacts/partial.template'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "<div>Test Partial</div>";
|
||||||
|
},"useData":true});
|
||||||
|
});
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
define(['some-path/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 "";
|
||||||
|
},"useData":true});
|
||||||
|
});
|
||||||
+22
-19
@@ -1,22 +1,25 @@
|
|||||||
Precompile handlebar templates.
|
Precompile handlebar templates.
|
||||||
Usage: handlebars.js [template|directory]...
|
Usage: handlebars.mjs [template|directory]...
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-f, --output Output File [string]
|
-f, --output Output File [string]
|
||||||
--map Source Map File [string]
|
--map Source Map File [string]
|
||||||
-k, --known Known helpers [string]
|
-a, --amd Exports amd style (require.js) [boolean]
|
||||||
-o, --knownOnly Known helpers only [boolean]
|
-c, --commonjs Exports CommonJS style, path to Handlebars module [string] [default: null]
|
||||||
-m, --min Minimize output [boolean]
|
-h, --handlebarPath Path to handlebar.js (only valid for amd-style) [string] [default: ""]
|
||||||
-n, --namespace Template namespace [string] [default: "Handlebars.templates"]
|
-k, --known Known helpers [string]
|
||||||
-s, --simple Output template function only. [boolean]
|
-o, --knownOnly Known helpers only [boolean]
|
||||||
-N, --name Name of passed string templates. Optional if running in a simple mode. Required when operating on
|
-m, --min Minimize output [boolean]
|
||||||
multiple templates. [string]
|
-n, --namespace Template namespace [string] [default: "Handlebars.templates"]
|
||||||
-i, --string Generates a template from the passed CLI argument.
|
-s, --simple Output template function only. [boolean]
|
||||||
"-" is treated as a special value and causes stdin to be read for the template value. [string]
|
-N, --name Name of passed string templates. Optional if running in a simple mode. Required when operating on
|
||||||
-r, --root Template root. Base value that will be stripped from template names. [string]
|
multiple templates. [string]
|
||||||
-p, --partial Compiling a partial template [boolean]
|
-i, --string Generates a template from the passed CLI argument.
|
||||||
-d, --data Include data when compiling [boolean]
|
"-" is treated as a special value and causes stdin to be read for the template value. [string]
|
||||||
-e, --extension Template extension. [string] [default: "handlebars"]
|
-r, --root Template root. Base value that will be stripped from template names. [string]
|
||||||
-b, --bom Removes the BOM (Byte Order Mark) from the beginning of the templates. [boolean]
|
-p, --partial Compiling a partial template [boolean]
|
||||||
-v, --version Prints the current compiler version [boolean]
|
-d, --data Include data when compiling [boolean]
|
||||||
--help Outputs this message [boolean]
|
-e, --extension Template extension. [string] [default: "handlebars"]
|
||||||
|
-b, --bom Removes the BOM (Byte Order Mark) from the beginning of the templates. [boolean]
|
||||||
|
-v, --version Prints the current compiler version [boolean]
|
||||||
|
--help Outputs this message [boolean]
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
define(['handlebars.runtime'], function(Handlebars) {
|
||||||
|
Handlebars = Handlebars["default"]; var template = Handlebars.template, templates = someNameSpace = someNameSpace || {};
|
||||||
|
templates['empty'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "";
|
||||||
|
},"useData":true});
|
||||||
|
templates['empty'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "";
|
||||||
|
},"useData":true});
|
||||||
|
return templates;
|
||||||
|
});
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
define(['handlebars.runtime'], function(Handlebars) {
|
||||||
|
Handlebars = Handlebars["default"]; var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
|
||||||
|
return templates['non.default.extension'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "<div>This is a test</div>";
|
||||||
|
},"useData":true});
|
||||||
|
});
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
define(['handlebars.runtime'], function(Handlebars) {
|
||||||
|
Handlebars = Handlebars["default"]; var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
|
||||||
|
return templates['known.helpers'] = template({"0":function(container,depth0,helpers,partials,data) {
|
||||||
|
var stack1, lookupProperty = container.lookupProperty || function(parent, propertyName) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
|
||||||
|
return parent[propertyName];
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
};
|
||||||
|
return " <div>Some known helper</div>\n"
|
||||||
|
+ ((stack1 = lookupProperty(helpers,"anotherHelper").call(depth0 != null ? depth0 : (container.nullContext || {}),true,{"name":"anotherHelper","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":3,"column":4},"end":{"line":5,"column":22}}})) != null ? stack1 : "");
|
||||||
|
},"1":function(container,depth0,helpers,partials,data) {
|
||||||
|
return " <div>Another known helper</div>\n";
|
||||||
|
},"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
var stack1, lookupProperty = container.lookupProperty || function(parent, propertyName) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
|
||||||
|
return parent[propertyName];
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
};
|
||||||
|
return ((stack1 = lookupProperty(helpers,"someHelper").call(depth0 != null ? depth0 : (container.nullContext || {}),true,{"name":"someHelper","hash":{},"fn":container.program(0, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":1,"column":0},"end":{"line":6,"column":15}}})) != null ? stack1 : "");
|
||||||
|
},"useData":true});
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
define(['handlebars.runtime'], function(Handlebars) {
|
||||||
|
Handlebars = Handlebars["default"]; var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
|
||||||
|
return Handlebars.partials['partial.template'] = template({"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "<div>Test Partial</div>";
|
||||||
|
},"useData":true});
|
||||||
|
});
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
define(["handlebars.runtime"],function(e){var t=(e=e.default).template;return(e.templates=e.templates||{}).test=t({compiler:[8,">= 4.3.0"],main:function(e,t,a,n,i){return"<div>1</div>"},useData:!0})});
|
||||||
|
//# sourceMappingURL=./spec/tmp/source.map.amd.txt
|
||||||
+114
-25
@@ -1,19 +1,15 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import Handlebars from '../lib/index.js';
|
|
||||||
import * as Precompiler from '../lib/precompiler.js';
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import uglify from 'uglify-js';
|
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
||||||
|
|
||||||
describe('precompiler', function () {
|
describe('precompiler', function () {
|
||||||
// NOP Under non-node environments
|
// NOP Under non-node environments
|
||||||
if (typeof process === 'undefined') {
|
if (typeof process === 'undefined') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Handlebars = require('../lib'),
|
||||||
|
Precompiler = require('../dist/cjs/precompiler'),
|
||||||
|
fs = require('fs'),
|
||||||
|
uglify = require('uglify-js');
|
||||||
|
|
||||||
var log,
|
var log,
|
||||||
logFunction,
|
logFunction,
|
||||||
errorLog,
|
errorLog,
|
||||||
@@ -29,6 +25,34 @@ describe('precompiler', function () {
|
|||||||
content,
|
content,
|
||||||
writeFileSync;
|
writeFileSync;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock the Module.prototype.require-function such that an error is thrown, when "uglify-js" is loaded.
|
||||||
|
*
|
||||||
|
* The function cleans up its mess when "callback" is finished
|
||||||
|
*
|
||||||
|
* @param {Error} loadError the error that should be thrown if uglify is loaded
|
||||||
|
* @param {function} callback a callback-function to run when the mock is active.
|
||||||
|
*/
|
||||||
|
async function mockRequireUglify(loadError, callback) {
|
||||||
|
var Module = require('module');
|
||||||
|
var _resolveFilename = Module._resolveFilename;
|
||||||
|
delete require.cache[require.resolve('uglify-js')];
|
||||||
|
delete require.cache[require.resolve('../dist/cjs/precompiler')];
|
||||||
|
Module._resolveFilename = function (request, mod) {
|
||||||
|
if (request === 'uglify-js') {
|
||||||
|
throw loadError;
|
||||||
|
}
|
||||||
|
return _resolveFilename.call(this, request, mod);
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
await callback();
|
||||||
|
} finally {
|
||||||
|
Module._resolveFilename = _resolveFilename;
|
||||||
|
delete require.cache[require.resolve('uglify-js')];
|
||||||
|
delete require.cache[require.resolve('../dist/cjs/precompiler')];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
precompile = Handlebars.precompile;
|
precompile = Handlebars.precompile;
|
||||||
minify = uglify.minify;
|
minify = uglify.minify;
|
||||||
@@ -93,10 +117,7 @@ describe('precompiler', function () {
|
|||||||
});
|
});
|
||||||
it('should throw when missing name', async function () {
|
it('should throw when missing name', async function () {
|
||||||
await expect(
|
await expect(
|
||||||
Precompiler.cli({
|
Precompiler.cli({ templates: [{ source: '' }], amd: true })
|
||||||
templates: [{ source: '' }, { source: '' }],
|
|
||||||
hasDirectory: true,
|
|
||||||
})
|
|
||||||
).rejects.toThrow('Name missing for template');
|
).rejects.toThrow('Name missing for template');
|
||||||
});
|
});
|
||||||
it('should throw when combining simple and directories', async function () {
|
it('should throw when combining simple and directories', async function () {
|
||||||
@@ -119,14 +140,56 @@ describe('precompiler', function () {
|
|||||||
await Precompiler.cli({ templates: [{ source: '' }] });
|
await Precompiler.cli({ templates: [{ source: '' }] });
|
||||||
expect(log).toBe('simple\n');
|
expect(log).toBe('simple\n');
|
||||||
});
|
});
|
||||||
|
it('should output amd templates', async function () {
|
||||||
it('should output wrapped templates', async function () {
|
|
||||||
Handlebars.precompile = function () {
|
Handlebars.precompile = function () {
|
||||||
return 'wrapped';
|
return 'amd';
|
||||||
};
|
};
|
||||||
await Precompiler.cli({ templates: [emptyTemplate] });
|
await Precompiler.cli({ templates: [emptyTemplate], amd: true });
|
||||||
expect(log).toMatch(/template\(wrapped\)/);
|
expect(log).toMatch(/template\(amd\)/);
|
||||||
expect(log).toMatch(/\(function\(\)/);
|
});
|
||||||
|
it('should output multiple amd', async function () {
|
||||||
|
Handlebars.precompile = function () {
|
||||||
|
return 'amd';
|
||||||
|
};
|
||||||
|
await Precompiler.cli({
|
||||||
|
templates: [emptyTemplate, emptyTemplate],
|
||||||
|
amd: true,
|
||||||
|
namespace: 'foo',
|
||||||
|
});
|
||||||
|
expect(log).toMatch(/templates = foo = foo \|\|/);
|
||||||
|
expect(log).toMatch(/return templates/);
|
||||||
|
expect(log).toMatch(/template\(amd\)/);
|
||||||
|
});
|
||||||
|
it('should output amd partials', async function () {
|
||||||
|
Handlebars.precompile = function () {
|
||||||
|
return 'amd';
|
||||||
|
};
|
||||||
|
await Precompiler.cli({
|
||||||
|
templates: [emptyTemplate],
|
||||||
|
amd: true,
|
||||||
|
partial: true,
|
||||||
|
});
|
||||||
|
expect(log).toMatch(/return Handlebars\.partials\['empty'\]/);
|
||||||
|
expect(log).toMatch(/template\(amd\)/);
|
||||||
|
});
|
||||||
|
it('should output multiple amd partials', async function () {
|
||||||
|
Handlebars.precompile = function () {
|
||||||
|
return 'amd';
|
||||||
|
};
|
||||||
|
await Precompiler.cli({
|
||||||
|
templates: [emptyTemplate, emptyTemplate],
|
||||||
|
amd: true,
|
||||||
|
partial: true,
|
||||||
|
});
|
||||||
|
expect(log).not.toMatch(/return Handlebars\.partials\[/);
|
||||||
|
expect(log).toMatch(/template\(amd\)/);
|
||||||
|
});
|
||||||
|
it('should output commonjs templates', async function () {
|
||||||
|
Handlebars.precompile = function () {
|
||||||
|
return 'commonjs';
|
||||||
|
};
|
||||||
|
await Precompiler.cli({ templates: [emptyTemplate], commonjs: true });
|
||||||
|
expect(log).toMatch(/template\(commonjs\)/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set data flag', async function () {
|
it('should set data flag', async function () {
|
||||||
@@ -170,7 +233,7 @@ describe('precompiler', function () {
|
|||||||
|
|
||||||
it('should output minimized templates', async function () {
|
it('should output minimized templates', async function () {
|
||||||
Handlebars.precompile = function () {
|
Handlebars.precompile = function () {
|
||||||
return 'iife';
|
return 'amd';
|
||||||
};
|
};
|
||||||
uglify.minify = function () {
|
uglify.minify = function () {
|
||||||
return { code: 'min' };
|
return { code: 'min' };
|
||||||
@@ -179,6 +242,33 @@ describe('precompiler', function () {
|
|||||||
expect(log).toBe('min');
|
expect(log).toBe('min');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should omit minimization gracefully, if uglify-js is missing', async function () {
|
||||||
|
var error = new Error("Cannot find module 'uglify-js'");
|
||||||
|
error.code = 'MODULE_NOT_FOUND';
|
||||||
|
await mockRequireUglify(error, async function () {
|
||||||
|
var Precompiler = require('../dist/cjs/precompiler');
|
||||||
|
Handlebars.precompile = function () {
|
||||||
|
return 'amd';
|
||||||
|
};
|
||||||
|
await Precompiler.cli({ templates: [emptyTemplate], min: true });
|
||||||
|
expect(log).toMatch(/template\(amd\)/);
|
||||||
|
expect(log).toMatch(/\n/);
|
||||||
|
expect(errorLog).toMatch(/Code minimization is disabled/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail on errors (other than missing module) while loading uglify-js', async function () {
|
||||||
|
await mockRequireUglify(new Error('Mock Error'), async function () {
|
||||||
|
var Precompiler = require('../dist/cjs/precompiler');
|
||||||
|
Handlebars.precompile = function () {
|
||||||
|
return 'amd';
|
||||||
|
};
|
||||||
|
await expect(
|
||||||
|
Precompiler.cli({ templates: [emptyTemplate], min: true })
|
||||||
|
).rejects.toThrow('Mock Error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should output map', async function () {
|
it('should output map', async function () {
|
||||||
await Precompiler.cli({ templates: [emptyTemplate], map: 'foo.js.map' });
|
await Precompiler.cli({ templates: [emptyTemplate], map: 'foo.js.map' });
|
||||||
|
|
||||||
@@ -277,12 +367,11 @@ describe('precompiler', function () {
|
|||||||
expect(opts.templates[1].source).toBe('bar');
|
expect(opts.templates[1].source).toBe('bar');
|
||||||
});
|
});
|
||||||
it('should accept stdin input', async function () {
|
it('should accept stdin input', async function () {
|
||||||
var { stdin } = await import('mock-stdin');
|
var stdin = require('mock-stdin').stdin();
|
||||||
var stdinMock = stdin();
|
|
||||||
var promise = loadTemplatesAsync({ string: '-' });
|
var promise = loadTemplatesAsync({ string: '-' });
|
||||||
stdinMock.send('fo');
|
stdin.send('fo');
|
||||||
stdinMock.send('o');
|
stdin.send('o');
|
||||||
stdinMock.end();
|
stdin.end();
|
||||||
var opts = await promise;
|
var opts = await promise;
|
||||||
expect(opts.templates[0].source).toBe('foo');
|
expect(opts.templates[0].source).toBe('foo');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
if (typeof require !== 'undefined' && require.extensions['.handlebars']) {
|
||||||
|
describe('Require', function () {
|
||||||
|
it('Load .handlebars files with require()', function () {
|
||||||
|
var template = require('./artifacts/example_1');
|
||||||
|
expect(template).toBe(require('./artifacts/example_1.handlebars'));
|
||||||
|
|
||||||
|
var expected = 'foo\n';
|
||||||
|
var result = template({ foo: 'foo' });
|
||||||
|
|
||||||
|
expect(result).toBe(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Load .hbs files with require()', function () {
|
||||||
|
var template = require('./artifacts/example_2');
|
||||||
|
expect(template).toBe(require('./artifacts/example_2.hbs'));
|
||||||
|
|
||||||
|
var expected = 'Hello, World!\n';
|
||||||
|
var result = template({ name: 'World' });
|
||||||
|
|
||||||
|
expect(result).toBe(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
+4
-5
@@ -1,9 +1,8 @@
|
|||||||
import { createRequire } from 'module';
|
|
||||||
|
|
||||||
var SourceMap, SourceMapConsumer;
|
|
||||||
try {
|
try {
|
||||||
SourceMap = createRequire(import.meta.url)('source-map');
|
if (typeof define !== 'function' || !define.amd) {
|
||||||
SourceMapConsumer = SourceMap.SourceMapConsumer;
|
var SourceMap = require('source-map'),
|
||||||
|
SourceMapConsumer = SourceMap.SourceMapConsumer;
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
/* NOP for in browser */
|
/* NOP for in browser */
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -1,20 +1,16 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import path from 'path';
|
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
||||||
|
|
||||||
describe('spec', function () {
|
describe('spec', function () {
|
||||||
// NOP Under non-node environments
|
// NOP Under non-node environments
|
||||||
if (typeof process === 'undefined') {
|
if (typeof process === 'undefined') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
var specDir = __dirname + '/mustache/specs/';
|
var specDir = __dirname + '/mustache/specs/';
|
||||||
var specs = fs.readdirSync(specDir).filter((name) => /.*\.json$/.test(name));
|
var specs = fs.readdirSync(specDir).filter((name) => /.*\.json$/.test(name));
|
||||||
|
|
||||||
specs.forEach(function (name) {
|
specs.forEach(function (name) {
|
||||||
var spec = JSON.parse(fs.readFileSync(specDir + name, 'utf8'));
|
var spec = require(specDir + name);
|
||||||
spec.tests.forEach(function (test) {
|
spec.tests.forEach(function (test) {
|
||||||
// Our lambda implementation knowingly deviates from the optional Mustache lambda spec
|
// Our lambda implementation knowingly deviates from the optional Mustache lambda spec
|
||||||
// We also do not support alternative delimiters
|
// We also do not support alternative delimiters
|
||||||
|
|||||||
@@ -121,63 +121,6 @@ describe('strict', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('strict and compat mode', function () {
|
|
||||||
it('GH-1741: should render a simple variable', function () {
|
|
||||||
expectTemplate('{{v}}')
|
|
||||||
.withCompileOptions({ strict: true, compat: true })
|
|
||||||
.withInput({ v: 'a' })
|
|
||||||
.toCompileTo('a');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw for a missing variable', function () {
|
|
||||||
expectTemplate('{{v}}')
|
|
||||||
.withCompileOptions({ strict: true, compat: true })
|
|
||||||
.toThrow(Exception, /"v" not defined in/);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('GH-2149: should render correctly when block context is a boolean', function () {
|
|
||||||
expectTemplate('{{#foo}}Hello {{bar}}{{/foo}}')
|
|
||||||
.withCompileOptions({ strict: true, compat: true })
|
|
||||||
.withInput({ foo: true, bar: 'World' })
|
|
||||||
.toCompileTo('Hello World');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('GH-2149: should render correctly when looking up a property on each item', function () {
|
|
||||||
expectTemplate('{{#each items}}{{name}}{{/each}}')
|
|
||||||
.withCompileOptions({ strict: true, compat: true })
|
|
||||||
.withInput({ items: [{ name: 'Hello' }] })
|
|
||||||
.toCompileTo('Hello');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should still throw when a property is missing at all depths', function () {
|
|
||||||
expectTemplate('{{#each items}}{{name}}{{/each}}')
|
|
||||||
.withCompileOptions({ strict: true, compat: true })
|
|
||||||
.withInput({ items: [1, 2] })
|
|
||||||
.toThrow(Exception, /"name" not defined in/);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should still perform recursive lookup when a property is not in the current context', function () {
|
|
||||||
expectTemplate('{{#each items}}{{name}}{{/each}}')
|
|
||||||
.withCompileOptions({ strict: true, compat: true })
|
|
||||||
.withInput({ name: 'root', items: [{}] })
|
|
||||||
.toCompileTo('root');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should still perform recursive lookup with a multi-part path not in context', function () {
|
|
||||||
expectTemplate('{{#with child}}{{name.first}}{{/with}}')
|
|
||||||
.withCompileOptions({ strict: true, compat: true })
|
|
||||||
.withInput({ name: { first: 'root' }, child: { name: null } })
|
|
||||||
.toCompileTo('root');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should directly return an explicitly null property', function () {
|
|
||||||
expectTemplate('{{#each items}}{{name}}{{/each}}')
|
|
||||||
.withCompileOptions({ strict: true, compat: true })
|
|
||||||
.withInput({ name: 'root', items: [{ name: null }] })
|
|
||||||
.toCompileTo('');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('assume objects', function () {
|
describe('assume objects', function () {
|
||||||
it('should ignore missing property', function () {
|
it('should ignore missing property', function () {
|
||||||
expectTemplate('{{hello}}')
|
expectTemplate('{{hello}}')
|
||||||
|
|||||||
@@ -0,0 +1,796 @@
|
|||||||
|
function shouldMatchTokens(result, tokens) {
|
||||||
|
for (var index = 0; index < result.length; index++) {
|
||||||
|
expect(result[index].name).toBe(tokens[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function shouldBeToken(result, name, text) {
|
||||||
|
expect(result.name).toBe(name);
|
||||||
|
expect(result.text).toBe(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Tokenizer', function () {
|
||||||
|
if (!Handlebars.Parser) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenize(template) {
|
||||||
|
var parser = Handlebars.Parser,
|
||||||
|
lexer = parser.lexer;
|
||||||
|
|
||||||
|
lexer.setInput(template);
|
||||||
|
var out = [],
|
||||||
|
token;
|
||||||
|
|
||||||
|
while ((token = lexer.lex())) {
|
||||||
|
var result = parser.terminals_[token] || token;
|
||||||
|
if (!result || result === 'EOF' || result === 'INVALID') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out.push({ name: result, text: lexer.yytext });
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
it('tokenizes a simple mustache as "OPEN ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{foo}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'CLOSE']);
|
||||||
|
shouldBeToken(result[1], 'ID', 'foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports unescaping with &', function () {
|
||||||
|
var result = tokenize('{{&bar}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'CLOSE']);
|
||||||
|
|
||||||
|
shouldBeToken(result[0], 'OPEN', '{{&');
|
||||||
|
shouldBeToken(result[1], 'ID', 'bar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports unescaping with {{{', function () {
|
||||||
|
var result = tokenize('{{{bar}}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN_UNESCAPED', 'ID', 'CLOSE_UNESCAPED']);
|
||||||
|
|
||||||
|
shouldBeToken(result[1], 'ID', 'bar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports escaping delimiters', function () {
|
||||||
|
var result = tokenize('{{foo}} \\{{bar}} {{baz}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
shouldBeToken(result[3], 'CONTENT', ' ');
|
||||||
|
shouldBeToken(result[4], 'CONTENT', '{{bar}} ');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports escaping multiple delimiters', function () {
|
||||||
|
var result = tokenize('{{foo}} \\{{bar}} \\{{baz}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'CONTENT',
|
||||||
|
'CONTENT',
|
||||||
|
]);
|
||||||
|
|
||||||
|
shouldBeToken(result[3], 'CONTENT', ' ');
|
||||||
|
shouldBeToken(result[4], 'CONTENT', '{{bar}} ');
|
||||||
|
shouldBeToken(result[5], 'CONTENT', '{{baz}}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports escaping a triple stash', function () {
|
||||||
|
var result = tokenize('{{foo}} \\{{{bar}}} {{baz}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
shouldBeToken(result[4], 'CONTENT', '{{{bar}}} ');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports escaping escape character', function () {
|
||||||
|
var result = tokenize('{{foo}} \\\\{{bar}} {{baz}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
shouldBeToken(result[3], 'CONTENT', ' \\');
|
||||||
|
shouldBeToken(result[5], 'ID', 'bar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports escaping multiple escape characters', function () {
|
||||||
|
var result = tokenize('{{foo}} \\\\{{bar}} \\\\{{baz}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
shouldBeToken(result[3], 'CONTENT', ' \\');
|
||||||
|
shouldBeToken(result[5], 'ID', 'bar');
|
||||||
|
shouldBeToken(result[7], 'CONTENT', ' \\');
|
||||||
|
shouldBeToken(result[9], 'ID', 'baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports escaped mustaches after escaped escape characters', function () {
|
||||||
|
var result = tokenize('{{foo}} \\\\{{bar}} \\{{baz}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'CONTENT',
|
||||||
|
'CONTENT',
|
||||||
|
]);
|
||||||
|
|
||||||
|
shouldBeToken(result[3], 'CONTENT', ' \\');
|
||||||
|
shouldBeToken(result[4], 'OPEN', '{{');
|
||||||
|
shouldBeToken(result[5], 'ID', 'bar');
|
||||||
|
shouldBeToken(result[7], 'CONTENT', ' ');
|
||||||
|
shouldBeToken(result[8], 'CONTENT', '{{baz}}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports escaped escape characters after escaped mustaches', function () {
|
||||||
|
var result = tokenize('{{foo}} \\{{bar}} \\\\{{baz}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'CONTENT',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
shouldBeToken(result[4], 'CONTENT', '{{bar}} ');
|
||||||
|
shouldBeToken(result[5], 'CONTENT', '\\');
|
||||||
|
shouldBeToken(result[6], 'OPEN', '{{');
|
||||||
|
shouldBeToken(result[7], 'ID', 'baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supports escaped escape character on a triple stash', function () {
|
||||||
|
var result = tokenize('{{foo}} \\\\{{{bar}}} {{baz}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN_UNESCAPED',
|
||||||
|
'ID',
|
||||||
|
'CLOSE_UNESCAPED',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
shouldBeToken(result[3], 'CONTENT', ' \\');
|
||||||
|
shouldBeToken(result[5], 'ID', 'bar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a simple path', function () {
|
||||||
|
var result = tokenize('{{foo/bar}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'SEP', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows dot notation', function () {
|
||||||
|
var result = tokenize('{{foo.bar}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'SEP', 'ID', 'CLOSE']);
|
||||||
|
|
||||||
|
shouldMatchTokens(tokenize('{{foo.bar.baz}}'), [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows path literals with []', function () {
|
||||||
|
var result = tokenize('{{foo.[bar]}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'SEP', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows multiple path literals on a line with []', function () {
|
||||||
|
var result = tokenize('{{foo.[bar]}}{{foo.[baz]}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows escaped literals in []', function () {
|
||||||
|
var result = tokenize('{{foo.[bar\\]]}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'SEP', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes {{.}} as OPEN ID CLOSE', function () {
|
||||||
|
var result = tokenize('{{.}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a path as "OPEN (ID SEP)* ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{../foo/bar}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[1], 'ID', '..');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a path with .. as a parent path', function () {
|
||||||
|
var result = tokenize('{{../foo.bar}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[1], 'ID', '..');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a path with this/foo as OPEN ID SEP ID CLOSE', function () {
|
||||||
|
var result = tokenize('{{this/foo}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'SEP', 'ID', 'CLOSE']);
|
||||||
|
shouldBeToken(result[1], 'ID', 'this');
|
||||||
|
shouldBeToken(result[3], 'ID', 'foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a simple mustache with spaces as "OPEN ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{ foo }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'CLOSE']);
|
||||||
|
shouldBeToken(result[1], 'ID', 'foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a simple mustache with line breaks as "OPEN ID ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{ foo \n bar }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'CLOSE']);
|
||||||
|
shouldBeToken(result[1], 'ID', 'foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes raw content as "CONTENT"', function () {
|
||||||
|
var result = tokenize('foo {{ bar }} baz');
|
||||||
|
shouldMatchTokens(result, ['CONTENT', 'OPEN', 'ID', 'CLOSE', 'CONTENT']);
|
||||||
|
shouldBeToken(result[0], 'CONTENT', 'foo ');
|
||||||
|
shouldBeToken(result[4], 'CONTENT', ' baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a partial as "OPEN_PARTIAL ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{> foo}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN_PARTIAL', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a partial with context as "OPEN_PARTIAL ID ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{> foo bar }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN_PARTIAL', 'ID', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a partial without spaces as "OPEN_PARTIAL ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{>foo}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN_PARTIAL', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a partial space at the }); as "OPEN_PARTIAL ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{>foo }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN_PARTIAL', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a partial space at the }); as "OPEN_PARTIAL ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{>foo/bar.baz }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN_PARTIAL',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'SEP',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes partial block declarations', function () {
|
||||||
|
var result = tokenize('{{#> foo}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN_PARTIAL_BLOCK', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
it('tokenizes a comment as "COMMENT"', function () {
|
||||||
|
var result = tokenize('foo {{! this is a comment }} bar {{ baz }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'CONTENT',
|
||||||
|
'COMMENT',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[1], 'COMMENT', '{{! this is a comment }}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a block comment as "COMMENT"', function () {
|
||||||
|
var result = tokenize('foo {{!-- this is a {{comment}} --}} bar {{ baz }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'CONTENT',
|
||||||
|
'COMMENT',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[1], 'COMMENT', '{{!-- this is a {{comment}} --}}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes a block comment with whitespace as "COMMENT"', function () {
|
||||||
|
var result = tokenize(
|
||||||
|
'foo {{!-- this is a\n{{comment}}\n--}} bar {{ baz }}'
|
||||||
|
);
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'CONTENT',
|
||||||
|
'COMMENT',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[1], 'COMMENT', '{{!-- this is a\n{{comment}}\n--}}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes open and closing blocks as OPEN_BLOCK, ID, CLOSE ..., OPEN_ENDBLOCK ID CLOSE', function () {
|
||||||
|
var result = tokenize('{{#foo}}content{{/foo}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN_BLOCK',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN_ENDBLOCK',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes directives', function () {
|
||||||
|
shouldMatchTokens(tokenize('{{#*foo}}content{{/foo}}'), [
|
||||||
|
'OPEN_BLOCK',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
'CONTENT',
|
||||||
|
'OPEN_ENDBLOCK',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldMatchTokens(tokenize('{{*foo}}'), ['OPEN', 'ID', 'CLOSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes inverse sections as "INVERSE"', function () {
|
||||||
|
shouldMatchTokens(tokenize('{{^}}'), ['INVERSE']);
|
||||||
|
shouldMatchTokens(tokenize('{{else}}'), ['INVERSE']);
|
||||||
|
shouldMatchTokens(tokenize('{{ else }}'), ['INVERSE']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes inverse sections with ID as "OPEN_INVERSE ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{^foo}}');
|
||||||
|
shouldMatchTokens(result, ['OPEN_INVERSE', 'ID', 'CLOSE']);
|
||||||
|
shouldBeToken(result[1], 'ID', 'foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes inverse sections with ID and spaces as "OPEN_INVERSE ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{^ foo }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN_INVERSE', 'ID', 'CLOSE']);
|
||||||
|
shouldBeToken(result[1], 'ID', 'foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes mustaches with params as "OPEN ID ID ID CLOSE"', function () {
|
||||||
|
var result = tokenize('{{ foo bar baz }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'ID', 'CLOSE']);
|
||||||
|
shouldBeToken(result[1], 'ID', 'foo');
|
||||||
|
shouldBeToken(result[2], 'ID', 'bar');
|
||||||
|
shouldBeToken(result[3], 'ID', 'baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes mustaches with String params as "OPEN ID ID STRING CLOSE"', function () {
|
||||||
|
var result = tokenize('{{ foo bar "baz" }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'STRING', 'CLOSE']);
|
||||||
|
shouldBeToken(result[3], 'STRING', 'baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes mustaches with String params using single quotes as "OPEN ID ID STRING CLOSE"', function () {
|
||||||
|
var result = tokenize("{{ foo bar 'baz' }}");
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'STRING', 'CLOSE']);
|
||||||
|
shouldBeToken(result[3], 'STRING', 'baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes String params with spaces inside as "STRING"', function () {
|
||||||
|
var result = tokenize('{{ foo bar "baz bat" }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'STRING', 'CLOSE']);
|
||||||
|
shouldBeToken(result[3], 'STRING', 'baz bat');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes String params with escapes quotes as STRING', function () {
|
||||||
|
var result = tokenize('{{ foo "bar\\"baz" }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'STRING', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'STRING', 'bar"baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes String params using single quotes with escapes quotes as STRING', function () {
|
||||||
|
var result = tokenize("{{ foo 'bar\\'baz' }}");
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'STRING', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'STRING', "bar'baz");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes numbers', function () {
|
||||||
|
var result = tokenize('{{ foo 1 }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'NUMBER', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'NUMBER', '1');
|
||||||
|
|
||||||
|
result = tokenize('{{ foo 1.1 }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'NUMBER', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'NUMBER', '1.1');
|
||||||
|
|
||||||
|
result = tokenize('{{ foo -1 }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'NUMBER', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'NUMBER', '-1');
|
||||||
|
|
||||||
|
result = tokenize('{{ foo -1.1 }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'NUMBER', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'NUMBER', '-1.1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes booleans', function () {
|
||||||
|
var result = tokenize('{{ foo true }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'BOOLEAN', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'BOOLEAN', 'true');
|
||||||
|
|
||||||
|
result = tokenize('{{ foo false }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'BOOLEAN', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'BOOLEAN', 'false');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes undefined and null', function () {
|
||||||
|
var result = tokenize('{{ foo undefined null }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'UNDEFINED', 'NULL', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'UNDEFINED', 'undefined');
|
||||||
|
shouldBeToken(result[3], 'NULL', 'null');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes hash arguments', function () {
|
||||||
|
var result = tokenize('{{ foo bar=baz }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'EQUALS', 'ID', 'CLOSE']);
|
||||||
|
|
||||||
|
result = tokenize('{{ foo bar baz=bat }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{ foo bar baz=1 }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'NUMBER',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{ foo bar baz=true }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'BOOLEAN',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{ foo bar baz=false }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'BOOLEAN',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{ foo bar\n baz=bat }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{ foo bar baz="bat" }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'STRING',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{ foo bar baz="bat" bam=wot }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'STRING',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{foo omg bar=baz bat="bam"}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'STRING',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[2], 'ID', 'omg');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes special @ identifiers', function () {
|
||||||
|
var result = tokenize('{{ @foo }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'DATA', 'ID', 'CLOSE']);
|
||||||
|
shouldBeToken(result[2], 'ID', 'foo');
|
||||||
|
|
||||||
|
result = tokenize('{{ foo @bar }}');
|
||||||
|
shouldMatchTokens(result, ['OPEN', 'ID', 'DATA', 'ID', 'CLOSE']);
|
||||||
|
shouldBeToken(result[3], 'ID', 'bar');
|
||||||
|
|
||||||
|
result = tokenize('{{ foo bar=@baz }}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'EQUALS',
|
||||||
|
'DATA',
|
||||||
|
'ID',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[5], 'ID', 'baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not time out in a mustache with a single } followed by EOF', function () {
|
||||||
|
shouldMatchTokens(tokenize('{{foo}'), ['OPEN', 'ID']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not time out in a mustache when invalid ID characters are used', function () {
|
||||||
|
shouldMatchTokens(tokenize('{{foo & }}'), ['OPEN', 'ID']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes subexpressions', function () {
|
||||||
|
var result = tokenize('{{foo (bar)}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[1], 'ID', 'foo');
|
||||||
|
shouldBeToken(result[3], 'ID', 'bar');
|
||||||
|
|
||||||
|
result = tokenize('{{foo (a-x b-y)}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[1], 'ID', 'foo');
|
||||||
|
shouldBeToken(result[3], 'ID', 'a-x');
|
||||||
|
shouldBeToken(result[4], 'ID', 'b-y');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes nested subexpressions', function () {
|
||||||
|
var result = tokenize('{{foo (bar (lol rofl)) (baz)}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
shouldBeToken(result[3], 'ID', 'bar');
|
||||||
|
shouldBeToken(result[5], 'ID', 'lol');
|
||||||
|
shouldBeToken(result[6], 'ID', 'rofl');
|
||||||
|
shouldBeToken(result[10], 'ID', 'baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes nested subexpressions: literals', function () {
|
||||||
|
var result = tokenize(
|
||||||
|
'{{foo (bar (lol true) false) (baz 1) (blah \'b\') (blorg "c")}}'
|
||||||
|
);
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN',
|
||||||
|
'ID',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'BOOLEAN',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'BOOLEAN',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'NUMBER',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'STRING',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'OPEN_SEXPR',
|
||||||
|
'ID',
|
||||||
|
'STRING',
|
||||||
|
'CLOSE_SEXPR',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tokenizes block params', function () {
|
||||||
|
var result = tokenize('{{#foo as |bar|}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN_BLOCK',
|
||||||
|
'ID',
|
||||||
|
'OPEN_BLOCK_PARAMS',
|
||||||
|
'ID',
|
||||||
|
'CLOSE_BLOCK_PARAMS',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{#foo as |bar baz|}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN_BLOCK',
|
||||||
|
'ID',
|
||||||
|
'OPEN_BLOCK_PARAMS',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'CLOSE_BLOCK_PARAMS',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{#foo as | bar baz |}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN_BLOCK',
|
||||||
|
'ID',
|
||||||
|
'OPEN_BLOCK_PARAMS',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'CLOSE_BLOCK_PARAMS',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
result = tokenize('{{#foo as as | bar baz |}}');
|
||||||
|
shouldMatchTokens(result, [
|
||||||
|
'OPEN_BLOCK',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'OPEN_BLOCK_PARAMS',
|
||||||
|
'ID',
|
||||||
|
'ID',
|
||||||
|
'CLOSE_BLOCK_PARAMS',
|
||||||
|
'CLOSE',
|
||||||
|
]);
|
||||||
|
|
||||||
|
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',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Handlebars Runtime UMD Smoke Test</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Handlebars Runtime UMD Smoke Test</h1>
|
||||||
|
<pre id="results"></pre>
|
||||||
|
<script src="/spec/vendor/require.js"></script>
|
||||||
|
<script>
|
||||||
|
var results = document.getElementById('results');
|
||||||
|
var failures = 0;
|
||||||
|
var tests = 0;
|
||||||
|
|
||||||
|
function assert(condition, message) {
|
||||||
|
tests++;
|
||||||
|
if (!condition) {
|
||||||
|
failures++;
|
||||||
|
results.textContent += 'FAIL: ' + message + '\n';
|
||||||
|
} else {
|
||||||
|
results.textContent += 'PASS: ' + message + '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requirejs.config({
|
||||||
|
paths: {
|
||||||
|
'handlebars.runtime': '/dist/handlebars.runtime',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
require(['handlebars.runtime'], function (Handlebars) {
|
||||||
|
try {
|
||||||
|
assert(
|
||||||
|
typeof Handlebars !== 'undefined',
|
||||||
|
'Handlebars runtime loaded via RequireJS'
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
typeof Handlebars.template === 'function',
|
||||||
|
'Handlebars.template exists'
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
typeof Handlebars.VERSION === 'string',
|
||||||
|
'Handlebars.VERSION exists'
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
failures++;
|
||||||
|
results.textContent += 'ERROR: ' + e.message + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
results.textContent +=
|
||||||
|
'\n' + tests + ' tests, ' + failures + ' failures\n';
|
||||||
|
window.mochaResults = { passes: tests - failures, failures: failures };
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Handlebars UMD Module Smoke Test</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Handlebars UMD Module Smoke Test</h1>
|
||||||
|
<pre id="results"></pre>
|
||||||
|
<script src="/spec/vendor/require.js"></script>
|
||||||
|
<script>
|
||||||
|
var results = document.getElementById('results');
|
||||||
|
var failures = 0;
|
||||||
|
var tests = 0;
|
||||||
|
|
||||||
|
function assert(condition, message) {
|
||||||
|
tests++;
|
||||||
|
if (!condition) {
|
||||||
|
failures++;
|
||||||
|
results.textContent += 'FAIL: ' + message + '\n';
|
||||||
|
} else {
|
||||||
|
results.textContent += 'PASS: ' + message + '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requirejs.config({
|
||||||
|
paths: {
|
||||||
|
handlebars: '/dist/handlebars',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
require(['handlebars'], function (Handlebars) {
|
||||||
|
try {
|
||||||
|
assert(
|
||||||
|
typeof Handlebars !== 'undefined',
|
||||||
|
'Handlebars loaded via RequireJS'
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
typeof Handlebars.compile === 'function',
|
||||||
|
'Handlebars.compile exists'
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
typeof Handlebars.template === 'function',
|
||||||
|
'Handlebars.template exists'
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
typeof Handlebars.VERSION === 'string',
|
||||||
|
'Handlebars.VERSION exists'
|
||||||
|
);
|
||||||
|
|
||||||
|
var template = Handlebars.compile('Hello {{name}}!');
|
||||||
|
var output = template({ name: 'UMD' });
|
||||||
|
assert(output === 'Hello UMD!', 'Basic compilation works: ' + output);
|
||||||
|
} catch (e) {
|
||||||
|
failures++;
|
||||||
|
results.textContent += 'ERROR: ' + e.message + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
results.textContent +=
|
||||||
|
'\n' + tests + ' tests, ' + failures + ' failures\n';
|
||||||
|
window.mochaResults = { passes: tests - failures, failures: failures };
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Vendored
+2054
File diff suppressed because it is too large
Load Diff
+19
-12
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import fs from 'fs';
|
const fs = require('fs');
|
||||||
import { S3, PutObjectCommand } from '@aws-sdk/client-s3';
|
const { S3, PutObjectCommand } = require('@aws-sdk/client-s3');
|
||||||
import * as git from './util/git.js';
|
const git = require('./util/git');
|
||||||
import semver from 'semver';
|
const semver = require('semver');
|
||||||
|
|
||||||
export const PUBLISHED_FILES = [
|
const PUBLISHED_FILES = [
|
||||||
'handlebars.js',
|
'handlebars.js',
|
||||||
'handlebars.min.js',
|
'handlebars.min.js',
|
||||||
'handlebars.runtime.js',
|
'handlebars.runtime.js',
|
||||||
@@ -29,7 +29,7 @@ async function main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildSuffixes(commitInfo) {
|
function buildSuffixes(commitInfo) {
|
||||||
const suffixes = [];
|
const suffixes = [];
|
||||||
|
|
||||||
if (commitInfo.isMaster) {
|
if (commitInfo.isMaster) {
|
||||||
@@ -44,7 +44,7 @@ export function buildSuffixes(commitInfo) {
|
|||||||
return suffixes;
|
return suffixes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateS3Env() {
|
function validateS3Env() {
|
||||||
const bucket = process.env.S3_BUCKET_NAME,
|
const bucket = process.env.S3_BUCKET_NAME,
|
||||||
region = process.env.S3_REGION,
|
region = process.env.S3_REGION,
|
||||||
key = process.env.S3_ACCESS_KEY_ID,
|
key = process.env.S3_ACCESS_KEY_ID,
|
||||||
@@ -55,7 +55,7 @@ export function validateS3Env() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function publish(suffixes, overrides) {
|
async function publish(suffixes, overrides) {
|
||||||
const publishPromises = suffixes.map((suffix) =>
|
const publishPromises = suffixes.map((suffix) =>
|
||||||
publishSuffix(suffix, overrides)
|
publishSuffix(suffix, overrides)
|
||||||
);
|
);
|
||||||
@@ -98,17 +98,24 @@ function getS3Client() {
|
|||||||
return s3Client;
|
return s3Client;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNameInBucket(filename, suffix) {
|
function getNameInBucket(filename, suffix) {
|
||||||
return filename.replace(/\.js$/, suffix + '.js');
|
return filename.replace(/\.js$/, suffix + '.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLocalFile(filename) {
|
function getLocalFile(filename) {
|
||||||
return 'dist/' + filename;
|
return 'dist/' + filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
import { fileURLToPath } from 'url';
|
module.exports = {
|
||||||
|
PUBLISHED_FILES,
|
||||||
|
buildSuffixes,
|
||||||
|
validateS3Env,
|
||||||
|
publish,
|
||||||
|
getNameInBucket,
|
||||||
|
getLocalFile,
|
||||||
|
};
|
||||||
|
|
||||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
if (require.main === module) {
|
||||||
main().catch((err) => {
|
main().catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
+113
-28
@@ -1,9 +1,9 @@
|
|||||||
import fs from 'fs';
|
const fs = require('fs');
|
||||||
import { exec } from 'child_process';
|
const { exec } = require('child_process');
|
||||||
import { execCommand, FileTestHelper } from 'cli-testlab';
|
const { execCommand, FileTestHelper } = require('cli-testlab');
|
||||||
import Handlebars from '../../lib/index.js';
|
const Handlebars = require('../../lib');
|
||||||
|
|
||||||
const cli = 'node ./bin/handlebars.js';
|
const cli = 'node ./bin/handlebars.mjs';
|
||||||
|
|
||||||
expect.extend({
|
expect.extend({
|
||||||
toEqualWithRelaxedSpace(received, expected) {
|
toEqualWithRelaxedSpace(received, expected) {
|
||||||
@@ -58,22 +58,71 @@ describe('bin/handlebars', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('AMD output', function () {
|
||||||
|
it('-a produces AMD output', async function () {
|
||||||
|
const result = await execCommand(
|
||||||
|
`${cli} -a spec/artifacts/empty.handlebars`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/empty.amd.js')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('-a -s produces simple AMD output', async function () {
|
||||||
|
const result = await execCommand(
|
||||||
|
`${cli} -a -s spec/artifacts/empty.handlebars`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/empty.amd.simple.js')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('-a -m produces minified AMD output', async function () {
|
||||||
|
const result = await execCommand(
|
||||||
|
`${cli} -a -m spec/artifacts/empty.handlebars`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/empty.amd.min.js')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('CommonJS output', function () {
|
||||||
|
it('-c produces CommonJS output', async function () {
|
||||||
|
const result = await execCommand(
|
||||||
|
`${cli} spec/artifacts/empty.handlebars -c`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/empty.common.js')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('namespace', function () {
|
describe('namespace', function () {
|
||||||
it('-n sets custom namespace', async function () {
|
it('-n sets custom namespace', async function () {
|
||||||
const result = await execCommand(
|
const result = await execCommand(
|
||||||
`${cli} -n CustomNamespace.templates spec/artifacts/empty.handlebars`
|
`${cli} -a -n CustomNamespace.templates spec/artifacts/empty.handlebars`
|
||||||
);
|
);
|
||||||
expect(result.stdout).toEqualWithRelaxedSpace(
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
expectedFile('./spec/expected/empty.namespace.js')
|
expectedFile('./spec/expected/empty.amd.namespace.js')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('--namespace sets custom namespace', async function () {
|
it('--namespace sets custom namespace', async function () {
|
||||||
const result = await execCommand(
|
const result = await execCommand(
|
||||||
`${cli} --namespace CustomNamespace.templates spec/artifacts/empty.handlebars`
|
`${cli} -a --namespace CustomNamespace.templates spec/artifacts/empty.handlebars`
|
||||||
);
|
);
|
||||||
expect(result.stdout).toEqualWithRelaxedSpace(
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
expectedFile('./spec/expected/empty.namespace.js')
|
expectedFile('./spec/expected/empty.amd.namespace.js')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('multiple files share a namespace', async function () {
|
||||||
|
const result = await execCommand(
|
||||||
|
`${cli} spec/artifacts/empty.handlebars spec/artifacts/empty.handlebars -a -n someNameSpace`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/namespace.amd.js')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -95,12 +144,14 @@ describe('bin/handlebars', function () {
|
|||||||
files.registerForCleanup(outputFile);
|
files.registerForCleanup(outputFile);
|
||||||
|
|
||||||
await execCommand(
|
await execCommand(
|
||||||
`${cli} -f ${outputFile} spec/artifacts/empty.handlebars`
|
`${cli} -a -f ${outputFile} spec/artifacts/empty.handlebars`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(files.fileExists(outputFile)).toBe(true);
|
expect(files.fileExists(outputFile)).toBe(true);
|
||||||
const content = files.getFileTextContent(outputFile);
|
const content = files.getFileTextContent(outputFile);
|
||||||
expect(content).toMatch(/template\(/);
|
expect(content).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/empty.amd.js')
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('--map writes source map and appends sourceMappingURL', async function () {
|
it('--map writes source map and appends sourceMappingURL', async function () {
|
||||||
@@ -108,7 +159,7 @@ describe('bin/handlebars', function () {
|
|||||||
files.registerForCleanup(mapFile);
|
files.registerForCleanup(mapFile);
|
||||||
|
|
||||||
const result = await execCommand(
|
const result = await execCommand(
|
||||||
`${cli} -i "<div>1</div>" -m -N test --map ${mapFile}`
|
`${cli} -i "<div>1</div>" -a -m -N test --map ${mapFile}`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.stdout).toContain('sourceMappingURL=');
|
expect(result.stdout).toContain('sourceMappingURL=');
|
||||||
@@ -123,52 +174,75 @@ describe('bin/handlebars', function () {
|
|||||||
describe('template options', function () {
|
describe('template options', function () {
|
||||||
it('-e sets custom extension', async function () {
|
it('-e sets custom extension', async function () {
|
||||||
const result = await execCommand(
|
const result = await execCommand(
|
||||||
`${cli} -e hbs ./spec/artifacts/non.default.extension.hbs`
|
`${cli} -a -e hbs ./spec/artifacts/non.default.extension.hbs`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/non.default.extension.amd.js')
|
||||||
);
|
);
|
||||||
expect(result.stdout).toMatch(/template\(/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('-p compiles as partial', async function () {
|
it('-p compiles as partial', async function () {
|
||||||
const result = await execCommand(
|
const result = await execCommand(
|
||||||
`${cli} -p ./spec/artifacts/partial.template.handlebars`
|
`${cli} -a -p ./spec/artifacts/partial.template.handlebars`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/partial.template.js')
|
||||||
);
|
);
|
||||||
expect(result.stdout).toMatch(/Handlebars\.partials/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('-r strips root from template names', async function () {
|
it('-r strips root from template names', async function () {
|
||||||
const result = await execCommand(
|
const result = await execCommand(
|
||||||
`${cli} spec/artifacts/partial.template.handlebars -r spec`
|
`${cli} spec/artifacts/partial.template.handlebars -r spec -a`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/empty.root.amd.js')
|
||||||
);
|
);
|
||||||
expect(result.stdout).toMatch(/template\(/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('-b strips BOM', async function () {
|
it('-b strips BOM', async function () {
|
||||||
const result = await execCommand(
|
const result = await execCommand(
|
||||||
`${cli} ./spec/artifacts/bom.handlebars -b`
|
`${cli} ./spec/artifacts/bom.handlebars -b -a`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/bom.amd.js')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('-h sets custom handlebar path', async function () {
|
||||||
|
const result = await execCommand(
|
||||||
|
`${cli} spec/artifacts/empty.handlebars -h some-path/ -a`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/handlebar.path.amd.js')
|
||||||
);
|
);
|
||||||
expect(result.stdout).toMatch(/template\(/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('-k -o sets known helpers only', async function () {
|
it('-k -o sets known helpers only', async function () {
|
||||||
const result = await execCommand(
|
const result = await execCommand(
|
||||||
`${cli} spec/artifacts/known.helpers.handlebars -k someHelper -k anotherHelper -o`
|
`${cli} spec/artifacts/known.helpers.handlebars -a -k someHelper -k anotherHelper -o`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/non.empty.amd.known.helper.js')
|
||||||
);
|
);
|
||||||
expect(result.stdout).toMatch(/template\(/);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('inline templates', function () {
|
describe('inline templates', function () {
|
||||||
it('-i compiles inline template', async function () {
|
it('-i compiles inline template', async function () {
|
||||||
const result = await execCommand(
|
const result = await execCommand(
|
||||||
`${cli} -i "<div>hello</div>" -N myTemplate`
|
`${cli} -i "<div>hello</div>" -a -N myTemplate`
|
||||||
);
|
);
|
||||||
|
expect(result.stdout).toContain("define(['handlebars.runtime']");
|
||||||
expect(result.stdout).toContain("templates['myTemplate']");
|
expect(result.stdout).toContain("templates['myTemplate']");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('-i compiles simple unnamed inline template', async function () {
|
it('-i compiles multiple inline templates with -N', async function () {
|
||||||
const result = await execCommand(`${cli} -i "<div>hello</div>"`);
|
const result = await execCommand(
|
||||||
// Unnamed single template defaults to simple mode
|
`${cli} -i "<div>1</div>" -i "<div>2</div>" -N firstTemplate -N secondTemplate -a`
|
||||||
expect(result.stdout).toMatch(/function/);
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/empty.name.amd.js')
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -176,7 +250,7 @@ describe('bin/handlebars', function () {
|
|||||||
it('should not produce unhandled promise rejections on async errors', async function () {
|
it('should not produce unhandled promise rejections on async errors', async function () {
|
||||||
const { stderr } = await new Promise((resolve) => {
|
const { stderr } = await new Promise((resolve) => {
|
||||||
exec(
|
exec(
|
||||||
`node --unhandled-rejections=warn ./bin/handlebars.js -i "<div>test</div>" -N test --map /nonexistent/dir/test.map`,
|
`node --unhandled-rejections=warn ./bin/handlebars.mjs -i "<div>test</div>" -N test --map /nonexistent/dir/test.map`,
|
||||||
(error, stdout, stderr) => {
|
(error, stdout, stderr) => {
|
||||||
resolve({ exitCode: error ? error.code : 0, stderr });
|
resolve({ exitCode: error ? error.code : 0, stderr });
|
||||||
}
|
}
|
||||||
@@ -186,4 +260,15 @@ describe('bin/handlebars', function () {
|
|||||||
expect(stderr).not.toMatch(/unhandled/i);
|
expect(stderr).not.toMatch(/unhandled/i);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('negated boolean flags', function () {
|
||||||
|
it('--no-amd negates --amd (issue #1673)', async function () {
|
||||||
|
const result = await execCommand(
|
||||||
|
`${cli} --amd --no-amd spec/artifacts/empty.handlebars`
|
||||||
|
);
|
||||||
|
expect(result.stdout).toEqualWithRelaxedSpace(
|
||||||
|
expectedFile('./spec/expected/empty.common.js')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import http from 'http';
|
const http = require('http');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimal in-memory S3-compatible server for testing.
|
* Minimal in-memory S3-compatible server for testing.
|
||||||
* Supports PutObject and GetObject via path-style requests.
|
* Supports PutObject and GetObject via path-style requests.
|
||||||
*/
|
*/
|
||||||
export function createFakeS3() {
|
function createFakeS3() {
|
||||||
const buckets = new Map();
|
const buckets = new Map();
|
||||||
|
|
||||||
const server = http.createServer((req, res) => {
|
const server = http.createServer((req, res) => {
|
||||||
@@ -77,3 +77,5 @@ function parsePath(url) {
|
|||||||
key: parts.slice(1).join('/') || null,
|
key: parts.slice(1).join('/') || null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { createFakeS3 };
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import os from 'os';
|
const os = require('os');
|
||||||
import path from 'path';
|
const path = require('path');
|
||||||
import fs from 'fs-extra';
|
const fs = require('fs-extra');
|
||||||
import { spawnSync } from 'child_process';
|
const { spawnSync } = require('child_process');
|
||||||
import * as git from '../util/git.js';
|
|
||||||
|
const git = require('../util/git');
|
||||||
|
|
||||||
const tmpBaseDir = path.join(os.tmpdir(), 'handlebars-task-tests');
|
const tmpBaseDir = path.join(os.tmpdir(), 'handlebars-task-tests');
|
||||||
const tmpDir = path.join(tmpBaseDir, Date.now().toString(36));
|
const tmpDir = path.join(tmpBaseDir, Date.now().toString(36));
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import fs from 'fs';
|
const fs = require('fs');
|
||||||
import { S3, GetObjectCommand } from '@aws-sdk/client-s3';
|
const { S3, GetObjectCommand } = require('@aws-sdk/client-s3');
|
||||||
import { createFakeS3 } from './fake-s3.js';
|
const { createFakeS3 } = require('./fake-s3');
|
||||||
|
|
||||||
const BUCKET = 'test-bucket';
|
const BUCKET = 'test-bucket';
|
||||||
|
|
||||||
import {
|
const {
|
||||||
PUBLISHED_FILES,
|
PUBLISHED_FILES,
|
||||||
buildSuffixes,
|
buildSuffixes,
|
||||||
validateS3Env,
|
validateS3Env,
|
||||||
publish,
|
publish,
|
||||||
getNameInBucket,
|
getNameInBucket,
|
||||||
getLocalFile,
|
getLocalFile,
|
||||||
} from '../publish-to-aws.js';
|
} = require('../publish-to-aws');
|
||||||
|
|
||||||
let server;
|
let server;
|
||||||
let s3Client;
|
let s3Client;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
const childProcess = require('child_process');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
execNodeJsScriptWithInheritedOutput,
|
||||||
|
};
|
||||||
|
|
||||||
|
async function execNodeJsScriptWithInheritedOutput(command, args) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const child = childProcess.fork(command, args, { stdio: 'inherit' });
|
||||||
|
child.on('close', (code) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
reject(new Error(`Child process failed with exit-code ${code}`));
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
+26
-29
@@ -1,33 +1,30 @@
|
|||||||
import childProcess from 'child_process';
|
const childProcess = require('child_process');
|
||||||
|
|
||||||
export async function remotes() {
|
module.exports = {
|
||||||
return git('remote', '-v');
|
async remotes() {
|
||||||
}
|
return git('remote', '-v');
|
||||||
|
},
|
||||||
export async function branches() {
|
async branches() {
|
||||||
return git('branch', '-a');
|
return git('branch', '-a');
|
||||||
}
|
},
|
||||||
|
async commitInfo() {
|
||||||
export async function commitInfo() {
|
const headSha = await getHeadSha();
|
||||||
const headSha = await getHeadSha();
|
const masterSha = await getMasterSha();
|
||||||
const masterSha = await getMasterSha();
|
return {
|
||||||
return {
|
headSha,
|
||||||
headSha,
|
masterSha,
|
||||||
masterSha,
|
tagName: await getTagName(),
|
||||||
tagName: await getTagName(),
|
isMaster: headSha === masterSha,
|
||||||
isMaster: headSha === masterSha,
|
};
|
||||||
};
|
},
|
||||||
}
|
async add(path) {
|
||||||
|
return git('add', '-f', path);
|
||||||
export async function add(path) {
|
},
|
||||||
return git('add', '-f', path);
|
async commit(message) {
|
||||||
}
|
return git('commit', '--message', message);
|
||||||
|
},
|
||||||
export async function commit(message) {
|
git, // visible for testing
|
||||||
return git('commit', '--message', message);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export { git };
|
|
||||||
|
|
||||||
async function getHeadSha() {
|
async function getHeadSha() {
|
||||||
const stdout = await git('rev-parse', '--short', 'HEAD');
|
const stdout = await git('rev-parse', '--short', 'HEAD');
|
||||||
|
|||||||
+7
-7
@@ -1,7 +1,7 @@
|
|||||||
import fs from 'fs';
|
const fs = require('fs');
|
||||||
import { execSync } from 'child_process';
|
const { execSync } = require('child_process');
|
||||||
import * as git from './util/git.js';
|
const git = require('./util/git');
|
||||||
import semver from 'semver';
|
const semver = require('semver');
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const version = process.argv[2];
|
const version = process.argv[2];
|
||||||
@@ -50,16 +50,16 @@ async function main() {
|
|||||||
execSync('npm run build', { stdio: 'inherit' });
|
execSync('npm run build', { stdio: 'inherit' });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function replaceAndAdd(filePath, regex, value) {
|
async function replaceAndAdd(filePath, regex, value) {
|
||||||
let content = fs.readFileSync(filePath, 'utf8');
|
let content = fs.readFileSync(filePath, 'utf8');
|
||||||
content = content.replace(regex, value);
|
content = content.replace(regex, value);
|
||||||
fs.writeFileSync(filePath, content);
|
fs.writeFileSync(filePath, content);
|
||||||
await git.add(filePath);
|
await git.add(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
import { fileURLToPath } from 'url';
|
module.exports = { replaceAndAdd };
|
||||||
|
|
||||||
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
if (require.main === module) {
|
||||||
main().catch((err) => {
|
main().catch((err) => {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "Hello ",
|
|
||||||
"value": "Hello ",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 6 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "name",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["name"],
|
|
||||||
"original": "name",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 8 },
|
|
||||||
"end": { "line": 1, "column": 12 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [],
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 6 },
|
|
||||||
"end": { "line": 1, "column": 14 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "!",
|
|
||||||
"value": "!",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 14 },
|
|
||||||
"end": { "line": 1, "column": 15 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 15 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Hello {{name}}!
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "BlockStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "if",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["if"],
|
|
||||||
"original": "if",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 3 },
|
|
||||||
"end": { "line": 1, "column": 5 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "active",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["active"],
|
|
||||||
"original": "active",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 6 },
|
|
||||||
"end": { "line": 1, "column": 12 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"program": {
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "yes",
|
|
||||||
"value": "yes",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 14 },
|
|
||||||
"end": { "line": 1, "column": 17 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 14 },
|
|
||||||
"end": { "line": 1, "column": 17 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inverse": {
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "no",
|
|
||||||
"value": "no",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 25 },
|
|
||||||
"end": { "line": 1, "column": 27 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 25 },
|
|
||||||
"end": { "line": 1, "column": 27 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"openStrip": { "open": false, "close": false },
|
|
||||||
"inverseStrip": { "open": false, "close": false },
|
|
||||||
"closeStrip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 34 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 34 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{#if active}}yes{{else}}no{{/if}}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "helper",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["helper"],
|
|
||||||
"original": "helper",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 2 },
|
|
||||||
"end": { "line": 1, "column": 8 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "NumberLiteral",
|
|
||||||
"value": 42,
|
|
||||||
"original": 42,
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 9 },
|
|
||||||
"end": { "line": 1, "column": 11 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{helper 42}}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "helper",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["helper"],
|
|
||||||
"original": "helper",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 2 },
|
|
||||||
"end": { "line": 1, "column": 8 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "BooleanLiteral",
|
|
||||||
"value": true,
|
|
||||||
"original": true,
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 9 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BooleanLiteral",
|
|
||||||
"value": false,
|
|
||||||
"original": false,
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 14 },
|
|
||||||
"end": { "line": 1, "column": 19 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 21 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 21 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{helper true false}}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "helper",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["helper"],
|
|
||||||
"original": "helper",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 2 },
|
|
||||||
"end": { "line": 1, "column": 8 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "StringLiteral",
|
|
||||||
"value": "str",
|
|
||||||
"original": "str",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 9 },
|
|
||||||
"end": { "line": 1, "column": 14 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 16 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 16 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{helper "str"}}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "foo",
|
|
||||||
"tail": ["bar", "baz"],
|
|
||||||
"parts": ["foo", "bar", "baz"],
|
|
||||||
"original": "foo.bar.baz",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 2 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [],
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 15 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 15 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{foo.bar.baz}}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 2,
|
|
||||||
"head": "parent",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["parent"],
|
|
||||||
"original": "../../parent",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 2 },
|
|
||||||
"end": { "line": 1, "column": 14 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [],
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 16 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 16 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{../../parent}}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "BlockStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "each",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["each"],
|
|
||||||
"original": "each",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 3 },
|
|
||||||
"end": { "line": 1, "column": 7 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "items",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["items"],
|
|
||||||
"original": "items",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 8 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"program": {
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "it",
|
|
||||||
"value": "it",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 29 },
|
|
||||||
"end": { "line": 1, "column": 31 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 29 },
|
|
||||||
"end": { "line": 1, "column": 31 }
|
|
||||||
},
|
|
||||||
"blockParams": ["item", "idx"]
|
|
||||||
},
|
|
||||||
"openStrip": { "open": false, "close": false },
|
|
||||||
"closeStrip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 40 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 40 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{#each items as |item idx|}}it{{/each}}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "DecoratorBlock",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "inline",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["inline"],
|
|
||||||
"original": "inline",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 4 },
|
|
||||||
"end": { "line": 1, "column": 10 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "StringLiteral",
|
|
||||||
"value": "foo",
|
|
||||||
"original": "foo",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 11 },
|
|
||||||
"end": { "line": 1, "column": 16 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"program": {
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "bar",
|
|
||||||
"value": "bar",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 18 },
|
|
||||||
"end": { "line": 1, "column": 21 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 18 },
|
|
||||||
"end": { "line": 1, "column": 21 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"openStrip": { "open": false, "close": false },
|
|
||||||
"closeStrip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 32 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 32 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{#*inline "foo"}}bar{{/inline}}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "before ",
|
|
||||||
"value": "before ",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 7 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "name",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["name"],
|
|
||||||
"original": "name",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 9 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [],
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 7 },
|
|
||||||
"end": { "line": 1, "column": 15 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": " after",
|
|
||||||
"value": " after",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 15 },
|
|
||||||
"end": { "line": 1, "column": 21 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 21 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
before {{name}} after
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "before ",
|
|
||||||
"value": "before ",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 7 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "name",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["name"],
|
|
||||||
"original": "name",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 9 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [],
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 7 },
|
|
||||||
"end": { "line": 1, "column": 15 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": " after",
|
|
||||||
"value": " after",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 15 },
|
|
||||||
"end": { "line": 1, "column": 21 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 21 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
before {{name}} after
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "BlockStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "each",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["each"],
|
|
||||||
"original": "each",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 3 },
|
|
||||||
"end": { "line": 1, "column": 7 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "items",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["items"],
|
|
||||||
"original": "items",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 8 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"program": {
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "item",
|
|
||||||
"value": "item",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 15 },
|
|
||||||
"end": { "line": 1, "column": 19 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 15 },
|
|
||||||
"end": { "line": 1, "column": 19 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"openStrip": { "open": false, "close": false },
|
|
||||||
"closeStrip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 28 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 28 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{#each items}}item{{/each}}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "BlockStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "each",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["each"],
|
|
||||||
"original": "each",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 3 },
|
|
||||||
"end": { "line": 1, "column": 7 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "items",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["items"],
|
|
||||||
"original": "items",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 8 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"program": {
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "item",
|
|
||||||
"value": "item",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 15 },
|
|
||||||
"end": { "line": 1, "column": 19 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 15 },
|
|
||||||
"end": { "line": 1, "column": 19 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"openStrip": { "open": false, "close": false },
|
|
||||||
"closeStrip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 28 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 28 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{#each items}}item{{/each}}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "BlockStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "inverted",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["inverted"],
|
|
||||||
"original": "inverted",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 3 },
|
|
||||||
"end": { "line": 1, "column": 11 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [],
|
|
||||||
"inverse": {
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "body",
|
|
||||||
"value": "body",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 13 },
|
|
||||||
"end": { "line": 1, "column": 17 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 13 },
|
|
||||||
"end": { "line": 1, "column": 17 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"openStrip": { "open": false, "close": false },
|
|
||||||
"closeStrip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 30 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 30 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{^inverted}}body{{/inverted}}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "PartialStatement",
|
|
||||||
"name": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "partial",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["partial"],
|
|
||||||
"original": "partial",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 4 },
|
|
||||||
"end": { "line": 1, "column": 11 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [],
|
|
||||||
"indent": "",
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{> partial}}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "PartialBlockStatement",
|
|
||||||
"name": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "layout",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["layout"],
|
|
||||||
"original": "layout",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 5 },
|
|
||||||
"end": { "line": 1, "column": 11 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [],
|
|
||||||
"program": {
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "ContentStatement",
|
|
||||||
"original": "body",
|
|
||||||
"value": "body",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 13 },
|
|
||||||
"end": { "line": 1, "column": 17 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 13 },
|
|
||||||
"end": { "line": 1, "column": 17 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"openStrip": { "open": false, "close": false },
|
|
||||||
"closeStrip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 28 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 28 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{#> layout}}body{{/layout}}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "helper",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["helper"],
|
|
||||||
"original": "helper",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 2 },
|
|
||||||
"end": { "line": 1, "column": 8 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "param1",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["param1"],
|
|
||||||
"original": "param1",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 9 },
|
|
||||||
"end": { "line": 1, "column": 15 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"hash": {
|
|
||||||
"type": "Hash",
|
|
||||||
"pairs": [
|
|
||||||
{
|
|
||||||
"type": "HashPair",
|
|
||||||
"key": "key",
|
|
||||||
"value": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "value",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["value"],
|
|
||||||
"original": "value",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 20 },
|
|
||||||
"end": { "line": 1, "column": 25 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 16 },
|
|
||||||
"end": { "line": 1, "column": 25 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 16 },
|
|
||||||
"end": { "line": 1, "column": 25 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 27 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 27 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{helper param1 key=value}}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"body": [
|
|
||||||
{
|
|
||||||
"type": "MustacheStatement",
|
|
||||||
"path": {
|
|
||||||
"type": "PathExpression",
|
|
||||||
"this": false,
|
|
||||||
"data": false,
|
|
||||||
"depth": 0,
|
|
||||||
"head": "helper",
|
|
||||||
"tail": [],
|
|
||||||
"parts": ["helper"],
|
|
||||||
"original": "helper",
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 2 },
|
|
||||||
"end": { "line": 1, "column": 8 }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"params": [
|
|
||||||
{
|
|
||||||
"type": "NumberLiteral",
|
|
||||||
"value": 42,
|
|
||||||
"original": 42,
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 9 },
|
|
||||||
"end": { "line": 1, "column": 11 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"escaped": true,
|
|
||||||
"strip": { "open": false, "close": false },
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"strip": {},
|
|
||||||
"loc": {
|
|
||||||
"start": { "line": 1, "column": 0 },
|
|
||||||
"end": { "line": 1, "column": 13 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{{helper 42}}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user