DMD — Docs Markdown Directives
Write your package documentation as Markdown files under
docs/ at the root of your repo.
This page is a complete reference of the directives available on top of
plain CommonMark — each section shows the source you would write next to
the result that ends up on the docs site.
Introduction
DMD is plain CommonMark plus a small set of block directives that start
with @. If your file doesn't use any of them, it renders
exactly as CommonMark. Directives are additive — pick the ones that fit
the page you're writing, ignore the rest.
Three shapes show up in this reference:
- Block directives open and close on their own lines (
@callout … @endcallout). - Inline directives are HTML comments (
<!-- @version-badge … -->) that flow with the surrounding text. - Self-closing directives have no body and end with a slash (
@version-badge type="added" version="v4.3.0" /).
Page structure
Each docs page is a single .md file. The first
# heading becomes the page title; every ##
heading appears in the right-side "On this page" navigation.
Subdirectories under docs/ become URL segments.
---
title: 'Opening and closing'
eyebrow: 'Docs · Connection'
lede: 'How to open a session and tear it down cleanly.'
---
# Opening and closing
## Open
Plain CommonMark goes here.
## Close
More CommonMark.
Frontmatter
Optional YAML block at the top of the file. Use it to set the page title, summary, related-links footer and prev/next arrows. Every key is optional — leave the block out entirely if you don't need it.
| Key | Used for |
|---|---|
title | Browser <title> + H1 if the body's first H1 differs. |
eyebrow | Small all-caps label above the H1. |
lede | One-sentence summary under the H1; also fills <meta description>. |
see_also | Array of related links rendered as a card at the bottom — each entry needs href, optional label + meta. |
prev / next | Manual navigation arrows. Object with href + label. |
---
title: 'Subscriptions'
eyebrow: 'Docs · Operations'
lede: 'Open a subscription, attach monitored items, consume notifications.'
see_also:
- { href: './monitored-items.md', meta: '5 min' }
- { href: 'https://opcfoundation.org/specs/part4', label: 'OPC UA Part 4', meta: 'external' }
prev: { label: 'Calling methods', href: './calling-methods.md' }
next: { label: 'Monitored items', href: './monitored-items.md' }
---
Callouts
Highlight a note, tip, warning, danger or success block.
variant defaults to note; title is optional.
@callout variant="warning" title="Heads up"
Subscriptions hold server resources — always close them
in a `finally` block or via the session destructor.
@endcallout
Renders as:
Heads up
finally block or via the session destructor.
Available variants: note · info · tip · success · warning · danger.
Do / Don't
Side-by-side good/bad example. Body must contain exactly one
@do and one @dont block.
@do-dont
@do
Use `NodeId::numeric(0, 2259)` — namespace + identifier are explicit.
@enddo
@dont
Pass `'i=2259'` as a string; the encoder will still accept it,
but readers of your code can't see the namespace.
@enddont
@enddo-dont
Renders as:
Use NodeId::numeric(0, 2259) — namespace + identifier are explicit.
Pass 'i=2259' as a string; the encoder will still accept it,
but readers of your code can't see the namespace.
Method signatures
Compact pill that introduces a function or method. Often pairs with a
following @params block. Available as block (@method … /)
and inline (<!-- @method … -->).
@method name="Client::read" returns="DataValue" visibility="public" /
Renders as:
Client::read
Parameter lists
Structured argument reference. @params wraps one or more
@param children; each child supports name,
type, required, default attributes plus
a free-form description in the body.
@params heading="Arguments"
@param name="nodeId" type="NodeId" required="true"
The node to read. Construct with `NodeId::numeric()` or `NodeId::string()`.
@endparam
@param name="attribute" type="int" default="13"
OPC UA attribute id — `13` (`Value`) is the most common.
@endparam
@endparams
Renders as:
nodeId
NodeId::numeric()
or NodeId::string().
attribute
13
(Value) is the most common.
Code blocks
@code-block wraps a fenced code block with the docs chrome:
terminal-style header, language pill, optional label, and a
copy-to-clipboard button. Body must contain exactly one fenced block.
@code-block language="php" label="examples/read.php"
```php
$client = ClientBuilder::create()->connect('opc.tcp://localhost:4840');
$value = $client->read(NodeId::numeric(0, 2259));
```
@endcode-block
Supported languages: php, bash,
text, yml, cs,
blade.php. Other languages get rendered without
syntax highlighting — write them as plain CommonMark fenced
code blocks instead.
Tabs
Switch between alternative views of the same content (often per-language code
samples). labels is a comma-separated list; the number of labels
must match the number of @tab children, indexed from zero.
@tabs labels="Laravel, Symfony, Plain PHP"
@tab index="0"
Use the `Opcua` facade — `Opcua::read(...)`.
@endtab
@tab index="1"
Inject `OpcuaManager` from the container.
@endtab
@tab index="2"
Build the client by hand via `ClientBuilder::create()`.
@endtab
@endtabs
Renders as:
Use the Opcua facade — Opcua::read(...).
Inject OpcuaManager from the container.
Build the client by hand via ClientBuilder::create().
Steps
Numbered walkthrough. The body MUST be a single Markdown list (bulleted or
ordered); each item becomes a numbered step. A leading **title**
on the item becomes the step heading; the rest is the body.
@steps
- **Install** the package with `composer require php-opcua/opcua-client`.
- **Connect** to your server.
```php
$client = ClientBuilder::create()->connect('opc.tcp://localhost:4840');
```
- **Read** a node and inspect the data value.
@endsteps
Renders as:
-
01
Install
Install the package with
composer require php-opcua/opcua-client. -
02
Connect
Connect to your server with
ClientBuilder::create()->connect(...). -
03
Read
Read a node and inspect the data value.
Section divider
Visual break between major topical groups inside a page.
eyebrow is the small all-caps label; the body is a one-line
description.
@divider eyebrow="Advanced"
For the curious — the bits below are not required for everyday usage.
@enddivider
Renders as:
Advanced
Version badge
Marker for "Added in vX.Y", "Changed in vX.Y" or "Deprecated since vX.Y".
Block form (@version-badge … /) renders as a standalone pill;
inline form (<!-- @version-badge … -->) flows with surrounding text.
@version-badge type="added" version="v4.3.0" date="2026-04-12" /
Subscriptions reuse the same session token across reconnects.
<!-- @version-badge type="changed" version="v4.3.0" -->
Renders as:
Supported type values: added · changed · deprecated.
Keyboard keys
Use the standard HTML <kbd> element inline.
It's restyled to look like a physical keyboard key — no DMD
directive needed.
Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to stop the daemon.
Renders as:
Press Ctrl + C to stop the daemon.
Cross-references
Use relative Markdown links to point at other pages in your docs —
the same way you would in any GitHub README. Links to
.md files are turned into the correct version-pinned
URL automatically, anchors are preserved, and external URLs pass
through unchanged.
See [Reading values](./reading.md) for the simpler case.
Anchors are preserved: [security policies](../security/policies.md#ecc).
External URLs pass through unchanged: [OPC Foundation](https://opcfoundation.org).
Authoring tip