All files / scripts/lib/readme readmeHandler.js

82.85% Statements 29/35
91.3% Branches 21/23
100% Functions 1/1
92% Lines 23/25

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  2x 2x 2x 2x                           7x 7x 2x 2x     7x 7x   5x 5x   5x   5x 5x     5x 5x 5x 5x 5x 5x     5x           2x  
#!/usr/bin/env node
const parseReadme = require('../parseReadme');
const mediaDownloader = require('../media/mediaDownloader');
const mediaHelper = require('../media');
const { fetchReadmeFromRaw } = require('./readmeFallback');
 
/**
 * Ensures a node has README text, then runs media download, technology extraction,
 * and docs link extraction. Falls back to raw.githubusercontent.com when the GraphQL
 * response omits the README object.
 *
 * @param {object} node - Repository node; mutated in place with parsed fields
 * @param {string} mediaRoot - Absolute path for storing downloaded media
 * @param {Function} getAxios - Factory returning an axios-like HTTP client
 * @param {object} [opts] - Optional overrides: { DEBUG_FETCH, parseReadme }
 * @returns {Promise<object>} The mutated node
 */
async function processNodeReadme(node, mediaRoot, getAxios, opts = {}) {
  try {
    if (!node.object || !node.object.text) {
      const r = await fetchReadmeFromRaw('keglev', node.name);
      if (r) { node.object = node.object || {}; node.object.text = r; }
    }
 
    const readme = node.object && node.object.text;
    if (!readme || typeof readme !== 'string') return node;
 
    let ast = null;
    try { ast = parseReadme.parseMarkdown(readme); } catch (e) { ast = null; }
    // _ast is stored so downstream stages (doc extraction, summary) share the same parsed tree
    try { node._ast = ast; } catch (e) { }
 
    try {
      await mediaHelper.processNodeMedia(node, mediaRoot, getAxios, Object.assign({ parseReadme, isBadgeLike: parseReadme.isBadgeLike, mediaDownloader, readme, ast }, opts));
    } catch (e) { /* swallow - caller may log via DEBUG_FETCH */ }
 
    try { node.technologies = parseReadme.extractTechnologiesFromAst(ast); } catch (e) { node.technologies = []; }
    try {
      const docs = parseReadme.extractDocsFromAst(ast, node.name) || { documentation: null, apiDocumentation: null, legacy: { docsLink: null, docsTitle: null } };
      node.docs = { documentation: docs.documentation, apiDocumentation: docs.apiDocumentation };
      node.docsLink = (docs.legacy && docs.legacy.docsLink) || null;
      node.docsTitle = (docs.legacy && docs.legacy.docsTitle) || null;
    } catch (e) { node.docs = { documentation: null, apiDocumentation: null }; node.docsLink = null; node.docsTitle = null; }
 
    return node;
  } catch (err) {
    return node;
  }
}
 
module.exports = { processNodeReadme };