Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/antora-playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ asciidoc:
logo-img: ''
logo-text: 'Mr. Docs'
icon-img: ''
# Render LaTeX math. `stem:[...]` and `[stem]` blocks become MathJax
# delimiters (\(...\) inline, \[...\] display); the UI head loads
# MathJax to typeset them. MrDocs's own `$...$` / `\f$...\f$` doc-comment
# math emits `stem:[...]`, so this lights up the generated reference too.
stem: latexmath
# Make every `[tabs]` block in the docs a synchronised tabset.
# A tab click in one tabset selects the matching label in every
# other tabset on the page, and the choice is persisted in
Expand Down
184 changes: 57 additions & 127 deletions docs/extensions/mrdocs-demos.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,25 +180,25 @@ module.exports = function (registry) {
// demos. The attribute is set by Antora.
const pageVersion = parent.getDocument().getAttribute(
'page-component-version')
// Collect all demo URLs
// Collect all demo URLs. The layout on the server is
// demos/<version>/<library>/<format>/, where <format> is one of
// adoc, adoc-asciidoc, html, or xml. Each format directory holds a
// full multipage tree (html, adoc, adoc-asciidoc) or a single file
// (xml); there is no separate single/multi level.
let finalDemoDirs = [];
const versions = getSubdirectoriesSync('https://mrdocs.com/demos/')
.filter((v) => !pageVersion || v === pageVersion);
for (const version of versions) {
const demoLibraries = getSubdirectoriesSync(`https://mrdocs.com/demos/${version}/`);
for (const demoLibrary of demoLibraries) {
const pageTypes = getSubdirectoriesSync(`https://mrdocs.com/demos/${version}/${demoLibrary}/`);
for (const pageType of pageTypes) {
const demoFormats = getSubdirectoriesSync(`https://mrdocs.com/demos/${version}/${demoLibrary}/${pageType}/`);
for (const demoFormat of demoFormats) {
finalDemoDirs.push({
url: `https://mrdocs.com/demos/${version}/${demoLibrary}/${pageType}/${demoFormat}`,
version: version,
library: demoLibrary,
pageType: pageType,
format: demoFormat
});
}
const demoFormats = getSubdirectoriesSync(`https://mrdocs.com/demos/${version}/${demoLibrary}/`);
for (const demoFormat of demoFormats) {
finalDemoDirs.push({
url: `https://mrdocs.com/demos/${version}/${demoLibrary}/${demoFormat}`,
version: version,
library: demoLibrary,
format: demoFormat
});
}
}
}
Expand All @@ -211,129 +211,59 @@ module.exports = function (registry) {
}
}

// Create tables. Each page renders only its own version (see
// the version filter above), so the per-version heading would
// just repeat the page title.
// Format columns, in display order. AsciiDoc links to the
// rendered (`adoc-asciidoc`) multipage output rather than the raw
// `.adoc` tree, so the reader sees a browsable page; each cell is
// the format icon linking to that demo.
const iconBase = 'https://raw.githubusercontent.com/cppalliance/mrdocs/refs/heads/develop/docs/modules/ROOT/images/icons/';
const formatColumns = [
{ key: 'html', label: 'HTML', icon: 'html5.svg', entry: 'index.html' },
{ key: 'adoc-asciidoc', label: 'AsciiDoc', icon: 'asciidoc.svg', entry: 'index.html' },
{ key: 'xml', label: 'XML', icon: 'code_blocks.svg', entry: 'reference.xml' },
];

// Each page renders only its own version (see the version filter
// above), so a per-version heading would just repeat the title.
let text = ''
for (const version of allVersions) {
text += '\n'
text += `|===\n`;
// Libraries present in this version, sorted by display name.
const versionLibraries = [...new Set(
finalDemoDirs
.filter(d => d.version === version)
.map(d => d.library))]
.sort((a, b) => humanizeLibrary(a).localeCompare(humanizeLibrary(b)));

// Collect all unique page types, formats, and libraries for this version
let versionPageTypes = [];
let versionFormats = [];
let versionLibraries = [];
for (const demoDir of finalDemoDirs) {
if (demoDir.version !== version) {
continue
}
if (!versionPageTypes.includes(demoDir.pageType)) {
versionPageTypes.push(demoDir.pageType);
}
if (!versionFormats.includes(demoDir.format)) {
versionFormats.push(demoDir.format);
}
if (!versionLibraries.includes(demoDir.library)) {
versionLibraries.push(demoDir.library);
}
// Keep only the format columns that exist for this version,
// preserving the column order above.
const columns = formatColumns.filter(col =>
finalDemoDirs.some(d => d.version === version && d.format === col.key));
if (versionLibraries.length === 0 || columns.length === 0) {
continue;
}

// Sort versionPageTypes so that multipage always comes first
versionPageTypes.sort((a, b) => {
if (a === 'multi' && b !== 'multi') return -1;
if (a !== 'multi' && b === 'multi') return 1;
return a.localeCompare(b);
});

// Drop the raw `.adoc` format and keep only the
// rendered AsciiDoc (`adoc-asciidoc`); the single
// AsciiDoc column links to the rendered version.
versionFormats = versionFormats.filter(format => format !== 'adoc');
// Order columns HTML first, then AsciiDoc, then XML.
versionFormats.sort((a, b) => {
const order = ['html', 'adoc-asciidoc', 'xml'];
const aIndex = order.indexOf(a);
const bIndex = order.indexOf(b);
if (aIndex === -1 && bIndex === -1) return a.localeCompare(b);
if (aIndex === -1) return 1;
if (bIndex === -1) return -1;
return aIndex - bIndex;
});

// Sort versionLibraries alphabetically
versionLibraries.sort((a, b) => humanizeLibrary(a).localeCompare(humanizeLibrary(b)));

// Ensure XML is never in the multipage formats
let multipageFormats = versionFormats.filter(format => format !== 'xml');
let versionFormatColumns = versionFormats.map(format => `*${humanizeFormat(format)}*`).join(' | ');
let multipageFormatColumns = multipageFormats.map(format => `*${humanizeFormat(format)}*`).join(' | ');

// Multicells for the page format taking as many formats as possible for that page type
const toPageTypeCell = pageType => `${(pageType === 'multi' ? multipageFormats : versionFormats).length}+| *${humanizePageType(pageType)}*`;
text += `| ${versionPageTypes.map(toPageTypeCell).join(' ')}\n`;

text += `| *Library* | ${multipageFormatColumns} | ${versionFormatColumns}\n\n`;
const colCount = columns.length + 1;
text += `\n[cols="${colCount}*a",options="header"]\n`;
text += `|===\n`;
text += `| Library ${columns.map(col => `| ${col.label}`).join(' ')}\n\n`;
for (const library of versionLibraries) {
text += `| ${libraryLink(library)}`
for (const pageType of versionPageTypes) {
const pageTypeFormats = pageType === 'multi' ? multipageFormats : versionFormats;
for (const format of pageTypeFormats) {
const demoDir = finalDemoDirs.find(
demoDir => demoDir.version === version &&
demoDir.library === library &&
demoDir.pageType === pageType &&
demoDir.format === format);
if (demoDir) {
const demoUrlWithSuffix = demoDir.url + (() => {
if (format === 'xml')
{
return '/reference.xml';
}
if (format === 'adoc')
{
if (pageType === 'multi')
{
return '/index.adoc'
}
else {
return '/reference.adoc'
}
}
if (format === 'html' || format === 'adoc-asciidoc')
{
if (pageType === 'multi')
{
return '/index.html'
}
else {
return '/reference.html'
}
}
return '';
})()
if (['adoc', 'xml', 'html', 'adoc-asciidoc'].includes(format)) {
const formatIcons = {
adoc: 'https://raw.githubusercontent.com/cppalliance/mrdocs/refs/heads/develop/docs/modules/ROOT/images/icons/asciidoc.svg',
html: 'https://raw.githubusercontent.com/cppalliance/mrdocs/refs/heads/develop/docs/modules/ROOT/images/icons/html5.svg',
// The single AsciiDoc column now points at the rendered
// form, but the cell still represents the AsciiDoc format,
// so use the AsciiDoc icon.
'adoc-asciidoc': 'https://raw.githubusercontent.com/cppalliance/mrdocs/refs/heads/develop/docs/modules/ROOT/images/icons/asciidoc.svg',
default: 'https://raw.githubusercontent.com/cppalliance/mrdocs/refs/heads/develop/docs/modules/ROOT/images/icons/code_blocks.svg'
};
const icon = formatIcons[format] || formatIcons.default;
text += `| image:${icon}[${humanizeLibrary(library)} reference in ${humanizeFormat(format)} format,width=16,height=16,link=${demoUrlWithSuffix},window=_blank]`
} else {
text += `| ${demoUrlWithSuffix}[🔗,window=_blank]`
}
} else {
text += `| `
}
text += `| ${libraryLink(library)}`;
for (const col of columns) {
const demoDir = finalDemoDirs.find(d =>
d.version === version &&
d.library === library &&
d.format === col.key);
if (demoDir) {
const icon = iconBase + col.icon;
const url = `${demoDir.url}/${col.entry}`;
const alt = `${humanizeLibrary(library)} reference in ${col.label} format`;
text += ` | image:${icon}[${alt},width=24,height=24,link=${url},window=_blank]`;
} else {
text += ` |`;
}
}
text += `\n`
text += `\n`;
}
text += `|===\n\n`
text += `|===\n\n`;
}

return self.parseContent(parent, text)
Expand Down
Binary file removed docs/modules/ROOT/images/MrDocsBanner.jpg
Binary file not shown.
2 changes: 2 additions & 0 deletions docs/modules/ROOT/pages/commands/inlines.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ MrDocs reads the usual Markdown spans, with Doxygen and HTML equivalents alongsi
* xref:commands/reference.adoc#cmd-code-span[Code span]: `+`text`+`.
* xref:commands/reference.adoc#cmd-strikethrough[Strikethrough]: `+~~text~~+`.
* xref:commands/reference.adoc#cmd-highlight[Highlight]: `+==text==+`.
* xref:commands/reference.adoc#cmd-subscript[Subscript]: `+~text~+` or `+<sub>text</sub>+`.
* xref:commands/reference.adoc#cmd-superscript[Superscript]: `+^text^+` or `+<sup>text</sup>+`.

.Text formatting
[source,cpp]
Expand Down
10 changes: 10 additions & 0 deletions docs/modules/ROOT/pages/demos.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,13 @@ A few examples of reference documentation generated with Mr.Docs are available i

mrdocs-demos::[]

== Libraries using Mr.Docs

These libraries publish their reference documentation with Mr.Docs:

* https://redboltz.github.io/async_mqtt/doc/latest/async_mqtt/reference.html[async_mqtt,window=_blank]
* https://www.boost.org/doc/libs/develop/libs/dynamic_bitset/doc/html/dynamic_bitset/reference/boost/dynamic_bitset.html[Boost.DynamicBitset,window=_blank]
* https://www.boost.org/doc/libs/develop/libs/openmethod/doc/html/openmethod/reference/boost/openmethod.html[Boost.OpenMethod,window=_blank]
* https://www.boost.org/doc/libs/develop/libs/redis/doc/html/redis/reference/boost/redis.html[Boost.Redis,window=_blank]
* https://www.boost.org/latest/doc/antora/url/reference/boost/urls.html[Boost.URL,window=_blank]

2 changes: 2 additions & 0 deletions docs/modules/ROOT/pages/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ Doc comments in the Javadoc and Doxygen tradition. Block-level commands describe
include::example$snippets/landing/sqrt.cpp[tag=doc]
----

Doc comments carry LaTeX math too. The `\f$...\f$` and `$...$` spans in the comment above render as real symbols, so a complexity like stem:[O(\log n)] or a definition like stem:[\lfloor\sqrt{value}\rfloor] reads the way it would in a paper.

== What Mr.Docs produces

* Several generators emit documentation in formats ranging from rendered documents for human readers to structured data for downstream tooling.
Expand Down
Loading
Loading