All files / scripts/political-intelligence catalog.ts

84.21% Statements 16/19
50% Branches 7/14
100% Functions 3/3
100% Lines 15/15

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 69 70 71 72 73 74 75 76 77 78 79 80 81                                            1x 1x                                           61185x 61185x 61185x                           30x 30x 2745x 810x 810x 810x 810x 810x 810x                 30x    
/**
 * @module Infrastructure/PoliticalIntelligence/Catalog
 * @category Intelligence Operations / Supporting Infrastructure
 * @name Methodology + template catalog discovery
 *
 * @description
 * Walks `analysis/methodologies/` and `analysis/templates/` to discover
 * every reference document, attaches the curated metadata from
 * `i18n/methodology-i18n.ts` / `i18n/template-i18n.ts`, and produces an
 * ordered `CatalogEntry[]`. Pure with respect to the filesystem.
 *
 * Round-6 split: extracted from `scripts/generate-political-intelligence.ts`.
 *
 * @author Hack23 AB (Infrastructure Team)
 * @license Apache-2.0
 */
 
import fs from 'fs';
import path from 'path';
 
import { prettifyMarkdownTitle } from './i18n/artifact-i18n.js';
 
const GITHUB_BLOB = 'https://github.com/Hack23/riksdagsmonitor/blob/main';
const GITHUB_TREE = 'https://github.com/Hack23/riksdagsmonitor/tree/main';
 
export interface CatalogEntry {
  readonly file: string;
  readonly title: string;
  readonly icon: string;
  /** English description used as canonical fallback when a language lacks a translation. */
  readonly description: string;
  readonly githubUrl: string;
  /** Which library this entry belongs to (methodology vs template); drives i18n lookup. */
  readonly library: 'methodologies' | 'templates';
}
 
/** Curated icons and English high-level descriptions keyed by filename. */
 
 
/**
 * Build an absolute GitHub URL to a `blob` (single file) or `tree`
 * (directory) under the canonical `main` branch. Each path segment is
 * encoded individually so spaces and unicode work correctly.
 */
export function buildGithubUrl(type: 'blob' | 'tree', relative: string): string {
  const base = type === 'blob' ? GITHUB_BLOB : GITHUB_TREE;
  const encoded = relative.split('/').map(encodeURIComponent).join('/');
  return `${base}/${encoded}`;
}
 
/**
 * Walk a methodology / template directory and produce one `CatalogEntry`
 * per `.md` / `.json` file. Hidden files and subdirectories are skipped.
 * Sorted alphabetically by filename so output is stable across runs.
 */
export function collectCatalog(
  dir: string,
  relativePrefix: string,
  metaMap: Record<string, { icon: string; description: string }>,
  library: 'methodologies' | 'templates',
): CatalogEntry[] {
  Iif (!fs.existsSync(dir)) return [];
  const entries: CatalogEntry[] = [];
  for (const name of fs.readdirSync(dir).sort((a, b) => a.localeCompare(b))) {
    const full = path.join(dir, name);
    const stat = fs.statSync(full);
    Iif (!stat.isFile()) continue;
    Iif (!/\.(md|json)$/i.test(name)) continue;
    const meta = metaMap[name];
    entries.push({
      file: name,
      title: prettifyMarkdownTitle(name),
      icon: meta?.icon ?? (name.endsWith('.json') ? '📊' : '📄'),
      description: meta?.description ?? `${prettifyMarkdownTitle(name)} — reference document in the ${relativePrefix.split('/').pop()} library.`,
      githubUrl: buildGithubUrl('blob', `${relativePrefix}/${name}`),
      library,
    });
  }
  return entries;
}