# Document markup: Capabilities and tradeoffs across Markdown, AsciiDoc, and DITA

Source: https://flowingdocs.com/en/docs/markup/

## Format characteristics and practical fit

Choose a format based on how you need to lay out, reuse, and publish the content:

- **Markdown**: Simple notation commonly used for READMEs, blogs, and API documentation. Standard syntax has no cell spans, variables, or content reuse mechanism; those features usually require HTML, extensions, or build tools.
- **AsciiDoc**: Supports row and column spans, document attributes, and `include` directives. These features help maintain shared parameters and snippets or assemble content from multiple files.
- **DITA**: Organizes XML content into topics, assembles documents with maps, and reuses content through mechanisms such as `conref`. Consider it when you need structural validation, content reuse, and multiple output formats, along with the editing and publishing tools those workflows require. See the [OASIS DITA overview](https://docs.oasis-open.org/dita/dita/v1.3/os/part0-overview/dita-v1.3-os-part0-overview.html).

The workshop above provides two learning tracks: **Write a guide** compares everyday Markdown and AsciiDoc notation side by side, while **DITA · Organize guides** demonstrates how Topics and Maps assemble into comprehensive publication suites.

Regarding table formatting: Markdown pipe tables follow the [GFM specification](https://github.github.com/gfm/#tables-extension-), which offers no span syntax. Exercises here use embedded HTML `rowspan` and `colspan`; verify whether your production site sanitizes or strips raw HTML. AsciiDoc [supports row and column spans natively](https://docs.asciidoctor.org/asciidoc/latest/tables/span-cells/).

## Real-world engineering scenarios {#database-docs}

The workshop uses **MySQL 8.0 scenarios** to compare document structure. These are writing exercises, not complete production procedures. Adapt the following patterns to your own documentation:

- **Parameter dictionaries & engine comparisons** → Configuration matrices and API specifications (data types, defaults, validation boundaries, scopes).
- **Initialization & lifecycle runbooks** → Cluster provisioning, certificate rotations, or failover SOPs (emphasizing prerequisites, actions, and verification feedback).
- **Console errors & literal blocks** → CLI outputs, connection status codes, and troubleshooting runbooks.

Regardless of markup choice, linters only validate syntax. Complete technical documentation requires explicit preconditions, expected outputs, and recovery steps when operations fail.

## Further reference by scenario {#format-resources}

Choose your next technical focus based on real documentation requirements:

| Scenario                                                          | Recommended path & references                                                                                                                                                                                                                    |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Writing open-source READMEs or internal team notes                | Consult [CommonMark](https://commonmark.org/help/) and the [GFM spec](https://github.github.com/gfm/); check which extensions your platform enables.                                                                                             |
| Reusing product names, version strings, or callouts across guides | See the Content Reuse panel on the left; explore [AsciiDoc attributes](https://docs.asciidoctor.org/asciidoc/latest/attributes/document-attributes/) and [include directives](https://docs.asciidoctor.org/asciidoc/latest/directives/include/). |
| Embedding interactive UI widgets inside articles                  | Explore [MDX](https://mdxjs.com/docs/what-is-mdx/), paired with a modern static generator (e.g. Docusaurus, Next.js).                                                                                                                            |
| Assembling modular product deliverables across large teams        | Work through the workshop's DITA track to master Topics and Maps, then export the project to continue in professional XML suites (e.g. Oxygen XML Editor).                                                                                       |

### Practice package & offline migration

You can export your workspace state anytime using the download controls above:

- **Source file only**: Downloads current draft files using site-wide resource paths.
- **Practice package (with assets)**: Bundles associated SVG assets with relative paths, ready to open in local editors or static build pipelines.

When choosing a site generator, explore the [Static site generators guide](https://flowingdocs.com/en/docs/publishing/). To refine information hierarchy and cognitive load, continue with [Information design](https://flowingdocs.com/en/docs/information-design/).

These reference answers share the data used by the interactive exercises\. Read or copy them here, or download the Markdown version\.

The MySQL fragments illustrate document structures, not complete production procedures\. Reuse examples use a fictional product; validate them in your chosen toolchain\.

## Headings

Add a document title and a section heading\. Leave a blank line between paragraphs\.

### Markdown

Use \# Title for the document and \#\# Section for a section\.

Leave a space after \# and a blank line between paragraphs\.

```markdown
# MySQL Database Service

## Overview

MySQL is a widely used open-source relational database management system. Supporting ACID transactions, high-concurrency connections, and pluggable storage engines, it powers mission-critical web applications.
```

### AsciiDoc

Use = Title for the document and == Section for a section\. Leave a blank line before the body\.

Leave a space after the equals signs and a blank line before the body\.

```asciidoc
= MySQL Database Service

== Overview

MySQL is a widely used open-source relational database management system. Supporting ACID transactions, high-concurrency connections, and pluggable storage engines, it powers mission-critical web applications.
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Unordered lists

Turn the three readiness checks into an unordered list\.

### Markdown

Prefix each line with \- and a space\. \* or \+ also work\.

Leave a space after \- and a blank line before the list\.

```markdown
## Pre-flight checks

- Confirm that port 3306 is not in use.
- Verify read and write permissions on the data directory.
- Prepare a valid my.cnf configuration file.
```

### AsciiDoc

Prefix each line with \* and a space\.

A space must follow the asterisk\. Leave a blank line before the list\.

```asciidoc
== Pre-flight checks

* Confirm that port 3306 is not in use.
* Verify read and write permissions on the data directory.
* Prepare a valid my.cnf configuration file.
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Ordered lists

Turn the three operational steps into an ordered list starting at 1\.

### Markdown

Use 1\., 2\., and 3\. followed by a space\. Writing 1\. on every line also auto\-numbers\.

The period needs a following space, or this may remain plain text\.

```markdown
## Initialize the instance

1. Run the initialization command to create data directories.
2. Start the mysqld service daemon.
3. Run the security script to set the root password.
```

### AsciiDoc

Start each line with a period and a space: \. step\. Numbers are generated by the processor\.

Use a period followed by a space; the numbers are automatic\.

```asciidoc
== Initialize the instance

. Run the initialization command to create data directories.
. Start the mysqld service daemon.
. Run the security script to set the root password.
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Bold and italics

Bold “systemctl start mysqld” and italicize “Before stopping, confirm that active client sessions can be interrupted”\.

### Markdown

\*\*text\*\* for bold, \*text\* for italics\.

Keep the markers next to the text: \*\*text\*\*, not \*\* text \*\*\.

```markdown
## Service lifecycle

To start the service, execute **systemctl start mysqld**. Use systemctl stop mysqld to stop it.

*Before stopping, confirm that active client sessions can be interrupted*.
```

### AsciiDoc

\*text\* for bold, \_text\_ for italics\. Leave spaces around markers\.

Use paired markers\. Keep spaces around the marked phrase in these examples to avoid adjacent\-word boundaries\.

```asciidoc
== Service lifecycle

To start the service, execute *systemctl start mysqld*. Use systemctl stop mysqld to stop it.

_Before stopping, confirm that active client sessions can be interrupted_.
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Nested lists

Group instance planning into Production and Staging clusters, each with one nested item\.

### Markdown

Indent sublists with two spaces\.

This example uses two leading spaces\. Aligning the markers makes them siblings\.

```markdown
## Deployment environments

- Production cluster
  - Primary write node and read replicas.
- Staging cluster
  - Unit test databases and sandbox instances.
```

### AsciiDoc

Use \* for top level and \*\* for nested level\.

Use two asterisks for the second level\. Here \*\* is not bold markup\.

```asciidoc
== Deployment environments

* Production cluster
** Primary write node and read replicas.
* Staging cluster
** Unit test databases and sandbox instances.
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Images and links

Insert the architecture diagram with descriptive alt text, then add a “View full\-size diagram” link\.

### Markdown

\!\[alt text\]\(path\) for images, \[link text\]\(url\) for links\. Alt text should describe the image\.

Images have an extra \!\. Use the supplied image path in the exercise\.

```markdown
## Architecture diagram

![MySQL architecture: connection pool, optimizer, and InnoDB engine](/img/markup/mysql-architecture.svg)

[View full-size diagram](/img/markup/mysql-architecture.svg)
```

### AsciiDoc

image::path\[alt text\] for block images, link:url\[link text\] for links\.

Block images use two colons \(image::\) and occupy their own line\.

```asciidoc
== Architecture diagram

image::/img/markup/mysql-architecture.svg[MySQL architecture: connection pool, optimizer, and InnoDB engine]

link:/img/markup/mysql-architecture.svg[View full-size diagram]
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Tables

Organize engine, transaction support, and workload into a three\-column table with two rows\.

### Markdown

GFM tables require header and delimiter rows\. :\-\-\- aligns left, :\-\-\-: center, \-\-\-: right\.

The delimiter row is required\. This is a GFM extension; pipe tables cannot merge cells\.

```markdown
## Storage engines

| Engine | Transactions | Workload |
| :--- | :--- | :--- |
| InnoDB | Supported (ACID) | High-concurrency online transactions |
| MyISAM | Not supported | Read-only historical archives |
```

### AsciiDoc

Wrap tables with \|===; leave a blank line after headers\. Use \[cols="1,2,2",options="header"\]\.

Leave a blank line after the header and close the table with \|===\.

```asciidoc
== Storage engines

[cols="1,2,2",options="header"]
|===
|Engine |Transactions |Workload

|InnoDB |Supported (ACID) |High-concurrency online transactions
|MyISAM |Not supported |Read-only historical archives
|===
```

[Markdown](https://github.github.com/gfm/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Merged cells

Markdown pipe tables have no native cell spans\. This example uses HTML rowspan and colspan, which the publishing platform must allow\. AsciiDoc supports row and column spans natively\.

### Markdown \+ HTML

This is embedded HTML, not native Markdown span syntax\. Remove cells displaced by the span\.

```markdown
## Backup and maintenance plan

<table>
  <thead><tr><th>Category</th><th>Method</th><th>Description</th></tr></thead>
  <tbody>
    <tr><td rowspan="2">Physical backup</td><td>Cold backup</td><td>Direct data directory snapshot</td></tr>
    <tr><td>Hot backup</td><td>Continuous redo log tracking</td></tr>
    <tr><td>General policy</td><td colspan="2">Archive backups off-site and verify recovery regularly.</td></tr>
  </tbody>
</table>
```

### AsciiDoc

Leading dot spans rows \(\.2\+\|\); no dot spans columns \(2\+\|\)\. The specifier replaces the pipe \(never write \| \.2\+\|\)\. Remove any displaced cells\.

```asciidoc
== Backup and maintenance plan

[cols="1,1,2",options="header"]
|===
|Category |Method |Description

.2+|Physical backup |Cold backup |Direct data directory snapshot
|Hot backup |Continuous redo log tracking

|General policy 2+|Archive backups off-site and verify recovery regularly.
|===
```

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/tables/span-cells/)

## Code and literal text

Mark 1045 as inline code and preserve the two status lines in a literal block\.

### Markdown

Use backticks for inline code and a fenced block for multiple lines\. The text label indicates plain text\.

Use backticks, not apostrophes\. Put each fence on its own line\.

````markdown
## Terminal status

The client returns error `1045` when credentials fail.

```text
State: Running
Active connections: 18
```
````

### AsciiDoc

Use backticks for inline code and two lines of \.\.\.\. around a literal block\.

Each delimiter is four periods, not an ellipsis\.

```asciidoc
== Terminal status

The client returns error `1045` when credentials fail.

....
State: Running
Active connections: 18
....
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Section links

Link “Instance maintenance” to its section, then try the link in the preview\.

### Markdown

Use \[Instance maintenance\]\(\#instance\-maintenance\)\. This preview generates IDs from headings\.

The target anchor must exist\. Heading\-ID rules can differ between platforms\.

```markdown
## Troubleshooting

See [Instance maintenance](#instance-maintenance) for permission and connection issues.
```

### AsciiDoc

Use \<\<maintenance,Instance maintenance\>\>\. The destination section already has a \[\[maintenance\]\] anchor\.

The anchor names must match; the displayed link text may differ\.

```asciidoc
== Troubleshooting

See <<maintenance,Instance maintenance>> for permission and connection issues.
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Notes

Set the backup reminder apart before the mysqldump export instruction\.

### Markdown

\> \*\*Note\*\*: text separates a reminder visually\. A blockquote has no built\-in warning severity\.

Put \> at the start of the line\. A blockquote label and color do not define a standard warning level\.

```markdown
## Instance maintenance

> **Note**: Back up all databases before applying schema changes.

Export SQL dump files using mysqldump.
```

### AsciiDoc

NOTE: text creates an admonition\. AsciiDoc has explicit types; a blockquote is not semantically identical\.

Use uppercase NOTE, a colon and a space\. Separate the note from surrounding paragraphs with blank lines\.

```asciidoc
[[maintenance]]
== Instance maintenance

NOTE: Back up all databases before applying schema changes.

Export SQL dump files using mysqldump.
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Task lists

Create a task list with one checked item and one unchecked item\.

### Markdown

\- \[x\] is checked; \- \[ \] is unchecked\. Edit the source to change the state; preview checkboxes are read\-only\.

Keep the spaces around the brackets\. Task lists are a GFM extension\.

```markdown
## Production checklist

- [x] Slow query log is enabled.
- [ ] Automated backup job is scheduled.
```

### AsciiDoc

\* \[x\] is checked; \* \[ \] is unchecked\. This preview uses static checkboxes\.

Keep the spaces around the brackets\. Change the checked state in the source\.

```asciidoc
== Production checklist

* [x] Slow query log is enabled.
* [ ] Automated backup job is scheduled.
```

[Markdown](https://github.github.com/gfm/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Escaping

Display “\*\.\*” with both asterisks rather than as emphasized text\.

### Markdown

Escape each asterisk with a backslash: \\\*\.\\\*\. Escape pipes in a table to keep them inside a cell\.

Place the backslash directly before the punctuation; the backslash disappears in the preview\.

```markdown
## Wildcard escaping

Granting global permissions is written as \*.\*.
```

### AsciiDoc

Escape the opening marker: \\\*\.\*\. Both asterisks should remain visible\.

This example escapes the opening marker\. AsciiDoc escaping differs from Markdown\.

```asciidoc
== Wildcard escaping

Granting global permissions is written as \*.*.
```

[Markdown](https://commonmark.org/help/)

[AsciiDoc](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)

## Markdown: Reuse depends on the tool

Markdown itself has no variables or file inclusion\. This Docusaurus example requires MDX and JavaScript; a plain Markdown editor cannot execute it\.

Manual B can import the same fragment or use its own notice\. VitePress has a different inclusion syntax; it is not interchangeable with this MDX example\.

### shared\.js

```javascript
export const productName = "PolarisDB Distributed Database";
export const clusterPort = "5432";
```

### snippets/SafetyNotice\.mdx

```markdown
> **Note**
>
> Before making a change, confirm the applicable version, verification steps, and recovery procedure. Refer to the instructions for that operation.
```

### guide\-production\.mdx

```markdown
---
title: Operations
---

import SafetyNotice from './snippets/SafetyNotice.mdx';
import { productName, clusterPort } from './shared.js';

# {productName}

Service port: {clusterPort}

<SafetyNotice />
```

[Docusaurus MDX reference](https://docusaurus.io/docs/3.9.2/markdown-features/react)

[VitePress file inclusion](https://vitepress.dev/guide/markdown#markdown-file-inclusion)

## AsciiDoc: Attributes, includes, and conditions

Place these four files in one project\. Both guides read the shared attributes; Manual B uses a condition to choose its own notice\.

### shared\-attributes\.adoc

```asciidoc
:product-name: PolarisDB Distributed Database
:cluster-port: 5432
```

### snippets/dr\-safety\-notice\.adoc

```asciidoc
[NOTE]
====
Before making a change, confirm the applicable version, verification steps, and recovery procedure. Refer to the instructions for that operation.
====
```

### guide\-production\.adoc

```asciidoc
= {product-name} Operations
include::shared-attributes.adoc[]

Service port: {cluster-port}

include::snippets/dr-safety-notice.adoc[]
```

### guide\-staging\.adoc

```asciidoc
= {product-name} Practice
include::shared-attributes.adoc[]

ifdef::env-staging[]
[NOTE]
====
This guide covers a practice environment. Use test data and restore the initial configuration afterwards.
====
endif::[]
ifndef::env-staging[]
include::snippets/dr-safety-notice.adoc[]
endif::[]
```

[AsciiDoc include reference](https://docs.asciidoctor.org/asciidoc/latest/directives/include/)

## DITA: Key and content references

Define keys in a map and reference the product name with keyref\. A note uses conref to reuse a notice from another file\. These structural fragments need a complete project and validation with DITA tools\.

A guide that needs its own notice can reference a different fragment\. More complex conditional publishing requires filtering attributes and DITAVAL\. This page does not run those processes\.

### root\.ditamap

```xml
<map>
  <title>Example guide</title>
  <keydef keys="product_name">
    <topicmeta><keywords><keyword>PolarisDB Distributed Database</keyword></keywords></topicmeta>
  </keydef>
  <topicref href="guide-production.dita"/>
</map>
```

### shared\-topics\.dita

```xml
<topic id="safety-defs">
  <title>Shared notice</title>
  <body>
    <note id="dr-warning">Before making a change, confirm the applicable version, verification steps, and recovery procedure. Refer to the instructions for that operation.</note>
  </body>
</topic>
```

### guide\-production\.dita

```xml
<concept id="prod-guide">
  <title>Operations</title>
  <conbody>
    <p>Product: <ph keyref="product_name"/></p>
    <note conref="shared-topics.dita#safety-defs/dr-warning"/>
  </conbody>
</concept>
```

## DITA: topics and maps

A concept explains an idea, a task gives steps, and a reference provides lookup information\. Both maps reference the same topic files; rebuild the guides to include changes to those topics\.

### engines\.dita

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="engines" xml:lang="en-US">
  <title>Choosing a storage engine</title>
  <conbody>
    <p>Use InnoDB for ACID transactions and row-level locks, and MyISAM for read-only analytical workloads.</p>
    <p>This database guide is a writing example. Consult the official MySQL manual for production tuning.</p>
  </conbody>
</concept>

```

### start\-service\.dita

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "task.dtd">
<task id="start-service" xml:lang="en-US">
  <title>Initialize and start the service</title>
  <taskbody>
    <steps>
      <step><cmd>Run the initialization command to create data directories.</cmd></step>
      <step><cmd>Configure my.cnf and start the mysqld service daemon.</cmd></step>
      <step><cmd>Run the security script to set the root password.</cmd></step>
    </steps>
  </taskbody>
</task>

```

### parameters\.dita

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE reference PUBLIC "-//OASIS//DTD DITA Reference//EN" "reference.dtd">
<reference id="parameters" xml:lang="en-US">
  <title>Core parameters reference</title>
  <refbody>
    <simpletable>
      <sthead><stentry>Parameter</stentry><stentry>Description</stentry><stentry>Recommendation</stentry></sthead>
      <strow><stentry>max_connections</stentry><stentry>Max connections</stentry><stentry>Adjust based on concurrent load</stentry></strow>
      <strow><stentry>innodb_buffer_pool_size</stentry><stentry>Buffer pool size</stentry><stentry>Recommended 50% to 70% of physical RAM</stentry></strow>
    </simpletable>
  </refbody>
</reference>

```

### quickstart\.ditamap

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN" "map.dtd">
<map xml:lang="en-US">
  <title>Quick start</title>
  <topicref href="engines.dita"/>
  <topicref href="start-service.dita"/>
</map>

```

### guide\.ditamap

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN" "map.dtd">
<map xml:lang="en-US">
  <title>Full operations guide</title>
  <topicref href="engines.dita"/>
  <topicref href="start-service.dita"/>
  <topicref href="parameters.dita"/>
</map>

```

[OASIS DITA 1.3](https://docs.oasis-open.org/dita/dita/v1.3/os/part0-overview/dita-v1.3-os-part0-overview.html)

## Continue in Oxygen

Download and extract the DITA project from the interactive exercises\. Open guide\.ditamap in Oxygen’s DITA Maps Manager, edit topics in Author mode, validate, then publish with a transformation scenario\.

A passing browser check is not full DITA validation\. Validate in Oxygen before publishing\.

[Oxygen DITA Maps Manager](https://www.oxygenxml.com/doc/versions/27.1/ug-editor/topics/dita-maps-manager.html)
