From 870e7ec6aab27a9600166ddd23c23a2c49b7ecc4 Mon Sep 17 00:00:00 2001 From: harttle Date: Sat, 8 Feb 2020 04:59:23 +0800 Subject: [PATCH] feat: globals shared between tags, see #185 --- src/context/context.ts | 15 +++++++++------ src/liquid-options.ts | 8 ++++++-- test/integration/builtin/tags/render.ts | 13 +++++++++++++ test/unit/parser/literal.ts | 2 +- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/context/context.ts b/src/context/context.ts index 3d211c8f76..e596d52280 100644 --- a/src/context/context.ts +++ b/src/context/context.ts @@ -1,7 +1,7 @@ import { Drop } from '../drop/drop' import { __assign } from 'tslib' import { assert } from '../util/assert' -import { NormalizedFullOptions, applyDefault } from '../liquid-options' +import { NormalizedFullOptions, defaultOptions } from '../liquid-options' import { Scope } from './scope' import { isArray, isNil, isString, isFunction, toLiquid } from '../util/underscore' @@ -9,11 +9,13 @@ export class Context { private scopes: Scope[] = [{}] private registers = {} public environments: Scope + public globals: Scope public sync: boolean public opts: NormalizedFullOptions - public constructor (env: object = {}, opts?: NormalizedFullOptions, sync = false) { + public constructor (env: object = {}, opts: NormalizedFullOptions = defaultOptions, sync = false) { this.sync = sync - this.opts = applyDefault(opts) + this.opts = opts + this.globals = opts.globals this.environments = env } public getRegister (key: string, defaultValue = {}) { @@ -23,12 +25,12 @@ export class Context { return (this.registers[key] = value) } public getAll () { - return [this.environments, ...this.scopes] + return [this.globals, this.environments, ...this.scopes] .reduce((ctx, val) => __assign(ctx, val), {}) } public get (path: string) { const paths = this.parseProp(path) - const scope = this.findScope(paths[0]) || this.environments + const scope = this.findScope(paths[0]) return this.getFromScope(scope, paths) } public getFromScope (scope: object, paths: string[] | string) { @@ -57,7 +59,8 @@ export class Context { return candidate } } - return null + if (key in this.environments) return this.environments + return this.globals } /* diff --git a/src/liquid-options.ts b/src/liquid-options.ts index 0bc1a029f0..15941d3953 100644 --- a/src/liquid-options.ts +++ b/src/liquid-options.ts @@ -34,6 +34,8 @@ export interface LiquidOptions { greedy?: boolean; /** `fs` is used to override the default file-system module with a custom implementation. */ fs?: IFS; + /** the global environment passed down to all partial templates, i.e. templates included by `include`, `layout` and `render` tags. */ + globals?: object; } interface NormalizedOptions extends LiquidOptions { @@ -56,9 +58,10 @@ export interface NormalizedFullOptions extends NormalizedOptions { outputDelimiterLeft: string; outputDelimiterRight: string; greedy: boolean; + globals: object; } -const defaultOptions: NormalizedFullOptions = { +export const defaultOptions: NormalizedFullOptions = { root: ['.'], cache: false, extname: '', @@ -73,7 +76,8 @@ const defaultOptions: NormalizedFullOptions = { outputDelimiterLeft: '{{', outputDelimiterRight: '}}', strictFilters: false, - strictVariables: false + strictVariables: false, + globals: {} } export function normalize (options?: LiquidOptions): NormalizedOptions { diff --git a/test/integration/builtin/tags/render.ts b/test/integration/builtin/tags/render.ts index 73f5340669..cb53c4ffc1 100644 --- a/test/integration/builtin/tags/render.ts +++ b/test/integration/builtin/tags/render.ts @@ -76,6 +76,19 @@ describe('tags/render', function () { return expect(html).to.equal('InParent: harttle InChild: ') }) + it('should be able to access globals', async function () { + mock({ + '/hash.html': 'InParent: {{name}} {% render "user.html" %}', + '/user.html': 'InChild: {{name}}' + }) + const html = await liquid.renderFile('hash.html', { + name: 'harttle' + }, { + globals: { name: 'Harttle' } + }) + return expect(html).to.equal('InParent: harttle InChild: Harttle') + }) + it('should support render: with', async function () { mock({ '/with.html': '{% render "color" with "red", shape: "rect" %}', diff --git a/test/unit/parser/literal.ts b/test/unit/parser/literal.ts index c5b6cc9c93..bf11b70f2e 100644 --- a/test/unit/parser/literal.ts +++ b/test/unit/parser/literal.ts @@ -57,4 +57,4 @@ describe('parseStringLiteral()', function () { it('should parse slash escape', () => { expect(parseStringLiteral(String.raw`'fo\\o'`)).to.equal('fo\\o') }) -}) \ No newline at end of file +})