You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2026/08/26 10:24:42 UTC
(skywalking-website) 01/01: Team: give every member a shareable permalink and a GitHub link
This is an automated email from the ASF dual-hosted git repository.
wu-sheng pushed a commit to branch feat/team-member-permalinks
in repository https://gitbox.apache.org/repos/asf/skywalking-website.git
commit c7ac2d45ab761a3b0f1ad06bc8aec74d71733c8c
Author: Wu Sheng <wu...@foxmail.com>
AuthorDate: Wed Aug 26 18:24:30 2026 +0800
Team: give every member a shareable permalink and a GitHub link
Members had no way to link to themselves on /team. Each PMC and committer
row now carries id="<apacheId>", and the name is the permalink: /team/#wusheng
scrolls to that person and holds a highlight while the hash does. Clicking a
name copies the absolute URL; clicking the row selects it without copying —
the same hook the docs and downloads cards already use.
The name doubles as the hook rather than a separate icon button because a
reserved icon slot cost enough row width to wrap the longest name onto two
lines. The chain glyph and the copied toast are both absolutely positioned,
so the idle page renders pixel-for-pixel as it did before.
Also adds a GitHub icon beside the existing Twitter one, for the 43 of 61
members whose handle could be established from evidence:
- commits authored under <apacheId>@apache.org, taking the login GitHub
itself resolved the address to
- login equal to the apacheId or to the twitter handle already on file,
confirmed by that account having commits in a SkyWalking repo
- a profile name matching the roster name, cross-checked the same way
The remaining 18 have no github: key and render no icon; nothing was guessed.
There is no public ASF-to-GitHub mapping to lean on, so anything unverifiable
was left out rather than risk pointing at a stranger's profile.
The second icon initially wrapped the longest name, so the row internals are
tightened (meta gap 8->5px, apacheId 11->10px, padding 12->10px) and the hook
is 11px. All 61 rows stay a uniform 42px and the tightest row clears the hook
by 5px; that budget is noted in the SCSS.
Fixes a pre-existing bug in the shared hook while here: it called
history.replaceState before setting location.hash. replaceState rewrites the
URL without moving the document's target element, leaving the assignment with
nothing to change, so :target never applied and clicking a card on /downloads
or /docs copied the right link but highlighted nothing. Landing on a URL that
already carried the hash was always fine; only the in-page click path broke.
---
assets/scss/_custom_team.scss | 62 ++++++++++++++++++++++--
data/committee.yml | 92 ++++++++++++++++++------------------
layouts/partials/card-permalink.html | 20 +++++---
layouts/shortcodes/team-members.html | 47 +++++++++---------
layouts/team/baseof.html | 1 +
5 files changed, 143 insertions(+), 79 deletions(-)
diff --git a/assets/scss/_custom_team.scss b/assets/scss/_custom_team.scss
index 654d5efbd949..8983a30f78d0 100644
--- a/assets/scss/_custom_team.scss
+++ b/assets/scss/_custom_team.scss
@@ -1,3 +1,5 @@
+$link-hook: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/%3E%3Cpath d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/%3E%3C/svg%3E");
+
// =====================================================================
// Team page — light theme, consistent with home/events/blog/downloads
// (uses $ink/$body/$muted/$line/$brand/$brand-grad from _custom_home.scss)
@@ -40,15 +42,65 @@
display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px;
}
.member {
- display: flex; align-items: center; justify-content: space-between; gap: 10px;
- padding: 10px 12px; background: #fff; border: 1px solid $line; border-radius: 10px;
+ display: flex; align-items: center; justify-content: space-between; gap: 8px;
+ padding: 10px 10px; background: #fff; border: 1px solid $line; border-radius: 10px;
+ scroll-margin-top: 90px; // clear the sticky navbar when jumped to via #apacheId
+ transition: box-shadow .18s ease, border-color .18s ease, background .18s ease;
&:hover { border-color: #d6e4f5; box-shadow: 0 10px 24px -18px rgba(17,24,39,.25); }
.m-name { font-size: 13.5px; font-weight: 600; color: $ink; }
- .m-meta { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; }
+ .m-meta { display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto; }
.m-id {
- font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; color: $muted;
+ font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 10px; color: $muted;
+ }
+ .m-tw { color: #1d9bf0; display: inline-flex; .icon-twitter { font-size: 12.5px; } &:hover { opacity: .8; } }
+ .m-gh { color: $body; display: inline-flex; .icon-github { font-size: 12.5px; } &:hover { color: $ink; } }
+ }
+
+ // The name is the shareable permalink. Its link-hook glyph (::after) and the copied
+ // toast (::before) are both absolutely positioned, so nothing here can widen a row
+ // and wrap a long name. The glyph is the same chain mark the project cards use,
+ // drawn as a mask so $brand tints it.
+ // The glyph needs 15px (4px offset + 11px) of clear space after the longest name.
+ // Today's tightest row, "Sheng Wu (Project V.P.)" carrying both icons, clears it by
+ // 5px. A longer name in committee.yml would collide with the apacheId — tighten
+ // .m-meta's gap or .m-id's size if that happens.
+ a.m-name {
+ position: relative; text-decoration: none;
+ &:hover { color: $brand; }
+ &:focus-visible { outline: 2px solid rgba(55, 136, 208, .5); outline-offset: 2px; border-radius: 4px; }
+ &::after {
+ content: ""; position: absolute; left: calc(100% + 4px); top: 50%;
+ width: 11px; height: 11px; margin-top: -5.5px;
+ background-color: $brand;
+ -webkit-mask: $link-hook center / contain no-repeat;
+ mask: $link-hook center / contain no-repeat;
+ opacity: 0; transition: opacity .15s ease; pointer-events: none;
+ }
+ &::before {
+ content: "Link copied"; position: absolute; left: calc(100% + 6px); top: 50%;
+ transform: translateY(-50%);
+ background: $brand; color: #fff; font-size: 10.5px; font-weight: 600;
+ padding: 3px 7px; border-radius: 6px; white-space: nowrap;
+ opacity: 0; transition: opacity .15s ease; pointer-events: none; z-index: 5;
}
- .m-tw { color: #1d9bf0; display: inline-flex; .icon-twitter { font-size: 13px; } &:hover { opacity: .8; } }
+ // while the toast shows it stands in for the glyph
+ &.copied::before { opacity: 1; }
+ &.copied::after { opacity: 0 !important; }
+ }
+ .member:hover a.m-name::after,
+ .member:target a.m-name::after,
+ a.m-name:focus-visible::after { opacity: 1; }
+ // no hover on touch, so keep the affordance visible there (same call the
+ // home page's .frow-anchor makes)
+ @media (hover: none) {
+ a.m-name::after { opacity: .55; }
+ }
+ // the shared person link landed on this row — keep it marked while the hash holds
+ .member:target {
+ background: #f7fbff;
+ border-color: $brand;
+ box-shadow: 0 0 0 3px rgba(55, 136, 208, .25), 0 10px 24px -18px rgba(17, 24, 39, .3);
+ .m-name { color: #1f5fa0; }
}
// total count pill
diff --git a/data/committee.yml b/data/committee.yml
index 45ddaebdad5c..1f9b80478e71 100644
--- a/data/committee.yml
+++ b/data/committee.yml
@@ -1,67 +1,69 @@
# SkyWalking PMC & Committers. Rendered on /team by the team-members shortcode.
-# Each entry: name, apacheId, and optional twitter handle (used for both the
-# link and the displayed text). Add new members here — the tables build themselves.
+# Each entry: name, apacheId, and optional github / twitter handles (each renders
+# as an icon link). Add new members here — the tables build themselves.
+# github: handles were resolved from GitHub-verified commit authorship and profile
+# data; members without one simply render no GitHub icon.
pmc:
- - { name: Can Li, apacheId: lican, twitter: Candy198088 }
+ - { name: Can Li, apacheId: lican, twitter: Candy198088, github: candyleer }
- { name: DongXue Si, apacheId: ilucky }
- { name: Han Liu, apacheId: liuhan, twitter: dalek_zero }
- { name: Haochao Zhuang, apacheId: daming }
- - { name: Haoyang Liu, apacheId: liuhaoyangzz }
- - { name: Hongtao Gao, apacheId: hanahmily }
- - { name: Hongwei Zhai, apacheId: innerpeacez }
- - { name: Ignasi Barrera, apacheId: nacx }
- - { name: Jiajing Lu, apacheId: lujiajing }
+ - { name: Haoyang Liu, apacheId: liuhaoyangzz, github: liuhaoyang }
+ - { name: Hongtao Gao, apacheId: hanahmily, github: hanahmily }
+ - { name: Hongwei Zhai, apacheId: innerpeacez, github: innerpeacez }
+ - { name: Ignasi Barrera, apacheId: nacx, github: nacx }
+ - { name: Jiajing Lu, apacheId: lujiajing, github: lujiajing1126 }
- { name: Jian Tan, apacheId: tanjian }
- { name: Jiaqi Lin, apacheId: linjiaqi }
- - { name: Jiemin Xia, apacheId: jmjoy }
- - { name: Jinlin Fu, apacheId: withlin }
- - { name: Juntao Zhang, apacheId: zhangjuntao }
- - { name: Kai Wan, apacheId: wankai, twitter: wankai123 }
+ - { name: Jiemin Xia, apacheId: jmjoy, github: jmjoy }
+ - { name: Jinlin Fu, apacheId: withlin, github: withlin }
+ - { name: Juntao Zhang, apacheId: zhangjuntao, github: Jtrust }
+ - { name: Kai Wan, apacheId: wankai, twitter: wankai123, github: wankai123 }
- { name: Kai Wang, apacheId: wangkai }
- { name: Lang Li, apacheId: lilang }
- - { name: Michael Semb Wever, apacheId: mck }
- - { name: Qiuxia Fan, apacheId: qiuxiafan }
- - { name: Sheng Wu (Project V.P.), apacheId: wusheng, twitter: wusheng1108 }
- - { name: Shinn Zhang, apacheId: zhangxin, twitter: ascrutae }
- - { name: Wei Zhang, apacheId: zhangwei24 }
+ - { name: Michael Semb Wever, apacheId: mck, github: michaelsembwever }
+ - { name: Qiuxia Fan, apacheId: qiuxiafan, github: Fine0830 }
+ - { name: Sheng Wu (Project V.P.), apacheId: wusheng, twitter: wusheng1108, github: wu-sheng }
+ - { name: Shinn Zhang, apacheId: zhangxin, twitter: ascrutae, github: ascrutae }
+ - { name: Wei Zhang, apacheId: zhangwei24, github: rainbend }
- { name: Wenbing Wang, apacheId: wangwenbin }
- - { name: Willem Ning Jiang, apacheId: ningjiang }
- - { name: Yang Bai, apacheId: baiyang }
- - { name: Yanlong He, apacheId: heyanlong, twitter: YanlongHe }
+ - { name: Willem Ning Jiang, apacheId: ningjiang, github: WillemJiang }
+ - { name: Yang Bai, apacheId: baiyang, github: bai-yang }
+ - { name: Yanlong He, apacheId: heyanlong, twitter: YanlongHe, github: heyanlong }
- { name: Yao Wang, apacheId: ywang }
- - { name: Ye Cao, apacheId: dashanji }
- - { name: Yihao Chen, apacheId: yihaochen, twitter: Superskyyyyy }
- - { name: Yixiong Cao, apacheId: caoyixiong }
- - { name: Yongsheng Peng, apacheId: pengys }
- - { name: Youliang Huang, apacheId: butterbright, twitter: butterbright }
- - { name: Yuguang Zhao, apacheId: zhaoyuguang }
- - { name: Zhang Kewei, apacheId: zhangkewei }
- - { name: Zhenxu Ke, apacheId: kezhenxu94, twitter: kezhenxu94 }
- - { name: Zixin Zhou, apacheId: zhouzixin, twitter: starry_loveee }
+ - { name: Ye Cao, apacheId: dashanji, github: dashanji }
+ - { name: Yihao Chen, apacheId: yihaochen, twitter: Superskyyyyy, github: Superskyyy }
+ - { name: Yixiong Cao, apacheId: caoyixiong, github: IanCao }
+ - { name: Yongsheng Peng, apacheId: pengys, github: peng-yongsheng }
+ - { name: Youliang Huang, apacheId: butterbright, twitter: butterbright, github: ButterBright }
+ - { name: Yuguang Zhao, apacheId: zhaoyuguang, github: zhaoyuguang }
+ - { name: Zhang Kewei, apacheId: zhangkewei, github: zhangkewei }
+ - { name: Zhenxu Ke, apacheId: kezhenxu94, twitter: kezhenxu94, github: kezhenxu94 }
+ - { name: Zixin Zhou, apacheId: zhouzixin, twitter: starry_loveee, github: CodePrometheus }
committer:
- - { name: Brandon Fergerson, apacheId: bfergerson }
- - { name: Ziyan Chen, apacheId: clairechen }
- - { name: Gong Dewei, apacheId: kylixs }
- - { name: Gui Cao, apacheId: zifeihan, twitter: zifeihan007 }
- - { name: Hailin Wang, apacheId: wanghailin }
+ - { name: Brandon Fergerson, apacheId: bfergerson, github: BFergerson }
+ - { name: Ziyan Chen, apacheId: clairechen, github: CzyerChen }
+ - { name: Gong Dewei, apacheId: kylixs, github: kylixs }
+ - { name: Gui Cao, apacheId: zifeihan, twitter: zifeihan007, github: zifeihan }
+ - { name: Hailin Wang, apacheId: wanghailin, github: hailin0 }
- { name: Huaxi Jiang, apacheId: hoshea, twitter: Zerone___01 }
- { name: Jiapeng Liu, apacheId: liujiapeng }
- - { name: JunXu Chen, apacheId: chenjunxu }
- - { name: Ke Zhang, apacheId: zhangke, twitter: Humbertttttt }
- - { name: Ming Wen, apacheId: wenming }
+ - { name: JunXu Chen, apacheId: chenjunxu, github: nic-chen }
+ - { name: Ke Zhang, apacheId: zhangke, twitter: Humbertttttt, github: maxkezhang }
+ - { name: Ming Wen, apacheId: wenming, github: moonming }
- { name: Puguang Yang, apacheId: ypg }
- - { name: Qiang Li, apacheId: liqiang }
+ - { name: Qiang Li, apacheId: liqiang, github: liqiangz }
- { name: Qiang Xu, apacheId: xuqiang }
- - { name: Ruixian Wang, apacheId: ax1an, twitter: Ax1anRISE }
+ - { name: Ruixian Wang, apacheId: ax1an, twitter: Ax1anRISE, github: Ax1an }
- { name: Sheng Wang, apacheId: wangsheng }
- - { name: Tomasz Pytel, apacheId: tompytel }
- - { name: Wei Hua, apacheId: alonelaval }
+ - { name: Tomasz Pytel, apacheId: tompytel, github: tom-pytel }
+ - { name: Wei Hua, apacheId: alonelaval, github: alonelaval }
- { name: Wei Jin, apacheId: kvn }
- { name: Weijie Zou, apacheId: kdump, twitter: RootShellExp }
- - { name: Weiyi Liu, apacheId: wayilau }
- - { name: Xiang Wei, apacheId: weixiang1862 }
- - { name: YiMing Shao, apacheId: peachisai }
- - { name: Yueqin Zhang, apacheId: yswdqz }
+ - { name: Weiyi Liu, apacheId: wayilau, github: wayilau }
+ - { name: Xiang Wei, apacheId: weixiang1862, github: weixiang1862 }
+ - { name: YiMing Shao, apacheId: peachisai, github: peachisai }
+ - { name: Yueqin Zhang, apacheId: yswdqz, github: yswdqz }
- { name: Yuntao Li, apacheId: liyuntao }
- { name: Zhusheng Xu, apacheId: aderm }
diff --git a/layouts/partials/card-permalink.html b/layouts/partials/card-permalink.html
index 2c7930b2f902..e5060c0f76d9 100644
--- a/layouts/partials/card-permalink.html
+++ b/layouts/partials/card-permalink.html
@@ -1,13 +1,19 @@
-{{- /* Deep-link "hook" for project cards (docs landing + downloads).
- - clicking the # hook copies the full anchored URL and selects the card
+{{- /* Deep-link "hook" for project cards (docs landing + downloads) and team member rows.
+ - clicking the # hook (or a team member's name) copies the full anchored URL
+ and selects the card
- clicking anywhere on the card (off real links) selects it + updates the URL hash */ -}}
<script>
(function () {
function selectAndCopy(id, withCopy, badge) {
if (!id) return;
- // history.replaceState keeps the back button clean; setting hash drives :target
- if (location.hash !== '#' + id) { history.replaceState(null, '', '#' + id); }
- // re-assert :target even if the hash was already set
+ // Only a real fragment navigation moves the document's target element, which is
+ // what drives :target and the scroll. history.replaceState rewrites the URL
+ // without moving it, so doing that first left `location.hash = id` with nothing
+ // to change and the selection never applied. Drop the fragment silently when it
+ // is already ours, then let the assignment below do the navigation.
+ if (location.hash === '#' + id) {
+ history.replaceState(null, '', location.pathname + location.search);
+ }
location.hash = id;
if (withCopy && navigator.clipboard) {
navigator.clipboard.writeText(location.href).then(function () {
@@ -18,7 +24,7 @@
}
}
- document.querySelectorAll('.card-anchor').forEach(function (a) {
+ document.querySelectorAll('.card-anchor, .m-link').forEach(function (a) {
a.addEventListener('click', function (e) {
e.preventDefault();
e.stopPropagation();
@@ -26,7 +32,7 @@
});
});
- document.querySelectorAll('.docs-card[id], .dl-card[id]').forEach(function (card) {
+ document.querySelectorAll('.docs-card[id], .dl-card[id], .member[id]').forEach(function (card) {
card.addEventListener('click', function (e) {
// don't hijack clicks on real interactive elements inside the card
if (e.target.closest('a, button, summary, details, input')) return;
diff --git a/layouts/shortcodes/team-members.html b/layouts/shortcodes/team-members.html
index 7325baa4ae96..c11b8b1eb47a 100644
--- a/layouts/shortcodes/team-members.html
+++ b/layouts/shortcodes/team-members.html
@@ -1,37 +1,40 @@
-{{- /* Renders PMC + Committer rosters from data/committee.yml as merged grids. */ -}}
+{{- /* Renders PMC + Committer rosters from data/committee.yml as merged grids.
+
+ Every member row carries id="<apacheId>" and its name is an .m-link permalink,
+ so /team/#wusheng scrolls to that person and highlights them via .member:target.
+ The name doubles as the hook rather than a separate icon because a reserved
+ icon slot cost enough row width to wrap the longest name onto two lines.
+ partials/card-permalink.html (loaded from layouts/team/baseof.html) wires the
+ click-to-copy behaviour. apacheIds are unique and URL-safe, and don't collide
+ with the other ids on this page (#contributors, the per-repo contributor
+ blocks, #team-contributor-input). */ -}}
{{ $c := .Site.Data.committee }}
+{{ $sections := slice
+ (dict "title" "Project Management Committee" "list" $c.pmc)
+ (dict "title" "Committers" "list" $c.committer) }}
<div class="team-roles">
- {{ with $c.pmc }}
+ {{ range $sections }}
+ {{ if .list }}
<section class="team-role">
- <h3>Project Management Committee <span class="role-count">{{ len . }}</span></h3>
+ <h3>{{ .title }} <span class="role-count">{{ len .list }}</span></h3>
<div class="member-grid">
- {{ range . }}
- <div class="member">
+ {{ range .list }}
+ {{ $m := . }}
+ <div class="member"{{ with .apacheId }} id="{{ . }}"{{ end }}>
+ {{ with .apacheId }}
+ <a class="m-name m-link" href="#{{ . }}" data-anchor="{{ . }}" title="Copy link to {{ $m.name }}" aria-label="Copy link to {{ $m.name }}">{{ $m.name }}</a>
+ {{ else }}
<span class="m-name">{{ .name }}</span>
+ {{ end }}
<span class="m-meta">
<span class="m-id">{{ .apacheId }}</span>
- {{ with .twitter }}<a class="m-tw" href="https://twitter.com/{{ . }}" target="_blank" rel="noopener" aria-label="Twitter {{ . }}"><i class="iconfont icon-twitter"></i></a>{{ end }}
+ {{ with .github }}<a class="m-gh" href="https://github.com/{{ . }}" target="_blank" rel="noopener" aria-label="GitHub {{ . }}" title="GitHub {{ . }}"><i class="iconfont icon-github"></i></a>{{ end }}
+ {{ with .twitter }}<a class="m-tw" href="https://twitter.com/{{ . }}" target="_blank" rel="noopener" aria-label="Twitter {{ . }}" title="Twitter {{ . }}"><i class="iconfont icon-twitter"></i></a>{{ end }}
</span>
</div>
{{ end }}
</div>
</section>
{{ end }}
-
- {{ with $c.committer }}
- <section class="team-role">
- <h3>Committers <span class="role-count">{{ len . }}</span></h3>
- <div class="member-grid">
- {{ range . }}
- <div class="member">
- <span class="m-name">{{ .name }}</span>
- <span class="m-meta">
- <span class="m-id">{{ .apacheId }}</span>
- {{ with .twitter }}<a class="m-tw" href="https://twitter.com/{{ . }}" target="_blank" rel="noopener" aria-label="Twitter {{ . }}"><i class="iconfont icon-twitter"></i></a>{{ end }}
- </span>
- </div>
- {{ end }}
- </div>
- </section>
{{ end }}
</div>
diff --git a/layouts/team/baseof.html b/layouts/team/baseof.html
index 74c94849e443..f57e30049e87 100644
--- a/layouts/team/baseof.html
+++ b/layouts/team/baseof.html
@@ -18,5 +18,6 @@
{{ partial "sidebar-skywalking.html" . }}
{{ partial "scripts.html" . }}
{{ partial "script-team.html" . }}
+ {{ partial "card-permalink.html" . }}
</body>
</html>