diff --git a/app/src/main/assets/epub/chapter.html b/app/src/main/assets/epub/chapter.html
new file mode 100644
index 000000000..57b8bce01
--- /dev/null
+++ b/app/src/main/assets/epub/chapter.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Chapter
+
+
+
+
+
+
+
+{title}
+{content}
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/epub/cover.html b/app/src/main/assets/epub/cover.html
new file mode 100644
index 000000000..268cc3f85
--- /dev/null
+++ b/app/src/main/assets/epub/cover.html
@@ -0,0 +1,22 @@
+
+
+
+
+ Cover
+
+
+
+
+{name}
+{author} / 著
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/epub/fonts.css b/app/src/main/assets/epub/fonts.css
new file mode 100644
index 000000000..3457a6511
--- /dev/null
+++ b/app/src/main/assets/epub/fonts.css
@@ -0,0 +1,267 @@
+@charset "utf-8";
+/*---常用---*/
+
+@font-face {
+ font-family: "zw";
+ src:
+ local("宋体"),local("明体"),local("明朝"),
+ local("Songti"),local("Songti SC"),local("Songti TC"), /*iOS6+iBooks3*/
+ local("Song S"),local("Song T"),local("STBShusong"),local("TBMincho"),local("HYMyeongJo"), /*Kindle Paperwihite*/
+ local("DK-SONGTI"),
+ url(../Fonts/zw.ttf),
+ url(res:///opt/sony/ebook/FONT/zw.ttf),
+ url(res:///Data/FONT/zw.ttf),
+ url(res:///opt/sony/ebook/FONT/tt0011m_.ttf),
+ url(res:///ebook/fonts/../../mnt/sdcard/fonts/zw.ttf),
+ url(res:///ebook/fonts/../../mnt/extsd/fonts/zw.ttf),
+ url(res:///ebook/fonts/zw.ttf),
+ url(res:///ebook/fonts/DroidSansFallback.ttf),
+ url(res:///fonts/ttf/zw.ttf),
+ url(res:///../../media/mmcblk0p1/fonts/zw.ttf),
+ url(file:///mnt/us/DK_System/system/fonts/zw.ttf), /*Duokan Old Path*/
+ url(file:///mnt/us/DK_System/xKindle/res/userfonts/zw.ttf), /*Duokan 2012 Path*/
+ url(res:///abook/fonts/zw.ttf),
+ url(res:///system/fonts/zw.ttf),
+ url(res:///system/media/sdcard/fonts/zw.ttf),
+ url(res:///media/fonts/zw.ttf),
+ url(res:///sdcard/fonts/zw.ttf),
+ url(res:///system/fonts/DroidSansFallback.ttf),
+ url(res:///mnt/MOVIFAT/font/zw.ttf),
+ url(res:///media/flash/fonts/zw.ttf),
+ url(res:///media/sd/fonts/zw.ttf),
+ url(res:///opt/onyx/arm/lib/fonts/AdobeHeitiStd-Regular.otf),
+ url(res:///../../fonts/zw.ttf),
+ url(res:///../fonts/zw.ttf),
+ url(../../../../../zw.ttf), /*EpubReaderI*/
+ url(res:///mnt/sdcard/fonts/zw.ttf), /*Nook for Android: fonts in TF Card*/
+ url(res:///fonts/zw.ttf), /*ADE1,8, 2.0 Program Path*/
+ url(res:///../../../../Windows/fonts/zw.ttf);
+ /*ADE1,8, 2.0 Windows Path*/;
+}
+
+@font-face {
+ font-family: "fs";
+ src:
+ local("amasis30"),local("仿宋"),local("仿宋_GB2312"),
+ local("Yuanti"),local("Yuanti SC"),local("Yuanti TC"), /*iOS6+iBooks3*/
+ local("DK-FANGSONG"),
+ url(../Fonts/fs.ttf),
+ url(res:///opt/sony/ebook/FONT/fs.ttf),
+ url(res:///Data/FONT/fs.ttf),
+ url(res:///opt/sony/ebook/FONT/tt0011m_.ttf),
+ url(res:///ebook/fonts/../../mnt/sdcard/fonts/fs.ttf),
+ url(res:///ebook/fonts/../../mnt/extsd/fonts/fs.ttf),
+ url(res:///ebook/fonts/fs.ttf),
+ url(res:///ebook/fonts/DroidSansFallback.ttf),
+ url(res:///fonts/ttf/fs.ttf),
+ url(res:///../../media/mmcblk0p1/fonts/fs.ttf),
+ url(file:///mnt/us/DK_System/system/fonts/fs.ttf), /*Duokan Old Path*/
+ url(file:///mnt/us/DK_System/xKindle/res/userfonts/fs.ttf), /*Duokan 2012 Path*/
+ url(res:///abook/fonts/fs.ttf),
+ url(res:///system/fonts/fs.ttf),
+ url(res:///system/media/sdcard/fonts/fs.ttf),
+ url(res:///media/fonts/fs.ttf),
+ url(res:///sdcard/fonts/fs.ttf),
+ url(res:///system/fonts/DroidSansFallback.ttf),
+ url(res:///mnt/MOVIFAT/font/fs.ttf),
+ url(res:///media/flash/fonts/fs.ttf),
+ url(res:///media/sd/fonts/fs.ttf),
+ url(res:///opt/onyx/arm/lib/fonts/AdobeHeitiStd-Regular.otf),
+ url(res:///../../fonts/fs.ttf),
+ url(res:///../fonts/fs.ttf),
+ url(../../../../../fs.ttf), /*EpubReaderI*/
+ url(res:///mnt/sdcard/fonts/fs.ttf), /*Nook for Android: fonts in TF Card*/
+ url(res:///fonts/fs.ttf), /*ADE1,8, 2.0 Program Path*/
+ url(res:///../../../../Windows/fonts/fs.ttf);
+ /*ADE1,8, 2.0 Windows Path*/;
+}
+
+@font-face {
+ font-family: "kt";
+ src:
+ local("Caecilia"),local("楷体"),local("楷体_GB2312"),
+ local("Kaiti"),local("Kaiti SC"),local("Kaiti TC"), /*iOS6+iBooks3*/
+ local("MKai PRC"),local("MKaiGB18030C-Medium"),local("MKaiGB18030C-Bold"), /*Kindle Paperwihite*/
+ local("DK-KAITI"),
+ url(../Fonts/kt.ttf),
+ url(res:///opt/sony/ebook/FONT/kt.ttf),
+ url(res:///Data/FONT/kt.ttf),
+ url(res:///opt/sony/ebook/FONT/tt0011m_.ttf),
+ url(res:///ebook/fonts/../../mnt/sdcard/fonts/kt.ttf),
+ url(res:///ebook/fonts/../../mnt/extsd/fonts/kt.ttf),
+ url(res:///ebook/fonts/kt.ttf),
+ url(res:///ebook/fonts/DroidSansFallback.ttf),
+ url(res:///fonts/ttf/kt.ttf),
+ url(res:///../../media/mmcblk0p1/fonts/kt.ttf),
+ url(file:///mnt/us/DK_System/system/fonts/kt.ttf), /*Duokan Old Path*/
+ url(file:///mnt/us/DK_System/xKindle/res/userfonts/kt.ttf), /*Duokan 2012 Path*/
+ url(res:///abook/fonts/kt.ttf),
+ url(res:///system/fonts/kt.ttf),
+ url(res:///system/media/sdcard/fonts/kt.ttf),
+ url(res:///media/fonts/kt.ttf),
+ url(res:///sdcard/fonts/kt.ttf),
+ url(res:///system/fonts/DroidSansFallback.ttf),
+ url(res:///mnt/MOVIFAT/font/kt.ttf),
+ url(res:///media/flash/fonts/kt.ttf),
+ url(res:///media/sd/fonts/kt.ttf),
+ url(res:///opt/onyx/arm/lib/fonts/AdobeHeitiStd-Regular.otf),
+ url(res:///../../fonts/kt.ttf),
+ url(res:///../fonts/kt.ttf),
+ url(../../../../../kt.ttf), /*EpubReaderI*/
+ url(res:///mnt/sdcard/fonts/kt.ttf), /*Nook for Android: fonts in TF Card*/
+ url(res:///fonts/kt.ttf), /*ADE1,8, 2.0 Program Path*/
+ url(res:///../../../../Windows/fonts/kt.ttf);
+ /*ADE1,8, 2.0 Windows Path*/;
+}
+
+@font-face {
+ font-family: "ht";
+ src:
+ local("黑体"),local("微软雅黑"),
+ local("Heiti"),local("Heiti SC"),local("Heiti TC"), /*iOS6+iBooks3*/
+ local("MYing Hei S"),local("MYing Hei T"),local("TBGothic"), /*Kindle Paperwihite*/
+ local("DK-HEITI"),
+ url(../Fonts/ht.ttf),
+ url(res:///opt/sony/ebook/FONT/ht.ttf),
+ url(res:///Data/FONT/ht.ttf),
+ url(res:///opt/sony/ebook/FONT/tt0011m_.ttf),
+ url(res:///ebook/fonts/../../mnt/sdcard/fonts/ht.ttf),
+ url(res:///ebook/fonts/../../mnt/extsd/fonts/ht.ttf),
+ url(res:///ebook/fonts/ht.ttf),
+ url(res:///ebook/fonts/DroidSansFallback.ttf),
+ url(res:///fonts/ttf/ht.ttf),
+ url(res:///../../media/mmcblk0p1/fonts/ht.ttf),
+ url(file:///mnt/us/DK_System/system/fonts/ht.ttf), /*Duokan Old Path*/
+ url(file:///mnt/us/DK_System/xKindle/res/userfonts/ht.ttf), /*Duokan 2012 Path*/
+ url(res:///abook/fonts/ht.ttf),
+ url(res:///system/fonts/ht.ttf),
+ url(res:///system/media/sdcard/fonts/ht.ttf),
+ url(res:///media/fonts/ht.ttf),
+ url(res:///sdcard/fonts/ht.ttf),
+ url(res:///system/fonts/DroidSansFallback.ttf),
+ url(res:///mnt/MOVIFAT/font/ht.ttf),
+ url(res:///media/flash/fonts/ht.ttf),
+ url(res:///media/sd/fonts/ht.ttf),
+ url(res:///opt/onyx/arm/lib/fonts/AdobeHeitiStd-Regular.otf),
+ url(res:///../../fonts/ht.ttf),
+ url(res:///../fonts/ht.ttf),
+ url(../../../../../ht.ttf), /*EpubReaderI*/
+ url(res:///mnt/sdcard/fonts/ht.ttf), /*Nook for Android: fonts in TF Card*/
+ url(res:///fonts/ht.ttf), /*ADE1,8, 2.0 Program Path*/
+ url(res:///../../../../Windows/fonts/ht.ttf);
+ /*ADE1,8, 2.0 Windows Path*/;
+}
+@font-face {
+ font-family:"h1";
+ src:
+ local("方正兰亭特黑长_GBK"),local("方正兰亭特黑长简体"),local("方正兰亭特黑长繁体"),
+ local("LantingTeheichang"),
+ local("Yuanti"),local("Yuanti SC"),local("Yuanti TC"),
+ local("DK-HEITI"),
+ url(../Fonts/h1.ttf),
+ url(res:///opt/sony/ebook/FONT/h1.ttf),
+ url(res:///Data/FONT/h1.ttf),
+ url(res:///opt/sony/ebook/FONT/tt0011m_.ttf),
+ url(res:///ebook/fonts/../../mnt/sdcard/fonts/h1.ttf),
+ url(res:///ebook/fonts/../../mnt/extsd/fonts/h1.ttf),
+ url(res:///ebook/fonts/h1.ttf),
+ url(res:///ebook/fonts/DroidSansFallback.ttf),
+ url(res:///fonts/ttf/h1.ttf),
+ url(res:///../../media/mmcblk0p1/fonts/h1.ttf),
+ url(file:///mnt/us/DK_System/system/fonts/h1.ttf), /*Duokan Old Path*/
+ url(file:///mnt/us/DK_System/xKindle/res/userfonts/h1.ttf), /*Duokan 2012 Path*/
+ url(res:///abook/fonts/h1.ttf),
+ url(res:///system/fonts/h1.ttf),
+ url(res:///system/media/sdcard/fonts/h1.ttf),
+ url(res:///media/fonts/h1.ttf),
+ url(res:///sdcard/fonts/h1.ttf),
+ url(res:///system/fonts/DroidSansFallback.ttf),
+ url(res:///mnt/MOVIFAT/font/h1.ttf),
+ url(res:///media/flash/fonts/h1.ttf),
+ url(res:///media/sd/fonts/h1.ttf),
+ url(res:///opt/onyx/arm/lib/fonts/AdobeHeitiStd-Regular.otf),
+ url(res:///../../fonts/h1.ttf),
+ url(res:///../fonts/h1.ttf),
+ url(../../../../../h1.ttf), /*EpubReaderI*/
+ url(res:///mnt/sdcard/fonts/h1.ttf), /*Nook for Android: fonts in TF Card*/
+ url(res:///fonts/h1.ttf), /*ADE1,8, 2.0 Program Path*/
+ url(res:///../../../../Windows/fonts/h1.ttf); /*ADE1,8, 2.0 Windows Path*/
+}
+@font-face {
+ font-family:"h2";
+ src:
+ local("方正大标宋_GBK"),local("方正大标宋简体"),local("方正大标宋繁体"),
+ local("Dabiaosong"),
+ local("Heiti"),local("Heiti SC"),local("Heiti TC"),
+ local("DK-XIAOBIAOSONG"),
+ url(../Fonts/h2.ttf),
+ url(res:///opt/sony/ebook/FONT/h2.ttf),
+ url(res:///Data/FONT/h2.ttf),
+ url(res:///opt/sony/ebook/FONT/tt0011m_.ttf),
+ url(res:///ebook/fonts/../../mnt/sdcard/fonts/h2.ttf),
+ url(res:///ebook/fonts/../../mnt/extsd/fonts/h2.ttf),
+ url(res:///ebook/fonts/h2.ttf),
+ url(res:///ebook/fonts/DroidSansFallback.ttf),
+ url(res:///fonts/ttf/h2.ttf),
+ url(res:///../../media/mmcblk0p1/fonts/h2.ttf),
+ url(file:///mnt/us/DK_System/system/fonts/h2.ttf), /*Duokan Old Path*/
+ url(file:///mnt/us/DK_System/xKindle/res/userfonts/h2.ttf), /*Duokan 2012 Path*/
+ url(res:///abook/fonts/h2.ttf),
+ url(res:///system/fonts/h2.ttf),
+ url(res:///system/media/sdcard/fonts/h2.ttf),
+ url(res:///media/fonts/h2.ttf),
+ url(res:///sdcard/fonts/h2.ttf),
+ url(res:///system/fonts/DroidSansFallback.ttf),
+ url(res:///mnt/MOVIFAT/font/h2.ttf),
+ url(res:///media/flash/fonts/h2.ttf),
+ url(res:///media/sd/fonts/h2.ttf),
+ url(res:///opt/onyx/arm/lib/fonts/AdobeHeitiStd-Regular.otf),
+ url(res:///../../fonts/h2.ttf),
+ url(res:///../fonts/h2.ttf),
+ url(../../../../../h2.ttf), /*EpubReaderI*/
+ url(res:///mnt/sdcard/fonts/h2.ttf), /*Nook for Android: fonts in TF Card*/
+ url(res:///fonts/h2.ttf), /*ADE1,8, 2.0 Program Path*/
+ url(res:///../../../../Windows/fonts/h2.ttf); /*ADE1,8, 2.0 Windows Path*/
+}
+
+@font-face {
+ font-family:"h3";
+ src:
+ local("方正华隶_GBK"),local("方正行黑简体"),local("方正行黑繁体"),
+ local("Yuanti"),local("Yuanti SC"),local("Yuanti TC"),
+ local("DK-FANGSONG"),
+ url(../Fonts/h3.ttf),
+ url(res:///opt/sony/ebook/FONT/h3.ttf),
+ url(res:///Data/FONT/h3.ttf),
+ url(res:///opt/sony/ebook/FONT/tt0011m_.ttf),
+ url(res:///ebook/fonts/../../mnt/sdcard/fonts/h3.ttf),
+ url(res:///ebook/fonts/../../mnt/extsd/fonts/h3.ttf),
+ url(res:///ebook/fonts/h3.ttf),
+ url(res:///ebook/fonts/DroidSansFallback.ttf),
+ url(res:///fonts/ttf/h3.ttf),
+ url(res:///../../media/mmcblk0p1/fonts/h3.ttf),
+ url(file:///mnt/us/DK_System/system/fonts/h3.ttf), /*Duokan Old Path*/
+ url(file:///mnt/us/DK_System/xKindle/res/userfonts/h3.ttf), /*Duokan 2012 Path*/
+ url(res:///abook/fonts/h3.ttf),
+ url(res:///system/fonts/h3.ttf),
+ url(res:///system/media/sdcard/fonts/h3.ttf),
+ url(res:///media/fonts/h3.ttf),
+ url(res:///sdcard/fonts/h3.ttf),
+ url(res:///system/fonts/DroidSansFallback.ttf),
+ url(res:///mnt/MOVIFAT/font/h3.ttf),
+ url(res:///media/flash/fonts/h3.ttf),
+ url(res:///media/sd/fonts/h3.ttf),
+ url(res:///opt/onyx/arm/lib/fonts/AdobeHeitiStd-Regular.otf),
+ url(res:///../../fonts/h3.ttf),
+ url(res:///../fonts/h3.ttf),
+ url(../../../../../h3.ttf), /*EpubReaderI*/
+ url(res:///mnt/sdcard/fonts/h3.ttf), /*Nook for Android: fonts in TF Card*/
+ url(res:///fonts/h3.ttf), /*ADE1,8, 2.0 Program Path*/
+ url(res:///../../../../Windows/fonts/h3.ttf); /*ADE1,8, 2.0 Windows Path*/
+}
+
+@font-face {
+ font-family:"luohua";
+ src:local("汉仪落花体"),
+ url("../Fonts/hylh.ttf");
+}
\ No newline at end of file
diff --git a/app/src/main/assets/epub/intro.html b/app/src/main/assets/epub/intro.html
new file mode 100644
index 000000000..85eb28a63
--- /dev/null
+++ b/app/src/main/assets/epub/intro.html
@@ -0,0 +1,12 @@
+
+
+
+
+ Intro
+
+
+
+
+内容简介
{intro}
+
diff --git a/app/src/main/assets/epub/logo.png b/app/src/main/assets/epub/logo.png
new file mode 100644
index 000000000..104d1777c
Binary files /dev/null and b/app/src/main/assets/epub/logo.png differ
diff --git a/app/src/main/assets/epub/main.css b/app/src/main/assets/epub/main.css
new file mode 100644
index 000000000..fcb287442
--- /dev/null
+++ b/app/src/main/assets/epub/main.css
@@ -0,0 +1,551 @@
+@charset "utf-8";
+@import url("../Styles/fonts.css");
+body {
+ padding: 0%;
+ margin-top: 0%;
+ margin-bottom: 0%;
+ margin-left: 0.5%;
+ margin-right: 0.5%;
+ line-height: 130%;
+ text-align: justify;
+ font-family: "DK-SONGTI","st","宋体","zw",sans-serif;
+}
+
+p {
+ text-align: justify;
+ text-indent: 2em;
+ line-height: 130%;
+ margin-right: 0.5%;
+ margin-left: 0.5%;
+ font-family: "DK-SONGTI","st","宋体","zw",sans-serif;
+}
+p.kaiti {
+ font-family: "DK-KAITI","kt","楷体","zw",serif;
+}
+
+p.fangsong {
+ font-family: "DK-FANGSONG","fs","仿宋","zw",serif;
+}
+
+span.xinli {
+ font-family: "DK-KAITI","kt","楷体","zw",serif;
+ color: #4e753f;
+}
+/** 英文斜体字 **/
+span.english{
+ font-style: italic;
+}
+div {
+ margin: 0px;
+ padding: 0px;
+ line-height: 120%;
+ text-align: justify;
+ font-family: "zw";
+}
+div.foot {
+ text-indent: 2em;
+ margin: 30% 5% 0 5%;
+ padding: 8px 0;
+}
+p.foot {
+ font-family: "DK-KAITI","kt","楷体","zw",serif;
+}
+
+/*扉页*/
+.booksubtitle {
+ padding: 10px 0 0px 0;
+ text-indent: 0em;
+ font-size: 75%;
+ font-family: "ht";
+}
+
+.booktitle {
+ padding: 9% 0 0 0;
+ font-size: 1.3em;
+ font-family: "方正小标宋_GBK","DK-XIAOBIAOSONG";
+ font-weight: normal;
+ text-indent: 0em;
+ color: #000;
+ text-align: center;
+ line-height: 1.6;
+}
+
+.booktitle0 {
+ font-size: 1.2em;
+ font-family: "fs";
+ text-indent: 0em;
+ text-align: center;
+ line-height: 1.8;
+}
+
+.booktitle1 {
+ padding: 0 0 0 0;
+ font-size: 0.85em;
+ font-family: "fs";
+ text-indent: 0em;
+ text-align: center;
+ line-height: 1.6;
+}
+
+.bookauthor {
+ font-family: "DK-FANGSONG",仿宋,"fs","fangsong",sans-serif;
+ padding: 5% 5px 0px 5px;
+ text-indent: 0em;
+ text-align: center;
+ color: #000;
+ font-size: 90%;
+ line-height: 1.3;
+}
+
+.booktranslator {
+ padding: 1% 5px 0px 5px;
+ text-indent: 0em;
+ text-align: center;
+ font-size: 85%;
+ line-height: 1.3;
+}
+
+.bookpub {
+ font-family: "DK-KAITI","kt","楷体","楷体_gb2312";
+ padding: 30% 5px 5px 5px;
+ text-indent: 0em;
+ color: #000;
+ text-align: center;
+ font-size: 80%;
+}
+
+/*标题页*/
+body.head {
+ background-repeat:no-repeat no-repeat;
+ background-size:160px 229px;
+ background-position:bottom right;
+ background-attachment:fixed;
+}
+
+body.xhead {
+ background-color: #FDF5E6;
+}
+
+h1.head {
+ font-family: "DK-HEITI",黑体,sans-serif;
+ font-size: 1.2em;
+ font-weight: bold;
+ color: #311a02;
+ text-indent: 0em;
+ font-weight: normal;
+ duokan-text-indent: 0em;
+ padding: auto;
+ text-align: center;
+ margin-top: -8em;
+}
+
+div.head {
+ border: solid 2px #ffffff;
+ padding: 2px;
+ margin: 2em auto 0.7em auto;
+ text-align: center;
+ width: 1em;
+}
+
+h1.head b {
+ font-family: "方正小标宋_GBK","DK-XIAOBIAOSONG";
+ font-weight: bold;
+ font-size: 1.2em;
+ text-align: center;
+ text-indent: 0em;
+ duokan-text-indent: 0em;
+ color: #311a02;
+ margin: 0.5em auto;
+ line-height: 140%;
+}
+
+div.back {
+ text-align: center;
+ text-indent: 0em;
+ duokan-text-indent: 0em;
+ margin: 4em auto;
+}
+
+img.back {
+ width: 70%;
+}
+img.back2 {
+ width: 40%;
+ margin: 2em 0 0 0;
+}
+/*正文*/
+/**楷体引文**/
+.titou {
+ font-family: "DK-FANGSONG",仿宋,"fs","fangsong",sans-serif;
+}
+.yinwen {
+ font-family: "DK-KAITI","kt","楷体","zw",serif;
+ margin-left: 2em;
+ text-indent: 0em;
+}
+.nicename {
+ font-family: "DK-HEITI",黑体,sans-serif;
+ font-weight: bold;
+ font-size: 0.9em;
+}
+body.head3 {
+ background-color: #a7bdcc;
+ color: #354f66;
+}
+
+body.head4 {
+ background-color: #bfd19b;
+ color: #4e753f;
+}
+
+h2.head {
+ font-family: "小标宋";
+ text-align: left;
+ font-weight: bold;
+ font-size: 1.1em;
+ margin: -3em 2em 2em 0;
+ color: #3f83e8;
+ line-height: 140%;
+}
+
+h2.head span {
+ font-family: "仿宋";
+ font-size: 0.7em;
+ background-color: #3f83e8;
+ border-radius: 9px;
+ padding: 4px;
+ color: #fff;
+}
+
+
+div.logo {
+ margin: -2em 0% 0 0;
+ text-align: right;
+}
+
+img.logo {
+ width: 40%;
+}
+.imgl {
+ /*图片居右*/
+ margin: -8.8em 1em 4em 0em;
+ width: 80%;
+ text-align: right;
+}
+
+h1.head {
+ line-height:130%;
+ font-size:1.4em;
+ text-align: center;
+ color: #BA2213;
+ font-weight: bold;
+ margin-top: 2em;
+ margin-bottom: 1em;
+ font-family: "方正小标宋_GBK","DK-XIAOBIAOSONG";
+
+}
+h3 {
+ font-family: "DK-HEITI",黑体,sans-serif;
+ font-size: 1.1em;
+ margin: 1em 0;
+ border-left: 1.2em solid #00a1e9;
+ line-height: 120%;
+ padding-left: 3px;
+ color: #00a1e9;
+}
+h4 {
+ font-family: "DK-HEITI",黑体,sans-serif;
+ font-size: 1.1em;
+ text-align: center;
+ margin: 1em 0;
+ line-height: 120%;
+ color: #000;
+}
+h1.post {
+ font-family: "方正小标宋_GBK","DK-XIAOBIAOSONG";
+ text-align: center;
+ font-size: 1.3em;
+ color: #026fca;
+ margin: 3em auto 2em auto;
+}
+.banquan {
+ font-family: "DK-FANGSONG",仿宋,"fs","fangsong",sans-serif;
+ text-align: left;
+ color: #000;
+ font-size:1.1em;
+ margin-bottom:1em;
+ text-indent: 1em;
+ duokan-text-indent: 1em;
+}
+p.post {
+ font-family: "DK-FANGSONG",仿宋,"fs","fangsong",sans-serif;
+}
+p.zy {
+ font-family: "DK-FANGSONG",仿宋,"fs","fangsong",sans-serif;
+ margin: 1em 0 0 1em;
+ padding: 5px 0px 5px 10px;
+ text-indent: 0em;
+ border-left: 5px solid #a9b5c1;
+}
+.sign {
+ font-family: "DK-KAITI","kt","楷体","zw",serif;
+ margin: 1em 2px 0 auto;
+ text-align: right;
+ font-size: 0.8em;
+ text-indent: 0em;
+ duokan-text-indent: 0em;
+}
+
+.mark {
+ font-family: "DK-HEITI",黑体,sans-serif;
+ font-size: 0.9em;
+ color: #fff;
+ text-indent: 0em;
+ duokan-text-indent: 0em;
+ background-color: maroon;
+ text-align: center;
+ padding: 0px;
+ margin: 2em 30%;
+}
+
+/*出版社*/
+.chubanshe img{
+ width:106px;
+ height:28px;
+}
+.chubanshe {
+ margin-top:20px;
+}
+.cr {
+ font-size:0.9em;
+}
+
+/*多看画廊*/
+div.duokan-image-single {
+ text-align: center;
+ margin: 0.5em auto; /*插图盒子上下外边距为0.5em,左右设置auto是为了水平居中这个盒子*/
+}
+img.picture-80 {
+ margin: 0; /*清除img元素的外边距*/
+ width: 80%; /*预览窗口的宽度*/
+ box-shadow: 3px 3px 10px #bfbfbf; /*给图片添加阴影效果*/
+}
+p.duokan-image-maintitle {
+ margin: 1em 0 0; /*图片说明的段间距*/
+ font-family: "楷体"; /*图片说明使用的字体*/
+ font-size: 0.9em; /*字体大小*/
+ text-indent: 0; /*首行缩进为零,当你使用单标签p来指定首行缩进为2em时,记得在需要居中的文本中清除缩进,因为样式是叠加的*/
+ text-align: center; /*图片说明水平居中*/
+ color: #a52a2a; /*字体颜色*/
+ line-height: 1.25em; /*行高,防止有很长的图片说明*/
+}
+
+
+/*制作说明页*/
+body.description {
+ background-image: url(../Images/001.png);
+ background-position: bottom center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ padding: 25% 10% 0;
+ font-size: 0.9em;
+}
+
+div.description-body {
+ width: 55%;
+ padding: 2em 1.3em;
+ border-radius: 0.5em;
+ font-size: 0.9em;
+ border-style: solid;
+ border-color: #393939;
+ border-width: 0.3em;
+ border-radius: 5em;
+ background-color: #5a5a5a;
+ box-shadow: 2px 2px 3px #828281;
+}
+
+h1.description-title {
+ text-align: center;
+ font-family: "黑体";
+ font-size: 1.2em;
+ margin: 0 0 1em 0;
+ color: #FF9;
+ text-shadow: 1px 1px 0 black;
+}
+
+p.description-text {
+ color: #f9ddd2;
+ font-family: "准圆";
+ margin: 0;
+ text-align: justify;
+ text-indent: 0;
+ duokan-text-indent: 0;
+}
+
+hr.description-hr {
+ margin: 0.5em -1em;
+ border-style: dotted;
+ border-color: #9C9;
+ border-width: 0.05em 0 0 0;
+}
+
+p.tips {
+ text-align: justify;
+ text-indent: 0;
+ duokan-text-indent: 0;
+ font-family: "楷体";
+ font-size: 0.7em;
+ color: #FFC;
+ margin: 0;
+}
+
+/*版本说明页*/
+.ver {
+ font-family: "DK-CODE","DK-XIHEITI",细黑体,"xihei",sans-serif;
+ font-weight: bold;
+ font-size: 100%;
+ color: #000;
+ margin: 1em 0 1em 0;
+ text-align: center;
+}
+
+.vertitle {
+ font-family: "DK-FANGSONG",仿宋,"fs","fangsong",sans-serif;
+ font-size: 100%;
+ text-indent: 0em;
+ text-align: left;
+ duokan-text-indent: 0em;
+}
+
+.vertxt {
+ font-family: "DK-FANGSONG",仿宋,"fs","fangsong",sans-serif;
+ line-height: 100%;
+ font-size: 85%;
+ text-indent: 0em;
+ text-align: left;
+ duokan-text-indent: 0em;
+}
+.verchar {
+ font-family: "DK-KAITI","kt","楷体","楷体_gb2312";
+ text-align: left;
+ text-indent: 1em;
+ duokan-text-indent: 1em;
+ margin-bottom: 1em;
+ margin-top: 1em;
+}
+.vernote {
+ font-family: "DK-FANGSONG",仿宋,"fs","fangsong",sans-serif;
+ font-size: 75%;
+ color: #686d70;
+ text-indent: 0em;
+ text-align: left;
+ duokan-text-indent: 0em;
+ padding-bottom: 15px;
+}
+
+.line {
+ border: dotted #A2906A;
+ border-width: 1px 0 0 0;
+}
+
+.entry {
+ margin-left: 18px;
+ font-size: 83%;
+ color: #8fe0a3;
+ text-indent: 0em;
+ duokan-text-indent: 0em;
+}
+/*版权信息*/
+.vol {
+ text-indent: 0em;
+ text-align: center;
+ padding: 0.8em;
+ margin: 0 auto 3px auto;
+ color: #000;
+ font-family: "方正小标宋_GBK","DK-XIAOBIAOSONG";
+ font-size: 130%;
+ text-shadow: none;
+}
+
+.cp {
+ font-family: "DK-CODE","DK-XIHEITI",细黑体,"xihei",sans-serif;
+ color: #412938;
+ font-size: 70%;
+ text-align: left;
+ text-indent: 0em;
+ duokan-text-indent: 0em;
+}
+
+.xchar {
+ font-family: "DK-KAITI","kt","楷体","楷体_gb2312";
+ text-indent: 0em;
+ duokan-text-indent: 0em;
+}
+/*多看弹注*/
+sup img {
+ line-height: 100%;
+ width: auto;
+ height: 1.0em;
+ margin: 0em;
+ padding: 0em;
+ vertical-align: text-top;
+}
+
+ol {
+ margin-bottom:0;
+ padding:0 auto;
+ list-style-type: decimal;
+}
+.hr {
+ width:50%;
+ margin:2em 0 0 0.5em;
+ padding:0;
+ height:2px;
+ background-color: #F3221D;
+}
+
+.duokan-footnote-content{
+ padding:0 auto;
+ text-align: left;
+}
+
+.duokan-footnote-item {
+ font-family:"DK-XIHEITI",细黑体,"xihei",sans-serif;
+ text-align: left;
+ font-size: 80%;
+ line-height: 100%;
+ clear: both;
+ color:#000;
+ list-style-type:decimal;
+}
+
+li.duokan-footnote-item a {
+ font-family:"DK-HEITI";
+ text-align: left;
+}
+a{
+ text-decoration: none;
+ color: #222;
+}
+
+a:hover {background: #81caf9}
+a:active {background: yellow}
+.duokan-image-maintitle {
+ font-family:"DK-HEITI",黑体,"hei",sans-serif;
+ text-align: center;
+ text-indent: 0em;
+ duokan-text-indent: 0em;
+ font-size:90%;
+ color: #1F4150;
+ margin-top: 1em;
+}
+
+.duokan-image-subtitle {
+ font-family:"DK-XIHEITI",细黑体,"xihei",sans-serif;
+ text-align: center;
+ text-indent: 0em;
+ duokan-text-indent: 0em;
+ font-size:70%;
+ color: #3A3348;
+ margin-top: 1em;
+}
\ No newline at end of file
diff --git a/app/src/main/assets/help/ruleHelp.md b/app/src/main/assets/help/ruleHelp.md
index 4d50dde6c..01eb44eba 100644
--- a/app/src/main/assets/help/ruleHelp.md
+++ b/app/src/main/assets/help/ruleHelp.md
@@ -11,6 +11,12 @@
: regex规则,不可省略,只可以用在书籍列表和目录列表
```
+* 获取登录后的cookie
+```
+java.getCookie("http://baidu.com", null) => userid=1234;pwd=adbcd
+java.getCookie("http://baidu.com", "userid") => 1234
+```
+
* 请求头,支持http代理,socks4 socks5代理设置
```
socks5代理
@@ -39,6 +45,49 @@ cache 变量-缓存操作类,方法见 io.legado.app.help.CacheManager
chapter 变量-当前目录类,方法见 io.legado.app.data.entities.BookChapter
title 变量-当前标题,String
src 内容,源码
+```
+
+* url添加js参数,解析url时执行,可在访问url时处理url,例
+```
+https://www.baidu.com,{"js":"java.headerMap.put('xxx', 'yyy')"}
+https://www.baidu.com,{"js":"java.url=java.url+'yyyy'"}
+```
+
+* 增加js方法,用于重定向拦截
+ * `java.get(urlStr: String, headers: Map)`
+ * `java.post(urlStr: String, body: String, headers: Map)`
+* 对于搜索重定向的源,可以使用此方法获得重定向后的url
+```
+(()=>{
+ if(page==1){
+ let url='https://www.yooread.net/e/search/index.php,'+JSON.stringify({
+ "method":"POST",
+ "body":"show=title&tempid=1&keyboard="+key
+ });
+ return java.put('surl',String(java.connect(url).raw().request().url()));
+ } else {
+ return java.get('surl')+'&page='+(page-1)
+ }
+})()
+或者
+(()=>{
+ let base='https://www.yooread.net/e/search/';
+ if(page==1){
+ let url=base+'index.php';
+ let body='show=title&tempid=1&keyboard='+key;
+ return base+java.put('surl',java.post(url,body,{}).header("Location"));
+ } else {
+ return base+java.get('surl')+'&page='+(page-1);
+ }
+})()
+```
+
+* 正文图片链接支持修改headers
+```
+let options = {
+"headers": {"User-Agent": "xxxx","Referrer":baseUrl,"Cookie":"aaa=vbbb;"}
+};
+''
```
## 部分js对象属性说明
@@ -95,14 +144,16 @@ variable // 自定义书籍变量信息(用于书源规则检索书籍信息)
### 字体解析使用
> 使用方法,在正文替换规则中使用,原理根据f1字体的字形数据到f2中查找字形对应的编码
```
-@js:
-var b64=String(src).match(/ttf;base64,([^\)]+)/);
-if (b64) {
- var f1 = java.queryBase64TTF(b64[1])
- var f2 = java.queryTTF("/storage/emulated/0/Fonts/Source Han Sans CN Regular.ttf")
- java.replaceFont(result, f1, f2)
-}else{
- result
-}
+
+(function(){
+ var b64=String(src).match(/ttf;base64,([^\)]+)/);
+ if(b64){
+ var f1 = java.queryBase64TTF(b64[1]);
+ var f2 = java.queryTTF("https://alanskycn.gitee.io/teachme/assets/font/Source Han Sans CN Regular.ttf");
+ return java.replaceFont(result, f1, f2);
+ }
+ return result;
+})()
+
```
diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md
index 0daafa351..20e915987 100644
--- a/app/src/main/assets/updateLog.md
+++ b/app/src/main/assets/updateLog.md
@@ -18,6 +18,18 @@
* 添加书架文件夹分组样式,未完成
* viewPager2 3层嵌套有问题,书架换回viewPager
+**2021/05/29**
+* 谷歌版可使用外部epub模板
+* Asset文件夹下二级以内目录全文件读取,Asset->文件夹->文件
+* epub元数据修改,使修改字体只对正文生效
+* 修复epub模板文件的排序问题
+* epub可自定义模板,模板路径为书籍导出目录的Asset文件夹,[模板范例](https://wwa.lanzoux.com/ibjBspkn05i)
+```
+Asset中里面必须有Text文件夹,Text文件夹里必须有chapter.html,否则导出正文会为空
+chapter.html的关键字有{title}、{content}
+其他html文件的关键字有{name}、{author}、{intro}、{kind}、{wordCount}
+```
+
**2021/05/26**
* 书签绑定书名与作者
* 修复详情页目录问题
diff --git a/app/src/main/java/io/legado/app/constant/AppConst.kt b/app/src/main/java/io/legado/app/constant/AppConst.kt
index a7db60a2d..e76b28df3 100644
--- a/app/src/main/java/io/legado/app/constant/AppConst.kt
+++ b/app/src/main/java/io/legado/app/constant/AppConst.kt
@@ -38,9 +38,9 @@ object AppConst {
val keyboardToolChars: List by lazy {
arrayListOf(
- "❓", "@css:", "", "{{}}", "&&", "%%", "||", "//", "$.", "@",
- "\\", ":", "class", "id", "href", "textNodes", "ownText", "all", "html",
- "[", "]", "<", ">", "##", "!", ".", "+", "-", "*", "=",",{\"webView\":true}"
+ "❓", "@css:", "", "{{}}", "##", "&&", "%%", "||", "//", "$.",
+ "@", ":", "class", "text", "href", "textNodes", "ownText", "all", "html",
+ "[", "]", "<", ">", "#", "!", ".", "+", "-", "*", "=", "{'webView': true}"
)
}
@@ -57,10 +57,12 @@ object AppConst {
val urlOption: String by lazy {
"""
,{
- "charset": "",
- "method": "POST",
- "body": "",
- "headers": {"User-Agent": ""}
+ 'charset': '',
+ 'method': 'POST',
+ 'body': '',
+ 'headers': {
+ 'User-Agent': ''
+ }
}
""".trimIndent()
}
diff --git a/app/src/main/java/io/legado/app/help/BookHelp.kt b/app/src/main/java/io/legado/app/help/BookHelp.kt
index 99adf90b1..6379d4cc3 100644
--- a/app/src/main/java/io/legado/app/help/BookHelp.kt
+++ b/app/src/main/java/io/legado/app/help/BookHelp.kt
@@ -38,7 +38,7 @@ object BookHelp {
}
/**
- * 清楚已删除书的缓存
+ * 清除已删除书的缓存
*/
fun clearRemovedCache() {
Coroutine.async {
diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt
index 43fcd60a9..a3698c76c 100644
--- a/app/src/main/java/io/legado/app/help/JsExtensions.kt
+++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt
@@ -311,9 +311,9 @@ interface JsExtensions {
* @param font2 正确的字体
*/
fun replaceFont(
- text: String,
- font1: QueryTTF?,
- font2: QueryTTF?
+ text: String,
+ font1: QueryTTF?,
+ font2: QueryTTF?
): String {
if (font1 == null || font2 == null) return text
val contentArray = text.toCharArray()
@@ -346,7 +346,7 @@ interface JsExtensions {
str: String,
key: String,
transformation: String,
- iv: String = ""
+ iv: String
): ByteArray? {
return EncoderUtils.decryptAES(
@@ -369,7 +369,7 @@ interface JsExtensions {
str: String,
key: String,
transformation: String,
- iv: String = ""
+ iv: String
): String? {
return aesDecodeToByteArray(str, key, transformation, iv)?.let { String(it) }
}
@@ -386,7 +386,7 @@ interface JsExtensions {
str: String,
key: String,
transformation: String,
- iv: String = ""
+ iv: String
): ByteArray? {
return EncoderUtils.decryptBase64AES(
data = str.encodeToByteArray(),
@@ -408,7 +408,7 @@ interface JsExtensions {
str: String,
key: String,
transformation: String,
- iv: String = ""
+ iv: String
): String? {
return aesBase64DecodeToByteArray(str, key, transformation, iv)?.let { String(it) }
}
@@ -422,7 +422,7 @@ interface JsExtensions {
*/
fun aesEncodeToByteArray(
data: String, key: String, transformation: String,
- iv: String = ""
+ iv: String
): ByteArray? {
return EncoderUtils.encryptAES(
data.encodeToByteArray(),
@@ -441,7 +441,7 @@ interface JsExtensions {
*/
fun aesEncodeToString(
data: String, key: String, transformation: String,
- iv: String = ""
+ iv: String
): String? {
return aesEncodeToByteArray(data, key, transformation, iv)?.let { String(it) }
}
@@ -455,7 +455,7 @@ interface JsExtensions {
*/
fun aesEncodeToBase64ByteArray(
data: String, key: String, transformation: String,
- iv: String = ""
+ iv: String
): ByteArray? {
return EncoderUtils.encryptAES2Base64(
data.encodeToByteArray(),
@@ -474,7 +474,7 @@ interface JsExtensions {
*/
fun aesEncodeToBase64String(
data: String, key: String, transformation: String,
- iv: String = ""
+ iv: String
): String? {
return aesEncodeToBase64ByteArray(data, key, transformation, iv)?.let { String(it) }
}
diff --git a/app/src/main/java/io/legado/app/model/Debug.kt b/app/src/main/java/io/legado/app/model/Debug.kt
index d8e606b0f..dc6259cc4 100644
--- a/app/src/main/java/io/legado/app/model/Debug.kt
+++ b/app/src/main/java/io/legado/app/model/Debug.kt
@@ -187,7 +187,7 @@ object Debug {
private fun infoDebug(scope: CoroutineScope, webBook: WebBook, book: Book) {
if (book.tocUrl.isNotBlank()) {
- log(debugSource, "目录url不为空,详情页已解析")
+ log(debugSource, "≡已获取目录链接,跳过详情页")
log(debugSource, showTime = false)
tocDebug(scope, webBook, book)
return
diff --git a/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt b/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
index 06ae294b4..24bf4981e 100644
--- a/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
+++ b/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
@@ -190,12 +190,12 @@ object BookChapterList {
chapterList.add(bookChapter)
}
}
- Debug.log(bookSource.bookSourceUrl, "└解析目录列表完成", log)
- Debug.log(bookSource.bookSourceUrl, "┌首章名称", log)
+ Debug.log(bookSource.bookSourceUrl, "└目录列表解析完成", log)
+ Debug.log(bookSource.bookSourceUrl, "┌获取首章名称", log)
Debug.log(bookSource.bookSourceUrl, "└${chapterList[0].title}", log)
- Debug.log(bookSource.bookSourceUrl, "┌首章链接", log)
+ Debug.log(bookSource.bookSourceUrl, "┌获取首章链接", log)
Debug.log(bookSource.bookSourceUrl, "└${chapterList[0].url}", log)
- Debug.log(bookSource.bookSourceUrl, "┌首章信息", log)
+ Debug.log(bookSource.bookSourceUrl, "┌获取首章信息", log)
Debug.log(bookSource.bookSourceUrl, "└${chapterList[0].tag}", log)
}
return ChapterData(chapterList, nextUrlList)
diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt
index fab7802b6..f89d997c3 100644
--- a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt
+++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt
@@ -23,6 +23,7 @@ import io.legado.app.utils.*
import me.ag2s.epublib.domain.*
import me.ag2s.epublib.epub.EpubWriter
import me.ag2s.epublib.util.ResourceUtil
+import splitties.init.appCtx
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
@@ -35,11 +36,11 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
fun getExportFileName(book: Book): String {
val jsStr = AppConfig.bookExportFileName
if (jsStr.isNullOrBlank()) {
- return "${book.name} by ${book.author}"
+ return "${book.name} 作者:${book.getRealAuthor()}"
}
val bindings = SimpleBindings()
bindings["name"] = book.name
- bindings["author"] = book.author
+ bindings["author"] = book.getRealAuthor()
return AppConst.SCRIPT_ENGINE.eval(jsStr, bindings).toString()
}
@@ -122,11 +123,29 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
private fun getAllContents(book: Book, append: (text: String) -> Unit) {
val useReplace = AppConfig.exportUseReplace
val contentProcessor = ContentProcessor(book.name, book.origin)
- append("${book.name}\n${context.getString(R.string.author_show, book.author)}")
+ append(
+ "${book.name}\n${
+ context.getString(
+ R.string.author_show,
+ book.getRealAuthor()
+ )
+ }\n${
+ context.getString(
+ R.string.intro_show,
+ "\n" + HtmlFormatter.format(book.getDisplayIntro())
+ )
+ }"
+ )
appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter ->
BookHelp.getContent(book, chapter).let { content ->
val content1 = contentProcessor
- .getContent(book, chapter.title, content ?: "null", false, useReplace)
+ .getContent(
+ book,
+ chapter.title.replace("\\r?\\n".toRegex(), " "),
+ content ?: "null",
+ false,
+ useReplace
+ )
.joinToString("\n")
append.invoke("\n\n$content1")
}
@@ -138,9 +157,9 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter ->
BookHelp.getContent(book, chapter)?.let { content ->
content.split("\n").forEachIndexed { index, text ->
- val matches = AppPattern.imgPattern.toRegex().findAll(input = text)
- matches.forEach { matchResult ->
- matchResult.groupValues[1].let {
+ val matcher = AppPattern.imgPattern.matcher(text)
+ while (matcher.find()) {
+ matcher.group(1)?.let {
val src = NetworkUtils.getAbsoluteURL(chapter.url, it)
srcList.add(Triple(chapter.title, index, src))
}
@@ -181,12 +200,11 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
setEpubMetadata(book, epubBook)
//set cover
setCover(book, epubBook)
-
//set css
- setCSS(epubBook)
- //设置正文
- setEpubContent(book, epubBook)
+ val contentModel = setAssets(doc, book, epubBook)
+ //设置正文
+ setEpubContent(contentModel, book, epubBook)
DocumentUtils.createFileIfNotExist(doc, filename)?.let { bookDoc ->
context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs ->
EpubWriter().write(epubBook, bookOs)
@@ -205,28 +223,144 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
//set cover
setCover(book, epubBook)
//set css
- setCSS(epubBook)
-
+ val contentModel = setAssets(book, epubBook)
val bookPath = FileUtils.getPath(file, filename)
val bookFile = FileUtils.createFileWithReplace(bookPath)
//设置正文
- setEpubContent(book, epubBook)
+ setEpubContent(contentModel, book, epubBook)
EpubWriter().write(epubBook, FileOutputStream(bookFile))
}
- private fun setCSS(epubBook: EpubBook) {
- //set css
+ private fun setAssets(doc: DocumentFile, book: Book, epubBook: EpubBook): String {
+ if(!AppConfig.isGooglePlay) return setAssets(book, epubBook)
+
+ var contentModel = ""
+ DocumentUtils.getDirDocument(doc, "Asset").let { customPath ->
+ if (customPath == null) {//使用内置模板
+ contentModel = setAssets(book, epubBook)
+ } else {//外部模板
+ customPath.listFiles().forEach { folder ->
+ if (folder.isDirectory && folder.name == "Text") {
+ folder.listFiles().sortedWith { o1, o2 ->
+ val name1 = o1.name ?: ""
+ val name2 = o2.name ?: ""
+ name1.cnCompare(name2)
+ }.forEach { file ->
+ if (file.isFile) {
+ when {
+ //正文模板
+ file.name.equals(
+ "chapter.html",
+ true
+ ) || file.name.equals("chapter.xhtml", true) -> {
+ contentModel = file.readText(context) ?: ""
+ }
+ //封面等其他模板
+ true == file.name?.endsWith("html", true) -> {
+ epubBook.addSection(
+ FileUtils.getNameExcludeExtension(
+ file.name ?: "Cover.html"
+ ),
+ ResourceUtil.createPublicResource(
+ book.name,
+ book.getRealAuthor(),
+ book.getDisplayIntro(),
+ book.kind,
+ book.wordCount,
+ file.readText(context) ?: "",
+ "${folder.name}/${file.name}"
+ )
+ )
+ }
+ else -> {
+ //其他格式文件当做资源文件
+ folder.listFiles().forEach {
+ if (it.isFile)
+ epubBook.resources.add(
+ Resource(
+ it.readBytes(context),
+ "${folder.name}/${it.name}"
+ )
+ )
+ }
+ }
+ }
+ }
+ }
+ } else if (folder.isDirectory) {
+ //资源文件
+ folder.listFiles().forEach {
+ if (it.isFile)
+ epubBook.resources.add(
+ Resource(
+ it.readBytes(context),
+ "${folder.name}/${it.name}"
+ )
+ )
+ }
+ } else {//Asset下面的资源文件
+ epubBook.resources.add(
+ Resource(
+ folder.readBytes(context),
+ "${folder.name}"
+ )
+ )
+ }
+ }
+ }
+ }
+
+ return contentModel
+ }
+
+ private fun setAssets(book: Book, epubBook: EpubBook): String {
+ epubBook.resources.add(
+ Resource(
+ appCtx.assets.open("epub/fonts.css").readBytes(),
+ "Styles/fonts.css"
+ )
+ )
+ epubBook.resources.add(
+ Resource(
+ appCtx.assets.open("epub/main.css").readBytes(),
+ "Styles/main.css"
+ )
+ )
epubBook.resources.add(
Resource(
- "body,div{background:white;outline:none;width:100%;}h2{color:#005a9c;text-align:left;}p{text-indent:2em;text-align:justify;}img{display:inline-block;width:100%;height:auto;max-width: 100%;max-height:100%;}".encodeToByteArray(),
- "css/style.css"
+ appCtx.assets.open("epub/logo.png").readBytes(),
+ "Images/logo.png"
+ )
+ )
+ epubBook.addSection(
+ context.getString(R.string.img_cover),
+ ResourceUtil.createPublicResource(
+ book.name,
+ book.getRealAuthor(),
+ book.getDisplayIntro(),
+ book.kind,
+ book.wordCount,
+ String(appCtx.assets.open("epub/cover.html").readBytes()),
+ "Text/cover.html"
+ )
+ )
+ epubBook.addSection(
+ context.getString(R.string.book_intro),
+ ResourceUtil.createPublicResource(
+ book.name,
+ book.getRealAuthor(),
+ book.getDisplayIntro(),
+ book.kind,
+ book.wordCount,
+ String(appCtx.assets.open("epub/intro.html").readBytes()),
+ "Text/intro.html"
)
)
+ return String(appCtx.assets.open("epub/chapter.html").readBytes())
}
private fun setCover(book: Book, epubBook: EpubBook) {
-
Glide.with(context)
.asBitmap()
.load(book.getDisplayCover())
@@ -237,21 +371,19 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
val byteArray: ByteArray = stream.toByteArray()
resource.recycle()
stream.close()
- epubBook.coverImage = Resource(byteArray, "cover.jpg")
+ epubBook.coverImage = Resource(byteArray, "Images/cover.jpg")
}
override fun onLoadCleared(placeholder: Drawable?) {
-
}
-
})
}
-
- private fun setEpubContent(book: Book, epubBook: EpubBook) {
+ private fun setEpubContent(contentModel: String, book: Book, epubBook: EpubBook) {
+ //正文
val useReplace = AppConfig.exportUseReplace
val contentProcessor = ContentProcessor(book.name, book.origin)
- appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter ->
+ appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter ->
BookHelp.getContent(book, chapter).let { content ->
var content1 = fixPic(epubBook, book, content ?: "null", chapter)
content1 = contentProcessor
@@ -259,23 +391,17 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
.joinToString("\n")
epubBook.addSection(
chapter.title,
- ResourceUtil.createHTMLResource(chapter.title, content1)
+ ResourceUtil.createChapterResource(
+ chapter.title.replace("\uD83D\uDD12", ""),
+ content1,
+ contentModel,
+ "Text/chapter_${index}.html"
+ )
)
}
}
}
- private fun setPic(src: String, book: Book, epubBook: EpubBook) {
-
- val href = "${MD5Utils.md5Encode16(src)}${BookHelp.getImageSuffix(src)}"
- val vFile = BookHelp.getImage(book, src)
- val fp = FileResourceProvider(vFile.parent)
- if (vFile.exists()) {
- val img = LazyResource(fp, href)
- epubBook.resources.add(img)
- }
- }
-
private fun fixPic(
epubBook: EpubBook,
book: Book,
@@ -285,19 +411,21 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
val data = StringBuilder("")
content.split("\n").forEach { text ->
var text1 = text
- val matches = AppPattern.imgPattern.toRegex().findAll(input = text)
- matches.forEach { matchResult ->
- matchResult.groupValues[1].let {
+ val matcher = AppPattern.imgPattern.matcher(text)
+ while (matcher.find()) {
+ matcher.group(1)?.let {
val src = NetworkUtils.getAbsoluteURL(chapter.url, it)
- setPic(src, book, epubBook)
- text1 = text1.replace(
- src,
- "${MD5Utils.md5Encode16(src)}${BookHelp.getImageSuffix(src)}"
- )
-
+ val originalHref = "${MD5Utils.md5Encode16(src)}${BookHelp.getImageSuffix(src)}"
+ val href = "Images/${MD5Utils.md5Encode16(src)}.${BookHelp.getImageSuffix(src)}"
+ val vFile = BookHelp.getImage(book, src)
+ val fp = FileResourceProvider(vFile.parent)
+ if (vFile.exists()) {
+ val img = LazyResource(fp, href, originalHref)
+ epubBook.resources.add(img)
+ }
+ text1 = text1.replace(src, "../${href}")
}
}
-
data.append(text1).append("\n")
}
return data.toString()
@@ -309,13 +437,11 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
metadata.authors.add(Author(book.getRealAuthor()))//书籍的作者
metadata.language = "zh"//数据的语言
metadata.dates.add(Date())//数据的创建日期
- metadata.publishers.add("Legado APP")//数据的创建者
+ metadata.publishers.add("Legado")//数据的创建者
metadata.descriptions.add(book.getDisplayIntro())//书籍的简介
//metadata.subjects.add("")//书籍的主题,在静读天下里面有使用这个分类书籍
epubBook.metadata = metadata
}
//////end of EPUB
-
-
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/utils/HtmlFormatter.kt b/app/src/main/java/io/legado/app/utils/HtmlFormatter.kt
index 21d45d62c..7d11df2b4 100644
--- a/app/src/main/java/io/legado/app/utils/HtmlFormatter.kt
+++ b/app/src/main/java/io/legado/app/utils/HtmlFormatter.kt
@@ -13,7 +13,7 @@ object HtmlFormatter {
html ?: return ""
return html.replace(wrapHtmlRegex, "\n")
.replace(otherRegex, "")
- .replace("^[\\n\\s]+".toRegex(), " ")
+ .replace("^[\\n\\s]*".toRegex(), " ")
.replace("[\\n\\s]+$".toRegex(), "")
.replace("\\s*\\n+\\s*".toRegex(), "\n ")
}
diff --git a/build.gradle b/build.gradle
index 894cbf12f..ae689e1a9 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,24 +4,22 @@ buildscript {
ext.kotlin_version = '1.5.10'
repositories {
google()
- maven { url 'https://maven.aliyun.com/repository/public/'}
- maven { url "https://s3.amazonaws.com/fabric-artifacts/public" }
- maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
- maven { url "https://plugins.gradle.org/m2/" }
+ maven { url 'https://maven.aliyun.com/repository/public' }
+ maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
+ maven { url 'https://plugins.gradle.org/m2/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath "de.timfreiheit.resourceplaceholders:placeholders:0.3"
+ classpath 'de.timfreiheit.resourceplaceholders:placeholders:0.3'
}
}
allprojects {
repositories {
google()
- maven { url 'https://maven.aliyun.com/repository/public/' }
- maven { url "https://jitpack.io" }
- maven { url "https://maven.google.com/" }
+ maven { url 'https://maven.aliyun.com/repository/public' }
+ maven { url 'https://jitpack.io' }
}
}
diff --git a/epublib/src/main/java/me/ag2s/epublib/Constants.java b/epublib/src/main/java/me/ag2s/epublib/Constants.java
index e26c56815..d9f873e41 100644
--- a/epublib/src/main/java/me/ag2s/epublib/Constants.java
+++ b/epublib/src/main/java/me/ag2s/epublib/Constants.java
@@ -7,6 +7,7 @@ public interface Constants {
String DOCTYPE_XHTML = "";
String NAMESPACE_XHTML = "http://www.w3.org/1999/xhtml";
String EPUB_GENERATOR_NAME = "Ag2S EpubLib";
+ String EPUB_DUOKAN_NAME = "DK-SONGTI";
char FRAGMENT_SEPARATOR_CHAR = '#';
String DEFAULT_TOC_ID = "toc";
}
diff --git a/epublib/src/main/java/me/ag2s/epublib/domain/LazyResource.java b/epublib/src/main/java/me/ag2s/epublib/domain/LazyResource.java
index 1c833401c..a0faf070e 100644
--- a/epublib/src/main/java/me/ag2s/epublib/domain/LazyResource.java
+++ b/epublib/src/main/java/me/ag2s/epublib/domain/LazyResource.java
@@ -28,6 +28,9 @@ public class LazyResource extends Resource {
public LazyResource(LazyResourceProvider resourceProvider, String href) {
this(resourceProvider, -1, href);
}
+ public LazyResource(LazyResourceProvider resourceProvider, String href, String originalHref) {
+ this(resourceProvider, -1, href, originalHref);
+ }
/**
* Creates a Lazy resource, by not actually loading the data for this entry.
@@ -39,11 +42,17 @@ public class LazyResource extends Resource {
* @param href The resource's href within the epub.
*/
public LazyResource(
- LazyResourceProvider resourceProvider, long size, String href) {
+ LazyResourceProvider resourceProvider, long size, String href) {
super(null, null, href, MediaTypes.determineMediaType(href));
this.resourceProvider = resourceProvider;
this.cachedSize = size;
}
+ public LazyResource(
+ LazyResourceProvider resourceProvider, long size, String href, String originalHref) {
+ super(null, null, href, originalHref, MediaTypes.determineMediaType(href));
+ this.resourceProvider = resourceProvider;
+ this.cachedSize = size;
+ }
/**
* Gets the contents of the Resource as an InputStream.
diff --git a/epublib/src/main/java/me/ag2s/epublib/domain/Resource.java b/epublib/src/main/java/me/ag2s/epublib/domain/Resource.java
index 4820a7aff..2349c9e91 100644
--- a/epublib/src/main/java/me/ag2s/epublib/domain/Resource.java
+++ b/epublib/src/main/java/me/ag2s/epublib/domain/Resource.java
@@ -120,6 +120,9 @@ public class Resource implements Serializable {
public Resource(String id, byte[] data, String href, MediaType mediaType) {
this(id, data, href, mediaType, Constants.CHARACTER_ENCODING);
}
+ public Resource(String id, byte[] data, String href, String originalHref, MediaType mediaType) {
+ this(id, data, href, originalHref, mediaType, Constants.CHARACTER_ENCODING);
+ }
/**
@@ -141,6 +144,15 @@ public class Resource implements Serializable {
this.inputEncoding = inputEncoding;
this.data = data;
}
+ public Resource(String id, byte[] data, String href, String originalHref, MediaType mediaType,
+ String inputEncoding) {
+ this.id = id;
+ this.href = href;
+ this.originalHref = originalHref;
+ this.mediaType = mediaType;
+ this.inputEncoding = inputEncoding;
+ this.data = data;
+ }
/**
* Gets the contents of the Resource as an InputStream.
diff --git a/epublib/src/main/java/me/ag2s/epublib/domain/Resources.java b/epublib/src/main/java/me/ag2s/epublib/domain/Resources.java
index 7566f4f3a..27d512700 100644
--- a/epublib/src/main/java/me/ag2s/epublib/domain/Resources.java
+++ b/epublib/src/main/java/me/ag2s/epublib/domain/Resources.java
@@ -193,9 +193,9 @@ public class Resources implements Serializable {
private String createHref(MediaType mediaType, int counter) {
if (MediaTypes.isBitmapImage(mediaType)) {
- return "image_" + counter + mediaType.getDefaultExtension();
+ return IMAGE_PREFIX + counter + mediaType.getDefaultExtension();
} else {
- return "item_" + counter + mediaType.getDefaultExtension();
+ return ITEM_PREFIX + counter + mediaType.getDefaultExtension();
}
}
diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentBase.java b/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentBase.java
index c7ce55b78..a172ce32d 100644
--- a/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentBase.java
+++ b/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentBase.java
@@ -9,7 +9,7 @@ package me.ag2s.epublib.epub;
*/
public class PackageDocumentBase {
- public static final String BOOK_ID_ID = "BookId";
+ public static final String BOOK_ID_ID = "duokan-book-id";
public static final String NAMESPACE_OPF = "http://www.idpf.org/2007/opf";
public static final String NAMESPACE_DUBLIN_CORE = "http://purl.org/dc/elements/1.1/";
public static final String PREFIX_DUBLIN_CORE = "dc";
@@ -92,5 +92,6 @@ public class PackageDocumentBase {
String reference_cover = "cover";
String no = "no";
String generator = "generator";
+ String duokan = "duokan-body-font";
}
}
\ No newline at end of file
diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataWriter.java b/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataWriter.java
index f4811a6c7..fc758bc03 100644
--- a/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataWriter.java
+++ b/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataWriter.java
@@ -120,6 +120,15 @@ public class PackageDocumentMetadataWriter extends PackageDocumentBase {
Constants.EPUB_GENERATOR_NAME);
serializer.endTag(NAMESPACE_OPF, OPFTags.meta);
+ // write duokan
+ serializer.startTag(NAMESPACE_OPF, OPFTags.meta);
+ serializer.attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.name,
+ OPFValues.duokan);
+ serializer
+ .attribute(EpubWriter.EMPTY_NAMESPACE_PREFIX, OPFAttributes.content,
+ Constants.EPUB_DUOKAN_NAME);
+ serializer.endTag(NAMESPACE_OPF, OPFTags.meta);
+
serializer.endTag(NAMESPACE_OPF, OPFTags.metadata);
}
diff --git a/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java b/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java
index 9b8f7896e..f270bdbb3 100644
--- a/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java
+++ b/epublib/src/main/java/me/ag2s/epublib/util/ResourceUtil.java
@@ -30,60 +30,31 @@ public class ResourceUtil {
/**
* 快速创建HTML类型的Resource
*
- * @param title 章节的标题
- * @param string 章节的正文
+ * @param title 章节的标题
+ * @param txt 章节的正文
+ * @param model html模板
* @return 返回Resource
*/
- public static Resource createHTMLResource(String title, String string) {
- String html = createHtml(title, string);
- MediaType mediaTypeProperty = MediaTypes.XHTML;
- byte[] data = html.getBytes();
- return new Resource(data, mediaTypeProperty);
- }
-
- /**
- * 快速创建HTML类型的Resource
- *
- * @param title 章节的标题
- * @param string 章节的正文
- * @param href Resource的href
- * @return 返回Resource
- */
-
- @SuppressWarnings("unused")
- public static Resource createHTMLResource(String title, String string, String href) {
- String html = createHtml(title, string);
- MediaType mediaTypeProperty = MediaTypes.XHTML;
- byte[] data = html.getBytes();
- return new Resource(null, data, href, mediaTypeProperty);
- }
-
- @SuppressWarnings("unused")
- private static String createHtml(String title, String txt) {
- StringBuilder body = new StringBuilder();
- for (String s : txt.split("\\r?\\n")) {
- //移除多余的开头结尾的空白字符,节省epub的体积
- s = StringUtil.FixTrim(s);
- if (s.length() != 0) {
- if (s.contains("").append(s).append("");
- } else {
- body.append("").append(s).append("
");
- }
-
- }
-
+ public static Resource createChapterResource(String title, String txt, String model, String href) {
+ if (title.contains("\n")) {
+ title = "" + title.replaceFirst("\\s*\\n\\s*", "
");
+ } else {
+ title = title.replaceFirst("\\s+", "
");
+ if (title.contains(""))
+ title = "" + title;
}
+ String html = model.replaceAll("\\{title\\}", title)
+ .replaceAll("\\{content\\}", StringUtil.formatHtml(txt));
+ return new Resource(html.getBytes(), href);
+ }
- return "" +
- "" +
- "" + title + "" +
- "" +
- "" +
- "" + title + "
" +
- body +
- "";
+ public static Resource createPublicResource(String name, String author, String intro, String kind, String wordCount, String model, String href) {
+ String html = model.replaceAll("\\{name\\}", name)
+ .replaceAll("\\{author\\}", author)
+ .replaceAll("\\{kind\\}", kind)
+ .replaceAll("\\{wordCount\\}", wordCount)
+ .replaceAll("\\{intro\\}", StringUtil.formatHtml(intro));
+ return new Resource(html.getBytes(), href);
}
/**
diff --git a/epublib/src/main/java/me/ag2s/epublib/util/StringUtil.java b/epublib/src/main/java/me/ag2s/epublib/util/StringUtil.java
index 929278b98..f3c0a6058 100644
--- a/epublib/src/main/java/me/ag2s/epublib/util/StringUtil.java
+++ b/epublib/src/main/java/me/ag2s/epublib/util/StringUtil.java
@@ -273,25 +273,19 @@ public class StringUtil {
}
return text.substring(cPos + 1);
}
- // 移除字符串首尾空字符的高效方法(利用ASCII值判断,包括全角空格)
- public static String FixTrim(String s) {
- if (s == null || s.isEmpty()) {
- return "";
- }
- int start = 0;
- int len = s.length();
- int end = len - 1;
- while (start < end && (s.charAt(start) <= 0x20 || s.charAt(start) == ' ')) {
- ++start;
- }
- while (start < end && (s.charAt(end) <= 0x20 || s.charAt(end) == ' ')) {
- --end;
- }
- if (end < len) {
- ++end;
- }
- return (start > 0 || end < len) ? s.substring(start, end) : s;
+ public static String formatHtml(String text) {
+ StringBuilder body = new StringBuilder();
+ for (String s : text.split("\\r?\\n")) {
+ s = s.replaceAll("^\\s+|\\s+$", "");
+ if (s.length() > 0) {
+ if (s.toLowerCase().contains("]+)/?>", ""));
+ } else {
+ body.append("").append(s).append("
");
+ }
+ }
+ }
+ return body.toString();
}
-
}