diff --git a/docs/source/_static/mermaid.css b/docs/source/_static/mermaid.css
new file mode 100644
index 0000000000..06b768c420
--- /dev/null
+++ b/docs/source/_static/mermaid.css
@@ -0,0 +1,5 @@
+/* Centre a Mermaid diagram narrower than the page; conf.py sizes each to fit its content. */
+pre.mermaid {
+ margin-left: auto;
+ margin-right: auto;
+}
diff --git a/docs/source/conf.py b/docs/source/conf.py
index e5370ba037..f637e454ca 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -282,6 +282,20 @@
ogp_site_url = "https://pypcapkit.jarryshaw.me/"
+# Mermaid diagrams render at their natural size and shrink only to fit the page
+# width. The ``sphinxcontrib-mermaid`` defaults -- ``mermaid_height = '500px'`` with
+# the SVG stretched to the full page width -- fit every diagram into the same fixed
+# box, so a tall class hierarchy shrank until its text could not be read and its
+# edges ran together. ``useMaxWidth`` has to be off as well, or Mermaid writes
+# ``width="100%"`` on the SVG in place of its own size and ``fit-content`` has
+# nothing to size the box from. ``startOnLoad`` repeats the plugin's default, which
+# this setting replaces wholesale. ``_static/mermaid.css`` centres a diagram
+# narrower than the page, as the full-width box did.
+mermaid_width = 'fit-content'
+mermaid_height = 'auto'
+mermaid_init_config = {'startOnLoad': False, 'flowchart': {'useMaxWidth': False}}
+html_css_files = ['mermaid.css']
+
def maybe_skip_member(app: 'Sphinx', what: str, name: str, # pylint: disable=unused-argument
obj: 'Any', skip: bool, options: 'Dict[str, Any]') -> bool: # pylint: disable=unused-argument
diff --git a/docs/source/contributing/conventions/documentation.rst b/docs/source/contributing/conventions/documentation.rst
index e77da36e70..6ced460603 100644
--- a/docs/source/contributing/conventions/documentation.rst
+++ b/docs/source/contributing/conventions/documentation.rst
@@ -107,25 +107,36 @@ would otherwise inflate both counts:
.. code-block:: shell
grep -rn 'mermaid::' docs/source --include='*.rst' \
- --exclude='documentation.rst' | wc -l # 12 directives
+ --exclude='documentation.rst' | wc -l # directives
grep -rl 'mermaid::' docs/source --include='*.rst' \
- --exclude='documentation.rst' | wc -l # on 11 pages
-
-All twelve are a bare ``.. mermaid::`` carrying no directive options, and all twelve
-are a ``flowchart``: ``TD`` where the subject is a sequence or a decision, ``LR`` for a
-type hierarchy. **Quote a node label whose text Mermaid would otherwise try to parse**,
-and leave a bare identifier bare. That is what the exemplars do with *node* labels, and
-it falls close to the ``TD``/``LR`` line without following it: every node label in the
-six ``TD`` graphs is quoted, since every one of them is prose; the ``LR`` graphs quote
-only where the text forces it, which is ``h1["HTTP/1.*"]`` and ``h2["HTTP/2"]`` in
+ --exclude='documentation.rst' | wc -l # pages carrying one
+
+Every one is a bare ``.. mermaid::`` carrying no directive options, and every one is a
+``flowchart``: ``LR`` for a type hierarchy, and for a graph whose ``TD`` layout would run
+wider than the page or pile its edge labels on top of each other -- a decision with many
+outcomes, a trigger map -- and ``TD`` for the other sequences and decisions. **Quote a
+node label whose text Mermaid would otherwise try to parse**, and leave a bare identifier
+bare. That is what the exemplars do with *node* labels, and it follows the subject rather
+than the direction: every node label in the sequence, decision and trigger graphs is
+quoted, since every one of them is prose; the type hierarchies quote only where the text
+forces it, which is ``h1["HTTP/1.*"]`` and ``h2["HTTP/2"]`` in
:file:`docs/source/pcapkit/protocols/index.rst` and nowhere else. Everything else there
uses the bare ``A{{Meta}}``, ``B(Base)``, ``D([user customisation ...])`` and
``subgraph name [Title]`` forms, and spends its quotes on ``click`` targets instead.
+**Write a** ``click`` **target relative to the page it is on** -- ``protocol.html#...``,
+``../../ext.html#...`` -- never from the site root: the published site is served under
+``/PyPCAPKit/``, so a target starting with ``/`` resolves outside it and 404s.
**Edge labels follow no rule at all.** The exemplars quote some and leave others bare,
including ``|workflow_run: completed|`` and ``|02:00|``, which the reason above would
have quoted and which Mermaid accepts anyway -- so match the graph being edited rather
than this paragraph. Inside a quoted label, ``
`` breaks the text across lines and a
-literal ``<`` or ``>`` is written ``<`` or ``>``.
+literal ``<`` or ``>`` is written ``<`` or ``>``. Mermaid also reads label text as
+Markdown, so an underscore that opens or closes a name is written ``\_`` --
+``\_missing\_``, ``pcapkit.\_\_version\_\_`` -- or the name renders as emphasis. Its
+own ``#95;`` escape is no substitute: in a label that carries a ``
`` it is decoded
+before the Markdown pass, and the emphasis comes back. Where a steep edge runs under
+a neighbouring edge label, ``curve: monotoneX`` in the graph's front matter keeps it
+clear, as the mint criterion's decision graph does.
:doc:`The release pipeline ` is the ``TD`` example and
:doc:`the field hierarchy ` the ``LR`` one.
diff --git a/docs/source/contributing/conventions/mint-criterion.rst b/docs/source/contributing/conventions/mint-criterion.rst
index 225dae6bca..042112c1ff 100644
--- a/docs/source/contributing/conventions/mint-criterion.rst
+++ b/docs/source/contributing/conventions/mint-criterion.rst
@@ -76,11 +76,16 @@ and :file:`pcapkit/vendor/ipx/socket.py`'s ``UNASSIGNED_RANGE_NAMES``.
.. mermaid::
- flowchart TD
- LOOKUP["cls(value) finds no member"] --> MISSING["_missing_"]
+ ---
+ config:
+ flowchart:
+ curve: monotoneX
+ ---
+ flowchart LR
+ LOOKUP["cls(value) finds no member"] --> MISSING["\_missing\_"]
MISSING -->|"out of range, or no block covers it"| RAISE["ValueError"]
MISSING -->|"CGAType only"| MINT["extend_enum
permanent member, registry grows"]
- MISSING -->|"flag registries"| FLAG["super()._missing_
pseudo-member cached in the value table only"]
+ MISSING -->|"flag registries"| FLAG["super().\_missing\_
pseudo-member cached in the value table only"]
MISSING -->|"block label names a party"| SUFFIXED["_unregistered_member
label + _0x<code>"]
MISSING -->|"block label names a procedure"| BARE["_unregistered_member
bare block label"]
diff --git a/docs/source/contributing/conventions/registry-protocol.rst b/docs/source/contributing/conventions/registry-protocol.rst
index e35639a173..48aa1dcc15 100644
--- a/docs/source/contributing/conventions/registry-protocol.rst
+++ b/docs/source/contributing/conventions/registry-protocol.rst
@@ -140,14 +140,11 @@ Which branch a key takes, and what each miss ends in:
.. mermaid::
flowchart TD
- GET["get(key, default)"] -->|"isinstance(key, str)"| NAME["_member_map_ lookup"]
+ GET["get(key, default)"] -->|"isinstance(key, str)"| NAME["\_member\_map\_ lookup"]
GET -->|"otherwise"| VALUE["_validate_value(key)
then cls(key)"]
- NAME -->|"hit"| OK["canonical member"]
- NAME -->|"miss, key is a registered value"| OK
- NAME -->|"miss, default is a registered value"| OK
NAME -->|"miss, no usable default"| KEYERR["EnumKeyError
quiet, derives KeyError"]
- VALUE -->|"resolves, or _missing_ answers"| OK
- VALUE -->|"ValueError, default is a registered value"| OK
+ NAME -->|"hit,
or miss, key is a registered value,
or miss, default is a registered value"| OK["canonical member"]
+ VALUE -->|"resolves, or \_missing\_ answers,
or ValueError, default is a registered value"| OK
VALUE -->|"ValueError, no usable default"| VALERR["EnumValueError
loud, derives ValueError"]
Do not "improve" on the shape by making both misses report identically. Converting
diff --git a/docs/source/contributing/releasing.rst b/docs/source/contributing/releasing.rst
index 86505ba8ad..6e297cd3ee 100644
--- a/docs/source/contributing/releasing.rst
+++ b/docs/source/contributing/releasing.rst
@@ -416,7 +416,7 @@ The Release Pipeline
flowchart TD
T1["push: tags v*
ref_name starts with v"] --> VC
T2["workflow_run: Vendor Update completed
ref_name = main"] --> VC
- VC["version_check -- reads pcapkit.__version__
computes each job's own evidence
no gate, read-only"]
+ VC["version_check -- reads pcapkit.\_\_version\_\_
computes each job's own evidence
no gate, read-only"]
VC --> UT
UT["unit-tests -- Release test gate
skipped when nothing is publishable"] --> GH
GH["github -- GitHub Release
creates/attaches the v* tag
THE ONLY APPROVAL"]
@@ -424,12 +424,12 @@ The Release Pipeline
GH --> PY["pypi -- build + publish
OIDC trusted publishing"]
TG --> CD["conda -- build + upload
matrix: 2 OS, per-leg evidence"]
GH --> CD
- UT --> RS
VC --> RS
+ UT --> RS
GH --> RS
TG --> RS
- PY --> RS
CD --> RS
+ PY --> RS
RS["release_status -- always runs
reports why nothing released, or that it did"]
classDef gate stroke-dasharray:6 3,stroke-width:2px
class GH gate
diff --git a/docs/source/contributing/workflows.rst b/docs/source/contributing/workflows.rst
index 90d90ec3c9..5274be2562 100644
--- a/docs/source/contributing/workflows.rst
+++ b/docs/source/contributing/workflows.rst
@@ -128,7 +128,9 @@ The Graph
---------
Solid arrows are direct triggers (``push``, ``pull_request``, ``schedule``,
-``workflow_dispatch``). Thick arrows are ``workflow_run`` edges -- a
+``workflow_dispatch``, ``issues``, ``pull_request_target``), drawn in the first
+graph with a node for each schedule day. The second graph is the edges from one
+workflow to another. Thick arrows are ``workflow_run`` edges -- a
*separate* run, started only after the upstream workflow's run has fully
completed. Dotted arrows are ``uses:`` edges -- a reusable-workflow call that
runs synchronously *inside* the caller's own run, sharing its run id rather
@@ -136,32 +138,29 @@ than starting a new one.
.. mermaid::
- flowchart TD
+ flowchart LR
PUSH["push: main"]
PR["pull_request: main"]
- TAG["push: tags v*"]
- SCHED["schedule (Saturday, Monday, or daily)"]
+ SAT["schedule: Saturday"]
+ MON["schedule: Monday"]
+ DISPATCH["workflow_dispatch"]
+ DAILY["schedule: daily"]
ISSUES["issues"]
PRT["pull_request_target"]
- DISPATCH["workflow_dispatch"]
+ TAG["push: tags v*"]
- CQ["CodeQL
codeql-analysis.yml"]
UT["Unit Tests
unit-tests.yml"]
EX["Experimental Tests
experimental.yml"]
PC["Python Compatibility
python-compatibility.yml"]
+ CQ["CodeQL
codeql-analysis.yml"]
+ GP["GitHub Pages
deploy-pages.yml"]
+ CU["Conda Update
cron-conda.yml"]
LT["Lint
lint.yml"]
VU["Vendor Update
cron-vendor.yml"]
- CU["Conda Update
cron-conda.yml"]
- GP["GitHub Pages
deploy-pages.yml"]
- CR["Create Release
create-release.yml"]
- PS["Project Status
project-status.yml"]
- CC["Coverage Comment
coverage-comment.yml"]
- CT["CI Timing
ci-timing.yml"]
PV["Python Versions
cron-python-versions.yml"]
-
- PUSH --> CQ
- PR --> CQ
- SCHED -->|02:00| CQ
+ CT["CI Timing
ci-timing.yml"]
+ PS["Project Status
project-status.yml"]
+ CR["Create Release
create-release.yml"]
PUSH --> UT
PR --> UT
@@ -171,30 +170,48 @@ than starting a new one.
PUSH --> PC
PR --> PC
- SCHED -->|04:00| PC
+ SAT -->|04:00| PC
+
+ PUSH --> CQ
+ PR --> CQ
+ SAT -->|02:00| CQ
+
+ PR --> GP
+ SAT -->|02:00| GP
+
+ SAT -->|10:00| CU
PR --> LT
- SCHED -->|06:00| LT
+ SAT -->|06:00| LT
DISPATCH --> LT
- PR --> GP
- SCHED -->|02:00| GP
+ SAT -->|10:00| VU
- SCHED -->|10:00| VU
- SCHED -->|10:00| CU
+ MON -->|05:41| PV
+ DISPATCH --> PV
- TAG --> CR
+ MON -->|07:23| CT
+ DISPATCH --> CT
+ DISPATCH --> PS
+ DAILY -->|00:37| PS
ISSUES --> PS
PRT --> PS
- SCHED -->|daily 00:37| PS
- DISPATCH --> PS
- SCHED -->|Mon 07:23| CT
- DISPATCH --> CT
+ TAG --> CR
- SCHED -->|Mon 05:41| PV
- DISPATCH --> PV
+ classDef trig fill:none,stroke-dasharray:2 2
+ class PUSH,PR,SAT,MON,DISPATCH,DAILY,ISSUES,PRT,TAG trig
+
+.. mermaid::
+
+ flowchart LR
+ UT["Unit Tests
unit-tests.yml"]
+ VU["Vendor Update
cron-vendor.yml"]
+ CU["Conda Update
cron-conda.yml"]
+ GP["GitHub Pages
deploy-pages.yml"]
+ CC["Coverage Comment
coverage-comment.yml"]
+ CR["Create Release
create-release.yml"]
UT ==>|workflow_run: completed| VU
UT ==>|workflow_run: completed| CU
@@ -202,26 +219,26 @@ than starting a new one.
VU ==>|workflow_run: completed| CR
UT ==>|workflow_run: completed| CC
- VU -.->|uses: gate-only| UT
- CU -.->|uses: gate-only| UT
- GP -.->|uses: gate-only| UT
- CR -.->|uses: gate-only| UT
-
- classDef trig fill:none,stroke-dasharray:2 2
- class PUSH,PR,TAG,SCHED,DISPATCH,ISSUES,PRT trig
-
-The double relationship between **Unit Tests** and the four dependants that
-also call it is the
-part that reading a single file cannot show, and it is deliberate rather than
-redundant: each of the four calls ``unit-tests.yml`` with ``gate-only: true``
-itself (dotted, above) **only when its own trigger is not** ``workflow_run``
-(their gate jobs' ``if:`` guards this explicitly) -- i.e. only on the
-Saturday ``schedule`` path, where no completed Unit Tests run exists yet to
-read a verdict from. On the ``workflow_run`` path (thick arrows), each reads
-the verdict Unit Tests already reached instead of re-running the gate a second
-time. Vendor Update, Conda Update and GitHub Pages act on it only once their
-``verdict`` job, described under the edge list below, says it is a verdict on
-the commit they build.
+ VU -.-> UT
+ CU -.-> UT
+ GP -.-> UT
+ CR -.-> UT
+
+The double relationship between **Unit Tests** and the dependants that also
+call it is the part that reading a single file cannot show, and it is
+deliberate rather than redundant. Vendor Update, Conda Update and GitHub Pages
+call ``unit-tests.yml`` with ``gate-only: true`` themselves (dotted, above)
+**only when their own trigger is** ``schedule`` -- their gate jobs' ``if:``
+skips ``workflow_run``, and GitHub Pages' skips ``pull_request`` as well -- so
+only on the Saturday path, where no completed Unit Tests run exists yet to read
+a verdict from. On the ``workflow_run`` path (thick arrows), each reads the
+verdict Unit Tests already reached instead of re-running the gate a second
+time, and acts on it only once its ``verdict`` job, described under the edge
+list below, says it is a verdict on the commit it builds. Create Release has
+no ``schedule``, and its gate job's ``if:`` reads ``version_check``'s evidence
+rather than the event, so its gate runs on both of its triggers: on a ``v*``
+tag push, and on a ``workflow_run`` from Vendor Update when some target is not
+yet published (:doc:`releasing` gives the conditions).
``workflow_run`` Edges
----------------------
diff --git a/docs/source/pcapkit/corekit/fields/index.rst b/docs/source/pcapkit/corekit/fields/index.rst
index e8b3e5a49b..e5e0a0e78e 100644
--- a/docs/source/pcapkit/corekit/fields/index.rst
+++ b/docs/source/pcapkit/corekit/fields/index.rst
@@ -75,42 +75,42 @@ hierarchy:
C --> D([user customisation ...])
- click A "/pcapkit/corekit/fields/field.html#pcapkit.corekit.fields.field.FieldMeta"
- click B "/pcapkit/corekit/fields/field.html#pcapkit.corekit.fields.field.FieldBase"
- click C "/pcapkit/corekit/fields/field.html#pcapkit.corekit.fields.field.Field"
-
- click NumberField "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.NumberField"
- click Int64Field "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.Int64Field"
- click UInt64Field "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.UInt64Field"
- click Int32Field "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.Int32Field"
- click UInt32Field "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.UInt32Field"
- click Int16Field "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.Int16Field"
- click UInt16Field "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.UInt16Field"
- click Int8Field "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.Int8Field"
- click UInt8Field "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.UInt8Field"
- click EnumField "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.EnumField"
- click PortEnumField "/pcapkit/corekit/fields/numbers.html#pcapkit.corekit.fields.numbers.PortEnumField"
-
- click _TextField "/pcapkit/corekit/fields/strings.html#pcapkit.corekit.fields.strings._TextField"
- click BytesField "/pcapkit/corekit/fields/strings.html#pcapkit.corekit.fields.strings.BytesField"
- click StringField "/pcapkit/corekit/fields/strings.html#pcapkit.corekit.fields.strings.StringField"
- click BitField "/pcapkit/corekit/fields/strings.html#pcapkit.corekit.fields.strings.BitField"
- click PaddingField "/pcapkit/corekit/fields/strings.html#pcapkit.corekit.fields.strings.PaddingField"
-
- click _IPField "/pcapkit/corekit/fields/ipaddress.html#pcapkit.corekit.fields.ipaddress._IPField"
- click _IPAddressField "/pcapkit/corekit/fields/ipaddress.html#pcapkit.corekit.fields.ipaddress._IPAddressField"
- click _IPInterfaceField "/pcapkit/corekit/fields/ipaddress.html#pcapkit.corekit.fields.ipaddress._IPInterfaceField"
- click IPv4AddressField "/pcapkit/corekit/fields/ipaddress.html#pcapkit.corekit.fields.ipaddress.IPv4AddressField"
- click IPv6AddressField "/pcapkit/corekit/fields/ipaddress.html#pcapkit.corekit.fields.ipaddress.IPv6AddressField"
- click IPv4InterfaceField "/pcapkit/corekit/fields/ipaddress.html#pcapkit.corekit.fields.ipaddress.IPv4InterfaceField"
- click IPv6InterfaceField "/pcapkit/corekit/fields/ipaddress.html#pcapkit.corekit.fields.ipaddress.IPv6InterfaceField"
-
- click ListField "/pcapkit/corekit/fields/collections.html#pcapkit.corekit.fields.collections.ListField"
- click OptionField "/pcapkit/corekit/fields/collections.html#pcapkit.corekit.fields.collections.OptionField"
-
- click NoValueField "/pcapkit/corekit/fields/misc.html#pcapkit.corekit.fields.misc.NoValueField"
- click ConditionalField "/pcapkit/corekit/fields/misc.html#pcapkit.corekit.fields.misc.ConditionalField"
- click PayloadField "/pcapkit/corekit/fields/misc.html#pcapkit.corekit.fields.misc.PayloadField"
- click SwitchField "/pcapkit/corekit/fields/misc.html#pcapkit.corekit.fields.misc.SwitchField"
- click SchemaField "/pcapkit/corekit/fields/misc.html#pcapkit.corekit.fields.misc.SchemaField"
- click ForwardMatchField "/pcapkit/corekit/fields/misc.html#pcapkit.corekit.fields.misc.ForwardMatchField"
+ click A "field.html#pcapkit.corekit.fields.field.FieldMeta"
+ click B "field.html#pcapkit.corekit.fields.field.FieldBase"
+ click C "field.html#pcapkit.corekit.fields.field.Field"
+
+ click NumberField "numbers.html#pcapkit.corekit.fields.numbers.NumberField"
+ click Int64Field "numbers.html#pcapkit.corekit.fields.numbers.Int64Field"
+ click UInt64Field "numbers.html#pcapkit.corekit.fields.numbers.UInt64Field"
+ click Int32Field "numbers.html#pcapkit.corekit.fields.numbers.Int32Field"
+ click UInt32Field "numbers.html#pcapkit.corekit.fields.numbers.UInt32Field"
+ click Int16Field "numbers.html#pcapkit.corekit.fields.numbers.Int16Field"
+ click UInt16Field "numbers.html#pcapkit.corekit.fields.numbers.UInt16Field"
+ click Int8Field "numbers.html#pcapkit.corekit.fields.numbers.Int8Field"
+ click UInt8Field "numbers.html#pcapkit.corekit.fields.numbers.UInt8Field"
+ click EnumField "numbers.html#pcapkit.corekit.fields.numbers.EnumField"
+ click PortEnumField "numbers.html#pcapkit.corekit.fields.numbers.PortEnumField"
+
+ click _TextField "strings.html#pcapkit.corekit.fields.strings._TextField"
+ click BytesField "strings.html#pcapkit.corekit.fields.strings.BytesField"
+ click StringField "strings.html#pcapkit.corekit.fields.strings.StringField"
+ click BitField "strings.html#pcapkit.corekit.fields.strings.BitField"
+ click PaddingField "strings.html#pcapkit.corekit.fields.strings.PaddingField"
+
+ click _IPField "ipaddress.html#pcapkit.corekit.fields.ipaddress._IPField"
+ click _IPAddressField "ipaddress.html#pcapkit.corekit.fields.ipaddress._IPAddressField"
+ click _IPInterfaceField "ipaddress.html#pcapkit.corekit.fields.ipaddress._IPInterfaceField"
+ click IPv4AddressField "ipaddress.html#pcapkit.corekit.fields.ipaddress.IPv4AddressField"
+ click IPv6AddressField "ipaddress.html#pcapkit.corekit.fields.ipaddress.IPv6AddressField"
+ click IPv4InterfaceField "ipaddress.html#pcapkit.corekit.fields.ipaddress.IPv4InterfaceField"
+ click IPv6InterfaceField "ipaddress.html#pcapkit.corekit.fields.ipaddress.IPv6InterfaceField"
+
+ click ListField "collections.html#pcapkit.corekit.fields.collections.ListField"
+ click OptionField "collections.html#pcapkit.corekit.fields.collections.OptionField"
+
+ click NoValueField "misc.html#pcapkit.corekit.fields.misc.NoValueField"
+ click ConditionalField "misc.html#pcapkit.corekit.fields.misc.ConditionalField"
+ click PayloadField "misc.html#pcapkit.corekit.fields.misc.PayloadField"
+ click SwitchField "misc.html#pcapkit.corekit.fields.misc.SwitchField"
+ click SchemaField "misc.html#pcapkit.corekit.fields.misc.SchemaField"
+ click ForwardMatchField "misc.html#pcapkit.corekit.fields.misc.ForwardMatchField"
diff --git a/docs/source/pcapkit/dumpkit/index.rst b/docs/source/pcapkit/dumpkit/index.rst
index 16b903a642..3784298bcf 100644
--- a/docs/source/pcapkit/dumpkit/index.rst
+++ b/docs/source/pcapkit/dumpkit/index.rst
@@ -44,10 +44,10 @@ hierarchy:
click PLIST "https://dictdumper.jarryshaw.me/en/latest/dictdumper.plist.html#dictdumper.plist.PLIST"
click VueJS "https://dictdumper.jarryshaw.me/en/latest/dictdumper.vuejs.html#dictdumper.vuejs.VueJS"
- click DumperBase "/pcapkit/dumpkit/common.html#pcapkit.dumpkit.common.DumperBase"
- click Dumper "/pcapkit/dumpkit/common.html#pcapkit.dumpkit.common.Dumper"
- click PCAPIO "/pcapkit/dumpkit/pcap.html#pcapkit.dumpkit.pcap.PCAPIO"
- click NotImplementedIO "/pcapkit/dumpkit/null.html#pcapkit.dumpkit.null.NotImplementedIO"
+ click DumperBase "common.html#pcapkit.dumpkit.common.DumperBase"
+ click Dumper "common.html#pcapkit.dumpkit.common.Dumper"
+ click PCAPIO "pcap.html#pcapkit.dumpkit.pcap.PCAPIO"
+ click NotImplementedIO "null.html#pcapkit.dumpkit.null.NotImplementedIO"
.. note::
diff --git a/docs/source/pcapkit/foundation/engines/index.rst b/docs/source/pcapkit/foundation/engines/index.rst
index 2d4c4171a2..9e69d054b1 100644
--- a/docs/source/pcapkit/foundation/engines/index.rst
+++ b/docs/source/pcapkit/foundation/engines/index.rst
@@ -32,7 +32,7 @@ class hierarchy of :mod:`pcapkit.foundation.engines`:
A{{EngineMeta}} -.->|metaclass| B(EngineBase)
subgraph built-in [Built-in Engines]
- %% direction TD
+ direction LR
PCAP
PCAPNG
@@ -40,7 +40,7 @@ class hierarchy of :mod:`pcapkit.foundation.engines`:
B --> built-in
subgraph third-party [3rd Party Engines]
- %% direction TD
+ direction LR
Scapy
DPKT
@@ -54,20 +54,20 @@ class hierarchy of :mod:`pcapkit.foundation.engines`:
B --> C(Engine)
C --> D([user customisation ...])
- click A "/pcapkit/foundation/engines/engine.html#pcapkit.foundation.engines.engine.EngineMeta"
- click B "/pcapkit/foundation/engines/engine.html#pcapkit.foundation.engines.engine.EngineBase"
- click C "/pcapkit/foundation/engines/engine.html#pcapkit.foundation.engines.engine.Engine"
- click D "/ext.html#extractor-engines"
+ click A "engine.html#pcapkit.foundation.engines.engine.EngineMeta"
+ click B "engine.html#pcapkit.foundation.engines.engine.EngineBase"
+ click C "engine.html#pcapkit.foundation.engines.engine.Engine"
+ click D "../../../ext.html#extractor-engines"
- click PCAP "/pcapkit/foundation/engines/builtin.html#pcapkit.foundation.engines.pcap.PCAP"
- click PCAPNG "/pcapkit/foundation/engines/builtin.html#pcapkit.foundation.engines.pcapng.PCAPNG"
+ click PCAP "builtin.html#pcapkit.foundation.engines.pcap.PCAP"
+ click PCAPNG "builtin.html#pcapkit.foundation.engines.pcapng.PCAPNG"
- click Scapy "/pcapkit/foundation/engines/3rdparty.html#pcapkit.foundation.engines.scapy.Scapy"
- click DPKT "/pcapkit/foundation/engines/3rdparty.html#pcapkit.foundation.engines.dpkt.DPKT"
- click PyShark "/pcapkit/foundation/engines/3rdparty.html#pcapkit.foundation.engines.pyshark.PyShark"
- click PyPCAP "/pcapkit/foundation/engines/3rdparty.html#pcapkit.foundation.engines.pypcap.PyPCAP"
- click PCAP_CT "/pcapkit/foundation/engines/3rdparty.html#pcapkit.foundation.engines.pcap_ct.PCAP_CT"
- click PyPCAPFile "/pcapkit/foundation/engines/3rdparty.html#pcapkit.foundation.engines.pypcapfile.PyPCAPFile"
+ click Scapy "3rdparty.html#pcapkit.foundation.engines.scapy.Scapy"
+ click DPKT "3rdparty.html#pcapkit.foundation.engines.dpkt.DPKT"
+ click PyShark "3rdparty.html#pcapkit.foundation.engines.pyshark.PyShark"
+ click PyPCAP "3rdparty.html#pcapkit.foundation.engines.pypcap.PyPCAP"
+ click PCAP_CT "3rdparty.html#pcapkit.foundation.engines.pcap_ct.PCAP_CT"
+ click PyPCAPFile "3rdparty.html#pcapkit.foundation.engines.pypcapfile.PyPCAPFile"
Not every engine can do everything :class:`~pcapkit.foundation.extraction.Extractor`
offers, and the ones that cannot say so rather than quietly doing less, unless
diff --git a/docs/source/pcapkit/foundation/reassembly/index.rst b/docs/source/pcapkit/foundation/reassembly/index.rst
index f9ef8be5c1..054834605b 100644
--- a/docs/source/pcapkit/foundation/reassembly/index.rst
+++ b/docs/source/pcapkit/foundation/reassembly/index.rst
@@ -36,15 +36,15 @@ diagram of the class hierarchy of :mod:`pcapkit.foundation.reassembly`:
B --> C(Reassembly)
C --> D([user customisation ...])
- click A "/pcapkit/foundation/reassembly/reassembly.html#pcapkit.foundation.reassembly.reassembly.ReassemblyMeta"
- click B "/pcapkit/foundation/reassembly/reassembly.html#pcapkit.foundation.reassembly.reassembly.ReassemblyBase"
- click C "/pcapkit/foundation/reassembly/reassembly.html#pcapkit.foundation.reassembly.reassembly.Reassembly"
- click D "/ext.html#reassembly-and-flow-tracing"
-
- click IP "/pcapkit/foundation/reassembly/ip/ip.html#pcapkit.foundation.reassembly.ip.IP"
- click IPv4 "/pcapkit/foundation/reassembly/ip/ipv4.html#pcapkit.foundation.reassembly.ipv4.IPv4"
- click IPv6 "/pcapkit/foundation/reassembly/ip/ipv6.html#pcapkit.foundation.reassembly.ipv6.IPv6"
- click TCP "/pcapkit/foundation/reassembly/tcp.html#pcapkit.foundation.reassembly.tcp.TCP"
+ click A "reassembly.html#pcapkit.foundation.reassembly.reassembly.ReassemblyMeta"
+ click B "reassembly.html#pcapkit.foundation.reassembly.reassembly.ReassemblyBase"
+ click C "reassembly.html#pcapkit.foundation.reassembly.reassembly.Reassembly"
+ click D "../../../ext.html#reassembly-and-flow-tracing"
+
+ click IP "ip/ip.html#pcapkit.foundation.reassembly.ip.IP"
+ click IPv4 "ip/ipv4.html#pcapkit.foundation.reassembly.ipv4.IPv4"
+ click IPv6 "ip/ipv6.html#pcapkit.foundation.reassembly.ipv6.IPv6"
+ click TCP "tcp.html#pcapkit.foundation.reassembly.tcp.TCP"
Auxiliary Data
==============
diff --git a/docs/source/pcapkit/foundation/traceflow/index.rst b/docs/source/pcapkit/foundation/traceflow/index.rst
index 544d9abe2d..e1780d24e2 100644
--- a/docs/source/pcapkit/foundation/traceflow/index.rst
+++ b/docs/source/pcapkit/foundation/traceflow/index.rst
@@ -38,12 +38,12 @@ diagram of the class hierarchy of :mod:`pcapkit.foundation.traceflow`:
B --> C(TraceFlow)
C --> D([user customisation ...])
- click A "/pcapkit/foundation/traceflow/traceflow.html#pcapkit.foundation.traceflow.traceflow.TraceFlowMeta"
- click B "/pcapkit/foundation/traceflow/traceflow.html#pcapkit.foundation.traceflow.traceflow.TraceFlowBase"
- click C "/pcapkit/foundation/traceflow/traceflow.html#pcapkit.foundation.traceflow.traceflow.TraceFlow"
- click D "/ext.html#reassembly-and-flow-tracing"
+ click A "traceflow.html#pcapkit.foundation.traceflow.traceflow.TraceFlowMeta"
+ click B "traceflow.html#pcapkit.foundation.traceflow.traceflow.TraceFlowBase"
+ click C "traceflow.html#pcapkit.foundation.traceflow.traceflow.TraceFlow"
+ click D "../../../ext.html#reassembly-and-flow-tracing"
- click TCP "/pcapkit/foundation/traceflow/tcp.html#pcapkit.foundation.traceflow.tcp.TCP"
+ click TCP "tcp.html#pcapkit.foundation.traceflow.tcp.TCP"
Auxiliary Data
--------------
diff --git a/docs/source/pcapkit/protocols/index.rst b/docs/source/pcapkit/protocols/index.rst
index 48f4c783d2..b0dfc55c0f 100644
--- a/docs/source/pcapkit/protocols/index.rst
+++ b/docs/source/pcapkit/protocols/index.rst
@@ -26,6 +26,37 @@ from given information. The class hierarchy of :mod:`pcapkit.protocols`:
flowchart LR
A{{ProtocolMeta}} -.->|metaclass| B(ProtocolBase)
+ %% The layers are declared in this order so that ARP --> RARP and
+ %% Raw --> FTP_DATA stay short instead of crossing the other layers.
+
+ subgraph misc [Miscellaneous]
+ subgraph pcap [PCAP Format]
+ Header & Frame
+ end
+
+ subgraph pcapng [PCAP-NG Format]
+ PCAPNG
+ end
+
+ Raw & NoPayload
+ end
+
+ subgraph application [Application Layer]
+ Application --> HTTP & FTP & NGAP & OSPF & RARP
+
+ subgraph http [HTTP Family]
+ HTTP --> h1["HTTP/1.*"] & h2["HTTP/2"]
+ end
+
+ subgraph ftp [FTP Family]
+ FTP & FTP_DATA
+ end
+
+ subgraph rarp [RARP Family]
+ RARP --> DRARP
+ end
+ end
+
subgraph link [Link Layer]
Link --> Ethernet & L2TP & Loopback & VLAN & ARP
@@ -62,34 +93,6 @@ from given information. The class hierarchy of :mod:`pcapkit.protocols`:
Transport --> TCP & UDP & SCTP
end
- subgraph application [Application Layer]
- Application --> HTTP & FTP & NGAP & OSPF & RARP
-
- subgraph http [HTTP Family]
- HTTP --> h1["HTTP/1.*"] & h2["HTTP/2"]
- end
-
- subgraph ftp [FTP Family]
- FTP & FTP_DATA
- end
-
- subgraph rarp [RARP Family]
- RARP --> DRARP
- end
- end
-
- subgraph misc [Miscellaneous]
- subgraph pcap [PCAP Format]
- Header & Frame
- end
-
- subgraph pcapng [PCAP-NG Format]
- PCAPNG
- end
-
- Raw & NoPayload
- end
-
B --> Link & Internet & Transport & Application
B --> Header & Frame & PCAPNG & Raw & NoPayload
@@ -100,59 +103,59 @@ from given information. The class hierarchy of :mod:`pcapkit.protocols`:
B --> C(Protocol)
C --> D([user customisation ...])
- click A "/pcapkit/protocols/protocol.html#pcapkit.protocols.protocol.ProtocolMeta"
- click B "/pcapkit/protocols/protocol.html#pcapkit.protocols.protocol.ProtocolBase"
- click C "/pcapkit/protocols/protocol.html#pcapkit.protocols.protocol.Protocol"
- click D "/ext.html#what-s-in-for-protocols"
-
- click Link "/pcapkit/protocols/link/link.html#pcapkit.protocols.link.link.Link"
- click Ethernet "/pcapkit/protocols/link/ethernet.html#pcapkit.protocols.link.ethernet.Ethernet"
- click L2TP "/pcapkit/protocols/link/l2tp.html#pcapkit.protocols.link.l2tp.L2TP"
- click L2TPv2 "/pcapkit/protocols/link/l2tpv2.html#pcapkit.protocols.link.l2tpv2.L2TPv2"
- click Loopback "/pcapkit/protocols/link/loopback.html#pcapkit.protocols.link.loopback.Loopback"
- click VLAN "/pcapkit/protocols/link/vlan.html#pcapkit.protocols.link.vlan.VLAN"
- click C_Tag "/pcapkit/protocols/link/c_tag.html#pcapkit.protocols.link.c_tag.C_Tag"
- click S_Tag "/pcapkit/protocols/link/s_tag.html#pcapkit.protocols.link.s_tag.S_Tag"
- click ARP "/pcapkit/protocols/link/arp.html#pcapkit.protocols.link.arp.ARP"
- click InARP "/pcapkit/protocols/link/arp.html#pcapkit.protocols.link.arp.InARP"
-
- click Internet "/pcapkit/protocols/internet/internet.html#pcapkit.protocols.internet.internet.Internet"
- click AH "/pcapkit/protocols/internet/ah.html#pcapkit.protocols.internet.ah.AH"
- click ESP "/pcapkit/protocols/internet/esp.html#pcapkit.protocols.internet.esp.ESP"
- click HIP "/pcapkit/protocols/internet/hip.html#pcapkit.protocols.internet.hip.HIP"
- click HOPOPT "/pcapkit/protocols/internet/hopopt.html#pcapkit.protocols.internet.hopopt.HOPOPT"
- click IP "/pcapkit/protocols/internet/ip.html#pcapkit.protocols.internet.ip.IP"
- click IPsec "/pcapkit/protocols/internet/ipsec.html#pcapkit.protocols.internet.ipsec.IPsec"
- click IPv4 "/pcapkit/protocols/internet/ipv4.html#pcapkit.protocols.internet.ipv4.IPv4"
- click IPv6 "/pcapkit/protocols/internet/ipv6.html#pcapkit.protocols.internet.ipv6.IPv6"
- click IPv6_Ext "/pcapkit/protocols/internet/ipv6_ext.html#pcapkit.protocols.internet.ipv6_ext.IPv6_Ext"
- click IPv6-Frag "/pcapkit/protocols/internet/ipv6_frag.html#pcapkit.protocols.internet.ipv6_frag.IPv6_Frag"
- click IPv6-Opts "/pcapkit/protocols/internet/ipv6_opts.html#pcapkit.protocols.internet.ipv6_opts.IPv6_Opts"
- click IPv6-Route "/pcapkit/protocols/internet/ipv6_route.html#pcapkit.protocols.internet.ipv6_route.IPv6_Route"
- click IPX "/pcapkit/protocols/internet/ipx.html#pcapkit.protocols.internet.ipx.IPX"
- click MH "/pcapkit/protocols/internet/mh.html#pcapkit.protocols.internet.mh.MH"
-
- click Transport "/pcapkit/protocols/transport/transport.html#pcapkit.protocols.transport.transport.Transport"
- click TCP "/pcapkit/protocols/transport/tcp.html#pcapkit.protocols.transport.tcp.TCP"
- click UDP "/pcapkit/protocols/transport/udp.html#pcapkit.protocols.transport.udp.UDP"
- click SCTP "/pcapkit/protocols/transport/sctp.html#pcapkit.protocols.transport.sctp.SCTP"
-
- click Application "/pcapkit/protocols/application/application.html#pcapkit.protocols.application.application.Application"
- click HTTP "/pcapkit/protocols/application/http.html#pcapkit.protocols.application.http.HTTP"
- click h1 "/pcapkit/protocols/application/httpv1.html#pcapkit.protocols.application.httpv1.HTTP"
- click h2 "/pcapkit/protocols/application/httpv2.html#pcapkit.protocols.application.httpv2.HTTP"
- click FTP "/pcapkit/protocols/application/ftp.html#pcapkit.protocols.application.ftp.FTP"
- click FTP_DATA "/pcapkit/protocols/application/ftp.html#pcapkit.protocols.application.ftp.FTP_DATA"
- click NGAP "/pcapkit/protocols/application/ngap.html#pcapkit.protocols.application.ngap.NGAP"
- click OSPF "/pcapkit/protocols/application/ospf.html#pcapkit.protocols.application.ospf.OSPF"
- click RARP "/pcapkit/protocols/application/rarp.html#pcapkit.protocols.application.rarp.RARP"
- click DRARP "/pcapkit/protocols/application/rarp.html#pcapkit.protocols.application.rarp.DRARP"
-
- click Raw "/pcapkit/protocols/misc/raw.html#pcapkit.protocols.misc.raw.Raw"
- click NoPayload "/pcapkit/protocols/misc/null.html#pcapkit.protocols.misc.null.NoPayload"
- click PCAPNG "/pcapkit/protocols/misc/pcapng.html#pcapkit.protocols.misc.pcapng.PCAPNG"
- click Header "/pcapkit/protocols/misc/pcap.html#pcapkit.protocols.misc.pcap.header.Header"
- click Frame "/pcapkit/protocols/misc/pcap.html#pcapkit.protocols.misc.pcap.frame.Frame"
+ click A "protocol.html#pcapkit.protocols.protocol.ProtocolMeta"
+ click B "protocol.html#pcapkit.protocols.protocol.ProtocolBase"
+ click C "protocol.html#pcapkit.protocols.protocol.Protocol"
+ click D "../../ext.html#what-s-in-for-protocols"
+
+ click Link "link/link.html#pcapkit.protocols.link.link.Link"
+ click Ethernet "link/ethernet.html#pcapkit.protocols.link.ethernet.Ethernet"
+ click L2TP "link/l2tp.html#pcapkit.protocols.link.l2tp.L2TP"
+ click L2TPv2 "link/l2tpv2.html#pcapkit.protocols.link.l2tpv2.L2TPv2"
+ click Loopback "link/loopback.html#pcapkit.protocols.link.loopback.Loopback"
+ click VLAN "link/vlan.html#pcapkit.protocols.link.vlan.VLAN"
+ click C_Tag "link/c_tag.html#pcapkit.protocols.link.c_tag.C_Tag"
+ click S_Tag "link/s_tag.html#pcapkit.protocols.link.s_tag.S_Tag"
+ click ARP "link/arp.html#pcapkit.protocols.link.arp.ARP"
+ click InARP "link/arp.html#pcapkit.protocols.link.arp.InARP"
+
+ click Internet "internet/internet.html#pcapkit.protocols.internet.internet.Internet"
+ click AH "internet/ah.html#pcapkit.protocols.internet.ah.AH"
+ click ESP "internet/esp.html#pcapkit.protocols.internet.esp.ESP"
+ click HIP "internet/hip.html#pcapkit.protocols.internet.hip.HIP"
+ click HOPOPT "internet/hopopt.html#pcapkit.protocols.internet.hopopt.HOPOPT"
+ click IP "internet/ip.html#pcapkit.protocols.internet.ip.IP"
+ click IPsec "internet/ipsec.html#pcapkit.protocols.internet.ipsec.IPsec"
+ click IPv4 "internet/ipv4.html#pcapkit.protocols.internet.ipv4.IPv4"
+ click IPv6 "internet/ipv6.html#pcapkit.protocols.internet.ipv6.IPv6"
+ click IPv6_Ext "internet/ipv6_ext.html#pcapkit.protocols.internet.ipv6_ext.IPv6_Ext"
+ click IPv6-Frag "internet/ipv6_frag.html#pcapkit.protocols.internet.ipv6_frag.IPv6_Frag"
+ click IPv6-Opts "internet/ipv6_opts.html#pcapkit.protocols.internet.ipv6_opts.IPv6_Opts"
+ click IPv6-Route "internet/ipv6_route.html#pcapkit.protocols.internet.ipv6_route.IPv6_Route"
+ click IPX "internet/ipx.html#pcapkit.protocols.internet.ipx.IPX"
+ click MH "internet/mh.html#pcapkit.protocols.internet.mh.MH"
+
+ click Transport "transport/transport.html#pcapkit.protocols.transport.transport.Transport"
+ click TCP "transport/tcp.html#pcapkit.protocols.transport.tcp.TCP"
+ click UDP "transport/udp.html#pcapkit.protocols.transport.udp.UDP"
+ click SCTP "transport/sctp.html#pcapkit.protocols.transport.sctp.SCTP"
+
+ click Application "application/application.html#pcapkit.protocols.application.application.Application"
+ click HTTP "application/http.html#pcapkit.protocols.application.http.HTTP"
+ click h1 "application/httpv1.html#pcapkit.protocols.application.httpv1.HTTP"
+ click h2 "application/httpv2.html#pcapkit.protocols.application.httpv2.HTTP"
+ click FTP "application/ftp.html#pcapkit.protocols.application.ftp.FTP"
+ click FTP_DATA "application/ftp.html#pcapkit.protocols.application.ftp.FTP_DATA"
+ click NGAP "application/ngap.html#pcapkit.protocols.application.ngap.NGAP"
+ click OSPF "application/ospf.html#pcapkit.protocols.application.ospf.OSPF"
+ click RARP "application/rarp.html#pcapkit.protocols.application.rarp.RARP"
+ click DRARP "application/rarp.html#pcapkit.protocols.application.rarp.DRARP"
+
+ click Raw "misc/raw.html#pcapkit.protocols.misc.raw.Raw"
+ click NoPayload "misc/null.html#pcapkit.protocols.misc.null.NoPayload"
+ click PCAPNG "misc/pcapng.html#pcapkit.protocols.misc.pcapng.PCAPNG"
+ click Header "misc/pcap.html#pcapkit.protocols.misc.pcap.header.Header"
+ click Frame "misc/pcap.html#pcapkit.protocols.misc.pcap.frame.Frame"
Protocol Registry
-----------------