docling-serve-client 0.4.0 → 0.6.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.
package/dist/index.js CHANGED
@@ -250,6 +250,70 @@ function fail(error) {
250
250
  return { ok: false, error };
251
251
  }
252
252
 
253
+ // src/capabilities.ts
254
+ function readCapabilities(body) {
255
+ if (!isPlainObject(body)) {
256
+ return fail(ERR.INVALID_RESPONSE("Capabilities response is not a JSON object"));
257
+ }
258
+ const targets = objectOf(body.targets);
259
+ const features = objectOf(body.features);
260
+ return ok({
261
+ versions: Object.fromEntries(Object.entries(objectOf(body.versions)).filter((entry) => typeof entry[1] === "string")),
262
+ stages: Object.fromEntries(Object.entries(objectOf(body.stages)).map(([name, stage]) => [name, readStage(objectOf(stage))])),
263
+ sources: stringsOf(body.sources),
264
+ targets: { allowed: stringsOf(targets.allowed), default: stringOf(targets.default) },
265
+ outputFormats: stringsOf(body.output_formats),
266
+ imageExportModes: stringsOf(body.image_export_modes),
267
+ limits: readLimits(objectOf(body.limits)),
268
+ features: {
269
+ apiKeyRequired: features.api_key_required === true,
270
+ artifactStorage: features.artifact_storage === true,
271
+ websocket: features.websocket === true
272
+ }
273
+ });
274
+ }
275
+ function readStage(stage) {
276
+ const presets = [];
277
+ for (const item of Array.isArray(stage.presets) ? stage.presets : []) {
278
+ const preset = objectOf(item);
279
+ if (typeof preset.id === "string") {
280
+ presets.push({
281
+ id: preset.id,
282
+ name: stringOf(preset.name),
283
+ description: typeof preset.description === "string" ? preset.description : null,
284
+ source: stringOf(preset.source)
285
+ });
286
+ }
287
+ }
288
+ return {
289
+ option: stringOf(stage.option),
290
+ customConfigOption: typeof stage.custom_config_option === "string" ? stage.custom_config_option : null,
291
+ default: stringOf(stage.default),
292
+ presets
293
+ };
294
+ }
295
+ function readLimits(limits) {
296
+ return {
297
+ maxDocumentTimeout: numberOf(limits.max_document_timeout),
298
+ maxImagesScale: numberOf(limits.max_images_scale),
299
+ maxSourcesPerRequest: numberOf(limits.max_sources_per_request),
300
+ maxNumPages: numberOf(limits.max_num_pages),
301
+ maxFileSize: numberOf(limits.max_file_size)
302
+ };
303
+ }
304
+ function objectOf(value) {
305
+ return isPlainObject(value) ? value : {};
306
+ }
307
+ function stringsOf(value) {
308
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
309
+ }
310
+ function stringOf(value) {
311
+ return typeof value === "string" ? value : "";
312
+ }
313
+ function numberOf(value) {
314
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
315
+ }
316
+
253
317
  // src/core/http.ts
254
318
  var STRING_TOO_LONG = "ERR_STRING_TOO_LONG";
255
319
  var MATCH_OUT_OF_MEMORY = /out of memory/i;
@@ -368,7 +432,8 @@ var DEFAULT_OPTIONS = Object.freeze({
368
432
  pipeline: "standard",
369
433
  pdfBackend: "docling_parse",
370
434
  ocr: true,
371
- forceOcr: false
435
+ forceOcr: false,
436
+ ocrEngine: "auto"
372
437
  });
373
438
  var CALL_OPTION_RULES = {
374
439
  headingHierarchy: isBoolean,
@@ -378,7 +443,8 @@ var CALL_OPTION_RULES = {
378
443
  pipeline: (value) => isOneOf(value, PIPELINES),
379
444
  pdfBackend: (value) => isOneOf(value, PDF_BACKENDS),
380
445
  ocr: isBoolean,
381
- forceOcr: isBoolean
446
+ forceOcr: isBoolean,
447
+ ocrEngine: (value) => typeof value === "string" && value !== ""
382
448
  };
383
449
  var CLIENT_OPTION_RULES = {
384
450
  ...CALL_OPTION_RULES,
@@ -405,24 +471,46 @@ var IMAGE_OPTION_RULES = {
405
471
  var CHECK_RULES = {
406
472
  signal: isAbortSignal
407
473
  };
474
+ var POLL_RULES = {
475
+ ...CHECK_RULES,
476
+ pollMs: isTimerDelay
477
+ };
478
+ var RUN_MARKDOWN_RULES = {
479
+ ...MARKDOWN_RULES,
480
+ ...POLL_RULES
481
+ };
482
+ var RUN_DOCUMENT_RULES = {
483
+ ...DOCUMENT_RULES,
484
+ ...POLL_RULES
485
+ };
408
486
  var CONFIG_RULES = {
409
487
  baseUrl: isHttpUrl,
410
488
  apiKey: (value) => typeof value === "string" && value !== "",
411
489
  fetch: (value) => typeof value === "function",
412
- timeoutMs: isPositiveNumber,
490
+ timeoutMs: isTimerDelay,
491
+ pollMs: isTimerDelay,
413
492
  options: isPlainObject
414
493
  };
494
+ var DEFAULT_POLL_MS = 10;
415
495
  var MATCH_JOB_ID = /^[\w-]+$/;
416
496
  var MATCH_LANGUAGE_TAG = /^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$/;
417
497
  var MATCH_IMAGE_PREFIX = /^[^\s()<>]+$/;
418
498
  var MATCH_TRAILING_SLASHES = /\/+$/;
419
499
  var MATCH_HTTP_PROTOCOL = /^https?:$/;
500
+ var MAX_TIMEOUT_MS = 2147483647;
420
501
  var INVALID_JOB = "Expected the job object returned by submitMarkdown() or submitDocument()";
421
502
  function resolveConfig(config) {
422
503
  if (!isPlainObject(config)) {
423
504
  throw new TypeError("Invalid config: expected an object");
424
505
  }
425
- const { baseUrl, apiKey, fetch: fetchFn, timeoutMs, options } = validateKeys(config, CONFIG_RULES);
506
+ const {
507
+ baseUrl,
508
+ apiKey,
509
+ fetch: fetchFn,
510
+ timeoutMs,
511
+ pollMs = DEFAULT_POLL_MS,
512
+ options
513
+ } = validateKeys(config, CONFIG_RULES);
426
514
  if (baseUrl === undefined) {
427
515
  throw new TypeError(invalidValue("baseUrl"));
428
516
  }
@@ -435,31 +523,31 @@ function resolveConfig(config) {
435
523
  ...apiKey === undefined ? {} : { apiKey },
436
524
  fetch: fetchFn ?? fetch,
437
525
  ...timeoutMs === undefined ? {} : { timeoutMs },
526
+ pollMs,
438
527
  defaults
439
528
  };
440
529
  }
441
530
  function resolveMarkdownCall(defaults, options) {
442
- const {
443
- signal,
444
- images = "placeholder",
445
- imageOptions,
446
- ...docling
447
- } = validateKeys(callObject(options), MARKDOWN_RULES);
448
- const output = resolveImageOutput(images, imageOptions);
449
- return { options: { ...defaults, ...docling }, output, ...signal === undefined ? {} : { signal } };
531
+ return toMarkdownCall(defaults, validateKeys(callObject(options), MARKDOWN_RULES));
450
532
  }
451
533
  function resolveDocumentCall(defaults, options) {
452
- const {
453
- signal,
454
- images = "embedded",
455
- pageImages = false,
456
- ...docling
457
- } = validateKeys(callObject(options), DOCUMENT_RULES);
458
- return { options: { ...defaults, ...docling }, images, pageImages, ...signal === undefined ? {} : { signal } };
534
+ return toDocumentCall(defaults, validateKeys(callObject(options), DOCUMENT_RULES));
535
+ }
536
+ function resolveRunMarkdownCall(defaults, defaultPollMs, options) {
537
+ const { pollMs = defaultPollMs, ...call } = validateKeys(callObject(options), RUN_MARKDOWN_RULES);
538
+ return { ...toMarkdownCall(defaults, call), pollMs };
539
+ }
540
+ function resolveRunDocumentCall(defaults, defaultPollMs, options) {
541
+ const { pollMs = defaultPollMs, ...call } = validateKeys(callObject(options), RUN_DOCUMENT_RULES);
542
+ return { ...toDocumentCall(defaults, call), pollMs };
459
543
  }
460
544
  function resolveCheckOptions(options) {
461
545
  return validateKeys(callObject(options), CHECK_RULES);
462
546
  }
547
+ function resolvePollOptions(defaultPollMs, options) {
548
+ const { pollMs = defaultPollMs, signal } = validateKeys(callObject(options), POLL_RULES);
549
+ return { pollMs, ...signal === undefined ? {} : { signal } };
550
+ }
463
551
  function validateJob(job) {
464
552
  if (!isPlainObject(job) || !isJobId(job.id)) {
465
553
  return fail(ERR.INVALID_INPUT(INVALID_JOB));
@@ -492,6 +580,15 @@ function callObject(options) {
492
580
  }
493
581
  return options;
494
582
  }
583
+ function toMarkdownCall(defaults, options) {
584
+ const { signal, images = "placeholder", imageOptions, ...docling } = options;
585
+ const output = resolveImageOutput(images, imageOptions);
586
+ return { options: { ...defaults, ...docling }, output, ...signal === undefined ? {} : { signal } };
587
+ }
588
+ function toDocumentCall(defaults, options) {
589
+ const { signal, images = "embedded", pageImages = false, ...docling } = options;
590
+ return { options: { ...defaults, ...docling }, images, pageImages, ...signal === undefined ? {} : { signal } };
591
+ }
495
592
  function resolveImageOutput(images, imageOptions) {
496
593
  if (images !== "extract") {
497
594
  if (imageOptions !== undefined) {
@@ -514,6 +611,9 @@ function resolveImageOutput(images, imageOptions) {
514
611
  function isPositiveNumber(value) {
515
612
  return typeof value === "number" && Number.isFinite(value) && value > 0;
516
613
  }
614
+ function isTimerDelay(value) {
615
+ return typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= MAX_TIMEOUT_MS;
616
+ }
517
617
  function isPageRange(value) {
518
618
  return Array.isArray(value) && value.length === 2 && Number.isInteger(value[0]) && Number.isInteger(value[1]) && value[0] >= 1 && value[1] >= value[0];
519
619
  }
@@ -527,7 +627,11 @@ function isAbortSignal(value) {
527
627
  return value instanceof AbortSignal;
528
628
  }
529
629
  function isHttpUrl(value) {
530
- return typeof value === "string" && URL.canParse(value) && MATCH_HTTP_PROTOCOL.test(new URL(value).protocol);
630
+ if (typeof value !== "string" || !URL.canParse(value) || value.includes("?") || value.includes("#")) {
631
+ return false;
632
+ }
633
+ const url = new URL(value);
634
+ return MATCH_HTTP_PROTOCOL.test(url.protocol) && url.username === "" && url.password === "";
531
635
  }
532
636
 
533
637
  // src/response.ts
@@ -635,10 +739,11 @@ function isPageNumber(value) {
635
739
  }
636
740
 
637
741
  // src/client.ts
638
- var FIXED_FORM_FIELDS = [
639
- ["do_table_structure", "true"],
640
- ["table_mode", "accurate"]
641
- ];
742
+ var TABLE_STRUCTURE_PRESET = "tableformer_v1_accurate";
743
+ var VLM_PIPELINE_PRESET = "granite_docling";
744
+ var CHART_EXTRACTION_PRESET = "granite_vision_v4";
745
+ var CODE_FORMULA_PRESET = "codeformulav2";
746
+ var MATCH_UPPER_CASE = /[A-Z]/g;
642
747
  var INVALID_INPUT = "Expected a non-empty PDF, PNG, JPEG, TIFF or WebP as Uint8Array";
643
748
  var SERVER_ANSWERED = new Set([
644
749
  "http",
@@ -649,7 +754,7 @@ var SERVER_ANSWERED = new Set([
649
754
  var VERSION_TIMEOUT_MS = 2000;
650
755
  var MAX_SHOWN_ID_LENGTH = 100;
651
756
  function createDoclingClient(config) {
652
- const { baseUrl, apiKey, fetch: fetchFn, timeoutMs, defaults } = resolveConfig(config);
757
+ const { baseUrl, apiKey, fetch: fetchFn, timeoutMs, pollMs, defaults } = resolveConfig(config);
653
758
  const headers = apiKey === undefined ? {} : { "X-Api-Key": apiKey };
654
759
  let versionsCache;
655
760
  return {
@@ -657,13 +762,21 @@ function createDoclingClient(config) {
657
762
  convertDocument,
658
763
  submitMarkdown,
659
764
  submitDocument,
660
- check
765
+ check,
766
+ runMarkdown,
767
+ runDocument,
768
+ waitForJob,
769
+ capabilities
661
770
  };
662
771
  async function convertMarkdown(input, options) {
663
772
  const call = resolveMarkdownCall(defaults, options);
664
773
  const fields = { format: "md", embedImages: call.output.images === "extract", pageImages: false };
665
774
  const res = await post("/v1/convert/file", input, call.options, fields, call.signal);
666
- return res.ok ? withVersions(readMarkdown(res.data, call.output)) : res;
775
+ if (!res.ok) {
776
+ return res;
777
+ }
778
+ const converted = await withVersions(readMarkdown(res.data.body, call.output));
779
+ return converted.ok ? ok({ ...converted.data, settings: res.data.settings }) : converted;
667
780
  }
668
781
  async function convertDocument(input, options) {
669
782
  const call = resolveDocumentCall(defaults, options);
@@ -673,31 +786,79 @@ function createDoclingClient(config) {
673
786
  pageImages: call.pageImages
674
787
  };
675
788
  const res = await post("/v1/convert/file", input, call.options, fields, call.signal);
676
- return res.ok ? withVersions(readDocument(res.data)) : res;
789
+ if (!res.ok) {
790
+ return res;
791
+ }
792
+ const converted = await withVersions(readDocument(res.data.body));
793
+ return converted.ok ? ok({ ...converted.data, settings: res.data.settings }) : converted;
677
794
  }
678
795
  async function submitMarkdown(input, options) {
679
796
  const call = resolveMarkdownCall(defaults, options);
680
- const fields = { format: "md", embedImages: call.output.images === "extract", pageImages: false };
681
- const id = await submit(input, call.options, fields, call.signal);
682
- return id.ok ? ok({ kind: "markdown", id: id.data, output: call.output }) : id;
797
+ return await startMarkdownJob(input, call);
683
798
  }
684
799
  async function submitDocument(input, options) {
685
800
  const call = resolveDocumentCall(defaults, options);
801
+ return await startDocumentJob(input, call);
802
+ }
803
+ async function runMarkdown(input, options) {
804
+ const call = resolveRunMarkdownCall(defaults, pollMs, options);
805
+ const job = await startMarkdownJob(input, call);
806
+ if (!job.ok) {
807
+ return job;
808
+ }
809
+ const done = await pollUntilDone(job.data, call);
810
+ return done.ok ? ok({ ...done.data, settings: job.data.settings }) : done;
811
+ }
812
+ async function runDocument(input, options) {
813
+ const call = resolveRunDocumentCall(defaults, pollMs, options);
814
+ const job = await startDocumentJob(input, call);
815
+ if (!job.ok) {
816
+ return job;
817
+ }
818
+ const done = await pollUntilDone(job.data, call);
819
+ return done.ok ? ok({ ...done.data, settings: job.data.settings }) : done;
820
+ }
821
+ async function waitForJob(job, options) {
822
+ const call = resolvePollOptions(pollMs, options);
823
+ const valid = validateJob(job);
824
+ return valid.ok ? pollUntilDone(valid.data, call) : valid;
825
+ }
826
+ async function startMarkdownJob(input, call) {
827
+ const fields = { format: "md", embedImages: call.output.images === "extract", pageImages: false };
828
+ const task = await submit(input, call.options, fields, call.signal);
829
+ return task.ok ? ok({ kind: "markdown", id: task.data.id, output: call.output, settings: task.data.settings }) : task;
830
+ }
831
+ async function startDocumentJob(input, call) {
686
832
  const fields = {
687
833
  format: "json",
688
834
  embedImages: call.images === "embedded",
689
835
  pageImages: call.pageImages
690
836
  };
691
- const id = await submit(input, call.options, fields, call.signal);
692
- return id.ok ? ok({ kind: "document", id: id.data }) : id;
837
+ const task = await submit(input, call.options, fields, call.signal);
838
+ return task.ok ? ok({ kind: "document", id: task.data.id, settings: task.data.settings }) : task;
839
+ }
840
+ async function pollUntilDone(job, { pollMs: waitMs, signal }) {
841
+ for (;; ) {
842
+ const state = await fetchJobState(job, signal);
843
+ if (!state.ok) {
844
+ return state;
845
+ }
846
+ if (state.data.status === "done") {
847
+ const { status: _done, ...result } = state.data;
848
+ return ok(result);
849
+ }
850
+ if (!await sleep(waitMs, signal)) {
851
+ return fail(ERR.ABORTED(`Aborted while waiting for job ${job.id}`));
852
+ }
853
+ }
693
854
  }
694
855
  async function check(job, options) {
695
856
  const { signal } = resolveCheckOptions(options);
696
857
  const valid = validateJob(job);
697
- if (!valid.ok) {
698
- return valid;
699
- }
700
- const { id } = valid.data;
858
+ return valid.ok ? fetchJobState(valid.data, signal) : valid;
859
+ }
860
+ async function fetchJobState(job, signal) {
861
+ const { id } = job;
701
862
  const res = await get(`/v1/status/poll/${id}`, signal);
702
863
  if (!res.ok) {
703
864
  const error = res.error.status === 404 ? ERR.NOT_FOUND(`Unknown job id: ${id} (${res.error.message})`) : res.error;
@@ -718,8 +879,7 @@ function createDoclingClient(config) {
718
879
  const error = result.error.status === 404 ? ERR.NOT_FOUND(`Result already fetched or expired: ${id}; resubmit the PDF (${result.error.message})`) : result.error;
719
880
  return failWithVersions(error);
720
881
  }
721
- const checked = valid.data;
722
- const output = checked.kind === "markdown" ? readMarkdown(result.data, checked.output) : readDocument(result.data);
882
+ const output = job.kind === "markdown" ? readMarkdown(result.data, job.output) : readDocument(result.data);
723
883
  const done = await withVersions(output);
724
884
  return done.ok ? ok({ status: "done", ...done.data }) : done;
725
885
  }
@@ -733,12 +893,21 @@ function createDoclingClient(config) {
733
893
  return failWithVersions(ERR.INVALID_RESPONSE(`Unexpected task status: ${String(task.task_status)}`));
734
894
  }
735
895
  }
896
+ async function capabilities(options) {
897
+ const { signal } = resolveCheckOptions(options);
898
+ const res = await get("/v1/capabilities", signal);
899
+ if (!res.ok) {
900
+ return failWithVersions(res.error);
901
+ }
902
+ const read = readCapabilities(res.data);
903
+ return read.ok ? read : failWithVersions(read.error);
904
+ }
736
905
  async function submit(input, options, fields, signal) {
737
906
  const res = await post("/v1/convert/file/async", input, options, fields, signal);
738
907
  if (!res.ok) {
739
908
  return res;
740
909
  }
741
- const id = res.data?.task_id;
910
+ const id = res.data.body?.task_id;
742
911
  if (readText(id) === undefined) {
743
912
  return failWithVersions(ERR.INVALID_RESPONSE("Response has no task_id"));
744
913
  }
@@ -746,16 +915,17 @@ function createDoclingClient(config) {
746
915
  const shown = JSON.stringify(id).slice(0, MAX_SHOWN_ID_LENGTH);
747
916
  return failWithVersions(ERR.INVALID_RESPONSE(`Response has an unusable task_id: ${shown}`));
748
917
  }
749
- return ok(id);
918
+ return ok({ id, settings: res.data.settings });
750
919
  }
751
920
  async function post(route, input, options, fields, signal) {
752
921
  const format = readInputFormat(input);
753
922
  if (!format.ok) {
754
923
  return format;
755
924
  }
925
+ const settings = buildSettings(format.data, options, fields);
756
926
  let body;
757
927
  try {
758
- body = buildFormData(input, format.data, options, fields);
928
+ body = buildFormData(input, format.data, settings);
759
929
  } catch (error) {
760
930
  return fail(ERR.INVALID_INPUT(`Input could not be prepared for upload: ${errorMessage(error)}`));
761
931
  }
@@ -766,7 +936,7 @@ function createDoclingClient(config) {
766
936
  body,
767
937
  ...limited === undefined ? {} : { signal: limited }
768
938
  });
769
- return res.ok ? res : failWithVersions(res.error);
939
+ return res.ok ? ok({ body: res.data, settings }) : failWithVersions(res.error);
770
940
  }
771
941
  function get(route, signal, limit = true) {
772
942
  const limited = limit ? withTimeout(signal, timeoutMs) : signal;
@@ -806,6 +976,22 @@ function createDoclingClient(config) {
806
976
  return versions.length === 0 ? null : Object.fromEntries(versions);
807
977
  }
808
978
  }
979
+ function sleep(ms, signal) {
980
+ if (signal?.aborted) {
981
+ return Promise.resolve(false);
982
+ }
983
+ return new Promise((resolve) => {
984
+ const timer = setTimeout(() => {
985
+ signal?.removeEventListener("abort", onAbort);
986
+ resolve(true);
987
+ }, ms);
988
+ function onAbort() {
989
+ clearTimeout(timer);
990
+ resolve(false);
991
+ }
992
+ signal?.addEventListener("abort", onAbort, { once: true });
993
+ });
994
+ }
809
995
  function withTimeout(signal, timeoutMs) {
810
996
  if (timeoutMs === undefined) {
811
997
  return signal;
@@ -822,43 +1008,51 @@ function readInputFormat(input) {
822
1008
  const offset = format.fromFormat === "pdf" ? findTruncatedXref(bytes) : undefined;
823
1009
  return offset === undefined ? ok(format) : fail(ERR.INVALID_INPUT(`PDF is truncated: cross-reference offset ${offset} lies past the end of the file (${bytes.length} bytes)`));
824
1010
  }
825
- function buildFormData(input, { fromFormat, mimeType, fileName }, options, { format, embedImages, pageImages }) {
1011
+ function buildSettings({ fromFormat }, options, { format, embedImages, pageImages }) {
1012
+ const isImage = fromFormat === "image";
1013
+ const isMarkdown = format === "md";
1014
+ return {
1015
+ fromFormats: fromFormat,
1016
+ toFormats: format,
1017
+ imageExportMode: embedImages || pageImages ? "embedded" : "placeholder",
1018
+ includeImages: embedImages,
1019
+ includePageImages: pageImages,
1020
+ imagesScale: PAGE_IMAGE_SCALE,
1021
+ mdCompactTables: isMarkdown ? true : null,
1022
+ mdPageBreakPlaceholder: isMarkdown ? "" : null,
1023
+ doOcr: isImage || options.ocr || options.forceOcr,
1024
+ forceOcr: !isImage && options.forceOcr,
1025
+ ocrPreset: options.ocrEngine,
1026
+ ocrLang: [...options.ocrLang ?? []],
1027
+ pdfBackend: options.pdfBackend,
1028
+ pipeline: options.pipeline,
1029
+ vlmPipelinePreset: options.pipeline === "vlm" ? VLM_PIPELINE_PRESET : null,
1030
+ doTableStructure: true,
1031
+ tableMode: "accurate",
1032
+ tableStructurePreset: TABLE_STRUCTURE_PRESET,
1033
+ tableCellMatching: true,
1034
+ doPdfHeadingHierarchy: options.headingHierarchy,
1035
+ doFormulaEnrichment: options.formulaEnrichment,
1036
+ doCodeEnrichment: options.codeEnrichment,
1037
+ codeFormulaPreset: options.formulaEnrichment || options.codeEnrichment ? CODE_FORMULA_PRESET : null,
1038
+ doChartExtraction: options.chartExtraction,
1039
+ chartExtractionPreset: options.chartExtraction ? CHART_EXTRACTION_PRESET : null,
1040
+ doPictureClassification: false,
1041
+ doPictureDescription: false,
1042
+ pageRange: options.pageRange === undefined ? null : [options.pageRange[0], options.pageRange[1]],
1043
+ documentTimeout: options.documentTimeout ?? null,
1044
+ abortOnError: false
1045
+ };
1046
+ }
1047
+ function buildFormData(input, { mimeType, fileName }, settings) {
826
1048
  const form = new FormData;
827
1049
  const bytes = input.buffer instanceof ArrayBuffer ? input : new Uint8Array(input);
828
1050
  form.append("files", new Blob([bytes], { type: mimeType }), fileName);
829
- form.append("from_formats", fromFormat);
830
- for (const [name, value] of FIXED_FORM_FIELDS) {
831
- form.append(name, value);
832
- }
833
- form.append("to_formats", format);
834
- if (format === "md") {
835
- form.append("md_compact_tables", "true");
836
- }
837
- form.append("include_images", String(embedImages));
838
- form.append("include_page_images", String(pageImages));
839
- form.append("image_export_mode", embedImages || pageImages ? "embedded" : "placeholder");
840
- form.append("images_scale", String(PAGE_IMAGE_SCALE));
841
- form.append("do_pdf_heading_hierarchy", String(options.headingHierarchy));
842
- form.append("do_formula_enrichment", String(options.formulaEnrichment));
843
- form.append("do_code_enrichment", String(options.codeEnrichment));
844
- if (options.formulaEnrichment || options.codeEnrichment) {
845
- form.append("code_formula_preset", "codeformulav2");
846
- }
847
- form.append("do_chart_extraction", String(options.chartExtraction));
848
- form.append("pipeline", options.pipeline);
849
- form.append("pdf_backend", options.pdfBackend);
850
- const isImage = fromFormat === "image";
851
- form.append("do_ocr", String(isImage || options.ocr));
852
- form.append("force_ocr", String(!isImage && options.forceOcr));
853
- for (const lang of options.ocrLang ?? []) {
854
- form.append("ocr_lang", lang);
855
- }
856
- if (options.pageRange !== undefined) {
857
- form.append("page_range", String(options.pageRange[0]));
858
- form.append("page_range", String(options.pageRange[1]));
859
- }
860
- if (options.documentTimeout !== undefined) {
861
- form.append("document_timeout", String(options.documentTimeout));
1051
+ for (const [key, value] of Object.entries(settings)) {
1052
+ const name = key.replace(MATCH_UPPER_CASE, (letter) => `_${letter.toLowerCase()}`);
1053
+ for (const item of value === null ? [] : Array.isArray(value) ? value : [value]) {
1054
+ form.append(name, String(item));
1055
+ }
862
1056
  }
863
1057
  return form;
864
1058
  }
@@ -870,5 +1064,5 @@ export {
870
1064
  toPageImageBox
871
1065
  };
872
1066
 
873
- //# debugId=B34739AC554F7F9C64756E2164756E21
1067
+ //# debugId=1022B5E8A749497A64756E2164756E21
874
1068
  //# sourceMappingURL=index.js.map