All files / scripts/lib/docs extractArchitecture.js

86.66% Statements 39/45
60.29% Branches 41/68
100% Functions 8/8
88.57% Lines 31/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 695x 5x     15x       5x 7x 5x 5x 9x 5x           8x 8x 8x 8x 8x                                   29x 29x 29x 23x 23x 13x 13x 13x 13x 13x         16x 16x 2x 2x 2x         14x     5x  
const DEBUG_FETCH = process.env.DEBUG_FETCH === '1' || process.env.DEBUG_FETCH === 'true';
const PREFIX_RE = /^[•\-.\s📁📚🏗️🎯🚀]*\s*/i;
 
function isIndexLabel(label) {
  return /^Index\b/i.test((label || '').replace(PREFIX_RE, '').trim());
}
 
function scanArchParagraph(nn, ctx) {
  for (const ch of (nn.children || [])) {
    if (ch.type !== 'link' || !ch.url) continue;
    const label = (ch.children || []).map(c => c.value || '').join('').trim();
    Iif (!isIndexLabel(label)) continue;
    const desc = (nn.children || []).filter(c => c.type === 'text').map(c => c.value).join(' ').trim();
    return { title: label || 'Architecture Overview', link: ctx.toRawGithub(ch.url), description: ctx.strip(desc) };
  }
  return null;
}
 
function scanArchList(nn, ctx) {
  for (const li of (nn.children || [])) {
    const flat = ctx.parseReadme.flattenNodeText(li || '').replace(/\r?\n/g, ' ');
    for (const m of flat.matchAll(/\[([^\]]+)\]\(([^)]+)\)/ig)) {
      Eif (isIndexLabel((m[1] || '').trim())) {
        return { title: (m[1] || '').trim() || 'Architecture Overview', link: ctx.toRawGithub((m[2] || '').trim()), description: '' };
      }
    }
  }
  return null;
}
 
/**
 * Finds a link labelled "Index" under an "Architecture Overview" heading in the README.
 * "Index" is the canonical label used for architecture HTML docs in this project's READMEs.
 * Falls back to a raw-text scan when the AST contains no matching heading.
 *
 * @param {object} ast - Parsed README AST
 * @param {string} readmeText - Raw README string (fallback)
 * @param {object} ctx - Shared context: { toRawGithub, parseReadme, strip }
 * @returns {{ title: string, link: string, description: string }|null}
 */
function extractArchitectureOverview(ast, readmeText, ctx) {
  try {
    Eif (ast && Array.isArray(ast.children)) {
      for (let i = 0; i < ast.children.length; i++) {
        const n = ast.children[i];
        if (n.type !== 'heading' || !/architecture overview/i.test((n.children || []).map(c => c.value || '').join(''))) continue;
        let j = i + 1;
        while (j < ast.children.length && ast.children[j].type !== 'heading') {
          const nn = ast.children[j];
          const found = nn.type === 'paragraph' ? scanArchParagraph(nn, ctx) : nn.type === 'list' ? scanArchList(nn, ctx) : null;
          Eif (found) return found;
          j++;
        }
      }
    }
    const idx = readmeText.search(/^\s*#{1,6}\s*.*architecture overview.*$/im);
    if (idx !== -1) {
      for (const m of readmeText.slice(idx).matchAll(/\[([^\]]+)\]\(([^)]+)\)/ig)) {
        Eif (isIndexLabel((m[1] || '').trim())) {
          return { title: (m[1] || '').trim(), link: ctx.toRawGithub((m[2] || '').trim()), description: '' };
        }
      }
    }
  } catch (e) { if (DEBUG_FETCH) console.log('extractArchitectureOverview error', e && e.message); }
  return null;
}
 
module.exports = { extractArchitectureOverview };