This is an automated email from the ASF dual-hosted git repository.

fmariani pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-website.git


The following commit(s) were added to refs/heads/main by this push:
     new e080a1a1 feat: Expose llms.txt and markdown content that is easily 
accessible to LLMs
e080a1a1 is described below

commit e080a1a1733536d41a3d2f0a3c3a94674f8af0a2
Author: Croway <[email protected]>
AuthorDate: Mon Nov 10 09:53:29 2025 +0100

    feat: Expose llms.txt and markdown content that is easily accessible to LLMs
---
 gulp/helpers/html-index.js      | 180 ++++++++++++++
 gulp/helpers/llms-txt.js        |  22 ++
 gulp/helpers/rss-feed.js        | 106 ++++++++
 gulp/helpers/toon-format.js     |  73 ++++++
 gulp/helpers/turndown-config.js |  87 +++++++
 gulp/tasks/generate-markdown.js | 124 ++++++++++
 gulpfile.js                     |   6 +-
 llms-txt-template.md            |  62 +++++
 package.json                    |  11 +-
 yarn.lock                       | 534 ++++++++++++++++++++++++++++++++++++++--
 10 files changed, 1175 insertions(+), 30 deletions(-)

diff --git a/gulp/helpers/html-index.js b/gulp/helpers/html-index.js
new file mode 100644
index 00000000..4409a8d5
--- /dev/null
+++ b/gulp/helpers/html-index.js
@@ -0,0 +1,180 @@
+const fs = require('fs');
+const { parse } = require('node-html-parser');
+const { createTurndownService } = require('./turndown-config');
+
+/**
+ * Generic function to generate markdown from HTML index pages.
+ *
+ * @param {Object} config - Configuration object
+ * @param {string} config.htmlPath - Path to the HTML file (e.g., 
'public/components/next/index.html')
+ * @param {string} config.title - Title for the markdown file (e.g., 
'Components Index')
+ * @param {string} config.description - Description text (e.g., 'List of all 
Camel components')
+ */
+async function generateHtmlIndex(config) {
+  const { htmlPath, title, description } = config;
+  const mdPath = htmlPath.replace(/\.html$/, '.md');
+
+  try {
+    // Check if file exists
+    if (!fs.existsSync(htmlPath)) {
+      return;
+    }
+
+    const htmlContent = fs.readFileSync(htmlPath, 'utf8');
+    const root = parse(htmlContent);
+
+    // Create turndown service
+    const turndownService = createTurndownService();
+
+    // Extract only the main article content
+    let mainContent = root.querySelector('article.doc') ||
+                     root.querySelector('main') ||
+                     root.querySelector('.article') ||
+                     root.querySelector('article');
+
+    if (!mainContent) {
+      return;
+    }
+
+    // Remove navigation elements
+    const elementsToRemove = mainContent.querySelectorAll('nav, header, 
footer, .nav, .navbar, .toolbar');
+    elementsToRemove.forEach(el => el.remove());
+
+    // Remove anchor links
+    const anchors = mainContent.querySelectorAll('a.anchor');
+    anchors.forEach(el => el.remove());
+
+    // Clean up table cells by unwrapping div.content and div.paragraph 
wrappers
+    const tableCells = mainContent.querySelectorAll('td.tableblock, 
th.tableblock');
+    tableCells.forEach(cell => {
+      let html = cell.innerHTML;
+      // Unwrap <div class="content"><div 
class="paragraph"><p>...</p></div></div>
+      html = html.replace(/<div class="content"><div 
class="paragraph">\s*<p>(.*?)<\/p>\s*<\/div><\/div>/gs, '$1');
+      // Unwrap <div class="content"><div id="..." 
class="paragraph"><p>...</p></div></div>
+      html = html.replace(/<div 
class="content"><div[^>]*class="paragraph"[^>]*>\s*<p>(.*?)<\/p>\s*<\/div><\/div>/gs,
 '$1');
+      // Also handle simple <p class="tableblock">...</p> wrappers
+      html = html.replace(/<p class="tableblock">(.*?)<\/p>/gs, '$1');
+      cell.set_content(html);
+    });
+
+    // Convert to Markdown
+    let markdown = turndownService.turndown(mainContent.innerHTML);
+
+    // Update links to point to .md files instead of .html
+    // Replace https://camel.apache.org/**/*.html with 
https://camel.apache.org/**/*.md
+    markdown = 
markdown.replace(/(https:\/\/camel\.apache\.org\/[^)\s]*?)\.html/g, '$1.md');
+    // Replace relative links *.html with *.md
+    markdown = markdown.replace(/\[([^\]]+)\]\(([^)]+?)\.html\)/g, 
'[$1]($2.md)');
+
+    // Add header if title and description provided
+    if (title && description) {
+      markdown = `# ${title}\n\n${description}\n\n${markdown}`;
+    }
+
+    // Write markdown file
+    fs.writeFileSync(mdPath, markdown, 'utf8');
+  } catch (error) {
+    console.error(`Error generating markdown for ${htmlPath}:`, error.message);
+  }
+}
+
+/**
+ * Generates markdown for all index files (HTML index pages).
+ * This function processes all the index files specified in the configuration.
+ */
+async function generateAllIndexes() {
+  console.log('\nGenerating markdown for all index files...');
+
+  const glob = require('glob');
+
+  // Define all HTML index files to process
+  const htmlIndexes = [
+    {
+      htmlPath: 'public/camel-k/next/index.html',
+      title: 'Camel K Documentation Index',
+      description: 'Index of Camel K documentation pages.'
+    },
+    {
+      htmlPath: 'public/camel-kafka-connector/next/index.html',
+      title: 'Camel Kafka Connector Documentation Index',
+      description: 'Index of Camel Kafka Connector documentation pages.'
+    },
+    {
+      htmlPath: 'public/camel-kamelets/next/index.html',
+      title: 'Camel Kamelets Documentation Index',
+      description: 'Index of Camel Kamelets documentation pages.'
+    },
+    {
+      htmlPath: 'public/camel-quarkus/next/index.html',
+      title: 'Camel Quarkus Documentation Index',
+      description: 'Index of Camel Quarkus documentation pages.'
+    },
+    {
+      htmlPath: 'public/camel-spring-boot/next/index.html',
+      title: 'Camel Spring Boot Documentation Index',
+      description: 'Index of Camel Spring Boot documentation pages.'
+    },
+    {
+      htmlPath: 'public/components/next/index.html',
+      title: 'Components Index',
+      description: 'Index of all Camel components.'
+    },
+    {
+      htmlPath: 'public/components/next/others/index.html',
+      title: 'Other Components Index',
+      description: 'Index of other Camel components.'
+    },
+    {
+      htmlPath: 'public/components/next/languages/index.html',
+      title: 'Languages Index',
+      description: 'Index of Camel expression and predicate languages.'
+    },
+    {
+      htmlPath: 'public/components/next/eips/index.html',
+      title: 'Enterprise Integration Patterns Index',
+      description: 'Index of Enterprise Integration Patterns (EIPs).'
+    },
+    {
+      htmlPath: 'public/components/next/dataformats/index.html',
+      title: 'Data Formats Index',
+      description: 'Index of Camel data formats.'
+    },
+    {
+      htmlPath: 'public/manual/index.html',
+      title: 'User Manual Index',
+      description: 'Index of Apache Camel user manual pages.'
+    },
+    {
+      htmlPath: 'public/manual/faq/index.html',
+      title: 'FAQ Index',
+      description: 'Frequently Asked Questions about Apache Camel.'
+    },
+    {
+      htmlPath: 'public/releases/index.html',
+      title: 'Releases Index',
+      description: 'Apache Camel version releases Index.'
+    }
+  ];
+
+  // Process all HTML indexes
+  for (const config of htmlIndexes) {
+    await generateHtmlIndex(config);
+  }
+
+  // Find all index.html files under public/releases/**/
+  console.log('\nGenerating markdown for all release index files...');
+  const releaseIndexFiles = glob.sync('public/releases/**/index.html');
+  console.log(`Found ${releaseIndexFiles.length} release index files to 
process`);
+
+  // Process each release index file without custom title/description
+  for (const htmlPath of releaseIndexFiles) {
+    await generateHtmlIndex({ htmlPath });
+  }
+
+  console.log('All index files generation complete');
+}
+
+module.exports = {
+  generateHtmlIndex,
+  generateAllIndexes
+};
diff --git a/gulp/helpers/llms-txt.js b/gulp/helpers/llms-txt.js
new file mode 100644
index 00000000..8f23afdc
--- /dev/null
+++ b/gulp/helpers/llms-txt.js
@@ -0,0 +1,22 @@
+const fs = require('fs');
+const path = require('path');
+
+/**
+ * Generates the /llms.txt file as per https://llmstxt.org/ specification.
+ * This file helps LLMs discover and understand the structure of the 
documentation.
+ * Reads from llms-txt-template.md and uses it as content.
+ *
+ * @param {Array<string>} pages - Array of page URLs that were converted to 
markdown
+ */
+function generateLlmsTxt(pages) {
+  // Read the template file
+  const templatePath = path.join(__dirname, '../../llms-txt-template.md');
+  let llmsTxtContent = fs.readFileSync(templatePath, 'utf8');
+
+  fs.writeFileSync('public/llms.txt', llmsTxtContent, 'utf8');
+  console.log('Generated /llms.txt');
+}
+
+module.exports = {
+  generateLlmsTxt
+};
diff --git a/gulp/helpers/rss-feed.js b/gulp/helpers/rss-feed.js
new file mode 100644
index 00000000..a8578909
--- /dev/null
+++ b/gulp/helpers/rss-feed.js
@@ -0,0 +1,106 @@
+const fs = require('fs');
+const xml2js = require('xml2js');
+
+/**
+ * Generic function to generate toon format markdown from RSS XML feeds.
+ * Converts RSS feeds to plain text files (.md) as per 
https://github.com/toon-format/toon specification.
+ *
+ * @param {Object} config - Configuration object
+ * @param {string} config.xmlPath - Path to the XML file (e.g., 
'public/blog/index.xml')
+ * @param {string} config.title - Title for the markdown file (e.g., 'Apache 
Camel Blog')
+ * @param {string} config.description - Description text (e.g., 'Blog posts 
about Apache Camel')
+ * @param {string} config.itemsName - Name for the items collection (e.g., 
'posts', 'releases')
+ */
+async function generateRssFeedIndex(config) {
+  const parser = new xml2js.Parser();
+
+  const { xmlPath, title, description, itemsName } = config;
+  const mdPath = xmlPath.replace(/\.xml$/, '.md');
+
+  try {
+    // Check if file exists
+    if (!fs.existsSync(xmlPath)) {
+      return;
+    }
+
+    // Read XML file
+    const xmlContent = fs.readFileSync(xmlPath, 'utf8');
+
+    // Parse XML to JavaScript object
+    const result = await parser.parseStringPromise(xmlContent);
+
+    let toonContent = '';
+
+    // Check if it's an RSS feed
+    if (result.rss && result.rss.channel && result.rss.channel[0]) {
+      const channel = result.rss.channel[0];
+      const items = channel.item || [];
+
+      // Create toon format header
+      toonContent = `# ${title}\n\n`;
+      toonContent += `${description}\n\n`;
+      toonContent += 
`${itemsName}[${items.length}]{title,link,pubDate,description}:\n`;
+
+      // Add each item
+      for (const item of items) {
+        const itemTitle = item.title ? item.title[0] : '';
+        const link = item.link ? item.link[0] : '';
+        const pubDate = item.pubDate ? item.pubDate[0] : '';
+        const itemDesc = item.description ? item.description[0].replace(/\n/g, 
' ').substring(0, 200) : '';
+
+        // Convert links to markdown format
+        let mdLink = link;
+        if (mdLink.endsWith('/')) {
+          mdLink = mdLink + 'index.md';
+        } else {
+          mdLink = mdLink.replace(/\.html$/, '.md');
+        }
+
+        toonContent += `  ${itemTitle}|${mdLink}|${pubDate}|${itemDesc}\n`;
+      }
+    }
+
+    // Write toon format file
+    fs.writeFileSync(mdPath, toonContent, 'utf8');
+  } catch (error) {
+    console.error(`Error generating toon format for ${xmlPath}:`, 
error.message);
+  }
+}
+
+/**
+ * Generates toon format markdown for the Releases category RSS feed.
+ * Converts public/categories/Releases/index.xml to index.md
+ * as per https://github.com/toon-format/toon specification.
+ */
+async function generateReleasesIndex() {
+  console.log('\nGenerating toon format for Releases index...');
+  await generateRssFeedIndex({
+    xmlPath: 'public/categories/Releases/index.xml',
+    title: 'Apache Camel Releases',
+    description: 'Release feed for Apache Camel and related projects.',
+    itemsName: 'releases'
+  });
+  console.log('Releases index toon format generation complete');
+}
+
+/**
+ * Generates toon format markdown for the Blog RSS feed.
+ * Converts public/blog/index.xml to index.md
+ * as per https://github.com/toon-format/toon specification.
+ */
+async function generateBlogIndex() {
+  console.log('\nGenerating toon format for Blog index...');
+  await generateRssFeedIndex({
+    xmlPath: 'public/blog/index.xml',
+    title: 'Apache Camel Blog',
+    description: 'Blog posts about Apache Camel and related topics.',
+    itemsName: 'posts'
+  });
+  console.log('Blog index toon format generation complete');
+}
+
+module.exports = {
+  generateRssFeedIndex,
+  generateReleasesIndex,
+  generateBlogIndex
+};
diff --git a/gulp/helpers/toon-format.js b/gulp/helpers/toon-format.js
new file mode 100644
index 00000000..ccde19a0
--- /dev/null
+++ b/gulp/helpers/toon-format.js
@@ -0,0 +1,73 @@
+const fs = require('fs');
+const path = require('path');
+const xml2js = require('xml2js');
+
+/**
+ * Generates toon format sitemaps from XML sitemaps.
+ * Converts all sitemap*.xml files to toon format (.md files)
+ * as per https://github.com/toon-format/toon specification.
+ */
+async function generateToonSitemaps() {
+  const parser = new xml2js.Parser();
+  const glob = require('glob');
+
+  console.log('\nGenerating toon format sitemaps...');
+
+  // Find all sitemap*.xml files in the public directory
+  const sitemapFiles = glob.sync('public/sitemap*.xml');
+
+  if (sitemapFiles.length === 0) {
+    return;
+  }
+
+  for (const xmlPath of sitemapFiles) {
+    const sitemapFile = path.basename(xmlPath);
+    const toonPath = xmlPath.replace(/\.xml$/, '.md');
+
+    try {
+      // Read XML file
+      const xmlContent = fs.readFileSync(xmlPath, 'utf8');
+
+      // Parse XML to JavaScript object
+      const result = await parser.parseStringPromise(xmlContent);
+
+      let toonContent = '';
+
+      // Check if it's a sitemap index or a urlset
+      if (result.sitemapindex) {
+        // This is a sitemap index (sitemap.xml)
+        const sitemaps = result.sitemapindex.sitemap || [];
+        toonContent = `sitemaps[${sitemaps.length}]{loc}:\n`;
+        for (const sitemap of sitemaps) {
+          let loc = sitemap.loc ? sitemap.loc[0] : '';
+          // Convert .xml URLs to .md
+          loc = loc.replace(/\.xml$/, '.md');
+          toonContent += `  ${loc}\n`;
+        }
+      } else if (result.urlset) {
+        // This is a regular sitemap with URLs
+        const urls = result.urlset.url || [];
+        toonContent = `urls[${urls.length}]{loc,lastmod}:\n`;
+        for (const url of urls) {
+          let loc = url.loc ? url.loc[0] : '';
+          const lastmod = url.lastmod ? url.lastmod[0] : '';
+          // Convert .html URLs to .md
+          loc = loc.replace(/\.html$/, '.md');
+          toonContent += `  ${loc},${lastmod}\n`;
+        }
+      }
+
+      // Write toon format file
+      fs.writeFileSync(toonPath, toonContent, 'utf8');
+      console.log(`Generated ${sitemapFile.replace('.xml', '.md')}`);
+    } catch (error) {
+      console.error(`Error generating toon sitemap for ${sitemapFile}:`, 
error.message);
+    }
+  }
+
+  console.log(`Toon format sitemaps generation complete - 
${sitemapFiles.length} files converted`);
+}
+
+module.exports = {
+  generateToonSitemaps
+};
diff --git a/gulp/helpers/turndown-config.js b/gulp/helpers/turndown-config.js
new file mode 100644
index 00000000..7b503ab8
--- /dev/null
+++ b/gulp/helpers/turndown-config.js
@@ -0,0 +1,87 @@
+const TurndownService = require('turndown');
+const turndownPluginGfm = require('turndown-plugin-gfm');
+
+/**
+ * Creates and configures a TurndownService instance for converting HTML to 
Markdown.
+ * Includes custom rules for Asciidoctor admonition blocks, table wrappers, 
and icons.
+ *
+ * @returns {TurndownService} Configured Turndown service instance
+ */
+function createTurndownService() {
+  const turndownService = new TurndownService({
+    headingStyle: 'atx',
+    codeBlockStyle: 'fenced',
+    bulletListMarker: '-',
+    emDelimiter: '_',
+  });
+
+  // Use GitHub-flavored Markdown for tables, strikethrough, etc.
+  const gfm = turndownPluginGfm.gfm;
+  turndownService.use(gfm);
+
+  // Custom rule to convert Asciidoctor admonition blocks to readable Markdown
+  turndownService.addRule('admonitionBlocks', {
+    filter: function (node) {
+      return node.classList && node.classList.contains('admonitionblock');
+    },
+    replacement: function (content, node) {
+      // Extract the icon type (tip, note, important, warning, caution)
+      const iconElement = node.querySelector('.icon i');
+      let admonitionType = 'Note';
+
+      if (iconElement) {
+        const title = iconElement.getAttribute('title') || '';
+        admonitionType = title || 'Note';
+      }
+
+      // Extract the content text
+      const contentDiv = node.querySelector('.content');
+      if (!contentDiv) return '';
+
+      // Convert the content div to markdown
+      const contentHtml = contentDiv.innerHTML;
+      const contentMarkdown = turndownService.turndown(contentHtml);
+
+      // Format as a blockquote with the admonition type
+      const lines = contentMarkdown.split('\n');
+      const quotedLines = lines.map(line => line ? `> ${line}` : '>');
+
+      return `\n> **${admonitionType}**\n${quotedLines.join('\n')}\n\n`;
+    }
+  });
+
+  // Custom rule to handle table-wrapper divs
+  turndownService.addRule('tableWrapper', {
+    filter: function (node) {
+      return node.classList && node.classList.contains('table-wrapper');
+    },
+    replacement: function (content, node) {
+      // Just extract the table inside
+      const table = node.querySelector('table');
+      if (table) {
+        return turndownService.turndown(table.outerHTML);
+      }
+      return content;
+    }
+  });
+
+  // Custom rule to clean up icon elements and other UI-only content
+  turndownService.addRule('removeIcons', {
+    filter: function (node) {
+      // Remove icon elements, anchors without text, etc.
+      if (node.classList) {
+        return node.classList.contains('icon') ||
+               node.classList.contains('anchor') ||
+               (node.tagName === 'I' && node.classList.contains('fa'));
+      }
+      return false;
+    },
+    replacement: function () {
+      return '';
+    }
+  });
+
+  return turndownService;
+}
+
+module.exports = { createTurndownService };
diff --git a/gulp/tasks/generate-markdown.js b/gulp/tasks/generate-markdown.js
new file mode 100644
index 00000000..cc5964e8
--- /dev/null
+++ b/gulp/tasks/generate-markdown.js
@@ -0,0 +1,124 @@
+const fs = require('fs');
+const { parse } = require('node-html-parser');
+const { createTurndownService } = require('../helpers/turndown-config');
+const { generateToonSitemaps } = require('../helpers/toon-format');
+const { generateLlmsTxt } = require('../helpers/llms-txt');
+const { generateReleasesIndex, generateBlogIndex } = 
require('../helpers/rss-feed');
+const { generateAllIndexes } = require('../helpers/html-index');
+
+/**
+ * Generates Markdown (.md) files from HTML files for LLM consumption.
+ * This task converts HTML documentation pages to Markdown format, making them
+ * accessible to LLMs as per https://llmstxt.org/ specification.
+ *
+ * For each .html file, it creates a corresponding .md file with:
+ * - Only the main article content (excluding nav, header, footer)
+ * - Clean Markdown formatting using Turndown
+ * - GitHub-flavored Markdown for tables and code blocks
+ */
+async function generateMarkdown(done) {
+  const turndownService = createTurndownService();
+
+  // Keep track of processed files for llms.txt
+  const processedPages = [];
+
+  const glob = require('glob');
+
+  // Get all HTML files
+  const htmlFiles = glob.sync('public/**/*.html', {
+    ignore: ['public/404.html', 'public/**/index.html'] // Skip error pages 
and index pages
+  });
+
+  let processedCount = 0;
+  const totalFiles = htmlFiles.length;
+  const BATCH_SIZE = 500; // Process in batches to avoid memory issues
+
+  console.log(`Found ${totalFiles} HTML files to convert`);
+
+  // Process files in batches
+  for (let i = 0; i < htmlFiles.length; i += BATCH_SIZE) {
+    const batch = htmlFiles.slice(i, i + BATCH_SIZE);
+
+    for (const htmlFile of batch) {
+      try {
+        const htmlContent = fs.readFileSync(htmlFile, 'utf8');
+        const root = parse(htmlContent);
+
+        // Extract only the main article content
+        // Try different selectors based on Antora and Hugo structure
+        let mainContent = root.querySelector('article.doc') ||
+                         root.querySelector('main') ||
+                         root.querySelector('.article') ||
+                         root.querySelector('article');
+
+        if (!mainContent) {
+          // Silently skip files without main content
+          continue;
+        }
+
+        // Remove navigation elements, headers, and footers from the content
+        const elementsToRemove = mainContent.querySelectorAll('nav, header, 
footer, .nav, .navbar, .toolbar');
+        elementsToRemove.forEach(el => el.remove());
+
+        // Remove anchor links (they are just UI navigation aids)
+        const anchors = mainContent.querySelectorAll('a.anchor');
+        anchors.forEach(el => el.remove());
+
+        // Clean up table cells by unwrapping div.content and div.paragraph 
wrappers
+        const tableCells = mainContent.querySelectorAll('td.tableblock, 
th.tableblock');
+        tableCells.forEach(cell => {
+          let html = cell.innerHTML;
+          // Unwrap <div class="content"><div 
class="paragraph"><p>...</p></div></div>
+          html = html.replace(/<div class="content"><div 
class="paragraph">\s*<p>(.*?)<\/p>\s*<\/div><\/div>/gs, '$1');
+          // Unwrap <div class="content"><div id="..." 
class="paragraph"><p>...</p></div></div>
+          html = html.replace(/<div 
class="content"><div[^>]*class="paragraph"[^>]*>\s*<p>(.*?)<\/p>\s*<\/div><\/div>/gs,
 '$1');
+          // Also handle simple <p class="tableblock">...</p> wrappers
+          html = html.replace(/<p class="tableblock">(.*?)<\/p>/gs, '$1');
+          cell.set_content(html);
+        });
+
+        // Convert to Markdown
+        let markdown = turndownService.turndown(mainContent.innerHTML);
+
+        // Update links to point to .md files instead of .html
+        // Replace https://camel.apache.org/**/*.html with 
https://camel.apache.org/**/*.md
+        markdown = 
markdown.replace(/(https:\/\/camel\.apache\.org\/[^)\s]*?)\.html/g, '$1.md');
+        // Replace relative links *.html with *.md
+        markdown = markdown.replace(/\[([^\]]+)\]\(([^)]+?)\.html\)/g, 
'[$1]($2.md)');
+
+        // Write .md file (replace .html extension with .md)
+        const mdFile = htmlFile.replace(/\.html$/, '.md');
+        fs.writeFileSync(mdFile, markdown, 'utf8');
+
+        // Track for llms.txt (convert to URL path)
+        const urlPath = htmlFile.replace('public/', '/').replace('.html', 
'.md');
+        processedPages.push(urlPath);
+
+        processedCount++;
+      } catch (error) {
+        console.error(`Error processing ${htmlFile}:`, error.message);
+      }
+    }
+  }
+
+  console.log(`\nSuccessfully generated ${processedCount} Markdown files`);
+
+  // Generate llms.txt file
+  generateLlmsTxt(processedPages);
+
+  // Generate toon format sitemaps
+  await generateToonSitemaps();
+
+  // Generate toon format for releases RSS feed
+  await generateReleasesIndex();
+
+  // Generate toon format for blog RSS feed
+  await generateBlogIndex();
+
+  // Generate all other index files
+  await generateAllIndexes();
+
+  done();
+}
+
+module.exports = generateMarkdown;
diff --git a/gulpfile.js b/gulpfile.js
index 853e669f..5e704165 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -2,7 +2,8 @@ const cheerio = require('gulp-cheerio');
 const env = process.env.CAMEL_ENV || 'development';
 const gulp = require('gulp');
 const htmlmin = require('gulp-htmlmin');
-const inject = require('gulp-inject')
+const inject = require('gulp-inject');
+const generateMarkdown = require('./gulp/tasks/generate-markdown');
 
 /**
  * We minify all HTML files using htmlmin, this is to make them smaller in size
@@ -113,6 +114,9 @@ function versionlessRedirects (text) {
   return processed.join('\n')
 }
 
+// Register the generate-markdown task
+gulp.task('generate-markdown', generateMarkdown);
+
 /*
  * Removes the content from the `public` directory.
  */
diff --git a/llms-txt-template.md b/llms-txt-template.md
new file mode 100644
index 00000000..5216e3f2
--- /dev/null
+++ b/llms-txt-template.md
@@ -0,0 +1,62 @@
+# Apache Camel
+
+> Apache Camel is an open source integration framework that empowers you to 
quickly and easily integrate various systems consuming or producing data. It 
provides 300+ components, Enterprise Integration Patterns (EIPs), multiple 
DSLs, and runs on various runtimes including Spring Boot, Quarkus, and 
Kubernetes.
+
+All Apache Camel documentation pages are available in LLM-friendly Markdown 
format by replacing `.html` with `.md` in any URL.
+For example:
+- HTML: 
`https://camel.apache.org/components/next/languages/simple-language.html`
+- Markdown: 
`https://camel.apache.org/components/next/languages/simple-language.md`
+
+## Overview
+
+- [Getting Started](https://camel.apache.org/manual/getting-started.md): Quick 
start guide for Apache Camel.
+- [User Manual](https://camel.apache.org/manual/index.md): Complete user guide 
and reference documentation.
+- [FAQ](https://camel.apache.org/manual/faq/index.md): Frequently Asked 
Questions about Apache Camel.
+- [Releases](https://camel.apache.org/releases/index.md): Apache Camel 
Releases and version history.
+- [Blog](https://camel.apache.org/blog/index.md): Latest blog posts about 
Apache Camel.
+
+## Components
+
+- [Components Index](https://camel.apache.org/components/next/index.md): 
Complete list of all Camel components (300+).
+- [Languages](https://camel.apache.org/components/next/languages/index.md): 
Expression and predicate languages (Simple, XPath, JSONPath, etc.).
+- [Enterprise Integration Patterns 
(EIPs)](https://camel.apache.org/components/next/eips/index.md): Message 
routing and transformation patterns.
+- [Data 
Formats](https://camel.apache.org/components/next/dataformats/index.md): Data 
marshalling and unmarshalling formats.
+- [Other 
Components](https://camel.apache.org/components/next/others/index.md): 
Additional Camel components and utilities.
+
+## Runtimes & Frameworks
+
+- [Camel Quarkus](https://camel.apache.org/camel-quarkus/next/index.md): Camel 
extensions for Quarkus runtime.
+- [Camel Spring 
Boot](https://camel.apache.org/camel-spring-boot/next/index.md): Camel 
integration with Spring Boot.
+- [Camel K](https://camel.apache.org/camel-k/next/index.md): Lightweight 
integration framework for Kubernetes.
+- [Camel Kafka 
Connector](https://camel.apache.org/camel-kafka-connector/next/index.md): Kafka 
Connect connectors based on Camel.
+- [Camel Kamelets](https://camel.apache.org/camel-kamelets/next/index.md): 
Route snippets for common integration scenarios.
+
+## Examples
+
+- [Camel 
Examples](https://github.com/apache/camel-examples/blob/main/README.adoc): Core 
Camel examples repository.
+- [Camel JBang Examples](https://github.com/apache/camel-jbang-examples): 
Examples using Camel JBang.
+- [Camel Quarkus 
Examples](https://camel.apache.org/camel-quarkus/next/user-guide/examples.md): 
Quarkus integration examples.
+- [Camel Spring Boot 
Examples](https://github.com/apache/camel-spring-boot-examples/blob/main/README.adoc):
 Spring Boot integration examples.
+- [Camel K 
Examples](https://github.com/apache/camel-k-examples/blob/main/generic-examples/README.md):
 Kubernetes integration examples.
+- [Camel Kamelets 
Examples](https://github.com/apache/camel-kamelets-examples): Kamelets usage 
examples.
+- [Camel Kafka Connector 
Examples](https://github.com/apache/camel-kafka-connector-examples/blob/main/README.adoc):
 Kafka Connect examples.
+
+## Sitemaps
+
+- [Main Sitemap](https://camel.apache.org/sitemap.md): Complete sitemap index.
+- [Camel Core](https://camel.apache.org/sitemap-camel-core.md): Core Camel 
documentation sitemap.
+- [Camel K](https://camel.apache.org/sitemap-camel-k.md): Camel K 
documentation sitemap.
+- [Camel Kafka 
Connector](https://camel.apache.org/sitemap-camel-kafka-connector.md): Camel 
Kafka Connector sitemap.
+- [Camel Kamelets](https://camel.apache.org/sitemap-camel-kamelets.md): Camel 
Kamelets sitemap.
+- [Camel Quarkus](https://camel.apache.org/sitemap-camel-quarkus.md): Camel 
Quarkus sitemap.
+- [Camel Spring Boot](https://camel.apache.org/sitemap-camel-spring-boot.md): 
Camel Spring Boot sitemap.
+- [Components](https://camel.apache.org/sitemap-components.md): Components 
documentation sitemap.
+- [Manual](https://camel.apache.org/sitemap-manual.md): User manual sitemap.
+
+## Additional Resources
+
+- [Migration and Upgrade 
Guides](https://camel.apache.org/manual/migration-and-upgrade.md): Apache Camel 
Migration and Upgrade Guides
+- [Camel Update Recipes](https://github.com/apache/camel-upgrade-recipes): 
Open rewrite recipes that can be used to automatically update Camel applications
+- [GitHub](https://github.com/apache/camel): Source code repository.
+- [Community](https://camel.apache.org/community/): Community resources and 
how to contribute.
+- [Camel JBang](https://camel.apache.org/manual/camel-jbang.md): Run Camel 
routes from the command line.
diff --git a/package.json b/package.json
index fcbedee2..d4a5b24b 100644
--- a/package.json
+++ b/package.json
@@ -3,12 +3,13 @@
   "version": "1.0.0-SNAPSHOT",
   "license": "Apache-2.0",
   "scripts": {
-    "build": "run-s -l build:antora build:hugo build:sitemap build:htaccess 
build:minify",
+    "build": "run-s -l build:antora build:hugo build:sitemap build:htaccess 
build:markdown build:minify",
     "build-all": "yarn workspaces foreach --all --topological-dev run build",
     "build:antora": "run-s -l build:antora-prep build:antora-perf",
     "build:antora-prep": "yarn exec 
antora-playbook-snippets/assemble-playbook.sh antora-playbook-production.yml 
playbook-export-site-manifest.yml",
     "build:antora-perf": "antora --clean --fetch 
antora-playbook-production.yml --stacktrace",
     "build:hugo": "hugo --cacheDir ${HUGO_CACHE_DIR:-$(pwd)/.hugo_data} 
${HUGO_OPTIONS:-}",
+    "build:markdown": "gulp generate-markdown",
     "build:minify": "gulp minify",
     "build:sitemap": "gulp sitemap",
     "build:htaccess": "gulp htaccess",
@@ -49,6 +50,7 @@
     "chalk": "5.3.0",
     "del": "^6.0.0",
     "escape-string-regexp": "~2.0",
+    "glob": "^11.0.3",
     "gulp": "~4.0",
     "gulp-cheerio": "~1.0",
     "gulp-htmlmin": "~5.0",
@@ -56,11 +58,16 @@
     "html-validate": "^8.9.1",
     "hugo-extended": "^0.121.2",
     "js-yaml": "~4.1.0",
+    "jsdom": "^27.1.0",
     "netlify-cli": "17.26.3",
+    "node-html-parser": "^7.0.1",
     "npm-run-all": "~4",
     "opal-runtime": "1.0.11",
     "pino-pretty": "^5.0.0",
-    "toml": "~3.0"
+    "toml": "~3.0",
+    "turndown": "^7.2.2",
+    "turndown-plugin-gfm": "^1.0.2",
+    "xml2js": "^0.6.2"
   },
   "workspaces": [
     "antora-ui-camel",
diff --git a/yarn.lock b/yarn.lock
index b97f8cab..a406ea53 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5,6 +5,13 @@ __metadata:
   version: 8
   cacheKey: 10
 
+"@acemir/cssom@npm:^0.9.19":
+  version: 0.9.23
+  resolution: "@acemir/cssom@npm:0.9.23"
+  checksum: 
10/752294359ddf691f402bf871f347c1d5ea8532ead5e197cf60eeb7ab25bdd6f6e98fc7fad74042f2e423bb45fe7e4a049db645e01fa0781a0ed4ea2cec911047
+  languageName: node
+  linkType: hard
+
 "@algolia/cache-browser-local-storage@npm:4.5.1":
   version: 4.5.1
   resolution: "@algolia/cache-browser-local-storage@npm:4.5.1"
@@ -348,6 +355,39 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@asamuzakjp/css-color@npm:^4.0.3":
+  version: 4.0.5
+  resolution: "@asamuzakjp/css-color@npm:4.0.5"
+  dependencies:
+    "@csstools/css-calc": "npm:^2.1.4"
+    "@csstools/css-color-parser": "npm:^3.1.0"
+    "@csstools/css-parser-algorithms": "npm:^3.0.5"
+    "@csstools/css-tokenizer": "npm:^3.0.4"
+    lru-cache: "npm:^11.2.1"
+  checksum: 
10/7021b5f200793a652fa64e181c6233b5910002575be2bff9d1bc63fcc8198837bab2bee36bf309a26f433ac006fb1b2869217d8198c901c89d79e47e8dd9d805
+  languageName: node
+  linkType: hard
+
+"@asamuzakjp/dom-selector@npm:^6.7.3":
+  version: 6.7.4
+  resolution: "@asamuzakjp/dom-selector@npm:6.7.4"
+  dependencies:
+    "@asamuzakjp/nwsapi": "npm:^2.3.9"
+    bidi-js: "npm:^1.0.3"
+    css-tree: "npm:^3.1.0"
+    is-potential-custom-element-name: "npm:^1.0.1"
+    lru-cache: "npm:^11.2.2"
+  checksum: 
10/dc550a4e32b956bfc820795e73bb3cae963496101a6dc1ebbd0cad409e734dadbcfbac22a44034c28ec401ee1454a379c64cc02d11eb2186e74c638482d8b2e1
+  languageName: node
+  linkType: hard
+
+"@asamuzakjp/nwsapi@npm:^2.3.9":
+  version: 2.3.9
+  resolution: "@asamuzakjp/nwsapi@npm:2.3.9"
+  checksum: 
10/95a6d1c102e1117fe818da087fcc5b914d23e0699855991bae50b891435dd1945ad7d384198f8bcf616207fd85b7ec32e3db6b96e9309d84c6903b8dc4151e34
+  languageName: node
+  linkType: hard
+
 "@asciidoctor/core@npm:^3.0.2":
   version: 3.0.2
   resolution: "@asciidoctor/core@npm:3.0.2"
@@ -517,6 +557,36 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@csstools/color-helpers@npm:^5.1.0":
+  version: 5.1.0
+  resolution: "@csstools/color-helpers@npm:5.1.0"
+  checksum: 
10/0138b3d5ccbe77aeccf6721fd008a53523c70e932f0c82dca24a1277ca780447e1d8357da47512ebf96358476f8764de57002f3e491920d67e69202f5a74c383
+  languageName: node
+  linkType: hard
+
+"@csstools/css-calc@npm:^2.1.4":
+  version: 2.1.4
+  resolution: "@csstools/css-calc@npm:2.1.4"
+  peerDependencies:
+    "@csstools/css-parser-algorithms": ^3.0.5
+    "@csstools/css-tokenizer": ^3.0.4
+  checksum: 
10/06975b650c0f44c60eeb7afdb3fd236f2dd607b2c622e0bc908d3f54de39eb84e0692833320d03dac04bd6c1ab0154aa3fa0dd442bd9e5f917cf14d8e2ba8d74
+  languageName: node
+  linkType: hard
+
+"@csstools/css-color-parser@npm:^3.1.0":
+  version: 3.1.0
+  resolution: "@csstools/css-color-parser@npm:3.1.0"
+  dependencies:
+    "@csstools/color-helpers": "npm:^5.1.0"
+    "@csstools/css-calc": "npm:^2.1.4"
+  peerDependencies:
+    "@csstools/css-parser-algorithms": ^3.0.5
+    "@csstools/css-tokenizer": ^3.0.4
+  checksum: 
10/4741095fdc4501e8e7ada4ed14fbf9dbbe6fea9b989818790ebca15657c29c62defbebacf18592cde2aa638a1d098bbe86d742d2c84ba932fbc00fac51cb8805
+  languageName: node
+  linkType: hard
+
 "@csstools/css-parser-algorithms@npm:^2.3.1":
   version: 2.5.0
   resolution: "@csstools/css-parser-algorithms@npm:2.5.0"
@@ -526,6 +596,22 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@csstools/css-parser-algorithms@npm:^3.0.5":
+  version: 3.0.5
+  resolution: "@csstools/css-parser-algorithms@npm:3.0.5"
+  peerDependencies:
+    "@csstools/css-tokenizer": ^3.0.4
+  checksum: 
10/e93083b5cb36a3c1e7a47ce10cf62961d05bd1e4c608bb3ee50186ff740157ab0ec16a3956f7b86251efd10703034d849693201eea858ae904848c68d2d46ada
+  languageName: node
+  linkType: hard
+
+"@csstools/css-syntax-patches-for-csstree@npm:^1.0.14":
+  version: 1.0.15
+  resolution: "@csstools/css-syntax-patches-for-csstree@npm:1.0.15"
+  checksum: 
10/73526cc73df98a2bf1dc0ec63e489d775131e92397e994d04843b7cd5da0ed2c9a849f5262005630f10cb41a5d1f28d0a22a496654c8941fd7bf41f3e83b734c
+  languageName: node
+  linkType: hard
+
 "@csstools/css-tokenizer@npm:^2.2.0":
   version: 2.2.3
   resolution: "@csstools/css-tokenizer@npm:2.2.3"
@@ -533,6 +619,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@csstools/css-tokenizer@npm:^3.0.4":
+  version: 3.0.4
+  resolution: "@csstools/css-tokenizer@npm:3.0.4"
+  checksum: 
10/eb6c84c086312f6bb8758dfe2c85addd7475b0927333c5e39a4d59fb210b9810f8c346972046f95e60a721329cffe98895abe451e51de753ad1ca7a8c24ec65f
+  languageName: node
+  linkType: hard
+
 "@csstools/media-query-list-parser@npm:^2.1.4":
   version: 2.1.7
   resolution: "@csstools/media-query-list-parser@npm:2.1.7"
@@ -1129,6 +1222,22 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@isaacs/balanced-match@npm:^4.0.1":
+  version: 4.0.1
+  resolution: "@isaacs/balanced-match@npm:4.0.1"
+  checksum: 
10/102fbc6d2c0d5edf8f6dbf2b3feb21695a21bc850f11bc47c4f06aa83bd8884fde3fe9d6d797d619901d96865fdcb4569ac2a54c937992c48885c5e3d9967fe8
+  languageName: node
+  linkType: hard
+
+"@isaacs/brace-expansion@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "@isaacs/brace-expansion@npm:5.0.0"
+  dependencies:
+    "@isaacs/balanced-match": "npm:^4.0.1"
+  checksum: 
10/cf3b7f206aff12128214a1df764ac8cdbc517c110db85249b945282407e3dfc5c6e66286383a7c9391a059fc8e6e6a8ca82262fc9d2590bd615376141fbebd2d
+  languageName: node
+  linkType: hard
+
 "@isaacs/cliui@npm:^8.0.2":
   version: 8.0.2
   resolution: "@isaacs/cliui@npm:8.0.2"
@@ -1251,6 +1360,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@mixmark-io/domino@npm:^2.2.0":
+  version: 2.2.0
+  resolution: "@mixmark-io/domino@npm:2.2.0"
+  checksum: 
10/839624ba6baab655c4f7393e8b8561516849926651e02f40484729b9869436b1e077906810bcac0bba4762448512d3ebd2f6d9b463d8ab0d5f54d75ca5306519
+  languageName: node
+  linkType: hard
+
 "@netlify/binary-info@npm:^1.0.0":
   version: 1.0.0
   resolution: "@netlify/binary-info@npm:1.0.0"
@@ -3153,12 +3269,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0":
-  version: 7.1.0
-  resolution: "agent-base@npm:7.1.0"
-  dependencies:
-    debug: "npm:^4.3.4"
-  checksum: 
10/f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f
+"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.2":
+  version: 7.1.4
+  resolution: "agent-base@npm:7.1.4"
+  checksum: 
10/79bef167247789f955aaba113bae74bf64aa1e1acca4b1d6bb444bdf91d82c3e07e9451ef6a6e2e35e8f71a6f97ce33e3d855a5328eb9fad1bc3cc4cfd031ed8
   languageName: node
   linkType: hard
 
@@ -3588,6 +3702,7 @@ __metadata:
     chalk: "npm:5.3.0"
     del: "npm:^6.0.0"
     escape-string-regexp: "npm:~2.0"
+    glob: "npm:^11.0.3"
     gulp: "npm:~4.0"
     gulp-cheerio: "npm:~1.0"
     gulp-htmlmin: "npm:~5.0"
@@ -3595,11 +3710,16 @@ __metadata:
     html-validate: "npm:^8.9.1"
     hugo-extended: "npm:^0.121.2"
     js-yaml: "npm:~4.1.0"
+    jsdom: "npm:^27.1.0"
     netlify-cli: "npm:17.26.3"
+    node-html-parser: "npm:^7.0.1"
     npm-run-all: "npm:~4"
     opal-runtime: "npm:1.0.11"
     pino-pretty: "npm:^5.0.0"
     toml: "npm:~3.0"
+    turndown: "npm:^7.2.2"
+    turndown-plugin-gfm: "npm:^1.0.2"
+    xml2js: "npm:^0.6.2"
   languageName: unknown
   linkType: soft
 
@@ -4253,6 +4373,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"bidi-js@npm:^1.0.3":
+  version: 1.0.3
+  resolution: "bidi-js@npm:1.0.3"
+  dependencies:
+    require-from-string: "npm:^2.0.2"
+  checksum: 
10/c4341c7a98797efe3d186cd99d6f97e9030a4f959794ca200ef2ec0a678483a916335bba6c2c0608a21d04a221288a31c9fd0faa0cd9b3903b93594b42466a6a
+  languageName: node
+  linkType: hard
+
 "bin-build@npm:^3.0.0":
   version: 3.0.0
   resolution: "bin-build@npm:3.0.0"
@@ -6306,14 +6435,14 @@ __metadata:
   languageName: node
   linkType: hard
 
-"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.3":
-  version: 7.0.3
-  resolution: "cross-spawn@npm:7.0.3"
+"cross-spawn@npm:^7.0.3, cross-spawn@npm:^7.0.6":
+  version: 7.0.6
+  resolution: "cross-spawn@npm:7.0.6"
   dependencies:
     path-key: "npm:^3.1.0"
     shebang-command: "npm:^2.0.0"
     which: "npm:^2.0.1"
-  checksum: 
10/e1a13869d2f57d974de0d9ef7acbf69dc6937db20b918525a01dacb5032129bd552d290d886d981e99f1b624cb03657084cc87bd40f115c07ecf376821c729ce
+  checksum: 
10/0d52657d7ae36eb130999dffff1168ec348687b48dd38e2ff59992ed916c88d328cf1d07ff4a4a10bc78de5e1c23f04b306d569e42f7a2293915c081e4dfee86
   languageName: node
   linkType: hard
 
@@ -6468,6 +6597,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"css-tree@npm:^3.1.0":
+  version: 3.1.0
+  resolution: "css-tree@npm:3.1.0"
+  dependencies:
+    mdn-data: "npm:2.12.2"
+    source-map-js: "npm:^1.0.1"
+  checksum: 
10/e8c5c8e98e3aa4a620fda0b813ce57ccf99281652bf9d23e5cdfc9961c9a93a6769941f9a92e31e65d90f446f42fa83879ab0185206dc7a178d9f656d0913e14
+  languageName: node
+  linkType: hard
+
 "css-tree@npm:~2.2.0":
   version: 2.2.1
   resolution: "css-tree@npm:2.2.1"
@@ -6613,6 +6752,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"cssstyle@npm:^5.3.2":
+  version: 5.3.3
+  resolution: "cssstyle@npm:5.3.3"
+  dependencies:
+    "@asamuzakjp/css-color": "npm:^4.0.3"
+    "@csstools/css-syntax-patches-for-csstree": "npm:^1.0.14"
+    css-tree: "npm:^3.1.0"
+  checksum: 
10/8c6133761395f03d50e74ff4c05473b4835b79013efed3f4b79dc452d94a7122082887d89c3c1164bba0e8919be209b75e4f4706197c086fc9f4b50182ab03d6
+  languageName: node
+  linkType: hard
+
 "cuint@npm:^0.2.2":
   version: 0.2.2
   resolution: "cuint@npm:0.2.2"
@@ -6651,6 +6801,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"data-urls@npm:^6.0.0":
+  version: 6.0.0
+  resolution: "data-urls@npm:6.0.0"
+  dependencies:
+    whatwg-mimetype: "npm:^4.0.0"
+    whatwg-url: "npm:^15.0.0"
+  checksum: 
10/a47f0dde184337c4f168d455aedf0b486fed87b6ca583b4b9ad55d1515f4836b418d4bdc5b5b6fc55e321feb826029586a0d47e1c9a9e7ac4d52a78faceb7fb0
+  languageName: node
+  linkType: hard
+
 "date-time@npm:^3.1.0":
   version: 3.1.0
   resolution: "date-time@npm:3.1.0"
@@ -6742,6 +6902,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"decimal.js@npm:^10.6.0":
+  version: 10.6.0
+  resolution: "decimal.js@npm:10.6.0"
+  checksum: 
10/c0d45842d47c311d11b38ce7ccc911121953d4df3ebb1465d92b31970eb4f6738a065426a06094af59bee4b0d64e42e7c8984abd57b6767c64ea90cf90bb4a69
+  languageName: node
+  linkType: hard
+
 "decode-uri-component@npm:^0.2.0":
   version: 0.2.2
   resolution: "decode-uri-component@npm:0.2.2"
@@ -7698,6 +7865,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"entities@npm:^6.0.0":
+  version: 6.0.1
+  resolution: "entities@npm:6.0.1"
+  checksum: 
10/62af1307202884349d2867f0aac5c60d8b57102ea0b0e768b16246099512c28e239254ad772d6834e7e14cb1b6f153fc3d0c031934e3183b086c86d3838d874a
+  languageName: node
+  linkType: hard
+
 "env-paths@npm:3.0.0, env-paths@npm:^3.0.0":
   version: 3.0.0
   resolution: "env-paths@npm:3.0.0"
@@ -9664,13 +9838,13 @@ __metadata:
   languageName: node
   linkType: hard
 
-"foreground-child@npm:^3.1.0":
-  version: 3.1.1
-  resolution: "foreground-child@npm:3.1.1"
+"foreground-child@npm:^3.1.0, foreground-child@npm:^3.3.1":
+  version: 3.3.1
+  resolution: "foreground-child@npm:3.3.1"
   dependencies:
-    cross-spawn: "npm:^7.0.0"
+    cross-spawn: "npm:^7.0.6"
     signal-exit: "npm:^4.0.1"
-  checksum: 
10/087edd44857d258c4f73ad84cb8df980826569656f2550c341b27adf5335354393eec24ea2fabd43a253233fb27cee177ebe46bd0b7ea129c77e87cb1e9936fb
+  checksum: 
10/427b33f997a98073c0424e5c07169264a62cda806d8d2ded159b5b903fdfc8f0a1457e06b5fc35506497acb3f1e353f025edee796300209ac6231e80edece835
   languageName: node
   linkType: hard
 
@@ -10272,6 +10446,22 @@ __metadata:
   languageName: node
   linkType: hard
 
+"glob@npm:^11.0.3":
+  version: 11.0.3
+  resolution: "glob@npm:11.0.3"
+  dependencies:
+    foreground-child: "npm:^3.3.1"
+    jackspeak: "npm:^4.1.1"
+    minimatch: "npm:^10.0.3"
+    minipass: "npm:^7.1.2"
+    package-json-from-dist: "npm:^1.0.0"
+    path-scurry: "npm:^2.0.0"
+  bin:
+    glob: dist/esm/bin.mjs
+  checksum: 
10/2ae536c1360c0266b523b2bfa6aadc10144a8b7e08869b088e37ac3c27cd30774f82e4bfb291cde796776e878f9e13200c7ff44010eb7054e00f46f649397893
+  languageName: node
+  linkType: hard
+
 "glob@npm:^7.1.0, glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, 
glob@npm:^7.2.0":
   version: 7.2.0
   resolution: "glob@npm:7.2.0"
@@ -11025,7 +11215,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"he@npm:1.2.x":
+"he@npm:1.2.0, he@npm:1.2.x":
   version: 1.2.0
   resolution: "he@npm:1.2.0"
   bin:
@@ -11143,6 +11333,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"html-encoding-sniffer@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "html-encoding-sniffer@npm:4.0.0"
+  dependencies:
+    whatwg-encoding: "npm:^3.1.1"
+  checksum: 
10/e86efd493293a5671b8239bd099d42128433bb3c7b0fdc7819282ef8e118a21f5dead0ad6f358e024a4e5c84f17ebb7a9b36075220fac0a6222b207248bede6f
+  languageName: node
+  linkType: hard
+
 "html-minifier@npm:^3.5.20":
   version: 3.5.21
   resolution: "html-minifier@npm:3.5.21"
@@ -11275,13 +11474,13 @@ __metadata:
   languageName: node
   linkType: hard
 
-"http-proxy-agent@npm:^7.0.0":
-  version: 7.0.0
-  resolution: "http-proxy-agent@npm:7.0.0"
+"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.2":
+  version: 7.0.2
+  resolution: "http-proxy-agent@npm:7.0.2"
   dependencies:
     agent-base: "npm:^7.1.0"
     debug: "npm:^4.3.4"
-  checksum: 
10/dbaaf3d9f3fc4df4a5d7ec45d456ec50f575240b557160fa63427b447d1f812dd7fe4a4f17d2e1ba003d231f07edf5a856ea6d91cb32d533062ff20a7803ccac
+  checksum: 
10/d062acfa0cb82beeb558f1043c6ba770ea892b5fb7b28654dbc70ea2aeea55226dd34c02a294f6c1ca179a5aa483c4ea641846821b182edbd9cc5d89b54c6848
   languageName: node
   linkType: hard
 
@@ -11348,7 +11547,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"https-proxy-agent@npm:7.0.4, https-proxy-agent@npm:^7.0.1":
+"https-proxy-agent@npm:7.0.4":
   version: 7.0.4
   resolution: "https-proxy-agent@npm:7.0.4"
   dependencies:
@@ -11368,6 +11567,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.6":
+  version: 7.0.6
+  resolution: "https-proxy-agent@npm:7.0.6"
+  dependencies:
+    agent-base: "npm:^7.1.2"
+    debug: "npm:4"
+  checksum: 
10/784b628cbd55b25542a9d85033bdfd03d4eda630fb8b3c9477959367f3be95dc476ed2ecbb9836c359c7c698027fc7b45723a302324433590f45d6c1706e8c13
+  languageName: node
+  linkType: hard
+
 "hugo-extended@npm:^0.121.2":
   version: 0.121.2
   resolution: "hugo-extended@npm:0.121.2"
@@ -11412,7 +11621,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"iconv-lite@npm:^0.6.2":
+"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2":
   version: 0.6.3
   resolution: "iconv-lite@npm:0.6.3"
   dependencies:
@@ -12339,6 +12548,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"is-potential-custom-element-name@npm:^1.0.1":
+  version: 1.0.1
+  resolution: "is-potential-custom-element-name@npm:1.0.1"
+  checksum: 
10/ced7bbbb6433a5b684af581872afe0e1767e2d1146b2207ca0068a648fb5cab9d898495d1ac0583524faaf24ca98176a7d9876363097c2d14fee6dd324f3a1ab
+  languageName: node
+  linkType: hard
+
 "is-promise@npm:^2.1.0":
   version: 2.1.0
   resolution: "is-promise@npm:2.1.0"
@@ -12666,6 +12882,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"jackspeak@npm:^4.1.1":
+  version: 4.1.1
+  resolution: "jackspeak@npm:4.1.1"
+  dependencies:
+    "@isaacs/cliui": "npm:^8.0.2"
+  checksum: 
10/ffceb270ec286841f48413bfb4a50b188662dfd599378ce142b6540f3f0a66821dc9dcb1e9ebc55c6c3b24dc2226c96e5819ba9bd7a241bd29031b61911718c7
+  languageName: node
+  linkType: hard
+
 "jest-get-type@npm:^27.5.1":
   version: 27.5.1
   resolution: "jest-get-type@npm:27.5.1"
@@ -12759,6 +12984,39 @@ __metadata:
   languageName: node
   linkType: hard
 
+"jsdom@npm:^27.1.0":
+  version: 27.1.0
+  resolution: "jsdom@npm:27.1.0"
+  dependencies:
+    "@acemir/cssom": "npm:^0.9.19"
+    "@asamuzakjp/dom-selector": "npm:^6.7.3"
+    cssstyle: "npm:^5.3.2"
+    data-urls: "npm:^6.0.0"
+    decimal.js: "npm:^10.6.0"
+    html-encoding-sniffer: "npm:^4.0.0"
+    http-proxy-agent: "npm:^7.0.2"
+    https-proxy-agent: "npm:^7.0.6"
+    is-potential-custom-element-name: "npm:^1.0.1"
+    parse5: "npm:^8.0.0"
+    saxes: "npm:^6.0.0"
+    symbol-tree: "npm:^3.2.4"
+    tough-cookie: "npm:^6.0.0"
+    w3c-xmlserializer: "npm:^5.0.0"
+    webidl-conversions: "npm:^8.0.0"
+    whatwg-encoding: "npm:^3.1.1"
+    whatwg-mimetype: "npm:^4.0.0"
+    whatwg-url: "npm:^15.1.0"
+    ws: "npm:^8.18.3"
+    xml-name-validator: "npm:^5.0.0"
+  peerDependencies:
+    canvas: ^3.0.0
+  peerDependenciesMeta:
+    canvas:
+      optional: true
+  checksum: 
10/9e2bd9824abed594da64fc58f1bdb817c7f82ba3025cef4817e6709807f886ac71b7b6a0f4f69ba604e9137bbcd6b7246b98dec53bde95500f5ac4b39a8ebb00
+  languageName: node
+  linkType: hard
+
 "json-buffer@npm:3.0.0":
   version: 3.0.0
   resolution: "json-buffer@npm:3.0.0"
@@ -13671,6 +13929,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"lru-cache@npm:^11.0.0, lru-cache@npm:^11.2.1, lru-cache@npm:^11.2.2":
+  version: 11.2.2
+  resolution: "lru-cache@npm:11.2.2"
+  checksum: 
10/fa7919fbf068a739f79a1ad461eb273514da7246cebb9dca68e3cd7ba19e3839e7e2aaecd9b72867e08038561eeb96941189e89b3d4091c75ced4f56c71c80db
+  languageName: node
+  linkType: hard
+
 "lru-cache@npm:^4.0.1":
   version: 4.1.5
   resolution: "lru-cache@npm:4.1.5"
@@ -13912,6 +14177,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"mdn-data@npm:2.12.2":
+  version: 2.12.2
+  resolution: "mdn-data@npm:2.12.2"
+  checksum: 
10/854e41715a9358e69f9a530117cd6ca7e71d06176469de8d70b1e629753b6827f5bd730995c16ad3750f3c9bad92230f8e4e178de2b34926b05f5205d27d76af
+  languageName: node
+  linkType: hard
+
 "media-typer@npm:0.3.0":
   version: 0.3.0
   resolution: "media-typer@npm:0.3.0"
@@ -14180,6 +14452,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"minimatch@npm:^10.0.3":
+  version: 10.1.1
+  resolution: "minimatch@npm:10.1.1"
+  dependencies:
+    "@isaacs/brace-expansion": "npm:^5.0.0"
+  checksum: 
10/110f38921ea527022e90f7a5f43721838ac740d0a0c26881c03b57c261354fb9a0430e40b2c56dfcea2ef3c773768f27210d1106f1f2be19cde3eea93f26f45e
+  languageName: node
+  linkType: hard
+
 "minimatch@npm:^5.0.1, minimatch@npm:^5.1.0":
   version: 5.1.6
   resolution: "minimatch@npm:5.1.6"
@@ -14964,6 +15245,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"node-html-parser@npm:^7.0.1":
+  version: 7.0.1
+  resolution: "node-html-parser@npm:7.0.1"
+  dependencies:
+    css-select: "npm:^5.1.0"
+    he: "npm:1.2.0"
+  checksum: 
10/726db99091551ab3620f001892d6afb4c87b505ffc8fc6b8cd7bb225701a805b85615504dd93a0d4ee095ef46d2ec4dabc9b61165d8034704b191601f5bf6936
+  languageName: node
+  linkType: hard
+
 "node-pre-gyp@npm:*":
   version: 0.16.0
   resolution: "node-pre-gyp@npm:0.16.0"
@@ -15977,6 +16268,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"package-json-from-dist@npm:^1.0.0":
+  version: 1.0.1
+  resolution: "package-json-from-dist@npm:1.0.1"
+  checksum: 
10/58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602
+  languageName: node
+  linkType: hard
+
 "package-json@npm:^8.1.0":
   version: 8.1.1
   resolution: "package-json@npm:8.1.1"
@@ -16137,6 +16435,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"parse5@npm:^8.0.0":
+  version: 8.0.0
+  resolution: "parse5@npm:8.0.0"
+  dependencies:
+    entities: "npm:^6.0.0"
+  checksum: 
10/1973850932bb1cbd52ab64502761489fbe1bb43a52dee7ce41aac0b6c33a51a92aaee04661590b0912b739ae9ee316bce4c78c8ea34af42a7e522c983c3c6cf5
+  languageName: node
+  linkType: hard
+
 "parseurl@npm:~1.3.2, parseurl@npm:~1.3.3":
   version: 1.3.3
   resolution: "parseurl@npm:1.3.3"
@@ -16270,6 +16577,16 @@ __metadata:
   languageName: node
   linkType: hard
 
+"path-scurry@npm:^2.0.0":
+  version: 2.0.1
+  resolution: "path-scurry@npm:2.0.1"
+  dependencies:
+    lru-cache: "npm:^11.0.0"
+    minipass: "npm:^7.1.2"
+  checksum: 
10/1e9c74e9ccf94d7c16056a5cb2dba9fa23eec1bc221ab15c44765486b9b9975b4cd9a4d55da15b96eadf67d5202e9a2f1cec9023fbb35fe7d9ccd0ff1891f88b
+  languageName: node
+  linkType: hard
+
 "path-to-regexp@npm:0.1.7":
   version: 0.1.7
   resolution: "path-to-regexp@npm:0.1.7"
@@ -17451,10 +17768,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"punycode@npm:^2.1.0":
-  version: 2.1.1
-  resolution: "punycode@npm:2.1.1"
-  checksum: 
10/939daa010c2cacebdb060c40ecb52fef0a739324a66f7fffe0f94353a1ee83e3b455e9032054c4a0c4977b0a28e27086f2171c392832b59a01bd948fd8e20914
+"punycode@npm:^2.1.0, punycode@npm:^2.3.1":
+  version: 2.3.1
+  resolution: "punycode@npm:2.3.1"
+  checksum: 
10/febdc4362bead22f9e2608ff0171713230b57aff9dddc1c273aa2a651fbd366f94b7d6a71d78342a7c0819906750351ca7f2edd26ea41b626d87d6a13d1bd059
   languageName: node
   linkType: hard
 
@@ -18443,13 +18760,29 @@ __metadata:
   languageName: node
   linkType: hard
 
-"sax@npm:^1.2.4, sax@npm:~1.2.4":
+"sax@npm:>=0.6.0, sax@npm:^1.2.4":
+  version: 1.4.3
+  resolution: "sax@npm:1.4.3"
+  checksum: 
10/99161215f23e0b13bc7f94adbaa63a6a2f188fe291c450790d92b5bc3cd7966d574a15dcd5918c30917e17ed68129e34cc3168564263b967f9b8f61869d6ccc4
+  languageName: node
+  linkType: hard
+
+"sax@npm:~1.2.4":
   version: 1.2.4
   resolution: "sax@npm:1.2.4"
   checksum: 
10/09b79ff6dc09689a24323352117c94593c69db348997b2af0edbd82fa08aba47d778055bf9616b57285bb73d25d790900c044bf631a8f10c8252412e3f3fe5dd
   languageName: node
   linkType: hard
 
+"saxes@npm:^6.0.0":
+  version: 6.0.0
+  resolution: "saxes@npm:6.0.0"
+  dependencies:
+    xmlchars: "npm:^2.2.0"
+  checksum: 
10/97b50daf6ca3a153e89842efa18a862e446248296622b7473c169c84c823ee8a16e4a43bac2f73f11fc8cb9168c73fbb0d73340f26552bac17970e9052367aa9
+  languageName: node
+  linkType: hard
+
 "scope-analyzer@npm:^2.0.0":
   version: 2.1.1
   resolution: "scope-analyzer@npm:2.1.1"
@@ -20002,6 +20335,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"symbol-tree@npm:^3.2.4":
+  version: 3.2.4
+  resolution: "symbol-tree@npm:3.2.4"
+  checksum: 
10/c09a00aadf279d47d0c5c46ca3b6b2fbaeb45f0a184976d599637d412d3a70bbdc043ff33effe1206dea0e36e0ad226cb957112e7ce9a4bf2daedf7fa4f85c53
+  languageName: node
+  linkType: hard
+
 "syntax-error@npm:^1.1.1":
   version: 1.4.0
   resolution: "syntax-error@npm:1.4.0"
@@ -20373,6 +20713,24 @@ __metadata:
   languageName: node
   linkType: hard
 
+"tldts-core@npm:^7.0.17":
+  version: 7.0.17
+  resolution: "tldts-core@npm:7.0.17"
+  checksum: 
10/246307f0d1b46ab07fcd00ea1d9afc4de3f1148a35cb0dd637ae04cc525e4ddcc66474b4ba7867d4361fbac70f19ec79db226103142e1d3f63cdd764938608da
+  languageName: node
+  linkType: hard
+
+"tldts@npm:^7.0.5":
+  version: 7.0.17
+  resolution: "tldts@npm:7.0.17"
+  dependencies:
+    tldts-core: "npm:^7.0.17"
+  bin:
+    tldts: bin/cli.js
+  checksum: 
10/8730b0c8d2a393e6e6ec061b10f967f4db59ca78ee0c0259feafc311eab9a986138602831b7b886807638e69c525d88964c2056f42be4ca2b95200fe2ac9164c
+  languageName: node
+  linkType: hard
+
 "tmp-promise@npm:^3.0.2, tmp-promise@npm:^3.0.3":
   version: 3.0.3
   resolution: "tmp-promise@npm:3.0.3"
@@ -20532,6 +20890,24 @@ __metadata:
   languageName: node
   linkType: hard
 
+"tough-cookie@npm:^6.0.0":
+  version: 6.0.0
+  resolution: "tough-cookie@npm:6.0.0"
+  dependencies:
+    tldts: "npm:^7.0.5"
+  checksum: 
10/1b0592241655912eb972e1c284ccf975af154576b8e9912cad4ed7b4b408a60ccfdad1bc53eef10d376f6a5ef9d84e2f8ea0b46c92263d52de855247ff100e27
+  languageName: node
+  linkType: hard
+
+"tr46@npm:^6.0.0":
+  version: 6.0.0
+  resolution: "tr46@npm:6.0.0"
+  dependencies:
+    punycode: "npm:^2.3.1"
+  checksum: 
10/e6d402eb2b780a40042f327f77b4ae316da1d2b18a29c16e48c239f5267c6005bbf780f854179cfae62b02dfaa70b0e9aad8f0078ccc4225f5b3b3b131928e8f
+  languageName: node
+  linkType: hard
+
 "tr46@npm:~0.0.3":
   version: 0.0.3
   resolution: "tr46@npm:0.0.3"
@@ -20665,6 +21041,22 @@ __metadata:
   languageName: node
   linkType: hard
 
+"turndown-plugin-gfm@npm:^1.0.2":
+  version: 1.0.2
+  resolution: "turndown-plugin-gfm@npm:1.0.2"
+  checksum: 
10/07d8520ad4d272da5b69ed8032bf10c4cf5ff605541da0df1ac2c61bd5e0df6e25cbd8395a4f66e5db03cb2c4421d202feeeebb39c59a0fe45966ffcde3c5564
+  languageName: node
+  linkType: hard
+
+"turndown@npm:^7.2.2":
+  version: 7.2.2
+  resolution: "turndown@npm:7.2.2"
+  dependencies:
+    "@mixmark-io/domino": "npm:^2.2.0"
+  checksum: 
10/e0a6f7f0c2bc8447ca7ea145348c9e337163a00c9d95f49e5eecdbc9931002aa0253c7561fbc299280c854d5308ed5a0eacfc9b4e399d698fce64be4d2d7bb52
+  languageName: node
+  linkType: hard
+
 "type-check@npm:~0.3.2":
   version: 0.3.2
   resolution: "type-check@npm:0.3.2"
@@ -21559,6 +21951,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"w3c-xmlserializer@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "w3c-xmlserializer@npm:5.0.0"
+  dependencies:
+    xml-name-validator: "npm:^5.0.0"
+  checksum: 
10/d78f59e6b4f924aa53b6dfc56949959229cae7fe05ea9374eb38d11edcec01398b7f5d7a12576bd5acc57ff446abb5c9115cd83b9d882555015437cf858d42f0
+  languageName: node
+  linkType: hard
+
 "wait-port@npm:1.1.0":
   version: 1.1.0
   resolution: "wait-port@npm:1.1.0"
@@ -21586,6 +21987,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"webidl-conversions@npm:^8.0.0":
+  version: 8.0.0
+  resolution: "webidl-conversions@npm:8.0.0"
+  checksum: 
10/8138d1b291c8f311d93de680653b13b04560aa35d83f9606642e746fca39d7dab9cddd9282ade21774115ea332b8b11f008106b82d4a0125e98a49479381aeee
+  languageName: node
+  linkType: hard
+
 "websocket-driver@npm:>=0.5.1":
   version: 0.7.4
   resolution: "websocket-driver@npm:0.7.4"
@@ -21611,6 +22019,32 @@ __metadata:
   languageName: node
   linkType: hard
 
+"whatwg-encoding@npm:^3.1.1":
+  version: 3.1.1
+  resolution: "whatwg-encoding@npm:3.1.1"
+  dependencies:
+    iconv-lite: "npm:0.6.3"
+  checksum: 
10/bbef815eb67f91487c7f2ef96329743f5fd8357d7d62b1119237d25d41c7e452dff8197235b2d3c031365a17f61d3bb73ca49d0ed1582475aa4a670815e79534
+  languageName: node
+  linkType: hard
+
+"whatwg-mimetype@npm:^4.0.0":
+  version: 4.0.0
+  resolution: "whatwg-mimetype@npm:4.0.0"
+  checksum: 
10/894a618e2d90bf444b6f309f3ceb6e58cf21b2beaa00c8b333696958c4076f0c7b30b9d33413c9ffff7c5832a0a0c8569e5bb347ef44beded72aeefd0acd62e8
+  languageName: node
+  linkType: hard
+
+"whatwg-url@npm:^15.0.0, whatwg-url@npm:^15.1.0":
+  version: 15.1.0
+  resolution: "whatwg-url@npm:15.1.0"
+  dependencies:
+    tr46: "npm:^6.0.0"
+    webidl-conversions: "npm:^8.0.0"
+  checksum: 
10/9ae5ce70060f2a9ea73799062af6e796ec2477f44bf1a886953b405700e3ab11d15aa0fe7088c4215f839e56a845d5d1c44584ed292a832837a8c8549c566886
+  languageName: node
+  linkType: hard
+
 "whatwg-url@npm:^5.0.0":
   version: 5.0.0
   resolution: "whatwg-url@npm:5.0.0"
@@ -21860,6 +22294,21 @@ __metadata:
   languageName: node
   linkType: hard
 
+"ws@npm:^8.18.3":
+  version: 8.18.3
+  resolution: "ws@npm:8.18.3"
+  peerDependencies:
+    bufferutil: ^4.0.1
+    utf-8-validate: ">=5.0.2"
+  peerDependenciesMeta:
+    bufferutil:
+      optional: true
+    utf-8-validate:
+      optional: true
+  checksum: 
10/725964438d752f0ab0de582cd48d6eeada58d1511c3f613485b5598a83680bedac6187c765b0fe082e2d8cc4341fc57707c813ae780feee82d0c5efe6a4c61b6
+  languageName: node
+  linkType: hard
+
 "ws@npm:~8.11.0":
   version: 8.11.0
   resolution: "ws@npm:8.11.0"
@@ -21889,6 +22338,37 @@ __metadata:
   languageName: node
   linkType: hard
 
+"xml-name-validator@npm:^5.0.0":
+  version: 5.0.0
+  resolution: "xml-name-validator@npm:5.0.0"
+  checksum: 
10/43f30f3f6786e406dd665acf08cd742d5f8a46486bd72517edb04b27d1bcd1599664c2a4a99fc3f1e56a3194bff588b12f178b7972bc45c8047bdc4c3ac8d4a1
+  languageName: node
+  linkType: hard
+
+"xml2js@npm:^0.6.2":
+  version: 0.6.2
+  resolution: "xml2js@npm:0.6.2"
+  dependencies:
+    sax: "npm:>=0.6.0"
+    xmlbuilder: "npm:~11.0.0"
+  checksum: 
10/df29de8eeedb762c367d87945c39bcf54db19a2c522607491c266ed6184b5a749e37ff29cfaed0ac149da9ba332ac3dcf8e5ff2bd0a206be3343eca95faa941d
+  languageName: node
+  linkType: hard
+
+"xmlbuilder@npm:~11.0.0":
+  version: 11.0.1
+  resolution: "xmlbuilder@npm:11.0.1"
+  checksum: 
10/c8c3d208783718db5b285101a736cd8e6b69a5c265199a0739abaa93d1a1b7de5489fd16df4e776e18b2c98cb91f421a7349e99fd8c1ebeb44ecfed72a25091a
+  languageName: node
+  linkType: hard
+
+"xmlchars@npm:^2.2.0":
+  version: 2.2.0
+  resolution: "xmlchars@npm:2.2.0"
+  checksum: 
10/4ad5924974efd004a47cce6acf5c0269aee0e62f9a805a426db3337af7bcbd331099df174b024ace4fb18971b8a56de386d2e73a1c4b020e3abd63a4a9b917f1
+  languageName: node
+  linkType: hard
+
 "xmlhttprequest-ssl@npm:~2.0.0":
   version: 2.0.0
   resolution: "xmlhttprequest-ssl@npm:2.0.0"

Reply via email to