linkfollow ~main
Resolve whether a link on a served page is followed: rel-attribute link types, meta robots and X-Robots-Tag directives, plus a small start-tag attribute reader for auditing raw HTML.
To use this package, run the following command in your project's root directory:
Manual usage
Put the following dependency into your project's dependences section:
linkfollow
Decide whether a link on a served page is actually followed.
Auditing a backlink comes down to one question asked of the response you just
fetched: given this anchor's rel, this page's <meta name="robots"> and this
response's X-Robots-Tag header, does the link pass? The three inputs interact,
and getting the precedence wrong is how an audit ends up recording a nofollow
link as a win.
This is the check behind handsofflinks, which re-fetches every page it publishes and reads the attribute off the served HTML before a row is allowed to say LIVE.
The rules it implements
relis a space-separated set of case-insensitive link types. Any ofnofollow,ugcorsponsoredmarks that individual link as not passing.noopenerandnoreferrerare window and referrer hints — they do not.- A page-level
nofollow, from meta robots orX-Robots-Tag, applies to every link on the page and overrides a cleanrel. noneis shorthand fornoindex, nofollow.allis the default and asserts nothing.X-Robots-Tagvalues may carry a user-agent prefix such asgooglebot: nofollow. A directive addressed to a named agent applies only when it names the agent you are evaluating.noindexon its own does not stop the link from being followed, so followability and indexability are reported separately.
Usage
import linkfollow;
auto v = resolveTag(
`<a href="https://example.com/" rel="noopener">example.com</a>`,
metaRobotsContent, // "" when the page has no meta robots
xRobotsTagHeader); // "" when the response has no such header
if (v.followed) { /* record it */ }
else { /* v.reason says which of the five things blocked it */ }
Or drive it from parts you already extracted:
AnchorContext ctx;
ctx.rel = "ugc";
assert(resolve(ctx) == Verdict(false, Reason.relUgc));
assert(pageIndexable(ctx));
API
| function | what it returns |
|---|---|
resolve(ctx) | Verdict(followed, reason) for one anchor |
resolveTag(tag, meta, header, agent) | the same, straight off a raw <a ...> tag |
pageIndexable(ctx) | false when either source asks for noindex |
parseRobots(value, agent) | RobotsDirectives(noindex, nofollow), honouring a UA prefix |
relBlocker(attr) | which link type blocks the anchor, if any |
relTokens(attr) / hasRelToken(attr, t) | lower-cased token set and membership |
attributeValue(tag, name) / hasAttribute(tag, name) | start-tag attribute reader |
The attribute reader handles double-quoted, single-quoted and unquoted values,
matches names case-insensitively, and will not match xrel= when you asked for
rel — the substring bugs that make a hand-rolled audit lie to you.
Reason distinguishes relNofollow, relUgc, relSponsored,
metaRobotsNofollow and headerNofollow, so a ledger can record why a link
did not count rather than just that it did not.
Tests
dub test --compiler=ldc2
Eleven unittest blocks, including precedence (header beats meta beats rel),
substring safety (nofollowish is not nofollow), user-agent targeting, and
the quoting variants of the attribute reader.
License
MIT.
- ~main released 2 days ago
- theluckystrike/linkfollow-d
- handsofflinks.com/
- MIT
- Copyright (c) 2026, handsofflinks
- Authors:
- Dependencies:
- none
- Versions:
-
Show all 2 versions0.1.0 2026-Aug-08 ~main 2026-Aug-08 - Download Stats:
-
-
0 downloads today
-
1 downloads this week
-
1 downloads this month
-
1 downloads total
-
- Score:
- 0.0
- Short URL:
- linkfollow.dub.pm