mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 20:30:39 -07:00
97 lines
2.9 KiB
TypeScript
97 lines
2.9 KiB
TypeScript
import { Drop } from '../drop/drop'
|
|
import { __assign } from 'tslib'
|
|
import { NormalizedFullOptions, defaultOptions } from '../liquid-options'
|
|
import { Scope } from './scope'
|
|
import { isArray, isNil, isString, isFunction, toLiquid } from '../util/underscore'
|
|
|
|
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 = defaultOptions, sync = false) {
|
|
this.sync = sync
|
|
this.opts = opts
|
|
this.globals = opts.globals
|
|
this.environments = env
|
|
}
|
|
public getRegister (key: string, defaultValue = {}) {
|
|
return (this.registers[key] = this.registers[key] || defaultValue)
|
|
}
|
|
public setRegister (key: string, value: any) {
|
|
return (this.registers[key] = value)
|
|
}
|
|
public saveRegister (...keys: string[]): [string, any][] {
|
|
return keys.map(key => [key, this.getRegister(key)])
|
|
}
|
|
public restoreRegister (keyValues: [string, any][]) {
|
|
return keyValues.forEach(([key, value]) => this.setRegister(key, value))
|
|
}
|
|
public getAll () {
|
|
return [this.globals, this.environments, ...this.scopes]
|
|
.reduce((ctx, val) => __assign(ctx, val), {})
|
|
}
|
|
public get (paths: string[]) {
|
|
const scope = this.findScope(paths[0])
|
|
return this.getFromScope(scope, paths)
|
|
}
|
|
public getFromScope (scope: object, paths: string[] | string) {
|
|
if (typeof paths === 'string') paths = paths.split('.')
|
|
return paths.reduce((scope, path) => {
|
|
scope = readProperty(scope, path)
|
|
if (isNil(scope) && this.opts.strictVariables) {
|
|
throw new TypeError(`undefined variable: ${path}`)
|
|
}
|
|
return scope
|
|
}, scope)
|
|
}
|
|
public push (ctx: object) {
|
|
return this.scopes.push(ctx)
|
|
}
|
|
public pop () {
|
|
return this.scopes.pop()
|
|
}
|
|
public bottom () {
|
|
return this.scopes[0]
|
|
}
|
|
private findScope (key: string) {
|
|
for (let i = this.scopes.length - 1; i >= 0; i--) {
|
|
const candidate = this.scopes[i]
|
|
if (key in candidate) return candidate
|
|
}
|
|
if (key in this.environments) return this.environments
|
|
return this.globals
|
|
}
|
|
}
|
|
|
|
export function readProperty (obj: Scope, key: string) {
|
|
if (isNil(obj)) return obj
|
|
obj = toLiquid(obj)
|
|
if (obj instanceof Drop) {
|
|
if (isFunction(obj[key])) return obj[key]()
|
|
if (obj.hasOwnProperty(key)) return obj[key]
|
|
return obj.liquidMethodMissing(key)
|
|
}
|
|
if (key === 'size') return readSize(obj)
|
|
if (key === 'first') return readFirst(obj)
|
|
if (key === 'last') return readLast(obj)
|
|
return obj[key]
|
|
}
|
|
|
|
function readFirst (obj: Scope) {
|
|
if (isArray(obj)) return obj[0]
|
|
return obj['first']
|
|
}
|
|
|
|
function readLast (obj: Scope) {
|
|
if (isArray(obj)) return obj[obj.length - 1]
|
|
return obj['last']
|
|
}
|
|
|
|
function readSize (obj: Scope) {
|
|
if (isArray(obj) || isString(obj)) return obj.length
|
|
return obj['size']
|
|
}
|