@piecemaker-legal/piecemaker 2.0.14 → 2.0.16
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/assets/{FindReplaceDialog-KU5TEIBJ-DwLQyvTV.js → FindReplaceDialog-KU5TEIBJ-BS2IquHh.js} +1 -1
- package/dist/assets/{FootnotePropertiesDialog-W3YHM4BV-B-Lq3Wxh.js → FootnotePropertiesDialog-W3YHM4BV-BaIL33wg.js} +1 -1
- package/dist/assets/{HyperlinkDialog-ZYH7ZHRF-lLf2tPu5.js → HyperlinkDialog-ZYH7ZHRF-BjI9sWR4.js} +4 -4
- package/dist/assets/{ImagePositionDialog-HEWYR6Q3-DnzhuAuM.js → ImagePositionDialog-HEWYR6Q3-C6BO_ttK.js} +1 -1
- package/dist/assets/{ImagePropertiesDialog-RAB47C6M-DGut41Ic.js → ImagePropertiesDialog-RAB47C6M-CGjpLtTI.js} +1 -1
- package/dist/assets/{PageSetupDialog-AIGIXO3E-DoTOiKsJ.js → PageSetupDialog-AIGIXO3E-C5OGjPCn.js} +1 -1
- package/dist/assets/{SplitCellDialog-IFBKYCD6-DNV_hFKw.js → SplitCellDialog-IFBKYCD6-DTUKFpZo.js} +1 -1
- package/dist/assets/{TablePropertiesDialog-TMLKGOOW-Ba57AtqO.js → TablePropertiesDialog-TMLKGOOW-2c-bDH8r.js} +1 -1
- package/dist/assets/{WatermarkDialog-KRL7WMIS-DpO_30sj.js → WatermarkDialog-KRL7WMIS-BeAZ0XuJ.js} +1 -1
- package/dist/assets/{abnfDiagram-VCTEODGH-D0mpNf2t.js → abnfDiagram-VCTEODGH-Cafje0km.js} +1 -1
- package/dist/assets/{arc-Bv8e2GDC.js → arc-B1nvw-hX.js} +1 -1
- package/dist/assets/{architectureDiagram-5GKGNRK7-MQBi2I4-.js → architectureDiagram-5GKGNRK7-DenAnPvr.js} +1 -1
- package/dist/assets/{blockDiagram-I7D4REHJ-DstJr0pC.js → blockDiagram-I7D4REHJ-C9TX8a8H.js} +1 -1
- package/dist/assets/{c4Diagram-7LVT6UL2-DotOtTxX.js → c4Diagram-7LVT6UL2-Dm7WYR8n.js} +1 -1
- package/dist/assets/channel-DTNnyhVz.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-B9gc2v9X.js → chunk-2Q5K7J3B-BzOJKJZR.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-CqpHPwaS.js → chunk-5VM5RSS4-BRUszDMV.js} +1 -1
- package/dist/assets/{chunk-F27PBJKO-CWQVjEgx.js → chunk-F27PBJKO-DXmbip6-.js} +1 -1
- package/dist/assets/{chunk-IMKFNOWR-BQcQ4Jwa.js → chunk-IMKFNOWR-CLo5fiT7.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-CekOmdH0.js → chunk-JWPE2WC7-BXctXDNM.js} +1 -1
- package/dist/assets/{chunk-POPQ4Y6H-pZoPNHJO.js → chunk-POPQ4Y6H-TKaN1BJU.js} +1 -1
- package/dist/assets/{chunk-SVP7TREG-CVT-NRlT.js → chunk-SVP7TREG-2Y_i2api.js} +1 -1
- package/dist/assets/{chunk-TICWLB2K-Z3lcU-HD.js → chunk-TICWLB2K-D67Oeu-d.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-gMwZV5S8.js → chunk-XXDRQBXY-C8btsXvp.js} +1 -1
- package/dist/assets/classDiagram-ZZMXUADV-DEpZ2Aie.js +1 -0
- package/dist/assets/classDiagram-v2-VYDZK3BY-DEpZ2Aie.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-BOB0fNzU.js → cose-bilkent-JH36ORCC-CDjmznJD.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-LjWmlV2d.js → cynefin-OW5HDTMX-Cz2Zila7.js} +1 -1
- package/dist/assets/{cynefinDiagram-5FMLGOSQ-BeHh6fRm.js → cynefinDiagram-5FMLGOSQ-CCDUntcs.js} +1 -1
- package/dist/assets/{dagre-GXQ25YYZ-PDH35d23.js → dagre-GXQ25YYZ-uf93EB4q.js} +1 -1
- package/dist/assets/{diagram-S7CK7UJ4-Dp43fqwJ.js → diagram-S7CK7UJ4-CWD5w1S0.js} +1 -1
- package/dist/assets/{diagram-UQ7AKVKN-C1uaZ7Ig.js → diagram-UQ7AKVKN-BupQSG7M.js} +1 -1
- package/dist/assets/{diagram-VSXAHHWV-b8UrSsgG.js → diagram-VSXAHHWV-CBQKW_yS.js} +1 -1
- package/dist/assets/{diagram-VX7I27RA-C47mA-f5.js → diagram-VX7I27RA-eWkYnL2g.js} +1 -1
- package/dist/assets/{diagram-Z3DM3KII-Ou-0Eovi.js → diagram-Z3DM3KII-eTIwrxxP.js} +1 -1
- package/dist/assets/{ebnfDiagram-PWID7BFC-aDi11OMO.js → ebnfDiagram-PWID7BFC-DJZxQQmA.js} +1 -1
- package/dist/assets/{erDiagram-RLTQ6QDP-BlytbfKL.js → erDiagram-RLTQ6QDP-BT8C_kdQ.js} +1 -1
- package/dist/assets/{flowDiagram-HODETNUW-DwhhloRz.js → flowDiagram-HODETNUW-CraoY0mi.js} +1 -1
- package/dist/assets/{ganttDiagram-EL5Y4UJY-D_F7V6ja.js → ganttDiagram-EL5Y4UJY-ZaXfhnzT.js} +1 -1
- package/dist/assets/{gitGraphDiagram-WWUBYQGX-CzbrEY2k.js → gitGraphDiagram-WWUBYQGX-BSuHCYPJ.js} +1 -1
- package/dist/assets/index-C1854KB7.css +1 -0
- package/dist/assets/{index-CIz0Nvp7.js → index-DIIIoNKx.js} +140 -140
- package/dist/assets/{infoDiagram-27XIBGKW-C94uRMDo.js → infoDiagram-27XIBGKW-D6JUTMr9.js} +1 -1
- package/dist/assets/{ishikawaDiagram-5VMMS53U-ChnIieKx.js → ishikawaDiagram-5VMMS53U-2SNX3Hct.js} +1 -1
- package/dist/assets/{journeyDiagram-3NMN7TZE-oA_qMCz8.js → journeyDiagram-3NMN7TZE-BfLxikQz.js} +1 -1
- package/dist/assets/{kanban-definition-UXKFOSKX-Fz6-FHOs.js → kanban-definition-UXKFOSKX-D-0rPWC6.js} +1 -1
- package/dist/assets/{layout-CJCUH450.js → layout-UbVHo6lA.js} +1 -1
- package/dist/assets/{linear-C9nZWhdo.js → linear-Cznk7QbI.js} +1 -1
- package/dist/assets/{mermaid.core-BeRDJU42.js → mermaid.core-BoSxdsJv.js} +6 -6
- package/dist/assets/{mindmap-definition-YA3MSWOX-CaJbUiMZ.js → mindmap-definition-YA3MSWOX-CGRFQBXc.js} +1 -1
- package/dist/assets/{pegDiagram-XKGWAZYB-DJjbKz1y.js → pegDiagram-XKGWAZYB-3iXA_L6R.js} +1 -1
- package/dist/assets/{pieDiagram-E7YTZNPT-CW-BLG1L.js → pieDiagram-E7YTZNPT-CarSnOYt.js} +1 -1
- package/dist/assets/{quadrantDiagram-AXDQQJYC-CiSMX_OO.js → quadrantDiagram-AXDQQJYC-BQ-GK9LK.js} +1 -1
- package/dist/assets/{railroadDiagram-O6MQD6OU-CTIuvunz.js → railroadDiagram-O6MQD6OU-BdFRm0Mb.js} +1 -1
- package/dist/assets/{requirementDiagram-BXWQKSXE-B-HUu134.js → requirementDiagram-BXWQKSXE-8MgrmWC2.js} +1 -1
- package/dist/assets/{sankeyDiagram-P5KCCOFB-B1p2E7hR.js → sankeyDiagram-P5KCCOFB-C9sw-tkq.js} +1 -1
- package/dist/assets/{sequenceDiagram-WJ2MYXX4-CZ3c10t3.js → sequenceDiagram-WJ2MYXX4-D0PC5AQ3.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-BgmoRqos.js → sizeCapture-INFHLROL-DbL8fCKK.js} +1 -1
- package/dist/assets/{stateDiagram-D77RDMKH-DPqnJMDr.js → stateDiagram-D77RDMKH-D1hcL0yu.js} +1 -1
- package/dist/assets/{stateDiagram-v2-MP3YSRHH-BJOyC96W.js → stateDiagram-v2-MP3YSRHH-Zer7OO4Q.js} +1 -1
- package/dist/assets/{swimlanes-42K2YHIH-77lt2sGV.js → swimlanes-42K2YHIH-CaFxs4HW.js} +1 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-D6dVAhUV.js +8 -0
- package/dist/assets/{timeline-definition-24CTP7MA-CxYTGgqp.js → timeline-definition-24CTP7MA-CicB5MP7.js} +1 -1
- package/dist/assets/{vennDiagram-4TSXK5OY-CEJXvAap.js → vennDiagram-4TSXK5OY-DC1WE4bR.js} +1 -1
- package/dist/assets/{wardleyDiagram-VM6X3IG4-DIQwX6bQ.js → wardleyDiagram-VM6X3IG4-C0XiXv2M.js} +1 -1
- package/dist/assets/{xychartDiagram-S5SC5T6Z-n9jd-Xax.js → xychartDiagram-S5SC5T6Z-CSZ90TfD.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/dist-server/server/piecemaker/desktop-update/index.js +3 -2
- package/dist-server/server/piecemaker/desktop-update/index.js.map +1 -1
- package/dist-server/server/piecemaker/harness/citation-instructions.js +2 -2
- package/dist-server/server/piecemaker/harness/citation-store.js +1 -1
- package/dist-server/server/piecemaker/harness/citation-store.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/local-routes.js +1 -1
- package/dist-server/server/piecemaker/knowledge/local-routes.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/pipeline.js +12 -1
- package/dist-server/server/piecemaker/knowledge/pipeline.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/routes.js +1 -1
- package/dist-server/server/piecemaker/knowledge/routes.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/scan-jobs.js +13 -0
- package/dist-server/server/piecemaker/knowledge/scan-jobs.js.map +1 -1
- package/dist-server/server/piecemaker/knowledge/service.js +3 -2
- package/dist-server/server/piecemaker/knowledge/service.js.map +1 -1
- package/package.json +1 -1
- package/server/piecemaker/desktop-update/index.ts +3 -2
- package/server/piecemaker/harness/citation-instructions.ts +2 -2
- package/server/piecemaker/harness/citation-store.ts +1 -1
- package/server/piecemaker/knowledge/local-routes.ts +1 -1
- package/server/piecemaker/knowledge/pipeline.ts +20 -2
- package/server/piecemaker/knowledge/routes.ts +1 -1
- package/server/piecemaker/knowledge/scan-jobs.ts +19 -1
- package/server/piecemaker/knowledge/service.ts +3 -2
- package/server/piecemaker/vendor/installer/steps/04-conversion-md.mjs +46 -9
- package/server/piecemaker/vendor/installer/steps/07-legifrance.mjs +3 -3
- package/server/piecemaker/vendor/piecemaker-plugin/README.md +8 -17
- package/server/piecemaker/vendor/piecemaker-plugin/skills/conversion-md/SKILL.md +3 -1
- package/server/piecemaker/vendor/piecemaker-plugin/skills/recherche-juridique/SKILL.md +19 -34
- package/server/piecemaker/vendor/websocket-server/admin-routes.cjs +6 -1
- package/server/piecemaker/vendor/websocket-server/originals-pipeline.cjs +10 -2
- package/server/piecemaker/vendor/websocket-server/scripts/convert_and_scan_pipeline.py +67 -13
- package/server/piecemaker/vendor/websocket-server/scripts/mineru_improved_1.py +17 -5
- package/server/piecemaker/vendor/websocket-server/scripts/smart_converter.py +20 -3
- package/dist/assets/channel-UVnVNzmE.js +0 -1
- package/dist/assets/classDiagram-ZZMXUADV-B5s2HyRp.js +0 -1
- package/dist/assets/classDiagram-v2-VYDZK3BY-B5s2HyRp.js +0 -1
- package/dist/assets/index-C5slQNvE.css +0 -1
- package/dist/assets/swimlanesDiagram-VR7AAH4N-D2sHCxQu.js +0 -8
|
@@ -50,7 +50,10 @@ from contextlib import closing
|
|
|
50
50
|
from pathlib import Path
|
|
51
51
|
from typing import List, Optional, Tuple, Dict, Set
|
|
52
52
|
|
|
53
|
+
from smart_converter import mineru_available, needs_ocr
|
|
53
54
|
|
|
55
|
+
|
|
56
|
+
EXIT_OCR_REQUIRED = 3
|
|
54
57
|
GLINER_CHUNK_SIZE = 384
|
|
55
58
|
GLINER_CHUNK_OVERLAP = 64
|
|
56
59
|
|
|
@@ -1575,7 +1578,9 @@ def source_is_anonymized(state: Dict, source_file: str, case_root: str) -> bool:
|
|
|
1575
1578
|
return source_is_processed(state, source_file, case_root, "scanned")
|
|
1576
1579
|
|
|
1577
1580
|
|
|
1578
|
-
def update_processing_state(
|
|
1581
|
+
def update_processing_state(
|
|
1582
|
+
state_path: Path, case_root: str, source_files: List[str], phase: str, ocr_missing: bool = False
|
|
1583
|
+
) -> None:
|
|
1579
1584
|
"""Atomically add successful conversions/scans without paths or entities."""
|
|
1580
1585
|
if not source_files:
|
|
1581
1586
|
return
|
|
@@ -1587,9 +1592,12 @@ def update_processing_state(state_path: Path, case_root: str, source_files: List
|
|
|
1587
1592
|
continue
|
|
1588
1593
|
fingerprint = {**source_fingerprint(source_file), "updatedAt": updated_at}
|
|
1589
1594
|
entry = state["files"].get(key, {})
|
|
1595
|
+
previous_ocr = entry.get("converted", {}).get("ocr")
|
|
1590
1596
|
entry[phase] = fingerprint
|
|
1597
|
+
if phase == "converted" and ocr_missing:
|
|
1598
|
+
entry["converted"] = {**fingerprint, "ocr": "missing"}
|
|
1591
1599
|
if phase == "scanned":
|
|
1592
|
-
entry["converted"] = fingerprint
|
|
1600
|
+
entry["converted"] = {**fingerprint, **({"ocr": previous_ocr} if previous_ocr else {})}
|
|
1593
1601
|
state["files"][key] = entry
|
|
1594
1602
|
state_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1595
1603
|
temporary = state_path.with_name(f"{state_path.name}.piecemaker-{os.getpid()}.tmp")
|
|
@@ -1800,6 +1808,15 @@ def run_pipeline(resources: PipelineResources):
|
|
|
1800
1808
|
help="MinerU processing mode (only used if engine=mineru)",
|
|
1801
1809
|
)
|
|
1802
1810
|
parser.add_argument("--lang", help="OCR language code (only used if engine=mineru)")
|
|
1811
|
+
parser.add_argument(
|
|
1812
|
+
"--ocr-missing",
|
|
1813
|
+
choices=["ask", "continue"],
|
|
1814
|
+
default="continue",
|
|
1815
|
+
help=(
|
|
1816
|
+
"When scanned documents need OCR but MinerU is not installed: 'ask' stops before "
|
|
1817
|
+
"any work and prints OCR_REQUIRED:<json>; 'continue' converts them from their text layer only"
|
|
1818
|
+
),
|
|
1819
|
+
)
|
|
1803
1820
|
parser.add_argument(
|
|
1804
1821
|
"--document-id",
|
|
1805
1822
|
default="default",
|
|
@@ -1871,7 +1888,36 @@ def run_pipeline(resources: PipelineResources):
|
|
|
1871
1888
|
def markdown_path(input_file: str) -> Path:
|
|
1872
1889
|
return Path(args.output) / f"{Path(input_file).stem}.md"
|
|
1873
1890
|
|
|
1874
|
-
|
|
1891
|
+
mineru_ready = args.engine == "mineru" or (args.engine == "auto" and mineru_available())
|
|
1892
|
+
|
|
1893
|
+
def converted_without_ocr(input_file: str) -> bool:
|
|
1894
|
+
entry = source_state_entry(anonymization_state, input_file, state_case_root) or {}
|
|
1895
|
+
return entry.get("converted", {}).get("ocr") == "missing"
|
|
1896
|
+
|
|
1897
|
+
def markdown_is_reusable(input_file: str) -> bool:
|
|
1898
|
+
if not markdown_path(input_file).exists():
|
|
1899
|
+
return False
|
|
1900
|
+
if mineru_ready and converted_without_ocr(input_file):
|
|
1901
|
+
return False
|
|
1902
|
+
state_entry = source_state_entry(anonymization_state, input_file, state_case_root)
|
|
1903
|
+
return state_entry is None or source_is_converted(anonymization_state, input_file, state_case_root)
|
|
1904
|
+
|
|
1905
|
+
def case_relative_name(input_file: str) -> str:
|
|
1906
|
+
try:
|
|
1907
|
+
return Path(input_file).resolve().relative_to(Path(state_case_root).resolve()).as_posix()
|
|
1908
|
+
except ValueError:
|
|
1909
|
+
return Path(input_file).name
|
|
1910
|
+
|
|
1911
|
+
conversions = [f for f in input_files if not (args.skip_existing and markdown_is_reusable(f))]
|
|
1912
|
+
ocr_fallback = set() if mineru_ready else {f for f in conversions if needs_ocr(f)}
|
|
1913
|
+
reconverted_with_ocr = {f for f in conversions if mineru_ready and converted_without_ocr(f)}
|
|
1914
|
+
|
|
1915
|
+
if ocr_fallback and args.engine == "auto" and args.ocr_missing == "ask":
|
|
1916
|
+
files = sorted(case_relative_name(f) for f in ocr_fallback)
|
|
1917
|
+
print(f"OCR_REQUIRED:{json.dumps({'files': files}, ensure_ascii=False)}", flush=True)
|
|
1918
|
+
return EXIT_OCR_REQUIRED
|
|
1919
|
+
|
|
1920
|
+
scan_needed = bool(reconverted_with_ocr) or any(
|
|
1875
1921
|
not (args.skip_existing and source_is_anonymized(anonymization_state, f, state_case_root))
|
|
1876
1922
|
for f in input_files
|
|
1877
1923
|
)
|
|
@@ -1899,31 +1945,38 @@ def run_pipeline(resources: PipelineResources):
|
|
|
1899
1945
|
print_progress("CONVERT", i, len(input_files))
|
|
1900
1946
|
existing_md = markdown_path(input_file)
|
|
1901
1947
|
|
|
1902
|
-
|
|
1903
|
-
reusable_markdown = existing_md.exists() and (
|
|
1904
|
-
state_entry is None
|
|
1905
|
-
or source_is_converted(anonymization_state, input_file, state_case_root)
|
|
1906
|
-
)
|
|
1907
|
-
if args.skip_existing and reusable_markdown:
|
|
1948
|
+
if input_file not in conversions:
|
|
1908
1949
|
print(f"📄 [{i}/{len(input_files)}] Already converted, reusing: {existing_md.name}")
|
|
1909
1950
|
md_files.append(str(existing_md))
|
|
1910
1951
|
md_sources[str(existing_md)] = input_file
|
|
1911
|
-
update_processing_state(
|
|
1952
|
+
update_processing_state(
|
|
1953
|
+
state_target, state_case_root, [input_file], "converted",
|
|
1954
|
+
ocr_missing=converted_without_ocr(input_file),
|
|
1955
|
+
)
|
|
1912
1956
|
convert_success_count += 1
|
|
1913
1957
|
print()
|
|
1914
1958
|
continue
|
|
1915
1959
|
|
|
1916
1960
|
print(f"📄 [{i}/{len(input_files)}] Converting: {Path(input_file).name}")
|
|
1961
|
+
without_ocr = input_file in ocr_fallback
|
|
1962
|
+
if without_ocr:
|
|
1963
|
+
print(" ⚠️ Scanned document converted without OCR (MinerU not installed): text layer only")
|
|
1917
1964
|
|
|
1918
1965
|
success, md_path = convert_file(
|
|
1919
|
-
input_file,
|
|
1966
|
+
input_file,
|
|
1967
|
+
args.output,
|
|
1968
|
+
engine="markitdown" if without_ocr else args.engine,
|
|
1969
|
+
mode=args.mode,
|
|
1970
|
+
lang=args.lang,
|
|
1920
1971
|
)
|
|
1921
1972
|
|
|
1922
1973
|
if success and md_path:
|
|
1923
1974
|
print(f" ✅ Markdown generated: {Path(md_path).name}")
|
|
1924
1975
|
md_files.append(md_path)
|
|
1925
1976
|
md_sources[md_path] = input_file
|
|
1926
|
-
update_processing_state(
|
|
1977
|
+
update_processing_state(
|
|
1978
|
+
state_target, state_case_root, [input_file], "converted", ocr_missing=without_ocr
|
|
1979
|
+
)
|
|
1927
1980
|
convert_success_count += 1
|
|
1928
1981
|
else:
|
|
1929
1982
|
print(f" ❌ Conversion failed, skipping...")
|
|
@@ -1948,7 +2001,8 @@ def run_pipeline(resources: PipelineResources):
|
|
|
1948
2001
|
pending_scans = [
|
|
1949
2002
|
md_file
|
|
1950
2003
|
for md_file in md_files
|
|
1951
|
-
if
|
|
2004
|
+
if md_sources[md_file] in reconverted_with_ocr
|
|
2005
|
+
or not (
|
|
1952
2006
|
args.skip_existing
|
|
1953
2007
|
and source_is_anonymized(anonymization_state, md_sources[md_file], state_case_root)
|
|
1954
2008
|
)
|
|
@@ -5,19 +5,31 @@ Supports both pipeline (direct PDF) and VLM/hybrid (image-based) modes
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import argparse
|
|
8
|
+
import importlib.util
|
|
8
9
|
import json
|
|
9
10
|
import os
|
|
11
|
+
import shutil
|
|
10
12
|
import subprocess
|
|
11
13
|
import sys
|
|
14
|
+
import sysconfig
|
|
12
15
|
from pathlib import Path
|
|
13
16
|
|
|
14
17
|
|
|
15
|
-
def
|
|
18
|
+
def find_mineru():
|
|
16
19
|
name = 'mineru.exe' if os.name == 'nt' else 'mineru'
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
for directory in (sysconfig.get_path('scripts'), Path(sys.executable).parent, Path(sys.executable).resolve().parent):
|
|
21
|
+
candidate = Path(directory) / name
|
|
22
|
+
if candidate.is_file():
|
|
23
|
+
return str(candidate)
|
|
24
|
+
return shutil.which(name)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def mineru_executable():
|
|
28
|
+
return find_mineru() or 'mineru'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def mineru_available():
|
|
32
|
+
return importlib.util.find_spec('mineru') is not None and find_mineru() is not None
|
|
21
33
|
|
|
22
34
|
def parse_with_pipeline(pdf_path, output_dir, lang=None):
|
|
23
35
|
"""
|
|
@@ -24,6 +24,10 @@ import argparse
|
|
|
24
24
|
import subprocess
|
|
25
25
|
from pathlib import Path
|
|
26
26
|
|
|
27
|
+
from mineru_improved_1 import mineru_available
|
|
28
|
+
|
|
29
|
+
IMAGE_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.tiff', '.tif', '.bmp', '.gif'}
|
|
30
|
+
|
|
27
31
|
# ---------------------------------------------------------------------------
|
|
28
32
|
# Markdown whitespace normalisation
|
|
29
33
|
# ---------------------------------------------------------------------------
|
|
@@ -188,6 +192,19 @@ def pdf_has_text_layer(pdf_path):
|
|
|
188
192
|
return False # Assume scanned if inspection fails
|
|
189
193
|
|
|
190
194
|
|
|
195
|
+
def needs_ocr(file_path):
|
|
196
|
+
ext = Path(file_path).suffix.lower()
|
|
197
|
+
if ext in IMAGE_EXTENSIONS:
|
|
198
|
+
return True
|
|
199
|
+
return ext == '.pdf' and not pdf_has_text_layer(file_path)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def ocr_engine(reason):
|
|
203
|
+
if HAS_MARKITDOWN and not mineru_available():
|
|
204
|
+
return 'markitdown', f'{reason}, but MinerU is not installed — text layer only'
|
|
205
|
+
return 'mineru', reason
|
|
206
|
+
|
|
207
|
+
|
|
191
208
|
def inspect_file(file_path):
|
|
192
209
|
"""Determine best conversion engine based on file inspection.
|
|
193
210
|
|
|
@@ -197,8 +214,8 @@ def inspect_file(file_path):
|
|
|
197
214
|
ext = Path(file_path).suffix.lower()
|
|
198
215
|
|
|
199
216
|
# Images always need OCR → MinerU
|
|
200
|
-
if ext in
|
|
201
|
-
return '
|
|
217
|
+
if ext in IMAGE_EXTENSIONS:
|
|
218
|
+
return ocr_engine('Image file requires OCR')
|
|
202
219
|
|
|
203
220
|
# Office docs have native text → markitdown
|
|
204
221
|
if ext in ['.docx', '.pptx', '.xlsx', '.xls', '.doc', '.ppt']:
|
|
@@ -214,7 +231,7 @@ def inspect_file(file_path):
|
|
|
214
231
|
if pdf_has_text_layer(file_path):
|
|
215
232
|
return 'markitdown', 'PDF has extractable text layer'
|
|
216
233
|
else:
|
|
217
|
-
return '
|
|
234
|
+
return ocr_engine('Scanned PDF requires OCR (no text layer)')
|
|
218
235
|
|
|
219
236
|
# HTML, TXT, etc. — try markitdown
|
|
220
237
|
if ext in ['.html', '.htm', '.txt', '.md', '.csv']:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{U as a,Q as n}from"./mermaid.core-BeRDJU42.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-TICWLB2K-Z3lcU-HD.js";import{_ as i}from"./mermaid.core-BeRDJU42.js";import"./chunk-5VM5RSS4-CqpHPwaS.js";import"./chunk-XXDRQBXY-gMwZV5S8.js";import"./chunk-POPQ4Y6H-pZoPNHJO.js";import"./chunk-F27PBJKO-CWQVjEgx.js";import"./index-CIz0Nvp7.js";import"./vendor-codemirror-CN-sJePf.js";import"./vendor-react-B22wqN3J.js";import"./vendor-xterm-BWUgpGtR.js";var c={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{c as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-TICWLB2K-Z3lcU-HD.js";import{_ as i}from"./mermaid.core-BeRDJU42.js";import"./chunk-5VM5RSS4-CqpHPwaS.js";import"./chunk-XXDRQBXY-gMwZV5S8.js";import"./chunk-POPQ4Y6H-pZoPNHJO.js";import"./chunk-F27PBJKO-CWQVjEgx.js";import"./index-CIz0Nvp7.js";import"./vendor-codemirror-CN-sJePf.js";import"./vendor-react-B22wqN3J.js";import"./vendor-xterm-BWUgpGtR.js";var c={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{c as diagram};
|