Skip to content

Commit

Permalink
✅build: add features to check links status and workflow to generate l…
Browse files Browse the repository at this point in the history
…ink status page
  • Loading branch information
xxrjun committed Apr 26, 2024
1 parent 432ac6f commit 927c2cd
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/link-status-report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Generate Link Status Report

on:
push:
branches:
- main

jobs:
generate_report:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install aiohttp
- name: Generate link status report
run: |
python utils/link_status_report.py
- name: Deploy report
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GH_TOKEN }}
publish_dir: ./
destination_dir: link-status-report
keep_files: true
3 changes: 3 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
> 作為自己學習 Computer Science 的紀錄與未來規劃,為自己在這茫茫碼海中留下一點痕跡
> 期許自己的血液裡都流著程式碼的那天

> [**Link Status Report**](https://xxrjun.github.io/cs-resources/link-status-report/links_report.html)
17 changes: 17 additions & 0 deletions utils/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
> [!TIP]
> Use [./link_statuc_repot.py](./link_statuc_repot.py) to check all links status in this folder.

## Usage

Install the required packages:

```bash
pip install -r requirements.txt
```

Run the script:

```bash
python link_statuc_repot.py
```
137 changes: 137 additions & 0 deletions utils/link_status_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import asyncio
import aiohttp
import re
import webbrowser
import os

# Regular expression to find Markdown links
markdown_link_re = r"\[([^\]]+)\]\((http[s]?://[^\s]+)\)"

async def is_link_active(url, session, semaphore):
async with semaphore: # Limit the number of concurrent requests
try:
async with session.head(url, allow_redirects=True, timeout=5) as response:
return ("✓", "green") if response.status == 200 else (f"{response.status}", "red")
except asyncio.TimeoutError:
return ("✕", "orange")
except aiohttp.ClientError as e:
return ("✕", "red")

async def check_links_in_markdown(file_path):
results = []

with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()

links = re.findall(markdown_link_re, content)

semaphore = asyncio.Semaphore(30) # Adjust the concurrency level as needed

async with aiohttp.ClientSession() as session:
tasks = [is_link_active(url, session, semaphore) for _, url in links]
statuses = await asyncio.gather(*tasks)

for (text, url), (status, color) in zip(links, statuses):
# remove '**' from text
text = text.replace('**', '')
results.append((text, status, url, color))

return results

async def generate_report(folder_path, report_path):
markdown_files = []
for root, dirs, files in os.walk(folder_path):
for file in files:
if file.endswith('.md'):
markdown_files.append(os.path.join(root, file))

html_content = """
<html>
<head>
<title>Link Status Report</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #1c1c1c;
color: #f2f2f2;
}
h1 {
color: #f2f2f2;
text-align: center;
margin-bottom: 30px;
}
h2 {
color: #f2f2f2;
margin-top: 40px;
}
table {
border-collapse: collapse;
width: 100%;
margin-bottom: 30px;
}
th, td {
border: 1px solid #444;
padding: 12px;
text-align: left;
}
th {
background-color: #333;
font-weight: bold;
}
tr:nth-child(even) {
background-color: #282828;
}
a {
color: #6fb3d2;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.status {
font-weight: bold;
text-align: center;
width: 60px;
}
.green {
color: #8bc34a;
}
.red {
color: #f44336;
}
.orange {
color: #ff9800;
}
</style>
</head>
<body>
<h1>Link Status Report</h1>
"""

for file in markdown_files:
results = await check_links_in_markdown(file)

html_content += f"<h2>{file}</h2>"
html_content += "<table><tr><th>Link Text</th><th class='status'>Status</th><th>URL</th></tr>"

for text, status, url, color in results:
html_content += f"<tr><td>{text}</td><td class='status {color}'>{status}</td><td><a href='{url}' target='_blank'>{url}</a></td></tr>"

html_content += "</table>"

html_content += "</body></html>"

with open(report_path, 'w', encoding='utf-8') as report_file:
report_file.write(html_content)

report_path = 'file://' + os.path.realpath(report_path)
webbrowser.open(report_path)
return report_path

if __name__ == "__main__":
markdown_folder_path = '../docs'
report_path = '../links_status_report.html'
report_path = asyncio.run(generate_report(markdown_folder_path, report_path))
print(f"Link status report generated for markdown files in {markdown_folder_path} at {report_path}")

0 comments on commit 927c2cd

Please sign in to comment.