|
116 | 116 | return str.length > len ? str.slice(0, len) + "..." : str; |
117 | 117 | } |
118 | 118 |
|
| 119 | + // Extract a human-friendly short name from a URL (e.g. GitHub/GitLab repo name) |
| 120 | + function smartLabel(str) { |
| 121 | + if (!str) return ""; |
| 122 | + try { |
| 123 | + var url = new URL(str); |
| 124 | + // GitHub / GitLab: use "owner/repo" |
| 125 | + var parts = url.pathname.replace(/^\/+|\/+$/g, "").split("/"); |
| 126 | + if (parts.length >= 2) return parts.slice(0, 2).join("/"); |
| 127 | + if (parts.length === 1 && parts[0]) return parts[0]; |
| 128 | + } catch (e) { /* not a URL, fall through */ } |
| 129 | + return str; |
| 130 | + } |
| 131 | + |
119 | 132 | function escapeHtml(str) { |
120 | 133 | const div = document.createElement("div"); |
121 | 134 | div.textContent = str; |
|
191 | 204 | return spec.creator && spec.creator.name ? [spec.creator.name] : []; |
192 | 205 | case "registry": |
193 | 206 | return (spec.registries || []) |
194 | | - .map(function (r) { return r.name || r.id || null; }) |
| 207 | + .map(function (r) { return r.name || smartLabel(r.id) || r.id || null; }) |
195 | 208 | .filter(Boolean); |
196 | 209 | default: |
197 | 210 | return []; |
|
380 | 393 | escapeHtml(display) + '</a>'; |
381 | 394 | } |
382 | 395 |
|
| 396 | + var STATUS_INFO = { |
| 397 | + ok: { icon: "✅", label: "OK", description: "Metadata was successfully extracted from this mapping set." }, |
| 398 | + no_metadata: { icon: "⚠️", label: "No metadata", description: "No machine-readable metadata header could be found in this mapping set." }, |
| 399 | + nonstandard_format: { icon: "⚠️", label: "Nonstandard format", description: "This mapping set is in a format that could not be parsed (e.g. compressed)." }, |
| 400 | + fetch_error: { icon: "⚠️", label: "Fetch error", description: "This mapping set could not be retrieved from its source URL." }, |
| 401 | + }; |
| 402 | + |
| 403 | + function renderStatus(status) { |
| 404 | + var info = STATUS_INFO[status || "ok"] || STATUS_INFO["ok"]; |
| 405 | + return '<span class="status-badge" title="' + escapeHtml(info.label + ": " + info.description) + '">' + |
| 406 | + info.icon + '</span>'; |
| 407 | + } |
| 408 | + |
383 | 409 | function renderFairScore(score) { |
384 | 410 | if (score == null) return ""; |
385 | 411 | var pct = Math.round(score * 100); |
|
442 | 468 |
|
443 | 469 | addDetail("ID", spec.id ? renderUrl(spec.id) : null); |
444 | 470 | addDetail("Version", spec.version ? escapeHtml(spec.version) : null); |
445 | | - addDetail("Type", spec.type ? escapeHtml(spec.type) : null); |
446 | 471 | addDetail("License", spec.license ? renderLicenseBadge(spec) : null); |
447 | 472 | addDetail("Publication date", spec.publication_date ? escapeHtml(spec.publication_date) : null); |
448 | 473 | addDetail("Mapping method", spec.mapping_method ? escapeHtml(spec.mapping_method) : null); |
|
456 | 481 | addDetail("Description", spec.description ? escapeHtml(spec.description) : null); |
457 | 482 | if (spec.registries && spec.registries.length) { |
458 | 483 | var regHtml = spec.registries.map(function(r) { |
459 | | - var label = escapeHtml(r.name || r.id || "Unknown"); |
| 484 | + var label = escapeHtml(r.name || smartLabel(r.id) || r.id || "Unknown"); |
460 | 485 | return r.url ? '<a href="' + escapeHtml(r.url) + '" target="_blank" rel="noopener" class="detail-link">' + label + '</a>' : label; |
461 | 486 | }).join(", "); |
462 | 487 | addDetail("Registries", regHtml); |
|
471 | 496 | '<div class="result-card">' + |
472 | 497 | '<div class="result-card-header">' + |
473 | 498 | '<span class="result-card-title">' + title + '</span>' + |
| 499 | + renderStatus(spec.status) + |
474 | 500 | typeBadge + |
475 | 501 | renderFairScore(spec.metadata_completeness_score) + |
476 | 502 | '</div>' + |
|
0 commit comments