diff --git a/.vscode/settings.json b/.vscode/settings.json index f86b8368..24436b8d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,15 @@ }, "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", + "[yaml]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[svelte]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[markdown]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, // https://github.com/microsoft/vscode-eslint#settings-options "eslint.validate": ["javascript", "svelte"], "eslint.experimental.useFlatConfig": true, diff --git a/README.md b/README.md index 5864d9b8..a9051730 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ After installing Userscripts on macOS, you **do not** need to select a userscrip - **Show Toolbar Count** - displays a badge on the toolbar icon with a number that represents how many enabled scripts match the url for the page you are on - **Save Location** - where your file are currently located and being saved to (click the blue text to open location) - **Change Save Location (cogs icon)** - this button, located directly to the right of the save location, is a shortcut for opening the host app, which will allow you to change the save location -- **Global Blacklist** - this input accepts a comma separated list of [`@match` patterns](https://developer.chrome.com/docs/extensions/mv3/match_patterns/), a page url that matches against a pattern in this list will be ignored for script injection +- **Global Blacklist** - this input accepts a comma separated list of `@match` patterns ([Match pattern structure](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#match_pattern_structure)), a page url that matches against a pattern in this list will be ignored for script injection ### Popup: @@ -125,7 +125,7 @@ Userscripts Safari currently supports the following userscript metadata: - `@name` - This will be the name that displays in the sidebar and be used as the filename - you can _not_ use the same name for multiple files of the same type - `@description`- Use this to describe what your userscript does - this will be displayed in the sidebar - there is a setting to hide descriptions - `@icon` - This doesn't have a function with this userscript manager, but the **first value** provided in the metadata will be accessible in the `GM_/GM.info` object -- `@match` - Domain match patterns - you can use several instances of this field if you'd like multiple domain matches - view [this article for more information on constructing patterns](https://developer.chrome.com/extensions/match_patterns) +- `@match` - Domain match patterns - you can use several instances of this field if you'd like multiple domain matches - please refer to: [Match pattern structure](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns#match_pattern_structure) - **Note:** this extension only supports `http/s` - `@exclude-match` - Domain patterns where you do _not_ want the script to run - `@include` - Used to match against urls for injection, globs and regular expressions are allowed, [read more here](https://wiki.greasespot.net/Include_and_exclude_rules) @@ -325,9 +325,7 @@ The quickest and easiest way to support the project is by [leaving a positive re The second best way to help out is to sign up to beta test new versions of the app. Since this extension values your privacy, and **does not collect any data from users**, it is difficult to gauge how the extension is being used. By signing up to be a beta tester it not only allows you to test upcoming features, but also gives me the opportunity to elicit direct feedback from real users. -**[iOS Beta Sign Up Form](https://forms.gle/QB46uYQHVyCxULue9)** - -**[macOS Beta Sign Up Form](https://forms.gle/cUDtKg1ip4Vc9Xhc7)** +**Please join and test the corresponding beta version in [releases](https://github.com/quoid/userscripts/releases) via the TestFlight public link.** ## Privacy Policy diff --git a/public/ext/safari-15/manifest.json b/public/ext/safari-15/manifest.json index 99c503ee..1b4e52db 100644 --- a/public/ext/safari-15/manifest.json +++ b/public/ext/safari-15/manifest.json @@ -22,6 +22,9 @@ "32": "images/toolbar-icon-32.png" } }, + "options_ui": { + "page": "dist/entry-ext-extension-page.html#state=settings" + }, "content_scripts": [ { "js": ["dist/content-scripts/userscripts.js"], diff --git a/public/ext/safari-16.4/manifest.json b/public/ext/safari-16.4/manifest.json index 7d2c00da..ab445895 100644 --- a/public/ext/safari-16.4/manifest.json +++ b/public/ext/safari-16.4/manifest.json @@ -19,6 +19,9 @@ "default_popup": "dist/entry-ext-action-popup.html", "default_icon": "images/action.svg" }, + "options_ui": { + "page": "dist/entry-ext-extension-page.html#state=settings" + }, "content_scripts": [ { "js": ["dist/content-scripts/userscripts.js"], diff --git a/public/ext/safari-dev/manifest-ios.json b/public/ext/safari-dev/manifest-ios.json index 2cb0308a..e1cac050 100644 --- a/public/ext/safari-dev/manifest-ios.json +++ b/public/ext/safari-dev/manifest-ios.json @@ -20,7 +20,7 @@ "default_icon": "images/action.svg" }, "options_ui": { - "page": "dist/entry-ext-extension-page.html#settings" + "page": "dist/entry-ext-extension-page.html#state=settings" }, "content_scripts": [ { diff --git a/public/ext/safari-dev/manifest-mac.json b/public/ext/safari-dev/manifest-mac.json index 046f8239..e469aa66 100644 --- a/public/ext/safari-dev/manifest-mac.json +++ b/public/ext/safari-dev/manifest-mac.json @@ -20,7 +20,7 @@ "default_icon": "images/action.svg" }, "options_ui": { - "page": "dist/entry-ext-extension-page.html#settings" + "page": "dist/entry-ext-extension-page.html#state=settings" }, "content_scripts": [ { diff --git a/public/ext/shared/_locales/en/messages.json b/public/ext/shared/_locales/en/messages.json index e840a3a2..8ef4fea6 100644 --- a/public/ext/shared/_locales/en/messages.json +++ b/public/ext/shared/_locales/en/messages.json @@ -6,5 +6,239 @@ "extension_description": { "message": "Save and run javascript for the web pages you visit", "description": "Description of what the extension does." + }, + "settings": { + "message": "Settings" + }, + "settings_section_editor": { + "message": "Editor Settings" + }, + "settings_section_general": { + "message": "General Settings" + }, + "settings_section_native": { + "message": "Native Settings" + }, + "settings_section_tools": { + "message": "Tools" + }, + "settings_section_about": { + "message": "About" + }, + "settings_editor_auto_hint": { + "message": "Auto Hint" + }, + "settings_editor_auto_hint_desc": { + "message": "Automatically shows completion hints while editing" + }, + "settings_editor_close_brackets": { + "message": "Auto Close Brackets" + }, + "settings_editor_close_brackets_desc": { + "message": "Toggles on/off auto closing of brackets in the editor, this affects the following characters: () [] {} \"\" ''" + }, + "settings_editor_javascript_lint": { + "message": "JavaScript Linter" + }, + "settings_editor_javascript_lint_desc": { + "message": "Toggles the basic javascript linting within the editor" + }, + "settings_editor_list_descriptions": { + "message": "Sidebar Item Descriptions" + }, + "settings_editor_list_descriptions_desc": { + "message": "Show or hides the item descriptions in the sidebar" + }, + "settings_editor_list_sort": { + "message": "Sidebar Item Sort Order" + }, + "settings_editor_list_sort_desc": { + "message": "Display order of items in the sidebar" + }, + "settings_editor_list_sort_nameAsc": { + "message": "Scripts Name: Asc" + }, + "settings_editor_list_sort_nameDesc": { + "message": "Scripts Name: Desc" + }, + "settings_editor_list_sort_lastModifiedAsc": { + "message": "Last Modified: Asc" + }, + "settings_editor_list_sort_lastModifiedDesc": { + "message": "Last Modified: Desc" + }, + "settings_editor_show_whitespace": { + "message": "Show Whitespace Characters" + }, + "settings_editor_show_whitespace_desc": { + "message": "Toggles the display of invisible characters in the editor" + }, + "settings_editor_tab_size": { + "message": "Tab Size" + }, + "settings_editor_tab_size_desc": { + "message": "Choose the number of spaces a tab is equal to when rendering code" + }, + "settings_global_active": { + "message": "Enable Injection" + }, + "settings_global_active_desc": { + "message": "Toggle on/off script injection for the pages you visit" + }, + "settings_global_exclude_match": { + "message": "Global Exclude Match patterns" + }, + "settings_global_exclude_match_desc": { + "message": "This input accepts a whitespace (spaces, newlines etc.) separated list of @match patterns, a page url that matches against a pattern in this list will be ignored for script injection" + }, + "settings_global_exclude_match_done": { + "message": "Done" + }, + "settings_global_exclude_match_saving": { + "message": "Saving..." + }, + "settings_global_exclude_match_placeholder": { + "message": "list of @match patterns, for example: \n*://*/*foo.bar\n*://*/*foo.bar?*\n*://*.example.net/*\nhttps://example.net/*/foo/*/\nhttps://*.example.net/a/b/c/?foo=/" + }, + "settings_global_exclude_match_refer": { + "message": "Please refer to:" + }, + "settings_scripts_update_automation": { + "message": "Scripts Updates Automatically" + }, + "settings_scripts_update_automation_desc": { + "message": "Script silently auto-updates in the background, which is dangerous and may introduce unconfirmed malicious code" + }, + "settings_scripts_update_check_interval": { + "message": "Scripts Update Check Interval" + }, + "settings_scripts_update_check_interval_desc": { + "message": "Disable or set user scripts update check interval (days)" + }, + "settings_scripts_update_check_interval_0": { + "message": "Never" + }, + "settings_scripts_update_check_lasttime": { + "message": "Scripts Update Check Lasttime" + }, + "settings_scripts_update_check_lasttime_desc": { + "message": "The lasttime for script update check in background" + }, + "settings_settings_sync": { + "message": "Sync Settings" + }, + "settings_settings_sync_desc": { + "message": "Sync settings across devices" + }, + "settings_toolbar_badge_count": { + "message": "Show Toolbar Count Badge" + }, + "settings_toolbar_badge_count_desc": { + "message": "Displays a badge on the toolbar icon with a number that represents how many enabled scripts match the url for the page you are on" + }, + "settings_scripts_directory": { + "message": "Save Location" + }, + "settings_scripts_directory_desc": { + "message": "Path to the folder where user scripts are stored" + }, + "settings_set_scripts_directory": { + "message": "Change save location" + }, + "settings_section_tools_import": { + "message": "Import" + }, + "settings_section_tools_export": { + "message": "Export" + }, + "settings_section_tools_reset": { + "message": "Reset" + }, + "settings_section_tools_goback": { + "message": "Go Back" + }, + "settings_section_tools_reset_all": { + "message": "Reset All Settings" + }, + "settings_section_tools_reset_single": { + "message": "Reset" + }, + "settings_section_tools_reset_section": { + "message": "Reset Section" + }, + "settings_scripts_tools_desc": { + "message": "These tools can help you import and export \"settings data\". Reset single, section or all settings." + }, + "settings_about_text1": { + "message": "Get more information about this extension by visiting the open source project:" + }, + "settings_about_text2": { + "message": "If you enjoy using this extension, please consider leaving a review on the App Store or sign up to beta test new versions:" + }, + "settings_about_button_repo": { + "message": "Code repository" + }, + "settings_about_button_docs": { + "message": "Documentation" + }, + "settings_about_button_issues": { + "message": "Report bugs" + }, + "settings_about_button_store": { + "message": "Open in the App Store" + }, + "settings_about_button_beta": { + "message": "Sign up for beta testing" + }, + "utils_check_match_patterns_0": { + "message": "The match pattern will match all URLs" + }, + "utils_check_match_patterns_1": { + "message": "The scheme component should one of *, https, http" + }, + "utils_check_match_patterns_2": { + "message": "The scheme and host should separated by `://`" + }, + "utils_check_match_patterns_3": { + "message": "The match pattern has no path component" + }, + "utils_check_match_patterns_4": { + "message": "The `*.` should followed by part of the hostname" + }, + "utils_check_match_patterns_5": { + "message": "The host component length should be 1-255" + }, + "utils_check_match_patterns_6": { + "message": "The `*` in host component should be independent or `*.` at the start" + }, + "utils_check_match_patterns_7": { + "message": "The host component contains empty label(s)" + }, + "utils_check_match_patterns_8": { + "message": "The hostname label cannot start or end with `-` character" + }, + "utils_check_match_patterns_9": { + "message": "The maximum length of the hostname label cannot exceed 63" + }, + "utils_check_match_patterns_10": { + "message": "The host component contains invalid character(s): $1" + }, + "utils_check_match_patterns_11": { + "message": "The path component contains invalid character(s): $1" + }, + "msg_invalid_match_pattern": { + "message": "Invalid match pattern" + }, + "msg_invalid_backup_file": { + "message": "Not a valid backup file" + }, + "msg_backup_import_finish": { + "message": "Import completed! ✅" + }, + "msg_backup_import_failed": { + "message": "Import failed, please check the error log in the console" + }, + "msg_settings_reset_finish": { + "message": "Reset all settings completed! ✅" } } diff --git a/public/ext/shared/_locales/zh/messages.json b/public/ext/shared/_locales/zh/messages.json new file mode 100644 index 00000000..d9fbaff9 --- /dev/null +++ b/public/ext/shared/_locales/zh/messages.json @@ -0,0 +1,240 @@ +{ + "extension_description": { + "message": "用户脚本和样式管理器", + "description": "Description of what the extension does." + }, + "settings": { + "message": "设置" + }, + "settings_section_editor": { + "message": "编辑器设置" + }, + "settings_section_general": { + "message": "通用设置" + }, + "settings_section_native": { + "message": "本地设置" + }, + "settings_section_tools": { + "message": "工具" + }, + "settings_section_about": { + "message": "关于" + }, + "settings_editor_auto_hint": { + "message": "自动提示(Hint)" + }, + "settings_editor_auto_hint_desc": { + "message": "编辑时自动显示完成提示" + }, + "settings_editor_close_brackets": { + "message": "自动关闭括号" + }, + "settings_editor_close_brackets_desc": { + "message": "在编辑器中启用自动关闭括号,这会影响以下字符:() [] {} \"\" ''" + }, + "settings_editor_javascript_lint": { + "message": "JavaScript Linter" + }, + "settings_editor_javascript_lint_desc": { + "message": "在编辑器中启用基本的 JavaScript Linting(代码检查)" + }, + "settings_editor_list_descriptions": { + "message": "侧栏项目描述" + }, + "settings_editor_list_descriptions_desc": { + "message": "显示或隐藏侧边栏中项目的描述" + }, + "settings_editor_list_sort": { + "message": "侧栏项目排序" + }, + "settings_editor_list_sort_desc": { + "message": "侧边栏中项目的显示顺序" + }, + "settings_editor_list_sort_nameAsc": { + "message": "项目名称: 升序" + }, + "settings_editor_list_sort_nameDesc": { + "message": "项目名称: 降序" + }, + "settings_editor_list_sort_lastModifiedAsc": { + "message": "最后修改: 升序" + }, + "settings_editor_list_sort_lastModifiedDesc": { + "message": "最后修改: 降序" + }, + "settings_editor_show_whitespace": { + "message": "显示空白字符" + }, + "settings_editor_show_whitespace_desc": { + "message": "切换编辑器中不可见字符的显示" + }, + "settings_editor_tab_size": { + "message": "制表符大小" + }, + "settings_editor_tab_size_desc": { + "message": "选择渲染代码时制表符等于的空格数" + }, + "settings_global_active": { + "message": "启用注入" + }, + "settings_global_active_desc": { + "message": "全局脚本注入的开启或关闭" + }, + "settings_global_exclude_match": { + "message": "全局排除匹配模式列表" + }, + "settings_global_exclude_match_desc": { + "message": "此输入接受以空白符(空格、换行等)分隔的 @match 模式列表,与此列表中的模式匹配的页面 URL 将在脚本注入时被忽略" + }, + "settings_global_exclude_match_done": { + "message": "完成" + }, + "settings_global_exclude_match_saving": { + "message": "保存中..." + }, + "settings_global_exclude_match_placeholder": { + "message": "@match 模式列表,例如:\n*://*/*foo.bar\n*://*/*foo.bar?*\n*://*.example.net/*\nhttps://example.net/*/foo/*/\nhttps://*.example.net/a/b/c/?foo=/" + }, + "settings_global_exclude_match_refer": { + "message": "匹配模式结构请参考:" + }, + "settings_scripts_update_automation": { + "message": "自动更新脚本" + }, + "settings_scripts_update_automation_desc": { + "message": "脚本在后台静默自动更新,这是危险的,可能引入未经确认的恶意代码" + }, + "settings_scripts_update_check_interval": { + "message": "脚本更新检查间隔" + }, + "settings_scripts_update_check_interval_desc": { + "message": "禁用或设置用户脚本更新检查间隔(天)" + }, + "settings_scripts_update_check_interval_0": { + "message": "从不" + }, + "settings_scripts_update_check_lasttime": { + "message": "脚本更新上次检查时间" + }, + "settings_scripts_update_check_lasttime_desc": { + "message": "后台脚本更新检查上次时间" + }, + "settings_settings_sync": { + "message": "同步设置" + }, + "settings_settings_sync_desc": { + "message": "跨设备同步设置" + }, + "settings_toolbar_badge_count": { + "message": "工具栏图标显示计数徽章" + }, + "settings_toolbar_badge_count_desc": { + "message": "在工具栏图标上显示一个徽章,其中的数字代表有多少个已启用的脚本与您所在页面的 URL 匹配" + }, + "settings_scripts_directory": { + "message": "保存位置" + }, + "settings_scripts_directory_desc": { + "message": "存储用户脚本的文件夹路径" + }, + "settings_set_scripts_directory": { + "message": "更改保存位置" + }, + "settings_section_tools_import": { + "message": "导入" + }, + "settings_section_tools_export": { + "message": "导出" + }, + "settings_section_tools_reset": { + "message": "还原" + }, + "settings_section_tools_goback": { + "message": "返回" + }, + "settings_section_tools_reset_all": { + "message": "还原所有设置" + }, + "settings_section_tools_reset_single": { + "message": "还原" + }, + "settings_section_tools_reset_section": { + "message": "还原该组" + }, + "settings_scripts_tools_desc": { + "message": "这些工具可以帮助您导入和导出“设置数据”。重置单个、一组或所有设置。" + }, + "settings_about_text1": { + "message": "获取有关此扩展的更多信息,请访问本开源项目:" + }, + "settings_about_text2": { + "message": "如果您喜欢使用此扩展,请考虑在 App Store 上留下您的评论或注册 Beta 测试新版本:" + }, + "settings_about_button_repo": { + "message": "代码库" + }, + "settings_about_button_docs": { + "message": "文档" + }, + "settings_about_button_issues": { + "message": "报告错误" + }, + "settings_about_button_store": { + "message": "在 App Store 中打开" + }, + "settings_about_button_beta": { + "message": "注册 Beta 测试版" + }, + "utils_check_match_patterns_0": { + "message": "此匹配模式将匹配所有 URL" + }, + "utils_check_match_patterns_1": { + "message": "这 scheme 部分应当为 *、https、http 之一" + }, + "utils_check_match_patterns_2": { + "message": "这 scheme 和 host 部分应当用 `://` 分隔" + }, + "utils_check_match_patterns_3": { + "message": "匹配模式缺少 path 部分(至少应当有`/`)" + }, + "utils_check_match_patterns_4": { + "message": "这 `*.` 后面应当跟随主机名的一部分" + }, + "utils_check_match_patterns_5": { + "message": "这 host 部分长度应当为 1-255" + }, + "utils_check_match_patterns_6": { + "message": "这 host 部分中的 `*` 应该是独立的或为 `*.` 在开头" + }, + "utils_check_match_patterns_7": { + "message": "这 host 部分包含一个或多个空标签" + }, + "utils_check_match_patterns_8": { + "message": "主机名标签不能以 `-` 字符开头或结尾" + }, + "utils_check_match_patterns_9": { + "message": "主机名标签最大长度不能超过 63" + }, + "utils_check_match_patterns_10": { + "message": "这 host 部分包含无效字符:$1" + }, + "utils_check_match_patterns_11": { + "message": "这 path 部分包含无效字符:$1" + }, + "msg_invalid_match_pattern": { + "message": "无效的匹配模式" + }, + "msg_invalid_backup_file": { + "message": "无效的备份文件" + }, + "msg_backup_import_finish": { + "message": "导入完成!✅" + }, + "msg_backup_import_failed": { + "message": "导入失败,请在控制台中检查错误日志" + }, + "msg_settings_reset_finish": { + "message": "还原所有设置完成!✅" + } +} diff --git a/public/ext/shared/_locales/zh_HK/messages.json b/public/ext/shared/_locales/zh_HK/messages.json new file mode 100644 index 00000000..bec11460 --- /dev/null +++ b/public/ext/shared/_locales/zh_HK/messages.json @@ -0,0 +1,240 @@ +{ + "extension_description": { + "message": "使用者腳本和樣式管理器", + "description": "Description of what the extension does." + }, + "settings": { + "message": "設定" + }, + "settings_section_editor": { + "message": "編輯器設定" + }, + "settings_section_general": { + "message": "一般設定" + }, + "settings_section_native": { + "message": "本地設定" + }, + "settings_section_tools": { + "message": "工具" + }, + "settings_section_about": { + "message": "關於" + }, + "settings_editor_auto_hint": { + "message": "自動提示(Hint)" + }, + "settings_editor_auto_hint_desc": { + "message": "編輯時自動顯示完成提示" + }, + "settings_editor_close_brackets": { + "message": "自動關閉括號" + }, + "settings_editor_close_brackets_desc": { + "message": "在編輯器中啟用自動關閉括號,這會影響以下字元:() [] {} \"\" ''" + }, + "settings_editor_javascript_lint": { + "message": "JavaScript Linter" + }, + "settings_editor_javascript_lint_desc": { + "message": "在編輯器中啟用基本的 JavaScript Linting(程式碼檢查)" + }, + "settings_editor_list_descriptions": { + "message": "側欄項目描述" + }, + "settings_editor_list_descriptions_desc": { + "message": "顯示或隱藏側邊欄中項目的描述" + }, + "settings_editor_list_sort": { + "message": "側欄項目排序" + }, + "settings_editor_list_sort_desc": { + "message": "側邊欄中項目的顯示順序" + }, + "settings_editor_list_sort_nameAsc": { + "message": "項目名稱: 升序" + }, + "settings_editor_list_sort_nameDesc": { + "message": "項目名稱: 降序" + }, + "settings_editor_list_sort_lastModifiedAsc": { + "message": "最後修改: 升序" + }, + "settings_editor_list_sort_lastModifiedDesc": { + "message": "最後修改: 降序" + }, + "settings_editor_show_whitespace": { + "message": "顯示空白字元" + }, + "settings_editor_show_whitespace_desc": { + "message": "切換編輯器中不可見字元的顯示" + }, + "settings_editor_tab_size": { + "message": "製表符大小" + }, + "settings_editor_tab_size_desc": { + "message": "選擇渲染程式碼時製表符等於的空格數" + }, + "settings_global_active": { + "message": "啟用注入" + }, + "settings_global_active_desc": { + "message": "全域性腳本注入的開啟或關閉" + }, + "settings_global_exclude_match": { + "message": "全域性排除匹配模式列表" + }, + "settings_global_exclude_match_desc": { + "message": "此輸入接受以空白符(空格、換行等)分隔的 @match 模式列表,與此列表中的模式匹配的頁面 URL 將在腳本注入時被忽略" + }, + "settings_global_exclude_match_done": { + "message": "完成" + }, + "settings_global_exclude_match_saving": { + "message": "儲存中..." + }, + "settings_global_exclude_match_placeholder": { + "message": "@match 模式列表,例如:\n*://*/*foo.bar\n*://*/*foo.bar?*\n*://*.example.net/*\nhttps://example.net/*/foo/*/\nhttps://*.example.net/a/b/c/?foo=/" + }, + "settings_global_exclude_match_refer": { + "message": "匹配模式結構請參考:" + }, + "settings_scripts_update_automation": { + "message": "自動更新腳本" + }, + "settings_scripts_update_automation_desc": { + "message": "腳本在後臺靜默自動更新,這是危險的,可能引入未經確認的惡意程式碼" + }, + "settings_scripts_update_check_interval": { + "message": "腳本更新檢查間隔" + }, + "settings_scripts_update_check_interval_desc": { + "message": "禁用或設定使用者腳本更新檢查間隔(天)" + }, + "settings_scripts_update_check_interval_0": { + "message": "從不" + }, + "settings_scripts_update_check_lasttime": { + "message": "腳本更新上次檢查時間" + }, + "settings_scripts_update_check_lasttime_desc": { + "message": "後臺腳本更新檢查上次時間" + }, + "settings_settings_sync": { + "message": "同步設定" + }, + "settings_settings_sync_desc": { + "message": "跨裝置同步設定" + }, + "settings_toolbar_badge_count": { + "message": "工具欄圖示顯示計數徽章" + }, + "settings_toolbar_badge_count_desc": { + "message": "在工具欄圖示上顯示一個徽章,其中的數字代表有多少個已啟用的腳本與您所在頁面的 URL 匹配" + }, + "settings_scripts_directory": { + "message": "儲存位置" + }, + "settings_scripts_directory_desc": { + "message": "儲存使用者腳本的資料夾路徑" + }, + "settings_set_scripts_directory": { + "message": "更改儲存位置" + }, + "settings_section_tools_import": { + "message": "匯入" + }, + "settings_section_tools_export": { + "message": "匯出" + }, + "settings_section_tools_reset": { + "message": "還原" + }, + "settings_section_tools_goback": { + "message": "返回" + }, + "settings_section_tools_reset_all": { + "message": "還原所有設定" + }, + "settings_section_tools_reset_single": { + "message": "還原" + }, + "settings_section_tools_reset_section": { + "message": "還原該組" + }, + "settings_scripts_tools_desc": { + "message": "這些工具可以幫助您匯入和匯出“設定資料”。重置單個、一組或所有設定。" + }, + "settings_about_text1": { + "message": "獲取有關此延伸功能的更多資訊,請訪問本開源項目:" + }, + "settings_about_text2": { + "message": "如果您喜歡使用此延伸功能,請考慮在 App Store 上留下您的評論或註冊 Beta 測試新版本:" + }, + "settings_about_button_repo": { + "message": "代碼庫" + }, + "settings_about_button_docs": { + "message": "文件" + }, + "settings_about_button_issues": { + "message": "報告錯誤" + }, + "settings_about_button_store": { + "message": "在 App Store 中開啟" + }, + "settings_about_button_beta": { + "message": "註冊 Beta 測試版" + }, + "utils_check_match_patterns_0": { + "message": "此匹配模式將匹配所有 URL" + }, + "utils_check_match_patterns_1": { + "message": "這 scheme 部分應當為 *、https、http 之一" + }, + "utils_check_match_patterns_2": { + "message": "這 scheme 和 host 部分應當用 `://` 分隔" + }, + "utils_check_match_patterns_3": { + "message": "匹配模式缺少 path 部分(至少應當有`/`)" + }, + "utils_check_match_patterns_4": { + "message": "這 `*.` 後面應當跟隨主機名的一部分" + }, + "utils_check_match_patterns_5": { + "message": "這 host 部分長度應當為 1-255" + }, + "utils_check_match_patterns_6": { + "message": "這 host 部分中的 `*` 應該是獨立的或為 `*.` 在開頭" + }, + "utils_check_match_patterns_7": { + "message": "這 host 部分包含一個或多個空標籤" + }, + "utils_check_match_patterns_8": { + "message": "主機名標籤不能以 `-` 字元開頭或結尾" + }, + "utils_check_match_patterns_9": { + "message": "主機名標籤最大長度不能超過 63" + }, + "utils_check_match_patterns_10": { + "message": "這 host 部分包含無效字元:$1" + }, + "utils_check_match_patterns_11": { + "message": "這 path 部分包含無效字元:$1" + }, + "msg_invalid_match_pattern": { + "message": "無效的匹配模式" + }, + "msg_invalid_backup_file": { + "message": "無效的備份檔案" + }, + "msg_backup_import_finish": { + "message": "匯入完成!✅" + }, + "msg_backup_import_failed": { + "message": "匯入失敗,請在控制檯中檢查錯誤日誌" + }, + "msg_settings_reset_finish": { + "message": "還原所有設定完成!✅" + } +} diff --git a/public/ext/shared/_locales/zh_MO/messages.json b/public/ext/shared/_locales/zh_MO/messages.json new file mode 100644 index 00000000..bec11460 --- /dev/null +++ b/public/ext/shared/_locales/zh_MO/messages.json @@ -0,0 +1,240 @@ +{ + "extension_description": { + "message": "使用者腳本和樣式管理器", + "description": "Description of what the extension does." + }, + "settings": { + "message": "設定" + }, + "settings_section_editor": { + "message": "編輯器設定" + }, + "settings_section_general": { + "message": "一般設定" + }, + "settings_section_native": { + "message": "本地設定" + }, + "settings_section_tools": { + "message": "工具" + }, + "settings_section_about": { + "message": "關於" + }, + "settings_editor_auto_hint": { + "message": "自動提示(Hint)" + }, + "settings_editor_auto_hint_desc": { + "message": "編輯時自動顯示完成提示" + }, + "settings_editor_close_brackets": { + "message": "自動關閉括號" + }, + "settings_editor_close_brackets_desc": { + "message": "在編輯器中啟用自動關閉括號,這會影響以下字元:() [] {} \"\" ''" + }, + "settings_editor_javascript_lint": { + "message": "JavaScript Linter" + }, + "settings_editor_javascript_lint_desc": { + "message": "在編輯器中啟用基本的 JavaScript Linting(程式碼檢查)" + }, + "settings_editor_list_descriptions": { + "message": "側欄項目描述" + }, + "settings_editor_list_descriptions_desc": { + "message": "顯示或隱藏側邊欄中項目的描述" + }, + "settings_editor_list_sort": { + "message": "側欄項目排序" + }, + "settings_editor_list_sort_desc": { + "message": "側邊欄中項目的顯示順序" + }, + "settings_editor_list_sort_nameAsc": { + "message": "項目名稱: 升序" + }, + "settings_editor_list_sort_nameDesc": { + "message": "項目名稱: 降序" + }, + "settings_editor_list_sort_lastModifiedAsc": { + "message": "最後修改: 升序" + }, + "settings_editor_list_sort_lastModifiedDesc": { + "message": "最後修改: 降序" + }, + "settings_editor_show_whitespace": { + "message": "顯示空白字元" + }, + "settings_editor_show_whitespace_desc": { + "message": "切換編輯器中不可見字元的顯示" + }, + "settings_editor_tab_size": { + "message": "製表符大小" + }, + "settings_editor_tab_size_desc": { + "message": "選擇渲染程式碼時製表符等於的空格數" + }, + "settings_global_active": { + "message": "啟用注入" + }, + "settings_global_active_desc": { + "message": "全域性腳本注入的開啟或關閉" + }, + "settings_global_exclude_match": { + "message": "全域性排除匹配模式列表" + }, + "settings_global_exclude_match_desc": { + "message": "此輸入接受以空白符(空格、換行等)分隔的 @match 模式列表,與此列表中的模式匹配的頁面 URL 將在腳本注入時被忽略" + }, + "settings_global_exclude_match_done": { + "message": "完成" + }, + "settings_global_exclude_match_saving": { + "message": "儲存中..." + }, + "settings_global_exclude_match_placeholder": { + "message": "@match 模式列表,例如:\n*://*/*foo.bar\n*://*/*foo.bar?*\n*://*.example.net/*\nhttps://example.net/*/foo/*/\nhttps://*.example.net/a/b/c/?foo=/" + }, + "settings_global_exclude_match_refer": { + "message": "匹配模式結構請參考:" + }, + "settings_scripts_update_automation": { + "message": "自動更新腳本" + }, + "settings_scripts_update_automation_desc": { + "message": "腳本在後臺靜默自動更新,這是危險的,可能引入未經確認的惡意程式碼" + }, + "settings_scripts_update_check_interval": { + "message": "腳本更新檢查間隔" + }, + "settings_scripts_update_check_interval_desc": { + "message": "禁用或設定使用者腳本更新檢查間隔(天)" + }, + "settings_scripts_update_check_interval_0": { + "message": "從不" + }, + "settings_scripts_update_check_lasttime": { + "message": "腳本更新上次檢查時間" + }, + "settings_scripts_update_check_lasttime_desc": { + "message": "後臺腳本更新檢查上次時間" + }, + "settings_settings_sync": { + "message": "同步設定" + }, + "settings_settings_sync_desc": { + "message": "跨裝置同步設定" + }, + "settings_toolbar_badge_count": { + "message": "工具欄圖示顯示計數徽章" + }, + "settings_toolbar_badge_count_desc": { + "message": "在工具欄圖示上顯示一個徽章,其中的數字代表有多少個已啟用的腳本與您所在頁面的 URL 匹配" + }, + "settings_scripts_directory": { + "message": "儲存位置" + }, + "settings_scripts_directory_desc": { + "message": "儲存使用者腳本的資料夾路徑" + }, + "settings_set_scripts_directory": { + "message": "更改儲存位置" + }, + "settings_section_tools_import": { + "message": "匯入" + }, + "settings_section_tools_export": { + "message": "匯出" + }, + "settings_section_tools_reset": { + "message": "還原" + }, + "settings_section_tools_goback": { + "message": "返回" + }, + "settings_section_tools_reset_all": { + "message": "還原所有設定" + }, + "settings_section_tools_reset_single": { + "message": "還原" + }, + "settings_section_tools_reset_section": { + "message": "還原該組" + }, + "settings_scripts_tools_desc": { + "message": "這些工具可以幫助您匯入和匯出“設定資料”。重置單個、一組或所有設定。" + }, + "settings_about_text1": { + "message": "獲取有關此延伸功能的更多資訊,請訪問本開源項目:" + }, + "settings_about_text2": { + "message": "如果您喜歡使用此延伸功能,請考慮在 App Store 上留下您的評論或註冊 Beta 測試新版本:" + }, + "settings_about_button_repo": { + "message": "代碼庫" + }, + "settings_about_button_docs": { + "message": "文件" + }, + "settings_about_button_issues": { + "message": "報告錯誤" + }, + "settings_about_button_store": { + "message": "在 App Store 中開啟" + }, + "settings_about_button_beta": { + "message": "註冊 Beta 測試版" + }, + "utils_check_match_patterns_0": { + "message": "此匹配模式將匹配所有 URL" + }, + "utils_check_match_patterns_1": { + "message": "這 scheme 部分應當為 *、https、http 之一" + }, + "utils_check_match_patterns_2": { + "message": "這 scheme 和 host 部分應當用 `://` 分隔" + }, + "utils_check_match_patterns_3": { + "message": "匹配模式缺少 path 部分(至少應當有`/`)" + }, + "utils_check_match_patterns_4": { + "message": "這 `*.` 後面應當跟隨主機名的一部分" + }, + "utils_check_match_patterns_5": { + "message": "這 host 部分長度應當為 1-255" + }, + "utils_check_match_patterns_6": { + "message": "這 host 部分中的 `*` 應該是獨立的或為 `*.` 在開頭" + }, + "utils_check_match_patterns_7": { + "message": "這 host 部分包含一個或多個空標籤" + }, + "utils_check_match_patterns_8": { + "message": "主機名標籤不能以 `-` 字元開頭或結尾" + }, + "utils_check_match_patterns_9": { + "message": "主機名標籤最大長度不能超過 63" + }, + "utils_check_match_patterns_10": { + "message": "這 host 部分包含無效字元:$1" + }, + "utils_check_match_patterns_11": { + "message": "這 path 部分包含無效字元:$1" + }, + "msg_invalid_match_pattern": { + "message": "無效的匹配模式" + }, + "msg_invalid_backup_file": { + "message": "無效的備份檔案" + }, + "msg_backup_import_finish": { + "message": "匯入完成!✅" + }, + "msg_backup_import_failed": { + "message": "匯入失敗,請在控制檯中檢查錯誤日誌" + }, + "msg_settings_reset_finish": { + "message": "還原所有設定完成!✅" + } +} diff --git a/public/ext/shared/_locales/zh_TW/messages.json b/public/ext/shared/_locales/zh_TW/messages.json new file mode 100644 index 00000000..bec11460 --- /dev/null +++ b/public/ext/shared/_locales/zh_TW/messages.json @@ -0,0 +1,240 @@ +{ + "extension_description": { + "message": "使用者腳本和樣式管理器", + "description": "Description of what the extension does." + }, + "settings": { + "message": "設定" + }, + "settings_section_editor": { + "message": "編輯器設定" + }, + "settings_section_general": { + "message": "一般設定" + }, + "settings_section_native": { + "message": "本地設定" + }, + "settings_section_tools": { + "message": "工具" + }, + "settings_section_about": { + "message": "關於" + }, + "settings_editor_auto_hint": { + "message": "自動提示(Hint)" + }, + "settings_editor_auto_hint_desc": { + "message": "編輯時自動顯示完成提示" + }, + "settings_editor_close_brackets": { + "message": "自動關閉括號" + }, + "settings_editor_close_brackets_desc": { + "message": "在編輯器中啟用自動關閉括號,這會影響以下字元:() [] {} \"\" ''" + }, + "settings_editor_javascript_lint": { + "message": "JavaScript Linter" + }, + "settings_editor_javascript_lint_desc": { + "message": "在編輯器中啟用基本的 JavaScript Linting(程式碼檢查)" + }, + "settings_editor_list_descriptions": { + "message": "側欄項目描述" + }, + "settings_editor_list_descriptions_desc": { + "message": "顯示或隱藏側邊欄中項目的描述" + }, + "settings_editor_list_sort": { + "message": "側欄項目排序" + }, + "settings_editor_list_sort_desc": { + "message": "側邊欄中項目的顯示順序" + }, + "settings_editor_list_sort_nameAsc": { + "message": "項目名稱: 升序" + }, + "settings_editor_list_sort_nameDesc": { + "message": "項目名稱: 降序" + }, + "settings_editor_list_sort_lastModifiedAsc": { + "message": "最後修改: 升序" + }, + "settings_editor_list_sort_lastModifiedDesc": { + "message": "最後修改: 降序" + }, + "settings_editor_show_whitespace": { + "message": "顯示空白字元" + }, + "settings_editor_show_whitespace_desc": { + "message": "切換編輯器中不可見字元的顯示" + }, + "settings_editor_tab_size": { + "message": "製表符大小" + }, + "settings_editor_tab_size_desc": { + "message": "選擇渲染程式碼時製表符等於的空格數" + }, + "settings_global_active": { + "message": "啟用注入" + }, + "settings_global_active_desc": { + "message": "全域性腳本注入的開啟或關閉" + }, + "settings_global_exclude_match": { + "message": "全域性排除匹配模式列表" + }, + "settings_global_exclude_match_desc": { + "message": "此輸入接受以空白符(空格、換行等)分隔的 @match 模式列表,與此列表中的模式匹配的頁面 URL 將在腳本注入時被忽略" + }, + "settings_global_exclude_match_done": { + "message": "完成" + }, + "settings_global_exclude_match_saving": { + "message": "儲存中..." + }, + "settings_global_exclude_match_placeholder": { + "message": "@match 模式列表,例如:\n*://*/*foo.bar\n*://*/*foo.bar?*\n*://*.example.net/*\nhttps://example.net/*/foo/*/\nhttps://*.example.net/a/b/c/?foo=/" + }, + "settings_global_exclude_match_refer": { + "message": "匹配模式結構請參考:" + }, + "settings_scripts_update_automation": { + "message": "自動更新腳本" + }, + "settings_scripts_update_automation_desc": { + "message": "腳本在後臺靜默自動更新,這是危險的,可能引入未經確認的惡意程式碼" + }, + "settings_scripts_update_check_interval": { + "message": "腳本更新檢查間隔" + }, + "settings_scripts_update_check_interval_desc": { + "message": "禁用或設定使用者腳本更新檢查間隔(天)" + }, + "settings_scripts_update_check_interval_0": { + "message": "從不" + }, + "settings_scripts_update_check_lasttime": { + "message": "腳本更新上次檢查時間" + }, + "settings_scripts_update_check_lasttime_desc": { + "message": "後臺腳本更新檢查上次時間" + }, + "settings_settings_sync": { + "message": "同步設定" + }, + "settings_settings_sync_desc": { + "message": "跨裝置同步設定" + }, + "settings_toolbar_badge_count": { + "message": "工具欄圖示顯示計數徽章" + }, + "settings_toolbar_badge_count_desc": { + "message": "在工具欄圖示上顯示一個徽章,其中的數字代表有多少個已啟用的腳本與您所在頁面的 URL 匹配" + }, + "settings_scripts_directory": { + "message": "儲存位置" + }, + "settings_scripts_directory_desc": { + "message": "儲存使用者腳本的資料夾路徑" + }, + "settings_set_scripts_directory": { + "message": "更改儲存位置" + }, + "settings_section_tools_import": { + "message": "匯入" + }, + "settings_section_tools_export": { + "message": "匯出" + }, + "settings_section_tools_reset": { + "message": "還原" + }, + "settings_section_tools_goback": { + "message": "返回" + }, + "settings_section_tools_reset_all": { + "message": "還原所有設定" + }, + "settings_section_tools_reset_single": { + "message": "還原" + }, + "settings_section_tools_reset_section": { + "message": "還原該組" + }, + "settings_scripts_tools_desc": { + "message": "這些工具可以幫助您匯入和匯出“設定資料”。重置單個、一組或所有設定。" + }, + "settings_about_text1": { + "message": "獲取有關此延伸功能的更多資訊,請訪問本開源項目:" + }, + "settings_about_text2": { + "message": "如果您喜歡使用此延伸功能,請考慮在 App Store 上留下您的評論或註冊 Beta 測試新版本:" + }, + "settings_about_button_repo": { + "message": "代碼庫" + }, + "settings_about_button_docs": { + "message": "文件" + }, + "settings_about_button_issues": { + "message": "報告錯誤" + }, + "settings_about_button_store": { + "message": "在 App Store 中開啟" + }, + "settings_about_button_beta": { + "message": "註冊 Beta 測試版" + }, + "utils_check_match_patterns_0": { + "message": "此匹配模式將匹配所有 URL" + }, + "utils_check_match_patterns_1": { + "message": "這 scheme 部分應當為 *、https、http 之一" + }, + "utils_check_match_patterns_2": { + "message": "這 scheme 和 host 部分應當用 `://` 分隔" + }, + "utils_check_match_patterns_3": { + "message": "匹配模式缺少 path 部分(至少應當有`/`)" + }, + "utils_check_match_patterns_4": { + "message": "這 `*.` 後面應當跟隨主機名的一部分" + }, + "utils_check_match_patterns_5": { + "message": "這 host 部分長度應當為 1-255" + }, + "utils_check_match_patterns_6": { + "message": "這 host 部分中的 `*` 應該是獨立的或為 `*.` 在開頭" + }, + "utils_check_match_patterns_7": { + "message": "這 host 部分包含一個或多個空標籤" + }, + "utils_check_match_patterns_8": { + "message": "主機名標籤不能以 `-` 字元開頭或結尾" + }, + "utils_check_match_patterns_9": { + "message": "主機名標籤最大長度不能超過 63" + }, + "utils_check_match_patterns_10": { + "message": "這 host 部分包含無效字元:$1" + }, + "utils_check_match_patterns_11": { + "message": "這 path 部分包含無效字元:$1" + }, + "msg_invalid_match_pattern": { + "message": "無效的匹配模式" + }, + "msg_invalid_backup_file": { + "message": "無效的備份檔案" + }, + "msg_backup_import_finish": { + "message": "匯入完成!✅" + }, + "msg_backup_import_failed": { + "message": "匯入失敗,請在控制檯中檢查錯誤日誌" + }, + "msg_settings_reset_finish": { + "message": "還原所有設定完成!✅" + } +} diff --git a/scripts/build-ext-demo.js b/scripts/build-ext-demo.js new file mode 100644 index 00000000..076f2d70 --- /dev/null +++ b/scripts/build-ext-demo.js @@ -0,0 +1,53 @@ +/** + * @file Build extension pages demonstration using the Vite JavaScript API + * @see {@link https://vitejs.dev/guide/api-javascript.html JavaScript API} + */ + +import { build } from "vite"; +import { svelte } from "@sveltejs/vite-plugin-svelte"; +import { cp, emptyBuildDir, rootDir } from "./utils.js"; + +/** + * Define default vite config options + * Disable auto resolving {@link vite.config.js} + * @see {@link https://vitejs.dev/config/ Config} + * @see {@link https://vitejs.dev/guide/api-javascript.html#inlineconfig InlineConfig} + * @type {import("vite").InlineConfig} + */ +const defineConfig = { + configFile: false, + envFile: false, + root: await rootDir(), + base: "./", + mode: "development", + define: { + "import.meta.env.BROWSER": JSON.stringify("Safari"), + "import.meta.env.NATIVE_APP": JSON.stringify("app"), + "import.meta.env.SAFARI_PLATFORM": JSON.stringify( + process.env.SAFARI_PLATFORM, + ), + "import.meta.env.EXT_DEMO_BUILD": JSON.stringify(true), + }, +}; + +/** + * Empty resources directory + * Copy public static assets + */ +await emptyBuildDir("dist"); +cp("public/ext/shared", "dist"); + +/** Build shared modules */ +build({ + ...defineConfig, + plugins: [svelte()], + publicDir: "public/ext/vendor/", + build: { + outDir: `dist/`, + emptyOutDir: false, + rollupOptions: { + input: ["entry-ext-action-popup.html", "entry-ext-extension-page.html"], + }, + target: "esnext", // top-level await + }, +}); diff --git a/scripts/build-ext-safari-15.js b/scripts/build-ext-safari-15.js index 3242f700..76361578 100644 --- a/scripts/build-ext-safari-15.js +++ b/scripts/build-ext-safari-15.js @@ -31,8 +31,11 @@ const defineConfig = { root: await rootDir(), base: "./", define: { - "import.meta.env.BROWSER": JSON.stringify("safari"), + "import.meta.env.BROWSER": JSON.stringify("Safari"), "import.meta.env.NATIVE_APP": JSON.stringify("app"), + "import.meta.env.SAFARI_PLATFORM": JSON.stringify( + process.env.SAFARI_PLATFORM, + ), }, }; @@ -79,11 +82,6 @@ build({ }); /** Build shared modules */ -/** @type {import("rollup").InputOption} */ -let input = ["entry-ext-action-popup.html", "entry-ext-extension-page.html"]; -if (process.env.SAFARI_PLATFORM === "ios") { - input = ["entry-ext-action-popup.html"]; -} build({ ...defineConfig, plugins: [svelte()], @@ -92,7 +90,7 @@ build({ outDir: `${SAFARI_EXT_RESOURCES}/dist/`, emptyOutDir: false, rollupOptions: { - input, + input: ["entry-ext-action-popup.html", "entry-ext-extension-page.html"], }, }, }); diff --git a/scripts/build-ext-safari-16.4.js b/scripts/build-ext-safari-16.4.js index 12a67481..2cc704c2 100644 --- a/scripts/build-ext-safari-16.4.js +++ b/scripts/build-ext-safari-16.4.js @@ -30,8 +30,11 @@ const defineConfig = { root: await rootDir(), base: "./", define: { - "import.meta.env.BROWSER": JSON.stringify("safari"), + "import.meta.env.BROWSER": JSON.stringify("Safari"), "import.meta.env.NATIVE_APP": JSON.stringify("app"), + "import.meta.env.SAFARI_PLATFORM": JSON.stringify( + process.env.SAFARI_PLATFORM, + ), }, }; @@ -82,15 +85,6 @@ build({ }); /** Build shared modules */ -/** @type {import("rollup").InputOption} */ -let input = { - // background: "src/ext/background/main.js", - "action-popup": "entry-ext-action-popup.html", - "extension-page": "entry-ext-extension-page.html", -}; -if (process.env.SAFARI_PLATFORM === "ios") { - delete input["extension-page"]; -} build({ ...defineConfig, plugins: [svelte()], @@ -99,7 +93,11 @@ build({ outDir: `${SAFARI_EXT_RESOURCES}/dist/`, emptyOutDir: false, rollupOptions: { - input, + input: { + // background: "src/ext/background/main.js", + "action-popup": "entry-ext-action-popup.html", + "extension-page": "entry-ext-extension-page.html", + }, output: { entryFileNames: "[name].js" }, }, }, diff --git a/scripts/dev-ext-safari.js b/scripts/dev-ext-safari.js index 2b4e7c25..58fd5c73 100644 --- a/scripts/dev-ext-safari.js +++ b/scripts/dev-ext-safari.js @@ -30,9 +30,13 @@ const defineConfig = { envFile: false, root: await rootDir(), base: "./", + mode: "development", define: { - "import.meta.env.BROWSER": JSON.stringify("safari"), + "import.meta.env.BROWSER": JSON.stringify("Safari"), "import.meta.env.NATIVE_APP": JSON.stringify("app"), + "import.meta.env.SAFARI_PLATFORM": JSON.stringify( + process.env.SAFARI_PLATFORM, + ), }, }; diff --git a/scripts/preview-ext-demo.js b/scripts/preview-ext-demo.js new file mode 100644 index 00000000..ee841b53 --- /dev/null +++ b/scripts/preview-ext-demo.js @@ -0,0 +1,35 @@ +/** + * @file Preview App WebView resources using the Vite JavaScript API + * @see {@link https://vitejs.dev/guide/api-javascript.html JavaScript API} + */ + +import { preview } from "vite"; + +/** + * Define default vite config options + * Disable auto resolving {@link vite.config.js} + * @see {@link https://vitejs.dev/config/ Config} + * @see {@link https://vitejs.dev/guide/api-javascript.html#inlineconfig configFile} + * @type {import("vite").InlineConfig} + */ +const defineConfig = { + base: "./", + configFile: false, +}; + +/** + * Preview App-Shared WebView resources from xcode dist + */ +(async () => { + const previewServer = await preview({ + ...defineConfig, + preview: { + // port: 4173, + open: "entry-ext-extension-page.html", + }, + build: { + outDir: "dist/", + }, + }); + previewServer.printUrls(); +})(); diff --git a/src/ext/action-popup/App.svelte b/src/ext/action-popup/App.svelte index 218721c5..511bd6fd 100644 --- a/src/ext/action-popup/App.svelte +++ b/src/ext/action-popup/App.svelte @@ -57,7 +57,9 @@ } async function toggleExtension() { - await settingsStorage.set({ global_active: !active }); + const keys = {}; + keys["global_active"] = !active; + await settingsStorage.set(keys); active = await settingsStorage.get("global_active"); // TODO: delete after migrating all related logic on the native sendNativeMessage({ name: "TOGGLE_EXTENSION", active: String(active) }); @@ -158,41 +160,36 @@ } // when an update check is run, a timestamp is saved to extension storage // only check for updates every n milliseconds to avoid delaying popup load regularly - const checkInterval = 24 * 60 * 60 * 1000; // 24hr, 86400000 - const timestampMs = Date.now(); - let lastUpdateCheck = 0; - // check extension storage for saved key/val - // if there's an issue getting extension storage, skip the check - let lastUpdateCheckObj; - try { - lastUpdateCheckObj = await browser.storage.local.get(["lastUpdateCheck"]); - } catch (error) { - console.error(`Error checking extension storage ${error}`); + const days = await settingsStorage.get("scripts_update_check_interval"); + // user set to never check + if (days === 0) { + console.info("user scripts update check disabled"); return false; } - // if extension storage doesn't have key, run the check - // key/val will be saved after the update check runs - if (Object.keys(lastUpdateCheckObj).length === 0) { + const checkInterval = days * 24 * 60 * 60 * 1000; // 24hr, 86400000 + const timestampMs = Date.now(); + const checkLasttime = await settingsStorage.get( + "scripts_update_check_lasttime", + ); + // If last check time does not exist, run the check + // new time will be saved after the update check runs + if (checkLasttime === 0) { console.info("no last check saved, running update check"); return true; } // if the val is not a number, something went wrong, check anyway // when update re-runs, new val of the proper type will be saved - if (!Number.isFinite(lastUpdateCheckObj.lastUpdateCheck)) { + if (!Number.isFinite(checkLasttime)) { console.info("run check saved with wrong type, running update check"); return true; } - // at this point it is known that key exists and value is a number - // update local var with the val saved to extension storage - lastUpdateCheck = lastUpdateCheckObj.lastUpdateCheck; // if less than n milliseconds have passed, don't check - if (timestampMs - lastUpdateCheck < checkInterval) { + if (timestampMs - checkLasttime < checkInterval) { console.info("not enough time has passed, not running update check"); return false; } - console.info( - `${(timestampMs - lastUpdateCheck) / (1000 * 60 * 60)} hours have passed`, + `${(timestampMs - checkLasttime) / (1000 * 60 * 60)} hours have passed`, ); console.info("running update check"); // otherwise run the check @@ -316,7 +313,9 @@ try { // save timestamp in ms to extension storage const timestampMs = Date.now(); - await browser.storage.local.set({ lastUpdateCheck: timestampMs }); + const keys = {}; + keys["scripts_update_check_lasttime"] = timestampMs; + await settingsStorage.set(keys); abort = true; updatesResponse = await sendNativeMessage({ name: "POPUP_UPDATES" }); } catch (error) { @@ -484,6 +483,12 @@ window.location.reload(); } }); + + /** + * Temporary settings page entrance for beta test (iOS) + * @todo new permanent button will be added via popup refactoring + */ + let showBetaNews = true; @@ -496,7 +501,7 @@ /> (showUpdates = true)} title={"Show updates"} {disabled} @@ -517,6 +522,17 @@ {#if !active} {/if} +{#if showBetaNews && platform !== "macos"} +
+ NEW: is + now available on iOS! + (showBetaNews = false)} + title={"Close"} + /> +
+{/if} {#if showInstallPrompt}
Userscript @@ -657,8 +673,8 @@ transform: scale(0.9); } - .header :global(label) { - font-size: 1.25rem !important; + .header :global(button:nth-of-type(4)) { + --toggle-font-size: 1.25rem; } .error, @@ -673,13 +689,15 @@ text-align: center; } - .error :global(button) { + .error :global(button), + .warn :global(button:has(svg)) { position: absolute; right: 0.5rem; top: 0; } - .error :global(button svg) { + .error :global(button svg), + .warn :global(button svg) { transform: scale(0.5); } diff --git a/src/ext/background/main.js b/src/ext/background/main.js index e0530cae..87b3cb5b 100644 --- a/src/ext/background/main.js +++ b/src/ext/background/main.js @@ -78,8 +78,8 @@ async function setBadgeCount() { "global_active", "toolbar_badge_count", ]); - if (settings.global_active === false) return clearBadge(); - if (settings.toolbar_badge_count === false) return clearBadge(); + if (settings["global_active"] === false) return clearBadge(); + if (settings["toolbar_badge_count"] === false) return clearBadge(); const currentTab = await browser.tabs.getCurrent(); // no active tabs exist (user closed all windows) @@ -297,6 +297,9 @@ async function handleMessage(request, sender, sendResponse) { // send request to swift layer to provide code for page url const message = { name: "REQ_USERSCRIPTS", url, isTop }; const response = await sendNativeMessage(message); + if (import.meta.env.MODE === "development") { + console.debug("REQ_USERSCRIPTS", message, response); + } // if request failed, send error to content script for logging if (response.error) return sendResponse(response); // sort files diff --git a/src/ext/content-scripts/entry-userscripts.js b/src/ext/content-scripts/entry-userscripts.js index ab620622..94ca0633 100644 --- a/src/ext/content-scripts/entry-userscripts.js +++ b/src/ext/content-scripts/entry-userscripts.js @@ -139,6 +139,9 @@ async function injection() { const response = await browser.runtime.sendMessage({ name: "REQ_USERSCRIPTS", }); + if (import.meta.env.MODE === "development") { + console.debug("REQ_USERSCRIPTS", response); + } // cancel injection if errors detected if (!response || response.error) { console.error(response?.error || "REQ_USERSCRIPTS returned undefined"); diff --git a/src/ext/extension-page/App.svelte b/src/ext/extension-page/App.svelte index a457e035..b7e5974b 100644 --- a/src/ext/extension-page/App.svelte +++ b/src/ext/extension-page/App.svelte @@ -1,10 +1,11 @@ - + {#if $state.includes("init")}
@@ -88,7 +83,11 @@ notifications.remove(item.id)} {item} /> {/each} -{#if $state.includes("settings")}{/if} +{#if $state.includes("settings")} + state.remove("settings")} let:navRegister> + + +{/if} diff --git a/src/ext/extension-page/Components/Editor/CodeMirror.svelte b/src/ext/extension-page/Components/Editor/CodeMirror.svelte index e0c39081..2eebb3d4 100644 --- a/src/ext/extension-page/Components/Editor/CodeMirror.svelte +++ b/src/ext/extension-page/Components/Editor/CodeMirror.svelte @@ -65,10 +65,13 @@ // update settings when changed $: if (instance) { - instance.setOption("autoCloseBrackets", $settings.autoCloseBrackets); - instance.setOption("showInvisibles", $settings.showInvisibles); - instance.setOption("tabSize", parseInt($settings.tabSize, 10)); - instance.setOption("indentUnit", parseInt($settings.tabSize, 10)); + instance.setOption("autoCloseBrackets", $settings["editor_close_brackets"]); + instance.setOption("showInvisibles", $settings["editor_show_whitespace"]); + instance.setOption("tabSize", parseInt($settings["editor_tab_size"], 10)); + instance.setOption( + "indentUnit", + parseInt($settings["editor_tab_size"], 10), + ); } // store cursor position and disable on save @@ -100,20 +103,20 @@ } // track lint settings and update accordingly - $: if (instance && $settings.lint) { + $: if (instance && $settings["editor_javascript_lint"]) { toggleLint("enable"); - } else if (instance && !$settings.lint) { + } else if (instance && !$settings["editor_javascript_lint"]) { toggleLint("disable"); } export function init() { // do lint settings check - const lint = $settings.lint ? lintOptions : false; + const lint = $settings["editor_javascript_lint"] ? lintOptions : false; // create codemirror instance instance = CodeMirror.fromTextArea(textarea, { mode: "javascript", - autoCloseBrackets: $settings.autoCloseBrackets, + autoCloseBrackets: $settings["editor_close_brackets"], continueComments: true, foldGutter: true, lineNumbers: true, @@ -121,9 +124,9 @@ matchBrackets: true, smartIndent: true, styleActiveLine: true, - indentUnit: parseInt($settings.tabSize, 10), - showInvisibles: $settings.showInvisibles, - tabSize: parseInt($settings.tabSize, 10), + indentUnit: parseInt($settings["editor_tab_size"], 10), + showInvisibles: $settings["editor_show_whitespace"], + tabSize: parseInt($settings["editor_tab_size"], 10), highlightSelectionMatches: false, lint, hintOptions: { @@ -192,7 +195,7 @@ }); if ( // check if setting is enabled - $settings.autoHint && + $settings["editor_auto_hint"] && // ensure hinting not active already !cm.state.completionActive && // not first position on the line @@ -406,10 +409,10 @@ {#if instance} {/if} + + diff --git a/src/ext/extension-page/Components/Editor/Editor.svelte b/src/ext/extension-page/Components/Editor/Editor.svelte index 5d831d39..362d7ed9 100644 --- a/src/ext/extension-page/Components/Editor/Editor.svelte +++ b/src/ext/extension-page/Components/Editor/Editor.svelte @@ -307,6 +307,7 @@ .editor__header__buttons { display: flex; + margin-right: 1rem; } :global(.editor__header__buttons > button:nth-of-type(2)) { diff --git a/src/ext/extension-page/Components/Editor/EditorSearch.svelte b/src/ext/extension-page/Components/Editor/EditorSearch.svelte index cc1f70db..ad132f0e 100644 --- a/src/ext/extension-page/Components/Editor/EditorSearch.svelte +++ b/src/ext/extension-page/Components/Editor/EditorSearch.svelte @@ -168,9 +168,9 @@ border-radius: var(--border-radius); box-shadow: var(--box-shadow); display: flex; - padding: 0.25rem 0; + padding: 0.25rem; position: absolute; - right: 0.5rem; + right: 1.5rem; top: 0; z-index: 4; } @@ -197,10 +197,6 @@ flex-shrink: 0; } - :global(button:nth-of-type(3)) { - margin-right: 0.25rem; - } - :global(div.editor__search button svg) { width: 45%; } diff --git a/src/ext/extension-page/Components/ModalWrapper.svelte b/src/ext/extension-page/Components/ModalWrapper.svelte new file mode 100644 index 00000000..826d5141 --- /dev/null +++ b/src/ext/extension-page/Components/ModalWrapper.svelte @@ -0,0 +1,149 @@ + + +
+ + + +
+ +
+ + diff --git a/src/ext/extension-page/Components/Settings.svelte b/src/ext/extension-page/Components/Settings.svelte index 0d759d11..084472ae 100644 --- a/src/ext/extension-page/Components/Settings.svelte +++ b/src/ext/extension-page/Components/Settings.svelte @@ -1,341 +1,648 @@ -
- - -
state.remove("settings")}>
-