feat!: drop TagImplOptions in favor of Tag classes (#839) (#927)

* feat!: drop TagImplOptions in favor of Tag classes (#839)

Remove tag-options-adapter and the registerTag object-literal overload.
Custom tags must extend Tag.

Co-authored-by: Cursor <[email protected]>

* test: drop TagImplOptions-specific e2e coverage (#839)

Remove #570 v9 object-literal registration test and unused metadata_file setup in #573.

Co-authored-by: Cursor <[email protected]>

* test: use inline Tag classes in register-tags spec

Co-authored-by: Cursor <[email protected]>

* test: remove dead throwingTag setup and duplicate throw stub

for.spec kept throwingTag registration after #713 removed its test. Reuse ThrowingTag in liquid.spec instead of IntendedRenderErrorTag.

Co-authored-by: Cursor <[email protected]>

* test: remove dead throwingTag setup and duplicate throw stub

for.spec kept throwingTag registration after #713 removed its test. Reuse ThrowingTag in liquid.spec instead of IntendedRenderErrorTag.

Co-authored-by: Cursor <[email protected]>

* fix(demo): ignore killall exit when express server already stopped

Co-authored-by: Cursor <[email protected]>

* fix(demo): revert unrelated return->exit change in express test

Co-authored-by: Cursor <[email protected]>

* fix(demo): use exit in express test script (no enclosing function)

Co-authored-by: Cursor <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Yang Jun
2026-07-09 00:58:43 +08:00
co-authored by Cursor
parent 5e3928654b
commit cc4a9ce0a7
11 changed files with 78 additions and 99 deletions
-1
View File
@@ -1,7 +1,6 @@
export * from './template'
export * from './template-impl'
export * from './tag'
export * from './tag-options-adapter'
export * from './filter'
export * from './filter-impl-options'
export * from './hash'
-28
View File
@@ -1,28 +0,0 @@
import { isFunction } from '../util'
import { Hash } from './hash'
import { Tag, TagClass, TagRenderReturn } from './tag'
import { TagToken, TopLevelToken } from '../tokens'
import { Emitter } from '../emitters'
import { Context } from '../context'
import type { Liquid } from '../liquid'
export interface TagImplOptions {
[key: string]: any
parse?: (this: Tag & TagImplOptions, token: TagToken, remainingTokens: TopLevelToken[]) => void;
render: (this: Tag & TagImplOptions, ctx: Context, emitter: Emitter, hash: Record<string, any>) => TagRenderReturn;
}
export function createTagClass (options: TagImplOptions): TagClass {
return class extends Tag {
constructor (token: TagToken, tokens: TopLevelToken[], liquid: Liquid) {
super(token, tokens, liquid)
if (isFunction(options.parse)) {
options.parse.call(this, token, tokens)
}
}
* render (ctx: Context, emitter: Emitter): TagRenderReturn {
const hash = (yield new Hash(this.token.args, ctx.opts.keyValueSeparator).render(ctx)) as Record<string, any>
return yield options.render.call(this, ctx, emitter, hash)
}
}
}