Repository navigation
Review and extend the documentation, and check it in CI - #5638
Merged
Merged
Conversation
A review of all documentation pages found factual errors, dead links, missing cross-references, and gaps in examples. This fixes them and adds checks so the same problems are caught automatically. Fixes: - wrong signatures and version histories (operator!= C++20 member, binary() subtype type, get<PointerType>(), JSON_NO_THREAD_LOCAL, ...) - stale descriptions (number parsing since #5283, UBJSON table, SAX example that no longer compiled, tsl::ordered_map advice) - dead internal and external links; repology.org badges (the domain is suspended) replaced by badges that query the registries directly - deprecation notes link the migration guide; the guide itself fixed Additions: - "See also" sections, cross-references, 25 runnable examples, 12 Mermaid diagrams, new API pages for json_pointer::operator<=> and byte_container_with_subtype::operator==/!= - landing page, guides for untrusted input and performance - "unreleased" badge after versions newer than the latest release Checks: - strict documentation build (broken links/anchors fail it); CI and the publish workflow fetch the full history the build needs - weekly external link check, Mermaid syntax check in CI - check_structure.py: example titles, heading levels, alt texts, header links, docset index coverage; its unused-example check works again - all examples produce the same output on every platform Signed-off-by: Niels Lohmann <mail@nlohmann.me>
A dead link on the customers page is still the evidence of where the use of the library was documented. Keep the original URLs of the entries without a working replacement (Marne, Cisco Webex Desk Camera, Philips Hue, CyberArk) and exclude exactly these URLs from the link check. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
The SAX interface's key() receives no position either; only parse_error() does. Also note that the recipe does not report the path to the repeated key (see discussion #5085). Signed-off-by: Niels Lohmann <mail@nlohmann.me>
gregmarr
reviewed
Sep 29, 2026
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
- patch/patch_inplace: list the JSON pointer errors parse_error.106-109 and out_of_range.402/404, and quote the actual parse_error.105 message. - unflatten: list parse_error.106/107/108 and out_of_range.404. - to_bson: list out_of_range.415 (binary subtype above 255) and note that 412 and 415 are new in 3.13.0. - to_string: state that string_t must be convertible to std::string, also in the StringType requirements table. - JSON Lines: a `while (input >> j)` loop also throws after the last value for concatenated JSON values; show a loop that works for both. - BON8: a string gets 0xFF only if nothing follows it in the message; a string at the end of an array or object is ended by 0xFE. - custom_string_type.hpp: add operator+=(char), which the "Always required" list asks for (json_pointer::to_string, flatten, unflatten, and diff did not compile), and an ADL int_to_string for diff and items. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
1 of 2 tasks
Codacy (Pylint) flagged the mutable default argument that header() used as its cache. functools.lru_cache keeps the same memoization without it. The script's output is unchanged. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This was referenced Sep 30, 2026
This was referenced Sep 30, 2026
nlohmann
added a commit
that referenced
this pull request
Sep 30, 2026
The checkout step in publish_documentation.yml left the default persist-credentials: true, so GITHUB_TOKEN stayed writable in .git/config for the rest of the job (zizmor's artipacked finding). The Deploy documentation step authenticates through its own github_token input to peaceiris/actions-gh-pages and does not push with the checked-out credentials, so persist-credentials: false is safe here, matching every other checkout in the workflow set. Overlaps #5638, which edits this same checkout step (adds fetch-depth: 0); expect a rebase conflict there. Part of #5718 item 2 Signed-off-by: Niels Lohmann <mail@nlohmann.me>
nlohmann
added a commit
that referenced
this pull request
Sep 30, 2026
The docset Makefile's list_missing_pages ran one sqlite3 query per mkdocs page, and list_removed_paths nested a loop over all mkdocs pages inside a loop over all docset index paths (O(n*m) shell iteration). Issue #5718 item 5 suggested removing or reducing these targets once #5638's check_docset() lands, but that PR is still open and covers only API pages and macros, not the full page set these targets check. Replace the loops with two sorted path lists (DOCSET_PAGE_PATHS from mkdocs' markdown sources, DOCSET_INDEX_PATHS from the built docset index) compared with a single comm(1) call each, verified to produce output identical to the old loops against the current docSet.dsidx. The sed expression used '#' as its delimiter, which GNU Make reads as a comment character even inside a variable assignment, truncating the line and orphaning the closing paren of $(shell ...) ("unterminated call to function 'shell': missing ')'"). Use '@' as the delimiter instead. Part of #5718 item 5 Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Conflicts: - include/nlohmann/json.hpp: took develop's removal of the UDLs (moved to json_literals.hpp, which already has the corrected @sa links) - single_include/nlohmann/json.hpp: regenerated with make amalgamate - docs/mkdocs/docs/api/operator_literal_json.md, operator_literal_json_pointer.md: kept the PR's migration guide link and develop's json_literals.hpp/JSON_NO_AUTOMATIC_UDLS note - docs/mkdocs/docs/api/basic_json/to_bson.md: both sides added out_of_range.415; kept develop's example message and both version history lines - docs/docset/docSet.sql: added JSON_NO_AUTOMATIC_UDLS (new on develop), which the PR's check_structure.py requires Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Owner
Author
|
Merged develop (289d61e). Develop moved the user-defined literals to — posted by Claude Code on behalf of @nlohmann |
nlohmann
added a commit
that referenced
this pull request
Sep 30, 2026
* Fix math formulas rendering as raw TeX in the published docs The privacy plugin self-hosts MathJax 2.7.0 but drops its ?config=TeX-MML-AM_CHTML query string, so the rehosted script loads no input jax and the 10 formulas across 6 pages render as raw TeX to readers. Remove pymdownx.arithmatex and the MathJax extra_javascript entry, and rewrite the formulas in plain HTML (<sup>, <i>) instead. This also drops a nine-year-old third-party script from every page. Part of #5718 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Fix publish_documentation triggers and persist unneeded git credentials publish_documentation.yml only triggered on docs/mkdocs/** pushes, but the site also embeds .github/CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, cmake/{clang,gcc}_flags.cmake, .clang-tidy, tools/astyle/.astylerc and tests/fmt_formatter/project/main.cpp via pymdownx.snippets, so changes to those files never republished the site. Extend the path filter to cover them, and switch runs-on from the long-pinned ubuntu-22.04 to ubuntu-latest to match ci_test_documentation. Also add persist-credentials: false to the checkouts in ci_icpx and ci_nvhpc (ubuntu.yml) and msvc-vs2026/msvc-arm64 (windows.yml), none of which pushes with git, matching every other checkout in these workflows. Part of #5718 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Fix example build: broken debug echo, deprecations hidden for everything docs/Makefile's debug echo used a space instead of a comma in $(call cxx_standard ...), so it always printed an empty standard. Every example was also compiled with -Wno-deprecated-declarations, which would silently hide an accidental deprecated-API call in any of them. Factor the duplicated compile flags into EXAMPLE_CPPFLAGS/ EXAMPLE_WARNFLAGS, build with -Werror=deprecated-declarations by default, and only allow the three examples that intentionally document deprecated API (the DEPRECATED_EXAMPLES list) to suppress it. Part of #5718 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Fix check_structure.py NOLINT parsing and an off-by-one report line `line.strip("<!-- NOLINT")` followed by `.strip(" -->")` strips any of the characters in those sets from both ends, not a literal prefix; it only happened to work for "Examples". A NOLINT'd section name starting with N, O, L, I or T (e.g. "Notes", "Template parameters", "Iterator invalidation", "Literals") was silently mangled, so the suppression did not apply and the checker could report a spurious missing/misordered section. Parse the comment with a regex instead. The same fragile strip() pattern was used for heading text; replace it with a plain prefix slice. Also fix the admonition_title report, which used the 0-based line index while every other report in the file uses lineno+1. Part of #5718 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Fix docset README's non-existent make target and stale fallback URL The README told readers to run `make nlohmann_json.docset`, but the Makefile's targets are `all`, `JSON_for_Modern_C++.docset` and `install_docset_zeal`; the documented command has failed with "No rule to make target" since #2967 (2021). Point the README at the real target and folder name. Info.plist's DashDocSetFallbackURL also still pointed at the old nlohmann.github.io/json/ URL instead of the canonical https://json.nlohmann.me/ from mkdocs.yml's site_url. Leave list_missing_pages/list_removed_paths alone: they may become redundant once #5638's check_docset() lands, which is a follow-up. Part of #5718 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Remove two leftover Doxygen-era .link files from the examples directory parse__iterator_pair.link and parse__pointers.link each held only a Wandbox "online" permalink from the old Doxygen docs. #3071 deleted every other .link file in 2021; these two came in through a parallel PR (#3100) and were never referenced by any page, script or config. Part of #5718 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Fix MacPorts CMake example to include its own snippet files The MacPorts "Example: CMake" block included integration/homebrew/example.cpp and integration/homebrew/CMakeLists.txt instead of the MacPorts files right next to it, a copy-paste slip from the Homebrew section. Nothing referenced integration/macports/CMakeLists.txt as a result. The page rendered correctly only because the homebrew, macports and vcpkg/CMakeLists.txt snippets are byte-identical, so a future edit to the MacPorts files would not have shown up on the page. Part of #5718 item 6 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Do not persist git credentials in publish_documentation's checkout The checkout step in publish_documentation.yml left the default persist-credentials: true, so GITHUB_TOKEN stayed writable in .git/config for the rest of the job (zizmor's artipacked finding). The Deploy documentation step authenticates through its own github_token input to peaceiris/actions-gh-pages and does not push with the checked-out credentials, so persist-credentials: false is safe here, matching every other checkout in the workflow set. Overlaps #5638, which edits this same checkout step (adds fetch-depth: 0); expect a rebase conflict there. Part of #5718 item 2 Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Replace list_missing_pages/list_removed_paths with a comm(1)-based diff The docset Makefile's list_missing_pages ran one sqlite3 query per mkdocs page, and list_removed_paths nested a loop over all mkdocs pages inside a loop over all docset index paths (O(n*m) shell iteration). Issue #5718 item 5 suggested removing or reducing these targets once #5638's check_docset() lands, but that PR is still open and covers only API pages and macros, not the full page set these targets check. Replace the loops with two sorted path lists (DOCSET_PAGE_PATHS from mkdocs' markdown sources, DOCSET_INDEX_PATHS from the built docset index) compared with a single comm(1) call each, verified to produce output identical to the old loops against the current docSet.dsidx. The sed expression used '#' as its delimiter, which GNU Make reads as a comment character even inside a variable assignment, truncating the line and orphaning the closing paren of $(shell ...) ("unterminated call to function 'shell': missing ')'"). Use '@' as the delimiter instead. Part of #5718 item 5 Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
gregmarr
approved these changes
Oct 2, 2026
Merged
Conflicts, each resolved by keeping both sides: - publish_documentation.yml: develop's persist-credentials: false and this branch's fetch-depth: 0. - mkdocs.yml: develop's JSON_DISABLE_TUPLE_REFERENCE_CONVERSION entry and this branch's JSON_HAS_CPP_23/26 title. - parser.hpp: combined the two rewordings of the class comment. Also prefixed the two example titles of the new json_disable_tuple_reference_conversion.md page with "Example:" for this branch's check_structure.py, and ran make amalgamate (keeping this branch's fixed api/operator_ltlt and api/operator_gtgt links). Signed-off-by: Niels Lohmann <mail@nlohmann.me>
nlohmann
added a commit
that referenced
this pull request
Oct 2, 2026
Conflict in operator_ne.md: took develop's corrected page (#5638 documents that there is no C++20 member operator!=) and re-added this branch's conditional noexcept for overload (2) and its version history note. Ran make amalgamate. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
nlohmann
added a commit
that referenced
this pull request
Oct 4, 2026
- Swift docs: take develop's reviewed version from #5638, which documents #4650 with the --build-system native workaround; the swiftpm CI job added here only copies example.cpp into a library target and still works with it - .reuse/dep5 stays deleted (migrated to REUSE.toml here); develop's removal of the stale tests/thirdparty/Fuzzer entry is applied to REUSE.toml instead Signed-off-by: Niels Lohmann <mail@nlohmann.me>
nlohmann
added a commit
that referenced
this pull request
Oct 4, 2026
- ordered_map.hpp: develop's refactored members, with this branch's @sa links on every public member - byte_container_with_subtype operator==/!= and ordered_map docs: develop's reviewed text (#5638); drop the now unreferenced examples - basic_json.md: keep both version-history additions - add the docset entries that develop's style check now requires for the 25 API pages this branch adds - regenerate tools/api_checker/api_surface.json for develop's API Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A review of all 263 documentation pages found factual errors, dead links, missing cross-references, and gaps in
examples and diagrams. This PR fixes them and adds checks so the same kinds of problems are caught automatically.
Fixes
operator!=still listed the C++20 member that Fix #3868: Remove operator!= to enable P2468R2 rewritten candidate synthesis #5253 removed.binary()gave the subtype asstd::uint8_t; it issubtype_type(std::uint64_t) since 3.10.0.get()listed its pointer overload asget_ptr().JSON_NO_THREAD_LOCALclaimed "3.12.1", which was never released.JSON_GlobalUDLswas documented as off by default; it is on.strtoull/strtoll, replaced in Speed up parsing of contiguous input (numbers, strings, UTF-8) #5283.ordered_map.mdrecommendedtsl::ordered_map, which the other pages say cannot be used.#overload-4, and a Doxygen-era link in the FAQ.replacement are kept and excluded from the link check by exact URL. The deleted sponsor profile is plain text.
@saURLs that only worked through redirects.replaced by shields.io badges that query the package registries directly.
json_pointer<basic_json>overloads ofat,contains,operator[], andvalue, and the legacyoperator<=/>=members, are now documented. The migration guide itself is fixed (
detail, notdetailsnamespace; thepointer/length overloads of
from_*).WORKSPACE, heading levelswere skipped, and images had no alt text.
Additions
to_bson/to_msgpack/..., partially appliedpatch_inplace,value()type errors, discarded values, overloads without an example.json_pointer::operator<=>,byte_container_with_subtype::operator==/!=.docs/mkdocs/hooks/unreleased_versions.py) marks every "version X.Y.Z" newerthan the version in
abi_macros.hpp. Today that is 3.13.0; the badges disappear after the release.Checks
make buildnow runsmkdocs build --strictwith link and anchor validation, sobroken links fail CI. A shallow clone makes the git-revision-date plugin warn, which fails the strict build. The
docs CI job and the publish workflow therefore fetch the full history, which also fixes the identical "last updated"
dates on the published site.
check_docs_links.yml: a weekly (and manual) external link check. It reports all broken linksand ignores bot blocking and rate limiting.
ci_test_documentation_mermaid: parses all Mermaid diagrams (Node,mermaid.parsewith jsdom).check_structure.py:@salinks, and docset index coverage.docSet.sqlgets 35 missing entries.pass
check_outputon macOS.scripts/check_version_history.py: a manual, report-only check of the macro pages' "Added in version" entriesagainst the release tags.
Notes for reviewers
features/parsing/untrusted_input.md,features/performance.md,index.md, and the NuGet and Android FAQrewrites.
include/changes are comments only (@saURLs,@since, parser class comment);single_includeisre-amalgamated.
untrusted_input.md(or vice versa).README.md.develop.Public API
No breaking changes. This PR changes documentation, documentation tooling, CI configuration, and comments in the
headers only; no code of the library changes.
OSS-Fuzz: <id>.make amalgamate.This pull request was written by Claude Code.
🤖 Generated with Claude Code