txt2ebook 0.1.146__tar.gz → 0.1.148__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.
Files changed (109) hide show
  1. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/PKG-INFO +19 -19
  2. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/pyproject.toml +4 -4
  3. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/__init__.py +6 -2
  4. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/base.py +9 -2
  5. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/epub.py +18 -6
  6. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/gmi.py +7 -2
  7. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/md.py +7 -2
  8. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/pdf.py +3 -1
  9. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/tex.py +6 -2
  10. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/txt.py +6 -2
  11. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/typ.py +4 -1
  12. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/locales/en/LC_MESSAGES/txt2ebook.po +6 -6
  13. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/locales/txt2ebook.pot +6 -6
  14. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/locales/zh-cn/LC_MESSAGES/txt2ebook.po +6 -6
  15. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/locales/zh-tw/LC_MESSAGES/txt2ebook.po +6 -6
  16. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/models/book.py +3 -1
  17. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/parser.py +10 -5
  18. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/__init__.py +2 -1
  19. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/gmi.py +3 -1
  20. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/massage.py +6 -5
  21. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/md.py +3 -1
  22. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/pdf.py +3 -1
  23. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/tex.py +3 -1
  24. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/typ.py +3 -1
  25. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/tokenizer.py +10 -3
  26. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/zh_utils.py +4 -1
  27. txt2ebook-0.1.146/.coveragerc +0 -18
  28. txt2ebook-0.1.146/.gitignore +0 -150
  29. txt2ebook-0.1.146/.pre-commit-config.yaml +0 -49
  30. txt2ebook-0.1.146/.python-version +0 -5
  31. txt2ebook-0.1.146/CHANGELOG.md +0 -1096
  32. txt2ebook-0.1.146/CONTRIBUTING.md +0 -124
  33. txt2ebook-0.1.146/docs/Makefile +0 -24
  34. txt2ebook-0.1.146/docs/make.bat +0 -35
  35. txt2ebook-0.1.146/docs/source/CHANGELOG.md +0 -1
  36. txt2ebook-0.1.146/docs/source/CONTRIBUTING.md +0 -1
  37. txt2ebook-0.1.146/docs/source/LICENSE.md +0 -1
  38. txt2ebook-0.1.146/docs/source/README.md +0 -1
  39. txt2ebook-0.1.146/docs/source/_static/logo.png +0 -0
  40. txt2ebook-0.1.146/docs/source/conf.py +0 -77
  41. txt2ebook-0.1.146/docs/source/index.rst +0 -11
  42. txt2ebook-0.1.146/docs/source/txt2ebook.formats.rst +0 -29
  43. txt2ebook-0.1.146/docs/source/txt2ebook.helpers.rst +0 -10
  44. txt2ebook-0.1.146/docs/source/txt2ebook.models.rst +0 -37
  45. txt2ebook-0.1.146/docs/source/txt2ebook.parsers.rst +0 -45
  46. txt2ebook-0.1.146/docs/source/txt2ebook.rst +0 -32
  47. txt2ebook-0.1.146/noxfile.py +0 -247
  48. txt2ebook-0.1.146/tests/__init__.py +0 -0
  49. txt2ebook-0.1.146/tests/conftest.py +0 -82
  50. txt2ebook-0.1.146/tests/fixtures/empty_file.txt +0 -0
  51. txt2ebook-0.1.146/tests/fixtures/missing_chapters.txt +0 -6
  52. txt2ebook-0.1.146/tests/fixtures/sample.txt +0 -37
  53. txt2ebook-0.1.146/tests/fixtures/sample_all_headers.txt +0 -31
  54. txt2ebook-0.1.146/tests/fixtures/sample_long_headers.txt +0 -35
  55. txt2ebook-0.1.146/tests/fixtures/sample_remove_wrapping.txt +0 -52
  56. txt2ebook-0.1.146/tests/fixtures/sample_unsorted_headers.txt +0 -33
  57. txt2ebook-0.1.146/tests/fixtures/sample_with_issues.txt +0 -15
  58. txt2ebook-0.1.146/tests/fixtures/sample_with_metadata.txt +0 -25
  59. txt2ebook-0.1.146/tests/test_filename_format_flag.py +0 -34
  60. txt2ebook-0.1.146/tests/test_format_option.py +0 -48
  61. txt2ebook-0.1.146/tests/test_header_number_flag.py +0 -33
  62. txt2ebook-0.1.146/tests/test_input_file_arg.py +0 -12
  63. txt2ebook-0.1.146/tests/test_language_option.py +0 -20
  64. txt2ebook-0.1.146/tests/test_output_file_arg.py +0 -19
  65. txt2ebook-0.1.146/tests/test_overwrite_flag.py +0 -10
  66. txt2ebook-0.1.146/tests/test_parser.py +0 -81
  67. txt2ebook-0.1.146/tests/test_purge_flag.py +0 -34
  68. txt2ebook-0.1.146/tests/test_quiet_flag.py +0 -11
  69. txt2ebook-0.1.146/tests/test_raise_warnings.py +0 -11
  70. txt2ebook-0.1.146/tests/test_sort_volume_and_chapter_flag.py +0 -31
  71. txt2ebook-0.1.146/tests/test_split_volume_and_chapter_flag.py +0 -36
  72. txt2ebook-0.1.146/tests/test_subcommand_env.py +0 -10
  73. txt2ebook-0.1.146/tests/test_subcommand_epub.py +0 -33
  74. txt2ebook-0.1.146/tests/test_subcommand_massage.py +0 -118
  75. txt2ebook-0.1.146/tests/test_test_parsing_flag.py +0 -15
  76. txt2ebook-0.1.146/tests/test_tokenizer.py +0 -114
  77. txt2ebook-0.1.146/tests/test_translator_option.py +0 -17
  78. txt2ebook-0.1.146/tests/test_txt2ebook.py +0 -8
  79. txt2ebook-0.1.146/tests/test_verbose_flag.py +0 -79
  80. txt2ebook-0.1.146/tests/test_volume_page_flag.py +0 -10
  81. txt2ebook-0.1.146/tests/test_zh_utils_zh_halfwidth_to_fullwidth.py +0 -8
  82. txt2ebook-0.1.146/tests/test_zh_utils_zh_numeric.py +0 -46
  83. txt2ebook-0.1.146/tests/test_zh_utils_zh_words_to_numbers.py +0 -29
  84. txt2ebook-0.1.146/uv.lock +0 -1799
  85. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/LICENSE.md +0 -0
  86. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/README.md +0 -0
  87. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/__main__.py +0 -0
  88. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/cli.py +0 -0
  89. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/exceptions.py +0 -0
  90. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/__init__.py +0 -0
  91. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/templates/__init__.py +0 -0
  92. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/templates/epub/__init__.py +0 -0
  93. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/templates/epub/clean.css +0 -0
  94. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/templates/epub/condense.css +0 -0
  95. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/formats/templates/epub/noindent.css +0 -0
  96. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/helpers/__init__.py +0 -0
  97. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/languages/__init__.py +0 -0
  98. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/languages/en.py +0 -0
  99. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/languages/zh_cn.py +0 -0
  100. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/languages/zh_tw.py +0 -0
  101. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/locales/en/LC_MESSAGES/txt2ebook.mo +0 -0
  102. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/locales/zh-cn/LC_MESSAGES/txt2ebook.mo +0 -0
  103. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/locales/zh-tw/LC_MESSAGES/txt2ebook.mo +0 -0
  104. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/models/__init__.py +0 -0
  105. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/models/chapter.py +0 -0
  106. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/models/volume.py +0 -0
  107. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/env.py +0 -0
  108. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/epub.py +0 -0
  109. {txt2ebook-0.1.146 → txt2ebook-0.1.148}/src/txt2ebook/subcommands/parse.py +0 -0
@@ -1,13 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: txt2ebook
3
- Version: 0.1.146
3
+ Version: 0.1.148
4
4
  Summary: CLI tool to convert txt file to ebook format
5
- Project-URL: Homepage, https://github.com/kianmeng/txt2ebook
6
- Project-URL: Repository, https://github.com/kianmeng/txt2ebook
7
- Author-email: Kian-Meng Ang <kianmeng@cpan.org>
8
- License-Expression: AGPL-3.0-or-later
9
- License-File: LICENSE.md
10
5
  Keywords: cjk,ebook,epub,gmi,latex,md,pdf,txt,typst
6
+ Author-email: Kian-Meng Ang <kianmeng@cpan.org>
7
+ Requires-Python: ~=3.9
8
+ Description-Content-Type: text/markdown
11
9
  Classifier: Development Status :: 4 - Beta
12
10
  Classifier: Environment :: Console
13
11
  Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
@@ -25,21 +23,22 @@ Classifier: Topic :: Text Processing :: Filters
25
23
  Classifier: Topic :: Text Processing :: General
26
24
  Classifier: Topic :: Text Processing :: Markup :: HTML
27
25
  Classifier: Topic :: Text Processing :: Markup :: Markdown
28
- Requires-Python: ~=3.9
29
- Requires-Dist: bs4<0.0.2,>=0.0.1
30
- Requires-Dist: cjkwrap~=2.2
31
- Requires-Dist: ebooklib<0.18,>=0.17.1
32
- Requires-Dist: importlib-resources<7,>=6.1.1
33
- Requires-Dist: jieba<0.43,>=0.42.1
34
- Requires-Dist: langdetect<2,>=1.0.9
35
- Requires-Dist: lxml<6,>=5.2.2
36
- Requires-Dist: pylatex<2,>=1.4.2
26
+ License-File: LICENSE.md
27
+ Requires-Dist: CJKwrap~=2.2
28
+ Requires-Dist: EbookLib>=0.17.1,<0.18
29
+ Requires-Dist: bs4>=0.0.1,<0.0.2
30
+ Requires-Dist: importlib-resources>=6.1.1,<7
31
+ Requires-Dist: jieba>=0.42.1,<0.43
32
+ Requires-Dist: langdetect>=1.0.9,<2
33
+ Requires-Dist: lxml>=5.2.2,<6
34
+ Requires-Dist: pylatex>=1.4.2,<2
37
35
  Requires-Dist: pypandoc~=1.11
38
- Requires-Dist: regex<2022,>=2021.11.10
39
- Requires-Dist: reportlab<5,>=4.0.0
40
- Requires-Dist: typing-extensions<5,>=4.5.0
36
+ Requires-Dist: regex>=2021.11.10,<2022
37
+ Requires-Dist: reportlab>=4.0.0,<5
38
+ Requires-Dist: typing-extensions>=4.5.0,<5
41
39
  Requires-Dist: typst>=0.13.0
42
- Description-Content-Type: text/markdown
40
+ Project-URL: Homepage, https://github.com/kianmeng/txt2ebook
41
+ Project-URL: Repository, https://github.com/kianmeng/txt2ebook
43
42
 
44
43
  # txt2ebook
45
44
 
@@ -151,3 +150,4 @@ The fish logo used in the documentation generated by Sphinx is a public domain
151
150
  drawing of Troschel's parrotfish (Chlorurus troschelii Var. A.) from
152
151
  <https://commons.wikimedia.org/entity/M18506436>.
153
152
  18506436>.
153
+
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "txt2ebook"
3
- version = "0.1.146"
3
+ version = "0.1.148"
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"
7
7
  readme = "README.md"
8
- license = "AGPL-3.0-or-later"
8
+ license = {file = "LICENSE.md"}
9
9
  keywords = [
10
10
  "cjk",
11
11
  "ebook",
@@ -84,5 +84,5 @@ dev = [
84
84
  ]
85
85
 
86
86
  [build-system]
87
- requires = ["hatchling"]
88
- build-backend = "hatchling.build"
87
+ requires = ["flit_core"]
88
+ build-backend = "flit_core.buildapi"
@@ -38,7 +38,9 @@ def setup_logger(config: argparse.Namespace) -> None:
38
38
  return
39
39
 
40
40
  log_level = logging.DEBUG if config.debug else logging.INFO
41
- log_format = "%(levelname)5s: %(message)s" if config.debug else "%(message)s"
41
+ log_format = (
42
+ "%(levelname)5s: %(message)s" if config.debug else "%(message)s"
43
+ )
42
44
 
43
45
  logging.basicConfig(
44
46
  level=log_level,
@@ -48,7 +50,9 @@ def setup_logger(config: argparse.Namespace) -> None:
48
50
  )
49
51
 
50
52
 
51
- def log_or_raise_on_warning(message: str, raise_on_warning: bool = False) -> None:
53
+ def log_or_raise_on_warning(
54
+ message: str, raise_on_warning: bool = False
55
+ ) -> None:
52
56
  """Logs a warning message or raises an exception.
53
57
 
54
58
  Args:
@@ -126,7 +126,9 @@ class BaseWriter(ABC):
126
126
  # do not create to output folder when we explicit set the output path
127
127
  # and file
128
128
  if self.config.output_file:
129
- return Path(file.parent, lower_underscore(file.stem)).with_suffix(extension)
129
+ return Path(file.parent, lower_underscore(file.stem)).with_suffix(
130
+ extension
131
+ )
130
132
 
131
133
  return Path(
132
134
  file.parent, self.config.output_folder, lower_underscore(file.stem)
@@ -139,7 +141,12 @@ class BaseWriter(ABC):
139
141
  self._("translator:") + ",".join(self.book.translators),
140
142
  self._("tag:") + ",".join(self.book.tags),
141
143
  ]
142
- return "---\n" + "\n".join(metadata) + "\n---" + self.config.paragraph_separator
144
+ return (
145
+ "---\n"
146
+ + "\n".join(metadata)
147
+ + "\n---"
148
+ + self.config.paragraph_separator
149
+ )
143
150
 
144
151
  def _to_toc(self, list_symbol, header_symbol="") -> str:
145
152
  toc = ""
@@ -81,7 +81,9 @@ class EpubWriter(BaseWriter):
81
81
  logger.debug("Create separate volume page: %s", section)
82
82
  book.toc.append((html_volume, html_chapters))
83
83
  else:
84
- book.toc.append((epub.Section(section.title), html_chapters))
84
+ book.toc.append(
85
+ (epub.Section(section.title), html_chapters)
86
+ )
85
87
 
86
88
  if isinstance(section, Chapter):
87
89
  html_chapter = self._build_chapter(section)
@@ -113,12 +115,16 @@ class EpubWriter(BaseWriter):
113
115
  book.add_item(book_css)
114
116
 
115
117
  nav = epub.EpubNav()
116
- nav.add_link(href="style/book.css", rel="stylesheet", type="text/css")
118
+ nav.add_link(
119
+ href="style/book.css", rel="stylesheet", type="text/css"
120
+ )
117
121
  book.add_item(nav)
118
122
  book.spine.append("nav")
119
123
 
120
124
  except FileNotFoundError as error:
121
- logger.error("Unknown EPUB template name: %s", self.config.epub_template)
125
+ logger.error(
126
+ "Unknown EPUB template name: %s", self.config.epub_template
127
+ )
122
128
  raise SystemExit() from error
123
129
 
124
130
  def _gen_id(self) -> str:
@@ -143,7 +149,9 @@ class EpubWriter(BaseWriter):
143
149
  lang=self.book.language,
144
150
  content=html,
145
151
  )
146
- cover.add_link(href="style/book.css", rel="stylesheet", type="text/css")
152
+ cover.add_link(
153
+ href="style/book.css", rel="stylesheet", type="text/css"
154
+ )
147
155
  return cover
148
156
 
149
157
  def _build_volume(self, volume: Volume) -> epub.EpubHtml:
@@ -166,7 +174,9 @@ class EpubWriter(BaseWriter):
166
174
  lang=self.book.language,
167
175
  content=html,
168
176
  )
169
- epub_html.add_link(href="style/book.css", rel="stylesheet", type="text/css")
177
+ epub_html.add_link(
178
+ href="style/book.css", rel="stylesheet", type="text/css"
179
+ )
170
180
 
171
181
  return epub_html
172
182
 
@@ -192,6 +202,8 @@ class EpubWriter(BaseWriter):
192
202
  lang=self.book.language,
193
203
  content=html,
194
204
  )
195
- epub_html.add_link(href="style/book.css", rel="stylesheet", type="text/css")
205
+ epub_html.add_link(
206
+ href="style/book.css", rel="stylesheet", type="text/css"
207
+ )
196
208
 
197
209
  return epub_html
@@ -96,7 +96,9 @@ class GmiWriter(BaseWriter):
96
96
  export_filename.parent.mkdir(parents=True, exist_ok=True)
97
97
  logger.info("Creating %s", export_filename)
98
98
  with open(export_filename, "w", encoding="utf8") as file:
99
- file.write(self._to_volume_chapter_txt(section, chapter))
99
+ file.write(
100
+ self._to_volume_chapter_txt(section, chapter)
101
+ )
100
102
  ct_seq = ct_seq + 1
101
103
  if isinstance(section, Chapter):
102
104
  filename = lower_underscore(
@@ -145,7 +147,10 @@ class GmiWriter(BaseWriter):
145
147
  f"# {volume.title}"
146
148
  + self.config.paragraph_separator
147
149
  + self.config.paragraph_separator.join(
148
- [self._to_chapter_txt(chapter, True) for chapter in volume.chapters]
150
+ [
151
+ self._to_chapter_txt(chapter, True)
152
+ for chapter in volume.chapters
153
+ ]
149
154
  )
150
155
  )
151
156
 
@@ -95,7 +95,9 @@ class MdWriter(BaseWriter):
95
95
  export_filename.parent.mkdir(parents=True, exist_ok=True)
96
96
  logger.info("Creating %s", export_filename)
97
97
  with open(export_filename, "w", encoding="utf8") as file:
98
- file.write(self._to_volume_chapter_txt(section, chapter))
98
+ file.write(
99
+ self._to_volume_chapter_txt(section, chapter)
100
+ )
99
101
  ct_seq = ct_seq + 1
100
102
  if isinstance(section, Chapter):
101
103
  filename = lower_underscore(
@@ -144,7 +146,10 @@ class MdWriter(BaseWriter):
144
146
  f"# {volume.title}"
145
147
  + self.config.paragraph_separator
146
148
  + self.config.paragraph_separator.join(
147
- [self._to_chapter_txt(chapter, True) for chapter in volume.chapters]
149
+ [
150
+ self._to_chapter_txt(chapter, True)
151
+ for chapter in volume.chapters
152
+ ]
148
153
  )
149
154
  )
150
155
 
@@ -153,7 +153,9 @@ class PdfWriter(BaseWriter):
153
153
  canvas.restoreState()
154
154
 
155
155
  def _get_pagesize(self) -> Tuple:
156
- page_size = self.config.page_size or self.langconf.DEFAULT_PDF_PAGE_SIZE
156
+ page_size = (
157
+ self.config.page_size or self.langconf.DEFAULT_PDF_PAGE_SIZE
158
+ )
157
159
  return portrait(getattr(reportlab.lib.pagesizes, page_size.upper()))
158
160
 
159
161
  def _init_styles(self) -> None:
@@ -100,7 +100,9 @@ class TexWriter(BaseWriter):
100
100
  doc.append(NoEsc(r"\maketitle"))
101
101
  doc.append(NoEsc(r"\thispagestyle{empty}"))
102
102
  doc.append(NoEsc(r"\addtocontents{toc}{\protect\pagestyle{empty}}"))
103
- doc.append(NoEsc(r"\addtocontents{toc}{\protect\thispagestyle{empty}}"))
103
+ doc.append(
104
+ NoEsc(r"\addtocontents{toc}{\protect\thispagestyle{empty}}")
105
+ )
104
106
  doc.append(NoEsc(r"\tableofcontents"))
105
107
  doc.append(NoEsc(r"\pagestyle{empty}"))
106
108
  doc.append(NoEsc(r"\cleardoublepage"))
@@ -126,7 +128,9 @@ class TexWriter(BaseWriter):
126
128
 
127
129
  filename = str(new_filename.parent / new_filename.stem)
128
130
  pdf_filename = Path(filename).with_suffix(".pdf")
129
- doc.generate_pdf(filename, compiler="latexmk", clean_tex=self.config.clean_tex)
131
+ doc.generate_pdf(
132
+ filename, compiler="latexmk", clean_tex=self.config.clean_tex
133
+ )
130
134
  logger.info("Generate PDF file: %s", pdf_filename.resolve())
131
135
 
132
136
  if self.config.open:
@@ -105,7 +105,9 @@ class TxtWriter(BaseWriter):
105
105
  export_filename.parent.mkdir(parents=True, exist_ok=True)
106
106
  logger.info("Creating %s", export_filename)
107
107
  with open(export_filename, "w", encoding="utf8") as file:
108
- file.write(self._to_volume_chapter_txt(section, chapter))
108
+ file.write(
109
+ self._to_volume_chapter_txt(section, chapter)
110
+ )
109
111
  ct_seq = ct_seq + 1
110
112
  if isinstance(section, Chapter):
111
113
  filename = lower_underscore(
@@ -132,7 +134,9 @@ class TxtWriter(BaseWriter):
132
134
  ymd_hms = dt.now().strftime("%Y%m%d_%H%M%S")
133
135
  new_filename = Path(
134
136
  txt_filename.resolve().parent.joinpath(
135
- lower_underscore(txt_filename.stem + "_" + ymd_hms + ".txt")
137
+ lower_underscore(
138
+ txt_filename.stem + "_" + ymd_hms + ".txt"
139
+ )
136
140
  )
137
141
  )
138
142
 
@@ -175,7 +175,10 @@ class TypWriter(BaseWriter):
175
175
  f"= {volume.title}"
176
176
  + self.config.paragraph_separator
177
177
  + self.config.paragraph_separator.join(
178
- [self._to_chapter_txt(chapter, True) for chapter in volume.chapters]
178
+ [
179
+ self._to_chapter_txt(chapter, True)
180
+ for chapter in volume.chapters
181
+ ]
179
182
  )
180
183
  )
181
184
 
@@ -1,26 +1,26 @@
1
- #: src/txt2ebook/formats/base.py:137
1
+ #: src/txt2ebook/formats/base.py:139
2
2
  msgid "title:"
3
3
  msgstr "Title:"
4
4
 
5
- #: src/txt2ebook/formats/base.py:138
5
+ #: src/txt2ebook/formats/base.py:140
6
6
  msgid "author:"
7
7
  msgstr "Author:"
8
8
 
9
- #: src/txt2ebook/formats/base.py:139
9
+ #: src/txt2ebook/formats/base.py:141
10
10
  msgid "translator:"
11
11
  msgstr "Translator:"
12
12
 
13
- #: src/txt2ebook/formats/base.py:140
13
+ #: src/txt2ebook/formats/base.py:142
14
14
  msgid "tag:"
15
15
  msgstr "Tag:"
16
16
 
17
- #: src/txt2ebook/formats/base.py:146 src/txt2ebook/formats/gmi.py:62
17
+ #: src/txt2ebook/formats/base.py:153 src/txt2ebook/formats/gmi.py:62
18
18
  #: src/txt2ebook/formats/md.py:61 src/txt2ebook/formats/pdf.py:130
19
19
  #: src/txt2ebook/formats/txt.py:71
20
20
  msgid "toc"
21
21
  msgstr "Table of Content"
22
22
 
23
- #: src/txt2ebook/formats/epub.py:141
23
+ #: src/txt2ebook/formats/epub.py:147
24
24
  msgid "cover"
25
25
  msgstr "Cover"
26
26
 
@@ -1,26 +1,26 @@
1
- #: src/txt2ebook/formats/base.py:137
1
+ #: src/txt2ebook/formats/base.py:139
2
2
  msgid "title:"
3
3
  msgstr ""
4
4
 
5
- #: src/txt2ebook/formats/base.py:138
5
+ #: src/txt2ebook/formats/base.py:140
6
6
  msgid "author:"
7
7
  msgstr ""
8
8
 
9
- #: src/txt2ebook/formats/base.py:139
9
+ #: src/txt2ebook/formats/base.py:141
10
10
  msgid "translator:"
11
11
  msgstr ""
12
12
 
13
- #: src/txt2ebook/formats/base.py:140
13
+ #: src/txt2ebook/formats/base.py:142
14
14
  msgid "tag:"
15
15
  msgstr ""
16
16
 
17
- #: src/txt2ebook/formats/base.py:146 src/txt2ebook/formats/gmi.py:62
17
+ #: src/txt2ebook/formats/base.py:153 src/txt2ebook/formats/gmi.py:62
18
18
  #: src/txt2ebook/formats/md.py:61 src/txt2ebook/formats/pdf.py:130
19
19
  #: src/txt2ebook/formats/txt.py:71
20
20
  msgid "toc"
21
21
  msgstr ""
22
22
 
23
- #: src/txt2ebook/formats/epub.py:141
23
+ #: src/txt2ebook/formats/epub.py:147
24
24
  msgid "cover"
25
25
  msgstr ""
26
26
 
@@ -1,26 +1,26 @@
1
- #: src/txt2ebook/formats/base.py:137
1
+ #: src/txt2ebook/formats/base.py:139
2
2
  msgid "title:"
3
3
  msgstr "书名:"
4
4
 
5
- #: src/txt2ebook/formats/base.py:138
5
+ #: src/txt2ebook/formats/base.py:140
6
6
  msgid "author:"
7
7
  msgstr "作者:"
8
8
 
9
- #: src/txt2ebook/formats/base.py:139
9
+ #: src/txt2ebook/formats/base.py:141
10
10
  msgid "translator:"
11
11
  msgstr "翻译:"
12
12
 
13
- #: src/txt2ebook/formats/base.py:140
13
+ #: src/txt2ebook/formats/base.py:142
14
14
  msgid "tag:"
15
15
  msgstr "票签:"
16
16
 
17
- #: src/txt2ebook/formats/base.py:146 src/txt2ebook/formats/gmi.py:62
17
+ #: src/txt2ebook/formats/base.py:153 src/txt2ebook/formats/gmi.py:62
18
18
  #: src/txt2ebook/formats/md.py:61 src/txt2ebook/formats/pdf.py:130
19
19
  #: src/txt2ebook/formats/txt.py:71
20
20
  msgid "toc"
21
21
  msgstr "目录"
22
22
 
23
- #: src/txt2ebook/formats/epub.py:141
23
+ #: src/txt2ebook/formats/epub.py:147
24
24
  msgid "cover"
25
25
  msgstr "封面"
26
26
 
@@ -1,26 +1,26 @@
1
- #: src/txt2ebook/formats/base.py:137
1
+ #: src/txt2ebook/formats/base.py:139
2
2
  msgid "title:"
3
3
  msgstr "书名:"
4
4
 
5
- #: src/txt2ebook/formats/base.py:138
5
+ #: src/txt2ebook/formats/base.py:140
6
6
  msgid "author:"
7
7
  msgstr "作者:"
8
8
 
9
- #: src/txt2ebook/formats/base.py:139
9
+ #: src/txt2ebook/formats/base.py:141
10
10
  msgid "translator:"
11
11
  msgstr "翻译:"
12
12
 
13
- #: src/txt2ebook/formats/base.py:140
13
+ #: src/txt2ebook/formats/base.py:142
14
14
  msgid "tag:"
15
15
  msgstr "标签:"
16
16
 
17
- #: src/txt2ebook/formats/base.py:146 src/txt2ebook/formats/gmi.py:62
17
+ #: src/txt2ebook/formats/base.py:153 src/txt2ebook/formats/gmi.py:62
18
18
  #: src/txt2ebook/formats/md.py:61 src/txt2ebook/formats/pdf.py:130
19
19
  #: src/txt2ebook/formats/txt.py:71
20
20
  msgid "toc"
21
21
  msgstr "目录"
22
22
 
23
- #: src/txt2ebook/formats/epub.py:141
23
+ #: src/txt2ebook/formats/epub.py:147
24
24
  msgid "cover"
25
25
  msgstr "封面"
26
26
 
@@ -60,7 +60,9 @@ class Book:
60
60
  try:
61
61
  return format_options[filename_format]
62
62
  except KeyError:
63
- raise AttributeError(f"Invalid filename format: '{filename_format}'!")
63
+ raise AttributeError(
64
+ f"Invalid filename format: '{filename_format}'!"
65
+ )
64
66
 
65
67
  def debug(self, verbosity: int = 1) -> None:
66
68
  """Dump debug log of sections in self.toc."""
@@ -57,8 +57,8 @@ class Parser:
57
57
  """
58
58
  tokenizer = Tokenizer(self.raw_content, self.config)
59
59
 
60
- (book_title, authors, translators, tags, index, toc) = self.parse_tokens(
61
- tokenizer
60
+ (book_title, authors, translators, tags, index, toc) = (
61
+ self.parse_tokens(tokenizer)
62
62
  )
63
63
 
64
64
  book = Book(
@@ -103,13 +103,17 @@ class Parser:
103
103
  match = re.match(rf"第([{self.langconf.HALFWIDTH_NUMS}]*)", words)
104
104
  if match and match.group(1) != "":
105
105
  header_nums = match.group(1)
106
- return words.replace(header_nums, str(header_nums).rjust(length, "0"))
106
+ return words.replace(
107
+ header_nums, str(header_nums).rjust(length, "0")
108
+ )
107
109
 
108
110
  # left pad the section number if found as fullwidth integer
109
111
  match = re.match(rf"第([{self.langconf.FULLWIDTH_NUMS}]*)", words)
110
112
  if match and match.group(1) != "":
111
113
  header_nums = match.group(1)
112
- return words.replace(header_nums, str(header_nums).rjust(length, "0"))
114
+ return words.replace(
115
+ header_nums, str(header_nums).rjust(length, "0")
116
+ )
113
117
 
114
118
  replaced_words = zh_words_to_numbers(words, length=length)
115
119
 
@@ -148,7 +152,8 @@ class Parser:
148
152
  if (
149
153
  token.type not in ["CHAPTER", "PARAGRAPH"]
150
154
  or (
151
- token.type == "CHAPTER" and self.config.verbose >= chapter_verbosity
155
+ token.type == "CHAPTER"
156
+ and self.config.verbose >= chapter_verbosity
152
157
  )
153
158
  or (
154
159
  token.type == "PARAGRAPH"
@@ -24,7 +24,8 @@ def build_subparser(subparsers):
24
24
  iter_namespace = pkgutil.iter_modules(__path__, __name__ + ".")
25
25
 
26
26
  subcommands = {
27
- name: importlib.import_module(name) for finder, name, ispkg in iter_namespace
27
+ name: importlib.import_module(name)
28
+ for finder, name, ispkg in iter_namespace
28
29
  }
29
30
 
30
31
  for subcommand in subcommands.values():
@@ -27,7 +27,9 @@ logger = logging.getLogger(__name__)
27
27
 
28
28
  def build_subparser(subparsers) -> None:
29
29
  """Build the subparser."""
30
- gmi_parser = subparsers.add_parser("gmi", help="generate ebook in Gemtext format")
30
+ gmi_parser = subparsers.add_parser(
31
+ "gmi", help="generate ebook in Gemtext format"
32
+ )
31
33
 
32
34
  gmi_parser.set_defaults(func=run)
33
35
 
@@ -25,11 +25,8 @@ import cjkwrap
25
25
  import regex as re
26
26
  from bs4 import UnicodeDammit
27
27
 
28
- from txt2ebook import detect_and_expect_language
29
28
  from txt2ebook.exceptions import EmptyFileError
30
- from txt2ebook.formats.txt import TxtWriter
31
29
  from txt2ebook.models.book import Book
32
- from txt2ebook.parser import Parser
33
30
  from txt2ebook.zh_utils import zh_halfwidth_to_fullwidth, zh_words_to_numbers
34
31
 
35
32
  logger = logging.getLogger(__name__)
@@ -258,7 +255,9 @@ def header_number(args: argparse.Namespace, book: Book) -> Book:
258
255
  for toc_item in book.toc:
259
256
  toc_type = type(toc_item).__name__
260
257
  if toc_type in seq_lengths:
261
- toc_item.title = words_to_nums(args, toc_item.title, seq_lengths[toc_type])
258
+ toc_item.title = words_to_nums(
259
+ args, toc_item.title, seq_lengths[toc_type]
260
+ )
262
261
 
263
262
  return book
264
263
 
@@ -365,7 +364,9 @@ def do_delete_regex(args, content: str) -> str:
365
364
  str: The formatted book content.
366
365
  """
367
366
  for delete_regex in args.re_delete:
368
- content = re.sub(re.compile(rf"{delete_regex}", re.MULTILINE), "", content)
367
+ content = re.sub(
368
+ re.compile(rf"{delete_regex}", re.MULTILINE), "", content
369
+ )
369
370
  return content
370
371
 
371
372
 
@@ -27,7 +27,9 @@ logger = logging.getLogger(__name__)
27
27
 
28
28
  def build_subparser(subparsers) -> None:
29
29
  """Build the subparser."""
30
- md_parser = subparsers.add_parser("md", help="generate ebook in Markdown format")
30
+ md_parser = subparsers.add_parser(
31
+ "md", help="generate ebook in Markdown format"
32
+ )
31
33
 
32
34
  md_parser.set_defaults(func=run)
33
35
 
@@ -28,7 +28,9 @@ logger = logging.getLogger(__name__)
28
28
 
29
29
  def build_subparser(subparsers) -> None:
30
30
  """Build the subparser."""
31
- pdf_parser = subparsers.add_parser("pdf", help="generate ebook in Markdown format")
31
+ pdf_parser = subparsers.add_parser(
32
+ "pdf", help="generate ebook in Markdown format"
33
+ )
32
34
 
33
35
  pdf_parser.set_defaults(func=run)
34
36
 
@@ -27,7 +27,9 @@ logger = logging.getLogger(__name__)
27
27
 
28
28
  def build_subparser(subparsers) -> None:
29
29
  """Build the subparser."""
30
- tex_parser = subparsers.add_parser("tex", help="generate ebook in TeX/PDF format")
30
+ tex_parser = subparsers.add_parser(
31
+ "tex", help="generate ebook in TeX/PDF format"
32
+ )
31
33
 
32
34
  tex_parser.add_argument(
33
35
  "input_file",
@@ -28,7 +28,9 @@ logger = logging.getLogger(__name__)
28
28
 
29
29
  def build_subparser(subparsers) -> None:
30
30
  """Build the subparser."""
31
- typ_parser = subparsers.add_parser("typ", help="generate ebook in Typst format")
31
+ typ_parser = subparsers.add_parser(
32
+ "typ", help="generate ebook in Typst format"
33
+ )
32
34
 
33
35
  typ_parser.set_defaults(func=run)
34
36
 
@@ -134,7 +134,9 @@ class Tokenizer:
134
134
  match = re.search(regex, line)
135
135
  if match:
136
136
  token_value = match.group(1).strip()
137
- token = Token(token_type, token_value, self._lineno(token_value))
137
+ token = Token(
138
+ token_type, token_value, self._lineno(token_value)
139
+ )
138
140
  self.tokens.append(token)
139
141
 
140
142
  def _extract_metadata(self) -> List:
@@ -172,7 +174,9 @@ class Tokenizer:
172
174
  metadata_block_re = (
173
175
  rf"^(?:{self.metadata_marker})\n(.*)\n(?:{self.metadata_marker})$"
174
176
  )
175
- match = re.search(metadata_block_re, self.raw_content, re.MULTILINE | re.DOTALL)
177
+ match = re.search(
178
+ metadata_block_re, self.raw_content, re.MULTILINE | re.DOTALL
179
+ )
176
180
 
177
181
  if match:
178
182
  # Content starts after the matched metadata block
@@ -217,7 +221,10 @@ class Tokenizer:
217
221
  rf"^{self.langconf.DEFAULT_RE_VOLUME}\s*"
218
222
  rf"{self.langconf.DEFAULT_RE_CHAPTER}"
219
223
  )
220
- if hasattr(self.config, "re_volume_chapter") and self.config.re_volume_chapter:
224
+ if (
225
+ hasattr(self.config, "re_volume_chapter")
226
+ and self.config.re_volume_chapter
227
+ ):
221
228
  re_volume_chapter = self.config.re_volume_chapter[0]
222
229
 
223
230
  match = re.search(re_volume_chapter, line)
@@ -121,7 +121,10 @@ def zh_words_to_numbers(words: str, **kwargs: Any) -> str:
121
121
  for word_grp in re.findall("..?", found_word):
122
122
  if len(word_grp) == 2:
123
123
  # 零 or 十
124
- if zh_numeric(word_grp[0]) == 0.0 or zh_numeric(word_grp[0]) == 10.0:
124
+ if (
125
+ zh_numeric(word_grp[0]) == 0.0
126
+ or zh_numeric(word_grp[0]) == 10.0
127
+ ):
125
128
  header_nums += int(
126
129
  zh_numeric(word_grp[0]) + zh_numeric(word_grp[1])
127
130
  )