PageSourceSearch

https://thescaleup.ca/src/content.js?v=20260511-cms-null-media

js thescaleup.ca collected 2026-10-05 08:54:07 UTC 14,627 bytes, 416 lines download raw bytes

1(function () {
2  const BUILD_TITLE_SINGLE_LINE =
3    "The Defence & Dual-Use pilot cohort is underway, with future cohorts planned every Spring and Fall. Future streams are being developed with industry, investors, and ecosystem leaders.";
4  const BUILD_TITLE_SOFT_BREAK =
5    "The Defence & Dual-Use pilot cohort is underway, with future cohorts planned every Spring and Fall.\nFuture streams are being developed with industry, investors, and ecosystem leaders.";
6  const BUILD_TITLE_WITH_BREAK =
7    "The Defence & Dual-Use pilot cohort is underway, with future cohorts planned every Spring and Fall.\n\nFuture streams are being developed with industry, investors, and ecosystem leaders.";
8
9  const DEFAULT_LANDING_CONTENT = {
10    navigation: {
11      eyebrow: "Get in touch",
12      interestLabel: "Founders - Express Interest",
13      interestHref: "https://airtable.com/app4M8raEWsyOVktS/pagEzxLGODRsnV5N9/form",
14      applyHref: "mailto:[email protected]",
15    },
16    chapters: {
17      brand: {
18        title:
19          "Scale Up is a cohort-based growth-stage platform helping founders transition from building products to operating and scaling companies—bringing together experienced operators, sector experts, investors, and partners to build Canada’s next generation of scaling companies.",
20        secondary: ["Built at UBC Sauder School of Business", "Informed by the success of Creative Destruction Lab Vancouver"],
21        visualLines: [
22          "From Traction to Scalable Growth",
23          "Built at UBC Sauder School of Business",
24          "Informed by the success of Creative Destruction Lab Vancouver",
25        ],
26        mobileVisualLines: [
27          "From Traction to\nScalable Growth",
28          "Built at UBC Sauder School of Business",
29          "Informed by the success of Creative Destruction Lab Vancouver",
30        ],
31        showSecondaryVisualLines: false,
32        desktopVisual: {
33          kind: "video",
34          src: "./public/_videos/SCALEUP FOOTAGE Clip 76.m4v",
35          poster: "./public/_photos/SCALEUPxZAK03546.jpg",
36          alt: "Scale Up participants in session.",
37        },
38        mobileVisual: {
39          kind: "video",
40          src: "./public/_videos/SCALEUP FOOTAGE Clip 76.m4v",
41          poster: "./public/_photos/SCALEUPxZAK03546.jpg",
42          alt: "Scale Up participants in session.",
43        },
44      },
45      context: {
46        title:
47          "Canada produces strong early-stage ventures, but relatively few scale into globally competitive companies. Scale Up exists to help high potential companies with traction make the transition from promising venture to the next great Canadian company.",
48        secondary: [
49          "Our mission is to to domicile the next great Canadian ventures here at home.",
50          "Our mandate is economic development.",
51        ],
52        visualLines: ["Why Scale", "Up Exists"],
53        mobileVisualLines: ["Why Scale", "Up Exists"],
54      },
55      network: {
56        title:
57          "There are few programs designed to identify Canada's highest-potential scale ups and invest sustained time, mentorship, and operating experience into their growth.",
58        secondary: [
59          "Built with founders, operators, investors, sector experts, and corporate partners.",
60          "Designed for companies beyond early traction.",
61        ],
62        visualLines: ["A Different", "Kind of Support"],
63        mobileVisualLines: ["A Different", "Kind of Support"],
64        desktopVisual: {
65          kind: "video",
66          src: "./public/_videos/SCALEUP FOOTAGE Clip 11.mp4",
67          alt: "",
68        },
69        mobileVisual: {
70          kind: "image",
71          src: "./public/_photos/SCALEUPxZAK03443.jpg",
72          alt: "Scale Up session participant seated in discussion.",
73        },
74      },
75      operators: {
76        title:
77          "Through more than 10 years of running Creative Destruction Lab at UBC Sauder, we observed a consistent challenge: the shift from building a product to operating and scaling a Company.",
78        secondary: [
79          "Building teams and organizational systems.",
80          "Creating repeatable enterprise sales.",
81          "Navigating complex markets and operational complexity.",
82        ],
83        visualLines: ["Operating Company", "Challenges"],
84        mobileVisualLines: ["Operating Company", "Challenges"],
85      },
86      scale: {
87        title:
88          "Scale Up combines applied learning, deep operator mentorship, and founder leadership support for founders of companies entering their next stage of growth.",
89        secondary: [
90          "Deep-dive discussions with experienced operators and functional experts.",
91          "Support for the transition from execution-focused foun
91der to organizational leader.",
92        ],
93        visualLines: ["Education", "Mentorship", "Leadership"],
94        mobileVisualLines: ["Education", "Mentorship", "Leadership"],
95        desktopVisual: {
96          kind: "video",
97          src: "./public/_videos/SCALEUP FOOTAGE Clip 23.mp4",
98          alt: "Scale Up education, mentorship, and leadership footage.",
99        },
100        mobileVisual: {
101          kind: "video",
102          src: "./public/_videos/SCALEUP FOOTAGE Clip 23.mp4",
103          alt: "Scale Up education, mentorship, and leadership footage.",
104        },
105      },
106      build: {
107        title: BUILD_TITLE_WITH_BREAK,
108        secondary: [
109          "Launching with a Defence & Dual-Use Stream.",
110          "Interested in shaping a future stream? Let’s talk.",
111        ],
112        visualLines: [
113          "Supporting high-potential Canadian ventures scale into defence, dual-use, and advanced industrial markets",
114        ],
115        mobileVisualLines: [
116          "Supporting high-potential Canadian ventures scale into defence, dual-use, and advanced industrial markets",
117        ],
118      },
119      support: {
120        title: "Supported By:",
121        secondary: ["[email protected]"],
122        desktopVisual: {
123          kind: "video",
124          src: "./public/_videos/SCALEUP FOOTAGE Clip 45.mp4",
125          alt: "Scale Up gathering footage.",
126        },
127        mobileVisual: {
128          kind: "video",
129          src: "./public/_videos/SCALEUP FOOTAGE Clip 45.mp4",
130          alt: "Scale Up gathering footage.",
131        },
132        logoWall: {
133          src: "./assets/partner-logos/logo-wall.png",
134          alt: "BDC, Innovate BC, Fasken, PacifiCan, and Mitsubishi Canada Ltd. logos",
135        },
136      },
137    },
138  };
139
140  const query = `*[_type == "landingPage" && _id == "landingPage"][0]{
141    navigation,
142    "chapters": chapters[]{
143      key,
144      title,
145      secondary,
146      visualLines,
147      mobileVisualLines,
148      showSecondaryVisualLines,
149      actions,
150      contactLabel,
151      contactSite,
152      contactSiteHref,
153      contactEmail,
154      contactEmailHref,
155      desktopVisual{kind, alt, existingSrc, "uploadedSrc": asset->url, poster{existingSrc, "uploadedSrc": asset->url}},
156      mobileVisual{kind, alt, existingSrc, "uploadedSrc": asset->url, poster{existingSrc, "uploadedSrc": asset->url}},
157      logoWall{kind, alt, existingSrc, "uploadedSrc": asset->url}
158    }
159  }`;
160
161  const mergeObjects = (base, override) => {
162    if (!override || Array.isArray(override) || typeof override !== "object") {
163      return override ?? base;
164    }
165
166    return Object.fromEntries(
167      Object.keys({ ...base, ...override }).map((key) => [
168        key,
169        mergeObjects(base?.[key], override[key]),
170      ]),
171    );
172  };
173
174  const normalizeMedia = (media) => {
175    const source = media && typeof media === "object" ? media : {};
176
177    return {
178      kind: source.kind || "image",
179      src: source.uploadedSrc || source.existingSrc || source.src || "",
180      alt: source.alt || "",
181      poster: source.poster?.uploadedSrc || source.poster?.existingSrc || source.poster || "",
182    };
183  };
184
185  function normalizeSanityContent(content) {
186    if (!content) {
187      return DEFAULT_LANDING_CONTENT;
188    }
189
190    const chapters = {};
191    (content.chapters || []).forEach((chapter) => {
192      if (!chapter?.key) {
193        return;
194      }
195
196      const normalizedChapter = {
197        ...chapter,
198        desktopVisual: normalizeMedia(chapter.desktopVisual),
199        mobileVisual: normalizeMedia(chapter.mobileVisual),
200        logoWall: normalizeMedia(chapter.logoWall),
201      };
202
203      if (
204        normalizedChapter.key === "build" &&
205        [BUILD_TITLE_SINGLE_LINE, BUILD_TITLE_SOFT_BREAK].includes(normalizedChapter.title)
206      ) {
207        normalizedChapter.title = BUILD_TITLE_WITH_BREAK;
208      }
209
210      if (
211        normalizedChapter.key === "build" &&
212        normalizedChapter.secondary?.[0] === "Pilot cohort underway" &&
213        normalizedChapter.secondary?.[1] === "Future cohorts every Spring & Fall"
214      ) {
215        normalizedChapter.secondary = DEFAULT_LANDING_CONTENT.chapters.build.secondary;
216      }
217
218      chapters[chapter.key] = normalizedChapter;
219    });
220
221    return mergeObjects(DEFAULT_LANDING_CONTENT, {
222      navigation: content.navigation,
223      chapters,
224    });
225  }
226
227  function getPathValue(content, path) {
228    return path.split(".").reduce((value, part) => value?.[part], content);
229  }
230
231  function setText(element, value) {
232    if (value === undefined || value === null) {
233      return;
234    }
235
236    if (Array.isArray(value)) {
237      const children = Array.from(element.children);
238      value.forEach((line, index) => {
239        const target = children[index] || document.createElement("span");
240        target.textContent = line;
241        if (!target.parentElement) {
242          element.append(target);
243        }
244      });
245      children.slice(value.length).forEach((child) => child.remove());
246      return;
247    }
248
249    element.textContent = value;
250  }
251
252  function linkBuildSecondaryContact(content) {
253    const element = document.querySelectorAll?.('[data-cms-text="chapters.build.secondary"]')?.[0];
254    const href = content.navigation?.applyHref;
255
256    if (!element || !href) {
257      return;
258    }
259
260    const paragraphs = Array.from(element.children);
261    const contactParagraph = paragraphs[1];
262    const marker = "Let’s talk.";
263
264    if (!contactParagraph || !contactParagraph.textContent.includes(marker)) {
265      return;
266    }
267
268    const text = contactParagraph.textContent;
269    const [before] = text.split(marker);
270    const link = document.createElement("a");
271
272    contactParagraph.textContent = before;
273    link.href = href;
274    link.textContent = marker;
275    link.dataset.cmsHref = "navigation.applyHref";
276    contactParagraph.append(link);
277  }
278
279  function setSecondaryVisualLineVisibility(element, value) {
280    const showSecondaryLines = value === true;
281    Array.from(element.children).forEach((child, index) => {
282      child.hidden = !showSecondaryLines && index > 0;
283    });
284  }
285
286  function setHref(element, value) {
287    if (value) {
288      element.setAttribute("href", value);
289    }
290  }
291
292  function setVideo(element, value) {
293    if (!value) {
294      return;
295    }
296
297    if (!/\.(mp4|m4v|webm)(?:[?#].*)?$/i.test(value)) {
298      return;
299    }
300
301    const video = element.matches("video") ? element : element.querySelector("video");
302    const source = video?.querySelector("source");
303
304    if (!video || !source) {
305      return;
306    }
307
308    source.setAttribute("src", value);
309    video.load();
310  }
311
312  function setImage(element, value) {
313    if (!value) {
314      return;
315    }
316
317    const image = element.matches("img") ? element : element.querySelector("img");
318    image?.setAttribute("src", value);
319  }
320
321  function setAlt(element, value) {
322    if (value === undefined || value === null) {
323      return;
324    }
325
326    if (element.matches("img")) {
327      element.setAttribute("alt", value);
328    } else if (element.matches("video")) {
329      element.setAttribute("aria-label", value);
330    }
331  }
332
333  function setPoster(element, value) {
334    if (value && element.matches("video")) {
335      element.setAttribute("poster", value);
336    }
337  }
338
339  function applyLandingContent(content) {
340    document.querySelectorAll("[data-cms-text]").forEach((element) => {
341      setText(element, getPathValue(content, element.dataset.cmsText));
342    });
343
344    linkBuildSecondaryContact(content);
345
346    document.querySelectorAll("[data-cms-secondary-visual-lines]").forEach((element) => {
347      setSecondaryVisualLineVisibility(
348        element,
349        getPathValue(content, element.dataset.cmsSecondaryVisualLines),
350      );
351    });
352
353    document.querySelectorAll("[data-cms-href]").forEach((element) => {
354      setHref(element, getPathValue(content, element.dataset.cmsHref));
355    });
356
357    document.querySelectorAll("[data-cms-action-text]").forEach((element) => {
358      setText(element.querySelector(".story-action-list__copy") || element, getPathValue(content, element.dataset.cmsActionText));
359    });
360
361    document.querySelectorAll("[data-cms-video]").forEach((element) => {
362      setVideo(element, getPathValue(content, element.dataset.cmsVideo));
363    });
364
365    document.querySelectorAll("[data-cms-image]").forEach((element) => {
366      setImage(element, getPathValue(content, element.dataset.cmsImage));
367    });
368
369    document.querySelectorAll("[data-cms-alt]").forEach((element) => {
370      setAlt(element, getPathValue(content, element.dataset.cmsAlt));
371    });
372
373    document.querySelectorAll("[data-cms-poster]").forEach((element) => {
374      setPoster(element, getPathValue(content, element.dataset.cmsPoster));
375    });
376  }
377
378  async function fetchSanityLandingContent() {
379    const config = window.SCALEUP_SANITY_CONFIG || {};
380
381    if (!config.projectId || !config.dataset) {
382      return DEFAULT_LANDING_CONTENT;
383    }
384
385    const encodedQuery = encodeURIComponent(query);
386    const cdn = config.useCdn === false ? "api" : "apicdn";
387    const endpoint = `https://${config.projectId}.${cdn}.sanity.io/v${config.apiVersion || "2025-05-11"}/data/query/${config.dataset}?query=${encodedQuery}`;
388    const response = await fetch(endpoint);
389
390    if (!response.ok) {
391      throw new Error(`Sanity content request failed with ${response.status}`);
392    }
393
394    const payload = await response.json();
395    return normalizeSanityContent(payload.result);
396  }
397
398  async function initLandingContent() {
399    try {
400      const content = await fetchSanityLandingContent();
401      applyLandingContent(content);
402      return content;
403    } catch (error) {
404      console.warn("[Scale Up CMS] Using static fallback content.", error);
405      applyLandingContent(DEFAULT_LANDING_CONTENT);
406      return DEFAULT_LANDING_CONTENT;
407    }
408  }
409
410  window.ScaleUpContent = {
411    DEFAULT_LANDING_CONTENT,
412    applyLandingContent,
413    fetchSanityLandingContent,
414    initLandingContent,
415  };
416})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.