diff --git a/.github/workflows/publish_documentation.yml b/.github/workflows/publish_documentation.yml
index 189d95419..f65d63a92 100644
--- a/.github/workflows/publish_documentation.yml
+++ b/.github/workflows/publish_documentation.yml
@@ -7,6 +7,16 @@ on:
- develop
paths:
- docs/mkdocs/**
+ # the site also embeds these files via pymdownx.snippets
+ # (mkdocs.yml sets restrict_base_path: false for this)
+ - .clang-tidy
+ - .github/CODE_OF_CONDUCT.md
+ - .github/CONTRIBUTING.md
+ - .github/SECURITY.md
+ - cmake/clang_flags.cmake
+ - cmake/gcc_flags.cmake
+ - tests/fmt_formatter/project/main.cpp
+ - tools/astyle/.astylerc
workflow_dispatch:
# we don't want to have concurrent jobs, and we don't want to cancel running jobs to avoid broken publications
@@ -23,7 +33,7 @@ jobs:
contents: write
if: github.repository == 'nlohmann/json'
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
@@ -31,6 +41,8 @@ jobs:
egress-policy: audit
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Install virtual environment
run: make install_venv -C docs/mkdocs
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index d8f15e3dd..fb3cd4148 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -346,6 +346,8 @@ jobs:
container: intel/oneapi-hpckit:latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake
@@ -358,6 +360,8 @@ jobs:
container: nvcr.io/nvidia/nvhpc:25.5-devel-cuda12.9-ubuntu22.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index ea742773f..65169eac4 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -87,6 +87,8 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Get latest CMake and ninja
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Set extra CXX_FLAGS for latest std_version
@@ -123,6 +125,8 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Run CMake (Release)
run: cmake -S . -B build -G "Visual Studio 18 2026" -A ARM64 -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
if: matrix.build_type == 'Release'
diff --git a/docs/Makefile b/docs/Makefile
index 0412fb90a..a61c30182 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -11,20 +11,31 @@ EXAMPLES = $(wildcard mkdocs/docs/examples/*.cpp)
cxx_standard = $(lastword c++11 $(filter c++%, $(subst ., ,$1)))
+# common compile flags for the stand-alone example files
+EXAMPLE_CPPFLAGS = -I $(SRCDIR) -DJSON_USE_GLOBAL_UDLS=0
+EXAMPLE_WARNFLAGS = -Werror=deprecated-declarations
+
+# examples that document deprecated API and are allowed to use it
+DEPRECATED_EXAMPLES = $(addprefix mkdocs/docs/examples/, \
+ json_pointer__operator__equal_stringtype \
+ json_pointer__operator__notequal_stringtype \
+ json_pointer__operator_string_t)
+$(DEPRECATED_EXAMPLES:=.output) $(DEPRECATED_EXAMPLES:=.test): EXAMPLE_WARNFLAGS = -Wno-deprecated-declarations
+
# create output from a stand-alone example file
%.output: %.cpp
- @echo "standard $(call cxx_standard $(<:.cpp=))"
+ @echo "standard $(call cxx_standard,$(<:.cpp=))"
$(MAKE) $(<:.cpp=) \
- CPPFLAGS="-I $(SRCDIR) -DJSON_USE_GLOBAL_UDLS=0" \
- CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) -Wno-deprecated-declarations"
+ CPPFLAGS="$(EXAMPLE_CPPFLAGS)" \
+ CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) $(EXAMPLE_WARNFLAGS)"
./$(<:.cpp=) > $@
rm $(<:.cpp=)
# compare created output with current output of the example files
%.test: %.cpp
$(MAKE) $(<:.cpp=) \
- CPPFLAGS="-I $(SRCDIR) -DJSON_USE_GLOBAL_UDLS=0" \
- CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) -Wno-deprecated-declarations"
+ CPPFLAGS="$(EXAMPLE_CPPFLAGS)" \
+ CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) $(EXAMPLE_WARNFLAGS)"
./$(<:.cpp=) > $@
diff $@ $(<:.cpp=.output)
rm $(<:.cpp=) $@
diff --git a/docs/docset/Info.plist b/docs/docset/Info.plist
index 772ec08af..8f63bc5dd 100644
--- a/docs/docset/Info.plist
+++ b/docs/docset/Info.plist
@@ -13,7 +13,7 @@
dashIndexFilePath
index.html
DashDocSetFallbackURL
- https://nlohmann.github.io/json/
+ https://json.nlohmann.me/
isJavaScriptEnabled
diff --git a/docs/docset/Makefile b/docs/docset/Makefile
index 9f4363462..b638390db 100644
--- a/docs/docset/Makefile
+++ b/docs/docset/Makefile
@@ -52,35 +52,25 @@ install_docset_zeal: JSON_for_Modern_C++.docset
mkdir -p $$docset_root; \
cp -r JSON_for_Modern_C++.docset $$docset_root/
+# both targets below compare the docset search index with the mkdocs page
+# set. They share the same normalization (docs/foo/index.md and
+# docs/foo.md both become foo/index.html, the URL mkdocs itself would
+# give the page; the top-level index.md is excluded, as it is not part
+# of the hand-curated docSet.sql) and use comm(1) on two sorted lists
+# instead of running a sqlite3 query, or an O(n*m) nested shell loop,
+# once per page.
+DOCSET_INDEX_PATHS=$(shell sqlite3 docSet.dsidx "SELECT DISTINCT path FROM searchIndex" | sort)
+DOCSET_PAGE_PATHS=$(shell echo '$(MKDOCS_PAGES)' | tr ' ' '\n' | grep -v '^index\.md$$' | $(SED) -E 's@/index\.md$$@/index.html@; s@\.md$$@/index.html@' | sort)
+
# list mkdocs pages missing from the docset index
.PHONY: list_missing_pages
list_missing_pages: docSet.dsidx
- @for page in $(MKDOCS_PAGES); do \
- case "$$page" in \
- */index.md) path=$${page/\/index.md/} ;; \
- *) path=$${page/.md/} ;; \
- esac; \
- if [ "x$$page" != "xindex.md" -a "x$$(sqlite3 docSet.dsidx "SELECT COUNT(*) FROM searchIndex WHERE path='$$path/index.html'")" = "x0" ]; then \
- echo $$page; \
- fi \
- done
+ @comm -23 <(echo '$(DOCSET_PAGE_PATHS)' | tr ' ' '\n') <(echo '$(DOCSET_INDEX_PATHS)' | tr ' ' '\n')
# list paths in the docset index without a corresponding mkdocs page
.PHONY: list_removed_paths
list_removed_paths: docSet.dsidx
- @for path in $$(sqlite3 docSet.dsidx "SELECT path FROM searchIndex"); do \
- page=$${path/\/index.html/.md}; \
- page_index=$${path/index.html/index.md}; \
- page_found=0; \
- for p in $(MKDOCS_PAGES); do \
- if [ "x$$p" = "x$$page" -o "x$$p" = "x$$page_index" ]; then \
- page_found=1; \
- fi \
- done; \
- if [ "x$$page_found" = "x0" ]; then \
- echo $$path; \
- fi \
- done
+ @comm -13 <(echo '$(DOCSET_PAGE_PATHS)' | tr ' ' '\n') <(echo '$(DOCSET_INDEX_PATHS)' | tr ' ' '\n')
.PHONY: clean
clean:
diff --git a/docs/docset/README.md b/docs/docset/README.md
index 79a778eb8..9d962a91c 100644
--- a/docs/docset/README.md
+++ b/docs/docset/README.md
@@ -7,10 +7,11 @@ documentation browsers like [Dash](https://kapeli.com/dash), [Velocity](https://
The docset can be created with
```sh
-make nlohmann_json.docset
+make JSON_for_Modern_C++.docset
```
-The generated folder `nlohmann_json.docset` can then be opened in the documentation browser.
+The generated folder `JSON_for_Modern_C++.docset` can then be opened in the documentation browser. `make all` builds a
+`JSON_for_Modern_C++.tgz` archive instead, and `make install_docset_zeal` installs the docset for Zeal directly.
A recent version is also part of the [Dash user contributions](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B).
diff --git a/docs/mkdocs/docs/api/basic_json/number_integer_t.md b/docs/mkdocs/docs/api/basic_json/number_integer_t.md
index 9a2ffab7f..9b1d7ae74 100644
--- a/docs/mkdocs/docs/api/basic_json/number_integer_t.md
+++ b/docs/mkdocs/docs/api/basic_json/number_integer_t.md
@@ -51,7 +51,7 @@ range will yield over/underflow when used in a constructor. During deserializati
will automatically be stored as [`number_unsigned_t`](number_unsigned_t.md) or [`number_float_t`](number_float_t.md).
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
-> Note that when such software is used, numbers that are integers and are in the range $[-2^{53}+1, 2^{53}-1]$ are
+> Note that when such software is used, numbers that are integers and are in the range [-253+1, 253-1] are
> interoperable in the sense that implementations will agree exactly on their numeric values.
As this range is a subrange of the exactly supported range [INT64_MIN, INT64_MAX], this class's integer type is
diff --git a/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md b/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md
index 674f7711d..f4799b2e9 100644
--- a/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md
+++ b/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md
@@ -52,7 +52,7 @@ when used in a constructor. During deserialization, too large or small integer n
as [`number_integer_t`](number_integer_t.md) or [`number_float_t`](number_float_t.md).
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
-> Note that when such software is used, numbers that are integers and are in the range $[-2^{53}+1, 2^{53}-1]$ are
+> Note that when such software is used, numbers that are integers and are in the range [-253+1, 253-1] are
> interoperable in the sense that implementations will agree exactly on their numeric values.
As this range is a subrange (when considered in conjunction with the `number_integer_t` type) of the exactly supported
diff --git a/docs/mkdocs/docs/api/basic_json/parse_error.md b/docs/mkdocs/docs/api/basic_json/parse_error.md
index 74e16f41a..c3f49ef13 100644
--- a/docs/mkdocs/docs/api/basic_json/parse_error.md
+++ b/docs/mkdocs/docs/api/basic_json/parse_error.md
@@ -54,7 +54,7 @@ classDiagram
## Notes
-For an input with $n$ bytes, 1 is the index of the first character and $n+1$ is the index of the terminating null byte
+For an input with n bytes, 1 is the index of the first character and n+1 is the index of the terminating null byte
or the end of file. This also holds true when reading a byte vector for binary formats.
## Examples
diff --git a/docs/mkdocs/docs/examples/parse__iterator_pair.link b/docs/mkdocs/docs/examples/parse__iterator_pair.link
deleted file mode 100644
index f464e54c8..000000000
--- a/docs/mkdocs/docs/examples/parse__iterator_pair.link
+++ /dev/null
@@ -1 +0,0 @@
-online
\ No newline at end of file
diff --git a/docs/mkdocs/docs/examples/parse__pointers.link b/docs/mkdocs/docs/examples/parse__pointers.link
deleted file mode 100644
index 9a93ef1c5..000000000
--- a/docs/mkdocs/docs/examples/parse__pointers.link
+++ /dev/null
@@ -1 +0,0 @@
-online
\ No newline at end of file
diff --git a/docs/mkdocs/docs/features/binary_formats/bjdata.md b/docs/mkdocs/docs/features/binary_formats/bjdata.md
index a0c84edaf..cd73b07e2 100644
--- a/docs/mkdocs/docs/features/binary_formats/bjdata.md
+++ b/docs/mkdocs/docs/features/binary_formats/bjdata.md
@@ -61,7 +61,7 @@ The library uses the following mapping from JSON values types to BJData types ac
The following values can **not** be converted to a BJData value:
- - strings with more than 18446744073709551615 bytes, i.e., $2^{64}-1$ bytes (theoretical)
+ - strings with more than 18446744073709551615 bytes, i.e., 264-1 bytes (theoretical)
!!! info "Unused BJData markers"
diff --git a/docs/mkdocs/docs/features/types/index.md b/docs/mkdocs/docs/features/types/index.md
index e6078b825..354acd5ac 100644
--- a/docs/mkdocs/docs/features/types/index.md
+++ b/docs/mkdocs/docs/features/types/index.md
@@ -273,7 +273,7 @@ When the default type is used, the maximal unsigned integer number that can be s
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
-> Note that when such software is used, numbers that are integers and are in the range $[-2^{53}+1, 2^{53}-1]$ are interoperable in the sense that implementations will agree exactly on their numeric values.
+> Note that when such software is used, numbers that are integers and are in the range [-253+1, 253-1] are interoperable in the sense that implementations will agree exactly on their numeric values.
As this range is a subrange of the exactly supported range [`INT64_MIN`, `INT64_MAX`], this class's integer type is interoperable.
diff --git a/docs/mkdocs/docs/features/types/number_handling.md b/docs/mkdocs/docs/features/types/number_handling.md
index cf37b044a..ef43054e5 100644
--- a/docs/mkdocs/docs/features/types/number_handling.md
+++ b/docs/mkdocs/docs/features/types/number_handling.md
@@ -48,7 +48,7 @@ On number interoperability, the following remarks are made:
for numeric magnitude and precision than is widely available.
Note that when such software is used, numbers that are integers and
- are in the range $[-2^{53}+1, 2^{53}-1]$ are interoperable in the
+ are in the range [-253+1, 253-1] are interoperable in the
sense that implementations will agree exactly on their numeric
values.
@@ -95,9 +95,9 @@ This is the same behavior as the code `#!c double x = 3.141592653589793238462643
!!! success "Interoperability"
- - The library is interoperable with respect to the specification, because its supported range $[-2^{63}, 2^{64}-1]$ is
- larger than the described range $[-2^{53}+1, 2^{53}-1]$.
- - All integers outside the range $[-2^{63}, 2^{64}-1]$, as well as floating-point numbers are stored as `double`.
+ - The library is interoperable with respect to the specification, because its supported range [-263, 264-1] is
+ larger than the described range [-253+1, 253-1].
+ - All integers outside the range [-263, 264-1], as well as floating-point numbers are stored as `double`.
This also concurs with the specification above.
### Zeros
diff --git a/docs/mkdocs/docs/integration/package_managers.md b/docs/mkdocs/docs/integration/package_managers.md
index 792a0fa5a..28f95e584 100644
--- a/docs/mkdocs/docs/integration/package_managers.md
+++ b/docs/mkdocs/docs/integration/package_managers.md
@@ -678,11 +678,11 @@ to install the [nlohmann-json](https://ports.macports.org/port/nlohmann-json/) p
1. Create the following files:
```cpp title="example.cpp"
- --8<-- "integration/homebrew/example.cpp"
+ --8<-- "integration/macports/example.cpp"
```
```cmake title="CMakeLists.txt"
- --8<-- "integration/homebrew/CMakeLists.txt"
+ --8<-- "integration/macports/CMakeLists.txt"
```
2. Install the package:
diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml
index b31fb1734..4bd207e60 100644
--- a/docs/mkdocs/mkdocs.yml
+++ b/docs/mkdocs/mkdocs.yml
@@ -351,7 +351,6 @@ markdown_extensions:
- toc:
permalink: true
- md_in_html
- - pymdownx.arithmatex
- pymdownx.betterem:
smart_enable: all
- pymdownx.caret
@@ -443,6 +442,3 @@ plugins:
extra_css:
- css/custom.css
-
-extra_javascript:
- - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML
diff --git a/docs/mkdocs/scripts/check_structure.py b/docs/mkdocs/scripts/check_structure.py
index c8d637d06..78ad0d9fa 100755
--- a/docs/mkdocs/scripts/check_structure.py
+++ b/docs/mkdocs/scripts/check_structure.py
@@ -79,9 +79,9 @@ def check_structure() -> None:
report("whitespace/line_length", f"{file}:{lineno+1} ({current_section})", f"line is too long ({len(line)} vs. 160 chars)")
# sections in `` comments are treated as present
- if line.startswith("")
+ nolint_match = re.match(r"", line)
+ if nolint_match:
+ current_section = nolint_match.group(1)
existing_sections.append(current_section)
# check if sections are correct
@@ -97,7 +97,7 @@ def check_structure() -> None:
if len(unexpected):
report("style/numbering", f"{file}:{lineno} ({current_section})", f'unexpected overloads: {", ".join([f"({x})" for x in unexpected])}')
- current_section = line.strip("## ")
+ current_section = line[3:]
existing_sections.append(current_section)
if current_section in expected_sections:
@@ -141,7 +141,7 @@ def check_structure() -> None:
# check that non-example admonitions have titles
untitled_admonition = re.match(r"^(\?\?\?|!!!) ([^ ]+)$", line)
if untitled_admonition and untitled_admonition.group(2) != "example":
- report("style/admonition_title", f"{file}:{lineno} ({current_section})", f'"{untitled_admonition.group(2)}" admonitions should have a title')
+ report("style/admonition_title", f"{file}:{lineno+1} ({current_section})", f'"{untitled_admonition.group(2)}" admonitions should have a title')
previous_line = line