All files / packages/design-system-2/scripts/buildCss sort-imports.js

76% Statements 19/25
63.63% Branches 7/11
85.71% Functions 6/7
73.91% Lines 17/23

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                          1x               1x 16x 16x                             1x 7x 12x   7x 8x 8x 8x         7x                   12x                     1x 2x 2x 2x    
/**
 * Import sorting and manifest generation for the CSS build.
 *
 * Sorts file lists by the canonical import order and optionally writes an
 * @import manifest file for PostCSS consumption.
 */
 
import path from 'node:path';
import fs from 'fs-extra';
import { args, THEME } from './args.js';
import { buildImportOrder } from './import-order.js';
 
/** Default import order, materialized once for the active CLI theme. */
export const importOrder = buildImportOrder(THEME);
 
/**
 * Strips the leading underscore and file extension from a CSS filename to produce
 * the lookup key used against `importOrder`.
 *
 * @param {string} file Absolute file path.
 */
export const fileToOrderKey = (file) => {
  const segments = file.split(path.sep);
  return segments
    .at(-1)
    .replace('_', '')
    .replace(/\.[^/.]+$/, '');
};
 
/**
 * Sorts `files` by import order and returns the @import manifest as a string.
 *
 * Files absent from the order (e.g. theme files named "cosmos") sort to the end.
 *
 * @param {string[]} files Absolute paths to CSS files.
 * @param {{ theme?: string }} [options] Override the sort theme (defaults to CLI --theme).
 * @returns {string} The @import manifest content.
 */
export const sortImports = (files, { theme } = {}) => {
  const order = theme ? buildImportOrder(theme) : importOrder;
  const namedImports = files.map((file) => ({ name: fileToOrderKey(file), file }));
 
  namedImports.sort((a, b) => {
    const aOrder = order.indexOf(a.name);
    const bOrder = order.indexOf(b.name);
    return (
      (aOrder === -1 ? Number.MAX_SAFE_INTEGER : aOrder) - (bOrder === -1 ? Number.MAX_SAFE_INTEGER : bOrder)
    );
  });
 
  Iif (args['--debug-imports']) {
    console.info('\n── Import order ──');
    namedImports.forEach((ni, i) => {
      const orderIdx = order.indexOf(ni.name);
      const tag = orderIdx === -1 ? '(unordered)' : `[${orderIdx}]`;
      console.info(`  ${String(i).padStart(3)}  ${tag.padEnd(14)} ${ni.name.padEnd(30)} ${ni.file}`);
    });
    console.info('──────────────────\n');
  }
 
  return namedImports.map((ni) => `@import "${ni.file}";`).join('\n');
};
 
/**
 * Sorts `files` by `importOrder`, writes an @import manifest to `importsPath`,
 * and returns the manifest content.
 *
 * @param {string[]} files       Absolute paths to CSS files.
 * @param {string}   importsPath Absolute path for the generated manifest file.
 * @returns {string} The @import manifest content.
 */
export const sortAndWriteImports = (files, importsPath) => {
  const imports = sortImports(files);
  fs.outputFileSync(importsPath, imports);
  return imports;
};