txt2ebook 0.1.65__py3-none-any.whl → 0.1.67__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/__init__.py CHANGED
@@ -21,7 +21,7 @@ import sys
21
21
 
22
22
  logger = logging.getLogger(__name__)
23
23
 
24
- __version__ = "0.1.65"
24
+ __version__ = "0.1.67"
25
25
 
26
26
 
27
27
  def setup_logger(config: argparse.Namespace) -> None:
@@ -25,10 +25,11 @@ from txt2ebook.formats.gmi import GmiWriter
25
25
  from txt2ebook.formats.md import MdWriter
26
26
  from txt2ebook.formats.pdf import PdfWriter
27
27
  from txt2ebook.formats.txt import TxtWriter
28
+ from txt2ebook.formats.typ import TypWriter
28
29
  from txt2ebook.helpers import load_class, to_classname
29
30
  from txt2ebook.models import Book
30
31
 
31
- EBOOK_FORMATS = ["epub", "gmi", "md", "pdf", "txt"]
32
+ EBOOK_FORMATS = ["epub", "gmi", "md", "pdf", "txt", "typ"]
32
33
  PAGE_SIZES = [
33
34
  "a0",
34
35
  "a1",
@@ -82,4 +83,5 @@ __all__ = [
82
83
  "PAGE_SIZES",
83
84
  "PdfWriter",
84
85
  "TxtWriter",
86
+ "TypWriter",
85
87
  ]
@@ -0,0 +1,165 @@
1
+ # Copyright (C) 2021,2022,2023 Kian-Meng Ang
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU Affero General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Affero General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
15
+
16
+ """Convert and back source text file into text as well."""
17
+
18
+ import importlib.resources as importlib_res
19
+ import logging
20
+ import textwrap
21
+
22
+ import importlib_resources
23
+ import typst
24
+
25
+ from txt2ebook.formats.base import BaseWriter
26
+ from txt2ebook.models import Chapter, Volume
27
+
28
+ # workaround for Python 3.8
29
+ # see https://github.com/messense/typst-py/issues/12#issuecomment-1812956252
30
+ setattr(importlib_res, "files", importlib_resources.files)
31
+ setattr(importlib_res, "as_file", importlib_resources.as_file)
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+
36
+ class TypWriter(BaseWriter):
37
+ """Module for writing ebook in Typst (typ) format."""
38
+
39
+ def write(self) -> None:
40
+ """Generate Typst files."""
41
+ self._new_file()
42
+
43
+ def _new_file(self) -> None:
44
+ new_filename = self._output_filename(".typ")
45
+ new_filename.parent.mkdir(parents=True, exist_ok=True)
46
+
47
+ with open(new_filename, "w", encoding="utf8") as file:
48
+ logger.info("Generate Typst file: %s", new_filename.resolve())
49
+ file.write(self._to_typ())
50
+
51
+ pdf_filename = new_filename.with_suffix(".pdf")
52
+ logger.info("Generate PDF file: %s", pdf_filename.resolve())
53
+ typst.compile(new_filename, output=pdf_filename)
54
+
55
+ def _to_typ(self) -> str:
56
+ return (
57
+ self._to_metadata_typ()
58
+ + self._to_cover()
59
+ + self._to_outline()
60
+ + '#set page(numbering: "1")'
61
+ + "\n"
62
+ + "#counter(page).update(1)"
63
+ + "\n"
64
+ + self._to_body_txt()
65
+ )
66
+
67
+ def _to_cover(self) -> str:
68
+ return textwrap.dedent(
69
+ f"""
70
+ #set page(paper: "a5", numbering: none)
71
+ #align(center, text(17pt)[{self.book.title}])
72
+ #pagebreak()
73
+
74
+ """
75
+ )
76
+
77
+ def _to_outline(self) -> str:
78
+ return (
79
+ textwrap.dedent(
80
+ """
81
+ #set page(paper: "a5", numbering: none)
82
+ #outline(title: [目录], indent: 2em,)
83
+ #pagebreak()
84
+ """
85
+ )
86
+ if self.config.with_toc
87
+ else ""
88
+ )
89
+
90
+ def _to_metadata_typ(self) -> str:
91
+ return textwrap.dedent(
92
+ """
93
+ #set page(
94
+ paper: "a5",
95
+ margin: (x: 2.5cm, y: 2.5cm),
96
+ numbering: "1",
97
+ number-align: right,
98
+ )
99
+ #show heading.where(
100
+ level: 1
101
+ ): it => block(width: 100%)[
102
+ #set align(center)
103
+ #set text(12pt, weight: "regular")
104
+ #smallcaps(it.body)
105
+ ]
106
+
107
+ #show heading.where(
108
+ level: 2
109
+ ): it => block(width: 100%)[
110
+ #set align(center)
111
+ #set text(12pt, weight: "regular")
112
+ #smallcaps(it.body)
113
+ ]
114
+
115
+ #set par(
116
+ justify: true,
117
+ leading: 1em,
118
+ first-line-indent: 2em,
119
+ )
120
+ #set text(
121
+ font: "Noto Serif CJK SC",
122
+ size: 11pt,
123
+ )
124
+
125
+ """
126
+ )
127
+
128
+ def _to_body_txt(self) -> str:
129
+ content = []
130
+ for section in self.book.toc:
131
+ if isinstance(section, Volume):
132
+ content.append(self._to_volume_txt(section))
133
+ if isinstance(section, Chapter):
134
+ content.append(self._to_chapter_txt(section))
135
+
136
+ return f"{self.config.paragraph_separator}".join(content)
137
+
138
+ def _to_volume_txt(self, volume) -> str:
139
+ return (
140
+ f"= {volume.title}"
141
+ + self.config.paragraph_separator
142
+ + self.config.paragraph_separator.join(
143
+ [
144
+ self._to_chapter_txt(chapter, True)
145
+ for chapter in volume.chapters
146
+ ]
147
+ )
148
+ )
149
+
150
+ def _to_chapter_txt(self, chapter, part_of_volume=False) -> str:
151
+ header = "==" if part_of_volume else "="
152
+ return (
153
+ f"{header} {chapter.title}"
154
+ + self.config.paragraph_separator
155
+ + self.config.paragraph_separator.join(chapter.paragraphs)
156
+ + "#pagebreak()"
157
+ )
158
+
159
+ def _to_volume_chapter_txt(self, volume, chapter) -> str:
160
+ return (
161
+ f"= {volume.title} {chapter.title}"
162
+ + self.config.paragraph_separator
163
+ + self.config.paragraph_separator.join(chapter.paragraphs)
164
+ + "#pagebreak()"
165
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: txt2ebook
3
- Version: 0.1.65
3
+ Version: 0.1.67
4
4
  Summary: CLI tool to convert txt file to ebook format
5
5
  Home-page: https://github.com/kianmeng/txt2ebook
6
6
  License: AGPL-3.0-or-later
@@ -29,11 +29,13 @@ Classifier: Topic :: Text Processing :: Markup :: Markdown
29
29
  Requires-Dist: CJKwrap (>=2.2,<3.0)
30
30
  Requires-Dist: EbookLib (>=0.17.1,<0.18.0)
31
31
  Requires-Dist: bs4 (>=0.0.1,<0.0.2)
32
+ Requires-Dist: importlib-resources (>=6.1.1,<7.0.0)
32
33
  Requires-Dist: langdetect (>=1.0.9,<2.0.0)
33
34
  Requires-Dist: pypandoc (>=1.11,<2.0)
34
35
  Requires-Dist: regex (>=2021.11.10,<2022.0.0)
35
36
  Requires-Dist: reportlab (>=4.0.0,<5.0.0)
36
37
  Requires-Dist: typing-extensions (>=4.5.0,<5.0.0)
38
+ Requires-Dist: typst (>=0.10.0,<0.11.0)
37
39
  Project-URL: Repository, https://github.com/kianmeng/txt2ebook
38
40
  Description-Content-Type: text/markdown
39
41
 
@@ -64,7 +66,8 @@ txt2ebook --help
64
66
  ```
65
67
 
66
68
  ```console
67
- usage: txt2ebook [-of OUTPUT_FOLDER] [-p] [-f {epub,gmi,md,pdf,txt}]
69
+
70
+ usage: txt2ebook [-of OUTPUT_FOLDER] [-p] [-f {epub,gmi,md,pdf,txt,typ
68
71
  [-t TITLE] [-l LANGUAGE] [-a AUTHOR] [-tr TRANSLATOR]
69
72
  [-c IMAGE_FILENAME] [-w WIDTH] [-ff FILENAME_FORMAT]
70
73
  [-ps SEPARATOR] [-pz PAGE_SIZE] [-rd REGEX] [-rvc REGEX]
@@ -91,7 +94,7 @@ optional arguments:
91
94
  set default output folder (default: 'output')
92
95
  -p, --purge
93
96
  remove converted ebooks specified by --output-folder option (default: 'False')
94
- -f {epub,gmi,md,pdf,txt}, --format {epub,gmi,md,pdf,txt}
97
+ -f {epub,gmi,md,pdf,txt,typ}, --format {epub,gmi,md,pdf,txt,typ}
95
98
  ebook format (default: 'epub')
96
99
  -t TITLE, --title TITLE
97
100
  title of the ebook (default: 'None')
@@ -1,7 +1,7 @@
1
- txt2ebook/__init__.py,sha256=lqueNor7XLbPbZLGWru8TS1WNMhCIZC0UPBXew6eC1U,1760
1
+ txt2ebook/__init__.py,sha256=XoYe79YmaVaV6agUP-YeNdSwBUa6OXzPa3Q8g6v5ooM,1760
2
2
  txt2ebook/__main__.py,sha256=69yaheH-Fv2VIPS0T9kiVmiMluSgLGvwo1fa7badX2I,845
3
3
  txt2ebook/exceptions.py,sha256=Y6rqjXhiKIxNeKWVqvAqsUAOaBFKxlUE5Tm5EBcoi9w,837
4
- txt2ebook/formats/__init__.py,sha256=lVclUeBZ0Rf_zEAYyzc6m5ak2wXV3696d1tv4gMP9GQ,2322
4
+ txt2ebook/formats/__init__.py,sha256=s-d0hdkCpAshcJNxa_7PHUroeFd-p5o1PY6ix5fxjx4,2390
5
5
  txt2ebook/formats/base.py,sha256=4LC8tY2Vw6KjwH-BBDWV2plPjPLCAv6kjphekYx_ofg,5438
6
6
  txt2ebook/formats/epub.py,sha256=M9el5NfM9NEoGb41tg-Fn8BUuyze7L2Umm-rdrSOc9w,6856
7
7
  txt2ebook/formats/gmi.py,sha256=lNHC7m3DMcLNSUZzfDjNUcOVtk6QI_c0pUI1ls7NhJQ,6706
@@ -13,6 +13,7 @@ txt2ebook/formats/templates/epub/clean.css,sha256=AnEwMckzUSKcjKsDiWtJW1oaceuklt
13
13
  txt2ebook/formats/templates/epub/condense.css,sha256=Fz80ZqkPsFRmGdURduAxqMV8drD0CCUlrv41P8rUsm8,477
14
14
  txt2ebook/formats/templates/epub/noindent.css,sha256=_O5Tv90TKyyPBRdgjuNKFwtKFbdheh2V9PtDhgRUg3U,483
15
15
  txt2ebook/formats/txt.py,sha256=mSTFj3X9_iEKjCCgaUflCSKA5V96TUJ1WFcwbSzIU7Y,7385
16
+ txt2ebook/formats/typ.py,sha256=v3qAYatehMFCxFBPDtexK7A4s2bbAu2AWaYQDHi_DNg,5017
16
17
  txt2ebook/helpers/__init__.py,sha256=5EFTheYifNYk24rniaehnxd0NRR4K3aakSldZTVot1c,1966
17
18
  txt2ebook/languages/__init__.py,sha256=-c9-YQEkXnb9LKLoi7EtNlQLAw2SqDKVw2UXlWt9Dl0,753
18
19
  txt2ebook/languages/en.py,sha256=xCIhL431eUgoGwci4LCBkso8bR2LBhxKqWCPczKKoJQ,915
@@ -33,8 +34,8 @@ txt2ebook/parser.py,sha256=I4g4gOxdc1CyocH7nafhJnA5MGKg8De7w4uSVZLHVKk,11818
33
34
  txt2ebook/tokenizer.py,sha256=kzUW-xtAU4zgDxyUmPZZ7HNbjGDeOQX0MYr3_eOuByM,9313
34
35
  txt2ebook/txt2ebook.py,sha256=DJhiEznSEBQVBaDJMm3ArQpRrTXRs7Emb01BFglv1W4,12527
35
36
  txt2ebook/zh_utils.py,sha256=CM6SnsQhJWzSevcJWQ_9Pj028JUGbG3v0AG6xK_KgBY,4877
36
- txt2ebook-0.1.65.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
37
- txt2ebook-0.1.65.dist-info/METADATA,sha256=V9kw5Ete2oqwyuiP0HVBHH7M7GMuUbKZBQ-pt34I5Jk,7115
38
- txt2ebook-0.1.65.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
39
- txt2ebook-0.1.65.dist-info/entry_points.txt,sha256=IQHyIIhd0MHjSSRVC1a6tMeIoLus8D06KHL_cumvEbg,83
40
- txt2ebook-0.1.65.dist-info/RECORD,,
37
+ txt2ebook-0.1.67.dist-info/LICENSE.md,sha256=tGtFDwxWTjuR9syrJoSv1Hiffd2u8Tu8cYClfrXS_YU,31956
38
+ txt2ebook-0.1.67.dist-info/METADATA,sha256=Fo9V8zk7SgJLgWmqqu9gJ9YbzUIMEqvUec-pCg6KaE4,7218
39
+ txt2ebook-0.1.67.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
40
+ txt2ebook-0.1.67.dist-info/entry_points.txt,sha256=IQHyIIhd0MHjSSRVC1a6tMeIoLus8D06KHL_cumvEbg,83
41
+ txt2ebook-0.1.67.dist-info/RECORD,,