Skip to content

Commit 44c2ba5

Browse files
committed
feat: no-server
1 parent 1170349 commit 44c2ba5

6 files changed

Lines changed: 117 additions & 11 deletions

File tree

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ It now supports:
2121
* Code highlight.
2222
* Remember your last reading chapter.
2323
* Custom CSS: you can write your own CSS style to improve your reading experience, such as `.content{margin: 50px;}.content p{ font-size: 2rem; }`(All the main content is under the element with the class `content`).
24+
* Can be directly deployed on any web server such as Apache: use `--no-server` parameter.
2425

2526
## Usage
2627

@@ -41,10 +42,14 @@ epub-browser *.epub
4142
# Open multiple books under the current path
4243
epub-browser .
4344

45+
# Do not start the server; only generate static website files, which can be directly deployed on any web server such as Apache.
46+
epub-browser . --no-server
47+
4448
# Specify the output directory of html files, or use tmp directory by default
4549
epub-browser book1.epub book2.epub --output-dir /path/to/output
4650

47-
# Save the converted html files, will not clean the target tmp directory
51+
# Save the converted html files, will not clean the target tmp directory;
52+
# Note: These files are for inspection purposes only and cannot be directly deployed to a web server. To enable direct deployment, please use the --no-server parameter.
4853
epub-browser book1.epub --keep-files
4954

5055
# Do not open the browser automatically

epub_browser/library.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,30 @@ def create_library_home(self):
660660
"""
661661
library_html += """<script>
662662
document.addEventListener('DOMContentLoaded', function() {
663+
// 检查当前的基路径
664+
base_path = window.location.pathname;
665+
if (base_path !== "/") {
666+
// 处理所有资源,都要加上基路径
667+
addBasePath(base_path);
668+
} else {
669+
}
670+
671+
function addBasePath(basePath) {
672+
// 处理所有链接、图片、脚本和样式表
673+
const resources = document.querySelectorAll('a[href^="/"], img[src^="/"], script[src^="/"], link[rel="stylesheet"][href^="/"]');
674+
resources.forEach(resource => {
675+
const src = resource.getAttribute('src');
676+
const href = resource.getAttribute('href');
677+
if (src && !src.startsWith('http') && !src.startsWith('//') && !src.startsWith(basePath)) {
678+
resource.setAttribute('src', basePath.substr(0, basePath.length - 1) + src);
679+
}
680+
if (href && !href.startsWith('http') && !href.startsWith('//') && !href.startsWith(basePath)) {
681+
resource.setAttribute('href', basePath.substr(0, basePath.length - 1) + href);
682+
}
683+
});
684+
}
685+
686+
663687
// 书籍目录锚点
664688
const allBookLinks = document.querySelectorAll('.book-card .book-link');
665689
allBookLinks.forEach(item => {
@@ -812,6 +836,30 @@ def create_library_home(self):
812836
with open(os.path.join(self.base_directory, 'index.html'), 'w', encoding='utf-8') as f:
813837
f.write(library_html)
814838

839+
def reorganize_files(self):
840+
"""按照 href 的格式组织目录"""
841+
# 创建 book 目录
842+
book_path = os.path.join(self.base_directory, "book")
843+
if os.path.exists(book_path):
844+
try:
845+
shutil.rmtree(book_path)
846+
os.mkdir(book_path)
847+
except Exception as e:
848+
print(f"book_path {book_path} exists, try to recreate failed, err: {e}")
849+
else:
850+
os.mkdir(book_path)
851+
# 把所有书籍移动到对应目录
852+
for book_hash, book_info in self.books.items():
853+
old_path = book_info['web_dir']
854+
old_temp_dir = book_info['temp_dir']
855+
cur_path = os.path.join(book_path, book_hash)
856+
try:
857+
shutil.move(old_path, cur_path)
858+
# 删除原来的 temp_dir 目录
859+
shutil.rmtree(old_temp_dir)
860+
except Exception as e:
861+
print(f"move {old_path} to {cur_path} failed, err: {e}")
862+
815863
def cleanup(self):
816864
"""清理所有文件"""
817865
if self.output_dir is not None:

epub_browser/main.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ def main():
1919
parser.add_argument('--port', '-p', type=int, default=8000, help='Web server port (default: 8000)')
2020
parser.add_argument('--no-browser', action='store_true', help='Do not automatically open browser')
2121
parser.add_argument('--output-dir', '-o', help='Output directory for converted books')
22-
parser.add_argument('--keep-files', action='store_true', help='Keep converted files after server stops')
22+
parser.add_argument('--keep-files', action='store_true', help='Keep converted files after server stops. To enable direct deployment, please use the --no-server parameter.')
2323
parser.add_argument('--log', action='store_true', help='Enable log messages')
24-
parser.add_argument('--no-server', action='store_true', help='Do not start a server, just generate files')
24+
parser.add_argument('--no-server', action='store_true', help='Do not start a server, just generate files which can be directly deployed on any web server such as Apache.')
2525

2626
args = parser.parse_args()
2727

@@ -51,10 +51,14 @@ def main():
5151

5252
library.create_library_home()
5353

54-
# 创建服务器
54+
# 仅生成文件
5555
if args.no_server:
56+
# 重新组织文件格式
57+
library.reorganize_files()
5658
print(f"Files generated in: {library.base_directory}")
5759
return
60+
61+
# 创建服务器
5862
server_instance = EPUBServer(library, args.log)
5963
try:
6064
server_instance.start_server(

epub_browser/processor.py

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -965,12 +965,36 @@ def create_index_page(self):
965965
<p>EPUB Library &copy; {datetime.now().year} | Powered by <a href="https://github.com/dfface/epub-browser" target="_blank">epub-browser</a></p>
966966
</footer>
967967
"""
968-
index_html += """<script>
969-
document.addEventListener('DOMContentLoaded', function() {
968+
index_html += f"""<script>
969+
document.addEventListener('DOMContentLoaded', function() {{
970+
const book_hash = "{self.book_hash}";"""
971+
index_html += """
970972
const path = window.location.pathname; // 获取当前URL路径
971973
let pathParts = path.split('/');
972974
pathParts = pathParts.filter(item => item !== "");
973-
const book_hash = pathParts[pathParts.length - 1];
975+
976+
// 检查当前的基路径
977+
if (!path.startsWith("/book/")) {
978+
// 获取基路径
979+
let basePath = "/" + pathParts[0] + "/";
980+
// 处理所有资源,都要加上基路径
981+
addBasePath(basePath);
982+
}
983+
984+
function addBasePath(basePath) {
985+
// 处理所有链接、图片、脚本和样式表
986+
const resources = document.querySelectorAll('a[href^="/"], img[src^="/"], script[src^="/"], link[rel="stylesheet"][href^="/"]');
987+
resources.forEach(resource => {
988+
const src = resource.getAttribute('src');
989+
const href = resource.getAttribute('href');
990+
if (src && !src.startsWith('http') && !src.startsWith('//') && !src.startsWith(basePath)) {
991+
resource.setAttribute('src', basePath.substr(0, basePath.length - 1) + src);
992+
}
993+
if (href && !href.startsWith('http') && !href.startsWith('//') && !href.startsWith(basePath)) {
994+
resource.setAttribute('href', basePath.substr(0, basePath.length - 1) + href);
995+
}
996+
});
997+
}
974998
975999
// 书籍目录锚点删除
9761000
const anchor = window.location.hash;
@@ -2240,6 +2264,33 @@ def create_chapter_template(self, content, style_links, chapter_index, chapter_t
22402264
const book_hash = "{self.book_hash}";
22412265
"""
22422266
chapter_html += """
2267+
const path = window.location.pathname; // 获取当前URL路径
2268+
let pathParts = path.split('/');
2269+
pathParts = pathParts.filter(item => item !== "");
2270+
2271+
// 检查当前的基路径
2272+
if (!path.startsWith("/book/")) {
2273+
// 获取基路径
2274+
let basePath = "/" + pathParts[0] + "/"
2275+
// 处理所有资源,都要加上基路径
2276+
addBasePath(basePath);
2277+
}
2278+
2279+
function addBasePath(basePath) {
2280+
// 处理所有链接、图片、脚本和样式表
2281+
const resources = document.querySelectorAll('iframe[src^="/"], a[href^="/"], img[src^="/"], script[src^="/"], link[rel="stylesheet"][href^="/"]');
2282+
resources.forEach(resource => {
2283+
const src = resource.getAttribute('src');
2284+
const href = resource.getAttribute('href');
2285+
if (src && !src.startsWith('http') && !src.startsWith('//') && !src.startsWith(basePath)) {
2286+
resource.setAttribute('src', basePath.substr(0, basePath.length - 1) + src);
2287+
}
2288+
if (href && !href.startsWith('http') && !href.startsWith('//') && !href.startsWith(basePath)) {
2289+
resource.setAttribute('href', basePath.substr(0, basePath.length - 1) + href);
2290+
}
2291+
});
2292+
}
2293+
22432294
// 自定义CSS功能
22442295
const cssPanelToggle = document.getElementById('cssPanelToggle');
22452296
const cssPanelContent = document.getElementById('cssPanelContent');
@@ -2494,8 +2545,6 @@ def create_chapter_template(self, content, style_links, chapter_index, chapter_t
24942545
wrapAllTables();
24952546
24962547
// 书籍目录锚点更新
2497-
const path = window.location.pathname; // 获取当前URL路径
2498-
const pathParts = path.split('/');
24992548
const lastPart = pathParts[pathParts.length - 1];
25002549
var anchor = '';
25012550
if (lastPart.startsWith('chapter_') && lastPart.endsWith('.html')) {

epub_browser/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def create_handler(*args, **kwargs):
251251
print(f"Web server started: http://{actual_host}:{actual_port}")
252252
print(f"Available books ({len(self.library.books)}):")
253253
for book_hash, book_info in self.library.books.items():
254-
print(f" - {book_info['title']}: http://{actual_host}:{actual_port}/book/{book_hash}/")
254+
print(f" - {book_info['title']}: http://{actual_host}:{actual_port}book/{book_hash}/")
255255
print("Press Ctrl+C to stop the server\n")
256256

257257
# 自动打开浏览器

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
setup(
88
name="epub-browser", # 在PyPI上显示的项目名称
9-
version="1.2.6", # 初始版本号
9+
version="1.2.7", # 初始版本号
1010
author="dfface", # 作者名
1111
author_email="dfface@sina.com", # 作者邮箱
1212
keywords="epub reader html export browser convert calibre-web calibre kindle",

0 commit comments

Comments
 (0)