(projectDir: string, html: string, compSrcPath?: string)
| 70 | } |
| 71 | |
| 72 | function collectCssSources(projectDir: string, html: string, compSrcPath?: string): CssSource[] { |
| 73 | const sources: CssSource[] = []; |
| 74 | |
| 75 | let styleMatch: RegExpExecArray | null; |
| 76 | const stylePattern = new RegExp(STYLE_BLOCK_RE.source, STYLE_BLOCK_RE.flags); |
| 77 | while ((styleMatch = stylePattern.exec(html)) !== null) { |
| 78 | sources.push({ content: styleMatch[1] ?? "" }); |
| 79 | } |
| 80 | |
| 81 | const linkRe = /<link\b[^>]*>/gi; |
| 82 | let linkMatch: RegExpExecArray | null; |
| 83 | while ((linkMatch = linkRe.exec(html)) !== null) { |
| 84 | const tag = linkMatch[0]; |
| 85 | const rel = readHtmlAttr(tag, "rel") ?? ""; |
| 86 | if (!rel.split(/\s+/).some((part) => part.toLowerCase() === "stylesheet")) continue; |
| 87 | const href = readHtmlAttr(tag, "href") ?? ""; |
| 88 | if (!isLocalStylesheetHref(href)) continue; |
| 89 | |
| 90 | const rootRelativePath = compSrcPath ? join(dirname(compSrcPath), href) : href; |
| 91 | const stylesheet = resolveExistingLocalAsset(projectDir, rootRelativePath); |
| 92 | if (!stylesheet) continue; |
| 93 | sources.push({ |
| 94 | content: readFileSync(stylesheet.resolved, "utf-8"), |
| 95 | rootRelativePath: stylesheet.rootRelativePath, |
| 96 | }); |
| 97 | } |
| 98 | |
| 99 | let tagMatch: RegExpExecArray | null; |
| 100 | const tagPattern = new RegExp(OPEN_TAG_RE.source, OPEN_TAG_RE.flags); |
| 101 | while ((tagMatch = tagPattern.exec(html)) !== null) { |
| 102 | const tag = tagMatch[0]; |
| 103 | const style = readHtmlAttr(tag, "style"); |
| 104 | if (!style) continue; |
| 105 | sources.push({ content: style }); |
| 106 | } |
| 107 | |
| 108 | return sources; |
| 109 | } |
| 110 | |
| 111 | function isRemoteOrInlineUrl(url: string): boolean { |
| 112 | return /^(https?:|data:|blob:|\/\/|#)/i.test(url); |
no test coverage detected