Sphinx HTML and 17-page LaTeX PDF for the audit-ready pack
Some checks are pending
ci / markdown (push) Waiting to run
Some checks are pending
ci / markdown (push) Waiting to run
source/ is the Sphinx tree. Companion PDF hrefs are relative, not Markdown.
This commit is contained in:
parent
afa270a141
commit
da60402e88
104 changed files with 16818 additions and 0 deletions
|
|
@ -17,3 +17,10 @@ jobs:
|
||||||
grep -q "not a HIPAA" README.md
|
grep -q "not a HIPAA" README.md
|
||||||
grep -q "Cure53" PEERGOS-VERIFICATION.md
|
grep -q "Cure53" PEERGOS-VERIFICATION.md
|
||||||
grep -q "Radically Open Security" PEERGOS-VERIFICATION.md
|
grep -q "Radically Open Security" PEERGOS-VERIFICATION.md
|
||||||
|
test -f source/conf.py
|
||||||
|
test -f source/index.rst
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
- run: pip install sphinx
|
||||||
|
- run: sphinx-build -b html source build/html
|
||||||
|
|
|
||||||
12
Makefile
Normal file
12
Makefile
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
SPHINXBUILD ?= sphinx-build
|
||||||
|
SOURCEDIR = source
|
||||||
|
BUILDDIR = build
|
||||||
|
PDFNAME = peergos-making-yourself-audit-ready-with-verae-datacubes
|
||||||
|
|
||||||
|
.PHONY: html latexpdf all
|
||||||
|
html:
|
||||||
|
$(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)/html"
|
||||||
|
latexpdf:
|
||||||
|
$(SPHINXBUILD) -b latex "$(SOURCEDIR)" "$(BUILDDIR)/latex"
|
||||||
|
cd "$(BUILDDIR)/latex" && pdflatex -interaction=nonstopmode $(PDFNAME).tex && pdflatex -interaction=nonstopmode $(PDFNAME).tex
|
||||||
|
all: html latexpdf
|
||||||
15
README.md
15
README.md
|
|
@ -71,3 +71,18 @@ https://pfc.georgelambert.org/v1/npe/keys ·
|
||||||
https://docs.pfc.georgelambert.org/controls.html
|
https://docs.pfc.georgelambert.org/controls.html
|
||||||
|
|
||||||
Related: https://git.georgelambert.org/marchon/system-git-sync
|
Related: https://git.georgelambert.org/marchon/system-git-sync
|
||||||
|
|
||||||
|
## Sphinx (HTML + LaTeX PDF)
|
||||||
|
|
||||||
|
Sources live in ``source/`` (Sphinx). Build:
|
||||||
|
|
||||||
|
```
|
||||||
|
make html
|
||||||
|
make latexpdf
|
||||||
|
```
|
||||||
|
|
||||||
|
* HTML: ``build/html/index.html``
|
||||||
|
* PDF: ``build/latex/peergos-making-yourself-audit-ready-with-verae-datacubes.pdf``
|
||||||
|
|
||||||
|
LaTeX companion links are **relative PDFs** (not Markdown). Live HTML:
|
||||||
|
https://docs.pfc.georgelambert.org/audit-ready/
|
||||||
|
|
|
||||||
4
build/html/.buildinfo
Normal file
4
build/html/.buildinfo
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Sphinx build info version 1
|
||||||
|
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||||
|
config: dcabbffa1333b74218cb7af3656cfe35
|
||||||
|
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||||
BIN
build/html/.doctrees/architecture.doctree
Normal file
BIN
build/html/.doctrees/architecture.doctree
Normal file
Binary file not shown.
BIN
build/html/.doctrees/baa-dpa.doctree
Normal file
BIN
build/html/.doctrees/baa-dpa.doctree
Normal file
Binary file not shown.
BIN
build/html/.doctrees/checklist.doctree
Normal file
BIN
build/html/.doctrees/checklist.doctree
Normal file
Binary file not shown.
BIN
build/html/.doctrees/environment.pickle
Normal file
BIN
build/html/.doctrees/environment.pickle
Normal file
Binary file not shown.
BIN
build/html/.doctrees/howto.doctree
Normal file
BIN
build/html/.doctrees/howto.doctree
Normal file
Binary file not shown.
BIN
build/html/.doctrees/index.doctree
Normal file
BIN
build/html/.doctrees/index.doctree
Normal file
Binary file not shown.
BIN
build/html/.doctrees/verification.doctree
Normal file
BIN
build/html/.doctrees/verification.doctree
Normal file
Binary file not shown.
43
build/html/_sources/architecture.rst.txt
Normal file
43
build/html/_sources/architecture.rst.txt
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
Architecture (audit interview)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Endpoint (keys stay here / HSM)
|
||||||
|
│ HPKE content (NPE suite)
|
||||||
|
│ routing: dest + subject in the clear
|
||||||
|
▼
|
||||||
|
Untrusted NATS (cannot read bodies)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Verae DataCube chain (append-only hashes)
|
||||||
|
│ written through Peergos client
|
||||||
|
▼
|
||||||
|
Peergos cryptree (encrypted names, sizes, graph)
|
||||||
|
│ chunks → CID / hash
|
||||||
|
▼
|
||||||
|
IPFS (distributed, hash-verified ciphertext)
|
||||||
|
|
||||||
|
* **At rest:** Peergos cryptree + IPFS. Hosts with disk/backup see
|
||||||
|
**opaque hashed ciphertext**, not PHI, if they lack keys.
|
||||||
|
* **In transit (NATS):** HPKE-Base to directory public keys. Broker is
|
||||||
|
honest-but-curious: destinations yes, bodies no.
|
||||||
|
* **Integrity:** cube JSONL chain + dual hash + IPFS CID check on
|
||||||
|
restore (re-fetch blocks, re-verify hashes — not a plaintext tape).
|
||||||
|
|
||||||
|
NATS remains an untrusted router. Production E2E is NPE/HPKE.
|
||||||
|
Passthrough means destination in the clear; the body is ciphertext.
|
||||||
|
|
||||||
|
.. only:: html
|
||||||
|
|
||||||
|
Live: https://pfc.georgelambert.org/v1/npe/keys (public keys only).
|
||||||
|
Controls: https://docs.pfc.georgelambert.org/controls.html
|
||||||
|
|
||||||
|
.. only:: latex
|
||||||
|
|
||||||
|
See companion ``peergos-for-compliance.pdf`` (same folder) for
|
||||||
|
controls, custody, and variables chapters.
|
||||||
|
|
||||||
|
.. raw:: latex
|
||||||
|
|
||||||
|
\href{peergos-for-compliance.pdf}{peergos-for-compliance.pdf}
|
||||||
76
build/html/_sources/baa-dpa.rst.txt
Normal file
76
build/html/_sources/baa-dpa.rst.txt
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
BAAs and DPAs when ciphertext has no host keys
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
This is **guidance for an evidence pack**, not legal advice.
|
||||||
|
|
||||||
|
The operator statement
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Data at rest lives in the **encrypted Peergos cryptree**. Restore uses
|
||||||
|
**distributed, hash-verified, encrypted IPFS blocks**. Hosts and backup
|
||||||
|
media see **opaque blobs** (and random CHAMP labels), not filenames, not
|
||||||
|
PHI, not social graph — if keys never leave the client / customer HSM.
|
||||||
|
|
||||||
|
That is **true of the Peergos design** (see :doc:`verification`).
|
||||||
|
It **changes the BAA/DPA conversation**. It does **not** auto-delete the
|
||||||
|
need for contracts.
|
||||||
|
|
||||||
|
HIPAA (US) — Business Associate
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
A Business Associate is a person who **creates, receives, maintains, or
|
||||||
|
transmits ePHI** for a covered entity.
|
||||||
|
|
||||||
|
**Technical argument you can make (and should document):**
|
||||||
|
|
||||||
|
1. ePHI is encrypted **before** it leaves the endpoint (Peergos client /
|
||||||
|
DataCube writer).
|
||||||
|
2. The storage node, IPFS, disk, and backup hold **ciphertext + hashes**.
|
||||||
|
3. Private keys **do not** reside on the storage host (customer HSM /
|
||||||
|
client). Hash verification detects tampering.
|
||||||
|
4. Therefore the host **cannot maintain ePHI in intelligible form**.
|
||||||
|
|
||||||
|
HHS distinguishes **conduits** and parties that never have access to
|
||||||
|
ePHI. Many programs still **sign a BAA** when a vendor touches
|
||||||
|
infrastructure, because misconfiguration, support exports, or logs could
|
||||||
|
later expose plaintext. OCR looks at **your** risk analysis.
|
||||||
|
|
||||||
|
**Practical pack:** risk analysis memo citing cryptree + IPFS hash checks
|
||||||
|
+ key custody; BAA **or** written determination that the vendor is
|
||||||
|
**not** a BA because they cannot decrypt; list every party with
|
||||||
|
disk/backup (ns1, IPFS cluster, offsite replica).
|
||||||
|
|
||||||
|
GDPR (EU/UK) — processor vs technical measure
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
Encrypted data can still be **personal data** if it is reasonably
|
||||||
|
attributable (usernames, IPs, invoice identity). GDPR **Art. 32** lists
|
||||||
|
encryption as a security measure.
|
||||||
|
|
||||||
|
Peergos is designed so the **server is an adversary** for content and
|
||||||
|
most metadata. EU-based **independent pentests** (Cure53 DE, ROS NL)
|
||||||
|
evaluated that design. Processing location for **self-host** is *your*
|
||||||
|
ns1 / customer region, not peergos.net’s Germany hosting, unless you use
|
||||||
|
peergos.net.
|
||||||
|
|
||||||
|
You may still need a **DPA (Art. 28)** with anyone who **processes**
|
||||||
|
personal data (usernames, logs, billing). Ciphertext-only storage
|
||||||
|
**narrows** the DPA’s technical annex.
|
||||||
|
|
||||||
|
NATS operators
|
||||||
|
--------------
|
||||||
|
|
||||||
|
NATS is an **untrusted broker**. Content is HPKE; destinations and
|
||||||
|
subjects are in the clear. A NATS operator **cannot** read bodies without
|
||||||
|
endpoint private keys; **can** see routing metadata; **can** drop/delay
|
||||||
|
copy **ciphertext**. Treat like a transit provider: DPA/BAA depends on
|
||||||
|
whether routing metadata is personal data in your jurisdiction.
|
||||||
|
|
||||||
|
What “making yourself audit-ready” means
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
You are **not** buying Peergos’s Cure53/ROS reports as *your* SOC 2.
|
||||||
|
You are **reusing** those public evaluations as **vendor/component
|
||||||
|
assurance**, then adding your scope, RoPA, key-custody, inspect k-of-n,
|
||||||
|
admin-history, instance evidence, and contracts that match who can
|
||||||
|
actually see plaintext.
|
||||||
62
build/html/_sources/checklist.rst.txt
Normal file
62
build/html/_sources/checklist.rst.txt
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
Audit-ready checklist
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Use this as a working list. Check items only when **evidence exists**
|
||||||
|
(screenshot, log export, signed policy, ticket). This list is not a
|
||||||
|
certificate.
|
||||||
|
|
||||||
|
A. Scope and data map
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
* Named legal entity and systems in scope (console, Drive, NATS, IPFS, ns1)
|
||||||
|
* Data-flow diagram: endpoint → HPKE/NATS → cryptree/IPFS
|
||||||
|
* What is PHI / personal data vs ciphertext vs routing metadata
|
||||||
|
* Peergos verification chapter attached (:doc:`verification`)
|
||||||
|
|
||||||
|
B. Keys and encryption
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
* Customer holds Peergos/Drive keys; not on storage host
|
||||||
|
* NPE/HPKE endpoint keys in directory; private 0600; no xor content
|
||||||
|
* Signed Ed25519 config; unsigned rejected; admin-history prev+new+diff
|
||||||
|
* HSM or documented lab-to-HSM path
|
||||||
|
|
||||||
|
C. Access
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Console ``PFC_REQUIRE_AUTH=1``, TOTP; Drive login separate
|
||||||
|
* Inspect k-of-n; author is not an officer; log-before-reveal
|
||||||
|
* Joiner / mover / leaver for console users
|
||||||
|
* Google SSO does **not** unwrap cubes
|
||||||
|
|
||||||
|
D. Integrity and backup
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
* Cube chain append-only JSONL; dual hash
|
||||||
|
* Hash registry: first SHA-256 and receipt win
|
||||||
|
* Peergos/IPFS: hash-verified encrypted blocks (restore = re-fetch CIDs)
|
||||||
|
* Restore test: recover a cube from content-addressed ciphertext without
|
||||||
|
plaintext backup tapes
|
||||||
|
|
||||||
|
E. Logging
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Inspect audit events
|
||||||
|
* SM summaries: codes + lookup_id only (no bodies)
|
||||||
|
* Admin-history cube for config
|
||||||
|
|
||||||
|
F. Contracts (counsel)
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
* Written BA / not-a-BA determination for disk, VM, backup, IPFS
|
||||||
|
* DPA Art. 28 where usernames/logs/IPs are processed
|
||||||
|
* NATS operator: metadata vs content in the annex
|
||||||
|
* Peergos component assurance: attach Cure53 2019 + ROS 2024 PDFs
|
||||||
|
(public; not your org’s ISO/SOC report)
|
||||||
|
|
||||||
|
G. Independent audit of *you*
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
* SOC 2 Type I/II engagement **or** ISO 27001 registrar **or** HIPAA
|
||||||
|
risk analysis + policies (pick the program you actually need)
|
||||||
|
* Evidence window (Type II / surveillance) if applicable
|
||||||
30
build/html/_sources/howto.rst.txt
Normal file
30
build/html/_sources/howto.rst.txt
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
How to use this pack
|
||||||
|
====================
|
||||||
|
|
||||||
|
1. Read :doc:`verification` so you do not over-claim Peergos audits.
|
||||||
|
2. Fill :doc:`checklist` with **your** instance evidence (ns1, keys, users).
|
||||||
|
3. Give :doc:`baa-dpa` to counsel with the data-flow from :doc:`architecture`.
|
||||||
|
4. Point auditors at live technical surfaces (do not give them private keys).
|
||||||
|
|
||||||
|
.. only:: html
|
||||||
|
|
||||||
|
* https://pfc.georgelambert.org/health
|
||||||
|
* https://pfc.georgelambert.org/v1/npe/keys (public keys only)
|
||||||
|
* https://docs.pfc.georgelambert.org/controls.html
|
||||||
|
* https://docs.pfc.georgelambert.org/custody.html
|
||||||
|
* Peergos Drive (cryptree) on your host
|
||||||
|
* https://git.georgelambert.org/marchon/peergos-for-compliance
|
||||||
|
* https://git.georgelambert.org/marchon/system-git-sync
|
||||||
|
* https://git.georgelambert.org/marchon/secure-messaging
|
||||||
|
|
||||||
|
5. Attach the two **public** Peergos pentest PDFs from the Peergos
|
||||||
|
``audits/`` tree as **vendor security evaluations**, labeled “not our
|
||||||
|
SOC 2 / ISO certificate”.
|
||||||
|
|
||||||
|
.. only:: latex
|
||||||
|
|
||||||
|
Companion system PDF (same folder):
|
||||||
|
|
||||||
|
.. raw:: latex
|
||||||
|
|
||||||
|
\href{peergos-for-compliance.pdf}{peergos-for-compliance.pdf}
|
||||||
61
build/html/_sources/index.rst.txt
Normal file
61
build/html/_sources/index.rst.txt
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
Making yourself audit-ready with Verae DataCubes
|
||||||
|
================================================
|
||||||
|
|
||||||
|
How to **prepare an organization** for HIPAA-aligned, SOC 2, or ISO 27001
|
||||||
|
work using Verae DataCubes on **Peergos** (encrypted cryptree + hashed
|
||||||
|
IPFS) and HPKE on an **untrusted NATS** broker.
|
||||||
|
|
||||||
|
**This document is not a HIPAA, SOC 2, or ISO certificate.**
|
||||||
|
Peergos’s public pentests are **not** your Type II or ISO registrar
|
||||||
|
certificate. They are **component security evaluations** you can attach.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
verification
|
||||||
|
architecture
|
||||||
|
baa-dpa
|
||||||
|
checklist
|
||||||
|
howto
|
||||||
|
|
||||||
|
What we verified about Peergos (EU)
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
See the full sourced table in :doc:`verification`.
|
||||||
|
|
||||||
|
* Encrypted client-side filesystem (cryptree); keys not on the storage
|
||||||
|
server — **yes** (Peergos book + Cure53 design review).
|
||||||
|
* IPFS blocks content-addressed; Peergos verifies hashes — **yes**.
|
||||||
|
* Independent **EU** security audits, reports published — **yes, two:**
|
||||||
|
Cure53 Berlin (2019); Radically Open Security Amsterdam (2024).
|
||||||
|
* “Peergos is HIPAA/SOC 2/ISO certified” — **no.** Those audits are
|
||||||
|
pentest/code/design reviews, not management-system certificates.
|
||||||
|
|
||||||
|
Peergos **was designed as a trust-minimized encrypted filesystem**,
|
||||||
|
**evaluated in Europe** by two specialist firms, with **public reports**.
|
||||||
|
That supports the **at-rest / backup** story. It does **not** finish
|
||||||
|
*your* audit.
|
||||||
|
|
||||||
|
.. only:: html
|
||||||
|
|
||||||
|
Live technical surfaces:
|
||||||
|
|
||||||
|
* https://pfc.georgelambert.org/health
|
||||||
|
* https://pfc.georgelambert.org/v1/npe/keys
|
||||||
|
* https://docs.pfc.georgelambert.org/controls.html
|
||||||
|
* https://git.georgelambert.org/marchon/peergos-making-yourself-audit-ready-with-verae-datacubes
|
||||||
|
|
||||||
|
Companion system docs (HTML): https://docs.pfc.georgelambert.org/
|
||||||
|
|
||||||
|
.. only:: latex
|
||||||
|
|
||||||
|
Companion PDFs in the **same directory** as this file (relative PDF
|
||||||
|
links, not Markdown):
|
||||||
|
|
||||||
|
.. raw:: latex
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \href{peergos-for-compliance.pdf}{peergos-for-compliance.pdf}
|
||||||
|
\item \href{nats-service-endpoints.pdf}{nats-service-endpoints.pdf}
|
||||||
|
\item \href{secure-messaging.pdf}{secure-messaging.pdf}
|
||||||
|
\end{itemize}
|
||||||
84
build/html/_sources/verification.rst.txt
Normal file
84
build/html/_sources/verification.rst.txt
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
Peergos verification (what was actually audited)
|
||||||
|
================================================
|
||||||
|
|
||||||
|
This chapter records **sourced** facts. It does **not** turn Peergos, Verae,
|
||||||
|
or DataCubes into a HIPAA, SOC 2, or ISO 27001 certificate.
|
||||||
|
|
||||||
|
Claim to check
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Data at rest is stored in an encrypted append-only Peergos filesystem;
|
||||||
|
backup/restore is managed via a distributed, hashed, encrypted Peergos
|
||||||
|
IPFS system, designed and evaluated in the EU as an audited secure
|
||||||
|
filesystem.
|
||||||
|
|
||||||
|
Independent security audits (Europe)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
**2019 — Cure53 (Berlin, Germany).**
|
||||||
|
Pentest, source-code audit, **crypto/design review** (May–June 2019).
|
||||||
|
No fundamental architectural or cryptographic problems; issues fixed.
|
||||||
|
Cure53: the platform **passed this evaluation**.
|
||||||
|
|
||||||
|
**2024 — Radically Open Security B.V. (Amsterdam, Netherlands).**
|
||||||
|
Crystal-box pentest + code audit of Peergos web-ui (Sep–Nov 2024).
|
||||||
|
**0** extreme / high / elevated; **2** moderate, **6** low; Peergos
|
||||||
|
states all fixed; no data exposure or integrity compromise (mostly UI
|
||||||
|
crashes).
|
||||||
|
|
||||||
|
Both firms are **EU-based**. Both full reports are **public**. That is a
|
||||||
|
**security evaluation of the Peergos protocol/implementation**, not a
|
||||||
|
HIPAA/SOC 2/ISO management-system certificate.
|
||||||
|
|
||||||
|
.. only:: html
|
||||||
|
|
||||||
|
Primary sources:
|
||||||
|
|
||||||
|
* https://peergos.org/posts/security-audit
|
||||||
|
* https://cure53.de/pentest-report_peergos.pdf
|
||||||
|
* https://peergos.org/posts/security-audit-2024
|
||||||
|
* https://github.com/Peergos/Peergos/tree/master/audits
|
||||||
|
|
||||||
|
EU funding / NLnet
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Peergos received funding from the **European Union Horizon 2020**
|
||||||
|
programme under **NGI-POINTER**, grant **871528** (stated on the 2024
|
||||||
|
audit post).
|
||||||
|
* The 2024 audit was supported by **NLnet** (Netherlands).
|
||||||
|
|
||||||
|
Hosted instance location
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Peergos’s hosted privacy notice states peergos.net uses servers in
|
||||||
|
**Germany**. **Self-hosted ns1 / customer cryptree is a different
|
||||||
|
processing location** and must be documented in *your* RoPA / BAA pack.
|
||||||
|
|
||||||
|
Encrypted filesystem + hashed IPFS (design)
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
* **Cryptree**: tree of symmetric keys; fine-grained read/write caps;
|
||||||
|
sibling names hidden; writes **signed**.
|
||||||
|
* **Chunks**: up to 5 MiB, padded, independently encrypted
|
||||||
|
(Salsa20-Poly1305); random 256-bit keys (not convergent).
|
||||||
|
* **IPFS**: content-addressed blocks. Peergos **verifies the hash** of
|
||||||
|
every block read from or written to IPFS. Clients verify hashes and
|
||||||
|
signatures from a Peergos server.
|
||||||
|
* **CHAMP**: encrypted cryptree nodes under **random 32-byte labels**.
|
||||||
|
* Sharing: hybrid **X25519 + ML-KEM-1024**.
|
||||||
|
|
||||||
|
“Append-only” in Verae DataCubes is the **cube chain JSONL** (application
|
||||||
|
integrity). Peergos uses signed updates and immutable blocks. Do not
|
||||||
|
conflate the two layers in an audit interview.
|
||||||
|
|
||||||
|
Not verified / do not claim
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* “Peergos is HIPAA certified” — **false.** HIPAA is not a product certificate.
|
||||||
|
* “Peergos is SOC 2 / ISO 27001 certified” — **not shown.** Published
|
||||||
|
work is pentest/code audit, not Type II or ISO registrar.
|
||||||
|
* “EU certified Peergos as a government-standard filesystem” —
|
||||||
|
**overstated.** What exists: EU grant funding, NLNet-funded ROS
|
||||||
|
pentest, Cure53 Berlin design+code audit.
|
||||||
|
* “Hosts with disk/backup never need a BAA/DPA” — **legal conclusion,
|
||||||
|
not a technical fact.** See :doc:`baa-dpa`.
|
||||||
663
build/html/_static/alabaster.css
Normal file
663
build/html/_static/alabaster.css
Normal file
|
|
@ -0,0 +1,663 @@
|
||||||
|
/* -- page layout ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 17px;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #000;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.document {
|
||||||
|
width: 940px;
|
||||||
|
margin: 30px auto 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.documentwrapper {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bodywrapper {
|
||||||
|
margin: 0 0 0 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar {
|
||||||
|
width: 220px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 1px solid #B1B4B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #3E4349;
|
||||||
|
padding: 0 30px 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body > .section {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footer {
|
||||||
|
width: 940px;
|
||||||
|
margin: 20px auto 30px auto;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #888;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footer a {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.caption {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.relations {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.sphinxsidebar {
|
||||||
|
max-height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar a {
|
||||||
|
color: #444;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px dotted #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar a:hover {
|
||||||
|
border-bottom: 1px solid #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper {
|
||||||
|
padding: 18px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper p.logo {
|
||||||
|
padding: 0;
|
||||||
|
margin: -10px 0 0 0px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper h1.logo {
|
||||||
|
margin-top: -10px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper h1.logo-name {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper p.blurb {
|
||||||
|
margin-top: 0;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h3,
|
||||||
|
div.sphinxsidebar h4 {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
color: #444;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h4 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h3 a {
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar p.logo a,
|
||||||
|
div.sphinxsidebar h3 a,
|
||||||
|
div.sphinxsidebar p.logo a:hover,
|
||||||
|
div.sphinxsidebar h3 a:hover {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar p {
|
||||||
|
color: #555;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul {
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 0;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul li.toctree-l1 > a {
|
||||||
|
font-size: 120%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul li.toctree-l2 > a {
|
||||||
|
font-size: 110%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar input {
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar .search > div {
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar hr {
|
||||||
|
border: none;
|
||||||
|
height: 1px;
|
||||||
|
color: #AAA;
|
||||||
|
background: #AAA;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
margin-left: 0;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar .badge {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar .badge:hover {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To address an issue with donation coming after search */
|
||||||
|
div.sphinxsidebar h3.donation {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- body styles ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #004B6B;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #6D4100;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body h1,
|
||||||
|
div.body h2,
|
||||||
|
div.body h3,
|
||||||
|
div.body h4,
|
||||||
|
div.body h5,
|
||||||
|
div.body h6 {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 30px 0px 10px 0px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
|
||||||
|
div.body h2 { font-size: 180%; }
|
||||||
|
div.body h3 { font-size: 150%; }
|
||||||
|
div.body h4 { font-size: 130%; }
|
||||||
|
div.body h5 { font-size: 100%; }
|
||||||
|
div.body h6 { font-size: 100%; }
|
||||||
|
|
||||||
|
a.headerlink {
|
||||||
|
color: #DDD;
|
||||||
|
padding: 0 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.headerlink:hover {
|
||||||
|
color: #444;
|
||||||
|
background: #EAEAEA;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p, div.body dd, div.body li {
|
||||||
|
line-height: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition {
|
||||||
|
margin: 20px 0px;
|
||||||
|
padding: 10px 30px;
|
||||||
|
background-color: #EEE;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
|
||||||
|
background-color: #FBFBFB;
|
||||||
|
border-bottom: 1px solid #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition p.admonition-title {
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 24px;
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition p.last {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt:target, .highlight {
|
||||||
|
background: #FAF3E8;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.warning {
|
||||||
|
background-color: #FCC;
|
||||||
|
border: 1px solid #FAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.danger {
|
||||||
|
background-color: #FCC;
|
||||||
|
border: 1px solid #FAA;
|
||||||
|
-moz-box-shadow: 2px 2px 4px #D52C2C;
|
||||||
|
-webkit-box-shadow: 2px 2px 4px #D52C2C;
|
||||||
|
box-shadow: 2px 2px 4px #D52C2C;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.error {
|
||||||
|
background-color: #FCC;
|
||||||
|
border: 1px solid #FAA;
|
||||||
|
-moz-box-shadow: 2px 2px 4px #D52C2C;
|
||||||
|
-webkit-box-shadow: 2px 2px 4px #D52C2C;
|
||||||
|
box-shadow: 2px 2px 4px #D52C2C;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.caution {
|
||||||
|
background-color: #FCC;
|
||||||
|
border: 1px solid #FAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.attention {
|
||||||
|
background-color: #FCC;
|
||||||
|
border: 1px solid #FAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.important {
|
||||||
|
background-color: #EEE;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.note {
|
||||||
|
background-color: #EEE;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.tip {
|
||||||
|
background-color: #EEE;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.hint {
|
||||||
|
background-color: #EEE;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.seealso {
|
||||||
|
background-color: #EEE;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.topic {
|
||||||
|
background-color: #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.admonition-title {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.admonition-title:after {
|
||||||
|
content: ":";
|
||||||
|
}
|
||||||
|
|
||||||
|
pre, tt, code {
|
||||||
|
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hll {
|
||||||
|
background-color: #FFC;
|
||||||
|
margin: 0 -12px;
|
||||||
|
padding: 0 12px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.screenshot {
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.descname, tt.descclassname, code.descname, code.descclassname {
|
||||||
|
font-size: 0.95em;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.descname, code.descname {
|
||||||
|
padding-right: 0.08em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.screenshot {
|
||||||
|
-moz-box-shadow: 2px 2px 4px #EEE;
|
||||||
|
-webkit-box-shadow: 2px 2px 4px #EEE;
|
||||||
|
box-shadow: 2px 2px 4px #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils {
|
||||||
|
border: 1px solid #888;
|
||||||
|
-moz-box-shadow: 2px 2px 4px #EEE;
|
||||||
|
-webkit-box-shadow: 2px 2px 4px #EEE;
|
||||||
|
box-shadow: 2px 2px 4px #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils td, table.docutils th {
|
||||||
|
border: 1px solid #888;
|
||||||
|
padding: 0.25em 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.field-list, table.footnote {
|
||||||
|
border: none;
|
||||||
|
-moz-box-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.footnote {
|
||||||
|
margin: 15px 0;
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #EEE;
|
||||||
|
background: #FDFDFD;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.footnote + table.footnote {
|
||||||
|
margin-top: -15px;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.field-list th {
|
||||||
|
padding: 0 0.8em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.field-list td {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.field-list p {
|
||||||
|
margin-bottom: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cloned from
|
||||||
|
* https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68
|
||||||
|
*/
|
||||||
|
.field-name {
|
||||||
|
-moz-hyphens: manual;
|
||||||
|
-ms-hyphens: manual;
|
||||||
|
-webkit-hyphens: manual;
|
||||||
|
hyphens: manual;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.footnote td.label {
|
||||||
|
width: .1px;
|
||||||
|
padding: 0.3em 0 0.3em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.footnote td {
|
||||||
|
padding: 0.3em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl dd {
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 0 0 0 30px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
|
/* Matches the 30px from the narrow-screen "li > ul" selector below */
|
||||||
|
margin: 10px 0 10px 30px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: unset;
|
||||||
|
padding: 7px 30px;
|
||||||
|
margin: 15px 0px;
|
||||||
|
line-height: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.viewcode-block:target {
|
||||||
|
background: #ffd;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl pre, blockquote pre, li pre {
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt, code {
|
||||||
|
background-color: #ecf0f3;
|
||||||
|
color: #222;
|
||||||
|
/* padding: 1px 2px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.xref, code.xref, a tt {
|
||||||
|
background-color: #FBFBFB;
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.reference {
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px dotted #004B6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.reference:hover {
|
||||||
|
border-bottom: 1px solid #6D4100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't put an underline on images */
|
||||||
|
a.image-reference, a.image-reference:hover {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.footnote-reference {
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.7em;
|
||||||
|
vertical-align: top;
|
||||||
|
border-bottom: 1px dotted #004B6B;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.footnote-reference:hover {
|
||||||
|
border-bottom: 1px solid #6D4100;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover tt, a:hover code {
|
||||||
|
background: #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 940px) {
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.documentwrapper {
|
||||||
|
float: none;
|
||||||
|
background: #fff;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar {
|
||||||
|
display: block;
|
||||||
|
float: none;
|
||||||
|
width: unset;
|
||||||
|
margin: 50px -30px -20px -30px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background: #333;
|
||||||
|
color: #FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
|
||||||
|
div.sphinxsidebar h3 a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar a {
|
||||||
|
color: #AAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar p.logo {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.document {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bodywrapper {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body {
|
||||||
|
min-height: 0;
|
||||||
|
min-width: auto; /* fixes width on small screens, breaks .hll */
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hll {
|
||||||
|
/* "fixes" the breakage */
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rtd_doc_footer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.document {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.github {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li > ul {
|
||||||
|
/* Matches the 30px from the "ul, ol" selector above */
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* misc. */
|
||||||
|
|
||||||
|
.revsys-inline {
|
||||||
|
display: none!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide ugly table cell borders in ..bibliography:: directive output */
|
||||||
|
table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
|
||||||
|
border: none;
|
||||||
|
/* Below needed in some edge cases; if not applied, bottom shadows appear */
|
||||||
|
-moz-box-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* relbar */
|
||||||
|
|
||||||
|
.related {
|
||||||
|
line-height: 30px;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related.top {
|
||||||
|
border-bottom: 1px solid #EEE;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related.bottom {
|
||||||
|
border-top: 1px solid #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related ul {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.related li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav#rellinks {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav#rellinks li+li:before {
|
||||||
|
content: "|";
|
||||||
|
}
|
||||||
|
|
||||||
|
nav#breadcrumbs li+li:before {
|
||||||
|
content: "\00BB";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide certain items when printing */
|
||||||
|
@media print {
|
||||||
|
div.related {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img.github {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
border: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
476
build/html/_static/base-stemmer.js
Normal file
476
build/html/_static/base-stemmer.js
Normal file
|
|
@ -0,0 +1,476 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
/**@constructor*/
|
||||||
|
BaseStemmer = function() {
|
||||||
|
/** @protected */
|
||||||
|
this.current = '';
|
||||||
|
this.cursor = 0;
|
||||||
|
this.limit = 0;
|
||||||
|
this.limit_backward = 0;
|
||||||
|
this.bra = 0;
|
||||||
|
this.ket = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} value
|
||||||
|
*/
|
||||||
|
this.setCurrent = function(value) {
|
||||||
|
this.current = value;
|
||||||
|
this.cursor = 0;
|
||||||
|
this.limit = this.current.length;
|
||||||
|
this.limit_backward = 0;
|
||||||
|
this.bra = this.cursor;
|
||||||
|
this.ket = this.limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
this.getCurrent = function() {
|
||||||
|
return this.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {BaseStemmer} other
|
||||||
|
*/
|
||||||
|
this.copy_from = function(other) {
|
||||||
|
/** @protected */
|
||||||
|
this.current = other.current;
|
||||||
|
this.cursor = other.cursor;
|
||||||
|
this.limit = other.limit;
|
||||||
|
this.limit_backward = other.limit_backward;
|
||||||
|
this.bra = other.bra;
|
||||||
|
this.ket = other.ket;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number[]} s
|
||||||
|
* @param {number} min
|
||||||
|
* @param {number} max
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.in_grouping = function(s, min, max) {
|
||||||
|
/** @protected */
|
||||||
|
if (this.cursor >= this.limit) return false;
|
||||||
|
var ch = this.current.charCodeAt(this.cursor);
|
||||||
|
if (ch > max || ch < min) return false;
|
||||||
|
ch -= min;
|
||||||
|
if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false;
|
||||||
|
this.cursor++;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number[]} s
|
||||||
|
* @param {number} min
|
||||||
|
* @param {number} max
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.go_in_grouping = function(s, min, max) {
|
||||||
|
/** @protected */
|
||||||
|
while (this.cursor < this.limit) {
|
||||||
|
var ch = this.current.charCodeAt(this.cursor);
|
||||||
|
if (ch > max || ch < min)
|
||||||
|
return true;
|
||||||
|
ch -= min;
|
||||||
|
if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0)
|
||||||
|
return true;
|
||||||
|
this.cursor++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number[]} s
|
||||||
|
* @param {number} min
|
||||||
|
* @param {number} max
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.in_grouping_b = function(s, min, max) {
|
||||||
|
/** @protected */
|
||||||
|
if (this.cursor <= this.limit_backward) return false;
|
||||||
|
var ch = this.current.charCodeAt(this.cursor - 1);
|
||||||
|
if (ch > max || ch < min) return false;
|
||||||
|
ch -= min;
|
||||||
|
if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return false;
|
||||||
|
this.cursor--;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number[]} s
|
||||||
|
* @param {number} min
|
||||||
|
* @param {number} max
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.go_in_grouping_b = function(s, min, max) {
|
||||||
|
/** @protected */
|
||||||
|
while (this.cursor > this.limit_backward) {
|
||||||
|
var ch = this.current.charCodeAt(this.cursor - 1);
|
||||||
|
if (ch > max || ch < min) return true;
|
||||||
|
ch -= min;
|
||||||
|
if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) return true;
|
||||||
|
this.cursor--;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number[]} s
|
||||||
|
* @param {number} min
|
||||||
|
* @param {number} max
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.out_grouping = function(s, min, max) {
|
||||||
|
/** @protected */
|
||||||
|
if (this.cursor >= this.limit) return false;
|
||||||
|
var ch = this.current.charCodeAt(this.cursor);
|
||||||
|
if (ch > max || ch < min) {
|
||||||
|
this.cursor++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ch -= min;
|
||||||
|
if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) == 0) {
|
||||||
|
this.cursor++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number[]} s
|
||||||
|
* @param {number} min
|
||||||
|
* @param {number} max
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.go_out_grouping = function(s, min, max) {
|
||||||
|
/** @protected */
|
||||||
|
while (this.cursor < this.limit) {
|
||||||
|
var ch = this.current.charCodeAt(this.cursor);
|
||||||
|
if (ch <= max && ch >= min) {
|
||||||
|
ch -= min;
|
||||||
|
if ((s[ch >>> 3] & (0X1 << (ch & 0x7))) != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.cursor++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number[]} s
|
||||||
|
* @param {number} min
|
||||||
|
* @param {number} max
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.out_grouping_b = function(s, min, max) {
|
||||||
|
/** @protected */
|
||||||
|
if (this.cursor <= this.limit_backward) return false;
|
||||||
|
var ch = this.current.charCodeAt(this.cursor - 1);
|
||||||
|
if (ch > max || ch < min) {
|
||||||
|
this.cursor--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ch -= min;
|
||||||
|
if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) == 0) {
|
||||||
|
this.cursor--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number[]} s
|
||||||
|
* @param {number} min
|
||||||
|
* @param {number} max
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.go_out_grouping_b = function(s, min, max) {
|
||||||
|
/** @protected */
|
||||||
|
while (this.cursor > this.limit_backward) {
|
||||||
|
var ch = this.current.charCodeAt(this.cursor - 1);
|
||||||
|
if (ch <= max && ch >= min) {
|
||||||
|
ch -= min;
|
||||||
|
if ((s[ch >>> 3] & (0x1 << (ch & 0x7))) != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.cursor--;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} s
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.eq_s = function(s)
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
if (this.limit - this.cursor < s.length) return false;
|
||||||
|
if (this.current.slice(this.cursor, this.cursor + s.length) != s)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.cursor += s.length;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} s
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.eq_s_b = function(s)
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
if (this.cursor - this.limit_backward < s.length) return false;
|
||||||
|
if (this.current.slice(this.cursor - s.length, this.cursor) != s)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.cursor -= s.length;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Among[]} v
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
this.find_among = function(v)
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
var i = 0;
|
||||||
|
var j = v.length;
|
||||||
|
|
||||||
|
var c = this.cursor;
|
||||||
|
var l = this.limit;
|
||||||
|
|
||||||
|
var common_i = 0;
|
||||||
|
var common_j = 0;
|
||||||
|
|
||||||
|
var first_key_inspected = false;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var k = i + ((j - i) >>> 1);
|
||||||
|
var diff = 0;
|
||||||
|
var common = common_i < common_j ? common_i : common_j; // smaller
|
||||||
|
// w[0]: string, w[1]: substring_i, w[2]: result, w[3]: function (optional)
|
||||||
|
var w = v[k];
|
||||||
|
var i2;
|
||||||
|
for (i2 = common; i2 < w[0].length; i2++)
|
||||||
|
{
|
||||||
|
if (c + common == l)
|
||||||
|
{
|
||||||
|
diff = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff = this.current.charCodeAt(c + common) - w[0].charCodeAt(i2);
|
||||||
|
if (diff != 0) break;
|
||||||
|
common++;
|
||||||
|
}
|
||||||
|
if (diff < 0)
|
||||||
|
{
|
||||||
|
j = k;
|
||||||
|
common_j = common;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = k;
|
||||||
|
common_i = common;
|
||||||
|
}
|
||||||
|
if (j - i <= 1)
|
||||||
|
{
|
||||||
|
if (i > 0) break; // v->s has been inspected
|
||||||
|
if (j == i) break; // only one item in v
|
||||||
|
|
||||||
|
// - but now we need to go round once more to get
|
||||||
|
// v->s inspected. This looks messy, but is actually
|
||||||
|
// the optimal approach.
|
||||||
|
|
||||||
|
if (first_key_inspected) break;
|
||||||
|
first_key_inspected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
var w = v[i];
|
||||||
|
if (common_i >= w[0].length)
|
||||||
|
{
|
||||||
|
this.cursor = c + w[0].length;
|
||||||
|
if (w.length < 4) return w[2];
|
||||||
|
var res = w[3](this);
|
||||||
|
this.cursor = c + w[0].length;
|
||||||
|
if (res) return w[2];
|
||||||
|
}
|
||||||
|
i = w[1];
|
||||||
|
} while (i >= 0);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// find_among_b is for backwards processing. Same comments apply
|
||||||
|
/**
|
||||||
|
* @param {Among[]} v
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
this.find_among_b = function(v)
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
var i = 0;
|
||||||
|
var j = v.length
|
||||||
|
|
||||||
|
var c = this.cursor;
|
||||||
|
var lb = this.limit_backward;
|
||||||
|
|
||||||
|
var common_i = 0;
|
||||||
|
var common_j = 0;
|
||||||
|
|
||||||
|
var first_key_inspected = false;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var k = i + ((j - i) >> 1);
|
||||||
|
var diff = 0;
|
||||||
|
var common = common_i < common_j ? common_i : common_j;
|
||||||
|
var w = v[k];
|
||||||
|
var i2;
|
||||||
|
for (i2 = w[0].length - 1 - common; i2 >= 0; i2--)
|
||||||
|
{
|
||||||
|
if (c - common == lb)
|
||||||
|
{
|
||||||
|
diff = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff = this.current.charCodeAt(c - 1 - common) - w[0].charCodeAt(i2);
|
||||||
|
if (diff != 0) break;
|
||||||
|
common++;
|
||||||
|
}
|
||||||
|
if (diff < 0)
|
||||||
|
{
|
||||||
|
j = k;
|
||||||
|
common_j = common;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = k;
|
||||||
|
common_i = common;
|
||||||
|
}
|
||||||
|
if (j - i <= 1)
|
||||||
|
{
|
||||||
|
if (i > 0) break;
|
||||||
|
if (j == i) break;
|
||||||
|
if (first_key_inspected) break;
|
||||||
|
first_key_inspected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
var w = v[i];
|
||||||
|
if (common_i >= w[0].length)
|
||||||
|
{
|
||||||
|
this.cursor = c - w[0].length;
|
||||||
|
if (w.length < 4) return w[2];
|
||||||
|
var res = w[3](this);
|
||||||
|
this.cursor = c - w[0].length;
|
||||||
|
if (res) return w[2];
|
||||||
|
}
|
||||||
|
i = w[1];
|
||||||
|
} while (i >= 0);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* to replace chars between c_bra and c_ket in this.current by the
|
||||||
|
* chars in s.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @param {number} c_bra
|
||||||
|
* @param {number} c_ket
|
||||||
|
* @param {string} s
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
this.replace_s = function(c_bra, c_ket, s)
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
var adjustment = s.length - (c_ket - c_bra);
|
||||||
|
this.current = this.current.slice(0, c_bra) + s + this.current.slice(c_ket);
|
||||||
|
this.limit += adjustment;
|
||||||
|
if (this.cursor >= c_ket) this.cursor += adjustment;
|
||||||
|
else if (this.cursor > c_bra) this.cursor = c_bra;
|
||||||
|
return adjustment;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.slice_check = function()
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
if (this.bra < 0 ||
|
||||||
|
this.bra > this.ket ||
|
||||||
|
this.ket > this.limit ||
|
||||||
|
this.limit > this.current.length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} c_bra
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.slice_from = function(s)
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
var result = false;
|
||||||
|
if (this.slice_check())
|
||||||
|
{
|
||||||
|
this.replace_s(this.bra, this.ket, s);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
this.slice_del = function()
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
return this.slice_from("");
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} c_bra
|
||||||
|
* @param {number} c_ket
|
||||||
|
* @param {string} s
|
||||||
|
*/
|
||||||
|
this.insert = function(c_bra, c_ket, s)
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
var adjustment = this.replace_s(c_bra, c_ket, s);
|
||||||
|
if (c_bra <= this.bra) this.bra += adjustment;
|
||||||
|
if (c_bra <= this.ket) this.ket += adjustment;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
this.slice_to = function()
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
var result = '';
|
||||||
|
if (this.slice_check())
|
||||||
|
{
|
||||||
|
result = this.current.slice(this.bra, this.ket);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
this.assign_to = function()
|
||||||
|
{
|
||||||
|
/** @protected */
|
||||||
|
return this.current.slice(0, this.limit);
|
||||||
|
};
|
||||||
|
};
|
||||||
906
build/html/_static/basic.css
Normal file
906
build/html/_static/basic.css
Normal file
|
|
@ -0,0 +1,906 @@
|
||||||
|
/*
|
||||||
|
* Sphinx stylesheet -- basic theme.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -- main layout ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.clearer {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.section::after {
|
||||||
|
display: block;
|
||||||
|
content: '';
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- relbar ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.related {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related h3 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0 10px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related li.right {
|
||||||
|
float: right;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- sidebar --------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper {
|
||||||
|
padding: 10px 5px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar {
|
||||||
|
float: left;
|
||||||
|
width: 230px;
|
||||||
|
margin-left: -100%;
|
||||||
|
font-size: 90%;
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow-wrap : break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul ul,
|
||||||
|
div.sphinxsidebar ul.want-points {
|
||||||
|
margin-left: 20px;
|
||||||
|
list-style: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul ul {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar form {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar input {
|
||||||
|
border: 1px solid #98dbcc;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox form.search {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox input[type="text"] {
|
||||||
|
float: left;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0.25em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
border-left: none;
|
||||||
|
padding: 0.25em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- search page ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
ul.search {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li {
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.search li p.context {
|
||||||
|
color: #888;
|
||||||
|
margin: 2px 0 0 30px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.keywordmatches li.goodmatch a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- index page ------------------------------------------------------------ */
|
||||||
|
|
||||||
|
table.contentstable {
|
||||||
|
width: 90%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.contentstable p.biglink {
|
||||||
|
line-height: 150%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.biglink {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.linkdescr {
|
||||||
|
font-style: italic;
|
||||||
|
padding-top: 5px;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- general index --------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.indextable {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable td {
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable ul {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable > tbody > tr > td > ul {
|
||||||
|
padding-left: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable tr.pcap {
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.indextable tr.cap {
|
||||||
|
margin-top: 10px;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.toggler {
|
||||||
|
margin-right: 3px;
|
||||||
|
margin-top: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.modindex-jumpbox {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.genindex-jumpbox {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- domain module index --------------------------------------------------- */
|
||||||
|
|
||||||
|
table.modindextable td {
|
||||||
|
padding: 2px;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- general body styles --------------------------------------------------- */
|
||||||
|
|
||||||
|
div.body {
|
||||||
|
min-width: inherit;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||||
|
-moz-hyphens: auto;
|
||||||
|
-ms-hyphens: auto;
|
||||||
|
-webkit-hyphens: auto;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.headerlink {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color: #551A8B;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1:hover > a.headerlink,
|
||||||
|
h2:hover > a.headerlink,
|
||||||
|
h3:hover > a.headerlink,
|
||||||
|
h4:hover > a.headerlink,
|
||||||
|
h5:hover > a.headerlink,
|
||||||
|
h6:hover > a.headerlink,
|
||||||
|
dt:hover > a.headerlink,
|
||||||
|
caption:hover > a.headerlink,
|
||||||
|
p.caption:hover > a.headerlink,
|
||||||
|
div.code-block-caption:hover > a.headerlink {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p.caption {
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.first {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.rubric {
|
||||||
|
margin-top: 30px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-left, figure.align-left, .figure.align-left, object.align-left {
|
||||||
|
clear: left;
|
||||||
|
float: left;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-right, figure.align-right, .figure.align-right, object.align-right {
|
||||||
|
clear: right;
|
||||||
|
float: right;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-center, figure.align-center, .figure.align-center, object.align-center {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.align-default, figure.align-default, .figure.align-default {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-default {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- sidebars -------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.sidebar,
|
||||||
|
aside.sidebar {
|
||||||
|
margin: 0 0 0.5em 1em;
|
||||||
|
border: 1px solid #ddb;
|
||||||
|
padding: 7px;
|
||||||
|
background-color: #ffe;
|
||||||
|
width: 40%;
|
||||||
|
float: right;
|
||||||
|
clear: right;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.sidebar-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.contents,
|
||||||
|
aside.topic,
|
||||||
|
div.admonition, div.topic, blockquote {
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- topics ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
nav.contents,
|
||||||
|
aside.topic,
|
||||||
|
div.topic {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 7px;
|
||||||
|
margin: 10px 0 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.topic-title {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- admonitions ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.admonition {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.admonition-title {
|
||||||
|
margin: 0px 10px 5px 0px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body p.centered {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- content of sidebars/topics/admonitions -------------------------------- */
|
||||||
|
|
||||||
|
div.sidebar > :last-child,
|
||||||
|
aside.sidebar > :last-child,
|
||||||
|
nav.contents > :last-child,
|
||||||
|
aside.topic > :last-child,
|
||||||
|
div.topic > :last-child,
|
||||||
|
div.admonition > :last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sidebar::after,
|
||||||
|
aside.sidebar::after,
|
||||||
|
nav.contents::after,
|
||||||
|
aside.topic::after,
|
||||||
|
div.topic::after,
|
||||||
|
div.admonition::after,
|
||||||
|
blockquote::after {
|
||||||
|
display: block;
|
||||||
|
content: '';
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- tables ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.docutils {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border: 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.align-center {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.align-default {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table caption span.caption-number {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
table caption span.caption-text {
|
||||||
|
}
|
||||||
|
|
||||||
|
table.docutils td, table.docutils th {
|
||||||
|
padding: 1px 8px 1px 5px;
|
||||||
|
border-top: 0;
|
||||||
|
border-left: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-bottom: 1px solid #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: left;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.citation {
|
||||||
|
border-left: solid 1px gray;
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.citation td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
th > :first-child,
|
||||||
|
td > :first-child {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th > :last-child,
|
||||||
|
td > :last-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- figures --------------------------------------------------------------- */
|
||||||
|
|
||||||
|
div.figure, figure {
|
||||||
|
margin: 0.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.figure p.caption, figcaption {
|
||||||
|
padding: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.figure p.caption span.caption-number,
|
||||||
|
figcaption span.caption-number {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.figure p.caption span.caption-text,
|
||||||
|
figcaption span.caption-text {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- field list styles ----------------------------------------------------- */
|
||||||
|
|
||||||
|
table.field-list td, table.field-list th {
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list ul {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-list p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-name {
|
||||||
|
-moz-hyphens: manual;
|
||||||
|
-ms-hyphens: manual;
|
||||||
|
-webkit-hyphens: manual;
|
||||||
|
hyphens: manual;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- hlist styles ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
table.hlist {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.hlist td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- object description styles --------------------------------------------- */
|
||||||
|
|
||||||
|
.sig {
|
||||||
|
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-name, code.descname {
|
||||||
|
background-color: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-name {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.descname {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-prename, code.descclassname {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.optional {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-paren {
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig-param.n {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* C++ specific styling */
|
||||||
|
|
||||||
|
.sig-inline.c-texpr,
|
||||||
|
.sig-inline.cpp-texpr {
|
||||||
|
font-family: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig.c .k, .sig.c .kt,
|
||||||
|
.sig.cpp .k, .sig.cpp .kt {
|
||||||
|
color: #0033B3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig.c .m,
|
||||||
|
.sig.cpp .m {
|
||||||
|
color: #1750EB;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig.c .s, .sig.c .sc,
|
||||||
|
.sig.cpp .s, .sig.cpp .sc {
|
||||||
|
color: #067D17;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -- other body styles ----------------------------------------------------- */
|
||||||
|
|
||||||
|
ol.arabic {
|
||||||
|
list-style: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.loweralpha {
|
||||||
|
list-style: lower-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.upperalpha {
|
||||||
|
list-style: upper-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.lowerroman {
|
||||||
|
list-style: lower-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.upperroman {
|
||||||
|
list-style: upper-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(li) > ol > li:first-child > :first-child,
|
||||||
|
:not(li) > ul > li:first-child > :first-child {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(li) > ol > li:last-child > :last-child,
|
||||||
|
:not(li) > ul > li:last-child > :last-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.simple ol p,
|
||||||
|
ol.simple ul p,
|
||||||
|
ul.simple ol p,
|
||||||
|
ul.simple ul p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.simple > li:not(:first-child) > p,
|
||||||
|
ul.simple > li:not(:first-child) > p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.simple p,
|
||||||
|
ul.simple p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside.footnote > span,
|
||||||
|
div.citation > span {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
aside.footnote > span:last-of-type,
|
||||||
|
div.citation > span:last-of-type {
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
aside.footnote > p {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
div.citation > p {
|
||||||
|
margin-left: 4em;
|
||||||
|
}
|
||||||
|
aside.footnote > p:last-of-type,
|
||||||
|
div.citation > p:last-of-type {
|
||||||
|
margin-bottom: 0em;
|
||||||
|
}
|
||||||
|
aside.footnote > p:last-of-type:after,
|
||||||
|
div.citation > p:last-of-type:after {
|
||||||
|
content: "";
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: fit-content(30%) auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list > dt {
|
||||||
|
font-weight: bold;
|
||||||
|
word-break: break-word;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.field-list > dd {
|
||||||
|
padding-left: 0.5em;
|
||||||
|
margin-top: 0em;
|
||||||
|
margin-left: 0em;
|
||||||
|
margin-bottom: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd > :first-child {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd ul, dd table {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-top: 3px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig dd {
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sig dl {
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl > dd:last-child,
|
||||||
|
dl > dd:last-child > :last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt:target, span.highlighted {
|
||||||
|
background-color: #fbe54e;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.highlighted {
|
||||||
|
fill: #fbe54e;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl.glossary dt {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.versionmodified {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-message {
|
||||||
|
background-color: #fda;
|
||||||
|
padding: 5px;
|
||||||
|
border: 3px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footnote:target {
|
||||||
|
background-color: #ffa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-block {
|
||||||
|
display: block;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-block .line-block {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-left: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guilabel, .menuselection {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accelerator {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.classifier {
|
||||||
|
font-style: oblique;
|
||||||
|
}
|
||||||
|
|
||||||
|
.classifier:before {
|
||||||
|
font-style: normal;
|
||||||
|
margin: 0 0.5em;
|
||||||
|
content: ":";
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr, acronym {
|
||||||
|
border-bottom: dotted 1px;
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- code displays --------------------------------------------------------- */
|
||||||
|
|
||||||
|
pre {
|
||||||
|
overflow: auto;
|
||||||
|
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||||
|
}
|
||||||
|
|
||||||
|
pre, div[class*="highlight-"] {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.pre {
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
div[class*="highlight-"] {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.linenos pre {
|
||||||
|
border: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable tbody {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable tr {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td.linenos {
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td.code {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .hll {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.highlight pre,
|
||||||
|
table.highlighttable pre {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption + div {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption {
|
||||||
|
margin-top: 1em;
|
||||||
|
padding: 2px 5px;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption code {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.highlighttable td.linenos,
|
||||||
|
span.linenos,
|
||||||
|
div.highlight span.gp { /* gp: Generic.Prompt */
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: text; /* Safari fallback only */
|
||||||
|
-webkit-user-select: none; /* Chrome/Safari */
|
||||||
|
-moz-user-select: none; /* Firefox */
|
||||||
|
-ms-user-select: none; /* IE10+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption span.caption-number {
|
||||||
|
padding: 0.1em 0.3em;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.code-block-caption span.caption-text {
|
||||||
|
}
|
||||||
|
|
||||||
|
div.literal-block-wrapper {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.xref, a code {
|
||||||
|
background-color: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-link {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-back {
|
||||||
|
float: right;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.viewcode-block:target {
|
||||||
|
margin: -1px -10px;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- math display ---------------------------------------------------------- */
|
||||||
|
|
||||||
|
img.math {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body div.math p {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.eqno {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.eqno a.headerlink {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.math:hover a.headerlink {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- printout stylesheet --------------------------------------------------- */
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
div.document,
|
||||||
|
div.documentwrapper,
|
||||||
|
div.bodywrapper {
|
||||||
|
margin: 0 !important;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar,
|
||||||
|
div.related,
|
||||||
|
div.footer,
|
||||||
|
#top-link {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
build/html/_static/custom.css
Normal file
1
build/html/_static/custom.css
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/* This file intentionally left blank. */
|
||||||
150
build/html/_static/doctools.js
Normal file
150
build/html/_static/doctools.js
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* Base JavaScript utilities for all Sphinx HTML documentation.
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
|
||||||
|
"TEXTAREA",
|
||||||
|
"INPUT",
|
||||||
|
"SELECT",
|
||||||
|
"BUTTON",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const _ready = (callback) => {
|
||||||
|
if (document.readyState !== "loading") {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("DOMContentLoaded", callback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small JavaScript module for the documentation.
|
||||||
|
*/
|
||||||
|
const Documentation = {
|
||||||
|
init: () => {
|
||||||
|
Documentation.initDomainIndexTable();
|
||||||
|
Documentation.initOnKeyListeners();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i18n support
|
||||||
|
*/
|
||||||
|
TRANSLATIONS: {},
|
||||||
|
PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
|
||||||
|
LOCALE: "unknown",
|
||||||
|
|
||||||
|
// gettext and ngettext don't access this so that the functions
|
||||||
|
// can safely bound to a different name (_ = Documentation.gettext)
|
||||||
|
gettext: (string) => {
|
||||||
|
const translated = Documentation.TRANSLATIONS[string];
|
||||||
|
switch (typeof translated) {
|
||||||
|
case "undefined":
|
||||||
|
return string; // no translation
|
||||||
|
case "string":
|
||||||
|
return translated; // translation exists
|
||||||
|
default:
|
||||||
|
return translated[0]; // (singular, plural) translation tuple exists
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ngettext: (singular, plural, n) => {
|
||||||
|
const translated = Documentation.TRANSLATIONS[singular];
|
||||||
|
if (typeof translated !== "undefined")
|
||||||
|
return translated[Documentation.PLURAL_EXPR(n)];
|
||||||
|
return n === 1 ? singular : plural;
|
||||||
|
},
|
||||||
|
|
||||||
|
addTranslations: (catalog) => {
|
||||||
|
Object.assign(Documentation.TRANSLATIONS, catalog.messages);
|
||||||
|
Documentation.PLURAL_EXPR = new Function(
|
||||||
|
"n",
|
||||||
|
`return (${catalog.plural_expr})`,
|
||||||
|
);
|
||||||
|
Documentation.LOCALE = catalog.locale;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to focus on search bar
|
||||||
|
*/
|
||||||
|
focusSearchBar: () => {
|
||||||
|
document.querySelectorAll("input[name=q]")[0]?.focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the domain index toggle buttons
|
||||||
|
*/
|
||||||
|
initDomainIndexTable: () => {
|
||||||
|
const toggler = (el) => {
|
||||||
|
const idNumber = el.id.substr(7);
|
||||||
|
const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
|
||||||
|
if (el.src.substr(-9) === "minus.png") {
|
||||||
|
el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
|
||||||
|
toggledRows.forEach((el) => (el.style.display = "none"));
|
||||||
|
} else {
|
||||||
|
el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
|
||||||
|
toggledRows.forEach((el) => (el.style.display = ""));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const togglerElements = document.querySelectorAll("img.toggler");
|
||||||
|
togglerElements.forEach((el) =>
|
||||||
|
el.addEventListener("click", (event) => toggler(event.currentTarget)),
|
||||||
|
);
|
||||||
|
togglerElements.forEach((el) => (el.style.display = ""));
|
||||||
|
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
|
||||||
|
},
|
||||||
|
|
||||||
|
initOnKeyListeners: () => {
|
||||||
|
// only install a listener if it is really needed
|
||||||
|
if (
|
||||||
|
!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS
|
||||||
|
&& !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (event) => {
|
||||||
|
// bail for input elements
|
||||||
|
if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName))
|
||||||
|
return;
|
||||||
|
// bail with special keys
|
||||||
|
if (event.altKey || event.ctrlKey || event.metaKey) return;
|
||||||
|
|
||||||
|
if (!event.shiftKey) {
|
||||||
|
switch (event.key) {
|
||||||
|
case "ArrowLeft":
|
||||||
|
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
||||||
|
|
||||||
|
const prevLink = document.querySelector('link[rel="prev"]');
|
||||||
|
if (prevLink && prevLink.href) {
|
||||||
|
window.location.href = prevLink.href;
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "ArrowRight":
|
||||||
|
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
||||||
|
|
||||||
|
const nextLink = document.querySelector('link[rel="next"]');
|
||||||
|
if (nextLink && nextLink.href) {
|
||||||
|
window.location.href = nextLink.href;
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// some keyboard layouts may need Shift to get /
|
||||||
|
switch (event.key) {
|
||||||
|
case "/":
|
||||||
|
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
|
||||||
|
Documentation.focusSearchBar();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// quick alias for translations
|
||||||
|
const _ = Documentation.gettext;
|
||||||
|
|
||||||
|
_ready(Documentation.init);
|
||||||
13
build/html/_static/documentation_options.js
Normal file
13
build/html/_static/documentation_options.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
const DOCUMENTATION_OPTIONS = {
|
||||||
|
VERSION: '',
|
||||||
|
LANGUAGE: 'en',
|
||||||
|
COLLAPSE_INDEX: false,
|
||||||
|
BUILDER: 'html',
|
||||||
|
FILE_SUFFIX: '.html',
|
||||||
|
LINK_SUFFIX: '.html',
|
||||||
|
HAS_SOURCE: true,
|
||||||
|
SOURCELINK_SUFFIX: '.txt',
|
||||||
|
NAVIGATION_WITH_KEYS: false,
|
||||||
|
SHOW_SEARCH_SUMMARY: true,
|
||||||
|
ENABLE_SEARCH_SHORTCUTS: true,
|
||||||
|
};
|
||||||
1066
build/html/_static/english-stemmer.js
Normal file
1066
build/html/_static/english-stemmer.js
Normal file
File diff suppressed because it is too large
Load diff
BIN
build/html/_static/file.png
Normal file
BIN
build/html/_static/file.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 286 B |
5
build/html/_static/github-banner.svg
Normal file
5
build/html/_static/github-banner.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 250 250" fill="#fff">
|
||||||
|
<path d="M0 0l115 115h15l12 27 108 108V0z" fill="#151513"/>
|
||||||
|
<path d="M128 109c-15-9-9-19-9-19 3-7 2-11 2-11-1-7 3-2 3-2 4 5 2 11 2 11-3 10 5 15 9 16"/>
|
||||||
|
<path d="M115 115s4 2 5 0l14-14c3-2 6-3 8-3-8-11-15-24 2-41 5-5 10-7 16-7 1-2 3-7 12-11 0 0 5 3 7 16 4 2 8 5 12 9s7 8 9 12c14 3 17 7 17 7-4 8-9 11-11 11 0 6-2 11-7 16-16 16-30 10-41 2 0 3-1 7-5 11l-12 11c-1 1 1 5 1 5z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 490 B |
13
build/html/_static/language_data.js
Normal file
13
build/html/_static/language_data.js
Normal file
File diff suppressed because one or more lines are too long
BIN
build/html/_static/minus.png
Normal file
BIN
build/html/_static/minus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 B |
BIN
build/html/_static/plus.png
Normal file
BIN
build/html/_static/plus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 B |
84
build/html/_static/pygments.css
Normal file
84
build/html/_static/pygments.css
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
pre { line-height: 125%; }
|
||||||
|
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||||
|
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||||
|
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||||
|
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||||
|
.highlight .hll { background-color: #ffffcc }
|
||||||
|
.highlight { background: #f8f8f8; }
|
||||||
|
.highlight .c { color: #8F5902; font-style: italic } /* Comment */
|
||||||
|
.highlight .err { color: #A40000; border: 1px solid #EF2929 } /* Error */
|
||||||
|
.highlight .g { color: #000 } /* Generic */
|
||||||
|
.highlight .k { color: #004461; font-weight: bold } /* Keyword */
|
||||||
|
.highlight .l { color: #000 } /* Literal */
|
||||||
|
.highlight .n { color: #000 } /* Name */
|
||||||
|
.highlight .o { color: #582800 } /* Operator */
|
||||||
|
.highlight .x { color: #000 } /* Other */
|
||||||
|
.highlight .p { color: #000; font-weight: bold } /* Punctuation */
|
||||||
|
.highlight .ch { color: #8F5902; font-style: italic } /* Comment.Hashbang */
|
||||||
|
.highlight .cm { color: #8F5902; font-style: italic } /* Comment.Multiline */
|
||||||
|
.highlight .cp { color: #8F5902 } /* Comment.Preproc */
|
||||||
|
.highlight .cpf { color: #8F5902; font-style: italic } /* Comment.PreprocFile */
|
||||||
|
.highlight .c1 { color: #8F5902; font-style: italic } /* Comment.Single */
|
||||||
|
.highlight .cs { color: #8F5902; font-style: italic } /* Comment.Special */
|
||||||
|
.highlight .gd { color: #A40000 } /* Generic.Deleted */
|
||||||
|
.highlight .ge { color: #000; font-style: italic } /* Generic.Emph */
|
||||||
|
.highlight .ges { color: #000 } /* Generic.EmphStrong */
|
||||||
|
.highlight .gr { color: #EF2929 } /* Generic.Error */
|
||||||
|
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||||
|
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||||
|
.highlight .go { color: #888 } /* Generic.Output */
|
||||||
|
.highlight .gp { color: #745334 } /* Generic.Prompt */
|
||||||
|
.highlight .gs { color: #000; font-weight: bold } /* Generic.Strong */
|
||||||
|
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||||
|
.highlight .gt { color: #A40000; font-weight: bold } /* Generic.Traceback */
|
||||||
|
.highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */
|
||||||
|
.highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */
|
||||||
|
.highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */
|
||||||
|
.highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */
|
||||||
|
.highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */
|
||||||
|
.highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */
|
||||||
|
.highlight .ld { color: #000 } /* Literal.Date */
|
||||||
|
.highlight .m { color: #900 } /* Literal.Number */
|
||||||
|
.highlight .s { color: #4E9A06 } /* Literal.String */
|
||||||
|
.highlight .na { color: #C4A000 } /* Name.Attribute */
|
||||||
|
.highlight .nb { color: #004461 } /* Name.Builtin */
|
||||||
|
.highlight .nc { color: #000 } /* Name.Class */
|
||||||
|
.highlight .no { color: #000 } /* Name.Constant */
|
||||||
|
.highlight .nd { color: #888 } /* Name.Decorator */
|
||||||
|
.highlight .ni { color: #CE5C00 } /* Name.Entity */
|
||||||
|
.highlight .ne { color: #C00; font-weight: bold } /* Name.Exception */
|
||||||
|
.highlight .nf { color: #000 } /* Name.Function */
|
||||||
|
.highlight .nl { color: #F57900 } /* Name.Label */
|
||||||
|
.highlight .nn { color: #000 } /* Name.Namespace */
|
||||||
|
.highlight .nx { color: #000 } /* Name.Other */
|
||||||
|
.highlight .py { color: #000 } /* Name.Property */
|
||||||
|
.highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */
|
||||||
|
.highlight .nv { color: #000 } /* Name.Variable */
|
||||||
|
.highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */
|
||||||
|
.highlight .pm { color: #000; font-weight: bold } /* Punctuation.Marker */
|
||||||
|
.highlight .w { color: #F8F8F8 } /* Text.Whitespace */
|
||||||
|
.highlight .mb { color: #900 } /* Literal.Number.Bin */
|
||||||
|
.highlight .mf { color: #900 } /* Literal.Number.Float */
|
||||||
|
.highlight .mh { color: #900 } /* Literal.Number.Hex */
|
||||||
|
.highlight .mi { color: #900 } /* Literal.Number.Integer */
|
||||||
|
.highlight .mo { color: #900 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sa { color: #4E9A06 } /* Literal.String.Affix */
|
||||||
|
.highlight .sb { color: #4E9A06 } /* Literal.String.Backtick */
|
||||||
|
.highlight .sc { color: #4E9A06 } /* Literal.String.Char */
|
||||||
|
.highlight .dl { color: #4E9A06 } /* Literal.String.Delimiter */
|
||||||
|
.highlight .sd { color: #8F5902; font-style: italic } /* Literal.String.Doc */
|
||||||
|
.highlight .s2 { color: #4E9A06 } /* Literal.String.Double */
|
||||||
|
.highlight .se { color: #4E9A06 } /* Literal.String.Escape */
|
||||||
|
.highlight .sh { color: #4E9A06 } /* Literal.String.Heredoc */
|
||||||
|
.highlight .si { color: #4E9A06 } /* Literal.String.Interpol */
|
||||||
|
.highlight .sx { color: #4E9A06 } /* Literal.String.Other */
|
||||||
|
.highlight .sr { color: #4E9A06 } /* Literal.String.Regex */
|
||||||
|
.highlight .s1 { color: #4E9A06 } /* Literal.String.Single */
|
||||||
|
.highlight .ss { color: #4E9A06 } /* Literal.String.Symbol */
|
||||||
|
.highlight .bp { color: #3465A4 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .fm { color: #000 } /* Name.Function.Magic */
|
||||||
|
.highlight .vc { color: #000 } /* Name.Variable.Class */
|
||||||
|
.highlight .vg { color: #000 } /* Name.Variable.Global */
|
||||||
|
.highlight .vi { color: #000 } /* Name.Variable.Instance */
|
||||||
|
.highlight .vm { color: #000 } /* Name.Variable.Magic */
|
||||||
|
.highlight .il { color: #900 } /* Literal.Number.Integer.Long */
|
||||||
693
build/html/_static/searchtools.js
Normal file
693
build/html/_static/searchtools.js
Normal file
|
|
@ -0,0 +1,693 @@
|
||||||
|
/*
|
||||||
|
* Sphinx JavaScript utilities for the full-text search.
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple result scoring code.
|
||||||
|
*/
|
||||||
|
if (typeof Scorer === "undefined") {
|
||||||
|
var Scorer = {
|
||||||
|
// Implement the following function to further tweak the score for each result
|
||||||
|
// The function takes a result array [docname, title, anchor, descr, score, filename]
|
||||||
|
// and returns the new score.
|
||||||
|
/*
|
||||||
|
score: result => {
|
||||||
|
const [docname, title, anchor, descr, score, filename, kind] = result
|
||||||
|
return score
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
// query matches the full name of an object
|
||||||
|
objNameMatch: 11,
|
||||||
|
// or matches in the last dotted part of the object name
|
||||||
|
objPartialMatch: 6,
|
||||||
|
// Additive scores depending on the priority of the object
|
||||||
|
objPrio: {
|
||||||
|
0: 15, // used to be importantResults
|
||||||
|
1: 5, // used to be objectResults
|
||||||
|
2: -5, // used to be unimportantResults
|
||||||
|
},
|
||||||
|
// Used when the priority is not in the mapping.
|
||||||
|
objPrioDefault: 0,
|
||||||
|
|
||||||
|
// query found in title
|
||||||
|
title: 15,
|
||||||
|
partialTitle: 7,
|
||||||
|
// query found in terms
|
||||||
|
term: 5,
|
||||||
|
partialTerm: 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global search result kind enum, used by themes to style search results.
|
||||||
|
// prettier-ignore
|
||||||
|
class SearchResultKind {
|
||||||
|
static get index() { return "index"; }
|
||||||
|
static get object() { return "object"; }
|
||||||
|
static get text() { return "text"; }
|
||||||
|
static get title() { return "title"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
const _removeChildren = (element) => {
|
||||||
|
while (element && element.lastChild) element.removeChild(element.lastChild);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
||||||
|
*/
|
||||||
|
const _escapeRegExp = (string) =>
|
||||||
|
string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
|
||||||
|
|
||||||
|
const _escapeHTML = (text) => {
|
||||||
|
return text
|
||||||
|
.replaceAll("&", "&")
|
||||||
|
.replaceAll("<", "<")
|
||||||
|
.replaceAll(">", ">")
|
||||||
|
.replaceAll('"', """)
|
||||||
|
.replaceAll("'", "'");
|
||||||
|
};
|
||||||
|
|
||||||
|
const _displayItem = (item, searchTerms, highlightTerms) => {
|
||||||
|
const docBuilder = DOCUMENTATION_OPTIONS.BUILDER;
|
||||||
|
const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX;
|
||||||
|
const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX;
|
||||||
|
const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY;
|
||||||
|
const contentRoot = document.documentElement.dataset.content_root;
|
||||||
|
|
||||||
|
const [docName, title, anchor, descr, score, _filename, kind] = item;
|
||||||
|
|
||||||
|
let listItem = document.createElement("li");
|
||||||
|
// Add a class representing the item's type:
|
||||||
|
// can be used by a theme's CSS selector for styling
|
||||||
|
// See SearchResultKind for the class names.
|
||||||
|
listItem.classList.add(`kind-${kind}`);
|
||||||
|
let requestUrl;
|
||||||
|
let linkUrl;
|
||||||
|
if (docBuilder === "dirhtml") {
|
||||||
|
// dirhtml builder
|
||||||
|
let dirname = docName + "/";
|
||||||
|
if (dirname.match(/\/index\/$/))
|
||||||
|
dirname = dirname.substring(0, dirname.length - 6);
|
||||||
|
else if (dirname === "index/") dirname = "";
|
||||||
|
requestUrl = contentRoot + dirname;
|
||||||
|
linkUrl = requestUrl;
|
||||||
|
} else {
|
||||||
|
// normal html builders
|
||||||
|
requestUrl = contentRoot + docName + docFileSuffix;
|
||||||
|
linkUrl = docName + docLinkSuffix;
|
||||||
|
}
|
||||||
|
let linkEl = listItem.appendChild(document.createElement("a"));
|
||||||
|
linkEl.href = linkUrl + anchor;
|
||||||
|
linkEl.dataset.score = score;
|
||||||
|
linkEl.innerHTML = _escapeHTML(title);
|
||||||
|
if (descr) {
|
||||||
|
listItem.appendChild(document.createElement("span")).innerHTML =
|
||||||
|
` (${_escapeHTML(descr)})`;
|
||||||
|
// highlight search terms in the description
|
||||||
|
if (SPHINX_HIGHLIGHT_ENABLED)
|
||||||
|
// SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js
|
||||||
|
highlightTerms.forEach((term) =>
|
||||||
|
_highlightText(listItem, term, "highlighted"),
|
||||||
|
);
|
||||||
|
} else if (showSearchSummary)
|
||||||
|
fetch(requestUrl)
|
||||||
|
.then((responseData) => responseData.text())
|
||||||
|
.then((data) => {
|
||||||
|
if (data)
|
||||||
|
listItem.appendChild(
|
||||||
|
Search.makeSearchSummary(data, searchTerms, anchor),
|
||||||
|
);
|
||||||
|
// highlight search terms in the summary
|
||||||
|
if (SPHINX_HIGHLIGHT_ENABLED)
|
||||||
|
// SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js
|
||||||
|
highlightTerms.forEach((term) =>
|
||||||
|
_highlightText(listItem, term, "highlighted"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
Search.output.appendChild(listItem);
|
||||||
|
};
|
||||||
|
const _finishSearch = (resultCount) => {
|
||||||
|
Search.stopPulse();
|
||||||
|
Search.title.innerText = _("Search Results");
|
||||||
|
if (!resultCount)
|
||||||
|
Search.status.innerText = Documentation.gettext(
|
||||||
|
"Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.",
|
||||||
|
);
|
||||||
|
else
|
||||||
|
Search.status.innerText = Documentation.ngettext(
|
||||||
|
"Search finished, found one page matching the search query.",
|
||||||
|
"Search finished, found ${resultCount} pages matching the search query.",
|
||||||
|
resultCount,
|
||||||
|
).replace("${resultCount}", resultCount);
|
||||||
|
};
|
||||||
|
const _displayNextItem = (
|
||||||
|
results,
|
||||||
|
resultCount,
|
||||||
|
searchTerms,
|
||||||
|
highlightTerms,
|
||||||
|
) => {
|
||||||
|
// results left, load the summary and display it
|
||||||
|
// this is intended to be dynamic (don't sub resultsCount)
|
||||||
|
if (results.length) {
|
||||||
|
_displayItem(results.pop(), searchTerms, highlightTerms);
|
||||||
|
setTimeout(
|
||||||
|
() => _displayNextItem(results, resultCount, searchTerms, highlightTerms),
|
||||||
|
5,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// search finished, update title and status message
|
||||||
|
else _finishSearch(resultCount);
|
||||||
|
};
|
||||||
|
// Helper function used by query() to order search results.
|
||||||
|
// Each input is an array of [docname, title, anchor, descr, score, filename, kind].
|
||||||
|
// Order the results by score (in opposite order of appearance, since the
|
||||||
|
// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically.
|
||||||
|
const _orderResultsByScoreThenName = (a, b) => {
|
||||||
|
const leftScore = a[4];
|
||||||
|
const rightScore = b[4];
|
||||||
|
if (leftScore === rightScore) {
|
||||||
|
// same score: sort alphabetically
|
||||||
|
const leftTitle = a[1].toLowerCase();
|
||||||
|
const rightTitle = b[1].toLowerCase();
|
||||||
|
if (leftTitle === rightTitle) return 0;
|
||||||
|
return leftTitle > rightTitle ? -1 : 1; // inverted is intentional
|
||||||
|
}
|
||||||
|
return leftScore > rightScore ? 1 : -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default splitQuery function. Can be overridden in ``sphinx.search`` with a
|
||||||
|
* custom function per language.
|
||||||
|
*
|
||||||
|
* The regular expression works by splitting the string on consecutive characters
|
||||||
|
* that are not Unicode letters, numbers, underscores, or emoji characters.
|
||||||
|
* This is the same as ``\W+`` in Python, preserving the surrogate pair area.
|
||||||
|
*/
|
||||||
|
if (typeof splitQuery === "undefined") {
|
||||||
|
var splitQuery = (query) =>
|
||||||
|
query
|
||||||
|
.split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu)
|
||||||
|
.filter((term) => term); // remove remaining empty strings
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search Module
|
||||||
|
*/
|
||||||
|
const Search = {
|
||||||
|
_index: null,
|
||||||
|
_queued_query: null,
|
||||||
|
_pulse_status: -1,
|
||||||
|
|
||||||
|
htmlToText: (htmlString, anchor) => {
|
||||||
|
const htmlElement = new DOMParser().parseFromString(
|
||||||
|
htmlString,
|
||||||
|
"text/html",
|
||||||
|
);
|
||||||
|
for (const removalQuery of [".headerlink", "script", "style"]) {
|
||||||
|
htmlElement.querySelectorAll(removalQuery).forEach((el) => {
|
||||||
|
el.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (anchor) {
|
||||||
|
const anchorContent = htmlElement.querySelector(
|
||||||
|
`[role="main"] ${anchor}`,
|
||||||
|
);
|
||||||
|
if (anchorContent) return anchorContent.textContent;
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
`Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if anchor not specified or not found, fall back to main content
|
||||||
|
const docContent = htmlElement.querySelector('[role="main"]');
|
||||||
|
if (docContent) return docContent.textContent;
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
"Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template.",
|
||||||
|
);
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
|
||||||
|
init: () => {
|
||||||
|
const query = new URLSearchParams(window.location.search).get("q");
|
||||||
|
document
|
||||||
|
.querySelectorAll('input[name="q"]')
|
||||||
|
.forEach((el) => (el.value = query));
|
||||||
|
if (query) Search.performSearch(query);
|
||||||
|
},
|
||||||
|
|
||||||
|
loadIndex: (url) =>
|
||||||
|
(document.body.appendChild(document.createElement("script")).src = url),
|
||||||
|
|
||||||
|
setIndex: (index) => {
|
||||||
|
Search._index = index;
|
||||||
|
if (Search._queued_query !== null) {
|
||||||
|
const query = Search._queued_query;
|
||||||
|
Search._queued_query = null;
|
||||||
|
Search.query(query);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
hasIndex: () => Search._index !== null,
|
||||||
|
|
||||||
|
deferQuery: (query) => (Search._queued_query = query),
|
||||||
|
|
||||||
|
stopPulse: () => (Search._pulse_status = -1),
|
||||||
|
|
||||||
|
startPulse: () => {
|
||||||
|
if (Search._pulse_status >= 0) return;
|
||||||
|
|
||||||
|
const pulse = () => {
|
||||||
|
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
||||||
|
Search.dots.innerText = ".".repeat(Search._pulse_status);
|
||||||
|
if (Search._pulse_status >= 0) window.setTimeout(pulse, 500);
|
||||||
|
};
|
||||||
|
pulse();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* perform a search for something (or wait until index is loaded)
|
||||||
|
*/
|
||||||
|
performSearch: (query) => {
|
||||||
|
// create the required interface elements
|
||||||
|
const searchText = document.createElement("h2");
|
||||||
|
searchText.textContent = _("Searching");
|
||||||
|
const searchSummary = document.createElement("p");
|
||||||
|
searchSummary.classList.add("search-summary");
|
||||||
|
searchSummary.innerText = "";
|
||||||
|
const searchList = document.createElement("ul");
|
||||||
|
searchList.setAttribute("role", "list");
|
||||||
|
searchList.classList.add("search");
|
||||||
|
|
||||||
|
const out = document.getElementById("search-results");
|
||||||
|
Search.title = out.appendChild(searchText);
|
||||||
|
Search.dots = Search.title.appendChild(document.createElement("span"));
|
||||||
|
Search.status = out.appendChild(searchSummary);
|
||||||
|
Search.output = out.appendChild(searchList);
|
||||||
|
|
||||||
|
const searchProgress = document.getElementById("search-progress");
|
||||||
|
// Some themes don't use the search progress node
|
||||||
|
if (searchProgress) {
|
||||||
|
searchProgress.innerText = _("Preparing search...");
|
||||||
|
}
|
||||||
|
Search.startPulse();
|
||||||
|
|
||||||
|
// index already loaded, the browser was quick!
|
||||||
|
if (Search.hasIndex()) Search.query(query);
|
||||||
|
else Search.deferQuery(query);
|
||||||
|
},
|
||||||
|
|
||||||
|
_parseQuery: (query) => {
|
||||||
|
// stem the search terms and add them to the correct list
|
||||||
|
const stemmer = new Stemmer();
|
||||||
|
const searchTerms = new Set();
|
||||||
|
const excludedTerms = new Set();
|
||||||
|
const highlightTerms = new Set();
|
||||||
|
const objectTerms = new Set(splitQuery(query.toLowerCase().trim()));
|
||||||
|
splitQuery(query.trim()).forEach((queryTerm) => {
|
||||||
|
const queryTermLower = queryTerm.toLowerCase();
|
||||||
|
|
||||||
|
// maybe skip this "word"
|
||||||
|
// stopwords set is from language_data.js
|
||||||
|
if (stopwords.has(queryTermLower) || queryTerm.match(/^\d+$/)) return;
|
||||||
|
|
||||||
|
// stem the word
|
||||||
|
let word = stemmer.stemWord(queryTermLower);
|
||||||
|
// select the correct list
|
||||||
|
if (word[0] === "-") excludedTerms.add(word.substr(1));
|
||||||
|
else {
|
||||||
|
searchTerms.add(word);
|
||||||
|
highlightTerms.add(queryTermLower);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (SPHINX_HIGHLIGHT_ENABLED) {
|
||||||
|
// SPHINX_HIGHLIGHT_ENABLED is set in sphinx_highlight.js
|
||||||
|
localStorage.setItem(
|
||||||
|
"sphinx_highlight_terms",
|
||||||
|
[...highlightTerms].join(" "),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.debug("SEARCH: searching for:");
|
||||||
|
// console.info("required: ", [...searchTerms]);
|
||||||
|
// console.info("excluded: ", [...excludedTerms]);
|
||||||
|
|
||||||
|
return [query, searchTerms, excludedTerms, highlightTerms, objectTerms];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* execute search (requires search index to be loaded)
|
||||||
|
*/
|
||||||
|
_performSearch: (
|
||||||
|
query,
|
||||||
|
searchTerms,
|
||||||
|
excludedTerms,
|
||||||
|
highlightTerms,
|
||||||
|
objectTerms,
|
||||||
|
) => {
|
||||||
|
const filenames = Search._index.filenames;
|
||||||
|
const docNames = Search._index.docnames;
|
||||||
|
const titles = Search._index.titles;
|
||||||
|
const allTitles = Search._index.alltitles;
|
||||||
|
const indexEntries = Search._index.indexentries;
|
||||||
|
|
||||||
|
// Collect multiple result groups to be sorted separately and then ordered.
|
||||||
|
// Each is an array of [docname, title, anchor, descr, score, filename, kind].
|
||||||
|
const normalResults = [];
|
||||||
|
const nonMainIndexResults = [];
|
||||||
|
|
||||||
|
_removeChildren(document.getElementById("search-progress"));
|
||||||
|
|
||||||
|
const queryLower = query.toLowerCase().trim();
|
||||||
|
for (const [title, foundTitles] of Object.entries(allTitles)) {
|
||||||
|
if (
|
||||||
|
title.toLowerCase().trim().includes(queryLower)
|
||||||
|
&& queryLower.length >= title.length / 2
|
||||||
|
) {
|
||||||
|
for (const [file, id] of foundTitles) {
|
||||||
|
const score = Math.round(
|
||||||
|
(Scorer.title * queryLower.length) / title.length,
|
||||||
|
);
|
||||||
|
const boost = titles[file] === title ? 1 : 0; // add a boost for document titles
|
||||||
|
normalResults.push([
|
||||||
|
docNames[file],
|
||||||
|
titles[file] !== title ? `${titles[file]} > ${title}` : title,
|
||||||
|
id !== null ? "#" + id : "",
|
||||||
|
null,
|
||||||
|
score + boost,
|
||||||
|
filenames[file],
|
||||||
|
SearchResultKind.title,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// search for explicit entries in index directives
|
||||||
|
for (const [entry, foundEntries] of Object.entries(indexEntries)) {
|
||||||
|
if (entry.includes(queryLower) && queryLower.length >= entry.length / 2) {
|
||||||
|
for (const [file, id, isMain] of foundEntries) {
|
||||||
|
const score = Math.round((100 * queryLower.length) / entry.length);
|
||||||
|
const result = [
|
||||||
|
docNames[file],
|
||||||
|
titles[file],
|
||||||
|
id ? "#" + id : "",
|
||||||
|
null,
|
||||||
|
score,
|
||||||
|
filenames[file],
|
||||||
|
SearchResultKind.index,
|
||||||
|
];
|
||||||
|
if (isMain) {
|
||||||
|
normalResults.push(result);
|
||||||
|
} else {
|
||||||
|
nonMainIndexResults.push(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookup as object
|
||||||
|
objectTerms.forEach((term) =>
|
||||||
|
normalResults.push(...Search.performObjectSearch(term, objectTerms)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// lookup as search terms in fulltext
|
||||||
|
normalResults.push(
|
||||||
|
...Search.performTermsSearch(searchTerms, excludedTerms),
|
||||||
|
);
|
||||||
|
|
||||||
|
// let the scorer override scores with a custom scoring function
|
||||||
|
if (Scorer.score) {
|
||||||
|
normalResults.forEach((item) => (item[4] = Scorer.score(item)));
|
||||||
|
nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort each group of results by score and then alphabetically by name.
|
||||||
|
normalResults.sort(_orderResultsByScoreThenName);
|
||||||
|
nonMainIndexResults.sort(_orderResultsByScoreThenName);
|
||||||
|
|
||||||
|
// Combine the result groups in (reverse) order.
|
||||||
|
// Non-main index entries are typically arbitrary cross-references,
|
||||||
|
// so display them after other results.
|
||||||
|
let results = [...nonMainIndexResults, ...normalResults];
|
||||||
|
|
||||||
|
// remove duplicate search results
|
||||||
|
// note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept
|
||||||
|
let seen = new Set();
|
||||||
|
results = results.reverse().reduce((acc, result) => {
|
||||||
|
let resultStr = result
|
||||||
|
.slice(0, 4)
|
||||||
|
.concat([result[5]])
|
||||||
|
.map((v) => String(v))
|
||||||
|
.join(",");
|
||||||
|
if (!seen.has(resultStr)) {
|
||||||
|
acc.push(result);
|
||||||
|
seen.add(resultStr);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return results.reverse();
|
||||||
|
},
|
||||||
|
|
||||||
|
query: (query) => {
|
||||||
|
const [
|
||||||
|
searchQuery,
|
||||||
|
searchTerms,
|
||||||
|
excludedTerms,
|
||||||
|
highlightTerms,
|
||||||
|
objectTerms,
|
||||||
|
] = Search._parseQuery(query);
|
||||||
|
const results = Search._performSearch(
|
||||||
|
searchQuery,
|
||||||
|
searchTerms,
|
||||||
|
excludedTerms,
|
||||||
|
highlightTerms,
|
||||||
|
objectTerms,
|
||||||
|
);
|
||||||
|
|
||||||
|
// for debugging
|
||||||
|
//Search.lastresults = results.slice(); // a copy
|
||||||
|
// console.info("search results:", Search.lastresults);
|
||||||
|
|
||||||
|
// print the results
|
||||||
|
_displayNextItem(results, results.length, searchTerms, highlightTerms);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search for object names
|
||||||
|
*/
|
||||||
|
performObjectSearch: (object, objectTerms) => {
|
||||||
|
const filenames = Search._index.filenames;
|
||||||
|
const docNames = Search._index.docnames;
|
||||||
|
const objects = Search._index.objects;
|
||||||
|
const objNames = Search._index.objnames;
|
||||||
|
const titles = Search._index.titles;
|
||||||
|
|
||||||
|
const results = [];
|
||||||
|
|
||||||
|
const objectSearchCallback = (prefix, match) => {
|
||||||
|
const name = match[4];
|
||||||
|
const fullname = (prefix ? prefix + "." : "") + name;
|
||||||
|
const fullnameLower = fullname.toLowerCase();
|
||||||
|
if (fullnameLower.indexOf(object) < 0) return;
|
||||||
|
|
||||||
|
let score = 0;
|
||||||
|
const parts = fullnameLower.split(".");
|
||||||
|
|
||||||
|
// check for different match types: exact matches of full name or
|
||||||
|
// "last name" (i.e. last dotted part)
|
||||||
|
if (fullnameLower === object || parts.slice(-1)[0] === object)
|
||||||
|
score += Scorer.objNameMatch;
|
||||||
|
else if (parts.slice(-1)[0].indexOf(object) > -1)
|
||||||
|
score += Scorer.objPartialMatch; // matches in last name
|
||||||
|
|
||||||
|
const objName = objNames[match[1]][2];
|
||||||
|
const title = titles[match[0]];
|
||||||
|
|
||||||
|
// If more than one term searched for, we require other words to be
|
||||||
|
// found in the name/title/description
|
||||||
|
const otherTerms = new Set(objectTerms);
|
||||||
|
otherTerms.delete(object);
|
||||||
|
if (otherTerms.size > 0) {
|
||||||
|
const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase();
|
||||||
|
if (
|
||||||
|
[...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let anchor = match[3];
|
||||||
|
if (anchor === "") anchor = fullname;
|
||||||
|
else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname;
|
||||||
|
|
||||||
|
const descr = objName + _(", in ") + title;
|
||||||
|
|
||||||
|
// add custom score for some objects according to scorer
|
||||||
|
if (Scorer.objPrio.hasOwnProperty(match[2]))
|
||||||
|
score += Scorer.objPrio[match[2]];
|
||||||
|
else score += Scorer.objPrioDefault;
|
||||||
|
|
||||||
|
results.push([
|
||||||
|
docNames[match[0]],
|
||||||
|
fullname,
|
||||||
|
"#" + anchor,
|
||||||
|
descr,
|
||||||
|
score,
|
||||||
|
filenames[match[0]],
|
||||||
|
SearchResultKind.object,
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
Object.keys(objects).forEach((prefix) =>
|
||||||
|
objects[prefix].forEach((array) => objectSearchCallback(prefix, array)),
|
||||||
|
);
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search for full-text terms in the index
|
||||||
|
*/
|
||||||
|
performTermsSearch: (searchTerms, excludedTerms) => {
|
||||||
|
// prepare search
|
||||||
|
const terms = Search._index.terms;
|
||||||
|
const titleTerms = Search._index.titleterms;
|
||||||
|
const filenames = Search._index.filenames;
|
||||||
|
const docNames = Search._index.docnames;
|
||||||
|
const titles = Search._index.titles;
|
||||||
|
|
||||||
|
const scoreMap = new Map();
|
||||||
|
const fileMap = new Map();
|
||||||
|
|
||||||
|
// perform the search on the required terms
|
||||||
|
searchTerms.forEach((word) => {
|
||||||
|
const files = [];
|
||||||
|
// find documents, if any, containing the query word in their text/title term indices
|
||||||
|
// use Object.hasOwnProperty to avoid mismatching against prototype properties
|
||||||
|
const arr = [
|
||||||
|
{
|
||||||
|
files: terms.hasOwnProperty(word) ? terms[word] : undefined,
|
||||||
|
score: Scorer.term,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: titleTerms.hasOwnProperty(word) ? titleTerms[word] : undefined,
|
||||||
|
score: Scorer.title,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
// add support for partial matches
|
||||||
|
if (word.length > 2) {
|
||||||
|
const escapedWord = _escapeRegExp(word);
|
||||||
|
if (!terms.hasOwnProperty(word)) {
|
||||||
|
Object.keys(terms).forEach((term) => {
|
||||||
|
if (term.match(escapedWord))
|
||||||
|
arr.push({ files: terms[term], score: Scorer.partialTerm });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!titleTerms.hasOwnProperty(word)) {
|
||||||
|
Object.keys(titleTerms).forEach((term) => {
|
||||||
|
if (term.match(escapedWord))
|
||||||
|
arr.push({ files: titleTerms[term], score: Scorer.partialTitle });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no match but word was a required one
|
||||||
|
if (arr.every((record) => record.files === undefined)) return;
|
||||||
|
|
||||||
|
// found search word in contents
|
||||||
|
arr.forEach((record) => {
|
||||||
|
if (record.files === undefined) return;
|
||||||
|
|
||||||
|
let recordFiles = record.files;
|
||||||
|
if (recordFiles.length === undefined) recordFiles = [recordFiles];
|
||||||
|
files.push(...recordFiles);
|
||||||
|
|
||||||
|
// set score for the word in each file
|
||||||
|
recordFiles.forEach((file) => {
|
||||||
|
if (!scoreMap.has(file)) scoreMap.set(file, new Map());
|
||||||
|
const fileScores = scoreMap.get(file);
|
||||||
|
fileScores.set(word, record.score);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// create the mapping
|
||||||
|
files.forEach((file) => {
|
||||||
|
if (!fileMap.has(file)) fileMap.set(file, [word]);
|
||||||
|
else if (fileMap.get(file).indexOf(word) === -1)
|
||||||
|
fileMap.get(file).push(word);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// now check if the files don't contain excluded terms
|
||||||
|
const results = [];
|
||||||
|
for (const [file, wordList] of fileMap) {
|
||||||
|
// check if all requirements are matched
|
||||||
|
|
||||||
|
// as search terms with length < 3 are discarded
|
||||||
|
const filteredTermCount = [...searchTerms].filter(
|
||||||
|
(term) => term.length > 2,
|
||||||
|
).length;
|
||||||
|
if (
|
||||||
|
wordList.length !== searchTerms.size
|
||||||
|
&& wordList.length !== filteredTermCount
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// ensure that none of the excluded terms is in the search result
|
||||||
|
if (
|
||||||
|
[...excludedTerms].some(
|
||||||
|
(term) =>
|
||||||
|
terms[term] === file
|
||||||
|
|| titleTerms[term] === file
|
||||||
|
|| (terms[term] || []).includes(file)
|
||||||
|
|| (titleTerms[term] || []).includes(file),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// select one (max) score for the file.
|
||||||
|
const score = Math.max(...wordList.map((w) => scoreMap.get(file).get(w)));
|
||||||
|
// add result to the result list
|
||||||
|
results.push([
|
||||||
|
docNames[file],
|
||||||
|
titles[file],
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
score,
|
||||||
|
filenames[file],
|
||||||
|
SearchResultKind.text,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to return a node containing the
|
||||||
|
* search summary for a given text. keywords is a list
|
||||||
|
* of stemmed words.
|
||||||
|
*/
|
||||||
|
makeSearchSummary: (htmlText, keywords, anchor) => {
|
||||||
|
const text = Search.htmlToText(htmlText, anchor);
|
||||||
|
if (text === "") return null;
|
||||||
|
|
||||||
|
const textLower = text.toLowerCase();
|
||||||
|
const actualStartPosition = [...keywords]
|
||||||
|
.map((k) => textLower.indexOf(k.toLowerCase()))
|
||||||
|
.filter((i) => i > -1)
|
||||||
|
.slice(-1)[0];
|
||||||
|
const startWithContext = Math.max(actualStartPosition - 120, 0);
|
||||||
|
|
||||||
|
const top = startWithContext === 0 ? "" : "...";
|
||||||
|
const tail = startWithContext + 240 < text.length ? "..." : "";
|
||||||
|
|
||||||
|
let summary = document.createElement("p");
|
||||||
|
summary.classList.add("context");
|
||||||
|
summary.textContent =
|
||||||
|
top + text.substr(startWithContext, 240).trim() + tail;
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
_ready(Search.init);
|
||||||
159
build/html/_static/sphinx_highlight.js
Normal file
159
build/html/_static/sphinx_highlight.js
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
/* Highlighting utilities for Sphinx HTML documentation. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const SPHINX_HIGHLIGHT_ENABLED = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* highlight a given string on a node by wrapping it in
|
||||||
|
* span elements with the given class name.
|
||||||
|
*/
|
||||||
|
const _highlight = (node, addItems, text, className) => {
|
||||||
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
|
const val = node.nodeValue;
|
||||||
|
const parent = node.parentNode;
|
||||||
|
const pos = val.toLowerCase().indexOf(text);
|
||||||
|
if (
|
||||||
|
pos >= 0
|
||||||
|
&& !parent.classList.contains(className)
|
||||||
|
&& !parent.classList.contains("nohighlight")
|
||||||
|
) {
|
||||||
|
let span;
|
||||||
|
|
||||||
|
const closestNode = parent.closest("body, svg, foreignObject");
|
||||||
|
const isInSVG = closestNode && closestNode.matches("svg");
|
||||||
|
if (isInSVG) {
|
||||||
|
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
|
||||||
|
} else {
|
||||||
|
span = document.createElement("span");
|
||||||
|
span.classList.add(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
||||||
|
const rest = document.createTextNode(val.substr(pos + text.length));
|
||||||
|
parent.insertBefore(span, parent.insertBefore(rest, node.nextSibling));
|
||||||
|
node.nodeValue = val.substr(0, pos);
|
||||||
|
/* There may be more occurrences of search term in this node. So call this
|
||||||
|
* function recursively on the remaining fragment.
|
||||||
|
*/
|
||||||
|
_highlight(rest, addItems, text, className);
|
||||||
|
|
||||||
|
if (isInSVG) {
|
||||||
|
const rect = document.createElementNS(
|
||||||
|
"http://www.w3.org/2000/svg",
|
||||||
|
"rect",
|
||||||
|
);
|
||||||
|
const bbox = parent.getBBox();
|
||||||
|
rect.x.baseVal.value = bbox.x;
|
||||||
|
rect.y.baseVal.value = bbox.y;
|
||||||
|
rect.width.baseVal.value = bbox.width;
|
||||||
|
rect.height.baseVal.value = bbox.height;
|
||||||
|
rect.setAttribute("class", className);
|
||||||
|
addItems.push({ parent: parent, target: rect });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (node.matches && !node.matches("button, select, textarea")) {
|
||||||
|
node.childNodes.forEach((el) => _highlight(el, addItems, text, className));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const _highlightText = (thisNode, text, className) => {
|
||||||
|
let addItems = [];
|
||||||
|
_highlight(thisNode, addItems, text, className);
|
||||||
|
addItems.forEach((obj) =>
|
||||||
|
obj.parent.insertAdjacentElement("beforebegin", obj.target),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small JavaScript module for the documentation.
|
||||||
|
*/
|
||||||
|
const SphinxHighlight = {
|
||||||
|
/**
|
||||||
|
* highlight the search words provided in localstorage in the text
|
||||||
|
*/
|
||||||
|
highlightSearchWords: () => {
|
||||||
|
if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight
|
||||||
|
|
||||||
|
// get and clear terms from localstorage
|
||||||
|
const url = new URL(window.location);
|
||||||
|
const highlight =
|
||||||
|
localStorage.getItem("sphinx_highlight_terms")
|
||||||
|
|| url.searchParams.get("highlight")
|
||||||
|
|| "";
|
||||||
|
localStorage.removeItem("sphinx_highlight_terms");
|
||||||
|
// Update history only if '?highlight' is present; otherwise it
|
||||||
|
// clears text fragments (not set in window.location by the browser)
|
||||||
|
if (url.searchParams.has("highlight")) {
|
||||||
|
url.searchParams.delete("highlight");
|
||||||
|
window.history.replaceState({}, "", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get individual terms from highlight string
|
||||||
|
const terms = highlight
|
||||||
|
.toLowerCase()
|
||||||
|
.split(/\s+/)
|
||||||
|
.filter((x) => x);
|
||||||
|
if (terms.length === 0) return; // nothing to do
|
||||||
|
|
||||||
|
// There should never be more than one element matching "div.body"
|
||||||
|
const divBody = document.querySelectorAll("div.body");
|
||||||
|
const body = divBody.length ? divBody[0] : document.querySelector("body");
|
||||||
|
window.setTimeout(() => {
|
||||||
|
terms.forEach((term) => _highlightText(body, term, "highlighted"));
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
const searchBox = document.getElementById("searchbox");
|
||||||
|
if (searchBox === null) return;
|
||||||
|
searchBox.appendChild(
|
||||||
|
document
|
||||||
|
.createRange()
|
||||||
|
.createContextualFragment(
|
||||||
|
'<p class="highlight-link">'
|
||||||
|
+ '<a href="javascript:SphinxHighlight.hideSearchWords()">'
|
||||||
|
+ _("Hide Search Matches")
|
||||||
|
+ "</a></p>",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to hide the search marks again
|
||||||
|
*/
|
||||||
|
hideSearchWords: () => {
|
||||||
|
document
|
||||||
|
.querySelectorAll("#searchbox .highlight-link")
|
||||||
|
.forEach((el) => el.remove());
|
||||||
|
document
|
||||||
|
.querySelectorAll("span.highlighted")
|
||||||
|
.forEach((el) => el.classList.remove("highlighted"));
|
||||||
|
localStorage.removeItem("sphinx_highlight_terms");
|
||||||
|
},
|
||||||
|
|
||||||
|
initEscapeListener: () => {
|
||||||
|
// only install a listener if it is really needed
|
||||||
|
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return;
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (event) => {
|
||||||
|
// bail for input elements
|
||||||
|
if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName))
|
||||||
|
return;
|
||||||
|
// bail with special keys
|
||||||
|
if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey)
|
||||||
|
return;
|
||||||
|
if (
|
||||||
|
DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
|
||||||
|
&& event.key === "Escape"
|
||||||
|
) {
|
||||||
|
SphinxHighlight.hideSearchWords();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
_ready(() => {
|
||||||
|
/* Do not call highlightSearchWords() when we are on the search page.
|
||||||
|
* It will highlight words from the *previous* search query.
|
||||||
|
*/
|
||||||
|
if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords();
|
||||||
|
SphinxHighlight.initEscapeListener();
|
||||||
|
});
|
||||||
139
build/html/architecture.html
Normal file
139
build/html/architecture.html
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" data-content_root="./">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
|
<title>Architecture (audit interview) — Making yourself audit-ready with Verae DataCubes</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
|
||||||
|
<script src="_static/documentation_options.js?v=5929fcd5"></script>
|
||||||
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
||||||
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="BAAs and DPAs when ciphertext has no host keys" href="baa-dpa.html" />
|
||||||
|
<link rel="prev" title="Peergos verification (what was actually audited)" href="verification.html" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<section id="architecture-audit-interview">
|
||||||
|
<h1>Architecture (audit interview)<a class="headerlink" href="#architecture-audit-interview" title="Link to this heading">¶</a></h1>
|
||||||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>Endpoint (keys stay here / HSM)
|
||||||
|
│ HPKE content (NPE suite)
|
||||||
|
│ routing: dest + subject in the clear
|
||||||
|
▼
|
||||||
|
Untrusted NATS (cannot read bodies)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Verae DataCube chain (append-only hashes)
|
||||||
|
│ written through Peergos client
|
||||||
|
▼
|
||||||
|
Peergos cryptree (encrypted names, sizes, graph)
|
||||||
|
│ chunks → CID / hash
|
||||||
|
▼
|
||||||
|
IPFS (distributed, hash-verified ciphertext)
|
||||||
|
</pre></div>
|
||||||
|
</div>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p><strong>At rest:</strong> Peergos cryptree + IPFS. Hosts with disk/backup see
|
||||||
|
<strong>opaque hashed ciphertext</strong>, not PHI, if they lack keys.</p></li>
|
||||||
|
<li><p><strong>In transit (NATS):</strong> HPKE-Base to directory public keys. Broker is
|
||||||
|
honest-but-curious: destinations yes, bodies no.</p></li>
|
||||||
|
<li><p><strong>Integrity:</strong> cube JSONL chain + dual hash + IPFS CID check on
|
||||||
|
restore (re-fetch blocks, re-verify hashes — not a plaintext tape).</p></li>
|
||||||
|
</ul>
|
||||||
|
<p>NATS remains an untrusted router. Production E2E is NPE/HPKE.
|
||||||
|
Passthrough means destination in the clear; the body is ciphertext.</p>
|
||||||
|
<p>Live: <a class="reference external" href="https://pfc.georgelambert.org/v1/npe/keys">https://pfc.georgelambert.org/v1/npe/keys</a> (public keys only).
|
||||||
|
Controls: <a class="reference external" href="https://docs.pfc.georgelambert.org/controls.html">https://docs.pfc.georgelambert.org/controls.html</a></p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h1 class="logo"><a href="index.html">Making yourself audit-ready with Verae DataCubes</a></h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<search id="searchbox" style="display: none" role="search">
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="Search"/>
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</search>
|
||||||
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Navigation</h3>
|
||||||
|
<ul class="current">
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="verification.html">Peergos verification (what was actually audited)</a></li>
|
||||||
|
<li class="toctree-l1 current"><a class="current reference internal" href="#">Architecture (audit interview)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="baa-dpa.html">BAAs and DPAs when ciphertext has no host keys</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="checklist.html">Audit-ready checklist</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="howto.html">How to use this pack</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="relations">
|
||||||
|
<h3>Related Topics</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">Documentation overview</a><ul>
|
||||||
|
<li>Previous: <a href="verification.html" title="previous chapter">Peergos verification (what was actually audited)</a></li>
|
||||||
|
<li>Next: <a href="baa-dpa.html" title="next chapter">BAAs and DPAs when ciphertext has no host keys</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
©2026, Verae.
|
||||||
|
|
||||||
|
|
|
||||||
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 9.1.0</a>
|
||||||
|
& <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
|
||||||
|
|
||||||
|
|
|
||||||
|
<a href="_sources/architecture.rst.txt"
|
||||||
|
rel="nofollow">Page source</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
181
build/html/baa-dpa.html
Normal file
181
build/html/baa-dpa.html
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" data-content_root="./">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
|
<title>BAAs and DPAs when ciphertext has no host keys — Making yourself audit-ready with Verae DataCubes</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
|
||||||
|
<script src="_static/documentation_options.js?v=5929fcd5"></script>
|
||||||
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
||||||
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="Audit-ready checklist" href="checklist.html" />
|
||||||
|
<link rel="prev" title="Architecture (audit interview)" href="architecture.html" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<section id="baas-and-dpas-when-ciphertext-has-no-host-keys">
|
||||||
|
<h1>BAAs and DPAs when ciphertext has no host keys<a class="headerlink" href="#baas-and-dpas-when-ciphertext-has-no-host-keys" title="Link to this heading">¶</a></h1>
|
||||||
|
<p>This is <strong>guidance for an evidence pack</strong>, not legal advice.</p>
|
||||||
|
<section id="the-operator-statement">
|
||||||
|
<h2>The operator statement<a class="headerlink" href="#the-operator-statement" title="Link to this heading">¶</a></h2>
|
||||||
|
<p>Data at rest lives in the <strong>encrypted Peergos cryptree</strong>. Restore uses
|
||||||
|
<strong>distributed, hash-verified, encrypted IPFS blocks</strong>. Hosts and backup
|
||||||
|
media see <strong>opaque blobs</strong> (and random CHAMP labels), not filenames, not
|
||||||
|
PHI, not social graph — if keys never leave the client / customer HSM.</p>
|
||||||
|
<p>That is <strong>true of the Peergos design</strong> (see <a class="reference internal" href="verification.html"><span class="doc">Peergos verification (what was actually audited)</span></a>).
|
||||||
|
It <strong>changes the BAA/DPA conversation</strong>. It does <strong>not</strong> auto-delete the
|
||||||
|
need for contracts.</p>
|
||||||
|
</section>
|
||||||
|
<section id="hipaa-us-business-associate">
|
||||||
|
<h2>HIPAA (US) — Business Associate<a class="headerlink" href="#hipaa-us-business-associate" title="Link to this heading">¶</a></h2>
|
||||||
|
<p>A Business Associate is a person who <strong>creates, receives, maintains, or
|
||||||
|
transmits ePHI</strong> for a covered entity.</p>
|
||||||
|
<p><strong>Technical argument you can make (and should document):</strong></p>
|
||||||
|
<ol class="arabic simple">
|
||||||
|
<li><p>ePHI is encrypted <strong>before</strong> it leaves the endpoint (Peergos client /
|
||||||
|
DataCube writer).</p></li>
|
||||||
|
<li><p>The storage node, IPFS, disk, and backup hold <strong>ciphertext + hashes</strong>.</p></li>
|
||||||
|
<li><p>Private keys <strong>do not</strong> reside on the storage host (customer HSM /
|
||||||
|
client). Hash verification detects tampering.</p></li>
|
||||||
|
<li><p>Therefore the host <strong>cannot maintain ePHI in intelligible form</strong>.</p></li>
|
||||||
|
</ol>
|
||||||
|
<p>HHS distinguishes <strong>conduits</strong> and parties that never have access to
|
||||||
|
ePHI. Many programs still <strong>sign a BAA</strong> when a vendor touches
|
||||||
|
infrastructure, because misconfiguration, support exports, or logs could
|
||||||
|
later expose plaintext. OCR looks at <strong>your</strong> risk analysis.</p>
|
||||||
|
<p><strong>Practical pack:</strong> risk analysis memo citing cryptree + IPFS hash checks
|
||||||
|
+ key custody; BAA <strong>or</strong> written determination that the vendor is
|
||||||
|
<strong>not</strong> a BA because they cannot decrypt; list every party with
|
||||||
|
disk/backup (ns1, IPFS cluster, offsite replica).</p>
|
||||||
|
</section>
|
||||||
|
<section id="gdpr-eu-uk-processor-vs-technical-measure">
|
||||||
|
<h2>GDPR (EU/UK) — processor vs technical measure<a class="headerlink" href="#gdpr-eu-uk-processor-vs-technical-measure" title="Link to this heading">¶</a></h2>
|
||||||
|
<p>Encrypted data can still be <strong>personal data</strong> if it is reasonably
|
||||||
|
attributable (usernames, IPs, invoice identity). GDPR <strong>Art. 32</strong> lists
|
||||||
|
encryption as a security measure.</p>
|
||||||
|
<p>Peergos is designed so the <strong>server is an adversary</strong> for content and
|
||||||
|
most metadata. EU-based <strong>independent pentests</strong> (Cure53 DE, ROS NL)
|
||||||
|
evaluated that design. Processing location for <strong>self-host</strong> is <em>your</em>
|
||||||
|
ns1 / customer region, not peergos.net’s Germany hosting, unless you use
|
||||||
|
peergos.net.</p>
|
||||||
|
<p>You may still need a <strong>DPA (Art. 28)</strong> with anyone who <strong>processes</strong>
|
||||||
|
personal data (usernames, logs, billing). Ciphertext-only storage
|
||||||
|
<strong>narrows</strong> the DPA’s technical annex.</p>
|
||||||
|
</section>
|
||||||
|
<section id="nats-operators">
|
||||||
|
<h2>NATS operators<a class="headerlink" href="#nats-operators" title="Link to this heading">¶</a></h2>
|
||||||
|
<p>NATS is an <strong>untrusted broker</strong>. Content is HPKE; destinations and
|
||||||
|
subjects are in the clear. A NATS operator <strong>cannot</strong> read bodies without
|
||||||
|
endpoint private keys; <strong>can</strong> see routing metadata; <strong>can</strong> drop/delay
|
||||||
|
copy <strong>ciphertext</strong>. Treat like a transit provider: DPA/BAA depends on
|
||||||
|
whether routing metadata is personal data in your jurisdiction.</p>
|
||||||
|
</section>
|
||||||
|
<section id="what-making-yourself-audit-ready-means">
|
||||||
|
<h2>What “making yourself audit-ready” means<a class="headerlink" href="#what-making-yourself-audit-ready-means" title="Link to this heading">¶</a></h2>
|
||||||
|
<p>You are <strong>not</strong> buying Peergos’s Cure53/ROS reports as <em>your</em> SOC 2.
|
||||||
|
You are <strong>reusing</strong> those public evaluations as <strong>vendor/component
|
||||||
|
assurance</strong>, then adding your scope, RoPA, key-custody, inspect k-of-n,
|
||||||
|
admin-history, instance evidence, and contracts that match who can
|
||||||
|
actually see plaintext.</p>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h1 class="logo"><a href="index.html">Making yourself audit-ready with Verae DataCubes</a></h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<search id="searchbox" style="display: none" role="search">
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="Search"/>
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</search>
|
||||||
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Navigation</h3>
|
||||||
|
<ul class="current">
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="verification.html">Peergos verification (what was actually audited)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="architecture.html">Architecture (audit interview)</a></li>
|
||||||
|
<li class="toctree-l1 current"><a class="current reference internal" href="#">BAAs and DPAs when ciphertext has no host keys</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#the-operator-statement">The operator statement</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#hipaa-us-business-associate">HIPAA (US) — Business Associate</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#gdpr-eu-uk-processor-vs-technical-measure">GDPR (EU/UK) — processor vs technical measure</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#nats-operators">NATS operators</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#what-making-yourself-audit-ready-means">What “making yourself audit-ready” means</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="checklist.html">Audit-ready checklist</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="howto.html">How to use this pack</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="relations">
|
||||||
|
<h3>Related Topics</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">Documentation overview</a><ul>
|
||||||
|
<li>Previous: <a href="architecture.html" title="previous chapter">Architecture (audit interview)</a></li>
|
||||||
|
<li>Next: <a href="checklist.html" title="next chapter">Audit-ready checklist</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
©2026, Verae.
|
||||||
|
|
||||||
|
|
|
||||||
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 9.1.0</a>
|
||||||
|
& <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
|
||||||
|
|
||||||
|
|
|
||||||
|
<a href="_sources/baa-dpa.rst.txt"
|
||||||
|
rel="nofollow">Page source</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
186
build/html/checklist.html
Normal file
186
build/html/checklist.html
Normal file
|
|
@ -0,0 +1,186 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" data-content_root="./">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
|
<title>Audit-ready checklist — Making yourself audit-ready with Verae DataCubes</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
|
||||||
|
<script src="_static/documentation_options.js?v=5929fcd5"></script>
|
||||||
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
||||||
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="How to use this pack" href="howto.html" />
|
||||||
|
<link rel="prev" title="BAAs and DPAs when ciphertext has no host keys" href="baa-dpa.html" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<section id="audit-ready-checklist">
|
||||||
|
<h1>Audit-ready checklist<a class="headerlink" href="#audit-ready-checklist" title="Link to this heading">¶</a></h1>
|
||||||
|
<p>Use this as a working list. Check items only when <strong>evidence exists</strong>
|
||||||
|
(screenshot, log export, signed policy, ticket). This list is not a
|
||||||
|
certificate.</p>
|
||||||
|
<section id="a-scope-and-data-map">
|
||||||
|
<h2>A. Scope and data map<a class="headerlink" href="#a-scope-and-data-map" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Named legal entity and systems in scope (console, Drive, NATS, IPFS, ns1)</p></li>
|
||||||
|
<li><p>Data-flow diagram: endpoint → HPKE/NATS → cryptree/IPFS</p></li>
|
||||||
|
<li><p>What is PHI / personal data vs ciphertext vs routing metadata</p></li>
|
||||||
|
<li><p>Peergos verification chapter attached (<a class="reference internal" href="verification.html"><span class="doc">Peergos verification (what was actually audited)</span></a>)</p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section id="b-keys-and-encryption">
|
||||||
|
<h2>B. Keys and encryption<a class="headerlink" href="#b-keys-and-encryption" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Customer holds Peergos/Drive keys; not on storage host</p></li>
|
||||||
|
<li><p>NPE/HPKE endpoint keys in directory; private 0600; no xor content</p></li>
|
||||||
|
<li><p>Signed Ed25519 config; unsigned rejected; admin-history prev+new+diff</p></li>
|
||||||
|
<li><p>HSM or documented lab-to-HSM path</p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section id="c-access">
|
||||||
|
<h2>C. Access<a class="headerlink" href="#c-access" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Console <code class="docutils literal notranslate"><span class="pre">PFC_REQUIRE_AUTH=1</span></code>, TOTP; Drive login separate</p></li>
|
||||||
|
<li><p>Inspect k-of-n; author is not an officer; log-before-reveal</p></li>
|
||||||
|
<li><p>Joiner / mover / leaver for console users</p></li>
|
||||||
|
<li><p>Google SSO does <strong>not</strong> unwrap cubes</p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section id="d-integrity-and-backup">
|
||||||
|
<h2>D. Integrity and backup<a class="headerlink" href="#d-integrity-and-backup" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Cube chain append-only JSONL; dual hash</p></li>
|
||||||
|
<li><p>Hash registry: first SHA-256 and receipt win</p></li>
|
||||||
|
<li><p>Peergos/IPFS: hash-verified encrypted blocks (restore = re-fetch CIDs)</p></li>
|
||||||
|
<li><p>Restore test: recover a cube from content-addressed ciphertext without
|
||||||
|
plaintext backup tapes</p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section id="e-logging">
|
||||||
|
<h2>E. Logging<a class="headerlink" href="#e-logging" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Inspect audit events</p></li>
|
||||||
|
<li><p>SM summaries: codes + lookup_id only (no bodies)</p></li>
|
||||||
|
<li><p>Admin-history cube for config</p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section id="f-contracts-counsel">
|
||||||
|
<h2>F. Contracts (counsel)<a class="headerlink" href="#f-contracts-counsel" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Written BA / not-a-BA determination for disk, VM, backup, IPFS</p></li>
|
||||||
|
<li><p>DPA Art. 28 where usernames/logs/IPs are processed</p></li>
|
||||||
|
<li><p>NATS operator: metadata vs content in the annex</p></li>
|
||||||
|
<li><p>Peergos component assurance: attach Cure53 2019 + ROS 2024 PDFs
|
||||||
|
(public; not your org’s ISO/SOC report)</p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section id="g-independent-audit-of-you">
|
||||||
|
<h2>G. Independent audit of <em>you</em><a class="headerlink" href="#g-independent-audit-of-you" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>SOC 2 Type I/II engagement <strong>or</strong> ISO 27001 registrar <strong>or</strong> HIPAA
|
||||||
|
risk analysis + policies (pick the program you actually need)</p></li>
|
||||||
|
<li><p>Evidence window (Type II / surveillance) if applicable</p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h1 class="logo"><a href="index.html">Making yourself audit-ready with Verae DataCubes</a></h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<search id="searchbox" style="display: none" role="search">
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="Search"/>
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</search>
|
||||||
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Navigation</h3>
|
||||||
|
<ul class="current">
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="verification.html">Peergos verification (what was actually audited)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="architecture.html">Architecture (audit interview)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="baa-dpa.html">BAAs and DPAs when ciphertext has no host keys</a></li>
|
||||||
|
<li class="toctree-l1 current"><a class="current reference internal" href="#">Audit-ready checklist</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#a-scope-and-data-map">A. Scope and data map</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#b-keys-and-encryption">B. Keys and encryption</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#c-access">C. Access</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#d-integrity-and-backup">D. Integrity and backup</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#e-logging">E. Logging</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#f-contracts-counsel">F. Contracts (counsel)</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#g-independent-audit-of-you">G. Independent audit of <em>you</em></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="howto.html">How to use this pack</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="relations">
|
||||||
|
<h3>Related Topics</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">Documentation overview</a><ul>
|
||||||
|
<li>Previous: <a href="baa-dpa.html" title="previous chapter">BAAs and DPAs when ciphertext has no host keys</a></li>
|
||||||
|
<li>Next: <a href="howto.html" title="next chapter">How to use this pack</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
©2026, Verae.
|
||||||
|
|
||||||
|
|
|
||||||
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 9.1.0</a>
|
||||||
|
& <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
|
||||||
|
|
||||||
|
|
|
||||||
|
<a href="_sources/checklist.rst.txt"
|
||||||
|
rel="nofollow">Page source</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
106
build/html/genindex.html
Normal file
106
build/html/genindex.html
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" data-content_root="./">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Index — Making yourself audit-ready with Verae DataCubes</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
|
||||||
|
<script src="_static/documentation_options.js?v=5929fcd5"></script>
|
||||||
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
||||||
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
||||||
|
<link rel="index" title="Index" href="#" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
|
||||||
|
<h1 id="index">Index</h1>
|
||||||
|
|
||||||
|
<div class="genindex-jumpbox">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h1 class="logo"><a href="index.html">Making yourself audit-ready with Verae DataCubes</a></h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<search id="searchbox" style="display: none" role="search">
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="Search"/>
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</search>
|
||||||
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="verification.html">Peergos verification (what was actually audited)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="architecture.html">Architecture (audit interview)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="baa-dpa.html">BAAs and DPAs when ciphertext has no host keys</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="checklist.html">Audit-ready checklist</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="howto.html">How to use this pack</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="relations">
|
||||||
|
<h3>Related Topics</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">Documentation overview</a><ul>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
©2026, Verae.
|
||||||
|
|
||||||
|
|
|
||||||
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 9.1.0</a>
|
||||||
|
& <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
130
build/html/howto.html
Normal file
130
build/html/howto.html
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" data-content_root="./">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
|
<title>How to use this pack — Making yourself audit-ready with Verae DataCubes</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
|
||||||
|
<script src="_static/documentation_options.js?v=5929fcd5"></script>
|
||||||
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
||||||
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="prev" title="Audit-ready checklist" href="checklist.html" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<section id="how-to-use-this-pack">
|
||||||
|
<h1>How to use this pack<a class="headerlink" href="#how-to-use-this-pack" title="Link to this heading">¶</a></h1>
|
||||||
|
<ol class="arabic simple">
|
||||||
|
<li><p>Read <a class="reference internal" href="verification.html"><span class="doc">Peergos verification (what was actually audited)</span></a> so you do not over-claim Peergos audits.</p></li>
|
||||||
|
<li><p>Fill <a class="reference internal" href="checklist.html"><span class="doc">Audit-ready checklist</span></a> with <strong>your</strong> instance evidence (ns1, keys, users).</p></li>
|
||||||
|
<li><p>Give <a class="reference internal" href="baa-dpa.html"><span class="doc">BAAs and DPAs when ciphertext has no host keys</span></a> to counsel with the data-flow from <a class="reference internal" href="architecture.html"><span class="doc">Architecture (audit interview)</span></a>.</p></li>
|
||||||
|
<li><p>Point auditors at live technical surfaces (do not give them private keys).</p></li>
|
||||||
|
</ol>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p><a class="reference external" href="https://pfc.georgelambert.org/health">https://pfc.georgelambert.org/health</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://pfc.georgelambert.org/v1/npe/keys">https://pfc.georgelambert.org/v1/npe/keys</a> (public keys only)</p></li>
|
||||||
|
<li><p><a class="reference external" href="https://docs.pfc.georgelambert.org/controls.html">https://docs.pfc.georgelambert.org/controls.html</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://docs.pfc.georgelambert.org/custody.html">https://docs.pfc.georgelambert.org/custody.html</a></p></li>
|
||||||
|
<li><p>Peergos Drive (cryptree) on your host</p></li>
|
||||||
|
<li><p><a class="reference external" href="https://git.georgelambert.org/marchon/peergos-for-compliance">https://git.georgelambert.org/marchon/peergos-for-compliance</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://git.georgelambert.org/marchon/system-git-sync">https://git.georgelambert.org/marchon/system-git-sync</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://git.georgelambert.org/marchon/secure-messaging">https://git.georgelambert.org/marchon/secure-messaging</a></p></li>
|
||||||
|
</ul>
|
||||||
|
<ol class="arabic simple" start="5">
|
||||||
|
<li><p>Attach the two <strong>public</strong> Peergos pentest PDFs from the Peergos
|
||||||
|
<code class="docutils literal notranslate"><span class="pre">audits/</span></code> tree as <strong>vendor security evaluations</strong>, labeled “not our
|
||||||
|
SOC 2 / ISO certificate”.</p></li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h1 class="logo"><a href="index.html">Making yourself audit-ready with Verae DataCubes</a></h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<search id="searchbox" style="display: none" role="search">
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="Search"/>
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</search>
|
||||||
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Navigation</h3>
|
||||||
|
<ul class="current">
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="verification.html">Peergos verification (what was actually audited)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="architecture.html">Architecture (audit interview)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="baa-dpa.html">BAAs and DPAs when ciphertext has no host keys</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="checklist.html">Audit-ready checklist</a></li>
|
||||||
|
<li class="toctree-l1 current"><a class="current reference internal" href="#">How to use this pack</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="relations">
|
||||||
|
<h3>Related Topics</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">Documentation overview</a><ul>
|
||||||
|
<li>Previous: <a href="checklist.html" title="previous chapter">Audit-ready checklist</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
©2026, Verae.
|
||||||
|
|
||||||
|
|
|
||||||
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 9.1.0</a>
|
||||||
|
& <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
|
||||||
|
|
||||||
|
|
|
||||||
|
<a href="_sources/howto.rst.txt"
|
||||||
|
rel="nofollow">Page source</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
173
build/html/index.html
Normal file
173
build/html/index.html
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" data-content_root="./">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
|
<title>Making yourself audit-ready with Verae DataCubes — Making yourself audit-ready with Verae DataCubes</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
|
||||||
|
<script src="_static/documentation_options.js?v=5929fcd5"></script>
|
||||||
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
||||||
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="Peergos verification (what was actually audited)" href="verification.html" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<section id="making-yourself-audit-ready-with-verae-datacubes">
|
||||||
|
<h1>Making yourself audit-ready with Verae DataCubes<a class="headerlink" href="#making-yourself-audit-ready-with-verae-datacubes" title="Link to this heading">¶</a></h1>
|
||||||
|
<p>How to <strong>prepare an organization</strong> for HIPAA-aligned, SOC 2, or ISO 27001
|
||||||
|
work using Verae DataCubes on <strong>Peergos</strong> (encrypted cryptree + hashed
|
||||||
|
IPFS) and HPKE on an <strong>untrusted NATS</strong> broker.</p>
|
||||||
|
<p><strong>This document is not a HIPAA, SOC 2, or ISO certificate.</strong>
|
||||||
|
Peergos’s public pentests are <strong>not</strong> your Type II or ISO registrar
|
||||||
|
certificate. They are <strong>component security evaluations</strong> you can attach.</p>
|
||||||
|
<div class="toctree-wrapper compound">
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="verification.html">Peergos verification (what was actually audited)</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="verification.html#claim-to-check">Claim to check</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="verification.html#independent-security-audits-europe">Independent security audits (Europe)</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="verification.html#eu-funding-nlnet">EU funding / NLnet</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="verification.html#hosted-instance-location">Hosted instance location</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="verification.html#encrypted-filesystem-hashed-ipfs-design">Encrypted filesystem + hashed IPFS (design)</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="verification.html#not-verified-do-not-claim">Not verified / do not claim</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="architecture.html">Architecture (audit interview)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="baa-dpa.html">BAAs and DPAs when ciphertext has no host keys</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="baa-dpa.html#the-operator-statement">The operator statement</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="baa-dpa.html#hipaa-us-business-associate">HIPAA (US) — Business Associate</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="baa-dpa.html#gdpr-eu-uk-processor-vs-technical-measure">GDPR (EU/UK) — processor vs technical measure</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="baa-dpa.html#nats-operators">NATS operators</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="baa-dpa.html#what-making-yourself-audit-ready-means">What “making yourself audit-ready” means</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="checklist.html">Audit-ready checklist</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="checklist.html#a-scope-and-data-map">A. Scope and data map</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="checklist.html#b-keys-and-encryption">B. Keys and encryption</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="checklist.html#c-access">C. Access</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="checklist.html#d-integrity-and-backup">D. Integrity and backup</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="checklist.html#e-logging">E. Logging</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="checklist.html#f-contracts-counsel">F. Contracts (counsel)</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="checklist.html#g-independent-audit-of-you">G. Independent audit of <em>you</em></a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="howto.html">How to use this pack</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<section id="what-we-verified-about-peergos-eu">
|
||||||
|
<h2>What we verified about Peergos (EU)<a class="headerlink" href="#what-we-verified-about-peergos-eu" title="Link to this heading">¶</a></h2>
|
||||||
|
<p>See the full sourced table in <a class="reference internal" href="verification.html"><span class="doc">Peergos verification (what was actually audited)</span></a>.</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Encrypted client-side filesystem (cryptree); keys not on the storage
|
||||||
|
server — <strong>yes</strong> (Peergos book + Cure53 design review).</p></li>
|
||||||
|
<li><p>IPFS blocks content-addressed; Peergos verifies hashes — <strong>yes</strong>.</p></li>
|
||||||
|
<li><p>Independent <strong>EU</strong> security audits, reports published — <strong>yes, two:</strong>
|
||||||
|
Cure53 Berlin (2019); Radically Open Security Amsterdam (2024).</p></li>
|
||||||
|
<li><p>“Peergos is HIPAA/SOC 2/ISO certified” — <strong>no.</strong> Those audits are
|
||||||
|
pentest/code/design reviews, not management-system certificates.</p></li>
|
||||||
|
</ul>
|
||||||
|
<p>Peergos <strong>was designed as a trust-minimized encrypted filesystem</strong>,
|
||||||
|
<strong>evaluated in Europe</strong> by two specialist firms, with <strong>public reports</strong>.
|
||||||
|
That supports the <strong>at-rest / backup</strong> story. It does <strong>not</strong> finish
|
||||||
|
<em>your</em> audit.</p>
|
||||||
|
<p>Live technical surfaces:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p><a class="reference external" href="https://pfc.georgelambert.org/health">https://pfc.georgelambert.org/health</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://pfc.georgelambert.org/v1/npe/keys">https://pfc.georgelambert.org/v1/npe/keys</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://docs.pfc.georgelambert.org/controls.html">https://docs.pfc.georgelambert.org/controls.html</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://git.georgelambert.org/marchon/peergos-making-yourself-audit-ready-with-verae-datacubes">https://git.georgelambert.org/marchon/peergos-making-yourself-audit-ready-with-verae-datacubes</a></p></li>
|
||||||
|
</ul>
|
||||||
|
<p>Companion system docs (HTML): <a class="reference external" href="https://docs.pfc.georgelambert.org/">https://docs.pfc.georgelambert.org/</a></p>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h1 class="logo"><a href="#">Making yourself audit-ready with Verae DataCubes</a></h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<search id="searchbox" style="display: none" role="search">
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="Search"/>
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</search>
|
||||||
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="verification.html">Peergos verification (what was actually audited)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="architecture.html">Architecture (audit interview)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="baa-dpa.html">BAAs and DPAs when ciphertext has no host keys</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="checklist.html">Audit-ready checklist</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="howto.html">How to use this pack</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="relations">
|
||||||
|
<h3>Related Topics</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#">Documentation overview</a><ul>
|
||||||
|
<li>Next: <a href="verification.html" title="next chapter">Peergos verification (what was actually audited)</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
©2026, Verae.
|
||||||
|
|
||||||
|
|
|
||||||
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 9.1.0</a>
|
||||||
|
& <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
|
||||||
|
|
||||||
|
|
|
||||||
|
<a href="_sources/index.rst.txt"
|
||||||
|
rel="nofollow">Page source</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
build/html/nats-service-endpoints.pdf
Normal file
BIN
build/html/nats-service-endpoints.pdf
Normal file
Binary file not shown.
BIN
build/html/objects.inv
Normal file
BIN
build/html/objects.inv
Normal file
Binary file not shown.
BIN
build/html/peergos-for-compliance.pdf
Normal file
BIN
build/html/peergos-for-compliance.pdf
Normal file
Binary file not shown.
Binary file not shown.
124
build/html/search.html
Normal file
124
build/html/search.html
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" data-content_root="./">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Search — Making yourself audit-ready with Verae DataCubes</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
|
||||||
|
|
||||||
|
<script src="_static/documentation_options.js?v=5929fcd5"></script>
|
||||||
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
||||||
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
||||||
|
<script src="_static/searchtools.js"></script>
|
||||||
|
<script src="_static/language_data.js"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="#" />
|
||||||
|
<script src="searchindex.js" defer="defer"></script>
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<h1 id="search-documentation">Search</h1>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<div class="admonition warning">
|
||||||
|
<p>
|
||||||
|
Please activate JavaScript to enable the search
|
||||||
|
functionality.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Searching for multiple words only shows matches that contain
|
||||||
|
all words.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<form action="" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="search-documentation" value="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||||
|
<input type="submit" value="search" />
|
||||||
|
<span id="search-progress" style="padding-left: 10px"></span>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="search-results"></div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h1 class="logo"><a href="index.html">Making yourself audit-ready with Verae DataCubes</a></h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Navigation</h3>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="verification.html">Peergos verification (what was actually audited)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="architecture.html">Architecture (audit interview)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="baa-dpa.html">BAAs and DPAs when ciphertext has no host keys</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="checklist.html">Audit-ready checklist</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="howto.html">How to use this pack</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="relations">
|
||||||
|
<h3>Related Topics</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">Documentation overview</a><ul>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
©2026, Verae.
|
||||||
|
|
||||||
|
|
|
||||||
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 9.1.0</a>
|
||||||
|
& <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
build/html/searchindex.js
Normal file
1
build/html/searchindex.js
Normal file
File diff suppressed because one or more lines are too long
BIN
build/html/secure-messaging.pdf
Normal file
BIN
build/html/secure-messaging.pdf
Normal file
Binary file not shown.
195
build/html/verification.html
Normal file
195
build/html/verification.html
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html lang="en" data-content_root="./">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
|
<title>Peergos verification (what was actually audited) — Making yourself audit-ready with Verae DataCubes</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
|
||||||
|
<script src="_static/documentation_options.js?v=5929fcd5"></script>
|
||||||
|
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
||||||
|
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
||||||
|
<link rel="index" title="Index" href="genindex.html" />
|
||||||
|
<link rel="search" title="Search" href="search.html" />
|
||||||
|
<link rel="next" title="Architecture (audit interview)" href="architecture.html" />
|
||||||
|
<link rel="prev" title="Making yourself audit-ready with Verae DataCubes" href="index.html" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head><body>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="document">
|
||||||
|
<div class="documentwrapper">
|
||||||
|
<div class="bodywrapper">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="body" role="main">
|
||||||
|
|
||||||
|
<section id="peergos-verification-what-was-actually-audited">
|
||||||
|
<h1>Peergos verification (what was actually audited)<a class="headerlink" href="#peergos-verification-what-was-actually-audited" title="Link to this heading">¶</a></h1>
|
||||||
|
<p>This chapter records <strong>sourced</strong> facts. It does <strong>not</strong> turn Peergos, Verae,
|
||||||
|
or DataCubes into a HIPAA, SOC 2, or ISO 27001 certificate.</p>
|
||||||
|
<section id="claim-to-check">
|
||||||
|
<h2>Claim to check<a class="headerlink" href="#claim-to-check" title="Link to this heading">¶</a></h2>
|
||||||
|
<p>Data at rest is stored in an encrypted append-only Peergos filesystem;
|
||||||
|
backup/restore is managed via a distributed, hashed, encrypted Peergos
|
||||||
|
IPFS system, designed and evaluated in the EU as an audited secure
|
||||||
|
filesystem.</p>
|
||||||
|
</section>
|
||||||
|
<section id="independent-security-audits-europe">
|
||||||
|
<h2>Independent security audits (Europe)<a class="headerlink" href="#independent-security-audits-europe" title="Link to this heading">¶</a></h2>
|
||||||
|
<p><strong>2019 — Cure53 (Berlin, Germany).</strong>
|
||||||
|
Pentest, source-code audit, <strong>crypto/design review</strong> (May–June 2019).
|
||||||
|
No fundamental architectural or cryptographic problems; issues fixed.
|
||||||
|
Cure53: the platform <strong>passed this evaluation</strong>.</p>
|
||||||
|
<p><strong>2024 — Radically Open Security B.V. (Amsterdam, Netherlands).</strong>
|
||||||
|
Crystal-box pentest + code audit of Peergos web-ui (Sep–Nov 2024).
|
||||||
|
<strong>0</strong> extreme / high / elevated; <strong>2</strong> moderate, <strong>6</strong> low; Peergos
|
||||||
|
states all fixed; no data exposure or integrity compromise (mostly UI
|
||||||
|
crashes).</p>
|
||||||
|
<p>Both firms are <strong>EU-based</strong>. Both full reports are <strong>public</strong>. That is a
|
||||||
|
<strong>security evaluation of the Peergos protocol/implementation</strong>, not a
|
||||||
|
HIPAA/SOC 2/ISO management-system certificate.</p>
|
||||||
|
<p>Primary sources:</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p><a class="reference external" href="https://peergos.org/posts/security-audit">https://peergos.org/posts/security-audit</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://cure53.de/pentest-report_peergos.pdf">https://cure53.de/pentest-report_peergos.pdf</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://peergos.org/posts/security-audit-2024">https://peergos.org/posts/security-audit-2024</a></p></li>
|
||||||
|
<li><p><a class="reference external" href="https://github.com/Peergos/Peergos/tree/master/audits">https://github.com/Peergos/Peergos/tree/master/audits</a></p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section id="eu-funding-nlnet">
|
||||||
|
<h2>EU funding / NLnet<a class="headerlink" href="#eu-funding-nlnet" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>Peergos received funding from the <strong>European Union Horizon 2020</strong>
|
||||||
|
programme under <strong>NGI-POINTER</strong>, grant <strong>871528</strong> (stated on the 2024
|
||||||
|
audit post).</p></li>
|
||||||
|
<li><p>The 2024 audit was supported by <strong>NLnet</strong> (Netherlands).</p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section id="hosted-instance-location">
|
||||||
|
<h2>Hosted instance location<a class="headerlink" href="#hosted-instance-location" title="Link to this heading">¶</a></h2>
|
||||||
|
<p>Peergos’s hosted privacy notice states peergos.net uses servers in
|
||||||
|
<strong>Germany</strong>. <strong>Self-hosted ns1 / customer cryptree is a different
|
||||||
|
processing location</strong> and must be documented in <em>your</em> RoPA / BAA pack.</p>
|
||||||
|
</section>
|
||||||
|
<section id="encrypted-filesystem-hashed-ipfs-design">
|
||||||
|
<h2>Encrypted filesystem + hashed IPFS (design)<a class="headerlink" href="#encrypted-filesystem-hashed-ipfs-design" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p><strong>Cryptree</strong>: tree of symmetric keys; fine-grained read/write caps;
|
||||||
|
sibling names hidden; writes <strong>signed</strong>.</p></li>
|
||||||
|
<li><p><strong>Chunks</strong>: up to 5 MiB, padded, independently encrypted
|
||||||
|
(Salsa20-Poly1305); random 256-bit keys (not convergent).</p></li>
|
||||||
|
<li><p><strong>IPFS</strong>: content-addressed blocks. Peergos <strong>verifies the hash</strong> of
|
||||||
|
every block read from or written to IPFS. Clients verify hashes and
|
||||||
|
signatures from a Peergos server.</p></li>
|
||||||
|
<li><p><strong>CHAMP</strong>: encrypted cryptree nodes under <strong>random 32-byte labels</strong>.</p></li>
|
||||||
|
<li><p>Sharing: hybrid <strong>X25519 + ML-KEM-1024</strong>.</p></li>
|
||||||
|
</ul>
|
||||||
|
<p>“Append-only” in Verae DataCubes is the <strong>cube chain JSONL</strong> (application
|
||||||
|
integrity). Peergos uses signed updates and immutable blocks. Do not
|
||||||
|
conflate the two layers in an audit interview.</p>
|
||||||
|
</section>
|
||||||
|
<section id="not-verified-do-not-claim">
|
||||||
|
<h2>Not verified / do not claim<a class="headerlink" href="#not-verified-do-not-claim" title="Link to this heading">¶</a></h2>
|
||||||
|
<ul class="simple">
|
||||||
|
<li><p>“Peergos is HIPAA certified” — <strong>false.</strong> HIPAA is not a product certificate.</p></li>
|
||||||
|
<li><p>“Peergos is SOC 2 / ISO 27001 certified” — <strong>not shown.</strong> Published
|
||||||
|
work is pentest/code audit, not Type II or ISO registrar.</p></li>
|
||||||
|
<li><p>“EU certified Peergos as a government-standard filesystem” —
|
||||||
|
<strong>overstated.</strong> What exists: EU grant funding, NLNet-funded ROS
|
||||||
|
pentest, Cure53 Berlin design+code audit.</p></li>
|
||||||
|
<li><p>“Hosts with disk/backup never need a BAA/DPA” — <strong>legal conclusion,
|
||||||
|
not a technical fact.</strong> See <a class="reference internal" href="baa-dpa.html"><span class="doc">BAAs and DPAs when ciphertext has no host keys</span></a>.</p></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||||
|
<div class="sphinxsidebarwrapper">
|
||||||
|
<h1 class="logo"><a href="index.html">Making yourself audit-ready with Verae DataCubes</a></h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<search id="searchbox" style="display: none" role="search">
|
||||||
|
<div class="searchformwrapper">
|
||||||
|
<form class="search" action="search.html" method="get">
|
||||||
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="Search"/>
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</search>
|
||||||
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Navigation</h3>
|
||||||
|
<ul class="current">
|
||||||
|
<li class="toctree-l1 current"><a class="current reference internal" href="#">Peergos verification (what was actually audited)</a><ul>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#claim-to-check">Claim to check</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#independent-security-audits-europe">Independent security audits (Europe)</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#eu-funding-nlnet">EU funding / NLnet</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#hosted-instance-location">Hosted instance location</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#encrypted-filesystem-hashed-ipfs-design">Encrypted filesystem + hashed IPFS (design)</a></li>
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#not-verified-do-not-claim">Not verified / do not claim</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="architecture.html">Architecture (audit interview)</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="baa-dpa.html">BAAs and DPAs when ciphertext has no host keys</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="checklist.html">Audit-ready checklist</a></li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="howto.html">How to use this pack</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="relations">
|
||||||
|
<h3>Related Topics</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">Documentation overview</a><ul>
|
||||||
|
<li>Previous: <a href="index.html" title="previous chapter">Making yourself audit-ready with Verae DataCubes</a></li>
|
||||||
|
<li>Next: <a href="architecture.html" title="next chapter">Architecture (audit interview)</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clearer"></div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
©2026, Verae.
|
||||||
|
|
||||||
|
|
|
||||||
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 9.1.0</a>
|
||||||
|
& <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
|
||||||
|
|
||||||
|
|
|
||||||
|
<a href="_sources/verification.rst.txt"
|
||||||
|
rel="nofollow">Page source</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
build/latex/.doctrees/architecture.doctree
Normal file
BIN
build/latex/.doctrees/architecture.doctree
Normal file
Binary file not shown.
BIN
build/latex/.doctrees/baa-dpa.doctree
Normal file
BIN
build/latex/.doctrees/baa-dpa.doctree
Normal file
Binary file not shown.
BIN
build/latex/.doctrees/checklist.doctree
Normal file
BIN
build/latex/.doctrees/checklist.doctree
Normal file
Binary file not shown.
BIN
build/latex/.doctrees/environment.pickle
Normal file
BIN
build/latex/.doctrees/environment.pickle
Normal file
Binary file not shown.
BIN
build/latex/.doctrees/howto.doctree
Normal file
BIN
build/latex/.doctrees/howto.doctree
Normal file
Binary file not shown.
BIN
build/latex/.doctrees/index.doctree
Normal file
BIN
build/latex/.doctrees/index.doctree
Normal file
Binary file not shown.
BIN
build/latex/.doctrees/verification.doctree
Normal file
BIN
build/latex/.doctrees/verification.doctree
Normal file
Binary file not shown.
101
build/latex/LICRcyr2utf8.xdy
Normal file
101
build/latex/LICRcyr2utf8.xdy
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
;; -*- coding: utf-8; mode: Lisp; -*-
|
||||||
|
;; style file for xindy
|
||||||
|
;; filename: LICRcyr2utf8.xdy
|
||||||
|
;; description: style file for xindy which maps back LaTeX Internal
|
||||||
|
;; Character Representation of Cyrillic to utf-8
|
||||||
|
;; usage: for use with pdflatex produced .idx files.
|
||||||
|
;; Contributed by the Sphinx team, July 2018.
|
||||||
|
(merge-rule "\IeC {\'\CYRG }" "Ѓ" :string)
|
||||||
|
(merge-rule "\IeC {\'\CYRK }" "Ќ" :string)
|
||||||
|
(merge-rule "\IeC {\'\cyrg }" "ѓ" :string)
|
||||||
|
(merge-rule "\IeC {\'\cyrk }" "ќ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRA }" "А" :string)
|
||||||
|
(merge-rule "\IeC {\CYRB }" "Б" :string)
|
||||||
|
(merge-rule "\IeC {\CYRC }" "Ц" :string)
|
||||||
|
(merge-rule "\IeC {\CYRCH }" "Ч" :string)
|
||||||
|
(merge-rule "\IeC {\CYRD }" "Д" :string)
|
||||||
|
(merge-rule "\IeC {\CYRDJE }" "Ђ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRDZE }" "Ѕ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRDZHE }" "Џ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRE }" "Е" :string)
|
||||||
|
(merge-rule "\IeC {\CYREREV }" "Э" :string)
|
||||||
|
(merge-rule "\IeC {\CYRERY }" "Ы" :string)
|
||||||
|
(merge-rule "\IeC {\CYRF }" "Ф" :string)
|
||||||
|
(merge-rule "\IeC {\CYRG }" "Г" :string)
|
||||||
|
(merge-rule "\IeC {\CYRGUP }" "Ґ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRH }" "Х" :string)
|
||||||
|
(merge-rule "\IeC {\CYRHRDSN }" "Ъ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRI }" "И" :string)
|
||||||
|
(merge-rule "\IeC {\CYRIE }" "Є" :string)
|
||||||
|
(merge-rule "\IeC {\CYRII }" "І" :string)
|
||||||
|
(merge-rule "\IeC {\CYRISHRT }" "Й" :string)
|
||||||
|
(merge-rule "\IeC {\CYRJE }" "Ј" :string)
|
||||||
|
(merge-rule "\IeC {\CYRK }" "К" :string)
|
||||||
|
(merge-rule "\IeC {\CYRL }" "Л" :string)
|
||||||
|
(merge-rule "\IeC {\CYRLJE }" "Љ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRM }" "М" :string)
|
||||||
|
(merge-rule "\IeC {\CYRN }" "Н" :string)
|
||||||
|
(merge-rule "\IeC {\CYRNJE }" "Њ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRO }" "О" :string)
|
||||||
|
(merge-rule "\IeC {\CYRP }" "П" :string)
|
||||||
|
(merge-rule "\IeC {\CYRR }" "Р" :string)
|
||||||
|
(merge-rule "\IeC {\CYRS }" "С" :string)
|
||||||
|
(merge-rule "\IeC {\CYRSFTSN }" "Ь" :string)
|
||||||
|
(merge-rule "\IeC {\CYRSH }" "Ш" :string)
|
||||||
|
(merge-rule "\IeC {\CYRSHCH }" "Щ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRT }" "Т" :string)
|
||||||
|
(merge-rule "\IeC {\CYRTSHE }" "Ћ" :string)
|
||||||
|
(merge-rule "\IeC {\CYRU }" "У" :string)
|
||||||
|
(merge-rule "\IeC {\CYRUSHRT }" "Ў" :string)
|
||||||
|
(merge-rule "\IeC {\CYRV }" "В" :string)
|
||||||
|
(merge-rule "\IeC {\CYRYA }" "Я" :string)
|
||||||
|
(merge-rule "\IeC {\CYRYI }" "Ї" :string)
|
||||||
|
(merge-rule "\IeC {\CYRYO }" "Ё" :string)
|
||||||
|
(merge-rule "\IeC {\CYRYU }" "Ю" :string)
|
||||||
|
(merge-rule "\IeC {\CYRZ }" "З" :string)
|
||||||
|
(merge-rule "\IeC {\CYRZH }" "Ж" :string)
|
||||||
|
(merge-rule "\IeC {\cyra }" "а" :string)
|
||||||
|
(merge-rule "\IeC {\cyrb }" "б" :string)
|
||||||
|
(merge-rule "\IeC {\cyrc }" "ц" :string)
|
||||||
|
(merge-rule "\IeC {\cyrch }" "ч" :string)
|
||||||
|
(merge-rule "\IeC {\cyrd }" "д" :string)
|
||||||
|
(merge-rule "\IeC {\cyrdje }" "ђ" :string)
|
||||||
|
(merge-rule "\IeC {\cyrdze }" "ѕ" :string)
|
||||||
|
(merge-rule "\IeC {\cyrdzhe }" "џ" :string)
|
||||||
|
(merge-rule "\IeC {\cyre }" "е" :string)
|
||||||
|
(merge-rule "\IeC {\cyrerev }" "э" :string)
|
||||||
|
(merge-rule "\IeC {\cyrery }" "ы" :string)
|
||||||
|
(merge-rule "\IeC {\cyrf }" "ф" :string)
|
||||||
|
(merge-rule "\IeC {\cyrg }" "г" :string)
|
||||||
|
(merge-rule "\IeC {\cyrgup }" "ґ" :string)
|
||||||
|
(merge-rule "\IeC {\cyrh }" "х" :string)
|
||||||
|
(merge-rule "\IeC {\cyrhrdsn }" "ъ" :string)
|
||||||
|
(merge-rule "\IeC {\cyri }" "и" :string)
|
||||||
|
(merge-rule "\IeC {\cyrie }" "є" :string)
|
||||||
|
(merge-rule "\IeC {\cyrii }" "і" :string)
|
||||||
|
(merge-rule "\IeC {\cyrishrt }" "й" :string)
|
||||||
|
(merge-rule "\IeC {\cyrje }" "ј" :string)
|
||||||
|
(merge-rule "\IeC {\cyrk }" "к" :string)
|
||||||
|
(merge-rule "\IeC {\cyrl }" "л" :string)
|
||||||
|
(merge-rule "\IeC {\cyrlje }" "љ" :string)
|
||||||
|
(merge-rule "\IeC {\cyrm }" "м" :string)
|
||||||
|
(merge-rule "\IeC {\cyrn }" "н" :string)
|
||||||
|
(merge-rule "\IeC {\cyrnje }" "њ" :string)
|
||||||
|
(merge-rule "\IeC {\cyro }" "о" :string)
|
||||||
|
(merge-rule "\IeC {\cyrp }" "п" :string)
|
||||||
|
(merge-rule "\IeC {\cyrr }" "р" :string)
|
||||||
|
(merge-rule "\IeC {\cyrs }" "с" :string)
|
||||||
|
(merge-rule "\IeC {\cyrsftsn }" "ь" :string)
|
||||||
|
(merge-rule "\IeC {\cyrsh }" "ш" :string)
|
||||||
|
(merge-rule "\IeC {\cyrshch }" "щ" :string)
|
||||||
|
(merge-rule "\IeC {\cyrt }" "т" :string)
|
||||||
|
(merge-rule "\IeC {\cyrtshe }" "ћ" :string)
|
||||||
|
(merge-rule "\IeC {\cyru }" "у" :string)
|
||||||
|
(merge-rule "\IeC {\cyrushrt }" "ў" :string)
|
||||||
|
(merge-rule "\IeC {\cyrv }" "в" :string)
|
||||||
|
(merge-rule "\IeC {\cyrya }" "я" :string)
|
||||||
|
(merge-rule "\IeC {\cyryi }" "ї" :string)
|
||||||
|
(merge-rule "\IeC {\cyryo }" "ё" :string)
|
||||||
|
(merge-rule "\IeC {\cyryu }" "ю" :string)
|
||||||
|
(merge-rule "\IeC {\cyrz }" "з" :string)
|
||||||
|
(merge-rule "\IeC {\cyrzh }" "ж" :string)
|
||||||
239
build/latex/LICRlatin2utf8.xdy
Normal file
239
build/latex/LICRlatin2utf8.xdy
Normal file
|
|
@ -0,0 +1,239 @@
|
||||||
|
;; style file for xindy
|
||||||
|
;; filename: LICRlatin2utf8.xdy
|
||||||
|
;; description: style file for xindy which maps back LaTeX Internal
|
||||||
|
;; Character Representation of letters (as arising in .idx index
|
||||||
|
;; file) to UTF-8 encoding for correct sorting by xindy.
|
||||||
|
;; usage: for use with the pdflatex engine,
|
||||||
|
;; *not* for use with xelatex or lualatex.
|
||||||
|
;;
|
||||||
|
;; This is based upon xindy's distributed file tex/inputenc/utf8.xdy.
|
||||||
|
;; The modifications include:
|
||||||
|
;;
|
||||||
|
;; - Updates for compatibility with current LaTeX macro encoding.
|
||||||
|
;;
|
||||||
|
;; - Systematic usage of the \IeC {...} mark-up, because mark-up in
|
||||||
|
;; tex/inputenc/utf8.xdy was using it on seemingly random basis, and
|
||||||
|
;; Sphinx coercing of xindy usability for both Latin and Cyrillic scripts
|
||||||
|
;; with pdflatex requires its systematic presence here.
|
||||||
|
;;
|
||||||
|
;; - Support for some extra letters: Ÿ, Ŋ, ŋ, Œ, œ, IJ, ij, ȷ and ẞ.
|
||||||
|
;;
|
||||||
|
;; Indeed Sphinx needs to support for pdflatex engine all Unicode letters
|
||||||
|
;; available in TeX T1 font encoding. The above letters are found in
|
||||||
|
;; that encoding but not in the Latin1, 2, 3 charsets which are those
|
||||||
|
;; covered by original tex/inputenc/utf8.xdy.
|
||||||
|
;;
|
||||||
|
;; - There is a problem that ȷ is not supported out-of-the box by LaTeX
|
||||||
|
;; with inputenc, one must add explicitly
|
||||||
|
;; \DeclareUnicodeCharacter{0237}{\j}
|
||||||
|
;; to preamble of LaTeX document. However this character is not supported
|
||||||
|
;; by the TeX "times" font used by default by Sphinx for pdflatex engine.
|
||||||
|
;;
|
||||||
|
;; **Update**: since LaTeX 2018/12/01, the \j as well as \SS, \k{} and
|
||||||
|
;; \.{} need no extra user declaration anymore.
|
||||||
|
;;
|
||||||
|
;; - ẞ needs \DeclareUnicodeCharacter{1E9E}{\SS} (but ß needs no extra set-up).
|
||||||
|
;;
|
||||||
|
;; - U+02DB (˛) and U+02D9 (˙) are also not supported by inputenc
|
||||||
|
;; out of the box and require
|
||||||
|
;; \DeclareUnicodeCharacter{02DB}{\k{}}
|
||||||
|
;; \DeclareUnicodeCharacter{02D9}{\.{}}
|
||||||
|
;; to be added to preamble.
|
||||||
|
;;
|
||||||
|
;; - U+0127 ħ and U+0126 Ħ are absent from TeX T1+TS1 font encodings.
|
||||||
|
;;
|
||||||
|
;; - Characters Ŋ and ŋ are not supported by TeX font "times" used by
|
||||||
|
;; default by Sphinx for pdflatex engine but they are supported by
|
||||||
|
;; some TeX fonts, in particular by the default LaTeX font for T1
|
||||||
|
;; encoding.
|
||||||
|
;;
|
||||||
|
;; - " and ~ must be escaped as ~" and resp. ~~ in xindy merge rules.
|
||||||
|
;;
|
||||||
|
;; Contributed by the Sphinx team, July 2018.
|
||||||
|
;;
|
||||||
|
;; See sphinx.xdy for superior figures, as they are escaped by LaTeX writer.
|
||||||
|
(merge-rule "\IeC {\textonesuperior }" "¹" :string)
|
||||||
|
(merge-rule "\IeC {\texttwosuperior }" "²" :string)
|
||||||
|
(merge-rule "\IeC {\textthreesuperior }" "³" :string)
|
||||||
|
(merge-rule "\IeC {\'a}" "á" :string)
|
||||||
|
(merge-rule "\IeC {\'A}" "Á" :string)
|
||||||
|
(merge-rule "\IeC {\`a}" "à" :string)
|
||||||
|
(merge-rule "\IeC {\`A}" "À" :string)
|
||||||
|
(merge-rule "\IeC {\^a}" "â" :string)
|
||||||
|
(merge-rule "\IeC {\^A}" "Â" :string)
|
||||||
|
(merge-rule "\IeC {\~"a}" "ä" :string)
|
||||||
|
(merge-rule "\IeC {\~"A}" "Ä" :string)
|
||||||
|
(merge-rule "\IeC {\~~a}" "ã" :string)
|
||||||
|
(merge-rule "\IeC {\~~A}" "Ã" :string)
|
||||||
|
(merge-rule "\IeC {\c c}" "ç" :string)
|
||||||
|
(merge-rule "\IeC {\c C}" "Ç" :string)
|
||||||
|
(merge-rule "\IeC {\'c}" "ć" :string)
|
||||||
|
(merge-rule "\IeC {\'C}" "Ć" :string)
|
||||||
|
(merge-rule "\IeC {\^c}" "ĉ" :string)
|
||||||
|
(merge-rule "\IeC {\^C}" "Ĉ" :string)
|
||||||
|
(merge-rule "\IeC {\.c}" "ċ" :string)
|
||||||
|
(merge-rule "\IeC {\.C}" "Ċ" :string)
|
||||||
|
(merge-rule "\IeC {\c s}" "ş" :string)
|
||||||
|
(merge-rule "\IeC {\c S}" "Ş" :string)
|
||||||
|
(merge-rule "\IeC {\c t}" "ţ" :string)
|
||||||
|
(merge-rule "\IeC {\c T}" "Ţ" :string)
|
||||||
|
(merge-rule "\IeC {\-}" "" :string); soft hyphen
|
||||||
|
(merge-rule "\IeC {\textdiv }" "÷" :string)
|
||||||
|
(merge-rule "\IeC {\'e}" "é" :string)
|
||||||
|
(merge-rule "\IeC {\'E}" "É" :string)
|
||||||
|
(merge-rule "\IeC {\`e}" "è" :string)
|
||||||
|
(merge-rule "\IeC {\`E}" "È" :string)
|
||||||
|
(merge-rule "\IeC {\^e}" "ê" :string)
|
||||||
|
(merge-rule "\IeC {\^E}" "Ê" :string)
|
||||||
|
(merge-rule "\IeC {\~"e}" "ë" :string)
|
||||||
|
(merge-rule "\IeC {\~"E}" "Ë" :string)
|
||||||
|
(merge-rule "\IeC {\^g}" "ĝ" :string)
|
||||||
|
(merge-rule "\IeC {\^G}" "Ĝ" :string)
|
||||||
|
(merge-rule "\IeC {\.g}" "ġ" :string)
|
||||||
|
(merge-rule "\IeC {\.G}" "Ġ" :string)
|
||||||
|
(merge-rule "\IeC {\^h}" "ĥ" :string)
|
||||||
|
(merge-rule "\IeC {\^H}" "Ĥ" :string)
|
||||||
|
(merge-rule "\IeC {\H o}" "ő" :string)
|
||||||
|
(merge-rule "\IeC {\H O}" "Ő" :string)
|
||||||
|
(merge-rule "\IeC {\textacutedbl }" "˝" :string)
|
||||||
|
(merge-rule "\IeC {\H u}" "ű" :string)
|
||||||
|
(merge-rule "\IeC {\H U}" "Ű" :string)
|
||||||
|
(merge-rule "\IeC {\ae }" "æ" :string)
|
||||||
|
(merge-rule "\IeC {\AE }" "Æ" :string)
|
||||||
|
(merge-rule "\IeC {\textcopyright }" "©" :string)
|
||||||
|
(merge-rule "\IeC {\c \ }" "¸" :string)
|
||||||
|
(merge-rule "\IeC {\dh }" "ð" :string)
|
||||||
|
(merge-rule "\IeC {\DH }" "Ð" :string)
|
||||||
|
(merge-rule "\IeC {\dj }" "đ" :string)
|
||||||
|
(merge-rule "\IeC {\DJ }" "Đ" :string)
|
||||||
|
(merge-rule "\IeC {\guillemotleft }" "«" :string)
|
||||||
|
(merge-rule "\IeC {\guillemotright }" "»" :string)
|
||||||
|
(merge-rule "\IeC {\'\i }" "í" :string)
|
||||||
|
(merge-rule "\IeC {\`\i }" "ì" :string)
|
||||||
|
(merge-rule "\IeC {\^\i }" "î" :string)
|
||||||
|
(merge-rule "\IeC {\~"\i }" "ï" :string)
|
||||||
|
(merge-rule "\IeC {\i }" "ı" :string)
|
||||||
|
(merge-rule "\IeC {\^\j }" "ĵ" :string)
|
||||||
|
(merge-rule "\IeC {\k {}}" "˛" :string)
|
||||||
|
(merge-rule "\IeC {\l }" "ł" :string)
|
||||||
|
(merge-rule "\IeC {\L }" "Ł" :string)
|
||||||
|
(merge-rule "\IeC {\nobreakspace }" " " :string)
|
||||||
|
(merge-rule "\IeC {\o }" "ø" :string)
|
||||||
|
(merge-rule "\IeC {\O }" "Ø" :string)
|
||||||
|
(merge-rule "\IeC {\textsterling }" "£" :string)
|
||||||
|
(merge-rule "\IeC {\textparagraph }" "¶" :string)
|
||||||
|
(merge-rule "\IeC {\ss }" "ß" :string)
|
||||||
|
(merge-rule "\IeC {\textsection }" "§" :string)
|
||||||
|
(merge-rule "\IeC {\textbrokenbar }" "¦" :string)
|
||||||
|
(merge-rule "\IeC {\textcent }" "¢" :string)
|
||||||
|
(merge-rule "\IeC {\textcurrency }" "¤" :string)
|
||||||
|
(merge-rule "\IeC {\textdegree }" "°" :string)
|
||||||
|
(merge-rule "\IeC {\textexclamdown }" "¡" :string)
|
||||||
|
(merge-rule "\IeC {\texthbar }" "ħ" :string)
|
||||||
|
(merge-rule "\IeC {\textHbar }" "Ħ" :string)
|
||||||
|
(merge-rule "\IeC {\textonehalf }" "½" :string)
|
||||||
|
(merge-rule "\IeC {\textonequarter }" "¼" :string)
|
||||||
|
(merge-rule "\IeC {\textordfeminine }" "ª" :string)
|
||||||
|
(merge-rule "\IeC {\textordmasculine }" "º" :string)
|
||||||
|
(merge-rule "\IeC {\textperiodcentered }" "·" :string)
|
||||||
|
(merge-rule "\IeC {\textquestiondown }" "¿" :string)
|
||||||
|
(merge-rule "\IeC {\textregistered }" "®" :string)
|
||||||
|
(merge-rule "\IeC {\textthreequarters }" "¾" :string)
|
||||||
|
(merge-rule "\IeC {\textyen }" "¥" :string)
|
||||||
|
(merge-rule "\IeC {\th }" "þ" :string)
|
||||||
|
(merge-rule "\IeC {\TH }" "Þ" :string)
|
||||||
|
(merge-rule "\IeC {\'I}" "Í" :string)
|
||||||
|
(merge-rule "\IeC {\`I}" "Ì" :string)
|
||||||
|
(merge-rule "\IeC {\^I}" "Î" :string)
|
||||||
|
(merge-rule "\IeC {\~"I}" "Ï" :string)
|
||||||
|
(merge-rule "\IeC {\.I}" "İ" :string)
|
||||||
|
(merge-rule "\IeC {\^J}" "Ĵ" :string)
|
||||||
|
(merge-rule "\IeC {\k a}" "ą" :string)
|
||||||
|
(merge-rule "\IeC {\k A}" "Ą" :string)
|
||||||
|
(merge-rule "\IeC {\k e}" "ę" :string)
|
||||||
|
(merge-rule "\IeC {\k E}" "Ę" :string)
|
||||||
|
(merge-rule "\IeC {\'l}" "ĺ" :string)
|
||||||
|
(merge-rule "\IeC {\'L}" "Ĺ" :string)
|
||||||
|
(merge-rule "\IeC {\textlnot }" "¬" :string)
|
||||||
|
(merge-rule "\IeC {\textmu }" "µ" :string)
|
||||||
|
(merge-rule "\IeC {\'n}" "ń" :string)
|
||||||
|
(merge-rule "\IeC {\'N}" "Ń" :string)
|
||||||
|
(merge-rule "\IeC {\~~n}" "ñ" :string)
|
||||||
|
(merge-rule "\IeC {\~~N}" "Ñ" :string)
|
||||||
|
(merge-rule "\IeC {\'o}" "ó" :string)
|
||||||
|
(merge-rule "\IeC {\'O}" "Ó" :string)
|
||||||
|
(merge-rule "\IeC {\`o}" "ò" :string)
|
||||||
|
(merge-rule "\IeC {\`O}" "Ò" :string)
|
||||||
|
(merge-rule "\IeC {\^o}" "ô" :string)
|
||||||
|
(merge-rule "\IeC {\^O}" "Ô" :string)
|
||||||
|
(merge-rule "\IeC {\~"o}" "ö" :string)
|
||||||
|
(merge-rule "\IeC {\~"O}" "Ö" :string)
|
||||||
|
(merge-rule "\IeC {\~~o}" "õ" :string)
|
||||||
|
(merge-rule "\IeC {\~~O}" "Õ" :string)
|
||||||
|
(merge-rule "\IeC {\textpm }" "±" :string)
|
||||||
|
(merge-rule "\IeC {\r a}" "å" :string)
|
||||||
|
(merge-rule "\IeC {\r A}" "Å" :string)
|
||||||
|
(merge-rule "\IeC {\'r}" "ŕ" :string)
|
||||||
|
(merge-rule "\IeC {\'R}" "Ŕ" :string)
|
||||||
|
(merge-rule "\IeC {\r u}" "ů" :string)
|
||||||
|
(merge-rule "\IeC {\r U}" "Ů" :string)
|
||||||
|
(merge-rule "\IeC {\'s}" "ś" :string)
|
||||||
|
(merge-rule "\IeC {\'S}" "Ś" :string)
|
||||||
|
(merge-rule "\IeC {\^s}" "ŝ" :string)
|
||||||
|
(merge-rule "\IeC {\^S}" "Ŝ" :string)
|
||||||
|
(merge-rule "\IeC {\textasciidieresis }" "¨" :string)
|
||||||
|
(merge-rule "\IeC {\textasciimacron }" "¯" :string)
|
||||||
|
(merge-rule "\IeC {\.{}}" "˙" :string)
|
||||||
|
(merge-rule "\IeC {\textasciiacute }" "´" :string)
|
||||||
|
(merge-rule "\IeC {\texttimes }" "×" :string)
|
||||||
|
(merge-rule "\IeC {\u a}" "ă" :string)
|
||||||
|
(merge-rule "\IeC {\u A}" "Ă" :string)
|
||||||
|
(merge-rule "\IeC {\u g}" "ğ" :string)
|
||||||
|
(merge-rule "\IeC {\u G}" "Ğ" :string)
|
||||||
|
(merge-rule "\IeC {\textasciibreve }" "˘" :string)
|
||||||
|
(merge-rule "\IeC {\'u}" "ú" :string)
|
||||||
|
(merge-rule "\IeC {\'U}" "Ú" :string)
|
||||||
|
(merge-rule "\IeC {\`u}" "ù" :string)
|
||||||
|
(merge-rule "\IeC {\`U}" "Ù" :string)
|
||||||
|
(merge-rule "\IeC {\^u}" "û" :string)
|
||||||
|
(merge-rule "\IeC {\^U}" "Û" :string)
|
||||||
|
(merge-rule "\IeC {\~"u}" "ü" :string)
|
||||||
|
(merge-rule "\IeC {\~"U}" "Ü" :string)
|
||||||
|
(merge-rule "\IeC {\u u}" "ŭ" :string)
|
||||||
|
(merge-rule "\IeC {\u U}" "Ŭ" :string)
|
||||||
|
(merge-rule "\IeC {\v c}" "č" :string)
|
||||||
|
(merge-rule "\IeC {\v C}" "Č" :string)
|
||||||
|
(merge-rule "\IeC {\v d}" "ď" :string)
|
||||||
|
(merge-rule "\IeC {\v D}" "Ď" :string)
|
||||||
|
(merge-rule "\IeC {\v e}" "ě" :string)
|
||||||
|
(merge-rule "\IeC {\v E}" "Ě" :string)
|
||||||
|
(merge-rule "\IeC {\v l}" "ľ" :string)
|
||||||
|
(merge-rule "\IeC {\v L}" "Ľ" :string)
|
||||||
|
(merge-rule "\IeC {\v n}" "ň" :string)
|
||||||
|
(merge-rule "\IeC {\v N}" "Ň" :string)
|
||||||
|
(merge-rule "\IeC {\v r}" "ř" :string)
|
||||||
|
(merge-rule "\IeC {\v R}" "Ř" :string)
|
||||||
|
(merge-rule "\IeC {\v s}" "š" :string)
|
||||||
|
(merge-rule "\IeC {\v S}" "Š" :string)
|
||||||
|
(merge-rule "\IeC {\textasciicaron }" "ˇ" :string)
|
||||||
|
(merge-rule "\IeC {\v t}" "ť" :string)
|
||||||
|
(merge-rule "\IeC {\v T}" "Ť" :string)
|
||||||
|
(merge-rule "\IeC {\v z}" "ž" :string)
|
||||||
|
(merge-rule "\IeC {\v Z}" "Ž" :string)
|
||||||
|
(merge-rule "\IeC {\'y}" "ý" :string)
|
||||||
|
(merge-rule "\IeC {\'Y}" "Ý" :string)
|
||||||
|
(merge-rule "\IeC {\~"y}" "ÿ" :string)
|
||||||
|
(merge-rule "\IeC {\'z}" "ź" :string)
|
||||||
|
(merge-rule "\IeC {\'Z}" "Ź" :string)
|
||||||
|
(merge-rule "\IeC {\.z}" "ż" :string)
|
||||||
|
(merge-rule "\IeC {\.Z}" "Ż" :string)
|
||||||
|
;; letters not in Latin1, 2, 3 but available in TeX T1 font encoding
|
||||||
|
(merge-rule "\IeC {\~"Y}" "Ÿ" :string)
|
||||||
|
(merge-rule "\IeC {\NG }" "Ŋ" :string)
|
||||||
|
(merge-rule "\IeC {\ng }" "ŋ" :string)
|
||||||
|
(merge-rule "\IeC {\OE }" "Œ" :string)
|
||||||
|
(merge-rule "\IeC {\oe }" "œ" :string)
|
||||||
|
(merge-rule "\IeC {\IJ }" "IJ" :string)
|
||||||
|
(merge-rule "\IeC {\ij }" "ij" :string)
|
||||||
|
(merge-rule "\IeC {\j }" "ȷ" :string)
|
||||||
|
(merge-rule "\IeC {\SS }" "ẞ" :string)
|
||||||
611
build/latex/LatinRules.xdy
Normal file
611
build/latex/LatinRules.xdy
Normal file
|
|
@ -0,0 +1,611 @@
|
||||||
|
;; Common Lisp style file for xindy
|
||||||
|
;; filename: LatinRules.xdy
|
||||||
|
;;
|
||||||
|
;; Please note that this data file deliberately uses strings
|
||||||
|
;; with single non-ascii bytes. This is intentional and
|
||||||
|
;; follows the usage observed in similar xindy support files.
|
||||||
|
;;
|
||||||
|
;; It is based upon xindy's files lang/general/utf8.xdy and
|
||||||
|
;; lang/general/utf8-lang.xdy which implement
|
||||||
|
;; "a general sorting order for Western European languages".
|
||||||
|
;;
|
||||||
|
;; The aim for Sphinx is to be able to index in a Cyrillic document
|
||||||
|
;; also terms using the Latin alphabets, inclusive of letters
|
||||||
|
;; with diacritics. To this effect the xindy rules from lang/general
|
||||||
|
;; got manually re-coded to avoid collisions with the encoding
|
||||||
|
;; done by xindy for sorting words in Cyrillic languages, which was
|
||||||
|
;; observed not to use bytes with octal encoding 0o266 or higher.
|
||||||
|
;;
|
||||||
|
;; So here we use only 0o266 or higher bytes.
|
||||||
|
;; (Ŋ, ŋ, IJ, and ij are absent from
|
||||||
|
;; lang/general/utf8.xdy and not included here.)
|
||||||
|
;; Contributed by the Sphinx team, 2018.
|
||||||
|
|
||||||
|
(define-letter-group "A" :prefixes ("¶"))
|
||||||
|
(define-letter-group "B" :after "A" :prefixes ("·"))
|
||||||
|
(define-letter-group "C" :after "B" :prefixes ("¸"))
|
||||||
|
(define-letter-group "D" :after "C" :prefixes ("¹"))
|
||||||
|
(define-letter-group "E" :after "D" :prefixes ("º"))
|
||||||
|
(define-letter-group "F" :after "E" :prefixes ("»"))
|
||||||
|
(define-letter-group "G" :after "F" :prefixes ("¼"))
|
||||||
|
(define-letter-group "H" :after "G" :prefixes ("½"))
|
||||||
|
(define-letter-group "I" :after "H" :prefixes ("¾"))
|
||||||
|
(define-letter-group "J" :after "I" :prefixes ("¿"))
|
||||||
|
(define-letter-group "K" :after "J" :prefixes ("À"))
|
||||||
|
(define-letter-group "L" :after "K" :prefixes ("Á"))
|
||||||
|
(define-letter-group "M" :after "L" :prefixes ("Â"))
|
||||||
|
(define-letter-group "N" :after "M" :prefixes ("Ã"))
|
||||||
|
(define-letter-group "O" :after "N" :prefixes ("Ä"))
|
||||||
|
(define-letter-group "P" :after "O" :prefixes ("È"))
|
||||||
|
(define-letter-group "Q" :after "P" :prefixes ("Ê"))
|
||||||
|
(define-letter-group "R" :after "Q" :prefixes ("Ë"))
|
||||||
|
(define-letter-group "S" :after "R" :prefixes ("Ð"))
|
||||||
|
(define-letter-group "T" :after "S" :prefixes ("Ú"))
|
||||||
|
(define-letter-group "U" :after "T" :prefixes ("à"))
|
||||||
|
(define-letter-group "V" :after "U" :prefixes ("å"))
|
||||||
|
(define-letter-group "W" :after "V" :prefixes ("æ"))
|
||||||
|
(define-letter-group "X" :after "W" :prefixes ("ë"))
|
||||||
|
(define-letter-group "Y" :after "X" :prefixes ("í"))
|
||||||
|
(define-letter-group "Z" :after "Y" :prefixes ("ð"))
|
||||||
|
|
||||||
|
(define-rule-set "sphinx-xy-alphabetize"
|
||||||
|
|
||||||
|
:rules (("À" "¶" :string)
|
||||||
|
("Ä‚" "¶" :string)
|
||||||
|
("â" "¶" :string)
|
||||||
|
("Ä" "¶" :string)
|
||||||
|
("Ã " "¶" :string)
|
||||||
|
("Ã…" "¶" :string)
|
||||||
|
("Ã" "¶" :string)
|
||||||
|
("Ã<>" "¶" :string)
|
||||||
|
("á" "¶" :string)
|
||||||
|
("ã" "¶" :string)
|
||||||
|
("Â" "¶" :string)
|
||||||
|
("ă" "¶" :string)
|
||||||
|
("Ã¥" "¶" :string)
|
||||||
|
("Ä…" "¶" :string)
|
||||||
|
("ä" "¶" :string)
|
||||||
|
("Ä„" "¶" :string)
|
||||||
|
("æ" "¶º" :string)
|
||||||
|
("Æ" "¶º" :string)
|
||||||
|
("ć" "¸" :string)
|
||||||
|
("ĉ" "¸" :string)
|
||||||
|
("ç" "¸" :string)
|
||||||
|
("ÄŒ" "¸" :string)
|
||||||
|
("Ä<>" "¸" :string)
|
||||||
|
("Ĉ" "¸" :string)
|
||||||
|
("Ç" "¸" :string)
|
||||||
|
("Ć" "¸" :string)
|
||||||
|
("Ä<>" "¹" :string)
|
||||||
|
("Ä<>" "¹" :string)
|
||||||
|
("ÄŽ" "¹" :string)
|
||||||
|
("Ä‘" "¹" :string)
|
||||||
|
("ê" "º" :string)
|
||||||
|
("Ę" "º" :string)
|
||||||
|
("Äš" "º" :string)
|
||||||
|
("ë" "º" :string)
|
||||||
|
("Ä›" "º" :string)
|
||||||
|
("é" "º" :string)
|
||||||
|
("È" "º" :string)
|
||||||
|
("Ë" "º" :string)
|
||||||
|
("É" "º" :string)
|
||||||
|
("è" "º" :string)
|
||||||
|
("Ê" "º" :string)
|
||||||
|
("Ä™" "º" :string)
|
||||||
|
("Ä<>" "¼" :string)
|
||||||
|
("ÄŸ" "¼" :string)
|
||||||
|
("Äž" "¼" :string)
|
||||||
|
("Äœ" "¼" :string)
|
||||||
|
("Ä¥" "½" :string)
|
||||||
|
("Ĥ" "½" :string)
|
||||||
|
("Ã<>" "¾" :string)
|
||||||
|
("Ã<>" "¾" :string)
|
||||||
|
("ï" "¾" :string)
|
||||||
|
("ÃŽ" "¾" :string)
|
||||||
|
("î" "¾" :string)
|
||||||
|
("ı" "¾" :string)
|
||||||
|
("İ" "¾" :string)
|
||||||
|
("Ã" "¾" :string)
|
||||||
|
("ÃŒ" "¾" :string)
|
||||||
|
("ì" "¾" :string)
|
||||||
|
("Ä´" "¿" :string)
|
||||||
|
("ĵ" "¿" :string)
|
||||||
|
("Å‚" "Á" :string)
|
||||||
|
("Å<>" "Á" :string)
|
||||||
|
("ľ" "Á" :string)
|
||||||
|
("Ľ" "Á" :string)
|
||||||
|
("Å„" "Ã" :string)
|
||||||
|
("Ń" "Ã" :string)
|
||||||
|
("ñ" "Ã" :string)
|
||||||
|
("ň" "Ã" :string)
|
||||||
|
("Ñ" "Ã" :string)
|
||||||
|
("Ň" "Ã" :string)
|
||||||
|
("Õ" "Ä" :string)
|
||||||
|
("Å<>" "Ä" :string)
|
||||||
|
("ó" "Ä" :string)
|
||||||
|
("ö" "Ä" :string)
|
||||||
|
("ô" "Ä" :string)
|
||||||
|
("Å‘" "Ä" :string)
|
||||||
|
("Ø" "Ä" :string)
|
||||||
|
("Ö" "Ä" :string)
|
||||||
|
("õ" "Ä" :string)
|
||||||
|
("Ô" "Ä" :string)
|
||||||
|
("ø" "Ä" :string)
|
||||||
|
("Ó" "Ä" :string)
|
||||||
|
("Ã’" "Ä" :string)
|
||||||
|
("ò" "Ä" :string)
|
||||||
|
("œ" "ĺ" :string)
|
||||||
|
("Œ" "ĺ" :string)
|
||||||
|
("Ř" "Ë" :string)
|
||||||
|
("Å™" "Ë" :string)
|
||||||
|
("Å”" "Ë" :string)
|
||||||
|
("Å•" "Ë" :string)
|
||||||
|
("Å<>" "Ð" :string)
|
||||||
|
("Åš" "Ð" :string)
|
||||||
|
("È™" "Ð" :string)
|
||||||
|
("ÅŸ" "Ð" :string)
|
||||||
|
("Åœ" "Ð" :string)
|
||||||
|
("Å›" "Ð" :string)
|
||||||
|
("Ș" "Ð" :string)
|
||||||
|
("Å¡" "Ð" :string)
|
||||||
|
("Åž" "Ð" :string)
|
||||||
|
("Å " "Ð" :string)
|
||||||
|
("ß" "ÐÐ" :string)
|
||||||
|
("Èš" "Ú" :string)
|
||||||
|
("Ť" "Ú" :string)
|
||||||
|
("È›" "Ú" :string)
|
||||||
|
("Å¥" "Ú" :string)
|
||||||
|
("û" "à" :string)
|
||||||
|
("Å" "à" :string)
|
||||||
|
("ů" "à" :string)
|
||||||
|
("ű" "à" :string)
|
||||||
|
("ù" "à" :string)
|
||||||
|
("Ŭ" "à" :string)
|
||||||
|
("Ù" "à" :string)
|
||||||
|
("Ű" "à" :string)
|
||||||
|
("Ü" "à" :string)
|
||||||
|
("Å®" "à" :string)
|
||||||
|
("ú" "à" :string)
|
||||||
|
("Ú" "à" :string)
|
||||||
|
("Û" "à" :string)
|
||||||
|
("ü" "à" :string)
|
||||||
|
("ÿ" "í" :string)
|
||||||
|
("Ã<>" "í" :string)
|
||||||
|
("Ÿ" "í" :string)
|
||||||
|
("ý" "í" :string)
|
||||||
|
("Å»" "ð" :string)
|
||||||
|
("Ž" "ð" :string)
|
||||||
|
("Ź" "ð" :string)
|
||||||
|
("ž" "ð" :string)
|
||||||
|
("ż" "ð" :string)
|
||||||
|
("ź" "ð" :string)
|
||||||
|
("a" "¶" :string)
|
||||||
|
("A" "¶" :string)
|
||||||
|
("b" "·" :string)
|
||||||
|
("B" "·" :string)
|
||||||
|
("c" "¸" :string)
|
||||||
|
("C" "¸" :string)
|
||||||
|
("d" "¹" :string)
|
||||||
|
("D" "¹" :string)
|
||||||
|
("e" "º" :string)
|
||||||
|
("E" "º" :string)
|
||||||
|
("F" "»" :string)
|
||||||
|
("f" "»" :string)
|
||||||
|
("G" "¼" :string)
|
||||||
|
("g" "¼" :string)
|
||||||
|
("H" "½" :string)
|
||||||
|
("h" "½" :string)
|
||||||
|
("i" "¾" :string)
|
||||||
|
("I" "¾" :string)
|
||||||
|
("J" "¿" :string)
|
||||||
|
("j" "¿" :string)
|
||||||
|
("K" "À" :string)
|
||||||
|
("k" "À" :string)
|
||||||
|
("L" "Á" :string)
|
||||||
|
("l" "Á" :string)
|
||||||
|
("M" "Â" :string)
|
||||||
|
("m" "Â" :string)
|
||||||
|
("n" "Ã" :string)
|
||||||
|
("N" "Ã" :string)
|
||||||
|
("O" "Ä" :string)
|
||||||
|
("o" "Ä" :string)
|
||||||
|
("p" "È" :string)
|
||||||
|
("P" "È" :string)
|
||||||
|
("Q" "Ê" :string)
|
||||||
|
("q" "Ê" :string)
|
||||||
|
("r" "Ë" :string)
|
||||||
|
("R" "Ë" :string)
|
||||||
|
("S" "Ð" :string)
|
||||||
|
("s" "Ð" :string)
|
||||||
|
("t" "Ú" :string)
|
||||||
|
("T" "Ú" :string)
|
||||||
|
("u" "à" :string)
|
||||||
|
("U" "à" :string)
|
||||||
|
("v" "å" :string)
|
||||||
|
("V" "å" :string)
|
||||||
|
("W" "æ" :string)
|
||||||
|
("w" "æ" :string)
|
||||||
|
("x" "ë" :string)
|
||||||
|
("X" "ë" :string)
|
||||||
|
("Y" "í" :string)
|
||||||
|
("y" "í" :string)
|
||||||
|
("z" "ð" :string)
|
||||||
|
("Z" "ð" :string)
|
||||||
|
))
|
||||||
|
|
||||||
|
(define-rule-set "sphinx-xy-resolve-diacritics"
|
||||||
|
|
||||||
|
:rules (("Ĥ" "£" :string)
|
||||||
|
("ó" "£" :string)
|
||||||
|
("ľ" "£" :string)
|
||||||
|
("Ř" "£" :string)
|
||||||
|
("Ä<>" "£" :string)
|
||||||
|
("Ä<>" "£" :string)
|
||||||
|
("Äš" "£" :string)
|
||||||
|
("Ä¥" "£" :string)
|
||||||
|
("ÄŒ" "£" :string)
|
||||||
|
("Ä´" "£" :string)
|
||||||
|
("Ä›" "£" :string)
|
||||||
|
("ž" "£" :string)
|
||||||
|
("ÄŽ" "£" :string)
|
||||||
|
("Å™" "£" :string)
|
||||||
|
("Ž" "£" :string)
|
||||||
|
("ı" "£" :string)
|
||||||
|
("Ť" "£" :string)
|
||||||
|
("á" "£" :string)
|
||||||
|
("Ä<>" "£" :string)
|
||||||
|
("Ã<>" "£" :string)
|
||||||
|
("ň" "£" :string)
|
||||||
|
("Å " "£" :string)
|
||||||
|
("Ň" "£" :string)
|
||||||
|
("ĵ" "£" :string)
|
||||||
|
("Å¥" "£" :string)
|
||||||
|
("Ó" "£" :string)
|
||||||
|
("ý" "£" :string)
|
||||||
|
("Äœ" "£" :string)
|
||||||
|
("Ú" "£" :string)
|
||||||
|
("Ľ" "£" :string)
|
||||||
|
("Å¡" "£" :string)
|
||||||
|
("Ã<>" "£" :string)
|
||||||
|
("ú" "£" :string)
|
||||||
|
("Åš" "¤" :string)
|
||||||
|
("ć" "¤" :string)
|
||||||
|
("Å<>" "¤" :string)
|
||||||
|
("Å‚" "¤" :string)
|
||||||
|
("Å„" "¤" :string)
|
||||||
|
("À" "¤" :string)
|
||||||
|
("Ź" "¤" :string)
|
||||||
|
("Ã " "¤" :string)
|
||||||
|
("Ń" "¤" :string)
|
||||||
|
("Ä<>" "¤" :string)
|
||||||
|
("ÿ" "¤" :string)
|
||||||
|
("Å›" "¤" :string)
|
||||||
|
("Äž" "¤" :string)
|
||||||
|
("ÄŸ" "¤" :string)
|
||||||
|
("Ù" "¤" :string)
|
||||||
|
("İ" "¤" :string)
|
||||||
|
("Ä‘" "¤" :string)
|
||||||
|
("ù" "¤" :string)
|
||||||
|
("Èš" "¤" :string)
|
||||||
|
("é" "¤" :string)
|
||||||
|
("Å•" "¤" :string)
|
||||||
|
("Ć" "¤" :string)
|
||||||
|
("È›" "¤" :string)
|
||||||
|
("ò" "¤" :string)
|
||||||
|
("ź" "¤" :string)
|
||||||
|
("Ã’" "¤" :string)
|
||||||
|
("Ÿ" "¤" :string)
|
||||||
|
("Å”" "¤" :string)
|
||||||
|
("É" "¤" :string)
|
||||||
|
("ĉ" "¥" :string)
|
||||||
|
("ô" "¥" :string)
|
||||||
|
("Ã<>" "¥" :string)
|
||||||
|
("Å<>" "¥" :string)
|
||||||
|
("Å»" "¥" :string)
|
||||||
|
("Ä‚" "¥" :string)
|
||||||
|
("Åœ" "¥" :string)
|
||||||
|
("ñ" "¥" :string)
|
||||||
|
("Å" "¥" :string)
|
||||||
|
("Ã" "¥" :string)
|
||||||
|
("È" "¥" :string)
|
||||||
|
("Ô" "¥" :string)
|
||||||
|
("Ŭ" "¥" :string)
|
||||||
|
("ż" "¥" :string)
|
||||||
|
("Ñ" "¥" :string)
|
||||||
|
("è" "¥" :string)
|
||||||
|
("Ĉ" "¥" :string)
|
||||||
|
("ă" "¥" :string)
|
||||||
|
("â" "¦" :string)
|
||||||
|
("û" "¦" :string)
|
||||||
|
("ê" "¦" :string)
|
||||||
|
("Õ" "¦" :string)
|
||||||
|
("õ" "¦" :string)
|
||||||
|
("È™" "¦" :string)
|
||||||
|
("ç" "¦" :string)
|
||||||
|
("Â" "¦" :string)
|
||||||
|
("Ê" "¦" :string)
|
||||||
|
("Û" "¦" :string)
|
||||||
|
("Ç" "¦" :string)
|
||||||
|
("ì" "¦" :string)
|
||||||
|
("ÃŒ" "¦" :string)
|
||||||
|
("Ș" "¦" :string)
|
||||||
|
("ö" "§" :string)
|
||||||
|
("Ö" "§" :string)
|
||||||
|
("ÅŸ" "§" :string)
|
||||||
|
("ů" "§" :string)
|
||||||
|
("ë" "§" :string)
|
||||||
|
("ã" "§" :string)
|
||||||
|
("î" "§" :string)
|
||||||
|
("ÃŽ" "§" :string)
|
||||||
|
("Ã" "§" :string)
|
||||||
|
("Åž" "§" :string)
|
||||||
|
("Å®" "§" :string)
|
||||||
|
("Ë" "§" :string)
|
||||||
|
("ï" "¨" :string)
|
||||||
|
("Å<>" "¨" :string)
|
||||||
|
("Ã<>" "¨" :string)
|
||||||
|
("Ę" "¨" :string)
|
||||||
|
("Å‘" "¨" :string)
|
||||||
|
("Ü" "¨" :string)
|
||||||
|
("Ã…" "¨" :string)
|
||||||
|
("ü" "¨" :string)
|
||||||
|
("Ä™" "¨" :string)
|
||||||
|
("Ã¥" "¨" :string)
|
||||||
|
("Ä" "©" :string)
|
||||||
|
("ű" "©" :string)
|
||||||
|
("Ø" "©" :string)
|
||||||
|
("ø" "©" :string)
|
||||||
|
("Ű" "©" :string)
|
||||||
|
("ä" "©" :string)
|
||||||
|
("Ä„" "ª" :string)
|
||||||
|
("Ä…" "ª" :string)
|
||||||
|
("Å“" "ÿ" :string)
|
||||||
|
("ß" "ÿ" :string)
|
||||||
|
("Æ" "ÿ" :string)
|
||||||
|
("Å’" "ÿ" :string)
|
||||||
|
("æ" "ÿ" :string)
|
||||||
|
("e" "¢" :string)
|
||||||
|
("t" "¢" :string)
|
||||||
|
("L" "¢" :string)
|
||||||
|
("Y" "¢" :string)
|
||||||
|
("J" "¢" :string)
|
||||||
|
("a" "¢" :string)
|
||||||
|
("p" "¢" :string)
|
||||||
|
("u" "¢" :string)
|
||||||
|
("j" "¢" :string)
|
||||||
|
("b" "¢" :string)
|
||||||
|
("G" "¢" :string)
|
||||||
|
("U" "¢" :string)
|
||||||
|
("F" "¢" :string)
|
||||||
|
("H" "¢" :string)
|
||||||
|
("i" "¢" :string)
|
||||||
|
("z" "¢" :string)
|
||||||
|
("c" "¢" :string)
|
||||||
|
("l" "¢" :string)
|
||||||
|
("A" "¢" :string)
|
||||||
|
("Q" "¢" :string)
|
||||||
|
("w" "¢" :string)
|
||||||
|
("D" "¢" :string)
|
||||||
|
("R" "¢" :string)
|
||||||
|
("d" "¢" :string)
|
||||||
|
("s" "¢" :string)
|
||||||
|
("r" "¢" :string)
|
||||||
|
("k" "¢" :string)
|
||||||
|
("v" "¢" :string)
|
||||||
|
("m" "¢" :string)
|
||||||
|
("P" "¢" :string)
|
||||||
|
("y" "¢" :string)
|
||||||
|
("K" "¢" :string)
|
||||||
|
("q" "¢" :string)
|
||||||
|
("S" "¢" :string)
|
||||||
|
("I" "¢" :string)
|
||||||
|
("C" "¢" :string)
|
||||||
|
("M" "¢" :string)
|
||||||
|
("Z" "¢" :string)
|
||||||
|
("T" "¢" :string)
|
||||||
|
("W" "¢" :string)
|
||||||
|
("B" "¢" :string)
|
||||||
|
("h" "¢" :string)
|
||||||
|
("x" "¢" :string)
|
||||||
|
("X" "¢" :string)
|
||||||
|
("f" "¢" :string)
|
||||||
|
("E" "¢" :string)
|
||||||
|
("V" "¢" :string)
|
||||||
|
("N" "¢" :string)
|
||||||
|
("O" "¢" :string)
|
||||||
|
("o" "¢" :string)
|
||||||
|
("g" "¢" :string)
|
||||||
|
("n" "¢" :string)
|
||||||
|
))
|
||||||
|
|
||||||
|
(define-rule-set "sphinx-xy-resolve-case"
|
||||||
|
|
||||||
|
:rules (("Ú" "8" :string)
|
||||||
|
("Ÿ" "8" :string)
|
||||||
|
("Ç" "8" :string)
|
||||||
|
("Ĉ" "8" :string)
|
||||||
|
("Å”" "8" :string)
|
||||||
|
("Ľ" "8" :string)
|
||||||
|
("Å®" "8" :string)
|
||||||
|
("Ã<>" "8" :string)
|
||||||
|
("É" "8" :string)
|
||||||
|
("Ë" "8" :string)
|
||||||
|
("Ș" "8" :string)
|
||||||
|
("Ì" "8" :string)
|
||||||
|
("Ê" "8" :string)
|
||||||
|
("Ň" "8" :string)
|
||||||
|
("Ä„" "8" :string)
|
||||||
|
("Å " "8" :string)
|
||||||
|
("Û" "8" :string)
|
||||||
|
("Åž" "8" :string)
|
||||||
|
("Ć" "8" :string)
|
||||||
|
("Ã’" "8" :string)
|
||||||
|
("Ĝ" "8" :string)
|
||||||
|
("Ñ" "8" :string)
|
||||||
|
("Ó" "8" :string)
|
||||||
|
("ÃŽ" "8" :string)
|
||||||
|
("Ã<>" "8" :string)
|
||||||
|
("Ã" "8" :string)
|
||||||
|
("Èš" "8" :string)
|
||||||
|
("Ã…" "8" :string)
|
||||||
|
("Äž" "8" :string)
|
||||||
|
("Ü" "8" :string)
|
||||||
|
("È" "8" :string)
|
||||||
|
("Ô" "8" :string)
|
||||||
|
("İ" "8" :string)
|
||||||
|
("Ű" "8" :string)
|
||||||
|
("Ù" "8" :string)
|
||||||
|
("Ŭ" "8" :string)
|
||||||
|
("Â" "8" :string)
|
||||||
|
("Ť" "8" :string)
|
||||||
|
("Ń" "8" :string)
|
||||||
|
("ÄŽ" "8" :string)
|
||||||
|
("Ź" "8" :string)
|
||||||
|
("Ž" "8" :string)
|
||||||
|
("Ä<>" "8" :string)
|
||||||
|
("Ŝ" "8" :string)
|
||||||
|
("Č" "8" :string)
|
||||||
|
("Ä´" "8" :string)
|
||||||
|
("Ö" "8" :string)
|
||||||
|
("Ø" "8" :string)
|
||||||
|
("Å»" "8" :string)
|
||||||
|
("Å<>" "8" :string)
|
||||||
|
("Ä‚" "8" :string)
|
||||||
|
("Äš" "8" :string)
|
||||||
|
("Å<>" "8" :string)
|
||||||
|
("Õ" "8" :string)
|
||||||
|
("Ę" "8" :string)
|
||||||
|
("Ã<>" "8" :string)
|
||||||
|
("À" "8" :string)
|
||||||
|
("Ĥ" "8" :string)
|
||||||
|
("Ä" "8" :string)
|
||||||
|
("Åš" "8" :string)
|
||||||
|
("Ř" "8" :string)
|
||||||
|
("Ã<>" "8" :string)
|
||||||
|
("Å’" "89" :string)
|
||||||
|
("Æ" "89" :string)
|
||||||
|
("ì" "9" :string)
|
||||||
|
("è" "9" :string)
|
||||||
|
("Ä…" "9" :string)
|
||||||
|
("Å¡" "9" :string)
|
||||||
|
("ú" "9" :string)
|
||||||
|
("Ã¥" "9" :string)
|
||||||
|
("ă" "9" :string)
|
||||||
|
("Ä™" "9" :string)
|
||||||
|
("ü" "9" :string)
|
||||||
|
("ź" "9" :string)
|
||||||
|
("ò" "9" :string)
|
||||||
|
("Å¥" "9" :string)
|
||||||
|
("È›" "9" :string)
|
||||||
|
("ĵ" "9" :string)
|
||||||
|
("Å•" "9" :string)
|
||||||
|
("ż" "9" :string)
|
||||||
|
("ä" "9" :string)
|
||||||
|
("ý" "9" :string)
|
||||||
|
("ù" "9" :string)
|
||||||
|
("á" "9" :string)
|
||||||
|
("é" "9" :string)
|
||||||
|
("Ä<>" "9" :string)
|
||||||
|
("ň" "9" :string)
|
||||||
|
("Å›" "9" :string)
|
||||||
|
("ø" "9" :string)
|
||||||
|
("Ã" "9" :string)
|
||||||
|
("Ä‘" "9" :string)
|
||||||
|
("ı" "9" :string)
|
||||||
|
("ÄŸ" "9" :string)
|
||||||
|
("î" "9" :string)
|
||||||
|
("ã" "9" :string)
|
||||||
|
("Ã " "9" :string)
|
||||||
|
("Å™" "9" :string)
|
||||||
|
("Å‘" "9" :string)
|
||||||
|
("ů" "9" :string)
|
||||||
|
("È™" "9" :string)
|
||||||
|
("ÿ" "9" :string)
|
||||||
|
("ë" "9" :string)
|
||||||
|
("Å" "9" :string)
|
||||||
|
("ç" "9" :string)
|
||||||
|
("ű" "9" :string)
|
||||||
|
("ñ" "9" :string)
|
||||||
|
("õ" "9" :string)
|
||||||
|
("Ä›" "9" :string)
|
||||||
|
("ÅŸ" "9" :string)
|
||||||
|
("ž" "9" :string)
|
||||||
|
("Ä<>" "9" :string)
|
||||||
|
("Å<>" "9" :string)
|
||||||
|
("Å„" "9" :string)
|
||||||
|
("û" "9" :string)
|
||||||
|
("Å‚" "9" :string)
|
||||||
|
("Ä<>" "9" :string)
|
||||||
|
("Ä¥" "9" :string)
|
||||||
|
("ê" "9" :string)
|
||||||
|
("ô" "9" :string)
|
||||||
|
("ĉ" "9" :string)
|
||||||
|
("â" "9" :string)
|
||||||
|
("ć" "9" :string)
|
||||||
|
("ï" "9" :string)
|
||||||
|
("ö" "9" :string)
|
||||||
|
("ľ" "9" :string)
|
||||||
|
("ó" "9" :string)
|
||||||
|
("æ" "99" :string)
|
||||||
|
("ß" "99" :string)
|
||||||
|
("Å“" "99" :string)
|
||||||
|
("N" "8" :string)
|
||||||
|
("V" "8" :string)
|
||||||
|
("O" "8" :string)
|
||||||
|
("X" "8" :string)
|
||||||
|
("E" "8" :string)
|
||||||
|
("P" "8" :string)
|
||||||
|
("K" "8" :string)
|
||||||
|
("T" "8" :string)
|
||||||
|
("Z" "8" :string)
|
||||||
|
("M" "8" :string)
|
||||||
|
("C" "8" :string)
|
||||||
|
("I" "8" :string)
|
||||||
|
("S" "8" :string)
|
||||||
|
("B" "8" :string)
|
||||||
|
("W" "8" :string)
|
||||||
|
("D" "8" :string)
|
||||||
|
("R" "8" :string)
|
||||||
|
("H" "8" :string)
|
||||||
|
("F" "8" :string)
|
||||||
|
("Q" "8" :string)
|
||||||
|
("A" "8" :string)
|
||||||
|
("G" "8" :string)
|
||||||
|
("U" "8" :string)
|
||||||
|
("J" "8" :string)
|
||||||
|
("Y" "8" :string)
|
||||||
|
("L" "8" :string)
|
||||||
|
("o" "9" :string)
|
||||||
|
("n" "9" :string)
|
||||||
|
("g" "9" :string)
|
||||||
|
("x" "9" :string)
|
||||||
|
("f" "9" :string)
|
||||||
|
("y" "9" :string)
|
||||||
|
("q" "9" :string)
|
||||||
|
("h" "9" :string)
|
||||||
|
("w" "9" :string)
|
||||||
|
("s" "9" :string)
|
||||||
|
("d" "9" :string)
|
||||||
|
("v" "9" :string)
|
||||||
|
("k" "9" :string)
|
||||||
|
("r" "9" :string)
|
||||||
|
("m" "9" :string)
|
||||||
|
("z" "9" :string)
|
||||||
|
("c" "9" :string)
|
||||||
|
("i" "9" :string)
|
||||||
|
("l" "9" :string)
|
||||||
|
("b" "9" :string)
|
||||||
|
("j" "9" :string)
|
||||||
|
("a" "9" :string)
|
||||||
|
("p" "9" :string)
|
||||||
|
("u" "9" :string)
|
||||||
|
("t" "9" :string)
|
||||||
|
("e" "9" :string)
|
||||||
|
))
|
||||||
|
|
||||||
|
(use-rule-set :run 0
|
||||||
|
:rule-set ("sphinx-xy-alphabetize"))
|
||||||
|
(use-rule-set :run 1
|
||||||
|
:rule-set ("sphinx-xy-resolve-diacritics"))
|
||||||
|
(use-rule-set :run 2
|
||||||
|
:rule-set ("sphinx-xy-resolve-case"))
|
||||||
65
build/latex/Makefile
Normal file
65
build/latex/Makefile
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Makefile for Sphinx LaTeX output
|
||||||
|
|
||||||
|
ALLDOCS = $(basename $(wildcard *.tex))
|
||||||
|
ALLPDF = $(addsuffix .pdf,$(ALLDOCS))
|
||||||
|
ALLDVI = $(addsuffix .dvi,$(ALLDOCS))
|
||||||
|
ALLXDV =
|
||||||
|
ALLPS = $(addsuffix .ps,$(ALLDOCS))
|
||||||
|
|
||||||
|
# Prefix for archive names
|
||||||
|
ARCHIVEPREFIX =
|
||||||
|
# Additional LaTeX options (passed via variables in latexmkrc/latexmkjarc file)
|
||||||
|
export LATEXOPTS ?=
|
||||||
|
# Additional latexmk options
|
||||||
|
LATEXMKOPTS ?=
|
||||||
|
# format: pdf or dvi (used only by archive targets)
|
||||||
|
FMT = pdf
|
||||||
|
|
||||||
|
LATEX = latexmk -dvi
|
||||||
|
PDFLATEX = latexmk -pdf -dvi- -ps-
|
||||||
|
|
||||||
|
|
||||||
|
%.dvi: %.tex FORCE_MAKE
|
||||||
|
$(LATEX) $(LATEXMKOPTS) '$<'
|
||||||
|
|
||||||
|
%.ps: %.dvi
|
||||||
|
dvips '$<'
|
||||||
|
|
||||||
|
%.pdf: %.tex FORCE_MAKE
|
||||||
|
$(PDFLATEX) $(LATEXMKOPTS) '$<'
|
||||||
|
|
||||||
|
all: $(ALLPDF)
|
||||||
|
|
||||||
|
all-dvi: $(ALLDVI)
|
||||||
|
|
||||||
|
all-ps: $(ALLPS)
|
||||||
|
|
||||||
|
all-pdf: $(ALLPDF)
|
||||||
|
|
||||||
|
zip: all-$(FMT)
|
||||||
|
mkdir $(ARCHIVEPREFIX)docs-$(FMT)
|
||||||
|
cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT)
|
||||||
|
zip -q -r -9 $(ARCHIVEPREFIX)docs-$(FMT).zip $(ARCHIVEPREFIX)docs-$(FMT)
|
||||||
|
rm -r $(ARCHIVEPREFIX)docs-$(FMT)
|
||||||
|
|
||||||
|
tar: all-$(FMT)
|
||||||
|
mkdir $(ARCHIVEPREFIX)docs-$(FMT)
|
||||||
|
cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT)
|
||||||
|
tar cf $(ARCHIVEPREFIX)docs-$(FMT).tar $(ARCHIVEPREFIX)docs-$(FMT)
|
||||||
|
rm -r $(ARCHIVEPREFIX)docs-$(FMT)
|
||||||
|
|
||||||
|
gz: tar
|
||||||
|
# -n to omit mtime from gzip headers
|
||||||
|
gzip -n -9 < $(ARCHIVEPREFIX)docs-$(FMT).tar > $(ARCHIVEPREFIX)docs-$(FMT).tar.gz
|
||||||
|
|
||||||
|
bz2: tar
|
||||||
|
bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar
|
||||||
|
|
||||||
|
xz: tar
|
||||||
|
xz -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz $(ALLPDF) $(ALLDVI) $(ALLXDV) *.fls *.fdb_latexmk
|
||||||
|
|
||||||
|
.PHONY: all all-pdf all-dvi all-ps clean zip tar gz bz2 xz
|
||||||
|
.PHONY: FORCE_MAKE
|
||||||
22
build/latex/latexmkjarc
Normal file
22
build/latex/latexmkjarc
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
$latex = 'pdflatex ' . $ENV{'LATEXOPTS'} . ' -kanji=utf8 %O %S';
|
||||||
|
$dvipdf = 'dvipdfmx %O -o %D %S';
|
||||||
|
$makeindex = 'internal mendex %S %B %D';
|
||||||
|
sub mendex {
|
||||||
|
my ($source, $basename, $destination) = @_;
|
||||||
|
my $dictfile = $basename . ".dic";
|
||||||
|
unlink($destination);
|
||||||
|
system("mendex", "-U", "-f", "-d", $dictfile, "-s", "python.ist", $source);
|
||||||
|
if ($? > 0) {
|
||||||
|
print("mendex exited with error code $? (ignored)\n");
|
||||||
|
}
|
||||||
|
if (!-e $destination) {
|
||||||
|
# create an empty .ind file if nothing
|
||||||
|
open(FH, ">" . $destination);
|
||||||
|
close(FH);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
add_cus_dep( "glo", "gls", 0, "makeglo" );
|
||||||
|
sub makeglo {
|
||||||
|
return system( "mendex -J -f -s gglo.ist -o '$_[0].gls' '$_[0].glo'" );
|
||||||
|
}
|
||||||
9
build/latex/latexmkrc
Normal file
9
build/latex/latexmkrc
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
$latex = 'latex ' . $ENV{'LATEXOPTS'} . ' %O %S';
|
||||||
|
$pdflatex = 'pdflatex ' . $ENV{'LATEXOPTS'} . ' %O %S';
|
||||||
|
$lualatex = 'lualatex ' . $ENV{'LATEXOPTS'} . ' %O %S';
|
||||||
|
$xelatex = 'xelatex --no-pdf ' . $ENV{'LATEXOPTS'} . ' %O %S';
|
||||||
|
$makeindex = 'makeindex -s python.ist %O -o %D %S';
|
||||||
|
add_cus_dep( "glo", "gls", 0, "makeglo" );
|
||||||
|
sub makeglo {
|
||||||
|
return system( "makeindex -s gglo.ist -o '$_[0].gls' '$_[0].glo'" );
|
||||||
|
}
|
||||||
31
build/latex/make.bat
Normal file
31
build/latex/make.bat
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
set PDFLATEX=latexmk -pdf -dvi- -ps-
|
||||||
|
|
||||||
|
set "LATEXOPTS= "
|
||||||
|
|
||||||
|
if "%1" == "" goto all-pdf
|
||||||
|
|
||||||
|
if "%1" == "all-pdf" (
|
||||||
|
:all-pdf
|
||||||
|
for %%i in (*.tex) do (
|
||||||
|
%PDFLATEX% %LATEXMKOPTS% %%i
|
||||||
|
)
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "all-pdf-ja" (
|
||||||
|
goto all-pdf
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "clean" (
|
||||||
|
del /q /s *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz *.fls *.fdb_latexmk
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
:end
|
||||||
|
popd
|
||||||
BIN
build/latex/nats-service-endpoints.pdf
Normal file
BIN
build/latex/nats-service-endpoints.pdf
Normal file
Binary file not shown.
BIN
build/latex/peergos-for-compliance.pdf
Normal file
BIN
build/latex/peergos-for-compliance.pdf
Normal file
Binary file not shown.
|
|
@ -0,0 +1,74 @@
|
||||||
|
\relax
|
||||||
|
\providecommand \babel@aux [2]{\global \let \babel@toc \@gobbletwo }
|
||||||
|
\@nameuse{bbl@beforestart}
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\providecommand\HyField@AuxAddToFields[1]{}
|
||||||
|
\providecommand\HyField@AuxAddToCoFields[2]{}
|
||||||
|
\babel@aux{english}{}
|
||||||
|
\newlabel{index::doc}{{}{1}{}{section*.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {1}Peergos verification (what was actually audited)}{3}{chapter.1}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{verification:peergos-verification-what-was-actually-audited}{{1}{3}{Peergos verification (what was actually audited)}{chapter.1}{}}
|
||||||
|
\newlabel{verification::doc}{{1}{3}{Peergos verification (what was actually audited)}{chapter.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {1.1}Claim to check}{3}{section.1.1}\protected@file@percent }
|
||||||
|
\newlabel{verification:claim-to-check}{{1.1}{3}{Claim to check}{section.1.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {1.2}Independent security audits (Europe)}{3}{section.1.2}\protected@file@percent }
|
||||||
|
\newlabel{verification:independent-security-audits-europe}{{1.2}{3}{Independent security audits (Europe)}{section.1.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {1.3}EU funding / NLnet}{3}{section.1.3}\protected@file@percent }
|
||||||
|
\newlabel{verification:eu-funding-nlnet}{{1.3}{3}{EU funding / NLnet}{section.1.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {1.4}Hosted instance location}{3}{section.1.4}\protected@file@percent }
|
||||||
|
\newlabel{verification:hosted-instance-location}{{1.4}{3}{Hosted instance location}{section.1.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {1.5}Encrypted filesystem + hashed IPFS (design)}{4}{section.1.5}\protected@file@percent }
|
||||||
|
\newlabel{verification:encrypted-filesystem-hashed-ipfs-design}{{1.5}{4}{Encrypted filesystem + hashed IPFS (design)}{section.1.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {1.6}Not verified / do not claim}{4}{section.1.6}\protected@file@percent }
|
||||||
|
\newlabel{verification:not-verified-do-not-claim}{{1.6}{4}{Not verified / do not claim}{section.1.6}{}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {2}Architecture (audit interview)}{5}{chapter.2}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{architecture:architecture-audit-interview}{{2}{5}{Architecture (audit interview)}{chapter.2}{}}
|
||||||
|
\newlabel{architecture::doc}{{2}{5}{Architecture (audit interview)}{chapter.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {3}BAAs and DPAs when ciphertext has no host keys}{7}{chapter.3}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{baa-dpa:baas-and-dpas-when-ciphertext-has-no-host-keys}{{3}{7}{BAAs and DPAs when ciphertext has no host keys}{chapter.3}{}}
|
||||||
|
\newlabel{baa-dpa::doc}{{3}{7}{BAAs and DPAs when ciphertext has no host keys}{chapter.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3.1}The operator statement}{7}{section.3.1}\protected@file@percent }
|
||||||
|
\newlabel{baa-dpa:the-operator-statement}{{3.1}{7}{The operator statement}{section.3.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3.2}HIPAA (US) — Business Associate}{7}{section.3.2}\protected@file@percent }
|
||||||
|
\newlabel{baa-dpa:hipaa-us-business-associate}{{3.2}{7}{HIPAA (US) — Business Associate}{section.3.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3.3}GDPR (EU/UK) — processor vs technical measure}{8}{section.3.3}\protected@file@percent }
|
||||||
|
\newlabel{baa-dpa:gdpr-eu-uk-processor-vs-technical-measure}{{3.3}{8}{GDPR (EU/UK) — processor vs technical measure}{section.3.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3.4}NATS operators}{8}{section.3.4}\protected@file@percent }
|
||||||
|
\newlabel{baa-dpa:nats-operators}{{3.4}{8}{NATS operators}{section.3.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3.5}What “making yourself audit\sphinxhyphen {}ready” means}{8}{section.3.5}\protected@file@percent }
|
||||||
|
\newlabel{baa-dpa:what-making-yourself-audit-ready-means}{{3.5}{8}{What “making yourself audit\sphinxhyphen {}ready” means}{section.3.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {4}Audit\sphinxhyphen {}ready checklist}{9}{chapter.4}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{checklist:audit-ready-checklist}{{4}{9}{Audit\sphinxhyphen {}ready checklist}{chapter.4}{}}
|
||||||
|
\newlabel{checklist::doc}{{4}{9}{Audit\sphinxhyphen {}ready checklist}{chapter.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4.1}A. Scope and data map}{9}{section.4.1}\protected@file@percent }
|
||||||
|
\newlabel{checklist:a-scope-and-data-map}{{4.1}{9}{A. Scope and data map}{section.4.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4.2}B. Keys and encryption}{9}{section.4.2}\protected@file@percent }
|
||||||
|
\newlabel{checklist:b-keys-and-encryption}{{4.2}{9}{B. Keys and encryption}{section.4.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4.3}C. Access}{9}{section.4.3}\protected@file@percent }
|
||||||
|
\newlabel{checklist:c-access}{{4.3}{9}{C. Access}{section.4.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4.4}D. Integrity and backup}{9}{section.4.4}\protected@file@percent }
|
||||||
|
\newlabel{checklist:d-integrity-and-backup}{{4.4}{9}{D. Integrity and backup}{section.4.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4.5}E. Logging}{10}{section.4.5}\protected@file@percent }
|
||||||
|
\newlabel{checklist:e-logging}{{4.5}{10}{E. Logging}{section.4.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4.6}F. Contracts (counsel)}{10}{section.4.6}\protected@file@percent }
|
||||||
|
\newlabel{checklist:f-contracts-counsel}{{4.6}{10}{F. Contracts (counsel)}{section.4.6}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4.7}G. Independent audit of \sphinxstyleemphasis {you}}{10}{section.4.7}\protected@file@percent }
|
||||||
|
\newlabel{checklist:g-independent-audit-of-you}{{4.7}{10}{G. Independent audit of \sphinxstyleemphasis {you}}{section.4.7}{}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {5}How to use this pack}{11}{chapter.5}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{howto:how-to-use-this-pack}{{5}{11}{How to use this pack}{chapter.5}{}}
|
||||||
|
\newlabel{howto::doc}{{5}{11}{How to use this pack}{chapter.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {6}What we verified about Peergos (EU)}{13}{chapter.6}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{index:what-we-verified-about-peergos-eu}{{6}{13}{What we verified about Peergos (EU)}{chapter.6}{}}
|
||||||
|
\gdef \@abspage@last{17}
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,24 @@
|
||||||
|
\BOOKMARK [0][-]{chapter.1}{\376\377\000P\000e\000e\000r\000g\000o\000s\000\040\000v\000e\000r\000i\000f\000i\000c\000a\000t\000i\000o\000n\000\040\000\050\000w\000h\000a\000t\000\040\000w\000a\000s\000\040\000a\000c\000t\000u\000a\000l\000l\000y\000\040\000a\000u\000d\000i\000t\000e\000d\000\051}{}% 1
|
||||||
|
\BOOKMARK [1][-]{section.1.1}{\376\377\000C\000l\000a\000i\000m\000\040\000t\000o\000\040\000c\000h\000e\000c\000k}{chapter.1}% 2
|
||||||
|
\BOOKMARK [1][-]{section.1.2}{\376\377\000I\000n\000d\000e\000p\000e\000n\000d\000e\000n\000t\000\040\000s\000e\000c\000u\000r\000i\000t\000y\000\040\000a\000u\000d\000i\000t\000s\000\040\000\050\000E\000u\000r\000o\000p\000e\000\051}{chapter.1}% 3
|
||||||
|
\BOOKMARK [1][-]{section.1.3}{\376\377\000E\000U\000\040\000f\000u\000n\000d\000i\000n\000g\000\040\000/\000\040\000N\000L\000n\000e\000t}{chapter.1}% 4
|
||||||
|
\BOOKMARK [1][-]{section.1.4}{\376\377\000H\000o\000s\000t\000e\000d\000\040\000i\000n\000s\000t\000a\000n\000c\000e\000\040\000l\000o\000c\000a\000t\000i\000o\000n}{chapter.1}% 5
|
||||||
|
\BOOKMARK [1][-]{section.1.5}{\376\377\000E\000n\000c\000r\000y\000p\000t\000e\000d\000\040\000f\000i\000l\000e\000s\000y\000s\000t\000e\000m\000\040\000+\000\040\000h\000a\000s\000h\000e\000d\000\040\000I\000P\000F\000S\000\040\000\050\000d\000e\000s\000i\000g\000n\000\051}{chapter.1}% 6
|
||||||
|
\BOOKMARK [1][-]{section.1.6}{\376\377\000N\000o\000t\000\040\000v\000e\000r\000i\000f\000i\000e\000d\000\040\000/\000\040\000d\000o\000\040\000n\000o\000t\000\040\000c\000l\000a\000i\000m}{chapter.1}% 7
|
||||||
|
\BOOKMARK [0][-]{chapter.2}{\376\377\000A\000r\000c\000h\000i\000t\000e\000c\000t\000u\000r\000e\000\040\000\050\000a\000u\000d\000i\000t\000\040\000i\000n\000t\000e\000r\000v\000i\000e\000w\000\051}{}% 8
|
||||||
|
\BOOKMARK [0][-]{chapter.3}{\376\377\000B\000A\000A\000s\000\040\000a\000n\000d\000\040\000D\000P\000A\000s\000\040\000w\000h\000e\000n\000\040\000c\000i\000p\000h\000e\000r\000t\000e\000x\000t\000\040\000h\000a\000s\000\040\000n\000o\000\040\000h\000o\000s\000t\000\040\000k\000e\000y\000s}{}% 9
|
||||||
|
\BOOKMARK [1][-]{section.3.1}{\376\377\000T\000h\000e\000\040\000o\000p\000e\000r\000a\000t\000o\000r\000\040\000s\000t\000a\000t\000e\000m\000e\000n\000t}{chapter.3}% 10
|
||||||
|
\BOOKMARK [1][-]{section.3.2}{\376\377\000H\000I\000P\000A\000A\000\040\000\050\000U\000S\000\051\000\040\040\024\000\040\000B\000u\000s\000i\000n\000e\000s\000s\000\040\000A\000s\000s\000o\000c\000i\000a\000t\000e}{chapter.3}% 11
|
||||||
|
\BOOKMARK [1][-]{section.3.3}{\376\377\000G\000D\000P\000R\000\040\000\050\000E\000U\000/\000U\000K\000\051\000\040\040\024\000\040\000p\000r\000o\000c\000e\000s\000s\000o\000r\000\040\000v\000s\000\040\000t\000e\000c\000h\000n\000i\000c\000a\000l\000\040\000m\000e\000a\000s\000u\000r\000e}{chapter.3}% 12
|
||||||
|
\BOOKMARK [1][-]{section.3.4}{\376\377\000N\000A\000T\000S\000\040\000o\000p\000e\000r\000a\000t\000o\000r\000s}{chapter.3}% 13
|
||||||
|
\BOOKMARK [1][-]{section.3.5}{\376\377\000W\000h\000a\000t\000\040\040\034\000m\000a\000k\000i\000n\000g\000\040\000y\000o\000u\000r\000s\000e\000l\000f\000\040\000a\000u\000d\000i\000t\000-\000r\000e\000a\000d\000y\040\035\000\040\000m\000e\000a\000n\000s}{chapter.3}% 14
|
||||||
|
\BOOKMARK [0][-]{chapter.4}{\376\377\000A\000u\000d\000i\000t\000-\000r\000e\000a\000d\000y\000\040\000c\000h\000e\000c\000k\000l\000i\000s\000t}{}% 15
|
||||||
|
\BOOKMARK [1][-]{section.4.1}{\376\377\000A\000.\000\040\000S\000c\000o\000p\000e\000\040\000a\000n\000d\000\040\000d\000a\000t\000a\000\040\000m\000a\000p}{chapter.4}% 16
|
||||||
|
\BOOKMARK [1][-]{section.4.2}{\376\377\000B\000.\000\040\000K\000e\000y\000s\000\040\000a\000n\000d\000\040\000e\000n\000c\000r\000y\000p\000t\000i\000o\000n}{chapter.4}% 17
|
||||||
|
\BOOKMARK [1][-]{section.4.3}{\376\377\000C\000.\000\040\000A\000c\000c\000e\000s\000s}{chapter.4}% 18
|
||||||
|
\BOOKMARK [1][-]{section.4.4}{\376\377\000D\000.\000\040\000I\000n\000t\000e\000g\000r\000i\000t\000y\000\040\000a\000n\000d\000\040\000b\000a\000c\000k\000u\000p}{chapter.4}% 19
|
||||||
|
\BOOKMARK [1][-]{section.4.5}{\376\377\000E\000.\000\040\000L\000o\000g\000g\000i\000n\000g}{chapter.4}% 20
|
||||||
|
\BOOKMARK [1][-]{section.4.6}{\376\377\000F\000.\000\040\000C\000o\000n\000t\000r\000a\000c\000t\000s\000\040\000\050\000c\000o\000u\000n\000s\000e\000l\000\051}{chapter.4}% 21
|
||||||
|
\BOOKMARK [1][-]{section.4.7}{\376\377\000G\000.\000\040\000I\000n\000d\000e\000p\000e\000n\000d\000e\000n\000t\000\040\000a\000u\000d\000i\000t\000\040\000o\000f\000\040\000y\000o\000u}{chapter.4}% 22
|
||||||
|
\BOOKMARK [0][-]{chapter.5}{\376\377\000H\000o\000w\000\040\000t\000o\000\040\000u\000s\000e\000\040\000t\000h\000i\000s\000\040\000p\000a\000c\000k}{}% 23
|
||||||
|
\BOOKMARK [0][-]{chapter.6}{\376\377\000W\000h\000a\000t\000\040\000w\000e\000\040\000v\000e\000r\000i\000f\000i\000e\000d\000\040\000a\000b\000o\000u\000t\000\040\000P\000e\000e\000r\000g\000o\000s\000\040\000\050\000E\000U\000\051}{}% 24
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,607 @@
|
||||||
|
%% Generated by Sphinx.
|
||||||
|
\def\sphinxdocclass{report}
|
||||||
|
\documentclass[letterpaper,11pt,english]{sphinxmanual}
|
||||||
|
\ifdefined\pdfpxdimen
|
||||||
|
\let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen
|
||||||
|
\fi \sphinxpxdimen=.75bp\relax
|
||||||
|
\ifdefined\pdfimageresolution
|
||||||
|
\pdfimageresolution= \numexpr \dimexpr1in\relax/\sphinxpxdimen\relax
|
||||||
|
\fi
|
||||||
|
\newdimen\sphinxremdimen\sphinxremdimen = 11pt
|
||||||
|
%% let collapsible pdf bookmarks panel have high depth per default
|
||||||
|
\PassOptionsToPackage{bookmarksdepth=5}{hyperref}
|
||||||
|
|
||||||
|
\PassOptionsToPackage{booktabs}{sphinx}
|
||||||
|
\PassOptionsToPackage{colorrows}{sphinx}
|
||||||
|
|
||||||
|
\PassOptionsToPackage{warn}{textcomp}
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\ifdefined\DeclareUnicodeCharacter
|
||||||
|
% support both utf8 and utf8x syntaxes
|
||||||
|
\ifdefined\DeclareUnicodeCharacterAsOptional
|
||||||
|
\def\sphinxDUC#1{\DeclareUnicodeCharacter{"#1}}
|
||||||
|
\else
|
||||||
|
\let\sphinxDUC\DeclareUnicodeCharacter
|
||||||
|
\fi
|
||||||
|
\sphinxDUC{00A0}{\nobreakspace}
|
||||||
|
\sphinxDUC{2500}{\sphinxunichar{2500}}
|
||||||
|
\sphinxDUC{2502}{\sphinxunichar{2502}}
|
||||||
|
\sphinxDUC{2514}{\sphinxunichar{2514}}
|
||||||
|
\sphinxDUC{251C}{\sphinxunichar{251C}}
|
||||||
|
\sphinxDUC{2572}{\textbackslash}
|
||||||
|
\fi
|
||||||
|
\usepackage{cmap}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage{amsmath,amssymb,amstext}
|
||||||
|
\usepackage{babel}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\usepackage{tgtermes}
|
||||||
|
\usepackage{tgheros}
|
||||||
|
\renewcommand{\ttdefault}{txtt}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\usepackage[Bjarne]{fncychap}
|
||||||
|
\usepackage{sphinx}
|
||||||
|
|
||||||
|
\fvset{fontsize=auto}
|
||||||
|
\usepackage{geometry}
|
||||||
|
|
||||||
|
|
||||||
|
% Include hyperref last.
|
||||||
|
\usepackage{hyperref}
|
||||||
|
% Fix anchor placement for figures with captions.
|
||||||
|
\usepackage{hypcap}% it must be loaded after hyperref.
|
||||||
|
% Set up styles of URL: it should be placed after hyperref.
|
||||||
|
\urlstyle{same}
|
||||||
|
|
||||||
|
|
||||||
|
\usepackage{sphinxmessages}
|
||||||
|
\setcounter{tocdepth}{1}
|
||||||
|
|
||||||
|
\usepackage{hyperref}
|
||||||
|
|
||||||
|
\title{Making yourself audit-ready with Verae DataCubes}
|
||||||
|
\date{Sep 16, 2026}
|
||||||
|
\release{}
|
||||||
|
\author{Verae}
|
||||||
|
\newcommand{\sphinxlogo}{\vbox{}}
|
||||||
|
\renewcommand{\releasename}{}
|
||||||
|
\makeindex
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\ifdefined\shorthandoff
|
||||||
|
\ifnum\catcode`\=\string=\active\shorthandoff{=}\fi
|
||||||
|
\ifnum\catcode`\"=\active\shorthandoff{"}\fi
|
||||||
|
\fi
|
||||||
|
|
||||||
|
\pagestyle{empty}
|
||||||
|
\sphinxmaketitle
|
||||||
|
\pagestyle{plain}
|
||||||
|
\sphinxtableofcontents
|
||||||
|
\pagestyle{normal}
|
||||||
|
\phantomsection\label{\detokenize{index::doc}}
|
||||||
|
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
How to \sphinxstylestrong{prepare an organization} for HIPAA\sphinxhyphen{}aligned, SOC 2, or ISO 27001
|
||||||
|
work using Verae DataCubes on \sphinxstylestrong{Peergos} (encrypted cryptree + hashed
|
||||||
|
IPFS) and HPKE on an \sphinxstylestrong{untrusted NATS} broker.
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{This document is not a HIPAA, SOC 2, or ISO certificate.}
|
||||||
|
Peergos’s public pentests are \sphinxstylestrong{not} your Type II or ISO registrar
|
||||||
|
certificate. They are \sphinxstylestrong{component security evaluations} you can attach.
|
||||||
|
|
||||||
|
\sphinxstepscope
|
||||||
|
|
||||||
|
|
||||||
|
\chapter{Peergos verification (what was actually audited)}
|
||||||
|
\label{\detokenize{verification:peergos-verification-what-was-actually-audited}}\label{\detokenize{verification::doc}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
This chapter records \sphinxstylestrong{sourced} facts. It does \sphinxstylestrong{not} turn Peergos, Verae,
|
||||||
|
or DataCubes into a HIPAA, SOC 2, or ISO 27001 certificate.
|
||||||
|
|
||||||
|
|
||||||
|
\section{Claim to check}
|
||||||
|
\label{\detokenize{verification:claim-to-check}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Data at rest is stored in an encrypted append\sphinxhyphen{}only Peergos filesystem;
|
||||||
|
backup/restore is managed via a distributed, hashed, encrypted Peergos
|
||||||
|
IPFS system, designed and evaluated in the EU as an audited secure
|
||||||
|
filesystem.
|
||||||
|
|
||||||
|
|
||||||
|
\section{Independent security audits (Europe)}
|
||||||
|
\label{\detokenize{verification:independent-security-audits-europe}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{2019 — Cure53 (Berlin, Germany).}
|
||||||
|
Pentest, source\sphinxhyphen{}code audit, \sphinxstylestrong{crypto/design review} (May\textendash{}June 2019).
|
||||||
|
No fundamental architectural or cryptographic problems; issues fixed.
|
||||||
|
Cure53: the platform \sphinxstylestrong{passed this evaluation}.
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{2024 — Radically Open Security B.V. (Amsterdam, Netherlands).}
|
||||||
|
Crystal\sphinxhyphen{}box pentest + code audit of Peergos web\sphinxhyphen{}ui (Sep\textendash{}Nov 2024).
|
||||||
|
\sphinxstylestrong{0} extreme / high / elevated; \sphinxstylestrong{2} moderate, \sphinxstylestrong{6} low; Peergos
|
||||||
|
states all fixed; no data exposure or integrity compromise (mostly UI
|
||||||
|
crashes).
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Both firms are \sphinxstylestrong{EU\sphinxhyphen{}based}. Both full reports are \sphinxstylestrong{public}. That is a
|
||||||
|
\sphinxstylestrong{security evaluation of the Peergos protocol/implementation}, not a
|
||||||
|
HIPAA/SOC 2/ISO management\sphinxhyphen{}system certificate.
|
||||||
|
|
||||||
|
|
||||||
|
\section{EU funding / NLnet}
|
||||||
|
\label{\detokenize{verification:eu-funding-nlnet}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Peergos received funding from the \sphinxstylestrong{European Union Horizon 2020}
|
||||||
|
programme under \sphinxstylestrong{NGI\sphinxhyphen{}POINTER}, grant \sphinxstylestrong{871528} (stated on the 2024
|
||||||
|
audit post).
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
The 2024 audit was supported by \sphinxstylestrong{NLnet} (Netherlands).
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Hosted instance location}
|
||||||
|
\label{\detokenize{verification:hosted-instance-location}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Peergos’s hosted privacy notice states peergos.net uses servers in
|
||||||
|
\sphinxstylestrong{Germany}. \sphinxstylestrong{Self\sphinxhyphen{}hosted ns1 / customer cryptree is a different
|
||||||
|
processing location} and must be documented in \sphinxstyleemphasis{your} RoPA / BAA pack.
|
||||||
|
|
||||||
|
|
||||||
|
\section{Encrypted filesystem + hashed IPFS (design)}
|
||||||
|
\label{\detokenize{verification:encrypted-filesystem-hashed-ipfs-design}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{Cryptree}: tree of symmetric keys; fine\sphinxhyphen{}grained read/write caps;
|
||||||
|
sibling names hidden; writes \sphinxstylestrong{signed}.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{Chunks}: up to 5 MiB, padded, independently encrypted
|
||||||
|
(Salsa20\sphinxhyphen{}Poly1305); random 256\sphinxhyphen{}bit keys (not convergent).
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{IPFS}: content\sphinxhyphen{}addressed blocks. Peergos \sphinxstylestrong{verifies the hash} of
|
||||||
|
every block read from or written to IPFS. Clients verify hashes and
|
||||||
|
signatures from a Peergos server.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{CHAMP}: encrypted cryptree nodes under \sphinxstylestrong{random 32\sphinxhyphen{}byte labels}.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Sharing: hybrid \sphinxstylestrong{X25519 + ML\sphinxhyphen{}KEM\sphinxhyphen{}1024}.
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
“Append\sphinxhyphen{}only” in Verae DataCubes is the \sphinxstylestrong{cube chain JSONL} (application
|
||||||
|
integrity). Peergos uses signed updates and immutable blocks. Do not
|
||||||
|
conflate the two layers in an audit interview.
|
||||||
|
|
||||||
|
|
||||||
|
\section{Not verified / do not claim}
|
||||||
|
\label{\detokenize{verification:not-verified-do-not-claim}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
“Peergos is HIPAA certified” — \sphinxstylestrong{false.} HIPAA is not a product certificate.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
“Peergos is SOC 2 / ISO 27001 certified” — \sphinxstylestrong{not shown.} Published
|
||||||
|
work is pentest/code audit, not Type II or ISO registrar.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
“EU certified Peergos as a government\sphinxhyphen{}standard filesystem” —
|
||||||
|
\sphinxstylestrong{overstated.} What exists: EU grant funding, NLNet\sphinxhyphen{}funded ROS
|
||||||
|
pentest, Cure53 Berlin design+code audit.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
“Hosts with disk/backup never need a BAA/DPA” — \sphinxstylestrong{legal conclusion,
|
||||||
|
not a technical fact.} See {\hyperref[\detokenize{baa-dpa::doc}]{\sphinxcrossref{\DUrole{doc}{BAAs and DPAs when ciphertext has no host keys}}}}.
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\sphinxstepscope
|
||||||
|
|
||||||
|
|
||||||
|
\chapter{Architecture (audit interview)}
|
||||||
|
\label{\detokenize{architecture:architecture-audit-interview}}\label{\detokenize{architecture::doc}}
|
||||||
|
\begin{sphinxVerbatim}[commandchars=\\\{\}]
|
||||||
|
Endpoint (keys stay here / HSM)
|
||||||
|
│ HPKE content (NPE suite)
|
||||||
|
│ routing: dest + subject in the clear
|
||||||
|
▼
|
||||||
|
Untrusted NATS (cannot read bodies)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Verae DataCube chain (append\PYGZhy{}only hashes)
|
||||||
|
│ written through Peergos client
|
||||||
|
▼
|
||||||
|
Peergos cryptree (encrypted names, sizes, graph)
|
||||||
|
│ chunks \(\rightarrow\) CID / hash
|
||||||
|
▼
|
||||||
|
IPFS (distributed, hash\PYGZhy{}verified ciphertext)
|
||||||
|
\end{sphinxVerbatim}
|
||||||
|
\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{At rest:} Peergos cryptree + IPFS. Hosts with disk/backup see
|
||||||
|
\sphinxstylestrong{opaque hashed ciphertext}, not PHI, if they lack keys.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{In transit (NATS):} HPKE\sphinxhyphen{}Base to directory public keys. Broker is
|
||||||
|
honest\sphinxhyphen{}but\sphinxhyphen{}curious: destinations yes, bodies no.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{Integrity:} cube JSONL chain + dual hash + IPFS CID check on
|
||||||
|
restore (re\sphinxhyphen{}fetch blocks, re\sphinxhyphen{}verify hashes — not a plaintext tape).
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
NATS remains an untrusted router. Production E2E is NPE/HPKE.
|
||||||
|
Passthrough means destination in the clear; the body is ciphertext.
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
See companion \sphinxcode{\sphinxupquote{peergos\sphinxhyphen{}for\sphinxhyphen{}compliance.pdf}} (same folder) for
|
||||||
|
controls, custody, and variables chapters.
|
||||||
|
|
||||||
|
\href{peergos-for-compliance.pdf}{peergos-for-compliance.pdf}
|
||||||
|
|
||||||
|
\sphinxstepscope
|
||||||
|
|
||||||
|
|
||||||
|
\chapter{BAAs and DPAs when ciphertext has no host keys}
|
||||||
|
\label{\detokenize{baa-dpa:baas-and-dpas-when-ciphertext-has-no-host-keys}}\label{\detokenize{baa-dpa::doc}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
This is \sphinxstylestrong{guidance for an evidence pack}, not legal advice.
|
||||||
|
|
||||||
|
|
||||||
|
\section{The operator statement}
|
||||||
|
\label{\detokenize{baa-dpa:the-operator-statement}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Data at rest lives in the \sphinxstylestrong{encrypted Peergos cryptree}. Restore uses
|
||||||
|
\sphinxstylestrong{distributed, hash\sphinxhyphen{}verified, encrypted IPFS blocks}. Hosts and backup
|
||||||
|
media see \sphinxstylestrong{opaque blobs} (and random CHAMP labels), not filenames, not
|
||||||
|
PHI, not social graph — if keys never leave the client / customer HSM.
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
That is \sphinxstylestrong{true of the Peergos design} (see {\hyperref[\detokenize{verification::doc}]{\sphinxcrossref{\DUrole{doc}{Peergos verification (what was actually audited)}}}}).
|
||||||
|
It \sphinxstylestrong{changes the BAA/DPA conversation}. It does \sphinxstylestrong{not} auto\sphinxhyphen{}delete the
|
||||||
|
need for contracts.
|
||||||
|
|
||||||
|
|
||||||
|
\section{HIPAA (US) — Business Associate}
|
||||||
|
\label{\detokenize{baa-dpa:hipaa-us-business-associate}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
A Business Associate is a person who \sphinxstylestrong{creates, receives, maintains, or
|
||||||
|
transmits ePHI} for a covered entity.
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{Technical argument you can make (and should document):}
|
||||||
|
\begin{enumerate}
|
||||||
|
\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}%
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
ePHI is encrypted \sphinxstylestrong{before} it leaves the endpoint (Peergos client /
|
||||||
|
DataCube writer).
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
The storage node, IPFS, disk, and backup hold \sphinxstylestrong{ciphertext + hashes}.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Private keys \sphinxstylestrong{do not} reside on the storage host (customer HSM /
|
||||||
|
client). Hash verification detects tampering.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Therefore the host \sphinxstylestrong{cannot maintain ePHI in intelligible form}.
|
||||||
|
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
HHS distinguishes \sphinxstylestrong{conduits} and parties that never have access to
|
||||||
|
ePHI. Many programs still \sphinxstylestrong{sign a BAA} when a vendor touches
|
||||||
|
infrastructure, because misconfiguration, support exports, or logs could
|
||||||
|
later expose plaintext. OCR looks at \sphinxstylestrong{your} risk analysis.
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
\sphinxstylestrong{Practical pack:} risk analysis memo citing cryptree + IPFS hash checks
|
||||||
|
+ key custody; BAA \sphinxstylestrong{or} written determination that the vendor is
|
||||||
|
\sphinxstylestrong{not} a BA because they cannot decrypt; list every party with
|
||||||
|
disk/backup (ns1, IPFS cluster, offsite replica).
|
||||||
|
|
||||||
|
|
||||||
|
\section{GDPR (EU/UK) — processor vs technical measure}
|
||||||
|
\label{\detokenize{baa-dpa:gdpr-eu-uk-processor-vs-technical-measure}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Encrypted data can still be \sphinxstylestrong{personal data} if it is reasonably
|
||||||
|
attributable (usernames, IPs, invoice identity). GDPR \sphinxstylestrong{Art. 32} lists
|
||||||
|
encryption as a security measure.
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Peergos is designed so the \sphinxstylestrong{server is an adversary} for content and
|
||||||
|
most metadata. EU\sphinxhyphen{}based \sphinxstylestrong{independent pentests} (Cure53 DE, ROS NL)
|
||||||
|
evaluated that design. Processing location for \sphinxstylestrong{self\sphinxhyphen{}host} is \sphinxstyleemphasis{your}
|
||||||
|
ns1 / customer region, not peergos.net’s Germany hosting, unless you use
|
||||||
|
peergos.net.
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
You may still need a \sphinxstylestrong{DPA (Art. 28)} with anyone who \sphinxstylestrong{processes}
|
||||||
|
personal data (usernames, logs, billing). Ciphertext\sphinxhyphen{}only storage
|
||||||
|
\sphinxstylestrong{narrows} the DPA’s technical annex.
|
||||||
|
|
||||||
|
|
||||||
|
\section{NATS operators}
|
||||||
|
\label{\detokenize{baa-dpa:nats-operators}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
NATS is an \sphinxstylestrong{untrusted broker}. Content is HPKE; destinations and
|
||||||
|
subjects are in the clear. A NATS operator \sphinxstylestrong{cannot} read bodies without
|
||||||
|
endpoint private keys; \sphinxstylestrong{can} see routing metadata; \sphinxstylestrong{can} drop/delay
|
||||||
|
copy \sphinxstylestrong{ciphertext}. Treat like a transit provider: DPA/BAA depends on
|
||||||
|
whether routing metadata is personal data in your jurisdiction.
|
||||||
|
|
||||||
|
|
||||||
|
\section{What “making yourself audit\sphinxhyphen{}ready” means}
|
||||||
|
\label{\detokenize{baa-dpa:what-making-yourself-audit-ready-means}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
You are \sphinxstylestrong{not} buying Peergos’s Cure53/ROS reports as \sphinxstyleemphasis{your} SOC 2.
|
||||||
|
You are \sphinxstylestrong{reusing} those public evaluations as \sphinxstylestrong{vendor/component
|
||||||
|
assurance}, then adding your scope, RoPA, key\sphinxhyphen{}custody, inspect k\sphinxhyphen{}of\sphinxhyphen{}n,
|
||||||
|
admin\sphinxhyphen{}history, instance evidence, and contracts that match who can
|
||||||
|
actually see plaintext.
|
||||||
|
|
||||||
|
\sphinxstepscope
|
||||||
|
|
||||||
|
|
||||||
|
\chapter{Audit\sphinxhyphen{}ready checklist}
|
||||||
|
\label{\detokenize{checklist:audit-ready-checklist}}\label{\detokenize{checklist::doc}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Use this as a working list. Check items only when \sphinxstylestrong{evidence exists}
|
||||||
|
(screenshot, log export, signed policy, ticket). This list is not a
|
||||||
|
certificate.
|
||||||
|
|
||||||
|
|
||||||
|
\section{A. Scope and data map}
|
||||||
|
\label{\detokenize{checklist:a-scope-and-data-map}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Named legal entity and systems in scope (console, Drive, NATS, IPFS, ns1)
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Data\sphinxhyphen{}flow diagram: endpoint \(\rightarrow\) HPKE/NATS \(\rightarrow\) cryptree/IPFS
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
What is PHI / personal data vs ciphertext vs routing metadata
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Peergos verification chapter attached ({\hyperref[\detokenize{verification::doc}]{\sphinxcrossref{\DUrole{doc}{Peergos verification (what was actually audited)}}}})
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\section{B. Keys and encryption}
|
||||||
|
\label{\detokenize{checklist:b-keys-and-encryption}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Customer holds Peergos/Drive keys; not on storage host
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
NPE/HPKE endpoint keys in directory; private 0600; no xor content
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Signed Ed25519 config; unsigned rejected; admin\sphinxhyphen{}history prev+new+diff
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
HSM or documented lab\sphinxhyphen{}to\sphinxhyphen{}HSM path
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\section{C. Access}
|
||||||
|
\label{\detokenize{checklist:c-access}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Console \sphinxcode{\sphinxupquote{PFC\_REQUIRE\_AUTH=1}}, TOTP; Drive login separate
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Inspect k\sphinxhyphen{}of\sphinxhyphen{}n; author is not an officer; log\sphinxhyphen{}before\sphinxhyphen{}reveal
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Joiner / mover / leaver for console users
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Google SSO does \sphinxstylestrong{not} unwrap cubes
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\section{D. Integrity and backup}
|
||||||
|
\label{\detokenize{checklist:d-integrity-and-backup}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Cube chain append\sphinxhyphen{}only JSONL; dual hash
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Hash registry: first SHA\sphinxhyphen{}256 and receipt win
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Peergos/IPFS: hash\sphinxhyphen{}verified encrypted blocks (restore = re\sphinxhyphen{}fetch CIDs)
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Restore test: recover a cube from content\sphinxhyphen{}addressed ciphertext without
|
||||||
|
plaintext backup tapes
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\section{E. Logging}
|
||||||
|
\label{\detokenize{checklist:e-logging}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Inspect audit events
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
SM summaries: codes + lookup\_id only (no bodies)
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Admin\sphinxhyphen{}history cube for config
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\section{F. Contracts (counsel)}
|
||||||
|
\label{\detokenize{checklist:f-contracts-counsel}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Written BA / not\sphinxhyphen{}a\sphinxhyphen{}BA determination for disk, VM, backup, IPFS
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
DPA Art. 28 where usernames/logs/IPs are processed
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
NATS operator: metadata vs content in the annex
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Peergos component assurance: attach Cure53 2019 + ROS 2024 PDFs
|
||||||
|
(public; not your org’s ISO/SOC report)
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\section{G. Independent audit of \sphinxstyleemphasis{you}}
|
||||||
|
\label{\detokenize{checklist:g-independent-audit-of-you}}\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
SOC 2 Type I/II engagement \sphinxstylestrong{or} ISO 27001 registrar \sphinxstylestrong{or} HIPAA
|
||||||
|
risk analysis + policies (pick the program you actually need)
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Evidence window (Type II / surveillance) if applicable
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\sphinxstepscope
|
||||||
|
|
||||||
|
|
||||||
|
\chapter{How to use this pack}
|
||||||
|
\label{\detokenize{howto:how-to-use-this-pack}}\label{\detokenize{howto::doc}}\begin{enumerate}
|
||||||
|
\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}%
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Read {\hyperref[\detokenize{verification::doc}]{\sphinxcrossref{\DUrole{doc}{Peergos verification (what was actually audited)}}}} so you do not over\sphinxhyphen{}claim Peergos audits.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Fill {\hyperref[\detokenize{checklist::doc}]{\sphinxcrossref{\DUrole{doc}{Audit\sphinxhyphen{}ready checklist}}}} with \sphinxstylestrong{your} instance evidence (ns1, keys, users).
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Give {\hyperref[\detokenize{baa-dpa::doc}]{\sphinxcrossref{\DUrole{doc}{BAAs and DPAs when ciphertext has no host keys}}}} to counsel with the data\sphinxhyphen{}flow from {\hyperref[\detokenize{architecture::doc}]{\sphinxcrossref{\DUrole{doc}{Architecture (audit interview)}}}}.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Point auditors at live technical surfaces (do not give them private keys).
|
||||||
|
|
||||||
|
\end{enumerate}
|
||||||
|
\begin{enumerate}
|
||||||
|
\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}%
|
||||||
|
\setcounter{enumi}{4}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Attach the two \sphinxstylestrong{public} Peergos pentest PDFs from the Peergos
|
||||||
|
\sphinxcode{\sphinxupquote{audits/}} tree as \sphinxstylestrong{vendor security evaluations}, labeled “not our
|
||||||
|
SOC 2 / ISO certificate”.
|
||||||
|
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Companion system PDF (same folder):
|
||||||
|
|
||||||
|
\href{peergos-for-compliance.pdf}{peergos-for-compliance.pdf}
|
||||||
|
|
||||||
|
|
||||||
|
\chapter{What we verified about Peergos (EU)}
|
||||||
|
\label{\detokenize{index:what-we-verified-about-peergos-eu}}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
See the full sourced table in {\hyperref[\detokenize{verification::doc}]{\sphinxcrossref{\DUrole{doc}{Peergos verification (what was actually audited)}}}}.
|
||||||
|
\begin{itemize}
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Encrypted client\sphinxhyphen{}side filesystem (cryptree); keys not on the storage
|
||||||
|
server — \sphinxstylestrong{yes} (Peergos book + Cure53 design review).
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
IPFS blocks content\sphinxhyphen{}addressed; Peergos verifies hashes — \sphinxstylestrong{yes}.
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Independent \sphinxstylestrong{EU} security audits, reports published — \sphinxstylestrong{yes, two:}
|
||||||
|
Cure53 Berlin (2019); Radically Open Security Amsterdam (2024).
|
||||||
|
|
||||||
|
\item {}
|
||||||
|
\sphinxAtStartPar
|
||||||
|
“Peergos is HIPAA/SOC 2/ISO certified” — \sphinxstylestrong{no.} Those audits are
|
||||||
|
pentest/code/design reviews, not management\sphinxhyphen{}system certificates.
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Peergos \sphinxstylestrong{was designed as a trust\sphinxhyphen{}minimized encrypted filesystem},
|
||||||
|
\sphinxstylestrong{evaluated in Europe} by two specialist firms, with \sphinxstylestrong{public reports}.
|
||||||
|
That supports the \sphinxstylestrong{at\sphinxhyphen{}rest / backup} story. It does \sphinxstylestrong{not} finish
|
||||||
|
\sphinxstyleemphasis{your} audit.
|
||||||
|
|
||||||
|
\sphinxAtStartPar
|
||||||
|
Companion PDFs in the \sphinxstylestrong{same directory} as this file (relative PDF
|
||||||
|
links, not Markdown):
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \href{peergos-for-compliance.pdf}{peergos-for-compliance.pdf}
|
||||||
|
\item \href{nats-service-endpoints.pdf}{nats-service-endpoints.pdf}
|
||||||
|
\item \href{secure-messaging.pdf}{secure-messaging.pdf}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\renewcommand{\indexname}{Index}
|
||||||
|
\printindex
|
||||||
|
\end{document}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
\babel@toc {english}{}\relax
|
||||||
|
\contentsline {chapter}{\numberline {1}Peergos verification (what was actually audited)}{3}{chapter.1}%
|
||||||
|
\contentsline {section}{\numberline {1.1}Claim to check}{3}{section.1.1}%
|
||||||
|
\contentsline {section}{\numberline {1.2}Independent security audits (Europe)}{3}{section.1.2}%
|
||||||
|
\contentsline {section}{\numberline {1.3}EU funding / NLnet}{3}{section.1.3}%
|
||||||
|
\contentsline {section}{\numberline {1.4}Hosted instance location}{3}{section.1.4}%
|
||||||
|
\contentsline {section}{\numberline {1.5}Encrypted filesystem + hashed IPFS (design)}{4}{section.1.5}%
|
||||||
|
\contentsline {section}{\numberline {1.6}Not verified / do not claim}{4}{section.1.6}%
|
||||||
|
\contentsline {chapter}{\numberline {2}Architecture (audit interview)}{5}{chapter.2}%
|
||||||
|
\contentsline {chapter}{\numberline {3}BAAs and DPAs when ciphertext has no host keys}{7}{chapter.3}%
|
||||||
|
\contentsline {section}{\numberline {3.1}The operator statement}{7}{section.3.1}%
|
||||||
|
\contentsline {section}{\numberline {3.2}HIPAA (US) — Business Associate}{7}{section.3.2}%
|
||||||
|
\contentsline {section}{\numberline {3.3}GDPR (EU/UK) — processor vs technical measure}{8}{section.3.3}%
|
||||||
|
\contentsline {section}{\numberline {3.4}NATS operators}{8}{section.3.4}%
|
||||||
|
\contentsline {section}{\numberline {3.5}What “making yourself audit\sphinxhyphen {}ready” means}{8}{section.3.5}%
|
||||||
|
\contentsline {chapter}{\numberline {4}Audit\sphinxhyphen {}ready checklist}{9}{chapter.4}%
|
||||||
|
\contentsline {section}{\numberline {4.1}A. Scope and data map}{9}{section.4.1}%
|
||||||
|
\contentsline {section}{\numberline {4.2}B. Keys and encryption}{9}{section.4.2}%
|
||||||
|
\contentsline {section}{\numberline {4.3}C. Access}{9}{section.4.3}%
|
||||||
|
\contentsline {section}{\numberline {4.4}D. Integrity and backup}{9}{section.4.4}%
|
||||||
|
\contentsline {section}{\numberline {4.5}E. Logging}{10}{section.4.5}%
|
||||||
|
\contentsline {section}{\numberline {4.6}F. Contracts (counsel)}{10}{section.4.6}%
|
||||||
|
\contentsline {section}{\numberline {4.7}G. Independent audit of \sphinxstyleemphasis {you}}{10}{section.4.7}%
|
||||||
|
\contentsline {chapter}{\numberline {5}How to use this pack}{11}{chapter.5}%
|
||||||
|
\contentsline {chapter}{\numberline {6}What we verified about Peergos (EU)}{13}{chapter.6}%
|
||||||
16
build/latex/python.ist
Normal file
16
build/latex/python.ist
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
line_max 100
|
||||||
|
headings_flag 1
|
||||||
|
heading_prefix " \\bigletter "
|
||||||
|
|
||||||
|
preamble "\\begin{sphinxtheindex}
|
||||||
|
\\let\\bigletter\\sphinxstyleindexlettergroup
|
||||||
|
\\let\\spxpagem \\sphinxstyleindexpagemain
|
||||||
|
\\let\\spxentry \\sphinxstyleindexentry
|
||||||
|
\\let\\spxextra \\sphinxstyleindexextra
|
||||||
|
|
||||||
|
"
|
||||||
|
|
||||||
|
postamble "\n\n\\end{sphinxtheindex}\n"
|
||||||
|
|
||||||
|
symhead_positive "{\\sphinxsymbolsname}"
|
||||||
|
numhead_positive "{\\sphinxnumbersname}"
|
||||||
BIN
build/latex/secure-messaging.pdf
Normal file
BIN
build/latex/secure-messaging.pdf
Normal file
Binary file not shown.
1263
build/latex/sphinx.sty
Normal file
1263
build/latex/sphinx.sty
Normal file
File diff suppressed because it is too large
Load diff
230
build/latex/sphinx.xdy
Normal file
230
build/latex/sphinx.xdy
Normal file
|
|
@ -0,0 +1,230 @@
|
||||||
|
;;; -*- mode: lisp; coding: utf-8; -*-
|
||||||
|
|
||||||
|
;; Unfortunately xindy is out-of-the-box hyperref-incompatible. This
|
||||||
|
;; configuration is a workaround, which requires to pass option
|
||||||
|
;; hyperindex=false to hyperref.
|
||||||
|
;; textit and emph not currently used, spxpagem replaces former textbf
|
||||||
|
(define-attributes (("textbf" "textit" "emph" "spxpagem" "default")))
|
||||||
|
(markup-locref :open "\textbf{\hyperpage{" :close "}}" :attr "textbf")
|
||||||
|
(markup-locref :open "\textit{\hyperpage{" :close "}}" :attr "textit")
|
||||||
|
(markup-locref :open "\emph{\hyperpage{" :close "}}" :attr "emph")
|
||||||
|
(markup-locref :open "\spxpagem{\hyperpage{" :close "}}" :attr "spxpagem")
|
||||||
|
(markup-locref :open "\hyperpage{" :close "}" :attr "default")
|
||||||
|
|
||||||
|
(require "numeric-sort.xdy")
|
||||||
|
|
||||||
|
;; xindy base module latex.xdy loads tex.xdy and the latter instructs
|
||||||
|
;; xindy to ignore **all** TeX macros in .idx entries, except those
|
||||||
|
;; explicitly described in merge rule. But when after applying all
|
||||||
|
;; merge rules an empty string results, xindy raises an error:
|
||||||
|
|
||||||
|
;; ERROR: CHAR: index 0 should be less than the length of the string
|
||||||
|
|
||||||
|
;; For example when using pdflatex with utf-8 characters the index
|
||||||
|
;; file will contain \IeC macros and they will get ignored except if
|
||||||
|
;; suitable merge rules are loaded early. The texindy script coming
|
||||||
|
;; with xindy provides this, but only for Latin scripts. The texindy
|
||||||
|
;; man page says to use rather xelatex or lualatex in case of Cyrillic
|
||||||
|
;; scripts.
|
||||||
|
|
||||||
|
;; Sphinx contributes LICRcyr2utf8.xdy to provide support for Cyrillic
|
||||||
|
;; scripts for the pdflatex engine.
|
||||||
|
|
||||||
|
;; Another issue caused by xindy ignoring all TeX macros except those
|
||||||
|
;; explicitly declared reveals itself when attempting to index ">>>",
|
||||||
|
;; as the ">" is converted to "\textgreater{}" by Sphinx's LaTeX
|
||||||
|
;; escaping.
|
||||||
|
|
||||||
|
;; To fix this, Sphinx does **not** use texindy, and does not even
|
||||||
|
;; load the xindy latex.xdy base module.
|
||||||
|
|
||||||
|
;(require "latex.xdy")
|
||||||
|
|
||||||
|
;; Rather it incorporates some suitable extracts from latex.xdy and
|
||||||
|
;; tex.xdy with additional Sphinx contributed rules.
|
||||||
|
|
||||||
|
;; But, this means for pdflatex and Latin scripts that the xindy file
|
||||||
|
;; tex/inputenc/uf8.xdy is not usable because it refers to the macro
|
||||||
|
;; \IeC only sporadically, and as tex.xdy is not loaded, a rule such as
|
||||||
|
;; (merge-rule "\'e" "é" :string)
|
||||||
|
;; does not work, it must be
|
||||||
|
;; (merge-rule "\IeC {\'e}" "é" :string)
|
||||||
|
;; So Sphinx contributes LICRlatin2utf8.xdy to mitigate that problem.
|
||||||
|
|
||||||
|
;;;;;;;; extracts from tex.xdy (discarding most original comments):
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; TeX conventions
|
||||||
|
;;;
|
||||||
|
|
||||||
|
;; Discard leading and trailing white space. Collapse multiple white
|
||||||
|
;; space characters to blank.
|
||||||
|
|
||||||
|
(merge-rule "^ +" "" :eregexp)
|
||||||
|
(merge-rule " +$" "" :eregexp)
|
||||||
|
(merge-rule " +" " " :eregexp)
|
||||||
|
|
||||||
|
;; Handle TeX markup
|
||||||
|
|
||||||
|
(merge-rule "\\([{}$%&#])" "\1" :eregexp)
|
||||||
|
|
||||||
|
;;;;;;;; end of extracts from xindy's tex.xdy
|
||||||
|
|
||||||
|
;;;;;;;; extracts from latex.xdy:
|
||||||
|
|
||||||
|
;; Standard location classes: arabic and roman numbers, and alphabets.
|
||||||
|
|
||||||
|
(define-location-class "arabic-page-numbers" ("arabic-numbers"))
|
||||||
|
(define-location-class "roman-page-numbers" ("roman-numbers-lowercase"))
|
||||||
|
(define-location-class "Roman-page-numbers" ("roman-numbers-uppercase"))
|
||||||
|
(define-location-class "alpha-page-numbers" ("alpha"))
|
||||||
|
(define-location-class "Alpha-page-numbers" ("ALPHA"))
|
||||||
|
|
||||||
|
;; Output Markup
|
||||||
|
|
||||||
|
(markup-letter-group-list :sep "~n~n \indexspace~n")
|
||||||
|
|
||||||
|
(markup-indexentry :open "~n \item " :depth 0)
|
||||||
|
(markup-indexentry :open "~n \subitem " :depth 1)
|
||||||
|
(markup-indexentry :open "~n \subsubitem " :depth 2)
|
||||||
|
|
||||||
|
(markup-locclass-list :open ", " :sep ", ")
|
||||||
|
(markup-locref-list :sep ", ")
|
||||||
|
|
||||||
|
;;;;;;;; end of extracts from latex.xdy
|
||||||
|
|
||||||
|
;; The LaTeX \index command turns \ into normal character so the TeX macros
|
||||||
|
;; written to .idx files are not followed by a blank. This is different
|
||||||
|
;; from non-ascii letters which end up (with pdflatex) as \IeC macros in .idx
|
||||||
|
;; file, with a blank space after \IeC
|
||||||
|
|
||||||
|
;; Details of the syntax are explained at
|
||||||
|
;; https://xindy.sourceforge.net/doc/manual-3.html
|
||||||
|
;; In absence of :string, "xindy uses an auto-detection mechanism to decide,
|
||||||
|
;; if the pattern is a regular expression or not". But it is not obvious to
|
||||||
|
;; guess, for example "\\_" is not detected as RE but "\\P\{\}" is, so for
|
||||||
|
;; being sure we apply the :string switch everywhere and do not use \\ etc...
|
||||||
|
|
||||||
|
;; Go back from sphinx.util.texescape TeX macros to UTF-8
|
||||||
|
|
||||||
|
(merge-rule "\sphinxleftcurlybrace{}" "{" :string)
|
||||||
|
(merge-rule "\sphinxrightcurlybrace{}" "}" :string)
|
||||||
|
(merge-rule "\_" "_" :string)
|
||||||
|
(merge-rule "{[}" "[" :string)
|
||||||
|
(merge-rule "{]}" "]" :string)
|
||||||
|
(merge-rule "\textbackslash{}" "\" :string) ; " for Emacs syntax highlighting
|
||||||
|
(merge-rule "\textasciitilde{}" "~~" :string); the ~~ escape is needed here
|
||||||
|
(merge-rule "\textasciicircum{}" "^" :string)
|
||||||
|
(merge-rule "\sphinxhyphen{}" "-" :string)
|
||||||
|
(merge-rule "\textquotesingle{}" "'" :string)
|
||||||
|
(merge-rule "\textasciigrave{}" "`" :string)
|
||||||
|
(merge-rule "\textless{}" "<" :string)
|
||||||
|
(merge-rule "\textgreater{}" ">" :string)
|
||||||
|
(merge-rule "\P{}" "¶" :string)
|
||||||
|
(merge-rule "\S{}" "§" :string)
|
||||||
|
(merge-rule "\texteuro{}" "€" :string)
|
||||||
|
(merge-rule "\(\infty\)" "∞" :string)
|
||||||
|
(merge-rule "\(\pm\)" "±" :string)
|
||||||
|
(merge-rule "\(\rightarrow\)" "→" :string)
|
||||||
|
(merge-rule "\(\checkmark\)" "✓" :string)
|
||||||
|
(merge-rule "\textendash{}" "–" :string)
|
||||||
|
(merge-rule "\textbar{}" "|" :string)
|
||||||
|
(merge-rule "\(\sp{\text{0}}\)" "⁰" :string)
|
||||||
|
(merge-rule "\(\sp{\text{1}}\)" "¹" :string)
|
||||||
|
(merge-rule "\(\sp{\text{2}}\)" "²" :string)
|
||||||
|
(merge-rule "\(\sp{\text{3}}\)" "³" :string)
|
||||||
|
(merge-rule "\(\sp{\text{4}}\)" "⁴" :string)
|
||||||
|
(merge-rule "\(\sp{\text{5}}\)" "⁵" :string)
|
||||||
|
(merge-rule "\(\sp{\text{6}}\)" "⁶" :string)
|
||||||
|
(merge-rule "\(\sp{\text{7}}\)" "⁷" :string)
|
||||||
|
(merge-rule "\(\sp{\text{8}}\)" "⁸" :string)
|
||||||
|
(merge-rule "\(\sp{\text{9}}\)" "⁹" :string)
|
||||||
|
(merge-rule "\(\sb{\text{0}}\)" "₀" :string)
|
||||||
|
(merge-rule "\(\sb{\text{1}}\)" "₁" :string)
|
||||||
|
(merge-rule "\(\sb{\text{2}}\)" "₂" :string)
|
||||||
|
(merge-rule "\(\sb{\text{3}}\)" "₃" :string)
|
||||||
|
(merge-rule "\(\sb{\text{4}}\)" "₄" :string)
|
||||||
|
(merge-rule "\(\sb{\text{5}}\)" "₅" :string)
|
||||||
|
(merge-rule "\(\sb{\text{6}}\)" "₆" :string)
|
||||||
|
(merge-rule "\(\sb{\text{7}}\)" "₇" :string)
|
||||||
|
(merge-rule "\(\sb{\text{8}}\)" "₈" :string)
|
||||||
|
(merge-rule "\(\sb{\text{9}}\)" "₉" :string)
|
||||||
|
(merge-rule "\IeC {\textalpha }" "α" :string)
|
||||||
|
(merge-rule "\IeC {\textbeta }" "β" :string)
|
||||||
|
(merge-rule "\IeC {\textgamma }" "γ" :string)
|
||||||
|
(merge-rule "\IeC {\textdelta }" "δ" :string)
|
||||||
|
(merge-rule "\IeC {\textepsilon }" "ε" :string)
|
||||||
|
(merge-rule "\IeC {\textzeta }" "ζ" :string)
|
||||||
|
(merge-rule "\IeC {\texteta }" "η" :string)
|
||||||
|
(merge-rule "\IeC {\texttheta }" "θ" :string)
|
||||||
|
(merge-rule "\IeC {\textiota }" "ι" :string)
|
||||||
|
(merge-rule "\IeC {\textkappa }" "κ" :string)
|
||||||
|
(merge-rule "\IeC {\textlambda }" "λ" :string)
|
||||||
|
(merge-rule "\IeC {\textmu }" "μ" :string)
|
||||||
|
(merge-rule "\IeC {\textnu }" "ν" :string)
|
||||||
|
(merge-rule "\IeC {\textxi }" "ξ" :string)
|
||||||
|
(merge-rule "\IeC {\textomicron }" "ο" :string)
|
||||||
|
(merge-rule "\IeC {\textpi }" "π" :string)
|
||||||
|
(merge-rule "\IeC {\textrho }" "ρ" :string)
|
||||||
|
(merge-rule "\IeC {\textsigma }" "σ" :string)
|
||||||
|
(merge-rule "\IeC {\texttau }" "τ" :string)
|
||||||
|
(merge-rule "\IeC {\textupsilon }" "υ" :string)
|
||||||
|
(merge-rule "\IeC {\textphi }" "φ" :string)
|
||||||
|
(merge-rule "\IeC {\textchi }" "χ" :string)
|
||||||
|
(merge-rule "\IeC {\textpsi }" "ψ" :string)
|
||||||
|
(merge-rule "\IeC {\textomega }" "ω" :string)
|
||||||
|
(merge-rule "\IeC {\textAlpha }" "Α" :string)
|
||||||
|
(merge-rule "\IeC {\textBeta }" "Β" :string)
|
||||||
|
(merge-rule "\IeC {\textGamma }" "Γ" :string)
|
||||||
|
(merge-rule "\IeC {\textDelta }" "Δ" :string)
|
||||||
|
(merge-rule "\IeC {\textEpsilon }" "Ε" :string)
|
||||||
|
(merge-rule "\IeC {\textZeta }" "Ζ" :string)
|
||||||
|
(merge-rule "\IeC {\textEta }" "Η" :string)
|
||||||
|
(merge-rule "\IeC {\textTheta }" "Θ" :string)
|
||||||
|
(merge-rule "\IeC {\textIota }" "Ι" :string)
|
||||||
|
(merge-rule "\IeC {\textKappa }" "Κ" :string)
|
||||||
|
(merge-rule "\IeC {\textLambda }" "Λ" :string)
|
||||||
|
(merge-rule "\IeC {\textMu }" "Μ" :string)
|
||||||
|
(merge-rule "\IeC {\textNu }" "Ν" :string)
|
||||||
|
(merge-rule "\IeC {\textTheta }" "Θ" :string)
|
||||||
|
(merge-rule "\IeC {\textIota }" "Ι" :string)
|
||||||
|
(merge-rule "\IeC {\textKappa }" "Κ" :string)
|
||||||
|
(merge-rule "\IeC {\textLambda }" "Λ" :string)
|
||||||
|
(merge-rule "\IeC {\textMu }" "Μ" :string)
|
||||||
|
(merge-rule "\IeC {\textNu }" "Ν" :string)
|
||||||
|
(merge-rule "\IeC {\textXi }" "Ξ" :string)
|
||||||
|
(merge-rule "\IeC {\textOmicron }" "Ο" :string)
|
||||||
|
(merge-rule "\IeC {\textPi }" "Π" :string)
|
||||||
|
(merge-rule "\IeC {\textRho }" "Ρ" :string)
|
||||||
|
(merge-rule "\IeC {\textSigma }" "Σ" :string)
|
||||||
|
(merge-rule "\IeC {\textTau }" "Τ" :string)
|
||||||
|
(merge-rule "\IeC {\textUpsilon }" "Υ" :string)
|
||||||
|
(merge-rule "\IeC {\textPhi }" "Φ" :string)
|
||||||
|
(merge-rule "\IeC {\textChi }" "Χ" :string)
|
||||||
|
(merge-rule "\IeC {\textPsi }" "Ψ" :string)
|
||||||
|
(merge-rule "\IeC {\textOmega }" "Ω" :string)
|
||||||
|
(merge-rule "\IeC {\textohm }" "Ω" :string)
|
||||||
|
|
||||||
|
;; This xindy module provides some basic support for "see"
|
||||||
|
(require "makeindex.xdy")
|
||||||
|
|
||||||
|
;; This creates one-letter headings and works fine with utf-8 letters.
|
||||||
|
;; For Cyrillic with pdflatex works thanks to LICRcyr2utf8.xdy
|
||||||
|
(require "latin-lettergroups.xdy")
|
||||||
|
|
||||||
|
;; currently we don't (know how to easily) separate "Numbers" from
|
||||||
|
;; "Symbols" with xindy as is the case with makeindex.
|
||||||
|
(markup-index :open "\begin{sphinxtheindex}
|
||||||
|
\let\lettergroup\sphinxstyleindexlettergroup
|
||||||
|
\let\lettergroupDefault\sphinxstyleindexlettergroupDefault
|
||||||
|
\let\spxpagem\sphinxstyleindexpagemain
|
||||||
|
\let\spxentry\sphinxstyleindexentry
|
||||||
|
\let\spxextra\sphinxstyleindexextra
|
||||||
|
|
||||||
|
"
|
||||||
|
:close "
|
||||||
|
|
||||||
|
\end{sphinxtheindex}
|
||||||
|
"
|
||||||
|
:tree)
|
||||||
|
|
||||||
130
build/latex/sphinxhighlight.sty
Normal file
130
build/latex/sphinxhighlight.sty
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||||
|
\ProvidesPackage{sphinxhighlight}[2022/06/30 stylesheet for highlighting with pygments]
|
||||||
|
% Its contents depend on pygments_style configuration variable.
|
||||||
|
|
||||||
|
|
||||||
|
\makeatletter
|
||||||
|
\def\PYG@reset{\let\PYG@it=\relax \let\PYG@bf=\relax%
|
||||||
|
\let\PYG@ul=\relax \let\PYG@tc=\relax%
|
||||||
|
\let\PYG@bc=\relax \let\PYG@ff=\relax}
|
||||||
|
\def\PYG@tok#1{\csname PYG@tok@#1\endcsname}
|
||||||
|
\def\PYG@toks#1+{\ifx\relax#1\empty\else%
|
||||||
|
\PYG@tok{#1}\expandafter\PYG@toks\fi}
|
||||||
|
\def\PYG@do#1{\PYG@bc{\PYG@tc{\PYG@ul{%
|
||||||
|
\PYG@it{\PYG@bf{\PYG@ff{#1}}}}}}}
|
||||||
|
\def\PYG#1#2{\PYG@reset\PYG@toks#1+\relax+\PYG@do{#2}}
|
||||||
|
|
||||||
|
\@namedef{PYG@tok@w}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.73,0.73}{##1}}}
|
||||||
|
\@namedef{PYG@tok@c}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}}
|
||||||
|
\@namedef{PYG@tok@cp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@cs}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}\def\PYG@bc##1{{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}}
|
||||||
|
\@namedef{PYG@tok@k}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@kp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@kt}{\def\PYG@tc##1{\textcolor[rgb]{0.56,0.13,0.00}{##1}}}
|
||||||
|
\@namedef{PYG@tok@o}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}}
|
||||||
|
\@namedef{PYG@tok@ow}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@nb}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@nf}{\def\PYG@tc##1{\textcolor[rgb]{0.02,0.16,0.49}{##1}}}
|
||||||
|
\@namedef{PYG@tok@nc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.05,0.52,0.71}{##1}}}
|
||||||
|
\@namedef{PYG@tok@nn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.05,0.52,0.71}{##1}}}
|
||||||
|
\@namedef{PYG@tok@ne}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@nv}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}}
|
||||||
|
\@namedef{PYG@tok@no}{\def\PYG@tc##1{\textcolor[rgb]{0.38,0.68,0.84}{##1}}}
|
||||||
|
\@namedef{PYG@tok@nl}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.13,0.44}{##1}}}
|
||||||
|
\@namedef{PYG@tok@ni}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.84,0.33,0.22}{##1}}}
|
||||||
|
\@namedef{PYG@tok@na}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@nt}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.02,0.16,0.45}{##1}}}
|
||||||
|
\@namedef{PYG@tok@nd}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.33,0.33,0.33}{##1}}}
|
||||||
|
\@namedef{PYG@tok@s}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@sd}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@si}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.44,0.63,0.82}{##1}}}
|
||||||
|
\@namedef{PYG@tok@se}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@sr}{\def\PYG@tc##1{\textcolor[rgb]{0.14,0.33,0.53}{##1}}}
|
||||||
|
\@namedef{PYG@tok@ss}{\def\PYG@tc##1{\textcolor[rgb]{0.32,0.47,0.09}{##1}}}
|
||||||
|
\@namedef{PYG@tok@sx}{\def\PYG@tc##1{\textcolor[rgb]{0.78,0.36,0.04}{##1}}}
|
||||||
|
\@namedef{PYG@tok@m}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}}
|
||||||
|
\@namedef{PYG@tok@gh}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}}
|
||||||
|
\@namedef{PYG@tok@gu}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.50,0.00,0.50}{##1}}}
|
||||||
|
\@namedef{PYG@tok@gd}{\def\PYG@tc##1{\textcolor[rgb]{0.63,0.00,0.00}{##1}}}
|
||||||
|
\@namedef{PYG@tok@gi}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.63,0.00}{##1}}}
|
||||||
|
\@namedef{PYG@tok@gr}{\def\PYG@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}}
|
||||||
|
\@namedef{PYG@tok@ge}{\let\PYG@it=\textit}
|
||||||
|
\@namedef{PYG@tok@gs}{\let\PYG@bf=\textbf}
|
||||||
|
\@namedef{PYG@tok@ges}{\let\PYG@bf=\textbf\let\PYG@it=\textit}
|
||||||
|
\@namedef{PYG@tok@gp}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.78,0.36,0.04}{##1}}}
|
||||||
|
\@namedef{PYG@tok@go}{\def\PYG@tc##1{\textcolor[rgb]{0.20,0.20,0.20}{##1}}}
|
||||||
|
\@namedef{PYG@tok@gt}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}}
|
||||||
|
\@namedef{PYG@tok@err}{\def\PYG@bc##1{{\setlength{\fboxsep}{\string -\fboxrule}\fcolorbox[rgb]{1.00,0.00,0.00}{1,1,1}{\strut ##1}}}}
|
||||||
|
\@namedef{PYG@tok@kc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@kd}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@kn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@kr}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@bp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}}
|
||||||
|
\@namedef{PYG@tok@fm}{\def\PYG@tc##1{\textcolor[rgb]{0.02,0.16,0.49}{##1}}}
|
||||||
|
\@namedef{PYG@tok@vc}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}}
|
||||||
|
\@namedef{PYG@tok@vg}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}}
|
||||||
|
\@namedef{PYG@tok@vi}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}}
|
||||||
|
\@namedef{PYG@tok@vm}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}}
|
||||||
|
\@namedef{PYG@tok@sa}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@sb}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@sc}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@dl}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@s2}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@sh}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@s1}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}}
|
||||||
|
\@namedef{PYG@tok@mb}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}}
|
||||||
|
\@namedef{PYG@tok@mf}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}}
|
||||||
|
\@namedef{PYG@tok@mh}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}}
|
||||||
|
\@namedef{PYG@tok@mi}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}}
|
||||||
|
\@namedef{PYG@tok@il}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}}
|
||||||
|
\@namedef{PYG@tok@mo}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}}
|
||||||
|
\@namedef{PYG@tok@ch}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}}
|
||||||
|
\@namedef{PYG@tok@cm}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}}
|
||||||
|
\@namedef{PYG@tok@cpf}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}}
|
||||||
|
\@namedef{PYG@tok@c1}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}}
|
||||||
|
|
||||||
|
\def\PYGZbs{\char`\\}
|
||||||
|
\def\PYGZus{\char`\_}
|
||||||
|
\def\PYGZob{\char`\{}
|
||||||
|
\def\PYGZcb{\char`\}}
|
||||||
|
\def\PYGZca{\char`\^}
|
||||||
|
\def\PYGZam{\char`\&}
|
||||||
|
\def\PYGZlt{\char`\<}
|
||||||
|
\def\PYGZgt{\char`\>}
|
||||||
|
\def\PYGZsh{\char`\#}
|
||||||
|
\def\PYGZpc{\char`\%}
|
||||||
|
\def\PYGZdl{\char`\$}
|
||||||
|
\def\PYGZhy{\char`\-}
|
||||||
|
\def\PYGZsq{\char`\'}
|
||||||
|
\def\PYGZdq{\char`\"}
|
||||||
|
\def\PYGZti{\char`\~}
|
||||||
|
% for compatibility with earlier versions
|
||||||
|
\def\PYGZat{@}
|
||||||
|
\def\PYGZlb{[}
|
||||||
|
\def\PYGZrb{]}
|
||||||
|
\makeatother
|
||||||
|
|
||||||
|
% Sphinx redefinitions
|
||||||
|
% Originally to obtain a straight single quote via package textcomp, then
|
||||||
|
% to fix problems for the 5.0.0 inline code highlighting (captions!).
|
||||||
|
% The \text is from amstext, a dependency of sphinx.sty. It is here only
|
||||||
|
% to avoid build errors if for some reason expansion is in math mode.
|
||||||
|
\def\PYGZbs{\text\textbackslash}
|
||||||
|
\def\PYGZus{\_}
|
||||||
|
\def\PYGZob{\{}
|
||||||
|
\def\PYGZcb{\}}
|
||||||
|
\def\PYGZca{\text\textasciicircum}
|
||||||
|
\def\PYGZam{\&}
|
||||||
|
\def\PYGZlt{\text\textless}
|
||||||
|
\def\PYGZgt{\text\textgreater}
|
||||||
|
\def\PYGZsh{\#}
|
||||||
|
\def\PYGZpc{\%}
|
||||||
|
\def\PYGZdl{\$}
|
||||||
|
\def\PYGZhy{\sphinxhyphen}% defined in sphinxlatexstyletext.sty
|
||||||
|
\def\PYGZsq{\text\textquotesingle}
|
||||||
|
\def\PYGZdq{"}
|
||||||
|
\def\PYGZti{\text\textasciitilde}
|
||||||
|
\makeatletter
|
||||||
|
% use \protected to allow syntax highlighting in captions
|
||||||
|
\protected\def\PYG#1#2{\PYG@reset\PYG@toks#1+\relax+{\PYG@do{#2}}}
|
||||||
|
\makeatother
|
||||||
102
build/latex/sphinxhowto.cls
Normal file
102
build/latex/sphinxhowto.cls
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
%
|
||||||
|
% sphinxhowto.cls for Sphinx (https://www.sphinx-doc.org/)
|
||||||
|
%
|
||||||
|
|
||||||
|
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||||
|
\ProvidesClass{sphinxhowto}[2019/12/01 v2.3.0 Document class (Sphinx howto)]
|
||||||
|
|
||||||
|
% 'oneside' option overriding the 'twoside' default
|
||||||
|
\newif\if@oneside
|
||||||
|
\DeclareOption{oneside}{\@onesidetrue}
|
||||||
|
% Pass remaining document options to the parent class.
|
||||||
|
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}}
|
||||||
|
\ProcessOptions\relax
|
||||||
|
|
||||||
|
% Default to two-side document
|
||||||
|
\if@oneside
|
||||||
|
% nothing to do (oneside is the default)
|
||||||
|
\else
|
||||||
|
\PassOptionsToClass{twoside}{\sphinxdocclass}
|
||||||
|
\fi
|
||||||
|
|
||||||
|
\LoadClass{\sphinxdocclass}
|
||||||
|
|
||||||
|
% Set some sane defaults for section numbering depth and TOC depth. You can
|
||||||
|
% reset these counters in your preamble.
|
||||||
|
%
|
||||||
|
\setcounter{secnumdepth}{2}
|
||||||
|
\setcounter{tocdepth}{2}% i.e. section and subsection
|
||||||
|
|
||||||
|
% Adapt \and command to the flushright context of \sphinxmaketitle, to
|
||||||
|
% avoid ragged line endings if author names do not fit all on one single line
|
||||||
|
\DeclareRobustCommand{\and}{%
|
||||||
|
\end{tabular}\kern-\tabcolsep
|
||||||
|
\allowbreak
|
||||||
|
\hskip\dimexpr1em+\tabcolsep\@plus.17fil\begin{tabular}[t]{c}%
|
||||||
|
}%
|
||||||
|
% If it is desired that each author name be on its own line, use in preamble:
|
||||||
|
%\DeclareRobustCommand{\and}{%
|
||||||
|
% \end{tabular}\kern-\tabcolsep\\\begin{tabular}[t]{c}%
|
||||||
|
%}%
|
||||||
|
% Change the title page to look a bit better, and fit in with the fncychap
|
||||||
|
% ``Bjarne'' style a bit better.
|
||||||
|
%
|
||||||
|
\newcommand{\sphinxmaketitle}{%
|
||||||
|
\noindent\rule{\linewidth}{1pt}\par
|
||||||
|
\begingroup % for PDF information dictionary
|
||||||
|
\def\endgraf{ }\def\and{\& }%
|
||||||
|
\pdfstringdefDisableCommands{\def\\{, }}% overwrite hyperref setup
|
||||||
|
\hypersetup{pdfauthor={\@author}, pdftitle={\@title}}%
|
||||||
|
\endgroup
|
||||||
|
\begin{flushright}
|
||||||
|
\sphinxlogo
|
||||||
|
\py@HeaderFamily
|
||||||
|
{\Huge \@title }\par
|
||||||
|
{\itshape\large \py@release \releaseinfo}\par
|
||||||
|
\vspace{25pt}
|
||||||
|
{\Large
|
||||||
|
\begin{tabular}[t]{c}
|
||||||
|
\@author
|
||||||
|
\end{tabular}\kern-\tabcolsep}\par
|
||||||
|
\vspace{25pt}
|
||||||
|
\@date \par
|
||||||
|
\py@authoraddress \par
|
||||||
|
\end{flushright}
|
||||||
|
\@thanks
|
||||||
|
\setcounter{footnote}{0}
|
||||||
|
\let\thanks\relax\let\maketitle\relax
|
||||||
|
%\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand{\sphinxtableofcontents}{%
|
||||||
|
\begingroup
|
||||||
|
\parskip \z@skip
|
||||||
|
\sphinxtableofcontentshook
|
||||||
|
\tableofcontents
|
||||||
|
\endgroup
|
||||||
|
\noindent\rule{\linewidth}{1pt}\par
|
||||||
|
\vspace{12pt}%
|
||||||
|
}
|
||||||
|
\newcommand\sphinxtableofcontentshook{}
|
||||||
|
\pagenumbering{arabic}
|
||||||
|
|
||||||
|
% Fix the bibliography environment to add an entry to the Table of
|
||||||
|
% Contents.
|
||||||
|
% For an article document class this environment is a section,
|
||||||
|
% so no page break before it.
|
||||||
|
%
|
||||||
|
\newenvironment{sphinxthebibliography}[1]{%
|
||||||
|
% \phantomsection % not needed here since TeXLive 2010's hyperref
|
||||||
|
\begin{thebibliography}{#1}%
|
||||||
|
\addcontentsline{toc}{section}{\ifdefined\refname\refname\else\ifdefined\bibname\bibname\fi\fi}}{\end{thebibliography}}
|
||||||
|
|
||||||
|
|
||||||
|
% Same for the indices.
|
||||||
|
% The memoir class already does this, so we don't duplicate it in that case.
|
||||||
|
%
|
||||||
|
\@ifclassloaded{memoir}
|
||||||
|
{\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}}
|
||||||
|
{\newenvironment{sphinxtheindex}{%
|
||||||
|
\phantomsection % needed because no chapter, section, ... is created by theindex
|
||||||
|
\begin{theindex}%
|
||||||
|
\addcontentsline{toc}{section}{\indexname}}{\end{theindex}}}
|
||||||
408
build/latex/sphinxlatexadmonitions.sty
Normal file
408
build/latex/sphinxlatexadmonitions.sty
Normal file
|
|
@ -0,0 +1,408 @@
|
||||||
|
%% NOTICES AND ADMONITIONS
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexadmonitions}[2025/10/24 v9.0.0 admonitions]
|
||||||
|
|
||||||
|
% Provides support for this output mark-up from Sphinx latex writer:
|
||||||
|
%
|
||||||
|
% - sphinxseealso environment added at 6.1.0.
|
||||||
|
%
|
||||||
|
% - sphinxtodo environment added at 7.4.0.
|
||||||
|
%
|
||||||
|
% - sphinxadmonition (environment)
|
||||||
|
% This is a dispatch which formerly configured
|
||||||
|
%
|
||||||
|
% - note, hint, important, tip to use sphinxlightbox (or optionally
|
||||||
|
% sphinxheavybox since 6.2.0),
|
||||||
|
% - warning, caution, attention, danger, error to use sphinxheavybox.
|
||||||
|
%
|
||||||
|
% Since 7.4.0 all admonitions use sphinxheavybox.
|
||||||
|
%
|
||||||
|
% - All environments sphinxnote, sphinxwarning, etc... can be redefined as
|
||||||
|
% will by user. Thay have a single parameter #1 which is the title.
|
||||||
|
%
|
||||||
|
% - Also redefinable by user are the one-argument commands
|
||||||
|
% * \sphinxstylenotetitle,
|
||||||
|
% * \sphinxstylewarningtitle,
|
||||||
|
% * etc.... one for each admonition type (also seealso and todo).
|
||||||
|
%
|
||||||
|
% - At 7.4.0, all commands of previous item use \sphinxdotitlerow.
|
||||||
|
% (the 7.4.0 name, still usable, was \sphinxdotitlerowwithicon; the 8.1.0
|
||||||
|
% version is also used for topic, contents and sidebar directives, see
|
||||||
|
% sphinxlatexshadowbox.sty, and handles both "with icon" and "without
|
||||||
|
% icon" situations).
|
||||||
|
%
|
||||||
|
% The sphinxlightbox environment is kept for backward compatibility, for user
|
||||||
|
% custom code which used it via custom definitions done in preamble or via
|
||||||
|
% raw latex directive.
|
||||||
|
% MEMO: here is for example how sphinxnote was formerly defined:
|
||||||
|
% (where #1 is the localized string Note, followed with a colon)
|
||||||
|
% \newenvironment{sphinxnote}[1]
|
||||||
|
% {\begin{sphinxlightbox}\sphinxstrong{#1} }
|
||||||
|
% {\end{sphinxlightbox}}
|
||||||
|
% Use this if you want to revert the 7.4.0 switch to usage of sphinxheavybox.
|
||||||
|
% (the 7.4.0 redefined \sphinxstylenotetitle will not work in sphinxlightbox,
|
||||||
|
% so \sphinxstrong{#1}<space> which was its former default is used above).
|
||||||
|
|
||||||
|
% Dependencies (they do not need to be defined at time of loading):
|
||||||
|
%
|
||||||
|
% - of course the various colour and dimension options handled via sphinx.sty
|
||||||
|
% - dimension register \spx@image@maxheight from sphinxlatexgraphics.sty
|
||||||
|
% - \savenotes/\spewnotes from sphinxpackagefootnote.sty
|
||||||
|
% - \ifspx@inframed defined in sphinx.sty
|
||||||
|
% - \spx@boxes@fcolorbox@setup from sphinxpackageboxes.sty
|
||||||
|
%
|
||||||
|
\RequirePackage{framed}
|
||||||
|
\RequirePackage{needspace}
|
||||||
|
% Those are required either before or after by sphinx.sty anyhow, but for
|
||||||
|
% clarity we list them here:
|
||||||
|
\RequirePackage{sphinxlatexgraphics}
|
||||||
|
\RequirePackage{sphinxpackagefootnote}
|
||||||
|
\RequirePackage{sphinxpackageboxes}
|
||||||
|
%
|
||||||
|
% Provides: (also in sphinxlatexliterals.sty)
|
||||||
|
% Only needed here by legacy (deprecated) sphinxlightbox environment.
|
||||||
|
\providecommand*\sphinxvspacefixafterfrenchlists{%
|
||||||
|
\ifvmode\ifdim\lastskip<\z@ \vskip\parskip\fi\else\par\fi
|
||||||
|
}
|
||||||
|
|
||||||
|
% This \dimen register is a legacy relic from Sphinx 1.5 which is used now
|
||||||
|
% only for sphinxlightbox. It is set in the sphinxadmonition environment.
|
||||||
|
\newdimen\spx@notice@border
|
||||||
|
% sphinxlightbox is now also a legacy relic, not used by Sphinx anymore
|
||||||
|
\newenvironment{sphinxlightbox}{%
|
||||||
|
\par
|
||||||
|
\noindent{\color{spx@notice@bordercolor}%
|
||||||
|
\rule{\linewidth}{\spx@notice@border}}%
|
||||||
|
\par\nobreak
|
||||||
|
{\parskip\z@skip\noindent}%
|
||||||
|
}
|
||||||
|
{%
|
||||||
|
% counteract previous possible negative skip (French lists!):
|
||||||
|
% (we can't cancel that any earlier \vskip introduced a potential pagebreak)
|
||||||
|
\sphinxvspacefixafterfrenchlists
|
||||||
|
\nobreak\vbox{\noindent\kern\@totalleftmargin
|
||||||
|
{\color{spx@notice@bordercolor}%
|
||||||
|
\rule[\dimexpr.4\baselineskip-\spx@notice@border\relax]
|
||||||
|
{\linewidth}{\spx@notice@border}}\hss}\allowbreak
|
||||||
|
}% end of sphinxlightbox environment definition
|
||||||
|
|
||||||
|
% Since 1.5 these environments are named individually sphinxnote, sphinxhint,
|
||||||
|
% etc... to allow user to redefine them entirely.
|
||||||
|
%
|
||||||
|
% The Sphinx definitions for note/hint/important/tip notices were done like
|
||||||
|
% this, prior to 6.2.0:
|
||||||
|
%
|
||||||
|
% \newenvironment{sphinxhint}[1]
|
||||||
|
% {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}}
|
||||||
|
%
|
||||||
|
% Then from 6.2.0 to 7.4.0 (exclusive) a more complex definition decided
|
||||||
|
% to use either sphinxlightbox or sphinxheavybox according to whether
|
||||||
|
% some CSS-like options had been used, for example for a background color.
|
||||||
|
%
|
||||||
|
% 6.2.0 also added one layer of mark-up via \sphinxnotetitle etc..., because
|
||||||
|
% the former \sphinxstrong{#1}<space> used a too generic \sphinxstrong.
|
||||||
|
%
|
||||||
|
% At 7.4.0, sphinxheavybox environment is default for all types of notices
|
||||||
|
% and also for the seealso and todo directives.
|
||||||
|
%
|
||||||
|
% Code adapted from framed.sty's "snugshade" environment.
|
||||||
|
% Nesting works (inner frames do not allow page breaks).
|
||||||
|
%
|
||||||
|
% At 9.0, avoid admonition title getting separated from contents at a
|
||||||
|
% page break.
|
||||||
|
\newcommand\sphinxheavyboxneedspacecommand{\needspace{5\baselineskip}}
|
||||||
|
\newenvironment{sphinxheavybox}{\par
|
||||||
|
\sphinxheavyboxneedspacecommand
|
||||||
|
% (MEMO: it is not a problem here if there is no sphinx<type>ShadowColor,
|
||||||
|
% as it used only if set)
|
||||||
|
\spx@boxes@fcolorbox@setup{\spx@noticetype}%
|
||||||
|
% Those are used by sphinxVerbatim if the \ifspx@inframed boolean is true
|
||||||
|
\setlength{\FrameRule}{0.5\dimexpr\spx@boxes@border@top+\spx@boxes@border@bottom\relax}%
|
||||||
|
% MEMO: prior to 5.1.0 \FrameSep was determined as 0.6\baselineskip -
|
||||||
|
% \FrameRule, and there was no possibility for user to adjust padding.
|
||||||
|
% Then \fcolorbox was used with \fboxrule set to \FrameRule and \fboxsep
|
||||||
|
% set to \FrameSep.
|
||||||
|
% The 5.1.0 default calculation of padding parameters maintains PDF output
|
||||||
|
% identical to legacy behaviour, as long as padding is not set by user.
|
||||||
|
\setlength{\FrameSep}{0.5\dimexpr\spx@boxes@padding@top+\spx@boxes@padding@bottom\relax}%
|
||||||
|
% "setup" macro has prepared the \spx@boxes@... dimen registers
|
||||||
|
\advance\spx@image@maxheight
|
||||||
|
-\dimexpr\spx@boxes@border@top+\spx@boxes@border@bottom
|
||||||
|
+\spx@boxes@padding@top+\spx@boxes@padding@bottom
|
||||||
|
+\baselineskip\relax % will happen again if nested, needed indeed!
|
||||||
|
% MEMO: the next comment is before boxing was extended to allow padding and
|
||||||
|
% multiple border-widths, not to mention shadows...
|
||||||
|
% configure framed.sty's parameters to obtain same vertical spacing
|
||||||
|
% as for "light" boxes. We need for this to manually insert parskip glue and
|
||||||
|
% revert a skip done by framed before the frame.
|
||||||
|
\ltx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}%
|
||||||
|
\vspace{\FrameHeightAdjust}
|
||||||
|
% copied/adapted from framed.sty's snugshade
|
||||||
|
% but now using in place of \fcolorbox the Sphinx sophisticated own
|
||||||
|
\def\FrameCommand##1{%
|
||||||
|
\hskip\@totalleftmargin
|
||||||
|
% "setup" macro MUST have been called before
|
||||||
|
\spx@boxes@fcolorbox{##1}%
|
||||||
|
\hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth
|
||||||
|
}%
|
||||||
|
% 6.2.0 adds support for div.<notice type>_box-decoration-break=slice.
|
||||||
|
% (it is yet undecided if slice style should inhibit a bottom shadow)
|
||||||
|
\csname ifspx@\spx@noticetype @border@open\endcsname
|
||||||
|
\def\FirstFrameCommand
|
||||||
|
{\spx@boxes@fcolorbox@setup@openbottom\FrameCommand}%
|
||||||
|
\def\MidFrameCommand
|
||||||
|
{\spx@boxes@fcolorbox@setup@openboth \FrameCommand}%
|
||||||
|
\def\LastFrameCommand
|
||||||
|
{\spx@boxes@fcolorbox@setup@opentop \FrameCommand}%
|
||||||
|
\fi
|
||||||
|
\savenotes
|
||||||
|
% use a minipage if we are already inside a framed environment
|
||||||
|
\ifspx@inframed
|
||||||
|
\noindent\begin{minipage}{\linewidth}
|
||||||
|
\else
|
||||||
|
% handle case where notice is first thing in a list item (or is quoted)
|
||||||
|
\if@inlabel
|
||||||
|
\noindent\par\vspace{-\baselineskip}
|
||||||
|
\else
|
||||||
|
\vspace{\parskip}
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\MakeFramed {\spx@inframedtrue
|
||||||
|
\advance\hsize-\width \@totalleftmargin\z@ \linewidth\hsize
|
||||||
|
% minipage initialization copied from LaTeX source code.
|
||||||
|
\@pboxswfalse
|
||||||
|
\let\@listdepth\@mplistdepth \@mplistdepth\z@
|
||||||
|
\@minipagerestore
|
||||||
|
\@setminipage }%
|
||||||
|
\color@begingroup % workaround to an upstream framed.sty bug
|
||||||
|
}
|
||||||
|
{%
|
||||||
|
\par\unskip
|
||||||
|
\color@endgroup % matches the \color@begingroup
|
||||||
|
\@minipagefalse
|
||||||
|
\endMakeFramed
|
||||||
|
\ifspx@inframed\end{minipage}\fi
|
||||||
|
% set footnotes at bottom of page
|
||||||
|
\spewnotes
|
||||||
|
% arrange for similar spacing below frame as for "light" boxes.
|
||||||
|
\vskip .4\baselineskip
|
||||||
|
}% end of sphinxheavybox environment definition
|
||||||
|
|
||||||
|
% - Since 1.5 these environments are named individually to allow user to
|
||||||
|
% redefine them entirely.
|
||||||
|
%
|
||||||
|
% - Since 5.1.0, sphinxheavybox is more versatile and four border widths, four
|
||||||
|
% padding widths, four corner radii, optional shadow, and three colors can all
|
||||||
|
% be modified via CSS-named alike options.
|
||||||
|
%
|
||||||
|
% - Since 6.2.0, also note/hint/important/tip notices can use these options
|
||||||
|
% and then they go automatically via sphinxheavybox. If only the legacy options
|
||||||
|
% are used, they keep using sphinxlightbox.
|
||||||
|
%
|
||||||
|
% - Since 6.2.0, \sphinxwarningtitle etc... add one level of mark-up (they
|
||||||
|
% expand to \sphinxstrong{#1}<space> which was former hard-coded mark-up).
|
||||||
|
% Example:
|
||||||
|
% \renewcommand{\sphinxwarningtitle}[1]{\textbf{#1}\par\smallskip
|
||||||
|
% {\color{sphinxwarningBorderColor}\hrule height1pt}\smallskip}
|
||||||
|
%
|
||||||
|
% - Since 7.4.0, all types of notices use sphinxheavybox and the default
|
||||||
|
% for \sphinxstyle<type>title is mapped to using \sphinxdotitlerowwithicon{<type>}
|
||||||
|
%
|
||||||
|
% MEMO: except for the generic admonition directive (which uses "note" type)
|
||||||
|
% the argument #1 in these environments has a postfixed colon originating
|
||||||
|
% in Sphinx LaTeX writer legacy code. The
|
||||||
|
% \sphinxremovefinalcolon utility in sphinxlatexstyletext.sty can be used as
|
||||||
|
% \sphinxremovefinalcolon{#1} from inside the definitions of
|
||||||
|
% \sphinxstylenotetitle et al. commands.
|
||||||
|
|
||||||
|
% Important: even prior to 5.1.0 it was not really possible to use directly
|
||||||
|
% sphinxheavybox if not triggered from sphinxadmonition, because some
|
||||||
|
% parameters were defined in sphinxadmonition. This meant that the
|
||||||
|
% sphinxwarning, sphinxcaution etc... environments (defined below) could not
|
||||||
|
% be used directly in a document, they had to be triggered via
|
||||||
|
% sphinxadmonition. The sole data since 5.1.0 needed by sphinxheavybox is the
|
||||||
|
% type of the notice which sphinxadmonition stores into \spx@noticetype.
|
||||||
|
%
|
||||||
|
% In order to facilitate recycling or imitation of the sphinx<type>
|
||||||
|
% environments, 7.4.0 inserts an extra \def\spx@noticetype{<type>} in their
|
||||||
|
% definitions, so that they can be used independently of sphinxadmonition
|
||||||
|
% dispatcher.
|
||||||
|
%
|
||||||
|
% MEMO: direct usage of these environments does not execute the div.<type>_TeXextras
|
||||||
|
% and div.<type>_TexColor code, there are only done from the sphinxadmonition wrapper.
|
||||||
|
\newenvironment{sphinxnote}[1]
|
||||||
|
{\def\spx@noticetype{note}\begin{sphinxheavybox}\sphinxstylenotetitle{#1}}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
\newenvironment{sphinxhint}[1]
|
||||||
|
{\def\spx@noticetype{hint}\begin{sphinxheavybox}\sphinxstylehinttitle{#1}}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
\newenvironment{sphinxtip}[1]
|
||||||
|
{\def\spx@noticetype{tip}\begin{sphinxheavybox}\sphinxstyletiptitle{#1}}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
\newenvironment{sphinximportant}[1]
|
||||||
|
{\def\spx@noticetype{important}\begin{sphinxheavybox}\sphinxstyleimportanttitle{#1}}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
\newenvironment{sphinxwarning}[1]
|
||||||
|
{\def\spx@noticetype{warning}\begin{sphinxheavybox}\sphinxstylewarningtitle{#1}}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
\newenvironment{sphinxcaution}[1]
|
||||||
|
{\def\spx@noticetype{caution}\begin{sphinxheavybox}\sphinxstylecautiontitle{#1}}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
\newenvironment{sphinxattention}[1]
|
||||||
|
{\def\spx@noticetype{attention}\begin{sphinxheavybox}\sphinxstyleattentiontitle{#1}}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
\newenvironment{sphinxdanger}[1]
|
||||||
|
{\def\spx@noticetype{danger}\begin{sphinxheavybox}\sphinxstyledangertitle{#1}}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
\newenvironment{sphinxerror}[1]
|
||||||
|
{\def\spx@noticetype{error}\begin{sphinxheavybox}\sphinxstyleerrortitle{#1}}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
% The "see also" was quite plain until 7.4.0 as it simply did
|
||||||
|
% \newenvironment{sphinxseealso}[1]{\sphinxstyleseealsotitle{#1}}{}
|
||||||
|
% Here we need to manually insert execution of div.seealso_TeX{color,extras} values
|
||||||
|
\newenvironment{sphinxseealso}[1]
|
||||||
|
{\def\spx@noticetype{seealso}%
|
||||||
|
\begin{sphinxheavybox}\sphinxstyleseealsotitle{#1}%
|
||||||
|
\ifspx@seealso@withtextcolor\color{sphinxseealsoTextColor}\fi
|
||||||
|
\spx@seealso@TeXextras
|
||||||
|
}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
% There was no sphinxtodo environment until 7.4.0 because sphinx.ext.todo
|
||||||
|
% generated \begin{sphinxadmonition}{note}{Todo:} mark-up.
|
||||||
|
\newcounter{sphinxtodo}% to provide targets from todolist directive output
|
||||||
|
\newenvironment{sphinxtodo}[1]
|
||||||
|
{\refstepcounter{sphinxtodo}\def\spx@noticetype{todo}%
|
||||||
|
\begin{sphinxheavybox}\sphinxstyletodotitle{#1}%
|
||||||
|
\ifspx@todo@withtextcolor\color{sphinxtodoTextColor}\fi
|
||||||
|
\spx@todo@TeXextras
|
||||||
|
}
|
||||||
|
{\end{sphinxheavybox}}
|
||||||
|
|
||||||
|
|
||||||
|
% the main dispatch for all types of notices
|
||||||
|
\newenvironment{sphinxadmonition}[2]{% #1=type, #2=heading
|
||||||
|
% can't use #1 directly in definition of end part
|
||||||
|
\def\spx@noticetype {#1}%
|
||||||
|
% those next three are a remnant of legacy code; they are not used at
|
||||||
|
% all by sphinxheavybox, and their usage could be disposed of by sphinxlightbox
|
||||||
|
% but we keep for backward compatibility and also because it may be simpler
|
||||||
|
% for user redefinitions to employ for example "spx@notice@bgcolor" and not
|
||||||
|
% the more bulky "sphinx\spx@noticetype BgColor".
|
||||||
|
\sphinxcolorlet{spx@notice@bordercolor}{sphinx#1BorderColor}%
|
||||||
|
\sphinxcolorlet{spx@notice@bgcolor}{sphinx#1BgColor}%
|
||||||
|
% At 7.4.0 there are no \spx@<type>@boder macros anymore only top, left,
|
||||||
|
% bottom, right. For this legacy \spx@notice@border only needed by
|
||||||
|
% sphinxlightbox (which is not used by own Sphinx environments anymore)
|
||||||
|
% we thus use here @top
|
||||||
|
\spx@notice@border \dimexpr\csname spx@#1@border@top\endcsname\relax
|
||||||
|
% trigger the sphinx<type> environment, #2=heading is passed as argument
|
||||||
|
\begin{sphinx#1}{#2}%
|
||||||
|
% MEMO: the heading #2 will be typeset before the next lines are executed
|
||||||
|
% 6.2.0 support of div.<type>_TeX{color,extras} options
|
||||||
|
\csname ifspx@\spx@noticetype @withtextcolor\endcsname
|
||||||
|
\color{sphinx\spx@noticetype TextColor}%
|
||||||
|
\fi
|
||||||
|
% Other code to be executed at start of contents (after title)
|
||||||
|
\csname spx@\spx@noticetype @TeXextras\endcsname
|
||||||
|
}
|
||||||
|
% workaround some LaTeX "feature" of \end command (i.e. can't use "sphinx#1" here)
|
||||||
|
{\edef\spx@temp{\noexpand\end{sphinx\spx@noticetype}}\spx@temp}
|
||||||
|
|
||||||
|
% TODO: allow these next three settings to be customized individually.
|
||||||
|
% This can however already be done at user level by \renewcommand
|
||||||
|
% inside renew'ed environments sphinxnote, sphinxhint etc...
|
||||||
|
\newcommand\sphinxtitlerowtoppadding{5pt}
|
||||||
|
\newcommand\sphinxtitlerowbottompadding{3pt}
|
||||||
|
\newcommand\sphinxtitlerowaftericonspacecmd{\hskip0.5em\relax}
|
||||||
|
% 7.4.0 used this longer name:
|
||||||
|
\newcommand\sphinxdotitlerowwithicon{\sphinxdotitlerow}
|
||||||
|
\newcommand\sphinxdotitlerow[2]{% #1=type, #2=heading (without final colon)
|
||||||
|
\begingroup
|
||||||
|
\kern-\spx@boxes@padding@top
|
||||||
|
\parskip\z@skip % the \parskip business is a workaround to a vertical
|
||||||
|
% glue issue showing in LaTeX earlier than 2023-06-01
|
||||||
|
\noindent
|
||||||
|
\kern-\spx@boxes@padding@left % must have been configured by a prior
|
||||||
|
% \spx@boxes@fcolorbox@setup{<type>}
|
||||||
|
% inherit settings from the enclosing box and modify what is needed
|
||||||
|
\spx@boxes@border@top =\z@
|
||||||
|
\spx@boxes@border@right =\z@
|
||||||
|
\spx@boxes@border@bottom =\z@
|
||||||
|
\spx@boxes@border@left =\z@
|
||||||
|
\spx@boxes@radius@bottomright@x=\z@
|
||||||
|
\spx@boxes@radius@bottomright@y=\z@
|
||||||
|
\spx@boxes@radius@bottomleft@x=\z@
|
||||||
|
\spx@boxes@radius@bottomleft@x=\z@
|
||||||
|
\spx@boxes@padding@top =\sphinxtitlerowtoppadding\relax
|
||||||
|
\spx@boxes@padding@bottom=\sphinxtitlerowbottompadding\relax
|
||||||
|
\spx@boxes@withshadowfalse
|
||||||
|
\sphinxcolorlet{spx@boxes@backgroundcolor}{sphinx#1TtlBgColor}%
|
||||||
|
\spx@boxes@fcolorbox{%
|
||||||
|
\parbox[t]{\linewidth}{% 7.4.0 used \makebox, but wrapping of long titles
|
||||||
|
% is needed for generic admonition or topic box.
|
||||||
|
\sphinxAtStartPar
|
||||||
|
% 8.1.0 auto-drops extra space if no icon
|
||||||
|
\sbox\z@{\@nameuse{sphinx#1TtlIcon}}%
|
||||||
|
\ifdim\wd\z@>\z@
|
||||||
|
\textcolor{sphinx#1TtlFgColor}{%
|
||||||
|
\@nameuse{sphinx#1TtlIcon}%
|
||||||
|
% The next macro is located here for legacy reasons of earlier
|
||||||
|
% functioning of sphinx.sty now removed \spx@faIcon macro.
|
||||||
|
% We leave it here now although it could be moved to after
|
||||||
|
% the closing brace.
|
||||||
|
\sphinxtitlerowaftericonspacecmd
|
||||||
|
}%
|
||||||
|
\fi
|
||||||
|
\sphinxstrong{#2}%
|
||||||
|
\strut
|
||||||
|
\par
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
\kern-\spx@boxes@padding@right
|
||||||
|
\par
|
||||||
|
\endgroup
|
||||||
|
\vskip-\parskip
|
||||||
|
\kern\spx@boxes@padding@top
|
||||||
|
}
|
||||||
|
|
||||||
|
% #1 holds the localized name of the notice, postfixed with a colon.
|
||||||
|
% \sphinxremovefinalcolon{#1} will typeset #1 without the colon.
|
||||||
|
% Legacy definitions (done in sphinxlatexstyletext.sty) were all using
|
||||||
|
% a boring plain \sphinxstrong{#1}, now we use a coloured title row.
|
||||||
|
\newcommand\sphinxstylenotetitle [1]{\sphinxdotitlerow{note}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstylehinttitle [1]{\sphinxdotitlerow{hint}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstyleimportanttitle[1]{\sphinxdotitlerow{important}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstyletiptitle [1]{\sphinxdotitlerow{tip}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstylewarningtitle [1]{\sphinxdotitlerow{warning}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstylecautiontitle [1]{\sphinxdotitlerow{caution}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstyleattentiontitle[1]{\sphinxdotitlerow{attention}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstyledangertitle [1]{\sphinxdotitlerow{danger}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstyleerrortitle [1]{\sphinxdotitlerow{error}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstyleseealsotitle [1]{\sphinxdotitlerow{seealso}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
\newcommand\sphinxstyletodotitle [1]{\sphinxdotitlerow{todo}{\sphinxremovefinalcolon{#1}}}
|
||||||
|
%
|
||||||
|
% A utility to remove a final colon. Removing last token is not easy in
|
||||||
|
% LaTeX, and there are additional complications:
|
||||||
|
% - some languages will make the : "active" in document body,
|
||||||
|
% - the generic admonition ends up using "note", so for \sphinxnotetitle to
|
||||||
|
% use it safely, the utility has to allow an input not having any final colon.
|
||||||
|
% - a bit far-fetched but maybe there is more than one colon inside the input
|
||||||
|
% (possible from a generic admonition title).
|
||||||
|
% Hence the scary code.
|
||||||
|
\newcommand\sphinxremovefinalcolon[1]{% #1 is the "active" : TeX token
|
||||||
|
% Prior to 7.4.0 this was defined with \protected\def but we do not
|
||||||
|
% see what usefulness this could have.
|
||||||
|
\renewcommand\sphinxremovefinalcolon[1]{%
|
||||||
|
% complications due to : possibly "active"
|
||||||
|
\begingroup\ifnum\catcode`:=\active
|
||||||
|
\def\x####1#1\relax{####1}%
|
||||||
|
\else\def\x####1:\relax{####1}\fi
|
||||||
|
\expandafter\endgroup\x##1\relax
|
||||||
|
% trick to let \x work also if input ##1 has no ending colon
|
||||||
|
\@gobblefour#1\relax:\relax\relax\relax
|
||||||
|
}%
|
||||||
|
}% end of wrapper to inject active :
|
||||||
|
\begingroup\catcode`:\active\expandafter\endgroup\sphinxremovefinalcolon:
|
||||||
|
|
||||||
|
\endinput
|
||||||
22
build/latex/sphinxlatexcontainers.sty
Normal file
22
build/latex/sphinxlatexcontainers.sty
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
%% CONTAINER DIRECTIVES
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexcontainers}[2021/05/03 containers]
|
||||||
|
|
||||||
|
% The purpose of this file is to provide a dummy environment sphinxclass which
|
||||||
|
% will be inserted for each class in each container directive. The class name
|
||||||
|
% will be passed as the argument to the environment.
|
||||||
|
%
|
||||||
|
% For a class foo, the user can define customised handling of that class by
|
||||||
|
% defining the sphinxclassfoo LaTeX environment.
|
||||||
|
|
||||||
|
\newenvironment{sphinxuseclass}[1]{%
|
||||||
|
\def\sphinxClassFunctionName{sphinxclass#1}%
|
||||||
|
\ltx@ifundefined{\sphinxClassFunctionName}%
|
||||||
|
{}% undefined so do nothing
|
||||||
|
{\expandafter\begin\expandafter{\sphinxClassFunctionName}}%
|
||||||
|
}{%
|
||||||
|
\ltx@ifundefined{\sphinxClassFunctionName}%
|
||||||
|
{}% we did nothing so we keep doing nothing
|
||||||
|
{\expandafter\end\expandafter{\sphinxClassFunctionName}}%
|
||||||
|
}%
|
||||||
123
build/latex/sphinxlatexgraphics.sty
Normal file
123
build/latex/sphinxlatexgraphics.sty
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
%% GRAPHICS
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexgraphics}[2024/08/13 v8.1.0 graphics]
|
||||||
|
|
||||||
|
% Provides support for this output mark-up from Sphinx latex writer:
|
||||||
|
%
|
||||||
|
% - macros:
|
||||||
|
%
|
||||||
|
% - \sphinxfigcaption
|
||||||
|
% - \sphinxincludegraphics
|
||||||
|
%
|
||||||
|
% - environments:
|
||||||
|
%
|
||||||
|
% - sphinxfigure-in-table
|
||||||
|
%
|
||||||
|
% May change:
|
||||||
|
%
|
||||||
|
% - \sphinxcaption (at begin document)
|
||||||
|
%
|
||||||
|
% Also provides:
|
||||||
|
%
|
||||||
|
% - \sphinxsafeincludegraphics (default of \sphinxincludegraphics since 2.0)
|
||||||
|
% - \spx@image@maxheight dimension (used by sphinxlatexadmonitions.sty)
|
||||||
|
% - \spx@image@box scratch box register (also used by sphinxlatexliterals.sty)
|
||||||
|
%
|
||||||
|
% Requires:
|
||||||
|
% \RequirePackage{graphicx}% done in sphinx.sty
|
||||||
|
\RequirePackage{amstext}% needed for \firstchoice@true(false)
|
||||||
|
|
||||||
|
% \sphinxincludegraphics resizes images larger than the TeX \linewidth (which
|
||||||
|
% is adjusted in indented environments), or taller than a certain maximal
|
||||||
|
% height (usually \textheight and this is reduced in the environments which use
|
||||||
|
% framed.sty to avoid infinite loop if image too tall).
|
||||||
|
%
|
||||||
|
% In case height or width options are present the rescaling is done
|
||||||
|
% (since 2.0), in a way keeping the width:height ratio either native from
|
||||||
|
% image or from the width and height options if both were present.
|
||||||
|
%
|
||||||
|
\newdimen\spx@image@maxheight
|
||||||
|
\AtBeginDocument{\spx@image@maxheight\textheight}
|
||||||
|
|
||||||
|
% box scratch register
|
||||||
|
\newbox\spx@image@box
|
||||||
|
\newcommand*{\sphinxsafeincludegraphics}[2][]{%
|
||||||
|
% #1 contains possibly width=, height=, but no scale= since 1.8.4
|
||||||
|
\setbox\spx@image@box\hbox{\includegraphics[#1,draft]{#2}}%
|
||||||
|
\in@false % use some handy boolean flag
|
||||||
|
\ifdim \wd\spx@image@box>\linewidth
|
||||||
|
\in@true % flag to remember to adjust options and set box dimensions
|
||||||
|
% compute height which results from rescaling width to \linewidth
|
||||||
|
% and keep current aspect ratio. multiply-divide in \numexpr uses
|
||||||
|
% temporarily doubled precision, hence no overflow. (of course we
|
||||||
|
% assume \ht is not a few sp's below \maxdimen...(about 16384pt).
|
||||||
|
\edef\spx@image@rescaledheight % with sp units
|
||||||
|
{\the\numexpr\ht\spx@image@box
|
||||||
|
*\linewidth/\wd\spx@image@box sp}%
|
||||||
|
\ifdim\spx@image@rescaledheight>\spx@image@maxheight
|
||||||
|
% the rescaled height will be too big, so it is height which decides
|
||||||
|
% the rescaling factor
|
||||||
|
\def\spx@image@requiredheight{\spx@image@maxheight}% dimen register
|
||||||
|
\edef\spx@image@requiredwidth % with sp units
|
||||||
|
{\the\numexpr\wd\spx@image@box
|
||||||
|
*\spx@image@maxheight/\ht\spx@image@box sp}%
|
||||||
|
% TODO: decide if this commented-out block could be needed due to
|
||||||
|
% rounding in numexpr operations going up
|
||||||
|
% \ifdim\spx@image@requiredwidth>\linewidth
|
||||||
|
% \def\spx@image@requiredwidth{\linewidth}% dimen register
|
||||||
|
% \fi
|
||||||
|
\else
|
||||||
|
\def\spx@image@requiredwidth{\linewidth}% dimen register
|
||||||
|
\let\spx@image@requiredheight\spx@image@rescaledheight% sp units
|
||||||
|
\fi
|
||||||
|
\else
|
||||||
|
% width is ok, let's check height
|
||||||
|
\ifdim\ht\spx@image@box>\spx@image@maxheight
|
||||||
|
\in@true
|
||||||
|
\edef\spx@image@requiredwidth % with sp units
|
||||||
|
{\the\numexpr\wd\spx@image@box
|
||||||
|
*\spx@image@maxheight/\ht\spx@image@box sp}%
|
||||||
|
\def\spx@image@requiredheight{\spx@image@maxheight}% dimen register
|
||||||
|
\fi
|
||||||
|
\fi % end of check of width and height
|
||||||
|
\ifin@
|
||||||
|
\setbox\spx@image@box
|
||||||
|
\hbox{\includegraphics
|
||||||
|
[#1,% contains only width and/or height which are overruled next
|
||||||
|
% but in future may contain page=N hence must be kept
|
||||||
|
width=\spx@image@requiredwidth,height=\spx@image@requiredheight]%
|
||||||
|
{#2}}%
|
||||||
|
% \includegraphics does not set box dimensions to the exactly
|
||||||
|
% requested ones, see https://github.com/latex3/latex2e/issues/112
|
||||||
|
\wd\spx@image@box\spx@image@requiredwidth
|
||||||
|
\ht\spx@image@box\spx@image@requiredheight
|
||||||
|
\leavevmode\box\spx@image@box
|
||||||
|
\else
|
||||||
|
% here we do not modify the options, no need to adjust width and height
|
||||||
|
% on output, they will be computed exactly as with "draft" option
|
||||||
|
\setbox\spx@image@box\box\voidb@x % clear memory
|
||||||
|
\includegraphics[#1]{#2}%
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
% Use the "safe" one by default (2.0)
|
||||||
|
\def\sphinxincludegraphics{\sphinxsafeincludegraphics}
|
||||||
|
|
||||||
|
|
||||||
|
%% FIGURE IN TABLE
|
||||||
|
%
|
||||||
|
\newenvironment{sphinxfigure-in-table}[1][\linewidth]{%
|
||||||
|
\def\@captype{figure}%
|
||||||
|
\sphinxsetvskipsforfigintablecaption
|
||||||
|
\begin{minipage}{#1}%
|
||||||
|
}{\end{minipage}}
|
||||||
|
% tabulary expands twice contents, we need to prevent double counter stepping
|
||||||
|
\newcommand*\sphinxfigcaption
|
||||||
|
{\ifx\equation$%$% this is trick to identify tabulary first pass
|
||||||
|
\firstchoice@false\else\firstchoice@true\fi
|
||||||
|
\spx@originalcaption }
|
||||||
|
\newcommand*\sphinxsetvskipsforfigintablecaption
|
||||||
|
{\abovecaptionskip\smallskipamount
|
||||||
|
\belowcaptionskip\smallskipamount}
|
||||||
|
|
||||||
|
\endinput
|
||||||
69
build/latex/sphinxlatexindbibtoc.sty
Normal file
69
build/latex/sphinxlatexindbibtoc.sty
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
%% INDEX, BIBLIOGRAPHY, APPENDIX, TABLE OF CONTENTS
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexindbibtoc}[2021/01/27 index, bib., toc]
|
||||||
|
|
||||||
|
% Provides support for this output mark-up from Sphinx latex writer:
|
||||||
|
%
|
||||||
|
% - environments: (backup defaults or get redefined)
|
||||||
|
%
|
||||||
|
% - sphinxtheindex (direct mark-up or via python.ist or sphinx.xdy)
|
||||||
|
% - sphinxthebibliography
|
||||||
|
%
|
||||||
|
% - macros: (defines defaults)
|
||||||
|
%
|
||||||
|
% - \sphinxmaketitle
|
||||||
|
% - \sphinxtableofcontents
|
||||||
|
% - \sphinxnonalphabeticalgroupname
|
||||||
|
% - \sphinxsymbolsname
|
||||||
|
% - \sphinxnumbersname
|
||||||
|
% - \sphinxcite
|
||||||
|
%
|
||||||
|
% Requires:
|
||||||
|
\RequirePackage{makeidx}
|
||||||
|
|
||||||
|
% fix the double index and bibliography on the table of contents
|
||||||
|
% in jsclasses (Japanese standard document classes)
|
||||||
|
\ifx\@jsc@uplatextrue\@undefined\else
|
||||||
|
\renewenvironment{sphinxtheindex}
|
||||||
|
{\cleardoublepage\phantomsection
|
||||||
|
\begin{theindex}}
|
||||||
|
{\end{theindex}}
|
||||||
|
|
||||||
|
\renewenvironment{sphinxthebibliography}[1]
|
||||||
|
{\cleardoublepage% \phantomsection % not needed here since TeXLive 2010's hyperref
|
||||||
|
\begin{thebibliography}{#1}}
|
||||||
|
{\end{thebibliography}}
|
||||||
|
\fi
|
||||||
|
|
||||||
|
% disable \@chappos in Appendix in pTeX
|
||||||
|
\ifx\kanjiskip\@undefined\else
|
||||||
|
\let\py@OldAppendix=\appendix
|
||||||
|
\renewcommand{\appendix}{
|
||||||
|
\py@OldAppendix
|
||||||
|
\gdef\@chappos{}
|
||||||
|
}
|
||||||
|
\fi
|
||||||
|
|
||||||
|
% make commands known to non-Sphinx document classes
|
||||||
|
\providecommand*{\sphinxmaketitle}{\maketitle}
|
||||||
|
\providecommand*{\sphinxtableofcontents}{\tableofcontents}
|
||||||
|
\ltx@ifundefined{sphinxthebibliography}
|
||||||
|
{\newenvironment
|
||||||
|
{sphinxthebibliography}{\begin{thebibliography}}{\end{thebibliography}}%
|
||||||
|
}
|
||||||
|
{}% else clause of \ltx@ifundefined
|
||||||
|
\ltx@ifundefined{sphinxtheindex}
|
||||||
|
{\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}}%
|
||||||
|
{}% else clause of \ltx@ifundefined
|
||||||
|
|
||||||
|
% for usage with xindy: this string gets internationalized in preamble
|
||||||
|
\newcommand*{\sphinxnonalphabeticalgroupname}{}
|
||||||
|
% redefined in preamble, headings for makeindex produced index
|
||||||
|
\newcommand*{\sphinxsymbolsname}{}
|
||||||
|
\newcommand*{\sphinxnumbersname}{}
|
||||||
|
|
||||||
|
\protected\def\sphinxcite{\cite}
|
||||||
|
|
||||||
|
|
||||||
|
\endinput
|
||||||
131
build/latex/sphinxlatexlists.sty
Normal file
131
build/latex/sphinxlatexlists.sty
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
%% ALPHANUMERIC LIST ITEMS
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexlists}[2021/12/20 lists]
|
||||||
|
|
||||||
|
% Provides support for this output mark-up from Sphinx latex writer:
|
||||||
|
% - \sphinxsetlistlabels
|
||||||
|
% - \sphinxlineitem
|
||||||
|
% and for the maxlistdepth key of sphinxsetup
|
||||||
|
% Dependencies: the \spx@opt@maxlistdepth from sphinx.sty
|
||||||
|
|
||||||
|
% We need some helpers macros
|
||||||
|
\newtoks\spx@lineitemlabel
|
||||||
|
\long\def\sphinx@gobto@sphinxlineitem#1\sphinxlineitem{}
|
||||||
|
% TeX/LaTeX has no (easy to use) built-in "peek-ahead" mechanism, but
|
||||||
|
% we would like to know if next token is another \sphinxlineitem (this
|
||||||
|
% can happen in glossary entries with multiple terms for same definition)
|
||||||
|
% so we simply grab next token (assuming it is not {tokens} originally)
|
||||||
|
\newcommand\sphinxlineitem[2]{%
|
||||||
|
% safe test of whether #2 is \sphinxlineitem
|
||||||
|
\sphinx@gobto@sphinxlineitem#2\@gobbletwo\sphinxlineitem\unless
|
||||||
|
\iftrue
|
||||||
|
% case with sphinxlineitem immediately followed by another \sphinxlineitem:
|
||||||
|
% accumulate successive terms until actual definition or sub-list is found
|
||||||
|
\spx@lineitemlabel\expandafter{\the\spx@lineitemlabel\strut#1\\}%
|
||||||
|
\else
|
||||||
|
% now issue the \item command with possibly multi-line contents
|
||||||
|
% these weird incantations with \kern are related to how LaTeX
|
||||||
|
% handles \item generally
|
||||||
|
\item[\kern\labelwidth\kern-\itemindent\kern-\leftmargin
|
||||||
|
{\parbox[t]{\dimexpr\linewidth+\leftmargin\relax}{%
|
||||||
|
\raggedright
|
||||||
|
\the\spx@lineitemlabel% accumulated terms before this one, CR separated
|
||||||
|
\strut#1}}% due to LaTeX internals no \par token allowed here,
|
||||||
|
% but the \parbox will insert one tacitly at end
|
||||||
|
\kern-\labelsep]%
|
||||||
|
\spx@lineitemlabel{}%
|
||||||
|
% this causes the label to be typeset (filling up the line), clearing up
|
||||||
|
% things in case a nested list follows.
|
||||||
|
\leavevmode
|
||||||
|
\fi #2%
|
||||||
|
}%
|
||||||
|
|
||||||
|
|
||||||
|
\newcommand\sphinxsetlistlabels[5]
|
||||||
|
{% #1 = style, #2 = enum, #3 = enumnext, #4 = prefix, #5 = suffix
|
||||||
|
% #2 and #3 are counters used by enumerate environment e.g. enumi, enumii.
|
||||||
|
% #1 is a macro such as \arabic or \alph
|
||||||
|
% prefix and suffix are strings (by default empty and a dot).
|
||||||
|
\@namedef{the#2}{#1{#2}}%
|
||||||
|
\@namedef{label#2}{#4\@nameuse{the#2}#5}%
|
||||||
|
\@namedef{p@#3}{\@nameuse{p@#2}#4\@nameuse{the#2}#5}%
|
||||||
|
}%
|
||||||
|
|
||||||
|
|
||||||
|
%% MAXLISTDEPTH
|
||||||
|
%
|
||||||
|
% remove LaTeX's cap on nesting depth if 'maxlistdepth' key used.
|
||||||
|
% This is a hack, which works with the standard classes: it assumes \@toodeep
|
||||||
|
% is always used in "true" branches: "\if ... \@toodeep \else .. \fi."
|
||||||
|
|
||||||
|
% will force use the "false" branch (if there is one)
|
||||||
|
\def\spx@toodeep@hack{\fi\iffalse}
|
||||||
|
|
||||||
|
% do nothing if 'maxlistdepth' key not used or if package enumitem loaded.
|
||||||
|
\ifnum\spx@opt@maxlistdepth=\z@\expandafter\@gobbletwo\fi
|
||||||
|
\AtBeginDocument{%
|
||||||
|
\@ifpackageloaded{enumitem}{\remove@to@nnil}{}%
|
||||||
|
\let\spx@toodeepORI\@toodeep
|
||||||
|
\def\@toodeep{%
|
||||||
|
\ifnum\@listdepth<\spx@opt@maxlistdepth\relax
|
||||||
|
\expandafter\spx@toodeep@hack
|
||||||
|
\else
|
||||||
|
\expandafter\spx@toodeepORI
|
||||||
|
\fi}%
|
||||||
|
% define all missing \@list... macros
|
||||||
|
\count@\@ne
|
||||||
|
\loop
|
||||||
|
\ltx@ifundefined{@list\romannumeral\the\count@}
|
||||||
|
{\iffalse}{\iftrue\advance\count@\@ne}%
|
||||||
|
\repeat
|
||||||
|
\loop
|
||||||
|
\ifnum\count@>\spx@opt@maxlistdepth\relax\else
|
||||||
|
\expandafter\let
|
||||||
|
\csname @list\romannumeral\the\count@\expandafter\endcsname
|
||||||
|
\csname @list\romannumeral\the\numexpr\count@-\@ne\endcsname
|
||||||
|
% workaround 2.6--3.2d babel-french issue (fixed in 3.2e; no change needed)
|
||||||
|
\ltx@ifundefined{leftmargin\romannumeral\the\count@}
|
||||||
|
{\expandafter\let
|
||||||
|
\csname leftmargin\romannumeral\the\count@\expandafter\endcsname
|
||||||
|
\csname leftmargin\romannumeral\the\numexpr\count@-\@ne\endcsname}{}%
|
||||||
|
\advance\count@\@ne
|
||||||
|
\repeat
|
||||||
|
% define all missing enum... counters and \labelenum... macros and \p@enum..
|
||||||
|
\count@\@ne
|
||||||
|
\loop
|
||||||
|
\ltx@ifundefined{c@enum\romannumeral\the\count@}
|
||||||
|
{\iffalse}{\iftrue\advance\count@\@ne}%
|
||||||
|
\repeat
|
||||||
|
\loop
|
||||||
|
\ifnum\count@>\spx@opt@maxlistdepth\relax\else
|
||||||
|
\newcounter{enum\romannumeral\the\count@}%
|
||||||
|
\expandafter\def
|
||||||
|
\csname labelenum\romannumeral\the\count@\expandafter\endcsname
|
||||||
|
\expandafter
|
||||||
|
{\csname theenum\romannumeral\the\numexpr\count@\endcsname.}%
|
||||||
|
\expandafter\def
|
||||||
|
\csname p@enum\romannumeral\the\count@\expandafter\endcsname
|
||||||
|
\expandafter
|
||||||
|
{\csname p@enum\romannumeral\the\numexpr\count@-\@ne\expandafter
|
||||||
|
\endcsname\csname theenum\romannumeral\the\numexpr\count@-\@ne\endcsname.}%
|
||||||
|
\advance\count@\@ne
|
||||||
|
\repeat
|
||||||
|
% define all missing labelitem... macros
|
||||||
|
\count@\@ne
|
||||||
|
\loop
|
||||||
|
\ltx@ifundefined{labelitem\romannumeral\the\count@}
|
||||||
|
{\iffalse}{\iftrue\advance\count@\@ne}%
|
||||||
|
\repeat
|
||||||
|
\loop
|
||||||
|
\ifnum\count@>\spx@opt@maxlistdepth\relax\else
|
||||||
|
\expandafter\let
|
||||||
|
\csname labelitem\romannumeral\the\count@\expandafter\endcsname
|
||||||
|
\csname labelitem\romannumeral\the\numexpr\count@-\@ne\endcsname
|
||||||
|
\advance\count@\@ne
|
||||||
|
\repeat
|
||||||
|
\PackageInfo{sphinx}{maximal list depth extended to \spx@opt@maxlistdepth}%
|
||||||
|
\@gobble\@nnil
|
||||||
|
}
|
||||||
|
|
||||||
|
\endinput
|
||||||
1229
build/latex/sphinxlatexliterals.sty
Normal file
1229
build/latex/sphinxlatexliterals.sty
Normal file
File diff suppressed because it is too large
Load diff
135
build/latex/sphinxlatexnumfig.sty
Normal file
135
build/latex/sphinxlatexnumfig.sty
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
%% NUMBERING OF FIGURES, TABLES, AND LITERAL BLOCKS
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexnumfig}[2024/07/31 v8.1.0 numbering]
|
||||||
|
|
||||||
|
% Requires: remreset (old LaTeX only)
|
||||||
|
% relates to numfig and numfig_secnum_depth configuration variables
|
||||||
|
|
||||||
|
% LaTeX 2018-04-01 and later provides \@removefromreset
|
||||||
|
\ltx@ifundefined{@removefromreset}
|
||||||
|
{\RequirePackage{remreset}}
|
||||||
|
{}% avoid warning
|
||||||
|
% Everything is delayed to \begin{document} to allow hyperref patches into
|
||||||
|
% \newcounter to solve duplicate label problems for internal hyperlinks to
|
||||||
|
% code listings (literalblock counter). User or extension re-definitions of
|
||||||
|
% \theliteralblock, et al., thus have also to be delayed. (changed at 3.5.0)
|
||||||
|
\AtBeginDocument{%
|
||||||
|
\ltx@ifundefined{c@chapter}
|
||||||
|
{\newcounter{literalblock}}%
|
||||||
|
{\newcounter{literalblock}[chapter]%
|
||||||
|
\def\theliteralblock{\ifnum\c@chapter>\z@\arabic{chapter}.\fi
|
||||||
|
\arabic{literalblock}}%
|
||||||
|
}%
|
||||||
|
\ifspx@opt@nonumfigreset
|
||||||
|
\ltx@ifundefined{c@chapter}{}{%
|
||||||
|
\@removefromreset{figure}{chapter}%
|
||||||
|
\@removefromreset{table}{chapter}%
|
||||||
|
\@removefromreset{literalblock}{chapter}%
|
||||||
|
\ifspx@opt@mathnumfig
|
||||||
|
\@removefromreset{equation}{chapter}%
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\def\thefigure{\arabic{figure}}%
|
||||||
|
\def\thetable {\arabic{table}}%
|
||||||
|
\def\theliteralblock{\arabic{literalblock}}%
|
||||||
|
\ifspx@opt@mathnumfig
|
||||||
|
\def\theequation{\arabic{equation}}%
|
||||||
|
\fi
|
||||||
|
\else
|
||||||
|
% See apologetic comments on TeX wizardry at bottom of file.
|
||||||
|
% The reason for this one is to catch case where there will be only
|
||||||
|
% the number with no prefix from enclosing sectioning (can happen
|
||||||
|
% with latex_toplevel_sectioning='part').
|
||||||
|
\def\spx@preAthefigure{\expandafter\spx@magicsep@s\romannumeral-`0}
|
||||||
|
\let\spx@preBthefigure\@empty
|
||||||
|
% \ifspx@opt@usespart % <-- LaTeX writer could pass such a 'usespart' boolean
|
||||||
|
% % as sphinx.sty package option
|
||||||
|
% If document uses \part, (triggered in Sphinx by latex_toplevel_sectioning)
|
||||||
|
% LaTeX core per default does not reset chapter or section
|
||||||
|
% counters at each part.
|
||||||
|
% But if we modify this, we need to redefine \thechapter, \thesection to
|
||||||
|
% include the part number and this will cause problems in table of contents
|
||||||
|
% because of too wide numbering. Simplest is to do nothing.
|
||||||
|
% \fi
|
||||||
|
\ifnum\spx@opt@numfigreset>0
|
||||||
|
\ltx@ifundefined{c@chapter}
|
||||||
|
{}
|
||||||
|
{\g@addto@macro\spx@preAthefigure{\ifnum\c@chapter>\z@\arabic{chapter}\spx@magicsep}%
|
||||||
|
\g@addto@macro\spx@preBthefigure{\fi}}%
|
||||||
|
\fi
|
||||||
|
\ifnum\spx@opt@numfigreset>1
|
||||||
|
\@addtoreset{figure}{section}%
|
||||||
|
\@addtoreset{table}{section}%
|
||||||
|
\@addtoreset{literalblock}{section}%
|
||||||
|
\ifspx@opt@mathnumfig
|
||||||
|
\@addtoreset{equation}{section}%
|
||||||
|
\fi%
|
||||||
|
\g@addto@macro\spx@preAthefigure{\ifnum\c@section>\z@\arabic{section}\spx@magicsep}%
|
||||||
|
\g@addto@macro\spx@preBthefigure{\fi}%
|
||||||
|
\fi
|
||||||
|
\ifnum\spx@opt@numfigreset>2
|
||||||
|
\@addtoreset{figure}{subsection}%
|
||||||
|
\@addtoreset{table}{subsection}%
|
||||||
|
\@addtoreset{literalblock}{subsection}%
|
||||||
|
\ifspx@opt@mathnumfig
|
||||||
|
\@addtoreset{equation}{subsection}%
|
||||||
|
\fi%
|
||||||
|
\g@addto@macro\spx@preAthefigure{\ifnum\c@subsection>\z@\arabic{subsection}\spx@magicsep}%
|
||||||
|
\g@addto@macro\spx@preBthefigure{\fi}%
|
||||||
|
\fi
|
||||||
|
\ifnum\spx@opt@numfigreset>3
|
||||||
|
\@addtoreset{figure}{subsubsection}%
|
||||||
|
\@addtoreset{table}{subsubsection}%
|
||||||
|
\@addtoreset{literalblock}{subsubsection}%
|
||||||
|
\ifspx@opt@mathnumfig
|
||||||
|
\@addtoreset{equation}{subsubsection}%
|
||||||
|
\fi%
|
||||||
|
\g@addto@macro\spx@preAthefigure{\ifnum\c@subsubsection>\z@\arabic{subsubsection}\spx@magicsep}%
|
||||||
|
\g@addto@macro\spx@preBthefigure{\fi}%
|
||||||
|
\fi
|
||||||
|
\ifnum\spx@opt@numfigreset>4
|
||||||
|
\@addtoreset{figure}{paragraph}%
|
||||||
|
\@addtoreset{table}{paragraph}%
|
||||||
|
\@addtoreset{literalblock}{paragraph}%
|
||||||
|
\ifspx@opt@mathnumfig
|
||||||
|
\@addtoreset{equation}{paragraph}%
|
||||||
|
\fi%
|
||||||
|
\g@addto@macro\spx@preAthefigure{\ifnum\c@subparagraph>\z@\arabic{subparagraph}\spx@magicsep}%
|
||||||
|
\g@addto@macro\spx@preBthefigure{\fi}%
|
||||||
|
\fi
|
||||||
|
\ifnum\spx@opt@numfigreset>5
|
||||||
|
\@addtoreset{figure}{subparagraph}%
|
||||||
|
\@addtoreset{table}{subparagraph}%
|
||||||
|
\@addtoreset{literalblock}{subparagraph}%
|
||||||
|
\ifspx@opt@mathnumfig
|
||||||
|
\@addtoreset{equation}{subparagraph}%
|
||||||
|
\fi%
|
||||||
|
\g@addto@macro\spx@preAthefigure{\ifnum\c@subsubparagraph>\z@\arabic{subsubparagraph}\spx@magicsep}%
|
||||||
|
\g@addto@macro\spx@preBthefigure{\fi}%
|
||||||
|
\fi
|
||||||
|
\expandafter\g@addto@macro
|
||||||
|
\expandafter\spx@preAthefigure\expandafter{\spx@preBthefigure}%
|
||||||
|
\let\thefigure\spx@preAthefigure
|
||||||
|
\let\thetable\spx@preAthefigure
|
||||||
|
\let\theliteralblock\spx@preAthefigure
|
||||||
|
\g@addto@macro\thefigure{\arabic{figure}}%
|
||||||
|
\g@addto@macro\thetable{\arabic{table}}%
|
||||||
|
\g@addto@macro\theliteralblock{\arabic{literalblock}}%
|
||||||
|
\ifspx@opt@mathnumfig
|
||||||
|
\let\theequation\spx@preAthefigure
|
||||||
|
\g@addto@macro\theequation{E}%
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
}% end of big \AtBeginDocument
|
||||||
|
|
||||||
|
% Sorry for TeX wizardry here. We need to keep expandability. Explaining
|
||||||
|
% the mechanism is not really feasible to non TeX-experts, but the idea
|
||||||
|
% is to force next `\ifnum` conditional so we can check what comes next.
|
||||||
|
% All cases are accounted for (i.e. not an equation, or an equation at top
|
||||||
|
% level, or an equation in some section at some depth).
|
||||||
|
\def\spx@magicsep{\expandafter\spx@magicsep@i\romannumeral-`0}
|
||||||
|
\def\spx@magicsep@i#1{\if#1E\spx@opt@mathnumsep\arabic{equation}\else.#1\fi}
|
||||||
|
%
|
||||||
|
\def\spx@magicsep@s#1{\if#1E\arabic{equation}\else#1\fi}
|
||||||
|
\endinput
|
||||||
386
build/latex/sphinxlatexobjects.sty
Normal file
386
build/latex/sphinxlatexobjects.sty
Normal file
|
|
@ -0,0 +1,386 @@
|
||||||
|
%% MODULE RELEASE DATA AND OBJECT DESCRIPTIONS
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexobjects}[2025/06/06 documentation environments]
|
||||||
|
|
||||||
|
% Provides support for this output mark-up from Sphinx latex writer:
|
||||||
|
%
|
||||||
|
% - environments
|
||||||
|
%
|
||||||
|
% - fulllineitems
|
||||||
|
% - productionlist
|
||||||
|
% - optionlist
|
||||||
|
% - DUlineblock (also "lineblock")
|
||||||
|
%
|
||||||
|
% - macros
|
||||||
|
%
|
||||||
|
% - \DUrole
|
||||||
|
% - various legacy support macros related to author and release
|
||||||
|
% data of documented objects and modules.
|
||||||
|
|
||||||
|
% \moduleauthor{name}{email}
|
||||||
|
\newcommand{\moduleauthor}[2]{}
|
||||||
|
|
||||||
|
% \sectionauthor{name}{email}
|
||||||
|
\newcommand{\sectionauthor}[2]{}
|
||||||
|
|
||||||
|
% Allow the release number to be specified independently of the
|
||||||
|
% \date{}. This allows the date to reflect the document's date and
|
||||||
|
% release to specify the release that is documented.
|
||||||
|
%
|
||||||
|
\newcommand{\py@release}{\releasename\space\version}
|
||||||
|
\newcommand{\version}{}% part of \py@release, used by title page and headers
|
||||||
|
% \releaseinfo is used on titlepage (sphinxmanual.cls, sphinxhowto.cls)
|
||||||
|
\newcommand{\releaseinfo}{}
|
||||||
|
\newcommand{\setreleaseinfo}[1]{\renewcommand{\releaseinfo}{#1}}
|
||||||
|
% this is inserted via template and #1=release config variable
|
||||||
|
\newcommand{\release}[1]{\renewcommand{\version}{#1}}
|
||||||
|
% this is defined by template to 'releasename' latex_elements key
|
||||||
|
\newcommand{\releasename}{}
|
||||||
|
% Fix issue in case release and releasename deliberately left blank
|
||||||
|
\newcommand{\sphinxheadercomma}{, }% used in fancyhdr header definition
|
||||||
|
\newcommand{\sphinxifemptyorblank}[1]{%
|
||||||
|
% test after one expansion of macro #1 if contents is empty or spaces
|
||||||
|
\if&\expandafter\@firstofone\detokenize\expandafter{#1}&%
|
||||||
|
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}%
|
||||||
|
\AtBeginDocument {%
|
||||||
|
\sphinxifemptyorblank{\releasename}
|
||||||
|
{\sphinxifemptyorblank{\version}{\let\sphinxheadercomma\empty}{}}
|
||||||
|
{}%
|
||||||
|
}%
|
||||||
|
|
||||||
|
% Allow specification of the author's address separately from the
|
||||||
|
% author's name. This can be used to format them differently, which
|
||||||
|
% is a good thing.
|
||||||
|
%
|
||||||
|
\newcommand{\py@authoraddress}{}
|
||||||
|
\newcommand{\authoraddress}[1]{\renewcommand{\py@authoraddress}{#1}}
|
||||||
|
|
||||||
|
% {fulllineitems} is the main environment for object descriptions.
|
||||||
|
%
|
||||||
|
% With 4.0.0 \pysigline (and \pysiglinewithargsret), used in a fulllineitems
|
||||||
|
% environment the #1 will already be of the width which is computed here, i.e.
|
||||||
|
% the available width on line, so the \makebox becomes a bit superfluous
|
||||||
|
\newcommand{\py@itemnewline}[1]{% macro used as \makelabel in fulllineitems
|
||||||
|
% Memo: this presupposes \itemindent is 0pt
|
||||||
|
\kern\labelsep % because \@labels core latex box does \hskip-\labelsep
|
||||||
|
\makebox[\dimexpr\linewidth+\labelwidth\relax][l]{#1}%
|
||||||
|
\kern-\labelsep % because at end of \@labels box there is \hskip\labelsep
|
||||||
|
}
|
||||||
|
|
||||||
|
\newenvironment{fulllineitems}{%
|
||||||
|
\begin{list}{}{\labelwidth \leftmargin
|
||||||
|
\rightmargin \z@ \topsep -\parskip \partopsep \parskip
|
||||||
|
\itemsep -\parsep
|
||||||
|
\let\makelabel=\py@itemnewline}%
|
||||||
|
}{\end{list}}
|
||||||
|
|
||||||
|
% Signatures, possibly multi-line
|
||||||
|
%
|
||||||
|
% For legacy reasons Sphinx uses LaTeX \list and \item's for signatures
|
||||||
|
% This is delicate:
|
||||||
|
% - the actual item label is not typeset immediately by \item but later as part
|
||||||
|
% of the \everypar which will be triggered by either next paragraph or a manual
|
||||||
|
% \leavevmode, or if nothing in-between by the next \item,
|
||||||
|
% - \begingroup <set-up>\item[foo] <setup>\endgroup leads to errors,
|
||||||
|
% - vertical space depends on \parskip and \itemsep values in somewhat
|
||||||
|
% subtle manners.
|
||||||
|
%
|
||||||
|
% Since the 2022/01/13 version things are simpler as \parskip is simply set
|
||||||
|
% to zero during execution of \pysigline/\pysiglinewithargsret
|
||||||
|
%
|
||||||
|
% Parameter for separation via \itemsep of multiple signatures with common desc
|
||||||
|
\newlength\sphinxsignaturesep
|
||||||
|
\setlength\sphinxsignaturesep{\smallskipamount}
|
||||||
|
% latex.py outputs mark-up like this:
|
||||||
|
% \pysigstartsignatures <signatures> \pysigstopsignatures <actual desc>
|
||||||
|
\newcommand{\pysigstartsignatures}{%
|
||||||
|
% store current \parskip and \itemsep
|
||||||
|
\edef\pysig@restore@itemsep@and@parskip{%
|
||||||
|
\itemsep\the\itemsep\relax
|
||||||
|
\parskip\the\parskip\relax
|
||||||
|
}%
|
||||||
|
% set them to control the spacing between signatures sharing common desc
|
||||||
|
\parskip\z@skip
|
||||||
|
\itemsep\sphinxsignaturesep
|
||||||
|
}
|
||||||
|
\newcommand{\pysigstopsignatures}{%
|
||||||
|
% 1) encourage a pagebreak in an attempt to try to avoid last
|
||||||
|
% signature ending up separated from description (due to voodoo next)
|
||||||
|
\penalty-100
|
||||||
|
% 2) some voodoo to separate last signature from description in a manner
|
||||||
|
% robust with respect to the latter being itself a LaTeX list object
|
||||||
|
\leavevmode\par\kern-\baselineskip\item[\strut]
|
||||||
|
%
|
||||||
|
\leavevmode
|
||||||
|
% it is important \leavevmode was issued before the \parskip reset, and
|
||||||
|
% it is also needed for the case of an object desc itself a LaTeX \list
|
||||||
|
% now restore \itemsep and \parskip
|
||||||
|
\pysig@restore@itemsep@and@parskip
|
||||||
|
}
|
||||||
|
% Each signature is rendered as NAME<SPACE>[TPLIST]<SPACE>(ARGLIST) where the
|
||||||
|
% size of <SPACE> is parametrized by \sphinxsignaturelistskip (0pt by default).
|
||||||
|
\newlength\sphinxsignaturelistskip
|
||||||
|
\setlength\sphinxsignaturelistskip{0pt}
|
||||||
|
\newcommand{\pysigtypelistopen}{\hskip\sphinxsignaturelistskip\sphinxcode{[}}
|
||||||
|
\newcommand{\pysigtypelistclose}{\sphinxcode{]}}
|
||||||
|
\newcommand{\pysigarglistopen}{\hskip\sphinxsignaturelistskip\sphinxcode{(}}
|
||||||
|
\newcommand{\pysigarglistclose}{\sphinxcode{)}}
|
||||||
|
%
|
||||||
|
% Use a \parbox to accommodate long argument list in signatures
|
||||||
|
% LaTeX did not imagine that an \item label could need multi-line rendering
|
||||||
|
\newlength{\py@argswidth}
|
||||||
|
\newcommand{\py@sigparams}[2]{%
|
||||||
|
% The \py@argswidth has been computed in \pysiglinewithargsret to make the
|
||||||
|
% argument list use full available width
|
||||||
|
\parbox[t]{\py@argswidth}{\raggedright #1\pysigarglistclose#2\strut}%
|
||||||
|
% final strut is to help get correct vertical separation
|
||||||
|
}
|
||||||
|
\newcommand{\py@sigparamswithtypelist}[3]{%
|
||||||
|
% similar to \py@sigparams but with different delimiters and an additional
|
||||||
|
% type parameters list given as #1, the argument list as #2 and the return
|
||||||
|
% annotation as #3
|
||||||
|
\parbox[t]{\py@argswidth}{%
|
||||||
|
\raggedright #1\pysigtypelistclose%
|
||||||
|
\pysigarglistopen#2\pysigarglistclose%
|
||||||
|
#3\strut}%
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand{\pysigline}[1]{%
|
||||||
|
% as \py@argswidth is available, we use it but no "args" here
|
||||||
|
% the \relax\relax is because \py@argswidth is a "skip" variable
|
||||||
|
% this will make the label occupy the full available linewidth
|
||||||
|
\py@argswidth=\dimexpr\linewidth+\labelwidth\relax\relax
|
||||||
|
\item[{\parbox[t]{\py@argswidth}{\raggedright #1\strut}}]
|
||||||
|
\pysigadjustitemsep
|
||||||
|
}
|
||||||
|
\newcommand{\pysiglinewithargsret}[3]{%
|
||||||
|
% #1 may contain a footnote (especially with latex_show_urls='footnote'
|
||||||
|
% and some intersphinx added hyperlinking). Here we want to measure
|
||||||
|
% a width but not typeset such a footnote (else #13619).
|
||||||
|
% Miraculously a sphinxpackagefootnote.sty tabulary compatibility
|
||||||
|
% layer employing the amsmath \ifmeasuring@ can be used here to let
|
||||||
|
% a footnote influence the actual width up to opening brace but not
|
||||||
|
% actually get typeset at this stage...
|
||||||
|
% MEMO: "argswidth" is misleading here, this code measures the name
|
||||||
|
% not the arguments.
|
||||||
|
\settowidth{\py@argswidth}{\measuring@true#1\pysigarglistopen}%
|
||||||
|
\py@argswidth=\dimexpr\linewidth+\labelwidth-\py@argswidth\relax\relax
|
||||||
|
\item[{#1\pysigarglistopen\py@sigparams{#2}{#3}\strut}]
|
||||||
|
\pysigadjustitemsep
|
||||||
|
}
|
||||||
|
\newcommand{\pysiglinewithargsretwithtypelist}[4]{%
|
||||||
|
% same comment as in \pysiglinewithargsret
|
||||||
|
\settowidth{\py@argswidth}{\measuring@true#1\pysigtypelistopen}%
|
||||||
|
\py@argswidth=\dimexpr\linewidth+\labelwidth-\py@argswidth\relax\relax
|
||||||
|
\item[{#1\pysigtypelistopen\py@sigparamswithtypelist{#2}{#3}{#4}\strut}]
|
||||||
|
\pysigadjustitemsep
|
||||||
|
}
|
||||||
|
|
||||||
|
\def\sphinxoptionalextraspace{0.5mm}
|
||||||
|
\newcommand{\pysigwithonelineperarg}[3]{%
|
||||||
|
% render each argument on its own line
|
||||||
|
\item[#1\pysigarglistopen\strut]
|
||||||
|
\leavevmode\par\nopagebreak
|
||||||
|
% this relies on \pysigstartsignatures having set \parskip to zero
|
||||||
|
\begingroup
|
||||||
|
\let\sphinxparamcomma\sphinxparamcommaoneperline
|
||||||
|
\def\sphinxoptionalhook{\ifvmode\else\kern\sphinxoptionalextraspace\relax\fi}%
|
||||||
|
% The very first \sphinxparam should not emit a \par hence a complication
|
||||||
|
% with a group and global definition here as it may occur in a \sphinxoptional
|
||||||
|
\global\let\spx@sphinxparam\sphinxparam
|
||||||
|
\gdef\sphinxparam{\gdef\sphinxparam{\par\spx@sphinxparam}\spx@sphinxparam}%
|
||||||
|
#2\par
|
||||||
|
\endgroup
|
||||||
|
\global\let\sphinxparam\spx@sphinxparam
|
||||||
|
% fulllineitems sets \labelwidth to be like \leftmargin
|
||||||
|
\nopagebreak\noindent\kern-\labelwidth\pysigarglistclose{#3}
|
||||||
|
\pysigadjustitemsep
|
||||||
|
}
|
||||||
|
\newcommand{\pysigwithonelineperargwithonelinepertparg}[4]{
|
||||||
|
% #1 = name, #2 = typelist, #3 = arglist, #4 = retann
|
||||||
|
% render each type parameter and argument on its own line
|
||||||
|
\item[#1\pysigtypelistopen\strut]
|
||||||
|
\leavevmode\par\nopagebreak
|
||||||
|
\begingroup
|
||||||
|
\let\sphinxparamcomma\sphinxparamcommaoneperline
|
||||||
|
% \sphinxtypeparam is treated similarly to \sphinxparam but since
|
||||||
|
% \sphinxoptional is not accepted in a type parameters list, we do
|
||||||
|
% not need the hook or the global definition
|
||||||
|
\let\spx@sphinxtypeparam\sphinxtypeparam
|
||||||
|
\def\sphinxtypeparam{\def\sphinxtypeparam{\par\spx@sphinxtypeparam}\spx@sphinxtypeparam}%
|
||||||
|
#2\par
|
||||||
|
\endgroup
|
||||||
|
\nopagebreak\noindent\kern-\labelwidth\pysigtypelistclose%
|
||||||
|
% render the rest of the signature like in \pysigwithonelineperarg
|
||||||
|
\pysigarglistopen\strut\par\nopagebreak
|
||||||
|
\begingroup
|
||||||
|
\let\sphinxparamcomma\sphinxparamcommaoneperline
|
||||||
|
\def\sphinxoptionalhook{\ifvmode\else\kern\sphinxoptionalextraspace\relax\fi}%
|
||||||
|
\global\let\spx@sphinxparam\sphinxparam
|
||||||
|
\gdef\sphinxparam{\gdef\sphinxparam{\par\spx@sphinxparam}\spx@sphinxparam}%
|
||||||
|
#3\par
|
||||||
|
\endgroup
|
||||||
|
\global\let\sphinxparam\spx@sphinxparam
|
||||||
|
\nopagebreak\noindent\kern-\labelwidth\pysigarglistclose{#4}
|
||||||
|
\pysigadjustitemsep
|
||||||
|
}
|
||||||
|
\newcommand{\pysiglinewithargsretwithonelinepertparg}[4]{
|
||||||
|
% #1 = name, #2 = typelist, #3 = arglist, #4 = retann
|
||||||
|
% render each type parameter on its own line but the arguments list inline
|
||||||
|
\item[#1\pysigtypelistopen\strut]
|
||||||
|
\leavevmode\par\nopagebreak
|
||||||
|
\begingroup
|
||||||
|
\let\sphinxparamcomma\sphinxparamcommaoneperline
|
||||||
|
% \sphinxtypeparam is treated similarly to \sphinxparam but since
|
||||||
|
% \sphinxoptional is not accepted in a type parameters list, we do
|
||||||
|
% not need the hook or the global definition
|
||||||
|
\let\spx@sphinxtypeparam\sphinxtypeparam
|
||||||
|
\def\sphinxtypeparam{\def\sphinxtypeparam{\par\spx@sphinxtypeparam}\spx@sphinxtypeparam}%
|
||||||
|
#2\par
|
||||||
|
\endgroup
|
||||||
|
\nopagebreak\noindent\kern-\labelwidth\pysigtypelistclose%
|
||||||
|
% render the arguments list on one line
|
||||||
|
\pysigarglistopen#3\pysigarglistclose#4\strut
|
||||||
|
\pysigadjustitemsep
|
||||||
|
}
|
||||||
|
\newcommand{\pysigwithonelineperargwithtypelist}[4]{
|
||||||
|
% #1 = name, #2 = typelist, #3 = arglist, #4 = retann
|
||||||
|
% render the type parameters list on one line, but each argument is rendered on its own line
|
||||||
|
% for \measuring@true see comment in \pysiglinewithargsret
|
||||||
|
\settowidth{\py@argswidth}{\measuring@true#1\pysigtypelistopen}%
|
||||||
|
\py@argswidth=\dimexpr\linewidth+\labelwidth-\py@argswidth\relax\relax
|
||||||
|
\item[{#1\pysigtypelistopen\parbox[t]{\py@argswidth}{%
|
||||||
|
\raggedright #2\pysigtypelistclose\pysigarglistopen\strut}\strut}]
|
||||||
|
% render the rest of the signature like in \pysigwithonelineperarg
|
||||||
|
\begingroup
|
||||||
|
\let\sphinxparamcomma\sphinxparamcommaoneperline
|
||||||
|
\def\sphinxoptionalhook{\ifvmode\else\kern\sphinxoptionalextraspace\relax\fi}%
|
||||||
|
\global\let\spx@sphinxparam\sphinxparam
|
||||||
|
\gdef\sphinxparam{\gdef\sphinxparam{\par\spx@sphinxparam}\spx@sphinxparam}%
|
||||||
|
#3\par
|
||||||
|
\endgroup
|
||||||
|
\global\let\sphinxparam\spx@sphinxparam
|
||||||
|
\nopagebreak\noindent\kern-\labelwidth\pysigarglistclose{#4}
|
||||||
|
\pysigadjustitemsep
|
||||||
|
}
|
||||||
|
\newcommand{\pysigadjustitemsep}{%
|
||||||
|
% adjust \itemsep to control the separation with the next signature
|
||||||
|
% sharing common description
|
||||||
|
\ifsphinxsigismultiline
|
||||||
|
% inside a multiline signature, no extra vertical spacing
|
||||||
|
% ("multiline" here does not refer to possibly long
|
||||||
|
% list of arguments, but to a cpp domain feature)
|
||||||
|
\itemsep\z@skip
|
||||||
|
\else
|
||||||
|
\itemsep\sphinxsignaturesep
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
\newif\ifsphinxsigismultiline
|
||||||
|
\newcommand{\pysigstartmultiline}{\sphinxsigismultilinetrue}%
|
||||||
|
\newcommand{\pysigstopmultiline}{\sphinxsigismultilinefalse\itemsep\sphinxsignaturesep}%
|
||||||
|
|
||||||
|
% Production lists
|
||||||
|
% This simply outputs the lines as is, in monospace font. Refers #13326.
|
||||||
|
% (the left padding for multi-line alignment is from the nodes themselves,
|
||||||
|
% and latex is configured below to obey such horizontal whitespace).
|
||||||
|
%
|
||||||
|
% - The legacy code used longtable and hardcoded the separator as ::=
|
||||||
|
% via dedicated macros defined by the environment itself.
|
||||||
|
% - Here the separator is part of the node. Any extra LaTeX mark-up would
|
||||||
|
% have to originate from the writer itself to decorate it.
|
||||||
|
% - The legacy code used strangely \parindent and \indent. Possibly
|
||||||
|
% (unchecked) due to an earlier tabular usage, but a longtable does not
|
||||||
|
% work in paragraph mode, so \parindent was without effect and
|
||||||
|
% \indent only caused some extra blank line above display.
|
||||||
|
% - The table had some whitespace on its left, which we imitate here via
|
||||||
|
% \parindent usage (which works in our context...).
|
||||||
|
%
|
||||||
|
\newenvironment{productionlist}{%
|
||||||
|
\bigskip % imitate close enough legacy vertical whitespace, which was
|
||||||
|
% visibly excessive
|
||||||
|
\ttfamily % needed for space tokens to have same width as letters
|
||||||
|
\parindent1em % width of a "quad", font-dependent, usually circa width of 2
|
||||||
|
% letters
|
||||||
|
\obeylines % line in = line out
|
||||||
|
\parskip\z@skip % prevent the parskip vertical whitespace between lines,
|
||||||
|
% which are technically to LaTeX now each its own paragraph
|
||||||
|
\@vobeyspaces % obey whitespace
|
||||||
|
% now a technicality to, only locally to this environment, prevent the
|
||||||
|
% suppression of indentation of first line, if it comes right after
|
||||||
|
% \section. Cf package indentfirst from which the code is borrowed.
|
||||||
|
\let\@afterindentfalse\@afterindenttrue\@afterindenttrue
|
||||||
|
}{%
|
||||||
|
\par % does not hurt...
|
||||||
|
}
|
||||||
|
|
||||||
|
% Definition lists; requested by AMK for HOWTO documents. Probably useful
|
||||||
|
% elsewhere as well, so keep in in the general style support.
|
||||||
|
%
|
||||||
|
\newenvironment{definitions}{%
|
||||||
|
\begin{description}%
|
||||||
|
\def\term##1{\item[{##1}]\mbox{}\\*[0mm]}%
|
||||||
|
}{%
|
||||||
|
\end{description}%
|
||||||
|
}
|
||||||
|
|
||||||
|
%% FROM DOCTUTILS LATEX WRITER
|
||||||
|
%
|
||||||
|
% The following is stuff copied from docutils' latex writer.
|
||||||
|
%
|
||||||
|
\newcommand{\optionlistlabel}[1]{\normalfont\bfseries #1 \hfill}% \bf deprecated
|
||||||
|
\newenvironment{optionlist}[1]
|
||||||
|
{\begin{list}{}
|
||||||
|
{\setlength{\labelwidth}{#1}%
|
||||||
|
\setlength{\rightmargin}{1cm}%
|
||||||
|
\setlength{\leftmargin}{\rightmargin}%
|
||||||
|
\addtolength{\leftmargin}{\labelwidth}%
|
||||||
|
\addtolength{\leftmargin}{\labelsep}%
|
||||||
|
\renewcommand{\makelabel}{\optionlistlabel}}%
|
||||||
|
}{\end{list}}
|
||||||
|
|
||||||
|
\newlength{\lineblockindentation}
|
||||||
|
\setlength{\lineblockindentation}{2.5em}
|
||||||
|
\newenvironment{lineblock}[1]
|
||||||
|
{\begin{list}{}
|
||||||
|
{\setlength{\partopsep}{\parskip}%
|
||||||
|
\addtolength{\partopsep}{\baselineskip}%
|
||||||
|
\topsep0pt\itemsep0.15\baselineskip\parsep0pt
|
||||||
|
\leftmargin#1\relax}%
|
||||||
|
\raggedright}
|
||||||
|
{\end{list}}
|
||||||
|
|
||||||
|
% From docutils.writers.latex2e
|
||||||
|
% inline markup (custom roles)
|
||||||
|
% \DUrole{#1}{#2} tries \DUrole#1{#2}
|
||||||
|
\providecommand*{\DUrole}[2]{%
|
||||||
|
\ifcsname DUrole\detokenize{#1}\endcsname
|
||||||
|
\csname DUrole\detokenize{#1}\endcsname{#2}%
|
||||||
|
\else% backwards compatibility: try \docutilsrole#1{#2}
|
||||||
|
\ifcsname docutilsrole\detokenize{#1}\endcsname
|
||||||
|
\csname docutilsrole\detokenize{#1}\endcsname{#2}%
|
||||||
|
\else
|
||||||
|
#2%
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
|
||||||
|
\providecommand*{\DUprovidelength}[2]{%
|
||||||
|
\ifdefined#1\else\newlength{#1}\setlength{#1}{#2}\fi
|
||||||
|
}
|
||||||
|
|
||||||
|
\DUprovidelength{\DUlineblockindent}{2.5em}
|
||||||
|
\ifdefined\DUlineblock\else
|
||||||
|
\newenvironment{DUlineblock}[1]{%
|
||||||
|
\list{}{\setlength{\partopsep}{\parskip}%
|
||||||
|
\addtolength{\partopsep}{\baselineskip}%
|
||||||
|
\setlength{\topsep}{0pt}%
|
||||||
|
\setlength{\itemsep}{0.15\baselineskip}%
|
||||||
|
\setlength{\parsep}{0pt}%
|
||||||
|
\setlength{\leftmargin}{#1}}%
|
||||||
|
\raggedright
|
||||||
|
}
|
||||||
|
{\endlist}
|
||||||
|
\fi
|
||||||
|
|
||||||
|
\endinput
|
||||||
178
build/latex/sphinxlatexshadowbox.sty
Normal file
178
build/latex/sphinxlatexshadowbox.sty
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
%% TOPIC AND CONTENTS BOXES
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexshadowbox}[2024/07/28 v8.1.0 sphinxShadowBox]
|
||||||
|
|
||||||
|
% Provides support for this output mark-up from Sphinx latex writer:
|
||||||
|
%
|
||||||
|
% - Environments: sphinxtopic, sphinxcontents, and sphinxsidebar.
|
||||||
|
%
|
||||||
|
% These wrappers replace at 8.1.0 former direct use of sphinxShadowBox
|
||||||
|
% environment which did not allow separate styling.
|
||||||
|
%
|
||||||
|
% - Commands: \sphinxstyletopictitle, \sphinxstylecontentstitle, and
|
||||||
|
% \sphinxstylesidebartitle.
|
||||||
|
%
|
||||||
|
% At 8.1.0 they default to use \sphinxdotitlerow whose definiion is done in
|
||||||
|
% sphinxlatexadmonitions.sty. There is also \sphinxstylesidebarsubtitle
|
||||||
|
% which does not use \sphinxdotitlerow.
|
||||||
|
%
|
||||||
|
% Dependencies (they do not need to be defined at time of loading):
|
||||||
|
%
|
||||||
|
% - of course the various colour and dimension options handled via sphinx.sty
|
||||||
|
% - dimension register \spx@image@maxheight from sphinxlatexgraphics.sty
|
||||||
|
% - \savenotes/\spewnotes from sphinxpackagefootnote.sty
|
||||||
|
% - \ifspx@inframed defined in sphinx.sty
|
||||||
|
% - \sphinxdotitlerow from sphinxlatexadmonitions.sty
|
||||||
|
% - \spx@boxes@fcolorbox@setup from sphinxpackageboxes.sty
|
||||||
|
%
|
||||||
|
\RequirePackage{framed}
|
||||||
|
% Those are required either before or after by sphinx.sty anyhow, but for
|
||||||
|
% clarity we list them here:
|
||||||
|
\RequirePackage{sphinxlatexgraphics}
|
||||||
|
\RequirePackage{sphinxpackagefootnote}
|
||||||
|
\RequirePackage{sphinxlatexadmonitions}
|
||||||
|
\RequirePackage{sphinxpackageboxes}
|
||||||
|
|
||||||
|
% At 5.1.0 the code formerly here in a definition of \spx@ShadowFBox has been
|
||||||
|
% refactored to hand over to a more powerful \spx@boxes@fcolorbox provided by
|
||||||
|
% file sphinxpackageboxes.sty, it can draw rounded corners and add a background
|
||||||
|
% color.
|
||||||
|
|
||||||
|
% At 6.2.0, \spx@ShadowFBox is so much simplified that it is now not
|
||||||
|
% separately defined but directly incorporated into the \FrameCommand
|
||||||
|
% definition done by sphinxShadowBox environment below.
|
||||||
|
|
||||||
|
% Use framed.sty \MakeFramed/\endMakeFramed to allow page breaks for topic
|
||||||
|
% boxes. Originally Sphinx used \shadowbox from fancybox.sty but it did not
|
||||||
|
% allow pagebreaks (which was problematic for "contents" directive if there
|
||||||
|
% are many subsections).
|
||||||
|
%
|
||||||
|
% Docutils does not allow topic to be nested within topics or other body
|
||||||
|
% elements. But the LaTeX code here does allow it:
|
||||||
|
%
|
||||||
|
% - a topic inside another topic would be rendered in a minipage (thus not
|
||||||
|
% allowing pagebreaks). Its external frame would adapt perfectly to
|
||||||
|
% the *current (smaller) width for text*.
|
||||||
|
%
|
||||||
|
% - a topic inside (nested) lists or quote environments would have its frame
|
||||||
|
% take the *full width* of the page, but its text contents on the other hand
|
||||||
|
% would obey exactly the current indentation plus inner separation. This is
|
||||||
|
% in contrast with the framing used for literal blocks, also based, but in a
|
||||||
|
% more sophisticated way on usage of \MakeFramed/\endMakeFramed, and
|
||||||
|
% adjusting to current text indentation.
|
||||||
|
%
|
||||||
|
% At 8.1.0, sphinxShadowBox takes an optional argument #1 and uses it as
|
||||||
|
% \spx@boxes@fcolorbox@setup{#1} rather than \spx@boxes@fcolorbox@setup{topic}.
|
||||||
|
% Some hesitation whether to move this line to newly added sphinxtopic,
|
||||||
|
% sphinxcontents and sphinxsidebar environmments. But anyhow the environment
|
||||||
|
% also requires later knowing a few more things: sphinx<type>TextColor and
|
||||||
|
% spx@<type>@texextras.
|
||||||
|
%
|
||||||
|
% The #1 defaulting to topic must be such that all parameters expected by
|
||||||
|
% \spx@boxes@fcolorbox@setup actually do exist, see CSS options in sphinx.sty
|
||||||
|
% which is what defines them for contents, topic, and sidebar.
|
||||||
|
%
|
||||||
|
% Fortunately the #1 is not needed in \end{sphinxShadowBox} so we don't have
|
||||||
|
% to work around a LaTeX conception bug that such #1 can not be used as is in
|
||||||
|
% the definition of the \end part of an environment.
|
||||||
|
%
|
||||||
|
% MEMO: the "shadow" is not really drawn directly by this environment but
|
||||||
|
% indirectly via the configuration which is passed over to \spx@boxes@fcolorbox,
|
||||||
|
% which is the macro creating frame and (perhaps but not necessarily) a shadow.
|
||||||
|
\newenvironment{sphinxShadowBox}[1][topic]%
|
||||||
|
{%
|
||||||
|
\spx@boxes@fcolorbox@setup{#1}%
|
||||||
|
% we will use the dimen registers from sphinxpackageboxes.sty which now hold
|
||||||
|
% the values from options related to topic/contents
|
||||||
|
% MEMO: \spx@boxes@fcolorbox creates an \hbox but does not quit vertical
|
||||||
|
% mode; but in context of framed.sty's \FrameCommand TeX is already
|
||||||
|
% in restricted horizontal mode, so no need for a \leavevmode here.
|
||||||
|
\def\FrameCommand {\spx@boxes@fcolorbox}%
|
||||||
|
% 6.2.0 adds support for div.topic_box-decoration-break=slice.
|
||||||
|
% (it is yet undecided if slice style should inhibit a bottom shadow)
|
||||||
|
\@nameuse{ifspx@#1@border@open}%
|
||||||
|
\def\FirstFrameCommand
|
||||||
|
{\spx@boxes@fcolorbox@setup@openbottom\FrameCommand}%
|
||||||
|
\def\MidFrameCommand
|
||||||
|
{\spx@boxes@fcolorbox@setup@openboth \FrameCommand}%
|
||||||
|
\def\LastFrameCommand
|
||||||
|
{\spx@boxes@fcolorbox@setup@opentop \FrameCommand}%
|
||||||
|
\fi
|
||||||
|
\advance\spx@image@maxheight
|
||||||
|
-\dimexpr\spx@boxes@border@top+\spx@boxes@border@bottom
|
||||||
|
+\spx@boxes@padding@top+\spx@boxes@padding@bottom
|
||||||
|
+\ifdim\spx@boxes@shadow@yoffset<\z@-\fi\spx@boxes@shadow@yoffset
|
||||||
|
+\baselineskip\relax
|
||||||
|
% configure framed.sty not to add extra vertical spacing
|
||||||
|
\ltx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}%
|
||||||
|
% the \trivlist will add the vertical spacing on top and bottom which is
|
||||||
|
% typical of center environment as used in Sphinx <= 1.4.1
|
||||||
|
% the \noindent has the effet of an extra blank line on top, to
|
||||||
|
% imitate closely the layout from Sphinx <= 1.4.1; the \FrameHeightAdjust
|
||||||
|
% will put top part of frame on this baseline.
|
||||||
|
\def\FrameHeightAdjust {\baselineskip}%
|
||||||
|
% use package footnote to handle footnotes
|
||||||
|
\savenotes
|
||||||
|
\trivlist\item\noindent
|
||||||
|
% use a minipage if we are already inside a framed environment
|
||||||
|
\ifspx@inframed\begin{minipage}{\linewidth}\fi
|
||||||
|
\MakeFramed {\spx@inframedtrue
|
||||||
|
% framed.sty puts into "\width" the added width (padding+border widths)
|
||||||
|
% adjust \hsize to what the contents must use
|
||||||
|
\advance\hsize-\width
|
||||||
|
% adjust LaTeX parameters to behave properly in indented/quoted contexts
|
||||||
|
\FrameRestore
|
||||||
|
% typeset the contents as in a minipage (Sphinx <= 1.4.1 used a minipage and
|
||||||
|
% itemize/enumerate are therein typeset more tightly, we want to keep
|
||||||
|
% that). We copy-paste from LaTeX source code but don't do a real minipage.
|
||||||
|
\@pboxswfalse
|
||||||
|
\let\@listdepth\@mplistdepth \@mplistdepth\z@
|
||||||
|
\@minipagerestore
|
||||||
|
\@setminipage
|
||||||
|
}%
|
||||||
|
\color@begingroup % workaround upstream framed.sty bug
|
||||||
|
\@nameuse{ifspx@#1@withtextcolor}%
|
||||||
|
\color{sphinx#1TextColor}%
|
||||||
|
\fi
|
||||||
|
\@nameuse{spx@#1@TeXextras}%
|
||||||
|
}%
|
||||||
|
{% insert the "endminipage" code
|
||||||
|
\par\unskip
|
||||||
|
\color@endgroup % matches the \color@begingroup
|
||||||
|
\@minipagefalse
|
||||||
|
\endMakeFramed
|
||||||
|
\ifspx@inframed\end{minipage}\fi
|
||||||
|
\endtrivlist
|
||||||
|
% output the stored footnotes
|
||||||
|
\spewnotes
|
||||||
|
}
|
||||||
|
|
||||||
|
% 8.1.0
|
||||||
|
\newenvironment{sphinxtopic}
|
||||||
|
{\begin{sphinxShadowBox}[topic]}{\end{sphinxShadowBox}}
|
||||||
|
\newenvironment{sphinxcontents}
|
||||||
|
{\begin{sphinxShadowBox}[contents]}{\end{sphinxShadowBox}}
|
||||||
|
% Arguably sphinxsidebar should rather use a wrapfig or similar environment
|
||||||
|
% but this is so dysfunctional in LaTeX (except for self-written documents)
|
||||||
|
% so we prefer to not venture into such a potential quagmire and keep the
|
||||||
|
% legacy rendering using a full width display.
|
||||||
|
\newenvironment{sphinxsidebar}
|
||||||
|
{\begin{sphinxShadowBox}[sidebar]}{\end{sphinxShadowBox}}
|
||||||
|
|
||||||
|
% TODO: decide if this should be in sphinxlatexstyletext.sty rather
|
||||||
|
%
|
||||||
|
% 8.1.0 styles topic/contents/sidebar with a title row, too.
|
||||||
|
% Prior to 8.1.0, definitions use \protected\def but there does not seem
|
||||||
|
% to be any reason so back to \newcommand.
|
||||||
|
\newcommand*\sphinxstyletopictitle[1]{\sphinxdotitlerow{topic}{#1}}
|
||||||
|
\newcommand*\sphinxstylecontentstitle[1]{\sphinxdotitlerow{contents}{#1}}
|
||||||
|
\newcommand*\sphinxstylesidebartitle[1]{\sphinxdotitlerow{sidebar}{#1}}
|
||||||
|
% No default color background for subtitle. The contents next are injected by
|
||||||
|
% LaTeX writer after a blank line in source hence will start a new paragrpah.
|
||||||
|
% The \sphinxAtStartPar here is only for coherence with other text paragraphs,
|
||||||
|
% but does not have serious necessity (its general role is to allow hyphenation
|
||||||
|
% for first word in narrow table cells).
|
||||||
|
\newcommand*\sphinxstylesidebarsubtitle[1]{\sphinxAtStartPar\textbf{#1}}
|
||||||
|
|
||||||
|
\endinput
|
||||||
91
build/latex/sphinxlatexstyleheadings.sty
Normal file
91
build/latex/sphinxlatexstyleheadings.sty
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
%% TITLES
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexstyleheadings}[2023/02/11 headings]
|
||||||
|
|
||||||
|
\RequirePackage[nobottomtitles*]{titlesec}
|
||||||
|
% tests showed that this setting guarantees \section title has
|
||||||
|
% 3 lines of text following it on same page if near bottom.
|
||||||
|
\renewcommand\bottomtitlespace{6\baselineskip}
|
||||||
|
% the default setting of 0.2\textheight is about 11\baselineskip
|
||||||
|
% (for 10pt letterpaper documents) and may create large voids.
|
||||||
|
|
||||||
|
\@ifpackagelater{titlesec}{2016/03/15}%
|
||||||
|
{\@ifpackagelater{titlesec}{2016/03/21}%
|
||||||
|
{}%
|
||||||
|
{\newif\ifsphinx@ttlpatch@ok
|
||||||
|
\IfFileExists{etoolbox.sty}{%
|
||||||
|
\RequirePackage{etoolbox}%
|
||||||
|
\patchcmd{\ttlh@hang}{\parindent\z@}{\parindent\z@\leavevmode}%
|
||||||
|
{\sphinx@ttlpatch@oktrue}{}%
|
||||||
|
\ifsphinx@ttlpatch@ok
|
||||||
|
\patchcmd{\ttlh@hang}{\noindent}{}{}{\sphinx@ttlpatch@okfalse}%
|
||||||
|
\fi
|
||||||
|
}{}%
|
||||||
|
\ifsphinx@ttlpatch@ok
|
||||||
|
\typeout{^^J Package Sphinx Info: ^^J
|
||||||
|
**** titlesec 2.10.1 successfully patched for bugfix ****^^J}%
|
||||||
|
\else
|
||||||
|
\AtEndDocument{\PackageWarningNoLine{sphinx}{^^J%
|
||||||
|
******** titlesec 2.10.1 has a bug, (section numbers disappear) ......|^^J%
|
||||||
|
******** and Sphinx could not patch it, perhaps because your local ...|^^J%
|
||||||
|
******** copy is already fixed without a changed release date. .......|^^J%
|
||||||
|
******** If not, you must update titlesec! ...........................|}}%
|
||||||
|
\sphinxbuildwarning{badtitlesec}%
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
}{}
|
||||||
|
|
||||||
|
% Augment the sectioning commands used to get our own font family in place,
|
||||||
|
% and reset some internal data items (\titleformat from titlesec package)
|
||||||
|
\titleformat{\section}{\Large\py@HeaderFamily}%
|
||||||
|
{\py@TitleColor\thesection}{0.5em}{\py@TitleColor}
|
||||||
|
\titleformat{\subsection}{\large\py@HeaderFamily}%
|
||||||
|
{\py@TitleColor\thesubsection}{0.5em}{\py@TitleColor}
|
||||||
|
% \normalsize added as work-around to a lualatex-ja upstream problem
|
||||||
|
% https://osdn.net/projects/luatex-ja/ticket/47321
|
||||||
|
\titleformat{\subsubsection}{\normalsize\py@HeaderFamily}%
|
||||||
|
{\py@TitleColor\thesubsubsection}{0.5em}{\py@TitleColor}
|
||||||
|
% By default paragraphs (and subsubsections) will not be numbered because
|
||||||
|
% sphinxmanual.cls and sphinxhowto.cls set secnumdepth to 2
|
||||||
|
\titleformat{\paragraph}{\normalsize\py@HeaderFamily}%
|
||||||
|
{\py@TitleColor\theparagraph}{0.5em}{\py@TitleColor}
|
||||||
|
\titleformat{\subparagraph}{\normalsize\py@HeaderFamily}%
|
||||||
|
{\py@TitleColor\thesubparagraph}{0.5em}{\py@TitleColor}
|
||||||
|
|
||||||
|
% Since Sphinx 1.5, users should use HeaderFamily key to 'sphinxsetup' rather
|
||||||
|
% than defining their own \py@HeaderFamily command (which is still possible).
|
||||||
|
% Memo: \py@HeaderFamily is also used by \maketitle as defined in
|
||||||
|
% sphinxmanual.cls/sphinxhowto.cls
|
||||||
|
\newcommand{\py@HeaderFamily}{\spx@opt@HeaderFamily}
|
||||||
|
|
||||||
|
% This sets up the fancy chapter headings that make the documents look
|
||||||
|
% at least a little better than the usual LaTeX output.
|
||||||
|
\@ifpackagewith{fncychap}{Bjarne}{
|
||||||
|
\ChNameVar {\raggedleft\normalsize \py@HeaderFamily}
|
||||||
|
\ChNumVar {\raggedleft\Large \py@HeaderFamily}
|
||||||
|
\ChTitleVar{\raggedleft\Large \py@HeaderFamily}
|
||||||
|
% This creates (numbered) chapter heads without the leading \vspace*{}:
|
||||||
|
\def\@makechapterhead#1{%
|
||||||
|
{\parindent \z@ \raggedright \normalfont
|
||||||
|
\ifnum \c@secnumdepth >\m@ne
|
||||||
|
\if@mainmatter
|
||||||
|
\DOCH
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\interlinepenalty\@M
|
||||||
|
\if@mainmatter
|
||||||
|
\DOTI{#1}%
|
||||||
|
\else%
|
||||||
|
\DOTIS{#1}%
|
||||||
|
\fi
|
||||||
|
}}
|
||||||
|
}{}% <-- "false" clause of \@ifpackagewith
|
||||||
|
|
||||||
|
% fix fncychap's bug which uses prematurely the \textwidth value
|
||||||
|
\@ifpackagewith{fncychap}{Bjornstrup}
|
||||||
|
{\AtBeginDocument{\mylen\textwidth\advance\mylen-2\myhi}}%
|
||||||
|
{}% <-- "false" clause of \@ifpackagewith
|
||||||
|
|
||||||
|
|
||||||
|
\endinput
|
||||||
73
build/latex/sphinxlatexstylepage.sty
Normal file
73
build/latex/sphinxlatexstylepage.sty
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
%% PAGE STYLING
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexstylepage}[2021/01/27 page styling]
|
||||||
|
|
||||||
|
% Separate paragraphs by space by default.
|
||||||
|
\RequirePackage{parskip}
|
||||||
|
|
||||||
|
% Style parameters and macros used by most documents here
|
||||||
|
\raggedbottom
|
||||||
|
\sloppy
|
||||||
|
\hbadness = 5000 % don't print trivial gripes
|
||||||
|
|
||||||
|
% Require package fancyhdr except under memoir class
|
||||||
|
\@ifclassloaded{memoir}{}{\RequirePackage{fancyhdr}}
|
||||||
|
% Use \pagestyle{normal} as the primary pagestyle for text.
|
||||||
|
% Redefine the 'normal' header/footer style when using "fancyhdr" package:
|
||||||
|
\@ifpackageloaded{fancyhdr}{%
|
||||||
|
\ltx@ifundefined{c@chapter}
|
||||||
|
{% no \chapter, "howto" (non-Japanese) docclass
|
||||||
|
\fancypagestyle{plain}{
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyfoot[C]{{\py@HeaderFamily\thepage}}
|
||||||
|
\renewcommand{\headrulewidth}{0pt}
|
||||||
|
\renewcommand{\footrulewidth}{0pt}
|
||||||
|
}
|
||||||
|
% Same as 'plain', this way we can use it in template
|
||||||
|
% FIXME: shouldn't this have a running header with Name and Release like 'manual'?
|
||||||
|
\fancypagestyle{normal}{
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyfoot[C]{{\py@HeaderFamily\thepage}}
|
||||||
|
\renewcommand{\headrulewidth}{0pt}
|
||||||
|
\renewcommand{\footrulewidth}{0pt}
|
||||||
|
}
|
||||||
|
}%
|
||||||
|
{% classes with \chapter command
|
||||||
|
\fancypagestyle{normal}{
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyfoot[RO]{{\py@HeaderFamily\thepage}}
|
||||||
|
\fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}}
|
||||||
|
\fancyhead[RO]{{\py@HeaderFamily \@title\sphinxheadercomma\py@release}}
|
||||||
|
\if@twoside
|
||||||
|
\fancyfoot[LE]{{\py@HeaderFamily\thepage}}
|
||||||
|
\fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}}
|
||||||
|
\fancyhead[LE]{{\py@HeaderFamily \@title\sphinxheadercomma\py@release}}
|
||||||
|
\fi
|
||||||
|
\renewcommand{\headrulewidth}{0.4pt}
|
||||||
|
\renewcommand{\footrulewidth}{0.4pt}
|
||||||
|
% define chaptermark with \@chappos when \@chappos is available for Japanese
|
||||||
|
\ltx@ifundefined{@chappos}{}
|
||||||
|
{\def\chaptermark##1{\markboth{\@chapapp\space\thechapter\space\@chappos\space ##1}{}}}
|
||||||
|
}
|
||||||
|
% Update the plain style so we get the page number & footer line,
|
||||||
|
% but not a chapter or section title. This is to keep the first
|
||||||
|
% page of a chapter `clean.'
|
||||||
|
\fancypagestyle{plain}{
|
||||||
|
\fancyhf{}
|
||||||
|
\fancyfoot[RO]{{\py@HeaderFamily\thepage}}
|
||||||
|
\if@twoside\fancyfoot[LE]{{\py@HeaderFamily\thepage}}\fi
|
||||||
|
\renewcommand{\headrulewidth}{0pt}
|
||||||
|
\renewcommand{\footrulewidth}{0.4pt}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{% no fancyhdr: memoir class
|
||||||
|
% Provide default for 'normal' style simply as an alias of 'plain' style
|
||||||
|
% This way we can use \pagestyle{normal} in LaTeX template
|
||||||
|
\def\ps@normal{\ps@plain}
|
||||||
|
% Users of memoir class are invited to redefine 'normal' style in preamble
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
\endinput
|
||||||
149
build/latex/sphinxlatexstyletext.sty
Normal file
149
build/latex/sphinxlatexstyletext.sty
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
%% TEXT STYLING
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxlatexstyletext}[2025/05/24 v9.0.0 text styling]
|
||||||
|
|
||||||
|
% 7.4.0 has moved all that is related to admonitions to sphinxlatexadmonitions.sty
|
||||||
|
% 8.1.0 has moved topic/contents/sidebar to sphinxlatexshadowbox.sty
|
||||||
|
% Most everything left here consists of macros which are part of the latex markup
|
||||||
|
% produced by the Sphinx LaTeX writer.
|
||||||
|
|
||||||
|
% Some custom font markup commands.
|
||||||
|
\protected\def\sphinxstrong#1{\textbf{#1}}
|
||||||
|
\protected\def\sphinxcode#1{\texttt{#1}}
|
||||||
|
\protected\def\sphinxbfcode#1{\textbf{\sphinxcode{#1}}}
|
||||||
|
\protected\def\sphinxemail#1{\textsf{#1}}
|
||||||
|
\protected\def\sphinxtablecontinued#1{\textsf{#1}}
|
||||||
|
\protected\def\sphinxtitleref#1{\emph{#1}}
|
||||||
|
\protected\def\sphinxmenuselection#1{\emph{#1}}
|
||||||
|
\protected\def\sphinxguilabel#1{\emph{#1}}
|
||||||
|
\protected\def\sphinxkeyboard#1{\sphinxcode{#1}}
|
||||||
|
\protected\def\sphinxaccelerator#1{\underline{#1}}
|
||||||
|
\protected\def\sphinxcrossref#1{\emph{#1}}
|
||||||
|
\protected\def\sphinxtermref#1{\emph{#1}}
|
||||||
|
\protected\def\sphinxsamedocref#1{\emph{#1}}
|
||||||
|
\protected\def\sphinxparam#1{\emph{#1}}
|
||||||
|
\protected\def\sphinxtypeparam#1{\emph{#1}}
|
||||||
|
% \optional is used for ``[, arg]``, i.e. desc_optional nodes.
|
||||||
|
\long\protected\def\sphinxoptional#1{%
|
||||||
|
{\sphinxoptionalhook\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}}
|
||||||
|
\let\sphinxoptionalhook\empty
|
||||||
|
|
||||||
|
% additional customizable styling
|
||||||
|
\def\sphinxstyleindexentry #1{\texttt{#1}}
|
||||||
|
\def\sphinxstyleindexextra #1{ (\emph{#1})}
|
||||||
|
\def\sphinxstyleindexpageref #1{, \pageref{#1}}
|
||||||
|
\def\sphinxstyleindexpagemain#1{\textbf{#1}}
|
||||||
|
\def\spxentry{\@backslashchar spxentry}% let to \sphinxstyleindexentry in index
|
||||||
|
\def\spxextra{\@backslashchar spxextra}% let to \sphinxstyleindexextra in index
|
||||||
|
\def\sphinxstyleindexlettergroup #1%
|
||||||
|
{{\Large\sffamily#1}\nopagebreak\vspace{1mm}}
|
||||||
|
\def\sphinxstyleindexlettergroupDefault #1%
|
||||||
|
{{\Large\sffamily\sphinxnonalphabeticalgroupname}\nopagebreak\vspace{1mm}}
|
||||||
|
\protected\def\sphinxstyleothertitle #1{\textbf{#1}}
|
||||||
|
% \text.. commands do not allow multiple paragraphs
|
||||||
|
% attention, this one is not self-delimiting
|
||||||
|
\protected\def\sphinxstyletheadfamily {\sffamily}
|
||||||
|
\protected\def\sphinxstyleemphasis #1{\emph{#1}}
|
||||||
|
\protected\def\sphinxstyleliteralemphasis#1{\emph{\sphinxcode{#1}}}
|
||||||
|
\protected\def\sphinxstylestrong #1{\textbf{#1}}
|
||||||
|
\protected\def\sphinxstyleliteralstrong#1{\sphinxbfcode{#1}}
|
||||||
|
\protected\def\sphinxstyleabbreviation #1{\textsc{#1}}
|
||||||
|
\protected\def\sphinxstyleliteralintitle#1{\sphinxcode{#1}}
|
||||||
|
\newcommand*\sphinxstylecodecontinued[1]{{\footnotesize(#1)}}%
|
||||||
|
\newcommand*\sphinxstylecodecontinues[1]{{\footnotesize(#1)}}%
|
||||||
|
% figure legend comes after caption and may contain arbitrary body elements
|
||||||
|
\newenvironment{sphinxlegend}{\par\small}{\par}
|
||||||
|
% reduce hyperref "Token not allowed in a PDF string" warnings on PDF builds
|
||||||
|
\AtBeginDocument{\pdfstringdefDisableCommands{%
|
||||||
|
% all "protected" macros possibly ending up in section titles should be here
|
||||||
|
% next four were added so that URLs and internal links in titles can be allowed
|
||||||
|
\let\sphinxurl \@firstofone
|
||||||
|
\let\sphinxnolinkurl\@firstofone
|
||||||
|
\let\sphinxhref \@secondoftwo
|
||||||
|
\def\hyperref[#1]#2{#2}% for PDF bookmark to ignore #1
|
||||||
|
\let\sphinxstyleemphasis \@firstofone
|
||||||
|
\let\sphinxstyleliteralemphasis \@firstofone
|
||||||
|
\let\sphinxstylestrong \@firstofone
|
||||||
|
\let\sphinxstyleliteralstrong \@firstofone
|
||||||
|
\let\sphinxstyleabbreviation \@firstofone
|
||||||
|
\let\sphinxstyleliteralintitle \@firstofone
|
||||||
|
\let\sphinxupquote \@firstofone
|
||||||
|
\let\sphinxstrong \@firstofone
|
||||||
|
\let\sphinxcode \@firstofone
|
||||||
|
\let\sphinxbfcode \@firstofone
|
||||||
|
\let\sphinxemail \@firstofone
|
||||||
|
\let\sphinxcrossref \@firstofone
|
||||||
|
\let\sphinxtermref \@firstofone
|
||||||
|
\let\sphinxsamedocref\@firstofone
|
||||||
|
\let\sphinxhyphen\sphinxhyphenforbookmarks
|
||||||
|
\def\PYG#1#2{#2}% (can not yet appear in section titles, but perhaps in future)
|
||||||
|
}}
|
||||||
|
|
||||||
|
% Special characters
|
||||||
|
%
|
||||||
|
\def\sphinxparamcomma{, }% by default separate parameters with comma + space
|
||||||
|
% If the signature is rendered with one line per param, this wil be used
|
||||||
|
% instead (this \texttt makes the comma slightly more distinctive).
|
||||||
|
\def\sphinxparamcommaoneperline{\texttt{,}}
|
||||||
|
%
|
||||||
|
% The \kern\z@ is to prevent en-dash and em-dash TeX ligatures.
|
||||||
|
% A linebreak can occur after the dash in regular text (this is
|
||||||
|
% normal behaviour of "-" in TeX, it is not related to \kern\z@).
|
||||||
|
%
|
||||||
|
% Parsed-literals and inline literals also use the \sphinxhyphen
|
||||||
|
% but linebreaks there are prevented due to monospace font family.
|
||||||
|
% (xelatex needs a special addition, cf. sphinxlatexliterals.sty)
|
||||||
|
%
|
||||||
|
% Inside code-blocks, dashes are escaped via another macro, from
|
||||||
|
% Pygments latex output (search for \PYGZhy in sphinxlatexliterals.sty),
|
||||||
|
% and are configured to allow linebreaks despite the monospace font.
|
||||||
|
% (the #1 swallows the {} from \sphinxhyphen{} mark-up)
|
||||||
|
\protected\def\sphinxhyphen#1{-\kern\z@}
|
||||||
|
\protected\def\sphinxhyphennobreak#1{\mbox{-}}
|
||||||
|
% The {} from texescape mark-up is kept, else -- gives en-dash in PDF bookmark
|
||||||
|
\def\sphinxhyphenforbookmarks{-}
|
||||||
|
|
||||||
|
% For curly braces inside \index macro
|
||||||
|
\def\sphinxleftcurlybrace{\{}
|
||||||
|
\def\sphinxrightcurlybrace{\}}
|
||||||
|
|
||||||
|
% Declare Unicode characters used by linux tree command to pdflatex utf8/utf8x
|
||||||
|
\def\spx@bd#1#2{%
|
||||||
|
\leavevmode
|
||||||
|
\begingroup
|
||||||
|
\ifx\spx@bd@height \@undefined\def\spx@bd@height{\baselineskip}\fi
|
||||||
|
\ifx\spx@bd@width \@undefined\setbox0\hbox{0}\def\spx@bd@width{\wd0 }\fi
|
||||||
|
\ifx\spx@bd@thickness\@undefined\def\spx@bd@thickness{.6\p@}\fi
|
||||||
|
\ifx\spx@bd@lower \@undefined\def\spx@bd@lower{\dp\strutbox}\fi
|
||||||
|
\lower\spx@bd@lower#1{#2}%
|
||||||
|
\endgroup
|
||||||
|
}%
|
||||||
|
\@namedef{sphinx@u2500}% BOX DRAWINGS LIGHT HORIZONTAL
|
||||||
|
{\spx@bd{\vbox to\spx@bd@height}
|
||||||
|
{\vss\hrule\@height\spx@bd@thickness
|
||||||
|
\@width\spx@bd@width\vss}}%
|
||||||
|
\@namedef{sphinx@u2502}% BOX DRAWINGS LIGHT VERTICAL
|
||||||
|
{\spx@bd{\hb@xt@\spx@bd@width}
|
||||||
|
{\hss\vrule\@height\spx@bd@height
|
||||||
|
\@width \spx@bd@thickness\hss}}%
|
||||||
|
\@namedef{sphinx@u2514}% BOX DRAWINGS LIGHT UP AND RIGHT
|
||||||
|
{\spx@bd{\hb@xt@\spx@bd@width}
|
||||||
|
{\hss\raise.5\spx@bd@height
|
||||||
|
\hb@xt@\z@{\hss\vrule\@height.5\spx@bd@height
|
||||||
|
\@width \spx@bd@thickness\hss}%
|
||||||
|
\vbox to\spx@bd@height{\vss\hrule\@height\spx@bd@thickness
|
||||||
|
\@width.5\spx@bd@width\vss}}}%
|
||||||
|
\@namedef{sphinx@u251C}% BOX DRAWINGS LIGHT VERTICAL AND RIGHT
|
||||||
|
{\spx@bd{\hb@xt@\spx@bd@width}
|
||||||
|
{\hss
|
||||||
|
\hb@xt@\z@{\hss\vrule\@height\spx@bd@height
|
||||||
|
\@width \spx@bd@thickness\hss}%
|
||||||
|
\vbox to\spx@bd@height{\vss\hrule\@height\spx@bd@thickness
|
||||||
|
\@width.5\spx@bd@width\vss}}}%
|
||||||
|
\protected\def\sphinxunichar#1{\@nameuse{sphinx@u#1}}%
|
||||||
|
|
||||||
|
% Tell TeX about pathological hyphenation cases:
|
||||||
|
\hyphenation{Base-HTTP-Re-quest-Hand-ler}
|
||||||
|
|
||||||
|
\endinput
|
||||||
1365
build/latex/sphinxlatextables.sty
Normal file
1365
build/latex/sphinxlatextables.sty
Normal file
File diff suppressed because it is too large
Load diff
128
build/latex/sphinxmanual.cls
Normal file
128
build/latex/sphinxmanual.cls
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
%
|
||||||
|
% sphinxmanual.cls for Sphinx (https://www.sphinx-doc.org/)
|
||||||
|
%
|
||||||
|
|
||||||
|
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||||
|
\ProvidesClass{sphinxmanual}[2019/12/01 v2.3.0 Document class (Sphinx manual)]
|
||||||
|
|
||||||
|
% chapters starting at odd pages (overridden by 'openany' document option)
|
||||||
|
\PassOptionsToClass{openright}{\sphinxdocclass}
|
||||||
|
|
||||||
|
% 'oneside' option overriding the 'twoside' default
|
||||||
|
\newif\if@oneside
|
||||||
|
\DeclareOption{oneside}{\@onesidetrue}
|
||||||
|
% Pass remaining document options to the parent class.
|
||||||
|
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}}
|
||||||
|
\ProcessOptions\relax
|
||||||
|
|
||||||
|
% Defaults two-side document
|
||||||
|
\if@oneside
|
||||||
|
% nothing to do (oneside is the default)
|
||||||
|
\else
|
||||||
|
\PassOptionsToClass{twoside}{\sphinxdocclass}
|
||||||
|
\fi
|
||||||
|
|
||||||
|
\LoadClass{\sphinxdocclass}
|
||||||
|
|
||||||
|
% Set some sane defaults for section numbering depth and TOC depth. You can
|
||||||
|
% reset these counters in your preamble.
|
||||||
|
%
|
||||||
|
\setcounter{secnumdepth}{2}
|
||||||
|
\setcounter{tocdepth}{1}
|
||||||
|
|
||||||
|
% Adapt \and command to the flushright context of \sphinxmaketitle, to
|
||||||
|
% avoid ragged line endings if author names do not fit all on one single line
|
||||||
|
\DeclareRobustCommand{\and}{%
|
||||||
|
\end{tabular}\kern-\tabcolsep
|
||||||
|
\allowbreak
|
||||||
|
\hskip\dimexpr1em+\tabcolsep\@plus.17fil\begin{tabular}[t]{c}%
|
||||||
|
}%
|
||||||
|
% If it is desired that each author name be on its own line, use in preamble:
|
||||||
|
%\DeclareRobustCommand{\and}{%
|
||||||
|
% \end{tabular}\kern-\tabcolsep\\\begin{tabular}[t]{c}%
|
||||||
|
%}%
|
||||||
|
% Change the title page to look a bit better, and fit in with the fncychap
|
||||||
|
% ``Bjarne'' style a bit better.
|
||||||
|
%
|
||||||
|
\newcommand{\sphinxmaketitle}{%
|
||||||
|
\let\sphinxrestorepageanchorsetting\relax
|
||||||
|
\ifHy@pageanchor\def\sphinxrestorepageanchorsetting{\Hy@pageanchortrue}\fi
|
||||||
|
\hypersetup{pageanchor=false}% avoid duplicate destination warnings
|
||||||
|
\begin{titlepage}%
|
||||||
|
\let\footnotesize\small
|
||||||
|
\let\footnoterule\relax
|
||||||
|
\noindent\rule{\textwidth}{1pt}\par
|
||||||
|
\begingroup % for PDF information dictionary
|
||||||
|
\def\endgraf{ }\def\and{\& }%
|
||||||
|
\pdfstringdefDisableCommands{\def\\{, }}% overwrite hyperref setup
|
||||||
|
\hypersetup{pdfauthor={\@author}, pdftitle={\@title}}%
|
||||||
|
\endgroup
|
||||||
|
\begin{flushright}%
|
||||||
|
\sphinxlogo
|
||||||
|
\py@HeaderFamily
|
||||||
|
{\Huge \@title \par}
|
||||||
|
{\itshape\LARGE \py@release\releaseinfo \par}
|
||||||
|
\vfill
|
||||||
|
{\LARGE
|
||||||
|
\begin{tabular}[t]{c}
|
||||||
|
\@author
|
||||||
|
\end{tabular}\kern-\tabcolsep
|
||||||
|
\par}
|
||||||
|
\vfill\vfill
|
||||||
|
{\large
|
||||||
|
\@date \par
|
||||||
|
\vfill
|
||||||
|
\py@authoraddress \par
|
||||||
|
}%
|
||||||
|
\end{flushright}%\par
|
||||||
|
\@thanks
|
||||||
|
\end{titlepage}%
|
||||||
|
\setcounter{footnote}{0}%
|
||||||
|
\let\thanks\relax\let\maketitle\relax
|
||||||
|
%\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
|
||||||
|
\clearpage
|
||||||
|
\ifdefined\sphinxbackoftitlepage\sphinxbackoftitlepage\fi
|
||||||
|
\if@openright\cleardoublepage\else\clearpage\fi
|
||||||
|
\sphinxrestorepageanchorsetting
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand{\sphinxtableofcontents}{%
|
||||||
|
\pagenumbering{roman}%
|
||||||
|
\begingroup
|
||||||
|
\parskip \z@skip
|
||||||
|
\sphinxtableofcontentshook
|
||||||
|
\tableofcontents
|
||||||
|
\endgroup
|
||||||
|
% before resetting page counter, let's do the right thing.
|
||||||
|
\if@openright\cleardoublepage\else\clearpage\fi
|
||||||
|
\pagenumbering{arabic}%
|
||||||
|
}
|
||||||
|
|
||||||
|
% This is needed to get the width of the section # area wide enough in the
|
||||||
|
% library reference. Doing it here keeps it the same for all the manuals.
|
||||||
|
%
|
||||||
|
\newcommand{\sphinxtableofcontentshook}{%
|
||||||
|
\renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.6em}}%
|
||||||
|
\renewcommand*\l@subsection{\@dottedtocline{2}{4.1em}{3.5em}}%
|
||||||
|
}
|
||||||
|
|
||||||
|
% Fix the bibliography environment to add an entry to the Table of
|
||||||
|
% Contents.
|
||||||
|
% For a report document class this environment is a chapter.
|
||||||
|
%
|
||||||
|
\newenvironment{sphinxthebibliography}[1]{%
|
||||||
|
\if@openright\cleardoublepage\else\clearpage\fi
|
||||||
|
% \phantomsection % not needed here since TeXLive 2010's hyperref
|
||||||
|
\begin{thebibliography}{#1}%
|
||||||
|
\addcontentsline{toc}{chapter}{\bibname}}{\end{thebibliography}}
|
||||||
|
|
||||||
|
% Same for the indices.
|
||||||
|
% The memoir class already does this, so we don't duplicate it in that case.
|
||||||
|
%
|
||||||
|
\@ifclassloaded{memoir}
|
||||||
|
{\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}}
|
||||||
|
{\newenvironment{sphinxtheindex}{%
|
||||||
|
\if@openright\cleardoublepage\else\clearpage\fi
|
||||||
|
\phantomsection % needed as no chapter, section, ... created
|
||||||
|
\begin{theindex}%
|
||||||
|
\addcontentsline{toc}{chapter}{\indexname}}{\end{theindex}}}
|
||||||
21
build/latex/sphinxmessages.sty
Normal file
21
build/latex/sphinxmessages.sty
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
%
|
||||||
|
% sphinxmessages.sty
|
||||||
|
%
|
||||||
|
% message resources for Sphinx
|
||||||
|
%
|
||||||
|
\ProvidesPackage{sphinxmessages}[2019/01/04 v2.0 Localized LaTeX macros (Sphinx team)]
|
||||||
|
|
||||||
|
\renewcommand{\literalblockcontinuedname}{continued from previous page}
|
||||||
|
\renewcommand{\literalblockcontinuesname}{continues on next page}
|
||||||
|
\renewcommand{\sphinxnonalphabeticalgroupname}{Non\sphinxhyphen{}alphabetical}
|
||||||
|
\renewcommand{\sphinxsymbolsname}{Symbols}
|
||||||
|
\renewcommand{\sphinxnumbersname}{Numbers}
|
||||||
|
\def\pageautorefname{page}
|
||||||
|
|
||||||
|
\addto\captionsenglish{\renewcommand{\figurename}{Fig.\@{} }}
|
||||||
|
\def\fnum@figure{\figurename\thefigure{}}
|
||||||
|
|
||||||
|
\addto\captionsenglish{\renewcommand{\tablename}{Table }}
|
||||||
|
\def\fnum@table{\tablename\thetable{}}
|
||||||
|
|
||||||
|
\addto\captionsenglish{\renewcommand{\literalblockname}{Listing}}
|
||||||
54
build/latex/sphinxoptionsgeometry.sty
Normal file
54
build/latex/sphinxoptionsgeometry.sty
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
%% OPTIONS FOR GEOMETRY
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxoptionsgeometry}[2021/01/27 geometry]
|
||||||
|
|
||||||
|
% geometry
|
||||||
|
\ifx\kanjiskip\@undefined
|
||||||
|
\PassOptionsToPackage{%
|
||||||
|
hmargin={\unexpanded{\spx@opt@hmargin}},%
|
||||||
|
vmargin={\unexpanded{\spx@opt@vmargin}},%
|
||||||
|
marginpar=\unexpanded{\spx@opt@marginpar}}
|
||||||
|
{geometry}
|
||||||
|
\else
|
||||||
|
% set text width for Japanese documents to be integer multiple of 1zw
|
||||||
|
% and text height to be integer multiple of \baselineskip
|
||||||
|
% the execution is delayed to \sphinxsetup then geometry.sty
|
||||||
|
\normalsize\normalfont
|
||||||
|
\newcommand*\sphinxtextwidthja[1]{%
|
||||||
|
\if@twocolumn\tw@\fi
|
||||||
|
\dimexpr
|
||||||
|
\numexpr\dimexpr\paperwidth-\tw@\dimexpr#1\relax\relax/
|
||||||
|
\dimexpr\if@twocolumn\tw@\else\@ne\fi zw\relax
|
||||||
|
zw\relax}%
|
||||||
|
\newcommand*\sphinxmarginparwidthja[1]{%
|
||||||
|
\dimexpr\numexpr\dimexpr#1\relax/\dimexpr1zw\relax zw\relax}%
|
||||||
|
\newcommand*\sphinxtextlinesja[1]{%
|
||||||
|
\numexpr\@ne+\dimexpr\paperheight-\topskip-\tw@\dimexpr#1\relax\relax/
|
||||||
|
\baselineskip\relax}%
|
||||||
|
\ifx\@jsc@uplatextrue\@undefined\else
|
||||||
|
% the way we found in order for the papersize special written by
|
||||||
|
% geometry in the dvi file to be correct in case of jsbook class
|
||||||
|
\ifnum\mag=\@m\else % do nothing special if nomag class option or 10pt
|
||||||
|
\PassOptionsToPackage{truedimen}{geometry}%
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\PassOptionsToPackage{%
|
||||||
|
hmarginratio={1:1},%
|
||||||
|
textwidth=\unexpanded{\sphinxtextwidthja{\spx@opt@hmargin}},%
|
||||||
|
vmarginratio={1:1},%
|
||||||
|
lines=\unexpanded{\sphinxtextlinesja{\spx@opt@vmargin}},%
|
||||||
|
marginpar=\unexpanded{\sphinxmarginparwidthja{\spx@opt@marginpar}},%
|
||||||
|
footskip=2\baselineskip,%
|
||||||
|
}{geometry}%
|
||||||
|
\AtBeginDocument
|
||||||
|
{% update a dimension used by the jsclasses
|
||||||
|
\ifx\@jsc@uplatextrue\@undefined\else\fullwidth\textwidth\fi
|
||||||
|
% for some reason, jreport normalizes all dimensions with \@settopoint
|
||||||
|
\@ifclassloaded{jreport}
|
||||||
|
{\@settopoint\textwidth\@settopoint\textheight\@settopoint\marginparwidth}
|
||||||
|
{}% <-- "false" clause of \@ifclassloaded
|
||||||
|
}%
|
||||||
|
\fi
|
||||||
|
|
||||||
|
\endinput
|
||||||
35
build/latex/sphinxoptionshyperref.sty
Normal file
35
build/latex/sphinxoptionshyperref.sty
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
%% Bookmarks and hyperlinks
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxoptionshyperref}[2021/01/27 hyperref]
|
||||||
|
|
||||||
|
% to make pdf with correct encoded bookmarks in Japanese
|
||||||
|
% this should precede the hyperref package
|
||||||
|
\ifx\kanjiskip\@undefined
|
||||||
|
% for non-Japanese: make sure bookmarks are ok also with lualatex
|
||||||
|
\PassOptionsToPackage{pdfencoding=unicode}{hyperref}
|
||||||
|
\else
|
||||||
|
\RequirePackage{atbegshi}
|
||||||
|
\ifx\ucs\@undefined
|
||||||
|
\ifnum 42146=\euc"A4A2
|
||||||
|
\AtBeginShipoutFirst{\special{pdf:tounicode EUC-UCS2}}
|
||||||
|
\else
|
||||||
|
\AtBeginShipoutFirst{\special{pdf:tounicode 90ms-RKSJ-UCS2}}
|
||||||
|
\fi
|
||||||
|
\else
|
||||||
|
\AtBeginShipoutFirst{\special{pdf:tounicode UTF8-UCS2}}
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
|
||||||
|
\ifx\@jsc@uplatextrue\@undefined\else
|
||||||
|
\PassOptionsToPackage{setpagesize=false}{hyperref}
|
||||||
|
\fi
|
||||||
|
|
||||||
|
% These options can be overridden inside 'hyperref' key
|
||||||
|
% or by later use of \hypersetup.
|
||||||
|
\PassOptionsToPackage{colorlinks,breaklinks,%
|
||||||
|
linkcolor=InnerLinkColor,filecolor=OuterLinkColor,%
|
||||||
|
menucolor=OuterLinkColor,urlcolor=OuterLinkColor,%
|
||||||
|
citecolor=InnerLinkColor}{hyperref}
|
||||||
|
|
||||||
|
\endinput
|
||||||
827
build/latex/sphinxpackageboxes.sty
Normal file
827
build/latex/sphinxpackageboxes.sty
Normal file
|
|
@ -0,0 +1,827 @@
|
||||||
|
%% COLOURED BOXES
|
||||||
|
%
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxpackageboxes}[2024/07/01 v7.4.0 advanced colored boxes]
|
||||||
|
% 7.4.0 removes usage of some booleans "...withbackgroundcolor" and
|
||||||
|
% "...withbordercolor" as well as \spx@boxes@border dimen which was
|
||||||
|
% actually really needed nowhere. This was done in sync with changes in
|
||||||
|
% sphinx.sty, sphinxlatexadmonitions.sty and sphinxlatexliterals.sty.
|
||||||
|
%
|
||||||
|
% Optionally executes \RequirePackage for:
|
||||||
|
%
|
||||||
|
% - pict2e. Ideally we would like to use the v0.4a 2020/08/16 release of this
|
||||||
|
% package as it allows dimensional arguments to its \moveto, \lineto, etc...
|
||||||
|
% Or we could use extra package "picture". We opt for custom wrappers
|
||||||
|
% \spx@moveto, \spx@lineto, ..., working with old versions.
|
||||||
|
%
|
||||||
|
% - ellipse. This package extends pict2e with elliptical arcs. Its author
|
||||||
|
% Daan Leijen also has contributed package longfbox which is part of
|
||||||
|
% TeXLive. Had I known about it, I would perhaps have based Sphinx CSS on
|
||||||
|
% top of longfbox at least partly. But this would not have spared me all
|
||||||
|
% the work in sphinx.sty, which was a long walk until 6.2.0 version.
|
||||||
|
% Besides I don't need the breakable boxes from longfbox, as Sphinx has
|
||||||
|
% its own rather advanced layer on top of framed. I would need to check if
|
||||||
|
% some thorny color issues solved by Sphinx (and not by tcolorbox) at page
|
||||||
|
% breaks are solved by longfbox as well. (I have not tested)
|
||||||
|
|
||||||
|
% At 6.2.0 refactoring, we do not wait for at begin document to try to load
|
||||||
|
% pict2e. Actually since 6.0.0 the default is for code-blocks to use
|
||||||
|
% rounded boxes, and the only reason since then to wait "at begin document"
|
||||||
|
% was to check if user had reverted that default and in fact pict2e was not
|
||||||
|
% needed. But with \sphinxbox, we can not know for sure even in that case
|
||||||
|
% that pict2e is not needed. And even back then it would have been possible
|
||||||
|
% to user to try to employ \sphinxsetup via raw directive in document body
|
||||||
|
% and require some rounded corners (which was thus impossible to satisfy).
|
||||||
|
% Time to be much simpler and attempt unconditionally to load pict2e
|
||||||
|
% immediately. This will also have advantage that we can use
|
||||||
|
% \@ifpackageloaded{pict2e} and not have to query and save its setting later
|
||||||
|
% at begin document.
|
||||||
|
\IfFileExists{pict2e.sty}
|
||||||
|
{\RequirePackage{pict2e}}
|
||||||
|
{\PackageWarningNoLine{sphinx}{%
|
||||||
|
The package pict2e is required for rounded boxes.\MessageBreak
|
||||||
|
It does not seem to be available on your system.\MessageBreak
|
||||||
|
Options for setting radii will be ignored%
|
||||||
|
}%
|
||||||
|
% Formerly a \sphinxbuildwarning was issued but if we did that now it
|
||||||
|
% would mean that the produced PDF will always have a red banner near its
|
||||||
|
% end about pict2e not being available if indeed it is not available, even
|
||||||
|
% if user has reverted the default and dropped rounded corners. Formerly
|
||||||
|
% the serious warning was done after having checked at begin document that
|
||||||
|
% indeed a rounded corner option had been used. As we drop the check now,
|
||||||
|
% let's be more discrete and simply duplicate the earlier warning to make
|
||||||
|
% it visible near end of compilation log and console output.
|
||||||
|
\AtEndDocument{\PackageWarningNoLine{sphinx}{%
|
||||||
|
The package pict2e is required for rounded boxes.\MessageBreak
|
||||||
|
As it does not seem to be available on your system,\MessageBreak
|
||||||
|
options setting radii have all been ignored}}%
|
||||||
|
}%
|
||||||
|
|
||||||
|
\IfFileExists{ellipse.sty}
|
||||||
|
{\RequirePackage{ellipse}}
|
||||||
|
{\PackageWarningNoLine{sphinx}{%
|
||||||
|
The package ellipse is required for elliptical corners.\MessageBreak
|
||||||
|
It does not seem to be available on your system.\MessageBreak
|
||||||
|
All non-straight corners will use circle arcs.%
|
||||||
|
}%
|
||||||
|
\AtEndDocument{\PackageWarningNoLine{sphinx}{%
|
||||||
|
The package ellipse is required for elliptical corners.\MessageBreak
|
||||||
|
As it does not seem to be available on your system,\MessageBreak
|
||||||
|
all non-straight corners have used circle arcs.}}%
|
||||||
|
}%
|
||||||
|
|
||||||
|
% The pict2e release v0.4b of 2020/09/30 does not allocate scratch dimen
|
||||||
|
% register \@tempdimd which ellipse package uses. Thus ellipse package is
|
||||||
|
% broken since (written on March 20, 2023). Simply allocate the register
|
||||||
|
% ourself to fix that, pending some upstream fix.
|
||||||
|
\@ifpackageloaded{ellipse}{\ifdefined\@tempdimd\else\newdimen\@tempdimd\fi}{}
|
||||||
|
|
||||||
|
% Provides box registers \spx@tempboxa, \spx@tempboxb usable in other places
|
||||||
|
\newbox\spx@tempboxa
|
||||||
|
\newbox\spx@tempboxb
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%
|
||||||
|
% Internal registers, conditionals, colors to be configured by each caller
|
||||||
|
% via a preliminary "setup" call
|
||||||
|
\newif\ifspx@boxes@withshadow
|
||||||
|
\newif\ifspx@boxes@insetshadow
|
||||||
|
%%% \newif\ifspx@boxes@withbackgroundcolor % removed at 7.4.0
|
||||||
|
\newif\ifspx@boxes@withshadowcolor
|
||||||
|
%%% \newif\ifspx@boxes@withbordercolor % removed at 7.4.0
|
||||||
|
\newif\ifspx@boxes@shadowinbbox
|
||||||
|
%
|
||||||
|
\newdimen\spx@boxes@border@top
|
||||||
|
\newdimen\spx@boxes@border@right
|
||||||
|
\newdimen\spx@boxes@border@bottom
|
||||||
|
\newdimen\spx@boxes@border@left
|
||||||
|
%
|
||||||
|
\newdimen\spx@boxes@padding@top
|
||||||
|
\newdimen\spx@boxes@padding@right
|
||||||
|
\newdimen\spx@boxes@padding@bottom
|
||||||
|
\newdimen\spx@boxes@padding@left
|
||||||
|
%
|
||||||
|
\newdimen\spx@boxes@shadow@xoffset
|
||||||
|
\newdimen\spx@boxes@shadow@yoffset
|
||||||
|
%
|
||||||
|
\newdimen\spx@boxes@radius@topleft@x
|
||||||
|
\newdimen\spx@boxes@radius@topright@x
|
||||||
|
\newdimen\spx@boxes@radius@bottomright@x
|
||||||
|
\newdimen\spx@boxes@radius@bottomleft@x
|
||||||
|
\newdimen\spx@boxes@radius@topleft@y
|
||||||
|
\newdimen\spx@boxes@radius@topright@y
|
||||||
|
\newdimen\spx@boxes@radius@bottomright@y
|
||||||
|
\newdimen\spx@boxes@radius@bottomleft@y
|
||||||
|
%
|
||||||
|
% These colors will be set to colors defined appropriately by caller of
|
||||||
|
% \spx@boxes@fcolorbox@setup macro
|
||||||
|
% spx@boxes@bordercolor
|
||||||
|
% spx@boxes@backgroundcolor
|
||||||
|
% spx@boxes@shadowcolor
|
||||||
|
% spx@boxes@textcolor
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%
|
||||||
|
% "setup" macro
|
||||||
|
%
|
||||||
|
% It must be called prior to \spx@boxes@fcolorbox for parameters of the latter
|
||||||
|
% to be initialized.
|
||||||
|
%
|
||||||
|
% It also prepares \spx@boxes@fcolorbox to expand to one of
|
||||||
|
% \spx@boxes@fcolorbox@rectangle or \spx@boxes@fcolorbox@rounded depending on
|
||||||
|
% the configuration and availability of the pict2e package.
|
||||||
|
%
|
||||||
|
% The #1 is one of: pre, topic, warning, danger, etc....
|
||||||
|
%
|
||||||
|
% We delay until here the parsing of radii options to extract x and y
|
||||||
|
% components.
|
||||||
|
\def\spx@boxes@setradii#1 #2 #3\@nnil#4#5{%
|
||||||
|
#4\dimexpr#1\relax
|
||||||
|
#5\dimexpr#2\relax
|
||||||
|
\ifdim#5=-\maxdimen#5#4\fi
|
||||||
|
% if one of them is zero or negative set both to zero
|
||||||
|
\ifdim#4>\z@\else#4\z@#5\z@\fi
|
||||||
|
\ifdim#5>\z@\else#4\z@#5\z@\fi
|
||||||
|
}%
|
||||||
|
% if ellipse.sty is not available ignore the second component of all radii
|
||||||
|
% specifications, use circle arcs with radius the x component
|
||||||
|
\@ifpackageloaded{ellipse}
|
||||||
|
{}
|
||||||
|
{\def\spx@boxes@setradii#1 #2 #3\@nnil#4#5{#4\dimexpr#1\relax #5#4}}
|
||||||
|
|
||||||
|
% Using \dimexpr for maximal user input flexibility.
|
||||||
|
\def\spx@boxes@fcolorbox@setup#1{%
|
||||||
|
\spx@boxes@border@top \dimexpr\@nameuse{spx@#1@border@top}\relax
|
||||||
|
\spx@boxes@border@right \dimexpr\@nameuse{spx@#1@border@right}\relax
|
||||||
|
\spx@boxes@border@bottom\dimexpr\@nameuse{spx@#1@border@bottom}\relax
|
||||||
|
\spx@boxes@border@left \dimexpr\@nameuse{spx@#1@border@left}\relax
|
||||||
|
%
|
||||||
|
\spx@boxes@padding@top \dimexpr\@nameuse{spx@#1@padding@top}\relax
|
||||||
|
\spx@boxes@padding@right \dimexpr\@nameuse{spx@#1@padding@right}\relax
|
||||||
|
\spx@boxes@padding@bottom\dimexpr\@nameuse{spx@#1@padding@bottom}\relax
|
||||||
|
\spx@boxes@padding@left \dimexpr\@nameuse{spx@#1@padding@left}\relax
|
||||||
|
%
|
||||||
|
\edef\spx@temp{\csname spx@#1@radius@topleft\endcsname\space}%
|
||||||
|
\expandafter
|
||||||
|
\spx@boxes@setradii
|
||||||
|
\spx@temp
|
||||||
|
{-\maxdimen}
|
||||||
|
\@nnil
|
||||||
|
\spx@boxes@radius@topleft@x\spx@boxes@radius@topleft@y
|
||||||
|
\edef\spx@temp{\csname spx@#1@radius@topright\endcsname\space}%
|
||||||
|
\expandafter
|
||||||
|
\spx@boxes@setradii
|
||||||
|
\spx@temp
|
||||||
|
{-\maxdimen}
|
||||||
|
\@nnil
|
||||||
|
\spx@boxes@radius@topright@x\spx@boxes@radius@topright@y
|
||||||
|
\edef\spx@temp{\csname spx@#1@radius@bottomright\endcsname\space}%
|
||||||
|
\expandafter
|
||||||
|
\spx@boxes@setradii
|
||||||
|
\spx@temp
|
||||||
|
{-\maxdimen}
|
||||||
|
\@nnil
|
||||||
|
\spx@boxes@radius@bottomright@x\spx@boxes@radius@bottomright@y
|
||||||
|
\edef\spx@temp{\csname spx@#1@radius@bottomleft\endcsname\space}%
|
||||||
|
\expandafter
|
||||||
|
\spx@boxes@setradii
|
||||||
|
\spx@temp
|
||||||
|
{-\maxdimen}
|
||||||
|
\@nnil
|
||||||
|
\spx@boxes@radius@bottomleft@x\spx@boxes@radius@bottomleft@y
|
||||||
|
%
|
||||||
|
\@nameuse{ifspx@#1@withshadow}%
|
||||||
|
\spx@boxes@withshadowtrue
|
||||||
|
\spx@boxes@shadow@xoffset \dimexpr\@nameuse{spx@#1@shadow@xoffset}\relax
|
||||||
|
\spx@boxes@shadow@yoffset \dimexpr\@nameuse{spx@#1@shadow@yoffset}\relax
|
||||||
|
\else
|
||||||
|
\spx@boxes@withshadowfalse
|
||||||
|
\fi
|
||||||
|
% not nesting in previous to avoid TeX conditional subtleties
|
||||||
|
\@nameuse{ifspx@#1@insetshadow}%
|
||||||
|
\spx@boxes@insetshadowtrue
|
||||||
|
\else
|
||||||
|
\spx@boxes@insetshadowfalse
|
||||||
|
\fi
|
||||||
|
%
|
||||||
|
\sphinxcolorlet{spx@boxes@bordercolor}{sphinx#1BorderColor}%
|
||||||
|
%
|
||||||
|
\sphinxcolorlet{spx@boxes@backgroundcolor}{sphinx#1BgColor}%
|
||||||
|
%
|
||||||
|
\@nameuse{ifspx@#1@withshadowcolor}%
|
||||||
|
\spx@boxes@withshadowcolortrue
|
||||||
|
\sphinxcolorlet{spx@boxes@shadowcolor}{sphinx#1ShadowColor}%
|
||||||
|
\else
|
||||||
|
\spx@boxes@withshadowcolorfalse
|
||||||
|
\fi
|
||||||
|
% Display elements pre, topic, warning et al. by default do not include
|
||||||
|
% shadow in box (legacy; and only topic actually uses a shadow per default)
|
||||||
|
% This may be refactored still more in future, but this 6.2.0 extra helped
|
||||||
|
% reduce workload from code-blocks (pre), contents (topic) and admonitions.
|
||||||
|
% As this conditional is a priori false and should only be changed locally
|
||||||
|
% (by \sphinxbox), this line is actually superfluous.
|
||||||
|
\spx@boxes@shadowinbboxfalse
|
||||||
|
\spx@boxes@fcolorbox@setup@fcolorbox
|
||||||
|
}
|
||||||
|
\@ifpackageloaded{pict2e}
|
||||||
|
{% pict2e is available and loaded
|
||||||
|
\def\spx@boxes@fcolorbox@setup@fcolorbox{%
|
||||||
|
\if1% use rounded boxes only if needed (rx>0 iff ry>0)
|
||||||
|
\ifdim\spx@boxes@radius@topleft@x >\z@0\fi
|
||||||
|
\ifdim\spx@boxes@radius@topright@x >\z@0\fi
|
||||||
|
\ifdim\spx@boxes@radius@bottomright@x>\z@0\fi
|
||||||
|
\ifdim\spx@boxes@radius@bottomleft@x >\z@0\fi
|
||||||
|
1\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}%
|
||||||
|
\else
|
||||||
|
\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rounded}%
|
||||||
|
\fi
|
||||||
|
}% end of definition of setup@fcolorbox in case of presence of pict2e
|
||||||
|
}%
|
||||||
|
{% pict2e could not be loaded, we must always use fcolorbox@rectangle
|
||||||
|
\def\spx@boxes@fcolorbox@setup@fcolorbox{%
|
||||||
|
\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}%
|
||||||
|
}% end of definition of setup@fcolorbox in case of absence of pict2e
|
||||||
|
}% end of "no pict2e" branch
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%
|
||||||
|
% Support of box-decoration-break=slice
|
||||||
|
%
|
||||||
|
% 6.2.0 has renamed and moved this here from sphinxlatexliterals.sty,
|
||||||
|
% to facilitate supporting box-decoration-break=slice for all directives,
|
||||||
|
% not only code-block.
|
||||||
|
%
|
||||||
|
% It also modified when these post actions are executed, in order
|
||||||
|
% for openboth to be able to trigger usage of fcolorbox@rectangle.
|
||||||
|
% So now openbottom and opentop also take advantage of this possible
|
||||||
|
% optimization.
|
||||||
|
\def\spx@boxes@fcolorbox@setup@openbottom{%
|
||||||
|
\spx@boxes@border@bottom \z@
|
||||||
|
\spx@boxes@radius@bottomright@x\z@ \spx@boxes@radius@bottomright@y\z@
|
||||||
|
\spx@boxes@radius@bottomleft@x \z@ \spx@boxes@radius@bottomleft@y \z@
|
||||||
|
\spx@boxes@fcolorbox@setup@fcolorbox
|
||||||
|
}%
|
||||||
|
\def\spx@boxes@fcolorbox@setup@opentop{%
|
||||||
|
\spx@boxes@border@top \z@
|
||||||
|
\spx@boxes@radius@topright@x\z@ \spx@boxes@radius@topright@y\z@
|
||||||
|
\spx@boxes@radius@topleft@x \z@ \spx@boxes@radius@topleft@y \z@
|
||||||
|
\spx@boxes@fcolorbox@setup@fcolorbox
|
||||||
|
}%
|
||||||
|
\def\spx@boxes@fcolorbox@setup@openboth{%
|
||||||
|
\spx@boxes@border@top \z@
|
||||||
|
\spx@boxes@border@bottom \z@
|
||||||
|
\spx@boxes@radius@bottomright@x\z@ \spx@boxes@radius@bottomright@y\z@
|
||||||
|
\spx@boxes@radius@bottomleft@x \z@ \spx@boxes@radius@bottomleft@y \z@
|
||||||
|
\spx@boxes@radius@topright@x\z@ \spx@boxes@radius@topright@y\z@
|
||||||
|
\spx@boxes@radius@topleft@x \z@ \spx@boxes@radius@topleft@y \z@
|
||||||
|
\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}%
|
||||||
|
}%
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%
|
||||||
|
% \sphinxbox (added at 6.2.0)
|
||||||
|
%
|
||||||
|
% For an inline box, possibly rounded.
|
||||||
|
\newcommand\sphinxbox[1][]{% #1 stands for the options, they are... optional!
|
||||||
|
% \leavevmode makes sure TeX switches to paragraph mode, which is necessary
|
||||||
|
% if this is first in a paragraph or a list element. The \sphinxAtStartPar
|
||||||
|
% mechanism also ensures this automatically, if not redefined, but not with
|
||||||
|
% lualatex as then it is by default doing nothing.
|
||||||
|
\leavevmode
|
||||||
|
\begingroup
|
||||||
|
\ifcsname spx@boxes@sphinxbox@isnested\endcsname
|
||||||
|
% nested boxes reset all box options to be as the \sphinxboxsetup
|
||||||
|
% defaults, before applying their specific options
|
||||||
|
\spx@boxes@sphinxbox@reset
|
||||||
|
\else
|
||||||
|
% top layer box, toggle the nested flag
|
||||||
|
\csname spx@boxes@sphinxbox@isnested\endcsname
|
||||||
|
\fi
|
||||||
|
% we do not use \sphinxboxsetup as it is a user command extending the
|
||||||
|
% "reset" storage
|
||||||
|
\setkeys{sphinxbox}{#1}%
|
||||||
|
\spx@boxes@fcolorbox@setup{box}%
|
||||||
|
\spx@boxes@shadowinbboxtrue% inline sphinx boxes include shadow in bbox
|
||||||
|
\ifspx@box@withtextcolor\color{sphinxboxTextColor}\fi
|
||||||
|
%
|
||||||
|
% MEMO: the fcolorbox@{rectangle,rounded} draw the contents (which here
|
||||||
|
% will be encapsulated as \box\z@) last, i.e. after shadow, background,
|
||||||
|
% and border and their color commands. The \reset@color from naked
|
||||||
|
% top-level \color commands in argument (which can not arise from Sphinx
|
||||||
|
% mark-up anyhow) would end up being placed via color.sty \aftergroup core
|
||||||
|
% mechanism in token stream after \spx@boxes@sphinxbox@a (which is the
|
||||||
|
% first \aftergroup) hence after the box contents with its unbalanced
|
||||||
|
% color pushes is shipped to PDF. So the missing color pop specials are
|
||||||
|
% inserted then in correct order at correct place (after the \endgroup at
|
||||||
|
% end of \spx@boxes@sphinxbox@a but this is not relevant) and do not end
|
||||||
|
% up causing havoc in push/pop pairs (and all this happens on same page).
|
||||||
|
%
|
||||||
|
% There is thus no reason here to go to the trouble to add an extra
|
||||||
|
% \color@begingroup/\color@endgroup or like pair to encapsulate the caught
|
||||||
|
% contents in order for the \box\z@ to contain as many color pop's as it
|
||||||
|
% has color pushes. But as this is subtle, this comment was added for
|
||||||
|
% future maintenance. Actually even if the contents were not drawn last,
|
||||||
|
% their (purely theoretical, as Sphinx mark-up can not create it) missing
|
||||||
|
% color pop's would not have caused trouble I guess as long as the color
|
||||||
|
% insertions for shadow, background, border are correctly balanced.
|
||||||
|
\setbox0\hbox\bgroup\aftergroup\spx@boxes@sphinxbox@a
|
||||||
|
\afterassignment\spx@box@TeXextras
|
||||||
|
\let\next=%
|
||||||
|
}
|
||||||
|
\def\spx@boxes@sphinxbox@a{\spx@boxes@fcolorbox{%
|
||||||
|
\ifspx@opt@box@addstrut\strut\fi\box\z@}\endgroup}
|
||||||
|
|
||||||
|
\newcommand\newsphinxbox[2][]{%
|
||||||
|
\newcommand#2[1][]{\sphinxbox[#1,##1]}%
|
||||||
|
}
|
||||||
|
% Let's catch \renewsphinxbox[...]{\sphinxbox} which would cause \sphinxbox
|
||||||
|
% to fall into infinite looping on use.
|
||||||
|
\newcommand\renewsphinxbox[2][]{%
|
||||||
|
\in@{#2}{\sphinxbox}%
|
||||||
|
\ifin@
|
||||||
|
\PackageWarning{sphinx}{Attempt to \string\renewsphinxbox\space
|
||||||
|
the \string\sphinxbox\space command\MessageBreak
|
||||||
|
itself. This is not allowed and will be ignored.\MessageBreak
|
||||||
|
Reported}%
|
||||||
|
\else
|
||||||
|
\renewcommand#2[1][]{\sphinxbox[#1,##1]}%
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%
|
||||||
|
% MACROS
|
||||||
|
%
|
||||||
|
% \spx@boxes@fcolorbox expands either to \spx@boxes@fcolorbox@rectangle
|
||||||
|
% or \spx@boxes@fcolorbox@rounded depending on preliminary set-up.
|
||||||
|
%
|
||||||
|
% This is decided by the "setup" which must have been executed by the caller.
|
||||||
|
% Let's give it some (thus unneeded) default fall-back for clarity.
|
||||||
|
\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}
|
||||||
|
%
|
||||||
|
% A macro \spx@boxes@fcolorbox@setuphook used to be executed at start of the
|
||||||
|
% \hbox constructs (rectangle or rounded). This was used until 6.2.0 for the
|
||||||
|
% support of pre_box-decoration-break option, hence was really an internal
|
||||||
|
% non-public macro. As it is not needed anymore, with some hesitation it got
|
||||||
|
% entirely removed at 6.2.0 on the occasion of a refactoring of interactions of
|
||||||
|
% this file with sphinxlatexliterals.sty. Besides its name should have been
|
||||||
|
% rather something such as \spx@boxes@fcolorbox@atstartofhbox.
|
||||||
|
%
|
||||||
|
% After "setup", \spx@boxes@fcolorbox expands to one of:
|
||||||
|
%
|
||||||
|
% - \spx@boxes@fcolorbox@rectangle (4 padding parameters, 4 border widths, 2 shadow widths,
|
||||||
|
% and three colours: background, border and shadow; same as in CSS styling)
|
||||||
|
%
|
||||||
|
% It branches to one of:
|
||||||
|
% - \spx@boxes@fcolorbox@externalshadow
|
||||||
|
% - \spx@boxes@fcolorbox@insetshadow (same concept of "inset" as in CSS styling)
|
||||||
|
%
|
||||||
|
% - \spx@boxes@fcolorbox@rounded: rounded corners using the picture environment
|
||||||
|
% and pict2e package for its low-weight interface to PDF graphics operations
|
||||||
|
|
||||||
|
% MEMO: we have also successfully tested usage of tcolorbox.sty (its \tcbox) but
|
||||||
|
% decided to use pict2e.sty for the following reasons:
|
||||||
|
% 1- PDF build was observed to be an order of magnitude faster,
|
||||||
|
% 2- the boxes we can do with pict2e appear to be fancy enough,
|
||||||
|
% almost matching what one can see in HTML renderings,
|
||||||
|
% 2- orders of magnitude smaller dependency (tcolorbox uses the pgf TeX
|
||||||
|
% framework), although on Ubuntu it seems texlive-pictures is
|
||||||
|
% needed which also contains the whole of pgf/TikZ... so this point
|
||||||
|
% is a bit moot...
|
||||||
|
|
||||||
|
% For code-blocks, attachments of caption and continuation hints are done
|
||||||
|
% exactly as prior to extension of Sphinx via this package, whether the box
|
||||||
|
% has straight or rounded corners. The vertical space occupied is the same,
|
||||||
|
% if nothing else is changed (perhaps in future the title itself could be also
|
||||||
|
% rendered in a rounded box?)
|
||||||
|
|
||||||
|
%%%%%%%%
|
||||||
|
%//// \spx@boxes@fcolorbox@rectangle
|
||||||
|
%
|
||||||
|
% This box will have the same baseline as its argument (which is typeset in
|
||||||
|
% horizontal mode). It takes into account four border widths parameters, four
|
||||||
|
% padding parameters, two shadow widths (each possibly negative), and three
|
||||||
|
% colors: background, border and shadow. Its boundary box takes into account
|
||||||
|
% border and padding. Width of shadow is taken into account if the boolean
|
||||||
|
% \ifspx@boxes@shadowinbbox is \iftrue. The "setup" sets it to \iffalse.
|
||||||
|
% Prior to 6.2.0, shadow size was included in bbox but the callers manually
|
||||||
|
% removed it by extra steps. The \sphinxbox command sets it to \iftrue after
|
||||||
|
% the "setup".
|
||||||
|
%
|
||||||
|
% It is up to the caller to take extra steps if the border and padding must go
|
||||||
|
% into margin as well (see sphinxlatexliterals.sty for how this is done in
|
||||||
|
% \spx@verb@FrameCommand).
|
||||||
|
%
|
||||||
|
% In usage as a "FrameCommand" with framed.sty, the argument will already be a
|
||||||
|
% collection of TeX boxes (and interline glues).
|
||||||
|
%
|
||||||
|
% This was designed so that the parameters configured by "setup" are
|
||||||
|
% interpreted as they would be as CSS properties in an HTML context.
|
||||||
|
\long\def\spx@boxes@fcolorbox@rectangle#1{%
|
||||||
|
\hbox\bgroup
|
||||||
|
\setbox\spx@tempboxa
|
||||||
|
\hbox{\kern\dimexpr\spx@boxes@border@left+\spx@boxes@padding@left\relax
|
||||||
|
{#1}%
|
||||||
|
\kern\dimexpr\spx@boxes@padding@right+\spx@boxes@border@right\relax}%
|
||||||
|
\ht\spx@tempboxa
|
||||||
|
\dimexpr\ht\spx@tempboxa+\spx@boxes@border@top+\spx@boxes@padding@top\relax
|
||||||
|
\dp\spx@tempboxa
|
||||||
|
\dimexpr\dp\spx@tempboxa+\spx@boxes@padding@bottom+\spx@boxes@border@bottom\relax
|
||||||
|
\ifspx@boxes@insetshadow
|
||||||
|
\expandafter\spx@boxes@fcolorbox@insetshadow
|
||||||
|
\else
|
||||||
|
\expandafter\spx@boxes@fcolorbox@externalshadow
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
|
||||||
|
% external shadow
|
||||||
|
\def\spx@boxes@fcolorbox@externalshadow{%
|
||||||
|
% reserve space to external shadow if on left
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\ifspx@boxes@shadowinbbox
|
||||||
|
\ifdim\spx@boxes@shadow@xoffset<\z@\kern-\spx@boxes@shadow@xoffset\fi
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
% BACKGROUND
|
||||||
|
% draw background and move back to reference point
|
||||||
|
{\color{spx@boxes@backgroundcolor}%
|
||||||
|
\vrule\@height\ht\spx@tempboxa
|
||||||
|
\@depth\dp\spx@tempboxa
|
||||||
|
\@width\wd\spx@tempboxa
|
||||||
|
\kern-\wd\spx@tempboxa
|
||||||
|
}%
|
||||||
|
% BOX SHADOW
|
||||||
|
% draw shadow and move back to reference point
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\vbox{%
|
||||||
|
\moveright\spx@boxes@shadow@xoffset
|
||||||
|
\hbox{\lower\spx@boxes@shadow@yoffset
|
||||||
|
\vbox{\ifspx@boxes@withshadowcolor
|
||||||
|
\color{spx@boxes@shadowcolor}%
|
||||||
|
\else
|
||||||
|
% 6.2.0: guard against a manually inserted \color command in
|
||||||
|
% contents which could leak at a page break to the shadow
|
||||||
|
\normalcolor
|
||||||
|
\fi
|
||||||
|
\ifdim\spx@boxes@shadow@yoffset<\z@
|
||||||
|
\hrule\@height-\spx@boxes@shadow@yoffset
|
||||||
|
\kern\spx@boxes@shadow@yoffset
|
||||||
|
\fi
|
||||||
|
\setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa{%
|
||||||
|
\ifdim\spx@boxes@shadow@xoffset<\z@\vrule\@width-\spx@boxes@shadow@xoffset\fi
|
||||||
|
\hss
|
||||||
|
\ifdim\spx@boxes@shadow@xoffset>\z@\vrule\@width\spx@boxes@shadow@xoffset\fi
|
||||||
|
}%
|
||||||
|
\ht\spx@tempboxb\ht\spx@tempboxa
|
||||||
|
\dp\spx@tempboxb\dp\spx@tempboxa
|
||||||
|
\box\spx@tempboxb
|
||||||
|
\ifdim\spx@boxes@shadow@yoffset>\z@
|
||||||
|
\kern-\spx@boxes@shadow@yoffset
|
||||||
|
\hrule\@height\spx@boxes@shadow@yoffset
|
||||||
|
\fi
|
||||||
|
\kern-\dp\spx@tempboxa
|
||||||
|
}% end of \vbox, attention it will have zero depth if yoffset>0
|
||||||
|
\kern-\wd\spx@tempboxa
|
||||||
|
\ifdim\spx@boxes@shadow@xoffset>\z@
|
||||||
|
\kern-\spx@boxes@shadow@xoffset
|
||||||
|
\fi
|
||||||
|
}% end of \hbox, attention its depth is only yoffset if yoffset>0
|
||||||
|
}% end of \vbox
|
||||||
|
\fi % end of shadow drawing, and we are back to horizontal reference point
|
||||||
|
% BOX BORDER
|
||||||
|
% 7.4.0 requires a set border color
|
||||||
|
\vbox{\color{spx@boxes@bordercolor}%
|
||||||
|
\hrule\@height\spx@boxes@border@top
|
||||||
|
\kern-\spx@boxes@border@top
|
||||||
|
\setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa
|
||||||
|
{\vrule\@width\spx@boxes@border@left
|
||||||
|
\hss\vrule\@width\spx@boxes@border@right
|
||||||
|
}%
|
||||||
|
\ht\spx@tempboxb\ht\spx@tempboxa
|
||||||
|
\dp\spx@tempboxb\dp\spx@tempboxa
|
||||||
|
\box\spx@tempboxb
|
||||||
|
\kern-\spx@boxes@border@bottom
|
||||||
|
\hrule\@height\spx@boxes@border@bottom
|
||||||
|
\kern-\dp\spx@tempboxa
|
||||||
|
}% attention this box has zero depth due to \hrule at bottom
|
||||||
|
% step back to horizontal reference point
|
||||||
|
\kern-\wd\spx@tempboxa
|
||||||
|
% end of border drawing
|
||||||
|
% CONTENTS
|
||||||
|
% adjust the total depth to include the bottom shadow
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\ifdim\spx@boxes@shadow@yoffset>\z@
|
||||||
|
\dp\spx@tempboxa\dimexpr\dp\spx@tempboxa+\spx@boxes@shadow@yoffset\relax
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\box\spx@tempboxa
|
||||||
|
% include lateral shadow in total width
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\ifspx@boxes@shadowinbbox
|
||||||
|
\ifdim\spx@boxes@shadow@xoffset>\z@\kern\spx@boxes@shadow@xoffset\fi
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\egroup
|
||||||
|
}
|
||||||
|
|
||||||
|
% inset shadow
|
||||||
|
%
|
||||||
|
% The parameters signs are interpreted as in CSS styling.
|
||||||
|
\def\spx@boxes@fcolorbox@insetshadow{%
|
||||||
|
% BACKGROUND
|
||||||
|
% draw background and move back to reference point
|
||||||
|
% 7.4.0 always assumes a background color
|
||||||
|
{\color{spx@boxes@backgroundcolor}%
|
||||||
|
\vrule\@height\ht\spx@tempboxa
|
||||||
|
\@depth\dp\spx@tempboxa
|
||||||
|
\@width\wd\spx@tempboxa
|
||||||
|
\kern-\wd\spx@tempboxa
|
||||||
|
}%
|
||||||
|
% BOX SHADOW
|
||||||
|
% draw shadow and move back to reference point
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\hbox{\vbox{\ifspx@boxes@withshadowcolor
|
||||||
|
\color{spx@boxes@shadowcolor}%
|
||||||
|
\else
|
||||||
|
% 6.2.0: guard against a manually inserted \color command in
|
||||||
|
% contents which could leak at a page break to the shadow
|
||||||
|
\normalcolor
|
||||||
|
\fi
|
||||||
|
% NOTA BENE
|
||||||
|
% We deliberately draw shadow partially under an area later covered by frame
|
||||||
|
% with the idea to avoid anti-aliasing problems but in fact this may be a bad
|
||||||
|
% idea with border is thin.
|
||||||
|
% This may need some extra testing with PDF viewers... reports welcome!
|
||||||
|
\ifdim\spx@boxes@shadow@yoffset>\z@
|
||||||
|
\hrule\@height\dimexpr\spx@boxes@border@top+\spx@boxes@shadow@yoffset\relax
|
||||||
|
\kern-\spx@boxes@shadow@yoffset
|
||||||
|
\kern-\spx@boxes@border@top
|
||||||
|
\fi
|
||||||
|
\setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa{%
|
||||||
|
\ifdim\spx@boxes@shadow@xoffset>\z@
|
||||||
|
\vrule\@width\dimexpr\spx@boxes@border@left+\spx@boxes@shadow@xoffset\relax\fi
|
||||||
|
\hss
|
||||||
|
\ifdim\spx@boxes@shadow@xoffset<\z@
|
||||||
|
\vrule\@width\dimexpr-\spx@boxes@shadow@xoffset+\spx@boxes@border@right\relax\fi
|
||||||
|
}%
|
||||||
|
\ht\spx@tempboxb\ht\spx@tempboxa
|
||||||
|
\dp\spx@tempboxb\dp\spx@tempboxa
|
||||||
|
\box\spx@tempboxb
|
||||||
|
\ifdim\spx@boxes@shadow@yoffset<\z@
|
||||||
|
\kern\spx@boxes@shadow@yoffset
|
||||||
|
\kern-\spx@boxes@border@bottom
|
||||||
|
\hrule\@height\dimexpr-\spx@boxes@shadow@yoffset+\spx@boxes@border@bottom\relax
|
||||||
|
\fi
|
||||||
|
\kern-\dp\spx@tempboxa
|
||||||
|
}% end of \vbox, attention it will have zero depth if yoffset<0
|
||||||
|
\kern-\wd\spx@tempboxa
|
||||||
|
}% end of \hbox, attention its depth is only |yoffset| if yoffset<0
|
||||||
|
\fi % end of inset shadow drawing, and we are back to horizontal reference point
|
||||||
|
% BOX BORDER
|
||||||
|
% 7.4.0 requires a set border color
|
||||||
|
\vbox{\color{spx@boxes@bordercolor}%
|
||||||
|
\hrule\@height\spx@boxes@border@top
|
||||||
|
\kern-\spx@boxes@border@top
|
||||||
|
\setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa
|
||||||
|
{\vrule\@width\spx@boxes@border@left
|
||||||
|
\hss\vrule\@width\spx@boxes@border@right
|
||||||
|
}%
|
||||||
|
\ht\spx@tempboxb\ht\spx@tempboxa
|
||||||
|
\dp\spx@tempboxb\dp\spx@tempboxa
|
||||||
|
\box\spx@tempboxb
|
||||||
|
\kern-\spx@boxes@border@bottom
|
||||||
|
\hrule\@height\spx@boxes@border@bottom
|
||||||
|
\kern-\dp\spx@tempboxa
|
||||||
|
}% attention this box has zero depth due to \hrule at bottom
|
||||||
|
% step back to horizontal reference point
|
||||||
|
\kern-\wd\spx@tempboxa
|
||||||
|
% end of border drawing
|
||||||
|
% CONTENTS
|
||||||
|
\box\spx@tempboxa
|
||||||
|
\egroup
|
||||||
|
}
|
||||||
|
|
||||||
|
% let's abort input if pict2e package could not be loaded.
|
||||||
|
% To be extra safe we also alias @rounded to @rectangle but
|
||||||
|
% a priori the architecture is done so that @rounded will never
|
||||||
|
% be called in that case by other Sphinx LaTeX components.
|
||||||
|
\@ifpackageloaded{pict2e}
|
||||||
|
{}
|
||||||
|
{\def\spx@boxes@fcolorbox@rounded{\spx@boxes@fcolorbox@rectangle}%
|
||||||
|
\endinput
|
||||||
|
}
|
||||||
|
|
||||||
|
% we proceed now in the context of pict2e being available and loaded
|
||||||
|
% (TeX being a macro-expansion based language it would have
|
||||||
|
% swallowed all the coming definitions even if pict2e
|
||||||
|
% had in fact not been loaded... but we aborted the input above)
|
||||||
|
%%%%%%%%
|
||||||
|
%//// \spx@boxes@fcolorbox@rounded
|
||||||
|
%
|
||||||
|
% Prior to 6.2.0, a constant border-width was applied as the border was
|
||||||
|
% obtained as a \strokepath. This allowed 4 distinct radii but not to vary the
|
||||||
|
% border widths. Now the border is drawn by two \fillpath operation, the first
|
||||||
|
% one filling up to external border, the second one actually filling for the
|
||||||
|
% background paradoxically on top of it, up to internal border path.
|
||||||
|
%
|
||||||
|
% This 6.2.0 abandonment of \strokepath allowed great simplification in
|
||||||
|
% supporting opentop, openbottom and openboth situations, and it can
|
||||||
|
% allow automatic support of openleft and openright analogs.
|
||||||
|
%
|
||||||
|
% And 6.2.0 also implements elliptical arcs thanks to ellipse package,
|
||||||
|
% which extends pict2e.
|
||||||
|
|
||||||
|
% Currently, inset shadow is not supported.
|
||||||
|
%
|
||||||
|
% Prior to 6.2.0 an inset shadow triggered the rectangle variant, so we never
|
||||||
|
% ended here, but now it is simply ignored. This change does not appear to me
|
||||||
|
% to be breaking, as it changes output only for conf.py's specifying both
|
||||||
|
% rounded corners and an inset shadow and the documentation said it was
|
||||||
|
% incompatible.
|
||||||
|
|
||||||
|
% wrappers for pict2e usage if old
|
||||||
|
% Better not to copy over 2020 pict2e definitions in case
|
||||||
|
% something internal changes
|
||||||
|
% However our wrappers will work ONLY with dimensional inputs
|
||||||
|
% No need to pre-expand the arguments
|
||||||
|
% Braces in case the expression uses parentheses
|
||||||
|
\def\spx@moveto(#1,#2){\moveto({\strip@pt\dimexpr#1\relax},{\strip@pt\dimexpr#2\relax})}
|
||||||
|
\def\spx@lineto(#1,#2){\lineto({\strip@pt\dimexpr#1\relax},{\strip@pt\dimexpr#2\relax})}
|
||||||
|
% attention here the [N] becomes mandatory
|
||||||
|
% \circlearc[<N>]{<X>}{<Y>}{<RAD>}{<ANGLE1>}{<ANGLE2>}
|
||||||
|
\def\spx@circlearc[#1]#2#3#4%#5#6
|
||||||
|
{\circlearc[#1]{\strip@pt\dimexpr#2\relax}%
|
||||||
|
{\strip@pt\dimexpr#3\relax}%
|
||||||
|
{\strip@pt\dimexpr#4\relax}%
|
||||||
|
}
|
||||||
|
% attention here too the [N] becomes mandatory
|
||||||
|
% the core path macro of ellipse.sty. Thanks to Daan Leijen, author of this
|
||||||
|
% package.
|
||||||
|
% \elliparc [<initial>]{<center-x>}{<center-y>}{<x-rad>}{<y-rad>}{<start-angle>}{<end-angle>}
|
||||||
|
% maybe this wrapper is unneeded but I don't have real time to check
|
||||||
|
\def\spx@elliparc[#1]#2#3#4#5%#6#7
|
||||||
|
{\elliparc[#1]{\strip@pt\dimexpr#2\relax}%
|
||||||
|
{\strip@pt\dimexpr#3\relax}%
|
||||||
|
{\strip@pt\dimexpr#4\relax}%
|
||||||
|
{\strip@pt\dimexpr#5\relax}%
|
||||||
|
}
|
||||||
|
|
||||||
|
% Macro whose execution prepares a path to be either stroked or filled
|
||||||
|
% Only fill operation is used at 6.2.0. The radii are given by the set box
|
||||||
|
% parameters, but the width and height are in \spx@width and \spx@height. A
|
||||||
|
% \put command will be used for appropriate shifts.
|
||||||
|
% 6.2.0 adds elliptical corners!
|
||||||
|
% But I feel perhaps I need to think about how x-radius and y-radius should
|
||||||
|
% interact with border-width. So consider output WIP for time being.
|
||||||
|
\def\spx@boxes@border@defpath{%
|
||||||
|
\spx@moveto(\spx@boxes@radius@bottomleft@x,\z@)% our \spx@moveto is a bit rigid
|
||||||
|
% and we must use \z@ not 0 here
|
||||||
|
\spx@lineto(\spx@width-\spx@boxes@radius@bottomright@x,\z@)%
|
||||||
|
% x and y radii are either both positive or both zero
|
||||||
|
% probably not needed to actually guard against the latter case,
|
||||||
|
% let's do it nevertheless
|
||||||
|
\ifdim\spx@boxes@radius@bottomright@x>\z@
|
||||||
|
\ifdim\spx@boxes@radius@bottomright@x=\spx@boxes@radius@bottomright@y
|
||||||
|
\spx@circlearc[2]{\spx@width-\spx@boxes@radius@bottomright@x}%
|
||||||
|
{\spx@boxes@radius@bottomright@y}%
|
||||||
|
{\spx@boxes@radius@bottomright@x}{-90}{0}%
|
||||||
|
\else
|
||||||
|
\spx@elliparc[2]{\spx@width-\spx@boxes@radius@bottomright@x}%
|
||||||
|
{\spx@boxes@radius@bottomright@y}%
|
||||||
|
{\spx@boxes@radius@bottomright@x}
|
||||||
|
{\spx@boxes@radius@bottomright@y}{-90}{0}%
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\spx@lineto(\spx@width,%
|
||||||
|
\spx@height-\spx@boxes@radius@topright@y)%
|
||||||
|
\ifdim\spx@boxes@radius@topright@x>\z@
|
||||||
|
\ifdim\spx@boxes@radius@topright@x=\spx@boxes@radius@topright@y
|
||||||
|
\spx@circlearc[2]{\spx@width-\spx@boxes@radius@topright@x}
|
||||||
|
{\spx@height-\spx@boxes@radius@topright@y}%
|
||||||
|
{\spx@boxes@radius@topright@x}{0}{90}%
|
||||||
|
\else
|
||||||
|
\spx@elliparc[2]{\spx@width-\spx@boxes@radius@topright@x}
|
||||||
|
{\spx@height-\spx@boxes@radius@topright@y}%
|
||||||
|
{\spx@boxes@radius@topright@x}%
|
||||||
|
{\spx@boxes@radius@topright@y}{0}{90}%
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\spx@lineto(\spx@boxes@radius@topleft@x,\spx@height)%
|
||||||
|
\ifdim\spx@boxes@radius@topleft@x>\z@
|
||||||
|
\ifdim\spx@boxes@radius@topleft@x=\spx@boxes@radius@topleft@y
|
||||||
|
\spx@circlearc[2]{\spx@boxes@radius@topleft@x}%
|
||||||
|
{\spx@height-\spx@boxes@radius@topleft@y}%
|
||||||
|
{\spx@boxes@radius@topleft@x}{90}{180}%
|
||||||
|
\else
|
||||||
|
\spx@elliparc[2]{\spx@boxes@radius@topleft@x}%
|
||||||
|
{\spx@height-\spx@boxes@radius@topleft@y}%
|
||||||
|
{\spx@boxes@radius@topleft@x}%
|
||||||
|
{\spx@boxes@radius@topleft@y}{90}{180}%
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\spx@lineto(\z@,\spx@boxes@radius@bottomleft@y)%
|
||||||
|
\ifdim\spx@boxes@radius@bottomleft@x>\z@
|
||||||
|
\ifdim\spx@boxes@radius@bottomleft@x=\spx@boxes@radius@bottomleft@y
|
||||||
|
\spx@circlearc[2]{\spx@boxes@radius@bottomleft@x}%
|
||||||
|
{\spx@boxes@radius@bottomleft@y}%
|
||||||
|
{\spx@boxes@radius@bottomleft@x}{180}{270}%
|
||||||
|
\else
|
||||||
|
\spx@elliparc[2]{\spx@boxes@radius@bottomleft@x}%
|
||||||
|
{\spx@boxes@radius@bottomleft@y}%
|
||||||
|
{\spx@boxes@radius@bottomleft@x}%
|
||||||
|
{\spx@boxes@radius@bottomleft@y}{180}{270}%
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
}% end of definition of \spx@boxes@border@defpath
|
||||||
|
|
||||||
|
% The customization of the various parameters must have been done via an
|
||||||
|
% appropriate call to \spx@boxes@fcolorbox@setup, which will have set up
|
||||||
|
% \spx@boxes@fcolorbox to expand to \spx@boxes@fcolorbox@rounded, and will
|
||||||
|
% have set its various parameters.
|
||||||
|
%
|
||||||
|
\long\def\spx@boxes@fcolorbox@rounded #1{%
|
||||||
|
\hbox{%
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\ifspx@boxes@insetshadow
|
||||||
|
\spx@boxes@withshadowfalse % ignore inset shadow
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
% reserve space to external shadow if on left
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\ifspx@boxes@shadowinbbox
|
||||||
|
\ifdim\spx@boxes@shadow@xoffset<\z@\kern-\spx@boxes@shadow@xoffset\fi
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\vbox{%
|
||||||
|
% adjust vertical bbox
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\ifdim\spx@boxes@shadow@yoffset<\z@
|
||||||
|
\kern-\spx@boxes@shadow@yoffset
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\setlength{\unitlength}{1pt}%
|
||||||
|
\setbox\spx@tempboxa
|
||||||
|
\hbox{\kern\dimexpr\spx@boxes@border@left+\spx@boxes@padding@left\relax
|
||||||
|
{#1}%
|
||||||
|
\kern\dimexpr\spx@boxes@padding@right+\spx@boxes@border@right\relax}%
|
||||||
|
\ht\spx@tempboxa
|
||||||
|
\dimexpr\ht\spx@tempboxa+\spx@boxes@border@top+\spx@boxes@padding@top\relax
|
||||||
|
\dp\spx@tempboxa
|
||||||
|
\dimexpr\dp\spx@tempboxa+\spx@boxes@padding@bottom+\spx@boxes@border@bottom\relax
|
||||||
|
\edef\spx@width{\number\wd\spx@tempboxa sp}%
|
||||||
|
\edef\spx@height{\number\dimexpr\ht\spx@tempboxa+\dp\spx@tempboxa sp}%
|
||||||
|
\hbox{%
|
||||||
|
\begin{picture}%
|
||||||
|
% \strip@pt\dimexpr to work around "old" LaTeX picture limitation
|
||||||
|
% (we could use the "picture" package, this would add another dependency)
|
||||||
|
(\strip@pt\dimexpr\spx@width\relax,\strip@pt\dimexpr\spx@height\relax)%
|
||||||
|
\spx@boxes@border@defpath
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\ifspx@boxes@withshadowcolor
|
||||||
|
\color{spx@boxes@shadowcolor}%
|
||||||
|
\else
|
||||||
|
% 6.2.0: here and elsewhere guard against a manually inserted
|
||||||
|
% \color command in contents which could leak to the shadow
|
||||||
|
% to the shadow
|
||||||
|
\normalcolor
|
||||||
|
\fi
|
||||||
|
\put(\strip@pt\spx@boxes@shadow@xoffset,%
|
||||||
|
\strip@pt\dimexpr-\spx@boxes@shadow@yoffset\relax)
|
||||||
|
{\fillpath}%
|
||||||
|
\fi
|
||||||
|
\spx@boxes@border@defpath% must be redone after each \fillpath! (even if
|
||||||
|
% was in a \put)
|
||||||
|
% 7.4.0 requires a set border color
|
||||||
|
\color{spx@boxes@bordercolor}%
|
||||||
|
\fillpath
|
||||||
|
% and backgroundcolor command
|
||||||
|
\color{spx@boxes@backgroundcolor}%
|
||||||
|
\edef\spx@width{\number\dimexpr\spx@width-\spx@boxes@border@left
|
||||||
|
-\spx@boxes@border@right sp}%
|
||||||
|
\edef\spx@height{\number\dimexpr\spx@height-\spx@boxes@border@top
|
||||||
|
-\spx@boxes@border@bottom sp}%
|
||||||
|
% redefine a path (in relative coordinates) matching the area delimited
|
||||||
|
% by the internal borders
|
||||||
|
\spx@boxes@border@defpath
|
||||||
|
% use \put to shift, and fill it with background color
|
||||||
|
\put(\strip@pt\spx@boxes@border@left,\strip@pt\spx@boxes@border@bottom)
|
||||||
|
{\fillpath}%
|
||||||
|
\end{picture}}% end of picture \hbox in \vbox
|
||||||
|
% back-up vertically for outputting the contents
|
||||||
|
\kern-\dimexpr\ht\spx@tempboxa+\dp\spx@tempboxa\relax
|
||||||
|
% adjust vertical bbox
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\ifdim\spx@boxes@shadow@yoffset>\z@
|
||||||
|
\dp\spx@tempboxa\dimexpr\dp\spx@tempboxa+\spx@boxes@shadow@yoffset\relax
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
% inhibit TeX's "line skip" adjustment when piling up hboxes in a vbox
|
||||||
|
\nointerlineskip
|
||||||
|
\box\spx@tempboxa
|
||||||
|
}% end of \vbox
|
||||||
|
% include lateral shadow in total width
|
||||||
|
\ifspx@boxes@withshadow
|
||||||
|
\ifspx@boxes@shadowinbbox
|
||||||
|
\ifdim\spx@boxes@shadow@xoffset>\z@\kern\spx@boxes@shadow@xoffset\fi
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
}% end of \hbox
|
||||||
|
}%
|
||||||
|
|
||||||
|
|
||||||
|
\endinput
|
||||||
55
build/latex/sphinxpackagecyrillic.sty
Normal file
55
build/latex/sphinxpackagecyrillic.sty
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
%% CYRILLIC IN NON-CYRILLIC DOCUMENTS (pdflatex only)
|
||||||
|
%
|
||||||
|
% refs: https://tex.stackexchange.com/q/460271/
|
||||||
|
\ProvidesPackage{sphinxpackagecyrillic}%
|
||||||
|
[2018/11/21 v2.0 support for Cyrillic in non-Cyrillic documents]
|
||||||
|
\RequirePackage{kvoptions}
|
||||||
|
\SetupKeyvalOptions{prefix=spx@cyropt@} % use \spx@cyropt@ prefix
|
||||||
|
\DeclareBoolOption[false]{Xtwo}
|
||||||
|
\DeclareBoolOption[false]{TtwoA}
|
||||||
|
\DeclareDefaultOption{\@unknownoptionerror}
|
||||||
|
\ProcessLocalKeyvalOptions* % ignore class options
|
||||||
|
|
||||||
|
\ifspx@cyropt@Xtwo
|
||||||
|
% original code by tex.sx user egreg (updated 2019/10/28):
|
||||||
|
% https://tex.stackexchange.com/a/460325/
|
||||||
|
% 159 Cyrillic glyphs as available in X2 TeX 8bit font encoding
|
||||||
|
% This assumes inputenc loaded with utf8 option, or LaTeX release
|
||||||
|
% as recent as 2018/04/01 which does it automatically.
|
||||||
|
\@tfor\next:=%
|
||||||
|
{Ё}{Ђ}{Є}{Ѕ}{І}{Ј}{Љ}{Њ}{Ћ}{Ў}{Џ}{А}{Б}{В}{Г}{Д}{Е}{Ж}{З}{И}{Й}%
|
||||||
|
{К}{Л}{М}{Н}{О}{П}{Р}{С}{Т}{У}{Ф}{Х}{Ц}{Ч}{Ш}{Щ}{Ъ}{Ы}{Ь}{Э}{Ю}%
|
||||||
|
{Я}{а}{б}{в}{г}{д}{е}{ж}{з}{и}{й}{к}{л}{м}{н}{о}{п}{р}{с}{т}{у}%
|
||||||
|
{ф}{х}{ц}{ч}{ш}{щ}{ъ}{ы}{ь}{э}{ю}{я}{ё}{ђ}{є}{ѕ}{і}{ј}{љ}{њ}{ћ}%
|
||||||
|
{ў}{џ}{Ѣ}{ѣ}{Ѫ}{ѫ}{Ѵ}{ѵ}{Ґ}{ґ}{Ғ}{ғ}{Ҕ}{ҕ}{Җ}{җ}{Ҙ}{ҙ}{Қ}{қ}{Ҝ}{ҝ}%
|
||||||
|
{Ҟ}{ҟ}{Ҡ}{ҡ}{Ң}{ң}{Ҥ}{ҥ}{Ҧ}{ҧ}{Ҩ}{ҩ}{Ҫ}{ҫ}{Ҭ}{ҭ}{Ү}{ү}{Ұ}{ұ}{Ҳ}{ҳ}%
|
||||||
|
{Ҵ}{ҵ}{Ҷ}{ҷ}{Ҹ}{ҹ}{Һ}{һ}{Ҽ}{ҽ}{Ҿ}{ҿ}{Ӏ}{Ӄ}{ӄ}{Ӆ}{ӆ}{Ӈ}{ӈ}{Ӌ}{ӌ}%
|
||||||
|
{Ӎ}{ӎ}{Ӕ}{ӕ}{Ә}{ә}{Ӡ}{ӡ}{Ө}{ө}\do
|
||||||
|
{%
|
||||||
|
\begingroup\def\IeC{\protect\DeclareTextSymbolDefault}%
|
||||||
|
\protected@edef\@temp{\endgroup
|
||||||
|
\@ifl@t@r{\fmtversion}{2019/10/01}{\csname u8:\next\endcsname}{\next}}%
|
||||||
|
\@temp{X2}%
|
||||||
|
}%
|
||||||
|
\else
|
||||||
|
\ifspx@cyropt@TtwoA
|
||||||
|
% original code by tex.sx user jfbu:
|
||||||
|
% https://tex.stackexchange.com/a/460305/
|
||||||
|
% 63*2+1=127 Cyrillic glyphs as found in T2A 8bit TeX font-encoding
|
||||||
|
\@tfor\@tempa:=%
|
||||||
|
{ae}{a}{b}{chrdsc}{chvcrs}{ch}{c}{dje}{dze}{dzhe}{d}{erev}{ery}{e}%
|
||||||
|
{f}{ghcrs}{gup}{g}{hdsc}{hrdsn}{h}{ie}{ii}{ishrt}{i}{je}%
|
||||||
|
{kbeak}{kdsc}{kvcrs}{k}{lje}{l}{m}{ndsc}{ng}{nje}{n}{otld}{o}{p}{r}%
|
||||||
|
{schwa}{sdsc}{sftsn}{shch}{shha}{sh}{s}{tshe}{t}{ushrt}{u}{v}%
|
||||||
|
{ya}{yhcrs}{yi}{yo}{yu}{y}{zdsc}{zhdsc}{zh}{z}\do
|
||||||
|
{%
|
||||||
|
\expandafter\DeclareTextSymbolDefault\expandafter
|
||||||
|
{\csname cyr\@tempa\endcsname}{T2A}%
|
||||||
|
\expandafter\uppercase\expandafter{\expandafter
|
||||||
|
\def\expandafter\@tempa\expandafter{\@tempa}}%
|
||||||
|
\expandafter\DeclareTextSymbolDefault\expandafter
|
||||||
|
{\csname CYR\@tempa\endcsname}{T2A}%
|
||||||
|
}%
|
||||||
|
\DeclareTextSymbolDefault{\CYRpalochka}{T2A}%
|
||||||
|
\fi\fi
|
||||||
|
\endinput
|
||||||
439
build/latex/sphinxpackagefootnote.sty
Normal file
439
build/latex/sphinxpackagefootnote.sty
Normal file
|
|
@ -0,0 +1,439 @@
|
||||||
|
\NeedsTeXFormat{LaTeX2e}
|
||||||
|
\ProvidesPackage{sphinxpackagefootnote}%
|
||||||
|
[2025/11/15 v9.0.0 Sphinx custom footnotehyper package (Sphinx team)]
|
||||||
|
%%
|
||||||
|
%% Package: sphinxpackagefootnote
|
||||||
|
%% Version: based on footnotehyper.sty 2021/02/04 v1.1d
|
||||||
|
%% https://www.ctan.org/pkg/footnotehyper
|
||||||
|
%% License: the one applying to Sphinx
|
||||||
|
%%
|
||||||
|
% Provides support for footnote mark-up from Sphinx latex writer:
|
||||||
|
% - "footnote" and "footnotetext" environments allowing verbatim material
|
||||||
|
% - "savenotes" environment for wrapping environments, such as for tables
|
||||||
|
% which have problems with LaTeX footnotes
|
||||||
|
% - hyperlinks
|
||||||
|
%
|
||||||
|
% Sphinx uses exclusively this mark-up for footnotes:
|
||||||
|
% - \begin{footnote}[N]
|
||||||
|
% - \begin{footnotetext}[N]
|
||||||
|
% - \sphinxfootnotemark[N]
|
||||||
|
% where N is a number.
|
||||||
|
%
|
||||||
|
%% Some small differences from footnotehyper.sty 2021/02/04 v1.1d:
|
||||||
|
%% - a tabulary compatibility layer (partial but enough for Sphinx),
|
||||||
|
%% - usage of \spx@opt@BeforeFootnote
|
||||||
|
%% - usage of \sphinxunactivateextrasandspace from sphinx.sty,
|
||||||
|
%% - \sphinxlongtablepatch
|
||||||
|
%% - fix for a change of babel-french from late June 2025
|
||||||
|
%% (\localleftbox undefined with pdflatex/xelatex, issue #14059)
|
||||||
|
%%
|
||||||
|
%% Starting with Sphinx v4.5.0, inherited footnotehyper macros for
|
||||||
|
%% footnote/footnotetext receive some Sphinx specific extras to
|
||||||
|
%% implement "intelligent" footnote marks checking page numbers.
|
||||||
|
%%
|
||||||
|
%% All footnotes output from Sphinx are hyperlinked. With "savenotes"
|
||||||
|
%% footnotes may appear on page distinct from footnote mark, the latter
|
||||||
|
%% will indicate page number of the footnote.
|
||||||
|
\newif\iffootnotehyperparse\footnotehyperparsetrue
|
||||||
|
\DeclareOption*{\PackageWarning{sphinxpackagefootnote}{Option `\CurrentOption' is unknown}}%
|
||||||
|
\ProcessOptions\relax
|
||||||
|
\newbox\FNH@notes
|
||||||
|
\newtoks\FNH@toks % 1.1c
|
||||||
|
\newdimen\FNH@width
|
||||||
|
\let\FNH@colwidth\columnwidth
|
||||||
|
\newif\ifFNH@savingnotes
|
||||||
|
\AtBeginDocument {%
|
||||||
|
\let\FNH@latex@footnote \footnote
|
||||||
|
\let\FNH@latex@footnotetext\footnotetext
|
||||||
|
\let\FNH@H@@footnotetext \@footnotetext
|
||||||
|
\let\FNH@H@@mpfootnotetext \@mpfootnotetext
|
||||||
|
\newenvironment{savenotes}
|
||||||
|
{\FNH@savenotes\ignorespaces}{\FNH@spewnotes\ignorespacesafterend}%
|
||||||
|
\let\spewnotes \FNH@spewnotes
|
||||||
|
\let\footnote \FNH@footnote
|
||||||
|
\let\footnotetext \FNH@footnotetext
|
||||||
|
\let\endfootnote \FNH@endfntext
|
||||||
|
\let\endfootnotetext\FNH@endfntext
|
||||||
|
% always True branch taken with Sphinx
|
||||||
|
\@ifpackageloaded{hyperref}
|
||||||
|
{\ifHy@hyperfootnotes
|
||||||
|
\let\FNH@H@@footnotetext\H@@footnotetext
|
||||||
|
\let\FNH@H@@mpfootnotetext\H@@mpfootnotetext
|
||||||
|
\else
|
||||||
|
\let\FNH@hyper@fntext\FNH@nohyp@fntext
|
||||||
|
\fi}%
|
||||||
|
{\let\FNH@hyper@fntext\FNH@nohyp@fntext}%
|
||||||
|
}%
|
||||||
|
\def\FNH@hyper@fntext{\FNH@fntext\FNH@hyper@fntext@i}%
|
||||||
|
\def\FNH@nohyp@fntext{\FNH@fntext\FNH@nohyp@fntext@i}%
|
||||||
|
\def\FNH@fntext #1{%
|
||||||
|
\ifx\ifmeasuring@\@undefined
|
||||||
|
\expandafter\@secondoftwo\else\expandafter\@firstofone\fi
|
||||||
|
% these two lines modified for Sphinx (tabulary compatibility):
|
||||||
|
{\ifmeasuring@\expandafter\@gobbletwo\else\expandafter\@firstofone\fi}%
|
||||||
|
{\ifx\equation$\expandafter\@gobbletwo\fi #1}%$
|
||||||
|
}%
|
||||||
|
\long\def\FNH@hyper@fntext@i#1{%
|
||||||
|
\global\setbox\FNH@notes\vbox
|
||||||
|
{\unvbox\FNH@notes
|
||||||
|
\FNH@startnote
|
||||||
|
\@makefntext
|
||||||
|
{\rule\z@\footnotesep\ignorespaces
|
||||||
|
\ifHy@nesting\expandafter\ltx@firstoftwo
|
||||||
|
\else\expandafter\ltx@secondoftwo
|
||||||
|
\fi
|
||||||
|
{\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}{#1}}%
|
||||||
|
{\Hy@raisedlink
|
||||||
|
{\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}%
|
||||||
|
{\relax}}%
|
||||||
|
\let\@currentHref\Hy@footnote@currentHref
|
||||||
|
\let\@currentlabelname\@empty
|
||||||
|
#1}%
|
||||||
|
\@finalstrut\strutbox
|
||||||
|
}%
|
||||||
|
\FNH@endnote
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
\long\def\FNH@nohyp@fntext@i#1{%
|
||||||
|
\global\setbox\FNH@notes\vbox
|
||||||
|
{\unvbox\FNH@notes
|
||||||
|
\FNH@startnote
|
||||||
|
\@makefntext{\rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
|
||||||
|
\FNH@endnote
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
\def\FNH@startnote{%
|
||||||
|
\hsize\FNH@colwidth
|
||||||
|
\interlinepenalty\interfootnotelinepenalty
|
||||||
|
\reset@font\footnotesize
|
||||||
|
\floatingpenalty\@MM
|
||||||
|
\@parboxrestore
|
||||||
|
\protected@edef\@currentlabel{\csname p@\@mpfn\endcsname\@thefnmark}%
|
||||||
|
\color@begingroup
|
||||||
|
}%
|
||||||
|
\def\FNH@endnote{\color@endgroup}%
|
||||||
|
\def\FNH@savenotes{%
|
||||||
|
\begingroup
|
||||||
|
\ifFNH@savingnotes\else
|
||||||
|
\FNH@savingnotestrue
|
||||||
|
\let\@footnotetext \FNH@hyper@fntext
|
||||||
|
\let\@mpfootnotetext \FNH@hyper@fntext
|
||||||
|
\let\H@@mpfootnotetext\FNH@nohyp@fntext
|
||||||
|
\FNH@width\columnwidth
|
||||||
|
\let\FNH@colwidth\FNH@width
|
||||||
|
\global\setbox\FNH@notes\box\voidb@x
|
||||||
|
\let\FNH@thempfn\thempfn
|
||||||
|
\let\FNH@mpfn\@mpfn
|
||||||
|
\ifx\@minipagerestore\relax\let\@minipagerestore\@empty\fi
|
||||||
|
\expandafter\def\expandafter\@minipagerestore\expandafter{%
|
||||||
|
\@minipagerestore
|
||||||
|
\let\thempfn\FNH@thempfn
|
||||||
|
\let\@mpfn\FNH@mpfn
|
||||||
|
}%
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\def\FNH@spewnotes {%
|
||||||
|
\if@endpe\ifx\par\@@par\FNH@toks{}\else
|
||||||
|
\FNH@toks\expandafter{\expandafter
|
||||||
|
\def\expandafter\par\expandafter{\par}\@endpetrue}%
|
||||||
|
\expandafter\expandafter\expandafter
|
||||||
|
\FNH@toks
|
||||||
|
\expandafter\expandafter\expandafter
|
||||||
|
{\expandafter\the\expandafter\FNH@toks
|
||||||
|
\expandafter\def\expandafter\@par\expandafter{\@par}}%
|
||||||
|
\expandafter\expandafter\expandafter
|
||||||
|
\FNH@toks
|
||||||
|
\expandafter\expandafter\expandafter
|
||||||
|
{\expandafter\the\expandafter\FNH@toks
|
||||||
|
\expandafter\everypar\expandafter{\the\everypar}}\fi
|
||||||
|
\else\FNH@toks{}\fi
|
||||||
|
\expandafter
|
||||||
|
\endgroup\the\FNH@toks
|
||||||
|
\ifFNH@savingnotes\else
|
||||||
|
\ifvoid\FNH@notes\else
|
||||||
|
\begingroup
|
||||||
|
\let\@makefntext\@empty
|
||||||
|
\let\@finalstrut\@gobble
|
||||||
|
\let\rule\@gobbletwo
|
||||||
|
\ifx\@footnotetext\@mpfootnotetext
|
||||||
|
\expandafter\FNH@H@@mpfootnotetext
|
||||||
|
\else
|
||||||
|
\expandafter\FNH@H@@footnotetext
|
||||||
|
\fi{\unvbox\FNH@notes}%
|
||||||
|
\endgroup
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\def\FNH@footnote@envname {footnote}%
|
||||||
|
\def\FNH@footnotetext@envname{footnotetext}%
|
||||||
|
\def\FNH@footnote{%
|
||||||
|
% this line added for Sphinx:
|
||||||
|
\spx@opt@BeforeFootnote
|
||||||
|
\ifx\@currenvir\FNH@footnote@envname
|
||||||
|
\expandafter\FNH@footnoteenv
|
||||||
|
\else
|
||||||
|
\expandafter\FNH@latex@footnote
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\def\FNH@footnoteenv{%
|
||||||
|
% this line added for Sphinx (footnotes in parsed literal blocks):
|
||||||
|
\catcode13=5 \sphinxunactivateextrasandspace
|
||||||
|
\@ifnextchar[%
|
||||||
|
\FNH@footnoteenv@i %]
|
||||||
|
{\stepcounter\@mpfn
|
||||||
|
\protected@xdef\@thefnmark{\thempfn}%
|
||||||
|
\@footnotemark
|
||||||
|
\def\FNH@endfntext@fntext{\@footnotetext}%
|
||||||
|
\FNH@startfntext}%
|
||||||
|
}%
|
||||||
|
\def\FNH@footnoteenv@i[#1]{%
|
||||||
|
\begingroup
|
||||||
|
% This legacy code from LaTeX core restricts #1 to be digits only
|
||||||
|
% This limitation could be lifted but legacy Sphinx anyhow obeys it
|
||||||
|
\csname c@\@mpfn\endcsname #1\relax
|
||||||
|
\unrestored@protected@xdef\@thefnmark{\thempfn}%
|
||||||
|
\endgroup
|
||||||
|
% -- Sphinx specific:
|
||||||
|
% currently commented out due to
|
||||||
|
% https://github.com/sphinx-doc/sphinx/pull/10191#issuecomment-1038807448
|
||||||
|
% Memo: memoir class detection of successive footnote marks (to separate them
|
||||||
|
% by commas) is broken by \refstepcounter and also by \label, and some
|
||||||
|
% mitigation such as in \sphinxfootref would be needed
|
||||||
|
% \global\let\spx@saved@thefnmark\@thefnmark
|
||||||
|
% % this is done to access robustly the page number where footnote mark is
|
||||||
|
% \refstepcounter{sphinxfootnotemark}\label{footnotemark.\thesphinxfootnotemark}%
|
||||||
|
% % if possible, compare page numbers of mark and footnote to define \@thefnmark
|
||||||
|
% \ltx@ifundefined{r@\thesphinxscope.footnote.#1}%
|
||||||
|
% {}% one more latex run is needed
|
||||||
|
% {\sphinx@xdef@thefnmark{#1}}% check of page numbers possible
|
||||||
|
% --
|
||||||
|
\@footnotemark
|
||||||
|
\def\FNH@endfntext@fntext{\@footnotetext}%
|
||||||
|
% -- Sphinx specific:
|
||||||
|
% we need to reset \@thefnmark as it is used by \FNH@startfntext via
|
||||||
|
% \FNH@startnote to set \@currentlabel which will be used by \label
|
||||||
|
% currently commented out (see above)
|
||||||
|
% \global\let\@thefnmark\spx@saved@thefnmark
|
||||||
|
% --
|
||||||
|
\FNH@startfntext
|
||||||
|
% -- again Sphinx specific
|
||||||
|
% \@currentlabel as needed by \label got set by \FNH@startnote
|
||||||
|
% insert this at start of footnote text then the label will allow
|
||||||
|
% to robustly know on which page the footnote text ends up
|
||||||
|
% currently only of use for extra footnote marks so in case footnote multiply referred
|
||||||
|
\phantomsection\label{\thesphinxscope.footnote.#1}%
|
||||||
|
}%
|
||||||
|
\def\FNH@footnotetext{%
|
||||||
|
\ifx\@currenvir\FNH@footnotetext@envname
|
||||||
|
\expandafter\FNH@footnotetextenv
|
||||||
|
\else
|
||||||
|
\expandafter\FNH@latex@footnotetext
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\def\FNH@footnotetextenv{%
|
||||||
|
\@ifnextchar[%
|
||||||
|
\FNH@footnotetextenv@i %]
|
||||||
|
{\protected@xdef\@thefnmark{\thempfn}%
|
||||||
|
\def\FNH@endfntext@fntext{\@footnotetext}%
|
||||||
|
\FNH@startfntext}%
|
||||||
|
}%
|
||||||
|
\def\FNH@footnotetextenv@i[#1]{%
|
||||||
|
\begingroup
|
||||||
|
\csname c@\@mpfn\endcsname #1\relax
|
||||||
|
\unrestored@protected@xdef\@thefnmark{\thempfn}%
|
||||||
|
\endgroup
|
||||||
|
\ifFNH@savingnotes
|
||||||
|
\def\FNH@endfntext@fntext{\FNH@nohyp@fntext}%
|
||||||
|
\else
|
||||||
|
\def\FNH@endfntext@fntext{\FNH@H@@footnotetext}%
|
||||||
|
\fi
|
||||||
|
\FNH@startfntext
|
||||||
|
% -- Sphinx specific addition
|
||||||
|
\phantomsection\label{\thesphinxscope.footnote.#1}%
|
||||||
|
}%
|
||||||
|
\def\FNH@startfntext{%
|
||||||
|
\setbox\z@\vbox\bgroup
|
||||||
|
\FNH@startnote
|
||||||
|
\FNH@prefntext
|
||||||
|
\rule\z@\footnotesep\ignorespaces
|
||||||
|
}%
|
||||||
|
\def\FNH@endfntext {%
|
||||||
|
\@finalstrut\strutbox
|
||||||
|
\FNH@postfntext
|
||||||
|
\FNH@endnote
|
||||||
|
\egroup
|
||||||
|
\begingroup
|
||||||
|
\let\@makefntext\@empty\let\@finalstrut\@gobble\let\rule\@gobbletwo
|
||||||
|
\FNH@endfntext@fntext {\unvbox\z@}%
|
||||||
|
\endgroup
|
||||||
|
}%
|
||||||
|
\let\FNH@prefntext\@empty
|
||||||
|
\let\FNH@postfntext\@empty
|
||||||
|
\AtBeginDocument{\iffootnotehyperparse\expandafter\FNH@check\fi}%
|
||||||
|
\def\FNH@safeif#1{%
|
||||||
|
\iftrue\csname if#1\endcsname\csname fi\endcsname\expandafter\@firstoftwo
|
||||||
|
\else\csname fi\endcsname\expandafter\@secondoftwo
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\def\FNH@check{%
|
||||||
|
\ifx\@makefntextFB\@undefined
|
||||||
|
\expandafter\FNH@check@
|
||||||
|
\else
|
||||||
|
\providecommand\localleftbox[1]{}%
|
||||||
|
\expandafter\FNH@frenchb@
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\def\FNH@frenchb@{%
|
||||||
|
\def\FNH@prefntext{%
|
||||||
|
\localleftbox{}%
|
||||||
|
\let\FBeverypar@save\FBeverypar@quote
|
||||||
|
\let\FBeverypar@quote\relax
|
||||||
|
\FNH@safeif{FB@koma}%
|
||||||
|
{\FNH@safeif{FBFrenchFootnotes}%
|
||||||
|
{\ifx\footnote\thanks
|
||||||
|
\let\@@makefnmark\@@makefnmarkTH
|
||||||
|
\@makefntextTH{} % space as in french.ldf
|
||||||
|
\else
|
||||||
|
\let\@@makefnmark\@@makefnmarkFB
|
||||||
|
\@makefntextFB{} % space as in french.ldf
|
||||||
|
\fi
|
||||||
|
}{\let\@@makefnmark\@@makefnmarkORI
|
||||||
|
\@makefntextORI{}% no space as in french.ldf
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
{\FNH@safeif{FBFrenchFootnotes}%
|
||||||
|
{\@makefntextFB{}}%
|
||||||
|
{\@makefntextORI{}}%
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
\def\FNH@postfntext{%
|
||||||
|
\let\FBeverypar@quote\FBeverypar@save
|
||||||
|
\localleftbox{\FBeveryline@quote}%
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
\def\FNH@check@{%
|
||||||
|
\expandafter\FNH@check@a\@makefntext{1.2!3?4,}%
|
||||||
|
\FNH@@@1.2!3?4,\FNH@@@\relax
|
||||||
|
}%
|
||||||
|
\long\def\FNH@check@a #11.2!3?4,#2\FNH@@@#3{%
|
||||||
|
\ifx\relax#3\expandafter\FNH@checkagain@
|
||||||
|
\else
|
||||||
|
\def\FNH@prefntext{#1}\def\FNH@postfntext{#2}%
|
||||||
|
\expandafter\FNH@check@b
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\def\FNH@checkagain@{%
|
||||||
|
\expandafter\FNH@checkagain@a
|
||||||
|
\detokenize\expandafter{\@makefntext{1.2!3?4,}}\relax\FNH@@@
|
||||||
|
}%
|
||||||
|
\edef\FNH@temp{\noexpand\FNH@checkagain@a ##1\string{1.2!3?4,\string}}%
|
||||||
|
\expandafter\def\FNH@temp#2#3\FNH@@@{%
|
||||||
|
\ifx\relax#2%
|
||||||
|
\def\FNH@prefntext{\@makefntext{}}%
|
||||||
|
\else\FNH@bad@makefntext@alert
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
\def\FNH@check@b #1\relax{%
|
||||||
|
\expandafter\expandafter\expandafter\FNH@check@c
|
||||||
|
\expandafter\meaning\expandafter\FNH@prefntext
|
||||||
|
\meaning\FNH@postfntext1.2!3?4,\FNH@check@c\relax
|
||||||
|
}%
|
||||||
|
\def\FNH@check@c #11.2!3?4,#2#3\relax{%
|
||||||
|
\ifx\FNH@check@c#2\else\FNH@bad@makefntext@alert\fi
|
||||||
|
}%
|
||||||
|
% slight reformulation for Sphinx
|
||||||
|
\def\FNH@bad@makefntext@alert{%
|
||||||
|
\sphinxbuildwarning{badfootnotes}%
|
||||||
|
\PackageWarningNoLine{sphinxpackagefootnote}%
|
||||||
|
{Footnotes will be sub-optimal, sorry. This is due to the document class or^^J
|
||||||
|
some package modifying macro \string\@makefntext.^^J
|
||||||
|
You can try to report this incompatibility at^^J
|
||||||
|
https://github.com/sphinx-doc/sphinx with this info:}%
|
||||||
|
\typeout{\meaning\@makefntext}%
|
||||||
|
\let\FNH@prefntext\@empty\let\FNH@postfntext\@empty
|
||||||
|
}%
|
||||||
|
% this macro from original footnote.sty is not used anymore by Sphinx
|
||||||
|
% but for simplicity sake let's just keep it as is
|
||||||
|
\def\makesavenoteenv{\@ifnextchar[\FNH@msne@ii\FNH@msne@i}%]
|
||||||
|
\def\FNH@msne@i #1{%
|
||||||
|
\expandafter\let\csname FNH$#1\expandafter\endcsname %$
|
||||||
|
\csname #1\endcsname
|
||||||
|
\expandafter\let\csname endFNH$#1\expandafter\endcsname %$
|
||||||
|
\csname end#1\endcsname
|
||||||
|
\FNH@msne@ii[#1]{FNH$#1}%$
|
||||||
|
}%
|
||||||
|
\def\FNH@msne@ii[#1]#2{%
|
||||||
|
\expandafter\edef\csname#1\endcsname{%
|
||||||
|
\noexpand\savenotes
|
||||||
|
\expandafter\noexpand\csname#2\endcsname
|
||||||
|
}%
|
||||||
|
\expandafter\edef\csname end#1\endcsname{%
|
||||||
|
\expandafter\noexpand\csname end#2\endcsname
|
||||||
|
\noexpand\expandafter
|
||||||
|
\noexpand\spewnotes
|
||||||
|
\noexpand\if@endpe\noexpand\@endpetrue\noexpand\fi
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
%
|
||||||
|
% some extras for Sphinx :
|
||||||
|
% \sphinxfootnotemark:
|
||||||
|
% - if in section titles will auto-remove itself from TOC
|
||||||
|
\def\sphinxfootnotemark [#1]%
|
||||||
|
{\ifx\thepage\relax\else\sphinxfootref{#1}\fi}%
|
||||||
|
\newcounter{sphinxfootnotemark}
|
||||||
|
\renewcommand\thesphinxfootnotemark{\number\value{sphinxfootnotemark}}
|
||||||
|
% - compares page number of footnote mark versus the one of footnote text
|
||||||
|
\def\sphinx@xdef@thefnmark#1{%
|
||||||
|
\expandafter\expandafter\expandafter\sphinx@footref@get
|
||||||
|
\csname r@\thesphinxscope.footnote.#1\endcsname\relax
|
||||||
|
\expandafter\expandafter\expandafter\sphinx@footmark@getpage
|
||||||
|
\csname r@footnotemark.\thesphinxfootnotemark\endcsname\thepage\relax
|
||||||
|
\protected@xdef\@thefnmark{%
|
||||||
|
\ifx\spx@footmarkpage\spx@footrefpage
|
||||||
|
\spx@footreflabel
|
||||||
|
\else
|
||||||
|
% the macro \sphinxthefootnotemark is in sphinx.sty
|
||||||
|
\sphinxthefootnotemark{\spx@footreflabel}{\spx@footrefpage}%
|
||||||
|
\fi
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
\def\sphinx@footref@get #1#2#3#4#5\relax{%
|
||||||
|
\def\spx@footreflabel{#1}%
|
||||||
|
\def\spx@footrefpage {#2}%
|
||||||
|
\def\spx@footrefHref {#4}%
|
||||||
|
}%
|
||||||
|
\def\sphinx@footmark@getpage #1#2#3\relax{%
|
||||||
|
\edef\spx@footmarkpage{#2}%
|
||||||
|
}%
|
||||||
|
\protected\def\sphinxfootref#1{% #1 always is explicit number in Sphinx
|
||||||
|
\spx@opt@BeforeFootnote
|
||||||
|
% each of \refstepcounter and \label interferes with memoir class detection
|
||||||
|
% of successive footnote marks, so we move them to inside \@makefnmark
|
||||||
|
\let\spx@saved@makefnmark\@makefnmark
|
||||||
|
\ltx@ifundefined{r@\thesphinxscope.footnote.#1}%
|
||||||
|
{\gdef\@thefnmark{?}% on first LaTeX run
|
||||||
|
\refstepcounter{sphinxfootnotemark}\label{footnotemark.\thesphinxfootnotemark}%
|
||||||
|
}%
|
||||||
|
{\def\@makefnmark{% will be used by \H@@footnotemark
|
||||||
|
\refstepcounter{sphinxfootnotemark}\label{footnotemark.\thesphinxfootnotemark}%
|
||||||
|
\sphinx@xdef@thefnmark{#1}% also defines \spx@footrefHref
|
||||||
|
% must be executed after \refstepcounter
|
||||||
|
\hyper@linkstart{link}{\spx@footrefHref}%
|
||||||
|
\spx@saved@makefnmark
|
||||||
|
\hyper@linkend
|
||||||
|
}%
|
||||||
|
}%
|
||||||
|
\H@@footnotemark
|
||||||
|
\let\@makefnmark\spx@saved@makefnmark
|
||||||
|
}%
|
||||||
|
\AtBeginDocument{%
|
||||||
|
% let hyperref less complain
|
||||||
|
\pdfstringdefDisableCommands{\def\sphinxfootnotemark [#1]{}}%
|
||||||
|
% to obtain hyperlinked footnotes in longtable environment we must replace
|
||||||
|
% hyperref's patch of longtable's patch of \@footnotetext by our own
|
||||||
|
\let\LT@p@ftntext\FNH@hyper@fntext
|
||||||
|
% this *requires* longtable to be used always wrapped in savenotes environment
|
||||||
|
}%
|
||||||
|
\endinput
|
||||||
|
%%
|
||||||
|
%% End of file `sphinxpackagefootnote.sty'.
|
||||||
21
build/latex/sphinxpackagesubstitutefont.sty
Normal file
21
build/latex/sphinxpackagesubstitutefont.sty
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
%% a stub for obsoleted LaTeX package substitutefont
|
||||||
|
% The package substitutefont stopped being distributed with TeXLive
|
||||||
|
% around August 2023 and was moved to "obsolete" section.
|
||||||
|
% cf https://ctan.org/pkg/substitutefont
|
||||||
|
% Trying to load it raises a LaTeX build error since.
|
||||||
|
|
||||||
|
% The \substitutefont has a LaTeX kernel replacement
|
||||||
|
% \DeclareFontFamilySubstitution
|
||||||
|
% which was added to LaTeX 2020-02-02
|
||||||
|
% The aim of this stub is to do that replacement silently.
|
||||||
|
|
||||||
|
% change this info string if making any custom modification
|
||||||
|
\ProvidesPackage{sphinxpackagesubstitutefont}[2023/15/11 v7.3.0 substitutefont stub]
|
||||||
|
|
||||||
|
\ifdefined\DeclareFontFamilySubstitution
|
||||||
|
\def\substitutefont{\DeclareFontFamilySubstitution}
|
||||||
|
\else
|
||||||
|
\usepackage{substitutefont}
|
||||||
|
\fi
|
||||||
|
|
||||||
|
\endinput
|
||||||
1
source/_static/.gitkeep
Normal file
1
source/_static/.gitkeep
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
|
||||||
43
source/architecture.rst
Normal file
43
source/architecture.rst
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
Architecture (audit interview)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
Endpoint (keys stay here / HSM)
|
||||||
|
│ HPKE content (NPE suite)
|
||||||
|
│ routing: dest + subject in the clear
|
||||||
|
▼
|
||||||
|
Untrusted NATS (cannot read bodies)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Verae DataCube chain (append-only hashes)
|
||||||
|
│ written through Peergos client
|
||||||
|
▼
|
||||||
|
Peergos cryptree (encrypted names, sizes, graph)
|
||||||
|
│ chunks → CID / hash
|
||||||
|
▼
|
||||||
|
IPFS (distributed, hash-verified ciphertext)
|
||||||
|
|
||||||
|
* **At rest:** Peergos cryptree + IPFS. Hosts with disk/backup see
|
||||||
|
**opaque hashed ciphertext**, not PHI, if they lack keys.
|
||||||
|
* **In transit (NATS):** HPKE-Base to directory public keys. Broker is
|
||||||
|
honest-but-curious: destinations yes, bodies no.
|
||||||
|
* **Integrity:** cube JSONL chain + dual hash + IPFS CID check on
|
||||||
|
restore (re-fetch blocks, re-verify hashes — not a plaintext tape).
|
||||||
|
|
||||||
|
NATS remains an untrusted router. Production E2E is NPE/HPKE.
|
||||||
|
Passthrough means destination in the clear; the body is ciphertext.
|
||||||
|
|
||||||
|
.. only:: html
|
||||||
|
|
||||||
|
Live: https://pfc.georgelambert.org/v1/npe/keys (public keys only).
|
||||||
|
Controls: https://docs.pfc.georgelambert.org/controls.html
|
||||||
|
|
||||||
|
.. only:: latex
|
||||||
|
|
||||||
|
See companion ``peergos-for-compliance.pdf`` (same folder) for
|
||||||
|
controls, custody, and variables chapters.
|
||||||
|
|
||||||
|
.. raw:: latex
|
||||||
|
|
||||||
|
\href{peergos-for-compliance.pdf}{peergos-for-compliance.pdf}
|
||||||
76
source/baa-dpa.rst
Normal file
76
source/baa-dpa.rst
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
BAAs and DPAs when ciphertext has no host keys
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
This is **guidance for an evidence pack**, not legal advice.
|
||||||
|
|
||||||
|
The operator statement
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Data at rest lives in the **encrypted Peergos cryptree**. Restore uses
|
||||||
|
**distributed, hash-verified, encrypted IPFS blocks**. Hosts and backup
|
||||||
|
media see **opaque blobs** (and random CHAMP labels), not filenames, not
|
||||||
|
PHI, not social graph — if keys never leave the client / customer HSM.
|
||||||
|
|
||||||
|
That is **true of the Peergos design** (see :doc:`verification`).
|
||||||
|
It **changes the BAA/DPA conversation**. It does **not** auto-delete the
|
||||||
|
need for contracts.
|
||||||
|
|
||||||
|
HIPAA (US) — Business Associate
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
A Business Associate is a person who **creates, receives, maintains, or
|
||||||
|
transmits ePHI** for a covered entity.
|
||||||
|
|
||||||
|
**Technical argument you can make (and should document):**
|
||||||
|
|
||||||
|
1. ePHI is encrypted **before** it leaves the endpoint (Peergos client /
|
||||||
|
DataCube writer).
|
||||||
|
2. The storage node, IPFS, disk, and backup hold **ciphertext + hashes**.
|
||||||
|
3. Private keys **do not** reside on the storage host (customer HSM /
|
||||||
|
client). Hash verification detects tampering.
|
||||||
|
4. Therefore the host **cannot maintain ePHI in intelligible form**.
|
||||||
|
|
||||||
|
HHS distinguishes **conduits** and parties that never have access to
|
||||||
|
ePHI. Many programs still **sign a BAA** when a vendor touches
|
||||||
|
infrastructure, because misconfiguration, support exports, or logs could
|
||||||
|
later expose plaintext. OCR looks at **your** risk analysis.
|
||||||
|
|
||||||
|
**Practical pack:** risk analysis memo citing cryptree + IPFS hash checks
|
||||||
|
+ key custody; BAA **or** written determination that the vendor is
|
||||||
|
**not** a BA because they cannot decrypt; list every party with
|
||||||
|
disk/backup (ns1, IPFS cluster, offsite replica).
|
||||||
|
|
||||||
|
GDPR (EU/UK) — processor vs technical measure
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
Encrypted data can still be **personal data** if it is reasonably
|
||||||
|
attributable (usernames, IPs, invoice identity). GDPR **Art. 32** lists
|
||||||
|
encryption as a security measure.
|
||||||
|
|
||||||
|
Peergos is designed so the **server is an adversary** for content and
|
||||||
|
most metadata. EU-based **independent pentests** (Cure53 DE, ROS NL)
|
||||||
|
evaluated that design. Processing location for **self-host** is *your*
|
||||||
|
ns1 / customer region, not peergos.net’s Germany hosting, unless you use
|
||||||
|
peergos.net.
|
||||||
|
|
||||||
|
You may still need a **DPA (Art. 28)** with anyone who **processes**
|
||||||
|
personal data (usernames, logs, billing). Ciphertext-only storage
|
||||||
|
**narrows** the DPA’s technical annex.
|
||||||
|
|
||||||
|
NATS operators
|
||||||
|
--------------
|
||||||
|
|
||||||
|
NATS is an **untrusted broker**. Content is HPKE; destinations and
|
||||||
|
subjects are in the clear. A NATS operator **cannot** read bodies without
|
||||||
|
endpoint private keys; **can** see routing metadata; **can** drop/delay
|
||||||
|
copy **ciphertext**. Treat like a transit provider: DPA/BAA depends on
|
||||||
|
whether routing metadata is personal data in your jurisdiction.
|
||||||
|
|
||||||
|
What “making yourself audit-ready” means
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
You are **not** buying Peergos’s Cure53/ROS reports as *your* SOC 2.
|
||||||
|
You are **reusing** those public evaluations as **vendor/component
|
||||||
|
assurance**, then adding your scope, RoPA, key-custody, inspect k-of-n,
|
||||||
|
admin-history, instance evidence, and contracts that match who can
|
||||||
|
actually see plaintext.
|
||||||
62
source/checklist.rst
Normal file
62
source/checklist.rst
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
Audit-ready checklist
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Use this as a working list. Check items only when **evidence exists**
|
||||||
|
(screenshot, log export, signed policy, ticket). This list is not a
|
||||||
|
certificate.
|
||||||
|
|
||||||
|
A. Scope and data map
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
* Named legal entity and systems in scope (console, Drive, NATS, IPFS, ns1)
|
||||||
|
* Data-flow diagram: endpoint → HPKE/NATS → cryptree/IPFS
|
||||||
|
* What is PHI / personal data vs ciphertext vs routing metadata
|
||||||
|
* Peergos verification chapter attached (:doc:`verification`)
|
||||||
|
|
||||||
|
B. Keys and encryption
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
* Customer holds Peergos/Drive keys; not on storage host
|
||||||
|
* NPE/HPKE endpoint keys in directory; private 0600; no xor content
|
||||||
|
* Signed Ed25519 config; unsigned rejected; admin-history prev+new+diff
|
||||||
|
* HSM or documented lab-to-HSM path
|
||||||
|
|
||||||
|
C. Access
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Console ``PFC_REQUIRE_AUTH=1``, TOTP; Drive login separate
|
||||||
|
* Inspect k-of-n; author is not an officer; log-before-reveal
|
||||||
|
* Joiner / mover / leaver for console users
|
||||||
|
* Google SSO does **not** unwrap cubes
|
||||||
|
|
||||||
|
D. Integrity and backup
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
* Cube chain append-only JSONL; dual hash
|
||||||
|
* Hash registry: first SHA-256 and receipt win
|
||||||
|
* Peergos/IPFS: hash-verified encrypted blocks (restore = re-fetch CIDs)
|
||||||
|
* Restore test: recover a cube from content-addressed ciphertext without
|
||||||
|
plaintext backup tapes
|
||||||
|
|
||||||
|
E. Logging
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Inspect audit events
|
||||||
|
* SM summaries: codes + lookup_id only (no bodies)
|
||||||
|
* Admin-history cube for config
|
||||||
|
|
||||||
|
F. Contracts (counsel)
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
* Written BA / not-a-BA determination for disk, VM, backup, IPFS
|
||||||
|
* DPA Art. 28 where usernames/logs/IPs are processed
|
||||||
|
* NATS operator: metadata vs content in the annex
|
||||||
|
* Peergos component assurance: attach Cure53 2019 + ROS 2024 PDFs
|
||||||
|
(public; not your org’s ISO/SOC report)
|
||||||
|
|
||||||
|
G. Independent audit of *you*
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
* SOC 2 Type I/II engagement **or** ISO 27001 registrar **or** HIPAA
|
||||||
|
risk analysis + policies (pick the program you actually need)
|
||||||
|
* Evidence window (Type II / surveillance) if applicable
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue