A simple, expressive and safe Shopify / Github Pages compatible template engine in pure JavaScript.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
LiquidJS provides static analysis capabilities for extracting variable dependencies and analyzing template requirements without rendering.
Extract variable names and dependencies from templates.
/**
* Get all variable names used in template
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Promise resolving to array of variable names
*/
variables(template: string | Template[], options?: StaticAnalysisOptions): Promise<string[]>;
/**
* Get all variable names used in template (synchronous)
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Array of variable names
*/
variablesSync(template: string | Template[], options?: StaticAnalysisOptions): string[];
/**
* Get full variable paths including property access
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Promise resolving to array of full variable paths
*/
fullVariables(template: string | Template[], options?: StaticAnalysisOptions): Promise<string[]>;
/**
* Get full variable paths including property access (synchronous)
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Array of full variable paths
*/
fullVariablesSync(template: string | Template[], options?: StaticAnalysisOptions): string[];Perform comprehensive static analysis of templates.
/**
* Analyze template for variables and dependencies
* @param template - Parsed Template array
* @param options - Analysis options
* @returns Promise resolving to StaticAnalysis result
*/
analyze(template: Template[], options?: StaticAnalysisOptions): Promise<StaticAnalysis>;
/**
* Analyze template for variables and dependencies (synchronous)
* @param template - Parsed Template array
* @param options - Analysis options
* @returns StaticAnalysis result
*/
analyzeSync(template: Template[], options?: StaticAnalysisOptions): StaticAnalysis;
/**
* Parse and analyze template in one step
* @param html - Template string
* @param filename - Optional filename for error reporting
* @param options - Analysis options
* @returns Promise resolving to StaticAnalysis result
*/
parseAndAnalyze(html: string, filename?: string, options?: StaticAnalysisOptions): Promise<StaticAnalysis>;
/**
* Parse and analyze template in one step (synchronous)
* @param html - Template string
* @param filename - Optional filename for error reporting
* @param options - Analysis options
* @returns StaticAnalysis result
*/
parseAndAnalyzeSync(html: string, filename?: string, options?: StaticAnalysisOptions): StaticAnalysis;Extract variables as arrays of property segments for detailed path analysis.
/**
* Get all variables as arrays of property segments
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Promise resolving to array of segment arrays
*/
variableSegments(template: string | Template[], options?: StaticAnalysisOptions): Promise<SegmentArray[]>;
/**
* Get all variables as arrays of property segments (synchronous)
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Array of segment arrays
*/
variableSegmentsSync(template: string | Template[], options?: StaticAnalysisOptions): SegmentArray[];Extract global (out-of-scope) variables that need to be provided by the application.
/**
* Get all global variable names (variables not in local scope)
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Promise resolving to array of global variable names
*/
globalVariables(template: string | Template[], options?: StaticAnalysisOptions): Promise<string[]>;
/**
* Get all global variable names (synchronous)
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Array of global variable names
*/
globalVariablesSync(template: string | Template[], options?: StaticAnalysisOptions): string[];
/**
* Get full global variable paths including property access
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Promise resolving to array of full global variable paths
*/
globalFullVariables(template: string | Template[], options?: StaticAnalysisOptions): Promise<string[]>;
/**
* Get full global variable paths including property access (synchronous)
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Array of full global variable paths
*/
globalFullVariablesSync(template: string | Template[], options?: StaticAnalysisOptions): string[];
/**
* Get all global variables as arrays of property segments
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Promise resolving to array of global segment arrays
*/
globalVariableSegments(template: string | Template[], options?: StaticAnalysisOptions): Promise<SegmentArray[]>;
/**
* Get all global variables as arrays of property segments (synchronous)
* @param template - Template string or parsed Template array
* @param options - Analysis options
* @returns Array of global segment arrays
*/
globalVariableSegmentsSync(template: string | Template[], options?: StaticAnalysisOptions): SegmentArray[];interface StaticAnalysis {
/** All variables referenced in the template */
variables: Variables;
/** Variables not in local scope (need to be provided by application) */
globals: Variables;
/** Variables added to local scope by tags like assign, capture, increment */
locals: Variables;
}
interface Variables {
[key: string]: Variable[];
}
interface VariableLocation {
row: number;
col: number;
file?: string;
}
class Variable {
readonly segments: Array<string | number | Variable>;
readonly location: VariableLocation;
toString(): string;
toArray(): SegmentArray;
}
type SegmentArray = Array<string | number | SegmentArray>;
interface StaticAnalysisOptions {
/** When true (default), try to load partial templates and analyze them too */
partials?: boolean;
}import { Liquid } from "liquidjs";
const engine = new Liquid();
const template = `
Hello {{ user.name }}!
{% for item in items %}
{{ item.title | capitalize }}
{% endfor %}
Total: {{ cart.total | money }}
`;
// Get variable names
const vars = await engine.variables(template);
console.log(vars); // ['user', 'items', 'cart']
// Get full variable paths
const fullVars = await engine.fullVariables(template);
console.log(fullVars); // ['user.name', 'items', 'cart.total']const templates = engine.parse(template);
const analysis = await engine.analyze(templates);
console.log('All variables:', analysis.variables);
console.log('Global variables:', analysis.globals);
console.log('Local variables:', analysis.locals);
// Variable locations with segments
const segments = await engine.variableSegments(template);
console.log(segments); // [['user', 'name'], ['items'], ['cart', 'total']]
// Global variable analysis
const globalVars = await engine.globalVariables(template);
console.log('Global variable names:', globalVars); // ['user', 'items', 'cart']
const globalFullVars = await engine.globalFullVariables(template);
console.log('Global full paths:', globalFullVars); // ['user.name', 'items', 'cart.total']// One-step parsing and analysis
const analysisResult = await engine.parseAndAnalyze(template);
console.log('Variables found:', Object.keys(analysisResult.variables));
// With filename for better error reporting
const result = await engine.parseAndAnalyze(template, 'product-card.liquid');
console.log('Analysis for product-card.liquid:', result);