| 270 | * ``` |
| 271 | */ |
| 272 | export class Parser { |
| 273 | private tokenizer: Tokenizer = createTokenizer() |
| 274 | |
| 275 | style: TextStyle = defaultStyle() |
| 276 | inLink = false |
| 277 | linkUrl: string | undefined |
| 278 | |
| 279 | reset(): void { |
| 280 | this.tokenizer.reset() |
| 281 | this.style = defaultStyle() |
| 282 | this.inLink = false |
| 283 | this.linkUrl = undefined |
| 284 | } |
| 285 | |
| 286 | /** Feed input and get resulting actions */ |
| 287 | feed(input: string): Action[] { |
| 288 | const tokens = this.tokenizer.feed(input) |
| 289 | const actions: Action[] = [] |
| 290 | |
| 291 | for (const token of tokens) { |
| 292 | const tokenActions = this.processToken(token) |
| 293 | actions.push(...tokenActions) |
| 294 | } |
| 295 | |
| 296 | return actions |
| 297 | } |
| 298 | |
| 299 | private processToken(token: Token): Action[] { |
| 300 | switch (token.type) { |
| 301 | case 'text': |
| 302 | return this.processText(token.value) |
| 303 | |
| 304 | case 'sequence': |
| 305 | return this.processSequence(token.value) |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | private processText(text: string): Action[] { |
| 310 | // Handle BEL characters embedded in text |
| 311 | const actions: Action[] = [] |
| 312 | let current = '' |
| 313 | |
| 314 | for (const char of text) { |
| 315 | if (char.charCodeAt(0) === C0.BEL) { |
| 316 | if (current) { |
| 317 | const graphemes = [...segmentGraphemes(current)] |
| 318 | if (graphemes.length > 0) { |
| 319 | actions.push({ type: 'text', graphemes, style: { ...this.style } }) |
| 320 | } |
| 321 | current = '' |
| 322 | } |
| 323 | actions.push({ type: 'bell' }) |
| 324 | } else { |
| 325 | current += char |
| 326 | } |
| 327 | } |
| 328 | |
| 329 | if (current) { |
nothing calls this directly
no test coverage detected