txt2ebook 0.1.156__py3-none-any.whl → 0.1.158__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 CHANGED
@@ -24,6 +24,7 @@ import shutil
24
24
  import subprocess
25
25
  import sys
26
26
  from abc import ABC, abstractmethod
27
+ from datetime import datetime as dt
27
28
  from importlib import import_module
28
29
  from pathlib import Path
29
30
 
@@ -134,6 +135,98 @@ class BaseWriter(ABC):
134
135
  file.parent, self.config.output_folder, lower_underscore(file.stem)
135
136
  ).with_suffix(extension)
136
137
 
138
+ def _get_toc_content_for_split(self) -> str:
139
+ raise NotImplementedError
140
+
141
+ def _get_volume_chapter_content_for_split(
142
+ self, volume: Volume, chapter: Chapter
143
+ ) -> str:
144
+ raise NotImplementedError
145
+
146
+ def _get_chapter_content_for_split(self, chapter: Chapter) -> str:
147
+ raise NotImplementedError
148
+
149
+ def _get_file_extension_for_split(self) -> str:
150
+ raise NotImplementedError
151
+
152
+ def _export_multiple_files(self) -> None:
153
+ logger.info("Split multiple files")
154
+
155
+ extension = self._get_file_extension_for_split()
156
+ txt_filename = Path(self.config.input_file.name)
157
+
158
+ export_filename = self._get_metadata_filename_for_split(txt_filename, extension)
159
+ export_filename.parent.mkdir(parents=True, exist_ok=True)
160
+ logger.info("Creating %s", export_filename)
161
+ with open(export_filename, "w", encoding="utf8") as file:
162
+ file.write(self._to_metadata_txt())
163
+
164
+ sc_seq = 1
165
+ if self.config.with_toc:
166
+ export_filename = self._get_toc_filename_for_split(txt_filename, extension)
167
+ export_filename.parent.mkdir(parents=True, exist_ok=True)
168
+ logger.info("Creating %s", export_filename)
169
+ with open(export_filename, "w", encoding="utf8") as file:
170
+ file.write(self._get_toc_content_for_split())
171
+
172
+ sc_seq = 2
173
+
174
+ for section in self.book.toc:
175
+ section_seq = str(sc_seq).rjust(2, "0")
176
+
177
+ ct_seq = 0
178
+ if isinstance(section, Volume):
179
+ for chapter in section.chapters:
180
+ chapter_seq = str(ct_seq).rjust(2, "0")
181
+ export_filename = self._get_volume_chapter_filename_for_split(
182
+ txt_filename, section_seq, chapter_seq, section, chapter, extension
183
+ )
184
+ export_filename.parent.mkdir(parents=True, exist_ok=True)
185
+ logger.info("Creating %s", export_filename)
186
+ with open(export_filename, "w", encoding="utf8") as file:
187
+ file.write(
188
+ self._get_volume_chapter_content_for_split(
189
+ section, chapter
190
+ )
191
+ )
192
+ ct_seq = ct_seq + 1
193
+ if isinstance(section, Chapter):
194
+ export_filename = self._get_chapter_filename_for_split(
195
+ txt_filename, section_seq, section, extension
196
+ )
197
+ export_filename.parent.mkdir(parents=True, exist_ok=True)
198
+ logger.info("Creating %s", export_filename)
199
+ with open(export_filename, "w", encoding="utf8") as file:
200
+ file.write(self._get_chapter_content_for_split(section))
201
+
202
+ sc_seq = sc_seq + 1
203
+
204
+ @abstractmethod
205
+ def _get_metadata_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
206
+ raise NotImplementedError
207
+
208
+ @abstractmethod
209
+ def _get_toc_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
210
+ raise NotImplementedError
211
+
212
+ @abstractmethod
213
+ def _get_volume_chapter_filename_for_split(
214
+ self,
215
+ txt_filename: Path,
216
+ section_seq: str,
217
+ chapter_seq: str,
218
+ volume: Volume,
219
+ chapter: Chapter,
220
+ extension: str,
221
+ ) -> Path:
222
+ raise NotImplementedError
223
+
224
+ @abstractmethod
225
+ def _get_chapter_filename_for_split(
226
+ self, txt_filename: Path, section_seq: str, chapter: Chapter, extension: str
227
+ ) -> Path:
228
+ raise NotImplementedError
229
+
137
230
  def _to_metadata_txt(self) -> str:
138
231
  metadata = [
139
232
  self._("title:") + self.book.title,
txt2ebook/formats/gmi.py CHANGED
@@ -34,99 +34,86 @@ class GmiWriter(BaseWriter):
34
34
  if self.config.split_volume_and_chapter:
35
35
  self._export_multiple_files()
36
36
  else:
37
- self._new_file()
37
+ output_filename = self._output_filename(".gmi")
38
+ output_filename.parent.mkdir(parents=True, exist_ok=True)
38
39
 
39
- def _export_multiple_files(self) -> None:
40
- logger.info("Split multiple files")
40
+ with open(output_filename, "w", encoding="utf8") as file:
41
+ logger.info("Generate Gemini file: %s", output_filename.resolve())
42
+ file.write(self._to_gmi())
41
43
 
42
- txt_filename = Path(self.config.input_file.name)
43
- export_filename = Path(
44
+ if self.config.open:
45
+ self._open_file(output_filename)
46
+
47
+ def _get_toc_content_for_split(self) -> str:
48
+ return self._to_toc("*", "# ")
49
+
50
+ def _get_volume_chapter_content_for_split(
51
+ self, volume: Volume, chapter: Chapter
52
+ ) -> str:
53
+ return self._to_volume_chapter_txt(volume, chapter)
54
+
55
+ def _get_chapter_content_for_split(self, chapter: Chapter) -> str:
56
+ return self._to_chapter_txt(chapter)
57
+
58
+ def _get_file_extension_for_split(self) -> str:
59
+ return ".gmi"
60
+
61
+ def _get_metadata_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
62
+ return Path(
44
63
  txt_filename.resolve().parent.joinpath(
45
64
  self.config.output_folder,
46
65
  lower_underscore(
47
- f"00_{txt_filename.stem}_" + self._("metadata") + ".gmi"
66
+ f"00_{txt_filename.stem}_" + self._("metadata") + extension
48
67
  ),
49
68
  )
50
69
  )
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
-
71
- sc_seq = 2
72
-
73
- for section in self.book.toc:
74
- section_seq = str(sc_seq).rjust(2, "0")
75
70
 
76
- ct_seq = 0
77
- if isinstance(section, Volume):
78
- for chapter in section.chapters:
79
- chapter_seq = str(ct_seq).rjust(2, "0")
80
- filename = lower_underscore(
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
- )
90
-
91
- export_filename = Path(
92
- txt_filename.resolve().parent.joinpath(
93
- self.config.output_folder, filename
94
- )
95
- )
96
- export_filename.parent.mkdir(parents=True, exist_ok=True)
97
- logger.info("Creating %s", export_filename)
98
- with open(export_filename, "w", encoding="utf8") as file:
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
- )
71
+ def _get_toc_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
72
+ return Path(
73
+ txt_filename.resolve().parent.joinpath(
74
+ self.config.output_folder,
75
+ lower_underscore(
76
+ f"01_{txt_filename.stem}_" + self._("toc") + extension
77
+ ),
78
+ )
79
+ )
107
80
 
108
- export_filename = Path(
109
- txt_filename.resolve().parent.joinpath(
110
- self.config.output_folder, filename
81
+ def _get_volume_chapter_filename_for_split(
82
+ self,
83
+ txt_filename: Path,
84
+ section_seq: str,
85
+ chapter_seq: str,
86
+ volume: Volume,
87
+ chapter: Chapter,
88
+ extension: str,
89
+ ) -> Path:
90
+ return Path(
91
+ txt_filename.resolve().parent.joinpath(
92
+ self.config.output_folder,
93
+ lower_underscore(
94
+ (
95
+ f"{section_seq}"
96
+ f"_{chapter_seq}"
97
+ f"_{txt_filename.stem}"
98
+ f"_{volume.title}"
99
+ f"_{chapter.title}"
100
+ f"{extension}"
111
101
  )
112
- )
113
- export_filename.parent.mkdir(parents=True, exist_ok=True)
114
- logger.info("Creating %s", export_filename)
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())
102
+ ),
103
+ )
104
+ )
127
105
 
128
- if self.config.open:
129
- self._open_file(new_filename)
106
+ def _get_chapter_filename_for_split(
107
+ self, txt_filename: Path, section_seq: str, chapter: Chapter, extension: str
108
+ ) -> Path:
109
+ return Path(
110
+ txt_filename.resolve().parent.joinpath(
111
+ self.config.output_folder,
112
+ lower_underscore(
113
+ (f"{section_seq}_{txt_filename.stem}_{chapter.title}{extension}")
114
+ ),
115
+ )
116
+ )
130
117
 
131
118
  def _to_gmi(self) -> str:
132
119
  toc = self._to_toc("*", "# ") if self.config.with_toc else ""
txt2ebook/formats/md.py CHANGED
@@ -17,6 +17,7 @@
17
17
 
18
18
  import logging
19
19
  from pathlib import Path
20
+ from pathlib import Path
20
21
 
21
22
  from txt2ebook.formats.base import BaseWriter
22
23
  from txt2ebook.helpers import lower_underscore
@@ -33,99 +34,86 @@ class MdWriter(BaseWriter):
33
34
  if self.config.split_volume_and_chapter:
34
35
  self._export_multiple_files()
35
36
  else:
36
- self._new_file()
37
+ output_filename = self._output_filename(".md")
38
+ output_filename.parent.mkdir(parents=True, exist_ok=True)
39
+
40
+ with open(output_filename, "w", encoding="utf8") as file:
41
+ logger.info("Generate Markdown file: %s", output_filename.resolve())
42
+ file.write(self._to_md())
43
+
44
+ if self.config.open:
45
+ self._open_file(output_filename)
46
+
47
+ def _get_toc_content_for_split(self) -> str:
48
+ return self._to_toc("-", "# ")
49
+
50
+ def _get_volume_chapter_content_for_split(
51
+ self, volume: Volume, chapter: Chapter
52
+ ) -> str:
53
+ return self._to_volume_chapter_txt(volume, chapter)
37
54
 
38
- def _export_multiple_files(self) -> None:
39
- logger.info("Split multiple files")
55
+ def _get_chapter_content_for_split(self, chapter: Chapter) -> str:
56
+ return self._to_chapter_txt(chapter)
40
57
 
41
- txt_filename = Path(self.config.input_file.name)
42
- export_filename = Path(
58
+ def _get_file_extension_for_split(self) -> str:
59
+ return ".md"
60
+
61
+ def _get_metadata_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
62
+ return Path(
43
63
  txt_filename.resolve().parent.joinpath(
44
64
  self.config.output_folder,
45
65
  lower_underscore(
46
- f"00_{txt_filename.stem}_" + self._("metadata") + ".md"
66
+ f"00_{txt_filename.stem}_" + self._("metadata") + extension
47
67
  ),
48
68
  )
49
69
  )
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
-
70
- sc_seq = 2
71
-
72
- for section in self.book.toc:
73
- section_seq = str(sc_seq).rjust(2, "0")
74
70
 
75
- ct_seq = 0
76
- if isinstance(section, Volume):
77
- for chapter in section.chapters:
78
- chapter_seq = str(ct_seq).rjust(2, "0")
79
- filename = lower_underscore(
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
- )
89
-
90
- export_filename = Path(
91
- txt_filename.resolve().parent.joinpath(
92
- self.config.output_folder, filename
93
- )
94
- )
95
- export_filename.parent.mkdir(parents=True, exist_ok=True)
96
- logger.info("Creating %s", export_filename)
97
- with open(export_filename, "w", encoding="utf8") as file:
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
- )
71
+ def _get_toc_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
72
+ return Path(
73
+ txt_filename.resolve().parent.joinpath(
74
+ self.config.output_folder,
75
+ lower_underscore(
76
+ f"01_{txt_filename.stem}_" + self._("toc") + extension
77
+ ),
78
+ )
79
+ )
106
80
 
107
- export_filename = Path(
108
- txt_filename.resolve().parent.joinpath(
109
- self.config.output_folder, filename
81
+ def _get_volume_chapter_filename_for_split(
82
+ self,
83
+ txt_filename: Path,
84
+ section_seq: str,
85
+ chapter_seq: str,
86
+ volume: Volume,
87
+ chapter: Chapter,
88
+ extension: str,
89
+ ) -> Path:
90
+ return Path(
91
+ txt_filename.resolve().parent.joinpath(
92
+ self.config.output_folder,
93
+ lower_underscore(
94
+ (
95
+ f"{section_seq}"
96
+ f"_{chapter_seq}"
97
+ f"_{txt_filename.stem}"
98
+ f"_{volume.title}"
99
+ f"_{chapter.title}"
100
+ f"{extension}"
110
101
  )
111
- )
112
- export_filename.parent.mkdir(parents=True, exist_ok=True)
113
- logger.info("Creating %s", export_filename)
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())
102
+ ),
103
+ )
104
+ )
126
105
 
127
- if self.config.open:
128
- self._open_file(new_filename)
106
+ def _get_chapter_filename_for_split(
107
+ self, txt_filename: Path, section_seq: str, chapter: Chapter, extension: str
108
+ ) -> Path:
109
+ return Path(
110
+ txt_filename.resolve().parent.joinpath(
111
+ self.config.output_folder,
112
+ lower_underscore(
113
+ (f"{section_seq}_{txt_filename.stem}_{chapter.title}{extension}")
114
+ ),
115
+ )
116
+ )
129
117
 
130
118
  def _to_md(self) -> str:
131
119
  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,124 +41,93 @@ class TxtWriter(BaseWriter):
40
41
  elif self.config.split_volume_and_chapter:
41
42
  self._export_multiple_files()
42
43
  else:
43
- if self.config.overwrite:
44
- self._overwrite_file()
45
- else:
46
- self._new_file()
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
+ + "_" + ymd_hms + ".txt"
58
+ )
59
+ )
60
+ )
61
+ logger.info("Backup source text file: %s", backup_filename.resolve())
62
+ shutil.copyfile(output_filename, backup_filename)
63
+
64
+ with open(output_filename, "w", encoding="utf8") as file:
65
+ logger.info("Generate TXT file: %s", output_filename.resolve())
66
+ file.write(self._to_txt())
67
+
68
+ if self.config.open:
69
+ self._open_file(output_filename)
70
+
71
+
47
72
 
48
- def _export_multiple_files(self) -> None:
49
- logger.info("Split multiple files")
73
+
50
74
 
51
- txt_filename = Path(self.config.input_file.name)
52
- export_filename = Path(
75
+ def _get_metadata_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
76
+ return Path(
53
77
  txt_filename.resolve().parent.joinpath(
54
78
  self.config.output_folder,
55
79
  lower_underscore(
56
- f"00_{txt_filename.stem}_" + self._("metadata") + ".txt"
80
+ f"00_{txt_filename.stem}_" + self._("metadata") + extension
57
81
  ),
58
82
  )
59
83
  )
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
-
65
- sc_seq = 1
66
- if self.config.with_toc:
67
- export_filename = Path(
68
- txt_filename.resolve().parent.joinpath(
69
- self.config.output_folder,
70
- lower_underscore(
71
- f"01_{txt_filename.stem}_" + self._("toc") + ".txt"
72
- ),
73
- )
74
- )
75
- export_filename.parent.mkdir(parents=True, exist_ok=True)
76
- logger.info("Creating %s", export_filename)
77
- with open(export_filename, "w", encoding="utf8") as file:
78
- file.write(self._to_toc("-"))
79
-
80
- sc_seq = 2
81
84
 
82
- for section in self.book.toc:
83
- section_seq = str(sc_seq).rjust(2, "0")
84
-
85
- ct_seq = 0
86
- if isinstance(section, Volume):
87
- for chapter in section.chapters:
88
- chapter_seq = str(ct_seq).rjust(2, "0")
89
- filename = lower_underscore(
90
- (
91
- f"{section_seq}"
92
- f"_{chapter_seq}"
93
- f"_{txt_filename.stem}"
94
- f"_{section.title}"
95
- f"_{chapter.title}"
96
- ".txt"
97
- )
98
- )
99
-
100
- export_filename = Path(
101
- txt_filename.resolve().parent.joinpath(
102
- self.config.output_folder, filename
103
- )
104
- )
105
- export_filename.parent.mkdir(parents=True, exist_ok=True)
106
- logger.info("Creating %s", export_filename)
107
- with open(export_filename, "w", encoding="utf8") as file:
108
- file.write(
109
- self._to_volume_chapter_txt(section, chapter)
110
- )
111
- ct_seq = ct_seq + 1
112
- if isinstance(section, Chapter):
113
- filename = lower_underscore(
114
- (f"{section_seq}_{txt_filename.stem}_{section.title}.txt")
115
- )
85
+ def _get_toc_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
86
+ return Path(
87
+ txt_filename.resolve().parent.joinpath(
88
+ self.config.output_folder,
89
+ lower_underscore(
90
+ f"01_{txt_filename.stem}_" + self._("toc") + extension
91
+ ),
92
+ )
93
+ )
116
94
 
117
- export_filename = Path(
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:
125
- file.write(self._to_chapter_txt(section))
126
-
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"
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
+ lower_underscore(
108
+ (
109
+ f"{section_seq}"
110
+ f"_{chapter_seq}"
111
+ f"_{txt_filename.stem}"
112
+ f"_{volume.title}"
113
+ f"_{chapter.title}"
114
+ f"{extension}"
139
115
  )
140
- )
116
+ ),
141
117
  )
118
+ )
142
119
 
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
- if self.config.open:
150
- self._open_file(new_filename)
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)
120
+ def _get_chapter_filename_for_split(
121
+ self, txt_filename: Path, section_seq: str, chapter: Chapter, extension: str
122
+ ) -> Path:
123
+ return Path(
124
+ txt_filename.resolve().parent.joinpath(
125
+ self.config.output_folder,
126
+ lower_underscore(
127
+ (f"{section_seq}_{txt_filename.stem}_{chapter.title}{extension}")
128
+ ),
129
+ )
130
+ )
161
131
 
162
132
  def _to_txt(self) -> str:
163
133
  toc = self._to_toc("-") if self.config.with_toc else ""
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,27 @@ class TypWriter(BaseWriter):
221
234
  ]
222
235
  """
223
236
  )
237
+
238
+ def _get_metadata_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
239
+ return Path(self._output_folder(), "metadata").with_suffix(extension)
240
+
241
+ def _get_toc_filename_for_split(self, txt_filename: Path, extension: str) -> Path:
242
+ return Path(self._output_folder(), "toc").with_suffix(extension)
243
+
244
+ def _get_volume_chapter_filename_for_split(
245
+ self,
246
+ txt_filename: Path,
247
+ section_seq: str,
248
+ chapter_seq: str,
249
+ volume: Volume,
250
+ chapter: Chapter,
251
+ extension: str,
252
+ ) -> Path:
253
+ filename = f"{section_seq}-{lower_underscore(volume.title)}-{chapter_seq}-{lower_underscore(chapter.title)}"
254
+ return Path(self._output_folder(), filename).with_suffix(extension)
255
+
256
+ def _get_chapter_filename_for_split(
257
+ self, txt_filename: Path, section_seq: str, chapter: Chapter, extension: str
258
+ ) -> Path:
259
+ filename = f"{section_seq}-{lower_underscore(chapter.title)}"
260
+ return Path(self._output_folder(), filename).with_suffix(extension)
@@ -210,7 +210,7 @@ def run(args: argparse.Namespace) -> None:
210
210
  """Run massage subcommand.
211
211
 
212
212
  Args:
213
- args (argparse.Namespace): args.from command line arguments
213
+ args (argparse.Namespace): arguments from command line arguments
214
214
 
215
215
  Returns:
216
216
  None
@@ -472,7 +472,6 @@ def extract_metadata_and_body(_args, content: str) -> tuple:
472
472
  metadata = match.group(0).strip()
473
473
  body = content.replace(metadata, "", 1)
474
474
 
475
-
476
475
  metadata_block = metadata.split("---")[1]
477
476
 
478
477
  metadata_dict = {}
@@ -492,33 +491,38 @@ def extract_metadata_and_body(_args, content: str) -> tuple:
492
491
  return (meta_str, body)
493
492
 
494
493
 
495
- def do_single_newline(args, content: str) -> str:
494
+ def do_single_newline(args: argparse.Namespace, content: str) -> str:
496
495
  """Set single newline.
497
496
 
498
497
  Args:
499
- content (str): The formatted book content.
498
+ args (argparse.Namespace): arguments from command line arguments
499
+ content (str): The formatted book content
500
500
 
501
501
  Returns:
502
502
  str: The formatted book content.
503
503
  """
504
- modified_content = re.sub(r"\n+", "\n\n", content)
504
+ unwrap_content = _unwrap_content(args, content)
505
+ modified_content = re.sub(r"\n+", "\n\n", unwrap_content)
505
506
  return modified_content
506
507
 
507
508
 
508
- def do_wrapping(args, content: str) -> str:
509
+ def do_wrapping(args: argparse.Namespace, content: str) -> str:
509
510
  """Wrap or fill CJK text.
510
511
 
511
512
  Args:
512
- content (str): The formatted book content.
513
+ args (argparse.Namespace): arguments from command line arguments
514
+ content (str): The formatted book content
513
515
 
514
516
  Returns:
515
517
  str: The formatted book content.
516
518
  """
517
519
  logger.info("Wrapping paragraph to width: %s", args.width)
518
520
 
521
+ unwrap_content = _unwrap_content(args, content)
522
+
523
+ # don't remove empty line and keep all formatting as it
519
524
  paragraphs = []
520
- # We don't remove empty line and keep all formatting as it.
521
- for paragraph in content.split("\n"):
525
+ for paragraph in unwrap_content.split("\n"):
522
526
  paragraph = paragraph.strip()
523
527
 
524
528
  lines = cjkwrap.wrap(paragraph, width=args.width)
@@ -527,3 +531,20 @@ def do_wrapping(args, content: str) -> str:
527
531
 
528
532
  wrapped_content = "\n".join(paragraphs)
529
533
  return wrapped_content
534
+
535
+
536
+ def _unwrap_content(args: argparse.Namespace, content: str) -> str:
537
+ """
538
+ Args:
539
+ args (argparse.Namespace): arguments from command line arguments
540
+ content (str): The formatted book content
541
+
542
+ Returns:
543
+ str: The formatted book content.
544
+ """
545
+ paragraphs = content.split(args.paragraph_separator)
546
+ processed_paragraphs = []
547
+ for paragraph in paragraphs:
548
+ single_line_paragraph = " ".join(paragraph.splitlines())
549
+ processed_paragraphs.append(single_line_paragraph.strip())
550
+ return args.paragraph_separator.join(processed_paragraphs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: txt2ebook
3
- Version: 0.1.156
3
+ Version: 0.1.158
4
4
  Summary: CLI tool to convert txt file to ebook format
5
5
  Author-email: Kian-Meng Ang <kianmeng@cpan.org>
6
6
  License-Expression: AGPL-3.0-or-later
@@ -39,6 +39,22 @@ Requires-Dist: regex<2022,>=2021.11.10
39
39
  Requires-Dist: reportlab<5,>=4.0.0
40
40
  Requires-Dist: typing-extensions<5,>=4.5.0
41
41
  Requires-Dist: typst>=0.13.0
42
+ Provides-Extra: test
43
+ Requires-Dist: pytest; extra == "test"
44
+ Requires-Dist: pytest-cov; extra == "test"
45
+ Requires-Dist: pytest-randomly; extra == "test"
46
+ Requires-Dist: pytest-xdist; extra == "test"
47
+ Requires-Dist: scripttest; extra == "test"
48
+ Provides-Extra: doc
49
+ Requires-Dist: myst-parser; extra == "doc"
50
+ Requires-Dist: sphinx; extra == "doc"
51
+ Requires-Dist: sphinx-autobuild; extra == "doc"
52
+ Requires-Dist: sphinx-autodoc-typehints; extra == "doc"
53
+ Requires-Dist: sphinx-copybutton; extra == "doc"
54
+ Provides-Extra: lint
55
+ Requires-Dist: pre-commit; extra == "lint"
56
+ Requires-Dist: ruff; extra == "lint"
57
+ Requires-Dist: mypy; extra == "lint"
42
58
  Dynamic: license-file
43
59
 
44
60
  # txt2ebook
@@ -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=xUrLOPlJyV_8tSIbBzrbBe3fP481CuHYSdOUSdtxeik,5796
9
+ txt2ebook/formats/base.py,sha256=3JIdLr0HowBYQL5-IdJKQa3eZD1a_cRYd2czfFRlg-0,9431
10
10
  txt2ebook/formats/epub.py,sha256=IVz-FmYQlcChOw38YqfKy46bPVSIrHyxA_94iz06N3Y,6941
11
- txt2ebook/formats/gmi.py,sha256=k9PY6tcXf1aXrW3ZGo-0nvt1PDS1LoG5i31hze5oYqM,6662
12
- txt2ebook/formats/md.py,sha256=BzT3jsSYZR7rx9Lxuu1DvxCWQutSmMzoab8huKvxaxE,6408
11
+ txt2ebook/formats/gmi.py,sha256=aIAoAG5HRNfC6OlkjMD54_wCveT0DXRaZCbTu1x8LYk,5692
12
+ txt2ebook/formats/md.py,sha256=lEsYyVWOV13aMt6WfspL2WQfSoC82urWYQx8kxa_6kY,5467
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=0DOVBTDRV2gcixham5Wj7NaZlNKAeLG9MLRlZgtUxqM,7412
16
- txt2ebook/formats/typ.py,sha256=MNclD5RdCnYAmPRzAaI6ZE6NnI8GdHKJla54wyfTUdc,6705
15
+ txt2ebook/formats/txt.py,sha256=7LYxS6wlJre_GFKemaVsTOTez_dpJcpoo6Emezt6rjc,5905
16
+ txt2ebook/formats/typ.py,sha256=eqh9kc5FxxKr06mOmdjl8nzAjrawY4ecxbqKH86QuQQ,8208
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
@@ -29,15 +29,15 @@ txt2ebook/subcommands/__init__.py,sha256=ldhzvsrMsR8lZmhZef77JFz0jValpV3pytFfwJS
29
29
  txt2ebook/subcommands/env.py,sha256=gEzra4b6guy7pRZUTCWX1_eiR7JmrtR1Z-J-vxljvMY,1549
30
30
  txt2ebook/subcommands/epub.py,sha256=oVk00rypqN53UAOIYhOofkAPbjrdlvkszLDIdVqexvE,4706
31
31
  txt2ebook/subcommands/gmi.py,sha256=ANnPg-RFsylTo44fUzFOSHN1fC3Ce82gBzrv-sBv5fU,3318
32
- txt2ebook/subcommands/massage.py,sha256=cjeee4wJJ6xPV76efnlWRVdeVkEtJYIBDaKhFMPjKTg,14643
32
+ txt2ebook/subcommands/massage.py,sha256=WmHHJQLowdjSDQnEqxVKsU9YsabY7fw4mBkfddsFZpI,15535
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.156.dist-info/licenses/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
39
- txt2ebook-0.1.156.dist-info/METADATA,sha256=FmlT-uz7lE9ZU6vp0U3X96lRMQSeNHEcuAu6NdQn7dw,4664
40
- txt2ebook-0.1.156.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
41
- txt2ebook-0.1.156.dist-info/entry_points.txt,sha256=3jm5vpUsDRgoM6S3CQVMMiP7tJQqfq1vfV0sh_KaK9s,74
42
- txt2ebook-0.1.156.dist-info/top_level.txt,sha256=pesdk4CJRlfhUXVD9vH3Dd_F8ATlLQoqlUsUnU8SJMw,10
43
- txt2ebook-0.1.156.dist-info/RECORD,,
38
+ txt2ebook-0.1.158.dist-info/licenses/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
39
+ txt2ebook-0.1.158.dist-info/METADATA,sha256=7gQjnlwM3PxI1mBQ7qsGT8k97A7nbdxAhwYlYrU0LdI,5295
40
+ txt2ebook-0.1.158.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
41
+ txt2ebook-0.1.158.dist-info/entry_points.txt,sha256=3jm5vpUsDRgoM6S3CQVMMiP7tJQqfq1vfV0sh_KaK9s,74
42
+ txt2ebook-0.1.158.dist-info/top_level.txt,sha256=pesdk4CJRlfhUXVD9vH3Dd_F8ATlLQoqlUsUnU8SJMw,10
43
+ txt2ebook-0.1.158.dist-info/RECORD,,