diff --git a/.github/ISSUE_TEMPLATE/01-bugReport.yml b/.github/ISSUE_TEMPLATE/01-bugReport.yml
deleted file mode 100644
index c30aa1c5f..000000000
--- a/.github/ISSUE_TEMPLATE/01-bugReport.yml
+++ /dev/null
@@ -1,65 +0,0 @@
-name: BUG提交 / BUG Report
-description: Report bugs to developers
-labels: ["BUG"]
-body:
- - type: checkboxes
- attributes:
- label: 确认 / Assignments
- description: 提交issue请确保完成以下前提,否则该issue可能被忽略 / Make sure you read checkboxs below
- options:
- - label: 搜索现有issues,不存在相似或相关的issue / No similar or related issues
- required: true
- - label: 最新[测试版](https://github.com/gedoor/legado/releases/beta)依然存在此问题 / Latest beta app does not work
- required: true
- - label: 此问题和Xposed、Lsposed、Magisk、手机主题、浏览器插件、无障碍服务等无关 / Make sure your machine is not touched by hook frameworks, plugins, accessibility etc
- required: true
-
- - type: textarea
- attributes:
- label: 问题描述 / Describe Bugs
- validations:
- required: true
- - type: textarea
- attributes:
- label: 复现步骤 / How to reproduce
- validations:
- required: true
- - type: checkboxes
- attributes:
- label: 确认 / Assignment
- options:
- - label: 已经提交复现所需要的附加资料 / Submit additions related with bugs
- required: true
- - type: textarea
- attributes:
- label: 其他信息 / Additions
- description: |
- 反馈WEB书架前端问题时请提供浏览器版本信息,如Edge 129.0.2792.89
- placeholder: "请用```将提交的内容包裹"
-
- - type: textarea
- attributes:
- label: 日志提交 / Relevant log output
- description: |
- 阅读日志位于我的-关于-崩溃日志、保存日志、书架-右上角-日志,或者自行使用log工具抓取日志
- 如果崩溃日志中包含`java.lang.OutOfMemoryError`,请安装最新测试版,在其他设置里打开记录堆转储,复现崩溃后去关于那里点保存日志,然后去备份目录里将heapDump文件夹里的文件打包压缩一下上传上来
- placeholder: "请用```将日志内容包裹"
-
- - type: input
- attributes:
- label: 阅读版本 / Legado version
- placeholder: "3.22.110823"
- validations:
- required: true
- - type: input
- attributes:
- label: Android版本 / Android version
- placeholder: "Android 12"
- validations:
- required: true
- - type: input
- attributes:
- label: 机型 / Model
- placeholder: "Redmi K30 Pro"
- validations:
- required: true
diff --git a/.github/ISSUE_TEMPLATE/02-featureRequest.yml b/.github/ISSUE_TEMPLATE/02-featureRequest.yml
deleted file mode 100644
index 163619682..000000000
--- a/.github/ISSUE_TEMPLATE/02-featureRequest.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-name: 功能请求 / Features
-description: Request new features
-labels: ["需求"]
-body:
- - type: checkboxes
- attributes:
- label: 确认 / Assignments
- description: 提交issue请确保完成以下前提,否则该issue可能被忽略 / Make sure you read checkbox below
- options:
- - label: 搜索现有issues,不存在相似或相关的issue / No related requests
- required: true
- - label: 最新[测试版](https://github.com/gedoor/legado/releases/beta)没有此功能 / Latest beta app does not this feature
- required: true
-
- - type: textarea
- attributes:
- label: 功能描述 / Features
- placeholder: 请清晰的、详细的描述你想要的功能
- validations:
- required: true
- - type: textarea
- attributes:
- label: 期望实现方式 / How to implement
- placeholder: 阅读应该如何实现该功能
- validations:
- required: true
- - type: input
- attributes:
- label: 阅读版本 / Legado version
- placeholder: "3.22.110823"
- validations:
- required: true
- - type: textarea
- attributes:
- label: 附加信息 / Additions
- placeholder: 其他的与功能相关的附加信息
- - type: textarea
- attributes:
- label: 效果演示 / Demo
- placeholder: 可以手绘一些草图,或者提供可借鉴的图片
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
deleted file mode 100644
index ee48d87b8..000000000
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-blank_issues_enabled: false
-contact_links:
- - name: 简繁转化
- url: https://github.com/liuyueyi/quick-chinese-transfer/issues/new
- about: 简繁转化问题请优先到quick-chinese-transfer反馈
- - name: 讨论 / Discussions
- url: https://github.com/gedoor/legado/discussions
- about: Please ask and answer questions here.
- - name: 常见问题 / Wiki
- url: https://github.com/gedoor/legado/wiki
- about: Read wiki if your are new here.
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index 64bd1ff5e..000000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-# To get started with Dependabot version updates, you'll need to specify which
-# package ecosystems to update and where the package manifests are located.
-# Please see the documentation for all configuration options:
-# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
-
-version: 2
-registries:
- maven-google:
- type: maven-repository
- # url: https://maven.google.com
- url: https://dl.google.com/dl/android/maven2/
- password: dummy
- username: dummy
- maven-central:
- type: maven-repository
- url: https://repo1.maven.org/maven2/
- password: dummy
- username: dummy
- maven-jitpack:
- type: maven-repository
- url: https://jitpack.io
- password: dummy
- username: dummy
-
-updates:
- - package-ecosystem: gradle
- directory: "/"
- schedule:
- interval: "weekly"
- registries: "*"
- open-pull-requests-limit: 20
- groups:
- kotlin_KSP:
- patterns:
- - "org.jetbrains.kotlin:*"
- - "com.google.devtools.ksp"
- # Maintain dependencies for GitHub Actions
- - package-ecosystem: "github-actions"
- directory: "/"
- schedule:
- interval: "weekly"
- - package-ecosystem: npm
- directory: "modules/web"
- schedule:
- interval: "weekly"
diff --git a/.github/scripts/cronet.sh b/.github/scripts/cronet.sh
deleted file mode 100644
index a9f293d74..000000000
--- a/.github/scripts/cronet.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/usr/bin/env bash
-
-#分支Stable Dev Beta
-branch=$1
-#api 最大偏移
-max_offset=$2
-
-[ -z $1 ] && branch=Stable
-[ -z $2 ] && max_offset=3
-[ -z $GITHUB_ENV ] && echo "Error: Unexpected github workflow environment" && exit
-
-offset=0
-
-function fetch_version() {
- # 获取最新cronet版本
- lastest_cronet_version=`curl -s "https://chromiumdash.appspot.com/fetch_releases?channel=$branch&platform=Android&num=1&offset=$offset" | jq .[0].version -r`
- echo "lastest_cronet_version: $lastest_cronet_version"
- #lastest_cronet_version=100.0.4845.0
- lastest_cronet_main_version=${lastest_cronet_version%%\.*}.0.0.0
- check_version_exit
-}
-function check_version_exit() {
- # 检查版本是否存在
- local jar_url="https://storage.googleapis.com/chromium-cronet/android/$lastest_cronet_version/Release/cronet/cronet_api.jar"
- statusCode=$(curl -s -I -w %{http_code} "$jar_url" -o /dev/null)
- if [ $statusCode == "404" ]; then
- echo "storage.googleapis.com return 404 for cronet $lastest_cronet_version"
- if [[ $max_offset > $offset ]]; then
- offset=$(expr $offset + 1)
- echo "retry with offset $offset"
- fetch_version
- else
- exit
- fi
- fi
-}
-function version_compare() {
- # 版本号比较 本地版本小于远程版本时返回0
- local local_version=$1
- local remote_version=$2
- if [[ $local_version == $remote_version ]]; then
- return 1
- fi
- if [[ $(printf '%s\n' "$1" "$2" | sort -V | head -n1) == $remote_version ]]; then
- return 1
- else
- return 0
- fi
-}
-
-# 添加变量到github env
-function write_github_env_variable() {
- echo "$1=$2" >> $GITHUB_ENV
-}
-
-function sync_proguard_rules() {
- local raw_github_git="https://raw.githubusercontent.com/chromium/chromium/$lastest_cronet_version"
- local proguard_paths=(
- components/cronet/android/cronet_combined_impl_native_proguard_golden.cfg
- )
- local proguard_rules_path="$GITHUB_WORKSPACE/app/cronet-proguard-rules.pro"
- rm -f $proguard_rules_path
- echo "fetch cronet proguard rules from upstream $raw_github_git"
- for path in ${proguard_paths[@]}
- do
- echo "fetching $path ..."
- curl "$raw_github_git/$path" >> $proguard_rules_path
- done
-}
-##########
-# 获取本地cronet版本
-path=$GITHUB_WORKSPACE/gradle.properties
-current_cronet_version=`cat $path | grep CronetVersion | sed s/CronetVersion=//`
-echo "current_cronet_version: $current_cronet_version"
-
-echo "fetch $branch release info from https://chromiumdash.appspot.com ..."
-fetch_version
-
-if version_compare $current_cronet_version $lastest_cronet_version; then
- # 更新gradle.properties
- sed -i s/CronetVersion=.*/CronetVersion=$lastest_cronet_version/ $path
- sed -i s/CronetMainVersion=.*/CronetMainVersion=$lastest_cronet_main_version/ $path
- # 更新cronet_proguard_rules.pro
- sync_proguard_rules
- # 更新cronet版本
- sed -i "s/## cronet版本: .*/## cronet版本: $lastest_cronet_version/" $GITHUB_WORKSPACE/app/src/main/assets/updateLog.md
- # 生成pull request信息
- write_github_env_variable PR_TITLE "Bump cronet from $current_cronet_version to $lastest_cronet_version"
- write_github_env_variable PR_BODY "Changes in the [Git log](https://chromium.googlesource.com/chromium/src/+log/$current_cronet_version..$lastest_cronet_version)"
- # 生成cronet flag
- write_github_env_variable cronet ok
-fi
diff --git a/.github/scripts/lzy_web.py b/.github/scripts/lzy_web.py
deleted file mode 100644
index f39d4b172..000000000
--- a/.github/scripts/lzy_web.py
+++ /dev/null
@@ -1,98 +0,0 @@
-import requests, os, datetime, sys
-
-# Cookie 中 phpdisk_info 的值
-cookie_phpdisk_info = os.environ.get('phpdisk_info')
-# Cookie 中 ylogin 的值
-cookie_ylogin = os.environ.get('ylogin')
-
-# 请求头
-headers = {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36 Edg/89.0.774.45',
- 'Accept-Language': 'zh-CN,zh;q=0.9',
- 'Referer': 'https://pc.woozooo.com/account.php?action=login'
-}
-
-# 小饼干
-cookie = {
- 'ylogin': cookie_ylogin,
- 'phpdisk_info': cookie_phpdisk_info
-}
-
-
-# 日志打印
-def log(msg):
- utc_time = datetime.datetime.utcnow()
- china_time = utc_time + datetime.timedelta(hours=8)
- print(f"[{china_time.strftime('%Y.%m.%d %H:%M:%S')}] {msg}")
-
-
-# 检查是否已登录
-def login_by_cookie():
- url_account = "https://pc.woozooo.com/account.php"
- if cookie['phpdisk_info'] is None:
- log('ERROR: 请指定 Cookie 中 phpdisk_info 的值!')
- return False
- if cookie['ylogin'] is None:
- log('ERROR: 请指定 Cookie 中 ylogin 的值!')
- return False
- res = requests.get(url_account, headers=headers, cookies=cookie, verify=True)
- if '网盘用户登录' in res.text:
- log('ERROR: 登录失败,请更新Cookie')
- return False
- else:
- log('登录成功')
- return True
-
-
-# 上传文件
-def upload_file(file_dir, folder_id):
- file_name = os.path.basename(file_dir)
- url_upload = "https://up.woozooo.com/fileup.php"
- headers['Referer'] = f'https://up.woozooo.com/mydisk.php?item=files&action=index&u={cookie_ylogin}'
- post_data = {
- "task": "1",
- "folder_id": folder_id,
- "id": "WU_FILE_0",
- "name": file_name,
- }
- files = {'upload_file': (file_name, open(file_dir, "rb"), 'application/octet-stream')}
- res = requests.post(url_upload, data=post_data, files=files, headers=headers, cookies=cookie, timeout=120).json()
- log(f"{file_dir} -> {res['info']}")
- return res['zt'] == 1
-
-
-# 上传文件夹内的文件
-def upload_folder(folder_dir, folder_id):
- file_list = sorted(os.listdir(folder_dir), reverse=True)
- for file in file_list:
- path = os.path.join(folder_dir, file)
- if os.path.isfile(path):
- upload_file(path, folder_id)
- else:
- upload_folder(path, folder_id)
-
-
-# 上传
-def upload(dir, folder_id):
- if dir is None:
- log('ERROR: 请指定上传的文件路径')
- return
- if folder_id is None:
- log('ERROR: 请指定蓝奏云的文件夹id')
- return
- if os.path.isfile(dir):
- upload_file(dir, str(folder_id))
- else:
- upload_folder(dir, str(folder_id))
-
-
-if __name__ == '__main__':
- argv = sys.argv[1:]
- if len(argv) != 2:
- log('ERROR: 参数错误,请以这种格式重新尝试\npython lzy_web.py 需上传的路径 蓝奏云文件夹id')
- # 需上传的路径
- upload_path = argv[0]
- # 蓝奏云文件夹id
- lzy_folder_id = argv[1]
- if login_by_cookie():
- upload(upload_path, lzy_folder_id)
diff --git a/.github/scripts/tg_bot.py b/.github/scripts/tg_bot.py
deleted file mode 100644
index 88a3a8bb5..000000000
--- a/.github/scripts/tg_bot.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import os, sys, telebot
-
-# 上传文件
-def upload_file(tb, chat_id, file_dir):
- doc = open(file_dir, 'rb')
- tb.send_document(chat_id, doc)
-
-# 上传文件夹内的文件
-def upload_folder(tb, chat_id, folder_dir):
- file_list = sorted(os.listdir(folder_dir))
- for file in file_list:
- path = os.path.join(folder_dir, file)
- if os.path.isfile(path):
- upload_file(tb, chat_id, path)
- else:
- upload_folder(tb, chat_id, path)
-
-# 上传
-def upload(tb, chat_id, dir):
- if tb is None:
- log('ERROR: 输入正确的token')
- return
- if chat_id is None:
- log('ERROR: 输入正确的chat_id')
- return
- if dir is None:
- log('ERROR: 请指定上传的文件路径')
- return
- if os.path.isfile(dir):
- upload_file(tb, chat_id, dir)
- else:
- upload_folder(tb, chat_id, dir)
-
-if __name__ == '__main__':
- argv = sys.argv[1:]
- if len(argv) != 3:
- log('ERROR: 参数错误,请以这种格式重新尝试\npython tg_bot.py $token $chat_id 待上传的路径')
- # Token
- TOKEN = argv[0]
- # chat_id
- chat_id = argv[1]
- # 待上传文件的路径
- upload_path = argv[2]
- #创建连接
- tb = telebot.TeleBot(TOKEN)
- #开始上传
- upload(tb, chat_id, upload_path)
diff --git a/.github/workflows/autoupdatefork.yml b/.github/workflows/autoupdatefork.yml
deleted file mode 100644
index 4206fd2b7..000000000
--- a/.github/workflows/autoupdatefork.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-#更新fork
-name: update fork
-
-on:
- schedule:
- - cron: '0 16 * * *' #0点定时任务
-
-jobs:
- build:
- runs-on: ubuntu-latest
- if: ${{ github.event.repository.owner.id == github.event.sender.id && github.actor != 'gedoor' }}
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set env
- run: |
- git config --global user.email "github-actions@github.com"
- git config --global user.name "github-actions"
- - name: Update fork
- run: |
- git remote add upstream https://github.com/gedoor/legado.git
- git remote -v
- git fetch upstream
- git checkout master
- git merge upstream/master
- git push origin master
diff --git a/.github/workflows/cronet.yml b/.github/workflows/cronet.yml
deleted file mode 100644
index 80ced27be..000000000
--- a/.github/workflows/cronet.yml
+++ /dev/null
@@ -1,53 +0,0 @@
-name: Update Cronet
-
-on:
- schedule:
- # 周一北京时间9点
- - cron: 0 1 * * 1
- workflow_dispatch:
-
-jobs:
- build:
- runs-on: ubuntu-latest
- if: ${{ github.repository == 'gedoor/legado' }}
- steps:
- - uses: actions/checkout@v4
-
- - name: Check Cronet Updates
- run: source .github/scripts/cronet.sh
-
- - name: Set up JDK 17
- if: ${{ env.cronet == 'ok' }}
- uses: actions/setup-java@v4
- with:
- distribution: 'temurin'
- java-version: 17
-
- - uses: gradle/actions/setup-gradle@v4
- if: ${{ env.cronet == 'ok' }}
-
- - name: Download Cronet
- if: ${{ env.cronet == 'ok' }}
- run: |
- chmod +x gradlew
- ./gradlew app:downloadCronet
-
- - name: Create Pull Request
- if: ${{ env.cronet == 'ok' }}
- uses: peter-evans/create-pull-request@v7
- continue-on-error: true
- with:
- token: ${{ secrets.ACTIONS_TOKEN }}
- title: ${{ env.PR_TITLE }}
- commit-message: |
- ${{ env.PR_TITLE }}
- - ${{ env.PR_BODY }}
- body: ${{ env.PR_BODY }}
- branch: cronet
- delete-branch: true
- add-paths: |
- *cronet*jar
- *cronet.json
- *updateLog.md
- *gradle.properties
- *cronet-proguard-rules.pro
diff --git a/.github/workflows/legado.jks b/.github/workflows/legado.jks
deleted file mode 100644
index 89ea725fd..000000000
Binary files a/.github/workflows/legado.jks and /dev/null differ
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index a2b8f367b..000000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,140 +0,0 @@
-name: Release Build
-
-on:
-# push:
-# branches:
-# - master
-# paths:
-# - 'CHANGELOG.md'
- workflow_dispatch:
-
-jobs:
- prepare:
- runs-on: ubuntu-latest
- if: github.event_name != 'pull_request' && github.ref == 'refs/heads/master'
- outputs:
- version: ${{ steps.set-ver.outputs.version }}
- play: ${{ steps.check.outputs.play }}
- sign: ${{ steps.check.outputs.sign }}
- steps:
- - id: set-ver
- run: |
- echo "version=$(date -d "8 hour" -u +3.%y.%m%d%H)" >> $GITHUB_OUTPUT
- - id: check
- run: |
- if [ ! -z "${{ secrets.RELEASE_KEY_STORE }}" ]; then
- echo "sign=yes" >> $GITHUB_OUTPUT
- fi
- if [ ! -z "${{ secrets.SERVICE_ACCOUNT_JSON }}" ]; then
- echo "play=yes" >> $GITHUB_OUTPUT
- fi
-
- build:
- needs: prepare
- if: ${{ needs.prepare.outputs.sign }}
- strategy:
- matrix:
- product: [ app, google ]
- fail-fast: false
- runs-on: ubuntu-latest
- env:
- product: ${{ matrix.product }}
- VERSION: ${{ needs.prepare.outputs.version }}
- play: ${{ needs.prepare.outputs.play }}
- steps:
- - uses: actions/checkout@v4
-
- - name: Set up JDK 17
- uses: actions/setup-java@v4
- with:
- distribution: 'temurin'
- java-version: 17
-
- - name: Release Apk Sign
- run: |
- # not use this output
- # echo "KeyStore=yes" >> $GITHUB_OUTPUT
- echo -e "\n" >> gradle.properties
- echo RELEASE_KEY_ALIAS='${{ secrets.RELEASE_KEY_ALIAS }}' >> gradle.properties
- echo RELEASE_KEY_PASSWORD='${{ secrets.RELEASE_KEY_PASSWORD }}' >> gradle.properties
- echo RELEASE_STORE_PASSWORD='${{ secrets.RELEASE_STORE_PASSWORD }}' >> gradle.properties
- echo RELEASE_STORE_FILE='./key.jks' >> gradle.properties
- echo ${{ secrets.RELEASE_KEY_STORE }} | base64 --decode > $GITHUB_WORKSPACE/app/key.jks
-
- - name: Unify Version Name
- run: |
- echo "统一版本号"
- sed "/def version/c def version = \"${{ env.VERSION }}\"" $GITHUB_WORKSPACE/app/build.gradle -i
-
- - name: Set up Gradle
- uses: gradle/actions/setup-gradle@v4
-
- - name: Build With Gradle
- run: |
- echo "开始进行${{ env.product }}构建"
- chmod +x gradlew
- ./gradlew assemble${{ env.product }}release --build-cache --parallel --daemon --warning-mode all
-
- - name: Organize the Files
- run: |
- mkdir -p ${{ github.workspace }}/apk/
- cp -rf ${{ github.workspace }}/app/build/outputs/apk/*/*/*.apk ${{ github.workspace }}/apk/
-
- - name: Upload App To Artifact
- uses: actions/upload-artifact@v4
- with:
- name: legado_${{ env.product }}
- path: ${{ github.workspace }}/apk/*.apk
-
- - name: Release
- if: ${{ env.product == 'app' }}
- uses: softprops/action-gh-release@v2
- with:
- name: legado_app_${{ env.VERSION }}
- tag_name: ${{ env.VERSION }}
- body_path: ${{ github.workspace }}/CHANGELOG.md
- draft: false
- prerelease: false
- files: ${{ github.workspace }}/apk/legado_app_*.apk
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Prepare For GooglePlay
- if: env.product == 'google' && env.play == 'yes'
- run: |
- mkdir -p ReleaseNotes
- ln -s ${{ github.workspace }}/CHANGELOG.md ReleaseNotes/whatsnew-en-US
- ln -s ${{ github.workspace }}/CHANGELOG.md ReleaseNotes/whatsnew-zh-CN
-
- - name: Release To GooglePlay
- if: env.product == 'google' && env.play == 'yes'
- uses: r0adkll/upload-google-play@v1
- with:
- serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
- packageName: io.legado.play
- releaseFiles: ${{ github.workspace }}/apk/legado_google_*.apk
- track: production
- whatsNewDirectory: ${{ github.workspace }}/ReleaseNotes
-
- - name: Push Assets To "release" Branch
- if: ${{ github.actor == 'gedoor' }}
- run: |
- cd $GITHUB_WORKSPACE/apk/
- git init
- git checkout -b release
- git config --global user.name "github-actions[bot]"
- git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
- git remote add origin "https://${{ github.actor }}:${{ secrets.ACTIONS_TOKEN }}@github.com/${{ github.actor }}/release"
- git add *.apk
- git commit -m "${{ env.VERSION }}"
- git push -f -u origin release
-
- - name: Purge Jsdelivr Cache
- if: ${{ github.actor == 'gedoor' }}
- run: |
- result=$(curl -s https://purge.jsdelivr.net/gh/${{ github.actor }}/release@release/)
- if echo $result |grep -q 'success.*true'; then
- echo "jsdelivr缓存更新成功"
- else
- echo $result
- fi
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
deleted file mode 100644
index bfa2c0d0c..000000000
--- a/.github/workflows/stale.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
-#
-# You can adjust the behavior by modifying this file.
-# For more information, see:
-# https://github.com/actions/stale
-name: closeStaleIssue
-
-on:
- schedule:
- # 每5天北京时间9点
- - cron: '30 1 1/5 * *'
- workflow_dispatch:
-
-jobs:
- stale:
-
- runs-on: ubuntu-latest
- if: ${{ github.repository == 'gedoor/legado' }}
- permissions:
- issues: write
-
- steps:
- - uses: actions/stale@v9
- with:
- repo-token: ${{ secrets.GITHUB_TOKEN }}
- stale-issue-message: '由于长期没有状态更新,该问题将于5天后自动关闭。如有需要可重新打开。'
- days-before-stale: 30
- days-before-close: 5
- operations-per-run: 100
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
deleted file mode 100644
index 2a7fdc83a..000000000
--- a/.github/workflows/test.yml
+++ /dev/null
@@ -1,278 +0,0 @@
-name: Test Build
-
-on:
- push:
- branches:
- - master
- paths:
- - '**'
- # - '!**/assets/**'
- # - '!**.md'
- - '!**/ISSUE_TEMPLATE/**'
- - '!**/modules/web/**'
- pull_request:
- paths-ignore:
- - '**/modules/web/**'
- workflow_run:
- workflows: [Build Web]
- branches: [master]
- types:
- - completed
- workflow_dispatch:
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
-
- prepare:
- runs-on: ubuntu-latest
- if: ${{ !startsWith(github.event.head_commit.message, 'Merge pull request') }}
- outputs:
- version: ${{ steps.set-ver.outputs.version }}
- versionL: ${{ steps.set-ver.outputs.versionL }}
- lanzou: ${{ steps.check.outputs.lanzou }}
- telegram: ${{ steps.check.outputs.telegram }}
- steps:
- - id: set-ver
- run: |
- echo "version=$(date -d "8 hour" -u +3.%y.%m%d%H)" >> $GITHUB_OUTPUT
- echo "versionL=$(date -d "8 hour" -u +3.%y.%m%d%H%M)" >> $GITHUB_OUTPUT
- - id: check
- run: |
- if [ ${{ secrets.LANZOU_ID }} ]; then
- echo "lanzou=yes" >> $GITHUB_OUTPUT
- fi
- if [ ${{ secrets.BOT_TOKEN }} ]; then
- echo "telegram=yes" >> $GITHUB_OUTPUT
- fi
-
- build:
- needs: prepare
- strategy:
- matrix:
- product: [ app ]
- type: [ release, releaseA ]
- fail-fast: false
- runs-on: ubuntu-latest
- env:
- product: ${{ matrix.product }}
- type: ${{ matrix.type }}
- VERSION: ${{ needs.prepare.outputs.version }}
- VERSIONL: ${{ needs.prepare.outputs.versionL }}
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- - name: Set up JDK 17
- uses: actions/setup-java@v4
- with:
- distribution: 'temurin'
- java-version: 17
- - name: Clear 18PlusList.txt
- run: |
- echo "清空18PlusList.txt"
- echo "">$GITHUB_WORKSPACE/app/src/main/assets/18PlusList.txt
- - name: Release Apk Sign
- run: |
- echo "给apk增加签名"
- cp $GITHUB_WORKSPACE/.github/workflows/legado.jks $GITHUB_WORKSPACE/app/legado.jks
- sed '$a\RELEASE_STORE_FILE=./legado.jks' $GITHUB_WORKSPACE/gradle.properties -i
- sed '$a\RELEASE_KEY_ALIAS=legado' $GITHUB_WORKSPACE/gradle.properties -i
- sed '$a\RELEASE_STORE_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i
- sed '$a\RELEASE_KEY_PASSWORD=gedoor_legado' $GITHUB_WORKSPACE/gradle.properties -i
-
- - name: Set up Gradle
- uses: gradle/actions/setup-gradle@v4
-
- - name: Build With Gradle
- continue-on-error: true
- run: |
- if [ ${{ env.type }} == 'release' ]; then
- typeName="原包名"
- else
- typeName="共存"
- sed "s/'.release'/'.releaseA'/" $GITHUB_WORKSPACE/app/build.gradle -i
- sed 's/.release/.releaseA/' $GITHUB_WORKSPACE/app/google-services.json -i
- fi
- echo "统一版本号"
- sed "/def version/c def version = \"${{ env.VERSION }}\"" $GITHUB_WORKSPACE/app/build.gradle -i
- echo "开始${{ env.product }}$typeName构建"
- chmod +x gradlew
- ./gradlew assemble${{ env.product }}release --build-cache --parallel --daemon --warning-mode all
- echo "修改APK文件名"
- mkdir -p ${{ github.workspace }}/apk/
- for file in `ls ${{ github.workspace }}/app/build/outputs/apk/*/*/*.apk`; do
- mv "$file" ${{ github.workspace }}/apk/legado_${{ env.product }}_${{ env.VERSIONL }}_$typeName.apk
- done
- echo "移动mapping文件"
- mkdir -p ${{ github.workspace }}/mapping/
- for file in `ls ${{ github.workspace }}/app/build/outputs/mapping/*/mapping.txt`; do
- mv "$file" ${{ github.workspace }}/mapping/mapping.txt
- done
-
- - name: Move Missing Rules Files
- run: |
- echo "移动missing_rules.txt文件"
- mkdir -p ${{ github.workspace }}/mapping/
- for file in `ls ${{ github.workspace }}/app/build/outputs/mapping/*/missing_rules.txt`; do
- mv "$file" ${{ github.workspace }}/mapping/missing_rules.txt
- done
-
- - name: Upload Missing Rules File To Artifact
- uses: actions/upload-artifact@v4
- with:
- name: legado.${{ env.product }}.${{ env.type }}.mapping.missing_rules
- if-no-files-found: ignore
- path: ${{ github.workspace }}/mapping/missing_rules.txt
-
- - name: Check Build production
- run: |
- if [ ! -d ${{ github.workspace }}/apk ]; then
- echo "Build production not found! Check gradle logs."
- exit 1
- fi
- cd ${{ github.workspace }}/apk/
- if [ ! -e legado_*.apk ]; then
- echo "Build production not found! Check gradle logs."
- exit 1
- fi
-
- - name: Upload App To Artifact
- uses: actions/upload-artifact@v4
- with:
- name: legado.${{ env.product }}.${{ env.type }}
- if-no-files-found: ignore
- path: ${{ github.workspace }}/apk/*.apk
-
- - name: Upload Mapping File To Artifact
- uses: actions/upload-artifact@v4
- with:
- name: legado.${{ env.product }}.${{ env.type }}.mapping
- if-no-files-found: ignore
- path: ${{ github.workspace }}/mapping/mapping.txt
-
- prerelease:
- needs: [ prepare, build ]
- if: github.event_name != 'pull_request' && github.repository == 'gedoor/legado'
- runs-on: ubuntu-latest
- env:
- VERSION: ${{ needs.prepare.outputs.version }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/download-artifact@v4
- with:
- path: apk/
-
- - working-directory: apk/
- run: |
- mv */*.apk .
- rm -rf */
-
- for file in `ls *.apk`; do
- if [[ "$file" == *原包名* ]]; then
- mv "$file" $(echo $file | sed s/原包名/release/)
- else
- mv "$file" $(echo $file | sed s/共存/releaseA/)
- fi
- done
-
- - name: Delete Pre-Release
- run: |
- if gh release view beta &>/dev/null; then
- gh release delete beta -y
- fi
- env:
- GH_TOKEN: ${{ github.token }}
-
- - name: Create or update beta tag
- uses: richardsimko/update-tag@v1
- with:
- tag_name: beta
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Publish Pre-Release
- uses: ncipollo/release-action@v1
- with:
- name: legado_app_${{ env.VERSION }}
- tag: "beta"
- body: |
- 此版本为测试版,签名与正式版不同,可能存在不稳定情况,升级前请务必备份好数据。
- releaseA 为共存版本,可同时安装使用,功能没有区别。
- prerelease: true
- artifacts: ${{ github.workspace }}/apk/*.apk
-
- lanzou:
- needs: [ prepare, build ]
- if: ${{ github.event_name != 'pull_request' && needs.prepare.outputs.lanzou == 'yes' }}
- runs-on: ubuntu-latest
- env:
- # 登录蓝奏云后在控制台运行document.cookie
- ylogin: ${{ secrets.LANZOU_ID }}
- phpdisk_info: ${{ secrets.LANZOU_PSD }}
- # 蓝奏云里的文件夹ID(阅读3测试版:2670621)
- LANZOU_FOLDER_ID: ${{ secrets.LANZOU_FOLDER_ID }}
- #蓝奏云分享链接
- LANZOU_URL: ${{ secrets.LANZOU_URL }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/download-artifact@v4
- with:
- path: apk/
- - working-directory: apk/
- run: mv */*.apk . ;rm -rf */
- - name: Upload To Lanzou
- continue-on-error: true
- run: |
- path="$GITHUB_WORKSPACE/apk/"
- python3 $GITHUB_WORKSPACE/.github/scripts/lzy_web.py "$path" "$LANZOU_FOLDER_ID"
- echo "[$(date -u -d '+8 hour' '+%Y.%m.%d %H:%M:%S')] 分享链接: $LANZOU_URL"
-
- test_Branch:
- needs: [ prepare, build ]
- runs-on: ubuntu-latest
- if: ${{ github.event_name != 'pull_request' && github.actor == 'gedoor' }}
- steps:
- - uses: actions/checkout@v4
- - uses: actions/download-artifact@v4
- with:
- path: apk/
- - working-directory: apk/
- run: mv */*.apk . ;rm -rf */
- - name: Push To "test" Branch
- run: |
- cd $GITHUB_WORKSPACE/apk/
- git init
- git checkout -b test
- git config --global user.name "github-actions[bot]"
- git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
- git remote add origin "https://${{ github.actor }}:${{ secrets.ACTIONS_TOKEN }}@github.com/${{ github.actor }}/release"
- git add *.apk
- git commit -m "${{ needs.prepare.outputs.versionL }}"
- git push -f -u origin test
-
- telegram:
- needs: [ prepare, build ]
- if: ${{ github.event_name != 'pull_request' && needs.prepare.outputs.telegram == 'yes' }}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: actions/download-artifact@v4
- with:
- path: apk/
- - working-directory: apk/
- run: |
- for file in `ls */*.apk`; do
- mv "$file" "$(echo "$file"|sed -e 's#.*\/##g' -e "s/_/ /g" -e 's/legado/阅读/')"
- done
- rm -rf */
- - name: Post to channel
- uses: xireiki/channel-post@v1
- with:
- chat_id: ${{ secrets.CHANNEL_ID }}
- bot_token: ${{ secrets.BOT_TOKEN }}
- context: "#阅读 #Legado #Beta ${{ needs.prepare.outputs.versionL }}"
- path: apk/*
- method: sendFile
diff --git a/.github/workflows/web.yml b/.github/workflows/web.yml
deleted file mode 100644
index 8a15e1eee..000000000
--- a/.github/workflows/web.yml
+++ /dev/null
@@ -1,65 +0,0 @@
-name: Build Web
-
-on:
- push:
- branches:
- - master
- paths:
- - '**/modules/web/**'
- pull_request:
- paths:
- - '**/modules/web/**'
- workflow_dispatch:
-
-env:
- UPSTREAM_REPOSITORY: gedoor/legado
-
-jobs:
- build:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Install Node.js
- uses: actions/setup-node@v4
- with:
- node-version: 22
-
- - uses: pnpm/action-setup@v4
- name: Install pnpm
- id: pnpm-install
- with:
- version: 9
- run_install: false
-
- - name: Get pnpm store directory
- id: pnpm-cache
- shell: bash
- run: |
- echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
-
- - uses: actions/cache@v4
- name: Setup pnpm cache
- with:
- path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
- key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/web/package.json') }}
- restore-keys: |
- ${{ runner.os }}-pnpm-store-
-
- - name: Build and move files
- working-directory: modules/web
- run: |
- pnpm i
- pnpm build
- version="v$(date -d "8 hour" -u +3.%y.%m%d%H)"
- echo "APP_VER=$version" >> $GITHUB_ENV
-
- - name: push changes
- if: ${{ github.event_name != 'pull_request' && github.repository == env.UPSTREAM_REPOSITORY }}
- uses: stefanzweifel/git-auto-commit-action@v5.1.0
- with:
- commit_message: Bump web ${{ env.APP_VER}}
- file_pattern: app/src/main/assets/web/vue/
-
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index d6401dcba..000000000
--- a/.gitignore
+++ /dev/null
@@ -1,18 +0,0 @@
-*.iml
-.gradle
-local.properties
-.DS_Store
-/build
-build/
-/captures
-.externalNativeBuild
-/release
-/tmp
-node_modules/
-/app/app
-/app/google
-/app/gradle.properties
-package-lock.json
-.idea/
-# Kotlin 2.0
-.kotlin/
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 1e3d601a0..000000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,11 +0,0 @@
-**2022/10/02**
-
-* 更新cronet: 106.0.5249.79
-* 正文选择菜单朗读按钮长按可切换朗读选择内容和从选择开始处一直朗读
-* 源编辑输入框设置最大行数12,在行数特别多的时候更容易滚动到其它输入
-* 修复某些情况下无法搜索到标题的bug,净化规则较多的可能会降低搜索速度 by Xwite
-* 修复文件类书源换源后阅读bug by Xwite
-* Cronet 支持DnsHttpsSvcb by g2s20150909
-* 修复web进度同步问题 by 821938089
-* 启用混淆以减小app大小 有bug请带日志反馈
-* 其它一些优化
diff --git a/English.md b/English.md
deleted file mode 100644
index 9cc6b9800..000000000
--- a/English.md
+++ /dev/null
@@ -1,149 +0,0 @@
-# [English](English.md) [中文](README.md)
-
-[](https://play.google.com/store/apps/details?id=io.legado.play.release)
-
-
-
-
-
-Legado / 开源阅读
-

-

-
-
- 
s;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;r>n&&!b.relative[e[n].type];n++);return Ce(s>1&&we(c),s>1&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,n>s&&Ee(e.slice(s,n)),r>n&&Ee(e=e.slice(n)),r>n&&xe(e))}c.push(t)}return we(c)}var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;r>n;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\x00-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\x00"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];for(i=t.getElementsByName(e),r=0;o=i[r++];)if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){return"undefined"!=typeof t.getElementsByClassName&&E?t.getElementsByClassName(e):void 0},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0","
"],col:[2,"
"],tr:[2,"","
"],td:[3,"
"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|?\w+;/;me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v)for(n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;l--;)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){for(l=(t=(t||"").match(R)||[""]).length;l--;)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){for(f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;o--;)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t","