mirror of
https://github.com/gavvvr/obsidian-timecodes-plugin.git
synced 2026-07-22 05:38:08 +00:00
build: add task producing instrumented build for measuring code coverage
#5
This commit is contained in:
parent
56f5a6362c
commit
8c674b5dcf
3 changed files with 59 additions and 0 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node scripts/dev.js",
|
"dev": "node scripts/dev.js",
|
||||||
"build": "tsc -noEmit -skipLibCheck && node scripts/esbuild.build.js production",
|
"build": "tsc -noEmit -skipLibCheck && node scripts/esbuild.build.js production",
|
||||||
|
"build:coverage": "node scripts/esbuild.build.js coverage",
|
||||||
"test:eslint": "eslint --cache --cache-location out/.eslintcache",
|
"test:eslint": "eslint --cache --cache-location out/.eslintcache",
|
||||||
"test:unit": "vitest --coverage"
|
"test:unit": "vitest --coverage"
|
||||||
},
|
},
|
||||||
|
|
@ -18,6 +19,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "9.37.0",
|
"@eslint/js": "9.37.0",
|
||||||
"@stylistic/eslint-plugin": "5.4.0",
|
"@stylistic/eslint-plugin": "5.4.0",
|
||||||
|
"@types/istanbul-lib-instrument": "1.7.8",
|
||||||
"@types/node": "24.6.2",
|
"@types/node": "24.6.2",
|
||||||
"@vitest/coverage-v8": "3.2.4",
|
"@vitest/coverage-v8": "3.2.4",
|
||||||
"enquirer": "2.4.1",
|
"enquirer": "2.4.1",
|
||||||
|
|
@ -26,6 +28,7 @@
|
||||||
"eslint-plugin-perfectionist": "4.15.1",
|
"eslint-plugin-perfectionist": "4.15.1",
|
||||||
"eslint-plugin-wdio": "9.16.2",
|
"eslint-plugin-wdio": "9.16.2",
|
||||||
"globals": "16.4.0",
|
"globals": "16.4.0",
|
||||||
|
"istanbul-lib-instrument": "6.0.3",
|
||||||
"obsidian": "1.10.0",
|
"obsidian": "1.10.0",
|
||||||
"obsidian-utils": "0.10.2",
|
"obsidian-utils": "0.10.2",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,30 @@ import process from 'node:process'
|
||||||
import esbuild from 'esbuild'
|
import esbuild from 'esbuild'
|
||||||
|
|
||||||
import { sharedEsbuildConfig } from './esbuild.config.js'
|
import { sharedEsbuildConfig } from './esbuild.config.js'
|
||||||
|
import { instrumentWithSourceMaps } from './utils/instrument.js'
|
||||||
|
|
||||||
const config = sharedEsbuildConfig
|
const config = sharedEsbuildConfig
|
||||||
|
|
||||||
const prod = process.argv[2] === 'production'
|
const prod = process.argv[2] === 'production'
|
||||||
|
const coverage = process.argv[2] === 'coverage'
|
||||||
|
|
||||||
const context = await esbuild.context({
|
const context = await esbuild.context({
|
||||||
...config,
|
...config,
|
||||||
...prod
|
...prod
|
||||||
? { minify: true, sourcemap: false }
|
? { minify: true, sourcemap: false }
|
||||||
: {},
|
: {},
|
||||||
|
...coverage
|
||||||
|
? { minify: false, sourcemap: 'inline' }
|
||||||
|
: {},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (prod) {
|
if (prod) {
|
||||||
await context.rebuild()
|
await context.rebuild()
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
|
} else if (coverage) {
|
||||||
|
await context.rebuild()
|
||||||
|
instrumentWithSourceMaps('out/main.js', 'out/main.js')
|
||||||
|
process.exit(0)
|
||||||
} else {
|
} else {
|
||||||
await context.watch()
|
await context.watch()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
47
scripts/utils/instrument.js
Normal file
47
scripts/utils/instrument.js
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
// @ts-check
|
||||||
|
import * as fs from 'node:fs'
|
||||||
|
|
||||||
|
import { createInstrumenter } from 'istanbul-lib-instrument'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrument a JavaScript file with Istanbul coverage instrumentation
|
||||||
|
* while preserving and remapping original sourcemaps
|
||||||
|
* @param {string} inputFile
|
||||||
|
* @param {string} outputFile
|
||||||
|
*/
|
||||||
|
export function instrumentWithSourceMaps(inputFile, outputFile) {
|
||||||
|
const code = fs.readFileSync(inputFile, 'utf8')
|
||||||
|
|
||||||
|
// Extract the original sourcemap from the bundled file
|
||||||
|
const sourceMapMatch
|
||||||
|
= code.match(/\/\/# sourceMappingURL=data:application\/json;base64,(.+)/)
|
||||||
|
if (!sourceMapMatch) throw new Error(`No sourcemap found in ${inputFile}`)
|
||||||
|
|
||||||
|
const sourceMapJson = Buffer.from(sourceMapMatch[1].trim(), 'base64').toString('utf8')
|
||||||
|
const originalSourceMap = JSON.parse(sourceMapJson)
|
||||||
|
|
||||||
|
const instrumenter = createInstrumenter({
|
||||||
|
esModules: false, // esbuild outputs Obsidian plugins as CommonJS
|
||||||
|
compact: false,
|
||||||
|
preserveComments: true,
|
||||||
|
produceSourceMap: true,
|
||||||
|
autoWrap: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const instrumentedCode = instrumenter.instrumentSync(
|
||||||
|
code,
|
||||||
|
inputFile,
|
||||||
|
originalSourceMap, // <- This is critical for sourcemaps remapping!
|
||||||
|
)
|
||||||
|
const sourceMap = instrumenter.lastSourceMap()
|
||||||
|
|
||||||
|
let output = instrumentedCode
|
||||||
|
if (!sourceMap) throw new Error('No source map found!')
|
||||||
|
|
||||||
|
const base64SourceMap = Buffer.from(JSON.stringify(sourceMap)).toString('base64')
|
||||||
|
output += `\n//# sourceMappingURL=data:application/json;base64,${base64SourceMap}`
|
||||||
|
|
||||||
|
fs.writeFileSync(outputFile, output, 'utf8')
|
||||||
|
|
||||||
|
console.log(`✓ Instrumented: ${inputFile} -> ${outputFile}`)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue