From 3839feac19a027ed1f09bd157c6dd061592ebf9e Mon Sep 17 00:00:00 2001 From: MikeHughes-BIN Date: Thu, 8 Jan 2026 00:48:00 +0100 Subject: [PATCH] created a new module that takes a html file path and a json path to replace all speakers. Currently only working on command line not integrated --- electron/main/script.js | 4 + package-lock.json | 12 +- .../modules/replace_speaker/replaceSpeaker.js | 120 ++++++++++++++++++ 3 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 services/modules/replace_speaker/replaceSpeaker.js diff --git a/electron/main/script.js b/electron/main/script.js index 910000e..d2ff938 100644 --- a/electron/main/script.js +++ b/electron/main/script.js @@ -338,3 +338,7 @@ function fileDownload() { console.error("Download failed:", error); } } + +function rewriteSpeakerName(){ + console.log("Rewriting speaker name..."); +} diff --git a/package-lock.json b/package-lock.json index 3f885ed..34102fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -450,6 +450,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.2.tgz", "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1305,7 +1306,8 @@ "version": "0.0.1534754", "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1534754.tgz", "integrity": "sha512-26T91cV5dbOYnXdJi5qQHoTtUoNEqwkHcAyu/IKtjIAxiEqPMrDiRkDOPWVsGfNZGmlQVHQbZRSjD8sxagWVsQ==", - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/diff": { "version": "4.0.2", @@ -3488,9 +3490,10 @@ } }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" }, @@ -4204,6 +4207,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/services/modules/replace_speaker/replaceSpeaker.js b/services/modules/replace_speaker/replaceSpeaker.js new file mode 100644 index 0000000..3101c6b --- /dev/null +++ b/services/modules/replace_speaker/replaceSpeaker.js @@ -0,0 +1,120 @@ +const fs = require('fs'); +const path = require('path'); + +const outputDir = path.join(__dirname, "../../../storage/documents"); // path for output directory + +if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); // Create output directory if it doesn't exist +} + +const module_exports = { + name: "replace_speaker", + type: "processor", + displayname: "Speaker Name Replacer", + description: "Replaces speaker placeholder names with actual names based on a mapping in HTML files", + + async function(parameter) { + return new Promise(async (resolve, reject) => { + try { + // console.log("Speaker replacer module invoked with parameters:", parameter); + + resolve(await this.replaceNames( + parameter.inputHtmlPath, // Path to input HTML file + parameter.speakerMappingPath // Path to speaker mapping file (JSON) + )); + + } catch (error) { + // console.error("Error in speaker replacer module:", error); + reject(error) + } + }) + }, + + replaceNames: async function(inputHtmlPath, speakerMappingPath) { + return new Promise(async(resolve, reject) => { + try { + const htmlContent = await fs.promises.readFile(inputHtmlPath, "utf-8"); // read HTML file + const mappingData = await fs.promises.readFile(speakerMappingPath, "utf-8"); // read mapping file + + // Parse mapping - supports JSON or simple format + let speakerMap = {}; + try { + speakerMap = JSON.parse(mappingData); // Try to parse as JSON + } catch (e) { + // If not JSON, try simple format: "Speaker A,Mike\nSpeaker B,Stefan" + const lines = mappingData.trim().split('\n'); + lines.forEach(line => { + const [placeholder, realName] = line.split(',').map(s => s.trim()); + if (placeholder && realName) { + speakerMap[placeholder] = realName; + } + }); + } + + // Replace all speaker names in HTML content + let outputContent = htmlContent; + Object.entries(speakerMap).forEach(([placeholder, realName]) => { + // Create regex to replace all occurrences (case-sensitive) + const regex = new RegExp(`\\b${placeholder}\\b`, 'g'); + outputContent = outputContent.replace(regex, realName); + }); + + // Generate output file path based on input file name + const inputFileName = path.basename(inputHtmlPath, path.extname(inputHtmlPath)); + const outPath = path.join(outputDir, `${inputFileName}_replaced.html`); + + // Write output to file + fs.writeFileSync(outPath, outputContent, "utf8"); + + // console.log("Replaced HTML file written to:", outPath); + resolve(outPath) + + } catch (error) { + // console.error("Error replacing speaker names:", error); + reject(error) + } + }) + } +}; + +module.exports = module_exports; + +// CLI Mode: Allow direct execution +if (require.main === module) { + (async () => { + const args = process.argv.slice(2); + + if (args.length < 2) { + console.error("Usage: node string-replacer.js "); + console.error("Example: node string-replacer.js ./document.html ./speaker_mapping.json"); + console.error("\nMapping file formats:"); + console.error("JSON: {\"Speaker A\": \"Mike\", \"Speaker B\": \"Stefan\"}"); + console.error("or simple: Speaker A,Mike\\nSpeaker B,Stefan"); + process.exit(1); + } + + const [inputHtmlPath, speakerMappingPath] = args; + + // Check if files exist + if (!fs.existsSync(inputHtmlPath)) { + console.error(`ERROR: HTML file not found: ${inputHtmlPath}`); + process.exit(1); + } + + if (!fs.existsSync(speakerMappingPath)) { + console.error(`ERROR: Speaker mapping file not found: ${speakerMappingPath}`); + process.exit(1); + } + + console.log("Starting speaker name replacement..."); + console.log(`HTML file: ${inputHtmlPath}`); + console.log(`Mapping file: ${speakerMappingPath}`); + + await module_exports.replaceNames( + inputHtmlPath, + speakerMappingPath + ); + + console.log("Done!"); + })(); +} \ No newline at end of file