UNPKG

@raven-js/glean

Version:

Glean documentation gold from your codebase - JSDoc parsing, validation, and beautiful doc generation

182 lines (162 loc) 4.85 kB
/** * @author Anonyfox <max@anonyfox.com> * @license MIT * @see {@link https://github.com/Anonyfox/ravenjs} * @see {@link https://ravenjs.dev} * @see {@link https://anonyfox.com} */ /** * @file See links component for JSDoc @see tag reference display. * * Renders @see tag links with proper external link handling and Bootstrap badge styling. * Groups links by type for organized presentation. Optional rendering - displays nothing * when no links exist. */ import { html } from "@raven-js/beak"; /** * Render external URL links as Bootstrap badges * @param {Array<Object>} urlLinks - URL link objects * @param {string} badgeClass - Bootstrap badge class * @returns {string} HTML for URL links */ function renderUrlLinks(urlLinks, badgeClass = "badge bg-secondary") { if (!Array.isArray(urlLinks) || urlLinks.length === 0) { return ""; } return urlLinks .filter( (link) => /** @type {any} */ (link).reference || /** @type {any} */ (link).url, ) .map((link) => { /** @type {any} */ const l = link; const url = l.url || l.reference; const displayText = l.description || new URL(url).hostname; return html` <a href="${url}" target="_blank" rel="noopener noreferrer" class="${badgeClass} text-decoration-none me-1"> ${displayText}</a> `; }) .join(" "); } /** * Render symbol references as internal badges * @param {Array<Object>} symbolLinks - Symbol link objects * @returns {string} HTML for symbol references */ function renderSymbolLinks(symbolLinks) { if (!Array.isArray(symbolLinks) || symbolLinks.length === 0) { return ""; } return symbolLinks .filter((link) => /** @type {any} */ (link).reference) .map((link) => { /** @type {any} */ const l = link; return html` <span class="badge bg-light text-dark me-1" title="Symbol reference"> <code>${l.reference}</code> </span> `; }) .join(" "); } /** * Render module references as module badges * @param {Array<Object>} moduleLinks - Module link objects * @returns {string} HTML for module references */ function renderModuleLinks(moduleLinks) { if (!Array.isArray(moduleLinks) || moduleLinks.length === 0) { return ""; } return moduleLinks .filter((link) => /** @type {any} */ (link).reference) .map((link) => { /** @type {any} */ const l = link; return html` <span class="badge bg-info text-dark me-1" title="Module reference"> ${l.reference} </span> `; }) .join(" "); } /** * Render text references as plain badges * @param {Array<Object>} textLinks - Text reference objects * @returns {string} HTML for text references */ function renderTextLinks(textLinks) { if (!Array.isArray(textLinks) || textLinks.length === 0) { return ""; } return textLinks .filter((link) => /** @type {any} */ (link).reference) .map((link) => { /** @type {any} */ const l = link; return html` <span class="badge bg-light text-muted me-1" title="Text reference"> ${l.reference} </span> `; }) .join(" "); } /** * See also links component displaying @see tag references organized by type. * * External URLs get external link icons, symbols get code styling, modules get info badges. * Returns empty string when no attribution context or links exist. * * @param {import('../../extract/models/attribution.js').AttributionContext} attributionContext - Attribution context * @param {boolean} [compact=false] - Whether to use compact styling * @returns {string} HTML see links display or empty string * * @example * // Compact style for cards * seeAlsoLinks(attributionContext, true); * * @example * // Full style for pages * seeAlsoLinks(attributionContext, false); */ export function seeAlsoLinks(attributionContext, compact = false) { if ( !attributionContext || !attributionContext.hasAttribution || !attributionContext.hasLinks ) { return ""; } const seeLinks = attributionContext.getSeeLinks(); const hasAnyLinks = Object.values(seeLinks).some( (linkArray) => Array.isArray(linkArray) && linkArray.length > 0, ); if (!hasAnyLinks) { return ""; } const linksHtml = renderUrlLinks(seeLinks.links, "badge bg-primary"); const urlsHtml = renderUrlLinks(seeLinks.urls, "badge bg-secondary"); const symbolsHtml = renderSymbolLinks(seeLinks.symbols); const modulesHtml = renderModuleLinks(seeLinks.modules); const textHtml = renderTextLinks(seeLinks.text); const allLinksHtml = [linksHtml, urlsHtml, symbolsHtml, modulesHtml, textHtml] .filter((html) => html.trim()) .join(" "); if (!allLinksHtml.trim()) { return ""; } const containerClass = compact ? "mt-1" : "mt-2"; const labelClass = compact ? "text-muted small" : "text-muted"; return html` <div class="${containerClass}"> <span class="${labelClass}">See also:</span> ${allLinksHtml} </div> `; }