• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hexojs / hexo-util / 16651986209

31 Jul 2025 02:35PM UTC coverage: 73.036% (-23.8%) from 96.875%
16651986209

Pull #426

github

web-flow
Merge e24598988 into d497bc760
Pull Request #426: build: restructure for dual ESM/CJS output, update tooling, and enhance utilities

811 of 1128 branches covered (71.9%)

1594 of 2028 new or added lines in 40 files covered. (78.6%)

6 existing lines in 1 file now uncovered.

5290 of 7243 relevant lines covered (73.04%)

69.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.7
/build.js
1
import fs from 'fs';
1✔
2
import path from 'path';
1✔
3
import { build, defineConfig } from 'tsup';
1✔
4
import { fileURLToPath } from 'url';
1✔
5
import packageJson from './package.json' with { type: 'json' };
1✔
6

1✔
7
const __filename = fileURLToPath(import.meta.url);
1✔
8
const __dirname = path.dirname(__filename);
1✔
9
const distDir = path.join(__dirname, 'dist');
1✔
10

1✔
11
/**
1✔
12
 * Packages that should be bundled (not marked as external)
1✔
13
 * @type {string[]}
1✔
14
 */
1✔
15
const bundledPackages = [];
1✔
16

1✔
17
/**
1✔
18
 * All dependencies except those in bundledPackages will be marked as external
1✔
19
 * @type {string[]}
1✔
20
 */
1✔
21
const externalDeps = [...Object.keys(packageJson.dependencies), ...Object.keys(packageJson.devDependencies)].filter(
1✔
22
  pkgName => !bundledPackages.includes(pkgName)
1✔
23
);
1✔
24

1✔
25
/**
1✔
26
 * Build the project using tsup with custom config
1✔
27
 * @returns {Promise<void>}
1✔
28
 */
1✔
29
function buildTsup() {
1✔
30
  const baseConfig = defineConfig({
1✔
31
    entry: ['lib/**/*.ts'],
1✔
32
    splitting: true,
1✔
33
    treeshake: true,
1✔
34
    bundle: false,
1✔
35
    shims: true,
1✔
36
    sourcemap: true,
1✔
37
    removeNodeProtocol: true,
1✔
38
    clean: false,
1✔
39
    external: externalDeps,
1✔
40
    format: ['esm', 'cjs'],
1✔
41
    dts: true,
1✔
42
    outDir: 'dist',
1✔
43
    outExtension({ format }) {
1✔
44
      switch (format) {
2✔
45
        case 'cjs':
2✔
46
          return { js: '.cjs', dts: '.d.cts' };
1✔
47
        default:
2✔
48
          return { js: '.js', dts: '.d.ts' };
1✔
49
      }
2✔
50
    }
2✔
51
  });
1✔
52
  return build(baseConfig);
1✔
53
}
1✔
54

1✔
55
/**
1✔
56
 * Patch a .cjs file to rewrite local .js imports/requires to .cjs
1✔
57
 * @param {string} filePath
1✔
58
 */
1✔
59
function patchFile(filePath) {
39✔
60
  let content = fs.readFileSync(filePath, 'utf8');
39✔
61
  // Only replace paths that start with './' or '../' (local files), not bare module imports
39✔
62
  content = content.replace(/(require\(["'])(\.\.?\/[^"']+)\.js(["']\))/g, (match, p1, p2, p3) => {
39✔
63
    return `${p1}${p2}.cjs${p3}`;
57✔
64
  });
39✔
65
  content = content.replace(/(from\s+["'])(\.\.?\/[^"']+)\.js(["'])/g, (match, p1, p2, p3) => {
39✔
NEW
66
    return `${p1}${p2}.cjs${p3}`;
×
67
  });
39✔
68
  fs.writeFileSync(filePath, content, 'utf8');
39✔
69
}
39✔
70

1✔
71
/**
1✔
72
 * Recursively patch all .cjs files in a directory
1✔
73
 * @param {string} dir
1✔
74
 */
1✔
75
function doPatch(dir) {
1✔
76
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1✔
77
    const fullPath = path.join(dir, entry.name);
231✔
78
    if (entry.isDirectory()) {
231!
NEW
79
      doPatch(fullPath);
×
80
    } else if (entry.isFile() && fullPath.endsWith('.cjs')) {
231✔
81
      patchFile(fullPath);
39✔
82
    }
39✔
83
  }
231✔
84
}
1✔
85

1✔
86
// Build and then patch .cjs imports
1✔
87
buildTsup().then(() => doPatch(distDir));
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc