|
5 | 5 |
|
6 | 6 | import json |
7 | 7 | import os |
| 8 | +import re |
8 | 9 | import tempfile |
9 | 10 | import typing |
10 | 11 | from pathlib import Path |
|
13 | 14 | import requests |
14 | 15 | import toml |
15 | 16 | from bs4 import BeautifulSoup |
16 | | -from m2r import parse_from_file # pylint: disable=import-error |
17 | 17 |
|
18 | 18 | import colrev.package_manager.colrev_internal_packages |
19 | 19 | from colrev.constants import EndpointType |
@@ -271,18 +271,83 @@ def _get_header_info(self) -> str: |
271 | 271 |
|
272 | 272 | def import_package_docs(self) -> None: |
273 | 273 | """Import the package documentation.""" |
274 | | - with open( |
275 | | - Filepaths.COLREV_PATH |
276 | | - / Path(f"docs/source/manual/packages/{self.docs_rst_path}"), |
277 | | - "w", |
278 | | - encoding="utf-8", |
279 | | - ) as file: |
| 274 | + docs_package_path = Filepaths.COLREV_PATH / Path( |
| 275 | + f"docs/source/manual/packages/{self.docs_rst_path}" |
| 276 | + ) |
| 277 | + |
| 278 | + readme_path = self._copy_readme_for_myst_include() |
| 279 | + readme_content = readme_path.read_text(encoding="utf-8") |
| 280 | + rst_readme_content = self._convert_markdown_to_rst(readme_content) |
| 281 | + |
| 282 | + with open(docs_package_path, "w", encoding="utf-8") as file: |
280 | 283 | file.write(self._get_header_info()) |
281 | | - output = parse_from_file(self.docs_package_readme_path) |
282 | | - output = output.replace( |
283 | | - ".. list-table::", ".. list-table::\n :align: left" |
284 | | - ) |
285 | | - file.write(output) |
| 284 | + file.write("\n") |
| 285 | + file.write(rst_readme_content) |
| 286 | + |
| 287 | + def _convert_markdown_to_rst(self, markdown_content: str) -> str: |
| 288 | + """Convert Markdown content to reStructuredText for generated docs pages.""" |
| 289 | + heading_chars = {1: "=", 2: "-", 3: "^", 4: '"'} |
| 290 | + converted_lines = [] |
| 291 | + in_fenced_code_block = False |
| 292 | + fenced_code_language = "" |
| 293 | + |
| 294 | + for line in markdown_content.splitlines(): |
| 295 | + fence_match = re.match(r"^```(\w+)?\s*$", line) |
| 296 | + if fence_match: |
| 297 | + if not in_fenced_code_block: |
| 298 | + in_fenced_code_block = True |
| 299 | + fenced_code_language = fence_match.group(1) or "" |
| 300 | + if fenced_code_language: |
| 301 | + converted_lines.append( |
| 302 | + f".. code-block:: {fenced_code_language}" |
| 303 | + ) |
| 304 | + else: |
| 305 | + converted_lines.append(".. code-block::") |
| 306 | + converted_lines.append("") |
| 307 | + else: |
| 308 | + in_fenced_code_block = False |
| 309 | + fenced_code_language = "" |
| 310 | + converted_lines.append("") |
| 311 | + continue |
| 312 | + |
| 313 | + if in_fenced_code_block: |
| 314 | + if line.strip() == "": |
| 315 | + converted_lines.append("") |
| 316 | + else: |
| 317 | + converted_lines.append(f" {line}") |
| 318 | + continue |
| 319 | + |
| 320 | + heading_match = re.match(r"^(#{1,6})\s+(.+?)\s*$", line) |
| 321 | + if heading_match: |
| 322 | + level = len(heading_match.group(1)) |
| 323 | + title = heading_match.group(2) |
| 324 | + underline_char = heading_chars.get(level, '"') |
| 325 | + converted_lines.append(title) |
| 326 | + converted_lines.append(underline_char * len(title)) |
| 327 | + converted_lines.append("") |
| 328 | + continue |
| 329 | + |
| 330 | + line = re.sub(r"\[([^\]]+)\]\(([^)]+)\)", r"`\1 <\2>`_", line) |
| 331 | + line = re.sub(r"^\s*-\s+`([^`]+)\s+<([^>]+)>`_\s*$", r"* `\1 <\2>`_", line) |
| 332 | + line = re.sub(r"``([^`]+)```\1`", r"``\1``", line) |
| 333 | + converted_lines.append(line) |
| 334 | + |
| 335 | + return "\n".join(converted_lines).rstrip() + "\n" |
| 336 | + |
| 337 | + def _copy_readme_for_myst_include(self) -> Path: |
| 338 | + """Copy the package README to a generated docs folder for MyST inclusion.""" |
| 339 | + readme_dir = Filepaths.COLREV_PATH / Path( |
| 340 | + "docs/source/manual/packages/_package_readmes" |
| 341 | + ) |
| 342 | + readme_dir.mkdir(parents=True, exist_ok=True) |
| 343 | + |
| 344 | + readme_path = readme_dir / f"{self.package_id}.md" |
| 345 | + readme_path.write_text( |
| 346 | + self.docs_package_readme_path.read_text(encoding="utf-8"), |
| 347 | + encoding="utf-8", |
| 348 | + ) |
| 349 | + |
| 350 | + return readme_path |
286 | 351 |
|
287 | 352 | def get_endpoint_item(self, endpoint_type: EndpointType) -> dict: |
288 | 353 | """Get the endpoint item for the package. |
|
0 commit comments