(fragment: string)
| 873 | } |
| 874 | |
| 875 | function autoCloseFragment(fragment: string): string { |
| 876 | const openTags: string[] = []; |
| 877 | const tagRe = /<\/?([a-zA-Z][a-zA-Z0-9-]*)\b[^>]*(\/)?>/g; |
| 878 | let match: RegExpExecArray | null; |
| 879 | |
| 880 | while ((match = tagRe.exec(fragment)) !== null) { |
| 881 | const tag = match[1]!.toLowerCase(); |
| 882 | const isClose = match[0]![1] === "/"; |
| 883 | const isSelfClose = Boolean(match[2]) || match[0]!.endsWith("/>"); |
| 884 | |
| 885 | if (isClose) { |
| 886 | const idx = openTags.lastIndexOf(tag); |
| 887 | if (idx !== -1) { |
| 888 | openTags.splice(idx); |
| 889 | } |
| 890 | } else if (!isSelfClose) { |
| 891 | openTags.push(tag); |
| 892 | } |
| 893 | } |
| 894 | |
| 895 | let result = fragment; |
| 896 | for (let i = openTags.length - 1; i >= 0; i--) { |
| 897 | result += `</${openTags[i]}>`; |
| 898 | } |
| 899 | return result; |
| 900 | } |
| 901 | |
| 902 | /** Remove every streaming caret under `container` (open-tag stack moves leave orphans). */ |
| 903 | export function removeStreamingCarets(container: HTMLElement): void { |
no outgoing calls
no test coverage detected