Merge branch 'develop' into claude/todo-191-plan-508110

Resolve the conflict in docs/mkdocs/docs/home/architecture.md by taking
develop's rewritten page and pointing its ordered_map links at the moved
api/ordered_map/index.md. Also update the ordered_map.md links develop
added in ordered_json.md, object_order.md, and template_parameters.md.

Regenerate api_surface.json for the new BON8 functions and the changed
comparison operator. Restrict the documented_non_public leak check to
@sa URLs into json.nlohmann.me: develop now uses @sa to link GitHub
issues from private members such as copy_structured, which is not a
documentation leak.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-27 18:07:00 +02:00
212 changed files with 22883 additions and 2105 deletions
+3 -2
View File
@@ -126,8 +126,9 @@ includes via `clang++ -E -x c++ -v /dev/null`, and walks the AST:
```
`documented_non_public` lists entities **not** part of the public surface (private/protected members of
the six tracked classes) that surprisingly carry a real `@sa` URL — a genuine documentation leak. It does
not list public entries that merely lack `@sa`; that's `check_docs.py`'s job.
the six tracked classes) that surprisingly carry an `@sa` URL into the documentation site
(`https://json.nlohmann.me/`) — a genuine documentation leak. `@sa` links to anything else, such as GitHub
issues, are ignored. It does not list public entries that merely lack `@sa`; that's `check_docs.py`'s job.
**Output (surface, from `--surface-output`):**
```json
+48 -3
View File
@@ -46,7 +46,7 @@
"name": "operator<",
"pretty_signature": "nlohmann::operator<",
"scope": "nlohmann",
"signature": "friend bool operator<(const_reference lhs, const_reference rhs) noexcept { JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type)) }",
"signature": "friend bool operator<(const_reference lhs, const_reference rhs) noexcept { JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type), compare_iteratively<true>(lhs, rhs, true) == compare_result::less, false) }",
"tier": "callable"
},
{
@@ -850,6 +850,24 @@
"signature": "template<typename IteratorType, typename SentinelType = IteratorType, detail::enable_if_t<detail::can_compare_ne<IteratorType, SentinelType>::value, int> = 0> JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json from_bjdata(IteratorType first, SentinelType last, const bool strict = true, const bool allow_exceptions = true)",
"tier": "callable"
},
{
"identity_name": "from_bon8",
"kind": "FUNCTION_TEMPLATE",
"name": "from_bon8",
"pretty_signature": "nlohmann::basic_json::from_bon8",
"scope": "nlohmann::basic_json",
"signature": "template<typename InputType> JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json from_bon8(InputType&& i, const bool strict = true, const bool allow_exceptions = true)",
"tier": "callable"
},
{
"identity_name": "from_bon8",
"kind": "FUNCTION_TEMPLATE",
"name": "from_bon8",
"pretty_signature": "nlohmann::basic_json::from_bon8",
"scope": "nlohmann::basic_json",
"signature": "template<typename IteratorType, typename SentinelType = IteratorType, detail::enable_if_t<detail::can_compare_ne<IteratorType, SentinelType>::value, int> = 0> JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json from_bon8(IteratorType first, SentinelType last, const bool strict = true, const bool allow_exceptions = true)",
"tier": "callable"
},
{
"identity_name": "from_bson",
"kind": "CXX_METHOD",
@@ -1966,6 +1984,33 @@
"signature": "static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o, const bool use_size = false, const bool use_type = false, const bjdata_version_t version = bjdata_version_t::draft2)",
"tier": "callable"
},
{
"identity_name": "to_bon8",
"kind": "CXX_METHOD",
"name": "to_bon8",
"pretty_signature": "nlohmann::basic_json::to_bon8",
"scope": "nlohmann::basic_json",
"signature": "static std::vector<std::uint8_t> to_bon8(const basic_json& j)",
"tier": "callable"
},
{
"identity_name": "to_bon8",
"kind": "CXX_METHOD",
"name": "to_bon8",
"pretty_signature": "nlohmann::basic_json::to_bon8",
"scope": "nlohmann::basic_json",
"signature": "static void to_bon8(const basic_json& j, detail::output_adapter<char> o)",
"tier": "callable"
},
{
"identity_name": "to_bon8",
"kind": "CXX_METHOD",
"name": "to_bon8",
"pretty_signature": "nlohmann::basic_json::to_bon8",
"scope": "nlohmann::basic_json",
"signature": "static void to_bon8(const basic_json& j, detail::output_adapter<std::uint8_t> o)",
"tier": "callable"
},
{
"identity_name": "to_bson",
"kind": "CXX_METHOD",
@@ -2383,8 +2428,8 @@
{
"identity_name": "operator string_t",
"kind": "CONVERSION_FUNCTION",
"name": "operator typename string_t_helper<type-parameter-0-0>::type",
"pretty_signature": "nlohmann::json_pointer::operator typename string_t_helper<type-parameter-0-0>::type",
"name": "operator nlohmann::json_pointer::string_t_helper<type-parameter-0-0>::type",
"pretty_signature": "nlohmann::json_pointer::operator nlohmann::json_pointer::string_t_helper<type-parameter-0-0>::type",
"scope": "nlohmann::json_pointer",
"signature": "JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) operator string_t() const",
"tier": "callable"
+5 -1
View File
@@ -35,6 +35,10 @@ except ImportError:
ABI_TAG_PATTERN = re.compile(r'::json(?:_abi)?[a-z_]*_v\d+_\d+_\d+(?=::|$)')
# Only @sa URLs into the documentation site are doc links; internal code also uses @sa to point at
# GitHub issues (e.g. the recursion-limit rationale), which is not a documentation leak.
DOCS_SITE_URL = 'https://json.nlohmann.me/'
# Bump whenever a change to this schema, or to the identity-computing algorithm
# (get_signature_text()/get_identity_name()/identity_key()), could alter the 'signature' or
# 'identity_name' text for otherwise-unchanged source. diff_api.py refuses by default to compare
@@ -377,7 +381,7 @@ def walk_class_template(cursor, public_classes: set, api_dict: dict, documented_
# nonetheless carry a real @sa URL -- a genuine documentation leak, not "any
# public member missing @sa" (that's what check_docs.py's missing-@sa check is for).
leaked_url = extract_sa_url(child.raw_comment)
if leaked_url:
if leaked_url and leaked_url.startswith(DOCS_SITE_URL):
documented_non_public.append({
'location': cursor_location(child),
'raw_comment_excerpt': (child.raw_comment or '')[:100],
+1 -1
View File
@@ -20,7 +20,7 @@ if __name__ == '__main__':
namespaces = ['nlohmann']
abi_prefix = 'json_abi'
abi_tags = ['_diag', '_ldvcmp']
abi_tags = ['_diag', '_ldvcmp', '_dp', '_bics', '_psp', '_snul']
version = '_v' + args.version.replace('.', '_')
inline_namespaces = []
+4
View File
@@ -60,6 +60,10 @@ int main() {
`serve_header.py` will try to read a configuration file `serve_header.yml` in the top level or project root directory, and will fall back on built-in defaults if the file cannot be read.
An annotated example configuration can be found in `tools/serve_header/serve_header.yml.example`.
By default, the server listens on `localhost` only, and only web pages from Compiler Explorer (`https://godbolt.org` and `https://compiler-explorer.com`) may read the header.
Set `bind` to serve other machines as well; anyone who can reach the server can then trigger `make` runs in your working trees.
Set `cors_origins` to allow other web pages.
## Serving `json.hpp` from multiple project directory instances or working trees
`serve_header.py` was designed with the goal of supporting multiple project roots or working trees at the same time.
+20 -4
View File
@@ -26,6 +26,10 @@ HEADER = 'json.hpp'
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
# origins whose pages may read the served header from a browser; Compiler
# Explorer downloads #include <https://...> headers client-side
DEFAULT_CORS_ORIGINS = ['https://godbolt.org', 'https://compiler-explorer.com']
JSON_VERSION_RE = re.compile(r'\s*#\s*define\s+NLOHMANN_JSON_VERSION_MAJOR\s+')
class ExitHandler(logging.StreamHandler):
@@ -247,6 +251,8 @@ class WorkTrees(FileSystemEventHandler):
self.observer.join()
class HeaderRequestHandler(SimpleHTTPRequestHandler): # lgtm[py/missing-call-to-init]
cors_origins = DEFAULT_CORS_ORIGINS
def __init__(self, request, client_address, server):
"""."""
self.worktrees = server.worktrees
@@ -310,8 +316,11 @@ class HeaderRequestHandler(SimpleHTTPRequestHandler): # lgtm[py/missing-call-to-
# set content length
super().send_header('Content-Length', length)
# CORS header
self.send_header('Access-Control-Allow-Origin', '*')
# CORS header; only for the configured origins
origin = self.headers.get('Origin')
if origin in self.cors_origins:
self.send_header('Access-Control-Allow-Origin', origin)
self.send_header('Vary', 'Origin')
# prevent caching
self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
self.send_header('Pragma', 'no-cache')
@@ -383,8 +392,15 @@ if __name__ == '__main__':
# find and monitor working trees
worktrees = WorkTrees(config.get('root', '.'))
# start web server
infos = socket.getaddrinfo(config.get('bind', None), config.get('port', 8443),
# origins allowed to read the header from a browser
cors_origins = config.get('cors_origins', DEFAULT_CORS_ORIGINS)
if isinstance(cors_origins, str):
cors_origins = [cors_origins]
HeaderRequestHandler.cors_origins = cors_origins
# start web server; only reachable from this machine unless configured
# otherwise (bind: null listens on all interfaces)
infos = socket.getaddrinfo(config.get('bind', 'localhost'), config.get('port', 8443),
type=socket.SOCK_STREAM, flags=socket.AI_PASSIVE)
DualStackServer.address_family = infos[0][0]
HeaderRequestHandler.protocol_version = 'HTTP/1.0'
+9 -2
View File
@@ -10,6 +10,13 @@
# cert_file: localhost.pem
# key_file: localhost-key.pem
# address and port for the server to listen on
# bind: null
# address and port for the server to listen on; by default, only this machine
# can connect. Binding to a network address, or to null for all interfaces,
# lets other machines connect, and every request runs make in a working tree.
# bind: localhost
# port: 8443
# origins whose web pages may read the header (CORS)
# cors_origins:
# - https://godbolt.org
# - https://compiler-explorer.com