diff --git a/fixtures/include-conditionals/compiled.js b/fixtures/include-conditionals/compiled.js new file mode 100644 index 0000000..309750f --- /dev/null +++ b/fixtures/include-conditionals/compiled.js @@ -0,0 +1,6 @@ +(function (template, ctx) { + let out = '' + out += template.renderInline(`include-conditionals/${ctx.resolve('username') === 'virk' ? 'virk.edge' : 'guest.edge'}`)(template, ctx) + out += '\n' + return out +})(template, ctx) \ No newline at end of file diff --git a/fixtures/include-conditionals/index.edge b/fixtures/include-conditionals/index.edge new file mode 100644 index 0000000..001c047 --- /dev/null +++ b/fixtures/include-conditionals/index.edge @@ -0,0 +1 @@ +@include(`include-conditionals/${username === 'virk' ? 'virk.edge' : 'guest.edge'}`) \ No newline at end of file diff --git a/fixtures/include-conditionals/index.json b/fixtures/include-conditionals/index.json new file mode 100644 index 0000000..d5f5540 --- /dev/null +++ b/fixtures/include-conditionals/index.json @@ -0,0 +1,3 @@ +{ + "username": "virk" +} \ No newline at end of file diff --git a/fixtures/include-conditionals/index.txt b/fixtures/include-conditionals/index.txt new file mode 100644 index 0000000..ef35402 --- /dev/null +++ b/fixtures/include-conditionals/index.txt @@ -0,0 +1 @@ +Hello from virk \ No newline at end of file diff --git a/fixtures/include-conditionals/virk.edge b/fixtures/include-conditionals/virk.edge new file mode 100644 index 0000000..ef35402 --- /dev/null +++ b/fixtures/include-conditionals/virk.edge @@ -0,0 +1 @@ +Hello from virk \ No newline at end of file diff --git a/fixtures/include-identifier/compiled.js b/fixtures/include-identifier/compiled.js new file mode 100644 index 0000000..0865c58 --- /dev/null +++ b/fixtures/include-identifier/compiled.js @@ -0,0 +1,6 @@ +(function (template, ctx) { + let out = '' + out += template.renderInline(ctx.resolve('partial'))(template, ctx) + out += '\n' + return out +})(template, ctx) \ No newline at end of file diff --git a/fixtures/include-identifier/index.edge b/fixtures/include-identifier/index.edge new file mode 100644 index 0000000..9ed9fc6 --- /dev/null +++ b/fixtures/include-identifier/index.edge @@ -0,0 +1 @@ +@include(partial) \ No newline at end of file diff --git a/fixtures/include-identifier/index.json b/fixtures/include-identifier/index.json new file mode 100644 index 0000000..e893447 --- /dev/null +++ b/fixtures/include-identifier/index.json @@ -0,0 +1,3 @@ +{ + "partial": "include-identifier/partial" +} \ No newline at end of file diff --git a/fixtures/include-identifier/index.txt b/fixtures/include-identifier/index.txt new file mode 100644 index 0000000..70c379b --- /dev/null +++ b/fixtures/include-identifier/index.txt @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/fixtures/include-identifier/partial.edge b/fixtures/include-identifier/partial.edge new file mode 100644 index 0000000..70c379b --- /dev/null +++ b/fixtures/include-identifier/partial.edge @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/fixtures/include-literal/compiled.js b/fixtures/include-literal/compiled.js new file mode 100644 index 0000000..f5ad8a3 --- /dev/null +++ b/fixtures/include-literal/compiled.js @@ -0,0 +1,6 @@ +(function (template, ctx) { + let out = '' + out += template.renderInline('include-literal/partial')(template, ctx) + out += '\n' + return out +})(template, ctx) \ No newline at end of file diff --git a/fixtures/include-literal/index.edge b/fixtures/include-literal/index.edge new file mode 100644 index 0000000..5605c07 --- /dev/null +++ b/fixtures/include-literal/index.edge @@ -0,0 +1 @@ +@include('include-literal/partial') \ No newline at end of file diff --git a/fixtures/include-literal/index.json b/fixtures/include-literal/index.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/include-literal/index.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/include-literal/index.txt b/fixtures/include-literal/index.txt new file mode 100644 index 0000000..70c379b --- /dev/null +++ b/fixtures/include-literal/index.txt @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/fixtures/include-literal/partial.edge b/fixtures/include-literal/partial.edge new file mode 100644 index 0000000..70c379b --- /dev/null +++ b/fixtures/include-literal/partial.edge @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/fixtures/include-nested/compiled.js b/fixtures/include-nested/compiled.js new file mode 100644 index 0000000..cd3e923 --- /dev/null +++ b/fixtures/include-nested/compiled.js @@ -0,0 +1,6 @@ +(function (template, ctx) { + let out = '' + out += template.renderInline('include-nested/partial')(template, ctx) + out += '\n' + return out +})(template, ctx) \ No newline at end of file diff --git a/fixtures/include-nested/index.edge b/fixtures/include-nested/index.edge new file mode 100644 index 0000000..0d009c6 --- /dev/null +++ b/fixtures/include-nested/index.edge @@ -0,0 +1 @@ +@include('include-nested/partial') \ No newline at end of file diff --git a/fixtures/include-nested/index.json b/fixtures/include-nested/index.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/fixtures/include-nested/index.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/fixtures/include-nested/index.txt b/fixtures/include-nested/index.txt new file mode 100644 index 0000000..70c379b --- /dev/null +++ b/fixtures/include-nested/index.txt @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/fixtures/include-nested/partial-1.edge b/fixtures/include-nested/partial-1.edge new file mode 100644 index 0000000..70c379b --- /dev/null +++ b/fixtures/include-nested/partial-1.edge @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/fixtures/include-nested/partial.edge b/fixtures/include-nested/partial.edge new file mode 100644 index 0000000..1e4cd1e --- /dev/null +++ b/fixtures/include-nested/partial.edge @@ -0,0 +1 @@ +@include('include-nested/partial-1') \ No newline at end of file diff --git a/fixtures/include-shared-ctx/compiled.js b/fixtures/include-shared-ctx/compiled.js new file mode 100644 index 0000000..09f0866 --- /dev/null +++ b/fixtures/include-shared-ctx/compiled.js @@ -0,0 +1,6 @@ +(function (template, ctx) { + let out = '' + out += template.renderInline('include-shared-ctx/partial')(template, ctx) + out += '\n' + return out +})(template, ctx) \ No newline at end of file diff --git a/fixtures/include-shared-ctx/index.edge b/fixtures/include-shared-ctx/index.edge new file mode 100644 index 0000000..cf06459 --- /dev/null +++ b/fixtures/include-shared-ctx/index.edge @@ -0,0 +1 @@ +@include('include-shared-ctx/partial') \ No newline at end of file diff --git a/fixtures/include-shared-ctx/index.json b/fixtures/include-shared-ctx/index.json new file mode 100644 index 0000000..d5f5540 --- /dev/null +++ b/fixtures/include-shared-ctx/index.json @@ -0,0 +1,3 @@ +{ + "username": "virk" +} \ No newline at end of file diff --git a/fixtures/include-shared-ctx/index.txt b/fixtures/include-shared-ctx/index.txt new file mode 100644 index 0000000..54be7f1 --- /dev/null +++ b/fixtures/include-shared-ctx/index.txt @@ -0,0 +1 @@ +Hello virk \ No newline at end of file diff --git a/fixtures/include-shared-ctx/partial.edge b/fixtures/include-shared-ctx/partial.edge new file mode 100644 index 0000000..6e74c91 --- /dev/null +++ b/fixtures/include-shared-ctx/partial.edge @@ -0,0 +1 @@ +Hello {{ username }} \ No newline at end of file diff --git a/src/Compiler/index.ts b/src/Compiler/index.ts index 816d21a..68041c6 100644 --- a/src/Compiler/index.ts +++ b/src/Compiler/index.ts @@ -20,29 +20,29 @@ export class Compiler { /** * Compiles a given template by loading it using the loader */ - private _compile (templatePath: string, diskName: string): string { + private _compile (templatePath: string, diskName: string, inline: boolean = false): string { const template = this.loader.resolve(templatePath, diskName) const parser = new Parser(this.tags) - return parser.parseTemplate(template) + return parser.parseTemplate(template, !inline) } /** * Compiles a given template by loading it using the loader, also caches * the template and returns from the cache (if exists). */ - public compile (templatePath: string, diskName: string = 'default'): string { + public compile (templatePath: string, diskName: string = 'default', inline: boolean = false): string { templatePath = this.loader.makePath(templatePath, diskName) /** * Compile right away when cache is disabled */ if (!this.shouldCache) { - return this._compile(templatePath, diskName) + return this._compile(templatePath, diskName, inline) } /* istanbul ignore else */ if (!this.cache.get(templatePath)) { - this.cache.set(templatePath, this._compile(templatePath, diskName)) + this.cache.set(templatePath, this._compile(templatePath, diskName, inline)) } return this.cache.get(templatePath)! diff --git a/src/Tags/Include.ts b/src/Tags/Include.ts new file mode 100644 index 0000000..3ee7e37 --- /dev/null +++ b/src/Tags/Include.ts @@ -0,0 +1,36 @@ +/* +* edge +* +* (c) Harminder Virk +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +import { Parser } from 'edge-parser' +import { EdgeBuffer } from 'edge-parser/build/src/EdgeBuffer' +import { IBlockNode } from 'edge-lexer/build/src/Contracts' +import { BaseTag } from './BaseTag' + +export class IncludeTag extends BaseTag { + public static block = false + public static seekable = true + public static selfclosed = false + + /** + * Expressions which are not allowed by the sequence + * expression + * + * @type {Array} + */ + protected bannedExpressions = ['SequenceExpression'] + + /** + * Compiles else block node to Javascript else statement + */ + public compile (parser: Parser, buffer: EdgeBuffer, token: IBlockNode) { + const parsed = parser.parseJsArg(token.properties.jsArg, token.lineno) + this._validateExpression(parsed, token.lineno) + buffer.writeLine(`template.renderInline(${parser.statementToString(parsed)})(template, ctx)`) + } +} diff --git a/src/Tags/index.ts b/src/Tags/index.ts index bcf53da..a09ad7f 100644 --- a/src/Tags/index.ts +++ b/src/Tags/index.ts @@ -10,3 +10,4 @@ export { IfTag as if } from './If' export { ElseTag as else } from './Else' export { ElseIfTag as elseif } from './ElseIf' +export { IncludeTag as include } from './Include' diff --git a/src/Template/index.ts b/src/Template/index.ts index d17cdc6..64b17fd 100644 --- a/src/Template/index.ts +++ b/src/Template/index.ts @@ -15,6 +15,10 @@ export class Template { constructor (private compiler: Compiler, private sharedState: any) { } + public renderInline (template: string): Function { + return new Function('template', 'ctx', this.compiler.compile(template, 'default', true)) + } + public render (template: string, presenter: IPresenter, diskName?: string): string { const compiledTemplate = this.compiler.compile(template, diskName) const ctx = new Context(presenter, this.sharedState) diff --git a/test/if-tag.spec.ts b/test/tags.spec.ts similarity index 67% rename from test/if-tag.spec.ts rename to test/tags.spec.ts index 82d026d..9f695a3 100644 --- a/test/if-tag.spec.ts +++ b/test/tags.spec.ts @@ -71,3 +71,33 @@ We are writing a bad if condition } }) }) + +test.group('Include', () => { + test('raise errors on correct line with include tag', async (assert) => { + assert.plan(1) + + const templateContent = `We are writing a bad include condition +@include(foo bar)` + + await fs.outputFile(join(viewsDir, 'foo.edge'), templateContent) + try { + compiler.compile('foo') + } catch (error) { + assert.equal(error.loc.line, 2) + } + }) + + test('raise errors when using sequence expression', async (assert) => { + assert.plan(2) + + const templateContent = `@include('foo', 'bar')` + + await fs.outputFile(join(viewsDir, 'foo.edge'), templateContent) + try { + compiler.compile('foo') + } catch (error) { + assert.equal(error.loc.line, 1) + assert.equal(error.message, 'E_UNALLOWED_EXPRESSION: SequenceExpression is not allowed for if tag\n> More details: https://err.sh/poppinss/edge-errors/E_UNALLOWED_EXPRESSION') + } + }) +})