Skip to content

Commit 870b8f6

Browse files
committed
feat: render sitemap.xml as a styled table in browsers
Add sitemap.xsl (dark monospace theme matching the site) and declare it via xml-stylesheet in the generated sitemap, mirroring mindmux.ai. Purely presentational — crawlers ignore the stylesheet PI.
1 parent 2e7b810 commit 870b8f6

2 files changed

Lines changed: 85 additions & 0 deletions

File tree

apps/www/public/sitemap.xsl

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xsl:stylesheet version="1.0"
3+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4+
xmlns:s="http://www.sitemaps.org/schemas/sitemap/0.9"
5+
xmlns:xhtml="http://www.w3.org/1999/xhtml">
6+
<xsl:output method="html" encoding="UTF-8" indent="yes" />
7+
<xsl:template match="/">
8+
<html lang="en">
9+
<head>
10+
<meta charset="utf-8" />
11+
<meta name="viewport" content="width=device-width, initial-scale=1" />
12+
<title>Sitemap — OpenSource.Win</title>
13+
<style>
14+
:root { color-scheme: dark; }
15+
* { box-sizing: border-box; }
16+
body {
17+
margin: 0; padding: 2rem 1rem 4rem;
18+
background: #0d0d0d; color: #d4d4d4;
19+
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
20+
font-size: 14px; line-height: 1.6;
21+
}
22+
main { max-width: 1100px; margin: 0 auto; }
23+
header { border-bottom: 1px solid #262626; padding-bottom: 1rem; margin-bottom: 1.5rem; }
24+
h1 { font-size: 1.25rem; font-weight: 700; margin: 0 0 .25rem; color: #4bf08e; }
25+
h1::before { content: ">_ "; color: #666; }
26+
.meta { color: #8a8a8a; font-size: .8rem; }
27+
.meta code { color: #d4d4d4; background: #1a1a1a; padding: .1rem .35rem; border-radius: 4px; }
28+
table { width: 100%; border-collapse: collapse; }
29+
th, td { text-align: left; padding: .45rem .6rem; border-bottom: 1px solid #1f1f1f; vertical-align: top; }
30+
th { color: #8a8a8a; font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; position: sticky; top: 0; background: #0d0d0d; }
31+
tr:hover td { background: #141414; }
32+
td.num, th.num { text-align: right; color: #8a8a8a; }
33+
a { color: #4bf08e; text-decoration: none; word-break: break-all; }
34+
a:hover { text-decoration: underline; }
35+
.tags { white-space: nowrap; }
36+
.tag {
37+
display: inline-block; font-size: .7rem; padding: .05rem .4rem; margin-right: .3rem;
38+
border: 1px solid #2c2c2c; border-radius: 999px; color: #a3a3a3;
39+
}
40+
.tag.x-default { border-color: #4bf08e55; color: #4bf08e; }
41+
.count { color: #4bf08e; }
42+
</style>
43+
</head>
44+
<body>
45+
<main>
46+
<header>
47+
<h1>OpenSource.Win Sitemap</h1>
48+
<p class="meta">
49+
<span class="count"><xsl:value-of select="count(s:urlset/s:url)" /></span> URLs ·
50+
hreflang <code>en</code> <code>zh-CN</code> <code>zh-TW</code> <code>x-default</code> ·
51+
raw XML: <a href="/sitemap.xml">/sitemap.xml</a>
52+
</p>
53+
</header>
54+
<table>
55+
<thead>
56+
<tr>
57+
<th>URL</th>
58+
<th>Alternates</th>
59+
<th>Last modified</th>
60+
<th>Changefreq</th>
61+
<th class="num">Priority</th>
62+
</tr>
63+
</thead>
64+
<tbody>
65+
<xsl:for-each select="s:urlset/s:url">
66+
<tr>
67+
<td><a href="{s:loc}"><xsl:value-of select="s:loc" /></a></td>
68+
<td class="tags">
69+
<xsl:for-each select="xhtml:link">
70+
<span class="tag {translate(@hreflang, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')}"><xsl:value-of select="@hreflang" /></span>
71+
</xsl:for-each>
72+
</td>
73+
<td><xsl:value-of select="s:lastmod" /></td>
74+
<td><xsl:value-of select="s:changefreq" /></td>
75+
<td class="num"><xsl:value-of select="s:priority" /></td>
76+
</tr>
77+
</xsl:for-each>
78+
</tbody>
79+
</table>
80+
</main>
81+
</body>
82+
</html>
83+
</xsl:template>
84+
</xsl:stylesheet>

apps/www/scripts/generate-seo-assets.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ function generateSitemap(logins, years) {
126126
LOCALES.map((locale) => sitemapUrlEntry(path, locale, changefreq, priority, lastmod)),
127127
);
128128
const xml = `<?xml version="1.0" encoding="UTF-8"?>
129+
<?xml-stylesheet type="text/xsl" href="/sitemap.xsl"?>
129130
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
130131
${entries.join('\n')}
131132
</urlset>

0 commit comments

Comments
 (0)