pdf-to-markdown-cli 0.4.0__tar.gz → 0.5.1__tar.gz
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.
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/LICENSE +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/MANIFEST.in +0 -0
- pdf_to_markdown_cli-0.5.1/PKG-INFO +119 -0
- pdf_to_markdown_cli-0.5.1/README.md +64 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/pyproject.toml +5 -2
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/__init__.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/__main__.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/api/__init__.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/api/client.py +16 -6
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/api/models.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/config/__init__.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/config/cli.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/config/settings.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/core/__init__.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/core/paths.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/core/processor.py +77 -74
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/core/result_handler.py +8 -3
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/main.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/storage/__init__.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/storage/cache.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/storage/models.py +2 -1
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/__init__.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/exceptions.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/file_utils.py +3 -2
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/logging.py +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/pdf_splitter.py +0 -0
- pdf_to_markdown_cli-0.5.1/src/pdf_to_markdown_cli.egg-info/PKG-INFO +119 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/pdf_to_markdown_cli.egg-info/SOURCES.txt +6 -1
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/pdf_to_markdown_cli.egg-info/dependency_links.txt +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/pdf_to_markdown_cli.egg-info/entry_points.txt +0 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/pdf_to_markdown_cli.egg-info/requires.txt +2 -0
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/pdf_to_markdown_cli.egg-info/top_level.txt +0 -0
- pdf_to_markdown_cli-0.5.1/tests/test_cli.py +37 -0
- pdf_to_markdown_cli-0.5.1/tests/test_cli_equations.py +113 -0
- pdf_to_markdown_cli-0.5.1/tests/test_paths.py +25 -0
- pdf_to_markdown_cli-0.5.1/tests/test_settings.py +65 -0
- pdf_to_markdown_cli-0.5.1/tests/test_utils.py +118 -0
- pdf_to_markdown_cli-0.4.0/PKG-INFO +0 -202
- pdf_to_markdown_cli-0.4.0/README.md +0 -148
- pdf_to_markdown_cli-0.4.0/src/pdf_to_markdown_cli.egg-info/PKG-INFO +0 -202
- {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/setup.cfg +0 -0
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pdf-to-markdown-cli
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Summary: CLI tool to convert PDF files (and other documents) to markdown using the Marker API.
|
|
5
|
+
Author: Nikita Sokolsky
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 SokolskyNikita
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/SokolskyNikita/pdf-to-markdown-cli
|
|
29
|
+
Project-URL: Bug Tracker, https://github.com/SokolskyNikita/pdf-to-markdown-cli/issues
|
|
30
|
+
Keywords: pdf,markdown,converter,cli,document,marker,md
|
|
31
|
+
Classifier: Development Status :: 4 - Beta
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Classifier: Topic :: Text Processing
|
|
41
|
+
Classifier: Topic :: Utilities
|
|
42
|
+
Requires-Python: >=3.10
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
License-File: LICENSE
|
|
45
|
+
Requires-Dist: backoff>=2.0
|
|
46
|
+
Requires-Dist: diskcache>=5.0
|
|
47
|
+
Requires-Dist: filetype>=1.0
|
|
48
|
+
Requires-Dist: pikepdf>=8.0
|
|
49
|
+
Requires-Dist: pydantic>=2.0
|
|
50
|
+
Requires-Dist: ratelimit>=2.0
|
|
51
|
+
Requires-Dist: requests>=2.0
|
|
52
|
+
Requires-Dist: tqdm>=4.0
|
|
53
|
+
Provides-Extra: test
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# PDF to Markdown CLI
|
|
57
|
+
|
|
58
|
+
Convert PDFs and other documents to Markdown using the [Marker API](https://www.datalab.to/marker).
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
- Convert PDFs, Word docs, PowerPoint, spreadsheets, EPUB, HTML, and images to Markdown/JSON/HTML
|
|
63
|
+
- Automatic chunking for large documents with parallel processing
|
|
64
|
+
- Progress tracking and local caching for interrupted runs
|
|
65
|
+
- Full OCR customization options
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
### From PyPI
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install pdf-to-markdown-cli
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### From source
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
git clone https://github.com/SokolskyNikita/pdf-to-markdown-cli.git
|
|
79
|
+
cd pdf-to-markdown-cli
|
|
80
|
+
pip install -e .
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Usage
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Get API key from https://www.datalab.to/marker
|
|
87
|
+
export MARKER_PDF_KEY=your_api_key_here
|
|
88
|
+
|
|
89
|
+
# Basic usage
|
|
90
|
+
pdf-to-md /path/to/file.pdf
|
|
91
|
+
|
|
92
|
+
# Common options
|
|
93
|
+
pdf-to-md /path/to/file.pdf --json # JSON output
|
|
94
|
+
pdf-to-md /path/to/file.pdf --noimg # Disable images
|
|
95
|
+
pdf-to-md /path/to/file.pdf --max # Enable all flags for maximum output quality
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## CLI Options
|
|
99
|
+
|
|
100
|
+
- `input`: Input file or directory path
|
|
101
|
+
- `--json`: Output in JSON format (default is markdown)
|
|
102
|
+
- `--langs`: Comma-separated OCR languages (default: "English")
|
|
103
|
+
- `--llm`: Use LLM for enhanced processing
|
|
104
|
+
- `--strip`: Redo OCR processing
|
|
105
|
+
- `--noimg`: Disable image extraction
|
|
106
|
+
- `--force`: Force OCR on all pages
|
|
107
|
+
- `--pages`: Add page delimiters
|
|
108
|
+
- `--max`: Enable all OCR enhancements (equivalent to --llm --strip --force)
|
|
109
|
+
- `-mp`, `--max-pages`: Maximum number of pages to process from the start of the file
|
|
110
|
+
- `--no-chunk`: Disable PDF chunking
|
|
111
|
+
- `-cs`, `--chunk-size`: Set PDF chunk size in pages (default: 25)
|
|
112
|
+
- `-o`, `--output-dir`: Absolute path to the output directory
|
|
113
|
+
- `-v`, `--verbose`: Enable verbose (DEBUG level) logging
|
|
114
|
+
- `--version`: Show the installed version and exit
|
|
115
|
+
|
|
116
|
+
## Requirements
|
|
117
|
+
|
|
118
|
+
- Python ≥3.10
|
|
119
|
+
- API key from [datalab.to](https://www.datalab.to/marker)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# PDF to Markdown CLI
|
|
2
|
+
|
|
3
|
+
Convert PDFs and other documents to Markdown using the [Marker API](https://www.datalab.to/marker).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Convert PDFs, Word docs, PowerPoint, spreadsheets, EPUB, HTML, and images to Markdown/JSON/HTML
|
|
8
|
+
- Automatic chunking for large documents with parallel processing
|
|
9
|
+
- Progress tracking and local caching for interrupted runs
|
|
10
|
+
- Full OCR customization options
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
### From PyPI
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install pdf-to-markdown-cli
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### From source
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/SokolskyNikita/pdf-to-markdown-cli.git
|
|
24
|
+
cd pdf-to-markdown-cli
|
|
25
|
+
pip install -e .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Get API key from https://www.datalab.to/marker
|
|
32
|
+
export MARKER_PDF_KEY=your_api_key_here
|
|
33
|
+
|
|
34
|
+
# Basic usage
|
|
35
|
+
pdf-to-md /path/to/file.pdf
|
|
36
|
+
|
|
37
|
+
# Common options
|
|
38
|
+
pdf-to-md /path/to/file.pdf --json # JSON output
|
|
39
|
+
pdf-to-md /path/to/file.pdf --noimg # Disable images
|
|
40
|
+
pdf-to-md /path/to/file.pdf --max # Enable all flags for maximum output quality
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## CLI Options
|
|
44
|
+
|
|
45
|
+
- `input`: Input file or directory path
|
|
46
|
+
- `--json`: Output in JSON format (default is markdown)
|
|
47
|
+
- `--langs`: Comma-separated OCR languages (default: "English")
|
|
48
|
+
- `--llm`: Use LLM for enhanced processing
|
|
49
|
+
- `--strip`: Redo OCR processing
|
|
50
|
+
- `--noimg`: Disable image extraction
|
|
51
|
+
- `--force`: Force OCR on all pages
|
|
52
|
+
- `--pages`: Add page delimiters
|
|
53
|
+
- `--max`: Enable all OCR enhancements (equivalent to --llm --strip --force)
|
|
54
|
+
- `-mp`, `--max-pages`: Maximum number of pages to process from the start of the file
|
|
55
|
+
- `--no-chunk`: Disable PDF chunking
|
|
56
|
+
- `-cs`, `--chunk-size`: Set PDF chunk size in pages (default: 25)
|
|
57
|
+
- `-o`, `--output-dir`: Absolute path to the output directory
|
|
58
|
+
- `-v`, `--verbose`: Enable verbose (DEBUG level) logging
|
|
59
|
+
- `--version`: Show the installed version and exit
|
|
60
|
+
|
|
61
|
+
## Requirements
|
|
62
|
+
|
|
63
|
+
- Python ≥3.10
|
|
64
|
+
- API key from [datalab.to](https://www.datalab.to/marker)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pdf-to-markdown-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.1"
|
|
8
8
|
description = "CLI tool to convert PDF files (and other documents) to markdown using the Marker API."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -48,4 +48,7 @@ pdf-to-md = "docs_to_md.main:main"
|
|
|
48
48
|
|
|
49
49
|
# Just in case: Configure setuptools to find packages in src/
|
|
50
50
|
[tool.setuptools.packages.find]
|
|
51
|
-
where = ["src"]
|
|
51
|
+
where = ["src"]
|
|
52
|
+
|
|
53
|
+
[project.optional-dependencies]
|
|
54
|
+
test = []
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -73,14 +73,24 @@ class MarkerClient:
|
|
|
73
73
|
form_data = {
|
|
74
74
|
"file": (file_path.name, file_data, kind.mime),
|
|
75
75
|
"langs": (None, langs),
|
|
76
|
-
"force_ocr": (None, force_ocr),
|
|
77
|
-
"paginate": (None, paginate),
|
|
78
|
-
"strip_existing_ocr": (None, strip_existing_ocr),
|
|
79
|
-
"disable_image_extraction": (None, disable_image_extraction),
|
|
80
|
-
"use_llm": (None, use_llm),
|
|
81
76
|
"output_format": (None, output_format),
|
|
82
|
-
"max_pages": (None, max_pages),
|
|
83
77
|
}
|
|
78
|
+
|
|
79
|
+
# Add boolean parameters with proper serialization
|
|
80
|
+
if force_ocr:
|
|
81
|
+
form_data["force_ocr"] = (None, "true")
|
|
82
|
+
if paginate:
|
|
83
|
+
form_data["paginate"] = (None, "true")
|
|
84
|
+
if strip_existing_ocr:
|
|
85
|
+
form_data["strip_existing_ocr"] = (None, "true")
|
|
86
|
+
if disable_image_extraction:
|
|
87
|
+
form_data["disable_image_extraction"] = (None, "true")
|
|
88
|
+
if use_llm:
|
|
89
|
+
form_data["use_llm"] = (None, "true")
|
|
90
|
+
|
|
91
|
+
# Add max_pages only if it has a value
|
|
92
|
+
if max_pages is not None:
|
|
93
|
+
form_data["max_pages"] = (None, str(max_pages))
|
|
84
94
|
|
|
85
95
|
response = requests.post(
|
|
86
96
|
self.BASE_MARKER_API_ENDPOINT,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -53,6 +53,75 @@ class BatchProcessor:
|
|
|
53
53
|
def should_chunk(self, file_path: Path) -> bool:
|
|
54
54
|
return file_path.suffix.lower() == ".pdf"
|
|
55
55
|
|
|
56
|
+
def _chunk_file(
|
|
57
|
+
self, file_path: Path, tmp_dir: Path, request: ConversionRequest
|
|
58
|
+
) -> bool:
|
|
59
|
+
"""Chunk the provided PDF and populate the request object.
|
|
60
|
+
|
|
61
|
+
Returns ``True`` if chunking fails and the request should be marked
|
|
62
|
+
as failed.
|
|
63
|
+
"""
|
|
64
|
+
try:
|
|
65
|
+
chunk_result = chunk_pdf_to_temp(str(file_path), self.chunk_size, tmp_dir)
|
|
66
|
+
if chunk_result:
|
|
67
|
+
for chunk_info in chunk_result.chunks:
|
|
68
|
+
request.add_chunk(Path(chunk_info.path), chunk_info.index)
|
|
69
|
+
logger.debug(
|
|
70
|
+
f"Created {len(request.chunks)} chunks in {tmp_dir}"
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
logger.debug(
|
|
74
|
+
f"No chunking needed for {file_path} (<= {self.chunk_size} pages)"
|
|
75
|
+
)
|
|
76
|
+
return False
|
|
77
|
+
except (PDFProcessingError, Exception) as e:
|
|
78
|
+
logger.error(f"Error chunking PDF {file_path}: {e}", exc_info=True)
|
|
79
|
+
request.set_status(Status.FAILED, f"Error chunking PDF: {e}")
|
|
80
|
+
self.cache.save(request)
|
|
81
|
+
return True
|
|
82
|
+
|
|
83
|
+
def _submit_chunks(
|
|
84
|
+
self, request: ConversionRequest, api_params: ApiParams
|
|
85
|
+
) -> bool:
|
|
86
|
+
"""Submit all chunks to the API.
|
|
87
|
+
|
|
88
|
+
Returns ``True`` if any submission fails.
|
|
89
|
+
"""
|
|
90
|
+
submission_failed = False
|
|
91
|
+
with ProgressTracker(len(request.chunks), "Submitting to API", "chunk") as progress:
|
|
92
|
+
for chunk in request.ordered_chunks:
|
|
93
|
+
try:
|
|
94
|
+
chunk_request_id = self.client.submit_file(
|
|
95
|
+
chunk.path,
|
|
96
|
+
output_format=api_params.output_format,
|
|
97
|
+
langs=api_params.langs,
|
|
98
|
+
use_llm=api_params.use_llm,
|
|
99
|
+
strip_existing_ocr=api_params.strip_existing_ocr,
|
|
100
|
+
disable_image_extraction=api_params.disable_image_extraction,
|
|
101
|
+
force_ocr=api_params.force_ocr,
|
|
102
|
+
paginate=api_params.paginate,
|
|
103
|
+
max_pages=api_params.max_pages,
|
|
104
|
+
)
|
|
105
|
+
if chunk_request_id:
|
|
106
|
+
chunk.mark_processing(chunk_request_id)
|
|
107
|
+
else:
|
|
108
|
+
chunk.mark_failed(
|
|
109
|
+
f"API submission failed for {chunk.path.name}"
|
|
110
|
+
)
|
|
111
|
+
submission_failed = True
|
|
112
|
+
break
|
|
113
|
+
except Exception as submit_e:
|
|
114
|
+
logger.error(
|
|
115
|
+
f"Unexpected error submitting chunk {chunk.path.name}: {submit_e}",
|
|
116
|
+
exc_info=True,
|
|
117
|
+
)
|
|
118
|
+
chunk.mark_failed(f"Error submitting chunk: {submit_e}")
|
|
119
|
+
submission_failed = True
|
|
120
|
+
break
|
|
121
|
+
finally:
|
|
122
|
+
progress.update()
|
|
123
|
+
return submission_failed or request.has_failed
|
|
124
|
+
|
|
56
125
|
def process_file(
|
|
57
126
|
self,
|
|
58
127
|
file_path: Path,
|
|
@@ -60,20 +129,11 @@ class BatchProcessor:
|
|
|
60
129
|
api_params: ApiParams,
|
|
61
130
|
output_paths_obj: OutputPaths,
|
|
62
131
|
) -> Optional[str]:
|
|
63
|
-
"""
|
|
64
|
-
Process a single file: chunk if needed, submit to API.
|
|
65
|
-
|
|
66
|
-
Args:
|
|
67
|
-
file_path: Path to the input file.
|
|
68
|
-
final_output_path: Path where the final output markdown file should be saved.
|
|
69
|
-
api_params: Parameters for the Marker API call.
|
|
70
|
-
output_paths_obj: The OutputPaths object containing final markdown and image paths.
|
|
132
|
+
"""Process a single file and submit it to the Marker API.
|
|
71
133
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
Raises:
|
|
76
|
-
FileError: Potentially raised by underlying operations (though many are caught).
|
|
134
|
+
The method now delegates chunking and submission to smaller helpers to
|
|
135
|
+
keep the logic readable. It returns the created request ID, which can
|
|
136
|
+
later be used to poll for results.
|
|
77
137
|
"""
|
|
78
138
|
with TemporaryDirectory(self.root_tmp_dir, file_path.stem) as tmp_dir:
|
|
79
139
|
request = ConversionRequest(
|
|
@@ -93,30 +153,7 @@ class BatchProcessor:
|
|
|
93
153
|
|
|
94
154
|
try:
|
|
95
155
|
if self.should_chunk(file_path):
|
|
96
|
-
|
|
97
|
-
chunk_result = chunk_pdf_to_temp(
|
|
98
|
-
str(file_path), self.chunk_size, tmp_dir
|
|
99
|
-
)
|
|
100
|
-
if chunk_result:
|
|
101
|
-
for chunk_info in chunk_result.chunks:
|
|
102
|
-
request.add_chunk(
|
|
103
|
-
Path(chunk_info.path), chunk_info.index
|
|
104
|
-
)
|
|
105
|
-
logger.debug(
|
|
106
|
-
f"Created {len(request.chunks)} chunks in {tmp_dir}"
|
|
107
|
-
)
|
|
108
|
-
else:
|
|
109
|
-
logger.debug(
|
|
110
|
-
f"No chunking needed for {file_path} (<= {self.chunk_size} pages)"
|
|
111
|
-
)
|
|
112
|
-
except (PDFProcessingError, Exception) as e:
|
|
113
|
-
logger.error(
|
|
114
|
-
f"Error chunking PDF {file_path}: {e}", exc_info=True
|
|
115
|
-
)
|
|
116
|
-
request.set_status(
|
|
117
|
-
Status.FAILED, f"Error chunking PDF: {str(e)}"
|
|
118
|
-
)
|
|
119
|
-
self.cache.save(request)
|
|
156
|
+
if self._chunk_file(file_path, tmp_dir, request):
|
|
120
157
|
return request.request_id
|
|
121
158
|
|
|
122
159
|
if not request.chunks:
|
|
@@ -126,43 +163,9 @@ class BatchProcessor:
|
|
|
126
163
|
f"Submitting {len(request.chunks)} chunk(s) to API for {request.original_file.name}..."
|
|
127
164
|
)
|
|
128
165
|
|
|
129
|
-
submission_failed =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
) as progress:
|
|
133
|
-
for chunk in request.ordered_chunks:
|
|
134
|
-
try:
|
|
135
|
-
chunk_request_id = self.client.submit_file(
|
|
136
|
-
chunk.path,
|
|
137
|
-
output_format=api_params.output_format,
|
|
138
|
-
langs=api_params.langs,
|
|
139
|
-
use_llm=api_params.use_llm,
|
|
140
|
-
strip_existing_ocr=api_params.strip_existing_ocr,
|
|
141
|
-
disable_image_extraction=api_params.disable_image_extraction,
|
|
142
|
-
force_ocr=api_params.force_ocr,
|
|
143
|
-
paginate=api_params.paginate,
|
|
144
|
-
max_pages=api_params.max_pages,
|
|
145
|
-
)
|
|
146
|
-
if chunk_request_id:
|
|
147
|
-
chunk.mark_processing(chunk_request_id)
|
|
148
|
-
else:
|
|
149
|
-
chunk.mark_failed(
|
|
150
|
-
f"API submission failed for {chunk.path.name}"
|
|
151
|
-
)
|
|
152
|
-
submission_failed = True
|
|
153
|
-
break
|
|
154
|
-
except Exception as submit_e:
|
|
155
|
-
logger.error(
|
|
156
|
-
f"Unexpected error submitting chunk {chunk.path.name}: {submit_e}",
|
|
157
|
-
exc_info=True,
|
|
158
|
-
)
|
|
159
|
-
chunk.mark_failed(f"Error submitting chunk: {submit_e}")
|
|
160
|
-
submission_failed = True
|
|
161
|
-
break
|
|
162
|
-
finally:
|
|
163
|
-
progress.update()
|
|
164
|
-
|
|
165
|
-
if submission_failed or request.has_failed:
|
|
166
|
+
submission_failed = self._submit_chunks(request, api_params)
|
|
167
|
+
|
|
168
|
+
if submission_failed:
|
|
166
169
|
request.set_status(
|
|
167
170
|
Status.FAILED,
|
|
168
171
|
request.error or "One or more chunk submissions failed.",
|
{pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/core/result_handler.py
RENAMED
|
@@ -91,9 +91,14 @@ class ResultSaver:
|
|
|
91
91
|
logger.debug(
|
|
92
92
|
f"Successfully combined results to {output_file} (Final size: {final_size} bytes)"
|
|
93
93
|
)
|
|
94
|
-
#
|
|
95
|
-
if req.images_dir:
|
|
96
|
-
|
|
94
|
+
# Only create images directory if there are actually images to move
|
|
95
|
+
if req.images_dir and req.tmp_dir:
|
|
96
|
+
source_images_dir = req.tmp_dir / "images"
|
|
97
|
+
if source_images_dir.exists():
|
|
98
|
+
ensure_directory(req.images_dir)
|
|
99
|
+
logger.debug(f"Created images directory {req.images_dir} (images will be moved)")
|
|
100
|
+
else:
|
|
101
|
+
logger.debug(f"No images found - skipping creation of {req.images_dir}")
|
|
97
102
|
return output_file, final_size
|
|
98
103
|
|
|
99
104
|
except Exception as e:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -48,7 +48,8 @@ class ConversionRequest(BaseModel):
|
|
|
48
48
|
output_format: str = "markdown"
|
|
49
49
|
status: Status = Status.PENDING
|
|
50
50
|
error: Optional[str] = None
|
|
51
|
-
|
|
51
|
+
# Use default_factory to avoid shared mutable list across instances
|
|
52
|
+
chunks: List[ChunkInfo] = Field(default_factory=list)
|
|
52
53
|
chunk_size: int
|
|
53
54
|
tmp_dir: Optional[Path] = None # Directory for temporary files for this conversion
|
|
54
55
|
images_dir: Optional[Path] = None # Added to store determined image path
|
|
File without changes
|
|
File without changes
|
|
@@ -94,8 +94,9 @@ class FileDiscovery:
|
|
|
94
94
|
logger.warning(f"Skipping {file_path}: Supported extension '{ext}', but unsupported detected MIME type '{kind.mime}'.")
|
|
95
95
|
return False
|
|
96
96
|
else:
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
# MIME detection failed - rely on the earlier suffix extension check
|
|
98
|
+
logger.debug(f"Adding {file_path}: Supported extension '{ext}', MIME detection failed - using extension as fallback.")
|
|
99
|
+
return True
|
|
99
100
|
|
|
100
101
|
@staticmethod
|
|
101
102
|
def find_processable_files(
|
|
File without changes
|
{pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/pdf_splitter.py
RENAMED
|
File without changes
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pdf-to-markdown-cli
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Summary: CLI tool to convert PDF files (and other documents) to markdown using the Marker API.
|
|
5
|
+
Author: Nikita Sokolsky
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 SokolskyNikita
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/SokolskyNikita/pdf-to-markdown-cli
|
|
29
|
+
Project-URL: Bug Tracker, https://github.com/SokolskyNikita/pdf-to-markdown-cli/issues
|
|
30
|
+
Keywords: pdf,markdown,converter,cli,document,marker,md
|
|
31
|
+
Classifier: Development Status :: 4 - Beta
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Classifier: Topic :: Text Processing
|
|
41
|
+
Classifier: Topic :: Utilities
|
|
42
|
+
Requires-Python: >=3.10
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
License-File: LICENSE
|
|
45
|
+
Requires-Dist: backoff>=2.0
|
|
46
|
+
Requires-Dist: diskcache>=5.0
|
|
47
|
+
Requires-Dist: filetype>=1.0
|
|
48
|
+
Requires-Dist: pikepdf>=8.0
|
|
49
|
+
Requires-Dist: pydantic>=2.0
|
|
50
|
+
Requires-Dist: ratelimit>=2.0
|
|
51
|
+
Requires-Dist: requests>=2.0
|
|
52
|
+
Requires-Dist: tqdm>=4.0
|
|
53
|
+
Provides-Extra: test
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# PDF to Markdown CLI
|
|
57
|
+
|
|
58
|
+
Convert PDFs and other documents to Markdown using the [Marker API](https://www.datalab.to/marker).
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
- Convert PDFs, Word docs, PowerPoint, spreadsheets, EPUB, HTML, and images to Markdown/JSON/HTML
|
|
63
|
+
- Automatic chunking for large documents with parallel processing
|
|
64
|
+
- Progress tracking and local caching for interrupted runs
|
|
65
|
+
- Full OCR customization options
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
### From PyPI
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install pdf-to-markdown-cli
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### From source
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
git clone https://github.com/SokolskyNikita/pdf-to-markdown-cli.git
|
|
79
|
+
cd pdf-to-markdown-cli
|
|
80
|
+
pip install -e .
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Usage
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Get API key from https://www.datalab.to/marker
|
|
87
|
+
export MARKER_PDF_KEY=your_api_key_here
|
|
88
|
+
|
|
89
|
+
# Basic usage
|
|
90
|
+
pdf-to-md /path/to/file.pdf
|
|
91
|
+
|
|
92
|
+
# Common options
|
|
93
|
+
pdf-to-md /path/to/file.pdf --json # JSON output
|
|
94
|
+
pdf-to-md /path/to/file.pdf --noimg # Disable images
|
|
95
|
+
pdf-to-md /path/to/file.pdf --max # Enable all flags for maximum output quality
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## CLI Options
|
|
99
|
+
|
|
100
|
+
- `input`: Input file or directory path
|
|
101
|
+
- `--json`: Output in JSON format (default is markdown)
|
|
102
|
+
- `--langs`: Comma-separated OCR languages (default: "English")
|
|
103
|
+
- `--llm`: Use LLM for enhanced processing
|
|
104
|
+
- `--strip`: Redo OCR processing
|
|
105
|
+
- `--noimg`: Disable image extraction
|
|
106
|
+
- `--force`: Force OCR on all pages
|
|
107
|
+
- `--pages`: Add page delimiters
|
|
108
|
+
- `--max`: Enable all OCR enhancements (equivalent to --llm --strip --force)
|
|
109
|
+
- `-mp`, `--max-pages`: Maximum number of pages to process from the start of the file
|
|
110
|
+
- `--no-chunk`: Disable PDF chunking
|
|
111
|
+
- `-cs`, `--chunk-size`: Set PDF chunk size in pages (default: 25)
|
|
112
|
+
- `-o`, `--output-dir`: Absolute path to the output directory
|
|
113
|
+
- `-v`, `--verbose`: Enable verbose (DEBUG level) logging
|
|
114
|
+
- `--version`: Show the installed version and exit
|
|
115
|
+
|
|
116
|
+
## Requirements
|
|
117
|
+
|
|
118
|
+
- Python ≥3.10
|
|
119
|
+
- API key from [datalab.to](https://www.datalab.to/marker)
|
{pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/pdf_to_markdown_cli.egg-info/SOURCES.txt
RENAMED
|
@@ -28,4 +28,9 @@ src/pdf_to_markdown_cli.egg-info/SOURCES.txt
|
|
|
28
28
|
src/pdf_to_markdown_cli.egg-info/dependency_links.txt
|
|
29
29
|
src/pdf_to_markdown_cli.egg-info/entry_points.txt
|
|
30
30
|
src/pdf_to_markdown_cli.egg-info/requires.txt
|
|
31
|
-
src/pdf_to_markdown_cli.egg-info/top_level.txt
|
|
31
|
+
src/pdf_to_markdown_cli.egg-info/top_level.txt
|
|
32
|
+
tests/test_cli.py
|
|
33
|
+
tests/test_cli_equations.py
|
|
34
|
+
tests/test_paths.py
|
|
35
|
+
tests/test_settings.py
|
|
36
|
+
tests/test_utils.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|