fetch太慢去除历史提交记录

This commit is contained in:
gedoor
2022-01-03 23:59:44 +08:00
commit 51c16a1efc
1294 changed files with 194322 additions and 0 deletions
@@ -0,0 +1,26 @@
package io.legado.app
import android.net.Uri
import android.util.Log
import androidx.test.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun testContentProvider() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getTargetContext()
Log.d("test",
appContext.contentResolver.query(Uri.parse("content://io.legado.app.api.ReaderProvider/sources/query"),null,null,null,null)
!!.getString(0)
)
}
}
@@ -0,0 +1,50 @@
package io.legado.app
import androidx.room.Room
import androidx.room.migration.Migration
import androidx.room.testing.MigrationTestHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import io.legado.app.data.AppDatabase
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import java.io.IOException
@RunWith(AndroidJUnit4::class)
class MigrationTest {
private val TEST_DB = "migration-test"
private val ALL_MIGRATIONS = arrayOf<Migration>(
)
@Rule
val helper: MigrationTestHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
AppDatabase::class.java.canonicalName,
FrameworkSQLiteOpenHelperFactory()
)
@Test
@Throws(IOException::class)
fun migrateAll() {
// Create earliest version of the database.
helper.createDatabase(TEST_DB, 30).apply {
close()
}
// Open latest version of the database. Room will validate the schema
// once all migrations execute.
Room.databaseBuilder(
InstrumentationRegistry.getInstrumentation().targetContext,
AppDatabase::class.java,
TEST_DB
).addMigrations(*ALL_MIGRATIONS)
.build().apply {
openHelper.writableDatabase
close()
}
}
}
+4
View File
@@ -0,0 +1,4 @@
<resources>
<string name="app_name">阅读·D</string>
<string name="receiving_shared_label">阅读·D·搜索</string>
</resources>
+4
View File
@@ -0,0 +1,4 @@
<resources>
<string name="app_name">legado·D</string>
<string name="receiving_shared_label">legado·D·search</string>
</resources>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">阅读Pro</string>
</resources>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">閱讀Pro</string>
</resources>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">閱讀Pro</string>
</resources>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">legadoPro</string>
</resources>
+465
View File
@@ -0,0 +1,465 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="io.legado.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:theme="@style/AppTheme.Light"
tools:ignore="AllowBackup,GoogleAppIndexingWarning,UnusedAttribute">
<!-- 主入口 -->
<activity
android:name=".ui.welcome.WelcomeActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:launchMode="singleTask"
android:resource="@xml/shortcuts" />
</activity>
<!-- 图标1 -->
<activity
android:name=".ui.welcome.Launcher1"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/launcher1">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:launchMode="singleTask"
android:resource="@xml/shortcuts" />
</activity>
<!-- 图标2 -->
<activity
android:name=".ui.welcome.Launcher2"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/launcher2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:launchMode="singleTask"
android:resource="@xml/shortcuts" />
</activity>
<!-- 图标3 -->
<activity
android:name=".ui.welcome.Launcher3"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/launcher3">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:launchMode="singleTask"
android:resource="@xml/shortcuts" />
</activity>
<!-- 图标4 -->
<activity
android:name=".ui.welcome.Launcher4"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/launcher4">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:launchMode="singleTask"
android:resource="@xml/shortcuts" />
</activity>
<!-- 图标5 -->
<activity
android:name=".ui.welcome.Launcher5"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/launcher5">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:launchMode="singleTask"
android:resource="@xml/shortcuts" />
</activity>
<!-- 图标6 -->
<activity
android:name=".ui.welcome.Launcher6"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/launcher6">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:launchMode="singleTask"
android:resource="@xml/shortcuts" />
</activity>
<!-- 主界面 -->
<activity
android:name=".ui.main.MainActivity"
android:alwaysRetainTaskState="true"
android:launchMode="singleTask" />
<!-- 阅读界面 -->
<activity
android:name=".ui.book.read.ReadBookActivity"
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="true"
android:launchMode="singleTask">
<intent-filter>
<action android:name="com.samsung.android.support.REMOTE_ACTION" />
</intent-filter>
<meta-data
android:name="com.samsung.android.support.REMOTE_ACTION"
android:resource="@xml/spen_remote_actions" />
</activity>
<!-- 书籍详情页 -->
<activity
android:name=".ui.book.info.BookInfoActivity"
android:launchMode="singleTop" />
<!-- 书籍信息编辑 -->
<activity
android:name=".ui.book.info.edit.BookInfoEditActivity"
android:launchMode="singleTask" />
<!-- 音频播放界面 -->
<activity
android:name="io.legado.app.ui.book.audio.AudioPlayActivity"
android:launchMode="singleTask" />
<!-- 授权界面 -->
<activity
android:name="io.legado.app.lib.permission.PermissionActivity"
android:theme="@style/Activity.Permission" />
<!-- 二维码扫描 -->
<activity
android:name=".ui.qrcode.QrCodeActivity"
android:launchMode="singleTask" />
<!-- 规则订阅 -->
<activity
android:name=".ui.rss.subscription.RuleSubActivity"
android:launchMode="singleTask" />
<!-- 书源编辑 -->
<activity
android:name=".ui.book.source.edit.BookSourceEditActivity"
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize|stateHidden" />
<!-- 订阅源编辑 -->
<activity
android:name=".ui.rss.source.edit.RssSourceEditActivity"
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize|stateHidden" />
<!-- 书源编辑 -->
<activity
android:name=".ui.replace.edit.ReplaceEditActivity"
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize|stateHidden" />
<!-- 配置界面 -->
<activity
android:name=".ui.config.ConfigActivity"
android:launchMode="singleTask" />
<!-- 搜索界面 -->
<activity
android:name=".ui.book.search.SearchActivity"
android:launchMode="standard" />
<!-- 关于界面 -->
<activity
android:name=".ui.about.AboutActivity"
android:launchMode="singleTask"
android:screenOrientation="behind" />
<!-- 捐赠界面 -->
<activity
android:name=".ui.about.DonateActivity"
android:launchMode="singleTask"
android:screenOrientation="behind" />
<!-- 书源管理 -->
<activity
android:name=".ui.book.source.manage.BookSourceActivity"
android:launchMode="singleTop"
android:screenOrientation="behind" />
<!-- 订阅源管理 -->
<activity
android:name=".ui.rss.source.manage.RssSourceActivity"
android:launchMode="singleTop"
android:screenOrientation="behind" />
<!-- txt目录规则管理 -->
<activity
android:name=".ui.book.local.rule.TxtTocRuleActivity"
android:launchMode="singleTop"
android:screenOrientation="behind" />
<!-- 替换规则界面 -->
<activity
android:name=".ui.replace.ReplaceRuleActivity"
android:launchMode="singleTop"
android:screenOrientation="behind" />
<!-- 书籍管理 -->
<activity
android:name=".ui.book.arrange.ArrangeBookActivity"
android:launchMode="singleTop"
android:screenOrientation="behind" />
<!-- 书源调试 -->
<activity
android:name=".ui.book.source.debug.BookSourceDebugActivity"
android:launchMode="singleTop"
android:screenOrientation="behind" />
<!-- 目录 -->
<activity
android:name=".ui.book.toc.TocActivity"
android:launchMode="singleTop"
android:screenOrientation="behind" />
<!-- 正文搜索 -->
<activity
android:name=".ui.book.searchContent.SearchContentActivity"
android:launchMode="singleTop"
android:screenOrientation="behind" />
<!-- RSS条目 -->
<activity
android:name=".ui.rss.article.RssSortActivity"
android:launchMode="singleTop" />
<!-- RSS阅读 -->
<activity
android:name=".ui.rss.read.ReadRssActivity"
android:configChanges="orientation|screenSize"
android:hardwareAccelerated="true"
android:launchMode="singleTop" />
<!-- 导入书籍 -->
<activity
android:name=".ui.book.local.ImportBookActivity"
android:launchMode="singleTop" />
<!-- 发现界面 -->
<activity
android:name=".ui.book.explore.ExploreShowActivity"
android:launchMode="singleTop" />
<!-- 订阅源调试 -->
<activity
android:name=".ui.rss.source.debug.RssSourceDebugActivity"
android:launchMode="singleTop" />
<!-- Rss收藏 -->
<activity
android:name=".ui.rss.favorites.RssFavoritesActivity"
android:launchMode="singleTop" />
<!-- 缓存界面 -->
<activity
android:name=".ui.book.cache.CacheActivity"
android:launchMode="singleTop" />
<!-- WebView界面 -->
<activity
android:name=".ui.browser.WebViewActivity"
android:launchMode="standard" />
<!-- 书源登录 -->
<activity
android:name="io.legado.app.ui.login.SourceLoginActivity"
android:configChanges="orientation|screenSize"
android:hardwareAccelerated="true"
android:theme="@style/AppTheme.Transparent" />
<!-- 阅读记录 -->
<activity
android:name=".ui.about.ReadRecordActivity"
android:configChanges="orientation|screenSize"
android:hardwareAccelerated="true" />
<!-- 选择文件 -->
<activity
android:name=".ui.document.HandleFileActivity"
android:configChanges="orientation|screenSize"
android:hardwareAccelerated="true"
android:theme="@style/AppTheme.Transparent" />
<!-- 文字处理 -->
<activity
android:name=".receiver.SharedReceiverActivity"
android:exported="true"
android:label="@string/receiving_shared_label"
android:theme="@style/AppTheme.Transparent">
<intent-filter>
<action android:name="android.intent.action.PROCESS_TEXT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<!-- 一键导入 -->
<activity
android:name=".ui.association.OnLineImportActivity"
android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="true"
android:theme="@style/AppTheme.Transparent">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="legado" />
<data android:scheme="yuedu" />
</intent-filter>
</activity>
<!-- 打开文件 -->
<activity
android:name=".ui.association.FileAssociationActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/AppTheme.Transparent">
<!-- VIEW (Open with) action -->
<!-- Works when an app knows the media type of a file, e.g. Gmail or Chrome. -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="app" />
<data android:scheme="content" />
<data android:scheme="file" />
<!-- text -->
<data android:mimeType="text/plain" />
<!-- json -->
<data android:mimeType="application/json" />
<!-- EPUB -->
<data android:mimeType="application/epub+zip" />
</intent-filter>
<!-- Works when an app doesn't know the media type, e.g. Dropbox -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="*" />
<data android:scheme="app" />
<data android:scheme="content" />
<data android:scheme="file" />
<!-- This media type is necessary, otherwise it won't match on the file extension -->
<data android:mimeType="*/*" />
<!--TXT-->
<data android:pathPattern=".*\\.txt" />
<data android:pathPattern=".*\\.TXT" />
<!--JSON-->
<data android:pathPattern=".*\\.json" />
<data android:pathPattern=".*\\.JSON" />
<!-- EPUB -->
<data android:pathPattern=".*\\.epub" />
<data android:pathPattern=".*\\.EPUB" />
</intent-filter>
</activity>
<service android:name=".service.CheckSourceService" />
<service android:name=".service.CacheBookService" />
<service android:name=".service.WebService" />
<service
android:name=".service.WebTileService"
android:exported="true"
android:icon="@drawable/ic_web_service_noti"
android:label="legado Web Service"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
<service android:name=".service.TTSReadAloudService" />
<service android:name=".service.HttpReadAloudService" />
<service android:name=".service.AudioPlayService" />
<service android:name=".service.DownloadService" />
<receiver
android:name=".receiver.MediaButtonReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<provider
android:name=".api.ReaderProvider"
android:authorities="${applicationId}.readerProvider"
android:enabled="true"
android:exported="true"
tools:ignore="ExportedContentProvider" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<meta-data
android:name="channel"
android:value="${APP_CHANNEL_VALUE}" />
</application>
<queries>
<intent>
<action android:name="android.intent.action.TTS_SERVICE" />
</intent>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain" />
</intent>
</queries>
</manifest>
+284
View File
@@ -0,0 +1,284 @@
OGN5dS5jb20=
c2cwMC54eXo=
aXRyYWZmaWNuZXQuY29t
eGlhb3FpYW5nNTIw
MTIzeGlhb3FpYW5n
eGlhb3FpYW5neHM=
eGlhb3FpYW5nNTIw
MzM1eHM=
eGN4czk=
eGN4czUyMA==
c2h1YmFvYW4=
c2h1YmFvd2FuZzEyMw==
c2h1YmFvYW4=
aGFpdGFuZzEyMw==
eXV6aGFpd3VsYQ==
cG8xOA==
Ymwtbm92ZWw=
NXRucw==
c2hhb3NodWdl
amluamlzaHV3dQ==
NDJ3Zw==
eWlxdXNodQ==
c2h1YmFvd2FuZzEyMw==
M2hlYmFv
MzNoZWJhbw==
bHVvcWl1enc=
bXlzaHVnZQ==
c3NzeHN3
eWl0ZQ==
Y3Vpd2VpanV1
Y3Vpd2VpanV4cw==
Y3Vpd2VpanV4
eGlhb3FpYW5nd3g=
YXN6dw==
YXN6dzY=
c2FuaGFveHM=
ODdzaHV3dQ==
NDh3eA==
bG9uZ3Rlbmcy
NnF3eA==
bG9uZ3Rlbmd4cw==
aGF4ZHU=
M3R3eA==
aGF4d3g1
NjZsZXdlbg==
eGJhbnpodQ==
aGR5cA==
ZHliejk=
ZGl5aWJhbnpodTk=
ZGl5aWJhbnpodQ==
ZGl5aWJhbnpodTc=
YnoyMjI=
d29kZWFwaTAwMQ==
dGFuZ3poZWthbg==
YmF4aWFueHM=
eGlhb3NodW9zaGVuemhhbg==
ZGFtb2tl
emh3ZW5wZw==
eXV6aGFpZ2U=
d21wOA==
OXhpYW53ZW4=
bmFucmVudmlw
cmV5b28=
eWZ4aWFvc2h1b2U=
c2Fuaml1enc=
N3Fpbmc3
cWR4aWFvc2h1bw==
Y2hpbmVzZXpq
MzlzaHViYW8=
a3l4czU=
NTZtcw==
bml1c2hh
bWt4czY=
MjIyMjJ4cw==
OTVkdXNodQ==
YmFuemh1MjI=
d3JsdHh0
dHVkb3V0eHQ=
cm5neHM=
OTl3ZW5rdQ==
bGFvc2lqaXhz
ZnVzaHV6aGFpMQ==
cG8xOA==
czUyMTc=
c2FuaGFveHM=
NTJrc2h1
NDhyeA==
ZWNub3ZlbA==
bGllaHVvenc=
eGlhb3FpYW5nd3g=
NTJrc2h1
NDh3eA==
NTJrc2h1
MDB1aQ==
MDFieg==
c2h1YmFvMQ==
ZG54aWFvc2h1b2E=
am5zaHViYQ==
MThzaHV3dQ==
bGV4cw==
MzM1eHM=
dXB1
ZnVndW9kdQ==
ODB0eHQ=
YWFyZWFk
eWlkdWR1MQ==
YmFuemh1d2FuZw==
cWloYW9xaWhhbw==
OHhpYW54cw==
amluamlzaHV3dQ==
d21wOA==
ZXl1c2h1d3U=
NTB4c2Y=
aGF4d3g1
cG93YW5qdWFu
d2luMTBjaXR5
eWV5ZXhzdw==
bXlzaHVnZQ==
eGlhbmd0eHN3
Y3Vpd2VpanV4
MzY2eHN3
aHVheXVld2Vua3U=
eW91ZGlhbmxlbg==
c291Nzg=
bGFucm91Mg==
cXFib29r
eW91d3V4cw==
cnVpbGlzYWxl
MzY1bXd3
ZnV3ZW5o
bGVzYmw=
YXd1Ym9vaw==
bGl5dXhpYW5nMjAyMA==
OTJwb3Bv
ZnVzaHV0dWFu
ODhkYW5tZWk=
ZG14cw==
eXVsaW56aGFueWU=
M2hlYmFv
eGd1YWd1YXhz
ZGl5aWJhbnpodTY=
aXJlYWR4cw==
c2h1YmFvOTY=
ZGl5aWJhbnpodTU1NQ==
c2Fuaml1enc=
N3Fpbmc3
NjZsZXdlbg==
a3l4czU=
MjIyMjJ4cw==
c2hhb3NodWdl
amlsaW41NQ==
bWt4czY=
amluc2h1bG91
eGlhbndhbmdz
eWlkdWR1
cWR0eHQ=
MTZib29rMQ==
am1zaHV3dQ==
MzY2eHN3
ZHliejk=
c2hvdWRhOA==
ZnlxMTg=
eWlzaHVn
eXV6aGFpd3VsYQ==
MTFiYW56aHU=
MTIzeGlhb3FpYW5n
ZGl5aWJhbnpodTk=
ZGl5aWJhbnpodQ==
MzY2eHN3
ODdzaHV3dQ==
NnF3eA==
emhlbmh1bnhpYW9zaHVv
bG9uZ3Rlbmc1Mg==
eGlueGluZ3hpYW5nemhpZmE=
ZHliejk=
ZHVvemhla2Fu
MTIzeGlhb3FpYW5n
MzM1eHM=
am1zaHV3dQ==
c2hhb3NodWdl
bGF3ZW54cw==
cnVzaHV3dQ==
MzY2eHN3
NTB4c2Y=
bGV3ZW41NQ==
aGFpdGFuZzEyMw==
aGViYW81MjA=
bHVvcWl1enc=
c3NzeHN3
c2h1c2h1d3V4cw==
cm5neHM=
cWR4aWFvc2h1bw==
dHl1ZQ==
Y2hlNDM=
bG9uZ3Rlbmcy
amZ5eHNo
aGV0dTI=
bGFvc2lqaXhz
bG9uZ3Rlbmd4cw==
bGllaHVvenc=
c2h1YmFvYW4=
eHNodW9zaHVv
NTIxZGFubWVp
YmFuemh1MjI=
cWtzaHU=
eWZ4aWFvc2h1b2U=
a3lnc28=
c2h1bG91YmE=
NXRucw==
N3Fpbmc3
bWlhb2R1NQ==
eXVzaHV3ZW4=
YWFyZWFk
cXRzaHU=
MTdzaHV3dQ==
c2h1YmFvMnM=
YnowMDE=
ZGFtb2dl
MTMxdGI=
aXhpYW9z
bXlzaHVnZQ==
OXhpYW53ZW4=
ZHVvemhla2Fu
MTIwdw==
c2h1c2h1d3U1MjA=
c2h1YmFvMnM=
YWd4c3c=
OTR4c3c=
cG8xOA==
eWFvY2hpeHM=
eGlhb3FpYW5neHM=
Ym9va2Js
c2Fuaml1eHM=
d29kZXNodWJhbw==
em9uZ2NhaXhpYW9zaHVvMg==
OWI4OTEzOTRkZjVi
MThub3ZlbA==
YWFib29r
YjF0eHQ=
eXVjYWl6dw==
Yzl0eHQ=
ZGl5aWJhbnpodTU1NQ==
MzBtYw==
eGlueXVzaHV3dQ==
c2h1YmFvd2FuZzEyMw==
YWd4cw==
YmlxdWdlbmw=
c2hpcWlzaHV3dQ==
c2lsdWtl
ZGl5aWJhbnpodTg=
ZGl5aWJhbnpodTk=
aGV0dW54cw==
OTl3ZW5rdQ==
aGFpdGFuZ3NodXd1
OTd5ZA==
eXV6aGFpd3UxMQ==
Y3Vpd2VpanV4cw==
Y2JpcXU=
NTIxZGFubWVp
c2h1YmFvMzM=
c2FuaGFvMQ==
dGlhbm1lbmd3ZW5rdQ==
eXVzaHV3dTUyMA==
c2h1YmFvMjIy
c2h1YmFvd2FuZzEyMw==
eXVib29r
Y2JpcXU=
MWxld2Vu
MTV4c3c=
eG5jd3h3
c2h1YmFvd2FuZzEyMw==
c2FuaGFveHM=
eXV3YW5nc2hl
YmlxdXRz
bGFtZWl4cw==
eGJhbnpodQ==
cWR4aWFvc2h1bw==
bWh0bGE=
OTl3ZW5rdQ==
eGlhb3FpYW5nNTIw
dGlhbm1lbmd3ZW5rdQ==
YWlmdXNodQ==
bWlhb2R1NQ==
bWlmZW5neHM=
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

+1
View File
@@ -0,0 +1 @@
{"arm64-v8a":"690c212d9bbad4b09b9e1ba450b273bb","armeabi-v7a":"4dbb88e5229abef7d84138218772f872","x86":"3f2421e040147da48abb07cfc6c7c87e","x86_64":"730a71ef4f03a27d1c8c8a77e7d09ff5","version":"96.0.4664.104"}
@@ -0,0 +1,48 @@
[
{
"bookSourceComment": "",
"bookSourceGroup": "听书",
"bookSourceName": "消消乐听书",
"bookSourceType": 1,
"bookSourceUrl": "https://www.kaixin7days.com",
"customOrder": 0,
"enabled": true,
"enabledExplore": true,
"exploreUrl": "@js:var header = JSON.parsesource.getLoginHeader()\nvar json = ''\nvar j = null\nif (header != null) {\n json = java.connect('https://www.kaixin7days.com/book-service/bookMgt/getBookCategroy,{\"method\":\"POST\",\"body\":{}}', header).body()\n j = JSON.parse(json)\n}\nif (j == null || j.statusCode != 200) {\n json = java.connect('https://www.kaixin7days.com/visitorLogin,{\"method\":\"POST\", \"body\":{} }').body()\n j = JSON.parse(json)\n var accessToken = {\n Authorization: 'Bearer ' + j.content.accessToken\n }\n header = JSON.stringify(accessToken)\n source.putLoginHeader(header)\n json = java.connect('https://www.kaixin7days.com/book-service/bookMgt/getBookCategroy,{\"method\":\"POST\",\"body\":{} }', header).body()\n j = JSON.parse(json)\n}\nvar fls = j.content\nvar fx = []\nfor (var i = 0; i < fls.length; i++) {\n fx.push({\n title: fls[i].categoryName,\n url: '/book-service/bookMgt/getAllBookByCategroyId,{\"method\":\"POST\",\"body\":{\"categoryIds\": \"' + fls[i].associationCategoryIDs + '\",\"pageNum\": {{page}},\"pageSize\": 100}}'\n })\n}\nJSON.stringify(fx)",
"searchUrl": "https://www.kaixin7days.com/book-service/bookMgt/findBookName,{\"method\":\"POST\",\"body\":{\"title\": \"searchKey\",\"pageNum\": {{searchPage}},\"pageSize\": 100}}",
"lastUpdateTime": 1630656684531,
"loginCheckJs": "var strRes = result\nvar c = JSON.parse(result.body())\nif (c.statusCode == 301) {\n var loginInfo = source.getLoginInfo()\n var dl = null\n if (loginInfo) {\n dl = java.connect('https://www.kaixin7days.com/login,{\"method\":\"POST\",\"body\":' + loginInfo + '}').body()\n } else {\n dl = java.connect('https://www.kaixin7days.com/visitorLogin,{\"method\":\"POST\",\"body\":{}}').body()\n }\n c = JSON.parse(dl)\n var accessToken = {\n Authorization: \"Bearer \" + c.content.accessToken\n }\n var header = JSON.stringify(accessToken)\n source.putLoginHeader(header)\n strRes = java.connect(url, header)\n}\nstrRes",
"loginUi": "[{\"name\": \"telephone\",\"type\": \"text\"},{\"name\": \"password\",\"type\": \"password\"},{\"name\": \"注册\",\"type\": \"button\",\"action\": \"http://www.yooike.com/xiaoshuo/#/register?title=%E6%B3%A8%E5%86%8C\"}]",
"loginUrl": "var loginInfo = source.getLoginInfo()\nvar json = java.connect('https://www.kaixin7days.com/login,{\"method\":\"POST\",\"body\":' + loginInfo + '}').body()\nvar loginRes = JSON.parse(json)\nvar header = null\nif (loginRes.statusCode == 200) {\n var accessToken = {\n Authorization: \"Bearer \" + loginRes.content.accessToken\n }\n header = JSON.stringify(accessToken)\n source.putLoginHeader(header)\n}\nheader",
"respondTime": 180000,
"ruleBookInfo": {},
"ruleContent": {
"content": "",
"payAction": "var header = JSON.parse(source.getLoginHeader()); var bookId = book.getVariableMap().get('bookId');var chapterId = java.get('chapterId');\n'http://www.shuidi.online/?name=' + book.getName() + '&type=2&cover=' + book.getCoverUrl() + '&chapterId=' + chapterId + '&chapter=203&allNumber=' + book.getTotalChapterNum() + '&bookId=' + bookId + '&chapterIds=' + chapterId + '&number=' + chapter.getIndex() + '&accessToken=' + header.Authorization.substring(7) + '#/pay'"
},
"ruleExplore": {
"author": "$.author",
"bookList": "$.content.content",
"bookUrl": "$.id@js:java.put('bookId', result);'https://www.kaixin7days.com/book-service/bookMgt/getAllChapterByBookId,{ \"method\": \"POST\",\"body\": {\"bookId\": \"'+result+'\",\"pageNum\": \"1\",\"pageSize\": \"10000\"} }'",
"coverUrl": "$.cover@js:var cover = JSON.parse(result);'https://www.shuidi.online/fileMgt/getPicture?filePath='+cover.storeFilePath",
"intro": "$.desc",
"lastChapter": "$.newestChapter",
"name": "$.title"
},
"ruleSearch": {
"author": "$.author",
"bookList": "$.content.content",
"bookUrl": "$.id@js:java.put('bookId', result);'https://www.kaixin7days.com/book-service/bookMgt/getAllChapterByBookId,{ \"method\": \"POST\",\"body\": {\"bookId\": \"'+result+'\",\"pageNum\": \"1\",\"pageSize\": \"10000\"} }'",
"coverUrl": "$.cover@js:var cover = JSON.parse(result);'https://www.shuidi.online/fileMgt/getPicture?filePath='+cover.storeFilePath",
"intro": "$.desc",
"lastChapter": "$.newestChapter",
"name": "$.title"
},
"ruleToc": {
"chapterList": "$.content.content",
"chapterName": "$.chapterTitle",
"chapterUrl": "$.id@js:java.put('chapterId', result);'https://www.shuidi.online/fileMgt/getAudioByChapterId?bookId=' + java.get('bookId') + '&chapterId=' + result + \"&pageNum=1&pageSize=50&keyId={{var header = JSON.parse(source.getLoginHeader());var keyId = '1632746188011002';var ks = java.md5Encode(keyId + java.get('chapterId') + header.Authorization);keyId + '&keySecret=' + ks}\" + '}'"
},
"weight": 0
}
]
@@ -0,0 +1,5 @@
{
"UploadUrl": "http://sy.miaogongzi.cc/shuyuan,{\"method\":\"POST\",\"body\": {\"file\": \"fileRequest\"},\"type\": \"multipart/form-data\"}",
"DownloadUrlRule": "$.data@js:if (result == '') \n '' \n else \n 'https://shuyuan.miaogongzi.cc/shuyuan/' + result",
"summary": "有效期2天"
}
@@ -0,0 +1,30 @@
[
{
"id": -100,
"name": "1.百度",
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{(speakSpeed + 5) / 10 + 4}}&per=4127&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=11&vol=5&aue=6&pit=3&_res_tag_=audio\"\n}",
"contentType": "audio/wav"
},
{
"id": -29,
"name": "2.阿里云语音",
"url": "https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/tts,{\"method\": \"POST\",\"body\": {\"appkey\":\"{{source.getLoginInfoMap().get('AppKey')}}\",\"text\":\"{{speakText}}\",\"format\":\"mp3\",\"volume\":100,\"speech_rate\":{{String((speakSpeed) * 20 - 400)}} }}",
"contentType": "audio/mpeg",
"loginUrl": "var loginInfo = source.getLoginInfoMap();\nvar accessKeyId = loginInfo.get('AccessKeyId');\nvar accessKeySecret = loginInfo.get('AccessKeySecret');\nvar timestamp = java.timeFormatUTC(new Date().getTime(), \"yyyy-MM-dd'T'HH:mm:ss'Z'\", 0);\nvar aly = new JavaImporter(Packages.javax.crypto.Mac, Packages.javax.crypto.spec.SecretKeySpec, Packages.javax.xml.bind.DatatypeConverter, Packages.java.net.URLEncoder, Packages.java.lang.String, Packages.android.util.Base64);\nwith (aly) {\n function percentEncode(value) {\n return URLEncoder.encode(value, \"UTF-8\").replace(\"+\", \"%20\")\n .replace(\"*\", \"%2A\").replace(\"%7E\", \"~\")\n }\n\n function sign(stringToSign, accessKeySecret) {\n var mac = Mac.getInstance('HmacSHA1');\n mac.init(new SecretKeySpec(String(accessKeySecret + '&').getBytes(\"UTF-8\"), \"HmacSHA1\"));\n var signData = mac.doFinal(String(stringToSign).getBytes(\"UTF-8\"));\n var signBase64 = Base64.encodeToString(signData, Base64.NO_WRAP);\n var signUrlEncode = percentEncode(signBase64);\n return signUrlEncode;\n }\n}\nvar query = 'AccessKeyId=' + accessKeyId + '&Action=CreateToken&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=' + java.randomUUID() + '&SignatureVersion=1.0&Timestamp=' + percentEncode(timestamp) + '&Version=2019-02-28';\nvar signStr = sign('GET&' + percentEncode('/') + '&' + percentEncode(query), accessKeySecret);\nvar queryStringWithSign = \"Signature=\" + signStr + \"&\" + query;\nvar body = java.ajax('http://nls-meta.cn-shanghai.aliyuncs.com/?' + queryStringWithSign)\nvar res = JSON.parse(body)\nif (res.Message) {\n throw new Error(res.Message)\n}\nvar header = { \"X-NLS-Token\": res.Token.Id };\nsource.putLoginHeader(JSON.stringify(header))",
"loginUi": [
{
"name": "AppKey",
"type": "text"
},
{
"name": "AccessKeyId",
"type": "text"
},
{
"name": "AccessKeySecret",
"type": "text"
}
],
"loginCheckJs": "var response = result;\nif (response.headers().get(\"Content-Type\") != \"audio/mpeg\") {\n var body = JSON.parse(response.body().string())\n if (body.status == 40000001) {\n source.login()\n java.getHeaderMap().putAll(source.getHeaderMap(true))\n response = java.getResponse()\n } else {\n throw body.message\n }\n}\nresponse"
}
]
@@ -0,0 +1,107 @@
[
{
"bgStr": "#ffc0edc6",
"bgStrEInk": "#FFFFFF",
"bgStrNight": "#000000",
"bgType": 0,
"bgTypeEInk": 0,
"bgTypeNight": 0,
"darkStatusIcon": true,
"darkStatusIconEInk": true,
"darkStatusIconNight": false,
"footerMode": 0,
"footerPaddingBottom": 10,
"footerPaddingLeft": 13,
"footerPaddingRight": 17,
"footerPaddingTop": 0,
"headerMode": 0,
"headerPaddingBottom": 0,
"headerPaddingLeft": 19,
"headerPaddingRight": 16,
"headerPaddingTop": 10,
"letterSpacing": 0,
"lineSpacingExtra": 10,
"name": "微信读书",
"paddingBottom": 4,
"paddingLeft": 22,
"paddingRight": 22,
"paddingTop": 5,
"pageAnim": 3,
"pageAnimEInk": 3,
"paragraphIndent": "  ",
"paragraphSpacing": 6,
"showFooterLine": true,
"showHeaderLine": true,
"textBold": 0,
"textColor": "#ff0b0b0b",
"textColorEInk": "#000000",
"textColorNight": "#ADADAD",
"textSize": 24,
"tipColor": -10461088,
"tipFooterLeft": 7,
"tipFooterMiddle": 0,
"tipFooterRight": 6,
"tipHeaderLeft": 1,
"tipHeaderMiddle": 0,
"tipHeaderRight": 2,
"titleBottomSpacing": 0,
"titleMode": 0,
"titleSize": 4,
"titleTopSpacing": 0
},
{
"name": "预设1",
"bgStr": "#FFFFFF",
"bgStrNight": "#000000",
"textColor": "#000000",
"textColorNight": "#FFFFFF",
"bgType": 0,
"bgTypeNight": 0,
"darkStatusIcon": true,
"darkStatusIconNight": false
},
{
"name": "预设2",
"bgStr": "#DDC090",
"bgStrNight": "#3C3F43",
"textColor": "#3E3422",
"textColorNight": "#DCDFE1",
"bgType": 0,
"bgTypeNight": 0,
"darkStatusIcon": true,
"darkStatusIconNight": false
},
{
"name": "预设3",
"bgStr": "#C2D8AA",
"bgStrNight": "#3C3F43",
"textColor": "#596C44",
"textColorNight": "#88C16F",
"bgType": 0,
"bgTypeNight": 0,
"darkStatusIcon": false,
"darkStatusIconNight": false
},
{
"name": "预设4",
"bgStr": "#DBB8E2",
"bgStrNight": "#3C3F43",
"textColor": "#68516C",
"textColorNight": "#F6AEAE",
"bgType": 0,
"bgTypeNight": 0,
"darkStatusIcon": false,
"darkStatusIconNight": false
},
{
"name": "预设5",
"bgStr": "#ABCEE0",
"bgStrNight": "#3C3F43",
"textColor": "#3D4C54",
"textColorNight": "#90BFF5",
"bgType": 0,
"bgTypeNight": 0,
"darkStatusIcon": false,
"darkStatusIconNight": false
}
]
@@ -0,0 +1,42 @@
[
{
"customOrder": 1,
"enableJs": true,
"enabled": true,
"singleUrl": true,
"sourceGroup": "legado",
"sourceIcon": "https://cdn.jsdelivr.net/gh/gedoor/legado@master/app/src/main/res/mipmap-hdpi/ic_launcher.png",
"sourceName": "使用说明",
"sourceUrl": "https://www.yuque.com/legado"
},
{
"customOrder": 2,
"enableJs": true,
"enabled": true,
"singleUrl": true,
"sourceGroup": "legado",
"sourceIcon": "http://mmbiz.qpic.cn/mmbiz_png/hpfMV8hEuL2eS6vnCxvTzoOiaCAibV6exBzJWq9xMic9xDg3YXAick87tsfafic0icRwkQ5ibV0bJ84JtSuxhPuEDVquA/0?wx_fmt=png",
"sourceName": "小说拾遗",
"sourceUrl": "snssdk1128://user/profile/562564899806367"
},
{
"customOrder": 3,
"enableJs": true,
"enabled": true,
"singleUrl": true,
"sourceGroup": "legado",
"sourceIcon": "https://Cloud.miaogongzi.site/images/icon.png",
"sourceName": "Meow云",
"sourceUrl": "https://pan.miaogongzi.net"
},
{
"customOrder": 4,
"enableJs": true,
"enabled": true,
"singleUrl": true,
"sourceGroup": "legado",
"sourceIcon": "https://cdn.jsdelivr.net/gh/gedoor/legado@master/app/src/main/res/mipmap-hdpi/ic_launcher.png",
"sourceName": "烏雲净化",
"sourceUrl": "https://www.lanzoux.com/b0bw8jwoh"
}
]
@@ -0,0 +1,26 @@
[
{
"themeName": "典雅蓝",
"isNightTheme": false,
"primaryColor": "#03A9F4",
"accentColor": "#AD1457",
"backgroundColor": "#F5F5F5",
"bottomBackground": "#EEEEEE"
},
{
"themeName": "黑白",
"isNightTheme": true,
"primaryColor": "#303030",
"accentColor": "#E0E0E0",
"backgroundColor": "#424242",
"bottomBackground": "#424242"
},
{
"themeName": "A屏黑",
"isNightTheme": true,
"primaryColor": "#000000",
"accentColor": "#FFFFFF",
"backgroundColor": "#000000",
"bottomBackground": "#000000"
}
]
@@ -0,0 +1,128 @@
[
{
"id": -1,
"enable": true,
"name": "目录(去空白)",
"rule": "(?<=[ \\s])(?:序章|序言|卷首语|扉页|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?![分赛游])|篇(?!张))).{0,30}$",
"serialNumber": 0
},
{
"id": -2,
"enable": true,
"name": "目录",
"rule": "^[  \\t]{0,4}(?:序章|序言|卷首语|扉页|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?![分赛游])|篇(?!张))).{0,30}$",
"serialNumber": 1
},
{
"id": -3,
"enable": false,
"name": "目录(匹配简介)",
"rule": "(?<=[ \\s])(?:(?:内容|文章)?简介|文案|前言|序章|序言|卷首语|扉页|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?![分赛游])|回(?![合来事去])|场(?![和合比电是])|篇(?!张))).{0,30}$",
"serialNumber": 2
},
{
"id": -4,
"enable": false,
"name": "目录(古典、轻小说备用)",
"rule": "^[  \\t]{0,4}(?:序章|楔子|正文(?!完|结)|终章|后记|尾声|番外|第?\\s{0,4}[\\d〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+?\\s{0,4}(?:章|节(?!课)|卷|集(?![合和])|部(?![分赛游])|回(?![合来事去])|场(?![和合比电是])|话|篇(?!张))).{0,30}$",
"serialNumber": 3
},
{
"id": -5,
"enable": false,
"name": "数字(纯数字标题)",
"rule": "(?<=[ \\s])\\d+\\.?[  \\t]{0,4}$",
"serialNumber": 4
},
{
"id": -6,
"enable": true,
"name": "数字 分隔符 标题名称",
"rule": "^[  \\t]{0,4}\\d{1,5}[:,. 、_—\\-].{1,30}$",
"serialNumber": 5
},
{
"id": -7,
"enable": true,
"name": "大写数字 分隔符 标题名称",
"rule": "^[  \\t]{0,4}(?:序章|序言|卷首语|扉页|楔子|正文(?!完|结)|终章|后记|尾声|番外|[〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8})[ 、_—\\-].{1,30}$",
"serialNumber": 6
},
{
"id": -8,
"enable": true,
"name": "正文 标题/序号",
"rule": "^[  \\t]{0,4}正文[  ]{1,4}.{0,20}$",
"serialNumber": 7
},
{
"id": -9,
"enable": true,
"name": "Chapter/Section/Part/Episode 序号 标题",
"rule": "^[  \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Nn][oO]\\.|[Ee]pisode|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)\\s{0,4}\\d{1,4}.{0,30}$",
"serialNumber": 8
},
{
"id": -10,
"enable": false,
"name": "Chapter(去简介)",
"rule": "^[  \\t]{0,4}(?:[Cc]hapter|[Ss]ection|[Pp]art|PART|[Nn][Oo]\\.|[Ee]pisode)\\s{0,4}\\d{1,4}.{0,30}$",
"serialNumber": 9
},
{
"id": -11,
"enable": true,
"name": "特殊符号 序号 标题",
"rule": "(?<=[\\s ])[【〔〖「『〈[\\[](?:第|[Cc]hapter)[\\d〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10}[章节].{0,20}$",
"serialNumber": 10
},
{
"id": -12,
"enable": false,
"name": "特殊符号 标题(成对)",
"rule": "(?<=[\\s ]{0,4})(?:[\\[〈「『〖〔《(【\\(].{1,30}[\\)】)》〕〗』」〉\\]]?|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)[  ]{0,4}$",
"serialNumber": 11
},
{
"id": -13,
"enable":true,
"name": "特殊符号 标题(单个)",
"rule": "(?<=[\\s ]{0,4})(?:[☆★✦✧].{1,30}|(?:内容|文章)?简介|文案|前言|序章|楔子|正文(?!完|结)|终章|后记|尾声|番外)[  ]{0,4}$",
"serialNumber": 12
},
{
"id": -14,
"enable": true,
"name": "章/卷 序号 标题",
"rule": "^[ \\t ]{0,4}(?:(?:内容|文章)?简介|文案|前言|序章|序言|卷首语|扉页|楔子|正文(?!完|结)|终章|后记|尾声|番外|[卷章][\\d〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8})[  ]{0,4}.{0,30}$",
"serialNumber": 13
},
{
"id": -15,
"enable":false,
"name": "顶格标题",
"rule": "^\\S.{1,20}$",
"serialNumber": 14
},
{
"id": -16,
"enable":false,
"name": "双标题(前向)",
"rule": "(?m)(?<=[ \\t ]{0,4})第[\\d〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$(?=[\\s ]{0,8}第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章)",
"serialNumber": 15
},
{
"id": -17,
"enable":false,
"name": "双标题(后向)",
"rule": "(?m)(?<=[ \\t ]{0,4}第[\\d〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$[\\s ]{0,8})第[\\d零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}章.{0,30}$",
"serialNumber": 16
},
{
"id":-18,
"enable": true,
"name": "标题 特殊符号 序号",
"rule": "^.{1,20}[(][\\d〇零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,8}[)][  \t]{0,4}$",
"serialNumber": 17
}
]
+16
View File
@@ -0,0 +1,16 @@
# 免责声明(Disclaimer
* 阅读是一款解析指定规则并获取内容的工具,为广大网络文学爱好者提供一种方便、快捷舒适的试读体验。
* 当您搜索一本书的时,阅读会您所使用的规则将该书的书名以关键词的形式提交到各个第三方网络文学网站。
各第三方网站返回的内容与阅读无关,阅读对其概不负责,亦不承担任何法律责任。
任何通过使用阅读而链接到的第三方网页均系他人制作或提供,您可能从第三方网页上获得其他服务,阅读对其合法性概不负责,亦不承担任何法律责任。
第三方搜索引擎结果根据您提交的书名自动搜索获得并提供试读,不代表阅读赞成或被搜索链接到的第三方网页上的内容或立场。
您应该对使用搜索引擎的结果自行承担风险。
* 阅读不做任何形式的保证:不保证第三方搜索引擎的搜索结果满足您的要求,不保证搜索服务不中断,不保证搜索结果的安全性、正确性、及时性、合法性。
因网络状况、通讯线路、第三方网站等任何原因而导致您不能正常使用阅读,阅读不承担任何法律责任。
阅读尊重并保护所有使用阅读用户的个人隐私权,您注册的用户名、电子邮件地址等个人资料,非经您亲自许可或根据相关法律、法规的强制性规定,阅读不会主动地泄露给第三方。
* 阅读致力于最大程度地减少网络文学阅读者在自行搜寻过程中的无意义的时间浪费,通过专业搜索展示不同网站中网络文学的最新章节。
阅读在为广大小说爱好者提供方便、快捷舒适的试读体验的同时,也使优秀网络文学得以迅速、更广泛的传播,从而达到了在一定程度促进网络文学充分繁荣发展之目的。
阅读鼓励广大小说爱好者通过阅读发现优秀网络小说及其提供商,并建议阅读正版图书。
任何单位或个人认为通过阅读搜索链接到的第三方网页内容可能涉嫌侵犯其信息网络传播权,应该及时向阅读提出书面权力通知,并提供身份证明、权属证明及详细侵权情况证明。
阅读在收到上述法律文件后,将会依法尽快断开相关链接内容。
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Chapter</title>
<link href="../Styles/fonts.css" type="text/css" rel="stylesheet"/>
<link href="../Styles/main.css" type="text/css" rel="stylesheet"/>
</head>
<body>
<!--<div class="logo">
<img alt="" class="logo" src="../Images/logo.png"/>
</div>-->
<br/>
<br/>
<h2 class="head">{title}</h2>
{content}
</body>
</html>
+21
View File
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Cover</title>
<style type="text/css">
.pic {
margin: 50% 30% 0 30%;
padding: 2px 2px;
border: 1px solid #f5f5dc;
background-color: rgba(250,250,250, 0);
border-radius: 1px;
}
</style>
</head>
<body style="text-align: center;">
<div class="pic"><img src="../Images/cover.jpg" style="width: 100%; height: auto;"/></div>
<h1 style="margin-top: 5%; font-size: 110%;">{name}</h1>
<div class="author" style="margin-top: 0;"><b>{author}</b> <span style="font-size: smaller;">/ 著</span></div>
</body>
</html>
+267
View File
@@ -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");
}
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN">
<head>
<title>Intro</title>
<link href="../Styles/fonts.css" type="text/css" rel="stylesheet" />
<link href="../Styles/main.css" type="text/css" rel="stylesheet" />
</head>
<body>
<h1 class="head" style="margin-bottom:2em;">内容简介</h1>{intro}</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

+551
View File
@@ -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;
}
Binary file not shown.
@@ -0,0 +1,156 @@
```java
public enum MimeTypeEnum {
AAC("acc", "AAC音频", "audio/aac"),
ABW("abw", "AbiWord文件", "application/x-abiword"),
ARC("arc", "存档文件", "application/x-freearc"),
AVI("avi", "音频视频交错格式", "video/x-msvideo"),
AZW("azw", "亚马逊Kindle电子书格式", "application/vnd.amazon.ebook"),
BIN("bin", "任何类型的二进制数据", "application/octet-stream"),
BMP("bmp", "Windows OS / 2位图图形", "image/bmp"),
BZ("bz", "BZip存档", "application/x-bzip"),
BZ2("bz2", "BZip2存档", "application/x-bzip2"),
CSH("csh", "C-Shell脚本", "application/x-csh"),
CSS("css", "级联样式表(CSS", "text/css"),
CSV("csv", "逗号分隔值(CSV", "text/csv"),
DOC("doc", "微软Word文件", "application/msword"),
DOCX("docx", "Microsoft WordOpenXML", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
EOT("eot", "MS Embedded OpenType字体", "application/vnd.ms-fontobject"),
EPUB("epub", "电子出版物(EPUB", "application/epub+zip"),
GZ("gz", "GZip压缩档案", "application/gzip"),
GIF("gif", "图形交换格式(GIF", "image/gif"),
HTM("htm", "超文本标记语言(HTML", "text/html"),
HTML("html", "超文本标记语言(HTML", "text/html"),
ICO("ico", "图标格式", "image/vnd.microsoft.icon"),
ICS("ics", "iCalendar格式", "text/calendar"),
JAR("jar", "Java存档", "application/java-archive"),
JPEG("jpeg", "JPEG图像", "image/jpeg"),
JPG("jpg", "JPEG图像", "image/jpeg"),
JS("js", "JavaScript", "text/javascript"),
JSON("json", "JSON格式", "application/json"),
JSONLD("jsonld", "JSON-LD格式", "application/ld+json"),
MID("mid", "乐器数字接口(MIDI", "audio/midi"),
MIDI("midi", "乐器数字接口(MIDI", "audio/midi"),
MJS("mjs", "JavaScript模块", "text/javascript"),
MP3("mp3", "MP3音频", "audio/mpeg"),
MPEG("mpeg", "MPEG视频", "video/mpeg"),
MPKG("mpkg", "苹果安装程序包", "application/vnd.apple.installer+xml"),
ODP("odp", "OpenDocument演示文稿文档", "application/vnd.oasis.opendocument.presentation"),
ODS("ods", "OpenDocument电子表格文档", "application/vnd.oasis.opendocument.spreadsheet"),
ODT("odt", "OpenDocument文字文件", "application/vnd.oasis.opendocument.text"),
OGA("oga", "OGG音讯", "audio/ogg"),
OGV("ogv", "OGG视频", "video/ogg"),
OGX("ogx", "OGG", "application/ogg"),
OPUS("opus", "OPUS音频", "audio/opus"),
OTF("otf", "otf字体", "font/otf"),
PNG("png", "便携式网络图形", "image/png"),
PDF("pdf", "Adobe 可移植文档格式(PDF", "application/pdf"),
PHP("php", "php", "application/x-httpd-php"),
PPT("ppt", "Microsoft PowerPoint", "application/vnd.ms-powerpoint"),
PPTX("pptx", "Microsoft PowerPointOpenXML", "application/vnd.openxmlformats-officedocument.presentationml.presentation"),
RAR("rar", "RAR档案", "application/vnd.rar"),
RTF("rtf", "富文本格式", "application/rtf"),
SH("sh", "Bourne Shell脚本", "application/x-sh"),
SVG("svg", "可缩放矢量图形(SVG", "image/svg+xml"),
SWF("swf", "小型Web格式(SWF)或Adobe Flash文档", "application/x-shockwave-flash"),
TAR("tar", "磁带存档(TAR", "application/x-tar"),
TIF("tif", "标记图像文件格式(TIFF", "image/tiff"),
TIFF("tiff", "标记图像文件格式(TIFF", "image/tiff"),
TS("ts", "MPEG传输流", "video/mp2t"),
TTF("ttf", "ttf字体", "font/ttf"),
TXT("txt", "文本(通常为ASCII或ISO 8859- n", "text/plain"),
VSD("vsd", "微软Visio", "application/vnd.visio"),
WAV("wav", "波形音频格式", "audio/wav"),
WEBA("weba", "WEBM音频", "audio/webm"),
WEBM("webm", "WEBM视频", "video/webm"),
WEBP("webp", "WEBP图像", "image/webp"),
WOFF("woff", "Web开放字体格式(WOFF", "font/woff"),
WOFF2("woff2", "Web开放字体格式(WOFF", "font/woff2"),
XHTML("xhtml", "XHTML", "application/xhtml+xml"),
XLS("xls", "微软Excel", "application/vnd.ms-excel"),
XLSX("xlsx", "微软ExcelOpenXML", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
XML("xml", "XML", "application/xml"),
XUL("xul", "XUL", "application/vnd.mozilla.xul+xml"),
ZIP("zip", "ZIP", "application/zip"),
MIME_3GP("3gp", "3GPP audio/video container", "video/3gpp"),
MIME_3GP_WITHOUT_VIDEO("3gp", "3GPP audio/video container doesn't contain video", "audio/3gpp2"),
MIME_3G2("3g2", "3GPP2 audio/video container", "video/3gpp2"),
MIME_3G2_WITHOUT_VIDEO("3g2", "3GPP2 audio/video container doesn't contain video", "audio/3gpp2"),
MIME_7Z("7z", "7-zip存档", "application/x-7z-compressed")
}
```
@@ -0,0 +1,25 @@
# 书源管理界面帮助
* 书源右上角标志
* 绿点表示书源有发现,且启用了发现
* 红点表示书源有发现,但是未启用
* 没有标志表示此书源没有发现
* 右上角有分组菜单,可以按分组筛选书源
* 右上角更多菜单里包含
* 新建书源
* 本地导入
* 网络导入
* 二维码导入
* 分享选中源
* 选择源的更多操作在右下角的菜单里面,操作都是针对选择的书源
* 启用所选
* 禁用所选
* 添加分组
* 移除分组
* 启用发现
* 禁用发现
* 置顶所选
* 置底所选
* 导出所选
* 校验所选
* 校验失败的书源分组会加上"失效",选择"失效"分组即可批量操作
@@ -0,0 +1,21 @@
# 订阅源管理界面帮助
* 订阅源可以通过规则订阅一些网络内容
* 书源右上角标志
* 绿点表示书源有发现,且启用了发现
* 红点表示书源有发现,但是未启用
* 没有标志表示此书源没有发现
* 右上角有分组菜单,可以按分组筛选书源
* 右上角更多菜单里包含
* 新建订阅源
* 本地导入
* 网络导入
* 二维码导入
* 分享选中源
* 选择源的更多操作在右下角的菜单里面,操作都是针对选择的书源
* 启用所选
* 禁用所选
* 置顶所选
* 置底所选
* 导出所选
* 校验失败的书源分组会加上"失效",选择"失效"分组即可批量操作
+190
View File
@@ -0,0 +1,190 @@
# 帮助文档
## **新人必读**
【温馨提醒】 *本帮助可以在我的-右上角帮助按钮再次打开,更新前一定要做好备份,以免数据丢失!*
1. 为什么第一次安装好之后什么东西都没有?
* 阅读只是一个转码工具,不提供内容,第一次安装app,需要自己手动导入书源,可以从公众号 **[开源阅读]**、QQ群、酷安评论里获取由书友制作分享的书源。
2. 正文出现缺字漏字、内容缺失、排版错乱等情况,如何处理?
* 有可能是净化规则出现问题,先关闭替换净化并刷新,再观察是否正常。如果正常说明净化规则存在误杀,如果关闭后仍然出现相关问题,请点击源链接查看原文与正文是否相同,如果不同,再进行反馈。
3. 漫画源看书显示乱码,如何解决?
* 异次元和阅读是两个不同的软件,**两个软件的源并不通用**,请导入阅读的支持的漫画源!
## 书源相关
1. 如何导入本地书源文件?
* 下载群文件里的书源文件(书源格式后缀有txt、json,其中json文件某些情况下无法导入,需要修改后缀为txt格式才可导入);
* 打开阅读软件;
* 我的 - 点击“书源管理”;
* 点击右上角选择“本地导入”;
* 左下角选择书源文件所在的路径;
* 点击书源文件导入;
* 导入后返回书源管理界面;
* 新版qq下载路径:Android/data/com.tencent.mobileqq/Tencent/QQfile_recv/
![QQ导入书源](https://cdn.jsdelivr.net/gh/gedoor/gedoor.github.io@master/images/importSource.jpg)
2. 如何新建大佬发的单独书源?
* 复制书源代码;
* 打开阅读软件;
* 我的 - 点击“书源管理”;
* 右上角选择“新建书源”;
* 进入新建书源后点击右上角“粘贴源”;
* 粘贴书源完成后点击上方保存;
* 本次新建单独书源操作完成。
* 注:如果书源有错误或者复制不全会显示格式错误,请重新复制。
3. 为什么导入2.0书源后无法阅读?
* 部分2.0书源并不适用于3.0版本的阅读,建议导入后进行筛选。
4. 阅读2.0数据如何导入阅读3.0
* 先对阅读2.0的数据进行备份,然后进入阅读3.0,点击“我的”,选择“备份与恢复”,再点击“导入旧版本数据”。
5. 如何给朋友分享我的书源?
* 打开阅读软件;
* 点击备份;
* 打开手机自带的文件管理;
* 手机自带内存根目录找到YueDu3.0文件夹;
* 找到myBookSource.json长按选择分享;
* 选择微信分享或者QQ分享;
* 选择你要分享的好友点击发送;
* 好友接收后在手机自带内存根目录找到myBookSource.json文件(最新版QQ 安卓10及以下版本在Android/data/com.tencent.mobileqq/Tencent/QQfile_recv/,安卓11版本用户由于系统限制无法访问data目录,微信在Tencent/MicroMsg/Download);
* 复制该文件到手机自带内存根目录找到YueDu3.0文件夹(如已有该文件请先删除该文件或者备份到其他地方再复制到文件夹);
* 打开阅读软件点击恢复。
* 注:备份路径如已修改过请在修改后的路径下查找书源文件。
6. 效验书源显示失效就说明书源不能用了吗?
* 效验书源只是测试书源,可以做个参考,失效了不代表书源不能用了。
7. 发现和正版书源能不能使用?
* 发现和正版书源只能用来找书,看排行榜,不能用来看书,如需看书请切换书源。
8. 为什么书源这么多,发现里却只有一点点?
* 书源想要在发现界面里显示需要在书源里添加发现规则,并不是所有书源都有发现规则。
## 本地书籍相关
1. 目前阅读支持哪些格式的本地书籍?
* 目前支持TXT、EPUB格式
2. 如何导入本地书籍?
* 在书架页面点击右上角,选择“添加本地”,授予相关权限后即可导入本地书籍。也可在文件管理器中使用 **阅读** 打开相关书籍。
3. 导入TXT文件提示“LoadTocError”或“List is empty”是怎么回事?
* 请先去应用详情中确认是否授予了阅读“读写手机存储”的权限。
* 自动识别目录失败,可能是相关目录规则未开启,请点击右上角的换源按钮手动更换目录规则。
* 如果尝试所有规则均无法识别,请在github上提交issue并附件相关txt文件,也可以发送邮件至i@qnmlgb.trade(标题:legado本地文件章节无法识别,内容对其具体情况进行简要说明,附件上传相关txt文件)。
4. 如何下载书籍到本地?
* 把在线书籍加入到书架后,在书架页面点击右上角,选择“离线缓存”即可。
5. 如何自定义导出的txt/epub文件名称?
* 点击 **离线缓存** - **导出文件名**.
* 使用方法:
- 导出文件名支持js语法
- 可用变量: name - 书名 author-作者
- 示例:
> {name+"作者:"+author}
- 导出文件名:
> Legado是最好的在线阅读软件 作者: kunfei.
**注意:** name、author等变量与字符串的拼接都需要在js环境中进行,即必须使用{ } 将变量与字符串包裹起来.
6. 为什么我打开本地的TXT文件,显示内容却是乱码?
* 部分编码在阅读上会识别错误,建议先用文本编辑器转换为常用的UTF-8格式。
7. 阅读对部分把正文(如所有含引号的句子)识别成标题,如何解决?
* 点击右上角更换目录规则即可。
## 书籍界面相关
1. 如何刷新书架?
* 在书架界面下拉即可刷新。
2. 书架界面书籍右上角的红色或者灰色背景小数字代表什么?
* 红色代表书籍有更新,灰色代表无更新,数字代表未读章节。
3. 如何查看书籍详情?
* 长按书籍。
4. 如何对书架上的书进行删除、切换书架的操作?
* 书籍详情页操作即可。
5. 如何禁止或允许某本书更新?
* 书籍详情页,点击右上角 - “允许更新”。
6. 如何更换小说封面、名字、作者或简介?
* 书籍详情页,点击右上角修改按钮。
7. 怎么使用自定义字体?
* 阅读界面 - 字体-点击右上角选择字体文件路径。
8. 目前支持哪些格式的字体文件?
* 目前支持ttf、otf格式。
9. 书籍经常“正在加载中”怎么办?
* 在线书籍出现这个问题通常是由于源质量不好或不兼容引起的,可以换其它源多试试;本地书籍出现这个问题大概率是目录规则问题,手动切换规则可以解决。
10. 书籍内容只有标题,正文内容是路径怎么办?
* 通常是缓存路径引起的,更换缓存路径即可。
11. 看书时如遇到“目录为空”、“加载失败”和长串英文等情况怎么办?
* 在线书籍一般是书源问题,切换或更新书源即可。本地书籍请尝试手动更换目录规则。
12. 为什么每一章的最后一页,阅读的文字和横线背景总是对不齐?
* 请在 设置-文字底部对齐 选项中关闭底部对齐,再调整排版。
13. 漫画源或图片章节只能看到第一页,如何解决?
* 请先查看原网页是否正常,若正常,请在书籍阅读界面点击右上角的 **⁝** 按钮,在弹出的菜单中,选择 **翻页动画(本书)**,将翻页动画更改为 **滚动**
14. 阅读图片章节、漫画或epub插图时,图片被缩放到一页中,以至无法看清,如何处理?
* 临时处理方案:长按图片可以进行双指缩放。图片章节请先参考Q13中的方案将翻页动画更改为**滚动**
* 3.0旧版可以点击书籍界面的章节标题进入 **编辑书源** 界面,在 正文-图片样式 中填入 *full*,保存更改,刷新当前章节即可。
* 3.0新版可以直接在书籍阅读界面点击右上角的 **⁝** 按钮,选择 图片样式- *full*.
## 替换净化相关
1. 替换净化是什么?
* 替换净化可以去除书籍内容里的广告、错别字、屏蔽词等。
2. 如何自己填写净化替换规则?
* 第一行:替换规则名称 - 根据自己需求对替换净化规则进行命名;
* 第二行:分组 - 净化规则的分组组别;
* 第三行:替换规则 - 填写需要被替换的内容;
* 第四行:替换为 - 填写想替换成的内容(如不填则默认表示删除第三行里填写的内容);
* 第五行:替换范围,选填书名或者源名 - 填写此替换净化规则需要对哪本书籍或者哪个书源生效(如不填则对所有书籍和书源生效)。
* 注:如常规去除方法去除不掉,则需要勾选“使用正则表达式”,同时第三行里的替换规则也需要按照正则表达式来填写(正则表达式填写方法可自行百度学习)。
## 备份相关
1. 云备份在哪?
* 我的 - 备份与恢复 - WebDav设置。
2. 如何操作进行云备份?
* 侧栏设置,WebDav设置;
* 正确填写WebDAV 服务器地址、WebDAV 账号、WebDAV 密码;(要获得这三项的信息,需要注册一个坚果云账号,如果直接在手机上注册,坚果云会让你下载app,过程比较麻烦,为了一步到位,最好是在电脑上打开这个注册链接:https://www.jianguoyun.com/d/signup ;注册后,进入坚果云;点击右上角账户名处选择 “账户信息”,然后选择“安全选项”;在“安全选项” 中找到“第三方应用管理”,并选择“添加应用”,输入名称如“阅读”后,会生成密码,选择完成;其中 https://dav.jianguoyun.com/dav/ 就是填入“WebDAV 服务器地址”的内容,“使用情况”后面的邮箱地址就是你的“WebDAV 账号”,点击显示密码后得到的密码就是你的“WebDAV 密码”。)
* 无需操作,APP默认每天自动云备份一次。
3. 关于云备份的相关说明
* 在正确设置好云备份的情况下,APP默认每天自动云备份一次,当日多次手动云备份会对当日的旧云备份文件进行覆盖,并不会覆盖之前及之后不同日期的备份文件,每天所自动云备份的文件会按照日期进行命名。
4. 本地备份和云备份都能备份哪些东西?
* 书架、看书进度、搜索记录、书源、替换、APP设置等都会备份,基本涵盖所有内容。
5. 出现某些未知bug怎么办?
* 清除软件数据试试看,不行再进行反馈。
## 其他
1. 如何听书?
* 可以使用手机自带的朗读引擎,也可使用第三方如谷歌、小米等朗读引擎。
* 【具体操作:安装-系统设置-其他高级设置-辅助功能-TTS输出-选择安装的朗读引擎(不同品牌手机的操作方法及步骤也不同,视情况而定)。】
2. 如何设置屏幕方向、屏幕显示时长、显示/隐藏状态栏、显示/隐藏导航栏、音量键翻页、长按选择文本、点击总是翻下一页、自定义翻页案件?
* 阅读界面,设置(可上划,下面还有其他设置)。
3. 搜索的时候感觉手机卡顿,如何解决?
* 我的 - 其他设置 - “更新和搜索线程数”调低。
+22
View File
@@ -0,0 +1,22 @@
# 书源调试
* 调试搜索>>输入关键字,如:
```
系统
```
* 调试发现>>输入发现URL,如:
```
月票榜::https://www.qidian.com/rank/yuepiao?page={{page}}
```
* 调试详情页>>输入详情页URL,如:
```
https://m.qidian.com/book/1015609210
```
* 调试目录页>>输入目录页URL,如:
```
++https://www.zhaishuyuan.com/read/30394
```
* 调试正文页>>输入正文页URL,如:
```
--https://www.zhaishuyuan.com/chapter/30394/20940996
```
+15
View File
@@ -0,0 +1,15 @@
# 在线朗读规则说明
* 在线朗读规则为url规则,同书源url
* js参数
```
speakText //朗读文本
speakSpeed //朗读速度,0-45
```
* 例:
```
http://tts.baidu.com/text2audio,{
"method": "POST",
"body": "tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=5003&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio"
}
```
File diff suppressed because one or more lines are too long
+204
View File
@@ -0,0 +1,204 @@
# 正则表达式学习
- [基本匹配]
- [元字符]
- [英文句号]
- [字符集]
- [否定字符集]
- [重复]
- [星号]
- [加号]
- [问号]
- [花括号]
- [字符组]
- [分支结构]
- [转义特殊字符]
- [定位符]
- [插入符号]
- [美元符号]
- [简写字符集]
- [断言]
- [正向先行断言]
- [负向先行断言]
- [正向后行断言]
- [负向后行断言]
- [标记]
- [不区分大小写]
- [全局搜索]
- [多行匹配]
- [常用正则表达式]
## 1. 基本匹配
正则表达式只是我们用于在文本中检索字母和数字的模式。例如正则表达式 `cat`,表示: 字母 `c` 后面跟着一个字母 `a`,再后面跟着一个字母 `t`。<pre>"cat" => The <a href="#learn-regex"><strong>cat</strong></a> sat on the mat</pre>
正则表达式 `123` 会匹配字符串 "123"。通过将正则表达式中的每个字符逐个与要匹配的字符串中的每个字符进行比较,来完成正则匹配。
正则表达式通常区分大小写,因此正则表达式 `Cat` 与字符串 "cat" 不匹配。<pre>"Cat" => The cat sat on the <a href="#learn-regex"><strong>Cat</strong></a></pre>
## 2. 元字符
元字符是正则表达式的基本组成元素。元字符在这里跟它通常表达的意思不一样,而是以某种特殊的含义去解释。有些元字符写在方括号内的时候有特殊含义。
元字符如下:
|元字符|描述|
|:----:|----|
|.|匹配除换行符以外的任意字符。|
|[ ]|字符类,匹配方括号中包含的任意字符。|
|[^ ]|否定字符类。匹配方括号中不包含的任意字符|
|*|匹配前面的子表达式零次或多次|
|+|匹配前面的子表达式一次或多次|
|?|匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。|
|{n,m}|花括号,匹配前面字符至少 n 次,但是不超过 m 次。|
|(xyz)|字符组,按照确切的顺序匹配字符xyz。|
|&#124;|分支结构,匹配符号之前的字符或后面的字符。|
|&#92;|转义符,它可以还原元字符原来的含义,允许你匹配保留字符 <code>[ ] ( ) { } . * + ? ^ $ \ &#124;</code>|
|^|匹配行的开始|
|$|匹配行的结束|
## 2.1 英文句号
英文句号 `.` 是元字符的最简单的例子。元字符 `.` 可以匹配任意单个字符。它不会匹配换行符和新行的字符。例如正则表达式 `.ar`,表示: 任意字符后面跟着一个字母 `a`
再后面跟着一个字母 `r`。<pre>".ar" => The <a href="#learn-regex"><strong>car</strong></a> <a href="#learn-regex"><strong>par</strong></a>ked in the <a href="#learn-regex"><strong>gar</strong></a>age.</pre>
## 2.2 字符集
字符集也称为字符类。方括号被用于指定字符集。使用字符集内的连字符来指定字符范围。方括号内的字符范围的顺序并不重要。
例如正则表达式 `[Tt]he`,表示: 大写 `T` 或小写 `t` ,后跟字母 `h`,再后跟字母 `e`。<pre>"[Tt]he" => <a href="#learn-regex"><strong>The</strong></a> car parked in <a href="#learn-regex"><strong>the</strong></a> garage.</pre>
然而,字符集中的英文句号表示它字面的含义。正则表达式 `ar[.]`,表示小写字母 `a`,后面跟着一个字母 `r`,再后面跟着一个英文句号 `.` 字符。<pre>"ar[.]" => A garage is a good place to park a c<a href="#learn-regex"><strong>ar.</strong></a></pre>
### 2.2.1 否定字符集
一般来说插入字符 `^` 表示一个字符串的开始,但是当它在方括号内出现时,它会取消字符集。例如正则表达式 `[^c]ar`,表示: 除了字母 `c` 以外的任意字符,后面跟着字符 `a`
再后面跟着一个字母 `r`。<pre>"[^c]ar" => The car <a href="#learn-regex"><strong>par</strong></a>ked in the <a href="#learn-regex"><strong>gar</strong></a>age.</pre>
## 2.3 重复
以下元字符 `+``*``?` 用于指定子模式可以出现多少次。这些元字符在不同情况下的作用不同。
### 2.3.1 星号
该符号 `*` 表示匹配上一个匹配规则的零次或多次。正则表达式 `a*` 表示小写字母 `a` 可以重复零次或者多次。但是它如果出现在字符集或者字符类之后,它表示整个字符集的重复。
例如正则表达式 `[a-z]*`,表示: 一行中可以包含任意数量的小写字母。<pre>"[a-z]*" => T<a href="#learn-regex"><strong>he</strong></a> <a href="#learn-regex"><strong>car</strong></a> <a href="#learn-regex"><strong>parked</strong></a> <a href="#learn-regex"><strong>in</strong></a> <a href="#learn-regex"><strong>the</strong></a> <a href="#learn-regex"><strong>garage</strong></a> #21.</pre>
`*` 符号可以与元符号 `.` 用在一起,用来匹配任意字符串 `.*`。该 `*` 符号可以与空格符 `\s` 一起使用,用来匹配一串空格字符。
例如正则表达式 `\s*cat\s*`,表示: 零个或多个空格,后面跟小写字母 `c`,再后面跟小写字母 `a`,再再后面跟小写字母 `t`,后面再跟零个或多个空格。<pre>"\s*cat\s*" => The fat<a href="#learn-regex"><strong> cat </strong></a>sat on the <a href="#learn-regex"><strong>cat</strong></a>.</pre>
### 2.3.2 加号
该符号 `+` 匹配上一个字符的一次或多次。例如正则表达式 `c.+t`,表示: 一个小写字母 `c`,后跟任意数量的字符,后跟小写字母 `t`。<pre>"c.+t" => The fat <a href="#learn-regex"><strong>cat sat on the mat</strong></a>.</pre>
### 2.3.3 问号
在正则表达式中,元字符 `?` 用来表示前一个字符是可选的。该符号匹配前一个字符的零次或一次。
例如正则表达式 `[T]?he`,表示: 可选的大写字母 `T`,后面跟小写字母 `h`,后跟小写字母 `e`。<pre>"[T]he" => <a href="#learn-regex"><strong>The</strong></a> car is parked in the garage.</pre><pre>"[T]?he" => <a href="#learn-regex"><strong>The</strong></a> car is parked in t<a href="#learn-regex"><strong>he</strong></a> garage.</pre>
## 2.4 花括号
在正则表达式中花括号(也被称为量词 ?)用于指定字符或一组字符可以重复的次数。例如正则表达式 `[0-9]{2,3}`,表示: 匹配至少2位数字但不超过3位(0到9范围内的字符)。<pre>"[0-9]{2,3}" => The number was 9.<a href="#learn-regex"><strong>999</strong></a>7 but we rounded it off to <a href="#learn-regex"><strong>10</strong></a>.0.</pre>
我们可以省略第二个数字。例如正则表达式 `[0-9]{2,}`,表示: 匹配2个或更多个数字。如果我们也删除逗号,则正则表达式 `[0-9]{2}`,表示: 匹配正好为2位数的数字。<pre>"[0-9]{2,}" => The number was 9.<a href="#learn-regex"><strong>9997</strong></a> but we rounded it off to <a href="#learn-regex"><strong>10</strong></a>.0.</pre><pre>"[0-9]{2}" => The number was 9.<a href="#learn-regex"><strong>99</strong></a><a href="#learn-regex"><strong>97</strong></a> but we rounded it off to <a href="#learn-regex"><strong>10</strong></a>.0.</pre>
## 2.5 字符组
字符组是一组写在圆括号内的子模式 `(...)`。正如我们在正则表达式中讨论的那样,如果我们把一个量词放在一个字符之后,它会重复前一个字符。
但是,如果我们把量词放在一个字符组之后,它会重复整个字符组。
例如正则表达式 `(ab)*` 表示匹配零个或多个的字符串 "ab"。我们还可以在字符组中使用元字符 `|`。例如正则表达式 `(c|g|p)ar`,表示: 小写字母 `c``g``p` 后面跟字母 `a`,后跟字母 `r`。<pre>"(c|g|p)ar" => The <a href="#learn-regex"><strong>car</strong></a> is <a href="#learn-regex"><strong>par</strong></a>ked in the <a href="#learn-regex"><strong>gar</strong></a>age.</pre>
## 2.6 分支结构
在正则表达式中垂直条 `|` 用来定义分支结构,分支结构就像多个表达式之间的条件。现在你可能认为这个字符集和分支机构的工作方式一样。
但是字符集和分支结构巨大的区别是字符集只在字符级别上有作用,然而分支结构在表达式级别上依然可以使用。
例如正则表达式 `(T|t)he|car`,表示: 大写字母 `T` 或小写字母 `t`,后面跟小写字母 `h`,后跟小写字母 `e` 或小写字母 `c`,后跟小写字母 `a`,后跟小写字母 `r`。<pre>"(T|t)he|car" => <a href="#learn-regex"><strong>The</strong></a> <a href="#learn-regex"><strong>car</strong></a> is parked in <a href="#learn-regex"><strong>the</strong></a> garage.</pre>
## 2.7 转义特殊字符
正则表达式中使用反斜杠 `\` 来转义下一个字符。这将允许你使用保留字符来作为匹配字符 `{ } [ ] / \ + * . $ ^ | ?`。在特殊字符前面加 `\`,就可以使用它来做匹配字符。
例如正则表达式 `.` 是用来匹配除了换行符以外的任意字符。现在要在输入字符串中匹配 `.` 字符,正则表达式 `(f|c|m)at\.?`,表示: 小写字母 `f``c` 或者 `m` 后跟小写字母 `a`,后跟小写字母 `t`,后跟可选的 `.` 字符。<pre>"(f|c|m)at\.?" => The <a href="#learn-regex"><strong>fat</strong></a> <a href="#learn-regex"><strong>cat</strong></a> sat on the <a href="#learn-regex"><strong>mat.</strong></a></pre>
## 2.8 定位符
在正则表达式中,为了检查匹配符号是否是起始符号或结尾符号,我们使用定位符。
定位符有两种类型: 第一种类型是 `^` 检查匹配字符是否是起始字符,第二种类型是 `$`,它检查匹配字符是否是输入字符串的最后一个字符。
### 2.8.1 插入符号
插入符号 `^` 符号用于检查匹配字符是否是输入字符串的第一个字符。如果我们使用正则表达式 `^a` (如果a是起始符号)匹配字符串 `abc`,它会匹配到 `a`
但是如果我们使用正则表达式 `^b`,它是匹配不到任何东西的,因为在字符串 `abc` 中 "b" 不是起始字符。
让我们来看看另一个正则表达式 `^(T|t)he`,这表示: 大写字母 `T` 或小写字母 `t` 是输入字符串的起始符号,后面跟着小写字母 `h`,后跟小写字母 `e`。<pre>"(T|t)he" => <a href="#learn-regex"><strong>The</strong></a> car is parked in <a href="#learn-regex"><strong>the</strong></a> garage.</pre><pre>"^(T|t)he" => <a href="#learn-regex"><strong>The</strong></a> car is parked in the garage.</pre>
### 2.8.2 美元符号
美元 `$` 符号用于检查匹配字符是否是输入字符串的最后一个字符。例如正则表达式 `(at\.)$`,表示: 小写字母 `a`,后跟小写字母 `t`,后跟一个 `.` 字符,且这个匹配器必须是字符串的结尾。<pre>"(at\.)" => The fat c<a href="#learn-regex"><strong>at.</strong></a> s<a href="#learn-regex"><strong>at.</strong></a> on the m<a href="#learn-regex"><strong>at.</strong></a></pre><pre>"(at\.)$" => The fat cat sat on the m<a href="#learn-regex"><strong>at.</strong></a></pre>
## 3. 简写字符集
正则表达式为常用的字符集和常用的正则表达式提供了简写。简写字符集如下:
|简写|描述|
|:----:|----|
|.|匹配除换行符以外的任意字符|
|\w|匹配所有字母和数字的字符: `[a-zA-Z0-9_]`|
|\W|匹配非字母和数字的字符: `[^\w]`|
|\d|匹配数字: `[0-9]`|
|\D|匹配非数字: `[^\d]`|
|\s|匹配空格符: `[\t\n\f\r\p{Z}]`|
|\S|匹配非空格符: `[^\s]`|
## 4. 断言
后行断言和先行断言有时候被称为断言,它们是特殊类型的 ***非捕获组*** (用于匹配模式,但不包括在匹配列表中)。当我们在一种特定模式之前或者之后有这种模式时,会优先使用断言。
例如我们想获取输入字符串 `$4.44 and $10.88` 中带有前缀 `$` 的所有数字。我们可以使用这个正则表达式 `(?<=\$)[0-9\.]*`,表示: 获取包含 `.` 字符且前缀为 `$` 的所有数字。
以下是正则表达式中使用的断言:
|符号|描述|
|:----:|----|
|?=|正向先行断言|
|?!|负向先行断言|
|?<=|正向后行断言|
|?<!|负向后行断言|
### 4.1 正向先行断言
正向先行断言认为第一部分的表达式必须是先行断言表达式。返回的匹配结果仅包含与第一部分表达式匹配的文本。
要在一个括号内定义一个正向先行断言,在括号中问号和等号是这样使用的 `(?=...)`。先行断言表达式写在括号中的等号后面。
例如正则表达式 `(T|t)he(?=\sfat)`,表示: 匹配大写字母 `T` 或小写字母 `t`,后面跟字母 `h`,后跟字母 `e`
在括号中,我们定义了正向先行断言,它会引导正则表达式引擎匹配 `The``the` 后面跟着 `fat`。<pre>"(T|t)he(?=\sfat)" => <a href="#learn-regex"><strong>The</strong></a> fat cat sat on the mat.</pre>
### 4.2 负向先行断言
当我们需要从输入字符串中获取不匹配表达式的内容时,使用负向先行断言。负向先行断言的定义跟我们定义的正向先行断言一样,
唯一的区别是不是等号 `=`,我们使用否定符号 `!`,例如 `(?!...)`
我们来看看下面的正则表达式 `(T|t)he(?!\sfat)`,表示: 从输入字符串中获取全部 `The` 或者 `the` 且不匹配 `fat` 前面加上一个空格字符。<pre>"(T|t)he(?!\sfat)" => The fat cat sat on <a href="#learn-regex"><strong>the</strong></a> mat.</pre>
### 4.3 正向后行断言
正向后行断言是用于获取在特定模式之前的所有匹配内容。正向后行断言表示为 `(?<=...)`。例如正则表达式 `(?<=(T|t)he\s)(fat|mat)`,表示: 从输入字符串中获取在单词 `The``the` 之后的所有 `fat``mat` 单词。<pre>"(?<=(T|t)he\s)(fat|mat)" => The <a href="#learn-regex"><strong>fat</strong></a> cat sat on the <a href="#learn-regex"><strong>mat</strong></a>.</pre>
### 4.4 负向后行断言
负向后行断言是用于获取不在特定模式之前的所有匹配的内容。负向后行断言表示为 `(?<!...)`。例如正则表达式 `(?<!(T|t)he\s)(cat)`,表示: 在输入字符中获取所有不在 `The``the` 之后的所有单词 `cat`。<pre>"(?&lt;!(T|t)he\s)(cat)" => The cat sat on <a href="#learn-regex"><strong>cat</strong></a>.</pre>
## 5. 标记
标记也称为修饰符,因为它会修改正则表达式的输出。这些标志可以以任意顺序或组合使用,并且是正则表达式的一部分。
|标记|描述|
|:----:|----|
|i|不区分大小写: 将匹配设置为不区分大小写。|
|g|全局搜索: 搜索整个输入字符串中的所有匹配。|
|m|多行匹配: 会匹配输入字符串每一行。|
* **数字**: `\d+$`
* **用户名**: `^[\w\d_.]{4,16}$`
* **字母数字字符**: `^[a-zA-Z0-9]*$`
* **带空格的字母数字字符**: `^[a-zA-Z0-9 ]*$`
* **小写字母**: `[a-z]+$`
* **大写字母**: `[A-Z]+$`
* **网址**: `^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]]){2,4}([[a-zA-Z0-9]\/+=%&_\.~?\-]*))*$`
* **日期 (MM/DD/YYYY)**: `^(0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2}$`
* **日期 (YYYY/MM/DD)**: `^(19|20)?[0-9]{2}[- /.](0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])$`
* **求更求转发致谢**: `[\((【].*?[求更谢乐发推].*?[】)\)]`
* **查找最新章节**: `您可以.*?查找最新章节`
* **ps/PS**: `(?i)ps\b.*`
* **Html标签**: `<[^>]+?>`
@@ -0,0 +1,6 @@
# 替换管理界面帮助
* 替换规则是用来替换正文内容的一种规则
* 菜单可以新建和导入规则
* 可以拖动排序
* 可以选择操作
+177
View File
@@ -0,0 +1,177 @@
# 源规则帮助
* [书源帮助文档](https://alanskycn.gitee.io/teachme/Rule/source.html)
* [订阅源帮助文档](https://alanskycn.gitee.io/teachme/Rule/rss.html)
* [js扩展类](https://github.com/gedoor/legado/blob/master/app/src/main/java/io/legado/app/help/JsExtensions.kt)
* 辅助键盘❓中可插入URL参数模板,打开帮助,选择文件
* 规则标志, {{......}}内使用规则必须有明显的规则标志,没有规则标志当作js执行
```
@@ 默认规则,直接写时可以省略@@
@XPath: xpath规则,直接写时以//开头可省略@XPath
@Json: json规则,直接写时以$.开头可省略@Json
: regex规则,不可省略,只可以用在书籍列表和目录列表
```
* 发现url格式
```json
[
{
"title": "xxx",
"url": "",
"style": {
"layout_flexGrow": 0,
"layout_flexShrink": 1,
"layout_alignSelf": "auto",
"layout_flexBasisPercent": -1,
"layout_wrapBefore": false
}
}
]
```
* 获取登录后的cookie
```
java.getCookie("http://baidu.com", null) => userid=1234;pwd=adbcd
java.getCookie("http://baidu.com", "userid") => 1234
```
* 请求头,支持http代理,socks4 socks5代理设置
```
socks5代理
{
"proxy":"socks5://127.0.0.1:1080"
}
http代理
{
"proxy":"http://127.0.0.1:1080"
}
支持代理服务器验证
{
"proxy":"socks5://127.0.0.1:1080@用户名@密码"
}
注意:这些请求头是无意义的,会被忽略掉
```
* js 变量和函数
```
java 变量-当前类
baseUrl 变量-当前url,String
result 变量-上一步的结果
book 变量-书籍类,方法见 io.legado.app.data.entities.Book
cookie 变量-cookie操作类,方法见 io.legado.app.help.http.CookieStore
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<String, String>)`
* `java.post(urlStr: String, body: String, headers: Map<String, String>)`
* 对于搜索重定向的源,可以使用此方法获得重定向后的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;"}
};
'<img src="'+src+","+JSON.stringify(options)+'">'
```
## 部分js对象属性说明
上述js变量与函数中,一些js的对象属性用的频率较高,在此列举。方便写源的时候快速翻阅。
### book对象的可用属性
> 使用方法: 在js中或{{}}中使用book.属性的方式即可获取.如在正文内容后加上 ##{{book.name+"正文卷"+title}} 可以净化 书名+正文卷+章节名称(如 我是大明星正文卷第二章我爸是豪门总裁) 这一类的字符.
```
bookUrl // 详情页Url(本地书源存储完整文件路径)
tocUrl // 目录页Url (toc=table of Contents)
origin // 书源URL(默认BookType.local)
originName //书源名称 or 本地书籍文件名
name // 书籍名称(书源获取)
author // 作者名称(书源获取)
kind // 分类信息(书源获取)
customTag // 分类信息(用户修改)
coverUrl // 封面Url(书源获取)
customCoverUrl // 封面Url(用户修改)
intro // 简介内容(书源获取)
customIntro // 简介内容(用户修改)
charset // 自定义字符集名称(仅适用于本地书籍)
type // 0:text 1:audio
group // 自定义分组索引号
latestChapterTitle // 最新章节标题
latestChapterTime // 最新章节标题更新时间
lastCheckTime // 最近一次更新书籍信息的时间
lastCheckCount // 最近一次发现新章节的数量
totalChapterNum // 书籍目录总数
durChapterTitle // 当前章节名称
durChapterIndex // 当前章节索引
durChapterPos // 当前阅读的进度(首行字符的索引位置)
durChapterTime // 最近一次阅读书籍的时间(打开正文的时间)
canUpdate // 刷新书架时更新书籍信息
order // 手动排序
originOrder //书源排序
variable // 自定义书籍变量信息(用于书源规则检索书籍信息)
```
### chapter对象的可用属性
> 使用方法: 在js中或{{}}中使用chapter.属性的方式即可获取.如在正文内容后加上 ##{{chapter.title+chapter.index}} 可以净化 章节标题+序号(如 第二章 天仙下凡2) 这一类的字符.
```
url // 章节地址
title // 章节标题
baseUrl //用来拼接相对url
bookUrl // 书籍地址
index // 章节序号
resourceUrl // 音频真实URL
tag //
start // 章节起始位置
end // 章节终止位置
variable //变量
```
### 字体解析使用
> 使用方法,在正文替换规则中使用,原理根据f1字体的字形数据到f2中查找字形对应的编码
```
<js>
(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;
})()
</js>
```
+19
View File
@@ -0,0 +1,19 @@
# WebDav备份教程
### 阅读支持云备份,采用WebDav协议,所有支持WebDav的云盘都可以,建议采用坚果云,每月免费1G流量,用来备份阅读足够了,下面就采用坚果云来讲解配置步骤.
1. 打开坚果云网站 https://www.jianguoyun.com/d/home#/
2. 如果没有注册过坚果云先注册一下
3. 登录坚果云
4. 右上角用户名点开点账户信息
5. 点击安全选项
6. 在第三方管理里添加应用
7. 将应用示例里的服务器地址,用户名,和密码填到阅读的WebDav设置里
8. 阅读的WebDav配置在我的-备份与恢复,创建子文件夹选项保持默认即可
9. 设置完成后手动执行一下备份,看看是否成功
10. 恢复时选择想要恢复的备份文件
### 自动备份说明
* 设置好备份之后每次退出App会自动进行备份
* WebDav同一天的备份会覆盖,不同日期的备份不会覆盖
+692
View File
@@ -0,0 +1,692 @@
# 更新日志
* 关注公众号 **[开源阅读]** 菜单•软件下载 提前享受新版本。
* 关注合作公众号 **[小说拾遗]** 获取好看的小说。
## **必读**
【温馨提醒】 *更新前一定要做好备份,以免数据丢失!*
* 阅读只是一个转码工具,不提供内容,第一次安装app,需要自己手动导入书源,可以从公众号 **[开源阅读]**、QQ群、酷安评论里获取由书友制作分享的书源。
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
**2022/01/03**
* 重新安装应用后没有权限的本地书籍会提示选择文件所在文件夹,不需要重新添加
* 更新okhttp和cronet
* 修复web阅读纪录同步问题 解决bug #1478
* 去除html中一些乱码&nbsp;&ensp;等 解决bug 页面乱码 #1465
**2022/01/01**
* 修复本地txt问题,不在拷贝到私有目录,可以正常打开
* 优化txt目录识别,取目录数量最多的规则
**2021/12/28**
* 用阅读打开本地朗读引擎文件和主体配置文件也可以导入
* 缓存图片采用多线程
* 本地书籍不在拷贝到私有目录,有权限的会直接打开,没权限的自己选择文件夹保存
**2021/12/19**
* 修复全面屏手势会触发翻页的bug
* js添加java.logType(*),打印变量类型,方便调试时查看
* 修复从发现中打开书籍是会打开其它书源书籍的bug
* 全文搜索增加跳转上一个下一个的功能 by Jason Yao
* post可以正确识别contentType
**2021/12/10**
* 朗读出错不弹出朗读界面的时候可以长按朗读按钮进入朗读界面切换朗读引擎,这个有很多人不知道
* 修复cronet访问出错时应用崩溃的bug
* 修复一些epub目录不全或内容不全的问题
* 修复横屏双页时文字选择的问题
* 电脑硬盘坏了还好资料恢复出来了,还是要经常备份比较好
**2021/11/27**
* 更新到SDK31,android 12
* 修复在线朗读引擎新建会替换之前已有的bug
* 修复目录界面自动跳转到顶部bug
* 修复阿里云在线朗读引擎模板中获取时间的兼容性问题
**2021/11/20**
* 修复部分平板双页问题
* 修复书源太多不能导出和备份的问题
* 给txt目录规则添加了一个入口,在书源管理的菜单里面
**2021/11/13**
* 修复没有目录时进入阅读界面不自动更新目录的bug
* 使用系统文件夹选择器出错时自动打开应用文件夹选择器,部分系统文件夹选择器被阉割了
**2021/11/02**
* 修复朗读错误时提示不消失的bug
* 修复滚动阅读选择文字错位bug by DuShuYuan
* 朗读语速调节添加微调按钮
**2021/10/24**
* 修复夜间模式不随系统变化的bug
**2021/10/22**
* 修复封面
* 添加全局字体大小设置
* 导入源和规则时可以先编辑再导入
**2021/10/21**
* 修复自定义封面会因为图片太大崩溃
* 修复play版本一个会引起崩溃的bug
**2021/10/17**
* 修复朗读时可能会崩溃的bug
**2021/10/16**
* 再次修复朗读卡住问题
* 导入书单改为多线程
* 修复其它一些bug
**2021/10/14**
* 修复遇到一些存标点段朗读出错后不继续的问题
* 朗读出错记录错误日志,现在很多界面的菜单里都可以打开日志
**2021/10/10**
* 阿里云语音自动登录
* 修复一些bug
* 优化阿里云登录,需重新登录
```
source登录相关方法,可在js内通过source.调用,可以参考阿里云语音登录
login()
getHeaderMap(hasLoginHeader: Boolean = false)
getLoginHeader(): String?
getLoginHeaderMap(): Map<String, String>?
putLoginHeader(header: String)
removeLoginHeader()
setVariable(variable: String?)
getVariable(): String?
AnalyzeUrl相关函数,js中通过java.调用
initUrl() //重新解析url,可以用于登录检测js登录后重新解析url重新访问
getHeaderMap().putAll(source.getHeaderMap(true)) //重新设置登录头
getStrResponse( jsStr: String? = null, sourceRegex: String? = null) //返回访问结果,文本类型,书源内部重新登录后可调用此方法重新返回结果
getResponse(): Response //返回访问结果,网络朗读引擎采用的是这个,调用登录后在调用这方法可以重新访问,参考阿里云登录检测
```
**2021/10/07**
1. 修复阅读界面长按菜单阻挡选择bug
2. 添加订阅源api
**2021/10/05**
1. 优化阅读界面导航栏
2. 规则添加代码高亮
3. web写源添加订阅源
4. httpTts朗读添加登录功能
```
返回语音之前加入了检测是否登录传入result为okhttp的Response,里面有headers和body,检测是否登录的js需返回正确的Response
```
**2021/10/02**
1. 紧急修复弹出框崩溃bug
2. 修复字体变粗后不能变回的bug
3. 修复底部对齐有时无效的bug
* 不要嫌更新得频繁,这是因为最近新加的功能比较多,出bug很正常,而且我是一个人写软件,没有测试人员,只有发出来大家一起找bug了,遇到bug及时反馈,能修复的我都会在第一时间修复
**2021/10/01**
1. 默认封面名称显示全
2. 发现js错误时可以查看错误详情
4. 修复rss标题显示url的问题
5. 长按正文网址可以选择是否外部浏览器打开,会记住选择
6. 添加书源操作按钮,编辑书源移到里面,增加网址点击区域包括书名,更容易点击
7. 优化内置浏览器
8. 其它一些优化
**2021/09/29**
1. 修复阅读界面导航栏挡住内容的bug
2. 修复webView=ture是自动跳转移动网站的bug
3. 导出添加进度条
**2021/09/28**
1. 添加横屏双页模式
**2021/09/27**
1. 非Play版本内置更新检测和下载,目前从github检测并下载, 不会自动提醒需手动检测, 可以关注公众号,比较重要的更新会在公众号发布然后可以在软件内更新
2. js添加java.webView(html: String?, url: String?, js: String?): String?
3. 修复一些bug
**2021/09/22**
1. 修复在线朗读遇到单独......崩溃的问题
2. 有人提到在线朗读能及时翻页了,本地行不行,这个是要靠本地的tts支持的,我目前用的谷歌文字转语音就是支持的,其它的我不太清楚
**2021/09/21**
1. 阅读界面区域设置添加朗读上一段和朗读下一段
2. 在线朗读采用平均速度计算及时翻页
3. 修复听书定时问题
4. 阅读小标题也使用替换
**2021/09/20**
1. 修复在线朗读跳段的bug
2. 优化默认封面,添加显示书名作者的配置, 后面会添加书名和作者大小位置配置
**2021/09/18**
1. 朗读可以选择非默认tts
2. 其它一些优化和bug修复
**2021/09/16**
1. 优化正文重复标题的去除,必须包含标题且标题后面有空格或换行才会去除,防止误删
```^(\s|\p{P}|${name})*${title}(\s|\p{P})+```
**2021/09/15**
1. 修复因标题加入替换和简繁转换导致的缩进问题
2. 如果出现标题不显示是净化规则的问题,可以先关闭净化
**2021/09/14**
1. 书架菜单添加了日志,更新失败的和下载失败的信息会显示在里面
2. 书源添加校验关键字,有校验关键字的书源用此关键字校验
3. 目录添加购买标识规则
4. 正文标题使用替换,简繁转换,正文中书名,标题开头的自动去重
5. 其它一些优化
**2021/09/08**
1. 优化离线缓存
2. 听书界面添加登录菜单,和拷贝播放url
3. 详情页添加设置源变量和书籍变量
4. 订阅添加登录菜单,添加设置源变量
**2021/09/06**
1. 采用exoPlayer播放音频,支持更多格式
2. 替换不再阻塞
3. 修复详情页初始化:规则bug
4. 书源内的并发率生效,两种格式
* 时间 格式: 如 500, 访问间隔500毫秒
* 次数/时间 格式: 如 5/60000, 每分钟最多访问5次
5. url参数添加js, 和webJs参数,js参数传入url返回新的url, webJs参数在webView内执行直到返回不为空,和正文规则webJs一样
6. 重写离线缓存
**2021/09/01**
1. 可以直接导出为链接,方便分享
2. 修复一些bug
**2021/08/28**
1. 发现界面添加登录菜单
2. 优化调试界面,预设搜索项可以点击
3. 修复再没有webDav恢复时恢复按钮没反应的bug
4. 自动阅读的设置改为选择翻页动画
**2021/08/27**
1. 修复导入书源问题
2. 合并cornet版本,添加cornet开关
3. 详情也选择分组后自动加入书架
4. 书源管理可以筛选有登录url的书源,分组需登录
5. 修复定时加快的问题
7. 修复其它一些小bug
**2021/08/24**
1. 修复bug
2. 可以加载证书过期网站的图片
3. 修复书源不兼容老版本的问题
4. 书源添加登录ui,和登录检测配置,稍后会给出示例,可以用来制作一些采用token登录的源,稍后会给出示例
5. 修复web阅读进度没有同步到webDav的问题
**2021/08/21**
1. 阅读时自动更新最新章节
2. 朗读添加媒体按键配置
3. 修复rss列表界面分类往回切换时没有数据的bug
4. 修复订阅分类往回切换时不显示内容的bug
5. 导入书源防止非json格式导入
6. 校验书源显示详细信息 by h11128
7. 其它一些优化
**2021/08/13**
1. web传书可以使用
2. 修复一些bug
**2021/08/09**
1. 修复选择文字不能选择单个文字的bug
2. 分组可选择封面
**2021/08/08**
1. 背景图片添加模糊设置
2. 书籍信息界面添加置顶操作
3. 自动翻页时屏幕常亮
4. 字典:中文使用百度汉语字典,英文使用海词字典。 by ag2s20150909
5. 导入规则时可以选择添加分组还是替换分组
**2021/08/02**
1. 换源界面功能添加:置顶,置底,删除 by h11128
2. Cronet:优化 by ag2s20150909
3. 优化自动翻页 by jiuZhouWorlds
4. 封面设置移到主题里面,白天和夜间可分别设置
**2021/08/01**
1. 为webService添加快捷操作
2. 规则内替换使用正则错误时自动切换为不使用正则
3. 优化Cronet
4. 阅读界面菜单显示的时候停止按键翻页和自动阅读
5. 切换后台停止自动阅读
**2021/07/29**
1. 修复每次更新都重新导入text规则的bug
2. RSS阅读页添加刷新按钮以应对页面内容过期失效的BUG by JiuZhouWorlds
3. 规则内替换使用正则报错时自动使用非正则替换
**2021/07/27**
1. 修复bug
2. web使用api获取封面,不会再出现没有封面的情况
3. 阅读亮度手动调节分别记住白天和夜间模式
4. legado://import/auto?src={url}, 自动识别导入类型
5. 一些优化并更新了一下web首页,感谢沚水, 传书暂时还不好用
**2021/07/22**
1. 非关键规则添加try防止报错中断解析
2. 添加获取封面的api
3. 获取正文api使用替换规则
4. 添加一个ronet版本,网络访问使用Chromium内核
5. web书架增加【最近一次更新书籍信息的时间】
6. 采用Flow替换LiveData,优化资源使用
7. 统一网络一键导入路径legado://import/{path}?src={url}
* path: bookSource,rssSource,replaceRule,textTocRule,httpTTS,theme,readConfig
* 添加了txt小说规则,在线朗读引擎,主题,排版 的一键导入支持,老url依然可用
8. 替换规则管理添加置顶所选和置底所选
**2021/07/16**
1. js扩展函数添加删除本地文件方法
2. js扩展函数对于文件的读写删操作都是相对路径,只能操作阅读缓存内的文件,/android/data/{package}/cache/...
**2021/07/15**
1. 添加js函数来修复开启js沙箱后某些书源失效。by ag2s20150909
```kotlin
/**
* 获取网络zip文件里面的数据
* @param url zip文件的链接
* @param path 所需获取文件在zip内的路径
* @return zip指定文件的数据
*/
fun getZipStringContent(url: String, path: String): String
/**
* 获取网络zip文件里面的数据
* @param url zip文件的链接
* @param path 所需获取文件在zip内的路径
* @return zip指定文件的数据
*/
fun getZipByteArrayContent(url: String, path: String): ByteArray?
```
* web服务添加一个导航页
**2021/07/11**
1. 开启JS沙箱限制
* 禁止在js里exec运行命令
* 禁止在js里通过geClass反射
* 禁止在js里创建File对象
* 禁止在js里获取Packages scope
2. 优化并修复bug
**2021/07/10**
1. 阅读界面长按菜单改回原来样式
2. 解决导入书源时重命名分组和保留名称冲突的问题
**2021/07/09**
1. 发现url添加json格式, 支持设置标签样式
* 样式属性可以搜索 [FleboxLayout子元素支持的属性介绍](https://www.jianshu.com/p/3c471953e36d)
* 样式属性可省略,有默认值
```json
[
{
"title": "xxx",
"url": "",
"style": {
"layout_flexGrow": 0,
"layout_flexShrink": 1,
"layout_alignSelf": "auto",
"layout_flexBasisPercent": -1,
"layout_wrapBefore": false
}
}
]
```
**2021/07/07**
1. 默认规则新增类似`jsonPath`的索引写法 by bushixuanqi
* 格式形如 `[index,index, ...]` 或 `[!index,index, ...]` 其中`[!`开头表示筛选方式为排除,`index`可以是单个索引,也可以是区间。
* 区间格式为 `start:end` 或 `start:end:step`,其中`start`为`0`可省略,`end`为`-1`可省略。
* 索引、区间两端、区间间隔都支持负数
* 例如 `tag.div[-1, 3:-2:-10, 2]`
* 特殊用法 `tag.div[-1:0]` 可在任意地方让列表反向
2. 允许索引作为@分段后每个部分的首规则,此时相当于前面是`children`
* `head@.1@text` 与 `head@[1]@text` 与 `head@children[1]@text` 等价
3. 添加Umd格式支持 by ag2s20150909
4. 修复web页面按键重复监听的bug
5. 亮度条往中间移了一点,防止误触
6. 添加内置字典
**2021/06/29**
* 修复html格式化bug
* 订阅界面webView支持css prefers-color-scheme: dark 查询,需webView v76或更高版本
* 如webView低于v76可以用js调用activity.isNightTheme()来获取当前是否暗模式
* 修复一些书籍导出epub失败 by ag2s20150909
**2021/06/22**
* 修复隐藏未读设置不生效的bug
* 修复系统字体大小选择大时导入界面按钮显示不全的bug
* 修复听书从后台打开时不对的bug
**2021/06/20**
* viewPager2 改回 viewPager
* 添加配置导入文件规则功能 by bushixuanqi
* 文件夹分组样式优化(未完成)
* epub支持外部模板
* 修复一些bug
**2021/06/06**
* 添加自定义导出文件名
* 添加书架文件夹分组样式,未完成
* 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/24**
* 反转目录后刷新内容
* 修复上下滑动会导致左右切换问题
* 精确搜索增加包含关键词的,比如搜索五行 五行天也显示出来, 五天行不显示
**2021/05/21**
* 添加反转目录功能
* 修复分享bug
* 详情页添加登录菜单
* 添加发现界面隐藏配置
**2021/05/16**
* 添加总是使用默认封面配置
* 添加一种语言 ptbr translation by mezysinc
* epublib 修bug by ag2s20150909
**2021/05/08**
* 预下载章节可调整数目
* 修复低版本Android使用TTS闪退。 by ag2s20150909
* 修复WebDav报错
* 优化翻页动画点击翻页
**2021/05/06**
* 修复bug
* url参数添加重置次数,retry
* 修改默认tts, 手动导入
* 升级android studio
**2021/04/30**
* epub插图,epublib优化,图片解码优化,epub读取导出优化。by ag2s20150909
* 添加高刷设置
* 其它一些优化
* pro版本被play商店下架了,先把pro设置图片背景的功能开放到所有版本,使用pro版本的可以使用备份恢复功能切换最新版本
**2021/04/16**
* 去掉google统计,解决华为手机使用崩溃的bug
* 添加规则订阅时判断重复提醒
* 添加恢复预设布局的功能, 添加一个微信读书布局作为预设布局
**2021/04/08**
* 缓存时重新检查并缓存图片
* 订阅源调试添加源码查看
* web调试不输出源码
* 修复bug
* 换源优化 --- by ag2s20150909
* 修复localBook获取书名作者名的逻辑
* 修复导出的epub的标题文字过大的bug
* 优化图片排版
**2021/04/02**
* 修复bug
* 书源调试添加源码查看
* 添加导出epub by ag2s20150909
* 换源添加是否校验作者选项
**2021/03/31**
* 优化epubLib by ag2s20150909
* 升级库,修改弃用方法
* tts引擎添加导入导出功能
**2021/03/23**
* 修复繁简转换“勐”“十”问题。使用了剥离HanLP简繁代码的民间库。APK减少6M左右
* js添加一个并发访问的方法 java.ajaxAll(urlList: Array<String>) 返回 Array<StrResponse?>
* 优化目录并发访问
* 添加自定义epublib,支持epub v3解析目录。by ag2s20150909
**2021/03/19**
* 修复图片地址参数缺少的bug
* 修复更改替换规则时多次重新加载正文导致朗读多次停顿的bug
* 修复是否使用替换默认值修改后不及时生效的bug
* 修复繁简转换“勐”“十”问题。使用了剥离HanLP简繁代码的民间库。APK减少6M左右 by hoodie13
* 百度tsn改为tts
**2021/03/15**
* 优化图片TEXT样式显示
* 图片url在解析正文时就拼接成绝对url
* 修复一些bug
**2021/03/08**
* 阅读页面停留10分钟之后自动备份进度
* 添加了针对中文的断行排版处理-by hoodie13, 需要再阅读界面设置里手动开启
* 添加朗读快捷方式
* 优化Epub解析 by hoodie13
* epub书籍增加cache by hoodie13
* 修复切换书籍或者章节时的断言崩溃问题。看漫画容易复现。 by hoodie13
* 修正增加书签alert的正文内容较多时,确定键溢出屏幕问题 by hoodie13
* 图片样式添加TEXT, 阅读界面菜单里可以选择图片样式
**2021/02/26**
* 添加反转内容功能
* 更新章节时若无目录url将自动加载详情页
* 添加变量nextChapterUrl
* 订阅跳转外部应用时提示
* 修复恢复bug
* 详情页拼接url改为重定向后的地址
* 不重复解析详情页
**2021/02/21**
* 下一页规则改为在内容规则之后执行
* 书籍导出增加编码设置和导出文件夹设置,使用替换设置
* 导入源添加等待框
* 修复一些崩溃bug
**2021/02/16**
* 修复分享内容不对的bug
* 优化主题颜色,添加透明度
* rss分类url支持js
* 打开阅读时同步阅读进度
**2021/02/09**
* 修复分组内书籍数目少于搜索线程数目,会导致搜索线程数目变低
* 修复保存书源时不更新书源时间的bug
* 订阅添加夜间模式,需启用js,还不是很完善
* 优化源导入界面
**2021/01/18**
* 增加三星 S Pen 支持 by [dacer](https://github.com/dacer)
* 订阅添加阅读下载,可以从多个渠道下载
* 修复一些BUG
**2020/12/30**
* 解决文件下载异常,在线语音可正常播放 by [Celeter](https://github.com/Celeter)
* 更新默认在线朗读库, 默认id小于0方便下次更新时删除旧数据, 有重复的自己删除
* 导入导出书单
* 其它一些优化
**2020/12/27**
* 订阅添加搜索和分组
* 修复部分手机状态栏bug
* 单url订阅支持内容规则和样式
**2020/12/09**
* 修复bug
* 优化中文排序
* 优化编码识别
* 选择文字时优先选词
* 优化进度同步,进入书籍时同步,每次同步单本书,减少同步文件大小
**2020/11/18**
* 优化导航栏
* js添加java.log(msg: String)用于调试时输出消息
* js添加cookie变量,方法见io.legado.app.help.http.api.CookieManager
* js添加cache变量,可以用来存储token之类的临时值,可以设置保存时间,方法见io.legado.app.help.CacheManager
* 需要token的网站可以用js来写了,比如阿里tts
**2020/11/15**
* 正文规则添加字体规则,返回ByteArray
* js添加方法:
```
base64DecodeToByteArray(str: String?): ByteArray?
base64DecodeToByteArray(str: String?, flags: Int): ByteArray?
```
**2020/11/07**
* 详情页菜单添加拷贝URL
* 解决一些书名太长缓存报错的bug
* 添加备份搜索记录
* 替换编辑界面添加正则学习教程
* 去除解析目录时拼接相对url,提升解析速度
* 自动分段优化 by [tumuyan](https://github.com/tumuyan)
* web支持图片显示 by [六月](https://github.com/Celeter)
**2020/10/24**
* 修复选择错误的bug
* 修复长图最后一张不能滚动的bug
* js添加java.getCookie(sourceUrl:String, key:String? = null)来获取登录后的cookie
by [AndyBernie](https://github.com/AndyBernie)
```
java.getCookie("http://baidu.com", null) => userid=1234;pwd=adbcd
java.getCookie("http://baidu.com", "userid") => 1234
```
* 修复简繁转换没有处理标题
* 每本书可以单独设置翻页动画,在菜单里
* 添加重新分段功能,针对每本书,在菜单里,分段代码来自[tumuyan](https://github.com/tumuyan)
**2020/10/07**
* 更新时预下载10章
* 支持更多分组
* 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'"}
```
**2020/09/29**
* 增加了几个方法用于处理文件 by [Celeter](https://github.com/Celeter)
```
//文件下载,content为十六进制字符串,url用于生成文件名,返回文件路径
downloadFile(content: String, url: String): String
//文件解压,zipPath为压缩文件路径,返回解压路径
unzipFile(zipPath: String): String
//文件夹内所有文件读取
getTxtInFolder(unzipPath: String): String
```
* 增加type字段,返回16进制字符串,例:`https://www.baidu.com,{"type":"zip"}`
* 底部操作栏阴影跟随设置调节
+5
View File
@@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/web.iml" filepath="$PROJECT_DIR$/.idea/web.iml" />
</modules>
</component>
</project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../../.." vcs="Git" />
</component>
</project>
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+256
View File
@@ -0,0 +1,256 @@
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
/*
* Perform a simple self-test to see if the VM is working
*/
function md5_vm_test()
{
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length
*/
function core_md5(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t)
{
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Calculate the HMAC-MD5, of a key and some data
*/
function core_hmac_md5(key, data)
{
var bkey = str2binl(key);
if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
return core_md5(opad.concat(hash), 512 + 128);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert a string to an array of little-endian words
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
*/
function str2binl(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
return bin;
}
/*
* Convert an array of little-endian words to a string
*/
function binl2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
return str;
}
/*
* Convert an array of little-endian words to a hex string.
*/
function binl2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of little-endian words to a base-64 string
*/
function binl2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
@@ -0,0 +1,150 @@
body {
margin: 0;
}
.editor {
display: flex;
align-items: stretch;
}
.setbox,
.menu,
.outbox {
flex: 1;
display: flex;
flex-flow: column;
max-height: 100vh;
overflow-y: auto;
}
.menu {
justify-content: center;
max-width: 90px;
margin: 0 5px;
}
.menu .button {
width: 90px;
height: 30px;
min-height: 30px;
margin: 5px 0px;
cursor: pointer;
}
@keyframes stroker {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -240;
}
}
.button rect {
width: 100%;
height: 100%;
fill: transparent;
stroke: #666;
stroke-width: 2px;
}
.button rect.busy {
stroke: #fd1850;
stroke-dasharray: 30 90;
animation: stroker 1s linear infinite;
}
.button text {
text-anchor: middle;
dominant-baseline: middle;
}
.setbox {
min-width: 40em;
}
.rules {
overflow: auto;
}
.tabbox {
flex: 1;
display: flex;
flex-flow: column;
}
.rules > * {
display: flex;
margin: 2px 0;
}
.rules textarea {
flex: 1;
margin-left: 5px;
}
.rules > *,
.rules > * > div,
.rules textarea {
min-height: 1em;
}
textarea {
word-break: break-all;
}
.tabtitle {
display: flex;
z-index: 1;
justify-content: flex-end;
}
.tabtitle > div {
cursor: pointer;
padding: 1px 10px 0 10px;
border-bottom: 3px solid transparent;
font-weight: bold;
}
.tabtitle > .this {
color: #4f9da6;
border-bottom-color: #4ebbe4;
}
.tabbody {
flex: 1;
display: flex;
margin-top: -1px;
border: 1px solid #a9a9a9;
height: 0;
}
.tabbody > * {
flex: 1;
flex-flow: column;
display: none;
}
.tabbody > .this {
display: flex;
}
.tabbody > * > .titlebar {
display: flex;
}
.tabbody > * > .titlebar > * {
flex: 1;
margin: 1px 1px 1px 1px;
}
.tabbody > * > .context {
flex: 1;
flex-flow: column;
border: 0;
padding: 5px;
overflow-y: auto;
}
.tabbody > * > .inputbox {
border: 0;
border-bottom: #a9a9a9 solid 1px;
height: 15px;
text-align: center;
}
.link > * {
display: flex;
margin: 5px;
border-bottom: 1px solid;
text-decoration: none;
}
#RuleList > label > * {
background: #eee;
padding-left: 3px;
margin: 2px 0;
cursor: pointer;
}
#RuleList input[type="radio"] {
display: none;
}
#RuleList input[type="radio"]:checked + * {
background: #15cda8;
}
.isError {
color: #ff0000;
}
@@ -0,0 +1,428 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>阅读3.0源编辑器_V4.0</title>
<link rel="icon" href="favicon.ico">
<link rel="stylesheet" type="text/css" href="index.css"/>
</head>
<body>
<div class="editor">
<div class="setbox">
<div>
<a href="../index.html">←主页</a>
<b>书源</b>
</div>
<div class="rules">
<div><b>基本</b></div>
<div>
<div>源域名 :</div>
<textarea rows="1" id="bookSourceUrl" class="base" title="bookSourceUrl"
placeholder="<必填>通常填写网站主页,例: https://www.qidian.com"></textarea>
</div>
<div>
<div>源类型 :</div>
<textarea rows="1" id="bookSourceType" class="base" title="bookSourceType"
placeholder="&lt;必填&gt;0:文本 1:音频"></textarea>
</div>
<div>
<div>源名称 :</div>
<textarea rows="1" id="bookSourceName" class="base" title="bookSourceName"
placeholder="&lt;必填&gt;会显示在源列表"></textarea>
</div>
<div>
<div>源分组 :</div>
<textarea rows="1" id="bookSourceGroup" class="base" title="bookSourceGroup"
placeholder="&lt;选填&gt;描述源的特征信息"></textarea>
</div>
<div>
<div>源注释 :</div>
<textarea rows="1" id="bookSourceComment" class="base" title="bookSourceComment"
placeholder="&lt;选填&gt;描述源作者和状态"></textarea>
</div>
<div>
<div>登录地址:</div>
<textarea rows="1" id="loginUrl" class="base" title="loginUrl"
placeholder="&lt;选填&gt;填写网站登录网址,仅在需要登录的源有用"></textarea>
</div>
<div>
<div>登录界面:</div>
<textarea rows="3" id="loginUi" class="base" title="loginUi"
placeholder="&lt;选填&gt;自定义登录界面"></textarea>
</div>
<div>
<div>登录检测:</div>
<textarea rows="3" id="loginCheckJs" class="base" title="loginCheckJs"
placeholder="&lt;选填&gt;登录检测js"></textarea>
</div>
<div>
<div>并发率 :</div>
<textarea rows="1" id="concurrentRate" class="base" title="concurrentRate"
placeholder="&lt;选填&gt;并发率"></textarea>
</div>
<div>
<div>请求头 :</div>
<textarea rows="3" id="header" class="base" title="header"
placeholder="&lt;选填&gt;客户端标识"></textarea>
</div>
<div>
<div>链接验证:</div>
<textarea rows="1" id="bookUrlPattern" class="base" title="bookUrlPattern"
placeholder="&lt;选填&gt;当详情页URL与源URL的域名不一致时有效,用于添加网址"></textarea>
</div>
<p></p>
<div><b>搜索</b></div>
<div>
<div>搜索地址:</div>
<textarea rows="1" id="searchUrl" class="base" title="searchUrl"
placeholder="[域名可省略]/search.php@kw={{key}}"></textarea>
</div>
<div>
<div>校验文字:</div>
<textarea rows="1" id="ruleSearch_checkKeyWord" class="ruleSearch"
title="checkKeyWord"
placeholder="校验关键字"></textarea>
</div>
<div>
<div>列表规则:</div>
<textarea rows="1" id="ruleSearch_bookList" class="ruleSearch" title="bookList"
placeholder="选择书籍节点 (规则结果为List&lt;Element&gt;)"></textarea>
</div>
<div>
<div>书名规则:</div>
<textarea rows="1" id="ruleSearch_name" class="ruleSearch" title="name"
placeholder="选择节点书名 (规则结果为String)"></textarea>
</div>
<div>
<div>作者规则:</div>
<textarea rows="1" id="ruleSearch_author" class="ruleSearch" title="author"
placeholder="选择节点作者 (规则结果为String)"></textarea>
</div>
<div>
<div>分类规则:</div>
<textarea rows="1" id="ruleSearch_kind" class="ruleSearch" title="kind"
placeholder="选择节点分类信息 (规则结果为String)"></textarea>
</div>
<div>
<div>字数规则:</div>
<textarea rows="1" id="ruleSearch_wordCount" class="ruleSearch" title="wordCount"
placeholder="选择节点字数信息 (规则结果为String)"></textarea>
</div>
<div>
<div>最新章节:</div>
<textarea rows="1" id="ruleSearch_lastChapter" class="ruleSearch"
title="lastChapter"
placeholder="选择节点最新章节 (规则结果为String)"></textarea>
</div>
<div>
<div>简介规则:</div>
<textarea rows="1" id="ruleSearch_intro" class="ruleSearch" title="intro"
placeholder="选择节点书籍简介 (规则结果为String)"></textarea>
</div>
<div>
<div>封面规则:</div>
<textarea rows="1" id="ruleSearch_coverUrl" class="ruleSearch" title="coverUrl"
placeholder="选择节点书籍封面 (规则结果为String类型的url)"></textarea>
</div>
<div>
<div>详情地址:</div>
<textarea rows="1" id="ruleSearch_bookUrl" class="ruleSearch" title="bookUrl"
placeholder="选择书籍详情页网址 (规则结果为String类型的url)"></textarea>
</div>
<p></p>
<div><b>发现</b></div>
<div>
<div>发现地址:</div>
<textarea rows="6" id="exploreUrl" class="base" title="exploreUrl"
placeholder="内容能显示在发现菜单&#10;每行一条发现分类(网址域名可省略),例:&#10;名称1::网址(Url)1&#10;名称2::网址(Url)2&#10;..."></textarea>
</div>
<div>
<div>列表规则:</div>
<textarea rows="1" id="ruleExplore_bookList" class="ruleExplore" title="bookList"
placeholder="选择书籍节点 (规则结果为List&lt;Element&gt;)"></textarea>
</div>
<div>
<div>书名规则:</div>
<textarea rows="1" id="ruleExplore_name" class="ruleExplore" title="name"
placeholder="选择节点书名 (规则结果为String)"></textarea>
</div>
<div>
<div>作者规则:</div>
<textarea rows="1" id="ruleExplore_author" class="ruleExplore" title="author"
placeholder="选择节点作者 (规则结果为String)"></textarea>
</div>
<div>
<div>分类规则:</div>
<textarea rows="1" id="ruleExplore_kind" class="ruleExplore" title="kind"
placeholder="选择节点分类信息 (规则结果为String)"></textarea>
</div>
<div>
<div>字数规则:</div>
<textarea rows="1" id="ruleExplore_wordCount" class="ruleExplore" title="wordCount"
placeholder="选择节点字数信息 (规则结果为String)"></textarea>
</div>
<div>
<div>最新章节:</div>
<textarea rows="1" id="ruleExplore_lastChapter" class="ruleExplore"
title="lastChapter"
placeholder="选择节点最新章节 (规则结果为String)"></textarea>
</div>
<div>
<div>简介规则:</div>
<textarea rows="1" id="ruleExplore_intro" class="ruleExplore" title="intro"
placeholder="选择节点书籍简介 (规则结果为String)"></textarea>
</div>
<div>
<div>封面规则:</div>
<textarea rows="1" id="ruleExplore_coverUrl" class="ruleExplore" title="coverUrl"
placeholder="选择节点书籍封面 (规则结果为String类型的url)"></textarea>
</div>
<div>
<div>详情地址:</div>
<textarea rows="1" id="ruleExplore_bookUrl" class="ruleExplore" title="bookUrl"
placeholder="选择书籍详情页网址 (规则结果为String类型的url)"></textarea>
</div>
<p></p>
<div><b>详情</b></div>
<div>
<div>预处理 :</div>
<textarea rows="3" id="ruleBookInfo_init" class="ruleBookInfo" title="init"
placeholder="用于加速详情信息检索,只支持AllInOne规则"></textarea>
</div>
<div>
<div>书名规则:</div>
<textarea rows="1" id="ruleBookInfo_name" class="ruleBookInfo" title="name"
placeholder="选择节点书名 (规则结果为String)"></textarea>
</div>
<div>
<div>作者规则:</div>
<textarea rows="1" id="ruleBookInfo_author" class="ruleBookInfo" title="author"
placeholder="选择节点作者 (规则结果为String)"></textarea>
</div>
<div>
<div>分类规则:</div>
<textarea rows="1" id="ruleBookInfo_kind" class="ruleBookInfo" title="kind"
placeholder="选择节点分类信息 (规则结果为String)"></textarea>
</div>
<div>
<div>字数规则:</div>
<textarea rows="1" id="ruleBookInfo_wordCount" class="ruleBookInfo"
title="wordCount"
placeholder="选择节点字数信息 (规则结果为String)"></textarea>
</div>
<div>
<div>最新章节:</div>
<textarea rows="1" id="ruleBookInfo_lastChapter" class="ruleBookInfo"
title="lastChapter"
placeholder="选择节点最新章节 (规则结果为String)"></textarea>
</div>
<div>
<div>简介规则:</div>
<textarea rows="1" id="ruleBookInfo_intro" class="ruleBookInfo" title="intro"
placeholder="选择节点书籍简介 (规则结果为String)"></textarea>
</div>
<div>
<div>封面规则:</div>
<textarea rows="1" id="ruleBookInfo_coverUrl" class="ruleBookInfo" title="coverUrl"
placeholder="选择节点书籍封面 (规则结果为String类型的url)"></textarea>
</div>
<div>
<div>目录地址:</div>
<textarea rows="1" id="ruleBookInfo_tocUrl" class="ruleBookInfo" title="tocUrl"
placeholder="选择书籍详情页网址 (规则结果为String类型的url, 与详情页相同时可省略)"></textarea>
</div>
<p></p>
<div><b>目录</b></div>
<div>
<div>列表规则:</div>
<textarea rows="3" id="ruleToc_chapterList" class="ruleToc" title="chapterList"
placeholder="选择目录列表的章节节点 (规则结果为List&lt;Element&gt;)"></textarea>
</div>
<div>
<div>章节名称:</div>
<textarea rows="1" id="ruleToc_chapterName" class="ruleToc" title="chapterName"
placeholder="选择章节名称 (规则结果为String)"></textarea>
</div>
<div>
<div>章节地址:</div>
<textarea rows="1" id="ruleToc_chapterUrl" class="ruleToc" title="chapterUrl"
placeholder="选择章节链接 (规则结果为String类型的Url)"></textarea>
</div>
<div>
<div>收费标识:</div>
<textarea rows="1" id="ruleToc_isVip" class="ruleToc" title="isVip"
placeholder="章节是否为VIP章节 (规则结果为Bool)"></textarea>
</div>
<div>
<div>购买标识:</div>
<textarea rows="1" id="ruleToc_isPay" class="ruleToc" title="isPay"
placeholder="章节是否为已购买 (规则结果为Bool)"></textarea>
</div>
<div>
<div>章节信息:</div>
<textarea rows="1" id="ruleToc_updateTime" class="ruleToc" title="updateTime"
placeholder="选择章节信息 (规则结果为String)"></textarea>
</div>
<div>
<div>翻页规则:</div>
<textarea rows="1" id="ruleToc_nextTocUrl" class="ruleToc" title="nextTocUrl"
placeholder="选择目录下一页链接 (规则结果为List&lt;String&gt;或String)"></textarea>
</div>
<p></p>
<div><b>正文</b></div>
<div>
<div>脚本注入:</div>
<textarea rows="3" id="ruleContent_webJs" class="ruleContent" title="webJs"
placeholder="注入javascript,用于模拟鼠标点击等,必须有返回值,一般为String类型"></textarea>
</div>
<div>
<div>正文规则:</div>
<textarea rows="1" id="ruleContent_content" class="ruleContent" title="content"
placeholder="选择正文内容 (规则结果为String)"></textarea>
</div>
<div>
<div>翻页规则:</div>
<textarea rows="1" id="ruleContent_nextContentUrl" class="ruleContent"
title="nextContentUrl"
placeholder="选择下一分页(不是下一章)链接 (规则结果为String类型的Url)"></textarea>
</div>
<div>
<div>资源正则:</div>
<textarea rows="1" id="ruleContent_sourceRegex" class="ruleContent"
title="sourceRegex"
placeholder="匹配资源的url特征,用于嗅探"></textarea>
</div>
<div>
<div>替换规则:</div>
<textarea rows="1" id="ruleContent_replaceRegex" class="ruleContent"
title="replaceRegex"
placeholder="多页内容合并后替换,用于正文净化"></textarea>
</div>
<div>
<div>图片样式:</div>
<textarea rows="1" id="ruleContent_imageStyle" class="ruleContent"
title="imageStyle"
placeholder="FULL:铺满 不填:默认样式"></textarea>
</div>
<p></p>
<div><b>其它规则</b></div>
<div>
<div>启用搜索:</div>
<textarea rows="1" id="enabled" class="base" title="enabled"
placeholder="启用: true 关闭: false (可选,默认true)"></textarea>
</div>
<div>
<div>启用发现:</div>
<textarea rows="1" id="enabledExplore" class="base" title="enabledExplore"
placeholder="启用: true 关闭: false (可选,默认true)"></textarea>
</div>
<div>
<div>搜索权重:</div>
<textarea rows="1" id="weight" class="base" title="weight"
placeholder="整数: 0~N (可选,默认0) | 数字越大越靠前"></textarea>
</div>
<div>
<div>排序编号:</div>
<textarea rows="1" id="customOrder" class="base" title="customOrder"
placeholder="整数: 0~N (可选,默认0) | 数字越小越靠前"></textarea>
</div>
<div style="display:none;">
<div>更新时间:</div>
<textarea rows="1" id="lastUpdateTime" class="base" title="lastUpdateTime"
placeholder="毫秒级时间戳 (自动生成) | 请勿手动填写"></textarea>
</div>
</div>
</div>
<div class="menu">
<svg class="button">
<text x="50%" y="55%">⇈推送源</text>
<rect id="push"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">⇊拉取源</text>
<rect id="pull"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">⋘编辑源</text>
<rect id="editor"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">⋙生成源</text>
<rect id="conver"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">✗清空表单</text>
<rect id="initial"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">↶撤销操作</text>
<rect id="undo"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">↷重做操作</text>
<rect id="redo"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">⇏调试源</text>
<rect id="debug"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">✓保存源</text>
<rect id="accept"></rect>
</svg>
</div>
<div class="outbox">
<div class="tabbox">
<div class="tabtitle">
<div name="编辑源" class="tab1 this">编辑源</div>
<div name="调试源" class="tab2">调试源</div>
<div name="源列表" class="tab3">源列表</div>
<div name="帮助信息" class="tab4">帮助信息</div>
</div>
<div class="tabbody">
<div class="tab1 this">
<textarea class="context" id="RuleJsonString"
placeholder="这里输出序列化的JSON数据,可直接导入'阅读'APP"></textarea>
</div>
<div class="tab2">
<input type="text" class="inputbox" id="DebugKey" placeholder="输入搜索关键字,默认搜「我的」">
<textarea class="context" id="DebugConsole" placeholder="这里用于输出调试信息"></textarea>
</div>
<div class="tab3">
<input type="text" class="inputbox" id="Filter"
placeholder="输入筛选关键词(源名称、源URL或源分组)后按回车筛选源">
<div class="titlebar">
<button id="Import">导入源文件</button>
<button id="Export">导出源文件</button>
<button id="Delete">删除选中源</button>
<button id="ClrAll">清空列表</button>
</div>
<div class="context" id="RuleList"></div>
</div>
<div class="tab4">
<div class="context link">
<a target="_blank" href="https://alanskycn.gitee.io/teachme">源制作教程</a>
<a target="_blank"
href="https://zhuanlan.zhihu.com/p/29436838">Xpath基础教程</a>
<a target="_blank"
href="https://zhuanlan.zhihu.com/p/32187820">Xpath高级教程</a>
<a target="_blank" href="https://www.w3cschool.cn/regex_rmjc">正则表达式教程</a>
<a target="_blank" href="https://regexr.com">正则表达式在线验证工具</a>
<div>^$()[]{}.?+*| 这些是Java正则特殊符号,匹配需转义
<br>(?s) 前缀表示跨行解析
<br>(?m) 前缀表示逐行匹配
<br>(?i) 前缀表示忽略大小写
</div>
<a target="_blank" href="https://www.beta.browxy.com">代码在线运行工具</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
+516
View File
@@ -0,0 +1,516 @@
// 简化js原生选择器
function $(selector) { return document.querySelector(selector); }
function $$(selector) { return document.querySelectorAll(selector); }
// 读写Hash值(val未赋值时为读取)
function hashParam(key, val) {
let hashstr = decodeURIComponent(window.location.hash);
let regKey = new RegExp(`${key}=([^&]*)`);
let getVal = regKey.test(hashstr) ? hashstr.match(regKey)[1] : null;
if (val == undefined) return getVal;
if (hashstr == '' || hashstr == '#') {
window.location.hash = `#${key}=${val}`;
}
else {
if (getVal) window.location.hash = hashstr.replace(getVal, val);
else {
window.location.hash = hashstr.indexOf(key) > -1 ? hashstr.replace(regKey, `${key}=${val}`) : `${hashstr}&${key}=${val}`;
}
}
}
// 创建源规则容器对象
function Container() {
let ruleJson = {};
let searchJson = {};
let exploreJson = {};
let bookInfoJson = {};
let tocJson = {};
let contentJson = {};
// 基本以及其他
$$('.rules .base').forEach(item => ruleJson[item.title] = '');
ruleJson.lastUpdateTime = 0;
ruleJson.customOrder = 0;
ruleJson.weight = 0;
ruleJson.enabled = true;
ruleJson.enabledExplore = true;
// 搜索规则
$$('.rules .ruleSearch').forEach(item => searchJson[item.title] = '');
ruleJson.ruleSearch = searchJson;
// 发现规则
$$('.rules .ruleExplore').forEach(item => exploreJson[item.title] = '');
ruleJson.ruleExplore = exploreJson;
// 详情页规则
$$('.rules .ruleBookInfo').forEach(item => bookInfoJson[item.title] = '');
ruleJson.ruleBookInfo = bookInfoJson;
// 目录规则
$$('.rules .ruleToc').forEach(item => tocJson[item.title] = '');
ruleJson.ruleToc = tocJson;
// 正文规则
$$('.rules .ruleContent').forEach(item => contentJson[item.title] = '');
ruleJson.ruleContent = contentJson;
return ruleJson;
}
// 选项卡Tab切换事件处理
function showTab(tabName) {
$$('.tabtitle>*').forEach(node => { node.className = node.className.replace(' this', ''); });
$$('.tabbody>*').forEach(node => { node.className = node.className.replace(' this', ''); });
$(`.tabbody>.${$(`.tabtitle>*[name=${tabName}]`).className}`).className += ' this';
$(`.tabtitle>*[name=${tabName}]`).className += ' this';
hashParam('tab', tabName);
}
// 源列表列表标签构造函数
function newRule(rule) {
return `<label for="${rule.bookSourceUrl}"><input type="radio" name="rule" id="${rule.bookSourceUrl}"><div>${rule.bookSourceName}<br>${rule.bookSourceUrl}</div></label>`;
}
// 缓存规则列表
var RuleSources = [];
if (localStorage.getItem('BookSources')) {
RuleSources = JSON.parse(localStorage.getItem('BookSources'));
RuleSources.forEach(item => $('#RuleList').innerHTML += newRule(item));
}
// 页面加载完成事件
window.onload = () => {
$$('.tabtitle>*').forEach(item => {
item.addEventListener('click', () => {
showTab(item.innerHTML);
});
});
if (hashParam('tab')) showTab(hashParam('tab'));
}
// 获取数据
function HttpGet(url) {
return fetch(hashParam('domain') ? hashParam('domain') + url : url)
.then(res => res.json()).catch(err => console.error('Error:', err));
}
// 提交数据
function HttpPost(url, data) {
return fetch(hashParam('domain') ? hashParam('domain') + url : url, {
body: JSON.stringify(data),
method: 'POST',
mode: "cors",
headers: new Headers({
'Content-Type': 'application/json;charset=utf-8'
})
}).then(res => res.json()).catch(err => console.error('Error:', err));
}
// 将源表单转化为源对象
function rule2json() {
let RuleJSON = Container();
// 转换base
Object.keys(RuleJSON).forEach(key => {
if (!key.startsWith("rule")) {
RuleJSON[key] = $('#' + key).value;
}
});
// 转换搜索规则
let searchJson = {};
Object.keys(RuleJSON.ruleSearch).forEach(key => {
if ($('#' + 'ruleSearch_' + key).value)
searchJson[key] = $('#' + 'ruleSearch_' + key).value;
});
RuleJSON.ruleSearch = searchJson;
// 转换发现规则
let exploreJson = {};
Object.keys(RuleJSON.ruleExplore).forEach(key => {
if ($('#' + 'ruleExplore_' + key).value)
exploreJson[key] = $('#' + 'ruleExplore_' + key).value;
});
RuleJSON.ruleExplore = exploreJson;
// 转换详情页规则
let bookInfoJson = {};
Object.keys(RuleJSON.ruleBookInfo).forEach(key => {
if ($('#' + 'ruleBookInfo_' + key).value)
bookInfoJson[key] = $('#' + 'ruleBookInfo_' + key).value;
});
RuleJSON.ruleBookInfo = bookInfoJson;
// 转换目录规则
let tocJson = {};
Object.keys(RuleJSON.ruleToc).forEach(key => {
if ($('#' + 'ruleToc_' + key).value)
tocJson[key] = $('#' + 'ruleToc_' + key).value;
});
RuleJSON.ruleToc = tocJson;
// 转换正文规则
let contentJson = {};
Object.keys(RuleJSON.ruleContent).forEach(key => {
if ($('#' + 'ruleContent_' + key).value)
contentJson[key] = $('#' + 'ruleContent_' + key).value;
});
RuleJSON.ruleContent = contentJson;
RuleJSON.lastUpdateTime = new Date().getTime();
RuleJSON.customOrder = RuleJSON.customOrder == '' ? 0 : parseInt(RuleJSON.customOrder);
RuleJSON.weight = RuleJSON.weight == '' ? 0 : parseInt(RuleJSON.weight);
RuleJSON.bookSourceType == RuleJSON.bookSourceType == '' ? 0 : parseInt(RuleJSON.bookSourceType);
RuleJSON.enabled = RuleJSON.enabled == '' || String(RuleJSON.enabled).toLocaleLowerCase().replace(/^\s*|\s*$/g, '') == 'true';
RuleJSON.enabledExplore = RuleJSON.enabledExplore == '' || String(RuleJSON.enabledExplore).toLocaleLowerCase().replace(/^\s*|\s*$/g, '') == 'true';
return RuleJSON;
}
// 将源对象填充到源表单
function json2rule(RuleEditor) {
let RuleJSON = Container();
// 转换base
Object.keys(RuleJSON).forEach(key => {
if (!key.startsWith("rule")) {
let val = RuleEditor[key];
if (typeof val == "number") {
$("#" + key).value = val ? String(val) : '0';
}
else if (typeof val == "boolean") {
$("#" + key).value = val ? String(val) : 'false';
}
else {
$("#" + key).value = val ? String(val) : '';
}
}
});
// 转换搜索规则
if (RuleEditor.ruleSearch) {
let searchJson = RuleEditor.ruleSearch;
Object.keys(RuleJSON.ruleSearch).forEach(key => {
$('#' + 'ruleSearch_' + key).value = searchJson[key] ? searchJson[key] : '';
});
}
// 转换发现规则
if (RuleEditor.ruleExplore) {
let exploreJson = RuleEditor.ruleExplore;
Object.keys(RuleJSON.ruleExplore).forEach(key => {
$('#' + 'ruleExplore_' + key).value = exploreJson[key] ? exploreJson[key] : '';
});
}
// 转换详情页规则
if (RuleEditor.ruleBookInfo) {
let bookInfoJson = RuleEditor.ruleBookInfo;
Object.keys(RuleJSON.ruleBookInfo).forEach(key => {
$('#' + 'ruleBookInfo_' + key).value = bookInfoJson[key] ? bookInfoJson[key] : '';
});
}
// 转换目录规则
if (RuleEditor.ruleToc) {
let tocJson = RuleEditor.ruleToc;
Object.keys(RuleJSON.ruleToc).forEach(key => {
$('#' + 'ruleToc_' + key).value = tocJson[key] ? tocJson[key] : '';
});
}
// 转换正文规则
if (RuleEditor.ruleContent) {
let contentJson = RuleEditor.ruleContent;
Object.keys(RuleJSON.ruleContent).forEach(key => {
$('#' + 'ruleContent_' + key).value = contentJson[key] ? contentJson[key] : '';
});
}
}
// 记录操作过程
var course = { "old": [], "now": {}, "new": [] };
if (localStorage.getItem('bookSourceCourse')) {
course = JSON.parse(localStorage.getItem('bookSourceCourse'));
json2rule(course.now);
}
else {
course.now = rule2json();
window.localStorage.setItem('bookSourceCourse', JSON.stringify(course));
}
function todo() {
course.old.push(Object.assign({}, course.now));
course.now = rule2json();
course.new = [];
if (course.old.length > 50) course.old.shift(); // 限制历史记录堆栈大小
localStorage.setItem('bookSourceCourse', JSON.stringify(course));
}
function undo() {
course = JSON.parse(localStorage.getItem('bookSourceCourse'));
if (course.old.length > 0) {
course.new.push(course.now);
course.now = course.old.pop();
localStorage.setItem('bookSourceCourse', JSON.stringify(course));
json2rule(course.now);
}
}
function redo() {
course = JSON.parse(localStorage.getItem('bookSourceCourse'));
if (course.new.length > 0) {
course.old.push(course.now);
course.now = course.new.pop();
localStorage.setItem('bookSourceCourse', JSON.stringify(course));
json2rule(course.now);
}
}
function setRule(editRule) {
let checkRule = RuleSources.find(x => x.bookSourceUrl == editRule.bookSourceUrl);
if ($(`input[id="${editRule.bookSourceUrl}"]`)) {
Object.keys(checkRule).forEach(key => { checkRule[key] = editRule[key]; });
$(`input[id="${editRule.bookSourceUrl}"]+*`).innerHTML = `${editRule.bookSourceName}<br>${editRule.bookSourceUrl}`;
} else {
RuleSources.push(editRule);
$('#RuleList').innerHTML += newRule(editRule);
}
}
$$('input').forEach((item) => { item.addEventListener('change', () => { todo() }) });
$$('textarea').forEach((item) => { item.addEventListener('change', () => { todo() }) });
// 处理按钮点击事件
$('.menu').addEventListener('click', e => {
let thisNode = e.target;
thisNode = thisNode.parentNode.nodeName == 'svg' ? thisNode.parentNode.querySelector('rect') :
thisNode.nodeName == 'svg' ? thisNode.querySelector('rect') : null;
if (!thisNode) return;
if (thisNode.getAttribute('class') == 'busy') return;
thisNode.setAttribute('class', 'busy');
switch (thisNode.id) {
case 'push':
$$('#RuleList>label>div').forEach(item => { item.className = ''; });
(async () => {
await HttpPost(`/saveBookSources`, RuleSources).then(json => {
if (json.isSuccess) {
let okData = json.data;
if (Array.isArray(okData)) {
let failMsg = ``;
if (RuleSources.length > okData.length) {
RuleSources.forEach(item => {
if (okData.find(x => x.bookSourceUrl == item.bookSourceUrl)) { }
else { $(`#RuleList #${item.bookSourceUrl}+*`).className += 'isError'; }
});
failMsg = '\n推送失败的源将用红色字体标注!';
}
alert(`批量推送源到「阅读3.0APP」\n共计: ${RuleSources.length}\n成功: ${okData.length}\n失败: ${RuleSources.length - okData.length}${failMsg}`);
}
else {
alert(`批量推送源到「阅读3.0APP」成功!\n共计: ${RuleSources.length}`);
}
}
else {
alert(`批量推送源失败!\nErrorMsg: ${json.errorMsg}`);
}
}).catch(err => { alert(`批量推送源失败,无法连接到「阅读3.0APP」!\n${err}`); });
thisNode.setAttribute('class', '');
})();
return;
case 'pull':
showTab('源列表');
(async () => {
await HttpGet(`/getBookSources`).then(json => {
if (json.isSuccess) {
$('#RuleList').innerHTML = ''
localStorage.setItem('BookSources', JSON.stringify(RuleSources = json.data));
RuleSources.forEach(item => {
$('#RuleList').innerHTML += newRule(item);
});
alert(`成功拉取 ${RuleSources.length} 条源`);
}
else {
alert(`批量拉取源失败!\nErrorMsg: ${json.errorMsg}`);
}
}).catch(err => { alert(`批量拉取源失败,无法连接到「阅读3.0APP」!\n${err}`); });
thisNode.setAttribute('class', '');
})();
return;
case 'editor':
if ($('#RuleJsonString').value == '') break;
try {
json2rule(JSON.parse($('#RuleJsonString').value));
todo();
} catch (error) {
console.log(error);
alert(error);
}
break;
case 'conver':
showTab('编辑源');
$('#RuleJsonString').value = JSON.stringify(rule2json(), null, 4);
break;
case 'initial':
$$('.rules textarea').forEach(item => { item.value = '' });
todo();
break;
case 'undo':
undo()
break;
case 'redo':
redo()
break;
case 'debug':
showTab('调试源');
let wsOrigin = (hashParam('domain') || location.origin).replace(/^.*?:/, 'ws:').replace(/\d+$/, (port) => (parseInt(port) + 1));
let DebugInfos = $('#DebugConsole');
function DebugPrint(msg) { DebugInfos.value += `\n${msg}`; DebugInfos.scrollTop = DebugInfos.scrollHeight; }
let saveRule = [rule2json()];
HttpPost(`/saveBookSources`, saveRule).then(sResult => {
if (sResult.isSuccess) {
let sKey = DebugKey.value ? DebugKey.value : '我的';
$('#DebugConsole').value = `源《${saveRule[0].bookSourceName}》保存成功!使用搜索关键字“${sKey}”开始调试...`;
let ws = new WebSocket(`${wsOrigin}/bookSourceDebug`);
ws.onopen = () => {
ws.send(`{"tag":"${saveRule[0].bookSourceUrl}", "key":"${sKey}"}`);
};
ws.onmessage = (msg) => {
console.log('[调试]', msg);
DebugPrint(msg.data);
};
ws.onerror = (err) => {
throw `${err.data}`;
}
ws.onclose = () => {
thisNode.setAttribute('class', '');
DebugPrint(`\n调试服务已关闭!`);
}
} else throw `${sResult.errorMsg}`;
}).catch(err => {
DebugPrint(`调试过程意外中止,以下是详细错误信息:\n${err}`);
thisNode.setAttribute('class', '');
});
return;
case 'accept':
(async () => {
let saveRule = [rule2json()];
await HttpPost(`/saveBookSource`, saveRule[0]).then(json => {
alert(json.isSuccess ? `源《${saveRule[0].bookSourceName}》已成功保存到「阅读3.0APP」` : `源《${saveRule[0].bookSourceName}》保存失败!\nErrorMsg: ${json.errorMsg}`);
setRule(saveRule[0]);
}).catch(err => { alert(`保存源失败,无法连接到「阅读3.0APP」!\n${err}`); });
thisNode.setAttribute('class', '');
})();
return;
default:
}
setTimeout(() => { thisNode.setAttribute('class', ''); }, 500);
});
$('#DebugKey').addEventListener('keydown', e => {
if (e.keyCode == 13) {
let clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent("click", true, false);
$('#debug').dispatchEvent(clickEvent);
}
});
$('#Filter').addEventListener('keydown', e => {
if (e.keyCode == 13) {
let cashList = [];
$('#RuleList').innerHTML = "";
let sKey = Filter.value ? Filter.value : '';
if (sKey == '') {
cashList = RuleSources;
} else {
let patt = new RegExp(sKey);
RuleSources.forEach(source => {
if (patt.test(source.bookSourceUrl) || patt.test(source.bookSourceName) || patt.test(source.bookSourceGroup)) {
cashList.push(source);
}
})
}
cashList.forEach(source => {
$('#RuleList').innerHTML += newRule(source);
})
}
});
// 列表规则更改事件
$('#RuleList').addEventListener('click', e => {
let editRule = null;
if (e.target && e.target.getAttribute('name') == 'rule') {
editRule = rule2json();
json2rule(RuleSources.find(x => x.bookSourceUrl == e.target.id));
} else return;
if (editRule.bookSourceUrl == '') return;
if (editRule.bookSourceName == '') editRule.bookSourceName = editRule.bookSourceUrl.replace(/.*?\/\/|\/.*/g, '');
setRule(editRule);
localStorage.setItem('BookSources', JSON.stringify(RuleSources));
});
// 处理列表按钮事件
$('.tab3>.titlebar').addEventListener('click', e => {
let thisNode = e.target;
if (thisNode.nodeName != 'BUTTON') return;
switch (thisNode.id) {
case 'Import':
let fileImport = document.createElement('input');
fileImport.type = 'file';
fileImport.accept = '.json';
fileImport.addEventListener('change', () => {
let file = fileImport.files[0];
let reader = new FileReader();
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) {
let fileText = evt.target.result;
try {
let fileJson = JSON.parse(fileText);
let newSources = [];
newSources.push(...fileJson);
if (window.confirm(`如何处理导入的源?\n"确定": 覆盖当前列表(不会删除APP源)\n"取消": 插入列表尾部(自动忽略重复源)`)) {
localStorage.setItem('BookSources', JSON.stringify(RuleSources = newSources));
$('#RuleList').innerHTML = ''
RuleSources.forEach(item => {
$('#RuleList').innerHTML += newRule(item);
});
}
else {
newSources = newSources.filter(item => !JSON.stringify(RuleSources).includes(item.bookSourceUrl));
RuleSources.push(...newSources);
localStorage.setItem('BookSources', JSON.stringify(RuleSources));
newSources.forEach(item => {
$('#RuleList').innerHTML += newRule(item);
});
}
alert(`成功导入 ${newSources.length} 条源`);
}
catch (err) {
alert(`导入源文件失败!\n${err}`);
}
}
};
reader.readAsText(file);
}, false);
fileImport.click();
break;
case 'Export':
let fileExport = document.createElement('a');
fileExport.download = `Rules${Date().replace(/.*?\s(\d+)\s(\d+)\s(\d+:\d+:\d+).*/, '$2$1$3').replace(/:/g, '')}.json`;
let myBlob = new Blob([JSON.stringify(RuleSources, null, 4)], { type: "application/json" });
fileExport.href = window.URL.createObjectURL(myBlob);
fileExport.click();
break;
case 'Delete':
let selectRule = $('#RuleList input:checked');
if (!selectRule) {
alert(`没有源被选中!`);
return;
}
if (confirm(`确定要删除选定源吗?\n(同时删除APP内源)`)) {
let selectRuleUrl = selectRule.id;
let deleteSources = RuleSources.filter(item => item.bookSourceUrl == selectRuleUrl); // 提取待删除的源
let laveSources = RuleSources.filter(item => !(item.bookSourceUrl == selectRuleUrl)); // 提取待留下的源
HttpPost(`/deleteBookSources`, deleteSources).then(json => {
if (json.isSuccess) {
let selectNode = document.getElementById(selectRuleUrl).parentNode;
selectNode.parentNode.removeChild(selectNode);
localStorage.setItem('BookSources', JSON.stringify(RuleSources = laveSources));
if ($('#bookSourceUrl').value == selectRuleUrl) {
$$('.rules textarea').forEach(item => { item.value = '' });
todo();
}
console.log(deleteSources);
console.log(`以上源已删除!`)
}
}).catch(err => { alert(`删除源失败,无法连接到「阅读3.0APP」!\n${err}`); });
}
break;
case 'ClrAll':
if (confirm(`确定要清空当前源列表吗?\n(不会删除APP内源)`)) {
localStorage.setItem('BookSources', JSON.stringify(RuleSources = []));
$('#RuleList').innerHTML = ''
}
break;
default:
}
});
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#2c3e50;margin:0;height:100%}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -0,0 +1,149 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="16.000000pt" height="16.000000pt" viewBox="0 0 16.000000 16.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,16.000000) scale(0.000320,-0.000320)"
fill="#000000" stroke="none">
<path d="M18 46618 c45 -75 122 -207 122 -211 0 -2 25 -45 55 -95 30 -50 55
-96 55 -102 0 -5 5 -10 10 -10 6 0 10 -4 10 -9 0 -5 73 -135 161 -288 89 -153
173 -298 187 -323 14 -25 32 -57 41 -72 88 -149 187 -324 189 -335 2 -7 8 -13
13 -13 5 0 9 -4 9 -10 0 -5 46 -89 103 -187 175 -302 490 -846 507 -876 8 -16
20 -36 25 -45 28 -46 290 -498 339 -585 13 -23 74 -129 136 -236 61 -107 123
-215 137 -240 14 -25 29 -50 33 -56 5 -5 23 -37 40 -70 18 -33 38 -67 44 -75
11 -16 21 -33 63 -109 14 -25 29 -50 33 -56 4 -5 21 -35 38 -65 55 -100 261
-455 269 -465 4 -5 14 -21 20 -35 15 -29 41 -75 103 -180 24 -41 52 -88 60
-105 9 -16 57 -100 107 -185 112 -193 362 -626 380 -660 8 -14 23 -38 33 -55
11 -16 23 -37 27 -45 4 -8 26 -46 48 -85 23 -38 53 -90 67 -115 46 -81 64
-113 178 -310 62 -107 121 -210 132 -227 37 -67 56 -99 85 -148 16 -27 32 -57
36 -65 4 -8 15 -27 25 -42 9 -15 53 -89 96 -165 44 -76 177 -307 296 -513 120
-206 268 -463 330 -570 131 -227 117 -203 200 -348 36 -62 73 -125 82 -140 10
-15 21 -34 25 -42 4 -8 20 -37 36 -65 17 -27 38 -65 48 -82 49 -85 64 -111 87
-153 13 -25 28 -49 32 -55 4 -5 78 -134 165 -285 87 -151 166 -288 176 -305
10 -16 26 -43 35 -59 9 -17 125 -217 257 -445 132 -229 253 -441 270 -471 17
-30 45 -79 64 -108 18 -29 33 -54 33 -57 0 -2 20 -37 44 -77 24 -40 123 -212
221 -383 97 -170 190 -330 205 -355 16 -25 39 -65 53 -90 13 -25 81 -144 152
-265 70 -121 137 -238 150 -260 12 -22 37 -65 55 -95 18 -30 43 -73 55 -95 12
-22 48 -85 80 -140 77 -132 163 -280 190 -330 13 -22 71 -123 130 -225 59
-102 116 -199 126 -217 10 -17 29 -50 43 -72 15 -22 26 -43 26 -45 0 -2 27
-50 60 -106 33 -56 60 -103 60 -105 0 -2 55 -98 90 -155 8 -14 182 -316 239
-414 13 -22 45 -79 72 -124 27 -46 49 -86 49 -89 0 -2 14 -24 30 -48 16 -24
30 -46 30 -49 0 -5 74 -135 100 -176 5 -8 24 -42 43 -75 50 -88 58 -101 262
-455 104 -179 199 -345 213 -370 14 -25 28 -49 32 -55 4 -5 17 -26 28 -45 10
-19 62 -109 114 -200 114 -197 133 -230 170 -295 16 -27 33 -57 38 -65 17 -28
96 -165 103 -180 4 -8 16 -28 26 -45 10 -16 77 -131 148 -255 72 -124 181
-313 243 -420 62 -107 121 -209 131 -227 35 -62 323 -560 392 -678 38 -66 83
-145 100 -175 16 -30 33 -59 37 -65 4 -5 17 -27 29 -47 34 -61 56 -100 90
-156 17 -29 31 -55 31 -57 0 -2 17 -32 39 -67 21 -35 134 -229 251 -433 117
-203 235 -407 261 -451 27 -45 49 -85 49 -88 0 -4 8 -19 19 -34 15 -21 200
-341 309 -533 10 -19 33 -58 51 -87 17 -29 31 -54 31 -56 0 -2 25 -44 55 -94
30 -50 55 -95 55 -98 0 -4 6 -15 14 -23 7 -9 27 -41 43 -71 17 -30 170 -297
342 -594 171 -296 311 -542 311 -547 0 -5 5 -9 10 -9 6 0 10 -4 10 -10 0 -5
22 -47 49 -92 27 -46 58 -99 68 -118 24 -43 81 -140 93 -160 5 -8 66 -114 135
-235 69 -121 130 -227 135 -235 12 -21 259 -447 283 -490 10 -19 28 -47 38
-62 11 -14 19 -29 19 -32 0 -3 37 -69 83 -148 99 -170 305 -526 337 -583 13
-22 31 -53 41 -70 11 -16 22 -37 26 -45 7 -14 82 -146 103 -180 14 -24 181
-311 205 -355 13 -22 46 -80 75 -130 29 -49 64 -110 78 -135 14 -25 51 -88 82
-140 31 -52 59 -102 63 -110 4 -8 18 -33 31 -55 205 -353 284 -489 309 -535
17 -30 45 -78 62 -106 18 -28 36 -60 39 -72 4 -12 12 -22 17 -22 5 0 9 -4 9
-10 0 -5 109 -197 241 -427 133 -230 250 -431 259 -448 51 -90 222 -385 280
-485 37 -63 78 -135 92 -160 14 -25 67 -117 118 -205 51 -88 101 -175 111
-193 34 -58 55 -95 149 -257 51 -88 101 -173 110 -190 9 -16 76 -131 147 -255
72 -124 140 -241 151 -260 61 -108 281 -489 355 -615 38 -66 77 -133 87 -150
35 -63 91 -161 100 -175 14 -23 99 -169 128 -220 54 -97 135 -235 142 -245 4
-5 20 -32 35 -60 26 -48 238 -416 276 -480 10 -16 26 -46 37 -65 30 -53 382
-661 403 -695 10 -16 22 -37 26 -45 4 -8 26 -48 50 -88 24 -41 43 -75 43 -77
0 -2 22 -40 50 -85 27 -45 50 -84 50 -86 0 -3 38 -69 83 -147 84 -142 302
-520 340 -587 10 -19 34 -60 52 -90 18 -30 44 -75 57 -100 14 -25 45 -79 70
-120 25 -41 56 -96 70 -121 14 -25 77 -133 138 -240 62 -107 122 -210 132
-229 25 -43 310 -535 337 -581 11 -19 26 -45 34 -59 17 -32 238 -414 266 -460
11 -19 24 -41 28 -49 3 -7 75 -133 160 -278 84 -146 153 -269 153 -274 0 -5 5
-9 10 -9 6 0 10 -4 10 -10 0 -5 82 -150 181 -322 182 -314 201 -346 240 -415
12 -21 80 -139 152 -263 71 -124 141 -245 155 -270 14 -25 28 -49 32 -55 6 -8
145 -248 220 -380 37 -66 209 -362 229 -395 11 -19 24 -42 28 -49 4 -8 67
-118 140 -243 73 -125 133 -230 133 -233 0 -2 15 -28 33 -57 19 -29 47 -78 64
-108 17 -30 53 -93 79 -139 53 -90 82 -141 157 -272 82 -142 115 -199 381
-659 142 -245 268 -463 281 -485 12 -22 71 -125 132 -230 60 -104 172 -298
248 -430 76 -132 146 -253 156 -270 11 -16 22 -36 26 -44 3 -8 30 -54 60 -103
29 -49 53 -91 53 -93 0 -3 18 -34 40 -70 22 -36 40 -67 40 -69 0 -2 37 -66 81
-142 45 -77 98 -168 119 -204 20 -36 47 -81 58 -100 12 -19 27 -47 33 -62 6
-16 15 -28 20 -28 5 0 9 -4 9 -9 0 -6 63 -118 140 -251 77 -133 140 -243 140
-245 0 -2 18 -33 41 -70 22 -37 49 -83 60 -101 10 -19 29 -51 40 -71 25 -45
109 -189 126 -218 7 -11 17 -29 22 -40 6 -11 22 -38 35 -60 14 -22 37 -62 52
-90 14 -27 35 -62 45 -77 11 -14 19 -29 19 -32 0 -3 18 -35 40 -71 22 -36 40
-67 40 -69 0 -2 19 -35 42 -72 23 -38 55 -94 72 -124 26 -47 139 -244 171
-298 6 -9 21 -36 34 -60 28 -48 37 -51 51 -19 6 12 19 36 29 52 10 17 27 46
38 65 11 19 104 181 208 360 103 179 199 345 213 370 14 25 42 74 64 109 21
34 38 65 38 67 0 2 18 33 40 69 22 36 40 67 40 69 0 3 177 310 199 346 16 26
136 234 140 244 2 5 25 44 52 88 27 44 49 81 49 84 0 2 18 34 40 70 22 36 40
67 40 69 0 2 20 36 43 77 35 58 169 289 297 513 9 17 50 86 90 155 40 69 86
150 103 180 16 30 35 62 41 70 6 8 16 24 22 35 35 64 72 129 167 293 59 100
116 199 127 220 11 20 30 53 41 72 43 72 1070 1850 1121 1940 14 25 65 113
113 195 48 83 96 166 107 185 10 19 28 50 38 68 11 18 73 124 137 235 64 111
175 303 246 427 71 124 173 299 225 390 52 91 116 202 143 248 27 45 49 85 49
89 0 4 6 14 14 22 7 9 28 43 46 76 26 47 251 436 378 655 11 19 29 51 40 70
11 19 101 176 201 348 99 172 181 317 181 323 0 5 5 9 10 9 6 0 10 5 10 11 0
6 8 23 18 37 11 15 32 52 49 82 16 30 130 228 253 440 122 212 234 405 248
430 13 25 39 70 57 100 39 65 69 117 130 225 25 44 50 87 55 95 12 19 78 134
220 380 61 107 129 224 150 260 161 277 222 382 246 425 15 28 47 83 71 123
24 41 43 78 43 83 0 5 4 9 8 9 4 0 13 12 19 28 7 15 23 45 36 67 66 110 277
478 277 483 0 3 6 13 14 21 7 9 27 41 43 71 17 30 45 80 63 110 34 57 375 649
394 685 6 11 16 27 22 35 6 8 26 42 44 75 18 33 41 74 51 90 10 17 24 41 32
55 54 97 72 128 88 152 11 14 19 28 19 30 0 3 79 141 175 308 96 167 175 305
175 308 0 3 6 13 14 21 7 9 26 39 41 66 33 60 276 483 338 587 24 40 46 80 50
88 4 8 13 24 20 35 14 23 95 163 125 215 11 19 52 91 92 160 40 69 80 139 90
155 9 17 103 179 207 360 105 182 200 346 211 365 103 181 463 802 489 845 7
11 15 27 19 35 4 8 29 51 55 95 64 110 828 1433 848 1470 9 17 24 41 33 55 9
14 29 48 45 77 15 28 52 93 82 145 30 51 62 107 71 123 17 30 231 398 400 690
51 88 103 179 115 202 12 23 26 48 32 55 6 7 24 38 40 68 17 30 61 107 98 170
37 63 84 144 103 180 19 36 41 72 48 81 8 8 14 18 14 21 0 4 27 51 59 106 32
55 72 124 89 154 16 29 71 125 122 213 51 88 104 180 118 205 13 25 28 50 32
55 4 6 17 26 28 45 11 19 45 80 77 135 31 55 66 116 77 135 11 19 88 152 171
295 401 694 620 1072 650 1125 11 19 87 152 170 295 83 143 158 273 166 288 9
16 21 36 26 45 6 9 31 52 55 96 25 43 54 94 66 115 11 20 95 164 186 321 91
157 173 299 182 315 9 17 26 46 37 65 12 19 66 114 121 210 56 96 108 186 117
200 8 14 24 40 34 59 24 45 383 664 412 713 5 9 17 29 26 45 15 28 120 210
241 419 36 61 68 117 72 125 4 8 12 23 19 34 35 57 245 420 262 453 11 20 35
61 53 90 17 29 32 54 32 56 0 3 28 51 62 108 33 57 70 119 80 138 10 19 23 42
28 50 5 8 32 53 59 100 27 47 149 258 271 470 122 212 234 405 248 430 30 53
62 108 80 135 6 11 15 27 19 35 4 8 85 150 181 315 96 165 187 323 202 350 31
56 116 202 130 225 5 8 25 42 43 75 19 33 92 159 162 280 149 257 157 271 202
350 19 33 38 67 43 75 9 14 228 392 275 475 12 22 55 96 95 165 40 69 80 139
90 155 24 42 202 350 221 383 9 15 27 47 41 72 14 25 75 131 136 236 61 106
121 210 134 232 99 172 271 470 279 482 5 8 23 40 40 70 18 30 81 141 142 245
60 105 121 210 135 235 14 25 71 124 127 220 56 96 143 247 194 335 51 88 96
167 102 175 14 24 180 311 204 355 23 43 340 590 356 615 5 8 50 87 101 175
171 301 517 898 582 1008 25 43 46 81 46 83 0 2 12 23 27 47 14 23 40 67 56
97 16 30 35 62 42 70 7 8 15 22 18 30 4 8 20 38 37 65 16 28 33 57 37 65 6 12
111 196 143 250 5 8 55 95 112 193 57 98 113 195 126 215 12 20 27 46 32 57 6
11 14 27 20 35 5 8 76 130 156 270 80 140 165 287 187 325 23 39 52 90 66 115
13 25 30 52 37 61 8 8 14 18 14 21 0 4 41 77 92 165 50 87 175 302 276 478
101 176 208 360 236 408 28 49 67 117 86 152 19 35 41 70 48 77 6 6 12 15 12
19 0 7 124 224 167 291 12 21 23 40 23 42 0 2 21 40 46 83 26 43 55 92 64 109
54 95 327 568 354 614 19 30 45 75 59 100 71 128 82 145 89 148 4 2 8 8 8 13
0 5 42 82 94 172 311 538 496 858 518 897 14 25 40 70 58 100 18 30 42 71 53
90 10 19 79 139 152 265 73 127 142 246 153 265 10 19 43 76 72 125 29 50 63
108 75 130 65 116 80 140 87 143 4 2 8 8 8 12 0 8 114 212 140 250 6 8 14 24
20 35 5 11 54 97 108 190 l100 170 -9611 3 c-5286 1 -9614 -1 -9618 -5 -5 -6
-419 -719 -619 -1068 -89 -155 -267 -463 -323 -560 -38 -66 -81 -140 -95 -165
-31 -56 -263 -457 -526 -910 -110 -190 -224 -388 -254 -440 -29 -52 -61 -109
-71 -125 -23 -39 -243 -420 -268 -465 -11 -19 -204 -352 -428 -740 -224 -388
-477 -826 -563 -975 -85 -148 -185 -322 -222 -385 -37 -63 -120 -207 -185
-320 -65 -113 -177 -306 -248 -430 -72 -124 -172 -297 -222 -385 -51 -88 -142
-245 -202 -350 -131 -226 -247 -427 -408 -705 -65 -113 -249 -432 -410 -710
-160 -278 -388 -673 -506 -877 -118 -205 -216 -373 -219 -373 -3 0 -52 82
-109 183 -58 100 -144 250 -192 332 -95 164 -402 696 -647 1120 -85 149 -228
396 -317 550 -212 365 -982 1700 -1008 1745 -10 19 -43 76 -72 125 -29 50 -64
110 -77 135 -14 25 -63 110 -110 190 -47 80 -96 165 -110 190 -14 25 -99 171
-188 325 -89 154 -174 300 -188 325 -13 25 -64 113 -112 195 -48 83 -140 242
-205 355 -65 113 -183 317 -263 454 -79 137 -152 264 -163 282 -50 89 -335
583 -354 614 -12 19 -34 58 -50 85 -15 28 -129 226 -253 440 -124 215 -235
408 -247 430 -12 22 -69 121 -127 220 -58 99 -226 389 -373 645 -148 256 -324
561 -392 678 -67 117 -134 232 -147 255 -13 23 -33 59 -46 80 l-22 37 -9615 0
-9615 0 20 -32z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en" style="padding: 0;height:100%">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<!--[if IE]>
<link rel="icon" href="favicon.ico"/><![endif]--><title>Legado Bookshelf</title>
<link href="css/about.b9bb4fe0.css" rel="prefetch">
<link href="css/detail.e03dc50b.css" rel="prefetch">
<link href="js/about.9f8f9ac0.js" rel="prefetch">
<link href="js/about~detail.8270a871.js" rel="prefetch">
<link href="js/detail.4e6a53a9.js" rel="prefetch">
<link href="css/app.e4c919b7.css" rel="preload" as="style">
<link href="css/chunk-vendors.8a465a1d.css" rel="preload" as="style">
<link href="js/app.e84ee963.js" rel="preload" as="script">
<link href="js/chunk-vendors.3ef7796f.js" rel="preload" as="script">
<link href="css/chunk-vendors.8a465a1d.css" rel="stylesheet">
<link href="css/app.e4c919b7.css" rel="stylesheet">
<link rel="icon" type="image/png" sizes="32x32" href="img/icons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="img/icons/favicon-16x16.png">
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#4DBA87">
<meta name="apple-mobile-web-app-capable" content="no">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="yd-web-tool">
<link rel="apple-touch-icon" href="img/icons/apple-touch-icon-152x152.png">
<link rel="mask-icon" href="img/icons/safari-pinned-tab.svg" color="#4DBA87">
<meta name="msapplication-TileImage" content="img/icons/msapplication-icon-144x144.png">
<meta name="msapplication-TileColor" content="#000000">
</head>
<style>body::-webkit-scrollbar {
display: none;
}
</style>
<body style="margin: 0;height:100%">
<noscript><strong>We're sorry but yd-web-tool doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong></noscript>
<div id="app"></div>
<script src="js/chunk-vendors.3ef7796f.js"></script>
<script src="js/app.e84ee963.js"></script>
</body>
</html>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"name":"yd-web-tool","short_name":"yd-web-tool","theme_color":"#4DBA87","icons":[{"src":"./img/icons/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"./img/icons/android-chrome-512x512.png","sizes":"512x512","type":"image/png"},{"src":"./img/icons/android-chrome-maskable-192x192.png","sizes":"192x192","type":"image/png","purpose":"maskable"},{"src":"./img/icons/android-chrome-maskable-512x512.png","sizes":"512x512","type":"image/png","purpose":"maskable"}],"start_url":".","display":"standalone","background_color":"#000000"}
@@ -0,0 +1,70 @@
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "c6913d775f2f965ac5f3",
"url": "css/about.b9bb4fe0.css"
},
{
"revision": "c7b3e35a4e0391b1ed37",
"url": "css/app.e4c919b7.css"
},
{
"revision": "9a65f05f9810a3ea7f46",
"url": "css/chunk-vendors.8a465a1d.css"
},
{
"revision": "5ab5c6be15b21e2d609b",
"url": "css/detail.e03dc50b.css"
},
{
"revision": "535877f50039c0cb49a6196a5b7517cd",
"url": "fonts/element-icons.535877f5.woff"
},
{
"revision": "732389ded34cb9c52dd88271f1345af9",
"url": "fonts/element-icons.732389de.ttf"
},
{
"revision": "f9a3fb0e145017e166dd4d91d9280cc4",
"url": "fonts/iconfont.f9a3fb0e.woff"
},
{
"revision": "f39ecc1a1d2a1eff3aca8aadd818bb61",
"url": "fonts/popfont.f39ecc1a.ttf"
},
{
"revision": "6c094b6d4ae9404dbed273c41b06fae8",
"url": "fonts/shelffont.6c094b6d.ttf"
},
{
"revision": "8a8424347500238b7b6c08a98d0f89af",
"url": "index.html"
},
{
"revision": "c6913d775f2f965ac5f3",
"url": "js/about.9f8f9ac0.js"
},
{
"revision": "5998ccb313ed338c15e1",
"url": "js/about~detail.8270a871.js"
},
{
"revision": "c7b3e35a4e0391b1ed37",
"url": "js/app.e84ee963.js"
},
{
"revision": "9a65f05f9810a3ea7f46",
"url": "js/chunk-vendors.3ef7796f.js"
},
{
"revision": "5ab5c6be15b21e2d609b",
"url": "js/detail.4e6a53a9.js"
},
{
"revision": "b46d04eb43bc31ca0f9f95121646440d",
"url": "manifest.json"
},
{
"revision": "b6216d61c03e6ce0c9aea6ca7808f7ca",
"url": "robots.txt"
}
]);
@@ -0,0 +1,2 @@
User-agent: *
Disallow:
@@ -0,0 +1,34 @@
/**
* Welcome to your Workbox-powered service worker!
*
* You'll need to register this file in your web app and you should
* disable HTTP caching for this file too.
* See https://goo.gl/nhQhGp
*
* The rest of the code is auto-generated. Please don't update this file
* directly; instead, make changes to your Workbox build configuration
* and re-run your build process.
* See https://goo.gl/2aRDsh
*/
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts(
"precache-manifest.5ae9ceec57e7f0f3cc808807b7fe5f32.js"
);
workbox.core.setCacheNameDetails({prefix: "yd-web-tool"});
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
/**
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
* requests for URLs in the manifest.
* See https://goo.gl/S9QRab
*/
self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

+68
View File
@@ -0,0 +1,68 @@
<!DOCTYPE HTML>
<!--
Forty by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
<head>
<title>Legado web 导航</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
<link rel="stylesheet" href="assets/css/main.css"/>
</head>
<body class="is-preload">
<!-- Wrapper -->
<div id="wrapper">
<!-- Header -->
<header id="header" class="alt">
<nav>
<a href="#menu">Menu</a>
</nav>
</header>
<!-- Menu -->
<nav id="menu">
<ul class="links">
<li><a href="https://github.com/gedoor/legado">Github</a></li>
<li><a href="https://github.com/zsakvo">zsakvo</a></li>
<li><a href="#">Design: HTML5 UP</a></li>
</ul>
</nav>
<!-- Banner -->
<section id="banner" class="major">
<div class="inner">
<header class="major">
<h1>昨日邻家乞新火,晓窗分与读书灯</h1>
</header>
<div class="content">
<!-- <p>A responsive site template designed by HTML5 UP<br />
and released under the Creative Commons.</p> -->
<ul class="actions">
<li><a href="bookshelf/index.html" class="button next scrolly">书架</a></li>
</ul>
<ul class="actions">
<li><a href="bookSource/index.html" class="button next scrolly">书源</a></li>
</ul>
<ul class="actions">
<li><a href="uploadBook/index.html" class="button next scrolly">传书</a></li>
</ul>
<ul class="actions">
<li><a href="rssSource/index.html" class="button next scrolly">订阅源</a></li>
</ul>
</div>
</div>
</section>
</div>
<!-- Scripts -->
<script src="assets/js/dist.js"></script>
</body>
</html>
+150
View File
@@ -0,0 +1,150 @@
body {
margin: 0;
}
.editor {
display: flex;
align-items: stretch;
}
.setbox,
.menu,
.outbox {
flex: 1;
display: flex;
flex-flow: column;
max-height: 100vh;
overflow-y: auto;
}
.menu {
justify-content: center;
max-width: 90px;
margin: 0 5px;
}
.menu .button {
width: 90px;
height: 30px;
min-height: 30px;
margin: 5px 0px;
cursor: pointer;
}
@keyframes stroker {
0% {
stroke-dashoffset: 0;
}
100% {
stroke-dashoffset: -240;
}
}
.button rect {
width: 100%;
height: 100%;
fill: transparent;
stroke: #666;
stroke-width: 2px;
}
.button rect.busy {
stroke: #fd1850;
stroke-dasharray: 30 90;
animation: stroker 1s linear infinite;
}
.button text {
text-anchor: middle;
dominant-baseline: middle;
}
.setbox {
min-width: 40em;
}
.rules {
overflow: auto;
}
.tabbox {
flex: 1;
display: flex;
flex-flow: column;
}
.rules > * {
display: flex;
margin: 2px 0;
}
.rules textarea {
flex: 1;
margin-left: 5px;
}
.rules > *,
.rules > * > div,
.rules textarea {
min-height: 1em;
}
textarea {
word-break: break-all;
}
.tabtitle {
display: flex;
z-index: 1;
justify-content: flex-end;
}
.tabtitle > div {
cursor: pointer;
padding: 1px 10px 0 10px;
border-bottom: 3px solid transparent;
font-weight: bold;
}
.tabtitle > .this {
color: #4f9da6;
border-bottom-color: #4ebbe4;
}
.tabbody {
flex: 1;
display: flex;
margin-top: -1px;
border: 1px solid #a9a9a9;
height: 0;
}
.tabbody > * {
flex: 1;
flex-flow: column;
display: none;
}
.tabbody > .this {
display: flex;
}
.tabbody > * > .titlebar {
display: flex;
}
.tabbody > * > .titlebar > * {
flex: 1;
margin: 1px 1px 1px 1px;
}
.tabbody > * > .context {
flex: 1;
flex-flow: column;
border: 0;
padding: 5px;
overflow-y: auto;
}
.tabbody > * > .inputbox {
border: 0;
border-bottom: #a9a9a9 solid 1px;
height: 15px;
text-align: center;
}
.link > * {
display: flex;
margin: 5px;
border-bottom: 1px solid;
text-decoration: none;
}
#RuleList > label > * {
background: #eee;
padding-left: 3px;
margin: 2px 0;
cursor: pointer;
}
#RuleList input[type="radio"] {
display: none;
}
#RuleList input[type="radio"]:checked + * {
background: #15cda8;
}
.isError {
color: #ff0000;
}
@@ -0,0 +1,243 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>阅读3.0订阅源编辑器_V4.0</title>
<link rel="icon" href="favicon.ico">
<link rel="stylesheet" type="text/css" href="index.css"/>
</head>
<body>
<div class="editor">
<div class="setbox">
<div>
<a href="../index.html">←主页</a>
<b>订阅源</b>
</div>
<div class="rules">
<div><b>基本</b></div>
<div>
<div>源域名 :</div>
<textarea rows="1" id="sourceUrl" class="base" title="sourceUrl"
placeholder="<必填>通常填写网站主页,例: https://www.qidian.com"></textarea>
</div>
<div>
<div>源名称 :</div>
<textarea rows="1" id="sourceName" class="base" title="sourceName"
placeholder="&lt;必填&gt;源名称"></textarea>
</div>
<div>
<div>图标  :</div>
<textarea rows="1" id="sourceIcon" class="base" title="sourceIcon"
placeholder="&lt;选填&gt;图标"></textarea>
</div>
<div>
<div>源分组 :</div>
<textarea rows="1" id="sourceGroup" class="base" title="sourceGroup"
placeholder="&lt;选填&gt;描述源的特征信息"></textarea>
</div>
<div>
<div>源注释 :</div>
<textarea rows="1" id="sourceComment" class="base" title="sourceComment"
placeholder="&lt;选填&gt;描述源作者和状态"></textarea>
</div>
<div>
<div>登录地址:</div>
<textarea rows="1" id="loginUrl" class="base" title="loginUrl"
placeholder="&lt;选填&gt;填写网站登录网址,仅在需要登录的源有用"></textarea>
</div>
<div>
<div>登录界面:</div>
<textarea rows="3" id="loginUi" class="base" title="loginUi"
placeholder="&lt;选填&gt;自定义登录界面"></textarea>
</div>
<div>
<div>登录检测:</div>
<textarea rows="3" id="loginCheckJs" class="base" title="loginCheckJs"
placeholder="&lt;选填&gt;登录检测js"></textarea>
</div>
<div>
<div>并发率 :</div>
<textarea rows="1" id="concurrentRate" class="base" title="concurrentRate"
placeholder="&lt;选填&gt;并发率"></textarea>
</div>
<div>
<div>请求头 :</div>
<textarea rows="3" id="header" class="base" title="header"
placeholder="&lt;选填&gt;客户端标识"></textarea>
</div>
<div>
<div>分类地址:</div>
<textarea rows="3" id="sortUrl" class="base" title="sortUrl"
placeholder="&lt;选填&gt;例:&#10;名称1::网址(Url)1&#10;名称2::网址(Url)2&#10;..."></textarea>
</div>
<p></p>
<div><b>列表规则</b></div>
<div>
<div>列表样式:</div>
<textarea rows="1" id="articleStyle" class="base" title="articleStyle"
placeholder="列表样式:0,1,2"></textarea>
</div>
<div>
<div>列表规则:</div>
<textarea rows="1" id="ruleArticles" class="base" title="ruleArticles"
placeholder="列表规则 (规则结果为List&lt;Element&gt;)"></textarea>
</div>
<div>
<div>标题规则:</div>
<textarea rows="1" id="ruleTitle" class="base" title="ruleTitle"
placeholder="选择节点书名 (规则结果为String)"></textarea>
</div>
<div>
<div>时间规则:</div>
<textarea rows="1" id="rulePubDate" class="base" title="rulePubDate"
placeholder="发表时间 (规则结果为String)"></textarea>
</div>
<div>
<div>翻页规则:</div>
<textarea rows="1" id="ruleNextPage" class="base" title="ruleNextPage"
placeholder="下一页链接 (规则结果为List&lt;String&gt;或String)"></textarea>
</div>
<p></p>
<div><b>WebView规则</b></div>
<div>
<div>加载地址:</div>
<textarea rows="1" id="loadWithBaseUrl" class="base" title="loadWithBaseUrl"
placeholder="是否加载url (启用: true 关闭: false (可选,默认true))"></textarea>
</div>
<div>
<div>启用JS :</div>
<textarea rows="1" id="enableJs" class="base" title="enableJs"
placeholder="是否启用Js (启用: true 关闭: false (可选,默认true))"></textarea>
</div>
<div>
<div>描述规则:</div>
<textarea rows="1" id="ruleDescription" class="base" title="ruleDescription"
placeholder="rss内容 (规则结果为String)"></textarea>
</div>
<div>
<div>图片地址:</div>
<textarea rows="1" id="ruleImage" class="base" title="ruleImage"
placeholder="图片rul规则 (规则结果为url)"></textarea>
</div>
<div>
<div>原文链接:</div>
<textarea rows="1" id="ruleLink" class="base" title="ruleLink"
placeholder="原文链接规则 (规则结果为url)"></textarea>
</div>
<div>
<div>内容规则:</div>
<textarea rows="1" id="ruleContent" class="base" title="ruleContent"
placeholder="内容规则 (规则结果为String)"></textarea>
</div>
<div>
<div>内容样式:</div>
<textarea rows="1" id="style" class="base" title="style"
placeholder="内容样式 (css样式)"></textarea>
</div>
<p></p>
<div><b>其它规则</b></div>
<div>
<div>启用  :</div>
<textarea rows="1" id="enabled" class="base" title="enabled"
placeholder="启用: true 关闭: false (可选,默认true)"></textarea>
</div>
<div>
<div>排序编号:</div>
<textarea rows="1" id="customOrder" class="base" title="customOrder"
placeholder="整数: 0~N (可选,默认0) | 数字越小越靠前"></textarea>
</div>
</div>
</div>
<div class="menu">
<svg class="button">
<text x="50%" y="55%">⇈推送源</text>
<rect id="push"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">⇊拉取源</text>
<rect id="pull"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">⋘编辑源</text>
<rect id="editor"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">⋙生成源</text>
<rect id="conver"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">✗清空表单</text>
<rect id="initial"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">↶撤销操作</text>
<rect id="undo"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">↷重做操作</text>
<rect id="redo"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">⇏调试源</text>
<rect id="debug"></rect>
</svg>
<svg class="button">
<text x="50%" y="55%">✓保存源</text>
<rect id="accept"></rect>
</svg>
</div>
<div class="outbox">
<div class="tabbox">
<div class="tabtitle">
<div name="编辑源" class="tab1 this">编辑源</div>
<div name="调试源" class="tab2">调试源</div>
<div name="源列表" class="tab3">源列表</div>
<div name="帮助信息" class="tab4">帮助信息</div>
</div>
<div class="tabbody">
<div class="tab1 this">
<textarea class="context" id="RuleJsonString"
placeholder="这里输出序列化的JSON数据,可直接导入'阅读'APP"></textarea>
</div>
<div class="tab2">
<textarea class="context" id="DebugConsole" placeholder="这里用于输出调试信息"></textarea>
</div>
<div class="tab3">
<input type="text" class="inputbox" id="Filter"
placeholder="输入筛选关键词(源名称、源URL或源分组)后按回车筛选源">
<div class="titlebar">
<button id="Import">导入源文件</button>
<button id="Export">导出源文件</button>
<button id="Delete">删除选中源</button>
<button id="ClrAll">清空列表</button>
</div>
<div class="context" id="RuleList"></div>
</div>
<div class="tab4">
<div class="context link">
<a target="_blank" href="https://alanskycn.gitee.io/teachme">源制作教程</a>
<a target="_blank"
href="https://zhuanlan.zhihu.com/p/29436838">Xpath基础教程</a>
<a target="_blank"
href="https://zhuanlan.zhihu.com/p/32187820">Xpath高级教程</a>
<a target="_blank" href="https://www.w3cschool.cn/regex_rmjc">正则表达式教程</a>
<a target="_blank" href="https://regexr.com">正则表达式在线验证工具</a>
<div>^$()[]{}.?+*| 这些是Java正则特殊符号,匹配需转义
<br>(?s) 前缀表示跨行解析
<br>(?m) 前缀表示逐行匹配
<br>(?i) 前缀表示忽略大小写
</div>
<a target="_blank" href="https://www.beta.browxy.com">代码在线运行工具</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="/assets/js/md5.js"></script>
<script type="text/javascript" src="index.js"></script>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More