UNPKG

@paroicms/server

Version:
102 lines 4.45 kB
import { Context, Hash, Tag, TypeGuards, assert, evalQuotedToken, evalToken } from 'liquidjs'; import { toEnumerable } from './collection.js'; import { ForloopDrop } from './forloop-drop.js'; export default class RenderTag extends Tag { static passThroughSymbol = Symbol("passThrough"); file; currentFile; hash; constructor(token, remainTokens, liquid) { super(token, remainTokens, liquid); const tokenizer = this.tokenizer; this.file = parseFilePath(tokenizer, this.liquid); this.currentFile = token.file; while (!tokenizer.end()) { tokenizer.skipBlank(); const begin = tokenizer.p; const keyword = tokenizer.readIdentifier(); if (keyword.content === 'with' || keyword.content === 'for') { tokenizer.skipBlank(); if (tokenizer.peek() !== ':') { const value = tokenizer.readValue(); if (value) { const beforeAs = tokenizer.p; const asStr = tokenizer.readIdentifier(); let alias; if (asStr.content === 'as') alias = tokenizer.readIdentifier(); else tokenizer.p = beforeAs(this)[keyword.content] = { value, alias: alias && alias.content }; tokenizer.skipBlank(); if (tokenizer.peek() === ',') tokenizer.advance(); continue; } } } tokenizer.p = begin; break; } this.hash = new Hash(tokenizer.remaining()); } *render(ctx, emitter) { const { liquid, hash } = this; let filepath = (yield renderFilePath(this['file'], ctx, liquid)); assert(filepath, () => `illegal file path "${filepath}"`); if (!filepath.endsWith(".liquid")) { filepath += ".liquid"; } const env = { [RenderTag.passThroughSymbol]: (ctx.environments ?? {})[RenderTag.passThroughSymbol] }; const childCtx = new Context(env, ctx.opts, { sync: ctx.sync, globals: ctx.globals, strictVariables: ctx.strictVariables }); const scope = childCtx.bottom(); Object.assign(scope, yield hash.render(ctx)); if (this['with']) { const { value, alias } = this['with']; scope[alias || filepath] = yield evalToken(value, ctx); } if (this['for']) { const { value, alias } = this['for']; const collection = toEnumerable(yield evalToken(value, ctx)); scope['forloop'] = new ForloopDrop(collection.length, value.getText(), alias); for (const item of collection) { scope[alias] = item; const templates = (yield liquid._parsePartialFile(filepath, childCtx.sync, this['currentFile'])); yield liquid.renderer.renderTemplates(templates, childCtx, emitter); scope['forloop'].next(); } } else { const templates = (yield liquid._parsePartialFile(filepath, childCtx.sync, this['currentFile'])); yield liquid.renderer.renderTemplates(templates, childCtx, emitter); } } } export function parseFilePath(tokenizer, liquid) { if (liquid.options.dynamicPartials) { const file = tokenizer.readValue(); tokenizer.assert(file, 'illegal file path'); if (file.getText() === 'none') return; if (TypeGuards.isQuotedToken(file)) { const templates = liquid.parse(evalQuotedToken(file)); return optimize(templates); } return file; } const tokens = [...tokenizer.readFileNameTemplate(liquid.options)]; const templates = optimize(liquid.parser.parseTokens(tokens)); return templates === 'none' ? undefined : templates; } function optimize(templates) { if (templates.length === 1 && TypeGuards.isHTMLToken(templates[0].token)) return templates[0].token.getContent(); return templates; } export function* renderFilePath(file, ctx, liquid) { if (typeof file === 'string') return file; if (Array.isArray(file)) return liquid.renderer.renderTemplates(file, ctx); return yield evalToken(file, ctx); } //# sourceMappingURL=render.js.map