txt2ebook 0.1.157__tar.gz → 0.1.159__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.
- {txt2ebook-0.1.157/src/txt2ebook.egg-info → txt2ebook-0.1.159}/PKG-INFO +1 -1
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/pyproject.toml +15 -1
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/formats/base.py +107 -0
- txt2ebook-0.1.159/src/txt2ebook/formats/gmi.py +176 -0
- txt2ebook-0.1.159/src/txt2ebook/formats/md.py +168 -0
- txt2ebook-0.1.159/src/txt2ebook/formats/txt.py +219 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/formats/typ.py +48 -3
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/epub.py +12 -8
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/massage.py +29 -23
- {txt2ebook-0.1.157 → txt2ebook-0.1.159/src/txt2ebook.egg-info}/PKG-INFO +1 -1
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook.egg-info/SOURCES.txt +1 -13
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/tests/test_parser.py +5 -3
- txt2ebook-0.1.157/src/txt2ebook/formats/gmi.py +0 -177
- txt2ebook-0.1.157/src/txt2ebook/formats/md.py +0 -169
- txt2ebook-0.1.157/src/txt2ebook/formats/txt.py +0 -199
- txt2ebook-0.1.157/tests/test_header_number_flag.py +0 -46
- txt2ebook-0.1.157/tests/test_input_file_arg.py +0 -28
- txt2ebook-0.1.157/tests/test_language_option.py +0 -33
- txt2ebook-0.1.157/tests/test_output_file_arg.py +0 -34
- txt2ebook-0.1.157/tests/test_overwrite_flag.py +0 -23
- txt2ebook-0.1.157/tests/test_purge_flag.py +0 -49
- txt2ebook-0.1.157/tests/test_quiet_flag.py +0 -24
- txt2ebook-0.1.157/tests/test_sort_volume_and_chapter_flag.py +0 -44
- txt2ebook-0.1.157/tests/test_split_volume_and_chapter_flag.py +0 -51
- txt2ebook-0.1.157/tests/test_test_parsing_flag.py +0 -28
- txt2ebook-0.1.157/tests/test_verbose_flag.py +0 -92
- txt2ebook-0.1.157/tests/test_volume_page_flag.py +0 -23
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/LICENSE.md +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/README.md +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/setup.cfg +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/__init__.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/__main__.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/cli.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/exceptions.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/formats/__init__.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/formats/epub.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/formats/pdf.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/formats/templates/__init__.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/formats/templates/epub/__init__.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/formats/tex.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/helpers/__init__.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/languages/__init__.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/languages/en.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/languages/zh_cn.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/languages/zh_tw.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/models/__init__.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/models/book.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/models/chapter.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/models/volume.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/parser.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/__init__.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/env.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/gmi.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/md.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/parse.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/pdf.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/tex.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/subcommands/typ.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/tokenizer.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook/zh_utils.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook.egg-info/dependency_links.txt +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook.egg-info/entry_points.txt +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook.egg-info/requires.txt +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/src/txt2ebook.egg-info/top_level.txt +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/tests/test_tokenizer.py +0 -0
- {txt2ebook-0.1.157 → txt2ebook-0.1.159}/tests/test_txt2ebook.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "txt2ebook"
|
3
|
-
version = "0.1.
|
3
|
+
version = "0.1.159"
|
4
4
|
description = "CLI tool to convert txt file to ebook format"
|
5
5
|
authors = [{ name = "Kian-Meng Ang", email = "kianmeng@cpan.org" }]
|
6
6
|
requires-python = "~=3.9"
|
@@ -89,6 +89,20 @@ build-backend = "setuptools.build_meta"
|
|
89
89
|
# verify through: uv run ruff check --show-settings
|
90
90
|
[tool.ruff]
|
91
91
|
line-length = 79
|
92
|
+
target-version = "py313"
|
93
|
+
exclude = [
|
94
|
+
"docs/",
|
95
|
+
"docs/source/conf.py",
|
96
|
+
]
|
97
|
+
|
98
|
+
[tool.ruff.lint]
|
99
|
+
extend-select = [
|
100
|
+
"E",
|
101
|
+
"W",
|
102
|
+
]
|
103
|
+
|
104
|
+
[tool.ruff.lint.pydocstyle]
|
105
|
+
convention = "google"
|
92
106
|
|
93
107
|
[tool.setuptools.packages.find]
|
94
108
|
where = ["src"]
|
@@ -134,6 +134,113 @@ class BaseWriter(ABC):
|
|
134
134
|
file.parent, self.config.output_folder, lower_underscore(file.stem)
|
135
135
|
).with_suffix(extension)
|
136
136
|
|
137
|
+
def _get_toc_content_for_split(self) -> str:
|
138
|
+
raise NotImplementedError
|
139
|
+
|
140
|
+
def _get_volume_chapter_content_for_split(
|
141
|
+
self, volume: Volume, chapter: Chapter
|
142
|
+
) -> str:
|
143
|
+
raise NotImplementedError
|
144
|
+
|
145
|
+
def _get_chapter_content_for_split(self, chapter: Chapter) -> str:
|
146
|
+
raise NotImplementedError
|
147
|
+
|
148
|
+
def _get_file_extension_for_split(self) -> str:
|
149
|
+
raise NotImplementedError
|
150
|
+
|
151
|
+
def _export_multiple_files(self) -> None:
|
152
|
+
logger.info("Split multiple files")
|
153
|
+
|
154
|
+
extension = self._get_file_extension_for_split()
|
155
|
+
txt_filename = Path(self.config.input_file.name)
|
156
|
+
|
157
|
+
export_filename = self._get_metadata_filename_for_split(
|
158
|
+
txt_filename, extension
|
159
|
+
)
|
160
|
+
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
161
|
+
logger.info("Creating %s", export_filename)
|
162
|
+
with open(export_filename, "w", encoding="utf8") as file:
|
163
|
+
file.write(self._to_metadata_txt())
|
164
|
+
|
165
|
+
sc_seq = 1
|
166
|
+
if self.config.with_toc:
|
167
|
+
export_filename = self._get_toc_filename_for_split(
|
168
|
+
txt_filename, extension
|
169
|
+
)
|
170
|
+
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
171
|
+
logger.info("Creating %s", export_filename)
|
172
|
+
with open(export_filename, "w", encoding="utf8") as file:
|
173
|
+
file.write(self._get_toc_content_for_split())
|
174
|
+
|
175
|
+
sc_seq = 2
|
176
|
+
|
177
|
+
for section in self.book.toc:
|
178
|
+
section_seq = str(sc_seq).rjust(2, "0")
|
179
|
+
|
180
|
+
ct_seq = 0
|
181
|
+
if isinstance(section, Volume):
|
182
|
+
for chapter in section.chapters:
|
183
|
+
chapter_seq = str(ct_seq).rjust(2, "0")
|
184
|
+
export_filename = (
|
185
|
+
self._get_volume_chapter_filename_for_split(
|
186
|
+
txt_filename,
|
187
|
+
section_seq,
|
188
|
+
chapter_seq,
|
189
|
+
section,
|
190
|
+
chapter,
|
191
|
+
extension,
|
192
|
+
)
|
193
|
+
)
|
194
|
+
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
195
|
+
logger.info("Creating %s", export_filename)
|
196
|
+
with open(export_filename, "w", encoding="utf8") as file:
|
197
|
+
file.write(
|
198
|
+
self._get_volume_chapter_content_for_split(
|
199
|
+
section, chapter
|
200
|
+
)
|
201
|
+
)
|
202
|
+
ct_seq = ct_seq + 1
|
203
|
+
if isinstance(section, Chapter):
|
204
|
+
export_filename = self._get_chapter_filename_for_split(
|
205
|
+
txt_filename, section_seq, section, extension
|
206
|
+
)
|
207
|
+
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
208
|
+
logger.info("Creating %s", export_filename)
|
209
|
+
with open(export_filename, "w", encoding="utf8") as file:
|
210
|
+
file.write(self._get_chapter_content_for_split(section))
|
211
|
+
|
212
|
+
sc_seq = sc_seq + 1
|
213
|
+
|
214
|
+
def _get_metadata_filename_for_split(
|
215
|
+
self, txt_filename: Path, extension: str
|
216
|
+
) -> Path:
|
217
|
+
raise NotImplementedError
|
218
|
+
|
219
|
+
def _get_toc_filename_for_split(
|
220
|
+
self, txt_filename: Path, extension: str
|
221
|
+
) -> Path:
|
222
|
+
raise NotImplementedError
|
223
|
+
|
224
|
+
def _get_volume_chapter_filename_for_split(
|
225
|
+
self,
|
226
|
+
txt_filename: Path,
|
227
|
+
section_seq: str,
|
228
|
+
chapter_seq: str,
|
229
|
+
volume: Volume,
|
230
|
+
chapter: Chapter,
|
231
|
+
extension: str,
|
232
|
+
) -> Path:
|
233
|
+
raise NotImplementedError
|
234
|
+
|
235
|
+
def _get_chapter_filename_for_split(
|
236
|
+
self,
|
237
|
+
txt_filename: Path,
|
238
|
+
section_seq: str,
|
239
|
+
chapter: Chapter,
|
240
|
+
extension: str,
|
241
|
+
) -> Path:
|
242
|
+
raise NotImplementedError
|
243
|
+
|
137
244
|
def _to_metadata_txt(self) -> str:
|
138
245
|
metadata = [
|
139
246
|
self._("title:") + self.book.title,
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# Copyright (c) 2021,2022,2023,2024,2025 Kian-Meng Ang
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Affero General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Affero General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Affero General Public License
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
"""Convert and back source text file into text as well."""
|
17
|
+
|
18
|
+
import logging
|
19
|
+
from pathlib import Path
|
20
|
+
from typing import List
|
21
|
+
|
22
|
+
from txt2ebook.formats.base import BaseWriter
|
23
|
+
from txt2ebook.helpers import lower_underscore
|
24
|
+
from txt2ebook.models import Chapter, Volume
|
25
|
+
|
26
|
+
logger = logging.getLogger(__name__)
|
27
|
+
|
28
|
+
|
29
|
+
class GmiWriter(BaseWriter):
|
30
|
+
"""Module for writing ebook in GemText (gmi) format."""
|
31
|
+
|
32
|
+
def write(self) -> None:
|
33
|
+
"""Generate GemText files."""
|
34
|
+
if self.config.split_volume_and_chapter:
|
35
|
+
self._export_multiple_files()
|
36
|
+
else:
|
37
|
+
output_filename = self._output_filename(".gmi")
|
38
|
+
output_filename.parent.mkdir(parents=True, exist_ok=True)
|
39
|
+
|
40
|
+
with open(output_filename, "w", encoding="utf8") as file:
|
41
|
+
logger.info(
|
42
|
+
"Generate Gemini file: %s", output_filename.resolve()
|
43
|
+
)
|
44
|
+
file.write(self._to_gmi())
|
45
|
+
|
46
|
+
if self.config.open:
|
47
|
+
self._open_file(output_filename)
|
48
|
+
|
49
|
+
def _get_toc_content_for_split(self) -> str:
|
50
|
+
return self._to_toc("*", "# ")
|
51
|
+
|
52
|
+
def _get_volume_chapter_content_for_split(
|
53
|
+
self, volume: Volume, chapter: Chapter
|
54
|
+
) -> str:
|
55
|
+
return self._to_volume_chapter_txt(volume, chapter)
|
56
|
+
|
57
|
+
def _get_chapter_content_for_split(self, chapter: Chapter) -> str:
|
58
|
+
return self._to_chapter_txt(chapter)
|
59
|
+
|
60
|
+
def _get_file_extension_for_split(self) -> str:
|
61
|
+
return ".gmi"
|
62
|
+
|
63
|
+
def _get_metadata_filename_for_split(
|
64
|
+
self, txt_filename: Path, extension: str
|
65
|
+
) -> Path:
|
66
|
+
return Path(
|
67
|
+
txt_filename.resolve().parent.joinpath(
|
68
|
+
self.config.output_folder,
|
69
|
+
lower_underscore(
|
70
|
+
f"00_{txt_filename.stem}_" + self._("metadata") + extension
|
71
|
+
),
|
72
|
+
)
|
73
|
+
)
|
74
|
+
|
75
|
+
def _get_toc_filename_for_split(
|
76
|
+
self, txt_filename: Path, extension: str
|
77
|
+
) -> Path:
|
78
|
+
return Path(
|
79
|
+
txt_filename.resolve().parent.joinpath(
|
80
|
+
self.config.output_folder,
|
81
|
+
lower_underscore(
|
82
|
+
f"01_{txt_filename.stem}_" + self._("toc") + extension
|
83
|
+
),
|
84
|
+
)
|
85
|
+
)
|
86
|
+
|
87
|
+
def _get_volume_chapter_filename_for_split(
|
88
|
+
self,
|
89
|
+
txt_filename: Path,
|
90
|
+
section_seq: str,
|
91
|
+
chapter_seq: str,
|
92
|
+
volume: Volume,
|
93
|
+
chapter: Chapter,
|
94
|
+
extension: str,
|
95
|
+
) -> Path:
|
96
|
+
return Path(
|
97
|
+
txt_filename.resolve().parent.joinpath(
|
98
|
+
self.config.output_folder,
|
99
|
+
lower_underscore(
|
100
|
+
(
|
101
|
+
f"{section_seq}"
|
102
|
+
f"_{chapter_seq}"
|
103
|
+
f"_{txt_filename.stem}"
|
104
|
+
f"_{volume.title}"
|
105
|
+
f"_{chapter.title}"
|
106
|
+
f"{extension}"
|
107
|
+
)
|
108
|
+
),
|
109
|
+
)
|
110
|
+
)
|
111
|
+
|
112
|
+
def _get_chapter_filename_for_split(
|
113
|
+
self,
|
114
|
+
txt_filename: Path,
|
115
|
+
section_seq: str,
|
116
|
+
chapter: Chapter,
|
117
|
+
extension: str,
|
118
|
+
) -> Path:
|
119
|
+
return Path(
|
120
|
+
txt_filename.resolve().parent.joinpath(
|
121
|
+
self.config.output_folder,
|
122
|
+
lower_underscore(
|
123
|
+
(
|
124
|
+
f"{section_seq}_{txt_filename.stem}_{chapter.title}{extension}"
|
125
|
+
)
|
126
|
+
),
|
127
|
+
)
|
128
|
+
)
|
129
|
+
|
130
|
+
def _to_gmi(self) -> str:
|
131
|
+
toc = self._to_toc("*", "# ") if self.config.with_toc else ""
|
132
|
+
return self._to_metadata_txt() + toc + self._to_body_txt()
|
133
|
+
|
134
|
+
def _to_body_txt(self) -> str:
|
135
|
+
content = []
|
136
|
+
for section in self.book.toc:
|
137
|
+
if isinstance(section, Volume):
|
138
|
+
content.append(self._to_volume_txt(section))
|
139
|
+
if isinstance(section, Chapter):
|
140
|
+
content.append(self._to_chapter_txt(section))
|
141
|
+
|
142
|
+
return f"{self.config.paragraph_separator}".join(content)
|
143
|
+
|
144
|
+
def _to_volume_txt(self, volume) -> str:
|
145
|
+
return (
|
146
|
+
f"# {volume.title}"
|
147
|
+
+ self.config.paragraph_separator
|
148
|
+
+ self.config.paragraph_separator.join(
|
149
|
+
[
|
150
|
+
self._to_chapter_txt(chapter, True)
|
151
|
+
for chapter in volume.chapters
|
152
|
+
]
|
153
|
+
)
|
154
|
+
)
|
155
|
+
|
156
|
+
def _to_chapter_txt(self, chapter, part_of_volume=False) -> str:
|
157
|
+
header = "##" if part_of_volume else "#"
|
158
|
+
return (
|
159
|
+
f"{header} {chapter.title}"
|
160
|
+
+ self.config.paragraph_separator
|
161
|
+
+ self.config.paragraph_separator.join(
|
162
|
+
self._remove_newline(chapter.paragraphs)
|
163
|
+
)
|
164
|
+
)
|
165
|
+
|
166
|
+
def _to_volume_chapter_txt(self, volume, chapter) -> str:
|
167
|
+
return (
|
168
|
+
f"# {volume.title} {chapter.title}"
|
169
|
+
+ self.config.paragraph_separator
|
170
|
+
+ self.config.paragraph_separator.join(
|
171
|
+
self._remove_newline(chapter.paragraphs)
|
172
|
+
)
|
173
|
+
)
|
174
|
+
|
175
|
+
def _remove_newline(self, paragraphs) -> List:
|
176
|
+
return list(map(lambda p: p.replace("\n", ""), paragraphs))
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# Copyright (c) 2021,2022,2023,2024,2025 Kian-Meng Ang
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU Affero General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU Affero General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU Affero General Public License
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
"""Convert and back source text file into text as well."""
|
17
|
+
|
18
|
+
import logging
|
19
|
+
from pathlib import Path
|
20
|
+
|
21
|
+
from txt2ebook.formats.base import BaseWriter
|
22
|
+
from txt2ebook.helpers import lower_underscore
|
23
|
+
from txt2ebook.models import Chapter, Volume
|
24
|
+
|
25
|
+
logger = logging.getLogger(__name__)
|
26
|
+
|
27
|
+
|
28
|
+
class MdWriter(BaseWriter):
|
29
|
+
"""Module for writing ebook in Markdown (md) format."""
|
30
|
+
|
31
|
+
def write(self) -> None:
|
32
|
+
"""Generate Markdown files."""
|
33
|
+
if self.config.split_volume_and_chapter:
|
34
|
+
self._export_multiple_files()
|
35
|
+
else:
|
36
|
+
output_filename = self._output_filename(".md")
|
37
|
+
output_filename.parent.mkdir(parents=True, exist_ok=True)
|
38
|
+
|
39
|
+
with open(output_filename, "w", encoding="utf8") as file:
|
40
|
+
logger.info(
|
41
|
+
"Generate Markdown file: %s", output_filename.resolve()
|
42
|
+
)
|
43
|
+
file.write(self._to_md())
|
44
|
+
|
45
|
+
if self.config.open:
|
46
|
+
self._open_file(output_filename)
|
47
|
+
|
48
|
+
def _get_toc_content_for_split(self) -> str:
|
49
|
+
return self._to_toc("-", "# ")
|
50
|
+
|
51
|
+
def _get_volume_chapter_content_for_split(
|
52
|
+
self, volume: Volume, chapter: Chapter
|
53
|
+
) -> str:
|
54
|
+
return self._to_volume_chapter_txt(volume, chapter)
|
55
|
+
|
56
|
+
def _get_chapter_content_for_split(self, chapter: Chapter) -> str:
|
57
|
+
return self._to_chapter_txt(chapter)
|
58
|
+
|
59
|
+
def _get_file_extension_for_split(self) -> str:
|
60
|
+
return ".md"
|
61
|
+
|
62
|
+
def _get_metadata_filename_for_split(
|
63
|
+
self, txt_filename: Path, extension: str
|
64
|
+
) -> Path:
|
65
|
+
return Path(
|
66
|
+
txt_filename.resolve().parent.joinpath(
|
67
|
+
self.config.output_folder,
|
68
|
+
lower_underscore(
|
69
|
+
f"00_{txt_filename.stem}_" + self._("metadata") + extension
|
70
|
+
),
|
71
|
+
)
|
72
|
+
)
|
73
|
+
|
74
|
+
def _get_toc_filename_for_split(
|
75
|
+
self, txt_filename: Path, extension: str
|
76
|
+
) -> Path:
|
77
|
+
return Path(
|
78
|
+
txt_filename.resolve().parent.joinpath(
|
79
|
+
self.config.output_folder,
|
80
|
+
lower_underscore(
|
81
|
+
f"01_{txt_filename.stem}_" + self._("toc") + extension
|
82
|
+
),
|
83
|
+
)
|
84
|
+
)
|
85
|
+
|
86
|
+
def _get_volume_chapter_filename_for_split(
|
87
|
+
self,
|
88
|
+
txt_filename: Path,
|
89
|
+
section_seq: str,
|
90
|
+
chapter_seq: str,
|
91
|
+
volume: Volume,
|
92
|
+
chapter: Chapter,
|
93
|
+
extension: str,
|
94
|
+
) -> Path:
|
95
|
+
return Path(
|
96
|
+
txt_filename.resolve().parent.joinpath(
|
97
|
+
self.config.output_folder,
|
98
|
+
lower_underscore(
|
99
|
+
(
|
100
|
+
f"{section_seq}"
|
101
|
+
f"_{chapter_seq}"
|
102
|
+
f"_{txt_filename.stem}"
|
103
|
+
f"_{volume.title}"
|
104
|
+
f"_{chapter.title}"
|
105
|
+
f"{extension}"
|
106
|
+
)
|
107
|
+
),
|
108
|
+
)
|
109
|
+
)
|
110
|
+
|
111
|
+
def _get_chapter_filename_for_split(
|
112
|
+
self,
|
113
|
+
txt_filename: Path,
|
114
|
+
section_seq: str,
|
115
|
+
chapter: Chapter,
|
116
|
+
extension: str,
|
117
|
+
) -> Path:
|
118
|
+
return Path(
|
119
|
+
txt_filename.resolve().parent.joinpath(
|
120
|
+
self.config.output_folder,
|
121
|
+
lower_underscore(
|
122
|
+
(
|
123
|
+
f"{section_seq}_{txt_filename.stem}_{chapter.title}{extension}"
|
124
|
+
)
|
125
|
+
),
|
126
|
+
)
|
127
|
+
)
|
128
|
+
|
129
|
+
def _to_md(self) -> str:
|
130
|
+
toc = self._to_toc("-", "# ") if self.config.with_toc else ""
|
131
|
+
return self._to_metadata_txt() + toc + self._to_body_txt()
|
132
|
+
|
133
|
+
def _to_body_txt(self) -> str:
|
134
|
+
content = []
|
135
|
+
for section in self.book.toc:
|
136
|
+
if isinstance(section, Volume):
|
137
|
+
content.append(self._to_volume_txt(section))
|
138
|
+
if isinstance(section, Chapter):
|
139
|
+
content.append(self._to_chapter_txt(section))
|
140
|
+
|
141
|
+
return f"{self.config.paragraph_separator}".join(content)
|
142
|
+
|
143
|
+
def _to_volume_txt(self, volume) -> str:
|
144
|
+
return (
|
145
|
+
f"# {volume.title}"
|
146
|
+
+ self.config.paragraph_separator
|
147
|
+
+ self.config.paragraph_separator.join(
|
148
|
+
[
|
149
|
+
self._to_chapter_txt(chapter, True)
|
150
|
+
for chapter in volume.chapters
|
151
|
+
]
|
152
|
+
)
|
153
|
+
)
|
154
|
+
|
155
|
+
def _to_chapter_txt(self, chapter, part_of_volume=False) -> str:
|
156
|
+
header = "##" if part_of_volume else "#"
|
157
|
+
return (
|
158
|
+
f"{header} {chapter.title}"
|
159
|
+
+ self.config.paragraph_separator
|
160
|
+
+ self.config.paragraph_separator.join(chapter.paragraphs)
|
161
|
+
)
|
162
|
+
|
163
|
+
def _to_volume_chapter_txt(self, volume, chapter) -> str:
|
164
|
+
return (
|
165
|
+
f"# {volume.title} {chapter.title}"
|
166
|
+
+ self.config.paragraph_separator
|
167
|
+
+ self.config.paragraph_separator.join(chapter.paragraphs)
|
168
|
+
)
|