Skip to content

Resolve feature API-reference links against the reader's docs version - #447

Merged
moritzhartmeier merged 3 commits into
mainfrom
fix/features-api-url-versioned
Oct 20, 2026
Merged

moritzhartmeier merged 3 commits into
mainfrom
fix/features-api-url-versioned

Conversation

@moritzhartmeier

@moritzhartmeier moritzhartmeier commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Follow-up to #445, which fixes the same class of bug for Markdown. Raised in
review there by @eugenia-scandit.

Nothing is broken today

<FeatureList/> is used on 10 pages, all in docs/ — the current version.
Neither frozen version renders it: 7.6.14 has the 6 label-definitions.md
pages but none uses the component, and 6.28.11 does not have them. The
component landed in 909d295cb, after both freezes.

For the current version, linking the unversioned API reference is correct —
the same convention its Markdown uses.

What breaks at the next freeze

docs:version copies docs/ verbatim, so the snapshot gets all 10 pages with
<FeatureList/> intact — and the component imports the shared
src/data/features.json, not a snapshot of it. The frozen version then renders
today's unversioned URLs, and once the following minor publishes those resolve to
its API reference.

That is exactly what #445 fixes for Markdown, somewhere a substitution over
versioned_docs/ structurally cannot reach: the URLs are not in the snapshot.

withCurrentDocsPath() looked like it might already cover this. It does not — it
prefixes relative /sdks/<framework> paths for unreleased frameworks only, and
returns an absolute URL untouched.

The change

features.json now stores the path within the API reference:

- "apiUrl": "https://docs.scandit.com/data-capture-sdk/ios/label-capture/api/serial-number-barcode.html#serial-number-barcode"
+ "apiUrl": "ios/label-capture/api/serial-number-barcode.html#serial-number-barcode"

and a new apiReferenceUrl(path, versionName) in docsPaths.ts applies the
version at render time:

version result
current docs.scandit.com/data-capture-sdk/ios/…
7.6.14 docs.scandit.com/7.6/data-capture-sdk/ios/…
6.28.11 docs.scandit.com/6.28/data-capture-sdk/ios/…
already absolute unchanged

FeatureList reads the active version through useActiveDocContext(), the
pattern FrameworkSelectorMobile already uses. 143 values converted.

Availability has to move with it

features.json records the SDK version each feature arrived in, and 86
framework entries are newer than 7.6
. Those were harmless while the links
pointed at the unversioned API reference — it always documents the newest
release. Resolving against the reader's own line turns each into a 404:
/7.6/data-capture-sdk/ has no page for a class added in 8.2.

So the filter is now version-aware at all three sites — the feature filter, the
isAvailable flag, and the per-framework chip list.

The comparison is numeric per component, which is less obvious than it
looks: "6.5" is earlier than "6.28", and both a string compare
("6.5" > "6.28") and a float one (6.5 > 6.28) get it backwards. 6.28 is a
real docs version, so a lazy compare would hide every 6.5-era feature from the
6.28 docs.

current shows everything; an unparseable version on either side shows the
feature rather than hiding it, so a data-entry slip degrades to today's
behaviour rather than silently emptying a table.

Verified

  • apiReferenceUrl() across current, frozen, leading-slash and already-absolute
    inputs
  • tsc --noEmit clean, full build passes
  • yarn verify:frameworks still passes — that gate also reads
    features.json, so the shape change had to keep it happy. I nearly missed it;
    FeatureList is not the only consumer.

Not verified, stated plainly

How a frozen page renders. No frozen version uses the component today, so
there is nothing to observe — and FeatureList is client-rendered: the
static HTML carries Loading features... and the data ships in the JS bundle, so
a build cannot see those links either way. The frozen path rests on
useActiveDocContext() reporting the version name, which the existing selector
component already depends on.

I tried to observe it by simulating a freeze and building. That failed three
times on release-process steps unrelated to this change — redirect collisions
from a snapshot that still contained kmp, then UNRELEASED_FRAMEWORK_SLUGS
having become derived rather than a literal list. Observing it properly needs a
real minor_beta on a throwaway branch; happy to do that if you would rather not
take the reasoning.

Sequencing

This makes a frozen version's feature links point at <major.minor>/, so it runs
into the same Algolia api-reference-<line> tag question as #445. Both want to
land alongside the crawler action rather than independently.

Overlap with #451

Both touch the href={…} line in the framework-list branch: #451 wraps it in a
conditional for a missing apiUrl, this one changes the function that builds
it. They combine cleanly — the conditional stays and the <a> branch calls
apiReferenceUrl(frameworkInfo.apiUrl, activeVersionName). Whichever lands
second takes the merge.

Rebased onto main for #448: features.json was regenerated from main with
the host-stripping re-applied, so the dotnet.ios / dotnet.android
corrections are preserved by construction rather than hand-merged — all 32
verified present, zero stale net/ paths.

@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-20 14:36 UTC

@eugenia-scandit eugenia-scandit left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hide features newer than the reader's version, otherwise the pages this PR is meant to fix get 404 links. Rebase onto #448 after its merge. It also has a one-line overlap with #451.

@moritzhartmeier

Copy link
Copy Markdown
Member Author

Thank you — the availability point is the one that mattered, and it would have
made this PR actively worse than the status quo. Addressed in 897983f1d.

Hide features newer than the reader's version. Confirmed and fixed. 86
framework entries in features.json are newer than 7.6. They were harmless
while the links pointed at the unversioned API reference, which always documents
the newest release — resolving against the reader's own line turns every one of
them into a 404, because /7.6/data-capture-sdk/ has no page for a class added
in 8.2. So the fix would have introduced exactly the breakage it exists to
prevent.

Availability is now version-aware at all three sites: the feature filter, the
isAvailable flag, and the per-framework chip list.

One thing worth flagging, because it is the kind of bug that would have looked
fine in review: the comparison is numeric per component. "6.5" is earlier
than "6.28", and both a string comparison ("6.5" > "6.28") and a float one
(6.5 > 6.28) get that backwards. 6.28 is a real docs version, so a lazy
compare would have hidden every 6.5-era feature from the 6.28 docs. Verified
across both frozen versions and current, that case included.

current shows everything, and an unparseable version on either side shows the
feature rather than hiding it — a data-entry slip degrades to today's behaviour
rather than silently emptying a table.

Rebase onto #448. Done. Rather than hand-resolving 32 conflicts in
features.json, I regenerated it from main and re-applied the host-stripping,
so your dotnet.ios / dotnet.android corrections are preserved by
construction; all 32 verified present, zero stale net/ paths.

Overlap with #451. Both touch the href={…} line in the framework-list
branch — yours wraps it in a conditional for a missing apiUrl, mine changes
the function that builds it. They combine cleanly: the conditional stays, and
the <a> branch calls apiReferenceUrl(frameworkInfo.apiUrl, activeVersionName).
Happy to rebase onto #451 once it merges, or to take it here if you would rather
land them together — your call which goes first.

Verified: tsc --noEmit clean, build passes, yarn verify:frameworks passes.

Still true and stated in the description: I cannot observe how a frozen page
renders, because no frozen version uses the component yet and FeatureList is
client-rendered, so the links never reach the built HTML. The frozen path rests
on useActiveDocContext() reporting the version name.

moritzhartmeier and others added 2 commits October 7, 2026 12:00
…version

features.json stored 143 absolute apiUrl values pointing at the UNVERSIONED API
reference, and FeatureList rendered them as-is. One shared data file serves
every docs version, so there is no single correct prefix to bake into it.

Nothing is broken today: the component is used on 10 pages, all in docs/, and
for the current version the unversioned tree is the right target -- the same
convention its Markdown uses. The problem is the next freeze. `docs:version`
copies docs/ verbatim, so the snapshot gets all 10 pages with <FeatureList/>
intact while still importing the SHARED features.json. The frozen version then
renders whatever the unversioned tree documents, which after the following minor
publishes is the newer release. That is the bug #445 fixes for Markdown, in a
place a substitution over versioned_docs/ cannot reach.

features.json now stores the path WITHIN the API reference
("ios/label-capture/api/serial-number-barcode.html#..."), and a new
apiReferenceUrl() applies the version at render time: the unversioned tree for
`current`, <major.minor>/data-capture-sdk/ for a frozen version. FeatureList
reads the active version through useActiveDocContext(), the pattern
FrameworkSelectorMobile already uses.

withCurrentDocsPath() did not cover this and still does not: it prefixes
relative /sdks/<framework> paths for unreleased frameworks only, and returns an
absolute URL untouched.

Verified: apiReferenceUrl() across current / frozen / already-absolute inputs,
tsc clean, a full build passes, and `yarn verify:frameworks` still passes --
that gate reads features.json, so the shape change had to keep it happy.

NOT verified, stated plainly: how a FROZEN page renders, because no frozen
version uses the component today, and FeatureList is client-rendered -- the
static HTML carries "Loading features..." and the data ships in the JS bundle,
so a build cannot observe those links either way. The frozen path rests on
useActiveDocContext() reporting the version name, which the existing selector
component already depends on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s on

features.json records the SDK version each feature arrived in, and one shared
file serves every docs version -- so a frozen version lists features that did
not exist in it. 86 framework entries are newer than 7.6.

That was harmless while their links pointed at the unversioned API reference,
which always documents the newest release. Resolving links against the reader's
own line turns every one of them into a 404: /7.6/data-capture-sdk/ has no page
for a class added in 8.2. The fix would have introduced the breakage it exists
to prevent.

Availability is now version-aware at all three sites: the feature filter, the
isAvailable flag, and the per-framework chip list.

The comparison is numeric PER COMPONENT, which matters more than it looks:
"6.5" is earlier than "6.28", and both a string comparison ("6.5" > "6.28") and
a float one (6.5 > 6.28) get that backwards. 6.28 is a real docs version, so it
is not hypothetical. `current` shows everything, and an unparseable version on
either side shows the feature rather than hiding it, so a data-entry slip
degrades to the previous behaviour rather than silently emptying a table.

Also rebased onto main for #448: features.json is regenerated from main with
the host-stripping re-applied, so the dotnet.ios / dotnet.android corrections
are preserved rather than hand-merged (32 values checked).

Verified: the comparison across both frozen versions and `current` including
the 6.5/6.28 case, tsc clean, build passes, verify:frameworks passes.

Reported by @eugenia-scandit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@moritzhartmeier
moritzhartmeier force-pushed the fix/features-api-url-versioned branch from 897983f to 2d53694 Compare October 7, 2026 10:01
@moritzhartmeier

Copy link
Copy Markdown
Member Author

Rebased onto main — conflict resolved, all five checks green.

The only conflicting file was src/data/features.json, and only because #448
changed it after this branch forked. Rather than hand-resolving 32 hunks, I took
main's copy and re-applied the host-stripping, so the result is derived rather
than merged:

143 host prefixes stripped
 32 dotnet.ios / dotnet.android values preserved
  0 stale net/ paths
  0 absolute docs.scandit.com URLs left

src/components/FeatureList/index.tsx and src/constants/docsPaths.ts had no
changes on main, so they rebased without conflict.

Re-verified after the rebase: tsc --noEmit clean, full build passes,
yarn verify:frameworks passes, Docs Quality Gate passes.

#451 is still open and still touches the same href={…} line in the
framework-list branch. They combine cleanly — the conditional stays, and the
<a> branch calls apiReferenceUrl(frameworkInfo.apiUrl, activeVersionName) —
but whichever lands second takes that merge. Happy to go second and rebase onto
it if you would rather land #451 first.

This is still waiting on your re-review for the availability change in
897983f1d (now 2d53694cff after the rebase).

@moritzhartmeier

Copy link
Copy Markdown
Member Author

@eugenia-scandit can you have another look please?

@eugenia-scandit
eugenia-scandit self-requested a review October 9, 2026 11:54

@eugenia-scandit eugenia-scandit left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved, thanks - both of my earlier points are addressed. One small thing before merging: the effect that computes the filtered list reads activeVersionName but doesn't list it in its dependencies (around line 120), so the list won't refilter if the docs version changes while the component stays mounted.

Keep main's non-link chip for frameworks without an API reference (#451)
and resolve the link through apiReferenceUrl against the reader's docs
version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@moritzhartmeier
moritzhartmeier merged commit 0d255d6 into main Oct 20, 2026
5 checks passed
@moritzhartmeier
moritzhartmeier deleted the fix/features-api-url-versioned branch October 20, 2026 14:35
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.

2 participants