Skip to content

Commit 11f013b

Browse files
authored
feat: allow drops in property access (#769)
1 parent ad039ab commit 11f013b

File tree

3 files changed

+19
-7
lines changed

3 files changed

+19
-7
lines changed

src/context/context.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Drop } from '../drop/drop'
33
import { __assign } from 'tslib'
44
import { NormalizedFullOptions, defaultOptions, RenderOptions } from '../liquid-options'
55
import { Scope } from './scope'
6-
import { hasOwnProperty, isArray, isNil, isUndefined, isString, isFunction, toLiquid, InternalUndefinedVariableError, toValueSync, isObject, Limiter } from '../util'
6+
import { hasOwnProperty, isArray, isNil, isUndefined, isString, isFunction, toLiquid, InternalUndefinedVariableError, toValueSync, isObject, Limiter, toValue } from '../util'
77

88
type PropertyKey = string | number;
99

@@ -71,8 +71,8 @@ export class Context {
7171
public getSync (paths: PropertyKey[]): unknown {
7272
return toValueSync(this._get(paths))
7373
}
74-
public * _get (paths: PropertyKey[]): IterableIterator<unknown> {
75-
const scope = this.findScope(paths[0])
74+
public * _get (paths: (PropertyKey | Drop)[]): IterableIterator<unknown> {
75+
const scope = this.findScope(paths[0] as string) // first prop should always be a string
7676
return yield this._getFromScope(scope, paths)
7777
}
7878
/**
@@ -81,7 +81,7 @@ export class Context {
8181
public getFromScope (scope: unknown, paths: PropertyKey[] | string): IterableIterator<unknown> {
8282
return toValueSync(this._getFromScope(scope, paths))
8383
}
84-
public * _getFromScope (scope: unknown, paths: PropertyKey[] | string, strictVariables = this.strictVariables): IterableIterator<unknown> {
84+
public * _getFromScope (scope: unknown, paths: (PropertyKey | Drop)[] | string, strictVariables = this.strictVariables): IterableIterator<unknown> {
8585
if (isString(paths)) paths = paths.split('.')
8686
for (let i = 0; i < paths.length; i++) {
8787
scope = yield readProperty(scope as object, paths[i], this.ownPropertyOnly)
@@ -120,8 +120,9 @@ export class Context {
120120
}
121121
}
122122

123-
export function readProperty (obj: Scope, key: PropertyKey, ownPropertyOnly: boolean) {
123+
export function readProperty (obj: Scope, key: (PropertyKey | Drop), ownPropertyOnly: boolean) {
124124
obj = toLiquid(obj)
125+
key = toValue(key) as PropertyKey
125126
if (isNil(obj)) return obj
126127
if (isArray(obj) && (key as number) < 0) return obj[obj.length + +key]
127128
const value = readJSProperty(obj, key, ownPropertyOnly)

src/render/expression.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ describe('Expression', function () {
5050
expect(await toPromise(create('foo[doo["foo"]]').evaluate(ctx, false))).toBe('BAR')
5151
expect(await toPromise(create('doo[coo].foo').evaluate(ctx, false))).toBe('bar')
5252
})
53+
it('should support drops in property access', async function () {
54+
class TemplateDrop extends Drop {
55+
valueOf () { return 'bar' }
56+
}
57+
const ctx = new Context({
58+
foo: { bar: 'BAR' },
59+
coo: new TemplateDrop()
60+
})
61+
expect(await toPromise(create('foo[coo]').evaluate(ctx, false))).toBe('BAR')
62+
})
5363
})
5464

5565
describe('simple expression', function () {

src/render/expression.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { QuotedToken, RangeToken, OperatorToken, Token, PropertyAccessToken, Ope
22
import { isRangeToken, isPropertyAccessToken, UndefinedVariableError, range, isOperatorToken, assert } from '../util'
33
import type { Context } from '../context'
44
import type { UnaryOperatorHandler } from '../render'
5+
import { Drop } from '../drop'
56

67
export class Expression {
78
private postfix: Token[]
@@ -42,9 +43,9 @@ export function * evalToken (token: Token | undefined, ctx: Context, lenient = f
4243
}
4344

4445
function * evalPropertyAccessToken (token: PropertyAccessToken, ctx: Context, lenient: boolean): IterableIterator<unknown> {
45-
const props: string[] = []
46+
const props: (string | number | Drop)[] = []
4647
for (const prop of token.props) {
47-
props.push((yield evalToken(prop, ctx, false)) as unknown as string)
48+
props.push((yield evalToken(prop, ctx, false)) as unknown as string | number | Drop)
4849
}
4950
try {
5051
if (token.variable) {

0 commit comments

Comments
 (0)