@clazic/kordoc 2.6.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ import {
7
7
  precheckZipSize,
8
8
  sanitizeHref,
9
9
  toArrayBuffer
10
- } from "./chunk-TND4YFBV.js";
10
+ } from "./chunk-USE7IDLV.js";
11
11
  import {
12
12
  parsePageRange
13
13
  } from "./chunk-MOL7MDBG.js";
@@ -9836,19 +9836,250 @@ var ConvertError = class extends Error {
9836
9836
  }
9837
9837
  };
9838
9838
 
9839
- // src/convert/libreoffice.ts
9840
- var libreConvert = libre.convert;
9841
- async function assertSofficeAvailable() {
9842
- const { runCommand } = await import("./utils-F66K7PXH.js");
9839
+ // src/convert/installer.ts
9840
+ import { homedir } from "os";
9841
+ import { join as join2, delimiter } from "path";
9842
+ import { mkdir, access, symlink, rm } from "fs/promises";
9843
+ import { createWriteStream } from "fs";
9844
+ import { spawn } from "child_process";
9845
+ var installInFlight = null;
9846
+ var CACHE_DIR = join2(homedir(), ".cache", "kordoc", "libreoffice");
9847
+ var VERSION_FILE = join2(CACHE_DIR, "version");
9848
+ var PACKAGES = {
9849
+ darwin: {
9850
+ url: "https://download.documentfoundation.org/libreoffice/stable/24.8.4/mac/x86_64/LibreOffice_24.8.4_MacOS_x86-64.dmg",
9851
+ binPath: "LibreOffice.app/Contents/MacOS/soffice",
9852
+ sizeMb: 300
9853
+ },
9854
+ linux: {
9855
+ url: "https://download.documentfoundation.org/libreoffice/stable/24.8.4/deb/x86_64/LibreOffice_24.8.4_Linux_x86-64_deb.tar.gz",
9856
+ binPath: "opt/libreoffice24.8/program/soffice",
9857
+ sizeMb: 200
9858
+ },
9859
+ win32: {
9860
+ url: "https://download.documentfoundation.org/libreoffice/stable/24.8.4/win/x86_64/LibreOffice_24.8.4_Win_x86-64.msi",
9861
+ binPath: "LibreOffice/program/soffice.exe",
9862
+ sizeMb: 350
9863
+ }
9864
+ };
9865
+ async function findInPath() {
9866
+ return new Promise((resolve2) => {
9867
+ const child = spawn("soffice", ["--version"], { stdio: "ignore" });
9868
+ child.on("close", (code) => resolve2(code === 0 ? "soffice" : null));
9869
+ child.on("error", () => resolve2(null));
9870
+ });
9871
+ }
9872
+ async function findInCache() {
9873
+ const cachedBin = join2(CACHE_DIR, "bin", "soffice");
9843
9874
  try {
9844
- await runCommand("soffice", ["--version"]);
9875
+ await access(cachedBin);
9876
+ return cachedBin;
9845
9877
  } catch {
9878
+ return null;
9879
+ }
9880
+ }
9881
+ async function findInDefaultPaths() {
9882
+ const platform = process.platform;
9883
+ const paths = [];
9884
+ if (platform === "darwin") {
9885
+ paths.push(
9886
+ "/Applications/LibreOffice.app/Contents/MacOS/soffice",
9887
+ "/opt/homebrew/bin/soffice",
9888
+ "/usr/local/bin/soffice"
9889
+ );
9890
+ } else if (platform === "linux") {
9891
+ paths.push(
9892
+ "/usr/bin/soffice",
9893
+ "/usr/lib/libreoffice/program/soffice"
9894
+ );
9895
+ } else if (platform === "win32") {
9896
+ const pf = process.env["ProgramFiles"] ?? "C:\\Program Files";
9897
+ const pf86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
9898
+ paths.push(
9899
+ join2(pf, "LibreOffice", "program", "soffice.exe"),
9900
+ join2(pf86, "LibreOffice", "program", "soffice.exe")
9901
+ );
9902
+ }
9903
+ for (const p of paths) {
9904
+ try {
9905
+ await access(p);
9906
+ return p;
9907
+ } catch {
9908
+ continue;
9909
+ }
9910
+ }
9911
+ return null;
9912
+ }
9913
+ async function downloadWithProgress(url, dest, totalBytes, onProgress) {
9914
+ const response = await fetch(url);
9915
+ if (!response.body) throw new Error("\uB2E4\uC6B4\uB85C\uB4DC \uC2E4\uD328: response body \uC5C6\uC74C");
9916
+ const file = createWriteStream(dest);
9917
+ const reader = response.body.getReader();
9918
+ let downloaded = 0;
9919
+ try {
9920
+ while (true) {
9921
+ const { done, value } = await reader.read();
9922
+ if (done) break;
9923
+ file.write(value);
9924
+ downloaded += value.length;
9925
+ onProgress?.(downloaded, totalBytes);
9926
+ }
9927
+ } finally {
9928
+ file.end();
9929
+ reader.releaseLock();
9930
+ }
9931
+ }
9932
+ async function installForPlatform(pkg, onProgress) {
9933
+ const platform = process.platform;
9934
+ await mkdir(CACHE_DIR, { recursive: true });
9935
+ const downloadPath = join2(CACHE_DIR, `download-${Date.now()}`);
9936
+ await downloadWithProgress(pkg.url, downloadPath, pkg.sizeMb * 1024 * 1024, onProgress);
9937
+ try {
9938
+ if (platform === "darwin") {
9939
+ return await installMacOS(pkg, downloadPath);
9940
+ } else if (platform === "linux") {
9941
+ return await installLinux(pkg, downloadPath);
9942
+ } else if (platform === "win32") {
9943
+ return await installWindows(pkg, downloadPath);
9944
+ }
9945
+ } catch (err) {
9946
+ await rm(downloadPath, { force: true });
9947
+ throw err;
9948
+ }
9949
+ throw new ConvertError("UNSUPPORTED_PLATFORM", `${platform}\uC740 \uC790\uB3D9 \uC124\uCE58\uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`);
9950
+ }
9951
+ async function installMacOS(pkg, downloadPath) {
9952
+ const mountPoint = `/Volumes/LibreOffice_${Date.now()}`;
9953
+ await new Promise((resolve2, reject) => {
9954
+ const child = spawn("hdiutil", ["attach", "-nobrowse", "-mountpoint", mountPoint, downloadPath]);
9955
+ child.on("close", (code) => code === 0 ? resolve2() : reject(new Error("dmg \uB9C8\uC6B4\uD2B8 \uC2E4\uD328")));
9956
+ });
9957
+ try {
9958
+ const appSource = join2(mountPoint, "LibreOffice.app");
9959
+ const appDest = join2(CACHE_DIR, "LibreOffice.app");
9960
+ await new Promise((resolve2, reject) => {
9961
+ const child = spawn("cp", ["-R", appSource, appDest]);
9962
+ child.on("close", (code) => code === 0 ? resolve2() : reject(new Error(".app \uBCF5\uC0AC \uC2E4\uD328")));
9963
+ });
9964
+ } finally {
9965
+ await new Promise((resolve2) => {
9966
+ const child = spawn("hdiutil", ["detach", mountPoint]);
9967
+ child.on("close", () => resolve2());
9968
+ });
9969
+ }
9970
+ await rm(downloadPath, { force: true });
9971
+ return await createSymlink(join2(CACHE_DIR, pkg.binPath));
9972
+ }
9973
+ async function installLinux(pkg, downloadPath) {
9974
+ const extractDir = join2(CACHE_DIR, `extract-${Date.now()}`);
9975
+ await mkdir(extractDir, { recursive: true });
9976
+ await new Promise((resolve2, reject) => {
9977
+ const child = spawn("tar", ["xzf", downloadPath, "-C", extractDir]);
9978
+ child.on("close", (code) => code === 0 ? resolve2() : reject(new Error("\uC555\uCD95 \uD574\uC81C \uC2E4\uD328")));
9979
+ });
9980
+ const debsDir = join2(extractDir, "DEBS");
9981
+ try {
9982
+ await access(debsDir);
9983
+ const entries = await (await import("fs/promises")).readdir(debsDir);
9984
+ for (const entry of entries) {
9985
+ if (entry.endsWith(".deb")) {
9986
+ await new Promise((resolve2, reject) => {
9987
+ const child = spawn("dpkg-deb", ["-x", join2(debsDir, entry), CACHE_DIR]);
9988
+ child.on("close", (code) => code === 0 ? resolve2() : reject(new Error(`${entry} \uCD94\uCD9C \uC2E4\uD328`)));
9989
+ });
9990
+ }
9991
+ }
9992
+ } catch {
9993
+ }
9994
+ await rm(downloadPath, { force: true });
9995
+ await rm(extractDir, { recursive: true, force: true });
9996
+ return await createSymlink(join2(CACHE_DIR, pkg.binPath));
9997
+ }
9998
+ async function installWindows(pkg, downloadPath) {
9999
+ await new Promise((resolve2, reject) => {
10000
+ const child = spawn("msiexec", ["/a", downloadPath, "/qn", `TARGETDIR=${CACHE_DIR}`]);
10001
+ child.on("close", (code) => code === 0 ? resolve2() : reject(new Error("MSI \uC124\uCE58 \uC2E4\uD328")));
10002
+ });
10003
+ await rm(downloadPath, { force: true });
10004
+ return join2(CACHE_DIR, pkg.binPath);
10005
+ }
10006
+ async function createSymlink(actualBin) {
10007
+ const binDir = join2(CACHE_DIR, "bin");
10008
+ await mkdir(binDir, { recursive: true });
10009
+ const linkBin = join2(binDir, "soffice");
10010
+ try {
10011
+ await symlink(actualBin, linkBin);
10012
+ } catch {
10013
+ }
10014
+ process.env.PATH = `${binDir}${delimiter}${process.env.PATH}`;
10015
+ return linkBin;
10016
+ }
10017
+ async function installLibreOffice(onProgress) {
10018
+ const platform = process.platform;
10019
+ const pkg = PACKAGES[platform];
10020
+ if (!pkg) {
9846
10021
  throw new ConvertError(
10022
+ "UNSUPPORTED_PLATFORM",
10023
+ `${platform}\uC740 \uC790\uB3D9 \uC124\uCE58\uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC218\uB3D9\uC73C\uB85C LibreOffice\uB97C \uC124\uCE58\uD574 \uC8FC\uC138\uC694.`
10024
+ );
10025
+ }
10026
+ return await installForPlatform(pkg, onProgress);
10027
+ }
10028
+ async function resolveSoffice(emitter, autoInstall = true) {
10029
+ emitter.validate("soffice_check", "LibreOffice \uAC00\uC6A9\uC131 \uD655\uC778 \uC911...");
10030
+ const inPath = await findInPath();
10031
+ if (inPath) {
10032
+ emitter.validate("soffice_found", "\uC2DC\uC2A4\uD15C PATH\uC5D0\uC11C LibreOffice \uBC1C\uACAC", { sofficePath: inPath });
10033
+ return inPath;
10034
+ }
10035
+ const inCache = await findInCache();
10036
+ if (inCache) {
10037
+ emitter.validate("soffice_found", "\uCE90\uC2DC\uB41C LibreOffice \uBC1C\uACAC", { sofficePath: inCache });
10038
+ return inCache;
10039
+ }
10040
+ const inDefault = await findInDefaultPaths();
10041
+ if (inDefault) {
10042
+ emitter.validate("soffice_found", "\uAE30\uBCF8 \uACBD\uB85C\uC5D0\uC11C LibreOffice \uBC1C\uACAC", { sofficePath: inDefault });
10043
+ return inDefault;
10044
+ }
10045
+ if (!autoInstall) {
10046
+ emitter.error(
10047
+ "validate",
9847
10048
  "SOFFICE_NOT_FOUND",
9848
- "soffice\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. LibreOffice\uB97C \uC124\uCE58\uD574 \uC8FC\uC138\uC694."
10049
+ "LibreOffice\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
10050
+ "\uC218\uB3D9\uC73C\uB85C \uC124\uCE58\uD558\uAC70\uB098 autoInstallLibreOffice: true \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694."
9849
10051
  );
10052
+ throw new ConvertError("SOFFICE_NOT_FOUND", "LibreOffice\uAC00 \uC124\uCE58\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
9850
10053
  }
10054
+ if (installInFlight) {
10055
+ return installInFlight;
10056
+ }
10057
+ emitter.install("install_start", "LibreOffice \uC790\uB3D9 \uC124\uCE58\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4...");
10058
+ installInFlight = (async () => {
10059
+ try {
10060
+ const installed = await installLibreOffice((downloaded, total) => {
10061
+ const percent = Math.round(downloaded / total * 100);
10062
+ emitter.install("download_progress", `\uB2E4\uC6B4\uB85C\uB4DC \uC911... ${percent}%`, {
10063
+ percent,
10064
+ downloadedBytes: downloaded,
10065
+ totalBytes: total
10066
+ });
10067
+ });
10068
+ emitter.install("install_complete", "\uC124\uCE58 \uC644\uB8CC", { installedPath: installed });
10069
+ return installed;
10070
+ } catch (err) {
10071
+ const errorMsg = err instanceof Error ? err.message : String(err);
10072
+ emitter.install("install_failed", "\uC124\uCE58 \uC2E4\uD328", { error: errorMsg });
10073
+ throw err;
10074
+ } finally {
10075
+ installInFlight = null;
10076
+ }
10077
+ })();
10078
+ return installInFlight;
9851
10079
  }
10080
+
10081
+ // src/convert/libreoffice.ts
10082
+ var libreConvert = libre.convert;
9852
10083
  async function convertBuffer(buffer, targetExt, timeoutMs = 6e4) {
9853
10084
  return new Promise((resolve2, reject) => {
9854
10085
  const timer = setTimeout(() => {
@@ -9872,6 +10103,54 @@ async function convertBuffer(buffer, targetExt, timeoutMs = 6e4) {
9872
10103
  });
9873
10104
  }
9874
10105
 
10106
+ // src/convert/events.ts
10107
+ var ConvertEventEmitter = class {
10108
+ listener = null;
10109
+ /** 이벤트 리스너 등록 */
10110
+ setListener(listener) {
10111
+ this.listener = listener;
10112
+ }
10113
+ /** 이벤트 발송 */
10114
+ emit(event) {
10115
+ try {
10116
+ this.listener?.(event);
10117
+ } catch {
10118
+ }
10119
+ }
10120
+ /** 타입 안전한 헬퍼: detect 이벤트 */
10121
+ detect(stage, message, meta) {
10122
+ this.emit({ type: "detect", stage, message, ...meta });
10123
+ }
10124
+ /** 타입 안전한 헬퍼: validate 이벤트 */
10125
+ validate(stage, message, meta) {
10126
+ this.emit({ type: "validate", stage, message, ...meta });
10127
+ }
10128
+ /** 타입 안전한 헬퍼: install 이벤트 */
10129
+ install(stage, message, meta) {
10130
+ this.emit({ type: "install", stage, message, ...meta });
10131
+ }
10132
+ /** 타입 안전한 헬퍼: convert 진행 이벤트 */
10133
+ progress(percent, message) {
10134
+ this.emit({ type: "convert", stage: "convert_progress", message, percent });
10135
+ }
10136
+ /** 타입 안전한 헬퍼: convert 시작 */
10137
+ convertStart(message) {
10138
+ this.emit({ type: "convert", stage: "convert_start", message, percent: 0 });
10139
+ }
10140
+ /** 타입 안전한 헬퍼: convert 완료 */
10141
+ convertDone(message) {
10142
+ this.emit({ type: "convert", stage: "convert_done", message, percent: 100 });
10143
+ }
10144
+ /** 타입 안전한 헬퍼: 완료 이벤트 */
10145
+ complete(result) {
10146
+ this.emit({ type: "complete", stage: "success", message: "\uBCC0\uD658 \uC644\uB8CC", result });
10147
+ }
10148
+ /** 타입 안전한 헬퍼: 에러 이벤트 */
10149
+ error(stage, code, message, suggestion) {
10150
+ this.emit({ type: "error", stage, code, message, recoverable: true, suggestion });
10151
+ }
10152
+ };
10153
+
9875
10154
  // src/convert/index.ts
9876
10155
  var isConverting = false;
9877
10156
  var queue = [];
@@ -9896,81 +10175,129 @@ async function acquireConvertLock() {
9896
10175
  });
9897
10176
  }
9898
10177
  async function convertToPdf(input, options) {
9899
- let buffer;
9900
- try {
9901
- if (typeof input === "string") {
9902
- buffer = await readFile(input);
9903
- } else if (Buffer.isBuffer(input)) {
9904
- buffer = input;
9905
- } else {
9906
- buffer = Buffer.from(input);
9907
- }
9908
- } catch (err) {
9909
- return {
9910
- success: false,
9911
- code: "PARSE_ERROR",
9912
- error: `\uC785\uB825 \uC77D\uAE30 \uC2E4\uD328: ${err instanceof Error ? err.message : String(err)}`,
9913
- stage: "detect"
9914
- };
9915
- }
9916
- const MAX_FILE_SIZE = 500 * 1024 * 1024;
9917
- if (buffer.length > MAX_FILE_SIZE) {
9918
- return {
9919
- success: false,
9920
- code: "FILE_TOO_LARGE",
9921
- error: `\uD30C\uC77C \uD06C\uAE30 \uCD08\uACFC: ${(buffer.length / 1024 / 1024).toFixed(1)}MB (\uCD5C\uB300 500MB)`,
9922
- stage: "detect"
9923
- };
10178
+ const emitter = new ConvertEventEmitter();
10179
+ if (options?.onEvent) {
10180
+ emitter.setListener(options.onEvent);
9924
10181
  }
9925
- const format = detectFormat(toArrayBuffer(buffer));
9926
- if (format !== "hwp" && format !== "hwpx") {
9927
- return {
9928
- success: false,
9929
- code: "UNSUPPORTED_FORMAT",
9930
- error: `\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD3EC\uB9F7\uC785\uB2C8\uB2E4: ${format}`,
9931
- stage: "detect"
9932
- };
10182
+ if (options?.onProgress) {
10183
+ const legacyProgress = options.onProgress;
10184
+ emitter.setListener((event) => {
10185
+ if (event.type === "convert" && event.stage === "convert_progress") {
10186
+ legacyProgress(event.percent, event.message);
10187
+ }
10188
+ });
9933
10189
  }
9934
10190
  try {
9935
- await assertSofficeAvailable();
9936
- } catch (err) {
9937
- if (err instanceof ConvertError) {
10191
+ emitter.detect("reading", "\uC785\uB825 \uD30C\uC77C \uC77D\uB294 \uC911...");
10192
+ let buffer;
10193
+ try {
10194
+ if (typeof input === "string") {
10195
+ buffer = await readFile(input);
10196
+ } else if (Buffer.isBuffer(input)) {
10197
+ buffer = input;
10198
+ } else {
10199
+ buffer = Buffer.from(input);
10200
+ }
10201
+ } catch (err) {
10202
+ emitter.error(
10203
+ "detect",
10204
+ "PARSE_ERROR",
10205
+ `\uC785\uB825 \uC77D\uAE30 \uC2E4\uD328: ${err instanceof Error ? err.message : String(err)}`
10206
+ );
9938
10207
  return {
9939
10208
  success: false,
9940
- code: err.code,
9941
- error: err.message,
9942
- stage: "validate"
10209
+ code: "PARSE_ERROR",
10210
+ error: `\uC785\uB825 \uC77D\uAE30 \uC2E4\uD328: ${err instanceof Error ? err.message : String(err)}`,
10211
+ stage: "detect"
9943
10212
  };
9944
10213
  }
9945
- throw err;
9946
- }
9947
- const releaseLock = await acquireConvertLock();
9948
- try {
9949
- options?.onProgress?.(10, "convert");
9950
- const pdf = await convertBuffer(buffer, ".pdf", options?.timeoutMs);
9951
- options?.onProgress?.(100, "done");
9952
- return {
9953
- success: true,
9954
- pdf: new Uint8Array(pdf),
9955
- sourceFormat: format
9956
- };
9957
- } catch (err) {
9958
- if (err instanceof ConvertError) {
10214
+ const MAX_FILE_SIZE = 500 * 1024 * 1024;
10215
+ if (buffer.length > MAX_FILE_SIZE) {
10216
+ emitter.error(
10217
+ "detect",
10218
+ "FILE_TOO_LARGE",
10219
+ `\uD30C\uC77C \uD06C\uAE30 \uCD08\uACFC: ${(buffer.length / 1024 / 1024).toFixed(1)}MB (\uCD5C\uB300 500MB)`
10220
+ );
10221
+ return {
10222
+ success: false,
10223
+ code: "FILE_TOO_LARGE",
10224
+ error: `\uD30C\uC77C \uD06C\uAE30 \uCD08\uACFC: ${(buffer.length / 1024 / 1024).toFixed(1)}MB (\uCD5C\uB300 500MB)`,
10225
+ stage: "detect"
10226
+ };
10227
+ }
10228
+ const format = detectFormat(toArrayBuffer(buffer));
10229
+ emitter.detect("format_detected", `\uD3EC\uB9F7 \uAC10\uC9C0 \uC644\uB8CC: ${format}`, { format });
10230
+ if (format !== "hwp" && format !== "hwpx") {
10231
+ emitter.error("detect", "UNSUPPORTED_FORMAT", `\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD3EC\uB9F7\uC785\uB2C8\uB2E4: ${format}`);
10232
+ return {
10233
+ success: false,
10234
+ code: "UNSUPPORTED_FORMAT",
10235
+ error: `\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD3EC\uB9F7\uC785\uB2C8\uB2E4: ${format}`,
10236
+ stage: "detect"
10237
+ };
10238
+ }
10239
+ emitter.validate("soffice_check", "LibreOffice \uAC00\uC6A9\uC131 \uD655\uC778 \uC911...");
10240
+ let sofficePath;
10241
+ try {
10242
+ sofficePath = await resolveSoffice(emitter, options?.autoInstallLibreOffice ?? true);
10243
+ } catch (err) {
10244
+ if (err instanceof ConvertError) {
10245
+ return {
10246
+ success: false,
10247
+ code: err.code,
10248
+ error: err.message,
10249
+ stage: "validate"
10250
+ };
10251
+ }
10252
+ throw err;
10253
+ }
10254
+ const releaseLock = await acquireConvertLock();
10255
+ try {
10256
+ emitter.convertStart("\uBCC0\uD658 \uC2DC\uC791...");
10257
+ emitter.progress(10, "\uBCC0\uD658 \uC911...");
10258
+ const pdf = await convertBuffer(buffer, ".pdf", options?.timeoutMs);
10259
+ emitter.progress(100, "\uBCC0\uD658 \uC644\uB8CC");
10260
+ emitter.convertDone("\uBCC0\uD658 \uC644\uB8CC");
10261
+ const result = {
10262
+ success: true,
10263
+ pdf: new Uint8Array(pdf),
10264
+ sourceFormat: format
10265
+ };
10266
+ emitter.complete({
10267
+ sourceFormat: format,
10268
+ pdfSize: pdf.length
10269
+ });
10270
+ return result;
10271
+ } catch (err) {
10272
+ if (err instanceof ConvertError) {
10273
+ emitter.error("convert", err.code, err.message);
10274
+ return {
10275
+ success: false,
10276
+ code: err.code,
10277
+ error: err.message,
10278
+ stage: "convert"
10279
+ };
10280
+ }
10281
+ const errorMsg = err instanceof Error ? err.message : "\uBCC0\uD658 \uC2E4\uD328";
10282
+ emitter.error("convert", classifyError(err), errorMsg);
9959
10283
  return {
9960
10284
  success: false,
9961
- code: err.code,
9962
- error: err.message,
10285
+ code: classifyError(err),
10286
+ error: errorMsg,
9963
10287
  stage: "convert"
9964
10288
  };
10289
+ } finally {
10290
+ releaseLock();
9965
10291
  }
10292
+ } catch (unexpectedErr) {
10293
+ const errorMsg = unexpectedErr instanceof Error ? unexpectedErr.message : "\uC608\uC0C1\uCE58 \uBABB\uD55C \uC624\uB958";
10294
+ emitter.error("convert", "PARSE_ERROR", errorMsg);
9966
10295
  return {
9967
10296
  success: false,
9968
- code: classifyError(err),
9969
- error: err instanceof Error ? err.message : "\uBCC0\uD658 \uC2E4\uD328",
10297
+ code: "PARSE_ERROR",
10298
+ error: errorMsg,
9970
10299
  stage: "convert"
9971
10300
  };
9972
- } finally {
9973
- releaseLock();
9974
10301
  }
9975
10302
  }
9976
10303
 
@@ -10358,4 +10685,4 @@ export {
10358
10685
  cfb/cfb.js:
10359
10686
  (*! crc32.js (C) 2014-present SheetJS -- http://sheetjs.com *)
10360
10687
  */
10361
- //# sourceMappingURL=chunk-TS3F57LY.js.map
10688
+ //# sourceMappingURL=chunk-3FTA6V7S.js.map