txt2ebook 0.1.157__py3-none-any.whl → 0.1.159__py3-none-any.whl
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/formats/base.py +107 -0
- txt2ebook/formats/gmi.py +79 -80
- txt2ebook/formats/md.py +79 -80
- txt2ebook/formats/txt.py +121 -101
- txt2ebook/formats/typ.py +48 -3
- txt2ebook/subcommands/epub.py +12 -8
- txt2ebook/subcommands/massage.py +29 -23
- {txt2ebook-0.1.157.dist-info → txt2ebook-0.1.159.dist-info}/METADATA +1 -1
- {txt2ebook-0.1.157.dist-info → txt2ebook-0.1.159.dist-info}/RECORD +13 -13
- {txt2ebook-0.1.157.dist-info → txt2ebook-0.1.159.dist-info}/WHEEL +0 -0
- {txt2ebook-0.1.157.dist-info → txt2ebook-0.1.159.dist-info}/entry_points.txt +0 -0
- {txt2ebook-0.1.157.dist-info → txt2ebook-0.1.159.dist-info}/licenses/LICENSE.md +0 -0
- {txt2ebook-0.1.157.dist-info → txt2ebook-0.1.159.dist-info}/top_level.txt +0 -0
txt2ebook/formats/base.py
CHANGED
@@ -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,
|
txt2ebook/formats/gmi.py
CHANGED
@@ -34,99 +34,98 @@ class GmiWriter(BaseWriter):
|
|
34
34
|
if self.config.split_volume_and_chapter:
|
35
35
|
self._export_multiple_files()
|
36
36
|
else:
|
37
|
-
self.
|
37
|
+
output_filename = self._output_filename(".gmi")
|
38
|
+
output_filename.parent.mkdir(parents=True, exist_ok=True)
|
38
39
|
|
39
|
-
|
40
|
-
|
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)
|
41
59
|
|
42
|
-
|
43
|
-
|
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(
|
44
67
|
txt_filename.resolve().parent.joinpath(
|
45
68
|
self.config.output_folder,
|
46
69
|
lower_underscore(
|
47
|
-
f"00_{txt_filename.stem}_" + self._("metadata") +
|
70
|
+
f"00_{txt_filename.stem}_" + self._("metadata") + extension
|
48
71
|
),
|
49
72
|
)
|
50
73
|
)
|
51
|
-
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
52
|
-
logger.info("Creating %s", export_filename)
|
53
|
-
with open(export_filename, "w", encoding="utf8") as file:
|
54
|
-
file.write(self._to_metadata_txt())
|
55
|
-
|
56
|
-
sc_seq = 1
|
57
|
-
if self.config.with_toc:
|
58
|
-
export_filename = Path(
|
59
|
-
txt_filename.resolve().parent.joinpath(
|
60
|
-
self.config.output_folder,
|
61
|
-
lower_underscore(
|
62
|
-
f"01_{txt_filename.stem}_" + self._("toc") + ".gmi"
|
63
|
-
),
|
64
|
-
)
|
65
|
-
)
|
66
|
-
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
67
|
-
logger.info("Creating %s", export_filename)
|
68
|
-
with open(export_filename, "w", encoding="utf8") as file:
|
69
|
-
file.write(self._to_toc("*", "# "))
|
70
74
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
f"{section_seq}"
|
83
|
-
f"_{chapter_seq}"
|
84
|
-
f"_{txt_filename.stem}"
|
85
|
-
f"_{section.title}"
|
86
|
-
f"_{chapter.title}"
|
87
|
-
".gmi"
|
88
|
-
)
|
89
|
-
)
|
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
|
+
)
|
90
86
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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}"
|
95
107
|
)
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
file.write(
|
100
|
-
self._to_volume_chapter_txt(section, chapter)
|
101
|
-
)
|
102
|
-
ct_seq = ct_seq + 1
|
103
|
-
if isinstance(section, Chapter):
|
104
|
-
filename = lower_underscore(
|
105
|
-
(f"{section_seq}_{txt_filename.stem}_{section.title}.gmi")
|
106
|
-
)
|
108
|
+
),
|
109
|
+
)
|
110
|
+
)
|
107
111
|
|
108
|
-
|
109
|
-
|
110
|
-
|
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}"
|
111
125
|
)
|
112
|
-
)
|
113
|
-
|
114
|
-
|
115
|
-
with open(export_filename, "w", encoding="utf8") as file:
|
116
|
-
file.write(self._to_chapter_txt(section))
|
117
|
-
|
118
|
-
sc_seq = sc_seq + 1
|
119
|
-
|
120
|
-
def _new_file(self) -> None:
|
121
|
-
new_filename = self._output_filename(".gmi")
|
122
|
-
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
123
|
-
|
124
|
-
with open(new_filename, "w", encoding="utf8") as file:
|
125
|
-
logger.info("Generate GemText file: %s", new_filename.resolve())
|
126
|
-
file.write(self._to_gmi())
|
127
|
-
|
128
|
-
if self.config.open:
|
129
|
-
self._open_file(new_filename)
|
126
|
+
),
|
127
|
+
)
|
128
|
+
)
|
130
129
|
|
131
130
|
def _to_gmi(self) -> str:
|
132
131
|
toc = self._to_toc("*", "# ") if self.config.with_toc else ""
|
txt2ebook/formats/md.py
CHANGED
@@ -33,99 +33,98 @@ class MdWriter(BaseWriter):
|
|
33
33
|
if self.config.split_volume_and_chapter:
|
34
34
|
self._export_multiple_files()
|
35
35
|
else:
|
36
|
-
self.
|
36
|
+
output_filename = self._output_filename(".md")
|
37
|
+
output_filename.parent.mkdir(parents=True, exist_ok=True)
|
37
38
|
|
38
|
-
|
39
|
-
|
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)
|
40
58
|
|
41
|
-
|
42
|
-
|
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(
|
43
66
|
txt_filename.resolve().parent.joinpath(
|
44
67
|
self.config.output_folder,
|
45
68
|
lower_underscore(
|
46
|
-
f"00_{txt_filename.stem}_" + self._("metadata") +
|
69
|
+
f"00_{txt_filename.stem}_" + self._("metadata") + extension
|
47
70
|
),
|
48
71
|
)
|
49
72
|
)
|
50
|
-
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
51
|
-
logger.info("Creating %s", export_filename)
|
52
|
-
with open(export_filename, "w", encoding="utf8") as file:
|
53
|
-
file.write(self._to_metadata_txt())
|
54
|
-
|
55
|
-
sc_seq = 1
|
56
|
-
if self.config.with_toc:
|
57
|
-
export_filename = Path(
|
58
|
-
txt_filename.resolve().parent.joinpath(
|
59
|
-
self.config.output_folder,
|
60
|
-
lower_underscore(
|
61
|
-
f"01_{txt_filename.stem}_" + self._("toc") + ".md"
|
62
|
-
),
|
63
|
-
)
|
64
|
-
)
|
65
|
-
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
66
|
-
logger.info("Creating %s", export_filename)
|
67
|
-
with open(export_filename, "w", encoding="utf8") as file:
|
68
|
-
file.write(self._to_toc("-", "# "))
|
69
73
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
f"{section_seq}"
|
82
|
-
f"_{chapter_seq}"
|
83
|
-
f"_{txt_filename.stem}"
|
84
|
-
f"_{section.title}"
|
85
|
-
f"_{chapter.title}"
|
86
|
-
".md"
|
87
|
-
)
|
88
|
-
)
|
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
|
+
)
|
89
85
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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}"
|
94
106
|
)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
file.write(
|
99
|
-
self._to_volume_chapter_txt(section, chapter)
|
100
|
-
)
|
101
|
-
ct_seq = ct_seq + 1
|
102
|
-
if isinstance(section, Chapter):
|
103
|
-
filename = lower_underscore(
|
104
|
-
(f"{section_seq}_{txt_filename.stem}_{section.title}.md")
|
105
|
-
)
|
107
|
+
),
|
108
|
+
)
|
109
|
+
)
|
106
110
|
|
107
|
-
|
108
|
-
|
109
|
-
|
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}"
|
110
124
|
)
|
111
|
-
)
|
112
|
-
|
113
|
-
|
114
|
-
with open(export_filename, "w", encoding="utf8") as file:
|
115
|
-
file.write(self._to_chapter_txt(section))
|
116
|
-
|
117
|
-
sc_seq = sc_seq + 1
|
118
|
-
|
119
|
-
def _new_file(self) -> None:
|
120
|
-
new_filename = self._output_filename(".md")
|
121
|
-
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
122
|
-
|
123
|
-
with open(new_filename, "w", encoding="utf8") as file:
|
124
|
-
logger.info("Generate Markdown file: %s", new_filename.resolve())
|
125
|
-
file.write(self._to_md())
|
126
|
-
|
127
|
-
if self.config.open:
|
128
|
-
self._open_file(new_filename)
|
125
|
+
),
|
126
|
+
)
|
127
|
+
)
|
129
128
|
|
130
129
|
def _to_md(self) -> str:
|
131
130
|
toc = self._to_toc("-", "# ") if self.config.with_toc else ""
|
txt2ebook/formats/txt.py
CHANGED
@@ -16,6 +16,7 @@
|
|
16
16
|
"""Convert and backup source text file into text as well."""
|
17
17
|
|
18
18
|
import logging
|
19
|
+
import shutil
|
19
20
|
from datetime import datetime as dt
|
20
21
|
from pathlib import Path
|
21
22
|
|
@@ -40,130 +41,149 @@ class TxtWriter(BaseWriter):
|
|
40
41
|
elif self.config.split_volume_and_chapter:
|
41
42
|
self._export_multiple_files()
|
42
43
|
else:
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
output_filename = self._output_filename(".txt")
|
45
|
+
output_filename.parent.mkdir(parents=True, exist_ok=True)
|
46
|
+
|
47
|
+
if self.config.overwrite and output_filename == Path(
|
48
|
+
self.config.input_file.name
|
49
|
+
):
|
50
|
+
ymd_hms = dt.now().strftime("%Y%m%d_%H%M%S")
|
51
|
+
backup_filename = Path(
|
52
|
+
Path(self.config.input_file.name)
|
53
|
+
.resolve()
|
54
|
+
.parent.joinpath(
|
55
|
+
lower_underscore(
|
56
|
+
Path(self.config.input_file.name).stem
|
57
|
+
+ "_"
|
58
|
+
+ ymd_hms
|
59
|
+
+ ".txt"
|
60
|
+
)
|
61
|
+
)
|
62
|
+
)
|
63
|
+
logger.info(
|
64
|
+
"Backup source text file: %s", backup_filename.resolve()
|
65
|
+
)
|
66
|
+
shutil.copyfile(output_filename, backup_filename)
|
47
67
|
|
48
|
-
|
49
|
-
|
68
|
+
with open(output_filename, "w", encoding="utf8") as file:
|
69
|
+
logger.info("Generate TXT file: %s", output_filename.resolve())
|
70
|
+
file.write(self._to_txt())
|
50
71
|
|
51
|
-
|
52
|
-
|
72
|
+
if self.config.open:
|
73
|
+
self._open_file(output_filename)
|
74
|
+
|
75
|
+
def _get_metadata_filename_for_split(
|
76
|
+
self, txt_filename: Path, extension: str
|
77
|
+
) -> Path:
|
78
|
+
return Path(
|
53
79
|
txt_filename.resolve().parent.joinpath(
|
54
80
|
self.config.output_folder,
|
55
|
-
|
56
|
-
|
81
|
+
f"00_{txt_filename.stem}_" + self._("metadata") + extension,
|
82
|
+
)
|
83
|
+
)
|
84
|
+
|
85
|
+
def _get_toc_filename_for_split(
|
86
|
+
self, txt_filename: Path, extension: str
|
87
|
+
) -> Path:
|
88
|
+
return Path(
|
89
|
+
txt_filename.resolve().parent.joinpath(
|
90
|
+
self.config.output_folder,
|
91
|
+
f"01_{txt_filename.stem}_" + self._("toc") + extension,
|
92
|
+
)
|
93
|
+
)
|
94
|
+
|
95
|
+
def _get_volume_chapter_filename_for_split(
|
96
|
+
self,
|
97
|
+
txt_filename: Path,
|
98
|
+
section_seq: str,
|
99
|
+
chapter_seq: str,
|
100
|
+
volume: Volume,
|
101
|
+
chapter: Chapter,
|
102
|
+
extension: str,
|
103
|
+
) -> Path:
|
104
|
+
return Path(
|
105
|
+
txt_filename.resolve().parent.joinpath(
|
106
|
+
self.config.output_folder,
|
107
|
+
(
|
108
|
+
f"{section_seq}"
|
109
|
+
f"_{chapter_seq}"
|
110
|
+
f"_{txt_filename.stem}"
|
111
|
+
f"_{volume.title}"
|
112
|
+
f"_{chapter.title}"
|
113
|
+
f"{extension}"
|
57
114
|
),
|
58
115
|
)
|
59
116
|
)
|
60
|
-
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
61
|
-
logger.info("Creating %s", export_filename)
|
62
|
-
with open(export_filename, "w", encoding="utf8") as file:
|
63
|
-
file.write(self._to_metadata_txt())
|
64
117
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
118
|
+
def _get_chapter_filename_for_split(
|
119
|
+
self,
|
120
|
+
txt_filename: Path,
|
121
|
+
section_seq: str,
|
122
|
+
chapter: Chapter,
|
123
|
+
extension: str,
|
124
|
+
) -> Path:
|
125
|
+
return Path(
|
126
|
+
txt_filename.resolve().parent.joinpath(
|
127
|
+
self.config.output_folder,
|
128
|
+
(
|
129
|
+
f"{section_seq}_{txt_filename.stem}_{chapter.title}{extension}"
|
130
|
+
),
|
74
131
|
)
|
75
|
-
|
76
|
-
logger.info("Creating %s", export_filename)
|
77
|
-
with open(export_filename, "w", encoding="utf8") as file:
|
78
|
-
file.write(self._to_toc("-"))
|
132
|
+
)
|
79
133
|
|
80
|
-
|
134
|
+
def _export_multiple_files(self) -> None:
|
135
|
+
"""Export multiple files based on volume and chapter."""
|
136
|
+
txt_filename = Path(self.config.input_file.name)
|
137
|
+
txt_filename.parent.joinpath(self.config.output_folder).mkdir(
|
138
|
+
parents=True, exist_ok=True
|
139
|
+
)
|
81
140
|
|
82
|
-
|
83
|
-
|
141
|
+
# 1. Write metadata file
|
142
|
+
metadata_filename = self._get_metadata_filename_for_split(
|
143
|
+
txt_filename, ".txt"
|
144
|
+
)
|
145
|
+
with open(metadata_filename, "w", encoding="utf8") as file:
|
146
|
+
logger.info("Creating %s", metadata_filename.resolve())
|
147
|
+
file.write(self._to_metadata_txt())
|
84
148
|
|
85
|
-
|
149
|
+
# 2. Write volume/chapter files
|
150
|
+
section_seq = 0
|
151
|
+
chapter_seq = 0
|
152
|
+
for section in self.book.toc:
|
86
153
|
if isinstance(section, Volume):
|
154
|
+
section_seq += 1
|
155
|
+
chapter_seq = 0
|
87
156
|
for chapter in section.chapters:
|
88
|
-
chapter_seq
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
".txt"
|
97
|
-
)
|
98
|
-
)
|
99
|
-
|
100
|
-
export_filename = Path(
|
101
|
-
txt_filename.resolve().parent.joinpath(
|
102
|
-
self.config.output_folder, filename
|
103
|
-
)
|
157
|
+
chapter_seq += 1
|
158
|
+
output_filename = self._get_volume_chapter_filename_for_split(
|
159
|
+
txt_filename,
|
160
|
+
str(section_seq).rjust(2, "0"),
|
161
|
+
str(chapter_seq).rjust(2, "0"),
|
162
|
+
section,
|
163
|
+
chapter,
|
164
|
+
".txt",
|
104
165
|
)
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
166
|
+
with open(output_filename, "w", encoding="utf8") as file:
|
167
|
+
logger.info("Creating %s", output_filename.resolve())
|
168
|
+
file.write(self._to_volume_chapter_txt(section, chapter))
|
169
|
+
elif isinstance(section, Chapter):
|
170
|
+
section_seq += 1
|
171
|
+
output_filename = self._get_chapter_filename_for_split(
|
172
|
+
txt_filename,
|
173
|
+
str(section_seq).rjust(2, "0"),
|
174
|
+
section,
|
175
|
+
".txt",
|
115
176
|
)
|
116
|
-
|
117
|
-
|
118
|
-
txt_filename.resolve().parent.joinpath(
|
119
|
-
self.config.output_folder, filename
|
120
|
-
)
|
121
|
-
)
|
122
|
-
export_filename.parent.mkdir(parents=True, exist_ok=True)
|
123
|
-
logger.info("Creating %s", export_filename)
|
124
|
-
with open(export_filename, "w", encoding="utf8") as file:
|
177
|
+
with open(output_filename, "w", encoding="utf8") as file:
|
178
|
+
logger.info("Creating %s", output_filename.resolve())
|
125
179
|
file.write(self._to_chapter_txt(section))
|
126
180
|
|
127
|
-
sc_seq = sc_seq + 1
|
128
|
-
|
129
|
-
def _new_file(self) -> None:
|
130
|
-
new_filename = self._output_filename(".txt")
|
131
|
-
txt_filename = Path(self.config.input_file.name)
|
132
|
-
|
133
|
-
if new_filename == txt_filename:
|
134
|
-
ymd_hms = dt.now().strftime("%Y%m%d_%H%M%S")
|
135
|
-
new_filename = Path(
|
136
|
-
txt_filename.resolve().parent.joinpath(
|
137
|
-
lower_underscore(
|
138
|
-
txt_filename.stem + "_" + ymd_hms + ".txt"
|
139
|
-
)
|
140
|
-
)
|
141
|
-
)
|
142
|
-
|
143
|
-
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
144
|
-
|
145
|
-
with open(new_filename, "w", encoding="utf8") as file:
|
146
|
-
file.write(self._to_txt())
|
147
|
-
logger.info("Generate TXT file: %s", new_filename.resolve())
|
148
|
-
|
149
181
|
if self.config.open:
|
150
|
-
self._open_file(
|
151
|
-
|
152
|
-
def _overwrite_file(self) -> None:
|
153
|
-
txt_filename = Path(self.config.input_file.name)
|
154
|
-
|
155
|
-
with open(txt_filename, "w", encoding="utf8") as file:
|
156
|
-
file.write(self._to_txt())
|
157
|
-
logger.info("Overwrite txt file: %s", txt_filename.resolve())
|
158
|
-
|
159
|
-
if self.config.open:
|
160
|
-
self._open_file(txt_filename)
|
182
|
+
self._open_file(metadata_filename)
|
161
183
|
|
162
184
|
def _to_txt(self) -> str:
|
163
185
|
toc = self._to_toc("-") if self.config.with_toc else ""
|
164
186
|
return self._to_metadata_txt() + toc + self._to_body_txt()
|
165
|
-
|
166
|
-
def _to_body_txt(self) -> str:
|
167
187
|
content = []
|
168
188
|
for section in self.book.toc:
|
169
189
|
if isinstance(section, Volume):
|
txt2ebook/formats/typ.py
CHANGED
@@ -18,11 +18,13 @@
|
|
18
18
|
import importlib.resources as importlib_res
|
19
19
|
import logging
|
20
20
|
import textwrap
|
21
|
+
from pathlib import Path
|
21
22
|
|
22
23
|
import importlib_resources
|
23
24
|
import typst
|
24
25
|
|
25
26
|
from txt2ebook.formats.base import BaseWriter
|
27
|
+
from txt2ebook.helpers import lower_underscore
|
26
28
|
from txt2ebook.models import Chapter, Volume
|
27
29
|
|
28
30
|
# workaround for Python 3.8
|
@@ -43,9 +45,6 @@ class TypWriter(BaseWriter):
|
|
43
45
|
|
44
46
|
def write(self) -> None:
|
45
47
|
"""Generate Typst files."""
|
46
|
-
self._new_file()
|
47
|
-
|
48
|
-
def _new_file(self) -> None:
|
49
48
|
new_filename = self._output_filename(".typ")
|
50
49
|
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
51
50
|
|
@@ -210,6 +209,20 @@ class TypWriter(BaseWriter):
|
|
210
209
|
|
211
210
|
return self.config.paragraph_separator.join(pars)
|
212
211
|
|
212
|
+
def _get_file_extension_for_split(self) -> str:
|
213
|
+
return ".typ"
|
214
|
+
|
215
|
+
def _get_toc_content_for_split(self) -> str:
|
216
|
+
return self._to_outline()
|
217
|
+
|
218
|
+
def _get_volume_chapter_content_for_split(
|
219
|
+
self, volume: Volume, chapter: Chapter
|
220
|
+
) -> str:
|
221
|
+
return self._to_volume_chapter_txt(volume, chapter)
|
222
|
+
|
223
|
+
def _get_chapter_content_for_split(self, chapter: Chapter) -> str:
|
224
|
+
return self._to_chapter_txt(chapter)
|
225
|
+
|
213
226
|
def _index_pages(self) -> str:
|
214
227
|
return textwrap.dedent(
|
215
228
|
"""
|
@@ -221,3 +234,35 @@ class TypWriter(BaseWriter):
|
|
221
234
|
]
|
222
235
|
"""
|
223
236
|
)
|
237
|
+
|
238
|
+
def _get_metadata_filename_for_split(
|
239
|
+
self, txt_filename: Path, extension: str
|
240
|
+
) -> Path:
|
241
|
+
return Path(self._output_folder(), "metadata").with_suffix(extension)
|
242
|
+
|
243
|
+
def _get_toc_filename_for_split(
|
244
|
+
self, txt_filename: Path, extension: str
|
245
|
+
) -> Path:
|
246
|
+
return Path(self._output_folder(), "toc").with_suffix(extension)
|
247
|
+
|
248
|
+
def _get_volume_chapter_filename_for_split(
|
249
|
+
self,
|
250
|
+
txt_filename: Path,
|
251
|
+
section_seq: str,
|
252
|
+
chapter_seq: str,
|
253
|
+
volume: Volume,
|
254
|
+
chapter: Chapter,
|
255
|
+
extension: str,
|
256
|
+
) -> Path:
|
257
|
+
filename = f"{section_seq}-{lower_underscore(volume.title)}-{chapter_seq}-{lower_underscore(chapter.title)}"
|
258
|
+
return Path(self._output_folder(), filename).with_suffix(extension)
|
259
|
+
|
260
|
+
def _get_chapter_filename_for_split(
|
261
|
+
self,
|
262
|
+
txt_filename: Path,
|
263
|
+
section_seq: str,
|
264
|
+
chapter: Chapter,
|
265
|
+
extension: str,
|
266
|
+
) -> Path:
|
267
|
+
filename = f"{section_seq}-{lower_underscore(chapter.title)}"
|
268
|
+
return Path(self._output_folder(), filename).with_suffix(extension)
|
txt2ebook/subcommands/epub.py
CHANGED
@@ -38,10 +38,10 @@ def build_subparser(subparsers) -> None:
|
|
38
38
|
|
39
39
|
epub_parser.add_argument(
|
40
40
|
"input_file",
|
41
|
-
nargs=
|
41
|
+
nargs=1,
|
42
42
|
type=argparse.FileType("rb"),
|
43
|
-
help="source text
|
44
|
-
metavar="
|
43
|
+
help="source text filename",
|
44
|
+
metavar="TXT_FILENAME",
|
45
45
|
)
|
46
46
|
|
47
47
|
epub_parser.add_argument(
|
@@ -125,12 +125,12 @@ def run(args: argparse.Namespace) -> None:
|
|
125
125
|
"""
|
126
126
|
input_sources = []
|
127
127
|
|
128
|
-
if
|
129
|
-
#
|
130
|
-
input_sources.append(sys.stdin)
|
131
|
-
elif args.input_file:
|
132
|
-
# multiple file(s)
|
128
|
+
if args.input_file:
|
129
|
+
# File path(s) were explicitly provided on the command line
|
133
130
|
input_sources.extend(args.input_file)
|
131
|
+
elif not sys.stdin.isatty():
|
132
|
+
# No file path provided, check for piped input
|
133
|
+
input_sources.append(sys.stdin)
|
134
134
|
else:
|
135
135
|
logger.error("No input files provided.")
|
136
136
|
sys.exit(1)
|
@@ -147,6 +147,10 @@ def run(args: argparse.Namespace) -> None:
|
|
147
147
|
current_file_args = argparse.Namespace(**vars(args))
|
148
148
|
current_file_args.input_file = current_input_stream
|
149
149
|
|
150
|
+
logger.debug(
|
151
|
+
"Create separate volume page: %s", current_file_args.volume_page
|
152
|
+
)
|
153
|
+
|
150
154
|
# if an explicit output_file was provided, it must apply to the first
|
151
155
|
# input
|
152
156
|
if i > 0 and args.output_file:
|
txt2ebook/subcommands/massage.py
CHANGED
@@ -28,7 +28,9 @@ from bs4 import UnicodeDammit
|
|
28
28
|
|
29
29
|
from txt2ebook import detect_and_expect_language
|
30
30
|
from txt2ebook.exceptions import EmptyFileError
|
31
|
+
from txt2ebook.formats.txt import TxtWriter
|
31
32
|
from txt2ebook.models.book import Book
|
33
|
+
from txt2ebook.parser import Parser
|
32
34
|
from txt2ebook.zh_utils import zh_halfwidth_to_fullwidth, zh_words_to_numbers
|
33
35
|
|
34
36
|
logger = logging.getLogger(__name__)
|
@@ -216,26 +218,27 @@ def run(args: argparse.Namespace) -> None:
|
|
216
218
|
None
|
217
219
|
"""
|
218
220
|
massaged_txt = massage_txt(args)
|
219
|
-
if args.overwrite:
|
220
|
-
_overwrite_file(args, massaged_txt)
|
221
|
-
else:
|
222
|
-
_new_file(args, massaged_txt)
|
223
221
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
222
|
+
if args.split_volume_and_chapter:
|
223
|
+
args.language = detect_and_expect_language(massaged_txt, args.language)
|
224
|
+
config_lang = args.language.replace("-", "_")
|
225
|
+
langconf = import_module(f"txt2ebook.languages.{config_lang}")
|
226
|
+
args.with_toc = False
|
227
|
+
parser = Parser(massaged_txt, args, langconf)
|
228
|
+
book = parser.parse()
|
230
229
|
|
231
|
-
|
232
|
-
|
230
|
+
if args.debug:
|
231
|
+
book.debug(args.verbose)
|
233
232
|
|
234
|
-
|
235
|
-
|
233
|
+
if args.header_number:
|
234
|
+
book = header_number(args, book)
|
236
235
|
|
237
|
-
|
238
|
-
|
236
|
+
writer = TxtWriter(book, args)
|
237
|
+
writer.write()
|
238
|
+
elif args.overwrite:
|
239
|
+
_overwrite_file(args, massaged_txt)
|
240
|
+
else:
|
241
|
+
_new_file(args, massaged_txt)
|
239
242
|
|
240
243
|
|
241
244
|
def _overwrite_file(args, massaged_txt) -> None:
|
@@ -356,11 +359,13 @@ def massage_txt(args: argparse.Namespace) -> str:
|
|
356
359
|
if args.re_delete_line:
|
357
360
|
body = do_delete_line_regex(args, body)
|
358
361
|
|
359
|
-
if args.single_newline:
|
360
|
-
body = do_single_newline(args, body)
|
361
|
-
|
362
362
|
if args.width:
|
363
363
|
body = do_wrapping(args, body)
|
364
|
+
elif args.single_newline:
|
365
|
+
body = do_single_newline(args, body)
|
366
|
+
else:
|
367
|
+
# Apply paragraph separation and line unwrapping by default
|
368
|
+
body = _unwrap_content(args, body)
|
364
369
|
|
365
370
|
return f"{metadata}{body}"
|
366
371
|
|
@@ -376,6 +381,7 @@ def to_unix_newline(content: str) -> str:
|
|
376
381
|
"""
|
377
382
|
return content.replace("\r\n", "\n").replace("\r", "\n")
|
378
383
|
|
384
|
+
|
379
385
|
def do_reindent_paragraph(args, content: str) -> str:
|
380
386
|
"""Reindent each paragraph.
|
381
387
|
|
@@ -385,16 +391,16 @@ def do_reindent_paragraph(args, content: str) -> str:
|
|
385
391
|
Returns:
|
386
392
|
str: The formatted book content.
|
387
393
|
"""
|
388
|
-
paragraphs = re.split(r
|
394
|
+
paragraphs = re.split(r"\n\s*\n+", content)
|
389
395
|
reindented_paragraphs = []
|
390
396
|
for paragraph in paragraphs:
|
391
|
-
lines = paragraph.split(
|
397
|
+
lines = paragraph.split("\n")
|
392
398
|
reindented_lines = []
|
393
399
|
for line in lines:
|
394
400
|
stripped_line = line.strip()
|
395
401
|
reindented_lines.append(stripped_line)
|
396
402
|
|
397
|
-
reindented_paragraph =
|
403
|
+
reindented_paragraph = "\n".join(reindented_lines)
|
398
404
|
reindented_paragraph = " " + reindented_paragraph
|
399
405
|
reindented_paragraphs.append(reindented_paragraph)
|
400
406
|
|
@@ -542,7 +548,7 @@ def _unwrap_content(args: argparse.Namespace, content: str) -> str:
|
|
542
548
|
Returns:
|
543
549
|
str: The formatted book content.
|
544
550
|
"""
|
545
|
-
paragraphs =
|
551
|
+
paragraphs = re.split(r"\n\s*\n+", content)
|
546
552
|
processed_paragraphs = []
|
547
553
|
for paragraph in paragraphs:
|
548
554
|
single_line_paragraph = " ".join(paragraph.splitlines())
|
@@ -6,14 +6,14 @@ txt2ebook/parser.py,sha256=ITn6pGHO4vTfdrYouVV2mEe9jUM2zm3-FKEcspp2qzI,8968
|
|
6
6
|
txt2ebook/tokenizer.py,sha256=UGyOBGxlKOXJtvP2UFp38EgFym8-PAU3A7Jl9RF3w6Y,10299
|
7
7
|
txt2ebook/zh_utils.py,sha256=0Yq9r-JL4HntW68vFR6TBP9yQim1a07mfsh_sp-XmaE,4887
|
8
8
|
txt2ebook/formats/__init__.py,sha256=_fW9UuoOTFxCKlej6t-PsFzJOqDFLzVatCci9tcPQeE,1645
|
9
|
-
txt2ebook/formats/base.py,sha256=
|
9
|
+
txt2ebook/formats/base.py,sha256=bPpfKZwz3KeEtNRYJPZJJIKRcANGs_tw5a3uOw1pzSs,9625
|
10
10
|
txt2ebook/formats/epub.py,sha256=IVz-FmYQlcChOw38YqfKy46bPVSIrHyxA_94iz06N3Y,6941
|
11
|
-
txt2ebook/formats/gmi.py,sha256=
|
12
|
-
txt2ebook/formats/md.py,sha256=
|
11
|
+
txt2ebook/formats/gmi.py,sha256=tUCEHtRHDupEPJ8dYPpxpE6yEKHCk8PRXR0zgjJFgsI,5837
|
12
|
+
txt2ebook/formats/md.py,sha256=ZleBFNOGRhWr5WgcA8uyLXBxJm1bdQaunqzjocQYSkI,5587
|
13
13
|
txt2ebook/formats/pdf.py,sha256=tr_ozVlL976yo7Ggny71zjOwzSd6tSnHTl7mcsLII_g,7263
|
14
14
|
txt2ebook/formats/tex.py,sha256=V5B1nPR-WzGc4jqWu-BqxfQhtQsUTKM_sZZJsCcDBAk,5897
|
15
|
-
txt2ebook/formats/txt.py,sha256=
|
16
|
-
txt2ebook/formats/typ.py,sha256=
|
15
|
+
txt2ebook/formats/txt.py,sha256=1f-e53oPyhyElLLKqZZ4_HJxIJkwyVjZLi0pnl02EM8,7929
|
16
|
+
txt2ebook/formats/typ.py,sha256=0WjGeZHxbdCV1grYkEpgUocehWfmeJz8Ur9cT2ADlFI,8269
|
17
17
|
txt2ebook/formats/templates/__init__.py,sha256=f3K7pJByNmmvu-wvziks6qb2QnnLmkDjUACXyw2s60E,760
|
18
18
|
txt2ebook/formats/templates/epub/__init__.py,sha256=-XVLvnknTJTmQZY9UTH705vMcHgy56rQVRTusYawEZ4,766
|
19
19
|
txt2ebook/helpers/__init__.py,sha256=c2EItHvPABDORfgfjArfa5XR--43es4D1tKWqaPcBxY,1309
|
@@ -27,17 +27,17 @@ txt2ebook/models/chapter.py,sha256=6YvUDHzR6amGMZgkQl_xHWrYZUmlfpF7mnDLilG2BpA,1
|
|
27
27
|
txt2ebook/models/volume.py,sha256=koz1KfWjvGWLFbmGEQlZ23frsP93cDsuBMySYBHiXm8,1597
|
28
28
|
txt2ebook/subcommands/__init__.py,sha256=ldhzvsrMsR8lZmhZef77JFz0jValpV3pytFfwJSkjls,1146
|
29
29
|
txt2ebook/subcommands/env.py,sha256=gEzra4b6guy7pRZUTCWX1_eiR7JmrtR1Z-J-vxljvMY,1549
|
30
|
-
txt2ebook/subcommands/epub.py,sha256=
|
30
|
+
txt2ebook/subcommands/epub.py,sha256=xaXKATCioRVr-vN_Lw4SqQxJdm6dSWs-y3RyTpV3ZV8,4824
|
31
31
|
txt2ebook/subcommands/gmi.py,sha256=ANnPg-RFsylTo44fUzFOSHN1fC3Ce82gBzrv-sBv5fU,3318
|
32
|
-
txt2ebook/subcommands/massage.py,sha256=
|
32
|
+
txt2ebook/subcommands/massage.py,sha256=f_moVt19n60QH2T2J_EwZnCv1JNFrqLGu5j2VZfp_Lk,15793
|
33
33
|
txt2ebook/subcommands/md.py,sha256=PmIqrqrnzLywvN4qTkle0V9N3FTIJGRWpC0Xbk76B5o,3329
|
34
34
|
txt2ebook/subcommands/parse.py,sha256=xjhW8I9zS5DL3n3m04RyFofgci-6-_L6aF3d4N7c7M4,2938
|
35
35
|
txt2ebook/subcommands/pdf.py,sha256=1JQtpugzAIaho6G3CK1rGYk74hotAexXZxPH9PHpRps,2980
|
36
36
|
txt2ebook/subcommands/tex.py,sha256=8XqTV5GsOEr7sGSLUJB-B1KefIMxW3_BDq_Jm96Bt1Y,4369
|
37
37
|
txt2ebook/subcommands/typ.py,sha256=xeJ_cPmyq_uouUBiH2kbcscckHLqewPmu9j0WO36sXY,4814
|
38
|
-
txt2ebook-0.1.
|
39
|
-
txt2ebook-0.1.
|
40
|
-
txt2ebook-0.1.
|
41
|
-
txt2ebook-0.1.
|
42
|
-
txt2ebook-0.1.
|
43
|
-
txt2ebook-0.1.
|
38
|
+
txt2ebook-0.1.159.dist-info/licenses/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
|
39
|
+
txt2ebook-0.1.159.dist-info/METADATA,sha256=SaESbcwNBN1WQMIbsaHoUWuEnjYxNQoZqZgg5CeYZag,5295
|
40
|
+
txt2ebook-0.1.159.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
41
|
+
txt2ebook-0.1.159.dist-info/entry_points.txt,sha256=3jm5vpUsDRgoM6S3CQVMMiP7tJQqfq1vfV0sh_KaK9s,74
|
42
|
+
txt2ebook-0.1.159.dist-info/top_level.txt,sha256=pesdk4CJRlfhUXVD9vH3Dd_F8ATlLQoqlUsUnU8SJMw,10
|
43
|
+
txt2ebook-0.1.159.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|