Skip to content

Commit 2b4fce2

Browse files
committed
Merge branch 'feat/seo-geo-enhancements'
2 parents 03ffd77 + 0909751 commit 2b4fce2

6 files changed

Lines changed: 333 additions & 11 deletions

File tree

ossheroes/themes/OpenSourceWin/layout/_partial/detail.ejs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
</div>
4747
<div class="detail-term-line">
4848
<span class="detail-term-out" aria-hidden="true">&gt;</span>
49-
<span class="detail-term-key" data-i18n-zh="简介" data-i18n-en="bio">简介</span>
49+
<span class="detail-term-key" data-i18n-zh="所在地" data-i18n-en="location">所在地</span>
5050
<span class="detail-term-sep" aria-hidden="true">::</span>
5151
<span class="text-secondary"><%- item.description %></span>
5252
</div>

ossheroes/themes/OpenSourceWin/layout/_partial/head.ejs

Lines changed: 115 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,87 @@
44
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
55
<meta name="viewport" content="width=device-width, initial-scale=1"/>
66

7+
<!-- 开发者详情页判定:page 布局、非年度榜单页(无 data_year)、带 slug -->
8+
<%
9+
// 历史数据里存在 "null" / "undefined" 之类的占位字符串,统一归一化为空
10+
var normalizeMeta = function (val) {
11+
if (val === null || val === undefined) return '';
12+
var s = String(val).trim();
13+
return /^(null|undefined|n\/?a)$/i.test(s) ? '' : s;
14+
};
15+
var isDevProfile = is_page() && !page.data_year && !!page.slug;
16+
var devName = '';
17+
var devLogin = '';
18+
var devLocation = '';
19+
var devAvatar = '';
20+
var devRepos = [];
21+
if (isDevProfile) {
22+
// 部分 login 是纯数字(如 1715173329),YAML 会解析成 Number,统一转字符串
23+
devLogin = String(page.slug);
24+
devName = normalizeMeta(page.name) || devLogin;
25+
// 注意:front-matter 的 description 字段实际存的是 GitHub location 数据
26+
devLocation = normalizeMeta(page.description);
27+
var rawAvatar = normalizeMeta(page.github_avatar);
28+
devAvatar = /^https?:\/\//.test(rawAvatar) ? rawAvatar : '';
29+
// 从正文 <li> 列表提取主要贡献项目(github.com/owner/repo 链接),取前 3 个仓库名
30+
var devContent = page.content || '';
31+
var devSeen = {};
32+
var devLiRe = /<li>([\s\S]*?)<\/li>/g;
33+
var devRepoRe = /href="https?:\/\/github\.com\/([A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?)\/([A-Za-z0-9_.-]+?)\/?"/;
34+
var devMatch;
35+
while ((devMatch = devLiRe.exec(devContent)) !== null) {
36+
var linkMatch = devMatch[1].match(devRepoRe);
37+
if (!linkMatch) continue;
38+
var repoKey = linkMatch[2].toLowerCase();
39+
if (devSeen[repoKey]) continue;
40+
devSeen[repoKey] = true;
41+
devRepos.push(linkMatch[2]);
42+
if (devRepos.length >= 3) break;
43+
}
44+
}
45+
%>
46+
747
<!-- Title -->
848
<%
949
var title = [];
10-
if (page.name) {
11-
title.push(page.name);
12-
} else if (page.slug) {
13-
title.push(page.slug);
50+
if (isDevProfile) {
51+
title.push(devName + ' (@' + devLogin + ')');
52+
title.push('中国开源码力榜开发者档案');
53+
} else {
54+
if (page.name) {
55+
title.push(page.name);
56+
} else if (page.slug) {
57+
title.push(page.slug);
58+
}
59+
title.push(config.title);
1460
}
15-
title.push(config.title);
1661
%>
1762
<title><%= title.join(' - ') %></title>
1863

1964
<!--Description-->
2065

2166
<%
2267
var description = '';
23-
if (page.description) {
68+
if (isDevProfile) {
69+
// 组合 name、login、location、主要贡献项目,生成可读的档案描述
70+
var devDesc = devName + ' (GitHub @' + devLogin + ')';
71+
if (devLocation) {
72+
devDesc += ',所在地 ' + devLocation;
73+
}
74+
devDesc += ',中国开源码力榜上榜开发者';
75+
if (devRepos.length) {
76+
devDesc += ',主要贡献项目包括 ' + devRepos.join('') + '';
77+
}
78+
// 数据稀疏时逐句补稳定说明,保证描述落在 80–160 字的目标区间
79+
var devFillers = [
80+
',档案收录其 GitHub 开源贡献、历年在榜名次与开发活动数据',
81+
',榜单由 OpenSource.Win、开源社与 X-lab 开放实验室基于 OpenRank 算法联合评选'
82+
];
83+
for (var fi = 0; fi < devFillers.length && devDesc.length < 79; fi++) {
84+
devDesc += devFillers[fi];
85+
}
86+
description = devDesc + '';
87+
} else if (page.description) {
2488
description = page.description;
2589
} else if (config.description) {
2690
description = config.description;
@@ -36,7 +100,12 @@
36100
<% } %>
37101

38102
<!--Keywords-->
39-
<% if (config.keywords) { %>
103+
<% if (isDevProfile) {
104+
var devKeywords = [devLogin, devName, '@' + devLogin, 'GitHub 开发者', '开源开发者', '中国开源码力榜', 'OpenSource.Win'];
105+
devKeywords = devKeywords.filter(function (kw, i) { return kw && devKeywords.indexOf(kw) === i; });
106+
%>
107+
<meta name="keywords" content="<%= devKeywords.join(',') %>"/>
108+
<% } else if (config.keywords) { %>
40109
<meta name="keywords" content="<%= Array.isArray(config.keywords) ? config.keywords.join(',') : config.keywords %>"/>
41110
<% } %>
42111

@@ -56,10 +125,14 @@
56125
<!--Open Graph Site Name-->
57126
<meta property="og:site_name" content="<%= config.title %>"/>
58127

59-
<!--Open Graph URL / Locale / Image-->
128+
<!--Open Graph URL / Locale / Image(开发者页 og:image 用其 GitHub avatar)-->
60129
<meta property="og:url" content="<%- full_url_for(page.path || '') %>"/>
61130
<meta property="og:locale" content="<%= (config.language || 'zh-CN').replace('-', '_') %>"/>
131+
<% if (isDevProfile && devAvatar) { %>
132+
<meta property="og:image" content="<%= devAvatar %>"/>
133+
<% } else { %>
62134
<meta property="og:image" content="https://opensource.win/ossheroes/img/banner-index-new.png"/>
135+
<% } %>
63136

64137
<!--Canonical / Theme Color-->
65138
<link rel="canonical" href="<%- full_url_for(page.path || '') %>"/>
@@ -78,7 +151,40 @@
78151
<% if (description) { %>
79152
<meta name="twitter:description" content="<%= description %>">
80153
<% } %>
81-
<meta name="twitter:image" content="https://opensource.win/ossheroes/img/banner-index-new.png">
154+
<% if (isDevProfile && devAvatar) { %>
155+
<meta name="twitter:image" content="<%= devAvatar %>">
156+
<% } else { %>
157+
<meta name="twitter:image" content="https://opensource.win/ossheroes/img/banner-index-new.png">
158+
<% } %>
159+
160+
<!--开发者详情页 JSON-LD 结构化数据:ProfilePage + Person-->
161+
<% if (isDevProfile) {
162+
var person = {
163+
'@type': 'Person',
164+
'name': devName,
165+
'alternateName': devLogin,
166+
'url': 'https://opensource.win/ossheroes/' + devLogin + '/',
167+
'sameAs': ['https://github.com/' + devLogin]
168+
};
169+
if (devAvatar) {
170+
person.image = devAvatar;
171+
}
172+
if (devLocation) {
173+
person.address = { '@type': 'PostalAddress', 'addressLocality': devLocation };
174+
}
175+
var jsonLd = {
176+
'@context': 'https://schema.org',
177+
'@type': 'ProfilePage',
178+
'name': title.join(' - '),
179+
'url': 'https://opensource.win/ossheroes/' + devLogin + '/',
180+
'mainEntity': person
181+
};
182+
if (description) {
183+
jsonLd.description = description;
184+
}
185+
%>
186+
<script type="application/ld+json"><%- JSON.stringify(jsonLd).replace(/</g, '\\u003c') %></script>
187+
<% } %>
82188

83189
<link rel="preconnect" href="https://fonts.googleapis.com">
84190
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "module",
66
"scripts": {
77
"dev": "vite",
8-
"build": "tsc -b && vite build",
8+
"build": "tsc -b && vite build && node scripts/generate-seo-assets.mjs",
99
"lint": "eslint .",
1010
"preview": "vite preview"
1111
},

public/llms.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# OpenSource.Win
2+
3+
> OpenSource.Win 是《OpenSource.Win 宣言》的发布站点,也是「中国开源码力榜」的官方网站。宣言主张相信开放的力量,构建人机共进的文明 —— Open Source Will Win the Future。中国开源码力榜由 OpenSource.Win、开源社、X-lab 开放实验室联合发起,基于 OpenRank 算法评选中国开源开发者年度榜单。
4+
>
5+
> 本站全部内容完全开放:欢迎搜索引擎与 AI 爬虫抓取、索引、引用,并明确允许用于 AI 模型训练(详见 https://opensource.win/robots.txt )。
6+
7+
## 宣言 / Manifesto
8+
9+
- [OpenSource.Win 宣言](https://opensource.win/): 站点首页,中英双语的 OpenSource.Win 宣言全文。
10+
11+
## 中国开源码力榜 / HeroRank
12+
13+
- [码力榜首页](https://opensource.win/ossheroes/): 中国开源码力榜介绍与历年榜单入口。
14+
- [2021 年度榜单](https://opensource.win/ossheroes/ranking-2021.html): 2021 中国开源码力榜完整榜单。
15+
- [2022 年度榜单](https://opensource.win/ossheroes/ranking-2022.html): 2022 中国开源码力榜完整榜单。
16+
- [2023 年度榜单](https://opensource.win/ossheroes/ranking-2023.html): 2023 中国开源码力榜完整榜单。
17+
- [2024 年度榜单](https://opensource.win/ossheroes/ranking-2024.html): 2024 中国开源码力榜完整榜单。
18+
- [2025 年度榜单](https://opensource.win/ossheroes/ranking-2025.html): 2025 中国开源码力榜完整榜单。
19+
20+
## 开发者档案 / Developer Profiles
21+
22+
- 路径模式为 `https://opensource.win/ossheroes/<login>/`,其中 `<login>` 为开发者的 GitHub 用户名,例如 [Goooler 的档案](https://opensource.win/ossheroes/Goooler/)。
23+
- 每个档案页包含开发者名称、所在地、GitHub 主页链接、历年在榜名次与主要贡献项目列表。
24+
- 完整开发者页面清单见站点地图: [sitemap.xml](https://opensource.win/sitemap.xml)
25+
26+
## 开放声明 / Openness
27+
28+
- 本站内容开放供搜索索引与 AI 训练使用,不要求署名(但欢迎注明来源)。
29+
- 结构化数据: 开发者档案页提供 JSON-LD(ProfilePage + Person)结构化数据。

public/robots.txt

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# OpenSource.Win — 本站内容完全开放
2+
# 我们以最开放的姿态欢迎所有搜索引擎与 AI 爬虫抓取、索引本站内容,
3+
# 包括用于 AI 模型训练。Open Source Will Win the Future.
4+
5+
User-agent: *
6+
Allow: /
7+
8+
# —— 主流 AI 爬虫:全部显式允许(含搜索、用户代理与训练用途)——
9+
10+
# OpenAI
11+
User-agent: GPTBot
12+
Allow: /
13+
14+
User-agent: OAI-SearchBot
15+
Allow: /
16+
17+
User-agent: ChatGPT-User
18+
Allow: /
19+
20+
# Anthropic
21+
User-agent: ClaudeBot
22+
Allow: /
23+
24+
User-agent: Claude-User
25+
Allow: /
26+
27+
User-agent: anthropic-ai
28+
Allow: /
29+
30+
# Google(AI 训练控制项)
31+
User-agent: Google-Extended
32+
Allow: /
33+
34+
# Perplexity
35+
User-agent: PerplexityBot
36+
Allow: /
37+
38+
User-agent: Perplexity-User
39+
Allow: /
40+
41+
# 字节跳动
42+
User-agent: Bytespider
43+
Allow: /
44+
45+
# Common Crawl
46+
User-agent: CCBot
47+
Allow: /
48+
49+
# Cohere
50+
User-agent: cohere-ai
51+
Allow: /
52+
53+
# Meta
54+
User-agent: Meta-ExternalAgent
55+
Allow: /
56+
57+
# Apple(AI 训练控制项)
58+
User-agent: Applebot-Extended
59+
Allow: /
60+
61+
# Amazon
62+
User-agent: Amazonbot
63+
Allow: /
64+
65+
# Diffbot
66+
User-agent: Diffbot
67+
Allow: /
68+
69+
Sitemap: https://opensource.win/sitemap.xml

0 commit comments

Comments
 (0)