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
18 changes: 16 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -697,11 +697,25 @@ jobs:
# mrdocs documenting mrdocs demo
mrdocs --config="$(pwd)/docs/mrdocs.yml" "$(pwd)/CMakeLists.txt" --output="$(pwd)/demos/mrdocs/$variant/$generator" --multipage=$multipage --generator="$generator" --log-level=debug
done

# Render the asciidoc files to html using asciidoctor
if [[ ${{ runner.os }} == 'Linux' ]]; then
for project in boost-url mrdocs; do
mkdir -p "$(pwd)/demos/$project/$variant/adoc-asciidoc"
asciidoctor -D "$(pwd)/demos/$project/$variant/adoc-asciidoc" "$(pwd)/demos/$project/$variant/adoc/*.adoc"
root="$(pwd)/demos/$project/$variant"
src="$root/adoc"
dst="$root/adoc-asciidoc"

# Create the top-level output dir
mkdir -p "$dst"

# Find every .adoc (recursively), mirror the directory structure, and render
find "$src" -type f -name '*.adoc' -print0 |
while IFS= read -r -d '' f; do
rel="${f#"$src/"}" # path relative to $src
outdir="$dst/$(dirname "$rel")" # mirror subdir inside $dst
mkdir -p "$outdir"
asciidoctor -D "$outdir" "$f"
done
done
fi
done
Expand Down
Empty file modified docs/build_docs.sh
100644 → 100755
Empty file.
Empty file modified docs/build_local_docs.sh
100644 → 100755
Empty file.
85 changes: 71 additions & 14 deletions docs/extensions/mrdocs-demos.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,83 @@ const fs = require("fs");

function getSubdirectoriesSync(url) {
try {
// cache setup
let urlPath = new URL(url).pathname;
let cacheFilenamePath = urlPath.replace(/[^a-zA-Z0-9]/g, '') + '.json';
let cachePath = `${__dirname}/../build/requests/${cacheFilenamePath}`;
fs.mkdirSync(`${__dirname}/../build/requests/`, {recursive: true});
const readFromCacheFile = fs.existsSync(cachePath) && fs.statSync(cachePath).mtime > new Date(Date.now() - 1000 * 60 * 60 * 24);

// read file or make request
const data =
readFromCacheFile ?
fs.readFileSync(cachePath, 'utf-8') :
request('GET', url).getBody('utf-8')
if (!readFromCacheFile) {
fs.writeFileSync(cachePath, data);
}
const regex = /<a href="([^"]+)\/">/g;
const directories = [];

// parse entries: name + date (if present)
// Matches: <a href="name/">name/</a> [spaces] 11-Sep-2025 20:51
const entryRe = /<a href="([^"]+)\/">[^<]*<\/a>\s+(\d{2}-[A-Za-z]{3}-\d{4}\s+\d{2}:\d{2})?/g;

const month = { Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,Sep:8,Oct:9,Nov:10,Dec:11 };
const parseDate = (s) => {
if (!s) return null; // missing or no date in listing
// "11-Sep-2025 20:51"
const m = /^(\d{2})-([A-Za-z]{3})-(\d{4})\s+(\d{2}):(\d{2})$/.exec(s.trim());
if (!m) return null;
const [, d, mon, y, hh, mm] = m;
return new Date(Date.UTC(+y, month[mon], +d, +hh, +mm));
};

const isSemver = (name) => {
// allow optional leading 'v', ignore pre-release/build metadata for ordering
const m = /^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(name);
if (!m) return null;
return { major: +m[1], minor: +m[2], patch: +m[3] };
};

const entries = [];
let match;
while ((match = regex.exec(data)) !== null) {
if (match[1] !== '..' && match[1] !== '.') {
directories.push(match[1]);
}
while ((match = entryRe.exec(data)) !== null) {
const name = match[1];
if (name === '.' || name === '..') continue;
const dt = parseDate(match[2] || null);
const sv = isSemver(name);
entries.push({
name,
date: dt, // may be null
semver: !!sv,
major: sv ? sv.major : 0,
minor: sv ? sv.minor : 0,
patch: sv ? sv.patch : 0,
});
}
return directories;

// sort
entries.sort((a, b) => {
// 1) non-semver first
if (a.semver !== b.semver) return a.semver ? 1 : -1;

if (!a.semver && !b.semver) {
// non-semver: newer date first; if no date, push to end among non-semver
const ad = a.date ? a.date.getTime() : -Infinity;
const bd = b.date ? b.date.getTime() : -Infinity;
if (ad !== bd) return bd - ad;
// tie-breaker: name asc for stability
return a.name.localeCompare(b.name);
}

// semver: major ↓, minor ↓, patch ↓
if (a.major !== b.major) return b.major - a.major;
if (a.minor !== b.minor) return b.minor - a.minor;
if (a.patch !== b.patch) return b.patch - a.patch;
// final tie-breaker: name asc
return a.name.localeCompare(b.name);
});

return entries.map(e => e.name);
} catch (error) {
console.error('Error:', error);
return [];
Expand Down Expand Up @@ -144,8 +200,6 @@ module.exports = function (registry) {
}

// Remove Rendered Asciidoc from the list of formats
// - The raw Asciidoc is already rendered by the mrdocs.com server as HTML
versionFormats = versionFormats.filter(format => format !== 'adoc-asciidoc');
let multipageFormats = versionFormats.filter(format => format !== 'xml');

let versionFormatColumns = versionFormats.map(format => `*${humanizeFormat(format)}*`).join(' | ');
Expand Down Expand Up @@ -194,11 +248,14 @@ module.exports = function (registry) {
}
return '';
})()
if (['adoc', 'xml', 'html'].includes(format)) {
const adoc_icon = 'https://avatars.githubusercontent.com/u/3137042?s=200&v=4'
const html_icon = 'https://raw.githubusercontent.com/FortAwesome/Font-Awesome/refs/heads/6.x/svgs/brands/html5.svg'
const code_file_icon = 'https://raw.githubusercontent.com/FortAwesome/Font-Awesome/6.x/svgs/solid/file-code.svg'
const icon = format === 'adoc' ? adoc_icon : format === 'html' ? html_icon : code_file_icon
if (['adoc', 'xml', 'html', 'adoc-asciidoc'].includes(format)) {
const formatIcons = {
adoc: 'https://avatars.githubusercontent.com/u/3137042?s=200&v=4',
html: 'https://raw.githubusercontent.com/FortAwesome/Font-Awesome/refs/heads/6.x/svgs/brands/html5.svg',
'adoc-asciidoc': 'https://raw.githubusercontent.com/FortAwesome/Font-Awesome/refs/heads/6.x/svgs/brands/html5.svg',
default: 'https://raw.githubusercontent.com/FortAwesome/Font-Awesome/6.x/svgs/solid/file-code.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]`
Expand Down
2 changes: 1 addition & 1 deletion docs/extensions/mrdocs-releases.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ module.exports = function (registry) {
for (const suffix of assetSuffixes) {
const asset = release.assets.find(asset => asset.name.endsWith(suffix))
if (asset) {
text += `| ${asset.browser_download_url}[🔗 ${asset.name}]\n\n(${humanizeBytes(asset.size)}) `
text += `| ${asset.browser_download_url}[${asset.name}]\n\n(${humanizeBytes(asset.size)}) `
} else {
text += '| - '
}
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/images/icons/apple.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading