| 100 | } |
| 101 | |
| 102 | filter(ast: { |
| 103 | type: 'filter'; |
| 104 | input: any; |
| 105 | filters: Array<{name: string; args: Array<any>}>; |
| 106 | }) { |
| 107 | let input = this.evalute(ast.input); |
| 108 | const filters = ast.filters.concat(); |
| 109 | const context: FilterContext = { |
| 110 | filter: undefined, |
| 111 | data: this.context, |
| 112 | restFilters: filters |
| 113 | }; |
| 114 | |
| 115 | while (filters.length) { |
| 116 | const filter = filters.shift()!; |
| 117 | const fn = this.filters[filter.name]; |
| 118 | if (!fn) { |
| 119 | throw new Error(`filter \`${filter.name}\` not exists.`); |
| 120 | } |
| 121 | context.filter = filter; |
| 122 | input = fn.apply( |
| 123 | context, |
| 124 | [input].concat( |
| 125 | filter.args.map((item: any) => { |
| 126 | if (item?.type === 'mixed') { |
| 127 | return item.body |
| 128 | .map((item: any) => |
| 129 | typeof item === 'string' ? item : this.evalute(item) |
| 130 | ) |
| 131 | .join(''); |
| 132 | } else if (item.type) { |
| 133 | return this.evalute(item); |
| 134 | } |
| 135 | return item; |
| 136 | }) |
| 137 | ) |
| 138 | ); |
| 139 | } |
| 140 | return input; |
| 141 | } |
| 142 | |
| 143 | raw(ast: {type: 'raw'; value: string}) { |
| 144 | return ast.value; |