()
| 244 | } |
| 245 | |
| 246 | parse(): [RootNode, SpecialBlock[]] { |
| 247 | const children: ElementNode[] = []; |
| 248 | const specialBlocks: SpecialBlock[] = []; |
| 249 | let varsBlock: VarsBlock | undefined = undefined; |
| 250 | |
| 251 | while (!this.check(TokenType.EOF)) { |
| 252 | const peekValue = this.peek().value; |
| 253 | const position = this.peek().position; |
| 254 | const type = "SpecialBlock"; |
| 255 | const codeblock = isSpecialCodeblock(peekValue); |
| 256 | |
| 257 | // Handle vars block |
| 258 | if ( |
| 259 | peekValue === "vars" && |
| 260 | this.check(TokenType.IDENTIFIER) && |
| 261 | this.peek(1).type === TokenType.BLOCK |
| 262 | ) { |
| 263 | if (varsBlock) { |
| 264 | throw new ParserError("Only one 'vars' block is allowed per document", position); |
| 265 | } |
| 266 | this.consume(TokenType.IDENTIFIER, "Expected 'vars' identifier"); |
| 267 | const blockToken = this.consume(TokenType.BLOCK, "Expected vars block"); |
| 268 | varsBlock = this.parseVarsBlock(blockToken, position); |
| 269 | continue; |
| 270 | } |
| 271 | |
| 272 | if ( |
| 273 | codeblock.valid && |
| 274 | this.check(TokenType.IDENTIFIER) && |
| 275 | this.peek(1).type === TokenType.BLOCK |
| 276 | ) { |
| 277 | this.consume(TokenType.IDENTIFIER, "Expected codeblock identifier"); |
| 278 | if (codeblock.kind === "style") { |
| 279 | specialBlocks.push({ |
| 280 | type, |
| 281 | style: "style", |
| 282 | content: this.consume(TokenType.BLOCK, "Expected style block") |
| 283 | .value.slice(1, -1) |
| 284 | .trim(), |
| 285 | position, |
| 286 | }); |
| 287 | continue; |
| 288 | } |
| 289 | if (codeblock.kind === "script") { |
| 290 | specialBlocks.push({ |
| 291 | type, |
| 292 | style: "script", |
| 293 | content: this.consume(TokenType.BLOCK, "Expected script block") |
| 294 | .value.slice(1, -1) |
| 295 | .trim(), |
| 296 | position, |
| 297 | }); |
| 298 | continue; |
| 299 | } |
| 300 | } |
| 301 | this.newGenTokens.push(this.peek()); |
| 302 | this.advance(); |
| 303 | } |
no test coverage detected