(source: string)
| 93 | } |
| 94 | |
| 95 | export function findRootTag(source: string): OpenTag | null { |
| 96 | const bodyOpenMatch = /<body\b([^>]*)>/i.exec(source); |
| 97 | const bodyCloseMatch = /<\/body>/i.exec(source); |
| 98 | if ( |
| 99 | bodyOpenMatch && |
| 100 | (readAttr(bodyOpenMatch[0], "data-composition-id") || |
| 101 | readAttr(bodyOpenMatch[0], "data-width") || |
| 102 | readAttr(bodyOpenMatch[0], "data-height")) |
| 103 | ) { |
| 104 | return { |
| 105 | raw: bodyOpenMatch[0], |
| 106 | name: "body", |
| 107 | attrs: bodyOpenMatch[1] ?? "", |
| 108 | index: bodyOpenMatch.index, |
| 109 | }; |
| 110 | } |
| 111 | const bodyStart = bodyOpenMatch ? bodyOpenMatch.index + bodyOpenMatch[0].length : 0; |
| 112 | const bodyEnd = |
| 113 | bodyOpenMatch && bodyCloseMatch && bodyCloseMatch.index > bodyStart |
| 114 | ? bodyCloseMatch.index |
| 115 | : source.length; |
| 116 | const bodyContent = bodyOpenMatch ? source.slice(bodyStart, bodyEnd) : source; |
| 117 | const bodyTags = extractOpenTags(bodyContent); |
| 118 | for (const tag of bodyTags) { |
| 119 | if (["script", "style", "meta", "link", "title"].includes(tag.name)) continue; |
| 120 | return { ...tag, index: tag.index + bodyStart }; |
| 121 | } |
| 122 | return null; |
| 123 | } |
| 124 | |
| 125 | export function readAttr(tagSource: string, attr: string): string | null { |
| 126 | if (!tagSource) return null; |
no test coverage detected