(scanner: Scanner)
| 132 | const sandbox = new Sandbox(); |
| 133 | |
| 134 | function generateFilterFn(scanner: Scanner): Filter { |
| 135 | // take all the tokens until we hit a closing bracket |
| 136 | const inner = [...scanner.takeUntil(Kind.CloseBracket, { |
| 137 | nestable: [[Kind.OpenBracket, Kind.CloseBracket]], |
| 138 | escape: [Kind.Backslash] |
| 139 | })]; |
| 140 | |
| 141 | // a filter expression is one or more of: |
| 142 | // - a regular expression |
| 143 | // - a JavaScript expression |
| 144 | // separated by && or || |
| 145 | const expression = new Array<string>(); |
| 146 | |
| 147 | // remove leading whitespace |
| 148 | eatWhitespace(inner); |
| 149 | |
| 150 | outer: |
| 151 | while (inner.length) { |
| 152 | eatWhitespace(inner); |
| 153 | let token = inner.shift()!; |
| 154 | |
| 155 | switch (token.kind) { |
| 156 | case Kind.Slash: { |
| 157 | // regular expression |
| 158 | // take all tokens until we hit a slash that isn't escaped |
| 159 | const rxExpression = [token]; |
| 160 | |
| 161 | while (inner.length) { |
| 162 | |
| 163 | token = inner.shift()!; |
| 164 | rxExpression.push(token); // store this token as part of the regex |
| 165 | |
| 166 | switch (token.kind) { |
| 167 | case Kind.Slash: |
| 168 | // now see if there are any flags |
| 169 | if (inner.length) { |
| 170 | token = inner[0]; |
| 171 | if (token.kind === Kind.Identifier) { |
| 172 | rxExpression.push(inner.shift()!); |
| 173 | } |
| 174 | } |
| 175 | // at this point, we should have the whole regex. |
| 176 | // turn this into an expression that tests against any $strings |
| 177 | expression.push(`(!!$strings.find( ($text)=> { const r = ${rxExpression.map(token => token.text).join('')}.exec($text); if( r ) { $captures.push( ...r ); return true; } } ))`); |
| 178 | continue outer; |
| 179 | |
| 180 | case Kind.Backslash: |
| 181 | // take the next token, and add it to the regex |
| 182 | rxExpression.push(inner.shift()!); |
| 183 | continue; |
| 184 | } |
| 185 | |
| 186 | // if we have nothing left, and we haven't closed the regex, then it's an error |
| 187 | if (!inner.length) { |
| 188 | throw new Error(`unterminated regular expression ${inner}`); |
| 189 | } |
| 190 | } |
| 191 | } |
no test coverage detected