txt2ebook 0.1.82__tar.gz → 0.1.86__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/PKG-INFO +12 -8
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/README.md +11 -7
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/pyproject.toml +1 -1
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/__init__.py +1 -1
- txt2ebook-0.1.86/src/txt2ebook/formats/tex.py +150 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/languages/en.py +1 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/languages/zh_cn.py +1 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/languages/zh_tw.py +2 -0
- txt2ebook-0.1.86/src/txt2ebook/locales/en/LC_MESSAGES/txt2ebook.po +31 -0
- txt2ebook-0.1.86/src/txt2ebook/locales/txt2ebook.pot +31 -0
- txt2ebook-0.1.86/src/txt2ebook/locales/zh-cn/LC_MESSAGES/txt2ebook.po +31 -0
- txt2ebook-0.1.86/src/txt2ebook/locales/zh-tw/LC_MESSAGES/txt2ebook.po +31 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/models/book.py +1 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/parser.py +15 -3
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/tokenizer.py +4 -2
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/txt2ebook.py +9 -0
- txt2ebook-0.1.82/src/txt2ebook/formats/tex.py +0 -91
- txt2ebook-0.1.82/src/txt2ebook/locales/en/LC_MESSAGES/txt2ebook.po +0 -34
- txt2ebook-0.1.82/src/txt2ebook/locales/txt2ebook.pot +0 -34
- txt2ebook-0.1.82/src/txt2ebook/locales/zh-cn/LC_MESSAGES/txt2ebook.po +0 -34
- txt2ebook-0.1.82/src/txt2ebook/locales/zh-tw/LC_MESSAGES/txt2ebook.po +0 -34
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/LICENSE.md +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/__main__.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/exceptions.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/__init__.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/base.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/epub.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/gmi.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/md.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/pdf.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/templates/__init__.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/templates/epub/__init__.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/templates/epub/clean.css +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/templates/epub/condense.css +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/templates/epub/noindent.css +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/txt.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/formats/typ.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/helpers/__init__.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/languages/__init__.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/locales/en/LC_MESSAGES/txt2ebook.mo +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/locales/zh-cn/LC_MESSAGES/txt2ebook.mo +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/locales/zh-tw/LC_MESSAGES/txt2ebook.mo +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/models/__init__.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/models/chapter.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/models/volume.py +0 -0
- {txt2ebook-0.1.82 → txt2ebook-0.1.86}/src/txt2ebook/zh_utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: txt2ebook
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.86
|
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
|
@@ -73,14 +73,16 @@ txt2ebook --help
|
|
73
73
|
```
|
74
74
|
|
75
75
|
```console
|
76
|
+
|
76
77
|
usage: txt2ebook [-of OUTPUT_FOLDER] [-p] [-f {epub,gmi,md,pdf,tex,txt,typ}]
|
77
|
-
[-t TITLE] [-l LANGUAGE] [-a AUTHOR]
|
78
|
-
[-
|
79
|
-
[-
|
80
|
-
[-
|
81
|
-
[-
|
82
|
-
[-
|
83
|
-
[-
|
78
|
+
[-ik INDEX_KEYWORD] [-t TITLE] [-l LANGUAGE] [-a AUTHOR]
|
79
|
+
[-tr TRANSLATOR] [-c IMAGE_FILENAME] [-w WIDTH]
|
80
|
+
[-ff FILENAME_FORMAT] [-ps SEPARATOR] [-pz PAGE_SIZE]
|
81
|
+
[-rd REGEX] [-rvc REGEX] [-rv REGEX] [-rc REGEX] [-rt REGEX]
|
82
|
+
[-ra REGEX] [-rl REGEX] [-rr REGEX REGEX]
|
83
|
+
[-et {clean,condense,noindent}] [-vp] [-tp] [-sp] [-ss]
|
84
|
+
[-toc] [-hn] [-fw] [-rw] [-ow] [-op] [-q] [-v] [-y] [-d]
|
85
|
+
[--env] [-h] [-V]
|
84
86
|
TXT_FILENAME [EBOOK_FILENAME]
|
85
87
|
|
86
88
|
txt2ebook/tte is a cli tool to convert txt file to ebook format.
|
@@ -102,6 +104,8 @@ optional arguments:
|
|
102
104
|
remove converted ebooks specified by --output-folder option (default: 'False')
|
103
105
|
-f {epub,gmi,md,pdf,tex,txt,typ}, --format {epub,gmi,md,pdf,tex,txt,typ}
|
104
106
|
ebook format (default: 'epub')
|
107
|
+
-ik INDEX_KEYWORD, --index-keyword INDEX_KEYWORD
|
108
|
+
keyword to index (default: '[]')
|
105
109
|
-t TITLE, --title TITLE
|
106
110
|
title of the ebook (default: 'None')
|
107
111
|
-l LANGUAGE, --language LANGUAGE
|
@@ -31,14 +31,16 @@ txt2ebook --help
|
|
31
31
|
```
|
32
32
|
|
33
33
|
```console
|
34
|
+
|
34
35
|
usage: txt2ebook [-of OUTPUT_FOLDER] [-p] [-f {epub,gmi,md,pdf,tex,txt,typ}]
|
35
|
-
[-t TITLE] [-l LANGUAGE] [-a AUTHOR]
|
36
|
-
[-
|
37
|
-
[-
|
38
|
-
[-
|
39
|
-
[-
|
40
|
-
[-
|
41
|
-
[-
|
36
|
+
[-ik INDEX_KEYWORD] [-t TITLE] [-l LANGUAGE] [-a AUTHOR]
|
37
|
+
[-tr TRANSLATOR] [-c IMAGE_FILENAME] [-w WIDTH]
|
38
|
+
[-ff FILENAME_FORMAT] [-ps SEPARATOR] [-pz PAGE_SIZE]
|
39
|
+
[-rd REGEX] [-rvc REGEX] [-rv REGEX] [-rc REGEX] [-rt REGEX]
|
40
|
+
[-ra REGEX] [-rl REGEX] [-rr REGEX REGEX]
|
41
|
+
[-et {clean,condense,noindent}] [-vp] [-tp] [-sp] [-ss]
|
42
|
+
[-toc] [-hn] [-fw] [-rw] [-ow] [-op] [-q] [-v] [-y] [-d]
|
43
|
+
[--env] [-h] [-V]
|
42
44
|
TXT_FILENAME [EBOOK_FILENAME]
|
43
45
|
|
44
46
|
txt2ebook/tte is a cli tool to convert txt file to ebook format.
|
@@ -60,6 +62,8 @@ optional arguments:
|
|
60
62
|
remove converted ebooks specified by --output-folder option (default: 'False')
|
61
63
|
-f {epub,gmi,md,pdf,tex,txt,typ}, --format {epub,gmi,md,pdf,tex,txt,typ}
|
62
64
|
ebook format (default: 'epub')
|
65
|
+
-ik INDEX_KEYWORD, --index-keyword INDEX_KEYWORD
|
66
|
+
keyword to index (default: '[]')
|
63
67
|
-t TITLE, --title TITLE
|
64
68
|
title of the ebook (default: 'None')
|
65
69
|
-l LANGUAGE, --language LANGUAGE
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# Copyright (C) 2021,2022,2023,2024 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 source text file into tex format."""
|
17
|
+
|
18
|
+
import importlib.resources as importlib_res
|
19
|
+
import logging
|
20
|
+
import sys
|
21
|
+
from pathlib import Path
|
22
|
+
|
23
|
+
import importlib_resources
|
24
|
+
from pylatex import Command as Cmd
|
25
|
+
from pylatex import Document as Doc
|
26
|
+
from pylatex import NoEscape as NoEsc
|
27
|
+
from pylatex import Package as Pkg
|
28
|
+
from pylatex.section import Chapter as Chap
|
29
|
+
from pylatex.section import Part
|
30
|
+
|
31
|
+
from txt2ebook.formats.base import BaseWriter
|
32
|
+
from txt2ebook.models import Chapter, Volume
|
33
|
+
|
34
|
+
# workaround for Python 3.8
|
35
|
+
# see https://github.com/messense/typst-py/issues/12#issuecomment-1812956252
|
36
|
+
setattr(importlib_res, "files", importlib_resources.files)
|
37
|
+
setattr(importlib_res, "as_file", importlib_resources.as_file)
|
38
|
+
|
39
|
+
logger = logging.getLogger(__name__)
|
40
|
+
|
41
|
+
|
42
|
+
class TexWriter(BaseWriter):
|
43
|
+
"""Module for writing ebook in LaTeX (tex) format."""
|
44
|
+
|
45
|
+
def write(self) -> None:
|
46
|
+
"""Generate Tex files."""
|
47
|
+
new_filename = self._output_filename(".tex")
|
48
|
+
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
49
|
+
|
50
|
+
logger.info("Generate TeX file: %s", new_filename.resolve())
|
51
|
+
|
52
|
+
doc = Doc(documentclass="ctexbook", document_options=[self._fontset()])
|
53
|
+
|
54
|
+
doc.packages.append(Pkg("geometry", options=["a6paper"]))
|
55
|
+
doc.packages.append(Pkg("makeidx"))
|
56
|
+
doc.packages.append(
|
57
|
+
Pkg(
|
58
|
+
"idxlayout",
|
59
|
+
options=[
|
60
|
+
"columns=1",
|
61
|
+
"font=footnotesize",
|
62
|
+
"itemlayout=singlepar",
|
63
|
+
"indentunit=0pt",
|
64
|
+
],
|
65
|
+
)
|
66
|
+
)
|
67
|
+
doc.packages.append(
|
68
|
+
Pkg("hyperref", options=["colorlinks=true", "linktocpage=true"])
|
69
|
+
)
|
70
|
+
|
71
|
+
doc.packages.append(Pkg("tocloft", options=["titles"]))
|
72
|
+
tocloft = NoEsc(
|
73
|
+
r"""
|
74
|
+
\renewcommand{\cftbeforepartskip}{1em}
|
75
|
+
\renewcommand{\cftbeforechapskip}{0em}
|
76
|
+
\renewcommand{\cftpartfont}{\normalfont\bfseries}
|
77
|
+
\renewcommand{\cftchapfont}{\normalfont}
|
78
|
+
\renewcommand{\cftchapleader}{\dotfill}
|
79
|
+
\renewcommand{\cftpartpagefont}{\small\bfseries}
|
80
|
+
\renewcommand{\cftchappagefont}{\small\bfseries}
|
81
|
+
"""
|
82
|
+
)
|
83
|
+
doc.preamble.append(tocloft)
|
84
|
+
|
85
|
+
hide_section_seq = (
|
86
|
+
r"chapter/name={},chapter/number={},part/name={},part/number={}"
|
87
|
+
)
|
88
|
+
doc.preamble.append(Cmd("ctexset", NoEsc(hide_section_seq)))
|
89
|
+
doc.preamble.append(Cmd("title", self.book.title))
|
90
|
+
doc.preamble.append(Cmd("author", ", ".join(self.book.authors)))
|
91
|
+
doc.preamble.append(NoEsc(r"\date{}"))
|
92
|
+
doc.preamble.append(Cmd("makeindex"))
|
93
|
+
|
94
|
+
doc.append(NoEsc(r"\maketitle"))
|
95
|
+
doc.append(NoEsc(r"\thispagestyle{empty}"))
|
96
|
+
doc.append(NoEsc(r"\addtocontents{toc}{\protect\pagestyle{empty}}"))
|
97
|
+
doc.append(
|
98
|
+
NoEsc(r"\addtocontents{toc}{\protect\thispagestyle{empty}}")
|
99
|
+
)
|
100
|
+
doc.append(NoEsc(r"\tableofcontents"))
|
101
|
+
doc.append(NoEsc(r"\pagestyle{empty}"))
|
102
|
+
doc.append(NoEsc(r"\cleardoublepage"))
|
103
|
+
doc.append(NoEsc(r"\pagenumbering{arabic}"))
|
104
|
+
doc.append(NoEsc(r"\pagestyle{headings}"))
|
105
|
+
|
106
|
+
for section in self.book.toc:
|
107
|
+
if isinstance(section, Volume):
|
108
|
+
with doc.create(Part(section.title, label=False)):
|
109
|
+
for chapter in section.chapters:
|
110
|
+
with doc.create(Chap(chapter.title, label=False)):
|
111
|
+
for paragraph in chapter.paragraphs:
|
112
|
+
par = self._process_paragraph(paragraph)
|
113
|
+
doc.append(NoEsc(rf"\par{{{par}}}"))
|
114
|
+
|
115
|
+
if isinstance(section, Chapter):
|
116
|
+
with doc.create(Chap(section.title, label=False)):
|
117
|
+
for paragraph in section.paragraphs:
|
118
|
+
par = self._process_paragraph(paragraph)
|
119
|
+
doc.append(NoEsc(rf"\par{{{par}}}"))
|
120
|
+
|
121
|
+
doc.append(Cmd("printindex"))
|
122
|
+
|
123
|
+
filename = str(new_filename.parent / new_filename.stem)
|
124
|
+
pdf_filename = Path(filename).with_suffix(".pdf")
|
125
|
+
doc.generate_pdf(filename, compiler="latexmk", clean_tex=False)
|
126
|
+
|
127
|
+
if self.config.open:
|
128
|
+
self._open_file(pdf_filename)
|
129
|
+
|
130
|
+
def _process_paragraph(self, paragraph) -> str:
|
131
|
+
par = paragraph.strip()
|
132
|
+
for keyword in self.config.index_keyword:
|
133
|
+
par = par.replace(keyword, rf"\index{{{keyword}}}")
|
134
|
+
|
135
|
+
for keyword in self.book.index:
|
136
|
+
par = par.replace(keyword, rf"\index{{{keyword}}}")
|
137
|
+
|
138
|
+
return par
|
139
|
+
|
140
|
+
def _fontset(self) -> str:
|
141
|
+
if sys.platform == "linux":
|
142
|
+
return "fontset=ubuntu"
|
143
|
+
|
144
|
+
if sys.platform == "darwin":
|
145
|
+
return "fontset=macos"
|
146
|
+
|
147
|
+
if sys.platform == "windows":
|
148
|
+
return "fontset=windows"
|
149
|
+
|
150
|
+
return "fontset=ubuntu"
|
@@ -52,6 +52,7 @@ RE_CHAPTERS = [
|
|
52
52
|
DEFAULT_RE_AUTHOR = r"作者:(.*)"
|
53
53
|
DEFAULT_RE_CHAPTER = "(" + "|".join(RE_CHAPTERS) + ")"
|
54
54
|
DEFAULT_RE_TAG = r"标签:(.*)"
|
55
|
+
DEFAULT_RE_INDEX = r"索引:(.*)"
|
55
56
|
DEFAULT_RE_TITLE = r"书名:(.*)"
|
56
57
|
DEFAULT_RE_TRANSLATOR = r"翻译:(.*)"
|
57
58
|
DEFAULT_RE_VOLUME = "(" + "|".join(RE_VOLUMES) + ")"
|
@@ -18,6 +18,7 @@
|
|
18
18
|
from txt2ebook.languages.zh_cn import (
|
19
19
|
DEFAULT_RE_AUTHOR,
|
20
20
|
DEFAULT_RE_CHAPTER,
|
21
|
+
DEFAULT_RE_INDEX,
|
21
22
|
DEFAULT_RE_TAG,
|
22
23
|
DEFAULT_RE_TITLE,
|
23
24
|
DEFAULT_RE_TRANSLATOR,
|
@@ -39,6 +40,7 @@ __all__ = [
|
|
39
40
|
"DEFAULT_RE_AUTHOR",
|
40
41
|
"DEFAULT_RE_CHAPTER",
|
41
42
|
"DEFAULT_RE_TAG",
|
43
|
+
"DEFAULT_RE_INDEX",
|
42
44
|
"DEFAULT_RE_TITLE",
|
43
45
|
"DEFAULT_RE_TRANSLATOR",
|
44
46
|
"DEFAULT_RE_VOLUME",
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#: src/txt2ebook/formats/base.py:141
|
2
|
+
msgid "title:"
|
3
|
+
msgstr "Title:"
|
4
|
+
|
5
|
+
#: src/txt2ebook/formats/base.py:142
|
6
|
+
msgid "author:"
|
7
|
+
msgstr "Author:"
|
8
|
+
|
9
|
+
#: src/txt2ebook/formats/base.py:143
|
10
|
+
msgid "translator:"
|
11
|
+
msgstr "Translator:"
|
12
|
+
|
13
|
+
#: src/txt2ebook/formats/base.py:144
|
14
|
+
msgid "tag:"
|
15
|
+
msgstr "Tag:"
|
16
|
+
|
17
|
+
#: src/txt2ebook/formats/base.py:155 src/txt2ebook/formats/gmi.py:62
|
18
|
+
#: src/txt2ebook/formats/md.py:61 src/txt2ebook/formats/pdf.py:130
|
19
|
+
#: src/txt2ebook/formats/txt.py:71
|
20
|
+
msgid "toc"
|
21
|
+
msgstr "Table of Content"
|
22
|
+
|
23
|
+
#: src/txt2ebook/formats/epub.py:147
|
24
|
+
msgid "cover"
|
25
|
+
msgstr "Cover"
|
26
|
+
|
27
|
+
#: src/txt2ebook/formats/gmi.py:47 src/txt2ebook/formats/md.py:46
|
28
|
+
#: src/txt2ebook/formats/txt.py:56
|
29
|
+
msgid "metadata"
|
30
|
+
msgstr "Metadata"
|
31
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#: src/txt2ebook/formats/base.py:141
|
2
|
+
msgid "title:"
|
3
|
+
msgstr ""
|
4
|
+
|
5
|
+
#: src/txt2ebook/formats/base.py:142
|
6
|
+
msgid "author:"
|
7
|
+
msgstr ""
|
8
|
+
|
9
|
+
#: src/txt2ebook/formats/base.py:143
|
10
|
+
msgid "translator:"
|
11
|
+
msgstr ""
|
12
|
+
|
13
|
+
#: src/txt2ebook/formats/base.py:144
|
14
|
+
msgid "tag:"
|
15
|
+
msgstr ""
|
16
|
+
|
17
|
+
#: src/txt2ebook/formats/base.py:155 src/txt2ebook/formats/gmi.py:62
|
18
|
+
#: src/txt2ebook/formats/md.py:61 src/txt2ebook/formats/pdf.py:130
|
19
|
+
#: src/txt2ebook/formats/txt.py:71
|
20
|
+
msgid "toc"
|
21
|
+
msgstr ""
|
22
|
+
|
23
|
+
#: src/txt2ebook/formats/epub.py:147
|
24
|
+
msgid "cover"
|
25
|
+
msgstr ""
|
26
|
+
|
27
|
+
#: src/txt2ebook/formats/gmi.py:47 src/txt2ebook/formats/md.py:46
|
28
|
+
#: src/txt2ebook/formats/txt.py:56
|
29
|
+
msgid "metadata"
|
30
|
+
msgstr ""
|
31
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#: src/txt2ebook/formats/base.py:141
|
2
|
+
msgid "title:"
|
3
|
+
msgstr "书名:"
|
4
|
+
|
5
|
+
#: src/txt2ebook/formats/base.py:142
|
6
|
+
msgid "author:"
|
7
|
+
msgstr "作者:"
|
8
|
+
|
9
|
+
#: src/txt2ebook/formats/base.py:143
|
10
|
+
msgid "translator:"
|
11
|
+
msgstr "翻译:"
|
12
|
+
|
13
|
+
#: src/txt2ebook/formats/base.py:144
|
14
|
+
msgid "tag:"
|
15
|
+
msgstr "票签:"
|
16
|
+
|
17
|
+
#: src/txt2ebook/formats/base.py:155 src/txt2ebook/formats/gmi.py:62
|
18
|
+
#: src/txt2ebook/formats/md.py:61 src/txt2ebook/formats/pdf.py:130
|
19
|
+
#: src/txt2ebook/formats/txt.py:71
|
20
|
+
msgid "toc"
|
21
|
+
msgstr "目录"
|
22
|
+
|
23
|
+
#: src/txt2ebook/formats/epub.py:147
|
24
|
+
msgid "cover"
|
25
|
+
msgstr "封面"
|
26
|
+
|
27
|
+
#: src/txt2ebook/formats/gmi.py:47 src/txt2ebook/formats/md.py:46
|
28
|
+
#: src/txt2ebook/formats/txt.py:56
|
29
|
+
msgid "metadata"
|
30
|
+
msgstr "元数据"
|
31
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#: src/txt2ebook/formats/base.py:141
|
2
|
+
msgid "title:"
|
3
|
+
msgstr "书名:"
|
4
|
+
|
5
|
+
#: src/txt2ebook/formats/base.py:142
|
6
|
+
msgid "author:"
|
7
|
+
msgstr "作者:"
|
8
|
+
|
9
|
+
#: src/txt2ebook/formats/base.py:143
|
10
|
+
msgid "translator:"
|
11
|
+
msgstr "翻译:"
|
12
|
+
|
13
|
+
#: src/txt2ebook/formats/base.py:144
|
14
|
+
msgid "tag:"
|
15
|
+
msgstr "标签:"
|
16
|
+
|
17
|
+
#: src/txt2ebook/formats/base.py:155 src/txt2ebook/formats/gmi.py:62
|
18
|
+
#: src/txt2ebook/formats/md.py:61 src/txt2ebook/formats/pdf.py:130
|
19
|
+
#: src/txt2ebook/formats/txt.py:71
|
20
|
+
msgid "toc"
|
21
|
+
msgstr "目录"
|
22
|
+
|
23
|
+
#: src/txt2ebook/formats/epub.py:147
|
24
|
+
msgid "cover"
|
25
|
+
msgstr "封面"
|
26
|
+
|
27
|
+
#: src/txt2ebook/formats/gmi.py:47 src/txt2ebook/formats/md.py:46
|
28
|
+
#: src/txt2ebook/formats/txt.py:56
|
29
|
+
msgid "metadata"
|
30
|
+
msgstr "元数据"
|
31
|
+
|
@@ -36,6 +36,7 @@ class Book:
|
|
36
36
|
authors: List[str] = field(default_factory=lambda: [])
|
37
37
|
translators: List[str] = field(default_factory=lambda: [])
|
38
38
|
tags: List[str] = field(default_factory=lambda: [])
|
39
|
+
index: List[str] = field(default_factory=lambda: [])
|
39
40
|
language: str = field(default="")
|
40
41
|
cover: str = field(default="", repr=False)
|
41
42
|
raw_content: str = field(default="", repr=False)
|
@@ -55,13 +55,17 @@ class Parser:
|
|
55
55
|
massaged_content = self.massage()
|
56
56
|
tokenizer = Tokenizer(massaged_content, self.config)
|
57
57
|
|
58
|
-
(book_title, authors, tags, toc) =
|
58
|
+
(book_title, authors, translators, tags, index, toc) = (
|
59
|
+
self.parse_tokens(tokenizer)
|
60
|
+
)
|
59
61
|
|
60
62
|
book = Book(
|
61
63
|
title=book_title,
|
62
64
|
language=self.config.language,
|
63
65
|
authors=authors,
|
66
|
+
translators=translators,
|
64
67
|
tags=tags,
|
68
|
+
index=index,
|
65
69
|
cover=self.config.cover,
|
66
70
|
raw_content=self.raw_content,
|
67
71
|
massaged_content=massaged_content,
|
@@ -126,6 +130,7 @@ class Parser:
|
|
126
130
|
book_title = ""
|
127
131
|
authors = []
|
128
132
|
tags = []
|
133
|
+
index = []
|
129
134
|
translators = []
|
130
135
|
current_volume = Volume("")
|
131
136
|
current_chapter = Chapter("")
|
@@ -163,6 +168,9 @@ class Parser:
|
|
163
168
|
if token.type == "TAG":
|
164
169
|
tags.append(token.value)
|
165
170
|
|
171
|
+
if token.type == "INDEX":
|
172
|
+
index = token.value.split(" ")
|
173
|
+
|
166
174
|
if token.type == "TRANSLATOR":
|
167
175
|
translators.append(token.value)
|
168
176
|
|
@@ -216,15 +224,19 @@ class Parser:
|
|
216
224
|
if self.config.title:
|
217
225
|
book_title = self.config.title
|
218
226
|
|
227
|
+
if self.config.translator:
|
228
|
+
authors = self.config.translator
|
229
|
+
|
219
230
|
logger.info("Found or set book title: %s", book_title)
|
220
231
|
logger.info("Found or set authors: %s", repr(authors))
|
221
|
-
logger.info("Found or set categories: %s", repr(tags))
|
222
232
|
logger.info("Found or set translators: %s", repr(translators))
|
233
|
+
logger.info("Found or set tags: %s", repr(tags))
|
234
|
+
logger.info("Found or set index: %s", repr(index))
|
223
235
|
|
224
236
|
if self.config.sort_volume_and_chapter:
|
225
237
|
self.sort_volume_and_chapter(toc)
|
226
238
|
|
227
|
-
return (book_title, authors, tags, toc)
|
239
|
+
return (book_title, authors, translators, tags, index, toc)
|
228
240
|
|
229
241
|
def sort_volume_and_chapter(self, toc: List) -> None:
|
230
242
|
"""Sort by title of volumes and its chapters.
|
@@ -129,6 +129,7 @@ class Tokenizer:
|
|
129
129
|
("TITLE", re_title),
|
130
130
|
("AUTHOR", re_author),
|
131
131
|
("TAG", f"{self.langconf.DEFAULT_RE_TAG}"),
|
132
|
+
("INDEX", f"{self.langconf.DEFAULT_RE_INDEX}"),
|
132
133
|
("TRANSLATOR", f"{self.langconf.DEFAULT_RE_TRANSLATOR}"),
|
133
134
|
]
|
134
135
|
|
@@ -151,8 +152,9 @@ class Tokenizer:
|
|
151
152
|
2 书名:
|
152
153
|
3 作者:
|
153
154
|
4 标签:
|
154
|
-
5
|
155
|
-
6
|
155
|
+
5 索引:
|
156
|
+
6 翻译:
|
157
|
+
7 ---
|
156
158
|
|
157
159
|
"""
|
158
160
|
match = re.search(
|
@@ -155,6 +155,15 @@ def build_parser(
|
|
155
155
|
help="ebook format (default: 'epub')",
|
156
156
|
)
|
157
157
|
|
158
|
+
parser.add_argument(
|
159
|
+
"-ik",
|
160
|
+
"--index-keyword",
|
161
|
+
dest="index_keyword",
|
162
|
+
action="append",
|
163
|
+
default=[],
|
164
|
+
help="keyword to index (default: '%(default)s')",
|
165
|
+
)
|
166
|
+
|
158
167
|
parser.add_argument(
|
159
168
|
"-t",
|
160
169
|
"--title",
|
@@ -1,91 +0,0 @@
|
|
1
|
-
# Copyright (C) 2021,2022,2023,2024 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 source text file into tex format."""
|
17
|
-
|
18
|
-
import importlib.resources as importlib_res
|
19
|
-
import logging
|
20
|
-
import sys
|
21
|
-
from pathlib import Path
|
22
|
-
|
23
|
-
import importlib_resources
|
24
|
-
from pylatex import Command as Cmd
|
25
|
-
from pylatex import Document as Doc
|
26
|
-
from pylatex import NoEscape as NoEsc
|
27
|
-
from pylatex import Package as Pkg
|
28
|
-
from pylatex.section import Chapter as Chap
|
29
|
-
from pylatex.section import Paragraph as Par
|
30
|
-
from pylatex.section import Part as Part
|
31
|
-
|
32
|
-
from txt2ebook.formats.base import BaseWriter
|
33
|
-
from txt2ebook.models import Chapter, Volume
|
34
|
-
|
35
|
-
# workaround for Python 3.8
|
36
|
-
# see https://github.com/messense/typst-py/issues/12#issuecomment-1812956252
|
37
|
-
setattr(importlib_res, "files", importlib_resources.files)
|
38
|
-
setattr(importlib_res, "as_file", importlib_resources.as_file)
|
39
|
-
|
40
|
-
logger = logging.getLogger(__name__)
|
41
|
-
|
42
|
-
|
43
|
-
class TexWriter(BaseWriter):
|
44
|
-
"""Module for writing ebook in LaTeX (tex) format."""
|
45
|
-
|
46
|
-
def write(self) -> None:
|
47
|
-
"""Generate Tex files."""
|
48
|
-
new_filename = self._output_filename(".tex")
|
49
|
-
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
50
|
-
|
51
|
-
logger.info("Generate TeX file: %s", new_filename.resolve())
|
52
|
-
|
53
|
-
doc = Doc(documentclass="ctexbook", document_options=[self._fontset()])
|
54
|
-
|
55
|
-
doc.packages.append(Pkg("geometry", options=["a5paper"]))
|
56
|
-
doc.preamble.append(Cmd("ctexset", NoEsc(r"chapter/name={},chapter/number={},part/name={},part/number={}")))
|
57
|
-
doc.preamble.append(Cmd("title", self.book.title))
|
58
|
-
doc.preamble.append(Cmd("author", ", ".join(self.book.authors)))
|
59
|
-
doc.preamble.append(Cmd("date", NoEsc(r"\today")))
|
60
|
-
|
61
|
-
doc.append(NoEsc(r"\maketitle"))
|
62
|
-
doc.append(NoEsc(r"\thispagestyle{empty}"))
|
63
|
-
|
64
|
-
for section in self.book.toc:
|
65
|
-
if isinstance(section, Volume):
|
66
|
-
with doc.create(Part(section.title)):
|
67
|
-
for chapter in section.chapters:
|
68
|
-
with doc.create(Chap(chapter.title)):
|
69
|
-
for paragraph in chapter.paragraphs:
|
70
|
-
doc.append(Par(paragraph.replace("\n", "")))
|
71
|
-
if isinstance(section, Chapter):
|
72
|
-
with doc.create(Chap(section.title)):
|
73
|
-
for paragraph in section.paragraphs:
|
74
|
-
doc.append(Par(paragraph.replace("\n", "")))
|
75
|
-
|
76
|
-
filename = str(new_filename.parent / new_filename.stem)
|
77
|
-
pdf_filename = Path(filename).with_suffix(".pdf")
|
78
|
-
doc.generate_pdf(filename, compiler="xelatex", clean_tex=False)
|
79
|
-
|
80
|
-
if self.config.open:
|
81
|
-
self._open_file(pdf_filename)
|
82
|
-
|
83
|
-
def _fontset(self) -> str:
|
84
|
-
if sys.platform == "linux":
|
85
|
-
return "fontset = ubuntu"
|
86
|
-
|
87
|
-
if sys.platform == "darwin":
|
88
|
-
return "fontset = macos"
|
89
|
-
|
90
|
-
if sys.platform == "windows":
|
91
|
-
return "fontset = windows"
|
@@ -1,34 +0,0 @@
|
|
1
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:141
|
2
|
-
msgid "title:"
|
3
|
-
msgstr "Title:"
|
4
|
-
|
5
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:142
|
6
|
-
msgid "author:"
|
7
|
-
msgstr "Author:"
|
8
|
-
|
9
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:143
|
10
|
-
msgid "translator:"
|
11
|
-
msgstr "Translator:"
|
12
|
-
|
13
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:144
|
14
|
-
msgid "tag:"
|
15
|
-
msgstr "Tag:"
|
16
|
-
|
17
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:155
|
18
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/gmi.py:62
|
19
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/md.py:61
|
20
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/pdf.py:130
|
21
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/txt.py:71
|
22
|
-
msgid "toc"
|
23
|
-
msgstr "Table of Content"
|
24
|
-
|
25
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/epub.py:147
|
26
|
-
msgid "cover"
|
27
|
-
msgstr "Cover"
|
28
|
-
|
29
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/gmi.py:47
|
30
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/md.py:46
|
31
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/txt.py:56
|
32
|
-
msgid "metadata"
|
33
|
-
msgstr "Metadata"
|
34
|
-
|
@@ -1,34 +0,0 @@
|
|
1
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:141
|
2
|
-
msgid "title:"
|
3
|
-
msgstr ""
|
4
|
-
|
5
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:142
|
6
|
-
msgid "author:"
|
7
|
-
msgstr ""
|
8
|
-
|
9
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:143
|
10
|
-
msgid "translator:"
|
11
|
-
msgstr ""
|
12
|
-
|
13
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:144
|
14
|
-
msgid "tag:"
|
15
|
-
msgstr ""
|
16
|
-
|
17
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:155
|
18
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/gmi.py:62
|
19
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/md.py:61
|
20
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/pdf.py:130
|
21
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/txt.py:71
|
22
|
-
msgid "toc"
|
23
|
-
msgstr ""
|
24
|
-
|
25
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/epub.py:147
|
26
|
-
msgid "cover"
|
27
|
-
msgstr ""
|
28
|
-
|
29
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/gmi.py:47
|
30
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/md.py:46
|
31
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/txt.py:56
|
32
|
-
msgid "metadata"
|
33
|
-
msgstr ""
|
34
|
-
|
@@ -1,34 +0,0 @@
|
|
1
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:141
|
2
|
-
msgid "title:"
|
3
|
-
msgstr "书名:"
|
4
|
-
|
5
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:142
|
6
|
-
msgid "author:"
|
7
|
-
msgstr "作者:"
|
8
|
-
|
9
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:143
|
10
|
-
msgid "translator:"
|
11
|
-
msgstr "翻译:"
|
12
|
-
|
13
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:144
|
14
|
-
msgid "tag:"
|
15
|
-
msgstr "票签:"
|
16
|
-
|
17
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:155
|
18
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/gmi.py:62
|
19
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/md.py:61
|
20
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/pdf.py:130
|
21
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/txt.py:71
|
22
|
-
msgid "toc"
|
23
|
-
msgstr "目录"
|
24
|
-
|
25
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/epub.py:147
|
26
|
-
msgid "cover"
|
27
|
-
msgstr "封面"
|
28
|
-
|
29
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/gmi.py:47
|
30
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/md.py:46
|
31
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/txt.py:56
|
32
|
-
msgid "metadata"
|
33
|
-
msgstr "元数据"
|
34
|
-
|
@@ -1,34 +0,0 @@
|
|
1
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:141
|
2
|
-
msgid "title:"
|
3
|
-
msgstr "书名:"
|
4
|
-
|
5
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:142
|
6
|
-
msgid "author:"
|
7
|
-
msgstr "作者:"
|
8
|
-
|
9
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:143
|
10
|
-
msgid "translator:"
|
11
|
-
msgstr "翻译:"
|
12
|
-
|
13
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:144
|
14
|
-
msgid "tag:"
|
15
|
-
msgstr "标签:"
|
16
|
-
|
17
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/base.py:155
|
18
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/gmi.py:62
|
19
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/md.py:61
|
20
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/pdf.py:130
|
21
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/txt.py:71
|
22
|
-
msgid "toc"
|
23
|
-
msgstr "目录"
|
24
|
-
|
25
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/epub.py:147
|
26
|
-
msgid "cover"
|
27
|
-
msgstr "封面"
|
28
|
-
|
29
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/gmi.py:47
|
30
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/md.py:46
|
31
|
-
#: /home/ang/src/self/txt2ebook/txt2ebook/src/txt2ebook/formats/txt.py:56
|
32
|
-
msgid "metadata"
|
33
|
-
msgstr "元数据"
|
34
|
-
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|