Repository: electron-userland/electron-builder
File: packages/app-builder-lib/src/targets/nsis/nsisLicense.ts (TypeScript)

Code before:
import { log } from "builder-util"
import { lcid } from "../../util/langs"
import { getLicenseFiles, getNotLocalizedLicenseFile } from "../../util/license"
import * as path from "path"
import { WinPackager } from "../../winPackager"
import { NsisOptions } from "./nsisOptions"
import { NsisScriptGenerator } from "./nsisScriptGenerator"
import { nsisTemplatesDir } from "./nsisUtil"
import * as fs from "fs"

function convertFileToUtf8WithBOMSync(filePath: string): boolean {
  try {
    const data = fs.readFileSync(filePath)
    const BOM = Buffer.from([0xef, 0xbb, 0xbf])

    // Check if the file already starts with a UTF-8 BOM
    if (data.length >= 3 && data[0] === 0xef && data[1] === 0xbb && data[2] === 0xbf) {
      log.info("File is already in UTF-8 with BOM format")
      return true
    }

    // If not, add the BOM
    const dataWithBOM = Buffer.concat([BOM, data])
    fs.writeFileSync(filePath, dataWithBOM)
    log.info("File successfully converted to UTF-8 with BOM")
    return true
  } catch (err: any) {
    log.error("Failed to convert file to UTF-8 with BOM: ", err.toString())
    return false
  }
}

export async function computeLicensePage(packager: WinPackager, options: NsisOptions, scriptGenerator: NsisScriptGenerator, languages: Array<string>): Promise<void> {
  const license = await getNotLocalizedLicenseFile(options.license, packager)
  if (license != null) {
    let licensePage: Array<string>
    if (license.endsWith(".html")) {
      licensePage = [
        "!define MUI_PAGE_CUSTOMFUNCTION_SHOW LicenseShow",
        "Function LicenseShow",
        "  FindWindow $R0 `#32770` `` $HWNDPARENT",
        "  GetDlgItem $R0 $R0 1000",

Review comment (bug):
Can we extract the common header config and then compare that here? Like this:
```
// UTF-8 BOM is EF BB BF
const header = [0xef, 0xbb, 0xbf];

// Check if the file already starts with a UTF-8 BOM
log.debug({ file: log.filePath(filePath) }, "checking file for BOM header")
if (data.length >= 3 && data[0] === header[0] && data[1] === header[1] && data[2] === header[2]) {
    log.debug({ file: log.filePath(filePath) }, "file is already in BOM format, skipping conversion.")
    return true
}

// If not, add the BOM
try {
    const BOM = Buffer.from(header)
    const dataWithBOM = Buffer.concat([BOM, data])
    fs.writeFileSync(filePath, dataWithBOM)
    log.debug({ file: log.filePath(filePath) }, "file successfully converted to UTF-8 with BOM")
    return true
} catch (err: any) {
    log.error({ file: log.filePath(filePath), message: err.message ?? err.stack }, "unable to convert file to UTF-8 with BOM")
    return false
}
```

Also, I'd recommend changing the `log.info` to `log.debug` so that we don't pollute the main console logs. I also added `file: log.filePath(...)` to the logging object so that it's easy to track down which file fails (might be overkill, but still informative enough for debug logs since multiple license files can be supplied to NSIS installers)

Code after:
import { log } from "builder-util"
import { lcid } from "../../util/langs"
import { getLicenseFiles, getNotLocalizedLicenseFile } from "../../util/license"
import * as path from "path"
import { WinPackager } from "../../winPackager"
import { NsisOptions } from "./nsisOptions"
import { NsisScriptGenerator } from "./nsisScriptGenerator"
import { nsisTemplatesDir } from "./nsisUtil"
import * as fs from "fs"

function convertFileToUtf8WithBOMSync(filePath: string): boolean {
  try {
    const UTF8_BOM_HEADER = Buffer.from([0xef, 0xbb, 0xbf])
    const data = fs.readFileSync(filePath)

    // Check if the file already starts with a UTF-8 BOM
    log.debug({ file: log.filePath(filePath) }, "checking file for BOM header")
    if (data.length >= UTF8_BOM_HEADER.length && data.subarray(0, UTF8_BOM_HEADER.length).equals(UTF8_BOM_HEADER)) {
      log.debug({ file: log.filePath(filePath) }, "file is already in BOM format, skipping conversion.")
      return true
    }

    // If not, add the BOM
    const dataWithBOM = Buffer.concat([UTF8_BOM_HEADER, data])
    fs.writeFileSync(filePath, dataWithBOM)
    log.debug({ file: log.filePath(filePath) }, "file successfully converted to UTF-8 with BOM")
    return true
  } catch (err: any) {
    log.error({ file: log.filePath(filePath), message: err.message ?? err.stack }, "unable to convert file to UTF-8 with BOM")
    return false
  }
}

export async function computeLicensePage(packager: WinPackager, options: NsisOptions, scriptGenerator: NsisScriptGenerator, languages: Array<string>): Promise<void> {
  const license = await getNotLocalizedLicenseFile(options.license, packager)
  if (license != null) {
    let licensePage: Array<string>
    if (license.endsWith(".html")) {
      licensePage = [
        "!define MUI_PAGE_CUSTOMFUNCTION_SHOW LicenseShow",
        "Function LicenseShow",
        "  FindWindow $R0 `#32770` `` $HWNDPARENT",