diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d4e6226c3..57bb52c6b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -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
diff --git a/docs/build_docs.sh b/docs/build_docs.sh
old mode 100644
new mode 100755
diff --git a/docs/build_local_docs.sh b/docs/build_local_docs.sh
old mode 100644
new mode 100755
diff --git a/docs/extensions/mrdocs-demos.js b/docs/extensions/mrdocs-demos.js
index 57a8d266b..a722abff3 100644
--- a/docs/extensions/mrdocs-demos.js
+++ b/docs/extensions/mrdocs-demos.js
@@ -13,11 +13,14 @@ 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') :
@@ -25,15 +28,68 @@ function getSubdirectoriesSync(url) {
if (!readFromCacheFile) {
fs.writeFileSync(cachePath, data);
}
- const regex = //g;
- const directories = [];
+
+ // parse entries: name + date (if present)
+ // Matches: name/ [spaces] 11-Sep-2025 20:51
+ const entryRe = /[^<]*<\/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 [];
@@ -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(' | ');
@@ -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]`
diff --git a/docs/extensions/mrdocs-releases.js b/docs/extensions/mrdocs-releases.js
index ec5c14996..5eb708523 100644
--- a/docs/extensions/mrdocs-releases.js
+++ b/docs/extensions/mrdocs-releases.js
@@ -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 += '| - '
}
diff --git a/docs/modules/ROOT/images/icons/apple.svg b/docs/modules/ROOT/images/icons/apple.svg
new file mode 100644
index 000000000..2ad7d19a3
--- /dev/null
+++ b/docs/modules/ROOT/images/icons/apple.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/modules/ROOT/images/icons/asciidoc.svg b/docs/modules/ROOT/images/icons/asciidoc.svg
new file mode 100644
index 000000000..2c525a981
--- /dev/null
+++ b/docs/modules/ROOT/images/icons/asciidoc.svg
@@ -0,0 +1,40 @@
+
+
\ No newline at end of file
diff --git a/docs/modules/ROOT/images/icons/code_blocks.svg b/docs/modules/ROOT/images/icons/code_blocks.svg
new file mode 100644
index 000000000..cd01e11a5
--- /dev/null
+++ b/docs/modules/ROOT/images/icons/code_blocks.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/modules/ROOT/images/icons/html5.svg b/docs/modules/ROOT/images/icons/html5.svg
new file mode 100644
index 000000000..1c994a7bf
--- /dev/null
+++ b/docs/modules/ROOT/images/icons/html5.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/modules/ROOT/images/icons/link.svg b/docs/modules/ROOT/images/icons/link.svg
new file mode 100644
index 000000000..13cf8ebd7
--- /dev/null
+++ b/docs/modules/ROOT/images/icons/link.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/modules/ROOT/images/icons/linux.svg b/docs/modules/ROOT/images/icons/linux.svg
new file mode 100644
index 000000000..6ffc1d99d
--- /dev/null
+++ b/docs/modules/ROOT/images/icons/linux.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/modules/ROOT/images/icons/package.svg b/docs/modules/ROOT/images/icons/package.svg
new file mode 100644
index 000000000..2b977b49d
--- /dev/null
+++ b/docs/modules/ROOT/images/icons/package.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/modules/ROOT/images/icons/windows.svg b/docs/modules/ROOT/images/icons/windows.svg
new file mode 100644
index 000000000..77db4cc65
--- /dev/null
+++ b/docs/modules/ROOT/images/icons/windows.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/ui/build.sh b/docs/ui/build.sh
old mode 100644
new mode 100755