doctoc 0.0.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.
doctoc-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 KtechHub
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
doctoc-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.1
2
+ Name: doctoc
3
+ Version: 0.0.1
4
+ Summary: Generate table of contents for Markdown files
5
+ Home-page: https://github.com/ktechhub/doctoc
6
+ Author: Ktechhub
7
+ Author-email: mm@ktechhub.com
8
+ License: MIT
9
+ Keywords: markdown table of contents
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.7
18
+ Classifier: Programming Language :: Python :: 3.6
19
+ Requires-Python: >=3.6
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: click
23
+ Requires-Dist: requests
24
+
25
+
26
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
27
+
28
+ **Table of Contents** *generated with [DocToc](https://github.com/ktechhub/doctoc)*
29
+
30
+ <!---toc start-->
31
+
32
+ - [DocToc](#doctoc)
33
+ - [Prerequisites](#prerequisites)
34
+ - [Installation](#installation)
35
+ - [Usage](#usage)
36
+ - [Options:](#options)
37
+ - [Features](#features)
38
+ - [GitHub](#github)
39
+ - [License](#license)
40
+ - [Contribution](#contribution)
41
+
42
+ <!---toc end-->
43
+
44
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
45
+
46
+ # DocToc
47
+ DocToc is a command-line tool built with Python that automatically generates and updates table of contents (TOC) for Markdown files. It scans through your Markdown file, identifies headers, and creates a TOC with clickable links.
48
+
49
+ ## Prerequisites
50
+ Before installing DocToc, ensure you have the following:
51
+ - Python 3.6+
52
+ - pip (Python package installer)
53
+
54
+ ## Installation
55
+ You can install DocToc using pip:
56
+
57
+ ```sh
58
+ pip install doctoc
59
+ ```
60
+ Alternatively, you can install it from the source on GitHub:
61
+
62
+ ```sh
63
+ git clone https://github.com/ktechhub/doctoc.git
64
+ cd doctoc
65
+ python setup.py install
66
+ ```
67
+
68
+ ## Usage
69
+ Generate a table of contents for a Markdown file:
70
+
71
+ ```sh
72
+ doctoc --help
73
+ Usage: doctoc [OPTIONS] MARKDOWN_FILE
74
+
75
+ Generate or update a table of contents for Markdown files and optionally
76
+ check hyperlinks.
77
+
78
+ Args:
79
+ markdown_file (str): Path to the Markdown file to process.
80
+ outfile (str, optional): Output file path. If specified, writes the modified content to this file instead of overwriting the original.
81
+ check_links (bool): Flag to enable checking the validity of hyperlinks found in the Markdown file.
82
+
83
+ Options:
84
+ -o, --outfile TEXT Specify an output file instead of overwriting.
85
+ -cl, --check-links Check validity of hyperlinks.
86
+ --help Show this message and exit.
87
+ ```
88
+
89
+ ### Options:
90
+
91
+ - `--outfile`: Specify an output file instead of overwriting.
92
+ - `--check-links`: Check the validity of hyperlinks within the Markdown file.
93
+
94
+ Example with options:
95
+ ```sh
96
+ doctoc README.md --check-links
97
+ ```
98
+ Output
99
+ ```sh
100
+ Success: wrote TOC to README.md
101
+ Checking hyperlinks...
102
+ VALID: [DocToc](https://github.com/ktechhub/doctoc)
103
+ VALID: [DocToc](#doctoc)
104
+ VALID: [Prerequisites](#prerequisites)
105
+ VALID: [Installation](#installation)
106
+ VALID: [Usage](#usage)
107
+ VALID: [Options:](#options)
108
+ VALID: [Features](#features)
109
+ VALID: [GitHub](#github)
110
+ VALID: [License](#license)
111
+ VALID: [GitHub repository](https://github.com/ktechhub/doctoc)
112
+ ```
113
+
114
+ ```sh
115
+ doctoc README.md --outfile README_with_toc.md
116
+ ```
117
+ Output
118
+ ```sh
119
+ Success: wrote TOC to README_with_toc.md
120
+ ```
121
+ ```sh
122
+ doctoc README.md --outfile README_with_toc.md --check-links
123
+ ```
124
+
125
+ ## Features
126
+ - Automatically generates a TOC based on Markdown headers.
127
+ - Supports customization with options to specify output file and check link validity.
128
+ - Simple and easy to use with a command-line interface.
129
+
130
+ ## GitHub
131
+ For more details, visit the [GitHub repository](https://github.com/ktechhub/doctoc).
132
+
133
+ ## License
134
+ This project is licensed under the MIT License - see the LICENSE file for details.
135
+
136
+ ### Contribution
137
+ If you want to contribute, kindly see this **[contribution](https://github.com/ktechhub/doctoc/tree/main/contribution.md)**
doctoc-0.0.1/README.md ADDED
@@ -0,0 +1,112 @@
1
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
2
+
3
+ **Table of Contents** *generated with [DocToc](https://github.com/ktechhub/doctoc)*
4
+
5
+ <!---toc start-->
6
+
7
+ - [DocToc](#doctoc)
8
+ - [Prerequisites](#prerequisites)
9
+ - [Installation](#installation)
10
+ - [Usage](#usage)
11
+ - [Options:](#options)
12
+ - [Features](#features)
13
+ - [GitHub](#github)
14
+ - [License](#license)
15
+ - [Contribution](#contribution)
16
+
17
+ <!---toc end-->
18
+
19
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
20
+
21
+ # DocToc
22
+ DocToc is a command-line tool built with Python that automatically generates and updates table of contents (TOC) for Markdown files. It scans through your Markdown file, identifies headers, and creates a TOC with clickable links.
23
+
24
+ ## Prerequisites
25
+ Before installing DocToc, ensure you have the following:
26
+ - Python 3.6+
27
+ - pip (Python package installer)
28
+
29
+ ## Installation
30
+ You can install DocToc using pip:
31
+
32
+ ```sh
33
+ pip install doctoc
34
+ ```
35
+ Alternatively, you can install it from the source on GitHub:
36
+
37
+ ```sh
38
+ git clone https://github.com/ktechhub/doctoc.git
39
+ cd doctoc
40
+ python setup.py install
41
+ ```
42
+
43
+ ## Usage
44
+ Generate a table of contents for a Markdown file:
45
+
46
+ ```sh
47
+ doctoc --help
48
+ Usage: doctoc [OPTIONS] MARKDOWN_FILE
49
+
50
+ Generate or update a table of contents for Markdown files and optionally
51
+ check hyperlinks.
52
+
53
+ Args:
54
+ markdown_file (str): Path to the Markdown file to process.
55
+ outfile (str, optional): Output file path. If specified, writes the modified content to this file instead of overwriting the original.
56
+ check_links (bool): Flag to enable checking the validity of hyperlinks found in the Markdown file.
57
+
58
+ Options:
59
+ -o, --outfile TEXT Specify an output file instead of overwriting.
60
+ -cl, --check-links Check validity of hyperlinks.
61
+ --help Show this message and exit.
62
+ ```
63
+
64
+ ### Options:
65
+
66
+ - `--outfile`: Specify an output file instead of overwriting.
67
+ - `--check-links`: Check the validity of hyperlinks within the Markdown file.
68
+
69
+ Example with options:
70
+ ```sh
71
+ doctoc README.md --check-links
72
+ ```
73
+ Output
74
+ ```sh
75
+ Success: wrote TOC to README.md
76
+ Checking hyperlinks...
77
+ VALID: [DocToc](https://github.com/ktechhub/doctoc)
78
+ VALID: [DocToc](#doctoc)
79
+ VALID: [Prerequisites](#prerequisites)
80
+ VALID: [Installation](#installation)
81
+ VALID: [Usage](#usage)
82
+ VALID: [Options:](#options)
83
+ VALID: [Features](#features)
84
+ VALID: [GitHub](#github)
85
+ VALID: [License](#license)
86
+ VALID: [GitHub repository](https://github.com/ktechhub/doctoc)
87
+ ```
88
+
89
+ ```sh
90
+ doctoc README.md --outfile README_with_toc.md
91
+ ```
92
+ Output
93
+ ```sh
94
+ Success: wrote TOC to README_with_toc.md
95
+ ```
96
+ ```sh
97
+ doctoc README.md --outfile README_with_toc.md --check-links
98
+ ```
99
+
100
+ ## Features
101
+ - Automatically generates a TOC based on Markdown headers.
102
+ - Supports customization with options to specify output file and check link validity.
103
+ - Simple and easy to use with a command-line interface.
104
+
105
+ ## GitHub
106
+ For more details, visit the [GitHub repository](https://github.com/ktechhub/doctoc).
107
+
108
+ ## License
109
+ This project is licensed under the MIT License - see the LICENSE file for details.
110
+
111
+ ### Contribution
112
+ If you want to contribute, kindly see this **[contribution](https://github.com/ktechhub/doctoc/tree/main/contribution.md)**
File without changes
@@ -0,0 +1,71 @@
1
+ import click
2
+ import os, sys
3
+ import requests
4
+ from .core import modify_and_write
5
+ from .markdown import headers, get_links, as_link, MarkdownError
6
+
7
+
8
+ @click.command()
9
+ @click.argument("markdown_file")
10
+ @click.option("--outfile", "-o", help="Specify an output file instead of overwriting.")
11
+ @click.option(
12
+ "--check-links", "-cl", is_flag=True, help="Check validity of hyperlinks."
13
+ )
14
+ def main(markdown_file, outfile, check_links):
15
+ """
16
+ Generate or update a table of contents for Markdown files and optionally check hyperlinks.
17
+
18
+ Args:
19
+ markdown_file (str): Path to the Markdown file to process.
20
+ outfile (str, optional): Output file path. If specified, writes the modified content to this file instead of overwriting the original.
21
+ check_links (bool): Flag to enable checking the validity of hyperlinks found in the Markdown file.
22
+ """
23
+ try:
24
+ markdown_file = os.path.expanduser(markdown_file)
25
+ modify_and_write(markdown_file, outfile)
26
+
27
+ if check_links:
28
+ click.echo(click.style("Checking hyperlinks...", fg="yellow"), color=True)
29
+ with open(markdown_file) as fp:
30
+ contents = fp.read()
31
+
32
+ valid_http_fragments = ["#" + as_link(h) for (_, h) in headers(contents)]
33
+ for text, link, _, _ in get_links(contents):
34
+ if link.startswith("#"):
35
+ if link not in valid_http_fragments:
36
+ click.echo(
37
+ click.style(f"INVALID: [{text}]({link})", fg="red"),
38
+ color=True,
39
+ )
40
+ else:
41
+ click.echo(
42
+ click.style(f"VALID: [{text}]({link})", fg="green"),
43
+ color=True,
44
+ )
45
+ elif link.startswith("http://") or link.startswith("https://"):
46
+ r = requests.get(link)
47
+ click.echo(
48
+ click.style(
49
+ f"{'VALID' if r.status_code == 200 else 'INVALID'}: [{text}]({link})",
50
+ fg="green" if r.status_code == 200 else "red",
51
+ ),
52
+ color=True,
53
+ )
54
+ else:
55
+ click.echo(
56
+ click.style(
57
+ f"UNRECOGNIZED LINK TYPE: [{text}]({link})", fg="yellow"
58
+ ),
59
+ color=True,
60
+ )
61
+
62
+ except OSError as e:
63
+ click.echo(click.style(f"Failed: {e}", fg="red"), color=True)
64
+ sys.exit(1)
65
+ except MarkdownError as e:
66
+ click.echo(click.style(f"Failed: {e}", fg="red"), color=True)
67
+ sys.exit(1)
68
+
69
+
70
+ if __name__ == "__main__":
71
+ main()
@@ -0,0 +1,47 @@
1
+ import click
2
+ from .markdown import toc
3
+
4
+ TOC_START_TAG = (
5
+ "<!-- START doctoc generated TOC please keep comment here to allow auto update -->"
6
+ )
7
+ TOC_END_TAG = (
8
+ "<!-- END doctoc generated TOC please keep comment here to allow auto update -->"
9
+ )
10
+
11
+
12
+ def modify_and_write(path, outfile=None):
13
+
14
+ with open(path) as fp:
15
+ markdown = fp.read()
16
+
17
+ table_of_contents = toc(markdown)
18
+
19
+ start_index = markdown.find(TOC_START_TAG)
20
+ end_index = markdown.find(TOC_END_TAG) + len(TOC_END_TAG)
21
+
22
+ if start_index != -1 and end_index != -1:
23
+ new_markdown = (
24
+ markdown[:start_index]
25
+ + TOC_START_TAG
26
+ + "\n\n"
27
+ + f"**Table of Contents** *generated with [DocToc](https://github.com/ktechhub/doctoc)*\n\n"
28
+ + f"<!---toc start-->\n\n{table_of_contents}\n\n<!---toc end-->\n\n"
29
+ + TOC_END_TAG
30
+ + "\n"
31
+ + markdown[end_index:]
32
+ )
33
+ else:
34
+ new_markdown = (
35
+ f"{TOC_START_TAG}\n"
36
+ f"<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n"
37
+ f"**Table of Contents** *generated with [DocToc](https://github.com/ktechhub/doctoc)*\n\n"
38
+ f"<!---toc start-->\n\n{table_of_contents}\n\n<!---toc end-->\n\n"
39
+ f"{TOC_END_TAG}\n" + markdown
40
+ )
41
+
42
+ with open(outfile or path, "w") as fp:
43
+ fp.write(new_markdown)
44
+
45
+ click.echo(
46
+ click.style(f"Success: wrote TOC to {outfile or path}", fg="green"), color=True
47
+ )
@@ -0,0 +1,250 @@
1
+ import re
2
+ import collections
3
+
4
+ TOC_PAT = re.compile(r"[ \t]*<!---toc start-->(.*?)<!---toc end-->\s*", flags=re.DOTALL)
5
+
6
+ MD_LINK_PAT = re.compile(r"\[([^\[\]]+)\]\((([^\s)(]|\([^\s)(]*\))*)\)", re.M)
7
+
8
+ HEADER_PAT = re.compile(r"^\s{,3}(#{1,6})\s+(.*)")
9
+
10
+ STRIP_CANDIDATE_PAT = re.compile(r"(?<!\\)[ \t#]+$|^[ \t#]+")
11
+
12
+ ITAL_PAT = re.compile(r"(?<!\\)_[^(?<!\\)_]+(?<!\\)_")
13
+ BOLD_PAT = re.compile(r"(?<!\\)\*[^(?<!\\)\*]+(?<!\\)\*")
14
+
15
+
16
+ class MarkdownError(Exception):
17
+ """Markdown formatted incorrectly & unparseable."""
18
+
19
+
20
+ def _strip(x):
21
+ """
22
+ Strip surrounding spaces, tabs, and hash signs from the input string `x`.
23
+
24
+ This function removes leading and trailing whitespace characters (spaces and tabs),
25
+ as well as leading hash signs (`#`) from the input string `x`.
26
+
27
+ Args:
28
+ x (str): The input string from which surrounding spaces, tabs, and hash signs should be stripped.
29
+
30
+ Returns:
31
+ str: A modified version of the input string `x` with leading and trailing spaces, tabs,
32
+ and hash signs removed.
33
+
34
+ Example:
35
+ >>> _strip(" # Hello, world! # ")
36
+ "Hello, world!"
37
+
38
+ Note:
39
+ This function assumes the existence of `STRIP_CANDIDATE_PAT`, which is a regular expression
40
+ pattern matching spaces, tabs, and hash signs. Ensure this pattern is defined and imported
41
+ in the context where this function is used.
42
+
43
+ """
44
+ return STRIP_CANDIDATE_PAT.sub("", x)
45
+
46
+
47
+ def _replace_ital_bold(s):
48
+ """
49
+ Replace italic and bold formatting markers in the input string `s`.
50
+
51
+ This function iterates through occurrences of italic and bold patterns (represented by
52
+ `ITAL_PAT` and `BOLD_PAT` respectively) within the string `s`. It removes leading and trailing
53
+ underscore (`_`) and asterisk (`*`) characters from these patterns. This is useful when
54
+ processing Markdown text that includes inline formatting for italics and bold.
55
+
56
+ Args:
57
+ s (str): The input string where italic and bold markers need to be processed.
58
+
59
+ Returns:
60
+ str: A modified version of the input string `s` where italic and bold formatting markers
61
+ have been adjusted to remove leading and trailing underscore (`_`) and asterisk (`*`)
62
+ characters.
63
+
64
+ Example:
65
+ >>> _replace_ital_bold("_*italic and bold*_ text")
66
+ "italic and bold text"
67
+
68
+ Note:
69
+ This function assumes the existence of `ITAL_PAT` and `BOLD_PAT` patterns that match the
70
+ respective italic and bold formatting markers. Ensure these patterns are defined and
71
+ imported in the context where this function is used.
72
+ """
73
+ to_repl = "_*"
74
+ for pat in (ITAL_PAT, BOLD_PAT):
75
+ for match in pat.finditer(s):
76
+ found = match.group(0)
77
+ s = s.replace(found, found.strip(to_repl))
78
+ return s
79
+
80
+
81
+ def as_link(x):
82
+ """
83
+ Convert a Markdown header string into a valid relative URL.
84
+
85
+ This function takes a Markdown header string, converts it to lowercase, removes special characters
86
+ except hyphens and underscores, replaces spaces with hyphens, and handles italics and bolds. It ensures
87
+ that resulting URLs are formatted correctly, particularly handling cases where the resulting string
88
+ ends with double hyphens by stripping one hyphen.
89
+
90
+ Args:
91
+ x (str): The input Markdown header string to convert into a URL.
92
+
93
+ Returns:
94
+ str: A valid relative URL converted from the input Markdown header string.
95
+
96
+ Example:
97
+ >>> as_link("Introduction to Markdown Syntax")
98
+ "introduction-to-markdown-syntax"
99
+
100
+ Note:
101
+ This function relies on the `_strip` and `_replace_ital_bold` helper functions to clean and format
102
+ the input string `x`. Ensure these functions are correctly defined and imported in the context
103
+ where this function is used.
104
+
105
+ """
106
+ res = re.sub(
107
+ r"[^-\w\s]",
108
+ "",
109
+ re.sub(r"\s+", "-", _strip(x.lower())),
110
+ flags=re.U,
111
+ )
112
+ res = _replace_ital_bold(res)
113
+
114
+ if res.endswith("--"):
115
+ res = res.strip("-") + "-"
116
+ return res
117
+
118
+
119
+ def escape(x):
120
+ """
121
+ Escape square brackets '[' and ']'.
122
+
123
+ This function takes a string `x` and escapes square brackets '[' and ']' by replacing them with
124
+ their escaped counterparts '\\[' and '\\]'.
125
+
126
+ Args:
127
+ x (str): The input string containing square brackets '[' and/or ']'.
128
+
129
+ Returns:
130
+ str: The input string `x` with square brackets '[' and ']' escaped as '\\[' and '\\]'.
131
+
132
+ Example:
133
+ >>> escape("Example [String]")
134
+ "Example \\[String\\]"
135
+ """
136
+ return x.replace("[", "\\[").replace("]", "\\]")
137
+
138
+
139
+ def get_links(md_string):
140
+ """
141
+ Find links in a Markdown string.
142
+
143
+ This function searches through a given Markdown string `md_string` for Markdown-style links
144
+ and yields tuples containing the link text, URL, line number, and column start index.
145
+
146
+ Args:
147
+ md_string (str): The Markdown string to search for links.
148
+
149
+ Yields:
150
+ tuple: A tuple containing four elements:
151
+ - link_text (str): The text of the Markdown link.
152
+ - link_url (str): The URL or target of the Markdown link.
153
+ - line_number (int): The line number in the Markdown string where the link was found (1-indexed).
154
+ - col_start (int): The column index in the line where the URL starts (0-indexed).
155
+ Example:
156
+ >>> md_string = "Here is a [sample link](https://example.com) in Markdown."
157
+ >>> list(get_links(md_string))
158
+ [('sample link', 'https://example.com', 1, 8)]
159
+
160
+ Notes:
161
+ - Assumes the Markdown links follow the format `[link_text](link_url)`.
162
+ """
163
+ lines = md_string.split("\n")
164
+ line_number = 0
165
+ for line in lines:
166
+ line_number += 1
167
+ for match in re.finditer(MD_LINK_PAT, line):
168
+ link_text = match.group(1)
169
+ link_url = match.group(2)
170
+ col_start = match.start(2)
171
+ yield link_text, link_url, line_number, col_start
172
+
173
+
174
+ def toc(md_string):
175
+ """
176
+ Generate a table of contents for a Markdown string.
177
+
178
+ This function generates a table of contents (TOC) based on the headers found in the Markdown
179
+ string `md_string`. It iterates through the headers, converts each header to a link, and
180
+ formats it in Markdown syntax suitable for a TOC.
181
+
182
+ Args:
183
+ md_string (str): The Markdown string for which the TOC is to be generated.
184
+
185
+ Returns:
186
+ str: A Markdown-formatted string representing the table of contents.
187
+
188
+ Example:
189
+ >>> md_string = "# Header 1\n## Subheader 1.1\n### Subsubheader\n# Header 2"
190
+ >>> print(toc(md_string))
191
+ * [Header 1](#header-1)
192
+ * [Subheader 1.1](#subheader-11)
193
+ * [Subsubheader](#subsubheader)
194
+ * [Header 2](#header-2)
195
+
196
+ Notes:
197
+ - Assumes headers are marked with Markdown syntax (#, ##, ###, etc.).
198
+ - Uses `as_link`, `escape`, and `_strip` functions for link conversion and formatting.
199
+ """
200
+ toc = []
201
+ n_seen = collections.defaultdict(int)
202
+
203
+ for level, header in headers(md_string):
204
+ link = as_link(header)
205
+ n = n_seen[link]
206
+ if n > 0:
207
+ n_seen[link] += 1
208
+ link += "-" + str(n)
209
+ else:
210
+ n_seen[link] += 1
211
+
212
+ toc.append(
213
+ "{spaces}* [{header}](#{link})".format(
214
+ spaces=" " * (level - 1),
215
+ header=escape(_strip(header)),
216
+ link=link,
217
+ )
218
+ )
219
+ return "\n".join(toc)
220
+
221
+
222
+ def headers(md_string):
223
+ """
224
+ Generate Markdown headers from a given Markdown string.
225
+
226
+ This function iterates through each line of the Markdown string `md_string`,
227
+ matches lines that start with Markdown header patterns defined in `HEADER_PAT`,
228
+ and yields tuples of header levels and header titles.
229
+
230
+ Args:
231
+ md_string (str): The Markdown string to extract headers from.
232
+
233
+ Yields:
234
+ tuple: A tuple containing the header level (int) and header title (str).
235
+
236
+ Example:
237
+ >>> md_string = "# Header 1\n## Subheader 1.1\n### Subsubheader\n# Header 2"
238
+ >>> list(headers(md_string))
239
+ [(1, 'Header 1'), (2, 'Subheader 1.1'), (3, 'Subsubheader'), (1, 'Header 2')]
240
+
241
+ Notes:
242
+ - Assumes headers are marked with Markdown syntax (#, ##, ###, etc.).
243
+ - Uses `HEADER_PAT` pattern for matching Markdown headers.
244
+ """
245
+ for line in md_string.split("\n"):
246
+ header = HEADER_PAT.match(line)
247
+ if header:
248
+ level = len(header.group(1))
249
+ header = header.group(2)
250
+ yield level, header
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.1
2
+ Name: doctoc
3
+ Version: 0.0.1
4
+ Summary: Generate table of contents for Markdown files
5
+ Home-page: https://github.com/ktechhub/doctoc
6
+ Author: Ktechhub
7
+ Author-email: mm@ktechhub.com
8
+ License: MIT
9
+ Keywords: markdown table of contents
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.7
18
+ Classifier: Programming Language :: Python :: 3.6
19
+ Requires-Python: >=3.6
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: click
23
+ Requires-Dist: requests
24
+
25
+
26
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
27
+
28
+ **Table of Contents** *generated with [DocToc](https://github.com/ktechhub/doctoc)*
29
+
30
+ <!---toc start-->
31
+
32
+ - [DocToc](#doctoc)
33
+ - [Prerequisites](#prerequisites)
34
+ - [Installation](#installation)
35
+ - [Usage](#usage)
36
+ - [Options:](#options)
37
+ - [Features](#features)
38
+ - [GitHub](#github)
39
+ - [License](#license)
40
+ - [Contribution](#contribution)
41
+
42
+ <!---toc end-->
43
+
44
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
45
+
46
+ # DocToc
47
+ DocToc is a command-line tool built with Python that automatically generates and updates table of contents (TOC) for Markdown files. It scans through your Markdown file, identifies headers, and creates a TOC with clickable links.
48
+
49
+ ## Prerequisites
50
+ Before installing DocToc, ensure you have the following:
51
+ - Python 3.6+
52
+ - pip (Python package installer)
53
+
54
+ ## Installation
55
+ You can install DocToc using pip:
56
+
57
+ ```sh
58
+ pip install doctoc
59
+ ```
60
+ Alternatively, you can install it from the source on GitHub:
61
+
62
+ ```sh
63
+ git clone https://github.com/ktechhub/doctoc.git
64
+ cd doctoc
65
+ python setup.py install
66
+ ```
67
+
68
+ ## Usage
69
+ Generate a table of contents for a Markdown file:
70
+
71
+ ```sh
72
+ doctoc --help
73
+ Usage: doctoc [OPTIONS] MARKDOWN_FILE
74
+
75
+ Generate or update a table of contents for Markdown files and optionally
76
+ check hyperlinks.
77
+
78
+ Args:
79
+ markdown_file (str): Path to the Markdown file to process.
80
+ outfile (str, optional): Output file path. If specified, writes the modified content to this file instead of overwriting the original.
81
+ check_links (bool): Flag to enable checking the validity of hyperlinks found in the Markdown file.
82
+
83
+ Options:
84
+ -o, --outfile TEXT Specify an output file instead of overwriting.
85
+ -cl, --check-links Check validity of hyperlinks.
86
+ --help Show this message and exit.
87
+ ```
88
+
89
+ ### Options:
90
+
91
+ - `--outfile`: Specify an output file instead of overwriting.
92
+ - `--check-links`: Check the validity of hyperlinks within the Markdown file.
93
+
94
+ Example with options:
95
+ ```sh
96
+ doctoc README.md --check-links
97
+ ```
98
+ Output
99
+ ```sh
100
+ Success: wrote TOC to README.md
101
+ Checking hyperlinks...
102
+ VALID: [DocToc](https://github.com/ktechhub/doctoc)
103
+ VALID: [DocToc](#doctoc)
104
+ VALID: [Prerequisites](#prerequisites)
105
+ VALID: [Installation](#installation)
106
+ VALID: [Usage](#usage)
107
+ VALID: [Options:](#options)
108
+ VALID: [Features](#features)
109
+ VALID: [GitHub](#github)
110
+ VALID: [License](#license)
111
+ VALID: [GitHub repository](https://github.com/ktechhub/doctoc)
112
+ ```
113
+
114
+ ```sh
115
+ doctoc README.md --outfile README_with_toc.md
116
+ ```
117
+ Output
118
+ ```sh
119
+ Success: wrote TOC to README_with_toc.md
120
+ ```
121
+ ```sh
122
+ doctoc README.md --outfile README_with_toc.md --check-links
123
+ ```
124
+
125
+ ## Features
126
+ - Automatically generates a TOC based on Markdown headers.
127
+ - Supports customization with options to specify output file and check link validity.
128
+ - Simple and easy to use with a command-line interface.
129
+
130
+ ## GitHub
131
+ For more details, visit the [GitHub repository](https://github.com/ktechhub/doctoc).
132
+
133
+ ## License
134
+ This project is licensed under the MIT License - see the LICENSE file for details.
135
+
136
+ ### Contribution
137
+ If you want to contribute, kindly see this **[contribution](https://github.com/ktechhub/doctoc/tree/main/contribution.md)**
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ setup.py
4
+ doctoc/__init__.py
5
+ doctoc/cli.py
6
+ doctoc/core.py
7
+ doctoc/markdown.py
8
+ doctoc.egg-info/PKG-INFO
9
+ doctoc.egg-info/SOURCES.txt
10
+ doctoc.egg-info/dependency_links.txt
11
+ doctoc.egg-info/entry_points.txt
12
+ doctoc.egg-info/requires.txt
13
+ doctoc.egg-info/top_level.txt
14
+ tests/test_doctoc.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ doctoc = doctoc.cli:main
@@ -0,0 +1,2 @@
1
+ click
2
+ requests
@@ -0,0 +1 @@
1
+ doctoc
doctoc-0.0.1/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
doctoc-0.0.1/setup.py ADDED
@@ -0,0 +1,57 @@
1
+ """
2
+ A setuptools based setup module.
3
+ See:
4
+ https://www.ktechhub.com/tutorials/how-to-package-a-python-code-and-upload-to-pypi
5
+ https://packaging.python.org/en/latest/distributing.html
6
+ https://github.com/pypa/sampleproject
7
+ """
8
+
9
+ import io
10
+ from os import path, getenv
11
+ from setuptools import setup, find_packages
12
+
13
+ VERSION = getenv("VERSION", "0.0.1") # package version
14
+ if "v" in VERSION:
15
+ VERSION = VERSION[1:]
16
+
17
+ here = path.abspath(path.dirname(__file__))
18
+ # Get the long description from the README file
19
+ with io.open(path.join(here, "README.md"), encoding="utf-8") as f:
20
+ long_description = "\n" + f.read()
21
+
22
+ REQUIRES_PYTHON = ">=3.6"
23
+
24
+ setup(
25
+ name="doctoc",
26
+ version=VERSION,
27
+ packages=find_packages(exclude=["tests", "docs", ".github"]),
28
+ install_requires=["click", "requests"],
29
+ entry_points={
30
+ "console_scripts": [
31
+ "doctoc = doctoc.cli:main",
32
+ ],
33
+ },
34
+ test_suite="tests",
35
+ python_requires=REQUIRES_PYTHON,
36
+ author="Ktechhub",
37
+ author_email="mm@ktechhub.com",
38
+ description="Generate table of contents for Markdown files",
39
+ long_description=long_description,
40
+ long_description_content_type="text/markdown",
41
+ url="https://github.com/ktechhub/doctoc",
42
+ license="MIT",
43
+ classifiers=[
44
+ "License :: OSI Approved :: MIT License",
45
+ "Intended Audience :: Developers",
46
+ "Programming Language :: Python :: 3.12",
47
+ "Programming Language :: Python :: 3.11",
48
+ "Programming Language :: Python :: 3.10",
49
+ "Programming Language :: Python :: 3.9",
50
+ "Programming Language :: Python :: 3.8",
51
+ "Programming Language :: Python :: 3.7",
52
+ "Programming Language :: Python :: 3.6",
53
+ ],
54
+ keywords="markdown table of contents",
55
+ setup_requires=["wheel"],
56
+ include_package_data=True,
57
+ )
@@ -0,0 +1,40 @@
1
+ import pytest
2
+ from doctoc.markdown import toc, headers, get_links, as_link, escape
3
+ from doctoc.core import modify_and_write
4
+
5
+
6
+ @pytest.fixture
7
+ def sample_markdown():
8
+ return """
9
+ # Title 1
10
+
11
+ ## Subtitle 1.1
12
+
13
+ ### Sub-subtitle 1.1.1
14
+ """
15
+
16
+
17
+ def test_modify_and_write(tmp_path):
18
+ markdown_file = tmp_path / "test.md"
19
+ markdown_file.write_text("# Title 1\n\n## Subtitle 1.1\n")
20
+
21
+ modify_and_write(markdown_file)
22
+ assert markdown_file.read_text().startswith(
23
+ "<!-- START doctoc generated TOC please keep comment here to allow auto update -->"
24
+ )
25
+
26
+
27
+ def test_get_links():
28
+ md_string = "[Link](#header)"
29
+ links = list(get_links(md_string))
30
+ assert len(links) == 1
31
+ assert links[0][0] == "Link"
32
+ assert links[0][1] == "#header"
33
+
34
+
35
+ def test_as_link():
36
+ assert as_link("Header with spaces") == "header-with-spaces"
37
+
38
+
39
+ if __name__ == "__main__":
40
+ pytest.main()