diff --git a/docs/src/components/AttributeCard.astro b/docs/src/components/AttributeCard.astro index 6550f9ce..dba99359 100644 --- a/docs/src/components/AttributeCard.astro +++ b/docs/src/components/AttributeCard.astro @@ -3,6 +3,7 @@ import PiiBadge from './PiiBadge.astro'; import VisibilityBadge from './VisibilityBadge.astro'; import OtelBadge from './OtelBadge.astro'; import TypeBadge from './TypeBadge.astro'; +import AttributeLink from './AttributeLink.astro'; import type { Attribute } from '../content.config'; import { parseAttributeId } from '../utils/category'; @@ -76,7 +77,7 @@ const rawJson = JSON.stringify(attribute, null, 2);
Aliases - {attribute.alias.map((a) => {a})} + {attribute.alias.map((a) => )}
)} @@ -102,7 +103,7 @@ const rawJson = JSON.stringify(attribute, null, 2); {isDeprecated && (
{attribute.deprecation?.replacement ? ( -

Use {attribute.deprecation.replacement} instead.

+

Use instead.

) : (

No replacement available at this time.

)} diff --git a/docs/src/components/AttributeLink.astro b/docs/src/components/AttributeLink.astro new file mode 100644 index 00000000..f23e09d9 --- /dev/null +++ b/docs/src/components/AttributeLink.astro @@ -0,0 +1,12 @@ +--- +import { attributeUrl } from '../utils/attributeUrl'; + +interface Props { + name: string; +} + +const { name } = Astro.props; +const href = attributeUrl(name, import.meta.env.BASE_URL); +--- + +{name} diff --git a/docs/src/components/LinkedTemplate.astro b/docs/src/components/LinkedTemplate.astro new file mode 100644 index 00000000..08e6ffba --- /dev/null +++ b/docs/src/components/LinkedTemplate.astro @@ -0,0 +1,49 @@ +--- +/** + * Renders a span name template string, turning `{{attribute.key}}` + * placeholders into clickable links to the corresponding attribute page. + */ +import { attributeUrl } from '../utils/attributeUrl'; + +interface Props { + template: string; +} + +const { template } = Astro.props; + +const PLACEHOLDER = /\{\{([^}]+)\}\}/g; + +interface Segment { + type: 'text' | 'link'; + value: string; +} + +const segments: Segment[] = []; +let lastIndex = 0; + +for (const match of template.matchAll(PLACEHOLDER)) { + if (match.index > lastIndex) { + segments.push({ type: 'text', value: template.slice(lastIndex, match.index) }); + } + segments.push({ type: 'link', value: match[1] }); + lastIndex = match.index + match[0].length; +} + +if (lastIndex < template.length) { + segments.push({ type: 'text', value: template.slice(lastIndex) }); +} + +const hasPlaceholders = segments.some((s) => s.type === 'link'); +--- + +{hasPlaceholders ? ( + segments.map((seg) => + seg.type === 'link' ? ( + {`{{${seg.value}}}`} + ) : ( + {seg.value} + ) + ) +) : ( + {template} +)} diff --git a/docs/src/pages/measurements/index.astro b/docs/src/pages/measurements/index.astro index 7186cd97..149a9b74 100644 --- a/docs/src/pages/measurements/index.astro +++ b/docs/src/pages/measurements/index.astro @@ -1,5 +1,6 @@ --- import BaseLayout from '../../layouts/BaseLayout.astro'; +import AttributeLink from '../../components/AttributeLink.astro'; import { getCollection } from 'astro:content'; const allMeasurements = await getCollection('measurements'); @@ -18,12 +19,6 @@ for (const measurements of platformMap.values()) { } const sortedPlatforms = Array.from(platformMap.keys()).sort(); - -function attributeUrl(key: string): string { - const category = key.includes('.') ? key.split('.')[0] : 'general'; - const anchor = key.replace(/\./g, '-').replace(//g, ''); - return `${import.meta.env.BASE_URL}attributes/${category}/#${anchor}`; -} --- @@ -80,9 +75,7 @@ function attributeUrl(key: string): string { {m.data.attribute ? ( - - {m.data.attribute} - + ) : ( )} diff --git a/docs/src/pages/names/index.astro b/docs/src/pages/names/index.astro index 4b5de2ef..719dec16 100644 --- a/docs/src/pages/names/index.astro +++ b/docs/src/pages/names/index.astro @@ -1,6 +1,7 @@ --- import BaseLayout from '../../layouts/BaseLayout.astro'; import CategoryChip from '../../components/CategoryChip.astro'; +import LinkedTemplate from '../../components/LinkedTemplate.astro'; import { getCollection } from 'astro:content'; // Get all name definitions @@ -107,13 +108,13 @@ const totalOperations = allNames.reduce((acc, name) => acc + name.data.operation

Templates

    - {op.templates.map((template, index) => ( + {op.templates.map((tmpl, index) => (
  1. {template} - {index === op.templates.length - 1 && !template.includes('{{') && ( + index === op.templates.length - 1 && !tmpl.includes('{{') ? 'border border-accent' : '' + ]}> + {index === op.templates.length - 1 && !tmpl.includes('{{') && ( fallback )}
  2. diff --git a/docs/src/utils/attributeUrl.ts b/docs/src/utils/attributeUrl.ts new file mode 100644 index 00000000..24a056c7 --- /dev/null +++ b/docs/src/utils/attributeUrl.ts @@ -0,0 +1,11 @@ +/** + * Builds a URL to an attribute's anchor on the docs site. + * Derives the category from the first segment of a dotted key + * (e.g. "http.request.method" → category "http"). + * Keys without a dot land in the "general" category. + */ +export function attributeUrl(key: string, base: string): string { + const category = key.includes('.') ? key.split('.')[0] : 'general'; + const anchor = key.replace(/\./g, '-').replace(//g, ''); + return `${base}attributes/${category}/#${anchor}`; +}