1/* Shared company-card renderer for the homepage preview and /:domain result. 2 * Both surfaces mount this exact markup; the homepage adds only the flip 3 * wrapper and demo data, while card.js supplies live source-backed data. */ 4(function () { 5 "use strict"; 6 7 var COPY_RESET_MS = 1600; 8 var CARD_SUMMARY_MAX_CHARACTERS = 96; 9 var API_ORIGIN = "https://xagent.id"; 10 var LABELS = { 11 en: { 12 publicIdentity: "Public business identity", 13 publicProfile: "Public company profile", 14 observed: "Publicly observed", 15 pending: "Pending", 16 unavailable: "Status unavailable", 17 officialWebsite: "Official website", 18 agentId: "Agent ID", 19 topics: "Website content topics", 20 companyOfferings: "Company products and services", 21 insufficientCompanyEvidence: "These sources do not yet establish the company's profile.", 22 moreTopics: "+ {count} more", 23 source: "Source: public company website", 24 waiting: "Waiting for source snapshot", 25 readAt: "Read on {date}", 26 readRecorded: "Read time recorded", 27 machineInterface: "Machine interface · A2A", 28 a2aAgentCard: "A2A Agent Card", 29 machineIdentity: "Machine-readable business identity", 30 assets: "AI-readable assets", 31 endpoint: "Agent-readable URL", 32 claimedTitle: "Company-confirmed profile", 33 claimedNote: "Company confirmation enables full brand assets.", 34 unclaimedTitle: "Not yet claimed by the company", 35 unclaimedNote: "A third-party profile built by xAgent ID from public information. Not an official publication, partnership or endorsement.", 36 gleifRecord: "GLEIF LEI legal entity record", 37 gleifIndex: "GLEIF Global LEI Index", 38 gleifLei: "GLEIF LEI:", 39 currentRecord: "Current record", 40 candidateRecord: "Candidate record · company confirmation required", 41 multipleCandidates: "Multiple candidates · company selection required", 42 noRecord: "No matching LEI record", 43 lookupUnavailable: "Lookup temporarily unavailable", 44 domainReverification: "Domain control re-verification required", 45 inactiveRecord: "Record is not current", 46 notChecked: "Not checked", 47 copy: "Copy", 48 copied: "Copied", 49 copyAgentId: "Copy Agent ID", 50 assetStates: { 51 available: "Readable", 52 observed: "Provided by website", 53 derived: "Derived from public brand", 54 ready_to_publish: "Ready for company approval", 55 source_indexed_draft: "Source-indexed draft", 56 owner_approval_required: "Company approval required", 57 not_observed: "Not observed in this read" 58 } 59 }, 60 zh: { 61 publicIdentity: "伿¥å ¬é身å", 62 publicProfile: "å ¬é伿¥è³æ", 63 observed: "å ¬éè³æè§å¯", 64 pending: "å¾ å»ºç«", 65 unavailable: "çæ æªæä¾", 66 officialWebsite: "伿¥å®ç¶²", 67 agentId: "Agent ID", 68 topics: "ç¶²ç«å ¬é說æç主é¡", 69 companyOfferings: "伿¥ç¢åèæå", 70 insufficientCompanyEvidence: "ç®å便ºä¸è¶³ä»¥å»ºç«ä¼æ¥ç°¡ä»ã", 71 moreTopics: "ï¼ å¦å¤ {count} å", 72 source: "便ºï¼ä¼æ¥å ¬éç¶²ç«", 73 waiting: "çå¾ ä¾æºå¿«ç §", 74 readAt: "è®åæ¼ {date}", 75 readRecorded: "è®åæéå·²è¨é", 76 machineInterface: "æ©å¨ä»é¢ · A2A", 77 a2aAgentCard: "A2A Agent Card", 78 machineIdentity: "æ©å¨å¯è®ä¼æ¥èº«å", 79 assets: "AI å¯è®è³ç¢", 80 endpoint: "Agent å¯è®ç¶²å", 81 claimedTitle: "伿¥å·²èªé ", 82 claimedNote: "伿¥ç¢ºèªå¾å¯é¡¯ç¤ºå®æ´åçè³ç¢ã", 83 unclaimedTitle: "宿¹å°æªèªé ", 84 unclaimedNote: "ç± xAgent ID ä¾å ¬éè³è¨å»ºç«çç¬¬ä¸æ¹æªæ¡ï¼é伿¥å®æ¹ç¼å¸ãåä½æèæ¸ã", 85 gleifRecord: "GLEIF LEI æ³å®å¯¦é«ç´é", 86 gleifIndex: "GLEIF Global LEI Index", 87 gleifLei: "GLEIF LEI:", 88 currentRecord: "ç´éææ", 89 candidateRecord: "æ¾å°åé¸ç´é · å¾ ä¼æ¥ç¢ºèª", 90 multipleCandidates: "æ¾å°å¤çåé¸ Â· å¾ ä¼æ¥é¸æ", 91 noRecord: "æªæ¾å°ç¸ç¬¦ LEI ç´é", 92 lookupUnavailable: "æ«æç¡æ³æ¥è©¢", 93 domainReverification: "ééæ°é©èç¶²åæ§å¶æ¬", 94 inactiveRecord: "ç´éç®åéææçæ ", 95 notChecked: "å°æªæ¥è©¢", 96 copy: "è¤è£½", 97 copied: "å·²è¤è£½", 98 copyAgentId: "è¤è£½ Agent ID", 99 assetStates: { 100 available: "å¯è®å", 101 observed: "ç¶²ç«å·²æä¾", 102 derived: "ä¾å ¬éåçæ¨å°", 103 ready_to_publish: "å¯ä¾ä¼æ¥æ ¸å", 104 source_indexed_draft: "便ºç´¢å¼è稿", 105 owner_approval_required: "é伿¥æ ¸å", 106 not_observed: "æ¬æ¬¡æªè®å" 107 } 108 } 109 }; 110 111 function labelsFor(root) { 112 var requested = root.getAttribute("data-company-card-locale") || document.documentElement.lang || "en"; 113 return String(requested).toLowerCase().startsWith("zh") ? LABELS.zh : LABELS.en; 114 } 115 116 function copyButtonMarkup(labels) { 117 return [ 118 '<button type="button" class="card-public-id" data-copy-agent-id aria-label="', labels.copyAgentId, '" disabled>', 119 '<span class="card-public-id-heading"><span>xagent ID</span><span class="card-copy-affordance"><span data-copy-feedback>
119', labels.copy, '</span> <span aria-hidden="true">â§</span></span></span>', 120 '<code data-card-public-agent-id-text>xagent.id/', labels.pending, '</code>', 121 '</button>' 122 ].join(""); 123 } 124 125 function legalEntityMarkup(labels) { 126 return [ 127 '<a class="namecard-legal-entity" data-card-lei-card data-card-lei-link aria-label="', labels.gleifRecord, '" target="_blank" rel="noopener" hidden>', 128 '<span class="namecard-legal-entity-icon namecard-gleif-icon namecard-legal-entity-index-icon" aria-hidden="true">', 129 '<img src="https://www.gleif.org/assets/build/img/logo/gleif-logo-new.svg" alt="" loading="lazy">', 130 '</span>', 131 '<span class="namecard-legal-entity-copy"><small class="namecard-legal-entity-label">', labels.gleifLei, '</small><code class="namecard-legal-entity-code" data-card-lei-value hidden></code><small data-card-lei-status>', labels.currentRecord, '</small></span>', 132 '<span class="namecard-legal-entity-arrow" data-card-lei-arrow aria-hidden="true">â</span>', 133 '</a>' 134 ].join(""); 135 } 136 137 function legalEntitySettingMarkup(labels) { 138 return [ 139 '<a class="namecard-legal-entity namecard-legal-entity-setting" data-card-lei-setting data-card-lei-link aria-label="', labels.gleifIndex, '" target="_blank" rel="noopener" hidden>', 140 '<span class="namecard-legal-entity-icon namecard-gleif-icon namecard-legal-entity-index-icon" aria-hidden="true">', 141 '<img src="https://www.gleif.org/assets/build/img/logo/gleif-logo-new.svg" alt="" loading="lazy">', 142 '</span>', 143 '<span class="namecard-legal-entity-copy"><small class="namecard-legal-entity-label">', labels.gleifLei, '</small><code class="namecard-legal-entity-code" data-card-lei-value data-card-lei-setting-value hidden></code><small data-card-lei-status>', labels.notChecked, '</small></span>', 144 '<span class="namecard-legal-entity-arrow" data-card-lei-arrow aria-hidden="true" hidden>â</span>', 145 '</a>' 146 ].join(""); 147 } 148 149 function a2aBadgeMarkup(labels) { 150 var pendingLabel = labels.a2aAgentCard; 151 return [ 152 '<span class="namecard-standard namecard-standard-a2a" data-card-a2a-badge title="', pendingLabel, '">', 153 '<span class="namecard-a2a-icon" aria-hidden="true"><img src="/assets/a2a-icon.svg" alt=""></span>', 154 '<span data-card-a2a-label>', pendingLabel, '</span>', 155 '</span>' 156 ].join(""); 157 } 158 159 function standardsMarkup(labels, legalEntity) { 160 return '<div class="namecard-standards-row">' + legalEntity + a2aBadgeMarkup(labels) + '</div>'; 161 } 162 163 function legalEntityStatusLabel(labels, legalEntity, current) { 164 if (current) return labels.currentRecord; 165 switch (legalEntity.status) { 166 case "candidate_requires_owner_confirmation": return labels.candidateRecord; 167 case "multiple_candidates_require_owner_selection": return labels.multipleCandidates; 168 case "not_found": return labels.noRecord; 169 case "lookup_unavailable": 170 case "owner_confirmation_refresh_unavailable": return labels.lookupUnavailable; 171 case "owner_confirmation_suspended": return labels.domainReverification; 172 case "owner_confirmation_record_inactive": return labels.inactiveRecord; 173 case "not_requested": return labels.notChecked; 174 default: return labels.unavailable; 175 } 176 } 177 178 function renderA2ALabel(root, labels) { 179 var label = labels.a2aAgentCard; 180 setText(root, "[data-card-a2a-label]", label); 181 root.querySelectorAll("[data-card-a2a-badge]").forEach(function (badge) { 182 badge.title = label; 183 badge.setAttribute("aria-label", label); 184 }); 185 } 186 187 function facesMarkup(labels) { 188 var ownership = [ 189 '<span class="namecard-ownership-copy">', 190 '<strong data-card-ownership-title>', labels.unclaimedTitle, '</strong>', 191 '<small data-card-ownership-note>', labels.unclaimedNote, '</small>', 192 '</span>' 193 ].join(""); 194 var logoAttribution = [ 195 '<span class="namecard-logo-attribution" data-card-logo-attribution hidden>', 196 '<a data-card-logo-source target="_blank" rel="noopener"></a>', 197 '<span aria-hidden="true"> · </span>', 198 '<a data-card-logo-license target="_blank" rel="noopener"></a>', 199 '</span>' 200 ].join(""); 201 var front = [ 202 '<article class="namecard-face namecard-front company-card-human" data-namecard data-company-card-human aria-label="Human-readable side">', 203 '<header class="namecard-top namecard-top-front"><span class="namecard-standard">', labels.publicIdentity, '</span></header>', 204 '<div class="namecard-front-main">', 205 '<div class="namecard-branding namecard-branding-front"><span class="namecard-logo-stack"><span class="namecard-logo-wrap"><img data-card-logo alt="" hidden><span data-card-logo-fallback></span></span>
205', logoAttribution, '</span>', ownership, '</div>', 206 standardsMarkup(labels, legalEntityMarkup(labels)), 207 '<p class="namecard-eyebrow"><span data-card-profile-state>', labels.observed, '</span><span aria-hidden="true"> · </span><span>', labels.publicProfile, '</span></p>', 208 '<h2 class="namecard-name" data-card-name>', labels.pending, '</h2>', 209 '<p class="namecard-desc" data-card-description hidden></p>', 210 '</div>', 211 '<div class="namecard-front-grid">', 212 '<div><span>', labels.officialWebsite, '</span><strong><a data-card-official-host target="_blank" rel="noopener">', labels.pending, '</a></strong></div>', 213 '<div><span>', labels.agentId, '</span><strong><a data-card-public-agent-id target="_blank" rel="noopener">xagent.id/', labels.pending, '</a></strong></div>', 214 '</div>', 215 '<p class="namecard-section-label" data-card-topics-label>', labels.topics, '</p>', 216 '<ul class="namecard-topics" data-card-topics></ul>', 217 '<div class="namecard-source-row"><span><span>', labels.source, '</span><span aria-hidden="true"> · </span><span data-card-freshness>', labels.waiting, '</span></span><span class="namecard-verify partial" data-verify-badge>', labels.unclaimedTitle, '</span></div>', 218 '</article>' 219 ].join(""); 220 221 var back = [ 222 '<article class="namecard-face namecard-back company-card-agent" data-company-card-agent aria-label="Agent-readable side">', 223 '<header class="namecard-top"><span class="namecard-brand" data-card-name>', labels.pending, '</span><span class="namecard-standard">', labels.machineInterface, '</span></header>', 224 '<div class="namecard-back-main">', 225 '<div class="namecard-branding namecard-branding-back"><span class="namecard-logo-stack"><span class="namecard-logo-wrap"><img data-card-logo alt="" hidden><span data-card-logo-fallback></span></span>', logoAttribution, '</span>', ownership, '</div>', 226 standardsMarkup(labels, legalEntitySettingMarkup(labels)), 227 '<p class="namecard-eyebrow">', labels.machineIdentity, '</p>', 228 '<p class="namecard-desc namecard-agent-summary" data-card-description hidden></p>', 229 '</div>', 230 '<dl class="namecard-agent-facts">', 231 '<div><dt>', labels.officialWebsite, '</dt><dd><a data-card-official-host target="_blank" rel="noopener">', labels.pending, '</a></dd></div>', 232 '<div><dt>', labels.agentId, '</dt><dd><a data-card-public-agent-id target="_blank" rel="noopener">xagent.id/', labels.pending, '</a></dd></div>', 233 '</dl>', 234 '<p class="namecard-section-label">', labels.assets, '</p>', 235 '<ul class="namecard-machine-assets" data-card-machine-assets></ul>', 236 '<div class="namecard-machine-link"><span>', labels.endpoint, '</span><a data-card-machine-url target="_blank" rel="noopener">xagent.id/', labels.pending, '.json</a></div>', 237 '<footer class="namecard-foot">', copyButtonMarkup(labels), '</footer>', 238 '</article>' 239 ].join(""); 240 241 return front + back; 242 } 243 244 function copyText(value) { 245 if (navigator.clipboard && window.isSecureContext) return navigator.clipboard.writeText(value); 246 return new Promise(function (resolve, reject) { 247 var area = document.createElement("textarea"); 248 area.value = value; 249 area.setAttribute("readonly", ""); 250 area.style.position = "fixed"; 251 area.style.opacity = "0"; 252 document.body.appendChild(area); 253 area.select(); 254 try { 255 if (!document.execCommand("copy")) throw new Error("copy_failed"); 256 resolve(); 257 } catch (error) { 258 reject(error); 259 } finally { 260 area.remove(); 261 } 262 }); 263 } 264 265 function installCopy(root, labels) { 266 function translated(source, fallback) { 267 return window.XAgentI18n && window.XAgentI18n.t ? window.XAgentI18n.t(source) : fallback; 268 } 269 root.querySelectorAll("[data-copy-agent-id]").forEach(function (button) { 270 button.addEventListener("click", function (event) { 271 event.stopPropagation(); 272 var value = button.dataset.copyValue || ""; 273 if (!value) return; 274 var feedback = button.querySelector("[data-copy-feedback]"); 275 copyText(value).then(function () { 276 button.dataset.copyState = "copied"; 277 if (feedback) feedback.textContent = translated("Copied", labels.copied); 278 window.setTimeout(function () { 279 delete button.dataset.copyState; 280 if (feedback) feedback.textContent = translated("Copy", labels.copy); 281 }, COPY_RESET_MS); 282 }).catch(function () { 283 if (feedback) feedback.textContent = value; 284 }); 285 }); 286 }); 287 } 288 289 function setText(root, selector, value) { 290 root.querySelectorAll(selector).forEach(function (node) { node.textContent = value; }); 291 } 292 293 function safeHttpUrl(value) { 294 var raw = String(value || "").trim(); 295 if (!raw) return ""; 296 try { 297 var parsed = new URL(raw, window.location.href); 298 return parsed.protocol === "http:" || parsed.protocol === "https:" ? parsed.href : ""; 299 } catch (_error) { 300 return ""; 301 } 302 } 303 304 function safeFeaturedCardSource(source) { 305 try { 306 var parsed = new URL(String(source || ""), API_ORIGIN); 307 if ( 308 parsed.protocol !== "https:" || 309 parsed.origin !== API_ORIGIN || 310 !["/api/featured-card", "/api/featured-card/"].includes(parsed.pathname) || 311 parsed.username || 312 parsed.password 313 ) return ""; 314 return parsed.href; 315 } catch (_error) { 316 return ""; 317 } 318 } 319 320 function safeGleifRecordUrl(value, lei) { 321 var normalizedLei = String(lei || "").trim().toUpperCase(); 322 var safeUrl = safeHttpUrl(value); 323 if (!safeUrl || !/^[A-Z0-9]{20}$/.test(normalizedLei)) return ""; 324 try { 325 var parsed = new URL(safeUrl); 326 if ( 327 parsed.protocol !== "https:" || 328 parsed.hostname !== "search.gleif.org" || 329 parsed.username || 330 parsed.password || 331 parsed.port || 332 parsed.pathname !== "/" || 333 parsed.search 334 ) return ""; 335 return parsed.hash === "#/record/" + normalizedLei ? parsed.href : ""; 336 } catch (_error) { 337 return ""; 338 } 339 } 340 341 function ownerConfirmedLegalEntity(legalEntity) { 342 return Boolean( 343 legalEntity.status === "owner_confirmed" && 344 legalEntity.current_record && 345 legalEntity.badge && 346 legalEntity.badge.visible 347 ); 348 } 349 350 function ownerConfirmableLegalEntity(legalEntity) { 351 var match = legalEntity.match || {}; 352 return Boolean( 353 legalEntity.schema === "xagent-legal-entity-identity-v1" && 354 legalEntity.status === "candidate_requires_owner_confirmation" && 355 legalEntity.lookup_status === "record_found" && 356 legalEntity.current_record === true && 357 legalEntity.needs_owner_confirmation === true && 358 match.needs_owner_confirmation === true && 359 (match.match_type === "exact" || match.match_type === "candidate") && 360 Array.isArray(match.matched_fields) && 361 match.matched_fields.indexOf("official_name_exact") !== -1 && 362 legalEntity.badge && 363 legalEntity.badge.visible === false 364 ); 365 } 366 367 function hasDisplayableLei(card) { 368 var legalEntity = (card || {}).legal_entity_identity || {}; 369 return Boolean( 370 (ownerConfirmedLegalEntity(legalEntity) || ownerConfirmableLegalEntity(legalEntity)) && 371 safeGleifRecordUrl(legalEntity.record_url, legalEntity.lei) 372 ); 373 } 374 375 function setLinks(root, selector, href, label) { 376 var safeUrl = safeHttpUrl(href); 377 root.querySelectorAll(selector).forEach(function (link) { 378 link.textContent = label || href || "â"; 379 if (safeUrl) link.href = safeUrl; 380 else link.removeAttribute("href"); 381 }); 382 } 383 384 function safeColor(value, fallback) { 385 return /^#[0-9a-f]{6}$/i.test(String(value || "")) ? String(value) : fallback; 386 } 387 388 function safeFontFamily(value) {
389 value = String(value || "").trim(); 390 return /^[a-z0-9][a-z0-9 ._-]{1,62}$/i.test(value) ? value : ""; 391 } 392 393 function wikimediaCommonsLogo(logo, subjectHost) { 394 logo = logo && typeof logo === "object" ? logo : {}; 395 var subject = normalizeLogoHost(String(subjectHost || "").trim().replace(/^www\./i, "")); 396 var allowed = { 397 "tsmc.com": { 398 source: "wikimedia_commons", 399 url: "https://xagent.id/assets/company-logos/tsmc-wordmark.svg", 400 asset_path: "/assets/company-logos/tsmc-wordmark.svg", 401 sha256: "5e843f0867a47a2f5effa0b73bee3b225651ee89da0e87ee07d6cbb01e1a5887", 402 source_url: "https://commons.wikimedia.org/wiki/File:TSMC_wordmark.svg", 403 license_name: "PD-shape", 404 license_url: "https://commons.wikimedia.org/wiki/Template:PD-shape", 405 observed_at: "2026-09-29T07:55:00Z", 406 officiality: "not_official", 407 same_site_verified: false, 408 evidence: "Wikimedia Commons file page lists Public domain (PD-shape) with a trademark notice." 409 }, 410 "tesla.com": { 411 source: "wikimedia_commons", 412 url: "https://xagent.id/assets/company-logos/tesla-motors.svg", 413 asset_path: "/assets/company-logos/tesla-motors.svg", 414 sha256: "63dffdd057fb53b00a6380476cff9bc424664b6eb3bbc82ef89f839f10717f6c", 415 source_url: "https://commons.wikimedia.org/wiki/File:Tesla_Motors.svg", 416 license_name: "PD-textlogo", 417 license_url: "https://commons.wikimedia.org/wiki/Template:PD-textlogo", 418 observed_at: "2026-09-27T21:55:04Z", 419 officiality: "not_official", 420 same_site_verified: false, 421 evidence: "Wikimedia Commons file page lists Public domain (PD-textlogo)." 422 }, 423 "openai.com": { 424 source: "wikimedia_commons", 425 url: "https://xagent.id/assets/company-logos/openai-logo-2025-wordmark.svg", 426 asset_path: "/assets/company-logos/openai-logo-2025-wordmark.svg", 427 sha256: "6e4c87d52178f47077b698ced2fb181a8b0115e031cce42f62c6ca7c83d46b9d", 428 source_url: "https://commons.wikimedia.org/wiki/File:OpenAI_logo_2025_(wordmark).svg", 429 license_name: "PD-textlogo", 430 license_url: "https://commons.wikimedia.org/wiki/Template:PD-textlogo", 431 observed_at: "2026-09-27T21:53:03Z", 432 officiality: "not_official", 433 same_site_verified: false, 434 evidence: "Wikimedia Commons file page lists Public domain (PD-textlogo)." 435 } 436 }; 437 var expected = allowed[subject]; 438 if (!expected) return null; 439 var matches = Object.keys(expected).every(function (field) { 440 return logo[field] === expected[field]; 441 }) && validObservedAt(logo.observed_at); 442 return matches ? Object.assign({}, expected, {source_name: "Wikimedia Commons"}) : null; 443 } 444 445 function logoHostLooksNumeric(host) { 446 return /^(?:\d+|0x[0-9a-f]+)(?:\.(?:\d+|0x[0-9a-f]+))*$/i.test(host); 447 } 448 449 function normalizeLogoHost(value) { 450 var host = String(value || "").trim().toLowerCase(); 451 if (!host || /[\/:@]/.test(host)) return ""; 452 if (host.includes("\\")) return ""; 453 if (/[\u00df\u03c2\u200c\u200d]/.test(host)) return ""; 454 if (host.endsWith(".")) host = host.slice(0, -1); 455 if (!host || host.endsWith(".") || host.split(".").some(function (label) { return !label; })) return ""; 456 if (logoHostLooksNumeric(host)) return ""; 457 try { 458 host = new URL("https://" + host + "/").hostname.toLowerCase(); 459 } catch (_error) { 460 return ""; 461 } 462 if (host.endsWith(".")) host = host.slice(0, -1); 463 if (!host || host.endsWith(".") || host.length > 253) return ""; 464 var labels = host.split("."); 465 if (labels.some(function (label) { 466 return !label || label.length > 63 || !/^[a-z0-9-]+$/.test(label) || label.startsWith("-") || label.endsWith("-"); 467 })) return ""; 468 if (logoHostLooksNumeric(host)) return ""; 469 return host; 470 } 471 472 function logoHostMatchesCard(host, subjectHost, sameSiteVerified) { 473 var normalizedHost = normalizeLogoHost(host); 474 var normalizedSubject = normalizeLogoHost(subjectHost); 475 return Boolean( 476 normalizedHost && 477 normalizedSubject && 478 (sameSiteVerified === true || normalizedHost === normalizedSubject) 479 ); 480 } 481 482 function displayableLogo(logo, subjectHost) { 483 logo = logo && typeof logo === "object" ? logo : {}; 484 var source = String(logo.source || "").trim(); 485 if (source === "wikimedia_commons") { 486 var commons = wikimediaCommonsLogo(logo, subjectHost); 487 return commons ? commons.url : ""; 488 } 489 if (source === "wikimedia_commons_auto") { 490 return autoCommonsLogoUrl(logo); 491 } 492 var evidence = String(logo.evidence || "").trim(); 493 var observedAt = String(logo.observed_at || "").trim(); 494 var sourceUrl = String(logo.source_url || "").trim(); 495 var logoUrl = String(logo.url || "").trim(); 496 var allowedSource = ["json_ld", "site_icon", "known_public_brand_catalog"].indexOf(source) !== -1; 497 var allowedEvidence = Boolean( 498 evidence && ( 499 (source === "json_ld" && evidence.indexOf("JSON-LD") !== -1) || 500 (source === "site_icon" && evidence === "Official favicon or apple-touch-icon link") || 501 source === "known_public_brand_catalog" 502 ) 503 ); 504 if ( 505 !allowedSource || 506 !allowedEvidence || 507 !validObservedAt(observedAt) 508 ) return ""; 509 function officialHost(value) { 510 var match = String(value || "").trim().match(/^https:\/\/([^/?#]*)/i); 511 if (!match || !match[1] || match[1].includes("@") || match[1].includes(":")) return ""; 512 return normalizeLogoHost(match[1]); 513 } 514 var normalizedSubject = normalizeLogoHost(subjectHost); 515 var normalizedUrl = officialHost(logoUrl); 516 var normalizedSource = officialHost(sourceUrl); 517 var official = normalizedSubject && 518 logoHostMatchesCard(normalizedUrl, normalizedSubject, logo.same_site_verified === true) && 519 logoHostMatchesCard(normalizedSource, normalizedSubject, logo.same_site_verified === true); 520 if (!official) return "";
521 return mirroredAssetUrl(logo.mirror_url, logo.mirror_sha256) || logoUrl; 522 } 523 524 function mirroredAssetUrl(url, sha256) { 525 var match = String(url || "").match(/^https:\/\/xagent\.id\/assets\/company-logos\/m\/([0-9a-f]{64})\.(svg|png|jpg|webp|gif|ico)$/); 526 return match && match[1] === String(sha256 || "") ? match[0] : ""; 527 } 528 529 function autoCommonsLogoUrl(logo) { 530 var license = String(logo.license_name || "").trim(); 531 var licensed = /^(public domain|pd(?:[-\s].*)?|cc0(?:\s.*)?)$/i.test(license); 532 var fromCommons = String(logo.source_url || "").indexOf("https://commons.wikimedia.org/wiki/File:") === 0; 533 if (!licensed || !fromCommons || logo.officiality !== "not_official" || logo.same_site_verified !== false) return ""; 534 return mirroredAssetUrl(logo.url, logo.sha256); 535 } 536 537 function validObservedAt(value) { 538 var match = String(value || "").trim().match( 539 /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?Z)?$/ 540 ); 541 if (!match) return false; 542 var year = Number(match[1]); 543 var month = Number(match[2]); 544 var day = Number(match[3]); 545 var leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); 546 var monthDays = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 547 if (month < 1 || month > 12 || day < 1 || day > monthDays[month - 1]) return false; 548 if (match[4] !== undefined) { 549 var hours = Number(match[4]); 550 var minutes = Number(match[5]); 551 var seconds = Number(match[6]); 552 if (hours > 23 || minutes > 59 || seconds > 59) return false; 553 } 554 return Number.isFinite(Date.parse(match[0])); 555 } 556 557 function currentLocale(root) { 558 var requested = window.XAgentI18n && window.XAgentI18n.getLocale 559 ? window.XAgentI18n.getLocale() 560 : root.getAttribute("data-company-card-locale") || document.documentElement.lang || "en"; 561 var normalized = String(requested || "en").trim().toLowerCase().replace(/_/g, "-"); 562 if (/^zh-(tw|hk|mo|hant)/.test(normalized)) return "zh-Hant"; 563 if (normalized.startsWith("zh")) return "zh-Hans"; 564 return normalized.split("-")[0] || "en"; 565 } 566 567 function textMatchesLocale(value, locale) { 568 var text = String(value || "").trim(); 569 if (!text) return false; 570 var hasHan = /[\u3400-\u9fff\uf900-\ufaff]/.test(text); 571 var hasKana = /[\u3040-\u30ff]/.test(text); 572 var hasHangul = /[\uac00-\ud7af]/.test(text); 573 var traditional = /[é«èºç£è£½èçºéåè³è¨ç¶²æ¥ç¼å¾è£¡é黿¸æå¯¦é]/.test(text); 574 var simplified = /[ä½å°æ¹¾å¶ä¸ä¸ºè¿ä¸ªèµè®¯ç½ä¸ååéé¨çµæ°æ®å®é ]/.test(text); 575 var words = text.toLocaleLowerCase().replace(/[â']/g, "'"); 576 if (locale === "zh-Hant") return hasHan && !hasKana && !hasHangul && !(simplified && !traditional); 577 if (locale === "zh-Hans") return hasHan && !hasKana && !hasHangul && !(traditional && !simplified); 578 if (locale === "ja") return hasKana && !hasHangul; 579 if (locale === "ko") return hasHangul; 580 if (hasHan || hasKana || hasHangul) return false; 581 if (locale === "es") return /\b(el|la|los|las|de|del|una|para|con|empresa|tecnolog[iÃ]a)\b/.test(words); 582 if (locale === "fr") return /\b(le|la|les|des|une|pour|avec|entreprise|technologie)\b/.test(words); 583 if (locale === "de") return /\b(der|die|das|den|dem|des|und|f[uü]r|mit|unternehmen|technologie)\b/.test(words); 584 return /\b(the|and|for|with|from|company|business|technology|provides?|develops?|builds?)\b/.test(words); 585 } 586 587 function boundedCardText(value) { 588 var text = String(value || "").replace(/\s+/g, " ").trim(); 589 var characters = Array.from(text); 590 if (characters.length <= CARD_SUMMARY_MAX_CHARACTERS) return text; 591 var sample = characters.slice(0, CARD_SUMMARY_MAX_CHARACTERS).join(""); 592 var sentenceEnd = Math.max( 593 sample.lastIndexOf("ã"), 594 sample.lastIndexOf("ï¼"), 595 sample.lastIndexOf("ï¼"), 596 sample.lastIndexOf(". ") 597 ); 598 if (sentenceEnd >= Math.floor(CARD_SUMMARY_MAX_CHARACTERS * 0.45)) { 599 return sample.slice(0, sentenceEnd + 1).trim(); 600 } 601 var wordBounded = sample.replace(/\s+\S*$/, "").trim(); 602 return (wordBounded.length >= Math.floor(CARD_SUMMARY_MAX_CHARACTERS * 0.7) ? wordBounded : sample).trim() + "â¦"; 603 } 604 605 function cardDescription(card, locale) { 606 var description = String((card || {}).description || "").trim(); 607 return textMatchesLocale(description, locale) ? boundedCardText(description) : ""; 608 } 609 610 function fillList(root, selector, items, stateLabels) { 611 var list = root.querySelector(selector); 612 if (!list) return; 613 list.replaceChildren();
614 items.forEach(function (item, index) { 615 var li = document.createElement("li"); 616 if (stateLabels) { 617 var strong = document.createElement("strong"); 618 var small = document.createElement("small"); 619 strong.textContent = item; 620 small.className = "machine-asset-state"; 621 small.textContent = stateLabels[index]; 622 li.append(strong, small); 623 } else { 624 li.textContent = item; 625 } 626 list.appendChild(li); 627 }); 628 } 629 630 function freshnessLabel(issuedAt, labels, locale) { 631 var seconds = Number(issuedAt || 0); 632 if (!Number.isFinite(seconds) || seconds <= 0) return labels.waiting; 633 try { 634 var date = new Intl.DateTimeFormat(locale, { 635 year: "numeric", 636 month: "2-digit", 637 day: "2-digit" 638 }).format(new Date(seconds * 1000)); 639 return labels.readAt.replace("{date}", date); 640 } catch (_error) { 641 return labels.readRecorded; 642 } 643 } 644 645 function renderTopics(root, card, labels, locale) { 646 var commercial = card.commercial_profile; 647 var source = commercial ? (commercial.primary_capabilities || []).map(function (item) { 648 return {topic: item.name, source_url: item.source_url}; 649 }) : (card.knowledgeAreas || []); 650 var areas = source.filter(function (area) { 651 return textMatchesLocale(area.topic || area.title || "", locale); 652 }); 653 var list = root.querySelector("[data-card-topics]"); 654 if (!list) return; 655 list.replaceChildren(); 656 list.hidden = !areas.length; 657 root.querySelectorAll("[data-card-topics-label]").forEach(function (label) { 658 label.textContent = commercial ? labels.companyOfferings : labels.topics; 659 label.hidden = !areas.length; 660 }); 661 areas.slice(0, 3).forEach(function (area) { 662 var item = document.createElement("li"); 663 var label = area.topic || area.title || ""; 664 if (commercial && safeHttpUrl(area.source_url)) { 665 var evidenceLink = document.createElement("a"); 666 evidenceLink.href = safeHttpUrl(area.source_url); 667 evidenceLink.target = "_blank"; 668 evidenceLink.rel = "noopener noreferrer"; 669 evidenceLink.textContent = label; 670 item.appendChild(evidenceLink); 671 } else if (document.getElementById("topic-library-title")) { 672 var link = document.createElement("a"); 673 link.href = "#topic-library-title"; 674 link.textContent = label; 675 item.appendChild(link); 676 } else { 677 item.textContent = label; 678 } 679 list.appendChild(item); 680 }); 681 if (areas.length > 3) { 682 var more = document.createElement("li"); 683 var moreLabel = labels.moreTopics.replace("{count}", String(areas.length - 3)); 684 more.className = "more"; 685 if (document.getElementById("topic-library-title")) { 686 var moreLink = document.createElement("a"); 687 moreLink.href = commercial ? safeHttpUrl(((card.public_card || {}).machine_url)) || "#topic-library-title" : "#topic-library-title"; 688 moreLink.setAttribute("data-card-topics-more", ""); 689 moreLink.textContent = moreLabel; 690 more.appendChild(moreLink); 691 } else { 692 more.textContent = moreLabel; 693 } 694 list.appendChild(more); 695 } 696 } 697 698 function renderMachineAssets(root, card, deliveryPackage, labels) { 699 var publication = (deliveryPackage || {}).publication_plan || {}; 700 var plannedFiles = publication.files || []; 701 var assets = (((card || {}).agent_view || {}).machine_assets || []).map(function (asset) { 702 return { 703 label: asset.label, 704 state: asset.state, 705 anchor: asset.anchor, 706 url: asset.url || "" 707 }; 708 }); 709 var a2aAsset = assets.find(function (asset) { return asset.anchor === "asset-a2a-agent-card"; }); 710 if (a2aAsset && plannedFiles.some(function (item) { return item.path === "/.well-known/agent-card.json"; })) { 711 a2aAsset.state = "ready_to_publish"; 712 } 713 root.querySelectorAll("[data-card-machine-assets]").forEach(function (list) { 714 list.replaceChildren(); 715 assets.forEach(function (asset) { 716 var item = document.createElement("li"); 717 var detailTarget = asset.anchor && document.getElementById(asset.anchor); 718 var name = document.createElement(detailTarget ? "a" : "strong"); 719 name.textContent = asset.label; 720 if (detailTarget) { 721 name.href = "#" + asset.anchor; 722 name.setAttribute("data-source-url", safeHttpUrl(asset.url)); 723 } 724 var state = document.createElement("small"); 725 var safeState = String(asset.state || "unknown").replace(/[^a-z0-9_-]/gi, ""); 726 state.className = "machine-asset-state state-" + safeState; 727 state.textContent = labels.assetStates[asset.state] || asset.state || labels.unavailable; 728 item.append(name, state); 729 list.appendChild(item); 730 }); 731 }); 732 } 733 734 function showLogo(image, src, alt, companyName, attribution) { 735 var wrap = image.parentElement;
736 var frontBranding = wrap && wrap.closest(".namecard-branding-front"); 737 var stack = wrap && wrap.closest(".namecard-logo-stack"); 738 var fallback = wrap && wrap.querySelector("[data-card-logo-fallback]"); 739 var attributionNode = stack && stack.querySelector("[data-card-logo-attribution]"); 740 var sourceLink = attributionNode && attributionNode.querySelector("[data-card-logo-source]"); 741 var licenseLink = attributionNode && attributionNode.querySelector("[data-card-logo-license]"); 742 function setAttribution(visible) { 743 var shown = Boolean(visible && attribution && attributionNode && sourceLink && licenseLink); 744 if (attributionNode) attributionNode.hidden = !shown; 745 if (sourceLink) { 746 sourceLink.textContent = shown ? attribution.source_name : ""; 747 sourceLink.href = shown ? attribution.source_url : ""; 748 } 749 if (licenseLink) { 750 licenseLink.textContent = shown ? attribution.license_name : ""; 751 licenseLink.href = shown ? attribution.license_url : ""; 752 } 753 } 754 function reset() { 755 image.hidden = true; 756 image.alt = ""; 757 image.onload = null; 758 image.onerror = null; 759 image.removeAttribute("src"); 760 if (fallback) { 761 fallback.textContent = companyName; 762 fallback.hidden = false; 763 } 764 setAttribution(false); 765 if (wrap) { 766 wrap.classList.remove("has-logo", "logo-wide", "logo-contrast-surface"); 767 wrap.classList.add("text-fallback"); 768 } 769 if (frontBranding) frontBranding.classList.remove("has-wide-logo"); 770 } 771 function loaded() { 772 var vector = /\.svg(?:[?#]|$)/i.test(String(image.currentSrc || image.src || "")); 773 var isWideLogo = image.naturalWidth > image.naturalHeight * 1.5; 774 var sharpEnough = vector || ( 775 isWideLogo 776 ? image.naturalWidth >= 160 && image.naturalHeight >= 40 777 : Math.min(image.naturalWidth, image.naturalHeight) >= 64 && Math.max(image.naturalWidth, image.naturalHeight) >= 96 778 ); 779 if (!sharpEnough) { 780 reset(); 781 return; 782 } 783 image.hidden = false; 784 if (fallback) fallback.hidden = true; 785 setAttribution(true); 786 if (!wrap) return; 787 wrap.classList.remove("text-fallback"); 788 wrap.classList.add("has-logo"); 789 wrap.classList.toggle("logo-wide", isWideLogo); 790 if (frontBranding) frontBranding.classList.toggle("has-wide-logo", isWideLogo); 791 wrap.classList.toggle( 792 "logo-contrast-surface", 793 isWideLogo && Boolean(image.closest("[data-company-card-agent]")) 794 ); 795 } 796 reset(); 797 if (!src) return; 798 image.onload = loaded; 799 image.onerror = reset; 800 image.alt = alt; 801 image.src = src; 802 if (image.complete && image.naturalWidth) loaded(); 803 } 804 805 function renderOwnership(root, options) { 806 if (!root) return; 807 options = options || {}; 808 var labels = labelsFor(root); 809 var claimed = options.companyConfirmed === true; 810 var cardSubject = options.cardSubject === undefined ? options.subjectHost : options.cardSubject; 811 var identity = options.brandIdentity || {}; 812 var logo = identity.logo || {}; 813 var theme = identity.theme || {}; 814 var cardName = options.cardName || ""; 815 var primary = safeColor(theme.primary, "#0e2a48"); 816 var accent = safeColor(theme.accent, "#2a6783"); 817 var fontFamily = safeFontFamily(theme.font_family); 818 819 root.dataset.companyClaimState = claimed ? "claimed" : "unclaimed"; 820 root.dataset.cardSubject = String(cardSubject || "").toLowerCase().replace(/^www\./, ""); 821 root.style.setProperty("--card-primary", primary); 822 root.style.setProperty("--card-accent", accent); 823 root.style.setProperty( 824 "--card-font", 825 fontFamily ? '"' + fontFamily.replace(/"/g, "") + '", system-ui, sans-serif' : "system-ui, sans-serif" 826 ); 827 setText(root, "[data-card-ownership-title]", claimed ? labels.claimedTitle : labels.unclaimedTitle); 828 setText(root, "[data-card-ownership-note]", claimed ? labels.claimedNote : labels.unclaimedNote); 829 830 // Cached cards can still carry a product/share preview as their old logo. 831 var socialPreview = logo.source === "og_image" || logo.source === "twitter_image"; 832 var logoUrl = socialPreview ? "" : displayableLogo(logo, options.subjectHost); 833 var logoAttribution = socialPreview ? null : wikimediaCommonsLogo(logo, options.subjectHost); 834 root.querySelectorAll("[data-card-logo]").forEach(function (image) { 835 showLogo(image, logoUrl, cardName ? cardName + " logo" : "Company logo", cardName, logoAttribution); 836 }); 837 root.querySelectorAll("[data-verify-badge]").forEach(function (badge) { 838 badge.textContent = claimed ? labels.claimedTitle : labels.unclaimedTitle; 839 badge.className = "namecard-verify " + (claimed ? "complete" : "partial"); 840 }); 841 } 842 843 function renderDemo(root) { 844 renderOwnership(root, { 845 companyConfirmed: true, 846 cardName: "twin3.ai", 847 subjectHost: "twin3.ai", 848 brandIdentity: { theme: { primary: "#0e2a48", accent: "#2a6783" } } 849 }); 850 setText(root, "[data-card-name]", "twin3.ai"); 851 setText(root, "[data-card-profile-state]", "Verified company identity"); 852 root.querySelectorAll("[data-card-description]").forEach(function (node) {
853 node.textContent = "Identity infrastructure for people, companies and Agents."; 854 node.hidden = false; 855 }); 856 setLinks(root, "[data-card-official-host]", "https://twin3.ai", "twin3.ai"); 857 setLinks(root, "[data-card-public-agent-id]", "/twin3.ai", "xagent.id/twin3.ai"); 858 setLinks(root, "[data-card-machine-url]", "/twin3.ai.json", "xagent.id/twin3.ai.json"); 859 setText(root, "[data-card-public-agent-id-text]", "xagent.id/twin3.ai"); 860 setText(root, "[data-card-freshness]", "Current public snapshot"); 861 renderA2ALabel(root, labelsFor(root)); 862 fillList(root, "[data-card-topics]", ["Agent ID", "Human ID", "Trust infrastructure", "AI Agents"]); 863 fillList( 864 root, 865 "[data-card-machine-assets]", 866 ["Agent ID JSON", "A2A Agent Card", "design.md", "llms.txt"], 867 ["Readable", "Owner approval", "Public brand projection", "Owner approval"] 868 ); 869 root.querySelectorAll("[data-copy-agent-id]").forEach(function (button) { 870 button.disabled = false; 871 button.dataset.copyValue = "https://xagent.id/twin3.ai"; 872 }); 873 } 874 875 function renderBootstrap(root, preload) { 876 if (!root || !preload) return; 877 var host = String(preload.host || "").trim().toLowerCase(); 878 if (!host) return; 879 var publicUrl = "/" + host; 880 render(root, { 881 name: String(preload.name || host), 882 description: String(preload.description || ""), 883 url: "https://" + host, 884 verification: { status: "unverified", subject_host: host }, 885 profile_state: { status: "publicly_observed", company_confirmed: false }, 886 public_card: { 887 url: publicUrl, 888 machine_url: publicUrl + ".json", 889 display_url: "xagent.id/" + host, 890 machine_display_url: "xagent.id/" + host + ".json" 891 }, 892 actions: [{ id: "visit_official_site", url: "https://" + host }], 893 knowledgeAreas: [], 894 agent_view: { machine_assets: [] }, 895 brand_identity: preload.brand_identity || {} 896 }, {}); 897 root.dataset.companyCardState = "preloaded"; 898 } 899 900 function normalizeCanonicalSubjectHost(value) { 901 if (typeof value !== "string" || !value || /[\s/:@\\?#\[\]]/.test(value)) return ""; 902 var host = value.toLowerCase(); 903 if (host.endsWith(".")) host = host.slice(0, -1); 904 if (host.startsWith("www.")) host = host.slice(4); 905 if (!host || host.length > 253 || host.endsWith(".")) return ""; 906 var labels = host.split("."); 907 if (labels.length < 2 || labels.some(function (label) { 908 return !label || label.length > 63 || !/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(label); 909 })) return ""; 910 return host; 911 } 912 913 function render(root, card, deliveryPackage) { 914 if (!root || !card) return; 915 if (root.dataset.companyCardReady !== "true") mount(root); 916 var labels = labelsFor(root); 917 var locale = currentLocale(root); 918 var verification = card.verification || {}; 919 var profile = card.profile_state || {}; 920 var publicCard = card.public_card || {}; 921 var actions = {}; 922 (card.actions || []).forEach(function (action) { actions[action.id] = action; }); 923 var officialAction = actions.visit_official_site || {}; 924 var officialUrl = officialAction.url || card.url || ""; 925 var host = verification.subject_host || ""; 926 var canonicalCardHost = ""; 927 var cardUrl = typeof card.url === "string" ? card.url : ""; 928 var cardAuthority = cardUrl.match(/^https:\/\/([^/?#]*)/i); 929 if (cardUrl && !/[\s]/.test(cardUrl) && cardAuthority && !cardAuthority[1].includes("@") && !cardAuthority[1].includes(":")) { 930 try { 931 var parsedCardUrl = new URL(cardUrl); 932 if (parsedCardUrl.protocol === "https:" && !parsedCardUrl.username && !parsedCardUrl.password && !parsedCardUrl.port) { 933 canonicalCardHost = normalizeCanonicalSubjectHost(parsedCardUrl.hostname); 934 } 935 } catch (_error) {} 936 } 937 var canonicalSubjectHost = normalizeCanonicalSubjectHost(verification.subject_host); 938 var cardSubject = canonicalCardHost && canonicalSubjectHost === canonicalCardHost ? canonicalSubjectHost : ""; 939 var displayAgentId = publicCard.display_url || publicCard.url || "xagent.id/â"; 940 var displayMachineUrl = publicCard.machine_display_url || publicCard.machine_url || "xagent.id/â.json"; 941 942 root.__companyCardPayload = { card: card, deliveryPackage: deliveryPackage || {} }; 943 renderOwnership(root, { 944 companyConfirmed: profile.company_confirmed === true, 945 cardName: card.name || host, 946 subjectHost: host, 947 cardSubject: cardSubject, 948 brandIdentity: card.brand_identity 949 }); 950 setText(root, "[data-card-name]", card.name || host || "â"); 951 setText( 952 root, 953 "[data-card-profile-state]", 954 profile.company_confirmed ? labels.claimedTitle : (profile.status === "publicly_observed" ? labels.observed : labels.unavailable) 955 ); 956 var description = cardDescription(card, locale); 957 if (!description && (card.commercial_profile || {}).evidence_status === "insufficient_company_evidence") { 958 description = labels.insufficientCompanyEvidence; 959 } 960 root.querySelectorAll("[data-card-description]").forEach(function (node) { 961 node.textContent = description; 962 node.hidden = !description; 963 });
964 setLinks(root, "[data-card-official-host]", officialUrl, host || officialUrl || "â"); 965 setLinks(root, "[data-card-public-agent-id]", publicCard.url, displayAgentId); 966 setLinks(root, "[data-card-machine-url]", publicCard.machine_url, displayMachineUrl); 967 setText(root, "[data-card-public-agent-id-text]", displayAgentId); 968 setText(root, "[data-card-freshness]", freshnessLabel(card.issued_at, labels, locale)); 969 renderA2ALabel(root, labels); 970 renderTopics(root, card, labels, locale); 971 renderMachineAssets(root, card, deliveryPackage, labels); 972 root.querySelectorAll("[data-copy-agent-id]").forEach(function (button) { 973 button.disabled = !publicCard.url; 974 button.dataset.copyValue = publicCard.url || ""; 975 }); 976 977 var legalEntity = card.legal_entity_identity || {}; 978 var showLegalEntity = ownerConfirmedLegalEntity(legalEntity); 979 var hasLegalEntityContract = Boolean(legalEntity.schema || legalEntity.source); 980 var showCandidateRecord = ownerConfirmableLegalEntity(legalEntity); 981 var leiUrl = safeGleifRecordUrl(legalEntity.record_url, legalEntity.lei); 982 var exposeLegalEntityRecord = Boolean((showLegalEntity || showCandidateRecord) && leiUrl); 983 var legalEntityStatus = legalEntityStatusLabel(labels, legalEntity, showLegalEntity); 984 root.querySelectorAll("[data-card-lei-card]").forEach(function (node) { 985 node.hidden = !hasLegalEntityContract; 986 node.classList.toggle("is-current", showLegalEntity); 987 }); 988 root.querySelectorAll("[data-card-lei-setting]").forEach(function (node) { 989 node.hidden = !hasLegalEntityContract; 990 node.classList.toggle("is-current", showLegalEntity); 991 }); 992 root.querySelectorAll("[data-card-lei-status]").forEach(function (node) { 993 node.textContent = legalEntityStatus; 994 node.hidden = Boolean(exposeLegalEntityRecord && legalEntity.lei); 995 }); 996 root.querySelectorAll("[data-card-lei-value]").forEach(function (node) { 997 node.textContent = exposeLegalEntityRecord && legalEntity.lei ? legalEntity.lei : ""; 998 node.hidden = !exposeLegalEntityRecord || !legalEntity.lei; 999 }); 1000 root.querySelectorAll("[data-card-lei-link]").forEach(function (link) { 1001 var visibleLeiUrl = exposeLegalEntityRecord ? leiUrl : ""; 1002 if (visibleLeiUrl) link.href = visibleLeiUrl; 1003 else link.removeAttribute("href"); 1004 link.setAttribute("aria-label", visibleLeiUrl && legalEntity.lei ? labels.gleifRecord + ": " + legalEntity.lei : labels.gleifIndex); 1005 var arrow = link.querySelector("[data-card-lei-arrow]"); 1006 if (arrow) arrow.hidden = !visibleLeiUrl; 1007 }); 1008 root.dataset.companyCardState = "ready"; 1009 root.removeAttribute("aria-busy"); 1010 } 1011 1012 function loadSource(root, source) { 1013 var endpoint = safeFeaturedCardSource(source); 1014 if (!endpoint) return Promise.reject(new Error("featured_card_source_not_allowed")); 1015 root.dataset.companyCardState = "loading"; 1016 root.setAttribute("aria-busy", "true"); 1017 return fetch(endpoint, { 1018 mode: "cors", 1019 credentials: "omit", 1020 headers: { Accept: "application/json" } 1021 }) 1022 .then(function (response) { 1023 return response.json().then(function (payload) { 1024 if (!response.ok || !payload || !payload.ok || !payload.agent_card) { 1025 throw new Error("featured_card_unavailable"); 1026 } 1027 return payload; 1028 }); 1029 }) 1030 .then(function (payload) { 1031 render(root, payload.agent_card, payload.package || {}); 1032 return payload; 1033 }) 1034 .catch(function (error) { 1035 root.dataset.companyCardState = "error"; 1036 root.removeAttribute("aria-busy"); 1037 throw error; 1038 }); 1039 } 1040 1041 function mount(root) { 1042 if (!root || root.dataset.companyCardReady === "true") return; 1043 var labels = labelsFor(root); 1044 var faces = facesMarkup(labels); 1045 root.innerHTML = root.hasAttribute("data-company-card-flip") 1046 ? '<div class="business-card-inner">' + faces + "</div>" 1047 : faces; 1048 root.dataset.companyCardReady = "true"; 1049 installCopy(root, labels); 1050 if (root.hasAttribute("data-company-card-demo")) renderDemo(root); 1051 var source = root.getAttribute("data-company-card-source"); 1052 if (source) loadSource(root, source).catch(function () {}); 1053 } 1054 1055 var embeddedComponent = false;
1056 try { 1057 embeddedComponent = Boolean( 1058 document.currentScript && 1059 new URL(document.currentScript.src).searchParams.get("embed") === "1" 1060 ); 1061 } catch (_error) {} 1062 if (!embeddedComponent) document.querySelectorAll("[data-company-card]").forEach(mount); 1063 window.addEventListener("xagent:languagechange", function () { 1064 if (embeddedComponent) return; 1065 document.querySelectorAll("[data-company-card]").forEach(function (root) { 1066 var payload = root.__companyCardPayload; 1067 if (payload && payload.card) render(root, payload.card, payload.deliveryPackage || {}); 1068 }); 1069 }); 1070 window.XAgentCompanyCard = { 1071 mount: mount, 1072 render: render, 1073 renderBootstrap: renderBootstrap, 1074 loadSource: loadSource, 1075 hasDisplayableLei: hasDisplayableLei, 1076 renderOwnership: renderOwnership 1077 }; 1078})();
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.