markitecture 0.1.15__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. markitecture/__init__.py +41 -0
  2. markitecture/__main__.py +4 -0
  3. markitecture/cli/__init__.py +3 -0
  4. markitecture/cli/app.py +38 -0
  5. markitecture/cli/commands/__init__.py +21 -0
  6. markitecture/cli/commands/config.py +84 -0
  7. markitecture/cli/commands/links.py +146 -0
  8. markitecture/cli/commands/metrics.py +193 -0
  9. markitecture/cli/commands/mkdocs.py +39 -0
  10. markitecture/cli/commands/split.py +48 -0
  11. markitecture/errors.py +64 -0
  12. markitecture/generators/__init__.py +3 -0
  13. markitecture/generators/configs/__init__.py +0 -0
  14. markitecture/generators/configs/mintlify_json.py +0 -0
  15. markitecture/generators/configs/mkdocs_yaml.py +317 -0
  16. markitecture/metrics/__init__.py +9 -0
  17. markitecture/metrics/analyzer.py +109 -0
  18. markitecture/metrics/badges/__init__.py +28 -0
  19. markitecture/metrics/badges/base.py +7 -0
  20. markitecture/metrics/badges/compact.py +35 -0
  21. markitecture/metrics/badges/detailed.py +60 -0
  22. markitecture/metrics/badges/minimal.py +19 -0
  23. markitecture/metrics/badges/modern.py +45 -0
  24. markitecture/metrics/badges/retro.py +23 -0
  25. markitecture/metrics/badges/shields.py +124 -0
  26. markitecture/metrics/svg_generator.py +70 -0
  27. markitecture/processing/__init__.py +0 -0
  28. markitecture/processing/link_validator.py +133 -0
  29. markitecture/processing/reflink_converter.py +198 -0
  30. markitecture/processing/reflink_extractor.py +82 -0
  31. markitecture/processing/text_splitter.py +290 -0
  32. markitecture/settings/__init__.py +9 -0
  33. markitecture/settings/config.py +61 -0
  34. markitecture/settings/validators.py +26 -0
  35. markitecture/utils/__init__.py +5 -0
  36. markitecture/utils/file_handler.py +24 -0
  37. markitecture/utils/printer.py +195 -0
  38. markitecture/utils/sanitizer.py +78 -0
  39. markitecture-0.1.15.dist-info/METADATA +271 -0
  40. markitecture-0.1.15.dist-info/RECORD +43 -0
  41. markitecture-0.1.15.dist-info/WHEEL +4 -0
  42. markitecture-0.1.15.dist-info/entry_points.txt +2 -0
  43. markitecture-0.1.15.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,41 @@
1
+ from importlib.metadata import version
2
+
3
+ from markitecture import metrics
4
+
5
+ from .errors import (
6
+ FileOperationError,
7
+ FileReadError,
8
+ FileWriteError,
9
+ InvalidPathError,
10
+ MarkitectureBaseError,
11
+ ParseError,
12
+ )
13
+ from .generators.configs.mkdocs_yaml import MkDocsConfig
14
+ from .metrics.svg_generator import MetricsSvgGenerator
15
+ from .processing.reflink_converter import (
16
+ ReferenceLinkConverter,
17
+ ReferencePlacement,
18
+ )
19
+ from .processing.text_splitter import MarkdownTextSplitter
20
+ from .utils.file_handler import FileHandler
21
+ from .utils.printer import RichPrinter
22
+
23
+ __version__ = version("markitecture")
24
+
25
+ __all__: list[str] = [
26
+ "FileHandler",
27
+ "FileOperationError",
28
+ "FileReadError",
29
+ "FileWriteError",
30
+ "InvalidPathError",
31
+ "MarkdownTextSplitter",
32
+ "MarkitectureBaseError",
33
+ "MetricsSvgGenerator",
34
+ "MkDocsConfig",
35
+ "ParseError",
36
+ "ReferenceLinkConverter",
37
+ "ReferencePlacement",
38
+ "RichPrinter",
39
+ "__version__",
40
+ "metrics",
41
+ ]
@@ -0,0 +1,4 @@
1
+ from markitecture.cli.app import run_cli
2
+
3
+ if __name__ == "__main__":
4
+ run_cli()
@@ -0,0 +1,3 @@
1
+ from markitecture.cli.app import run_cli
2
+
3
+ __all__ = ["run_cli"]
@@ -0,0 +1,38 @@
1
+ from markitecture.settings.config import MarkitectureApp
2
+ from markitecture.utils.printer import RichPrinter
3
+
4
+ _printer = RichPrinter()
5
+
6
+
7
+ def run_cli() -> None:
8
+ """
9
+ Main entry point for the CLI. Routes commands to their appropriate handlers.
10
+ """
11
+ from markitecture import __version__
12
+
13
+ try:
14
+ settings = MarkitectureApp()
15
+ if settings.version:
16
+ _printer.print_version(__version__)
17
+ return
18
+
19
+ if settings.config:
20
+ settings.config.cli_cmd()
21
+ elif settings.check_links:
22
+ settings.check_links.cli_cmd()
23
+ elif settings.reference_links:
24
+ settings.reference_links.cli_cmd()
25
+ elif settings.metrics:
26
+ settings.metrics.cli_cmd()
27
+ elif settings.mkdocs:
28
+ settings.mkdocs.cli_cmd()
29
+ elif settings.split:
30
+ settings.split.cli_cmd()
31
+ else:
32
+ _printer.print_error(
33
+ "No command provided. Use `--help` for more information."
34
+ )
35
+
36
+ except Exception as e:
37
+ _printer.print_error(f"An error occurred: {e!r}")
38
+ raise e
@@ -0,0 +1,21 @@
1
+ """
2
+ Command implementations for the Markitecture CLI.
3
+
4
+ This module contains all available commands that can be executed through the CLI.
5
+ Each command is implemented as a separate class inheriting from BaseCommand.
6
+ """
7
+
8
+ from .config import ConfigCommand
9
+ from .links import CheckLinksCommand, ReferenceLinksCommand
10
+ from .metrics import MetricsCommand
11
+ from .mkdocs import MkDocsCommand
12
+ from .split import SplitCommand
13
+
14
+ __all__ = [
15
+ "CheckLinksCommand",
16
+ "ConfigCommand",
17
+ "MetricsCommand",
18
+ "MkDocsCommand",
19
+ "ReferenceLinksCommand",
20
+ "SplitCommand",
21
+ ]
@@ -0,0 +1,84 @@
1
+ """CLI command for managing configurations via YAML files."""
2
+
3
+ from pathlib import Path
4
+
5
+ import yaml
6
+ from pydantic import AliasChoices, BaseModel, Field, field_validator
7
+
8
+ from markitecture.settings.validators import convert_to_path
9
+ from markitecture.utils.printer import RichPrinter
10
+
11
+ _printer = RichPrinter()
12
+
13
+
14
+ class ConfigCommand(BaseModel):
15
+ """
16
+ CLI command for managing configurations via YAML files.
17
+ """
18
+
19
+ config_path: Path = Field(
20
+ default=Path("markitect.yml"),
21
+ description="Path to the configuration file.",
22
+ validation_alias=AliasChoices("p", "path"),
23
+ )
24
+ generate: bool = Field(
25
+ default=False,
26
+ description="Generate a default configuration file.",
27
+ validation_alias=AliasChoices("g", "generate"),
28
+ )
29
+ show: bool = Field(
30
+ default=False,
31
+ description="Display the current configuration settings.",
32
+ validation_alias=AliasChoices("s", "show"),
33
+ )
34
+
35
+ validate_fields = field_validator("config_path")(convert_to_path)
36
+
37
+ def cli_cmd(self) -> None:
38
+ """Execute the configuration command."""
39
+ if self.generate:
40
+ self.generate_config()
41
+
42
+ if self.show:
43
+ self.show_config()
44
+
45
+ def generate_config(self) -> None:
46
+ """Generates a default configuration file."""
47
+ from markitecture.cli.app import MarkitectureApp
48
+
49
+ _printer.print_info(
50
+ f"Generating default configuration file at {self.config_path}"
51
+ )
52
+ settings = MarkitectureApp()
53
+ settings_dict = settings.model_dump(mode="json")
54
+
55
+ with self.config_path.open("w", encoding="utf-8") as file:
56
+ yaml.dump(
57
+ settings_dict,
58
+ file,
59
+ default_flow_style=False,
60
+ sort_keys=False,
61
+ )
62
+ _printer.print_success(
63
+ f"Markitecture configuration file generated at: {self.config_path}"
64
+ )
65
+
66
+ def show_config(self) -> None:
67
+ """Displays the current configuration settings."""
68
+ if self.config_path.exists():
69
+ _printer.print_debug(f"Reading configuration file: {self.config_path}")
70
+
71
+ try:
72
+ with self.config_path.open(encoding="utf-8") as file:
73
+ settings = yaml.safe_load(file)
74
+ except yaml.YAMLError as e:
75
+ _printer.print_error(f"Error reading configuration file: {e}")
76
+ return
77
+
78
+ _printer.print_key_value_table("Configuration Settings", settings)
79
+
80
+ else:
81
+ _printer.print_error(
82
+ f"No configuration file found at {self.config_path}. "
83
+ "Use '--generate' to create one."
84
+ )
@@ -0,0 +1,146 @@
1
+ """Commands for checking and converting markdown links."""
2
+
3
+ import re
4
+ from pathlib import Path
5
+
6
+ from pydantic import AliasChoices, BaseModel, Field
7
+
8
+ from markitecture.processing.link_validator import LinkValidator
9
+ from markitecture.processing.reflink_converter import (
10
+ ReferenceLinkConverter,
11
+ ReferencePlacement,
12
+ )
13
+ from markitecture.settings.validators import ExistingFilePath
14
+ from markitecture.utils.printer import RichPrinter
15
+
16
+ _printer = RichPrinter()
17
+
18
+
19
+ class CheckLinksCommand(BaseModel):
20
+ """
21
+ Validate all links in a markdown file.
22
+ """
23
+
24
+ input_file: ExistingFilePath = Field(
25
+ ...,
26
+ description="Path to the markdown file.",
27
+ validation_alias=AliasChoices("i", "input"),
28
+ )
29
+ report_path: Path = Field(
30
+ default=Path(".markitecture/link_health.txt"),
31
+ description="Path to save the report.",
32
+ validation_alias=AliasChoices("rp", "report-path"),
33
+ )
34
+ max_workers: int = Field(
35
+ default=5,
36
+ ge=1,
37
+ le=10,
38
+ description="Number of concurrent link checks.",
39
+ validation_alias=AliasChoices("mw", "max-workers"),
40
+ )
41
+ timeout: int = Field(
42
+ default=10,
43
+ ge=1,
44
+ le=180,
45
+ description="Timeout for link validation in seconds.",
46
+ validation_alias=AliasChoices("t", "timeout"),
47
+ )
48
+
49
+ def cli_cmd(self) -> None:
50
+ """Execute the check links command."""
51
+ _printer.print_info(
52
+ f"Scanning markdown file {self.input_file} for broken links..."
53
+ )
54
+
55
+ checker = LinkValidator(timeout=self.timeout, max_workers=self.max_workers)
56
+ results = checker.check_markdown_file(str(self.input_file))
57
+ if not results:
58
+ _printer.print_info("No links found.")
59
+ return
60
+
61
+ broken_links = 0
62
+ rows = []
63
+ for result in results:
64
+ status = "✓" if result["status"] == "ok" else "𝗫"
65
+ error = result["error"] if result["error"] else ""
66
+ rows.append([status, str(result["line"]), result["url"], error])
67
+ if result["error"]:
68
+ broken_links += 1
69
+
70
+ _printer.print_table(
71
+ "Markdown Link Check Results",
72
+ ["Status", "Line", "Link", "Error"],
73
+ rows,
74
+ )
75
+ _printer.print_success(
76
+ f"Summary: {broken_links} broken links out of {len(results)} total links.\n"
77
+ )
78
+
79
+
80
+ class ReferenceLinksCommand(BaseModel):
81
+ """Convert inline markdown links to reference-style links."""
82
+
83
+ input_file: ExistingFilePath = Field(
84
+ ...,
85
+ description="Path to the markdown file.",
86
+ validation_alias=AliasChoices("i", "input"),
87
+ )
88
+ output_file: Path | str = Field(
89
+ default=Path("reflinks_output.md"),
90
+ description="Path to save updated document.",
91
+ validation_alias=AliasChoices("o", "output"),
92
+ )
93
+ placement: ReferencePlacement = Field(
94
+ default=ReferencePlacement.END,
95
+ description="Where to place reference links (end/section).",
96
+ validation_alias=AliasChoices("p", "placement"),
97
+ )
98
+
99
+ def cli_cmd(self) -> None:
100
+ """Execute the reference link conversion."""
101
+ _printer.print_title("Reference Link Conversion")
102
+ _printer.print_info("Configuration:")
103
+ _printer.print_key_value_table(
104
+ "Settings",
105
+ {
106
+ "Input File": str(self.input_file),
107
+ "Output File": str(self.output_file),
108
+ "Placement": self.placement.value,
109
+ },
110
+ )
111
+
112
+ try:
113
+ # Initialize converter
114
+ converter = ReferenceLinkConverter()
115
+ content = Path(self.input_file).read_text()
116
+
117
+ # Extract initial metrics
118
+ initial_links = len(re.findall(r"\[([^\]]+)\]\(([^\)]+)\)", content))
119
+ _printer.print_info(f"Found {initial_links} inline links to convert")
120
+
121
+ # Process file
122
+ _printer.print_debug("Starting conversion process...")
123
+ converter.process_file(
124
+ self.input_file,
125
+ self.output_file or self.input_file,
126
+ self.placement,
127
+ )
128
+
129
+ # Get final metrics
130
+ result = Path(self.output_file).read_text()
131
+ final_refs = len(re.findall(r"^\[[^\]]+\]:", result, re.MULTILINE))
132
+
133
+ # Summary
134
+ _printer.print_success("\nConversion Summary:")
135
+ _printer.print_key_value_table(
136
+ "Results",
137
+ {
138
+ "Links Processed": str(initial_links),
139
+ "References Created": str(final_refs),
140
+ "Output Location": str(self.output_file),
141
+ },
142
+ )
143
+
144
+ except Exception as e:
145
+ _printer.print_error(f"Error during conversion: {e!s}")
146
+ raise
@@ -0,0 +1,193 @@
1
+ from pathlib import Path
2
+
3
+ from pydantic import AliasChoices, BaseModel, Field
4
+
5
+ from markitecture.metrics.analyzer import ReadabilityAnalyzer, ReadabilityMetrics
6
+ from markitecture.metrics.svg_generator import (
7
+ BadgeStyle,
8
+ MetricsSvgGenerator,
9
+ )
10
+ from markitecture.settings.validators import ExistingFilePath
11
+ from markitecture.utils.file_handler import FileHandler
12
+ from markitecture.utils.printer import RichPrinter
13
+
14
+ _printer = RichPrinter()
15
+
16
+
17
+ class MetricsCommand(BaseModel):
18
+ """
19
+ Generate reading time estimates and complexity metrics for markdown files.
20
+ """
21
+
22
+ input: ExistingFilePath = Field(
23
+ ...,
24
+ description="Path to the markdown file.",
25
+ validation_alias=AliasChoices("i", "input"),
26
+ )
27
+ output: Path | None = Field(
28
+ default=None,
29
+ description=f"Path to save the SVG badge. If not specified, creates {input}_metrics.svg",
30
+ validation_alias=AliasChoices("o", "output"),
31
+ )
32
+ output_dir: Path | None = Field(
33
+ default=None,
34
+ description="Directory to save all badge styles when using --style all",
35
+ validation_alias=AliasChoices("d", "dir", "output-dir"),
36
+ )
37
+ insert: bool = Field(
38
+ default=True,
39
+ description="Insert metrics badge into the document.",
40
+ validation_alias=AliasChoices("ins", "insert"),
41
+ )
42
+ position: str = Field(
43
+ default="top",
44
+ description="Position to insert badge (top/bottom).",
45
+ validation_alias=AliasChoices("p", "pos", "position"),
46
+ )
47
+ style: BadgeStyle | str = Field(
48
+ default=BadgeStyle.MODERN,
49
+ description="Badge style (modern/compact/detailed/minimal/retro) or 'all' for all styles",
50
+ validation_alias=AliasChoices("s", "style"),
51
+ )
52
+
53
+ def _generate_single_badge(
54
+ self,
55
+ metrics: ReadabilityMetrics,
56
+ style: BadgeStyle,
57
+ content: str,
58
+ output_path: Path,
59
+ ) -> None:
60
+ """Generate a single badge style."""
61
+ generator = MetricsSvgGenerator()
62
+ svg_content = generator.generate_svg(metrics, style)
63
+
64
+ # Save badge
65
+ Path(output_path).write_text(svg_content, encoding="utf-8")
66
+ _printer.print_info(f"Generated {style.value} style badge: {output_path}")
67
+
68
+ # Insert if requested and this is the primary style
69
+ if self.insert and style == self.style:
70
+ doc_content = content
71
+ svg_ref = f"![Reading Metrics]({output_path})"
72
+ if self.position.lower() == "top":
73
+ doc_content = f"{svg_ref}\n\n{content}"
74
+ else:
75
+ doc_content = f"{content}\n\n{svg_ref}"
76
+ Path(self.input).write_text(doc_content, encoding="utf-8")
77
+ _printer.print_info(f"Metrics badge added to document at: {self.position}")
78
+
79
+ def _generate_all_badges(self, metrics: ReadabilityAnalyzer, content: str) -> None:
80
+ """Generate badges in all available styles."""
81
+ # Create output directory if needed
82
+ output_dir = self.output_dir or Path(self.input).parent / "metrics_badges"
83
+ output_dir.mkdir(parents=True, exist_ok=True)
84
+
85
+ # Generate each style
86
+ for style in BadgeStyle:
87
+ output_path = output_dir / f"metrics_{style.value}.svg"
88
+ self._generate_single_badge(metrics, style, content, output_path)
89
+
90
+ _printer.print_info(f"\nAll badge styles generated in: {output_dir}")
91
+
92
+ # Generate preview HTML
93
+ preview_path = output_dir / "preview.html"
94
+ self._generate_preview_page(metrics, output_dir, preview_path)
95
+ _printer.print_info(f"Preview page generated: {preview_path}")
96
+
97
+ def _generate_preview_page(
98
+ self, metrics: ReadabilityMetrics, badge_dir: Path, output_path: Path
99
+ ) -> None:
100
+ """Generate HTML preview page showing all badge styles."""
101
+ html = f"""<!DOCTYPE html>
102
+ <html>
103
+ <head>
104
+ <title>Metrics Badge Styles - {self.input.name}</title>
105
+ <style>
106
+ body {{
107
+ font-family: Arial, sans-serif;
108
+ max-width: 800px;
109
+ margin: 40px auto;
110
+ padding: 0 20px;
111
+ background: #f5f5f5;
112
+ }}
113
+ .badge-container {{
114
+ background: white;
115
+ border-radius: 8px;
116
+ padding: 20px;
117
+ margin: 20px 0;
118
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
119
+ }}
120
+ h1 {{
121
+ color: #333;
122
+ border-bottom: 2px solid #eee;
123
+ padding-bottom: 10px;
124
+ }}
125
+ h2 {{
126
+ color: #666;
127
+ margin-top: 30px;
128
+ }}
129
+ .badge {{
130
+ margin: 20px 0;
131
+ }}
132
+ .style-name {{
133
+ color: #888;
134
+ font-size: 0.9em;
135
+ margin-bottom: 10px;
136
+ }}
137
+ </style>
138
+ </head>
139
+ <body>
140
+ <h1>Metrics Badge Styles</h1>
141
+ <p>Document: <strong>{self.input.name}</strong></p>
142
+ """
143
+
144
+ # Add each badge
145
+ for style in BadgeStyle:
146
+ badge_path = f"metrics_{style.value}.svg"
147
+ html += f'''
148
+ <div class="badge-container">
149
+ <div class="style-name">{style.value.title()} Style</div>
150
+ <div class="badge">
151
+ <img src="{badge_path}" alt="Metrics Badge - {style.value} Style">
152
+ </div>
153
+ </div>'''
154
+
155
+ html += """
156
+ </body>
157
+ </html>"""
158
+
159
+ output_path.write_text(html, encoding="utf-8")
160
+
161
+ def cli_cmd(self) -> None:
162
+ """Execute the metrics generation command."""
163
+ _printer.print_info(f"Analyzing document metrics for: {self.input}")
164
+
165
+ # Read content and generate metrics
166
+ content = FileHandler().read(self.input)
167
+ analyzer = ReadabilityAnalyzer()
168
+ metrics = analyzer.analyze_document(content)
169
+
170
+ # Generate badges based on style option
171
+ if self.style == "all":
172
+ self._generate_all_badges(metrics, content)
173
+ else:
174
+ output_path = self.output or Path(f"{self.input.stem}_metrics.svg")
175
+ self._generate_single_badge(
176
+ metrics, BadgeStyle(self.style), content, output_path
177
+ )
178
+
179
+ # Display metrics summary
180
+ _printer.print_title("Document Metrics Summary")
181
+ _printer.print_key_value_table(
182
+ "Metrics",
183
+ {
184
+ "Reading Time": f"{metrics.reading_time_mins} minutes",
185
+ "Word Count": f"{metrics.word_count:,}",
186
+ "Complexity Score": f"{metrics.complexity_score}%",
187
+ "Average Words/Sentence": f"{metrics.avg_words_per_sentence:.1f}",
188
+ "Headings": f"{metrics.heading_count}",
189
+ "Code Blocks": f"{metrics.code_block_count}",
190
+ "Links": f"{metrics.link_count}",
191
+ "Images": f"{metrics.image_count}",
192
+ },
193
+ )
@@ -0,0 +1,39 @@
1
+ from pathlib import Path
2
+
3
+ from pydantic import AliasChoices, BaseModel, Field, field_validator
4
+
5
+ from markitecture.generators.configs.mkdocs_yaml import MkDocsConfig
6
+ from markitecture.settings.validators import convert_to_path
7
+ from markitecture.utils.printer import RichPrinter
8
+
9
+ _printer = RichPrinter()
10
+
11
+
12
+ class MkDocsCommand(BaseModel):
13
+ """
14
+ Generate a basic MkDocs configuration.
15
+ """
16
+
17
+ docs_dir: Path = Field(
18
+ default=Path(".markitecture/docs"),
19
+ description="Path to the documentation directory.",
20
+ validation_alias=AliasChoices("d", "dir", "docs-dir"),
21
+ )
22
+ site_name: str = Field(
23
+ default="MkDocs Static Site Documentation",
24
+ description="Name of the MkDocs site.",
25
+ validation_alias=AliasChoices("name", "site-name"),
26
+ )
27
+
28
+ validate_fields = field_validator("docs_dir")(convert_to_path)
29
+
30
+ def cli_cmd(self) -> None:
31
+ """Execute MkDocs configuration generation."""
32
+ _printer.print_info(
33
+ f"Generating MkDocs static site config for: {self.docs_dir}"
34
+ )
35
+ MkDocsConfig(
36
+ docs_dir=self.docs_dir,
37
+ site_name=self.site_name,
38
+ ).generate_config()
39
+ _printer.print_info(f"MkDocs config generated and saved to: {self.docs_dir}.")
@@ -0,0 +1,48 @@
1
+ from pathlib import Path
2
+
3
+ from pydantic import AliasChoices, BaseModel, Field
4
+
5
+ from markitecture.settings.validators import ExistingFilePath
6
+ from markitecture.utils.file_handler import FileHandler
7
+ from markitecture.utils.printer import RichPrinter
8
+
9
+ _printer = RichPrinter()
10
+
11
+
12
+ class SplitCommand(BaseModel):
13
+ """
14
+ Split a markdown file into sections based on headings.
15
+ """
16
+
17
+ input_file: ExistingFilePath = Field(
18
+ ...,
19
+ description="Path to the input markdown file.",
20
+ validation_alias=AliasChoices("i", "input"),
21
+ )
22
+ output_dir: Path = Field(
23
+ default=Path(".markitecture/docs"),
24
+ description="Directory to save split files.",
25
+ validation_alias=AliasChoices("o", "output"),
26
+ )
27
+ heading_level: str = Field(
28
+ default="##",
29
+ description="Heading level to split on (e.g., '#', '##').",
30
+ validation_alias=AliasChoices("hl", "heading", "level", "heading-level"),
31
+ )
32
+ case_sensitive: bool = Field(
33
+ default=False,
34
+ description="Enable case-sensitive heading matching.",
35
+ validation_alias=AliasChoices("cs", "case-sensitive"),
36
+ )
37
+
38
+ def cli_cmd(self) -> None:
39
+ """Execute the split command."""
40
+ from markitecture.processing.text_splitter import MarkdownTextSplitter
41
+
42
+ _printer.print_info(f"Splitting Markdown file: {self.input_file}")
43
+ _printer.print_info(f"Splitting on heading level: {self.heading_level}")
44
+ splitter = MarkdownTextSplitter()
45
+ content = FileHandler().read(self.input_file)
46
+ # splitter.settings = self.model_dump()
47
+ splitter.process_file(content)
48
+ _printer.print_info(f"Split completed. Files saved to: {self.output_dir}")
markitecture/errors.py ADDED
@@ -0,0 +1,64 @@
1
+ """Custom exceptions for the markitecture package."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ # ----- Base ----- #
8
+
9
+
10
+ class MarkitectureBaseError(Exception):
11
+ """Base exception for markitecture errors."""
12
+
13
+ ...
14
+
15
+
16
+ class ParseError(MarkitectureBaseError):
17
+ """Raised when parsing markdown content fails."""
18
+
19
+ ...
20
+
21
+
22
+ class FileOperationError(MarkitectureBaseError):
23
+ """Raised when file operations fail."""
24
+
25
+ ...
26
+
27
+
28
+ # ----- CLI ----- #
29
+
30
+
31
+ class CLIError(MarkitectureBaseError):
32
+ """Exceptions related to the CLI."""
33
+
34
+ def __init__(self, message: str, *args: Any) -> None:
35
+ super().__init__(f"Invalid option provided to CLI: {message}", *args)
36
+
37
+
38
+ # ----- File IO ----- #
39
+
40
+
41
+ class FileSystemError(MarkitectureBaseError):
42
+ """Exceptions related to file system operations."""
43
+
44
+ def __init__(self, message: str, path: str, *args: Any) -> None:
45
+ self.file_path = path
46
+ super().__init__(f"{message}: {path}", *args)
47
+
48
+
49
+ class FileReadError(FileSystemError):
50
+ """Could not read file."""
51
+
52
+ ...
53
+
54
+
55
+ class FileWriteError(FileSystemError):
56
+ """Could not write file."""
57
+
58
+ ...
59
+
60
+
61
+ class InvalidPathError(FileSystemError):
62
+ """Invalid path provided."""
63
+
64
+ ...
@@ -0,0 +1,3 @@
1
+ from markitecture.generators.configs.mkdocs_yaml import MkDocsConfig
2
+
3
+ __all__: list[str] = ["MkDocsConfig"]