diff --git a/.cmake-format.yaml b/.cmake-format.yaml
index b1465f47c..600658bd1 100644
--- a/.cmake-format.yaml
+++ b/.cmake-format.yaml
@@ -1,3 +1,4 @@
+include: ["cmake/.cmake-format-additional_commands-jegp.cmake_modules.yaml"]
parse:
additional_commands:
add_mp_units_module:
diff --git a/.gitignore b/.gitignore
index a4547914a..d0a116be4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,3 +46,7 @@ CMakeUserPresets.json
# Conan
*.pyc
/test_package/build/
+
+# cxxdraft-htmlgen
+docs/api_reference/src/source/
+docs/api_reference/gen/
diff --git a/cmake/.cmake-format-additional_commands-jegp.cmake_modules.yaml b/cmake/.cmake-format-additional_commands-jegp.cmake_modules.yaml
new file mode 100644
index 000000000..232dc6f55
--- /dev/null
+++ b/cmake/.cmake-format-additional_commands-jegp.cmake_modules.yaml
@@ -0,0 +1,82 @@
+parse:
+ additional_commands:
+ _jegp_common_yaml_anchors:
+ kwargs:
+ PUBLIC_INTERFACE_PRIVATE: &public_interface_private
+ kwargs:
+ PUBLIC: +
+ INTERFACE: +
+ PRIVATE: +
+ jegp_add_standardese_sources:
+ pargs:
+ nargs: 1
+ flags:
+ - EXCLUDE_FROM_ALL
+ kwargs:
+ LIBRARIES: +
+ APPENDICES: +
+ EXTENSIONS: +
+ CHECKED: 1
+ PDF: &standardese_pdf
+ pargs:
+ flags:
+ - EXCLUDE_FROM_MAIN
+ kwargs:
+ PATH: 1
+ HTML:
+ <<: *standardese_pdf
+ kwargs:
+ SECTION_FILE_STYLE: 1
+ LATEX_REGEX_REPLACE: +
+ HTML_REGEX_REPLACE: +
+ jegp_add_module:
+ pargs: &jegp_add_module_pargs
+ nargs: 1
+ flags:
+ - IMPORTABLE_HEADER
+ kwargs:
+ SOURCES: +
+ COMPILE_OPTIONS: *public_interface_private
+ LINK_LIBRARIES: *public_interface_private
+ jegp_cpp_module:
+ pargs: *jegp_add_module_pargs
+ jegp_target_link_header_units:
+ pargs:
+ nargs: 1+
+ jegp_cpp2_target_sources:
+ pargs:
+ nargs: 1
+ kwargs:
+ JEGP_FILE_SET_KWARGS: &file_set
+ kwargs:
+ FILE_SET: 1
+ TYPE: 1
+ BASE_DIRS: +
+ FILES: +
+ PUBLIC: *file_set
+ INTERFACE: *file_set
+ PRIVATE: *file_set
+ jegp_add_headers_test:
+ pargs:
+ nargs: 1+
+ kwargs:
+ PRIVATE_REGEXES: +
+ jegp_add_test:
+ pargs:
+ nargs: 1+
+ flags:
+ - COMPILE_ONLY
+ kwargs:
+ TYPE: 1
+ SOURCES: +
+ COMPILE_OPTIONS: +
+ LINK_LIBRARIES: +
+ jegp_add_build_error:
+ pargs:
+ nargs: 1+
+ kwargs:
+ AS: 1
+ TYPE: 1
+ SOURCE: 1
+ COMPILE_OPTIONS: +
+ LINK_LIBRARIES: +
diff --git a/docs/api.md b/docs/api_reference.md
similarity index 100%
rename from docs/api.md
rename to docs/api_reference.md
diff --git a/docs/api_reference/src/CMakeLists.txt b/docs/api_reference/src/CMakeLists.txt
new file mode 100644
index 000000000..40186a0d5
--- /dev/null
+++ b/docs/api_reference/src/CMakeLists.txt
@@ -0,0 +1,41 @@
+cmake_minimum_required(VERSION 3.24.0)
+project(mp-units_reference_documentations LANGUAGES NONE)
+
+include(JEGPAddStandardeseSources)
+
+set(pdf_title "mp-units Library")
+set(page_license "MIT License")
+set(first_library_chapter "qties")
+set(last_library_chapter "qties")
+set(cover_title "mp-units Library Reference Documentations")
+set(reply_to "\\href{${PROJECT_HOMEPAGE_URL}/discussions}{Discussions}, \\href{${PROJECT_HOMEPAGE_URL}/issues}{issues}")
+jegp_add_standardese_sources(
+ mp-units_reference_documentations
+ LIBRARIES intro quantities
+ EXTENSIONS macros_extensions
+ CHECKED TRUE
+# PDF PATH "mp-units.pdf" #[[EXCLUDE_FROM_MAIN]]
+ HTML PATH "mp-units.html" #[[EXCLUDE_FROM_MAIN]]
+ SECTION_FILE_STYLE "WithExtension"
+ LATEX_REGEX_REPLACE
+ # Latex commands.
+ [[\\href{([^}]+)}{([^}]+)};HREF(\1)(\2)]]
+ # Macros extensions.
+ [[\\refcpp{([^}]+)};REFCPP(\1)]]
+ [[\\irefcpp{([^}]+)};~(REFCPP(\1))]]
+ [[\\refcppx{([^}]+)}{([^}]+)};REFCPPX(\1)(\2)]]
+ [[\\irefcppx{([^}]+)}{([^}]+)};~(REFCPPX(\1)(\2))]]
+ [[\\refiev{([^}]+)};REFIEV(\1)]]
+ [[\\irefiev{([^}]+)};~(REFIEV(\1))]]
+ # Main matter and annexes.
+ [[\\\"{o};รถ]]
+ HTML_REGEX_REPLACE
+ # Latex commands.
+ [[HREF\(([^)]+)\)\(([^)]+)\);\2]]
+ # Macros extensions.
+ [[REFCPP\(([^)]+)\);ISOCPP, [\1]]]
+ [[REFCPPX\(([^)]+)\)\(([^)]+)\);ISOCPP, [\1]]] #
+ [[ISOCPP;N4971]]
+ [[REFIEV\(([^)]+)\);IEC 60050, \1]]
+ # Main matter and annexes.
+)
diff --git a/docs/api_reference/src/intro.tex b/docs/api_reference/src/intro.tex
new file mode 100644
index 000000000..4daca1c50
--- /dev/null
+++ b/docs/api_reference/src/intro.tex
@@ -0,0 +1,134 @@
+%!TEX root = std.tex
+
+
+\rSec0[scope]{Scope}
+
+\pnum
+\indextext{scope|(}%
+This document describes the contents of the \defn{mp-units library}.
+\indextext{scope|)}
+
+
+\rSec0[refs]{References}
+
+\pnum
+\indextext{references|(}%
+The following documents are referred to in the text
+in such a way that some or all of their content
+constitutes requirements of this document.
+For dated references, only the edition cited applies.
+For undated references,
+the latest edition of the referenced document
+(including any amendments) applies.
+\begin{itemize}
+\item
+IEC 60050-102:2007/AMD3:2021,
+\doccite{Amendment 3 --- International Electrotechnical Vocabulary (IEV) ---
+Part 102: Mathematics --- General concepts and linear algebra}
+\item
+IEC 60050-112:2010/AMD2:2020,
+\doccite{Amendment 2 --- International Electrotechnical Vocabulary (IEV) ---
+Part 112: Quantities and units}
+\item
+ISO 80000 (all parts), \doccite{Quantities and units}
+\item
+The \Cpp{} Standards Committee.
+\IsoCpp{}: \doccite{Working Draft, Standard for Programming Language \Cpp{}}.
+Edited by Thomas K\"{o}ppe.
+Available from: \url{https://wg21.link/\IsoCpp{}}
+\item
+The \Cpp{} Standards Committee.
+SD-8: \doccite{Standard Library Compatibility}.
+Edited by Bryce Lelbach.
+Available from: \url{https://wg21.link/SD8}
+\end{itemize}
+\indextext{references|)}
+
+
+\rSec0[defs]{Terms and definitions}
+
+\pnum
+\indextext{definitions|(}%
+For the purposes of this document,
+the terms and definitions given in
+IEC 60050-102:2007/AMD3:2021,
+IEC 60050-112:2010/AMD2:2020,
+ISO 80000-2:2019,
+and
+\IsoCpp{},
+and the following apply.
+
+\pnum
+ISO and IEC maintain terminology databases
+for use in standardization
+at the following addresses:
+\begin{itemize}
+\item ISO Online browsing platform: available at \url{https://www.iso.org/obp}
+\item IEC Electropedia: available at \url{http://www.electropedia.org}
+\end{itemize}
+\indextext{definitions|)}
+
+
+\rSec0[spec]{Specification}
+
+\rSec1[spec.ext]{External}
+
+\pnum
+The specification of the mp-units library subsumes
+\refcpp{description}, \refcpp{requirements}, \refcpp{concepts.equality}, and SD-8,
+all assumingly amended for the context of this library.
+\begin{note}
+This means that, non exhaustively,
+\begin{itemize}
+\item \tcode{::mp_units2} is a reserved namespace, and
+\item
+\tcode{std::vector}
+is a program-defined specialization and a library-defined specialization
+from the point of view of the \Cpp{} standard library and the mp-units library, respectively.
+\end{itemize}
+\end{note}
+
+\pnum
+The mp-units library is not part of the \Cpp{} implementation.
+
+\rSec1[spec.cats]{Categories}
+
+\pnum
+Detailed specifications for each of the components in the library are in
+\ref{\firstlibchapter}--\ref{\lastlibchapter},
+as shown in \tref{lib.cats}.
+
+\begin{floattable}{Library categories}{lib.cats}
+{ll}
+\topline
+\hdstyle{Clause} & \hdstyle{Category} \\ \capsep
+\ref{qties} & Quantities library \\
+\end{floattable}
+
+\pnum
+The quantities library\iref{qties}
+describes components for dealing with quantities.
+
+\rSec1[spec.mods]{Modules}
+
+\pnum
+The mp-units library provides the
+\defnx{mp-units modules}{module!mp-units},
+shown in \tref{modules}.
+
+\begin{multicolfloattable}{mp-units modules}{modules}
+{lll}
+\tcode{mp_units} \\
+\columnbreak
+\tcode{mp_units.core} \\
+\columnbreak
+\tcode{mp_units.systems} \\
+\end{multicolfloattable}
+
+\rSec1[spec.reqs]{Library-wide requirements}
+
+\rSec2[spec.res.names]{Reserved names}
+
+\pnum
+The mp-units library reserves macro names that start with
+\tcode{MP_UNITS\opt{\gterm{digit-sequence}}_}.
diff --git a/docs/api_reference/src/macros_extensions.tex b/docs/api_reference/src/macros_extensions.tex
new file mode 100644
index 000000000..53eabe670
--- /dev/null
+++ b/docs/api_reference/src/macros_extensions.tex
@@ -0,0 +1,11 @@
+\newcommand{\IsoCpp}{N4971}
+
+%% Inline non-parenthesized C++ reference
+\newcommand{\refcpp}[1]{\href{https://wg21.link/#1}{\IsoCpp{}, [#1]}}
+\newcommand{\irefcpp}[1]{\nolinebreak[3] (\refcpp{#1})}
+\newcommand{\refcppx}[2]{\href{https://wg21.link/#1\##2}{\IsoCpp{}, [#1]}}
+\newcommand{\irefcppx}[2]{\nolinebreak[3] (\refcppx{#1}{#2})}
+
+%% Inline IEV reference
+\newcommand{\refiev}[1]{\href{https://www.electropedia.org/iev/iev.nsf/display?openform&ievref=#1}{IEC 60050, #1}}
+\newcommand{\irefiev}[1]{\nolinebreak[3] (\refiev{#1})}
diff --git a/docs/api_reference/src/quantities.tex b/docs/api_reference/src/quantities.tex
new file mode 100644
index 000000000..56e0d69e5
--- /dev/null
+++ b/docs/api_reference/src/quantities.tex
@@ -0,0 +1,266 @@
+%!TEX root = std.tex
+\rSec0[qties]{Quantities library}
+
+\rSec1[qties.summary]{Summary}
+
+\pnum
+This Clause describes components for dealing with quantities,
+as summarized in \tref{qties.summary}.
+
+\begin{modularlibsumtab}{Quantities library summary}{qties.summary}
+\ref{qty.helpers} & Helpers & \tcode{mp_units.core} \\
+\ref{qty.traits} & Traits & \\
+\ref{qty.concepts} & Concepts & \\
+\ref{qty.types} & Types & \\
+\ref{qty.compat} & Compatibility & \\
+\ref{qty.one} & Dimension one & \\ \rowsep
+\ref{qty.systems} & Systems & \tcode{mp_units.systems} \\
+\ref{qty.chrono} & \tcode{std::chrono} compatibility & \\
+\end{modularlibsumtab}
+
+\rSec1[mp.units.syn]{Module \tcode{mp_units} synopsis}
+\indexmodule{mp_units}%
+\begin{codeblock}
+export module mp_units;
+
+export import mp_units.core;
+export import mp_units.systems;
+\end{codeblock}
+
+\rSec1[mp.units.core.syn]{Module \tcode{mp_units.core} synopsis}
+\indexmodule{mp_units.core}%
+\begin{codeblock}
+export module mp_units.core;
+
+import std;
+
+export namespace mp_units {
+
+export enum class quantity_character { scalar, vector, tensor };
+
+// \ref{qty.traits}, traits
+
+template
+constexpr bool treat_as_floating_point = std::is_floating_point_v;
+
+template
+constexpr bool is_scalar =
+ std::is_floating_point_v || (std::is_integral_v && !is_same_v);
+
+template
+constexpr bool is_vector = false;
+
+template
+constexpr bool is_tensor = false;
+
+template
+struct quantity_values;
+
+template
+struct quantity_like_traits;
+
+template
+struct quantity_point_like_traits;
+
+// \ref{qty.concepts}, concepts
+
+template
+concept @\deflibconcept{some_reference}@ = template_of(^std::remove_cvref_t) == ^reference;
+
+template
+concept representation = @\seebelownc@;
+
+template
+concept representation_of = @\seebelownc@;
+
+template
+concept some_quantity_spec = @\seebelownc@;
+
+// \ref{qty.types}, types
+
+template
+struct quantity_spec; // \notdef
+
+template
+struct kind_of_; // \notdef
+
+template<@\unspec@... Expr>
+struct derived_quantity_spec;
+
+// \ref{qty.type}, class template \tcode{quantity}
+export template<@\libconcept{some_reference}@ auto R,
+ @\libconcept{representation_of}@ Rep = double>
+class quantity;
+
+// \ref{qty.point.type}, class template \tcode{quantity_point}
+template<@\unspec@>
+class quantity_point;
+
+}
+\end{codeblock}
+
+\rSec1[mp.units.systems.syn]{Module \tcode{mp_units.systems} synopsis}
+\indexmodule{mp_units.systems}%
+\begin{codeblock}
+export module mp_units.systems;
+
+export import mp_units.core;
+import std;
+
+export namespace mp_units {
+
+}
+\end{codeblock}
+
+\rSec1[qty.helpers]{Helpers}
+
+\begin{itemdecl}
+consteval bool @\exposidnc{converts-to-base-subobject-of}@(std::meta type, std::meta template_name);
+\end{itemdecl}
+
+\begin{itemdescr}
+\pnum
+\expects
+\tcode{is_type(type) \&\& is_template(template_name)} is \tcode{true}.
+
+\pnum
+\returns
+\tcode{true} if
+\tcode{[:type:]} has an unambiguous and accessible base
+that is a specialization of \tcode{[:template_name:]}, and
+\tcode{false} otherwise.
+\end{itemdescr}
+
+\rSec1[qty.traits]{Traits}
+
+\begin{itemdecl}
+template
+constexpr bool @\libglobal{is_scalar}@ =
+ std::is_floating_point_v || (std::is_integral_v && !is_same_v);
+
+template
+constexpr bool @\libglobal{is_vector}@ = false;
+
+template
+constexpr bool @\libglobal{is_tensor}@ = false;
+\end{itemdecl}
+
+\begin{itemdescr}
+\pnum
+\remarks
+Pursuant to \refcpp{namespace.std}\iref{spec.ext},
+users may specialize \tcode{is_scalar}, \tcode{is_vector}, and \tcode{is_tensor} to \tcode{true}
+for cv-unqualified program-defined types
+which respectively represent
+a scalar\irefiev{102-02-18},
+a vector\irefiev{102-03-04}, and
+% FIXME Undefined term.
+a tensor,
+and \tcode{false} for types which respectively do not.
+\end{itemdescr}
+
+\rSec1[qty.concepts]{Concepts}
+
+\begin{itemdecl}
+export template
+concept @\deflibconcept{representation}@ =
+ (is_scalar || is_vector || is_tensor)&&std::regular && @\exposidnc{scalable}@;
+\end{itemdecl}
+
+\begin{itemdecl}
+export template
+concept @\deflibconcept{representation_of}@ =
+ @\libconcept{representation}@ && ((Ch == quantity_character::scalar && is_scalar) ||
+ (Ch == quantity_character::vector && is_vector) ||
+ (Ch == quantity_character::tensor && is_tensor));
+\end{itemdecl}
+
+% FIXME Despite the `some_` prefix, it doesn't conform to the convention
+% `template_of(^std::remove_cvref_t) == ^template_name`.
+\begin{itemdecl}
+template
+concept @\defexposconceptnc{named-quantity-spec}@ =
+ (@\exposidnc{converts-to-base-subobject-of}@(^T, ^quantity_spec) && template_of(^T) != ^kind_of_);
+
+template
+concept @\deflibconcept{some_quantity_spec}@ =
+ @\exposconceptnc{named-quantity-spec}@ ||
+ detail::IntermediateDerivedQuantitySpec ||
+ template_of(^T) == ^kind_of;
+\end{itemdecl}
+
+\rSec1[qty.types]{Types}
+
+\rSec2[qty.types.general]{General}
+
+\pnum
+A \defnadj{quantity}{type}
+is a type \tcode{\placeholder{Q}}
+that is a specialization of \tcode{quantity} or \tcode{quantity_point}.
+\tcode{\placeholder{Q}} represents a quantity\irefiev{112-01-01}
+with \tcode{\placeholder{Q}::rep} as its number
+and \tcode{\placeholder{Q}::reference} as its reference.
+\tcode{\placeholder{Q}} is a structural type\irefcppx{temp.param}{term.structural.type}
+if \tcode{\placeholder{Q}::rep} is a structural type.
+
+\pnum
+Each class template defined in subclause \ref{qty.types}
+has data members and special members specified below, and
+has no base classes or members other than those specified.
+
+\rSec2[qty.type]{Class template \tcode{quantity}}
+
+\begin{codeblock}
+namespace mp_units {
+
+export template<@\libconcept{some_reference}@ auto R,
+ @\libconcept{representation_of}@ Rep = double>
+class quantity { @\unspec@ };
+
+}
+\end{codeblock}
+
+Let \tcode{\placeholder{Q}} be a specialization of \tcode{quantity}.
+\begin{itemize}
+\item
+If \tcode{Rep} is a scalar,
+\tcode{\placeholder{Q}} represents a scalar quantity\irefiev{102-02-19}.
+\item
+If \tcode{Rep} is a vector,
+\tcode{\placeholder{Q}} represents a vector\irefiev{102-03-04}.
+% FIXME What if `Rep` is a tensor?
+\end{itemize}
+
+\rSec2[qty.point.type]{Class template \tcode{quantity_point}}
+
+\begin{codeblock}
+namespace mp_units {
+
+export template<@\unspec@>
+class quantity_point { @\unspec@ };
+
+}
+\end{codeblock}
+
+A \defnadj{quantity point}{type} is a specialization of \tcode{quantity_point}.
+Let \tcode{\placeholder{Q}} be a quantity point type.
+\tcode{\placeholdernc{Q}::point_origin} represents
+the origin point of a position vector\irefiev{102-03-15}.
+\begin{itemize}
+\item
+If \tcode{Rep} is a scalar,
+\tcode{\placeholder{Q}} represents the scalar quantity\irefiev{102-02-19}
+of a position vector.
+\item
+If \tcode{Rep} is a vector,
+\tcode{\placeholder{Q}} represents a position vector.
+% FIXME What if `Rep` is a tensor?
+\end{itemize}
+
+\rSec1[qty.compat]{Compatibility}
+
+\rSec1[qty.one]{Dimension one}
+
+\rSec1[qty.systems]{Systems}
+
+\rSec1[qty.chrono]{\tcode{std::chrono} compatibility}
diff --git a/mkdocs.yml b/mkdocs.yml
index cd39fe376..da83c3c84 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -64,6 +64,9 @@ theme:
# Plugins
plugins:
- blog
+ - exclude:
+ glob:
+ - api_reference/src/*
- rss:
match_path: blog/posts/.*
date_from_meta:
@@ -175,7 +178,7 @@ nav:
- Appendix:
- Glossary: appendix/glossary.md
- References: appendix/references.md
- - API Reference: api.md
+ - API Reference: api_reference.md
- Blog:
- blog/index.md
- Release Notes: release_notes.md
diff --git a/requirements.txt b/requirements.txt
index 0392e2c0f..7651936c3 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,4 +4,5 @@ identify
mkdocs-material
mkdocs-rss-plugin
mkdocs-material[imaging]
+mkdocs-exclude
mike