- You can turn on the Userscripts iOS Safari extension in Settings or
- Safari, then use the extension in Safari. Please refer to the "Usage"
- section in the
- README of this version.
-
+
-
-
CURRENT DIRECTORY:
-
+
{:catch error}
{error}
{/await}
-
-
diff --git a/src/app/_locales/en/messages.js b/src/app/_locales/en/messages.js
new file mode 100644
index 00000000..4cee3c24
--- /dev/null
+++ b/src/app/_locales/en/messages.js
@@ -0,0 +1,85 @@
+import nativeLoggerCaveat from "./native-logger-caveat.md?raw";
+import quickStartGuideMac from "./quick-start-guide-mac.md?raw";
+import quickStartGuideIos from "./quick-start-guide-ios.md?raw";
+
+import { marked } from "marked";
+
+/** @satisfies {Types.I18nMessages} */
+export const markdown = {
+ native_logger_caveat: {
+ message: await marked.parse(nativeLoggerCaveat),
+ },
+ quick_start_guide_mac: {
+ message: await marked.parse(quickStartGuideMac),
+ },
+ quick_start_guide_ios: {
+ message: await marked.parse(quickStartGuideIos),
+ },
+};
+
+/** @satisfies {Types.I18nMessages} */
+export const messages = {
+ enabled: {
+ message: "Enabled",
+ },
+ disabled: {
+ message: "Disabled",
+ },
+ unknown: {
+ message: "Unknown",
+ },
+ error: {
+ message: "Error",
+ },
+ button_ok: {
+ message: "OK",
+ },
+ button_dismiss: {
+ message: "Dismiss",
+ },
+ button_disable: {
+ message: "Disable",
+ },
+ safari_extension_status: {
+ message: "Safari Extension Status",
+ },
+ native_logger_enabled_title: {
+ message: "Native Logger Enabled",
+ },
+ quick_start_guide_title: {
+ message: "Quick Start Guide",
+ },
+ open_safari_settings: {
+ message: "Open Safari Settings",
+ },
+ open_safari_preferences: {
+ message: "Open Safari Preferences",
+ },
+ show_usage_guide: {
+ message: "Show Usage Guide",
+ },
+ change_directory: {
+ message: "Change Userscripts Directory",
+ },
+ current_directory: {
+ message: "CURRENT DIRECTORY:",
+ },
+ documentation: {
+ message: "Documentation",
+ },
+ discussions: {
+ message: "Discussions",
+ },
+ report_an_issue: {
+ message: "Report an Issue",
+ },
+ privacy_policy: {
+ message: "Privacy Policy",
+ },
+ export_log_files: {
+ message: "Export log files",
+ },
+ disable_logger: {
+ message: "Disable Logger",
+ },
+};
diff --git a/src/app/_locales/en/native-logger-caveat.md b/src/app/_locales/en/native-logger-caveat.md
new file mode 100644
index 00000000..f1ba6b62
--- /dev/null
+++ b/src/app/_locales/en/native-logger-caveat.md
@@ -0,0 +1,5 @@
+- The logger is for local debugging only and can be streamed through the macOS console while writing to a local file when enabled.
+- You can repeat the steps to reproduce the issue after enabling it, then export the log files and inspect them in the app.
+- There is no built-in upload function. If you need to submit it to developers, please manually attach the exported log files to your issue report.
+- To reduce energy consumption and disk reading and writing, please disbale the logger promptly after debugging.
+- If the log file exceeds $1, the logger will be automatically disbaled and the log files will be cleared.
diff --git a/src/app/_locales/en/quick-start-guide-ios.md b/src/app/_locales/en/quick-start-guide-ios.md
new file mode 100644
index 00000000..4bc2316b
--- /dev/null
+++ b/src/app/_locales/en/quick-start-guide-ios.md
@@ -0,0 +1,27 @@
+### Welcome, follow these two main steps to get the extension up and running:
+
+- **Open the app and set a directory**
+
+ - When you first launch the app, a local directory will be set by default.
+ - If needed, you can select a new directory to suit your preferences.
+ - This directory is used for saving and loading your user scripts.
+ - Click the current directory to jump to the default directory or the one you set.
+
+- **Enable the extension in Safari**
+
+ - Manage extensions from the Settings App (Settings > Safari > Extensions) or Safari App (`AA` button on iPhone, `extension-icon` on iPad, the same location where you open the extension's `popup` interface).
+ - For an optimal experience it's recommended that you "Always Allow" Userscripts for "All Websites", but you could also allow only the sites you want, but please don't forget your settings if your script doesn't work.
+
+### How to install and inject a user script and some things to note:
+
+- The mobile extension does not currently have a built-in script editor, but you could still write your own scripts and install them.
+- You could save files that extension with `.user.js` directly to the Userscripts directory.
+ - The script file must contain a valid metadata block to match the web pages and be displayed in the extension popup.
+- When you visit a `.user.js` URL in Safari, open the extension popup and you will see an installation prompt, or it will pop up automatically if you have enhanced prompts turned on.
+ - The URL should end with `.user.js` in `/PATH` part, not the `?QUERY` or `#HASH` parts, otherwise it will not be considered a valid user script URL by the extension.
+- When you enabled the extension and write the metadata correctly especially like `@match`, it will automatically complete the injection when you visit a matching web page.
+ - You could temporarily disable individual user scripts or all of them, just open the extension popup interface to toggle them.
+
+### That’s it, start improving your quality of life now!
+
+_Hey, don't forget to read our detailed documentation to learn more._
diff --git a/src/app/_locales/en/quick-start-guide-mac.md b/src/app/_locales/en/quick-start-guide-mac.md
new file mode 100644
index 00000000..c6ae6ef7
--- /dev/null
+++ b/src/app/_locales/en/quick-start-guide-mac.md
@@ -0,0 +1,27 @@
+### Welcome to this project, you will need two main steps to make the extension work:
+
+- **Open the app and set a directory**
+
+ - When you first launch the app, a local directory will be set by default.
+ - If needed, you can select a new directory to suit your preferences.
+ - This directory is used for saving and loading your user scripts.
+ - Click the current directory to jump to the default directory or the one you set.
+
+- **Enable the extension in Safari**
+
+ - Enable Userscripts in Safari > Settings... > Extensions list.
+ - For an optimal experience it's recommended that you "Always Allow" Userscripts for "All Websites", but you could also allow only the sites you want, but please don't forget your settings if your script doesn't work.
+
+### How to install and inject a user script and some things to note:
+
+- The preferred method is of course to create your own scripts, open the extension page and click on the plus sign in the editor to create a new JS, write code and save it.
+- You could also save files that extension with `.user.js` directly to the Userscripts directory.
+ - The script file must contain a valid metadata block to match the web pages and be displayed in the extension popup.
+- When you visit a `.user.js` URL in Safari, open the extension popup and you will see an installation prompt, or it will pop up automatically if you have enhanced prompts turned on.
+ - The URL should end with `.user.js` in `/PATH` part, not the `?QUERY` or `#HASH` parts, otherwise it will not be considered a valid user script URL by the extension.
+- When you enabled the extension and write the metadata correctly especially like `@match`, it will automatically complete the injection when you visit a matching web page.
+ - You could temporarily disable individual user scripts or all of them, just open the extension popup interface to toggle them.
+
+### That’s it, start improving your quality of life now!
+
+_Hey, don't forget to read our detailed documentation to learn more._
diff --git a/src/app/_locales/zh/messages.js b/src/app/_locales/zh/messages.js
new file mode 100644
index 00000000..e69057b0
--- /dev/null
+++ b/src/app/_locales/zh/messages.js
@@ -0,0 +1,85 @@
+import nativeLoggerCaveat from "./native-logger-caveat.md?raw";
+import quickStartGuideMac from "./quick-start-guide-mac.md?raw";
+import quickStartGuideIos from "./quick-start-guide-ios.md?raw";
+
+import { marked } from "marked";
+
+/** @satisfies {typeof import("../en/messages.js").markdown} */
+export const markdown = {
+ native_logger_caveat: {
+ message: await marked.parse(nativeLoggerCaveat),
+ },
+ quick_start_guide_mac: {
+ message: await marked.parse(quickStartGuideMac),
+ },
+ quick_start_guide_ios: {
+ message: await marked.parse(quickStartGuideIos),
+ },
+};
+
+/** @satisfies {typeof import("../en/messages.js").messages} */
+export const messages = {
+ enabled: {
+ message: "已启用",
+ },
+ disabled: {
+ message: "已停用",
+ },
+ unknown: {
+ message: "未知",
+ },
+ error: {
+ message: "错误",
+ },
+ button_ok: {
+ message: "确定",
+ },
+ button_dismiss: {
+ message: "关闭",
+ },
+ button_disable: {
+ message: "停用",
+ },
+ safari_extension_status: {
+ message: "Safari 扩展状态",
+ },
+ native_logger_enabled_title: {
+ message: "本地日志记录器已启用",
+ },
+ quick_start_guide_title: {
+ message: "快速入门指南",
+ },
+ open_safari_settings: {
+ message: "打开 Safari 设置",
+ },
+ open_safari_preferences: {
+ message: "打开 Safari 偏好",
+ },
+ show_usage_guide: {
+ message: "显示使用指南",
+ },
+ change_directory: {
+ message: "更改用户脚本目录",
+ },
+ current_directory: {
+ message: "当前目录:",
+ },
+ documentation: {
+ message: "详细文档",
+ },
+ discussions: {
+ message: "交流讨论",
+ },
+ report_an_issue: {
+ message: "报告问题",
+ },
+ privacy_policy: {
+ message: "隐私政策",
+ },
+ export_log_files: {
+ message: "导出日志文件",
+ },
+ disable_logger: {
+ message: "停用日志记录",
+ },
+};
diff --git a/src/app/_locales/zh/native-logger-caveat.md b/src/app/_locales/zh/native-logger-caveat.md
new file mode 100644
index 00000000..005723d0
--- /dev/null
+++ b/src/app/_locales/zh/native-logger-caveat.md
@@ -0,0 +1,5 @@
+- 日志记录器仅用于本地调试,开启期间可通过 macOS 控制台流式传输,同时写入本地文件。
+- 您可以在开启后重复复现问题的相关操作,然后在 App 中导出日志文件和检查它们。
+- 没有内建的上传功能,如需提交给开发者,请手动将导出的日志文件附加到您的问题报告中。
+- 为减少能耗和磁盘读写,请调试结束后及时关闭日志记录器。
+- 如日志文件超过 $1 将自动关闭日志记录器并清除日志。
diff --git a/src/app/_locales/zh/quick-start-guide-ios.md b/src/app/_locales/zh/quick-start-guide-ios.md
new file mode 100644
index 00000000..d24bda16
--- /dev/null
+++ b/src/app/_locales/zh/quick-start-guide-ios.md
@@ -0,0 +1,26 @@
+### 欢迎来到这个项目,您需要两个主要步骤来使扩展工作:
+
+- **打开 App 并设置目录**
+
+ - 该目录用于保存和加载您的用户脚本。
+ - 首次启动 App 时已为您设置默认本地目录。
+ - 点击当前目录可跳转到默认目录或您设置的目录。
+
+- **在 Safari 中启用扩展**
+
+ - 从 `设置` 应用(设置 > Safari > 扩展)或 `Safari` 应用(iPhone 上的“AA”按钮,iPad 上的“扩展图标”,也是您打开扩展的“弹出界面”的位置)管理扩展。
+ - 为了获得最佳体验,建议您“始终允许” Userscripts 为“所有网站”,但您也可以仅允许您想要的网站,但当您的脚本不起作用时,请不要忘记您的设置。
+
+### 那么,如何安装和注入用户脚本,以及一些注意事项?
+
+- 移动版扩展目前不包含内置的脚本编辑器,但您仍然可以编写您自己的脚本并安装它们。
+- 您可以直接保存扩展名为 `.user.js` 的文件到您上面设置的 Userscripts 目录中。
+ - 您的脚本文件必须包含有效的元数据块以匹配网站页面并正确显示在扩展的弹出界面中。
+- 当您在 Safari 中访问一个 `.user.js` 网址,然后打开扩展弹出界面,您将看到安装提示;如果您启用了增强提示,它会自动弹出。
+ - 请注意该网址的 `/路径` 部分应该以 `.user.js` 结尾,而不是 `?查询` 或 `#锚点` 部分,否则该网址将不会被视为有效的用户脚本。
+- 当您启用该扩展并正确编写元数据尤其是像 `@match` 后,当您访问匹配的网页时,它将自动完成注入。
+ - 您可以暂时禁用单个用户脚本或所有用户脚本,只需打开扩展弹出界面即可切换它们。
+
+### 就这样,现在就开始改善您的生活质量吧!
+
+_嘿,不要忘记阅读我们的详细文档以了解更多信息。_
diff --git a/src/app/_locales/zh/quick-start-guide-mac.md b/src/app/_locales/zh/quick-start-guide-mac.md
new file mode 100644
index 00000000..f9983ced
--- /dev/null
+++ b/src/app/_locales/zh/quick-start-guide-mac.md
@@ -0,0 +1,26 @@
+### 欢迎来到这个项目,您需要两个主要步骤来使扩展工作:
+
+- **打开 App 并设置目录**
+
+ - 该目录用于保存和加载您的用户脚本。
+ - 首次启动 App 时已为您设置默认本地目录。
+ - 点击当前目录可跳转到默认目录或您设置的目录。
+
+- **在 Safari 中启用扩展**
+
+ - 在 Safari > 设置... > 扩展列表中启用 Userscripts 条目。
+ - 为了获得最佳体验,建议您“始终允许” Userscripts 为“所有网站”,但您也可以仅允许您想要的网站,但当您的脚本不起作用时,请不要忘记您的设置。
+
+### 那么,如何安装和注入用户脚本,以及一些注意事项?
+
+- 首选的方法当然是撰写您自己的用户脚本,打开扩展页面点击加号创建新脚本,编辑和保存它。
+- 您还可以直接保存扩展名为 `.user.js` 的文件到您上面设置的 Userscripts 目录中。
+ - 您的脚本文件必须包含有效的元数据块以匹配网站页面并正确显示在扩展的弹出界面中。
+- 当您在 Safari 中访问一个 `.user.js` 网址,然后打开扩展弹出界面,您将看到安装提示;如果您启用了增强提示,它会自动弹出。
+ - 请注意该网址的 `/路径` 部分应该以 `.user.js` 结尾,而不是 `?查询` 或 `#锚点` 部分,否则该网址将不会被视为有效的用户脚本。
+- 当您启用该扩展并正确编写元数据尤其是像 `@match` 后,当您访问匹配的网页时,它将自动完成注入。
+ - 您可以暂时禁用单个用户脚本或所有用户脚本,只需打开扩展弹出界面即可切换它们。
+
+### 就这样,现在就开始改善您的生活质量吧!
+
+_嘿,不要忘记阅读我们的详细文档以了解更多信息。_
diff --git a/src/app/_locales/zh_Hant/messages.js b/src/app/_locales/zh_Hant/messages.js
new file mode 100644
index 00000000..e0fadede
--- /dev/null
+++ b/src/app/_locales/zh_Hant/messages.js
@@ -0,0 +1,85 @@
+import nativeLoggerCaveat from "./native-logger-caveat.md?raw";
+import quickStartGuideMac from "./quick-start-guide-mac.md?raw";
+import quickStartGuideIos from "./quick-start-guide-ios.md?raw";
+
+import { marked } from "marked";
+
+/** @satisfies {typeof import("../en/messages.js").markdown} */
+export const markdown = {
+ native_logger_caveat: {
+ message: await marked.parse(nativeLoggerCaveat),
+ },
+ quick_start_guide_mac: {
+ message: await marked.parse(quickStartGuideMac),
+ },
+ quick_start_guide_ios: {
+ message: await marked.parse(quickStartGuideIos),
+ },
+};
+
+/** @satisfies {typeof import("../en/messages.js").messages} */
+export const messages = {
+ enabled: {
+ message: "已啟用",
+ },
+ disabled: {
+ message: "已停用",
+ },
+ unknown: {
+ message: "未知",
+ },
+ error: {
+ message: "錯誤",
+ },
+ button_ok: {
+ message: "確定",
+ },
+ button_dismiss: {
+ message: "關閉",
+ },
+ button_disable: {
+ message: "停用",
+ },
+ safari_extension_status: {
+ message: "Safari 延伸功能狀態",
+ },
+ native_logger_enabled_title: {
+ message: "本地日誌記錄器已啟用",
+ },
+ quick_start_guide_title: {
+ message: "快速入門指南",
+ },
+ open_safari_settings: {
+ message: "開啟 Safari 設定",
+ },
+ open_safari_preferences: {
+ message: "開啟 Safari 偏好",
+ },
+ show_usage_guide: {
+ message: "顯示使用指南",
+ },
+ change_directory: {
+ message: "更改使用者腳本目錄",
+ },
+ current_directory: {
+ message: "當前目錄:",
+ },
+ documentation: {
+ message: "詳細文件",
+ },
+ discussions: {
+ message: "交流討論",
+ },
+ report_an_issue: {
+ message: "報告問題",
+ },
+ privacy_policy: {
+ message: "隱私政策",
+ },
+ export_log_files: {
+ message: "匯出日誌檔案",
+ },
+ disable_logger: {
+ message: "停用日誌記錄",
+ },
+};
diff --git a/src/app/_locales/zh_Hant/native-logger-caveat.md b/src/app/_locales/zh_Hant/native-logger-caveat.md
new file mode 100644
index 00000000..0c9b4baa
--- /dev/null
+++ b/src/app/_locales/zh_Hant/native-logger-caveat.md
@@ -0,0 +1,5 @@
+- 日誌記錄器僅用於本地除錯,開啟期間可透過 macOS 控制檯流式傳輸,同時寫入本地檔案。
+- 您可以在開啟後重複復現問題的相關操作,然後在 App 中匯出日誌檔案和檢查它們。
+- 沒有內建的上傳功能,如需提交給開發者,請手動將匯出的日誌檔案附加到您的問題報告中。
+- 為減少能耗和磁碟讀寫,請除錯結束後及時關閉日誌記錄器。
+- 如日誌檔案超過 $1 將自動關閉日誌記錄器並清除日誌。
diff --git a/src/app/_locales/zh_Hant/quick-start-guide-ios.md b/src/app/_locales/zh_Hant/quick-start-guide-ios.md
new file mode 100644
index 00000000..0d7f5e51
--- /dev/null
+++ b/src/app/_locales/zh_Hant/quick-start-guide-ios.md
@@ -0,0 +1,26 @@
+### 歡迎來到這個專案,您需要兩個主要步驟來使延伸功能工作:
+
+- **開啟 App 並設定目錄**
+
+ - 該目錄用於儲存和載入您的使用者腳本。
+ - 首次啟動 App 時已為您設定預設本地目錄。
+ - 點選當前目錄可跳轉到預設目錄或您設定的目錄。
+
+- **在 Safari 中啟用延伸功能**
+
+ - 從 `設定` 應用(設定 > Safari > 延伸功能)或 `Safari` 應用(iPhone 上的“AA”按鈕,iPad 上的“延伸功能圖示”,也是您開啟延伸功能的“彈出介面”的位置)管理延伸功能。
+ - 為了獲得最佳體驗,建議您“始終允許” Userscripts 為“所有網站”,但您也可以僅允許您想要的網站,但當您的腳本不起作用時,請不要忘記您的設定。
+
+### 那麼,如何安裝和注入使用者腳本,以及一些注意事項?
+
+- 移動版延伸功能目前不包含內建的腳本編輯器,但您仍然可以編寫您自己的腳本並安裝它們。
+- 您可以直接儲存副檔名為 `.user.js` 的檔案到您上面設定的 Userscripts 目錄中。
+ - 您的腳本檔案必須包含有效的元資料塊以匹配網站頁面並正確顯示在延伸功能的彈出介面中。
+- 當您在 Safari 中訪問一個 `.user.js` 網址,然後開啟延伸功能彈出介面,您將看到安裝提示;如果您啟用了增強提示,它會自動彈出。
+ - 請注意該網址的 `/路徑` 部分應該以 `.user.js` 結尾,而不是 `?查詢` 或 `#錨點` 部分,否則該網址將不會被視為有效的使用者腳本。
+- 當您啟用該延伸功能並正確編寫元資料尤其是像 `@match` 後,當您訪問匹配的網頁時,它將自動完成注入。
+ - 您可以暫時禁用單個使用者腳本或所有使用者腳本,只需開啟延伸功能彈出介面即可切換它們。
+
+### 就這樣,現在就開始改善您的生活質量吧!
+
+_嘿,不要忘記閱讀我們的詳細文件以瞭解更多資訊。_
diff --git a/src/app/_locales/zh_Hant/quick-start-guide-mac.md b/src/app/_locales/zh_Hant/quick-start-guide-mac.md
new file mode 100644
index 00000000..3331a109
--- /dev/null
+++ b/src/app/_locales/zh_Hant/quick-start-guide-mac.md
@@ -0,0 +1,26 @@
+### 歡迎來到這個專案,您需要兩個主要步驟來使延伸功能工作:
+
+- **開啟 App 並設定目錄**
+
+ - 該目錄用於儲存和載入您的使用者腳本。
+ - 首次啟動 App 時已為您設定預設本地目錄。
+ - 點選當前目錄可跳轉到預設目錄或您設定的目錄。
+
+- **在 Safari 中啟用延伸功能**
+
+ - 在 Safari > 設定... > 延伸功能列表中啟用 Userscripts 條目。
+ - 為了獲得最佳體驗,建議您“始終允許” Userscripts 為“所有網站”,但您也可以僅允許您想要的網站,但當您的腳本不起作用時,請不要忘記您的設定。
+
+### 那麼,如何安裝和注入使用者腳本,以及一些注意事項?
+
+- 首選的方法當然是撰寫您自己的使用者腳本,開啟延伸功能頁面點選加號建立新腳本,編輯和儲存它。
+- 您還可以直接儲存副檔名為 `.user.js` 的檔案到您上面設定的 Userscripts 目錄中。
+ - 您的腳本檔案必須包含有效的元資料塊以匹配網站頁面並正確顯示在延伸功能的彈出介面中。
+- 當您在 Safari 中訪問一個 `.user.js` 網址,然後開啟延伸功能彈出介面,您將看到安裝提示;如果您啟用了增強提示,它會自動彈出。
+ - 請注意該網址的 `/路徑` 部分應該以 `.user.js` 結尾,而不是 `?查詢` 或 `#錨點` 部分,否則該網址將不會被視為有效的使用者腳本。
+- 當您啟用該延伸功能並正確編寫元資料尤其是像 `@match` 後,當您訪問匹配的網頁時,它將自動完成注入。
+ - 您可以暫時禁用單個使用者腳本或所有使用者腳本,只需開啟延伸功能彈出介面即可切換它們。
+
+### 就這樣,現在就開始改善您的生活質量吧!
+
+_嘿,不要忘記閱讀我們的詳細文件以瞭解更多資訊。_
diff --git a/src/app/app.css b/src/app/app.css
index a5d041a3..40c7cfa2 100644
--- a/src/app/app.css
+++ b/src/app/app.css
@@ -1,28 +1,20 @@
html {
- font-size: 100%;
- height: 100vh;
- overflow: hidden;
+ height: auto;
+ overflow: visible;
+ overscroll-behavior: none;
}
body {
- background-color: var(--color-bg-secondary);
+ background-color: var(--color-bg-primary);
color: var(--text-color-primary);
- font: var(--text-medium);
- height: 100%;
+ font: var(--text-default);
letter-spacing: var(--letter-spacing-medium);
- position: relative;
text-rendering: optimizelegibility;
-webkit-font-smoothing: antialiased;
}
/* ios */
@supports (-webkit-touch-callout: none) {
- html {
- height: auto;
- overflow: visible;
- overscroll-behavior: none;
- }
-
/**
* Dynamic Type
* https://support.apple.com/102453
@@ -45,25 +37,23 @@ body {
}
}
-@media screen and (height <= 400px) {
- html {
- font-size: 80%;
- }
-
- p {
- font: var(--text-large);
- letter-spacing: var(--letter-spacing-large);
- }
-}
-
-@media screen and (height >= 700px) and (width >= 600px) {
- html {
- font-size: 150%;
- }
+#app {
+ flex-direction: column;
}
-#app {
- height: 100%;
+address,
+article,
+aside,
+button,
+div,
+footer,
+header,
+hgroup,
+main,
+nav,
+search,
+section {
+ display: flex;
}
button {
@@ -73,9 +63,59 @@ button {
user-select: none;
}
+button:disabled {
+ opacity: var(--opacity-disabled);
+ pointer-events: none;
+}
+
+a,
.link {
background: none;
color: var(--color-blue);
cursor: pointer;
text-decoration: underline;
}
+
+.truncate {
+ flex-grow: 1;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.flexible_space {
+ flex-grow: 1;
+}
+
+x-markdown {
+ display: flex;
+ flex-direction: column;
+ overflow: auto;
+ text-align: left;
+ gap: var(--gap);
+ padding: 0 3rem;
+ --gap: 0.75rem;
+}
+
+@media (width < 500px) {
+ x-markdown {
+ padding: 0 1.5rem;
+ }
+}
+
+x-markdown :is(h1, h2, h3, h4, h5, h6) {
+ padding: 0;
+ margin: 0;
+}
+
+x-markdown ul {
+ display: flex;
+ flex-direction: column;
+ gap: var(--gap);
+ padding-left: 1.5rem;
+}
+
+x-markdown > ul ul {
+ margin-top: var(--gap);
+}
diff --git a/src/app/global.d.ts b/src/app/global.d.ts
index 6a83a4d5..b3f9487f 100644
--- a/src/app/global.d.ts
+++ b/src/app/global.d.ts
@@ -7,6 +7,8 @@ declare global {
interface Window {
webapp: {
updateDirectory: (directory: string) => void;
+ updateExtStatus: (extStatus: ExtensionStatus) => void;
+ switchLogger: (enableLogger: boolean, promptLogger: boolean) => void;
};
webkit: {
messageHandlers: {
@@ -20,10 +22,4 @@ declare global {
}
}
-type MessageBody = "INIT" | "CHANGE_DIRECTORY" | "OPEN_DIRECTORY";
-
-type MessageReply = T extends "INIT"
- ? { build: string; version: string; directory: string }
- : void;
-
export {};
diff --git a/src/app/i18n.js b/src/app/i18n.js
new file mode 100644
index 00000000..389042d8
--- /dev/null
+++ b/src/app/i18n.js
@@ -0,0 +1,58 @@
+/**
+ * @typedef {typeof import("./_locales/en/messages.js").messages} MessagesT
+ * @typedef {typeof import("./_locales/en/messages.js").markdown} MarkdownT
+ */
+
+/**
+ * @param {Types.I18nMessages} messages
+ * @param {string} messageName
+ * @param {string | string[]} substitutions
+ * @returns {string}
+ */
+function getLangFrom(messages, messageName, substitutions = undefined) {
+ if (!(messageName in messages)) {
+ console.warn(`i18n - "${messageName}" not found`, messages);
+ return "";
+ }
+ let text = messages[messageName].message;
+ // handle substitutions
+ if (typeof substitutions === "string") {
+ text = text.replace("$1", substitutions);
+ } else if (Array.isArray(substitutions)) {
+ for (let i = 0; i < substitutions.length; i++) {
+ text = text.replace(`$${i + 1}`, substitutions[i]);
+ }
+ }
+ if (import.meta.env.MODE === "development") {
+ console.debug("i18n", messages[messageName].message, text, substitutions);
+ }
+ return text;
+}
+
+export async function i18nInit() {
+ const languages = [navigator.language.replace("-", "_")];
+ if (["zh-HK", "zh-MO", "zh-TW"].includes(navigator.language)) {
+ languages.unshift("zh_Hant");
+ }
+ languages.push(navigator.language.split("-")[0]);
+ languages.push("en"); // fallback
+ if (import.meta.env.MODE === "development") {
+ // languages.unshift("en"); // DEBUG
+ }
+ for (const language of languages) {
+ try {
+ /** @type {{messages: MessagesT, markdown: MarkdownT}} */
+ const module = await import(`./_locales/${language}/messages.js`);
+ const { messages, markdown } = module;
+ return {
+ /** @type {Types.GetLang} */
+ gl: (n, s) => getLangFrom(messages, n, s),
+ /** @type {Types.GetLang} */
+ md: (n, s) => getLangFrom(markdown, n, s),
+ };
+ } catch (error) {
+ console.debug("Will fall back to `en`", error);
+ }
+ }
+ throw Error("I18n initialization failed");
+}
diff --git a/src/app/img/icon.png b/src/app/img/icon.png
deleted file mode 100644
index 9fe96182..00000000
Binary files a/src/app/img/icon.png and /dev/null differ
diff --git a/src/app/img/logo.svg b/src/app/img/logo.svg
deleted file mode 100644
index 9bf95127..00000000
--- a/src/app/img/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/app/jsconfig.json b/src/app/jsconfig.json
index 899038cd..95a69da9 100644
--- a/src/app/jsconfig.json
+++ b/src/app/jsconfig.json
@@ -20,7 +20,11 @@
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
- "sourceMap": true
+ "sourceMap": true,
+
+ "paths": {
+ "@shared/*": ["../shared/*"]
+ }
},
"include": ["**/*.d.ts", "**/*.js", "**/*.svelte"]
}
diff --git a/src/app/main.js b/src/app/main.js
index 70c8f3a5..8a28fe48 100644
--- a/src/app/main.js
+++ b/src/app/main.js
@@ -1,9 +1,42 @@
import "./reset.css";
-import "./variables.css";
+import "@shared/variables.css";
import "./app.css";
import { mount } from "svelte";
import App from "./App.svelte";
+if (import.meta.env.MODE === "development") {
+ // Simulation in non-WkWebView dev environment
+ if (import.meta.env.SAFARI_PLATFORM === undefined) {
+ console.warn("Simulation webkit...");
+ window.webkit = {
+ messageHandlers: {
+ controller: {
+ postMessage: async (message) => {
+ switch (message) {
+ case "INIT":
+ return {
+ build: "2",
+ directory: "Userscripts App Documents",
+ enableLogger: true,
+ extStatus: "unknown",
+ firstRunTime: 1,
+ maxLogFileSize: 500_000_000,
+ platform: "mac",
+ promptLogger: true,
+ useSettingsInsteadOfPreferences: true,
+ version: "2.0.0",
+ };
+ default:
+ console.debug("Simulation.webkit.messageHandler:", message);
+ break;
+ }
+ },
+ },
+ },
+ };
+ }
+}
+
const app = mount(App, { target: document.getElementById("app") });
export default app;
diff --git a/src/app/reset.css b/src/app/reset.css
index 5748075f..0b8335ad 100644
--- a/src/app/reset.css
+++ b/src/app/reset.css
@@ -10,9 +10,7 @@ p {
}
ul {
- list-style: none;
margin: 0;
- padding: 0;
}
button,
diff --git a/src/app/types.d.ts b/src/app/types.d.ts
new file mode 100644
index 00000000..f282812b
--- /dev/null
+++ b/src/app/types.d.ts
@@ -0,0 +1,43 @@
+declare namespace Types {
+ /** @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n/Locale-Specific_Message_reference} */
+ type I18nMessages = {
+ [x: string]: {
+ message: string;
+ description?: string;
+ placeholders?: Object;
+ };
+ };
+
+ type GetLang = (
+ messageName: T,
+ substitutions?: string | string[],
+ ) => string;
+
+ type SystemPlatform = "mac" | "ios";
+
+ type ExtensionStatus = "unknown" | "disabled" | "enabled" | "error";
+
+ type MessageBody =
+ | "INIT"
+ | "CHANGE_DIRECTORY"
+ | "OPEN_DIRECTORY"
+ | "SHOW_PREFERENCES"
+ | "EXPORT_LOG_FILES"
+ | "DISABLE_LOGGER"
+ | "DISMISS_LOGGER_PROMPT";
+
+ type MessageReply = T extends "INIT"
+ ? {
+ build: string;
+ version: string;
+ platform: SystemPlatform;
+ directory: string;
+ extStatus: ExtensionStatus;
+ useSettingsInsteadOfPreferences: boolean;
+ enableLogger: boolean;
+ promptLogger: boolean;
+ maxLogFileSize: number;
+ firstRunTime: number;
+ }
+ : void;
+}
diff --git a/src/app/variables.css b/src/app/variables.css
deleted file mode 100644
index 04ab9458..00000000
--- a/src/app/variables.css
+++ /dev/null
@@ -1,51 +0,0 @@
-:root {
- --border-radius: 0.188rem;
- --box-shadow: 0 0.5rem 1rem 0 rgb(0 0 0 / 0.25);
- --color-bg-primary: #323639;
- --color-bg-secondary: #2f3337;
- --color-script-highlighted: #364049; /* rgba(116, 178, 235, 0.1); */
- --color-black: #1d2023;
- --color-blue: #74b1eb;
- --color-green: #60f36c;
- --color-grey: rgb(255 255 255 / 0.15);
- --color-red: #ff453a;
- --color-yellow: #e4f360;
- --letter-spacing-large: -0.031rem;
- --letter-spacing-default: -0.029rem;
- --letter-spacing-medium: -0.018rem;
- --letter-spacing-small: -0.008rem;
- --opacity-disabled: 0.3;
- --text-color-primary: rgb(255 255 255);
- --text-color-secondary: rgb(255 255 255 / 0.65);
- --text-color-disabled: rgb(255 255 255 / 0.4);
- --font-family: -apple-system, "Helvetica Neue", "Helvetica", sans-serif;
- --text-default: 1rem/1.5rem var(--font-family);
- --text-large: 1.25rem/1.5rem var(--font-family);
- --text-medium: 0.875rem/1.313rem var(--font-family);
- --text-small: 0.719rem/1rem var(--font-family);
-
- /* editor variables */
- --editor-font: monaco, monospace;
- --editor-font-size: 14px;
- --editor-line-height: 24px;
- --editor-invisible: rgb(255 255 255 / 0.15);
- --editor-active-line: var(--color-bg-secondary);
- --editor-selected-bg: rgb(116 178 235 / 0.35);
- --editor-matched-highlight: rgb(116 178 235 / 0.2);
- --editor-search-highlight: rgb(255 166 0 / 0.3);
- --editor-number: #77e26a;
- --editor-comment: rgb(255 255 255 / 0.35);
- --editor-def: #efc371;
- --editor-default: #cdcfd1;
- --editor-keyword: #96c3ed;
- --editor-atom: #59ebf5;
- --editor-operator: #8c99a7;
- --editor-property: #e86c8a;
- --editor-string: #f5eea2;
- --editor-string-2: #cdabff;
- --editor-error: var(--color-red);
- --editor-cursor: #e3e7eb;
- --editor-matching-bracket-color: #fff;
- --editor-matching-bracket-border: var(--editor-number);
- --editor-non-matching-bracket: var(--editor-error);
-}
diff --git a/src/ext/action-popup/App.svelte b/src/ext/action-popup/App.svelte
index 7731e81f..6d593530 100644
--- a/src/ext/action-popup/App.svelte
+++ b/src/ext/action-popup/App.svelte
@@ -1,20 +1,20 @@
-{#if $state.includes("init")}
+{#if $v4state.includes("init")}