(parsed, depth)
| 48 | |
| 49 | // Recursively flatten a sitemap-index into its child url sets |
| 50 | const expandSitemap = async (parsed, depth) => { |
| 51 | if (!parsed?.sitemapindex?.sitemap || depth >= MAX_DEPTH) return parsed; |
| 52 | const children = parsed.sitemapindex.sitemap |
| 53 | .map((s) => s?.loc?.[0]) |
| 54 | .filter(Boolean) |
| 55 | .slice(0, MAX_CHILD_SITEMAPS); |
| 56 | const fetched = await Promise.all( |
| 57 | children.map((loc) => |
| 58 | fetchSitemap(loc).catch((error) => { |
| 59 | log.debug(`child sitemap failed for ${loc}`, error.message); |
| 60 | return null; |
| 61 | }), |
| 62 | ), |
| 63 | ); |
| 64 | const expanded = await Promise.all( |
| 65 | fetched.map((child) => (child ? expandSitemap(child, depth + 1) : null)), |
| 66 | ); |
| 67 | const urls = expanded.flatMap((child) => child?.urlset?.url || []); |
| 68 | return { |
| 69 | sitemapindex: parsed.sitemapindex, |
| 70 | urlset: urls.length ? { url: urls } : undefined, |
| 71 | sources: children, |
| 72 | }; |
| 73 | }; |
| 74 | |
| 75 | // Whether the parsed XML matched one of the canonical sitemap shapes |
| 76 | const isValidSitemap = (p) => !!(p?.urlset?.url?.length || p?.sitemapindex?.sitemap?.length); |
no test coverage detected