Skip to content

Commit 2ee0e04

Browse files
committed
Update badge
1 parent bd89403 commit 2ee0e04

3 files changed

Lines changed: 101 additions & 32 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,40 @@ jobs:
5151
-e "ssh -i ~/.ssh/deploy_key -p ${SERVER_PORT:-22} -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o PubkeyAcceptedAlgorithms=+ssh-rsa" \
5252
./website/public/ \
5353
"${SSH_USERNAME}@${SSH_HOST}:${SERVER_DESTINATION:-/var/www/books/leetcode/}"
54+
55+
word-count: # 重新统计总字数并把 README 里的徽章数字刷新、自动提交回仓库
56+
# 只在 master 上跑(add_hugo 等分支不自动改 README)。
57+
if: github.ref == 'refs/heads/master'
58+
runs-on: ubuntu-latest
59+
permissions:
60+
contents: write # 需要写权限才能 commit & push 回仓库
61+
steps:
62+
- uses: actions/checkout@v5
63+
64+
- name: Compute total word count # 跑仓库自带脚本(标准库即可,ubuntu-latest 自带 python3)
65+
id: wc
66+
run: |
67+
COUNT=$(python3 website/content/ChapterFour/pytool/WordCount.py | awk '/total word count/{print $NF}')
68+
# 防御:脚本异常时不要用空值/非数字去覆盖徽章
69+
if ! echo "$COUNT" | grep -qE '^[0-9]+$'; then
70+
echo "WordCount.py 未返回有效数字:'$COUNT'"; exit 1
71+
fi
72+
echo "total word count = $COUNT"
73+
echo "count=$COUNT" >> "$GITHUB_OUTPUT"
74+
75+
- name: Update badge & commit if changed
76+
run: |
77+
# 只替换 README 里 Total Word Count 徽章的数字部分
78+
COUNT="${{ steps.wc.outputs.count }}"
79+
sed -i -E "s#(Total%20Word%20Count-)[0-9]+(-success)#\1${COUNT}\2#" README.md
80+
if git diff --quiet -- README.md; then
81+
echo "徽章已是最新(${COUNT}),无需提交。"
82+
else
83+
git config user.name "github-actions[bot]"
84+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
85+
git add README.md
86+
# [skip ci]:这次只改 README 的自动提交不必再触发任何 workflow(deploy 已 paths-ignore,
87+
# 但 test.yml 没有,所以统一用 skip ci 防止多余构建,也彻底杜绝循环触发)。
88+
git commit -m "chore: update Total Word Count badge to ${COUNT} [skip ci]"
89+
git push
90+
fi

README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,27 @@
1010
![](./website/static/wechat-qr-code.png)
1111

1212
<p align='center'>
13-
<a href="https://github.com/halfrost/leetcode-go/releases/" rel="nofollow"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/halfrost/LeetCode-Go/total?label=PDF%20downloads"></a>
14-
<img src="https://img.shields.io/badge/Total%20Word%20Count-738884-success">
13+
<a href="https://github.com/halfrost/LeetCode-Go/releases/" rel="nofollow"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/halfrost/LeetCode-Go/total?label=PDF%20downloads"></a>
14+
<img src="https://img.shields.io/badge/Total%20Word%20Count-717961-success">
1515
<a href="https://github.com/halfrost/LeetCode-Go/actions/workflows/deploy.yml" rel="nofollow"><img src="https://github.com/halfrost/LeetCode-Go/actions/workflows/deploy.yml/badge.svg?branch=master" alt="Deploy Status"></a>
1616
<a href="https://github.com/halfrost/LeetCode-Go/actions/workflows/test.yml" rel="nofollow"><img src="https://github.com/halfrost/LeetCode-Go/actions/workflows/test.yml/badge.svg?branch=master" alt="Go Test Status"></a>
1717
<a href="https://goreportcard.com/report/github.com/halfrost/LeetCode-Go" rel="nofollow"><img src="https://goreportcard.com/badge/github.com/halfrost/LeetCode-Go"></a>
1818
<img src="https://img.shields.io/badge/runtime%20beats-100%25-success">
1919
<a href="https://codecov.io/gh/halfrost/LeetCode-Go"><img src="https://codecov.io/gh/halfrost/LeetCode-Go/branch/master/graph/badge.svg" /></a>
20-
<!--<img alt="GitHub go.mod Go version" src="https://img.shields.io/github/go-mod/go-version/halfrost/LeetCode-Go?color=26C2F0">-->
21-
<img alt="Support Go version" src="https://img.shields.io/badge/Go-v1.15-26C2F0">
20+
<img alt="Go Version" src="https://img.shields.io/github/go-mod/go-version/halfrost/LeetCode-Go?label=Go&color=26C2F0">
2221
<img src="https://visitor-badge.laobi.icu/badge?page_id=halfrost.LeetCode-Go">
2322
</p>
2423

2524
<p align='center'>
26-
<a href="https://github.com/halfrost/leetcode-go/blob/master/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/halfrost/LeetCode-Go?label=License"></a>
27-
<img src="https://img.shields.io/badge/License-CC-000000.svg">
25+
<a href="https://github.com/halfrost/LeetCode-Go/blob/master/LICENSE"><img alt="Code License" src="https://img.shields.io/github/license/halfrost/LeetCode-Go?label=Code%20License"></a>
26+
<img alt="Book License" src="https://img.shields.io/badge/Book%20License-CC-000000.svg">
2827
<a href="https://leetcode.com/halfrost/"><img src="https://img.shields.io/badge/@halfrost-8751-yellow.svg">
2928
<img src="https://img.shields.io/badge/language-Golang-26C2F0.svg">
3029
<a href="https://halfrost.com"><img src="https://img.shields.io/badge/Blog-Halfrost--Field-80d4f9.svg?style=flat"></a>
3130
<a href="http://weibo.com/halfrost"><img src="https://img.shields.io/badge/weibo-@halfrost-f974ce.svg?style=flat&colorA=f4292e"></a>
3231
<a href="https://twitter.com/halffrost"><img src="https://img.shields.io/badge/twitter-@halffrost-F8E81C.svg?style=flat&colorA=009df2"></a>
3332
<a href="https://www.zhihu.com/people/halfrost/activities"><img src="https://img.shields.io/badge/%E7%9F%A5%E4%B9%8E-@halfrost-fd6f32.svg?style=flat&colorA=0083ea"></a>
34-
<img src="https://img.shields.io/badge/made%20with-=1-blue.svg">
33+
<img src="https://img.shields.io/badge/made%20with-%E2%99%A5-blue.svg">
3534
<a href="https://github.com/halfrost/LeetCode-Go/pulls"><img src="https://img.shields.io/badge/PR-Welcome-brightgreen.svg"></a>
3635
</p>
3736

@@ -3090,6 +3089,10 @@ Thank you for reading here. This is bonus. You can download my [《ACM-ICPC Algo
30903089
30913090
30923091
3092+
## License
3093+
3094+
The **code** in this repository (all Go solutions) is licensed under the [MIT License](https://github.com/halfrost/LeetCode-Go/blob/master/LICENSE). The **book content** of *LeetCode Cookbook* (the articles and illustrations served from the website) is licensed under a Creative Commons (CC) license. In short: feel free to reuse the code under MIT; the written/illustrated book content is shared under CC.
3095+
30933096
## ♥️ Thanks
30943097
30953098
Thanks for your Star!
Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,58 @@
1-
from collections import defaultdict
1+
#!/usr/bin/env python3
2+
"""Count the total word count of the LeetCode-Go book.
3+
4+
Metric: Chinese characters (CJK ideographs) + English words, counted over the
5+
authored Markdown only (the book content, the per-problem pages and the
6+
top-level docs). Fenced / inline code blocks are stripped and the third-party
7+
Hugo theme and code templates are excluded, so the number reflects written
8+
prose rather than source code or numeric data.
9+
10+
The repo root is resolved from this file's location, so it can be run from any
11+
directory:
12+
13+
python3 website/content/ChapterFour/pytool/WordCount.py
14+
"""
215
import glob
316
import os
17+
import re
18+
19+
HAN = re.compile(r"[一-鿿]") # CJK unified ideographs (汉字)
20+
EN_WORD = re.compile(r"[A-Za-z]+") # English words
21+
FENCED = re.compile(r"```.*?```", re.S) # ```fenced code blocks```
22+
INLINE = re.compile(r"`[^`\n]*`") # `inline code`
23+
24+
# repo root = four levels up from website/content/ChapterFour/pytool/
25+
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", ".."))
26+
27+
# Globs of authored Markdown, relative to the repo root.
28+
GLOBS = [
29+
"website/content/**/*.md", # the book《LeetCode Cookbook》
30+
"leetcode/**/*.md", # per-problem pages
31+
"note/*.md",
32+
"*.md", # README and other top-level docs
33+
]
34+
35+
36+
def strip_code(text):
37+
"""Remove fenced and inline code so only prose is counted."""
38+
return INLINE.sub(" ", FENCED.sub(" ", text))
39+
40+
41+
def count_words(text):
42+
"""汉字 + English words, after stripping code."""
43+
text = strip_code(text)
44+
return len(HAN.findall(text)) + len(EN_WORD.findall(text))
45+
46+
47+
def main():
48+
files = sorted({f for g in GLOBS for f in glob.glob(os.path.join(ROOT, g), recursive=True)})
49+
total = 0
50+
for file_name in files:
51+
with open(file_name, encoding="utf-8", errors="ignore") as fh:
52+
total += count_words(fh.read())
53+
print("files counted: {}".format(len(files)))
54+
print("total word count (汉字 + English words, code excluded): {}".format(total))
455

556

6-
def str_count2(str):
7-
count_zh = count_dg = 0
8-
for s in str:
9-
# 中文字符范围
10-
if '\u4e00' <= s <= '\u9fff':
11-
count_zh += 1
12-
if s.isdigit():
13-
count_dg += 1
14-
# print(count_zh + count_dg)
15-
return count_zh + count_dg
16-
17-
current_working_dir = os.getcwd()
18-
# print(f"current_working_dir: {current_working_dir}")
19-
20-
dir_names = glob.glob("*.md")
21-
dir_names.sort()
22-
23-
word_count = 0
24-
for file_name in dir_names:
25-
with open(file_name, "r") as myfile:
26-
codeContent = myfile.read()
27-
print("当前读取文件: {}, 字数统计: {}".format(file_name, str_count2(codeContent)))
28-
word_count += str_count2(codeContent)
29-
print(word_count)
57+
if __name__ == "__main__":
58+
main()

0 commit comments

Comments
 (0)