Skip to content

Commit 2e2659e

Browse files
committed
Convert attributes list into a table
1 parent 361c32c commit 2e2659e

3 files changed

Lines changed: 91 additions & 40 deletions

File tree

.vitepress/signature.ts

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -787,49 +787,47 @@ function renderAttributesList(md: MarkdownIt, locale?: LocaleConfig): string {
787787

788788
if (entries.length === 0) return ''
789789

790-
// Group by pagePath
791-
const groups = new Map<string, RegistryEntry[]>()
792-
for (const entry of entries) {
793-
const list = groups.get(entry.pagePath) || []
794-
list.push(entry)
795-
groups.set(entry.pagePath, list)
796-
}
797-
798-
const tableLabels: Record<string, { attr: string; desc: string }> = {
799-
en: { attr: 'Attribute', desc: 'Description' },
800-
ru: { attr: 'Атрибут', desc: 'Описание' },
790+
const tableLabels: Record<string, { attr: string; plugin: string; desc: string }> = {
791+
en: { attr: 'Attribute', plugin: 'Plugin', desc: 'Description' },
792+
ru: { attr: 'Атрибут', plugin: 'Плагин', desc: 'Описание' },
801793
}
802794
const l = tableLabels[localeCode] ?? tableLabels.en
803795

804-
// Sort groups by plugin name
805-
const sortedGroups = [...groups.entries()].sort((a, b) => {
806-
const nameA = getPluginByPagePath(localeCode, a[0])?.name ?? a[0]
807-
const nameB = getPluginByPagePath(localeCode, b[0])?.name ?? b[0]
808-
return nameA.localeCompare(nameB)
809-
})
810-
811-
let html = ''
812-
813-
for (const [pagePath, attrs] of sortedGroups) {
814-
const plugin = getPluginByPagePath(localeCode, pagePath)
815-
const groupName = plugin?.name ?? pagePath.split('/').pop() ?? 'Unknown'
816-
const slug = 'attrs-' + groupName.toLowerCase().replace(/\s+/g, '-')
817-
818-
if (plugin) {
819-
const pluginHtml = renderPluginRefHtml(plugin.name, locale)
820-
html += `<h2 id="${escapeHtml(slug)}">${pluginHtml}</h2>\n`
821-
} else {
822-
html += `<h2 id="${escapeHtml(slug)}">${escapeHtml(groupName)}</h2>\n`
823-
}
824-
825-
html += `<table>\n<thead><tr><th>${escapeHtml(l.attr)}</th><th>${escapeHtml(l.desc)}</th></tr></thead>\n<tbody>\n`
826-
for (const attr of attrs) {
827-
const attrHtml = renderAttrRefHtml(md, attr.fqn, locale)
828-
const shortHtml = attr.short ? md.renderInline(attr.short) : ''
829-
html += `<tr><td>${attrHtml}</td><td>${shortHtml}</td></tr>\n`
830-
}
831-
html += '</tbody>\n</table>\n'
832-
}
796+
// Build flat rows
797+
const rows: { name: string; plugin: string; attrHtml: string; pluginHtml: string; shortHtml: string }[] = []
833798

799+
for (const entry of entries) {
800+
const plugin = getPluginByPagePath(localeCode, entry.pagePath)
801+
const pluginName = plugin?.name ?? entry.pagePath.split('/').pop() ?? ''
802+
const shortName = stripNamespaceShort(entry.fqn)
803+
804+
rows.push({
805+
name: shortName,
806+
plugin: pluginName,
807+
attrHtml: renderAttrRefHtml(md, entry.fqn, locale),
808+
pluginHtml: plugin ? renderPluginRefHtml(plugin.name, locale) : escapeHtml(pluginName),
809+
shortHtml: entry.short ? md.renderInline(entry.short) : '',
810+
})
811+
}
812+
813+
// Default sort by name
814+
rows.sort((a, b) => a.name.localeCompare(b.name))
815+
816+
let html = '<table class="attr-sortable">\n'
817+
html += '<thead><tr>'
818+
html += `<th data-sort="name" data-dir="asc">${escapeHtml(l.attr)}</th>`
819+
html += `<th data-sort="plugin">${escapeHtml(l.plugin)}</th>`
820+
html += `<th>${escapeHtml(l.desc)}</th>`
821+
html += '</tr></thead>\n<tbody>\n'
822+
823+
for (const row of rows) {
824+
html += `<tr data-name="${escapeHtml(row.name.toLowerCase())}" data-plugin="${escapeHtml(row.plugin.toLowerCase())}">`
825+
html += `<td>${row.attrHtml}</td>`
826+
html += `<td>${row.pluginHtml}</td>`
827+
html += `<td>${row.shortHtml}</td>`
828+
html += '</tr>\n'
829+
}
830+
831+
html += '</tbody>\n</table>\n'
834832
return html
835833
}

.vitepress/theme/index.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,34 @@ import BlogPostHeader from './BlogPostHeader.vue'
1313
import { isBlogPath, getBlogBackLink, localNavBackKey } from '../locales'
1414
import './style.css'
1515

16+
function setupSortableTable() {
17+
document.addEventListener('click', (e) => {
18+
const th = (e.target as Element).closest?.('th[data-sort]') as HTMLElement | null
19+
if (!th) return
20+
21+
const table = th.closest('table.attr-sortable')
22+
if (!table) return
23+
24+
const tbody = table.querySelector('tbody')
25+
if (!tbody) return
26+
27+
const key = th.dataset.sort!
28+
const asc = th.dataset.dir !== 'asc'
29+
30+
table.querySelectorAll('th[data-sort]').forEach(h => delete (h as HTMLElement).dataset.dir)
31+
th.dataset.dir = asc ? 'asc' : 'desc'
32+
33+
const rows = [...tbody.querySelectorAll('tr')]
34+
rows.sort((a, b) => {
35+
const va = (a as HTMLElement).dataset[key] || ''
36+
const vb = (b as HTMLElement).dataset[key] || ''
37+
return asc ? va.localeCompare(vb) : vb.localeCompare(va)
38+
})
39+
40+
rows.forEach(r => tbody.appendChild(r))
41+
})
42+
}
43+
1644
function setupFuncRefTooltips() {
1745
let activeTooltip: HTMLElement | null = null
1846
let activeRef: Element | null = null
@@ -108,6 +136,7 @@ export default {
108136

109137
if (typeof window !== 'undefined') {
110138
setupFuncRefTooltips()
139+
setupSortableTable()
111140
}
112141
},
113142
} satisfies Theme

.vitepress/theme/style.css

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,3 +901,27 @@ a.featured-post-card:hover {
901901
aspect-ratio: 16 / 9;
902902
}
903903
}
904+
905+
/* ── Sortable attributes table ────────────────────────── */
906+
907+
.attr-sortable th[data-sort] {
908+
cursor: pointer;
909+
user-select: none;
910+
white-space: nowrap;
911+
}
912+
913+
.attr-sortable th[data-sort]::after {
914+
content: ' ↕';
915+
opacity: 0.35;
916+
font-size: 0.85em;
917+
}
918+
919+
.attr-sortable th[data-sort][data-dir="asc"]::after {
920+
content: ' ↑';
921+
opacity: 0.7;
922+
}
923+
924+
.attr-sortable th[data-sort][data-dir="desc"]::after {
925+
content: ' ↓';
926+
opacity: 0.7;
927+
}

0 commit comments

Comments
 (0)