Skip to content

Add ESLint rule to catch broken internal links - #157

Open
allgandalf wants to merge 7 commits into
PecanProject:masterfrom
allgandalf:add-eslint-internal-links-rule
Open

Add ESLint rule to catch broken internal links#157
allgandalf wants to merge 7 commits into
PecanProject:masterfrom
allgandalf:add-eslint-internal-links-rule

Conversation

@allgandalf

@allgandalf allgandalf commented Feb 26, 2026

Copy link
Copy Markdown
Collaborator

Description of Changes

Closes #156

Adds ESLint with a custom no-bad-internal-links rule to prevent the class of bugs fixed in #155 (broken internal links in JSX). The rule flags href and to attributes where:

  • Whitespace in URLs — leading/trailing spaces (e.g. href=" https://...")
  • Relative internal links — missing leading / (e.g. href="gsoc.html"href="/gsoc/")
  • .html extensions — Docusaurus uses clean URLs
  • Missing trailing slash — internal links should end with /

Also adds a GitHub Actions lint workflow that runs on every PR and push to master.

All 46 existing violations across the codebase have been fixed in this PR.

Removes yarn.lock and standardizes the project on npm, consistent with all CI workflows (publish-docs.yml and lint.yml both use npm ci).

Files added:

  • eslint-rules/no-bad-internal-links.js — the custom ESLint rule
  • .eslintrc.js — ESLint config
  • .eslintignore — ignores build artifacts
  • .github/workflows/lint.yml — CI workflow

Files modified:

  • package.json — added lint script, eslint and eslint-plugin-react devDependencies
  • package-lock.json — updated lockfile with eslint dependencies
  • src/pages/index.js — fixed missing trailing slash
  • src/pages/news.js — fixed relative link, whitespace in URLs, missing trailing slashes
  • src/pages/documentation/*.js — fixed missing trailing slash on 12 files

Files removed:

  • yarn.lock — project standardized on npm

  • I have tested my changes on both desktop and mobile views.

    • N/A — this is a linting/CI-only change, no UI impact.
  • Screenshots are attached below for desktop and mobile layouts.

    • N/A — no visual changes.

Screenshots

N/A — tooling and link-fix change only, no UI modifications.

How to Test

  1. npm install
  2. npm run lint — should pass with 0 errors
  3. The GitHub Actions workflows run automatically on this PR

Add a no-bad-internal-links ESLint rule that flags JSX href/to attributes
with relative paths, .html extensions, missing trailing slashes, or
whitespace in URLs. Includes a GitHub Actions workflow to run lint on
every PR and push to master.

Closes PecanProject#156
@allgandalf
allgandalf force-pushed the add-eslint-internal-links-rule branch from 8f2c6d2 to ac4dcb6 Compare February 26, 2026 04:16
- Fix leading whitespace in URLs in news.js
- Fix relative link gsoc.html -> /gsoc/ in news.js
- Add trailing slash to /site/pecanworkflow/pecan_news/* links in news.js
- Add trailing slash to /en-US/docs/Glossary in all documentation pages
- Add trailing slash to /documentation/latest in index.js
- Regenerate package-lock.json to include new devDependencies
The build workflow (publish-docs.yml) uses npm ci, so the lint
workflow should match to keep CI consistent.
Lockfile includes eslint dependency tree and minor transitive
dep updates from npm resolution.
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Preview Ready!
Your docs preview for this PR is available here:

https://PecanProject.github.io/pr-157/

Comment thread .github/workflows/lint.yml

@AritraDey-Dev AritraDey-Dev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Comment on lines +6 to +8
* - Internal links must start with '/'
* - Internal links must not use .html extension
* - Internal links must end with '/'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there technical reasons for all of these? I'm OK with requiring no extensions, but I like relative links and I think of a trailing slash as an indicator this page has children (eg gsoc/ reads to me as a landing page that implies the existence of gsoc/ideas and gsoc/contributor_guidance) rather than something that should be appended everywhere.

@dlebauer dlebauer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @allgandalf thanks for fixing these links and implementing the link checking.

Can you help me understand the unique the value of ESLint compared to Lychee, which is proposed in #135? Lychee can test internal links; is there something that this PR implements that Lychee cannot? It would make more sense to have a single checker tool if one can support the needs.

Also, I was surprised at the number of lines relative to what seems like a common set of ways links can break. Could you help me understand whether this level of complexity is warranted?

@allgandalf

Copy link
Copy Markdown
Collaborator Author

👋 Hey i'm out today and tomorrow I will take a look at the comments before thursday, apologies for the delay here 🙇

@allgandalf

Copy link
Copy Markdown
Collaborator Author

extended OoO, will look on the weekend

@dlebauer dlebauer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We definitely want to merge in the fixed links, thanks for that. But before merging, I'm wondering if we should include the ESLint workflow + rules.

  • Please compare the use of ESLint to Lychee, which is proposed in #135; see #157 (review)
  • fix merge conflicts

@allgandalf

Copy link
Copy Markdown
Collaborator Author

On my list for this week 👍

@ANAMASGARD

Copy link
Copy Markdown

Updated implementation (rewritten from current master)

@allgandalf @dlebauer @infotroph — picking up the inactive PR with a scoped revision per maintainer feedback.

What changed vs the original PR

  • Rebuilt from current master — preserves news→blog migration (Migrate news section to blog (fixes #115) #120), gsoc fixes (Fix gsoc_ideas links #155), and dependabot updates. The old branch would have reverted the 3,700-line news.js and other master changes.
  • Link fixes kept:
    • Documentation iframe fallback links now match their iframe src (12 files)
    • Homepage Get Started link uses trailing slash (/documentation/latest/) for consistency with trailingSlash: true
  • npm standardization: removed yarn.lock, updated README to use npm ci / npm run
  • ESLint removed — deferred automated checking to Add lychee link checker #135 (Lychee) to avoid overlapping tools per @dlebauer review

ESLint vs Lychee

ESLint can catch JSX source patterns (whitespace, relative paths) before build. Lychee validates rendered/source links including external 404s. This revision uses neither — link fixes only; #135 handles future automated checking.

Issue scope

This addresses the existing-link and npm-standardization portions of #156. It does not close the automated-checking portion (deferred to #135).

Verification (VERIFIED FOR SCOPED PR)

  • npm ci — exit 0, no lockfile changes
  • npm run clear && npm run build — exit 0
  • iframe src==href check — 12/12 OK
  • curl smoke tests on /, /documentation/latest/, /blog/, /news/ — all OK
  • Diff: 15 files only (no ESLint, no stale news.js)

Branch location

Could not push to allgandalf/add-eslint-internal-links-rule (403). Rewritten commits are on:

https://github.com/ANAMASGARD/PecanProject.github.io/tree/add-eslint-internal-links-rule

Cross-fork PR into @allgandalf's branch opened for easy merge.

Signed-off-by: ANAMASGARD

@ANAMASGARD

Copy link
Copy Markdown

Fix: closed incorrect cross-fork PR (allgandalf#1)

The previous PR into `allgandalf:add-eslint-internal-links-rule` showed 18 commits and merge conflicts because that branch is stale (7 old ESLint commits from Feb). GitHub included every master commit since then as part of the diff.

Closed: allgandalf#1

Clean replacement

Opened a new PR against current master with only 2 signed-off commits (no merge conflicts, no other contributors' commits in the diff):

👉 Please use the new PR instead of merging this stale branch.

@allgandalf — to update this PR's branch, you can reset `add-eslint-internal-links-rule` to match `ANAMASGARD:add-eslint-internal-links-rule`:

```bash
git fetch https://github.com/ANAMASGARD/PecanProject.github.io.git add-eslint-internal-links-rule
git checkout add-eslint-internal-links-rule
git reset --hard FETCH_HEAD
git push --force-with-lease origin add-eslint-internal-links-rule
```

Or close #157 in favor of the new PR.

Signed-off-by: ANAMASGARD

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add ESLint rule to catch broken internal links and standardize on npm

5 participants