SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
4 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
3.9 KB · 57 lines typescript
Raw Blame History
1import { load } from "cheerio";2import type { ExtractedRecord, Parser, RawDocument } from "@dci/connectors";3import { areaSqm, cleanText, description, parseMw, record, renewableFrom, usStateCode } from "./shared.js";45/**6 * Switch campus pages (www.switch.com/core|citadel|keep|pyramid/). The body is rendered client-side (the <article> is7 * empty in the HTML), so the only server-rendered facts are the <title> ("Switch – The Core Campus, Las Vegas, Nevada")8 * and the meta description ("Switch's Tier 5 Platinum rated multi-tenant/colocation data center with up to 2.4 million sqft9 * and 315 MW."). "up to N MW" is the design/full-build figure → plannedPowerMw. No address/coordinates on the page.10 */11export const switchCampus: Parser = {12  name: "switch_campus_v1",13  version: "1.0.0",14  pageTypes: ["facility_page"],15  parse(doc: RawDocument): ExtractedRecord[] {16    const url = doc.finalUrl;17    const m = url.match(/switch\.com\/(core|citadel|keep|pyramid|rock)\/?$/);18    if (!m) return [];19    const slug = m[1]!;20    const $ = load(doc.text);21    const title = cleanText($('meta[property="og:title"]').attr("content") ?? $("title").first().text());22    if (!title) return [];23    const t = title.replace(/^Switch\s*[–—-]\s*/, "");24    const parts = t.split(",").map((s) => s.trim()).filter(Boolean);25    // "The Core Campus, Las Vegas, Nevada" → campus / city / state. When the title is a slogan instead26    // (Pyramid: "GRAND RAPIDS: Largest, Most Advanced Campus …"), fall back to the campus table published on27    // Switch's own market pages (/las-vegas/, /tahoe-reno/, /atlanta/, /grand-rapids/, /austin/).28    const TABLE: Record<string, { campus: string; city: string; state: string }> = { core: { campus: "The Core Campus", city: "Las Vegas", state: "NV" }, citadel: { campus: "The Citadel Campus", city: "Tahoe Reno", state: "NV" }, keep: { campus: "The Keep Campus", city: "Atlanta", state: "GA" }, pyramid: { campus: "The Pyramid Campus", city: "Grand Rapids", state: "MI" }, rock: { campus: "The Rock Campus", city: "Austin", state: "TX" } };29    const parsedState = usStateCode(parts[2] ?? null);30    const fromTitle = parts.length >= 3 && parsedState && /campus/i.test(parts[0] ?? "");31    const tbl = TABLE[slug];32    const campus = fromTitle ? parts[0]! : tbl?.campus ?? `The ${slug[0]!.toUpperCase()}${slug.slice(1)} Campus`;33    const city = fromTitle ? parts[1]! : tbl?.city ?? null;34    const regionName = fromTitle ? parsedState : tbl?.state ?? null;35    const desc = description(doc.text);36    const tier = desc?.match(/Tier\s?(?:5|IV|4|III|3)(?:\s?(?:Platinum|Gold))?/i)?.[0] ?? null;37    const upTo = desc?.match(/up to[\s\S]{0,80}?(\d[\d.,]*\s*(?:MW|megawatts?))\b/i)?.[1] ?? null;38    const anyMw = desc ? parseMw(desc) : null;39    const plannedPowerMw = upTo ? parseMw(upTo) : null;40    const totalPowerMw = !upTo && anyMw ? anyMw : null;41    const buildingSqm = areaSqm(desc);42    const data: Record<string, unknown> = {43      name: /^switch/i.test(campus) ? campus : `Switch ${campus}`, code: slug.toUpperCase(), aliases: [campus, `Switch ${slug.toUpperCase()}`],44      city, regionName, countryIso2: regionName ? "US" : null,45      tier, plannedPowerMw, totalPowerMw, buildingSqm, renewableClaim: renewableFrom(desc),46      facilityType: "colocation", description: desc,47      externalIds: { switch_slug: slug },48    };49    const src = fromTitle ? "meta:og:title+parse" : "fallback:switch-campus-table";50    const methods: Record<string, string> = {51      name: src, code: "url:slug", city: src, regionName: src, countryIso2: `${src}>state`,52      tier: "meta:description+regex:tier", plannedPowerMw: "meta:description+regex:up_to_mw", totalPowerMw: "meta:description>mw", buildingSqm: "meta:description>sqm", renewableClaim: "meta:description+regex:renewable_v1", facilityType: "meta:description", description: "meta:description", externalIds: "url:slug",53    };54    return [record("facility", `switch:${slug}`, url, data, methods, 0.7)];55  },56};57