| 316 | * ``` |
| 317 | */ |
| 318 | export class Parser { |
| 319 | private tokenizer: Tokenizer = createTokenizer() |
| 320 | |
| 321 | style: TextStyle = defaultStyle() |
| 322 | inLink = false |
| 323 | linkUrl: string | undefined |
| 324 | |
| 325 | reset(): void { |
| 326 | this.tokenizer.reset() |
| 327 | this.style = defaultStyle() |
| 328 | this.inLink = false |
| 329 | this.linkUrl = undefined |
| 330 | } |
| 331 | |
| 332 | /** Feed input and get resulting actions */ |
| 333 | feed(input: string): Action[] { |
| 334 | const tokens = this.tokenizer.feed(input) |
| 335 | const actions: Action[] = [] |
| 336 | |
| 337 | for (const token of tokens) { |
| 338 | const tokenActions = this.processToken(token) |
| 339 | actions.push(...tokenActions) |
| 340 | } |
| 341 | |
| 342 | return actions |
| 343 | } |
| 344 | |
| 345 | private processToken(token: Token): Action[] { |
| 346 | switch (token.type) { |
| 347 | case 'text': |
| 348 | return this.processText(token.value) |
| 349 | |
| 350 | case 'sequence': |
| 351 | return this.processSequence(token.value) |
| 352 | } |
| 353 | } |
| 354 | |
| 355 | private processText(text: string): Action[] { |
| 356 | // Handle BEL characters embedded in text |
| 357 | const actions: Action[] = [] |
| 358 | let current = '' |
| 359 | |
| 360 | for (const char of text) { |
| 361 | if (char.charCodeAt(0) === C0.BEL) { |
| 362 | if (current) { |
| 363 | const graphemes = [...segmentGraphemes(current)] |
| 364 | if (graphemes.length > 0) { |
| 365 | actions.push({ type: 'text', graphemes, style: { ...this.style } }) |
| 366 | } |
| 367 | current = '' |
| 368 | } |
| 369 | actions.push({ type: 'bell' }) |
| 370 | } else { |
| 371 | current += char |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | if (current) { |
nothing calls this directly
no test coverage detected