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