@ohhwells/bridge 0.1.54-next.154 → 0.1.54-next.156

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -192,6 +192,59 @@ function deleteSectionFromState(state, sectionId) {
192
192
  return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
193
193
  }
194
194
 
195
+ // src/lib/brand-chrome.ts
196
+ var BRAND_NAME_KEY = "__ohw_brand_name";
197
+ var BRAND_TITLE_KEY = "__ohw_site_title";
198
+ var BRAND_FAVICON_LETTER_KEY = "__ohw_favicon_letter";
199
+ var BRAND_CHROME_KEYS = /* @__PURE__ */ new Set([
200
+ BRAND_NAME_KEY,
201
+ BRAND_TITLE_KEY,
202
+ BRAND_FAVICON_LETTER_KEY
203
+ ]);
204
+ function upsertMeta(selector, attr, token, value) {
205
+ let el = document.head.querySelector(selector);
206
+ if (!el) {
207
+ el = document.createElement("meta");
208
+ el.setAttribute(attr, token);
209
+ document.head.appendChild(el);
210
+ }
211
+ if (el.getAttribute("content") !== value) el.setAttribute("content", value);
212
+ }
213
+ function escapeXml(value) {
214
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
215
+ }
216
+ function applyLetterFavicon(letter) {
217
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="12" fill="#111827"/><text x="32" y="46" font-family="system-ui,-apple-system,Segoe UI,sans-serif" font-size="40" font-weight="700" text-anchor="middle" fill="#ffffff">${escapeXml(letter)}</text></svg>`;
218
+ const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
219
+ let link = document.head.querySelector('link[rel="icon"]');
220
+ if (!link) {
221
+ link = document.createElement("link");
222
+ link.rel = "icon";
223
+ document.head.appendChild(link);
224
+ }
225
+ link.type = "image/svg+xml";
226
+ if (link.href !== href) link.href = href;
227
+ }
228
+ function applyBrandChrome(content) {
229
+ const name = content[BRAND_NAME_KEY];
230
+ if (typeof name === "string" && name.length > 0) {
231
+ document.querySelectorAll("[data-ohw-wordmark]").forEach((el) => {
232
+ if (el.textContent !== name) el.textContent = name;
233
+ if (el.getAttribute("title") !== name) el.setAttribute("title", name);
234
+ });
235
+ }
236
+ const title = content[BRAND_TITLE_KEY];
237
+ if (typeof title === "string" && title.length > 0) {
238
+ if (document.title !== title) document.title = title;
239
+ upsertMeta('meta[property="og:title"]', "property", "og:title", title);
240
+ upsertMeta('meta[name="twitter:title"]', "name", "twitter:title", title);
241
+ }
242
+ const letter = content[BRAND_FAVICON_LETTER_KEY];
243
+ if (typeof letter === "string" && letter.length > 0) {
244
+ applyLetterFavicon(letter);
245
+ }
246
+ }
247
+
195
248
  // src/ui/ai-tree/aiSectionsManager.tsx
196
249
  var import_react_dom = require("react-dom");
197
250
  var import_client = require("react-dom/client");
@@ -15291,11 +15344,13 @@ function OhhwellsBridge() {
15291
15344
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
15292
15345
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
15293
15346
  }
15347
+ applyBrandChrome(content);
15294
15348
  for (const [key, val] of Object.entries(content)) {
15295
15349
  if (key === "__ohw_sections") continue;
15296
15350
  if (key === AI_SECTIONS_KEY) continue;
15297
15351
  if (key === LOGO_PLACEHOLDER_KEY) continue;
15298
15352
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
15353
+ if (BRAND_CHROME_KEYS.has(key)) continue;
15299
15354
  if (applyVideoSettingNode(key, val)) continue;
15300
15355
  if (applyCarouselNode(key, val)) continue;
15301
15356
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15376,10 +15431,12 @@ function OhhwellsBridge() {
15376
15431
  retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
15377
15432
  observer?.disconnect();
15378
15433
  try {
15434
+ applyBrandChrome(content);
15379
15435
  for (const [key, val] of Object.entries(content)) {
15380
15436
  if (key === "__ohw_sections") continue;
15381
15437
  if (key === LOGO_PLACEHOLDER_KEY) continue;
15382
15438
  if (LOGO_IMAGE_KEYS.includes(key)) continue;
15439
+ if (BRAND_CHROME_KEYS.has(key)) continue;
15383
15440
  if (applyVideoSettingNode(key, val)) continue;
15384
15441
  if (applyCarouselNode(key, val)) continue;
15385
15442
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16937,6 +16994,7 @@ function OhhwellsBridge() {
16937
16994
  aiSectionsRef.current = content[AI_SECTIONS_KEY];
16938
16995
  applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
16939
16996
  }
16997
+ applyBrandChrome(content);
16940
16998
  let sectionsJson = null;
16941
16999
  for (const [key, val] of Object.entries(content)) {
16942
17000
  if (key === "__ohw_sections") {
@@ -16946,6 +17004,7 @@ function OhhwellsBridge() {
16946
17004
  if (key === AI_SECTIONS_KEY) continue;
16947
17005
  if (key === LOGO_PLACEHOLDER_KEY) continue;
16948
17006
  if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
17007
+ if (BRAND_CHROME_KEYS.has(key)) continue;
16949
17008
  if (applyVideoSettingNode(key, val)) continue;
16950
17009
  if (applyCarouselNode(key, val)) continue;
16951
17010
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {