Skip to content

[FEATURE] Support marker based partial include in literalinclude - #1351

Open
CybotTM wants to merge 2 commits into
phpDocumentor:mainfrom
netresearch:feature/literalinclude-markers
Open

[FEATURE] Support marker based partial include in literalinclude#1351
CybotTM wants to merge 2 commits into
phpDocumentor:mainfrom
netresearch:feature/literalinclude-markers

Conversation

@CybotTM

@CybotTM CybotTM commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Problem

literalinclude currently always includes the complete referenced file. An author who wants to show one relevant region of a real source or configuration file therefore has to duplicate that region into a dedicated snippet file, and that copy then silently drifts away from the original, or include unrelated content around the interesting part.

This came out of a TYPO3 documentation pull request (TYPO3-Documentation/TYPO3CMS-Guide-HowToDocument#547) that documented the Sphinx options for partial inclusion. It was closed as wrong, because the documented behaviour does not exist here — the missing piece is the feature, not the documentation.

What this adds

The Sphinx options :start-after: and :end-before::

..  literalinclude:: Example.php
    :language: php
    :start-after: // begin example
    :end-before: // end example

The included region starts on the line following the first line containing the start-after text and ends on the line preceding the first line containing the end-before text. end-before is searched behind the start of the region, so the same marker text may be used more than once in one file.

Markers were chosen over line numbers because they stay valid when the file changes above or below the selected region.

Behaviour when a marker is not found

A warning is logged (rst-file and line number included, as usual) and nothing is included. Falling back to the complete file would publish exactly the content the option was meant to exclude, and a build using --fail-on-log still fails on the warning. The same applies when an option is used without a value, when end-before occurs only above the line matched by start-after — that case gets its own message, because reporting the marker as "not found" for a marker that is plainly in the file sends the reader hunting for a typo that is not there — and when the marked region turns out to be empty, which is what a stale marker left directly under its partner looks like.

Notes for review

  • The selection happens before the CodeNode is created, so it lives in LiteralincludeDirective and not in DefaultCodeNodeOptionMapper. That mapper is shared with code-block, and it maps display options (language, caption, emphasized lines, line numbering) rather than changing the input.
  • LiteralincludeDirective now takes a logger. It is optional and defaults to null, following ConfvalDirective, which is the one place in this directory where a logger was added to an existing directive; that keeps the constructor change additive for anyone building the directive outside the container. No change to the service definition was needed, the container autowires it.
  • Six integration tests cover: start-after alone, end-before alone, both together, a marker that does not exist, markers given in the wrong order, and an empty marked region.
  • The second commit adds docs/reference/restructuredtext/literalinclude.rst. The reference section had no page for literalinclude at all, so the new options had nowhere to be documented; the page therefore also covers the directive itself and the options the shared code node option mapper provides. Every documented behaviour was rendered with vendor/bin/guides and read back before it was written down, including the missing file case (error logged, nothing rendered) and the missing marker case (warning logged, nothing included).
  • :diff: is deliberately out of scope, it needs a different data and render model.
  • The Sphinx option :lines: is proposed separately in #1352, which is stacked on this branch.

Local run of phpunit (unit, functional, integration), phpcs, phpstan and deptrac: green.

Assisted by claude-code:claude-opus-5 — Session

`literalinclude` always included the complete referenced file. Authors who
want to show one relevant region of a real source or configuration file had
to duplicate that region into a dedicated snippet file, which then silently
drifts away from the original.

Add the Sphinx options `:start-after:` and `:end-before:`. The included
region starts on the line following the first line containing the
`start-after` text and ends on the line preceding the first line containing
the `end-before` text. `end-before` is searched behind the start of the
region, so the same marker text may be used more than once in a file.

Markers are stable against edits outside the marked region, unlike line
numbers.

Nothing is included, and a warning names the reason, when a marker is not
found, when an option is used without a value, when `end-before` occurs only
above the line matched by `start-after`, and when the marked region is empty.
Falling back to the complete file in those cases would publish exactly the
content the option was meant to exclude.

The selection happens before the CodeNode is created, so it stays in the
directive rather than in DefaultCodeNodeOptionMapper, which is shared with
`code-block` and only maps display options.

The logger is an optional constructor argument, as in ConfvalDirective, so
that adding it does not break consumers that build the directive themselves.

Assisted-by: claude-code:claude-opus-5
Agent-Session: https://claude.ai/code/session_015QXXkquh2eQNBiTYA39Wss
Signed-off-by: Sebastian Mendel <sebastian.mendel@netresearch.de>
The reference section had no page for `literalinclude`, so neither the
directive itself nor its options were documented anywhere.

Add one, covering the directive, the new `:start-after:` and `:end-before:`
options, and the options the shared code node option mapper provides. Every
documented behaviour was rendered and read back before being written down,
including what happens when the file is missing (error, nothing rendered) and
when a marker is not found (warning, nothing included).

Assisted-by: claude-code:claude-opus-5
Agent-Session: https://claude.ai/code/session_015QXXkquh2eQNBiTYA39Wss
Signed-off-by: Sebastian Mendel <sebastian.mendel@netresearch.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant