or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analysis.mdbuilt-in-tags.mdconfiguration.mdcontext-and-scoping.mdcore-engine.mdextensions.mdfilesystem.mdfilters.mdindex.md
tile.json

extensions.mddocs/

0

# Custom Extensions

1

2

LiquidJS provides a powerful extension system for registering custom filters and tags to extend template functionality with domain-specific processing capabilities.

3

4

## Capabilities

5

6

### Custom Filters

7

8

Register custom filters to transform template output values.

9

10

```typescript { .api }

11

/**

12

* Register a custom filter

13

* @param name - Filter name

14

* @param filter - Filter implementation function

15

*/

16

registerFilter(name: string, filter: FilterImplOptions): void;

17

18

type FilterImplOptions = (this: FilterImpl, value: any, ...args: any[]) => any;

19

20

interface FilterImpl {

21

context: Context;

22

liquid: Liquid;

23

}

24

```

25

26

**Usage Examples:**

27

28

```typescript

29

import { Liquid } from "liquidjs";

30

31

const engine = new Liquid();

32

33

// Simple filter

34

engine.registerFilter('shout', (str) => String(str).toUpperCase() + '!');

35

36

// Filter with arguments

37

engine.registerFilter('repeat', (str, times) => {

38

return String(str).repeat(Number(times) || 1);

39

});

40

41

// Async filter

42

engine.registerFilter('fetchData', async function(url) {

43

const response = await fetch(String(url));

44

return response.json();

45

});

46

47

// Template usage

48

const result = await engine.parseAndRender(`

49

{{ "hello" | shout }}

50

{{ "world" | repeat: 3 }}

51

`, {});

52

```

53

54

### Custom Tags

55

56

Register custom tags for template control flow and logic.

57

58

```typescript { .api }

59

/**

60

* Register a custom tag

61

* @param name - Tag name

62

* @param tag - Tag class or implementation options

63

*/

64

registerTag(name: string, tag: TagClass | TagImplOptions): void;

65

66

type TagClass = new (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) => Tag;

67

68

interface TagImplOptions {

69

parse?(token: TagToken, remainTokens: TopLevelToken[]): void;

70

render?(ctx: Context, emitter: Emitter): any;

71

}

72

73

interface Tag {

74

token: TagToken;

75

render(ctx: Context, emitter: Emitter): any;

76

}

77

```

78

79

**Usage Examples:**

80

81

```typescript

82

// Simple tag

83

engine.registerTag('hello', {

84

render: function(ctx, emitter) {

85

emitter.write('Hello from custom tag!');

86

}

87

});

88

89

// Tag with parsing

90

engine.registerTag('upper', {

91

parse: function(token, remainTokens) {

92

this.str = token.args;

93

},

94

render: function(ctx, emitter) {

95

const str = this.liquid.renderer.renderTemplates(this.str, ctx, {sync: true});

96

emitter.write(String(str).toUpperCase());

97

}

98

});

99

```

100

101

### Plugin System

102

103

Use the plugin system to bundle multiple extensions together.

104

105

```typescript { .api }

106

/**

107

* Apply a plugin to the Liquid instance

108

* @param plugin - Plugin function that extends the engine

109

*/

110

plugin(plugin: (this: Liquid, L: typeof Liquid) => void): void;

111

```

112

113

**Usage Examples:**

114

115

```typescript

116

// Create a plugin

117

function myPlugin(Liquid) {

118

this.registerFilter('reverse', str => String(str).split('').reverse().join(''));

119

this.registerFilter('bold', str => `<strong>${str}</strong>`);

120

121

this.registerTag('timestamp', {

122

render: function(ctx, emitter) {

123

emitter.write(new Date().toISOString());

124

}

125

});

126

}

127

128

// Use the plugin

129

engine.plugin(myPlugin);

130

```