diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json
index ff7d3e24..ed001e56 100644
--- a/.changelog/lang_zh-Hans.json
+++ b/.changelog/lang_zh-Hans.json
@@ -1,12 +1,13 @@
{
"$data": {
"v6.7.0": {
- "released_date": "2025/07/22",
+ "released_date": "2025/09/09",
"feature": [
"zip 模块, 用于文件压缩与解压缩操作 (Ref to [Auto.js Pro](https://g.pro.autojs.org/)) (参阅 项目文档 > [Zip](https://docs.autojs6.com/#/zip))",
"mediainfo 模块, 用于查看媒体文件的详细信息 (参阅 项目文档 > [媒体信息](https://docs.autojs6.com/#/mediainfo))",
"UiObject#isShifted 方法, 用于检测控件位置变化",
- "设置页面支持应用启动器图标设置选项 _[`issue #405`](http://issues.autojs6.com/405)_"
+ "设置页面支持应用启动器图标设置选项 _[`issue #405`](http://issues.autojs6.com/405)_",
+ "JS 脚本工具 (run-scrapers.mjs) 用于自动更新 Gradle 构建脚本锚点数据/README 通用数据/README 模板数据"
],
"fix": [
"使用 XML 语法将 JavaScript 表达式作为属性值时, this 对象可能出现指向错误的问题",
@@ -29,9 +30,9 @@
"应用启动器图标支持自适应图标特性 _[`issue #405`](http://issues.autojs6.com/405)_"
],
"dependency": [
- "附加 Androidx Core (KTX) 版本 1.16.0",
- "升级 Gradle 版本 8.14 -> 8.14.2",
- "升级 Apache Commons 版本 3.16.0 -> 3.17.0",
+ "附加 Androidx Core (KTX) 版本 1.15.0",
+ "升级 Gradle 版本 8.14 -> 8.14.3",
+ "升级 Apache Commons 版本 3.16.0 -> 3.18.0",
"升级 Retrofit2 Retrofit 版本 2.11.0 -> 2.12.0",
"升级 Retrofit2 Converter Gson 版本 2.11.0 -> 2.12.0",
"升级 Retrofit2 RxJava2 版本 2.11.0 -> 2.12.0",
diff --git a/.python/generate_markdown.py b/.python/generate_markdown.py
index b6157f28..64f6dce9 100644
--- a/.python/generate_markdown.py
+++ b/.python/generate_markdown.py
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
import locale
-import sys
# 设置语言环境为 UTF-8
locale.setlocale(locale.LC_ALL, '')
@@ -8,9 +7,6 @@ encoding = locale.getpreferredencoding()
if encoding.lower() != 'utf-8':
# 强制使用 UTF-8 编码
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
- # 如果 locale 无法设置, 使用以下方式
- # sys.stdout.reconfigure(encoding='utf-8')
- # sys.stderr.reconfigure(encoding='utf-8')
from jinja2 import Environment, FileSystemLoader, StrictUndefined
from collections import defaultdict
@@ -53,7 +49,101 @@ env = Environment(
undefined=StrictUndefined,
)
-# 读取模板文件
+# 从 version.properties 读取 JDK 相关限制, 以便注入到 merged_data
+def _load_version_properties(props_path: str) -> dict:
+ props = {}
+ try:
+ with open(props_path, 'r', encoding='utf-8') as f:
+ for raw in f.read().splitlines():
+ line = raw.strip()
+ if not line or line.startswith('#') or line.startswith('!'):
+ continue
+ sep = line.find('=')
+ if sep <= 0:
+ continue
+ key = line[:sep].strip()
+ val = line[sep + 1 :].strip()
+ props[key] = val
+ except FileNotFoundError:
+ print(f'[warn] version.properties not found at {props_path}, skip injecting JDK constraints')
+ except Exception as e:
+ print(f'[warn] Failed to read version.properties: {e}')
+ return props
+
+_version_props_path = os.path.join(project_root_dir, 'version.properties')
+_version_props = _load_version_properties(_version_props_path)
+
+_jdk_min_supported = _version_props.get('JAVA_VERSION_MIN_SUPPORTED')
+_jdk_min_suggested = _version_props.get('JAVA_VERSION_MIN_SUGGESTED')
+_jdk_max_supported = _version_props.get('JAVA_VERSION_MAX_SUPPORTED')
+_android_studio_min_supported = _version_props.get('MIN_SUPPORTED_ANDROID_STUDIO_IDE_VERSION')
+_intellij_idea_min_supported = _version_props.get('MIN_SUPPORTED_INTELLIJ_IDEA_IDE_VERSION')
+
+# 在加载模板前, 先更新模板中的 Android Studio 与 IntelliJ IDEA Badge 版本
+def update_readme_badge_versions():
+ """
+ 读取 .readme/template_readme.md, 将 Android Studio 与 IntelliJ IDEA 的徽标版本替换为
+ version.properties 中的最小支持版本:
+ - MIN_SUPPORTED_ANDROID_STUDIO_IDE_VERSION
+ - MIN_SUPPORTED_INTELLIJ_IDEA_IDE_VERSION
+ """
+ template_path = os.path.join(readme_root_dir, 'template_readme.md')
+ try:
+ with open(template_path, 'r', encoding='utf-8') as f:
+ data = f.read()
+ except FileNotFoundError:
+ print(f'[warn] template_readme.md not found at {template_path}, skip badge update')
+ return
+ except Exception as e:
+ print(f'[warn] Failed to read template_readme.md: {e}')
+ return
+
+ # 与原逻辑等价的正则片段
+ prefix = r' ]*?src="https://img\.shields\.io/badge/'
+ android_fragment = r'android(?:%20|\s)studio'
+ idea_fragment = r'intellij(?:%20|\s)idea'
+ # 捕获 2024.1 或 2024.1.2 这类版本, 末尾带一个 '+'
+ version_group = r'.*?-([0-9]{4}\.[0-9]+(?:\.[0-9]+)?)\+'
+
+ re_android = re.compile(prefix + android_fragment + version_group, re.IGNORECASE)
+ re_idea = re.compile(prefix + idea_fragment + version_group, re.IGNORECASE)
+
+ original = data
+
+ if _android_studio_min_supported:
+ def _repl_android(m):
+ old = m.group(1)
+ if old != _android_studio_min_supported:
+ return m.group(0).replace(old, _android_studio_min_supported)
+ return m.group(0)
+ data = re_android.sub(_repl_android, data)
+
+ if _intellij_idea_min_supported:
+ def _repl_idea(m):
+ old = m.group(1)
+ if old != _intellij_idea_min_supported:
+ return m.group(0).replace(old, _intellij_idea_min_supported)
+ return m.group(0)
+ data = re_idea.sub(_repl_idea, data)
+
+ if data == original:
+ return
+
+ try:
+ with open(template_path, 'w', encoding='utf-8') as f:
+ f.write(data)
+ print(f'Updated badge(s) in {template_path}')
+ except Exception as e:
+ print(f'[warn] Failed to write template_readme.md: {e}')
+
+# 执行模板内徽标版本更新, 并清空 Jinja2 缓存后再获取模板
+update_readme_badge_versions()
+try:
+ env.cache.clear() # 确保重新读取更新后的模板文件
+except Exception:
+ pass
+
+# 读取模板文件 (在更新徽标版本之后)
template_readme = env.get_template('template_readme.md')
template_changelog = env.get_template('template_changelog.md')
@@ -111,6 +201,14 @@ def init_languages():
# 合并共用 JSON 数据
merged_data = {**common_data, **processed_data}
+ # 注入 JDK 版本约束 (来自 version.properties)
+ if _jdk_min_supported is not None:
+ merged_data['jdk_min_supported'] = str(_jdk_min_supported)
+ if _jdk_min_suggested is not None:
+ merged_data['jdk_min_suggested'] = str(_jdk_min_suggested)
+ if _jdk_max_supported is not None:
+ merged_data['jdk_max_supported'] = str(_jdk_max_supported)
+
# 处理日期转换标记
for key, value in merged_data.items():
if key.startswith('var_date_'):
diff --git a/.readme/README-ar.md b/.readme/README-ar.md
index 3c0bd085..db408794 100644
--- a/.readme/README-ar.md
+++ b/.readme/README-ar.md
@@ -8,16 +8,16 @@
أداة أتمتة JavaScript لنظام Android مدعومة بخدمة الوصول
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
التواريخ في الجدول هي تقديرات وقد تختلف عن الواقع.
@@ -76,7 +76,7 @@
في الجدول، تشير البيانات في العمود `تاريخ نهاية التطوير` التي تحتوي على أقواس مربعة (`[]`) إلى أن مشروع المصدر المفتوح غير متاح مؤقتًا.
-في الجدول، يتم احتساب البيانات في العمود `فترة الصيانة النشطة` التي تحتوي على أقواس زاوية (`<>`) حتى 17 August 2025.
+في الجدول، يتم احتساب البيانات في العمود `فترة الصيانة النشطة` التي تحتوي على أقواس زاوية (`<>`) حتى 9 September 2025.
******
@@ -133,7 +133,7 @@
* تكييف ألوان الموضوع [ التجميع / الموقع / البحث / السجل / التكييف التلقائي للسطوع والتباين / ... ]
* دعم وضع الليل [ صفحة الإعدادات / صفحة الوثائق / صفحة تحليل التخطيط / النافذة العائمة / ... ]
* دعم الاتصال بـ [المكون الإضافي لـ VSCode](http://vscext-project.autojs6.com) بطرق الاتصال عبر الشبكة المحلية (LAN) و ADB
-* تم ترقية محرك [Rhino](https://github.com/mozilla/rhino/) من [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) إلى [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)
+* تم ترقية محرك [Rhino](https://github.com/mozilla/rhino/) من [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) إلى [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (تم التحديث في 11 April 2025)
* دعم هروب نقطة الرمز Unicode [للأحرف متعددة المستويات](https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84#%E7%AC%AC%E4%B8%80%E8%BC%94%E5%8A%A9%E5%B9%B3%E9%9D%A2)
```javascript
'\u{1D160}'; /* تمثل "𝅘𝅥𝅮", طريقة تقليدية: '\uD834\uDD60'. */
@@ -307,12 +307,12 @@
#### تحضير Android Studio
-قم بتنزيل إصدار `Android Studio Narwhal Feature Drop | 2025.1.2` (حدد أحدها حسب الحاجة):
+قم بتنزيل إصدار `Android Studio Narwhal 3 Feature Drop | 2025.1.3` (حدد أحدها حسب الحاجة):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> ملاحظة: تاريخ الإصدار بالنسخة المذكورة أعلاه هو 31 July 2025. إذا كنت بحاجة إلى تنزيل إصدار آخر، أو إذا كان الرابط المذكور غير صالح، يمكنك زيارة [أرشيف إصدارات Android Studio](https://developer.android.com/studio/archive?hl=en).
+> ملاحظة: تاريخ الإصدار بالنسخة المذكورة أعلاه هو 2 September 2025. إذا كنت بحاجة إلى تنزيل إصدار آخر، أو إذا كان الرابط المذكور غير صالح، يمكنك زيارة [أرشيف إصدارات Android Studio](https://developer.android.com/studio/archive?hl=en).
قم بتثبيت أو فك ضغط الملف المذكور سابقًا، ثم قم بتشغيل برنامج Android Studio (مثل `"D:\android-studio\bin\studio64.exe"`).
@@ -361,9 +361,9 @@ File (ملف) | Settings (إعدادات) | Appearance & Behavior (المظهر
#### تحضير JDK
-يعتمد مشروع AutoJs6 على إصدار `JDK (مجموعة تطوير جافا)` بإصدار لا يقل عن `17`، ولكن يفضل الإصدار الذي لا يقل عن `19`.
+يعتمد مشروع AutoJs6 على إصدار `JDK (مجموعة تطوير جافا)` بإصدار لا يقل عن `17`، ولكن يفضل الإصدار الذي لا يقل عن `21`.
-اعتبارًا من 17 August 2025، الإصدار الأقصى المدعوم من JDK لمشروع AutoJs6 هو `24`.
+اعتبارًا من 9 September 2025، الإصدار الأقصى المدعوم من JDK لمشروع AutoJs6 هو `24`.
> ملاحظة: إذا كان نظام الكمبيوتر يحتوي على JDK والإصدار يفي بالمتطلبات المذكورة أعلاه، فيمكنك تخطي هذا القسم.
@@ -514,19 +514,19 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
شكرًا لكل من ساهم في تطوير مشروع AutoJs6.
-| المساهمون | عدد الإرساليات | أحدث الإرساليات |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| المساهمون | عدد الإرساليات | أحدث الإرساليات |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-تم تحديث البيانات في 27 May 2025.
+تم تحديث البيانات في 6 September 2025.
تم تصنيف سجلات البيانات بترتيب تنازلي حسب `أحدث الإرساليات`.
@@ -547,11 +547,12 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/README-en.md b/.readme/README-en.md
index 9f26d3a4..bd54346c 100644
--- a/.readme/README-en.md
+++ b/.readme/README-en.md
@@ -8,16 +8,16 @@
JavaScript automation tool supporting accessibility service on the Android platform
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ The table below lists some Auto.js-related projects (sorted by development date)
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
The dates in the table are estimated and may differ from actual dates.
@@ -76,7 +76,7 @@ Auto.js Pro 7/8/9 in the table are paid versions, and the rest are free open-sou
In the table, data in the `Development End Date` column that contains square brackets (`[]`) indicates that the open-source project is temporarily inaccessible.
-In the table, data in the `Active Maintenance` column that contains angle brackets (`<>`) is calculated up to Aug 17, 2025.
+In the table, data in the `Active Maintenance` column that contains angle brackets (`<>`) is calculated up to Sep 9, 2025.
******
@@ -133,7 +133,7 @@ Compared to the final open-source version `4.1.1 Alpha2` of Auto.js, the main up
* Theme color adaptation [ Grouping / Location / Search / History / Automatic Adaptation of Brightness and Contrast / ... ]
* Night mode adaptation [ Settings page / Documentation page / Layout analysis page / Floating window / ... ]
* [VSCode plugin](http://vscext-project.autojs6.com) supports both client (LAN) and server (LAN/ADB) connection methods
-* [Rhino](https://github.com/mozilla/rhino/) engine upgraded from [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) to [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)
+* [Rhino](https://github.com/mozilla/rhino/) engine upgraded from [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) to [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (Updated on Apr 11, 2025)
* Unicode [code point](https://developer.mozilla.org/en-US/docs/Glossary/Code_point) escape support for [supplementary plane](https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane) characters
```javascript
'\u{1D160}'; /* stands for "𝅘𝅥𝅮", traditional method: '\uD834\uDD60'. */
@@ -307,12 +307,12 @@ This section introduces the compilation and build methods of the AutoJs6 open-so
#### Android Studio Preparation
-Download `Android Studio Narwhal Feature Drop | 2025.1.2` version (choose one as needed):
+Download `Android Studio Narwhal 3 Feature Drop | 2025.1.3` version (choose one as needed):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> Note: The release date for the above version is Jul 31, 2025. To download other versions, or if the above link is invalid, you can visit the [Android Studio release archive](https://developer.android.com/studio/archive?hl=en) page.
+> Note: The release date for the above version is Sep 2, 2025. To download other versions, or if the above link is invalid, you can visit the [Android Studio release archive](https://developer.android.com/studio/archive?hl=en) page.
Install or extract the above file, then run the Android Studio software (e.g., `"D:\android-studio\bin\studio64.exe"`).
@@ -361,9 +361,9 @@ Check `Show Package Details`, click NDK and CMake respectively to ensure the cor
#### JDK Preparation
-The `JDK (Java Development Kit)` version required for the AutoJs6 project should be at least `17`, but `19` or higher is recommended.
+The `JDK (Java Development Kit)` version required for the AutoJs6 project should be at least `17`, but `21` or higher is recommended.
-As of Aug 17, 2025, AutoJs6 supports up to version `24` of the JDK.
+As of Sep 9, 2025, AutoJs6 supports up to version `24` of the JDK.
> Note: If the JDK is already installed on the computer system and the version meets the above requirements, this section can be skipped.
@@ -514,19 +514,19 @@ Existing script development projects can serve as references and inspire creativ
Thank you to everyone who contributed to the AutoJs6 project development.
-| Contributors | Number of Commits | Recent Submissions |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| Contributors | Number of Commits | Recent Submissions |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-Data updated on May 27, 2025.
+Data updated on Sep 6, 2025.
Data entries sorted in descending order by `recent submissions`.
@@ -547,11 +547,12 @@ Some contributors do not appear correctly in the [GitHub Contributors](https://g
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/README-es.md b/.readme/README-es.md
index 4914dd59..ae8816f5 100644
--- a/.readme/README-es.md
+++ b/.readme/README-es.md
@@ -8,16 +8,16 @@
Herramienta de automatización JavaScript que soporta servicios de accesibilidad en la plataforma Android
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ La siguiente tabla enumera algunos proyectos relacionados con Auto.js (ordenados
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
Las fechas en la tabla son estimadas y pueden no coincidir con las reales.
@@ -76,7 +76,7 @@ En la tabla, Auto.js Pro 7/8/9 son versiones pagas, mientras que las demás son
En la tabla, los datos de la columna `Fecha de finalización del desarrollo` que contienen corchetes (`[]`) indican que el proyecto de código abierto no está temporalmente accesible.
-En la tabla, los datos de la columna `Mantenimiento activo` que contienen paréntesis angulares (`<>`) se han calculado hasta 17 de August de 2025.
+En la tabla, los datos de la columna `Mantenimiento activo` que contienen paréntesis angulares (`<>`) se han calculado hasta 9 de September de 2025.
******
@@ -133,7 +133,7 @@ En comparación con la versión final de Auto.js `4.1.1 Alpha2`, AutoJs6 ha real
* Adaptation des couleurs du thème [ Groupement / Localisation / Recherche / Historique / Adaptation automatique de la luminosité et du contraste / ... ]
* Soporte para modo nocturno en varias páginas [ página de configuración / página de documentación / página de análisis de diseño / ventana flotante / ... ]
* El [complemento de VSCode](http://vscext-project.autojs6.com) soporta conexiones cliente (LAN) y servidor (LAN/ADB)
-* El motor [Rhino](https://github.com/mozilla/rhino/) se ha actualizado de [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) a [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)
+* El motor [Rhino](https://github.com/mozilla/rhino/) se ha actualizado de [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) a [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (actualizado el 11 de April de 2025)
* Soporte para secuencias de escape de [puntos de código](https://developer.mozilla.org/zh-CN/docs/Glossary/Code_point) Unicode [ plano suplementario](https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84#%E7%AC%AC%E4%B8%80%E8%BC%94%E5%8A%A9%E5%B9%B3%E9%9D%A2)
```javascript
'\u{1D160}'; /* significa "𝅘𝅥𝅮", método tradicional: '\uD834\uDD60'. */
@@ -307,12 +307,12 @@ Esta sección toma como ejemplo Android Studio para presentar los métodos de co
#### Preparación de Android Studio
-Descarga la versión `Android Studio Narwhal Feature Drop | 2025.1.2` (elige una según tus necesidades):
+Descarga la versión `Android Studio Narwhal 3 Feature Drop | 2025.1.3` (elige una según tus necesidades):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> Nota: La fecha de lanzamiento de la versión anterior es el 31 de July de 2025. Para descargar otras versiones, o si los enlaces anteriores ya no funcionan, puedes visitar la página del [Archivo de versiones de Android Studio](https://developer.android.com/studio/archive?hl=en).
+> Nota: La fecha de lanzamiento de la versión anterior es el 2 de September de 2025. Para descargar otras versiones, o si los enlaces anteriores ya no funcionan, puedes visitar la página del [Archivo de versiones de Android Studio](https://developer.android.com/studio/archive?hl=en).
Instala o descomprime los archivos mencionados anteriormente y ejecuta el software Android Studio (por ejemplo, `"D:\android-studio\bin\studio64.exe"`).
@@ -361,9 +361,9 @@ Marca `Show Package Details (Mostrar detalles del paquete)`, haz clic en NDK y C
#### Preparación del JDK
-La versión mínima requerida del `JDK (Kit de Desarrollo de Java)` para el proyecto AutoJs6 es `17`, pero se recomienda usar una versión no inferior a `19`.
+La versión mínima requerida del `JDK (Kit de Desarrollo de Java)` para el proyecto AutoJs6 es `17`, pero se recomienda usar una versión no inferior a `21`.
-Hasta el 17 de August de 2025, AutoJs6 soporta hasta la versión `24` de JDK.
+Hasta el 9 de September de 2025, AutoJs6 soporta hasta la versión `24` de JDK.
> Nota: Si el sistema ya tiene instalado JDK y cumple con los requisitos anteriores, puedes omitir esta sección.
@@ -514,19 +514,19 @@ Los proyectos de desarrollo de scripts existentes pueden servir como referencia
Agradecemos a todos los que han contribuido al desarrollo del proyecto AutoJs6.
-| Contribuyentes | Número de commits | Últimas presentaciones |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| Contribuyentes | Número de commits | Últimas presentaciones |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-Datos actualizados el 27 de May de 2025.
+Datos actualizados el 6 de September de 2025.
Las entradas de datos están ordenadas en orden descendente por `últimas presentaciones`.
@@ -547,11 +547,12 @@ Algunos contribuyentes no aparecen en [GitHub Contributors](https://github.com/S
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/README-fr.md b/.readme/README-fr.md
index 64797fbc..33c9290d 100644
--- a/.readme/README-fr.md
+++ b/.readme/README-fr.md
@@ -8,16 +8,16 @@
Outil d'automatisation JavaScript prenant en charge les services d'accessibilité sur la plateforme Android
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ Le tableau suivant énumère certains projets liés à Auto.js (classés par dat
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
Les dates dans le tableau sont des estimations et peuvent différer des dates réelles.
@@ -76,7 +76,7 @@ Dans le tableau, Auto.js Pro 7/8/9 sont des versions payantes, les autres sont d
Dans le tableau, les données de la colonne `Date de fin de développement` contenant des crochets (`[]`) indiquent que le projet open source est temporairement inaccessible.
-Dans le tableau, les données de la colonne `Maintenance active` contenant des chevrons (`<>`) sont calculées jusqu’au 17 August 2025.
+Dans le tableau, les données de la colonne `Maintenance active` contenant des chevrons (`<>`) sont calculées jusqu’au 9 September 2025.
******
@@ -133,7 +133,7 @@ Par rapport à la version finale open source de Auto.js `4.1.1 Alpha2`, AutoJs6
* Adaptación del color del tema [ Agrupación / Ubicación / Búsqueda / Historial / Adaptación automática de brillo y contraste / ... ]
* Adaptation du mode nuit [ Paramètres / Documentation / Analyse de la disposition / Fenêtre flottante / ... ]
* Prise en charge de l'extension [VSCode](http://vscext-project.autojs6.com) pour la connexion client (LAN) et serveur (LAN/ADB)
-* Le moteur [Rhino](https://github.com/mozilla/rhino/) a été mis à niveau de [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) à [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)
+* Le moteur [Rhino](https://github.com/mozilla/rhino/) a été mis à niveau de [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) à [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (mis à jour le 11 April 2025)
* [Échappements](https://developer.mozilla.org/zh-CN/docs/Glossary/Code_point) pour les points de code Unicode supportent les caractères du [plan complémentaire](https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84#%E7%AC%AC%E4%B8%80%E8%BC%94%E5%8A%A9%E5%B9%B3%E9%9D%A2)
```javascript
'\u{1D160}'; /* signifie "𝅘𝅥𝅮", méthode traditionnelle: '\uD834\uDD60'. */
@@ -307,12 +307,12 @@ Cette section présente la méthode de compilation et de construction du projet
#### Préparation de Android Studio
-Téléchargez la version `Android Studio Narwhal Feature Drop | 2025.1.2` (choisissez-en une selon vos besoins):
+Téléchargez la version `Android Studio Narwhal 3 Feature Drop | 2025.1.3` (choisissez-en une selon vos besoins):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> Note : La version mentionnée ci-dessus a été publiée le 31 July 2025. Pour télécharger d'autres versions ou si le lien ci-dessus n'est plus valide, visitez la page [archive des versions de Android Studio](https://developer.android.com/studio/archive?hl=en).
+> Note : La version mentionnée ci-dessus a été publiée le 2 September 2025. Pour télécharger d'autres versions ou si le lien ci-dessus n'est plus valide, visitez la page [archive des versions de Android Studio](https://developer.android.com/studio/archive?hl=en).
Installez ou extrayez le fichier ci-dessus, exécutez Android Studio (par exemple `"D:\android-studio\bin\studio64.exe"`).
@@ -361,9 +361,9 @@ Cochez `Show Package Details (afficher les détails du package)`, puis cliquez r
#### Préparation du JDK
-La version de JDK (Kit de développement Java) requise pour le projet AutoJs6 doit être au moins `17`, mais il est recommandé d'avoir au moins `19`.
+La version de JDK (Kit de développement Java) requise pour le projet AutoJs6 doit être au moins `17`, mais il est recommandé d'avoir au moins `21`.
-À partir du 17 August 2025, AutoJs6 prend en charge la version maximale de JDK `24`.
+À partir du 9 September 2025, AutoJs6 prend en charge la version maximale de JDK `24`.
> Note : Si le JDK est déjà installé sur le système informatique et que la version répond aux exigences ci-dessus, vous pouvez ignorer cette section.
@@ -514,19 +514,19 @@ Les projets de développement de scripts existants peuvent servir de référence
Merci à chaque contributeur participant au développement du projet AutoJs6.
-| Contributeurs | Nombre de commits | Soumissions récentes |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| Contributeurs | Nombre de commits | Soumissions récentes |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-Données mises à jour le 27 May 2025.
+Données mises à jour le 6 September 2025.
Les entrées de données sont triées par `soumissions récentes` en ordre décroissant.
@@ -547,11 +547,12 @@ Certains contributeurs ne figurant pas correctement dans [GitHub Contributors](h
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/README-ja.md b/.readme/README-ja.md
index 340cc384..6ec3bc2b 100644
--- a/.readme/README-ja.md
+++ b/.readme/README-ja.md
@@ -8,16 +8,16 @@
アクセシビリティサービスをサポートする Android プラットフォーム用の JavaScript 自動化ツール
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ AutoJs6 は `2021/12/01` に Auto.js 最終プロジェクトを基に二次開
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
表の日付は推定値であり, 実際とは異なる場合があります.
@@ -76,7 +76,7 @@ AutoJs6 は `2021/12/01` に Auto.js 最終プロジェクトを基に二次開
表では, `開発終了日` 列に角括弧 (`[]`) を含むデータは, オープンソースプロジェクトが一時的にアクセス不能であることを示します.
-表では, `アクティブメンテナンス期間` 列に山括弧 (`<>`) を含むデータは, 統計の締め日が 2025 年 8 月 17 日 であることを示します.
+表では, `アクティブメンテナンス期間` 列に山括弧 (`<>`) を含むデータは, 統計の締め日が 2025 年 9 月 9 日 であることを示します.
******
@@ -133,7 +133,7 @@ Auto.js の最終オープンソースバージョン `4.1.1 Alpha2` と比較
* テーマカラーの適応 [ グループ化 / ロケーション / 検索 / 履歴 / 明るさとコントラストの自動適応 / ... ]
* ナイトモード対応 [ 設定ページ / ドキュメントページ / レイアウト分析ページ / 浮動ウィンドウ / ... ]
* [VSCodeプラグイン](http://vscext-project.autojs6.com)がクライアント (LAN)とサーバ (LAN/ADB)接続方法をサポート
-* [Rhino](https://github.com/mozilla/rhino/)エンジンが [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) から [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) にアップグレードされました
+* [Rhino](https://github.com/mozilla/rhino/)エンジンが [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) から [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (2025 年 4 月 11 日 更新) にアップグレードされました
* Unicode [コードポイント](https://developer.mozilla.org/ja/docs/Glossary/Code_point)エスケープのサポート [補助平面](https://ja.wikipedia.org/wiki/多言語面#補助平面)文字
```javascript
'\u{1D160}'; /* を表します "𝅘𝅥𝅮", 従来の方法: '\uD834\uDD60'. */
@@ -307,12 +307,12 @@ AutoJs6 オープンソース プロジェクトのデバッグや開発が必
#### Android Studioの準備
-`Android Studio Narwhal Feature Drop | 2025.1.2` バージョンをダウンロードしてください (いずれかを選択):
+`Android Studio Narwhal 3 Feature Drop | 2025.1.3` バージョンをダウンロードしてください (いずれかを選択):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> 注: 上述バージョンのリリース日は 2025 年 7 月 31 日 です. その他のバージョンをダウンロードするか, 上記のリンクが失効している場合は, [Android Studioリリースアーカイブ](https://developer.android.com/studio/archive?hl=en)のページをご覧ください.
+> 注: 上述バージョンのリリース日は 2025 年 9 月 2 日 です. その他のバージョンをダウンロードするか, 上記のリンクが失効している場合は, [Android Studioリリースアーカイブ](https://developer.android.com/studio/archive?hl=en)のページをご覧ください.
上記のファイルをインストールまたは解凍し, Android Studio ソフトウェアを実行します (例: `"D:\android-studio\bin\studio64.exe"`).
@@ -361,9 +361,9 @@ File (ファイル) | Settings (設定) | Appearance & Behavior (外観と動作
#### JDKの準備
-AutoJs6プロジェクトが依存する `JDK (Java開発キット)` のリリースバージョンは少なくとも `17` で, それ以下のバージョンは推奨されませんが, 最低でも `19` の使用を推奨します.
+AutoJs6プロジェクトが依存する `JDK (Java開発キット)` のリリースバージョンは少なくとも `17` で, それ以下のバージョンは推奨されませんが, 最低でも `21` の使用を推奨します.
-2025 年 8 月 17 日 現在, AutoJs6がサポートする最大のJDKバージョンは `24` です.
+2025 年 9 月 9 日 現在, AutoJs6がサポートする最大のJDKバージョンは `24` です.
> 注: コンピュータシステムに適切なバージョンのJDKがインストールされている場合, この節の内容をスキップできます.
@@ -514,19 +514,19 @@ AutoJs6に関するAPIおよび使用方法については, 常にアプリケ
AutoJs6 プロジェクト開発に参加したすべての貢献者に感謝します.
-| 貢献者 | コミット数 | 最近の提出 |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| 貢献者 | コミット数 | 最近の提出 |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-データは 2025 年 5 月 27 日 に更新されました.
+データは 2025 年 9 月 6 日 に更新されました.
データ項目は `最近の提出` の降順で並べ替えられます.
@@ -547,11 +547,12 @@ AutoJs6 プロジェクト開発に参加したすべての貢献者に感謝し
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/README-ko.md b/.readme/README-ko.md
index b169ccbc..8e6a5d2d 100644
--- a/.readme/README-ko.md
+++ b/.readme/README-ko.md
@@ -8,16 +8,16 @@
안드로이드 플랫폼에서 접근성 서비스를 지원하는 JavaScript 자동화 도구
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ AutoJs6는 Auto.js 최종 프로젝트를 기반으로 `2021/12/01` 에 다시
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
표에 표시된 날짜는 예상 날짜로, 실제 날짜와 다를 수 있습니다.
@@ -76,7 +76,7 @@ AutoJs6는 Auto.js 최종 프로젝트를 기반으로 `2021/12/01` 에 다시
표에서 `개발 종료 날짜` 열에 대괄호 (`[]`) 가 포함된 데이터는 오픈 소스 프로젝트가 일시적으로 접근 불가함을 나타냅니다.
-표에서 `활성 유지보수 기간` 열에 꺾쇠괄호 (`<>`) 가 포함된 데이터는 통계 기준일이 2025 년 8 월 17 일 임을 나타냅니다.
+표에서 `활성 유지보수 기간` 열에 꺾쇠괄호 (`<>`) 가 포함된 데이터는 통계 기준일이 2025 년 9 월 9 일 임을 나타냅니다.
******
@@ -95,7 +95,7 @@ AutoJs6는 Auto.js 최종 프로젝트를 기반으로 `2021/12/01` 에 다시
* 스크립트 파일 또는 프로젝트를 APK 파일로 패키징 지원
* Root 권한을 이용한 기능 확장 지원 (화면 클릭/스크롤/녹화/Shell)
* Tasker 플러그인으로 사용 가능
-* VSCode와 연결하여 데스크톱 개발 지원 ( [AutoJs6-VSCode-Extension](http://vscext-project.autojs6.com) 플러그인 필요)
+* VSCode와 연결하여 데스크톱 개발 지원 ([AutoJs6-VSCode-Extension](http://vscext-project.autojs6.com) 플러그인 필요)
******
@@ -133,7 +133,7 @@ Auto.js 최종 오픈 소스 버전 `4.1.1 Alpha2` 와 비교하여 AutoJs6는
* 테마 색상 적응 [ 그룹화 / 위치 / 검색 / 기록 / 밝기 및 대비 자동 적응 / ...]
* 야경 모드 지원 [ 설정 페이지 / 문서 페이지 / 레이아웃 분석 페이지 / 플로팅 창 / ... ]
* [VSCode 플러그인](http://vscext-project.autojs6.com) 지원 클라이언트 (LAN) 및 서버 (LAN/ADB) 연결 방식
-* [Rhino](https://github.com/mozilla/rhino/) 엔진을 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release)에서 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)로 업그레이드
+* [Rhino](https://github.com/mozilla/rhino/) 엔진을 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 에서 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) 로 업그레이드 (2025 년 4 월 11 일 업데이트됨)
* 유니코드 [코드 포인트](https://developer.mozilla.org/zh-CN/docs/Glossary/Code_point) 이스케이프 지원 [보조 평면](https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84#%E7%AC%AC%E4%B8%80%E8%BC%94%E5%8A%A9%E5%B9%B3%E9%9D%A2) 문자
```javascript
'\u{1D160}'; /* 의 의미 "𝅘𝅥𝅮", 전통적인 방법: '\uD834\uDD60'. */
@@ -307,12 +307,12 @@ AutoJs6 오픈 소스 프로젝트를 디버깅하거나 개발하려면 [Androi
#### Android Studio 준비
-`Android Studio Narwhal Feature Drop | 2025.1.2` 버전을 다운로드하십시오 (필요에 따라 선택):
+`Android Studio Narwhal 3 Feature Drop | 2025.1.3` 버전을 다운로드하십시오 (필요에 따라 선택):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> 메모: 상기 버전 출시 날짜는 2025 년 7 월 31 일입니다. 다른 버전을 다운로드하거나 상기 링크가 만료되었을 경우, [Android Studio 릴리스 아카이브](https://developer.android.com/studio/archive?hl=en) 페이지를 방문하십시오.
+> 메모: 상기 버전 출시 날짜는 2025 년 9 월 2 일입니다. 다른 버전을 다운로드하거나 상기 링크가 만료되었을 경우, [Android Studio 릴리스 아카이브](https://developer.android.com/studio/archive?hl=en) 페이지를 방문하십시오.
위의 파일을 설치하거나 압축을 풀고 Android Studio 소프트웨어를 실행합니다 (예: `"D:\android-studio\bin\studio64.exe"`).
@@ -361,9 +361,9 @@ File (파일) | Settings (설정) | Appearance & Behavior (모양 및 동작) |
#### JDK 준비
-AutoJs6 프로젝트는 `JDK (Java 개발 도구 키트)` 버전이 `17` 이상이어야 하지만, `19` 이상을 권장합니다.
+AutoJs6 프로젝트는 `JDK (Java 개발 도구 키트)` 버전이 `17` 이상이어야 하지만, `21` 이상을 권장합니다.
-2025 년 8 월 17 일 기준으로, AutoJs6이 지원하는 최대 JDK 버전은 `24` 입니다.
+2025 년 9 월 9 일 기준으로, AutoJs6이 지원하는 최대 JDK 버전은 `24` 입니다.
> 메모: 시스템에 JDK가 설치되어 있고, 버전이 위의 요구 사항을 충족하는 경우, 이 섹션을 건너뛸 수 있습니다.
@@ -514,19 +514,19 @@ PC에서 스크립트를 작성하고 디버깅하려면 VSCode 플러그인을
AutoJs6 프로젝트 개발에 참여한 모든 기여자분들께 감사합니다.
-| 기여자 | 커밋 수 | 최근 제출 |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| 기여자 | 커밋 수 | 최근 제출 |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-데이터 갱신일: 2025 년 5 월 27 일.
+데이터 갱신일: 2025 년 9 월 6 일.
데이터 항목은 `최근 제출` 순으로 내림차순 정렬됩니다.
@@ -547,11 +547,12 @@ AutoJs6 프로젝트 개발에 참여한 모든 기여자분들께 감사합니
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/README-ru.md b/.readme/README-ru.md
index 79fb0aa8..bcf509ad 100644
--- a/.readme/README-ru.md
+++ b/.readme/README-ru.md
@@ -8,16 +8,16 @@
Инструмент автоматизации на языке JavaScript для платформы Android с поддержкой службы доступности
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ AutoJs6 разработан на основе финальной версии
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
Даты в таблице являются оценочными и могут отличаться от фактических.
@@ -76,7 +76,7 @@ AutoJs6 разработан на основе финальной версии
В таблице данные в столбце `Дата окончания разработки`, содержащие квадратные скобки (`[]`), означают, что открытый проект временно недоступен.
-В таблице данные в столбце `Период активного обслуживания`, содержащие угловые скобки (`<>`), учитываются по состоянию на 17 August 2025 года.
+В таблице данные в столбце `Период активного обслуживания`, содержащие угловые скобки (`<>`), учитываются по состоянию на 9 September 2025 года.
******
@@ -133,7 +133,7 @@ AutoJs6 разработан на основе финальной версии
* Адаптация темы [ Группировка / Локация / Поиск / История / Автоматическая адаптация яркости и контрастности / ... ]
* Поддержка ночного режима [ страница настроек / страница документации / страница анализа макета / плавающее окно / ... ]
* Плагин [VSCode](http://vscext-project.autojs6.com) поддерживает варианты подключения клиента (LAN) и сервера (LAN/ADB)
-* Движок [Rhino](https://github.com/mozilla/rhino/) обновлен с версии [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) до версии [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)
+* Движок [Rhino](https://github.com/mozilla/rhino/) обновлен с версии [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) до версии [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (обновлено 11 April 2025 года)
* Поддержка Unicode для [экранирования кодовых точек](https://developer.mozilla.org/zh-CN/docs/Glossary/Code_point) и символов [в дополнительных плоскостях](https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84#%E7%AC%AC%E4%B8%80%E8%BC%94%E5%8A%A9%E5%B9%B3%E9%9D%A2)
```javascript
'\u{1D160}'; /* означает "𝅘𝅥𝅮", традиционный метод: '\uD834\uDD60'. */
@@ -307,12 +307,12 @@ AutoJs6 разработан на основе финальной версии
#### Подготовка Android Studio
-Скачайте версию `Android Studio Narwhal Feature Drop | 2025.1.2` (выберите одну из них по необходимости):
+Скачайте версию `Android Studio Narwhal 3 Feature Drop | 2025.1.3` (выберите одну из них по необходимости):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> Примечание: Указанная версия была выпущена 31 July 2025 года. Для загрузки других версий или если указанная ссылка недействительна, посетите страницу [архива версий Android Studio](https://developer.android.com/studio/archive?hl=en).
+> Примечание: Указанная версия была выпущена 2 September 2025 года. Для загрузки других версий или если указанная ссылка недействительна, посетите страницу [архива версий Android Studio](https://developer.android.com/studio/archive?hl=en).
Установите или распакуйте указанные файлы, запустите программное обеспечение Android Studio (например, `"D:\android-studio\bin\studio64.exe"`).
@@ -361,9 +361,9 @@ File (Файл) | Settings (Настройки) | Appearance & Behavior (Вне
#### Подготовка JDK
-Для проекта AutoJs6 требуется версия `JDK (Java Development Kit)` не ниже `17`, но рекомендуется не ниже `19`.
+Для проекта AutoJs6 требуется версия `JDK (Java Development Kit)` не ниже `17`, но рекомендуется не ниже `21`.
-По состоянию на 17 August 2025 года AutoJs6 поддерживает JDK максимальной версии `24`.
+По состоянию на 9 September 2025 года AutoJs6 поддерживает JDK максимальной версии `24`.
> Примечание: Если на компьютере уже установлен JDK и версия соответствует указанным требованиям, этот раздел можно пропустить.
@@ -514,19 +514,19 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
Благодарим всех участников проекта AutoJs6 за их вклад.
-| Участники | Количество коммитов | Последние коммиты |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| Участники | Количество коммитов | Последние коммиты |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-Данные обновлены на 27 May 2025 года.
+Данные обновлены на 6 September 2025 года.
Данные отсортированы по `последним отправкам` в порядке убывания.
@@ -547,11 +547,12 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/README-zh-Hans.md b/.readme/README-zh-Hans.md
index 6219233b..2c979743 100644
--- a/.readme/README-zh-Hans.md
+++ b/.readme/README-zh-Hans.md
@@ -8,16 +8,16 @@
Android 平台支持无障碍服务的 JavaScript 自动化工具
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ AutoJs6 在 Auto.js 最终项目的基础上, 于 `2021/12/01` 进行二次开
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
表格中的日期为预估值, 实际可能存在出入.
@@ -76,7 +76,7 @@ AutoJs6 在 Auto.js 最终项目的基础上, 于 `2021/12/01` 进行二次开
表格中 `终止开发日期` 列包含方括号 (`[]`) 的数据, 表示开源项目暂时无法访问.
-表格中 `活跃维护期` 列包含尖括号 (`<>`) 的数据, 其统计截止日期为 2025 年 8 月 17 日.
+表格中 `活跃维护期` 列包含尖括号 (`<>`) 的数据, 其统计截止日期为 2025 年 9 月 9 日.
******
@@ -133,7 +133,7 @@ AutoJs6 在 Auto.js 最终项目的基础上, 于 `2021/12/01` 进行二次开
* 主题色适配 [ 分组 / 定位 / 搜索 / 历史记录 / 亮度及对比度自动适配 / ... ]
* 夜间模式适配 [ 设置页面 / 文档页面 / 布局分析页面 / 浮动窗口 / ... ]
* [VSCode 插件](http://vscext-project.autojs6.com) 支持客户端 (LAN) 及服务端 (LAN/ADB) 连接方式
-* [Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升级至 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)
+* [Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升级至 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (更新于 2025 年 4 月 11 日)
* Unicode [码位](https://developer.mozilla.org/zh-CN/docs/Glossary/Code_point) 转义支持 [辅助平面](https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84#%E7%AC%AC%E4%B8%80%E8%BC%94%E5%8A%A9%E5%B9%B3%E9%9D%A2) 字符
```javascript
'\u{1D160}'; /* 表示 "𝅘𝅥𝅮", 传统方式: '\uD834\uDD60'. */
@@ -280,12 +280,12 @@ AutoJs6 在 Auto.js 最终项目的基础上, 于 `2021/12/01` 进行二次开
#### Android Studio 准备
-下载 `Android Studio Narwhal Feature Drop | 2025.1.2` 版本 (按需选择其一):
+下载 `Android Studio Narwhal 3 Feature Drop | 2025.1.3` 版本 (按需选择其一):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> 注: 上述版本发布时间为 2025 年 7 月 31 日. 如需下载其他版本, 或上述链接已失效, 可访问 [Android Studio 发行版本归档](https://developer.android.com/studio/archive?hl=en) 页面.
+> 注: 上述版本发布时间为 2025 年 9 月 2 日. 如需下载其他版本, 或上述链接已失效, 可访问 [Android Studio 发行版本归档](https://developer.android.com/studio/archive?hl=en) 页面.
安装或解压上述文件, 运行 Android Studio 软件 (如 `"D:\android-studio\bin\studio64.exe"`).
@@ -334,9 +334,9 @@ File (文件) | Settings (设置) | Appearance & Behavior (外观与行为) | Sy
#### JDK 准备
-AutoJs6 项目依赖的 `JDK (Java 开发工具包)` 发行版本不低于 `17`, 但建议不低于 `19`.
+AutoJs6 项目依赖的 `JDK (Java 开发工具包)` 发行版本不低于 `17`, 但建议不低于 `21`.
-截至 2025 年 8 月 17 日, AutoJs6 可支持 JDK 最高版本为 `24`.
+截至 2025 年 9 月 9 日, AutoJs6 可支持 JDK 最高版本为 `24`.
> 注: 如果计算机系统已安装 JDK 且版本满足上述要求, 则可跳过此小节内容.
@@ -487,19 +487,19 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
感谢每一位参与 AutoJs6 项目开发的贡献人员.
-| 贡献人员 | 提交数 | 最近提交 |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| 贡献人员 | 提交数 | 最近提交 |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-数据更新于 2025 年 5 月 27 日.
+数据更新于 2025 年 9 月 6 日.
数据条目按 `最近提交` 降序排序.
@@ -520,11 +520,12 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/README-zh-Hant-HK.md b/.readme/README-zh-Hant-HK.md
index 29974d39..62b382f5 100644
--- a/.readme/README-zh-Hant-HK.md
+++ b/.readme/README-zh-Hant-HK.md
@@ -8,16 +8,16 @@
Android 平台支持無障礙服務的 JavaScript 自動化工具
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ AutoJs6 在 Auto.js 最終項目的基礎上, 於 `2021/12/01` 進行二次開
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
表格中的日期為預估值, 與實際可能存在出入.
@@ -76,7 +76,7 @@ AutoJs6 在 Auto.js 最終項目的基礎上, 於 `2021/12/01` 進行二次開
表格中 `終止開發日期` 列包含方括號 (`[]`) 的數據, 表示開源項目暫時無法訪問.
-表格中 `活躍維護期` 列包含尖括號 (`<>`) 的數據, 其統計截止日期為 2025 年 8 月 17 日.
+表格中 `活躍維護期` 列包含尖括號 (`<>`) 的數據, 其統計截止日期為 2025 年 9 月 9 日.
******
@@ -133,7 +133,7 @@ AutoJs6 在 Auto.js 最終項目的基礎上, 於 `2021/12/01` 進行二次開
* 主題色適配 [ 分組 / 定位 / 搜索 / 歷史記錄 / 亮度及對比度自動適配 / ... ]
* 夜間模式適配 [ 設置頁面 / 文檔頁面 / 佈局分析頁面 / 浮動窗口 / ... ]
* [VSCode 插件](http://vscext-project.autojs6.com) 支持客户端 (LAN) 及服務端 (LAN/ADB) 連接方式
-* [Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升級至 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)
+* [Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升級至 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (更新於 2025 年 4 月 11 日)
* Unicode [碼位](https://developer.mozilla.org/zh-CN/docs/Glossary/Code_point) 轉義支持 [輔助平面](https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84#%E7%AC%AC%E4%B8%80%E8%BC%94%E5%8A%A9%E5%B9%B3%E9%9D%A2) 字符
```javascript
'\u{1D160}'; /* 表示 "𝅘𝅥𝅮", 傳統方式: '\uD834\uDD60'. */
@@ -307,12 +307,12 @@ AutoJs6 在 Auto.js 最終項目的基礎上, 於 `2021/12/01` 進行二次開
#### Android Studio 準備
-下載 `Android Studio Narwhal Feature Drop | 2025.1.2` 版本 (按需選擇其一):
+下載 `Android Studio Narwhal 3 Feature Drop | 2025.1.3` 版本 (按需選擇其一):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> 注: 上述版本發佈時間為 2025 年 7 月 31 日. 如需下載其他版本, 或上述鏈接已失效, 可訪問 [Android Studio 發行版本歸檔](https://developer.android.com/studio/archive?hl=en) 頁面.
+> 注: 上述版本發佈時間為 2025 年 9 月 2 日. 如需下載其他版本, 或上述鏈接已失效, 可訪問 [Android Studio 發行版本歸檔](https://developer.android.com/studio/archive?hl=en) 頁面.
安裝或解壓上述文件, 運行 Android Studio 軟件 (如 `"D:\android-studio\bin\studio64.exe"`).
@@ -361,9 +361,9 @@ File (文件) | Settings (設置) | Appearance & Behavior (外觀與行為) | Sy
#### JDK 準備
-AutoJs6 項目依賴的 `JDK (Java 開發工具包)` 發行版本不低於 `17`, 但建議不低於 `19`.
+AutoJs6 項目依賴的 `JDK (Java 開發工具包)` 發行版本不低於 `17`, 但建議不低於 `21`.
-截至 2025 年 8 月 17 日, AutoJs6 可支持 JDK 最高版本為 `24`.
+截至 2025 年 9 月 9 日, AutoJs6 可支持 JDK 最高版本為 `24`.
> 注: 如果計算機系統已安裝 JDK 且版本滿足上述要求, 則可跳過此小節內容.
@@ -514,19 +514,19 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
感謝每一位參與 AutoJs6 項目開發的貢獻人員.
-| 貢獻人員 | 提交數 | 最近提交 |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| 貢獻人員 | 提交數 | 最近提交 |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-數據更新於 2025 年 5 月 27 日.
+數據更新於 2025 年 9 月 6 日.
數據條目按 `最近提交` 降序排序.
@@ -547,11 +547,12 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/README-zh-Hant-TW.md b/.readme/README-zh-Hant-TW.md
index 926c49d9..5e1f54c2 100644
--- a/.readme/README-zh-Hant-TW.md
+++ b/.readme/README-zh-Hant-TW.md
@@ -8,16 +8,16 @@
Android 平臺支援無障礙服務的 JavaScript 自動化工具
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ AutoJs6 在 Auto.js 最終專案的基礎上, 於 `2021/12/01` 進行二次開
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
表格中的日期為預估值, 與實際可能存在出入.
@@ -76,7 +76,7 @@ AutoJs6 在 Auto.js 最終專案的基礎上, 於 `2021/12/01` 進行二次開
表格中 `終止開發日期` 列包含方括號 (`[]`) 的資料, 表示開源專案暫時無法訪問.
-表格中 `活躍維護期` 列包含尖括號 (`<>`) 的資料, 其統計截止日期為 2025 年 8 月 17 日.
+表格中 `活躍維護期` 列包含尖括號 (`<>`) 的資料, 其統計截止日期為 2025 年 9 月 9 日.
******
@@ -133,7 +133,7 @@ AutoJs6 在 Auto.js 最終專案的基礎上, 於 `2021/12/01` 進行二次開
* 主題色適配 [ 分組 / 定位 / 搜尋 / 歷史記錄 / 亮度及對比度自動適配 / ... ]
* 夜間模式適配 [ 設定頁面 / 文件頁面 / 佈局分析頁面 / 浮動視窗 / ... ]
* [VSCode 外掛](http://vscext-project.autojs6.com) 支援客戶端 (LAN) 及服務端 (LAN/ADB) 連線方式
-* [Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升級至 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)
+* [Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升級至 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (更新於 2025 年 4 月 11 日)
* Unicode [碼位](https://developer.mozilla.org/zh-CN/docs/Glossary/Code_point) 轉義支援 [輔助平面](https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84#%E7%AC%AC%E4%B8%80%E8%BC%94%E5%8A%A9%E5%B9%B3%E9%9D%A2) 字元
```javascript
'\u{1D160}'; /* 表示 "𝅘𝅥𝅮", 傳統方式: '\uD834\uDD60'. */
@@ -307,12 +307,12 @@ AutoJs6 在 Auto.js 最終專案的基礎上, 於 `2021/12/01` 進行二次開
#### Android Studio 準備
-下載 `Android Studio Narwhal Feature Drop | 2025.1.2` 版本 (按需選擇其一):
+下載 `Android Studio Narwhal 3 Feature Drop | 2025.1.3` 版本 (按需選擇其一):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> 注: 上述版本釋出時間為 2025 年 7 月 31 日. 如需下載其他版本, 或上述連結已失效, 可訪問 [Android Studio 發行版本歸檔](https://developer.android.com/studio/archive?hl=en) 頁面.
+> 注: 上述版本釋出時間為 2025 年 9 月 2 日. 如需下載其他版本, 或上述連結已失效, 可訪問 [Android Studio 發行版本歸檔](https://developer.android.com/studio/archive?hl=en) 頁面.
安裝或解壓上述檔案, 執行 Android Studio 軟體 (如 `"D:\android-studio\bin\studio64.exe"`).
@@ -361,9 +361,9 @@ File (文件) | Settings (設置) | Appearance & Behavior (外觀與行為) | Sy
#### JDK 準備
-AutoJs6 專案依賴的 `JDK (Java 開發工具包)` 發行版本不低於 `17`, 但建議不低於 `19`.
+AutoJs6 專案依賴的 `JDK (Java 開發工具包)` 發行版本不低於 `17`, 但建議不低於 `21`.
-截至 2025 年 8 月 17 日, AutoJs6 可支援 JDK 最高版本為 `24`.
+截至 2025 年 9 月 9 日, AutoJs6 可支援 JDK 最高版本為 `24`.
> 注: 如果計算機系統已安裝 JDK 且版本滿足上述要求, 則可跳過此小節內容.
@@ -514,19 +514,19 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
感謝每一位參與 AutoJs6 專案開發的貢獻人員.
-| 貢獻人員 | 提交數 | 最近提交 |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| 貢獻人員 | 提交數 | 最近提交 |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-資料更新於 2025 年 5 月 27 日.
+資料更新於 2025 年 9 月 6 日.
資料條目按 `最近提交` 降序排序.
@@ -547,11 +547,12 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.readme/common.json b/.readme/common.json
index 5596c015..c93e3ff1 100644
--- a/.readme/common.json
+++ b/.readme/common.json
@@ -1,17 +1,15 @@
{
- "android_studio_latest_recommended_version_name": "Android Studio Narwhal Feature Drop | 2025.1.2",
- "var_date_android_studio_latest_recommended_version_name": "2025/07/31",
- "android_studio_latest_recommended_file_name_of_exe": "android-studio-2025.1.2.11-windows.exe",
- "android_studio_latest_recommended_download_address_of_exe": "https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe",
- "android_studio_latest_recommended_file_size_of_exe": "1.39 GB",
- "android_studio_latest_recommended_file_name_of_zip": "android-studio-2025.1.2.11-windows.zip",
- "android_studio_latest_recommended_download_address_of_zip": "https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip",
- "android_studio_latest_recommended_file_size_of_zip": "1.40 GB",
- "var_date_contribution_table_data_updated": "2025/05/27",
+ "android_studio_latest_recommended_version_name": "Android Studio Narwhal 3 Feature Drop | 2025.1.3",
+ "var_date_android_studio_latest_recommended_version_name": "2025/09/02",
+ "android_studio_latest_recommended_file_name_of_exe": "android-studio-2025.1.3.7-windows.exe",
+ "android_studio_latest_recommended_download_address_of_exe": "https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe",
+ "android_studio_latest_recommended_file_size_of_exe": "1.33 GiB",
+ "android_studio_latest_recommended_file_name_of_zip": "android-studio-2025.1.3.7-windows.zip",
+ "android_studio_latest_recommended_download_address_of_zip": "https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip",
+ "android_studio_latest_recommended_file_size_of_zip": "1.34 GiB",
+ "var_date_contribution_table_data_updated": "2025/09/06",
"latest_rhino_engine_name_with_github_lineno_address": "[v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)",
- "jdk_min_supported": 17,
- "jdk_min_suggested": 19,
- "jdk_max_supported": 24,
+ "var_date_rhino_engine_latest_committed": "2025/04/11",
"var_date_jdk_max_supported": "%CURRENT_DATE%",
"var_date_active_maintenance_phase_statistics_since_when": "%CURRENT_DATE%"
}
\ No newline at end of file
diff --git a/.readme/lang_ar.json b/.readme/lang_ar.json
index 4c827a60..71bca46a 100644
--- a/.readme/lang_ar.json
+++ b/.readme/lang_ar.json
@@ -66,7 +66,7 @@
"li_major_changes_multilingual_support": "دعم التكيف متعدد اللغات [ الإسبانية / الفرنسية / الروسية / العربية / اليابانية / الكورية / الإنجليزية / الصينية المبسطة / الصينية التقليدية / ... ]",
"li_major_changes_new_modules": "وحدات جديدة [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "دعم وضع الليل [ صفحة الإعدادات / صفحة الوثائق / صفحة تحليل التخطيط / النافذة العائمة / ... ]",
- "li_major_changes_rhino_engine_upgrade": "تم ترقية محرك [Rhino](https://github.com/mozilla/rhino/) من [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) إلى {{ latest_rhino_engine_name_with_github_lineno_address }}",
+ "li_major_changes_rhino_engine_upgrade": "تم ترقية محرك [Rhino](https://github.com/mozilla/rhino/) من [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) إلى {{ latest_rhino_engine_name_with_github_lineno_address }} (تم التحديث في {{ var_date_rhino_engine_latest_committed }})",
"li_major_changes_shizuku_adb_privileges_support": "دعم امتيازات ADB باستخدام [Shizuku](https://shizuku.rikka.app/introduction/) واستخدام واجهة برمجة التطبيقات للنظام",
"li_major_changes_theme_color_support": "تكييف ألوان الموضوع [ التجميع / الموقع / البحث / السجل / التكييف التلقائي للسطوع والتباين / ... ]",
"li_major_changes_vscode_plugin_support": "دعم الاتصال بـ [المكون الإضافي لـ VSCode](http://vscext-project.autojs6.com) بطرق الاتصال عبر الشبكة المحلية (LAN) و ADB",
diff --git a/.readme/lang_en.json b/.readme/lang_en.json
index 66ba600d..054077a4 100644
--- a/.readme/lang_en.json
+++ b/.readme/lang_en.json
@@ -66,7 +66,7 @@
"li_major_changes_multilingual_support": "Multilingual support [ Spanish / French / Russian / Arabic / Japanese / Korean / English / Simplified Chinese / Traditional Chinese / ... ]",
"li_major_changes_new_modules": "New modules [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "Night mode adaptation [ Settings page / Documentation page / Layout analysis page / Floating window / ... ]",
- "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) engine upgraded from [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) to {{ latest_rhino_engine_name_with_github_lineno_address }}",
+ "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) engine upgraded from [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) to {{ latest_rhino_engine_name_with_github_lineno_address }} (Updated on {{ var_date_rhino_engine_latest_committed }})",
"li_major_changes_shizuku_adb_privileges_support": "Supports obtaining ADB privileges through [Shizuku](https://shizuku.rikka.app/introduction/) and using system API",
"li_major_changes_theme_color_support": "Theme color adaptation [ Grouping / Location / Search / History / Automatic Adaptation of Brightness and Contrast / ... ]",
"li_major_changes_vscode_plugin_support": "[VSCode plugin](http://vscext-project.autojs6.com) supports both client (LAN) and server (LAN/ADB) connection methods",
diff --git a/.readme/lang_es.json b/.readme/lang_es.json
index ae79118d..92b63df2 100644
--- a/.readme/lang_es.json
+++ b/.readme/lang_es.json
@@ -66,7 +66,7 @@
"li_major_changes_multilingual_support": "Soporte multilingüe [Español / Francés / Ruso / Árabe / Japonés / Coreano / Inglés / Chino Simplificado / Chino Tradicional / ...]",
"li_major_changes_new_modules": "Nuevos módulos [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "Soporte para modo nocturno en varias páginas [ página de configuración / página de documentación / página de análisis de diseño / ventana flotante / ... ]",
- "li_major_changes_rhino_engine_upgrade": "El motor [Rhino](https://github.com/mozilla/rhino/) se ha actualizado de [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) a {{ latest_rhino_engine_name_with_github_lineno_address }}",
+ "li_major_changes_rhino_engine_upgrade": "El motor [Rhino](https://github.com/mozilla/rhino/) se ha actualizado de [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) a {{ latest_rhino_engine_name_with_github_lineno_address }} (actualizado el {{ var_date_rhino_engine_latest_committed }})",
"li_major_changes_shizuku_adb_privileges_support": "Soporte para obtener privilegios ADB usando [Shizuku](https://shizuku.rikka.app/introduction/) y usar las API del sistema",
"li_major_changes_theme_color_support": "Adaptation des couleurs du thème [ Groupement / Localisation / Recherche / Historique / Adaptation automatique de la luminosité et du contraste / ... ]",
"li_major_changes_vscode_plugin_support": "El [complemento de VSCode](http://vscext-project.autojs6.com) soporta conexiones cliente (LAN) y servidor (LAN/ADB)",
diff --git a/.readme/lang_fr.json b/.readme/lang_fr.json
index 2f5561e5..5cfa54d8 100644
--- a/.readme/lang_fr.json
+++ b/.readme/lang_fr.json
@@ -66,7 +66,7 @@
"li_major_changes_multilingual_support": "Adaptation multilingue [ Espagnol / Français / Russe / Arabe / Japonais / Coréen / Anglais / Chinois Simplifié / Chinois Traditionnel / ... ]",
"li_major_changes_new_modules": "Nouveaux modules ajoutés [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "Adaptation du mode nuit [ Paramètres / Documentation / Analyse de la disposition / Fenêtre flottante / ... ]",
- "li_major_changes_rhino_engine_upgrade": "Le moteur [Rhino](https://github.com/mozilla/rhino/) a été mis à niveau de [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) à {{ latest_rhino_engine_name_with_github_lineno_address }}",
+ "li_major_changes_rhino_engine_upgrade": "Le moteur [Rhino](https://github.com/mozilla/rhino/) a été mis à niveau de [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) à {{ latest_rhino_engine_name_with_github_lineno_address }} (mis à jour le {{ var_date_rhino_engine_latest_committed }})",
"li_major_changes_shizuku_adb_privileges_support": "Prise en charge des privilèges ADB via [Shizuku](https://shizuku.rikka.app/introduction/) pour utiliser les API système",
"li_major_changes_theme_color_support": "Adaptación del color del tema [ Agrupación / Ubicación / Búsqueda / Historial / Adaptación automática de brillo y contraste / ... ]",
"li_major_changes_vscode_plugin_support": "Prise en charge de l'extension [VSCode](http://vscext-project.autojs6.com) pour la connexion client (LAN) et serveur (LAN/ADB)",
diff --git a/.readme/lang_ja.json b/.readme/lang_ja.json
index 288b69db..c510a2db 100644
--- a/.readme/lang_ja.json
+++ b/.readme/lang_ja.json
@@ -66,7 +66,7 @@
"li_major_changes_multilingual_support": "多言語対応 [ 西 / 仏 / 露 / 阿 / 日 / 韓 / 英 / 簡中 / 繁中 / ... ]",
"li_major_changes_new_modules": "新モジュール [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "ナイトモード対応 [ 設定ページ / ドキュメントページ / レイアウト分析ページ / 浮動ウィンドウ / ... ]",
- "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/)エンジンが [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) から {{ latest_rhino_engine_name_with_github_lineno_address }} にアップグレードされました",
+ "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/)エンジンが [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) から {{ latest_rhino_engine_name_with_github_lineno_address }} ({{ var_date_rhino_engine_latest_committed }} 更新) にアップグレードされました",
"li_major_changes_shizuku_adb_privileges_support": "[Shizuku](https://shizuku.rikka.app/introduction/)経由でADB特権を取得し, システムAPIを使用可能",
"li_major_changes_theme_color_support": "テーマカラーの適応 [ グループ化 / ロケーション / 検索 / 履歴 / 明るさとコントラストの自動適応 / ... ]",
"li_major_changes_vscode_plugin_support": "[VSCodeプラグイン](http://vscext-project.autojs6.com)がクライアント (LAN)とサーバ (LAN/ADB)接続方法をサポート",
diff --git a/.readme/lang_ko.json b/.readme/lang_ko.json
index c19ca660..cbbd2a7f 100644
--- a/.readme/lang_ko.json
+++ b/.readme/lang_ko.json
@@ -62,11 +62,11 @@
"li_function_screenshot_and_image_matching_support": "스크린샷 찍기/스크린샷 저장/이미지 색상 찾기/이미지 매칭 지원",
"li_function_selector_api_support": "선택기 API 지원 및 컨트롤 탐색/정보 가져오기/컨트롤 작업 지원 ( [UiAutomator](https://developer.android.com/training/testing/ui-automator)와 유사)",
"li_function_tasker_plugin_support": "Tasker 플러그인으로 사용 가능",
- "li_function_vscode_integration_support": "VSCode와 연결하여 데스크톱 개발 지원 ( [AutoJs6-VSCode-Extension](http://vscext-project.autojs6.com) 플러그인 필요)",
+ "li_function_vscode_integration_support": "VSCode와 연결하여 데스크톱 개발 지원 ([AutoJs6-VSCode-Extension](http://vscext-project.autojs6.com) 플러그인 필요)",
"li_major_changes_multilingual_support": "다국어 지원 [ 서 / 프 / 러 / 아 / 일 / 한 / 영어 / 중국어 / 번체 중 ... ]",
"li_major_changes_new_modules": "새로운 모듈 추가 [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "야경 모드 지원 [ 설정 페이지 / 문서 페이지 / 레이아웃 분석 페이지 / 플로팅 창 / ... ]",
- "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) 엔진을 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release)에서 {{ latest_rhino_engine_name_with_github_lineno_address }}로 업그레이드",
+ "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) 엔진을 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 에서 {{ latest_rhino_engine_name_with_github_lineno_address }} 로 업그레이드 ({{ var_date_rhino_engine_latest_committed }} 업데이트됨)",
"li_major_changes_shizuku_adb_privileges_support": "[Shizuku](https://shizuku.rikka.app/introduction/)를 통해 ADB 특권을 얻고 시스템 API 사용 지원",
"li_major_changes_theme_color_support": "테마 색상 적응 [ 그룹화 / 위치 / 검색 / 기록 / 밝기 및 대비 자동 적응 / ...]",
"li_major_changes_vscode_plugin_support": "[VSCode 플러그인](http://vscext-project.autojs6.com) 지원 클라이언트 (LAN) 및 서버 (LAN/ADB) 연결 방식",
diff --git a/.readme/lang_ru.json b/.readme/lang_ru.json
index b8cbb461..97bee5e7 100644
--- a/.readme/lang_ru.json
+++ b/.readme/lang_ru.json
@@ -66,7 +66,7 @@
"li_major_changes_multilingual_support": "Поддержка нескольких языков [ испанский / французский / русский / арабский / японский / корейский / английский / упрощенный китайский / традиционный китайский / ... ]",
"li_major_changes_new_modules": "Добавлены новые модули [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "Поддержка ночного режима [ страница настроек / страница документации / страница анализа макета / плавающее окно / ... ]",
- "li_major_changes_rhino_engine_upgrade": "Движок [Rhino](https://github.com/mozilla/rhino/) обновлен с версии [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) до версии {{ latest_rhino_engine_name_with_github_lineno_address }}",
+ "li_major_changes_rhino_engine_upgrade": "Движок [Rhino](https://github.com/mozilla/rhino/) обновлен с версии [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) до версии {{ latest_rhino_engine_name_with_github_lineno_address }} (обновлено {{ var_date_rhino_engine_latest_committed }})",
"li_major_changes_shizuku_adb_privileges_support": "Поддержка получения привилегий ADB через [Shizuku](https://shizuku.rikka.app/introduction/) и использование системных API",
"li_major_changes_theme_color_support": "Адаптация темы [ Группировка / Локация / Поиск / История / Автоматическая адаптация яркости и контрастности / ... ]",
"li_major_changes_vscode_plugin_support": "Плагин [VSCode](http://vscext-project.autojs6.com) поддерживает варианты подключения клиента (LAN) и сервера (LAN/ADB)",
diff --git a/.readme/lang_zh-Hans.json b/.readme/lang_zh-Hans.json
index 7d0dc2fe..76368a34 100644
--- a/.readme/lang_zh-Hans.json
+++ b/.readme/lang_zh-Hans.json
@@ -66,7 +66,7 @@
"li_major_changes_multilingual_support": "多语言适配 [ 西 / 法 / 俄 / 阿 / 日 / 韩 / 英 / 简中 / 繁中 / ... ]",
"li_major_changes_new_modules": "新增模块 [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "夜间模式适配 [ 设置页面 / 文档页面 / 布局分析页面 / 浮动窗口 / ... ]",
- "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升级至 {{ latest_rhino_engine_name_with_github_lineno_address }}",
+ "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升级至 {{ latest_rhino_engine_name_with_github_lineno_address }} (更新于 {{ var_date_rhino_engine_latest_committed }})",
"li_major_changes_shizuku_adb_privileges_support": "支持通过 [Shizuku](https://shizuku.rikka.app/introduction/) 获得 ADB 特权并使用系统 API",
"li_major_changes_theme_color_support": "主题色适配 [ 分组 / 定位 / 搜索 / 历史记录 / 亮度及对比度自动适配 / ... ]",
"li_major_changes_vscode_plugin_support": "[VSCode 插件](http://vscext-project.autojs6.com) 支持客户端 (LAN) 及服务端 (LAN/ADB) 连接方式",
diff --git a/.readme/lang_zh-Hant-HK.json b/.readme/lang_zh-Hant-HK.json
index 3e293282..fb71a812 100644
--- a/.readme/lang_zh-Hant-HK.json
+++ b/.readme/lang_zh-Hant-HK.json
@@ -66,7 +66,7 @@
"li_major_changes_multilingual_support": "多語言適配 [ 西 / 法 / 俄 / 阿 / 日 / 韓 / 英 / 簡中 / 繁中 / ... ]",
"li_major_changes_new_modules": "新增模塊 [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "夜間模式適配 [ 設置頁面 / 文檔頁面 / 佈局分析頁面 / 浮動窗口 / ... ]",
- "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升級至 {{ latest_rhino_engine_name_with_github_lineno_address }}",
+ "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升級至 {{ latest_rhino_engine_name_with_github_lineno_address }} (更新於 {{ var_date_rhino_engine_latest_committed }})",
"li_major_changes_shizuku_adb_privileges_support": "支持通過 [Shizuku](https://shizuku.rikka.app/introduction/) 獲得 ADB 特權並使用系統 API",
"li_major_changes_theme_color_support": "主題色適配 [ 分組 / 定位 / 搜索 / 歷史記錄 / 亮度及對比度自動適配 / ... ]",
"li_major_changes_vscode_plugin_support": "[VSCode 插件](http://vscext-project.autojs6.com) 支持客户端 (LAN) 及服務端 (LAN/ADB) 連接方式",
diff --git a/.readme/lang_zh-Hant-TW.json b/.readme/lang_zh-Hant-TW.json
index 60173a8d..6bfed449 100644
--- a/.readme/lang_zh-Hant-TW.json
+++ b/.readme/lang_zh-Hant-TW.json
@@ -66,7 +66,7 @@
"li_major_changes_multilingual_support": "多語言適配 [ 西 / 法 / 俄 / 阿 / 日 / 韓 / 英 / 簡中 / 繁中 / ... ]",
"li_major_changes_new_modules": "新增模組 [ [base64](https://docs.autojs6.com/#/base64) / [crypto](https://docs.autojs6.com/#/crypto) / [sqlite](https://docs.autojs6.com/#/sqlite) / [i18n](https://docs.autojs6.com/#/i18n) / [notice](https://docs.autojs6.com/#/notice) / [ocr](https://docs.autojs6.com/#/ocr) / [opencc](https://docs.autojs6.com/#/opencc) / [qrcode](https://docs.autojs6.com/#/qrcode) / [shizuku](https://docs.autojs6.com/#/shizuku) / ... ]",
"li_major_changes_night_mode_support": "夜間模式適配 [ 設定頁面 / 文件頁面 / 佈局分析頁面 / 浮動視窗 / ... ]",
- "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升級至 {{ latest_rhino_engine_name_with_github_lineno_address }}",
+ "li_major_changes_rhino_engine_upgrade": "[Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升級至 {{ latest_rhino_engine_name_with_github_lineno_address }} (更新於 {{ var_date_rhino_engine_latest_committed }})",
"li_major_changes_shizuku_adb_privileges_support": "支援透過 [Shizuku](https://shizuku.rikka.app/introduction/) 獲得 ADB 特權並使用系統 API",
"li_major_changes_theme_color_support": "主題色適配 [ 分組 / 定位 / 搜尋 / 歷史記錄 / 亮度及對比度自動適配 / ... ]",
"li_major_changes_vscode_plugin_support": "[VSCode 外掛](http://vscext-project.autojs6.com) 支援客戶端 (LAN) 及服務端 (LAN/ADB) 連線方式",
diff --git a/.readme/template_readme.md b/.readme/template_readme.md
index f4b1bce7..187e3ade 100644
--- a/.readme/template_readme.md
+++ b/.readme/template_readme.md
@@ -8,16 +8,16 @@
{{ text_autojs6_synopsis }}
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -379,17 +379,17 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
{{ p_contribution_table_thank_all_contributors }}.
-| {{ table_header_contribution_contributors }} | {{ table_header_contribution_number_of_commits }} | {{ table_header_contribution_recent_submissions }} |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| {{ table_header_contribution_contributors }} | {{ table_header_contribution_number_of_commits }} | {{ table_header_contribution_recent_submissions }} |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
{{ p_contribution_table_data_updated_on }}.
@@ -412,11 +412,12 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/.utils/.gitignore b/.utils/.gitignore
new file mode 100644
index 00000000..7af7f047
--- /dev/null
+++ b/.utils/.gitignore
@@ -0,0 +1,2 @@
+/node_modules
+.env
\ No newline at end of file
diff --git a/.utils/fetch-and-parse-android-studio-agp-compatibility-table.mjs b/.utils/fetch-and-parse-android-studio-agp-compatibility-table.mjs
new file mode 100644
index 00000000..f199d60a
--- /dev/null
+++ b/.utils/fetch-and-parse-android-studio-agp-compatibility-table.mjs
@@ -0,0 +1,48 @@
+// fetch-and-parse-android-studio-agp-compatibility-table.mjs
+
+import fetch from 'node-fetch';
+import { load } from 'cheerio';
+import { fileURLToPath } from 'node:url';
+
+const URL = 'https://developer.android.com/studio/releases#android_gradle_plugin_and_android_studio_compatibility';
+
+/**
+ * @return {Promise>}
+ */
+export async function fetchStudioAgpTable() {
+ const html = await fetch(URL).then(r => r.text());
+ const $ = load(html);
+
+ const targetTable = $('table').filter((_, el) => {
+ let text = $(el).find('th').first().text();
+ return /Android Studio version/i.test(text);
+ });
+
+ if (!targetTable.length) {
+ throw new Error('未找到目标表格, 页面结构可能已变更');
+ }
+
+ const rows = [];
+ targetTable.find('tbody tr').each((_, tr) => {
+ const cells = $(tr).find('td').map((_, td) => {
+ return $(td).text().trim().replace(/\s+/g, ' ');
+ }).get();
+ if (cells.length < 2) return;
+ const [ studioVersion, agpRange ] = cells;
+ rows.push({ studioVersion, agpRange });
+ });
+
+ return rows;
+}
+
+async function main() {
+ console.table(await fetchStudioAgpTable());
+}
+
+// 判断是否为直接执行该文件
+if (fileURLToPath(import.meta.url) === process.argv[1]) {
+ main().catch(err => {
+ console.error(err);
+ process.exitCode = 1;
+ });
+}
\ No newline at end of file
diff --git a/.utils/fetch-and-parse-android-studio-latest-stable-version.mjs b/.utils/fetch-and-parse-android-studio-latest-stable-version.mjs
new file mode 100644
index 00000000..429ce05e
--- /dev/null
+++ b/.utils/fetch-and-parse-android-studio-latest-stable-version.mjs
@@ -0,0 +1,138 @@
+// fetch-and-parse-android-studio-latest-stable-version.mjs
+
+import { load } from 'cheerio';
+import { fileURLToPath } from 'node:url';
+
+const URL = 'https://developer.android.com/studio?hl=en';
+
+/**
+ * @param {string} s
+ * @return {string}
+ */
+function norm(s) {
+ return (s ?? '').replace(/\s+/g, ' ').trim();
+}
+
+/**
+ * @param {string} filename
+ * @return {string | null}
+ */
+function buildDownloadUrlFromFilename(filename) {
+ // 例: android-studio-2025.1.2.13-windows.exe
+ const m = /android-studio-([\d.]+)-/.exec(filename);
+ if (!m) return null;
+ const version = m[1];
+ return `https://redirector.gvt1.com/edgedl/android/studio/install/${version}/${filename}`;
+}
+
+/**
+ * @param {string} url
+ * @return {Promise}
+ */
+async function fetchHtml(url) {
+ const res = await fetch(url, {
+ headers: {
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124 Safari/537.36',
+ 'accept-language': 'en',
+ },
+ });
+ if (!res.ok) throw new Error(`HTTP ${res.status} for ${url}`);
+ return await res.text();
+}
+
+/**
+ * @typedef {'exe' | 'zip' | 'other'} RowKind
+ */
+
+/**
+ * @typedef {Object} Row
+ * @property {string} platform
+ * @property {string} filename
+ * @property {string} size
+ * @property {string} sha256
+ * @property {string | null} url
+ * @property {RowKind} kind
+ */
+/**
+ * @param {string} html
+ * @return {Row[]}
+ */
+function parseWindowsRowsFromHtml(html) {
+ const $ = load(html);
+ const rows = [];
+
+ /** @type {import('cheerio').Cheerio} */
+ const tableRows = $('table.download tbody tr');
+ tableRows.each((_, tr) => {
+ const tds = $(tr).find('td');
+ if (tds.length !== 4) return;
+
+ const platform = norm($(tds[0]).text());
+ if (!/windows/i.test(platform)) return;
+
+ const btn = $(tds[1]).find('button.devsite-dialog-button').first();
+ const filename = norm(btn.text());
+ if (!filename || !filename.includes('android-studio')) return;
+
+ const size = norm($(tds[2]).text());
+ const sha256 = norm($(tds[3]).text());
+ const url = buildDownloadUrlFromFilename(filename);
+
+ rows.push({
+ platform,
+ filename,
+ size,
+ sha256,
+ url,
+ kind: filename.endsWith('.exe')
+ ? 'exe'
+ : filename.endsWith('.zip')
+ ? 'zip'
+ : 'other',
+ });
+ });
+
+ return rows
+ .filter(r => r.kind === 'exe' || r.kind === 'zip')
+ .sort((a) => a.kind === 'exe' ? -1 : 1);
+}
+
+/**
+ * 导出: 获取最新稳定版 Windows 的下载信息 (exe 与 zip)
+ * 返回形如:
+ * [
+ * { platform, filename, size, sha256, url, kind: 'exe' },
+ * { platform, filename, size, sha256, url, kind: 'zip' }
+ * ]
+ *
+ * @param {string} [sourceUrl=URL]
+ * @returns {Promise}
+ */
+export async function getLatestStableWindows(sourceUrl = URL) {
+ const html = await fetchHtml(sourceUrl);
+ const rows = parseWindowsRowsFromHtml(html);
+ if (!rows.length) {
+ throw new Error('未在页面中找到 Windows 稳定版下载条目');
+ }
+ return rows;
+}
+
+// CLI 模式: 直接运行则打印结果; 被 import 时不执行
+async function main() {
+ const rows = await getLatestStableWindows(URL);
+ for (const r of rows) {
+ console.log(`${r.kind.toUpperCase()}:`);
+ console.log(` filename : ${r.filename}`);
+ console.log(` size : ${r.size}`);
+ console.log(` sha256 : ${r.sha256}`);
+ console.log(` url : ${r.url}`);
+ }
+}
+
+// 判断是否为直接执行该文件
+if (fileURLToPath(import.meta.url) === process.argv[1]) {
+ main().catch(err => {
+ console.error(err);
+ process.exitCode = 1;
+ });
+}
diff --git a/.utils/fetch-and-parse-autojs6-merged-pr-commits-statistics.mjs b/.utils/fetch-and-parse-autojs6-merged-pr-commits-statistics.mjs
new file mode 100644
index 00000000..5add5cfb
--- /dev/null
+++ b/.utils/fetch-and-parse-autojs6-merged-pr-commits-statistics.mjs
@@ -0,0 +1,373 @@
+// fetch-and-parse-autojs6-merged-pr-commits-statistics.mjs
+
+/** @typedef {import('@octokit/types').Endpoints['GET /repos/{owner}/{repo}/pulls']['response']['data']} PullsData */
+/** @typedef {import('@octokit/types').Endpoints['GET /repos/{owner}/{repo}/pulls/{pull_number}/commits']['response']['data']} PullCommitsData */
+
+import fetch from 'node-fetch';
+import * as dotenv from 'dotenv';
+import { fileURLToPath } from 'node:url';
+import { toYYYYMMDD } from './utils/date.mjs';
+
+dotenv.config({ path: '.env', quiet: true });
+
+const REPO = 'AutoJs6';
+const OWNER = 'SuperMonster003';
+const BASE = `https://api.github.com/repos/${OWNER}/${REPO}`;
+const GITHUB_TOKEN = process.env.GITHUB_TOKEN || '';
+
+// 调试: 设置为某个作者的登录名 (login) 以打印该作者的匹配细节
+const DEBUG_LOGIN = process.env.DEBUG_LOGIN || '';
+const DEBUG_VERBOSE = process.env.DEBUG_VERBOSE === '1';
+
+// 可排除的登录名列表 (默认排除仓库维护者); 可用 EXCLUDED_LOGINS 环境变量覆盖, 逗号分隔
+const EXCLUDED_LOGINS = (process.env.EXCLUDED_LOGINS || OWNER)
+ .split(',')
+ .map(s => s.trim())
+ .filter(Boolean);
+
+/**
+ * @return {import('node-fetch').HeadersInit}
+ */
+function headers() {
+ return {
+ accept: 'application/vnd.github+json',
+ ...(GITHUB_TOKEN ? { authorization: `Bearer ${GITHUB_TOKEN}` } : {}),
+ 'user-agent': 'pr-commit-contributions',
+ };
+}
+
+/**
+ * @typedef {Object} UserProfile
+ * @property {string} login
+ * @property {string | null} name
+ */
+/**
+ * 简单内存缓存, 避免重复请求.
+ *
+ * @type {Map}
+ */
+const userProfileCache = new Map();
+
+/**
+ * @param {string} login
+ * @return {Promise}
+ */
+async function getUserProfile(login) {
+ if (userProfileCache.has(login)) return userProfileCache.get(login);
+ const url = `https://api.github.com/users/${login}`;
+ const res = await fetch(url, { headers: headers() });
+ if (!res.ok) {
+ userProfileCache.set(login, { login, name: null });
+ return { login, name: null };
+ }
+ const data = await res.json();
+ const profile = {
+ login: data?.['login'] || login,
+ name: data?.['name'] || null,
+ };
+ userProfileCache.set(login, profile);
+ return profile;
+}
+
+/**
+ * @return {Promise}
+ */
+async function fetchAllMergedPRs() {
+ const perPage = 100;
+ let page = 1;
+ const merged = [];
+
+ while (true) {
+ const url = `${BASE}/pulls?state=closed&per_page=${perPage}&page=${page}&sort=created&direction=asc`;
+ const res = await fetch(url, { headers: headers() });
+ if (!res.ok) {
+ const text = await res.text();
+ throw new Error(`获取 PR 列表失败: ${res.status} ${res.statusText} - ${text}`);
+ }
+ const prs = /** @type {PullsData} */ await res.json();
+ if (!Array.isArray(prs) || prs.length === 0) break;
+
+ for (const pr of prs) {
+ if (pr.merged_at) merged.push(pr);
+ }
+
+ if (prs.length < perPage) break;
+ page += 1;
+ }
+
+ return merged;
+}
+
+/**
+ * @param {string} a
+ * @param {string} b
+ * @return {boolean}
+ */
+function equalsIgnoreCase(a, b) {
+ return typeof a === 'string'
+ && typeof b === 'string'
+ && a.toLowerCase() === b.toLowerCase();
+}
+
+/**
+ * @param {PullCommitsData[number]} c
+ * @return {string | null}
+ */
+function commitTimeFrom(c) {
+ return c.commit?.committer?.date
+ || c.commit?.author?.date
+ || null;
+}
+
+/**
+ * 规则: 排除 EXCLUDED_LOGINS (author.login 或 committer.login 命中即排除); 其余一律计入.
+ *
+ * @param {PullCommitsData[number]} c
+ * @return {boolean}
+ */
+function isCommitBelongsToLogin(c) {
+ const authorLogin = c.author?.login || null;
+ const committerLogin = c.committer?.login || null;
+
+ return !(authorLogin && EXCLUDED_LOGINS.some(x => equalsIgnoreCase(x, authorLogin)))
+ && !(committerLogin && EXCLUDED_LOGINS.some(x => equalsIgnoreCase(x, committerLogin)));
+}
+
+/**
+ * @typedef {Object} DebugRecord
+ * @property {string} sha
+ * @property {boolean} belongs
+ * @property {string | null} author_login
+ * @property {string | null} committer_login
+ * @property {string | null} author_name
+ * @property {string | null} author_email
+ * @property {string | null} time
+ */
+/**
+ * @param {PullsData[number]} pr
+ * @return {Promise<{count: number, latestCommitAt: string | null}>} - 该 PR 中属于 PR 作者本人的提交计数与最新提交时间.
+ */
+async function getPRCommitStatsByAuthor(pr) {
+ const perPage = 100;
+ let page = 1;
+ let total = 0;
+ let latestCommitAt = null;
+
+ const login = pr.user?.login;
+ if (!login) return { count: 0, latestCommitAt: null };
+
+ // 仅在调试该作者时收集详细信息
+ /** @type {DebugRecord[]} */
+ const debugRecords = [];
+
+ while (true) {
+ const url = `${BASE}/pulls/${pr.number}/commits?per_page=${perPage}&page=${page}`;
+ const res = await fetch(url, { headers: headers() });
+ if (!res.ok) {
+ const text = await res.text();
+ throw new Error(`获取 PR #${pr.number} 的 commits 失败: ${res.status} ${res.statusText} - ${text}`);
+ }
+ const commits = /** @type {PullCommitsData} */ await res.json();
+ if (!Array.isArray(commits) || commits.length === 0) break;
+
+ for (const c of commits) {
+ const included = isCommitBelongsToLogin(c);
+ if (included) {
+ total += 1;
+ const t = commitTimeFrom(c);
+ if (t && (!latestCommitAt || new Date(t) > new Date(latestCommitAt))) {
+ latestCommitAt = t;
+ }
+ }
+ if (DEBUG_LOGIN && equalsIgnoreCase(login, DEBUG_LOGIN)) {
+ debugRecords.push({
+ sha: c.sha,
+ belongs: included,
+ author_login: c.author?.login || null,
+ committer_login: c.committer?.login || null,
+ author_name: c.commit?.author?.name || null,
+ author_email: c.commit?.author?.email || null,
+ time: c.commit?.committer?.date || c.commit?.author?.date || null,
+ });
+ }
+ }
+
+ if (commits.length < perPage) break;
+ page += 1;
+ }
+
+ // 打印调试: 仅针对目标作者; 默认仅在该 PR 统计结果为 0 时打印, 或开启 DEBUG_VERBOSE 时总是打印
+ if (DEBUG_LOGIN && equalsIgnoreCase(login, DEBUG_LOGIN) && (DEBUG_VERBOSE || total === 0)) {
+ const matched = debugRecords.filter(r => r.belongs).length;
+ const unmatched = debugRecords.length - matched;
+ console.log(`\n[DEBUG] PR #${pr.number} by ${login}: commits=${debugRecords.length}, included=${matched}, excluded=${unmatched}`);
+ for (const r of debugRecords) {
+ if (DEBUG_VERBOSE || !r.belongs) {
+ console.log(`[DEBUG] ${r.sha} | included=${r.belongs} | author_login=${r.author_login} | committer_login=${r.committer_login} | author_name=${r.author_name} | author_email=${r.author_email} | time=${r.time}`);
+ }
+ }
+ }
+
+ return { count: total, latestCommitAt };
+}
+
+/**
+ * @template Item
+ * @template MapperResult
+ * @param {Item[]} items
+ * @param {number} limit
+ * @param {(item: Item, idx: number) => Promise} mapper
+ * @return {Promise}
+ */
+async function mapWithLimit(items, limit, mapper) {
+ const results = new Array(items.length);
+ let i = 0;
+ const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
+ while (true) {
+ const idx = i++;
+ if (idx >= items.length) break;
+ results[idx] = await mapper(items[idx], idx);
+ }
+ });
+ await Promise.all(workers);
+ return results;
+}
+
+/**
+ * 批量获取作者资料 (并发受限), 返回 Map.
+ *
+ * @param {string[]} logins
+ * @param {number} [concurrency=6]
+ * @return {Promise>}
+ */
+async function fetchProfilesForLogins(logins, concurrency = 6) {
+ const unique = Array.from(new Set(logins)).filter(Boolean);
+ const profiles = await mapWithLimit(unique, concurrency, async (login) => {
+ return await getUserProfile(login);
+ });
+ const map = new Map();
+ for (const p of profiles) {
+ map.set(p.login, p);
+ }
+ return map;
+}
+
+/**
+ * @return {Promise}
+ */
+export async function fetchStatistics() {
+ const mergedPRs = await fetchAllMergedPRs();
+ const CONCURRENCY = 6;
+ const prWithStats = await mapWithLimit(mergedPRs, CONCURRENCY, async (pr) => {
+ const { count, latestCommitAt } = await getPRCommitStatsByAuthor(pr);
+ return { pr, count, latestCommitAt };
+ });
+
+ // 先收集所有作者, 再批量获取资料 (并发受限 + 内存缓存)
+ const allLogins = prWithStats
+ .map(({ pr }) => pr.user?.login)
+ .filter(Boolean);
+ const profileMap = await fetchProfilesForLogins(allLogins, 6);
+
+ // 按 PR 发起者聚合
+ const byAuthor = new Map();
+ for (const { pr, count, latestCommitAt } of prWithStats) {
+ const user = pr.user;
+ if (!user?.login) continue;
+
+ const entry = byAuthor.get(user.login) || {
+ login: user.login,
+ name: profileMap.get(user.login)?.name || null,
+ html_url: `https://github.com/${user.login}`,
+ totalCommitsInMergedPRs: 0,
+ latestCommitAt: null,
+ };
+
+ entry.totalCommitsInMergedPRs += count;
+
+ if (latestCommitAt && (!entry.latestCommitAt || new Date(latestCommitAt) > new Date(entry.latestCommitAt))) {
+ entry.latestCommitAt = latestCommitAt;
+ }
+
+ byAuthor.set(user.login, entry);
+ }
+
+ // 按最近提交倒序
+ const rows = Array.from(byAuthor.values()).sort((a, b) => {
+ const da = a.latestCommitAt ? new Date(a.latestCommitAt).getTime() : 0;
+ const db = b.latestCommitAt ? new Date(b.latestCommitAt).getTime() : 0;
+ return db - da;
+ });
+
+ return rows.map(r => new Statistics(r));
+}
+
+async function main() {
+ return await fetchStatistics();
+}
+
+class Statistics {
+ /**
+ * @param row {{
+ * login: string,
+ * name: string | null,
+ * html_url: string,
+ * totalCommitsInMergedPRs: number,
+ * latestCommitAt: string | null,
+ * prListLink: string,
+ * }}
+ */
+ constructor(row) {
+ this.login = row.login;
+ this.name = row.name;
+ this.html_url = row.html_url;
+ this.totalCommitsInMergedPRs = row.totalCommitsInMergedPRs;
+ this.latestCommitAt = row.latestCommitAt;
+ this.prListLink = `https://github.com/${OWNER}/${REPO}/pulls?q=`
+ + 'is' + '%3A' + 'pr' + '+'
+ + 'is' + '%3A' + 'merged' + '+'
+ + 'author' + '%3A' + encodeURIComponent(row.login);
+ }
+
+ /**
+ * @param {string} text
+ * @param {string} [style='word-break:keep-all;white-space:nowrap']
+ * @returns {string}
+ */
+ #wrapInSpan(text, style = 'word-break:keep-all;white-space:nowrap') {
+ return `${text} `;
+ }
+
+ get contributorMarkdown() {
+ let markdownName = `[${this.login.replace(/-/g, '‑')}](${this.html_url})`;
+ if (this.name && this.name !== this.login) {
+ markdownName += ` \`(${this.name})\``;
+ }
+ return this.#wrapInSpan(markdownName);
+ }
+
+ get commitsCountMarkdown() {
+ return this.#wrapInSpan(`[${this.totalCommitsInMergedPRs}](${this.prListLink})`);
+ }
+
+ get latestCommitMarkdown() {
+ if (!this.latestCommitAt) {
+ return this.#wrapInSpan('`N/A`');
+ }
+ return this.#wrapInSpan(`\`${toYYYYMMDD(this.latestCommitAt)}\``);
+ }
+}
+
+// 判断是否为直接执行该文件
+if (fileURLToPath(import.meta.url) === process.argv[1]) {
+ main().then((dataList) => {
+ console.table(dataList.map(r => ({
+ contributor: r.name && r.name !== r.login ? `${r.login} (${r.name})` : r.login,
+ commits: r.totalCommitsInMergedPRs,
+ recent: r.latestCommitAt ? toYYYYMMDD(r.latestCommitAt) : 'N/A',
+ })));
+ }).catch(err => {
+ console.error(err);
+ process.exit(1);
+ });
+}
\ No newline at end of file
diff --git a/.utils/package-lock.json b/.utils/package-lock.json
new file mode 100644
index 00000000..a7738a38
--- /dev/null
+++ b/.utils/package-lock.json
@@ -0,0 +1,1505 @@
+{
+ "name": ".utils",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "cheerio": "^1.1.2",
+ "domhandler": "^5.0.3",
+ "dotenv": "^17.2.2",
+ "node-fetch": "^3.3.2",
+ "puppeteer": "^24.17.1"
+ },
+ "devDependencies": {
+ "@octokit/types": "^14.1.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+ "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@octokit/openapi-types": {
+ "version": "25.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
+ "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@octokit/types": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
+ "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/openapi-types": "^25.1.0"
+ }
+ },
+ "node_modules/@puppeteer/browsers": {
+ "version": "2.10.8",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.8.tgz",
+ "integrity": "sha512-f02QYEnBDE0p8cteNoPYHHjbDuwyfbe4cCIVlNi8/MRicIxFW4w4CfgU0LNgWEID6s06P+hRJ1qjpBLMhPRCiQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "debug": "^4.4.1",
+ "extract-zip": "^2.0.1",
+ "progress": "^2.0.3",
+ "proxy-agent": "^6.5.0",
+ "semver": "^7.7.2",
+ "tar-fs": "^3.1.0",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "browsers": "lib/cjs/main-cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@tootallnate/quickjs-emscripten": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
+ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "24.3.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz",
+ "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "undici-types": "~7.10.0"
+ }
+ },
+ "node_modules/@types/yauzl": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
+ "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
+ "node_modules/ast-types": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
+ "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/b4a": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
+ "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/bare-events": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.6.1.tgz",
+ "integrity": "sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g==",
+ "license": "Apache-2.0",
+ "optional": true
+ },
+ "node_modules/bare-fs": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.2.1.tgz",
+ "integrity": "sha512-mELROzV0IhqilFgsl1gyp48pnZsaV9xhQapHLDsvn4d4ZTfbFhcghQezl7FTEDNBcGqLUnNI3lUlm6ecrLWdFA==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "bare-events": "^2.5.4",
+ "bare-path": "^3.0.0",
+ "bare-stream": "^2.6.4"
+ },
+ "engines": {
+ "bare": ">=1.16.0"
+ },
+ "peerDependencies": {
+ "bare-buffer": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-buffer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/bare-os": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz",
+ "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "engines": {
+ "bare": ">=1.14.0"
+ }
+ },
+ "node_modules/bare-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
+ "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "bare-os": "^3.0.1"
+ }
+ },
+ "node_modules/bare-stream": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz",
+ "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "streamx": "^2.21.0"
+ },
+ "peerDependencies": {
+ "bare-buffer": "*",
+ "bare-events": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-buffer": {
+ "optional": true
+ },
+ "bare-events": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/basic-ftp": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
+ "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cheerio": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz",
+ "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==",
+ "license": "MIT",
+ "dependencies": {
+ "cheerio-select": "^2.1.0",
+ "dom-serializer": "^2.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.2",
+ "encoding-sniffer": "^0.2.1",
+ "htmlparser2": "^10.0.0",
+ "parse5": "^7.3.0",
+ "parse5-htmlparser2-tree-adapter": "^7.1.0",
+ "parse5-parser-stream": "^7.1.2",
+ "undici": "^7.12.0",
+ "whatwg-mimetype": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=20.18.1"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+ "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-select": "^5.1.0",
+ "css-what": "^6.1.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/chromium-bidi": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-8.0.0.tgz",
+ "integrity": "sha512-d1VmE0FD7lxZQHzcDUCKZSNRtRwISXDsdg4HjdTR5+Ll5nQ/vzU12JeNmupD6VWffrPSlrnGhEWlLESKH3VO+g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "mitt": "^3.0.1",
+ "zod": "^3.24.1"
+ },
+ "peerDependencies": {
+ "devtools-protocol": "*"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/cosmiconfig": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
+ "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
+ "license": "MIT",
+ "dependencies": {
+ "env-paths": "^2.2.1",
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/css-select": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
+ "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
+ "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/degenerator": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
+ "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ast-types": "^0.13.4",
+ "escodegen": "^2.1.0",
+ "esprima": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/devtools-protocol": {
+ "version": "0.0.1475386",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1475386.tgz",
+ "integrity": "sha512-RQ809ykTfJ+dgj9bftdeL2vRVxASAuGU+I9LEx9Ij5TXU5HrgAQVmzi72VA+mkzscE12uzlRv5/tWWv9R9J1SA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "17.2.2",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz",
+ "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/encoding-sniffer": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
+ "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "^0.6.3",
+ "whatwg-encoding": "^3.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escodegen": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ },
+ "bin": {
+ "extract-zip": "cli.js"
+ },
+ "engines": {
+ "node": ">= 10.17.0"
+ },
+ "optionalDependencies": {
+ "@types/yauzl": "^2.9.1"
+ }
+ },
+ "node_modules/fast-fifo": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
+ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
+ "license": "MIT"
+ },
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+ "license": "MIT",
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
+ "node_modules/fetch-blob": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "node-domexception": "^1.0.0",
+ "web-streams-polyfill": "^3.0.3"
+ },
+ "engines": {
+ "node": "^12.20 || >= 14.13"
+ }
+ },
+ "node_modules/formdata-polyfill": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "license": "MIT",
+ "dependencies": {
+ "fetch-blob": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "license": "MIT",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-uri": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz",
+ "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==",
+ "license": "MIT",
+ "dependencies": {
+ "basic-ftp": "^5.0.2",
+ "data-uri-to-buffer": "^6.0.2",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz",
+ "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.1",
+ "entities": "^6.0.0"
+ }
+ },
+ "node_modules/htmlparser2/node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ip-address": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
+ "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "license": "MIT"
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "license": "MIT"
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "license": "MIT"
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/netmask": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
+ "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "license": "MIT",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
+ "node_modules/node-fetch/node_modules/data-uri-to-buffer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/pac-proxy-agent": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
+ "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==",
+ "license": "MIT",
+ "dependencies": {
+ "@tootallnate/quickjs-emscripten": "^0.23.0",
+ "agent-base": "^7.1.2",
+ "debug": "^4.3.4",
+ "get-uri": "^6.0.1",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.6",
+ "pac-resolver": "^7.0.1",
+ "socks-proxy-agent": "^8.0.5"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-resolver": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
+ "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
+ "license": "MIT",
+ "dependencies": {
+ "degenerator": "^5.0.0",
+ "netmask": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
+ "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
+ "license": "MIT",
+ "dependencies": {
+ "domhandler": "^5.0.3",
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-parser-stream": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
+ "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
+ "license": "MIT",
+ "dependencies": {
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5/node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/proxy-agent": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
+ "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "^4.3.4",
+ "http-proxy-agent": "^7.0.1",
+ "https-proxy-agent": "^7.0.6",
+ "lru-cache": "^7.14.1",
+ "pac-proxy-agent": "^7.1.0",
+ "proxy-from-env": "^1.1.0",
+ "socks-proxy-agent": "^8.0.5"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
+ "node_modules/pump": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
+ "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/puppeteer": {
+ "version": "24.17.1",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.17.1.tgz",
+ "integrity": "sha512-KIuX0w+0um4TUbm55yFl2WIsbgjya2BHIgW9ylTuhavtwjXCOM7lMo9oLR1jQnCxrFvm9h/Yeb+zfs4nlgntPg==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@puppeteer/browsers": "2.10.8",
+ "chromium-bidi": "8.0.0",
+ "cosmiconfig": "^9.0.0",
+ "devtools-protocol": "0.0.1475386",
+ "puppeteer-core": "24.17.1",
+ "typed-query-selector": "^2.12.0"
+ },
+ "bin": {
+ "puppeteer": "lib/cjs/puppeteer/node/cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/puppeteer-core": {
+ "version": "24.17.1",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.17.1.tgz",
+ "integrity": "sha512-Msh/kf9k1XFN0wuKiT4/npMmMWOT7kPBEUw01gWvRoKOOoz3It9TEmWjnt4Gl4eO+p73VMrvR+wfa0dm9rfxjw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@puppeteer/browsers": "2.10.8",
+ "chromium-bidi": "8.0.0",
+ "debug": "^4.4.1",
+ "devtools-protocol": "0.0.1475386",
+ "typed-query-selector": "^2.12.0",
+ "ws": "^8.18.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.7",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
+ "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
+ "license": "MIT",
+ "dependencies": {
+ "ip-address": "^10.0.1",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "8.0.5",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
+ "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/streamx": {
+ "version": "2.22.1",
+ "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.1.tgz",
+ "integrity": "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-fifo": "^1.3.2",
+ "text-decoder": "^1.1.0"
+ },
+ "optionalDependencies": {
+ "bare-events": "^2.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.0.tgz",
+ "integrity": "sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w==",
+ "license": "MIT",
+ "dependencies": {
+ "pump": "^3.0.0",
+ "tar-stream": "^3.1.5"
+ },
+ "optionalDependencies": {
+ "bare-fs": "^4.0.1",
+ "bare-path": "^3.0.0"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
+ "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
+ "license": "MIT",
+ "dependencies": {
+ "b4a": "^1.6.4",
+ "fast-fifo": "^1.2.0",
+ "streamx": "^2.15.0"
+ }
+ },
+ "node_modules/text-decoder": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz",
+ "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "b4a": "^1.6.4"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/typed-query-selector": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
+ "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==",
+ "license": "MIT"
+ },
+ "node_modules/undici": {
+ "version": "7.15.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.15.0.tgz",
+ "integrity": "sha512-7oZJCPvvMvTd0OlqWsIxTuItTpJBpU1tcbVl24FMn3xt3+VSunwUasmfPJRE57oNO1KsZ4PgA1xTdAX4hq8NyQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.10.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
+ "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/web-streams-polyfill": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/ws": {
+ "version": "8.18.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ }
+ }
+}
diff --git a/.utils/package.json b/.utils/package.json
new file mode 100644
index 00000000..307853e6
--- /dev/null
+++ b/.utils/package.json
@@ -0,0 +1,13 @@
+{
+ "type": "module",
+ "dependencies": {
+ "cheerio": "^1.1.2",
+ "node-fetch": "^3.3.2",
+ "puppeteer": "^24.17.1",
+ "domhandler": "^5.0.3",
+ "dotenv": "^17.2.2"
+ },
+ "devDependencies": {
+ "@octokit/types": "^14.1.0"
+ }
+}
diff --git a/.utils/run-scrapers.bat b/.utils/run-scrapers.bat
new file mode 100644
index 00000000..a08b2b8d
--- /dev/null
+++ b/.utils/run-scrapers.bat
@@ -0,0 +1,17 @@
+@ECHO OFF
+:RUN
+node "run-scrapers.mjs"
+ECHO.
+
+REM 显示提示并等待单键 (无需按回车)
+ECHO Press [R] to rerun the scrapers, or [ESC]/[Enter]/[Space] to exit...
+powershell -NoLogo -NoProfile -Command "$ErrorActionPreference='Stop'; while($true){ $k=$Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown'); if($k.VirtualKeyCode -eq 27 -or $k.VirtualKeyCode -eq 13 -or $k.Character -eq ' '){ exit 1 } elseif($k.Character -match '^[Rr]$'){ exit 0 } }"
+
+IF ERRORLEVEL 1 GOTO EXIT
+
+ECHO.
+GOTO RUN
+
+:EXIT
+ECHO.
+EXIT /B
\ No newline at end of file
diff --git a/.utils/run-scrapers.mjs b/.utils/run-scrapers.mjs
new file mode 100644
index 00000000..f5351aad
--- /dev/null
+++ b/.utils/run-scrapers.mjs
@@ -0,0 +1,175 @@
+// run-scrapers.mjs
+
+import { spawn } from 'node:child_process';
+import { fileURLToPath } from 'node:url';
+import * as path from 'node:path';
+import * as fs from 'node:fs/promises';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+// 待执行脚本 (顺序可按需调整)
+const SCRIPT_LIST = [
+ 'scrape-and-inject-agp-releases.mjs',
+ 'scrape-and-inject-android-studio-agp-version-map.mjs',
+ 'scrape-and-inject-android-studio-codename_maps.mjs',
+ 'scrape-and-inject-embedded-kotlin-list.mjs',
+ 'scrape-and-inject-ksp-releases.mjs',
+ 'scrape-and-inject-agp-gradle-compatibility-list.mjs',
+ 'scrape-and-inject-java-gradle-compatibility-list.mjs',
+ 'scrape-and-inject-rhino-engine-data.mjs',
+ 'scrape-and-update-readme-template-contributors-table.mjs',
+];
+
+/**
+ * 解析 CLI 参数.
+ *
+ * @param {string[]} [argv=process.argv.slice(2)]
+ * @return {{ continueOnError: boolean, dryRun: boolean, nodePath: string, filters: string[] }}
+ */
+function parseArgs(argv = process.argv.slice(2)) {
+ const opts = {
+ continueOnError: false,
+ dryRun: false,
+ nodePath: process.execPath, // 使用当前 Node 可执行文件, 避免 PATH 问题
+ filters: [],
+ };
+ for (let i = 0; i < argv.length; i++) {
+ const a = argv[i];
+ if (a === '--continue-on-error') opts.continueOnError = true;
+ else if (a === '--dry-run') opts.dryRun = true;
+ else if (a === '--node') opts.nodePath = argv[++i];
+ else if (a === '--filter') opts.filters.push(argv[++i]);
+ else if (a.startsWith('--filter=')) opts.filters.push(a.split('=').slice(1).join('='));
+ else if (a.startsWith('--node=')) opts.nodePath = a.split('=').slice(1).join('=');
+ }
+ return opts;
+}
+
+/**
+ * @param {number} ms
+ * @return {string}
+ */
+function formatDuration(ms) {
+ const sec = Math.floor(ms / 1000);
+ const msPart = ms % 1000;
+ return `${sec}.${String(msPart).padStart(3, '0')}s`;
+}
+
+/**
+ * @param {import("fs").PathLike} filePath
+ * @return {Promise}
+ */
+async function ensureExists(filePath) {
+ try {
+ await fs.access(filePath);
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+/**
+ * @param {Object} options
+ * @param {string} options.nodePath
+ * @param {string} options.scriptPath
+ * @param {string | URL | undefined} options.cwd
+ * @return {Promise<{ code: number, signal: NodeJS.Signals | null, ms: number, error?: Error }>}
+ */
+async function runOne({ nodePath, scriptPath, cwd }) {
+ return new Promise((resolve) => {
+ const start = Date.now();
+ const child = spawn(nodePath, [ scriptPath ], {
+ cwd,
+ stdio: 'inherit', // 直接把子进程的输出打到当前控制台
+ env: process.env,
+ });
+ child.on('close', (code, signal) => {
+ const end = Date.now();
+ resolve({
+ code: code ?? 0,
+ signal: signal ?? null,
+ ms: end - start,
+ });
+ });
+ child.on('error', (err) => {
+ const end = Date.now();
+ resolve({ code: 1, signal: null, ms: end - start, error: err });
+ });
+ });
+}
+
+async function main() {
+ const opts = parseArgs();
+
+ const utilsDir = __dirname; // 运行器位于 .utils
+ const scripts = SCRIPT_LIST
+ .map(name => ({ name, abs: path.resolve(utilsDir, name) }))
+ .filter(s => opts.filters.length === 0 || opts.filters.some(f => s.name.includes(f)));
+
+ console.log('\n============================================================');
+ console.log(' Running scrapers in sequence (Node ESM)');
+ console.log(` UTILS_DIR = ${utilsDir}`);
+ console.log(` NODE_EXE = ${opts.nodePath}`);
+ if (opts.filters.length) console.log(` FILTERS = ${opts.filters.join(', ')}`);
+ console.log('============================================================\n');
+
+ if (scripts.length === 0) {
+ console.log('No scripts to run after filtering.');
+ return process.exit(0);
+ }
+
+ // 检查存在性
+ const finalScripts = [];
+ for (const s of scripts) {
+ if (await ensureExists(s.abs)) {
+ finalScripts.push(s);
+ } else {
+ console.log(`File not found: ${s.name}`);
+ }
+ }
+ if (finalScripts.length === 0) {
+ console.log('No existing scripts to run.');
+ return process.exit(0);
+ }
+
+ if (opts.dryRun) {
+ console.log('The following scripts would run in order:');
+ finalScripts.forEach((s, i) => console.log(` (${i + 1}/${finalScripts.length}) ${s.name}`));
+ return process.exit(0);
+ }
+
+ const results = [];
+ for (let i = 0; i < finalScripts.length; i++) {
+ const s = finalScripts[i];
+ console.log(`[${i + 1}/${finalScripts.length}] ${s.name}`);
+ const res = await runOne({ nodePath: opts.nodePath, scriptPath: s.abs, cwd: utilsDir });
+ if (res.code === 0) {
+ console.log(`[Duration] ${formatDuration(res.ms)}\n`);
+ } else {
+ console.log(`[Duration] ${formatDuration(res.ms)} | [Exit Code] ${res.code}\n`);
+ results.push({ ...res, name: s.name });
+ if (!opts.continueOnError) break;
+ continue;
+ }
+ results.push({ ...res, name: s.name });
+ }
+
+ const failed = results.filter(r => r.code !== 0);
+ console.log('============================================================');
+ if (failed.length === 0) {
+ console.log(' All tasks completed successfully.');
+ console.log('============================================================\n');
+ process.exit(0);
+ } else {
+ console.log(` ${failed.length} task(s) failed:`);
+ failed.forEach(r => console.log(` - ${r.name} (code ${r.code}, ${formatDuration(r.ms)})`));
+ console.log('============================================================\n');
+ process.exit(1);
+ }
+}
+
+main().catch(err => {
+ console.error(err);
+ process.exit(1);
+});
\ No newline at end of file
diff --git a/.utils/scrape-and-inject-agp-gradle-compatibility-list.mjs b/.utils/scrape-and-inject-agp-gradle-compatibility-list.mjs
new file mode 100644
index 00000000..5ae9764b
--- /dev/null
+++ b/.utils/scrape-and-inject-agp-gradle-compatibility-list.mjs
@@ -0,0 +1,47 @@
+// scrape-and-inject-agp-gradle-compatibility-list.mjs
+
+import { getMinSupportedAgpVersion, getMinSupportedGradleVersion } from './utils/properties.mjs';
+import { compareVersionStrings } from './utils/versioning.mjs';
+import { updateAnchoredListInFile } from './utils/anchors.mjs';
+import { findTargetRows } from './utils/puppeteer-helpers.mjs';
+
+const URL = 'https://developer.android.com/build/releases/gradle-plugin#updating-gradle';
+
+(async function main() {
+ const rows = await findTargetRows({
+ url: URL,
+ tableSelector: '.devsite-table-wrapper table',
+ tableFilter: {
+ 'tr th': [
+ `:RegExp:i:${/Plugin version/.source}`,
+ `:RegExp:i:${/Minimum required Gradle version/.source}`,
+ ],
+ },
+ tableRowSelector: 'tbody tr',
+ tableDataSelector: 'td',
+ tableDataStructure: [
+ 'pluginVersion',
+ 'gradleVersion',
+ ],
+ });
+ const minSupportedAgpVersion = getMinSupportedAgpVersion();
+ const minSupportedGradleVersion = getMinSupportedGradleVersion();
+ const map = {};
+ for (const { pluginVersion, gradleVersion } of rows) {
+ if (compareVersionStrings(pluginVersion, minSupportedAgpVersion) < 0) continue;
+ if (compareVersionStrings(gradleVersion, minSupportedGradleVersion) < 0) continue;
+ map[pluginVersion] = gradleVersion;
+ }
+
+ await updateAnchoredListInFile('../settings.gradle.kts', {
+ anchorTag: 'AGP_GRADLE_COMPATIBILITY_LIST',
+ listName: 'agpGradleCompatibility',
+ lines: Object.entries(map)
+ .sort((a, b) => compareVersionStrings(b[0], a[0]))
+ .map(([ pluginVersion, gradleVersion ]) => `"${pluginVersion}" to "${gradleVersion}",`),
+ updatedLabel: 'AGP 与 Gradle 兼容性映射',
+ });
+})().catch(err => {
+ console.error(err);
+ process.exitCode = 1;
+});
\ No newline at end of file
diff --git a/.utils/scrape-and-inject-agp-releases.mjs b/.utils/scrape-and-inject-agp-releases.mjs
new file mode 100644
index 00000000..ce15dfe0
--- /dev/null
+++ b/.utils/scrape-and-inject-agp-releases.mjs
@@ -0,0 +1,32 @@
+// scrape-and-inject-agp-releases.mjs
+
+import * as cheerio from 'cheerio';
+import { getMinSupportedAgpVersion } from './utils/properties.mjs';
+import { compareVersionStrings, compareVersionStringsDescending } from './utils/versioning.mjs';
+import { updateAnchoredListInFile } from './utils/anchors.mjs';
+
+const URL = 'https://developer.android.com/reference/tools/gradle-api';
+
+(async function main() {
+ const res = await fetch(URL);
+ const $ = cheerio.load(await res.text());
+ const results = new Set();
+ $('table').find('a').each((_, el) => {
+ const a = $(el);
+ const href = a.attr('href');
+ if (href.includes('reference/tools/gradle-api')) {
+ results.add(a.text());
+ }
+ });
+ const minSupportedVersion = getMinSupportedAgpVersion();
+ const agpList = Array.from(results).filter(v => compareVersionStrings(v, minSupportedVersion) >= 0).sort(compareVersionStringsDescending);
+ await updateAnchoredListInFile('../settings.gradle.kts', {
+ anchorTag: 'ANDROID_GRADLE_PLUGIN_RELEASES_LIST',
+ listName: 'agpReleases',
+ lines: agpList.map(v => `"${v}",`),
+ updatedLabel: 'AGP 发行版本数据',
+ });
+})().catch((e) => {
+ console.error('Failed to fetch AGP releases:', e)
+ process.exit(1);
+})
\ No newline at end of file
diff --git a/.utils/scrape-and-inject-android-studio-agp-version-map.mjs b/.utils/scrape-and-inject-android-studio-agp-version-map.mjs
new file mode 100644
index 00000000..dbdf0344
--- /dev/null
+++ b/.utils/scrape-and-inject-android-studio-agp-version-map.mjs
@@ -0,0 +1,44 @@
+// scrape-android-studio-agp_version_maps.mjs
+
+import { fetchStudioAgpTable } from './fetch-and-parse-android-studio-agp-compatibility-table.mjs';
+import { readPropertiesSync } from './utils/properties.mjs';
+import { compareVersionStrings } from './utils/versioning.mjs';
+import { updateAnchoredMapInFile } from './utils/anchors.mjs';
+
+const props = readPropertiesSync();
+
+const version = {
+ MIN_IDE: props['MIN_SUPPORTED_ANDROID_STUDIO_IDE_VERSION'],
+ MIN_AGP: props['MIN_SUPPORTED_ANDROID_STUDIO_AGP_VERSION'],
+};
+
+(async function main() {
+ const agpTable = await fetchStudioAgpTable();
+ /** @type {{ [targetStudioVersion: string]: string }} */
+ const agpMap = {};
+
+ for (const { studioVersion, agpRange } of agpTable) {
+ const [ _, targetAgpVersion ] = agpRange.split('-');
+ const targetStudioVersion = studioVersion.match(/\d{2,}\.\d+\.\d/)?.[0];
+ if (!targetStudioVersion) continue;
+ if (targetStudioVersion in agpMap) {
+ if (compareVersionStrings(targetAgpVersion, agpMap[targetStudioVersion]) < 0) {
+ agpMap[targetStudioVersion] = targetAgpVersion;
+ }
+ } else {
+ agpMap[targetStudioVersion] = targetAgpVersion;
+ }
+ if (compareVersionStrings(targetStudioVersion, version.MIN_IDE) <= 0) break;
+ if (compareVersionStrings(targetAgpVersion, version.MIN_AGP) <= 0) break;
+ }
+
+ await updateAnchoredMapInFile('../settings.gradle.kts', {
+ anchorTag: 'ANDROID_STUDIO_AGP_VERSION_MAP',
+ mapName: 'agpVersionMap',
+ lines: Object.entries(agpMap).map(([ studioVer, agpVer ]) => `"${studioVer}" to "${agpVer}",`),
+ updatedLabel: 'AGP 版本映射',
+ });
+})().catch(err => {
+ console.error(err);
+ process.exitCode = 1;
+});
\ No newline at end of file
diff --git a/.utils/scrape-and-inject-android-studio-codename_maps.mjs b/.utils/scrape-and-inject-android-studio-codename_maps.mjs
new file mode 100644
index 00000000..0b09e901
--- /dev/null
+++ b/.utils/scrape-and-inject-android-studio-codename_maps.mjs
@@ -0,0 +1,480 @@
+// scrape-and-inject-android-studio-codename_maps.mjs
+
+/** @typedef {import('puppeteer').Page} Page */
+/** @typedef {import('puppeteer').Frame} Frame */
+/**
+ * @template {Node} T
+ * @typedef {import('puppeteer').ElementHandle} ElementHandle
+ */
+
+import puppeteer from 'puppeteer';
+import { getLatestStableWindows } from './fetch-and-parse-android-studio-latest-stable-version.mjs';
+import { batchUpdateAnchoredBlocks } from './utils/anchors.mjs';
+import { compareVersionStrings } from './utils/versioning.mjs';
+import { toUpdatedStamp, toYYYYMMDD } from './utils/date.mjs';
+import { sleep } from './utils/async.mjs';
+import { bytes2GiB } from './utils/format.mjs';
+import { getRemoteFileSizeBytes } from './utils/fetch.mjs';
+
+const URL = 'https://developer.android.com/studio/archive?hl=en';
+
+/**
+ * 在所有 frame (含主文档) 中查找 "同意" 按钮.
+ *
+ * @param {Page} page
+ * @param {number} [timeoutMs=30000]
+ * @returns {Promise<{handle: ElementHandle, frame: Frame}>}
+ */
+async function waitAndFindAgreeButton(page, timeoutMs = 30000) {
+ const deadline = Date.now() + timeoutMs;
+ const selector = 'button.button-primary';
+
+ while (Date.now() < deadline) {
+
+ // 1) 先尝试主文档
+
+ const mainBtn = await page.$$(selector);
+ for (const h of mainBtn) {
+ const txt = await page.evaluate(el => (el.textContent || '').trim().toLowerCase(), h);
+ if (txt.includes('agree')) return { handle: h, frame: page.mainFrame() };
+ }
+
+ // 2) 再查所有子 frame
+
+ const frames = page.frames();
+ for (const f of frames) {
+ /** @type {ElementHandle} */
+ const btn = await f.$(selector);
+ if (!btn) continue;
+ const txt = await f.evaluate(el => (el.textContent || '').trim().toLowerCase(), btn);
+ if (txt.includes('i agree') || txt.includes('agree to the terms') || txt === 'agree') {
+ return { handle: btn, frame: f };
+ }
+ }
+
+ // 3) 触发懒加载: 轻微滚动几次
+
+ await page.evaluate(() => window.scrollBy(0, 600));
+ await sleep(250);
+ }
+ throw new Error('未在任何文档中找到 "同意" 按钮 (超时)');
+}
+
+/**
+ * 在所有 frame 中等待某个选择器出现, 并返回该 frame.
+ *
+ * @param {Page} page
+ * @param {string} selector
+ * @param [timeoutMs=30000]
+ * @returns {Promise }
+ */
+async function waitForFrameWithSelector(page, selector, timeoutMs = 30000) {
+ const deadline = Date.now() + timeoutMs;
+ while (Date.now() < deadline) {
+ for (const f of page.frames()) {
+ const el = await f.$(selector);
+ if (el) return f;
+ }
+ await sleep(250);
+ }
+ throw new Error(` 未在任何 frame 中找到选择器: ${selector}`);
+}
+
+async function main() {
+ const browser = await puppeteer.launch({
+ headless: true,
+ args: [
+ '--no-sandbox',
+ '--disable-setuid-sandbox',
+ ],
+ });
+
+ const page = await browser.newPage();
+ await page.setUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36');
+ await page.goto(URL, { waitUntil: 'networkidle2', timeout: 60000 });
+
+ // 滚动到下载区域, 促发懒加载 (有助于注入承载 "同意" 按钮的 iframe)
+ await page.evaluate(() => {
+ const anchor = document.querySelector('#downloads')
+ || Array.from(document.querySelectorAll('h2, h3'))
+ .find(h => /download|archive/i.test(h.textContent || ''));
+ if (anchor) anchor.scrollIntoView({ behavior: 'instant', block: 'start' });
+ });
+ await sleep(500);
+
+ // 等待并点击 "同意" 按钮
+ try {
+ const { handle, frame } = await waitAndFindAgreeButton(page, 30000);
+ await frame.waitForSelector('button.button-primary', { visible: true, timeout: 15000 }).catch(() => {
+ });
+ await handle.click();
+ } catch (e) {
+ console.log('未检测到协议或已同意, 继续解析...');
+ }
+
+ // 同意后不要在主文档等待; 改为在包含内容的 frame 里等待 devsite-expandable
+ // 若首次未出现, 尝试轻微滚动以触发懒加载, 再次检查
+ /** @type {Frame} */
+ let contentFrame;
+ try {
+ contentFrame = await waitForFrameWithSelector(page, 'devsite-expandable', 20000);
+ } catch {
+ // 尝试滚动触发
+ for (let i = 0; i < 8; i++) {
+ await page.evaluate(() => window.scrollBy(0, 800));
+ await sleep(250);
+ }
+ // 再次寻找
+ contentFrame = await waitForFrameWithSelector(page, 'devsite-expandable', 20000);
+ }
+
+ /**
+ * @typedef {Object} ArchiveItem
+ * @property {string} title
+ * @property {string} date
+ * @property {string | null} version
+ * @property {{ text: string, href: string }[]} links
+ * @property {{ [filename: string]: string }} checksums
+ */
+ /**
+ * @type {ArchiveItem[]}
+ */
+ const archives = await contentFrame.$$eval('devsite-expandable', nodes => {
+
+ // 从内容 frame 中直接抽取 devsite-expandable 数据
+
+ /**
+ * @param {Node | null} el
+ * @returns {string}
+ */
+ const pickText = el => (el?.textContent || '').trim();
+
+ return nodes.map(n => {
+ /** @type {Node} */
+ const titleEl = n.querySelector('.expand-control');
+ const title = pickText(titleEl?.childNodes?.[0]); // 不含日期的主标题
+ const date = pickText(n.querySelector('.expand-control span')); // 例如 "April 1, 2025"
+ /** @type {Element[]} */
+ const linkEls = Array.from(n.querySelectorAll('.downloads a[href]'));
+ const links = linkEls.map(a => ({
+ text: pickText(a),
+ href: a.getAttribute('href') || '',
+ }));
+
+ // 收集 checksums (在 .downloads 文本中)
+ /** @type {HTMLElement} */
+ const downloadsElement = n.querySelector('.downloads');
+ const bodyText = (downloadsElement?.innerText || '').trim();
+ /** @type {{[filename: string]: string}} */
+ const checksums = {};
+ // 行格式:
+ bodyText.split('\n').forEach(line => {
+ const m = /^\s*([a-f0-9]{64})\s+(.+?)\s*$/.exec(line);
+ if (m) {
+ const [ _, sha256, filename ] = m;
+ checksums[filename] = sha256;
+ }
+ });
+
+ // 解析版本号 (2025.1.2 等), 优先从标题中提取
+ let version = null;
+ const vm = title.match(/\d{2,}\.\d+(?:\.\d+)?/);
+ if (vm) version = vm[0];
+
+ return { title, date, version, links, checksums };
+ });
+ });
+
+ // 1) 用 "最新稳定版" 的校验和/文件名, 在归档中定位条目, 补全并更新 common.json
+
+ const latestRows = await getLatestStableWindows(); // [{kind, filename, sha256, url, size, ...}]
+ const latestExe = latestRows.find(x => x.kind === 'exe');
+ const latestZip = latestRows.find(x => x.kind === 'zip');
+ if (!latestExe || !latestZip) {
+ throw new Error('最新稳定版条目缺少 Windows EXE 或 ZIP');
+ }
+
+ /**
+ * 在归档中查找: 优先用 sha256 命中, 其次用文件名.
+ *
+ * @param {ArchiveItem[]} rows
+ * @param {import('./fetch-and-parse-android-studio-latest-stable-version.mjs').Row} target
+ * @return {ArchiveItem | null}
+ */
+ const matchArchive = (rows, target) => {
+ for (const arc of rows) {
+ const bySha = target.sha256 && arc.checksums[target.filename] === target.sha256;
+ const byName = arc.links.some(l => l.text === target.filename);
+ if (bySha || byName) return arc;
+ }
+ return null;
+ };
+ const matchedArc = matchArchive(archives, latestExe) || matchArchive(archives, latestZip);
+ if (!matchedArc) {
+ throw new Error('未能在归档中定位到与最新版本对应的条目 (按 sha256/文件名均未命中)');
+ }
+
+ /**
+ * 从匹配到的 expandable 中抽取 Windows EXE/ZIP 的链接/文件名.
+ *
+ * @param {string} suffix
+ * @return {{ filename: string, url: string, sizeGiB?: string | null } | null}
+ */
+ const pickWinItem = suffix => {
+ // suffix: "-windows.exe" | "-windows.zip"
+ const link = matchedArc.links.find(l => l.text.endsWith(suffix));
+ if (!link) return null;
+ return {
+ filename: link.text,
+ url: link.href,
+ };
+ };
+ const exeItem = pickWinItem('-windows.exe');
+ const zipItem = pickWinItem('-windows.zip');
+
+ // 查询真实文件大小 (并发获取), 格式化为 GiB
+ const [ exeBytes, zipBytes ] = await Promise.all([
+ exeItem ? getRemoteFileSizeBytes(exeItem.url) : Promise.resolve(null),
+ zipItem ? getRemoteFileSizeBytes(zipItem.url) : Promise.resolve(null),
+ ]);
+ if (exeItem) exeItem.sizeGiB = bytes2GiB(exeBytes);
+ if (zipItem) zipItem.sizeGiB = bytes2GiB(zipBytes);
+
+ // 准备写回 common.json 所需字段
+ const latestVersionName = matchedArc.title.trim(); // 例: "Android Studio Narwhal Feature Drop | 2025.1.2"
+ const latestVersionDate = toYYYYMMDD(matchedArc.date) || ''; // 例: "2025/07/31"
+
+ if (!exeItem || !zipItem) {
+ throw new Error('匹配到的归档条目缺少 Windows EXE 或 ZIP 下载信息');
+ }
+
+ // 读取并更新 common.json (仅更新带有 "android_studio_latest_" 片段的键与版本名日期键)
+ const fs = await import('node:fs/promises');
+ const path = await import('node:path');
+
+ const commonJsonPath = path.resolve(process.cwd(), '../.readme/common.json');
+ const commonRaw = await fs.readFile(commonJsonPath, 'utf8');
+ const commonObj = JSON.parse(commonRaw);
+
+ const updatedCommon = {
+ ...commonObj,
+ android_studio_latest_recommended_version_name: latestVersionName,
+ var_date_android_studio_latest_recommended_version_name: latestVersionDate,
+ android_studio_latest_recommended_file_name_of_exe: exeItem.filename,
+ android_studio_latest_recommended_download_address_of_exe: exeItem.url,
+ android_studio_latest_recommended_file_size_of_exe: exeItem.sizeGiB ?? commonObj.android_studio_latest_recommended_file_size_of_exe,
+ android_studio_latest_recommended_file_name_of_zip: zipItem.filename,
+ android_studio_latest_recommended_download_address_of_zip: zipItem.url,
+ android_studio_latest_recommended_file_size_of_zip: zipItem.sizeGiB ?? commonObj.android_studio_latest_recommended_file_size_of_zip,
+ };
+
+ if (JSON.stringify(updatedCommon) !== JSON.stringify(commonObj)) {
+ await fs.writeFile(commonJsonPath, JSON.stringify(updatedCommon, null, 2), 'utf8');
+ console.log('[common.json] 已更新 (Android Studio 数据)');
+ console.log(`-- '${commonObj.android_studio_latest_recommended_version_name}'`);
+ console.log(`-> '${updatedCommon.android_studio_latest_recommended_version_name}'`);
+ } else {
+ // console.log('[common.json] 无需更新 (Android Studio 数据)');
+ }
+
+ // 2) 汇总代号 - 版本映射与代号首发日期, 更新 settings.gradle.kts 两个锚点块
+ // 2.1 从标题中解析 "代号与版本号"
+ // 标题模式示例: "Android Studio Meerkat Feature Drop | 2024.3.2 RC 1"
+ /**
+ * @param {string} t
+ * @return {string | null}
+ */
+ const codenameFromTitle = t => {
+ // 捕获 "Android Studio [Feature Drop] |"
+ const m = /Android Studio\s+(.+?)\s*(?:(\s+\d+\s+)?Feature Drop)?\s*\|/i.exec(t);
+ return m ? m[1].trim() : null;
+ };
+
+ // 用户手动覆盖映射 (可按需填写或从外部读取)
+ /** @type {Object} */
+ const manualCodenameOverrides = {
+ /* e.g. 'Meerkat': 'Mkt' */
+ };
+
+ // 生成唯一代码: 按顺序, 出现冲突则对冲突组统一递增长度; 覆盖项优先生效且不可被自动改动
+ /**
+ * @param {string[]} names 原始代号 (保留大小写与空格, 顺序与站点一致)
+ * @param {Object} overrides 手动覆盖映射
+ * @returns {Map} name -> code
+ */
+ function buildUniquePrefixes(names, overrides) {
+ // 代码不包含空格; 按名称去空格后逐字符递增长度
+ const entries = names.map(n => ({
+ name: n,
+ base: n.replace(/\s+/g, ''), // 去空格用于截取
+ len: Math.max(1, overrides[n] ? overrides[n].replace(/\s+/g, '').length : 1),
+ code: overrides[n] ? overrides[n].replace(/\s+/g, '') : null,
+ locked: !!overrides[n],
+ }));
+
+ // 先赋初值
+ for (const e of entries) {
+ if (!e.code) e.code = e.base.slice(0, e.len);
+ }
+
+ // 检测并解决冲突
+ const maxLenByName = new Map(entries.map(e => [ e.name, e.base.length ]));
+ // 循环上限保护, 防止极端情况下死循环
+ for (let step = 0; step < 1024; step++) {
+ // 统计冲突组: code -> indices
+ /** @type {Map} */
+ const bucket = new Map();
+ entries.forEach((e, idx) => {
+ const key = e.code;
+ if (!bucket.has(key)) bucket.set(key, []);
+ bucket.get(key).push(idx);
+ });
+
+ // 找到有冲突的组 (size >= 2)
+ const conflicts = Array.from(bucket.entries()).filter(([ , indices ]) => indices.length >= 2);
+ if (conflicts.length === 0) break; // 已无冲突
+
+ // 逐组处理
+ for (const [ code, indices ] of conflicts) {
+ // 若组内存在 >=2 个锁定项且 code 相同 -> 直接报错
+ const lockedIndices = indices.filter(i => entries[i].locked);
+ if (lockedIndices.length >= 2) {
+ const letter = code[0]?.toUpperCase() || '?';
+ const groupNames = indices.map(i => entries[i].name);
+ throw new Error(`[CodenameMap] 手动覆盖映射发生冲突: "${code}" -> ${groupNames.join(', ')}. 请调整覆盖映射. 冲突首字母组: ${letter}*`);
+ }
+
+ // 让组内所有 "未锁定项" 统一递增长度
+ for (const i of indices) {
+ const e = entries[i];
+ if (e.locked) continue; // 覆盖项不改
+ const maxLen = maxLenByName.get(e.name);
+ if (e.len >= maxLen) {
+ // 已经用到全长仍冲突 -> 无法自动消解
+ const letter = e.base[0]?.toUpperCase() || '?';
+ const groupNames = indices.map(ii => entries[ii].name);
+ throw new Error(`[CodenameMap] 无法自动消解冲突 ("${e.name}" 与同组名称完全相同或为彼此前缀到尽头). 请为该首字母组手动指定覆盖映射.\n- 组首字母: ${letter}\n- 组成员: ${groupNames.join(', ')}`);
+ }
+ e.len += 1;
+ e.code = e.base.slice(0, e.len);
+ }
+ }
+ }
+
+ return new Map(entries.map(e => [ e.name, e.code ]));
+ }
+
+ // 提取按页面顺序的代号列表 (去重, 保留第一次出现顺序)
+ const codenamesOrdered = [];
+ const seen = new Set();
+ for (const arc of archives) {
+ const cname = codenameFromTitle(arc.title);
+ if (!cname) continue;
+ if (!seen.has(cname)) {
+ seen.add(cname);
+ codenamesOrdered.push(cname);
+ }
+ }
+
+ // 构建 name->code 映射 (按规则自动消解冲突; 支持手动覆盖)
+ const nameToCode = buildUniquePrefixes(codenamesOrdered, manualCodenameOverrides);
+
+ // 收集每版本 (yyyy.m.patch) 对应的代号集合, 以及每个代号的首发日期
+ /** @type {Map>} */
+ const versionToLetters = new Map();
+ /** @type {Map} */
+ const letterBorn = new Map();
+
+ for (const arc of archives) {
+ if (!arc.version) continue; // 版本号 (yyyy.m.patch)
+ const cname = codenameFromTitle(arc.title);
+ if (!cname) continue;
+
+ const code = nameToCode.get(cname);
+ if (!code) continue;
+
+ // 映射 version -> codes
+ if (!versionToLetters.has(arc.version)) versionToLetters.set(arc.version, new Set());
+ versionToLetters.get(arc.version).add(code);
+
+ // 记录代号首次出现日期
+ const d = new Date(arc.date);
+ const existed = letterBorn.get(code);
+ if (!existed || d < existed.born) {
+ letterBorn.set(code, { name: cname, born: d });
+ }
+ }
+
+ // 生成 codenameVersionMap 文本 (按版本倒序排列, 值用 "A|B" 连接)
+ const sortedVersions = Array.from(versionToLetters.keys()).sort((a, b) => {
+ const [ ay, am, ap ] = a.split('.').map(Number);
+ const [ by, bm, bp ] = b.split('.').map(Number);
+ return by - ay || bm - am || bp - ap;
+ });
+
+ const versionLettersList = sortedVersions.map(v => [ v, Array.from(versionToLetters.get(v)).sort().join('|') ]);
+
+ /* e.g. { "2023.3": {1: "J", 2: "J|K"} }. */
+ /** @type {Object} */
+ const rawVersionLettersMap = {};
+ for (let i = 0; i < versionLettersList.length; i++) {
+ const [ v, letters ] = versionLettersList[i];
+ const matched = v.match(/(^\d+\.\d+)(?:\.(\d+))?/);
+ if (!matched) continue;
+ const [ , major, patch ] = matched;
+ if (major in rawVersionLettersMap) {
+ rawVersionLettersMap[major][patch] = letters;
+ } else {
+ rawVersionLettersMap[major] = { [patch]: letters };
+ }
+ }
+
+ /* e.g. { "2024.3": "M", "2024.1.2": "K" }. */
+ const combinedVersionLettersMap = {};
+
+ Object.entries(rawVersionLettersMap).forEach(([ major, patchToLetters ]) => {
+ const letterValues = Object.values(patchToLetters);
+ if (new Set(letterValues).size === 1) {
+ combinedVersionLettersMap[major] = letterValues[0];
+ } else {
+ Object.entries(patchToLetters).forEach(([ patch, letters ]) => {
+ combinedVersionLettersMap[`${major}.${patch}`] = letters;
+ });
+ }
+ });
+
+ const versionMapLines = Object.entries(combinedVersionLettersMap)
+ .sort((a, b) => compareVersionStrings(b[0], a[0]))
+ .map(([ v, letters ]) => `"${v}" to "${letters}",`);
+
+ // 生成 codenameMap 文本 (按 born 日期倒序; 注释: Born on Mon d, yyyy.)
+ // 这里 key 为自动生成的 code (可能为一到多字符), value 为完整代号
+ const sortedLetters = Array.from(letterBorn.entries())
+ .sort((a, b) => b[1].born.getTime() - a[1].born.getTime());
+
+ const codenameMapLines = sortedLetters.map(([ code, { name, born } ]) => {
+ const bornStr = toUpdatedStamp(born);
+ return `"${code}" to "${name}", /* Born on ${bornStr}. */`;
+ });
+
+ await batchUpdateAnchoredBlocks('../settings.gradle.kts', [ {
+ type: 'map',
+ anchorTag: 'ANDROID_STUDIO_CODENAME_VERSION_MAP',
+ mapName: 'codenameVersionMap',
+ lines: versionMapLines,
+ updatedLabel: 'Android Studio 代号版本映射',
+ }, {
+ type: 'map',
+ anchorTag: 'ANDROID_STUDIO_CODENAME_MAP',
+ mapName: 'codenameMap',
+ lines: codenameMapLines,
+ updatedLabel: 'Android Studio 代号名称映射',
+ } ]);
+
+ await browser.close();
+}
+
+main().catch(err => {
+ console.error(err);
+ process.exitCode = 1;
+});
\ No newline at end of file
diff --git a/.utils/scrape-and-inject-embedded-kotlin-list.mjs b/.utils/scrape-and-inject-embedded-kotlin-list.mjs
new file mode 100644
index 00000000..f6853fd4
--- /dev/null
+++ b/.utils/scrape-and-inject-embedded-kotlin-list.mjs
@@ -0,0 +1,98 @@
+// scrape-and-inject-embedded-kotlin-list.mjs
+
+/** @typedef {import('puppeteer').Page} Page */
+
+import puppeteer from 'puppeteer';
+import { getMinSupportedGradleVersion } from './utils/properties.mjs';
+import { updateAnchoredListInFile } from './utils/anchors.mjs';
+import { compareVersionStrings } from './utils/versioning.mjs';
+import { autoScroll } from './utils/puppeteer-helpers.mjs';
+import { sleep } from './utils/async.mjs';
+
+const URL = 'https://docs.gradle.org/current/userguide/compatibility.html#kotlin';
+
+const unofficialKotlinCompatibilityList = {
+ '8.14': '2.1.10',
+ '8.13': '2.1.10',
+};
+
+/**
+ * @param {Page} page
+ * @return {Promise}
+ */
+async function findTargetRows(page) {
+ return await page.evaluate(() => {
+ /** @type {HTMLTableElement[]} */
+ const targets = Array.from(document.querySelectorAll('table.tableblock'));
+ const target = targets.find(t => {
+ const tableHeadList = t.querySelectorAll('th');
+ return Array.from(tableHeadList).some(th => /Embedded Kotlin version|Minimum Gradle version|Kotlin Language version/i.test(th.textContent));
+ });
+ if (!target) return null;
+
+ return Array.from(target.querySelectorAll('tbody tr'))
+ .map(tr => {
+ const tds = tr.querySelectorAll('td');
+ if (tds.length < 3) return null;
+ const kotlin = tds[0]?.querySelector('p')?.textContent?.trim();
+ const gradle = tds[1]?.querySelector('p')?.textContent?.trim();
+ const ktLanguage = tds[2]?.querySelector('p')?.textContent?.trim();
+ return kotlin && gradle && ktLanguage ? [ kotlin, gradle, ktLanguage ] : null;
+ })
+ .filter(Boolean);
+ });
+}
+
+(async function main() {
+ const browser = await puppeteer.launch({ headless: true });
+ const page = await browser.newPage();
+ try {
+ await page.goto(URL, { waitUntil: 'networkidle0', timeout: 120000 });
+
+ // 页面为懒加载: 滚动并多次尝试, 直到目标表格出现或超时
+ let rows = null;
+ const deadline = Date.now() + 30000; // 30s 总超时
+ while (Date.now() < deadline) {
+ rows = await findTargetRows(page);
+ if (rows && rows.length) break;
+ await autoScroll(page);
+ await sleep(300);
+ }
+ if (!rows || !rows.length) {
+ throw new Error('Unable to locate target table rows (lazy-loaded content not found in time)');
+ }
+
+ /**
+ * @type {{ [gradle: string]: { kotlin: string, isUnofficial: boolean } }}
+ */
+ const map = {};
+ const minSupportedGradleVersion = getMinSupportedGradleVersion();
+
+ for (const [ kotlin, gradle ] of rows) {
+ if (compareVersionStrings(gradle, minSupportedGradleVersion) < 0) continue;
+ map[gradle] = { kotlin, isUnofficial: false };
+ }
+
+ Object.entries(unofficialKotlinCompatibilityList).forEach(([ gradle, kotlin ]) => {
+ if (!(gradle in map)) map[gradle] = { kotlin, isUnofficial: true };
+ });
+
+ await updateAnchoredListInFile('../settings.gradle.kts', {
+ anchorTag: 'EMBEDDED_KOTLIN_LIST',
+ listName: 'embeddedKotlin',
+ lines: Object.entries(map)
+ .sort((a, b) => compareVersionStrings(b[1]['kotlin'], a[1]['kotlin']))
+ .map(([ gradle, { kotlin, isUnofficial } ]) => {
+ return isUnofficial
+ ? `"${gradle}" to "${kotlin}", /* Unofficial. */`
+ : `"${gradle}" to "${kotlin}",`;
+ }),
+ updatedLabel: 'Java 与 Gradle 兼容性映射',
+ });
+ } finally {
+ await browser.close();
+ }
+})().catch(err => {
+ console.error(err);
+ process.exitCode = 1;
+});
\ No newline at end of file
diff --git a/.utils/scrape-and-inject-java-gradle-compatibility-list.mjs b/.utils/scrape-and-inject-java-gradle-compatibility-list.mjs
new file mode 100644
index 00000000..c4fb4463
--- /dev/null
+++ b/.utils/scrape-and-inject-java-gradle-compatibility-list.mjs
@@ -0,0 +1,62 @@
+// scrape-and-inject-java-gradle-compatibility-list.mjs
+
+import { getMinSupportedJavaVersionInt } from './utils/properties.mjs';
+import { updateAnchoredListInFile } from './utils/anchors.mjs';
+import { findTargetRows } from './utils/puppeteer-helpers.mjs';
+
+const URL = 'https://docs.gradle.org/current/userguide/compatibility.html#java_runtime';
+
+const unofficialGradleCompatibilityList = {
+ 25: '9.0',
+};
+
+(async function main() {
+ const rows = await findTargetRows({
+ url: URL,
+ tableSelector: 'table.tableblock',
+ tableFilter: {
+ 'caption': `:RegExp:i:${/java compatibility/.source}`,
+ },
+ tableRowSelector: 'tbody tr',
+ tableDataSelector: 'td',
+ tableDataStructure: [
+ { 'java': `:RegExp:${/^\d+$/.source}` },
+ { 'toolchain': `:RegExp:${/^N\/A$|\d+\.\d+/.source}` },
+ { 'gradle': `:RegExp:${/^N\/A$|\d+\.\d+/.source}` },
+ ],
+ });
+ /**
+ * @type {{ [javaInt: string]: string }}
+ */
+ const map = {};
+ const minSupportedJavaVersionInt = getMinSupportedJavaVersionInt();
+ for (const { java, gradle } of rows) {
+ const javaInt = parseInt(java);
+ if (Number.isNaN(javaInt)) {
+ throw Error(`Invalid java version int: ${java}`);
+ }
+ if (javaInt >= minSupportedJavaVersionInt) {
+ map[javaInt] = gradle;
+ }
+ }
+
+ await updateAnchoredListInFile('../settings.gradle.kts', {
+ anchorTag: 'JAVA_GRADLE_COMPATIBILITY_LIST',
+ listName: 'javaGradleCompatibility',
+ lines: Object.entries(map)
+ .sort((a, b) => Number(b[0]) - Number(a[0]))
+ .map(([ java, gradle ]) => {
+ if (gradle === 'N/A') {
+ const unofficialGradleVersion = unofficialGradleCompatibilityList[java];
+ if (unofficialGradleVersion) {
+ return `${java} to "${unofficialGradleVersion}", /* Unofficial. */`;
+ }
+ }
+ return `${java} to "${gradle}",`;
+ }),
+ updatedLabel: 'Java 与 Gradle 兼容性映射',
+ });
+})().catch(err => {
+ console.error(err);
+ process.exitCode = 1;
+});
\ No newline at end of file
diff --git a/.utils/scrape-and-inject-ksp-releases.mjs b/.utils/scrape-and-inject-ksp-releases.mjs
new file mode 100644
index 00000000..d1b4e206
--- /dev/null
+++ b/.utils/scrape-and-inject-ksp-releases.mjs
@@ -0,0 +1,224 @@
+// scrape-and-inject-ksp-releases.mjs
+
+/** @typedef {import('@octokit/types').Endpoints['GET /repos/{owner}/{repo}/releases']['response']['data']} ReleasesData */
+
+import * as https from 'https';
+import { updateAnchoredMapInFile } from './utils/anchors.mjs';
+import { toUpdatedStamp } from './utils/date.mjs';
+
+/**
+ * @param {string} url
+ * @param {Object} [options={}]
+ * @param {import("http").OutgoingHttpHeaders} [options.headers={}]
+ * @param {number} [options.timeout=15000]
+ * @return {Promise}
+ */
+function httpsGetJson(url, options = {}) {
+ return new Promise((resolve, reject) => {
+ const req = https.request(
+ url,
+ {
+ method: 'GET',
+ headers: {
+ 'User-Agent': 'node',
+ 'Accept': 'application/vnd.github+json',
+ ...(options.headers || {}),
+ },
+ timeout: options.timeout || 15000,
+ },
+ (res) => {
+ const { statusCode } = res;
+ const chunks = [];
+
+ res.on('data', (d) => chunks.push(d));
+ res.on('end', () => {
+ const body = Buffer.concat(chunks).toString('utf8');
+
+ if (statusCode < 200 || statusCode >= 300) {
+ return reject(
+ new Error(`HTTP ${statusCode}: ${body.slice(0, 200)}`),
+ );
+ }
+
+ try {
+ const json = /** @type {ReleasesData} */ JSON.parse(body);
+ resolve(json);
+ } catch (e) {
+ reject(new Error(`JSON parse error: ${e.message}`));
+ }
+ });
+ },
+ );
+
+ req.on('error', reject);
+ req.on('timeout', () => {
+ req.destroy(new Error('Request timed out'));
+ });
+ req.end();
+ });
+}
+
+/**
+ * @typedef {Object} KspRelease
+ * @property {string} version
+ * @property {string} name
+ * @property {string} publishedAt
+ */
+/**
+ * @return {Promise}
+ */
+async function fetchKspReleases() {
+ const base = 'https://api.github.com/repos/google/ksp/releases';
+ const perPage = 100;
+ let page = 1;
+ let reached = false;
+ const out = [];
+
+ /** @type {import("http").OutgoingHttpHeaders} */
+ const headers = {};
+ if (process.env.GITHUB_TOKEN) {
+ headers.authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
+ }
+
+ while (!reached) {
+ const url = `${base}?per_page=${perPage}&page=${page}`;
+ const releases = await httpsGetJson(url, { headers });
+ if (!Array.isArray(releases) || releases.length === 0) break;
+
+ for (const release of releases) {
+ const tag = String(release.tag_name || '').trim();
+ // 记录
+ out.push({
+ version: tag,
+ name: release.name,
+ publishedAt: release.published_at,
+ });
+
+ // 判断是否已到达目标最旧版本(含)
+ const parts = tag.split('-');
+ if (parts.length >= 2) {
+ const kspVer = parts.slice(0, -1).join('-');
+ if (kspVer === '1.8.0-RC2') {
+ reached = true;
+ break;
+ }
+ }
+ }
+
+ if (reached) break;
+ page += 1;
+ }
+
+ return out;
+}
+
+/**
+ * @param {KspRelease[]} releases
+ * @return {string[]}
+ */
+function parseReleases(releases) {
+ if (!Array.isArray(releases)) return [];
+
+ // 先根据 KSP 版本去重,保留发布时间最新的一条
+ /** @type {Map} */
+ const latestByKsp = new Map(); // kspVer -> { kotlinVer, date }
+ for (const r of releases) {
+ const rawVer = String(r.version || '').trim();
+ const parts = rawVer.split('-');
+ if (parts.length < 2) continue; // 跳过无效项
+
+ const kotlinVer = parts.pop();
+ const kspVer = parts.join('-');
+
+ const d = new Date(r.publishedAt);
+ if (Number.isNaN(d.getTime())) continue;
+
+ const prev = latestByKsp.get(kspVer);
+ if (!prev || d > prev.date) {
+ latestByKsp.set(kspVer, { kotlinVer, date: d });
+ }
+ }
+
+ /**
+ * 解析 KSP 版本用于排序.
+ *
+ * @param {string} ksp
+ * @return {{ baseNums: number[], rank: number, qName: string, qNum: number }}
+ */
+ function parseKspVer(ksp) {
+ const [ base, qualifierRaw = '' ] = ksp.split('-', 2);
+ const baseNums = base.split('.').map((n) => parseInt(String(n), 10) || 0);
+
+ let qName = '';
+ let qNum = 0;
+ if (qualifierRaw) {
+ const m = /^([A-Za-z]+)(\d+)?$/i.exec(qualifierRaw.trim());
+ if (m) {
+ qName = m[1].toUpperCase();
+ qNum = m[2] ? parseInt(m[2], 10) : 0;
+ } else {
+ qName = qualifierRaw.toUpperCase();
+ }
+ }
+
+ // 等级:稳定版 > RC > Beta > 其他
+ const rankMap = { '': 3, RC: 2, BETA: 1 };
+ const rank = Object.prototype.hasOwnProperty.call(rankMap, qName) ? rankMap[qName] : 0;
+
+ return { baseNums, rank, qName, qNum };
+ }
+
+ /**
+ * @param {number[]} aNums
+ * @param {number[]} bNums
+ * @return {number}
+ */
+ function cmpBaseDesc(aNums, bNums) {
+ const len = Math.max(aNums.length, bNums.length);
+ for (let i = 0; i < len; i++) {
+ const av = aNums[i] ?? 0;
+ const bv = bNums[i] ?? 0;
+ if (av !== bv) return bv - av; // 降序
+ }
+ return 0;
+ }
+
+ // 转为数组并按 KSP 版本降序排列
+ /**
+ * @type {Array<{ kspVer: string, kotlinVer: string, date: Date, parsed: { baseNums: number[], rank: number, qName: string, qNum: number } }>}
+ */
+ const items = Array.from(latestByKsp.entries())
+ .map(([ kspVer, v ]) => {
+ const parsed = parseKspVer(kspVer);
+ return { kspVer, kotlinVer: v.kotlinVer, date: v.date, parsed };
+ })
+ .sort((a, b) => {
+ // 1) 基础版本号降序
+ let c = cmpBaseDesc(a.parsed.baseNums, b.parsed.baseNums);
+ if (c !== 0) return c;
+ // 2) 级别降序(稳定版 > RC > Beta > 其他)
+ if (a.parsed.rank !== b.parsed.rank) return b.parsed.rank - a.parsed.rank;
+ // 3) 同级别数字降序(RC2 > RC1;Beta2 > Beta1;无数字视为 0)
+ if (a.parsed.qNum !== b.parsed.qNum) return b.parsed.qNum - a.parsed.qNum;
+ // 4) 兜底,限定词字典序降序(稳定排序用)
+ if (a.parsed.qName !== b.parsed.qName) return a.parsed.qName < b.parsed.qName ? 1 : -1;
+ // 5) 仍然相同则按日期降序(保险)
+ return b.date.getTime() - a.date.getTime();
+ });
+
+ return items.map(({ kspVer, kotlinVer, date }) => {
+ const dateStr = toUpdatedStamp(date);
+ return `"${kspVer}" to "${kotlinVer}", /* ${dateStr}. */`;
+ });
+}
+
+fetchKspReleases()
+ .then(async (releases) => {
+ await updateAnchoredMapInFile('../settings.gradle.kts', {
+ anchorTag: 'KSP_VERSION_MAP',
+ mapName: 'kspVersionMap',
+ lines: parseReleases(releases).map(l => `${l}`),
+ updatedLabel: 'KSP 发行版本映射',
+ });
+ })
+ .catch((error) => console.error('Failed to fetch KSP releases:', error));
\ No newline at end of file
diff --git a/.utils/scrape-and-inject-rhino-engine-data.mjs b/.utils/scrape-and-inject-rhino-engine-data.mjs
new file mode 100644
index 00000000..e1583bf2
--- /dev/null
+++ b/.utils/scrape-and-inject-rhino-engine-data.mjs
@@ -0,0 +1,80 @@
+// scrape-and-inject-rhino-engine-data.mjs
+
+import { getLatestCommitDate } from './utils/fetch.mjs';
+import * as fs from 'node:fs';
+import * as path from 'node:path';
+
+const URL = 'https://raw.githubusercontent.com/SuperMonster003/Rhino-For-AutoJs6/refs/heads/master/gradle.properties';
+
+/**
+ * @param {string} latestVersion
+ * @return {Promise}
+ */
+async function updateTemplateReadmeRhinoBadge(latestVersion) {
+ const templateReadmePath = path.resolve(process.cwd(), '../.readme/template_readme.md');
+ const fileContent = fs.readFileSync(templateReadmePath, 'utf8');
+ const rhinoBadgeRegex = /(href=.*?https:\/\/github\.com\/mozilla\/rhino.+?img\.shields\.io\/badge\/Rhino-)(.+)(-[a-f\d]{6}\b)/;
+ const matched = fileContent.match(rhinoBadgeRegex);
+ const oldVersion = matched[2].replaceAll('--', '-');
+ if (oldVersion !== latestVersion) {
+ const updatedFileContent = fileContent.replace(rhinoBadgeRegex, `$1${latestVersion.replaceAll('-', '--')}$3`);
+ fs.writeFileSync(templateReadmePath, updatedFileContent, 'utf8');
+ console.log('[template_readme.md] 已更新 (Rhino 徽标版本)');
+ console.log(`-- ${oldVersion}`);
+ console.log(`-> ${latestVersion}`);
+ } else {
+ // console.log('[template_readme.md] 无需更新 (Rhino 徽标版本)');
+ }
+}
+
+/**
+ * @param {string} latestVersion
+ * @param {number} linenoOfLatestVersion
+ * @return {Promise}
+ */
+async function updateCommonJsonWithRhinoData(latestVersion, linenoOfLatestVersion) {
+ const commonJsonPath = path.resolve(process.cwd(), '../.readme/common.json');
+ const commonRaw = fs.readFileSync(commonJsonPath, 'utf8');
+ const commonObj = JSON.parse(commonRaw);
+
+ const addressPrefix = 'http://rhino.autojs6.com/blob/master/gradle.properties';
+ const addressSuffix = linenoOfLatestVersion > 0 ? `#L${linenoOfLatestVersion}` : '';
+ const addressJsonValue = `[v${latestVersion}](${addressPrefix}${addressSuffix})`;
+ const latestCommitValue = await getLatestCommitDate('SuperMonster003', 'Rhino-For-AutoJs6');
+
+ const updatedCommon = {
+ ...commonObj,
+ latest_rhino_engine_name_with_github_lineno_address: addressJsonValue,
+ var_date_rhino_engine_latest_committed: latestCommitValue,
+ };
+
+ if (JSON.stringify(updatedCommon) !== JSON.stringify(commonObj)) {
+ fs.writeFileSync(commonJsonPath, JSON.stringify(updatedCommon, null, 2), 'utf8');
+ console.log('[common.json] 已更新 (Rhino 数据)');
+ [ 'latest_rhino_engine_name_with_github_lineno_address', 'var_date_rhino_engine_latest_committed' ].forEach(key => {
+ if (key in updatedCommon && key in commonObj && updatedCommon[key] !== commonObj[key]) {
+ console.log(`## ${key}`);
+ console.log(`-- ${commonObj[key]}`);
+ console.log(`-> ${updatedCommon[key]}`);
+ }
+ });
+ } else {
+ // console.log('[common.json] 无需更新 (Rhino 数据)');
+ }
+}
+
+async function main() {
+ const response = await fetch(URL);
+ const text = await response.text();
+ const lines = text.split('\n');
+ const latestVersion = lines.find(line => line.startsWith('version=')).split('=')[1];
+ const linenoOfLatestVersion = lines.findIndex(line => line.startsWith('version=')) + 1;
+
+ await updateTemplateReadmeRhinoBadge(latestVersion);
+ await updateCommonJsonWithRhinoData(latestVersion, linenoOfLatestVersion);
+}
+
+main().catch(err => {
+ console.error(err);
+ process.exitCode = 1;
+});
\ No newline at end of file
diff --git a/.utils/scrape-and-update-readme-template-contributors-table.mjs b/.utils/scrape-and-update-readme-template-contributors-table.mjs
new file mode 100644
index 00000000..65d6c75f
--- /dev/null
+++ b/.utils/scrape-and-update-readme-template-contributors-table.mjs
@@ -0,0 +1,46 @@
+// scrape-and-update-readme-template-contributors-table.mjs
+
+import { fetchStatistics } from './fetch-and-parse-autojs6-merged-pr-commits-statistics.mjs';
+import * as fs from 'node:fs';
+import { toYYYYMMDD } from './utils/date.mjs';
+import * as path from 'node:path';
+
+function updateCommonJsonFile() {
+ const commonJsonPath = path.resolve(process.cwd(), '../.readme/common.json');
+ const commonRaw = fs.readFileSync(commonJsonPath, 'utf8');
+ const commonObj = JSON.parse(commonRaw);
+
+ const updatedCommon = {
+ ...commonObj,
+ var_date_contribution_table_data_updated: toYYYYMMDD(),
+ };
+
+ if (JSON.stringify(updatedCommon) !== JSON.stringify(commonObj)) {
+ fs.writeFileSync(commonJsonPath, JSON.stringify(updatedCommon, null, 2), 'utf8');
+ console.log('[common.json] 已更新 (贡献参与数据统计日期)');
+ }
+}
+
+(async function main() {
+ const path = '../.readme/template_readme.md';
+
+ const stats = await fetchStatistics();
+ const newMarkdown = stats.map(stat => `| ${stat.contributorMarkdown} | ${stat.commitsCountMarkdown} | ${stat.latestCommitMarkdown} |`).join('\n');
+
+ const text = fs.readFileSync(path, { encoding: 'utf-8' });
+ const newText = text.replace(/((?:table_header_contribution_contributors|table_header_contribution_number_of_commits|table_header_contribution_recent_submissions).+\r?\n)([\s|:\-]+\r?\n)(\|\s* {
+ console.error(err);
+ process.exitCode = 1;
+});
\ No newline at end of file
diff --git a/.utils/tsconfig.json b/.utils/tsconfig.json
new file mode 100644
index 00000000..596d5a2e
--- /dev/null
+++ b/.utils/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "target": "ES2022",
+ "lib": ["ES2022", "DOM"],
+ "types": ["node"],
+ },
+ "include": ["**/*.js", "**/*.mjs", "**/*.ts"]
+}
diff --git a/.utils/utils/anchors.mjs b/.utils/utils/anchors.mjs
new file mode 100644
index 00000000..1273e275
--- /dev/null
+++ b/.utils/utils/anchors.mjs
@@ -0,0 +1,263 @@
+// utils/anchors.mjs
+
+import * as fsp from 'node:fs/promises';
+import * as path from 'node:path';
+import { toUpdatedStamp } from './date.mjs';
+
+/**
+ * @param {string} s
+ * @returns {string}
+ */
+const normalize = s => String(s).replace(/\s+/g, '');
+
+/**
+ * 在指定 Anchor 块中, 用给定的替换函数生成新块内容.
+ *
+ * @param {string} src
+ * @param {string} anchorTag
+ * @param {(block: string) => { newBlock: string, changed: boolean }} replaceBlockFn
+ * @returns {{ src: string, changed: boolean }} - 返回 { src: 新源码, changed: 是否发生变更 }. 若找不到锚点, 原样返回.
+ */
+export function replaceInAnchoredBlock(src, anchorTag, replaceBlockFn) {
+ const beginTag = `// @AnchorBegin ${anchorTag}`;
+ const endTag = `// @AnchorEnd ${anchorTag}`;
+
+ const beginIdx = src.indexOf(beginTag);
+ if (beginIdx === -1) return { src, changed: false };
+
+ const endIdx = src.indexOf(endTag, beginIdx + beginTag.length);
+ if (endIdx === -1) return { src, changed: false };
+
+ const before = src.slice(0, beginIdx);
+ const block = src.slice(beginIdx, endIdx); // 不包含 endTag
+ const after = src.slice(endIdx);
+
+ const { newBlock, changed } = replaceBlockFn(block) || {};
+ if (!changed || !newBlock) return { src, changed: false };
+
+ return { src: before + newBlock + after, changed };
+}
+
+/**
+ * 替换锚点块中的某个 map 声明 (如 mapOf(...)), 并在变更时自动刷新 @Updated 日期.
+ *
+ * @param {string} src
+ * @param {Object} options
+ * @param {string} options.anchorTag - 块的锚点名
+ * @param {string} options.mapName - 变量名, 如 agpVersionMap
+ * @param {string[]} options.lines - map 体内的每行 (不含缩进, 由函数自动缩进)
+ * @param {number} [options.linesIndent=4]
+ * @param {(date?: Date) => string} [options.toUpdatedStamp=toUpdatedStamp] - 自定义时间戳函数 (可选)
+ * @returns {{ src: string, changed: boolean }}}
+ */
+export function replaceAnchoredMapBlock(src, {
+ anchorTag,
+ mapName,
+ lines,
+ linesIndent = 4,
+ toUpdatedStamp: toStamp = toUpdatedStamp,
+}) {
+ return replaceInAnchoredBlock(src, anchorTag, (block) => {
+ let changed = false;
+
+ const re = new RegExp(`([\\t\\x20]*)(va[lr]\\s+)?${mapName}\\s*=\\s*mapOf\\([\\s\\S]*?\\)(,?)`, 'm');
+ let updatedBlock = block.replace(re, (/** @type {string} */ original, /** @type {string} */ indent, /** @type {string} */ keyword, /** @type {string} */ comma) => {
+ const kw = keyword ?? '';
+ const body = lines.map(l => `${' '.repeat(linesIndent)}${indent}${l}`).join('\n');
+ const next = `${indent}${kw}${mapName} = mapOf(\n${body}\n${indent})${comma}`;
+ if (normalize(original) !== normalize(next)) changed = true;
+ return next;
+ });
+ if (changed) {
+ updatedBlock = updatedBlock.replace(
+ /(@Updated[^\n]*?\son\s)([A-Z][a-z]{2}\s\d{1,2},\s\d{4})(\.?)/,
+ (_, p1, _old, p3) => `${p1}${(toStamp())}${p3}`,
+ );
+ }
+
+ return { newBlock: updatedBlock, changed };
+ });
+}
+
+/**
+ * 替换锚点块中的某个 list 声明 (如 listOf(...)), 并在变更时自动刷新 @Updated 日期.
+ *
+ * @param {string} src
+ * @param {Object} options
+ * @param {string} options.anchorTag - 块的锚点名
+ * @param {string} options.listName - 变量名, 如 modules 或 libs
+ * @param {string[]} options.lines - list 体内的每行 (不含缩进, 由函数自动缩进)
+ * @param {number} [options.linesIndent=4]
+ * @param {(date?: Date) => string} [options.toUpdatedStamp=toUpdatedStamp] - 自定义时间戳函数 (可选)
+ * @returns {{ src: string, changed: boolean }}}
+ */
+export function replaceAnchoredListBlock(src, {
+ anchorTag,
+ listName,
+ lines,
+ linesIndent = 4,
+ toUpdatedStamp: toStamp = toUpdatedStamp,
+}) {
+ return replaceInAnchoredBlock(src, anchorTag, (block) => {
+ let changed = false;
+
+ const re = new RegExp(`([\\t\\x20]*)(va[lr]\\s+)?${listName}\\s*=\\s*listOf\\([\\s\\S]*?\\)(,?)`, 'm');
+ let updatedBlock = block.replace(re, (original, indent, keyword, comma) => {
+ const kw = keyword ?? '';
+ const body = lines.map(l => `${' '.repeat(linesIndent)}${indent}${l}`).join('\n');
+ const next = `${indent}${kw}${listName} = listOf(\n${body}\n${indent})${comma}`;
+ if (normalize(original) !== normalize(next)) changed = true;
+ return next;
+ });
+ if (changed) {
+ updatedBlock = updatedBlock.replace(
+ /(@Updated[^\n]*?\son\s)([A-Z][a-z]{2}\s\d{1,2},\s\d{4})(\.?)/,
+ (_, p1, _old, p3) => `${p1}${(toStamp())}${p3}`,
+ );
+ }
+
+ return { newBlock: updatedBlock, changed };
+ });
+}
+
+/**
+ * 高层封装: 读取文件 -> 替换锚点 map -> 若有变更则写回 -> 打印日志.
+ *
+ * @param {string} filePath
+ * @param {Object} options
+ * @param {string} options.anchorTag - 块的锚点名
+ * @param {string} options.mapName - 变量名, 如 agpVersionMap
+ * @param {string[]} options.lines - map 体内的每行 (不含缩进, 由函数自动缩进)
+ * @param {number} [options.linesIndent=4]
+ * @param {string} [options.updatedLabel='']
+ * @param {(date?: Date) => string} [options.toUpdatedStamp=toUpdatedStamp] - 自定义时间戳函数 (可选)
+ * @param {Console} [options.logger=console]
+ * @returns {Promise<{ changed: boolean, content: string }>}
+ */
+export async function updateAnchoredMapInFile(filePath, {
+ anchorTag,
+ mapName,
+ lines,
+ linesIndent = 4,
+ updatedLabel = '',
+ toUpdatedStamp: toStamp = toUpdatedStamp,
+ logger = console,
+}) {
+ const filename = path.basename(filePath);
+ const raw = await fsp.readFile(filePath, 'utf8');
+ const { src: updated, changed } = replaceAnchoredMapBlock(raw, { anchorTag, mapName, lines, linesIndent, toUpdatedStamp: toStamp });
+
+ if (changed) {
+ await fsp.writeFile(filePath, updated, 'utf8');
+ logger.log(`[${filename}] 已更新` + (updatedLabel ? ` (${updatedLabel})` : ''));
+ } else {
+ // logger.log(`[${filename}] 无需更新` + (updatedLabel ? ` (${updatedLabel})` : ''));
+ }
+ return { changed, content: updated };
+}
+
+/**
+ * 高层封装: 读取文件 -> 替换锚点 list -> 若有变更则写回 -> 打印日志.
+ *
+ * @param {string} filePath
+ * @param {Object} options
+ * @param {string} options.anchorTag - 块的锚点名
+ * @param {string} options.listName - 变量名, 如 modules 或 libs
+ * @param {string[]} options.lines - list 体内的每行 (不含缩进, 由函数自动缩进)
+ * @param {number} [options.linesIndent=4]
+ * @param {string} [options.updatedLabel='']
+ * @param {(date?: Date) => string} [options.toUpdatedStamp=toUpdatedStamp] - 自定义时间戳函数 (可选)
+ * @param {Console} [options.logger=console]
+ * @returns {Promise<{ changed: boolean, content: string }>}
+ */
+export async function updateAnchoredListInFile(filePath, {
+ anchorTag,
+ listName,
+ lines,
+ linesIndent = 4,
+ updatedLabel = '',
+ toUpdatedStamp: toStamp = toUpdatedStamp,
+ logger = console,
+}) {
+ const filename = path.basename(filePath);
+ const raw = await fsp.readFile(filePath, 'utf8');
+ const { src: updated, changed } = replaceAnchoredListBlock(raw, { anchorTag, listName, lines, linesIndent, toUpdatedStamp: toStamp });
+
+ if (changed) {
+ await fsp.writeFile(filePath, updated, 'utf8');
+ logger.log(`[${filename}] 已更新` + (updatedLabel ? ` (${updatedLabel})` : ''));
+ } else {
+ // logger.log(`[${filename}] 无需更新` + (updatedLabel ? ` (${updatedLabel})` : ''));
+ }
+ return { changed, content: updated };
+}
+
+/**
+ * @typedef {Object} AnchoredBlockUpdateOption
+ * @property {'map' | 'list' | 'custom'} type
+ * @property {string} anchorTag
+ * @property {string} [mapName]
+ * @property {string} [listName]
+ * @property {string[]} lines
+ * @property {number} [linesIndent=4]
+ * @property {string} [updatedLabel]
+ * @property {(srcInBlock: string, options: { toUpdatedStamp?: (date?: Date) => string }) => { newBlock: string, changed: boolean }} [replacer]
+ */
+/**
+ * 批量在同一文件内进行多锚点替换 (map 与 list 都支持, 读一次/写一次).
+ *
+ * @param {string} filePath
+ * @param {AnchoredBlockUpdateOption[]} optionList
+ * @param {Object} [extraOptions={}]
+ * @param {(date?: Date) => string} [extraOptions.toUpdatedStamp=toUpdatedStamp] - 自定义时间戳函数 (可选)
+ * @param {Console} [extraOptions.logger=console]
+ * @returns {Promise<{ changed: boolean, content: string }>}
+ */
+export async function batchUpdateAnchoredBlocks(filePath, optionList, {
+ toUpdatedStamp: toStamp = toUpdatedStamp,
+ logger = console,
+} = {}) {
+ const filename = path.basename(filePath);
+ let raw = await fsp.readFile(filePath, 'utf8');
+ let changedAny = false;
+
+ for (const op of optionList) {
+ let res = { src: raw, changed: false };
+
+ if (op.type === 'map') {
+ res = replaceAnchoredMapBlock(raw, {
+ anchorTag: op.anchorTag,
+ mapName: op.mapName,
+ lines: op.lines,
+ linesIndent: op.linesIndent,
+ toUpdatedStamp: toStamp,
+ });
+ } else if (op.type === 'list') {
+ res = replaceAnchoredListBlock(raw, {
+ anchorTag: op.anchorTag,
+ listName: op.listName,
+ lines: op.lines,
+ linesIndent: op.linesIndent,
+ toUpdatedStamp: toStamp,
+ });
+ } else if (op.type === 'custom' && typeof op.replacer === 'function') {
+ res = replaceInAnchoredBlock(raw, op.anchorTag, (block) => op.replacer(block, { toUpdatedStamp: toStamp }));
+ } else {
+ logger.warn(`[${filename}] 未知操作类型或缺少参数:`, op);
+ continue;
+ }
+
+ if (res.changed) {
+ changedAny = true;
+ raw = res.src;
+ logger.log(`[${filename}] 已更新 (${op['updatedLabel'] ?? op.anchorTag})`);
+ } else {
+ // logger.log(`[${filename}] 无需更新 (${op['updatedLabel'] ?? op.anchorTag})`);
+ }
+ }
+
+ if (changedAny) {
+ await fsp.writeFile(filePath, raw, 'utf8');
+ }
+ return { changed: changedAny, content: raw };
+}
diff --git a/.utils/utils/async.mjs b/.utils/utils/async.mjs
new file mode 100644
index 00000000..37f8d8bc
--- /dev/null
+++ b/.utils/utils/async.mjs
@@ -0,0 +1,9 @@
+// utils/async.mjs
+
+/**
+ * @param {number} ms
+ * @returns {Promise}
+ */
+export async function sleep(ms) {
+ return new Promise(r => setTimeout(r, ms));
+}
diff --git a/.utils/utils/date.mjs b/.utils/utils/date.mjs
new file mode 100644
index 00000000..ffd0b192
--- /dev/null
+++ b/.utils/utils/date.mjs
@@ -0,0 +1,23 @@
+// utils/date.mjs
+
+/**
+ * @param {Date} [date=new Date()]
+ * @returns {string}
+ */
+export function toUpdatedStamp(date = new Date()) {
+ /* e.g. "Aug 23, 2025". */
+ return date.toLocaleString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
+}
+
+/**
+ * @param {string} [dateText='']
+ * @returns {string | null}
+ */
+export function toYYYYMMDD(dateText = '') {
+ const d = dateText ? new Date(dateText) : new Date();
+ if (Number.isNaN(d.getTime())) return null;
+ const y = d.getFullYear();
+ const m = String(d.getMonth() + 1).padStart(2, '0');
+ const day = String(d.getDate()).padStart(2, '0');
+ return `${y}/${m}/${day}`;
+}
\ No newline at end of file
diff --git a/.utils/utils/fetch.mjs b/.utils/utils/fetch.mjs
new file mode 100644
index 00000000..da2e6850
--- /dev/null
+++ b/.utils/utils/fetch.mjs
@@ -0,0 +1,100 @@
+// utils/fetch.mjs
+
+/** @typedef {import('@octokit/types').Endpoints['GET /repos/{owner}/{repo}/commits']['response']['data']} CommitsData */
+
+import fetch from 'node-fetch';
+import * as dotenv from 'dotenv';
+import { toYYYYMMDD } from './date.mjs';
+
+dotenv.config({ path: '../.env', quiet: true });
+
+/**
+ * 获取远程文件真实大小.
+ *
+ * @param {string} url
+ * @param {{timeout?: number}} [options]
+ * @returns {Promise}
+ */
+export async function getRemoteFileSizeBytes(url, { timeout = 30000 } = {}) {
+ const headers = {
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124 Safari/537.36',
+ 'accept': '*/*',
+ };
+
+ // 1) 尝试 HEAD
+
+ try {
+ const res = await fetch(url, {
+ method: 'HEAD',
+ redirect: 'follow',
+ headers,
+ });
+ if (res.ok) {
+ const len = res.headers.get('content-length');
+ if (len && /^\d+$/.test(len)) return Number(len);
+ }
+ } catch (_) {
+ /* Ignored. */
+ }
+
+ // 2) 尝试 Range GET (bytes=0-0), 从 Content-Range 解析总长度
+
+ try {
+ const ac = new AbortController();
+ const t = setTimeout(() => ac.abort(), timeout);
+ const res = await fetch(url, {
+ method: 'GET',
+ redirect: 'follow',
+ headers: { ...headers, range: 'bytes=0-0' },
+ signal: ac.signal,
+ }).finally(() => clearTimeout(t));
+
+ if (res.ok || res.status === 206) {
+ // Content-Range: bytes 0-0/123456789
+ const cr = res.headers.get('content-range');
+ if (cr) {
+ const m = /bytes\s+\d+-\d+\/(\d+)/i.exec(cr);
+ if (m) return Number(m[1]);
+ }
+ // 退化: 仍然尝试 content-length
+ const len = res.headers.get('content-length');
+ if (len && /^\d+$/.test(len)) return Number(len);
+ }
+ } catch (_) {
+ /* Ignored. */
+ }
+
+ return null;
+}
+
+/**
+ * @param {string} owner
+ * @param {string} repo
+ * @return {Promise}
+ */
+export async function getLatestCommitDate(owner, repo) {
+ const token = process.env.GITHUB_TOKEN; // 可选:避免频繁请求受限
+ const url = `https://api.github.com/repos/${owner}/${repo}/commits?per_page=1`;
+
+ /** @type {import('node-fetch').HeadersInit} */
+ const headers = {
+ accept: 'application/vnd.github+json',
+ 'user-agent': 'repo-last-commit-script',
+ ...(token ? { authorization: `Bearer ${token}` } : {}),
+ };
+ const res = await fetch(url, { headers });
+
+ if (!res.ok) {
+ throw new Error(`GitHub API 请求失败: ${res.status} ${res.statusText}`);
+ }
+
+ const data = /** @type {CommitsData} */ await res.json();
+ const latest = Array.isArray(data) ? data[0] : null;
+ if (!latest?.commit) throw new Error('未获取到最新提交');
+
+ // 优先使用 committer 的提交时间,fallback 到 author
+ const iso = latest.commit.committer?.date ?? latest.commit.author?.date;
+ if (!iso) throw new Error('提交对象缺少日期字段');
+
+ return toYYYYMMDD(iso);
+}
diff --git a/.utils/utils/format.mjs b/.utils/utils/format.mjs
new file mode 100644
index 00000000..99adac25
--- /dev/null
+++ b/.utils/utils/format.mjs
@@ -0,0 +1,11 @@
+// utils/format.mjs
+
+/**
+ * @param {number | null} bytes
+ * @param {number} [fractionDigits=2]
+ */
+export function bytes2GiB(bytes, fractionDigits = 2) {
+ if (bytes == null) return null;
+ const gib = bytes / 1024 ** 3;
+ return `${gib.toFixed(fractionDigits)} GiB`;
+}
\ No newline at end of file
diff --git a/.utils/utils/properties.mjs b/.utils/utils/properties.mjs
new file mode 100644
index 00000000..92bad626
--- /dev/null
+++ b/.utils/utils/properties.mjs
@@ -0,0 +1,234 @@
+// utils/properties.mjs
+
+import * as fs from 'node:fs';
+import * as fsp from 'node:fs/promises';
+import { compareVersionStrings } from './versioning.mjs';
+
+/**
+ * @param {string} str
+ * @returns {string}
+ */
+function unescapeProperty(str) {
+ let i = 0, out = '';
+ while (i < str.length) {
+ const ch = str[i++];
+ if (ch !== '\\') {
+ out += ch;
+ continue;
+ }
+ const next = str[i++];
+ switch (next) {
+ case 't':
+ out += '\t';
+ break;
+ case 'n':
+ out += '\n';
+ break;
+ case 'r':
+ out += '\r';
+ break;
+ case 'f':
+ out += '\f';
+ break;
+ case 'u': {
+ const hex = str.slice(i, i + 4);
+ if (/^[0-9a-fA-F] {4}$/.test(hex)) {
+ out += String.fromCharCode(parseInt(hex, 16));
+ i += 4;
+ } else {
+ // 非法 \u 序列, 按字面量保留
+ out += '\\u';
+ }
+ break;
+ }
+ case ':':
+ case '=':
+ case ' ':
+ case '\\':
+ out += next;
+ break;
+ default:
+ // 未知转义, 保留第二个字符
+ out += next;
+ }
+ }
+ return out;
+}
+
+/**
+ * @param {string} text
+ * @returns {Object}
+ */
+export function parseProperties(text) {
+ const props = Object.create(null);
+ if (!text) return props;
+
+ const lines = [];
+ const rawLines = text.split(/\r?\n/);
+
+ // 合并续行 (以反斜杠结尾且反斜杠未被转义)
+ for (let i = 0; i < rawLines.length; i++) {
+ let line = rawLines[i];
+ if (line == null) continue;
+
+ // 去除行尾 CR (兼容 \r\n 已 split 的情况, 一般无需此步)
+ line = line.replace(/\r$/, '');
+
+ // 合并续行
+ while (true) {
+ // 统计结尾连续反斜杠数量, 奇数表示续行
+ let backslashes = 0;
+ for (let j = line.length - 1; j >= 0 && line[j] === '\\'; j--) backslashes++;
+ const isContinuation = backslashes % 2 === 1;
+
+ if (!isContinuation) break;
+ const next = rawLines[++i];
+ if (next == null) break;
+ // 去掉一个续行用的反斜杠, 再拼接后续行, 续行处按规范会吞掉换行
+ line = line.slice(0, -1) + next;
+ }
+ lines.push(line);
+ }
+
+ for (const raw of lines) {
+ const line = raw.trim();
+ if (!line || line.startsWith('#') || line.startsWith('!')) continue;
+
+ // 键值分隔: 第一个 =/: 或未转义空白
+ let key = '';
+ let value = '';
+ let sepIdx = -1;
+
+ // 逐字符扫描, 识别未转义的分隔符
+ let escaped = false;
+ for (let i = 0; i < line.length; i++) {
+ const ch = line[i];
+ if (!escaped && (ch === '=' || ch === ':')) {
+ sepIdx = i;
+ break;
+ }
+ if (!escaped && /\s/.test(ch)) {
+ sepIdx = i;
+ break;
+ }
+ escaped = ch === '\\' && !escaped;
+ if (!escaped && ch !== '\\') escaped = false;
+ }
+
+ if (sepIdx === -1) {
+ key = line;
+ value = '';
+ } else {
+ key = line.slice(0, sepIdx);
+ value = line.slice(sepIdx + 1);
+ // 如果分隔符是空白, value 应该从第一个非空白处开始
+ if (/^\s$/.test(line[sepIdx])) {
+ value = value.replace(/^\s+/, '');
+ }
+ }
+
+ key = key.replace(/\s+$/, ''); // 规范里 key 前部空白可作为分隔符, 末尾空白需要去掉
+ const k = unescapeProperty(key);
+ const v = unescapeProperty(value.trim());
+
+ if (k) props[k] = v;
+ }
+ return props;
+}
+
+/**
+ * @param {string} [filePath='../version.properties']
+ * @param {Object} options
+ * @param {BufferEncoding} [options.encoding='utf8']
+ * @returns {Promise>}
+ */
+export async function readProperties(filePath = '../version.properties', { encoding = 'utf8' } = {}) {
+ const text = await fsp.readFile(filePath, { encoding });
+ return parseProperties(text);
+}
+
+/**
+ * @param {string} [filePath='../version.properties']
+ * @param {Object} options
+ * @param {BufferEncoding} [options.encoding='utf8']
+ * @returns {Object}
+ */
+export function readPropertiesSync(filePath = '../version.properties', { encoding = 'utf8' } = {}) {
+ const text = fs.readFileSync(filePath, { encoding });
+ return parseProperties(text);
+}
+
+/**
+ * @param {string} [filePath='../version.properties']
+ * @param {Object} options
+ * @param {BufferEncoding} [options.encoding='utf8']
+ * @returns {string}
+ */
+export function getMinSupportedAgpVersion(filePath = '../version.properties', { encoding = 'utf8' } = {}) {
+ let minSupportedVersion = null;
+ Object.entries(readPropertiesSync(filePath, { encoding })).forEach(([ key, value ]) => {
+ if (!/agp.version.*min.supported|min.supported.*agp.version/i.test(key)) return;
+ if (minSupportedVersion === null || compareVersionStrings(value, minSupportedVersion) < 0) {
+ minSupportedVersion = value;
+ }
+ });
+ return minSupportedVersion ?? '8.0';
+}
+
+/**
+ * @param {string} [filePath='../version.properties']
+ * @param {Object} options
+ * @param {BufferEncoding} [options.encoding='utf8']
+ * @returns {string}
+ */
+export function getMinSupportedGradleVersion(filePath = '../version.properties', { encoding = 'utf8' } = {}) {
+ let minSupportedVersion = null;
+ Object.entries(readPropertiesSync(filePath, { encoding })).forEach(([ key, value ]) => {
+ if (!/gradle.version.*min.supported|min.supported.*gradle.version/i.test(key)) return;
+ if (minSupportedVersion === null || compareVersionStrings(value, minSupportedVersion) < 0) {
+ minSupportedVersion = value;
+ }
+ });
+ return minSupportedVersion ?? '8.0';
+}
+
+/**
+ * @param {string} [filePath='../version.properties']
+ * @param {Object} options
+ * @param {BufferEncoding} [options.encoding='utf8']
+ * @returns {number}
+ */
+export function getMinSupportedJavaVersionInt(filePath = '../version.properties', { encoding = 'utf8' } = {}) {
+ return getJavaVersionInfo(filePath, { encoding }).minSupportedJavaVersionInt;
+}
+
+/**
+ * @param {string} [filePath='../version.properties']
+ * @param {Object} options
+ * @param {BufferEncoding} [options.encoding='utf8']
+ * @returns {{ currentJavaVersionInt: number, minSupportedJavaVersionInt: number, minSuggestedJavaVersionInt: number, maxSupportedJavaVersionInt: number }}
+ */
+export function getJavaVersionInfo(filePath = '../version.properties', { encoding = 'utf8' } = {}) {
+ let currentVersion = 0;
+ let minSuggestedVersion = 19;
+ let minSupportedVersion = 17;
+ let maxSupportedVersion = 0;
+ Object.entries(readPropertiesSync(filePath, { encoding })).forEach(([ key, value ]) => {
+ const versionNumber = parseInt(value, 10);
+ if (/^java.version$/i.test(key)) {
+ currentVersion = Math.max(currentVersion, versionNumber);
+ } else if (/java.version.*min.suggested|min.suggested.*java.version/i.test(key)) {
+ minSuggestedVersion = Math.min(minSuggestedVersion, versionNumber);
+ } else if (/java.version.*min.supported|min.supported.*java.version/i.test(key)) {
+ minSupportedVersion = Math.min(minSupportedVersion, versionNumber);
+ } else if (/java.version.*max.supported|max.supported.*java.version/i.test(key)) {
+ maxSupportedVersion = Math.max(maxSupportedVersion, versionNumber);
+ }
+ });
+ return {
+ currentJavaVersionInt: currentVersion,
+ minSuggestedJavaVersionInt: minSuggestedVersion,
+ minSupportedJavaVersionInt: minSupportedVersion,
+ maxSupportedJavaVersionInt: maxSupportedVersion,
+ };
+}
\ No newline at end of file
diff --git a/.utils/utils/puppeteer-helpers.mjs b/.utils/utils/puppeteer-helpers.mjs
new file mode 100644
index 00000000..b1213368
--- /dev/null
+++ b/.utils/utils/puppeteer-helpers.mjs
@@ -0,0 +1,160 @@
+// utils/puppeteer-helpers.mjs
+
+/** @typedef {import('puppeteer').Page} Page */
+
+import puppeteer from 'puppeteer';
+import { sleep } from './async.mjs';
+
+/**
+ * @param {Page} page
+ * @returns {Promise}
+ */
+export async function autoScroll(page) {
+ await page.evaluate(async () => {
+ await new Promise(resolve => {
+ let total = 0;
+ const step = 400;
+ const timer = setInterval(() => {
+ window.scrollBy(0, step);
+ total += step;
+ if (total >= document.body.scrollHeight) {
+ clearInterval(timer);
+ resolve();
+ }
+ }, 100);
+ });
+ });
+}
+
+/**
+ * @typedef {object} FindTargetRowsOptions
+ * @property {string} [tableSelector='table']
+ * @property {{ [selector: string]: string | string[] }}[tableFilter={}]
+ * @property {string} [tableRowSelector='tbody tr']
+ * @property {string} [tableDataSelector='td']
+ * @property {Array<{ [dataItemName: string]: string } | string>} [tableDataStructure=[]]
+ */
+/**
+ * @param {Page} page
+ * @param {FindTargetRowsOptions} [options={}]
+ * @returns {Promise>}
+ */
+async function findTargetRowsWithPage(page, options = {}) {
+ return await page.evaluate((options) => {
+ const targets = Array.from(document.querySelectorAll(options.tableSelector ?? 'table'));
+ const target = targets.find(t => {
+ for (const [ selector, filter ] of Object.entries(options.tableFilter ?? {})) {
+ const elements = Array.from(t.querySelectorAll(selector));
+ if (Array.isArray(filter)) {
+ if (!filter.some(f => elements.some(e => {
+ if (typeof f === 'string') {
+ if (!f.startsWith(':RegExp:')) {
+ return e.textContent.trim() === f;
+ }
+ const [ _, flags, pattern ] = f.match(/:RegExp:(?:(\w+):)?(.+)/);
+ const re = new RegExp(pattern, flags);
+ return re.test(e.textContent.trim());
+ }
+ throw TypeError(`Unknown type of filter (${f})`);
+ }))) {
+ return false;
+ }
+ } else {
+ if (!elements.some(e => {
+ if (typeof filter === 'string') {
+ if (!filter.startsWith(':RegExp:')) {
+ return e.textContent.trim() === filter;
+ }
+ const [ _, flags, pattern ] = filter.match(/:RegExp:(?:(\w+):)?(.+)/);
+ const re = new RegExp(pattern, flags);
+ return re.test(e.textContent.trim());
+ }
+ throw TypeError(`Unknown type of filter (${filter})`);
+ })) {
+ return false;
+ }
+ }
+ }
+ return true;
+ });
+ if (!target) {
+ throw Error('No target table found');
+ }
+
+ const tableRows = Array.from(target.querySelectorAll(options.tableRowSelector ?? 'tbody tr'));
+ const tableDataList = [];
+ tableRows.forEach((tr) => {
+ const tableData = {};
+ const tds = Array.from(tr.querySelectorAll(options.tableDataSelector ?? 'td'));
+ const tableDataStructure = options.tableDataStructure ?? [];
+ if (tds.length === 0 || tableDataStructure.length === 0) return null;
+ if (options.tableDataStructure.length > tds.length) {
+ throw Error(`Table data size (${tds.length}) is less than table data structure (${options.tableDataStructure.length})`);
+ }
+ for (let i = 0; i < options.tableDataStructure.length; i++) {
+ const o = options.tableDataStructure[i];
+ let dataItemName = null;
+ let dataItemFilter = null;
+ if (typeof o === 'string') {
+ dataItemName = o;
+ } else if (typeof o === 'object' && o !== null) {
+ if (Object.keys(o).length !== 1) {
+ throw Error(`Table data structure (${options.tableDataStructure}) must be a string or an object with only one key`);
+ }
+ dataItemName = Object.keys(o)[0];
+ dataItemFilter = o[dataItemName];
+ } else {
+ throw Error(`Unknown type of table data structure (${options.tableDataStructure})`);
+ }
+ const dataItemValueRaw = tds[i].textContent.trim();
+ if (dataItemFilter == null) {
+ tableData[dataItemName] = dataItemValueRaw;
+ } else if (typeof dataItemFilter === 'string') {
+ if (!dataItemFilter.startsWith(':RegExp:')) {
+ tableData[dataItemName] = dataItemValueRaw === dataItemFilter ? dataItemValueRaw : null;
+ } else {
+ const [ _, flags, pattern ] = dataItemFilter.match(/:RegExp:(?:(\w+):)?(.+)/);
+ const re = new RegExp(pattern, flags);
+ tableData[dataItemName] = dataItemValueRaw.match(re)?.[0] ?? null;
+ }
+ }
+ }
+ tableDataList.push(tableData);
+ });
+ return tableDataList;
+ }, options);
+}
+
+/**
+ * @typedef {object} PuppeteerOptions
+ * @property {string} url
+ * @property {number} [pageGoToTimeout=120000]
+ * @property {number} [findTargetRowsTimeout=30000]
+ */
+/**
+ * @param {FindTargetRowsOptions & PuppeteerOptions} options
+ * @returns {Promise>}
+ */
+export async function findTargetRows(options) {
+ const browser = await puppeteer.launch({ headless: true });
+ const page = await browser.newPage();
+ try {
+ await page.goto(options.url, { waitUntil: 'networkidle0', timeout: options.pageGoToTimeout ?? 120000 });
+
+ // 页面为懒加载: 滚动并多次尝试, 直到目标表格出现或超时
+ let rows = null;
+ const deadline = Date.now() + (options.findTargetRowsTimeout ?? 30000);
+ while (Date.now() < deadline) {
+ rows = await findTargetRowsWithPage(page, options);
+ if (rows && rows.length) break;
+ await autoScroll(page);
+ await sleep(300);
+ }
+ if (rows && rows.length > 0) {
+ return rows;
+ }
+ throw new Error('Unable to locate target table rows (lazy-loaded content not found in time)');
+ } finally {
+ await browser.close();
+ }
+}
\ No newline at end of file
diff --git a/.utils/utils/versioning.mjs b/.utils/utils/versioning.mjs
new file mode 100644
index 00000000..5c0d896c
--- /dev/null
+++ b/.utils/utils/versioning.mjs
@@ -0,0 +1,97 @@
+// utils/versioning.mjs
+
+const SUFFIX_PRIORITY = { '': 10, 'alpha': 1, 'beta': 2, 'canary': 3, 'rc': 5 };
+
+/**
+ * @param {string} version
+ * @return { [number[], [string, number]]}
+ */
+export function toVersionParts(version) {
+ const parts = version.split(/[\s+-]/);
+ const numberParts = parts[0].split('.').map(part => {
+ const num = parseInt(String(part), 10);
+ if (Number.isNaN(num)) {
+ throw new Error(`Invalid version part: '${part}' in version: '${version}'`);
+ }
+ return num;
+ });
+
+ // 解析后缀, 如 Alpha2 / Beta / RC1 等; 默认数字为 1
+ const suffixPattern = /([A-Za-z]+)\s*(\d*)|([A-Za-z]*)\s*(\d+)/;
+ const suffixStr = parts[1] || '';
+ const m = suffixStr.match(suffixPattern);
+ if (!m) return [ numberParts, [ '', 0 ] ];
+
+ const suffixName = m[1] || '';
+ const suffixNumber = parseInt(m[2] || '1', 10);
+ return [ numberParts, [ suffixName, Number.isNaN(suffixNumber) ? 1 : suffixNumber ] ];
+}
+
+/**
+ * @param {number[]} a
+ * @param {number[]} b
+ * @return {number}
+ */
+export function compareVersionParts(a, b) {
+ const max = Math.max(a.length, b.length);
+ for (let i = 0; i < max; i++) {
+ const x = a[i] ?? 0;
+ const y = b[i] ?? 0;
+ if (x !== y) return x > y ? 1 : -1;
+ }
+ return 0;
+}
+
+/**
+ * @param {[string, number]} s1
+ * @param {[string, number]} s2
+ * @return {number}
+ */
+export function compareVersionSuffix(s1, s2) {
+ const [ name1Raw, num1 ] = s1;
+ const [ name2Raw, num2 ] = s2;
+ const name1 = name1Raw.toLowerCase();
+ const name2 = name2Raw.toLowerCase();
+ const p1 = SUFFIX_PRIORITY[name1] ?? Number.MAX_SAFE_INTEGER;
+ const p2 = SUFFIX_PRIORITY[name2] ?? Number.MAX_SAFE_INTEGER;
+ if (p1 !== p2) return p1 > p2 ? 1 : -1;
+ if (num1 !== num2) return num1 > num2 ? 1 : -1;
+ return 0;
+}
+
+/**
+ * @param {string} v1
+ * @param {string} v2
+ * @return {number}
+ */
+export function compareVersionStrings(v1, v2) {
+ const [ n1, s1 ] = toVersionParts(v1);
+ const [ n2, s2 ] = toVersionParts(v2);
+ const cmp = compareVersionParts(n1, n2);
+ return cmp !== 0 ? cmp : compareVersionSuffix(s1, s2);
+}
+
+/**
+ * @param {string} v1
+ * @param {string} v2
+ * @return {number}
+ */
+export function compareVersionStringsDescending(v1, v2) {
+ const [ n1, s1 ] = toVersionParts(v1);
+ const [ n2, s2 ] = toVersionParts(v2);
+ const cmp = compareVersionParts(n2, n1);
+ return cmp !== 0 ? cmp : compareVersionSuffix(s2, s1);
+}
+
+/**
+ * @param {string} v
+ * @param {Object} options
+ * @param {string} [options.min]
+ * @param {string} [options.max]
+ * @return {boolean}
+ */
+export function isVersionInRange(v, { min, max } = {}) {
+ return (min !== null && compareVersionStrings(v, min) >= 0)
+ && (max !== null && compareVersionStrings(v, max) <= 0);
+
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 6219233b..2c979743 100644
--- a/README.md
+++ b/README.md
@@ -8,16 +8,16 @@
Android 平台支持无障碍服务的 JavaScript 自动化工具
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -59,16 +59,16 @@ AutoJs6 在 Auto.js 最终项目的基础上, 于 `2021/12/01` 进行二次开
| [Auto.js](https://github.com/hyb1996/Auto.js) | [Auto.js](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [hyb1996](https://github.com/hyb1996) | `2017/01/27` | `2020/03/13` | 3.13 |
| Auto.js Pro 7 | Auto.js | [hyb1996](https://github.com/hyb1996) | `2019/03/13` | `2019/07/08` | 0.32 |
| Auto.js Pro 8 | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2019/10/13` | `2021/07/24` | 1.78 |
-| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.74 > |
+| [Auto.js](https://github.com/TonyJiangWJ/Auto.js) | [Auto.js M](https://github.com/TonyJiangWJ/Auto.js/commit/268ec8895bbfa28fc7715154eb15b1c1eaaefd14#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [TonyJiangWJ](https://github.com/TonyJiangWJ) | `2019/11/21` | - | < 5.81 > |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js](https://github.com/kkevsekk1/AutoX/commit/8143e4ed893d4af05d22aa791b83a962f9959873#diff-5e01f7d37a66e4ca03deefc205d8e7008661cdd0284a05aaba1858e6b7bf9103R2) | [kkevsekk1](https://github.com/kkevsekk1) | `2020/07/24` | [ `2025/01/07` ] | 4.46 |
| [Auto.js Pro 9](https://pro.autojs.org/) | AutoJsPro | [hyb1996](https://github.com/hyb1996) | `2021/03/28` | `2023/02/09` | 1.87 |
-| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.71 > |
+| [AutoJs6](https://github.com/SuperMonster003/AutoJs6) | [AutoJs6](https://github.com/SuperMonster003/AutoJs6/commit/a8ce1b9acb541e9736c33134be3194c3148a15a3#diff-833a46a97033e77558372a2dce103fd6fee29aaaa899f610022a7aece592ee7bR27) | [SuperMonster003](https://github.com/SuperMonster003) | `2021/12/01` | - | < 3.78 > |
| [autojs4](https://github.com/blackcd318/autojs4) | Auto.js | [blackcd318](https://github.com/blackcd318) | `2021/12/15` | `2023/07/31` | 1.62 |
| [AutoX](https://github.com/kkevsekk1/AutoX) | [Autox.js v6](https://github.com/kkevsekk1/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [wilinz](https://github.com/wilinz) / [aiselp](https://github.com/aiselp) | `2022/05/26` | [ `2025/01/07` ] | 2.62 |
| [openautojs](https://github.com/openautojs/openautojs) | [OpenAuto.js](https://github.com/openautojs/openautojs/commit/a11feaad025154de9b453ba70b49e94a6ca8b48a#diff-7d757295fcec3b37c258337e048644c258233d79259152e77baa6d36bb0ec418R2) | [openautojs](https://github.com/openautojs) | `2023/02/17` | `2023/04/16` | 0.16 |
-| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.32 > |
-| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.88 > |
-| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.38 > |
+| [AutoX](https://github.com/aiselp/AutoX) | [Autox.js v7](https://github.com/aiselp/AutoX/commit/484491fd5fe12b8203d0b09c181eb0f471c0ea9f#diff-8cff73265af19c059547b76aca8882cbaa3209291406f52df1dafbbc78e80c46R120) | [aiselp](https://github.com/aiselp) | `2024/04/21` | - | < 1.39 > |
+| [Autoxjs_v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi) | [Autox.js v6_ozobi](https://github.com/ozobiozobi/Autoxjs_v6_ozobi/blob/a651d02246e09cfbbfa87e6eaccf900fab/app/build.gradle.kts#L143) | [ozobiozobi](https://github.com/ozobiozobi) | `2024/10/01` | - | < 0.94 > |
+| [AutoX](https://github.com/autox-community/AutoX) | [Autox.js v6](https://github.com/autox-community/AutoX/commit/8b6776cff8b0fca4be4a52719b7d7d07c0a058f3#diff-51a0b488f963eb0be6c6599bf5df497313877cf5bdff3950807373912ac1cdc9R130) | [autox-community](https://github.com/autox-community) | `2025/03/30` | - | < 0.45 > |
表格中的日期为预估值, 实际可能存在出入.
@@ -76,7 +76,7 @@ AutoJs6 在 Auto.js 最终项目的基础上, 于 `2021/12/01` 进行二次开
表格中 `终止开发日期` 列包含方括号 (`[]`) 的数据, 表示开源项目暂时无法访问.
-表格中 `活跃维护期` 列包含尖括号 (`<>`) 的数据, 其统计截止日期为 2025 年 8 月 17 日.
+表格中 `活跃维护期` 列包含尖括号 (`<>`) 的数据, 其统计截止日期为 2025 年 9 月 9 日.
******
@@ -133,7 +133,7 @@ AutoJs6 在 Auto.js 最终项目的基础上, 于 `2021/12/01` 进行二次开
* 主题色适配 [ 分组 / 定位 / 搜索 / 历史记录 / 亮度及对比度自动适配 / ... ]
* 夜间模式适配 [ 设置页面 / 文档页面 / 布局分析页面 / 浮动窗口 / ... ]
* [VSCode 插件](http://vscext-project.autojs6.com) 支持客户端 (LAN) 及服务端 (LAN/ADB) 连接方式
-* [Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升级至 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3)
+* [Rhino](https://github.com/mozilla/rhino/) 引擎由 [v1.7.7.2](https://github.com/mozilla/rhino/releases/tag/Rhino1_7_7_2_Release) 升级至 [v1.8.1-SNAPSHOT](http://rhino.autojs6.com/blob/master/gradle.properties#L3) (更新于 2025 年 4 月 11 日)
* Unicode [码位](https://developer.mozilla.org/zh-CN/docs/Glossary/Code_point) 转义支持 [辅助平面](https://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84#%E7%AC%AC%E4%B8%80%E8%BC%94%E5%8A%A9%E5%B9%B3%E9%9D%A2) 字符
```javascript
'\u{1D160}'; /* 表示 "𝅘𝅥𝅮", 传统方式: '\uD834\uDD60'. */
@@ -280,12 +280,12 @@ AutoJs6 在 Auto.js 最终项目的基础上, 于 `2021/12/01` 进行二次开
#### Android Studio 准备
-下载 `Android Studio Narwhal Feature Drop | 2025.1.2` 版本 (按需选择其一):
+下载 `Android Studio Narwhal 3 Feature Drop | 2025.1.3` 版本 (按需选择其一):
-- [android-studio-2025.1.2.11-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.2.11/android-studio-2025.1.2.11-windows.exe) (1.39 GB)
-- [android-studio-2025.1.2.11-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.2.11/android-studio-2025.1.2.11-windows.zip) (1.40 GB)
+- [android-studio-2025.1.3.7-windows.exe](https://redirector.gvt1.com/edgedl/android/studio/install/2025.1.3.7/android-studio-2025.1.3.7-windows.exe) (1.33 GiB)
+- [android-studio-2025.1.3.7-windows.zip](https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2025.1.3.7/android-studio-2025.1.3.7-windows.zip) (1.34 GiB)
-> 注: 上述版本发布时间为 2025 年 7 月 31 日. 如需下载其他版本, 或上述链接已失效, 可访问 [Android Studio 发行版本归档](https://developer.android.com/studio/archive?hl=en) 页面.
+> 注: 上述版本发布时间为 2025 年 9 月 2 日. 如需下载其他版本, 或上述链接已失效, 可访问 [Android Studio 发行版本归档](https://developer.android.com/studio/archive?hl=en) 页面.
安装或解压上述文件, 运行 Android Studio 软件 (如 `"D:\android-studio\bin\studio64.exe"`).
@@ -334,9 +334,9 @@ File (文件) | Settings (设置) | Appearance & Behavior (外观与行为) | Sy
#### JDK 准备
-AutoJs6 项目依赖的 `JDK (Java 开发工具包)` 发行版本不低于 `17`, 但建议不低于 `19`.
+AutoJs6 项目依赖的 `JDK (Java 开发工具包)` 发行版本不低于 `17`, 但建议不低于 `21`.
-截至 2025 年 8 月 17 日, AutoJs6 可支持 JDK 最高版本为 `24`.
+截至 2025 年 9 月 9 日, AutoJs6 可支持 JDK 最高版本为 `24`.
> 注: 如果计算机系统已安装 JDK 且版本满足上述要求, 则可跳过此小节内容.
@@ -487,19 +487,19 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
感谢每一位参与 AutoJs6 项目开发的贡献人员.
-| 贡献人员 | 提交数 | 最近提交 |
-|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
-| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=wirsnow) | `2025/05/19` |
-| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [5](https://github.com/SuperMonster003/AutoJs6/commits?author=TonyJiangWJ) | `2025/04/24` |
-| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/commits?author=luckyloogn) | `2025/01/01` |
-| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/commits?author=kvii) | `2024/10/16` |
-| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Achenguangming) | `2024/05/14` |
-| [LZX284](https://github.com/LZX284) `(AI)` | [17](https://github.com/SuperMonster003/AutoJs6/commits?author=LZX284) | `2023/11/19` |
-| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/commits?author=little-alei) | `2023/07/12` |
-| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+author%3Aaiselp) | `2023/06/14` |
-| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/commits?author=LYS86) | `2023/06/03` |
+| 贡献人员 | 提交数 | 最近提交 |
+|:-------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------:|
+| [wirsnow](https://github.com/wirsnow) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Awirsnow) | `2025/05/19` |
+| [TonyJiangWJ](https://github.com/TonyJiangWJ) | [4](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ATonyJiangWJ) | `2025/04/24` |
+| [luckyloogn](https://github.com/luckyloogn) | [3](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aluckyloogn) | `2024/12/31` |
+| [kvii](https://github.com/kvii) | [1](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Akvii) | `2024/10/16` |
+| [chenguangming](https://github.com/chenguangming) `(Tom)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Achenguangming) | `2024/05/14` |
+| [LZX284](https://github.com/LZX284) `(AI)` | [7](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALZX284) | `2023/11/15` |
+| [little‑alei](https://github.com/little-alei) `(抠脚本人)` | [12](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Alittle-alei) | `2023/07/12` |
+| [aiselp](https://github.com/aiselp) | [6](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3Aaiselp) | `2023/06/14` |
+| [LYS86](https://github.com/LYS86) `(Lin)` | [2](https://github.com/SuperMonster003/AutoJs6/pulls?q=is%3Apr+is%3Amerged+author%3ALYS86) | `2023/06/03` |
-数据更新于 2025 年 5 月 27 日.
+数据更新于 2025 年 9 月 6 日.
数据条目按 `最近提交` 降序排序.
@@ -520,11 +520,12 @@ autojs6-v6.6.2-arm64-v8a-0f2a9d74.apk
- Translate into other languages
- Update TypeScript declarations according to section `dependency` if needed
- $projectDir/.readme/template_readme.md
- - Update badges like [ android studio / rhino / ... ]
- - Update contribution section: [ h3_contribution ]
+ - Update Rhino badge
+ - Update Android Studio and IntelliJ IDEA badges [ link: aj6mdgen ]
+ - Update contribution section: [ h3_contribution ] [ link: aj6scrapers ]
- $projectDir/.readme/common.json
- - Update android studio download links and version names
- - Update contribution section: var_date_contribution_table_data_updated
+ - Update android studio download links and version names [ link: aj6scrapers ]
+ - Update contribution section: var_date_contribution_table_data_updated [ link: aj6scrapers ]
- $projectDir/.python/generate_markdown.py
- Re-generate markdown by running the python script [ link: aj6mdgen ]
- Others
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index a1a66ae5..62c78738 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -43,7 +43,13 @@ dependencies /* Unclassified */ {
implementation(kotlin("reflect"))
// Androidx Core
- implementation("androidx.core:core-ktx:1.16.0")
+ implementation("androidx.core:core-ktx") {
+ because("Compatibility for Android Gradle plugin 8.2.2")
+ version {
+ strictly("1.15.0")
+ because("Exception on newer versions: Dependency 'androidx.core:core:1.16.0' requires Android Gradle plugin 8.6.0 or higher")
+ }
+ }
// LeakCanary
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.14")
@@ -74,7 +80,7 @@ dependencies /* Unclassified */ {
implementation("de.psdev.licensesdialog:licensesdialog:2.2.0")
// Apache Commons
- implementation("org.apache.commons:commons-lang3:3.17.0")
+ implementation("org.apache.commons:commons-lang3:3.18.0")
// Retrofit
implementation("com.squareup.retrofit2:retrofit:2.12.0")
@@ -657,6 +663,7 @@ android {
}
}
+ @Suppress("DEPRECATION")
kotlinOptions {
jvmTarget = versions.javaVersion.toString()
// freeCompilerArgs = listOf("-Xjvm-default=all-compatibility")
@@ -857,7 +864,7 @@ class Versions(filePath: String) {
}
}
private val javaVersionMinSuggested: Int = properties["JAVA_VERSION_MIN_SUGGESTED"].let { it as String }.toInt()
- private val javaVersionMinRadical: Int = properties["JAVA_VERSION_MIN_RADICAL"].let { it as String }.toInt()
+ private val javaVersionMaxSupported: Int = properties["JAVA_VERSION_MAX_SUPPORTED"].let { it as String }.toInt()
private val javaVersionRaw = properties["JAVA_VERSION"] as String
private var javaVersionInfoSuffix = ""
@@ -920,15 +927,15 @@ class Versions(filePath: String) {
if (currentVersionInt < javaVersionMinSuggested) {
logger.error(
"It is recommended to upgrade current Gradle JDK version ${JavaVersion.current()} to $javaVersionMinSuggested or higher${
- if (javaVersionMinRadical > 0) " (but lower than $javaVersionMinRadical)" else ""
+ if (javaVersionMaxSupported > 0) " (but not higher than $javaVersionMaxSupported)" else ""
}."
)
}
- if (javaVersionMinRadical in 1..currentVersionInt) {
+ if (currentVersionInt > javaVersionMaxSupported) {
logger.error(
"It is recommended to downgrade current Gradle JDK version $currentVersionInt " +
- "to ${javaVersionMinRadical - 1}${if (javaVersionMinRadical - 1 > javaVersionMinSuggested) " or lower (but not lower than $javaVersionMinSuggested)" else ""}, " +
- "as Gradle may be not compatible with JDK $javaVersionMinRadical${if (currentVersionInt > javaVersionMinRadical) " (and above)" else ""} for now."
+ "to $javaVersionMaxSupported${if (javaVersionMaxSupported > javaVersionMinSuggested) " or lower (but not lower than $javaVersionMinSuggested)" else ""}, " +
+ "as Gradle may be not compatible with JDK $currentVersionInt for now."
)
}
}
@@ -939,7 +946,7 @@ class Versions(filePath: String) {
val infoVerName = "Version name: $appVersionName"
val infoVerCode = "Version code: ${if (isBuildNumberAutoIncremented) "${appVersionCode + 1} [auto-incremented]" else appVersionCode}"
val infoVerSdk = "SDK versions: min [$sdkVersionMin] / target [$sdkVersionTarget] / compile [$sdkVersionCompile]"
- val infoVerJava = "Java version: $javaVersion$javaVersionInfoSuffix"
+ val infoVerJava = "Java version: $javaVersion${if (gradle.extra.has("isHideConsoleInfoHintSuffix") && gradle.extra.get("isHideConsoleInfoHintSuffix") == true) "" else javaVersionInfoSuffix}"
val maxLength = arrayOf(title, infoVerName, infoVerCode, infoVerSdk, infoVerJava).maxOf { it.length }
diff --git a/app/src/main/assets/modules/dayjs/package.json b/app/src/main/assets/modules/dayjs/package.json
deleted file mode 100644
index 417c30b9..00000000
--- a/app/src/main/assets/modules/dayjs/package.json
+++ /dev/null
@@ -1,84 +0,0 @@
-{
- "name": "dayjs",
- "version": "1.11.10",
- "description": "2KB immutable date time library alternative to Moment.js with the same modern API ",
- "main": "dayjs.min.js",
- "types": "index.d.ts",
- "scripts": {
- "test": "TZ=Pacific/Auckland npm run test-tz && TZ=Europe/London npm run test-tz && TZ=America/Whitehorse npm run test-tz && npm run test-tz && jest",
- "test-tz": "date && jest test/timezone.test --coverage=false",
- "lint": "./node_modules/.bin/eslint src/* test/* build/*",
- "prettier": "prettier --write \"docs/**/*.md\"",
- "babel": "cross-env BABEL_ENV=build babel src --out-dir esm --copy-files && node build/esm",
- "build": "cross-env BABEL_ENV=build node build && npm run size",
- "sauce": "npx karma start karma.sauce.conf.js",
- "test:sauce": "npm run sauce -- 0 && npm run sauce -- 1 && npm run sauce -- 2 && npm run sauce -- 3",
- "size": "size-limit && gzip-size dayjs.min.js"
- },
- "pre-commit": [
- "lint"
- ],
- "size-limit": [
- {
- "limit": "2.99 KB",
- "path": "dayjs.min.js"
- }
- ],
- "jest": {
- "roots": [
- "test"
- ],
- "testRegex": "test/(.*?/)?.*test.js$",
- "testURL": "http://localhost",
- "coverageDirectory": "./coverage/",
- "collectCoverage": true,
- "collectCoverageFrom": [
- "src/**/*"
- ]
- },
- "keywords": [
- "dayjs",
- "date",
- "time",
- "immutable",
- "moment"
- ],
- "author": "iamkun",
- "license": "MIT",
- "homepage": "https://day.js.org",
- "repository": {
- "type": "git",
- "url": "https://github.com/iamkun/dayjs.git"
- },
- "devDependencies": {
- "@babel/cli": "^7.0.0-beta.44",
- "@babel/core": "^7.0.0-beta.44",
- "@babel/node": "^7.0.0-beta.44",
- "@babel/preset-env": "^7.0.0-beta.44",
- "babel-core": "^7.0.0-bridge.0",
- "babel-jest": "^22.4.3",
- "babel-plugin-external-helpers": "^6.22.0",
- "cross-env": "^5.1.6",
- "eslint": "^4.19.1",
- "eslint-config-airbnb-base": "^12.1.0",
- "eslint-plugin-import": "^2.10.0",
- "eslint-plugin-jest": "^21.15.0",
- "gzip-size-cli": "^2.1.0",
- "jasmine-core": "^2.99.1",
- "jest": "^22.4.3",
- "karma": "^2.0.2",
- "karma-jasmine": "^1.1.2",
- "karma-sauce-launcher": "^1.1.0",
- "mockdate": "^2.0.2",
- "moment": "2.29.2",
- "moment-timezone": "0.5.31",
- "ncp": "^2.0.0",
- "pre-commit": "^1.2.2",
- "prettier": "^1.16.1",
- "rollup": "^2.45.1",
- "rollup-plugin-babel": "^4.4.0",
- "rollup-plugin-terser": "^7.0.2",
- "size-limit": "^0.18.0",
- "typescript": "^2.8.3"
- }
-}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index b7204511..5bdde407 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Jun 06 00:45:56 CST 2025
+#Thu Aug 28 12:05:55 CST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 8828a14a..1bda8c47 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -58,11 +58,17 @@ pluginManagement {
// ! plugin("com.google.devtools.ksp")
val overriddenKspVersion: String? = null
+ val versionProperties = java.util.Properties().apply {
+ load(java.io.FileInputStream("$rootDir/version.properties"))
+ }
+
+ // @AnchorBegin EMBEDDED_KOTLIN_LIST
+ // @Script /.utils/scrape-and-inject-embedded-kotlin-list.mjs
// @Signature Pair
// @Reference gradle--src.zip\gradle\dependency-management\kotlin-version.properties
// @Reference https://docs.gradle.org/current/userguide/compatibility.html#kotlin
// @Updated by SuperMonster003 on Aug 9, 2025.
- val embeddedKotlin: List> = listOf(
+ val embeddedKotlin = listOf(
"9.0" to "2.2.0",
"8.14" to "2.1.10", /* Unofficial. */
"8.13" to "2.1.10", /* Unofficial. */
@@ -75,9 +81,11 @@ pluginManagement {
"8.4" to "1.9.10",
"8.3" to "1.9.0",
"8.2" to "1.8.20",
- "8.0" to "1.8.10",
)
+ // @AnchorEnd EMBEDDED_KOTLIN_LIST
+ // @AnchorBegin JAVA_GRADLE_COMPATIBILITY_LIST
+ // @Script /.utils/scrape-java-gradle-compatibility-map.mjs
// @Signature Pair
// @Reference https://docs.gradle.org/current/userguide/compatibility.html#java_runtime
// @Updated by SuperMonster003 on May 12, 2025.
@@ -92,11 +100,15 @@ pluginManagement {
18 to "7.5",
17 to "7.3",
)
+ // @AnchorEnd JAVA_GRADLE_COMPATIBILITY_LIST
+ // @AnchorBegin AGP_GRADLE_COMPATIBILITY_LIST
+ // @Script /.utils/scrape-and-inject-agp-gradle-compatibility-list.mjs
// @Signature Pair
// @Reference https://developer.android.com/build/releases/gradle-plugin#updating-gradle
- // @Updated by SuperMonster003 on Aug 9, 2025.
- val agpGradleCompatibility: List> = listOf(
+ // @Updated by SuperMonster003 on Sep 3, 2025.
+ val agpGradleCompatibility = listOf(
+ "8.13" to "8.13",
"8.12" to "8.13",
"8.11" to "8.13",
"8.10" to "8.11.1",
@@ -108,20 +120,20 @@ pluginManagement {
"8.4" to "8.6",
"8.3" to "8.4",
"8.2" to "8.2",
- "8.1" to "8.0",
- "8.0" to "8.0",
- "7.4" to "7.5",
- "7.3" to "7.4",
)
+ // @AnchorEnd AGP_GRADLE_COMPATIBILITY_LIST
+ // @AnchorBegin ANDROID_GRADLE_PLUGIN_RELEASES_LIST
+ // @Script /.utils/scrape-and-inject-agp-releases.mjs
// @Reference https://developer.android.com/reference/tools/gradle-api
- // @Updated by SuperMonster003 on Aug 9, 2025.
- val agpReleases: List = listOf(
- "8.13.0-alpha04", /* Aug 9, 2025. */
- "8.12.0", /* Aug 9, 2025. */
- "8.11.1", /* Aug 9, 2025. */
- "8.10.1", /* Jun 7, 2025. */
- "8.9.3", /* May 17, 2025. */
+ // @Updated by SuperMonster003 on Sep 5, 2025.
+ val agpReleases = listOf(
+ "9.0.0-alpha04",
+ "8.13.0",
+ "8.12.2",
+ "8.11.1",
+ "8.10.1",
+ "8.9.3",
"8.8.2",
"8.7.3",
"8.6.1",
@@ -129,10 +141,8 @@ pluginManagement {
"8.4.2",
"8.3.2",
"8.2.2",
- "8.1.4",
- "8.0.2",
- "7.4.2",
)
+ // @AnchorEnd ANDROID_GRADLE_PLUGIN_RELEASES_LIST
val consts = object {
val DEFAULT_VERSION = "0"
@@ -146,37 +156,41 @@ pluginManagement {
val vendorName: String? = System.getProperty("idea.vendor.name")
?: System.getProperty("java.vendor")
?: System.getProperty("java.vm.vendor")
- val concerns: List by lazy {
- val concernedKeyWords = setOf("name", "vendor", "version", "platform", "paths", "os")
- val unconcernedKeyWords = setOf("url", "user", "runtime", "specification", "date")
- val unconcernedKeys = setOf(
- "java.class.version",
- "java.vm.name",
- "java.vm.version",
- "java.version",
- "platform.random.idempotence.check.rate",
- "sun.os.patch.level",
- )
- System.getProperties().filterKeys { key ->
- return@filterKeys key is String
- && key !in unconcernedKeys
- && key.split(Regex("\\W")).any { it in concernedKeyWords }
- && key.split(Regex("\\W")).none { it in unconcernedKeyWords }
- }.map { (key, value) -> "[ $key: $value ]" }
- }
- var isConcernsAlreadyPrinted = false
+ }
+
+ var isConcernedPropertiesAlreadyPrinted = false
+
+ val concernedProperties: List by lazy {
+ val concernedKeyWords = setOf("name", "vendor", "version", "platform", "paths", "os")
+ val unconcernedKeyWords = setOf("url", "user", "runtime", "specification", "date")
+ val unconcernedKeys = setOf(
+ "java.class.version",
+ "java.vm.name",
+ "java.vm.version",
+ "java.version",
+ "platform.random.idempotence.check.rate",
+ "sun.os.patch.level",
+ )
+ System.getProperties().apply {
+ putAll(gradle.startParameter.projectProperties)
+ }.filterKeys { key ->
+ return@filterKeys key is String
+ && key !in unconcernedKeys
+ && key.split(Regex("\\W")).any { it in concernedKeyWords }
+ && key.split(Regex("\\W")).none { it in unconcernedKeyWords }
+ }.map { (key, value) -> "[ $key: $value ]" }
}
data class Classpath(val id: String, val version: String)
data class Plugin(val id: String, val version: String, val isApply: Boolean = false)
- class Formatted(title: String, private val contents: Collection = emptyList(), subtitle: String? = null) {
+ class Formatted(title: String, private val contents: Collection = emptyList(), subtitle: String? = null, footers: Collection = emptyList()) {
private val formattedOutput = run {
val elements = mutableListOf()
subtitle?.let { elements.add(it) }
elements.addAll(contents)
- val maxLength = elements.plus(title).maxOf { it.length }
+ val maxLength = elements.plus(title).plus(footers).maxOf { it.length }
listOfNotNull(
"=".repeat(maxLength),
@@ -184,6 +198,8 @@ pluginManagement {
subtitle,
"-".repeat(maxLength).takeUnless { contents.isEmpty() },
*contents.toTypedArray(),
+ "-".repeat(maxLength).takeUnless { footers.isEmpty() },
+ *footers.toTypedArray(),
"=".repeat(maxLength),
"",
)
@@ -194,59 +210,145 @@ pluginManagement {
fun throwException(): Unit = throw Exception(formattedOutput.joinToString("\n"))
}
+ val utils = object {
+ fun compareVersionStrings(v1: String, v2: String): Int {
+ val (ver1Numbers, ver1Suffix) = toVersionParts(v1)
+ val (ver2Numbers, ver2Suffix) = toVersionParts(v2)
+ return compareVersionParts(ver1Numbers, ver2Numbers)
+ .takeIf { it != 0 }
+ ?: compareVersionSuffix(ver1Suffix, ver2Suffix)
+ }
+
+ fun compareVersionParts(parts1: List, parts2: List): Int {
+ for (i in 0 until maxOf(parts1.size, parts2.size)) {
+ val part1 = parts1.getOrElse(i) { 0 }
+ val part2 = parts2.getOrElse(i) { 0 }
+ if (part1 != part2) return part1.compareTo(part2)
+ }
+ return 0
+ }
+
+ fun compareVersionSuffix(suffix1: Pair, suffix2: Pair): Int {
+ val suffixPriority = mapOf("" to 10, "Alpha" to 1, "Beta" to 2, "RC" to 5)
+ val (suffixName1, suffixNumber1) = suffix1
+ val (suffixName2, suffixNumber2) = suffix2
+ val priority1 = suffixPriority[suffixName1] ?: Int.MAX_VALUE
+ val priority2 = suffixPriority[suffixName2] ?: Int.MAX_VALUE
+ return priority1.compareTo(priority2).takeIf { it != 0 } ?: suffixNumber1.compareTo(suffixNumber2)
+ }
+
+ fun toVersionParts(version: String): Pair, Pair> {
+ val parts = version.split(Regex("[+-]"))
+ val numberParts = parts[0].split('.').map {
+ it.toIntOrNull() ?: throw IllegalArgumentException("Invalid version part: '$it' in version: '$version'")
+ }
+
+ val suffixPattern = Regex("([A-Za-z]+)(\\d*)|([A-Za-z]*)(\\d+)")
+ val suffixMatch = suffixPattern.matchEntire(parts.getOrElse(1) { "" }) ?: return numberParts to ("" to 0)
+
+ val suffixName = suffixMatch.groupValues[1] // "Alpha", "Beta", "RC" or empty string
+ val suffixNumber = suffixMatch.groupValues[2].toIntOrNull() ?: 1 // Default to 1 for suffixes like "Alpha", "Beta", "RC"
+
+ return numberParts to (suffixName to suffixNumber)
+ }
+
+ fun parseAndroidStudioBuildToVersion(): String? {
+ // e.g. "251.26094.121.2513.13991806".
+ val build = providers.gradleProperty("android.studio.version")
+ .orElse(providers.systemProperty("android.studio.version"))
+ .orNull ?: return null
+ val parts = build.split('.')
+ val baseStr = parts.getOrNull(0) ?: return null
+ val base = baseStr.toIntOrNull() ?: return null
+ val year = 2000 + base / 10
+ val minor = base % 10
+
+ // Look for strings starting with base and having longer length in the remaining fragments.
+ // e.g. "2513" means patch version is "3".
+ // zh-CN:
+ // 在其余片段里找以 base 开头且长度更长的字段.
+ // 如 "2513" 意味着补丁版本为 "3".
+ val patch = parts.drop(1).firstNotNullOfOrNull { seg ->
+ if (seg.startsWith(baseStr) && seg.length > baseStr.length) {
+ seg.substring(baseStr.length).toIntOrNull()
+ } else null
+ }
+
+ return if (patch != null && patch > 0) "$year.$minor.$patch" else "$year.$minor"
+ }
+ }
+
val config = object {
- /* Print concerned info by `System.getProperties()`. */
- val isShowConcernedSystemProperties = true
+ /* Hide concerned properties by `System.getProperties()` and `gradle.startParameter.projectProperties`. */
+ val isHideConcernedProperties = false
+
+ /* Hide hint suffix like `[auto-specified]`, `[nearest-lower-matched]`, etc. in console. */
+ val isHideConsoleInfoHintSuffix = false
val isCleanupPaddleOcr = false
val isCleanupRapidOcr = false
- val fallbackAgpVersion = "7.4.2"
- val fallbackKotlinVersion = "1.7.10"
+ val fallbackAgpVersion = "8.2.2"
+ val fallbackKotlinVersion = "1.8.10"
@Suppress("unused")
val platforms = object {
val androidStudio = object : Platform(
name = "AndroidStudio", vendor = "Google",
+ // @AnchorBegin ANDROID_STUDIO_AGP_VERSION_MAP
+ // @Script /.utils/scrape-android-studio-agp_version_maps.mjs
// @Reference https://developer.android.com/studio/releases#android_gradle_plugin_and_android_studio_compatibility
- // @Updated by SuperMonster003 on Aug 9, 2025.
+ // @Updated by SuperMonster003 on Sep 5, 2025.
agpVersionMap = mapOf(
- "2025.1" to "8.11", /* Jun 7, 2025. */
- "2024.3" to "8.9", /* May 17, 2025. */
- "2024.2" to "8.7", /* Jan 13, 2025. */
- "2024.1" to "8.5", /* Aug 30, 2024. */
- "2023.3" to "8.4", /* Mar 28, 2024. */
- "2023.2" to "8.3", /* Feb 14, 2024. */
- "2023.1" to "8.2", /* Feb 6, 2024. */
- "2022.3" to "8.1", /* Mar 31, 2024. */
- "2022.2" to "8.0", /* May 26, 2023. */
- "2022.1" to "7.4", /* Mar 25, 2023. */
- ),
- // @Updated by SuperMonster003 on May 13, 2025.
- kotlinVersionMap = mapOf(
- "2024.3" to "2.1.21", /* May 17, 2025. */
- "2024.2" to "2.1.0", /* Nov 29, 2024. */
- "2024.1" to "2.0.0", /* Aug 13, 2024. */
+ "2025.1.3" to "8.13",
+ "2025.1.2" to "8.12",
+ "2025.1.1" to "8.11",
+ "2024.3.2" to "8.10",
+ "2024.3.1" to "8.9",
+ "2024.2.2" to "8.8",
+ "2024.2.1" to "8.7",
+ "2024.1.2" to "8.6",
+ "2024.1.1" to "8.5",
+ "2023.3.1" to "8.4",
),
+ // @AnchorEnd ANDROID_STUDIO_AGP_VERSION_MAP
+
+ // @AnchorBegin ANDROID_STUDIO_CODENAME_VERSION_MAP
+ // @Script /.utils/scrape-and-inject-android-studio-codename_maps.mjs
+ // @Reference https://developer.android.com/studio/archive?hl=en
+ // @Updated by SuperMonster003 on Sep 5, 2025.
codenameVersionMap = mapOf(
- "2025.1" to "N", /* Apr 11, 2025. */
- "2024.3" to "M", /* Nov 29, 2024. */
- "2024.2" to "L", /* Aug 13, 2024. */
- "2024.1" to "K|L", /* May 14, 2024. */
- "2023.3" to "J|K", /* Jan 21, 2024. */
- "2023.2" to "I", /* Aug 25, 2023. */
- "2023.1" to "H", /* May 13, 2023. */
- "2022.3" to "G", /* May 3, 2023. */
- "2022.2" to "F", /* May 3, 2023. */
- "2022.1" to "E", /* May 3, 2023. */
+ "2025.1" to "N",
+ "2024.3" to "M",
+ "2024.2" to "L",
+ "2024.1.3" to "L",
+ "2024.1.2" to "K",
+ "2024.1.1" to "K",
+ "2023.3.2" to "J|K",
+ "2023.3.1" to "J",
+ "2023.2" to "I",
+ "2023.1" to "H",
+ "2022.3" to "G",
+ "2022.2" to "F",
+ "2022.1" to "E",
+ "2021.3" to "D",
+ "2021.2" to "C",
+ "2021.1" to "B",
+ "2020.3" to "A",
),
+ // @AnchorEnd ANDROID_STUDIO_CODENAME_VERSION_MAP
+
+ // @AnchorBegin ANDROID_STUDIO_CODENAME_MAP
+ // @Script /.utils/scrape-and-inject-android-studio-codename_maps.mjs
+ // @Reference https://developer.android.com/studio/archive?hl=en
+ // @Updated by SuperMonster003 on Apr 11, 2025.
codenameMap = mapOf(
"N" to "Narwhal", /* Born on Mar 19, 2025. */
"M" to "Meerkat", /* Born on Nov 12, 2024. */
"L" to "Ladybug", /* Born on Jul 15, 2024. */
- "K" to "Koala", /* Born on Mar 19, 2024. */
+ "K" to "Koala", /* Born on Mar 22, 2024. */
"J" to "Jellyfish", /* Born on Dec 28, 2023. */
"I" to "Iguana", /* Born on Aug 25, 2023. */
"H" to "Hedgehog", /* Born on Apr 25, 2023. */
@@ -258,59 +360,53 @@ pluginManagement {
"B" to "Bumblebee", /* Born on May 18, 2021. */
"A" to "Arctic Fox", /* Born on Jan 26, 2021. */
),
+ // @AnchorEnd ANDROID_STUDIO_CODENAME_MAP
) {
override val weight = Int.MAX_VALUE
override val gradleSettingsName = "Gradle JDK"
override val fullName by lazy {
- val suffix = codenameVersionMap?.get(version)
- ?.split("|")
- ?.joinToString(" / ", prefix = " ") { key ->
- codenameMap?.get(key.trim()) ?: key
- } ?: ""
+ val suffix = codenameVersionMap?.let { map ->
+ val letters = map[version]
+ ?: map[version.split(".").take(2).joinToString(".")]
+ ?: return@let null
+ letters
+ .split("|")
+ .joinToString(" / ", prefix = " ") { key ->
+ codenameMap?.get(key.trim()) ?: key
+ }
+ } ?: ""
return@lazy "Android Studio$suffix"
}
+ override val minSupportedVersion = versionProperties["MIN_SUPPORTED_ANDROID_STUDIO_IDE_VERSION"] as String
}
val intelliJIdea = object : Platform(
name = "IntelliJIdea", vendor = "Jetbrains",
// @Reference AGP Upgrade Assistant integrated within JetBrains IntelliJ IDEA.
- // @Updated by SuperMonster003 on Aug 10, 2025.
+ // @Updated by SuperMonster003 on Aug 10, 2025. (Manual)
agpVersionMap = mapOf(
- "2025.2" to "8.11.0", /* Aug 10, 2025. */
- "2025.1" to "8.10.1", /* Jun 7, 2025. */
- "2024.3.1" to "8.7.3", /* Dec 10, 2024. */
- "2024.3" to "8.7.0-rc01", /* Nov 15, 2024. */
- "2024.2" to "8.5.2", /* Aug 13, 2024. */
- "2024.1" to "8.2.2", /* Apr 6, 2024. */
- "2023.3" to "8.2.2", /* Jan 19, 2024. */
- "2023.1" to "7.4.2", /* May 26, 2023. */
- "2022.3" to "7.4.0-beta02", /* Mar 25, 2023. */
- ),
- // @Updated by SuperMonster003 on Apr 23, 2025.
- kotlinVersionMap = mapOf(
- "2025.1" to "2.1.21", /* May 17, 2025. */
- "2024.3.4" to "2.1.10", /* Feb 28, 2025. */
- "2024.2.3" to "2.0.21", /* Oct 17, 2024. */
- "2024.2" to "2.0.21-RC", /* Sep 27, 2024. */
- "2024.1" to "1.9.24", /* Dec 3, 2024. */
- "2023.3" to "1.9.23", /* Mar 29, 2024. */
+ "2025.2" to "8.11.1",
+ "2025.1" to "8.10.1",
+ "2024.3" to "8.7.3",
+ "2024.2" to "8.5.2",
+ "2024.1" to "8.2.2",
+ "2023.3" to "8.2.2", /* Settings: Enable sync with future AGP version. */
),
) {
override val weight = 10
override val gradleSettingsName = "Gradle JVM"
override val fullName = "IntelliJ IDEA"
+ override val minSupportedVersion = versionProperties["MIN_SUPPORTED_INTELLIJ_IDEA_IDE_VERSION"] as String
}
val temurin = object : Platform(
- name = "Temurin", vendor = "temurin", /* More common as "Eclipse Adoptium". */
+ name = "Temurin", vendor = "temurin",
+ /* More common as "Eclipse Adoptium". */
+ // @Updated by SuperMonster003 on Apr 16, 2025. (Manual)
agpVersionMap = mapOf(
"21.0.6+7" to "8.7.3", /* Apr 16, 2025. */
"20.0.2+9" to "8.2.2", /* Dec 2, 2024. */
),
- kotlinVersionMap = mapOf(
- "21.0.6+7" to "2.1.10", /* Apr 16, 2025. */
- "20.0.2+9" to "1.9.24", /* Dec 2, 2024. */
- ),
) {
override val weight = 5
override val shouldPrintProgress = false
@@ -323,9 +419,9 @@ pluginManagement {
println("Unexpected platform: $it")
} ?: Formatted(
"Current platform is unknown",
- systemProperties.concerns,
+ concernedProperties,
"However, here are some props may be useful for determining platform info",
- ).print().also { systemProperties.isConcernsAlreadyPrinted = true }
+ ).print().also { isConcernedPropertiesAlreadyPrinted = true }
}
fun determine(): Platform {
@@ -336,6 +432,16 @@ pluginManagement {
}?.let { tmpPlatform as? Platform }
}
}
+
+ fun parseVersion(platform: Platform) = systemProperties.version ?: when {
+ platform != unknown && systemProperties.platform != null -> {
+ systemProperties.platform.substring(platform.name.length)
+ .replace(Regex("^\\W*"), "")
+ .replace(Regex("^Preview", RegexOption.IGNORE_CASE), "")
+ }
+ else -> consts.DEFAULT_VERSION
+ }
+
return when {
candidates.isEmpty() -> when (val osName = System.getProperty("os.name")) {
is String -> unknown.also { it.name = osName }
@@ -344,13 +450,13 @@ pluginManagement {
candidates.size > 1 -> candidates.maxBy { it.weight }
else -> candidates.first()
}.also {
- it.version = systemProperties.version ?: when {
- it != unknown && systemProperties.platform != null -> {
- systemProperties.platform.substring(it.name.length)
- .replace(Regex("^\\W*"), "")
- .replace(Regex("^Preview", RegexOption.IGNORE_CASE), "")
+ when (it) {
+ androidStudio -> {
+ it.version = utils.parseAndroidStudioBuildToVersion() ?: parseVersion(it)
+ }
+ else -> {
+ it.version = parseVersion(it)
}
- else -> consts.DEFAULT_VERSION
}
}
}
@@ -363,11 +469,16 @@ pluginManagement {
Plugin(id = "com.google.devtools.ksp", version = overriddenKspVersion ?: "auto:ksp"),
)
+ // @AnchorBegin KSP_VERSION_MAP
+ // @Script /.utils/scrape-and-inject-ksp-releases.mjs
// @Reference https://github.com/google/ksp/releases
- // @Updated by SuperMonster003 on Aug 9, 2025.
+ // @Updated by SuperMonster003 on Sep 4, 2025.
val kspVersionMap = mapOf(
+ "2.2.20-RC2" to "2.0.2", /* Sep 4, 2025. */
+ "2.2.20-RC" to "2.0.2", /* Aug 20, 2025. */
"2.2.20-Beta2" to "2.0.2", /* Aug 1, 2025. */
"2.2.20-Beta1" to "2.0.2", /* Jul 11, 2025. */
+ "2.2.10" to "2.0.2", /* Aug 15, 2025. */
"2.2.10-RC2" to "2.0.2", /* Aug 7, 2025. */
"2.2.10-RC" to "2.0.2", /* Jul 25, 2025. */
"2.2.0" to "2.0.2", /* Jun 25, 2025. */
@@ -436,12 +547,12 @@ pluginManagement {
"1.8.0" to "1.0.9", /* Jan 26, 2023. */
"1.8.0-RC2" to "1.0.8", /* Dec 21, 2022. */
)
+ // @AnchorEnd KSP_VERSION_MAP
abstract inner class Platform(
var name: String,
val vendor: String,
val agpVersionMap: Map = emptyMap(),
- val kotlinVersionMap: Map = emptyMap(),
val codenameVersionMap: Map? = null,
val codenameMap: Map? = null,
) {
@@ -449,6 +560,7 @@ pluginManagement {
open val gradleSettingsName: String? = null
open val weight: Int = -Int.MAX_VALUE
open var version: String = consts.DEFAULT_VERSION
+ open val minSupportedVersion: String = consts.DEFAULT_VERSION
@Suppress("unused")
open val shouldPrintProgress: Boolean = true
@@ -460,9 +572,7 @@ pluginManagement {
|| systemProperties.vendorName?.contains(vendor, true) == true
fun ensureMinimalGradleJdkVersion() {
- val minVer = java.util.Properties().apply {
- load(java.io.FileInputStream("$rootDir/version.properties"))
- }["JAVA_VERSION_MIN_SUPPORTED"].let { it as String }.toInt()
+ val minVer = versionProperties["JAVA_VERSION_MIN_SUPPORTED"].let { it as String }.toInt()
if (JavaVersion.current().majorVersion.toInt() < minVer) {
Formatted(
@@ -476,6 +586,12 @@ pluginManagement {
}
}
+ fun ensureMinimalIdeVersion() {
+ if (minSupportedVersion == consts.DEFAULT_VERSION) return
+ if (utils.compareVersionStrings(version, minSupportedVersion) >= 0) return
+ throw Exception("Current IDE (${this.fullName}) version $version does not meet the minimum requirement which $minSupportedVersion is needed")
+ }
+
fun prependConsoleInformation(consoleInfo: MutableList) {
val versionSuffix = when (this.version.isNotEmpty() && this.version != consts.DEFAULT_VERSION) {
true -> " | ${this.version}"
@@ -527,18 +643,20 @@ pluginManagement {
var versionInfo = mutableListOf()
- fun printConcernedSystemPropertiesIfNeeded() {
- if (config.isShowConcernedSystemProperties && !systemProperties.isConcernsAlreadyPrinted) {
- Formatted("Information for concerned system properties", systemProperties.concerns).print(true)
+ fun printConcernedPropertiesIfNeeded() {
+ if (!config.isHideConcernedProperties && !isConcernedPropertiesAlreadyPrinted) {
+ Formatted("Information for concerned properties", concernedProperties).print(true)
}
}
fun printVersionsOfIdeAndGradlePlugins() {
- Formatted("Version information for IDE platform and Gradle plugins", versionInfo).print()
+ val footers = listOf("Gradle version: ${gradle.gradleVersion}")
+ Formatted("Version information for IDE platform and Gradle plugins", versionInfo, footers = footers).print()
}
}
+ platform.ensureMinimalIdeVersion()
platform.ensureMinimalGradleJdkVersion()
platform.prependConsoleInformation(console.versionInfo)
@@ -551,35 +669,37 @@ pluginManagement {
override fun refinedBestMatchingValue(bestMatchingValue: String?): String? {
val currentGradleVersion = gradle.gradleVersion.toGradleVersion()
val sorted = agpGradleCompatibility.sortedByDescending { it.second.toGradleVersion() }
- var maxSupporedAgpVersionPrefix: String? = null
+ var maxSupportedAgpVersionPrefix: String? = null
for (pair in sorted) {
- maxSupporedAgpVersionPrefix = pair.first
+ maxSupportedAgpVersionPrefix = pair.first
if (currentGradleVersion >= pair.second.toGradleVersion()) {
break
}
}
- val maxSupporedAgpVersion = maxSupporedAgpVersionPrefix?.let { getAgpReleasedVersion(it) }
- return when {
- maxSupporedAgpVersion == null -> bestMatchingValue
- bestMatchingValue == null -> {
- bestMatchingOperationHintSuffix = identifier.autoSpecifiedSuffix
- maxSupporedAgpVersion
- }
- compareVersionStrings(bestMatchingValue, maxSupporedAgpVersion) > 0 -> {
- bestMatchingOperationHintSuffix = identifier.downgradedSuffix
- maxSupporedAgpVersion
- }
- else -> bestMatchingValue
+ val maxSupporedAgpVersion = maxSupportedAgpVersionPrefix?.let { getAgpReleasedVersion(it) }
+ maxSupporedAgpVersion ?: return bestMatchingValue
+ bestMatchingValue ?: return maxSupporedAgpVersion.also {
+ bestMatchingOperationHintSuffix += identifier.autoSpecifiedSuffix
}
+ if (!bestMatchingValue.contains("\\d+\\.\\d+\\.\\d+".toRegex())) {
+ bestMatchingOperationHintSuffix += identifier.autoSpecifiedSuffix
+ return getAgpReleasedVersion(bestMatchingValue) ?: "$bestMatchingValue.0"
+ }
+ if (utils.compareVersionStrings(bestMatchingValue, maxSupporedAgpVersion) > 0) {
+ bestMatchingOperationHintSuffix += identifier.downgradedSuffix
+ return maxSupporedAgpVersion
+ }
+ return bestMatchingValue
}
private fun getAgpReleasedVersion(referenceAgpVersion: String): String? {
- return agpReleases.find { it.startsWith(referenceAgpVersion) && !it.contains("-") }
+ val sortedAgpReleases = agpReleases.sortByVersionName(isDescend = true)
+ return sortedAgpReleases.find { it.startsWith(referenceAgpVersion) && !it.contains("-") }
}
}
- val kotlin = object : Version(platform.kotlinVersionMap, platform.version, config.fallbackKotlinVersion) {
+ val kotlin = object : Version(emptyMap(), platform.version, config.fallbackKotlinVersion) {
override fun refinedBestMatchingValue(bestMatchingValue: String?): String? {
val currentGradleVersion = gradle.gradleVersion.toGradleVersion()
@@ -590,15 +710,15 @@ pluginManagement {
return when {
embeddedMin == null -> bestMatchingValue
bestMatchingValue == null -> {
- bestMatchingOperationHintSuffix = identifier.autoSpecifiedSuffix
+ bestMatchingOperationHintSuffix += identifier.autoSpecifiedSuffix
embeddedMin
}
bestMatchingValue.toGradleVersion() < embeddedMin.toGradleVersion() -> {
- bestMatchingOperationHintSuffix = identifier.upgradedSuffix
+ bestMatchingOperationHintSuffix += identifier.upgradedSuffix
embeddedMin
}
bestMatchingValue.toGradleVersion() > embeddedMin.toGradleVersion() -> {
- bestMatchingOperationHintSuffix = identifier.downgradedSuffix
+ bestMatchingOperationHintSuffix += identifier.downgradedSuffix
embeddedMin
}
else -> bestMatchingValue
@@ -630,7 +750,7 @@ pluginManagement {
val ver = Version(config.kspVersionMap, kt)
val key = ver.bestMatchingKey ?: return@let null
val value = ver.bestMatchingValue ?: return@let null
- ver.bestMatchingOperationHintSuffix?.let { suffix += it }
+ suffix += ver.bestMatchingOperationHintSuffix
"$key-$value"
}
@@ -649,7 +769,7 @@ pluginManagement {
else -> throw Exception("Unknown version ${lib.version} for classpath ${lib.id}")
}
ver.bestMatchingValue?.also {
- ver.bestMatchingOperationHintSuffix?.let { s -> suffix += s }
+ suffix += ver.bestMatchingOperationHintSuffix
} ?: ver.fallbackVersion?.also {
suffix += identifier.fallbackSuffix
} ?: consts.DEFAULT_VERSION
@@ -663,7 +783,7 @@ pluginManagement {
gradle.extra.set("javaVersionOverriddenByUser", overriddenJavaVersion)
}
"${lib.id}:$version".also { notation ->
- console.versionInfo += "Classpath: \"$notation\"$suffix"
+ console.versionInfo += "Classpath: \"$notation\"${if (config.isHideConsoleInfoHintSuffix) "" else suffix}"
}
}
@@ -681,7 +801,7 @@ pluginManagement {
lib.version
}
}
- console.versionInfo += "Plugin: \"${lib.id}:$version\"$suffix"
+ console.versionInfo += "Plugin: \"${lib.id}:$version\"${if (config.isHideConsoleInfoHintSuffix) "" else suffix}"
mapOf("id" to lib.id, "version" to version, "isApply" to lib.isApply)
}
@@ -689,8 +809,9 @@ pluginManagement {
val bestMatchingKey: String? = findBestMatchingMapKey(platformVersion)
- var bestMatchingOperationHintSuffix: String? = identifier.nearestLowerMatchedSuffix.takeIf {
- bestMatchingKey != null && bestMatchingKey != platformVersion
+ var bestMatchingOperationHintSuffix: String = when (bestMatchingKey != null && bestMatchingKey != platformVersion) {
+ true -> identifier.nearestLowerMatchedSuffix
+ else -> ""
}
val bestMatchingValue: String? = refinedBestMatchingValue(bestMatchingKey?.let { map[it] })
@@ -698,60 +819,23 @@ pluginManagement {
open fun refinedBestMatchingValue(bestMatchingValue: String?) = bestMatchingValue
fun findBestMatchingMapKey(platformVersion: String): String? {
- val (platformVersionNumbers, platformVersionSuffix) = toVersionParts(platformVersion)
- val sortedVersions = map.keys.filter { it != identifier.fallback }.sortedWith(::compareVersionStrings).reversed()
+ val (platformVersionNumbers, platformVersionSuffix) = utils.toVersionParts(platformVersion)
+ val sortedVersions = map.keys.filter { it != identifier.fallback }.sortedWith(utils::compareVersionStrings).reversed()
for (version in sortedVersions) {
- val (versionNumbers, versionSuffix) = toVersionParts(version)
- val versionComparisonScore = compareVersionParts(versionNumbers, platformVersionNumbers)
+ val (versionNumbers, versionSuffix) = utils.toVersionParts(version)
+ val versionComparisonScore = utils.compareVersionParts(versionNumbers, platformVersionNumbers)
if (versionComparisonScore < 0) {
return version
}
- if (versionComparisonScore == 0 && compareSuffix(versionSuffix, platformVersionSuffix) <= 0) {
+ if (versionComparisonScore == 0 && utils.compareVersionSuffix(versionSuffix, platformVersionSuffix) <= 0) {
return version
}
}
return null
}
- fun compareVersionStrings(v1: String, v2: String): Int {
- val (ver1Numbers, ver1Suffix) = toVersionParts(v1)
- val (ver2Numbers, ver2Suffix) = toVersionParts(v2)
- return compareVersionParts(ver1Numbers, ver2Numbers)
- .takeIf { it != 0 }
- ?: compareSuffix(ver1Suffix, ver2Suffix)
- }
-
- private fun compareVersionParts(parts1: List, parts2: List): Int {
- for (i in 0 until maxOf(parts1.size, parts2.size)) {
- val part1 = parts1.getOrElse(i) { 0 }
- val part2 = parts2.getOrElse(i) { 0 }
- if (part1 != part2) return part1.compareTo(part2)
- }
- return 0
- }
-
- private fun compareSuffix(suffix1: Pair, suffix2: Pair): Int {
- val suffixPriority = mapOf("" to 10, "Alpha" to 1, "Beta" to 2, "RC" to 5)
- val (suffixName1, suffixNumber1) = suffix1
- val (suffixName2, suffixNumber2) = suffix2
- val priority1 = suffixPriority[suffixName1] ?: Int.MAX_VALUE
- val priority2 = suffixPriority[suffixName2] ?: Int.MAX_VALUE
- return priority1.compareTo(priority2).takeIf { it != 0 } ?: suffixNumber1.compareTo(suffixNumber2)
- }
-
- private fun toVersionParts(version: String): Pair, Pair> {
- val parts = version.split(Regex("[+-]"))
- val numberParts = parts[0].split('.').map {
- it.toIntOrNull() ?: throw IllegalArgumentException("Invalid version part: '$it' in version: '$version'")
- }
-
- val suffixPattern = Regex("([A-Za-z]+)(\\d*)|([A-Za-z]*)(\\d+)")
- val suffixMatch = suffixPattern.matchEntire(parts.getOrElse(1) { "" }) ?: return numberParts to ("" to 0)
-
- val suffixName = suffixMatch.groupValues[1] // "Alpha", "Beta", "RC" or empty string
- val suffixNumber = suffixMatch.groupValues[2].toIntOrNull() ?: 1 // Default to 1 for suffixes like "Alpha", "Beta", "RC"
-
- return numberParts to (suffixName to suffixNumber)
+ fun List.sortByVersionName(isDescend: Boolean = false): List {
+ return sortedWith { v1, v2 -> utils.compareVersionStrings(v1, v2) * if (isDescend) -1 else 1 }
}
}
@@ -803,8 +887,8 @@ pluginManagement {
notations.classpath.forEach { classpath(it) }
}
dependencies /* Apache Compress for utils.build.gradle module. */ {
- classpath("org.apache.commons:commons-compress:1.27.1")
- classpath("org.tukaani:xz:1.9")
+ classpath("org.apache.commons:commons-compress:1.28.0")
+ classpath("org.tukaani:xz:1.10")
}
}
@@ -816,7 +900,7 @@ pluginManagement {
gradle.taskGraph.whenReady {
if (allTasks.none { it.name == "clean" }) {
- console.printConcernedSystemPropertiesIfNeeded()
+ console.printConcernedPropertiesIfNeeded()
console.printVersionsOfIdeAndGradlePlugins()
}
}
@@ -824,6 +908,7 @@ pluginManagement {
gradle.extra.apply {
set("isCleanupPaddleOcr", config.isCleanupPaddleOcr)
set("isCleanupRapidOcr", config.isCleanupRapidOcr)
+ set("isHideConsoleInfoHintSuffix", config.isHideConsoleInfoHintSuffix)
}
gradle.beforeProject {
diff --git a/version.properties b/version.properties
index edbc28a8..bec3cdd1 100644
--- a/version.properties
+++ b/version.properties
@@ -1,13 +1,18 @@
-#Sun Aug 10 14:25:33 CST 2025
-BUILD_TIME=1754807133222
+#Fri Sep 05 15:31:16 CST 2025
+BUILD_TIME=1757057476985
COMPILE_SDK_VERSION=35
IMAGE_QUANT_CMAKE_VERSION=3.22.1
IMAGE_QUANT_NDK_VERSION=26.1.10909125
JAVA_VERSION=24
-JAVA_VERSION_MIN_RADICAL=0
-JAVA_VERSION_MIN_SUGGESTED=19
+JAVA_VERSION_MAX_SUPPORTED=24
+JAVA_VERSION_MIN_SUGGESTED=21
JAVA_VERSION_MIN_SUPPORTED=17
MIN_SDK_VERSION=24
+MIN_SUPPORTED_ANDROID_STUDIO_AGP_VERSION=8.4
+MIN_SUPPORTED_ANDROID_STUDIO_IDE_VERSION=2023.3
+MIN_SUPPORTED_GRADLE_VERSION=8.2
+MIN_SUPPORTED_INTELLIJ_IDEA_AGP_VERSION=8.2
+MIN_SUPPORTED_INTELLIJ_IDEA_IDE_VERSION=2023.3
PADDLE_OCR_CMAKE_VERSION=3.10.2
PADDLE_OCR_NDK_VERSION=21.1.6352462
PADDLE_OCR_OPENCV_VERSION=4.8.0
@@ -19,6 +24,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=35
TARGET_SDK_VERSION_INRT=29
-VERSION_BUILD=3341
+VERSION_BUILD=3355
VERSION_NAME=6.7.0 Alpha4
VSCODE_EXT_REQUIRED_VERSION=1.0.8