mirror of
https://github.com/wilsonfreitas/awesome-quant.git
synced 2026-08-19 14:58:06 +00:00
Replace Quarto site with static HTML generator
- Add site/generate.py: static site with search, filtering, sorting, dark mode - Add site/static/style.css and main.js for the new frontend - Extend parse.py: fetch CRAN published dates, PyPI release dates, and discover GitHub repos from CRAN pages as fallback data sources - Migrate from Poetry to uv (pyproject.toml + uv.lock) - Update CI workflow to use uv and generate.py pipeline - Add CONTRIBUTING.md with entry format guidelines - Add "Submit a Project" button to site nav - Update review-pr skill with all accepted entry formats - Update CLAUDE.md to reflect new architecture - Remove Quarto files (_quarto.yml, *.qmd, sync-site skill, poetry.lock) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
157e6cbd79
commit
5a6f90cc85
@@ -21,40 +21,73 @@ Use the GitHub MCP tools to read the PR details. If the PR has merge conflicts,
|
||||
|
||||
Read the PR diff. Focus only on changes to `README.md`. If the PR modifies files other than `README.md` (like `parse.py`, `site/`, etc.), flag this as unusual — most contributions should only touch `README.md`.
|
||||
|
||||
### Step 4: Validate each added entry
|
||||
### Step 4: Automatic rejection checks
|
||||
|
||||
Reject the PR immediately (close with a polite comment) if any of these apply:
|
||||
|
||||
- **Multiple projects in one PR** — each PR should add exactly one project.
|
||||
- **Empty PR description** — the contributor must explain what they're adding.
|
||||
- **Duplicate** — the project name or URL is already in `README.md` or in a recently closed PR.
|
||||
- **Archived or abandoned** — the project has no activity in 12+ months.
|
||||
|
||||
### Step 5: Validate each added entry
|
||||
|
||||
For every new line added to `README.md`, check the following:
|
||||
|
||||
#### 4a. Entry format
|
||||
#### 5a. Entry format
|
||||
|
||||
Each entry MUST match this exact pattern:
|
||||
Each entry MUST match one of these accepted formats:
|
||||
|
||||
**GitHub project:**
|
||||
```
|
||||
- [Project Name](https://url) - Short description ending with a period.
|
||||
- [Project Name](https://github.com/owner/repo) - Short description ending with a period.
|
||||
```
|
||||
|
||||
Specifically:
|
||||
**Project with website and GitHub repo:**
|
||||
```
|
||||
- [Project Name](https://project-site.com) - Short description ending with a period. [GitHub](https://github.com/owner/repo)
|
||||
```
|
||||
|
||||
**CRAN project (with optional GitHub link):**
|
||||
```
|
||||
- [Package Name](https://cran.r-project.org/package=pkgname) - Short description ending with a period.
|
||||
- [Package Name](https://cran.r-project.org/package=pkgname) - Short description ending with a period. [GitHub](https://github.com/owner/repo)
|
||||
```
|
||||
|
||||
**PyPI project (with optional GitHub link):**
|
||||
```
|
||||
- [package-name](https://pypi.org/project/package-name/) - Short description ending with a period.
|
||||
- [package-name](https://pypi.org/project/package-name/) - Short description ending with a period. [GitHub](https://github.com/owner/repo)
|
||||
```
|
||||
|
||||
The core regex used by `parse.py` to extract entries is: `^\s*- \[(.*)\]\((.*)\) - (.*)$`
|
||||
|
||||
Specifically check:
|
||||
- Starts with `- ` (dash + space)
|
||||
- Followed by a markdown link `[Name](URL)`
|
||||
- Followed by ` - ` (space, dash, space)
|
||||
- Followed by a description that ends with a period `.`
|
||||
|
||||
The regex used by `parse.py` to extract entries is: `^\s*- \[(.*)\]\((.*)\) - (.*)$`
|
||||
- The period must come before the optional `[GitHub](url)` link
|
||||
- The `[GitHub]` link, if present, must use the exact format `[GitHub](https://github.com/owner/repo)`
|
||||
|
||||
If the entry doesn't match, report exactly what's wrong (missing period, wrong separator, etc.).
|
||||
|
||||
#### 4b. URL validation
|
||||
#### 5b. URL validation
|
||||
|
||||
- **GitHub URLs are preferred.** If the URL points to `github.com`, that's ideal — no warning needed.
|
||||
- **Non-GitHub URLs**: If the URL points somewhere else (PyPI, personal site, docs site, etc.), flag it with a warning: "This is not a GitHub URL. GitHub repos are preferred because they allow automated tracking of activity and archive status. Consider whether a GitHub link exists for this project."
|
||||
- Check that the URL looks well-formed (starts with `https://`).
|
||||
- **GitHub URLs are preferred.** If the primary URL points to `github.com`, that's ideal.
|
||||
- **CRAN URLs** (`cran.r-project.org`) are acceptable for R packages.
|
||||
- **PyPI URLs** (`pypi.org`) are acceptable for Python packages.
|
||||
- **Non-GitHub URLs with `[GitHub]` link**: If the primary URL is a project website but includes a `[GitHub](url)` link in the description, that's the preferred format for non-GitHub projects.
|
||||
- **Non-GitHub URLs without `[GitHub]` link**: Flag with a suggestion to add a `[GitHub](url)` link if one exists, since GitHub repos enable automated tracking of stars and activity.
|
||||
- All URLs must use `https://`.
|
||||
|
||||
#### 4c. Section placement
|
||||
#### 5c. Section placement
|
||||
|
||||
Look at which `##` (language) and `###` (category) heading the entry was added under. Evaluate whether the project fits that section based on its description and URL:
|
||||
Look at which `##` (language) and `###` (category) heading the entry was added under. Evaluate whether the project fits that section:
|
||||
|
||||
- Does the project's language match the section? (e.g., a Python library should be under `## Python`)
|
||||
- Does the project's purpose match the category? (e.g., a backtesting framework should be under `### Trading & Backtesting`, not `### Indicators`)
|
||||
- Commercial/proprietary projects must go under `## Commercial & Proprietary Services`.
|
||||
- If the placement seems wrong, suggest a better section.
|
||||
|
||||
The current sections in the README are:
|
||||
@@ -67,13 +100,20 @@ The current sections in the README are:
|
||||
|
||||
**Cross-language**: Frameworks, Reproducing Works Training & Books
|
||||
|
||||
**Commercial & Proprietary Services**
|
||||
|
||||
If the project doesn't fit any existing section, suggest the closest match or recommend creating a new subsection (rare).
|
||||
|
||||
#### 4d. Duplicate check
|
||||
#### 5d. Duplicate check
|
||||
|
||||
Grep the current `README.md` for the project name and URL to ensure it's not already listed.
|
||||
|
||||
### Step 5: Summarize findings
|
||||
#### 5e. Quality check
|
||||
|
||||
- **Active**: Project should show recent activity (commits within the last 12 months).
|
||||
- **Documented**: Project should have a clear README with usage examples.
|
||||
|
||||
### Step 6: Summarize findings
|
||||
|
||||
Present a clear summary:
|
||||
|
||||
@@ -87,22 +127,26 @@ Entries reviewed: <count>
|
||||
<For each entry>
|
||||
- [Name](URL) - Description
|
||||
Format: OK / ISSUE: <details>
|
||||
URL: GitHub / WARNING: Non-GitHub URL (<domain>)
|
||||
URL: GitHub / CRAN / PyPI / WARNING: <details>
|
||||
Section: OK (<section>) / SUGGESTION: Move to <section>
|
||||
Duplicate: No / YES: Already listed at line <N>
|
||||
Quality: OK / WARNING: <details>
|
||||
</For each entry>
|
||||
|
||||
Conflicts: None / YES: Needs rebase
|
||||
|
||||
Verdict: APPROVE / NEEDS CHANGES
|
||||
Verdict: APPROVE / NEEDS CHANGES / REJECT
|
||||
```
|
||||
|
||||
### Step 6: Take action
|
||||
### Step 7: Take action
|
||||
|
||||
- **If everything passes**: Ask the user for confirmation, then approve and merge the PR.
|
||||
- **If there are issues**: Leave a constructive review comment on the PR listing what needs to be fixed. Be polite and specific — these are open-source contributors.
|
||||
- **If there are fixable issues**: Leave a constructive review comment on the PR listing what needs to be fixed. Be polite and specific — these are open-source contributors. Link to `CONTRIBUTING.md` for reference.
|
||||
- **If it should be rejected** (automatic rejection criteria): Close the PR with a polite explanation and link to `CONTRIBUTING.md`.
|
||||
|
||||
When leaving comments, be friendly and grateful for the contribution. Example tone:
|
||||
> Thanks for the contribution! A couple of things to address before we can merge:
|
||||
> - The description should end with a period.
|
||||
> - Consider linking to the GitHub repo instead of the docs site so we can track activity.
|
||||
> - Consider adding a `[GitHub](url)` link so we can track activity.
|
||||
>
|
||||
> Please see our [contributing guidelines](https://github.com/wilsonfreitas/awesome-quant/blob/master/CONTRIBUTING.md) for the accepted entry formats.
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
---
|
||||
name: sync-site
|
||||
description: Sync site/index.qmd with README.md content. Use this skill whenever README.md has been updated and the site needs to reflect those changes — after merging PRs, editing entries, adding libraries, or any modification to README.md. Also triggers for "update site", "sync site", "deploy site", "update qmd", or mentions of site/index.qmd being out of date.
|
||||
---
|
||||
|
||||
# Sync Site
|
||||
|
||||
Update `site/index.qmd` to match the current `README.md` content, then commit and push.
|
||||
|
||||
## How it works
|
||||
|
||||
`site/index.qmd` is composed of two parts:
|
||||
|
||||
1. **YAML frontmatter** (lines 1-11) — Quarto metadata that never changes. Preserve it exactly as-is.
|
||||
2. **Body content** — Everything from `## Python` to the end of the file. This must match `README.md` from the `## Python` heading onward.
|
||||
|
||||
The preamble in README.md (title, badges, language table of contents) is intentionally excluded from `index.qmd` because the Quarto frontmatter replaces it.
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Extract the frontmatter from index.qmd
|
||||
|
||||
Read `site/index.qmd` and capture everything up to and including the closing `---` and the blank line + description + badge lines that follow it (lines 1-16).
|
||||
|
||||
The header looks like this:
|
||||
```
|
||||
---
|
||||
title: "Awesome Quant"
|
||||
...
|
||||
---
|
||||
|
||||
A curated list of insanely awesome libraries, packages and resources for Quants (Quantitative Finance).
|
||||
|
||||
[](https://awesome.re)
|
||||
```
|
||||
|
||||
### 2. Extract the body from README.md
|
||||
|
||||
Read `README.md` and capture everything starting from the line `## Python` (inclusive) to the end of the file.
|
||||
|
||||
### 3. Combine and write
|
||||
|
||||
Concatenate the frontmatter header and the README body, then write to `site/index.qmd`.
|
||||
|
||||
Use a shell script for reliability:
|
||||
|
||||
```bash
|
||||
# Extract line number where "## Python" starts in README.md
|
||||
START=$(grep -n '^## Python' README.md | head -1 | cut -d: -f1)
|
||||
|
||||
# Extract frontmatter + preamble from index.qmd (up to the badge line)
|
||||
END=$(grep -n 'awesome.re/badge' site/index.qmd | head -1 | cut -d: -f1)
|
||||
|
||||
# Combine: header from qmd + body from README
|
||||
{ head -n "$END" site/index.qmd; echo; tail -n +"$START" README.md; } > site/index.qmd.tmp
|
||||
mv site/index.qmd.tmp site/index.qmd
|
||||
```
|
||||
|
||||
### 4. Verify
|
||||
|
||||
Run a quick diff to confirm the update looks correct:
|
||||
|
||||
```bash
|
||||
# Show line count to sanity-check
|
||||
wc -l site/index.qmd
|
||||
|
||||
# Optionally diff the body portion to confirm they match
|
||||
diff <(tail -n +"$START" README.md) <(sed -n "$((END+2)),\$p" site/index.qmd)
|
||||
```
|
||||
|
||||
### 5. Commit and push
|
||||
|
||||
Stage, commit, and push the change:
|
||||
|
||||
```bash
|
||||
git add site/index.qmd
|
||||
git commit -m "Sync site/index.qmd with README.md"
|
||||
git push origin main
|
||||
```
|
||||
Reference in New Issue
Block a user