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.
Files changed (41) hide show
  1. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/LICENSE +0 -0
  2. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/MANIFEST.in +0 -0
  3. pdf_to_markdown_cli-0.5.1/PKG-INFO +119 -0
  4. pdf_to_markdown_cli-0.5.1/README.md +64 -0
  5. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/pyproject.toml +5 -2
  6. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/__init__.py +0 -0
  7. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/__main__.py +0 -0
  8. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/api/__init__.py +0 -0
  9. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/api/client.py +16 -6
  10. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/api/models.py +0 -0
  11. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/config/__init__.py +0 -0
  12. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/config/cli.py +0 -0
  13. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/config/settings.py +0 -0
  14. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/core/__init__.py +0 -0
  15. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/core/paths.py +0 -0
  16. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/core/processor.py +77 -74
  17. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/core/result_handler.py +8 -3
  18. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/main.py +0 -0
  19. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/storage/__init__.py +0 -0
  20. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/storage/cache.py +0 -0
  21. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/storage/models.py +2 -1
  22. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/__init__.py +0 -0
  23. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/exceptions.py +0 -0
  24. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/file_utils.py +3 -2
  25. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/logging.py +0 -0
  26. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/src/docs_to_md/utils/pdf_splitter.py +0 -0
  27. pdf_to_markdown_cli-0.5.1/src/pdf_to_markdown_cli.egg-info/PKG-INFO +119 -0
  28. {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
  29. {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
  30. {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
  31. {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
  32. {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
  33. pdf_to_markdown_cli-0.5.1/tests/test_cli.py +37 -0
  34. pdf_to_markdown_cli-0.5.1/tests/test_cli_equations.py +113 -0
  35. pdf_to_markdown_cli-0.5.1/tests/test_paths.py +25 -0
  36. pdf_to_markdown_cli-0.5.1/tests/test_settings.py +65 -0
  37. pdf_to_markdown_cli-0.5.1/tests/test_utils.py +118 -0
  38. pdf_to_markdown_cli-0.4.0/PKG-INFO +0 -202
  39. pdf_to_markdown_cli-0.4.0/README.md +0 -148
  40. pdf_to_markdown_cli-0.4.0/src/pdf_to_markdown_cli.egg-info/PKG-INFO +0 -202
  41. {pdf_to_markdown_cli-0.4.0 → pdf_to_markdown_cli-0.5.1}/setup.cfg +0 -0
@@ -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.4.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 = []
@@ -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,
@@ -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
- Returns:
73
- Request ID for tracking if submission is initiated, otherwise None.
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
- try:
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 = False
130
- with ProgressTracker(
131
- len(request.chunks), "Submitting to API", "chunk"
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.",
@@ -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
- # Ensure images dir exists before returning (though determine_output_paths should have done it)
95
- if req.images_dir:
96
- ensure_directory(req.images_dir)
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:
@@ -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
- chunks: List[ChunkInfo] = []
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
@@ -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
- logger.info(f"Skipping {file_path}: Supported extension '{ext}', but MIME detection failed or ambiguous.")
98
- return False
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(
@@ -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)
@@ -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
@@ -6,3 +6,5 @@ pydantic>=2.0
6
6
  ratelimit>=2.0
7
7
  requests>=2.0
8
8
  tqdm>=4.0
9
+
10
+ [test]