diff --git a/.gitignore b/.gitignore index 23718be..5ee1b8c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ .temp .vscode -**/*.zip vmf/bundleV1 vmf/bundleV2 -node_modules \ No newline at end of file diff --git a/CONTRIBUTORS.MD b/CONTRIBUTORS.MD index bad3b4d..be9f4ea 100644 --- a/CONTRIBUTORS.MD +++ b/CONTRIBUTORS.MD @@ -1,13 +1,9 @@ # DMF contributors (sorted alphabetically) Contribute to DMF -- add your name here! -+ [alxl](https://github.com/ItsAlxl) + [Aussiemon](https://github.com/Aussiemon) -+ [deluxghost](https://github.com/deluxghost) -+ [raindish](https://github.com/danreeves) + [Fracticality](https://github.com/fracticality) + [grasmann](https://github.com/grasmann) + [philipdestroyer](https://github.com/philippedavid) -+ [ronvoluted](https://github.com/ronvoluted) + [SirAiedail](https://github.com/SirAiedail) # VMF contributors (sorted alphabetically) diff --git a/README.MD b/README.MD index ca24fa5..2ac0773 100644 --- a/README.MD +++ b/README.MD @@ -1,10 +1,13 @@ -
- - - - Darktide Mod Framework - -
+

+ + Darktide Mod Framework + +

+ ## Welcome to the Darktide Mod Framework (DMF) Repository! @@ -19,6 +22,36 @@ Mods created for the project may utilize: * Rewritten, lightweight mod functions * An on-event call system -The Darktide Mod Framework is a fork of the Vermintide Mod Framework that originally started in Warhammer End Times: Vermintide as an unofficial modding platform. In the time since, the framework has been rewritten and redesigned with contributions from many unique members of the community; culminating in this unified project. +The Darktide Mod Framework originally started in Warhammer End Times: Vermintide as an unofficial modding platform. In the time since, DMF has been rewritten and redesigned with contributions from many unique members of the community; culminating in this unified project. -For more information, check out **[the framework's wiki pages](http://dmf-docs.darkti.de)**. +For more information, check out **[the framework's wiki pages](https://github.com/Darktide-Mod-Framework/Darktide-Mod-Framework/wiki)**. + + +## Building the Framework + +### Prerequisites: + +- To start, you should be subscribed to the VMF Beta in Steam Workshop. (**[Warhammer End Times - Vermintide](https://steamcommunity.com/sharedfiles/filedetails/?id=1500136933)** or **[Warhammer: Vermintide 2](https://steamcommunity.com/sharedfiles/filedetails/?id=1500112422)**, depending on which version you want to compile) +- You should also install **[Vermintide Mod Builder (VMB)](https://github.com/Vermintide-Mod-Framework/Vermintide-Mod-Framework/wiki/Get-Vermintide-Mod-Builder)**. + + +### Building Steps: + +1. Navigate to your VMB directory. Let's assume it's unpacked into a folder named `vermintide-mod-builder`. +2. Create a folder inside `vermintide-mod-builder` (we'll call it `vermintide-mod-framework`) and **[clone](https://git-scm.com/docs/git-clone)** in the VMF repository's contents. +3. Open a console/Command Prompt/PowerShell window inside your `vermintide-mod-builder` directory and use the following VMB command: `vmb build vmf -f vermintide-mod-framework -g [1|2]`, where the number after `-g` indicates the target Vermintide game. + + +You can find more VMB mod-building information in the **[Vermintide Mod Builder documentation](https://github.com/Vermintide-Mod-Framework/Vermintide-Mod-Builder/blob/master/README.md)**. + +## Steam Workshop Links + +Beta builds: + + - [Warhammer End Times - Vermintide](https://steamcommunity.com/sharedfiles/filedetails/?id=1500136933) + - [Warhammer: Vermintide 2](https://steamcommunity.com/sharedfiles/filedetails/?id=1500112422) + +Stable builds: + + - [Warhammer End Times - Vermintide](https://steamcommunity.com/sharedfiles/filedetails/?id=1289946781) + - [Warhammer: Vermintide 2](https://steamcommunity.com/sharedfiles/filedetails/?id=1369573612) diff --git a/assets/dmf_logo_black.png b/assets/dmf_logo_black.png index 01be5fe..9b2d6e2 100644 Binary files a/assets/dmf_logo_black.png and b/assets/dmf_logo_black.png differ diff --git a/assets/dmf_logo_white.png b/assets/dmf_logo_white.png deleted file mode 100644 index fa97a4a..0000000 Binary files a/assets/dmf_logo_white.png and /dev/null differ diff --git a/dmf/localization/dmf.lua b/dmf/localization/dmf.lua index 13b5dec..748fbb4 100644 --- a/dmf/localization/dmf.lua +++ b/dmf/localization/dmf.lua @@ -3,108 +3,75 @@ return { en = "Mod Options", es = "Configuración de mods", ru = "Настройки модов", - ["zh-cn"] = "模组选项", - ja = "Modオプション", }, open_dmf_options = { en = "Open Options Menu", es = "Abrir el menu de configuración", ru = "Открыть меню настроек", - ["zh-cn"] = "打开选项菜单", - ja = "オプションメニューを開く", }, open_dmf_options_description = { en = "Keybind for opening and closing mods options menu.", es = "Atajo para abrir/cerrar el menu de configuración de mods.", - ru = "Клавиша/сочетание клавиш для открытия и закрытия меню настроек модов.", - ["zh-cn"] = "打开关闭模组选项菜单的按键绑定。", - ja = "オプションメニューを開閉するキーバインド", + ru = "Клавиша / сочетание клавиш для открытия и закрытия меню настроек модов.", }, dmf_options_scrolling_speed = { en = "Options Menu Scrolling Speed", es = "Velocidad de desplazamiento en el menu", ru = "Скорость прокрутки меню", - ["zh-cn"] = "选项菜单滚动速度", - ja = "オプションメニューのスクロール速度", }, dmf_first_run_notification = { en = "Welcome to the Darktide Mod Framework. Mod options have been added to the Options Menu.", es = "Bienvenidos a el Mod Framework de Darktide. Hemos agregado las opciones de Mod a el menu de opciones.", de = "Willkommen beim Darktide Mod Framework. Ein Button für Mod-Optionen wurde dem Hauptmenu hinzugefügt.", - ["zh-cn"] = "欢迎使用 Darktide Mod Framework。模组选项已添加到选项菜单。", - ru = "Добро пожаловать в Darktide Mod Framework. Параметры мода были добавлены в меню параметров.", - ja = "Darktide Mod Frameworkのご利用ありがとうございます。Modオプションがオプションメニューに追加されました。", }, percent = { en = "%%", }, - toggle_mods = { - en = "Toggle Mods", - ["zh-cn"] = "开启关闭模组", - ru = "Включение/выключение модов", - ja = "Modのオン/オフ", + toggle_mod = { + en = "Toggle Mod", }, - toggle_mods_description = { - en = "Enable or disable your mods.", - ["zh-cn"] = "启用或禁用安装的模组。", - ru = "Включите или отключите ваши моды.", - ja = "Modを有効化/無効化します。", + toggle_mod_description = { + en = "Enable or disable the mod", }, ui_scaling = { en = "UI Scaling for FHD+ Resolutions", es = "Reescalado de la interfaz para resoluciones Full HD+", - ru = "Нормализация масштаба интерфейса для FHD+ разрешений", - ["zh-cn"] = "高分辨率 UI 缩放", - ja = "解像度FHD以上でのUIスケーリング", + ru = "Нормализация масштаба UI для FHD+ разрешений", }, ui_scaling_description = { en = "Automatically scale UI when resolution exceeds 1080p.", es = "Redimensionar automáticamente la interfaz cuando la resolución exceda 1080p.", ru = "Нормализует масштаб элементов интерфейса, если разрешений экрана превышает 1080p.", - ["zh-cn"] = "分辨率超过 1080p 时自动缩放 UI", - ja = "1080pを超える解像度でUIの大きさを自動調節します。", }, developer_mode = { en = "Developer Mode", es = "Modo de desarrollo", ru = "Режим разработчика", - ["zh-cn"] = "开发者模式", - ja = "開発者モード", }, developer_mode_description = { en = "Allows you to reload DMF and mods (CTRL+SHIFT+R), gives you access to some debug features.", es = "Permite recargar los mods (CTRL+SHIFT+R) y configurar herramientas de depuración.", ru = "Позволяет перезагружать DMF и моды (CTRL+SHIFT+R), даёт доступ к инструментам отладки.", - ["zh-cn"] = "允许重新加载 DMF 和模组(CTRL+SHIFT+R),并启用一些调试功能。", - ja = "DMFとModのリロード (CTRL+SHIFT+R) や、いくつかのデバッグ機能へのアクセスを可能にします。", }, show_developer_console = { en = "Show Developer Console", es = "Mostrar el registro (log) a tiempo real", ru = "Консоль разработчика", - ["zh-cn"] = "显示开发者控制台", - ja = "開発者コンソールの表示", }, show_developer_console_description = { en = "Opens up the new window showing game log in real time.", es = "Abre una ventana que muestra el registro (log) del juego en tiempo real.", ru = "Открывает новое окно, в которое в реальном времени выводится игровой лог.", - ["zh-cn"] = "在一个新窗口中显示游戏实时日志。", - ja = "ゲームのログをリアルタイムで表示する新たなウィンドウを開きます。", }, toggle_developer_console = { en = "Toggle Developer Console", es = "Abrir el registro (log) a tiempo real", ru = "Открыть/закрыть консоль разработчика", - ["zh-cn"] = "开关开发者控制台", - ja = "開発者コンソールの表示/非表示", }, show_network_debug_info = { en = "Log Network Calls", es = "Depurar las llamadas de red", ru = "Логирование сетевых вызовов", - ["zh-cn"] = "记录网络调用日志", - ja = "ネットワーク呼び出しの記録", }, show_network_debug_info_description = { en = "Log all the DMF network calls and all the data transfered with them.\n\n" .. @@ -113,17 +80,11 @@ return { "Esta información se registra en el nivel 'info'.", ru = "Логирование всех сетевых вызовов DMF и передаваемых с ними данных.\n\n" .. "Для логирования используется метод 'info'.", - ["zh-cn"] = "记录所有 DMF 网络调用及其所传输数据的日志。\n\n" .. - "记录日志时会使用 'info' 方法。", - ja = "すべてのDMFのネットワーク呼び出しと通信データをログに記録します。\n\n" .. - "記録には 'info' メソッドが使用されます。", }, log_ui_renderers_info = { en = "Log UI Renderers Creation Info", es = "Depurar la renderización de la interfaz de usuario", ru = "Логирование информации при создании UI Renderer", - ["zh-cn"] = "记录 UI 渲染器创建信息", - ja = "UIレンダラー生成情報の記録", }, log_ui_renderers_info_description = { en = "Log the UI Renderer's creator name and all the materials passed as the arguments.\n\n" .. @@ -132,131 +93,86 @@ return { "Esta información se registra en el nivel 'info'.", ru = "Логирование имени создателя UI Renderer'а и всех материалов, переданных в качестве аргументов.\n\n" .. "Для логирования используется метод 'info'.", - ["zh-cn"] = "记录 UI 渲染器的创建者名称以及作为参数传入的所有材质。\n\n" .. - "记录日志时会使用 'info' 方法。", - ja = "UIレンダラー生成元の名称と、引数として渡されたすべてのマテリアルをログに記録します。\n\n" .. - "記録には 'info' メソッドが使用されます。", }, logging_mode = { en = "Logging Settings", es = "Opciones de logging", ru = "Настройки логирования", - ["zh-cn"] = "日志设置", - ja = "ログの設定", }, settings_default = { en = "Default", es = "Valor por defecto", ru = "Стандартные", - ["zh-cn"] = "默认", - ja = "デフォルト", }, settings_custom = { en = "Custom", es = "Personalizado", ru = "Пользовательские", - ["zh-cn"] = "自定义", - ja = "カスタム", }, output_mode_notification = { en = "'Notification' Output", - ["zh-cn"] = "'Notification' 通知输出", - ru = "Вывод 'Notification'", - ja = "'Notification' の出力", }, output_mode_echo = { en = "'Echo' Output", es = "Mensajes de 'Echo'", ru = "Вывод 'Echo'", - ["zh-cn"] = "'Echo' 回显输出", - ja = "'Echo' の出力", }, output_mode_error = { en = "'Error' Output", es = "Mensajes de 'Error'", ru = "Вывод 'Error'", - ["zh-cn"] = "'Error' 错误输出", - ja = "'Error' の出力", }, output_mode_warning = { en = "'Warning' Output", es = "Mensajes de 'Warning'", ru = "Вывод 'Warning'", - ["zh-cn"] = "'Warning' 警告输出", - ja = "'Warning' の出力", }, output_mode_info = { en = "'Info' Output", es = "Mensajes de 'Info'", ru = "Вывод 'Info'", - ["zh-cn"] = "'Info' 信息输出", - ja = "'Info' の出力", }, output_mode_debug = { en = "'Debug' Output", es = "Mensajes de 'Debug'", ru = "Вывод 'Debug'", - ["zh-cn"] = "'Debug' 调试输出", - ja = "'Debug' の出力", }, output_disabled = { en = "Disabled", es = "Desactivado", ru = "Выключен", - ["zh-cn"] = "禁用", - ja = "無効", }, output_log = { en = "Log", es = "Registro (log)", ru = "Лог", - ["zh-cn"] = "日志", - ja = "ログ", }, output_chat = { en = "Chat", es = "Chat", ru = "Чат", - ["zh-cn"] = "聊天", - ja = "チャット", }, output_notification = { en = "Notification", - ["zh-cn"] = "通知", - ru = "Уведомление", - ja = "通知", }, output_log_and_chat = { en = "Log & Chat", es = "Registro (log) y chat", ru = "Лог и чат", - ["zh-cn"] = "日志与聊天", - ja = "ログとチャット", }, output_all = { en = "All", - ["zh-cn"] = "全部", - ru = "Все", - ja = "すべて", }, output_log_and_notification = { en = "Log & Notification", - ["zh-cn"] = "日志与通知", - ru = "Лог и Уведомление", - ja = "ログと通知", }, output_chat_and_notification = { en = "Chat & Notification", - ["zh-cn"] = "聊天与通知", - ru = "Чат и Уведомление", - ja = "チャットと通知", }, chat_history_enable = { en = "Chat Input History", es = "Historial de chat", ru = "История ввода чата", - ["zh-cn"] = "聊天输入历史记录", - ja = "チャット入力の履歴", }, chat_history_enable_description = { en = "Saves all the messages and commands you typed in the chat window.\n\n" .. @@ -265,31 +181,21 @@ return { "Puedes navegar por tu historial de comandos abriendo el chat y usando las flechas del teclado.", ru = "Сохраняет все сообщения и команды, введённые в чате.\n\n" .. "Чтобы пролистывать историю ввода, откройте чат и используйте клавиши \"стрелка вверх\" и \"стрелка вниз\".", - ["zh-cn"] = "保存所有你在聊天窗口内输入过的消息和命令。\n\n" .. - "你可以打开聊天窗口,按“上下方向键”浏览输入历史记录。", - ja = "チャット欄に記入したすべてのメッセージとコマンドを保存します。\n\n" .. - "入力履歴はチャットを開いて「上矢印」と「下矢印」キーで表示できます。", }, chat_history_save = { en = "Save Input History Between Game Sessions", es = "Guardar la entrada", ru = "Сохранять историю ввода между сеансами игры", - ["zh-cn"] = "重启游戏仍保留输入历史", - ja = "ゲームセッション間での入力履歴の保存", }, chat_history_save_description = { en = "Your chat input history will be saved even after reloading your game (or just DMF).", es = "El texto que introduzcas en el chat se guardara incluso al recargar el juego (o solo DMF)", ru = "Когда игрок выключает игру (или перезагружает DMF), DMF cохраняет историю ввода в файл настроек, чтобы загрузить её при следующем запуске игры.", - ["zh-cn"] = "即使重新启动游戏(或者重新加载 DMF),仍然保存聊天输入历史记录。", - ja = "ゲームの再起動 (またはDMFのリロード) 後もチャットの入力履歴が保持されます。", }, chat_history_buffer_size = { en = "Input History Buffer Size", es = "Número de comandos antiguos guardados", ru = "Размер буфера истории ввода", - ["zh-cn"] = "输入历史记录大小", - ja = "入力履歴のバッファサイズ", }, chat_history_buffer_size_description = { en = "Maximum number of saved entries.\n\n" .. @@ -298,24 +204,16 @@ return { "ATENCIÓN: Cambiar esta preferencia borra el historial del chat.", ru = "Максимальное количество сохраняемых записей.\n\n" .. "ВНИМАНИЕ: изменение этой настройки очистит вашу историю ввода.", - ["zh-cn"] = "最大保存记录条数。\n\n" .. - "警告:更改此设置会删除所有聊天历史记录。", - ja = "履歴の最大保存数。\n\n" .. - "警告:この設定を変更するとチャット履歴が消去されます。", }, chat_history_remove_dups = { en = "Remove Duplicate Entries", es = "Eliminar lineas repetidas", ru = "Удалять повторяющиеся записи", - ["zh-cn"] = "删除重复记录", - ja = "重複する履歴の削除", }, chat_history_remove_dups_mode = { en = "Removal Mode", es = "Modo de eliminación de repetidos", ru = "Режим удаления", - ["zh-cn"] = "删除模式", - ja = "削除方式", }, chat_history_remove_dups_mode_description = { en = "Which duplicate entries should be removed.\n\n" .. @@ -327,33 +225,21 @@ return { ru = "Повторяющиеся записи, которые будут удалены.\n\n" .. "-- ПОСЛЕДНИЕ --\nПредпоследняя запись будет удалена, если она совпадает с последней.\n\n" .. "-- ВСЕ --\nВсе записи, совпадающие с последней записью, будут удалены.", - ["zh-cn"] = "应该删除哪些重复记录。\n\n" .. - "-- 最新 --\n如果和最新一条匹配,则删除上一条记录。\n\n" .. - "-- 所有 --\n如果和最新一条匹配,则删除所有匹配的记录。", - ja = "重複した際にどの履歴を削除するか。\n\n" .. - "-- 直前 --\n直前の履歴が重複する場合、それを削除します。\n\n" .. - "-- すべて --\n重複するすべての履歴を削除します。", }, settings_last = { en = "Last", es = "Última", ru = "Последние", - ["zh-cn"] = "最新", - ja = "直前", }, settings_all = { en = "All", es = "Todas", ru = "Все", - ["zh-cn"] = "所有", - ja = "すべて", }, chat_history_commands_only = { en = "Save only executed commands", es = "Salvar unicamente los comandos ejecutados", ru = "Сохранять только выполненные команды", - ["zh-cn"] = "只保存执行的命令", - ja = "実行したコマンドのみを保存", }, chat_history_commands_only_description = { en = "Only successfully executed commands will be saved in the chat history.\n\n" .. @@ -362,50 +248,28 @@ return { "ATENCIÓN: Cambiar esta preferencia borra el historial del chat.", ru = "Только успешно выполненные команды будут сохранены в истории ввода.\n\n" .. "ВНИМАНИЕ: изменение этой настройки очистит вашу историю ввода.", - ["zh-cn"] = "只有成功执行的命令才会保存在聊天历史记录里。\n\n" .. - "警告:更改此设置会删除所有聊天历史记录。", - ja = "実行できたコマンドのみをチャット履歴に保存します。\n\n" .. - "警告:この設定を変更するとチャット履歴が消去されます。", }, chat_command_not_recognized = { en = "Command not recognized", - ["zh-cn"] = "无法识别的命令", - ru = "Команда не распознана", - ja = "不明なコマンド", }, clean_chat_history = { en = "cleans chat input history", es = "Borra el historial de usuario", ru = "очищает историю ввода", - ["zh-cn"] = "清除聊天输入历史记录", - ja = "チャット入力履歴の消去", }, clean_chat_notifications = { - en = "cleans chat notification alerts", - ["zh-cn"] = "清除聊天通知警告", - ru = "очищает предупреждения об уведомлениях чата", - ja = "チャット通知警告の消去", + en = "cleans chat notification alerts" }, dev_console_opened = { en = "Developer console opened.", es = "Abierto la consola de desarrollo.", ru = "Консоль разработчика открыта.", - ["zh-cn"] = "已打开开发者控制台。", - ja = "開発者コンソールを開きました。", }, dev_console_closed = { en = "Developer console closed.", es = "Cerrado la consola de desarrollo.", ru = "Консоль разработчика закрыта.", - ["zh-cn"] = "已关闭开发者控制台。", - ja = "開発者コンソールを閉じました。", - }, - dev_console_close_warning = { - en = "The developer console is disabled, but must be closed manually.", - ["zh-cn"] = "开发者控制台已禁用,但必须手动关闭。", - ru = "Консоль разработчика отключена, но ее необходимо закрыть вручную.", - ja = "開発者コンソールが無効になっていますが、手動で閉じる必要があります。", }, @@ -414,197 +278,116 @@ return { mutator_no_description_provided = { en = "No description provided.", es = "No se proporcionó una descripción.", - ["zh-cn"] = "未提供描述。", - ru = "Описание не предоставлено.", - ja = "説明がありません。", }, -- Difficulties' names lowest = { - en = "Sedition", - ["zh-cn"] = "煽动", - ru = "Мятеж", - ja = "反乱", + en = "Sedition" }, low = { - en = "Uprising", - ["zh-cn"] = "暴乱", - ru = "Восстание", - ja = "アップライジング", + en = "Uprising" }, medium = { - en = "Malice", - ["zh-cn"] = "憎恶", - ru = "Злоба", - ja = "悪意", + en = "Malice" }, high = { - en = "Heresy", - ["zh-cn"] = "异端", - ru = "Ересь", - ja = "異端", + en = "Heresy" }, highest = { - en = "Damnation", - ["zh-cn"] = "诅咒", - ru = "Проклятие", - ja = "破滅", + en = "Damnation" }, -- Chat messages broadcast_enabled_mutators = { en = "ENABLED MUTATORS", es = "MUTACIONES ACTIVADAS", - ["zh-cn"] = "启用突变器", - ru = "МУТАТОРЫ ВКЛЮЧЕНЫ", - ja = "ミューテーターが有効化されました", }, broadcast_all_disabled = { en = "ALL MUTATORS DISABLED", es = "TODAS LAS MUTACIONES DESACTIVADAS", - ["zh-cn"] = "禁用所有突变器", - ru = "ВСЕ МУТАТОРЫ ОТКЛЮЧЕНЫ", - ja = "すべてのミューテーターが無効化されました", }, broadcast_disabled_mutators = { en = "MUTATORS DISABLED", es = "MUTACIONES DESACTIVADAS", - ["zh-cn"] = "禁用突变器", - ru = "МУТАТОРЫ ОТКЛЮЧЕНЫ", - ja = "ミューテーターが無効化されました", }, local_disabled_mutators = { en = "Mutators disabled", es = "Mutaciones desactivadas", - ["zh-cn"] = "突变器已禁用", - ru = "Мутаторы отключены", - ja = "ミューテーターが無効化されました", }, whisper_enabled_mutators = { en = "[Automated message] This lobby has the following mutators active", es = "[Mensaje automático] Esta partida tiene las siguientes mutaciones", - ["zh-cn"] = "[自动消息] 此大厅激活了以下突变器", - ru = "[Автоматическое сообщение] В этом лобби активны следующие мутаторы", - ja = "[自動メッセージ] このロビーでは以下のミューテーターが有効になっています", }, disabled_reason_not_server = { en = "because you're no longer the host", es = "porque ya no eres el anfitrión", - ["zh-cn"] = "因为你不再是主机", - ru = "потому что вы больше не хост", - ja = "あなたがホストではなくなったため", }, disabled_reason_difficulty_change = { en = "DUE TO CHANGE IN DIFFICULTY", es = "DEBIDO A UN CAMBIO DE DIFICULTAD", - ["zh-cn"] = "由于难度变更", - ru = "ИЗ-ЗА ИЗМЕНЕНИЯ СЛОЖНОСТИ", - ja = "難易度が変更されたため", }, -- Interface mutators_title = { en = "Mutators", es = "Mutaciones", - ["zh-cn"] = "突变器", - ru = "Мутаторы", - ja = "ミューテーター", }, mutators_banner_description = { en = "Enable and disable mutators", es = "Activa y desactiva las mutaciones", - ["zh-cn"] = "启用和禁用突变器", - ru = "Включить и отключить мутаторы", - ja = "ミューテーターのオン/オフ", }, no_mutators = { en = "No mutators installed", es = "No hay mutaciones instaladas", - ["zh-cn"] = "未安装突变器", - ru = "Нет установленных мутаторов", - ja = "ミューテーターがインストールされていません", }, no_mutators_description = { en = "Subscribe to mods and mutators on the workshop", es = "Subscribete a mutaciones en el Steam Workshop", - ["zh-cn"] = "在创意工坊订阅模组和突变器", - ru = "Подпишитесь на моды и мутаторы в мастерской Steam", - ja = "ワークショップでModやミューテーターをサブスクライブしてください", }, -- Mutator widgets' tooltips tooltip_incompatible_mutators = { en = "\n\n-- INCOMPATIBLE WITH MUTATORS --\n", es = "\n\n-- INCOMPATIBLE CON LAS MUTACIONES --\n", - ["zh-cn"] = "\n\n-- 不兼容突变器 --\n", - ru = "\n\n-- НЕСОВМЕСТИМО С МУТАТОРАМИ --\n", - ja = "\n\n-- ミューテーターと互換性なし --\n", }, tooltip_compatible_mutators = { en = "\n\n-- COMPATIBLE ONLY WITH MUTATORS --\n", es = "\n\n-- COMPATIBLE CON LAS MUTACIONES --\n", - ["zh-cn"] = "\n\n-- 仅兼容突变器 --\n", - ru = "\n\n-- СОВМЕСТИМО ТОЛЬКО С МУТАТОРАМИ --\n", - ja = "\n\n-- ミューテーターとのみ互換性あり", }, tooltip_compatible_with_all_mutators = { en = "\n\n-- COMPATIBLE WITH ALL MUTATORS --", es = "\n\n-- COMPATIBLE CON TODAS LAS MUTACIONES --", - ["zh-cn"] = "\n\n-- 兼容所有突变器 --\n", - ru = "\n\n-- СОВМЕСТИМО СО ВСЕМИ МУТАТОРАМИ --\n", - ja = "\n\n-- すべてのミューテーターと互換性あり --\n", }, tooltip_incompatible_with_all_mutators = { en = "\n\n-- INCOMPATIBLE WITH ALL MUTATORS --", es = "\n\n-- INCOMPATIBLE CON TODAS LAS MUTACIONES --", - ["zh-cn"] = "\n\n-- 不兼容所有突变器 --\n", - ru = "\n\n-- НЕСОВМЕСТИМО СО ВСЕМИ МУТАТОРАМИ --\n", - ja = "\n\n-- すべてのミューテーターと互換性なし --\n", }, tooltip_incompatible_diffs = { en = "\n\n-- INCOMPATIBLE WITH DIFFICULTIES --\n", es = "\n\n-- INCOMPATIBLE CON LAS DIFICULTADES --\n", - ["zh-cn"] = "\n\n-- 不兼容难度 --\n", - ru = "\n\n-- НЕСОВМЕСТИМО СО СЛОЖНОСТЯМИ --\n", - ja = "\n\n-- 難易度と互換性なし --\n", }, tooltip_compatible_diffs = { en = "\n\n-- COMPATIBLE ONLY WITH DIFFICULTIES --\n", es = "\n\n-- COMPATIBLE CON LAS DIFICULTADES --\n", - ["zh-cn"] = "\n\n-- 仅兼容难度 --\n", - ru = "\n\n-- СОВМЕСТИМО ТОЛЬКО СО СЛОЖНОСТЯМИ --\n", - ja = "\n\n-- 難易度とのみ互換性あり --\n", }, tooltip_compatible_with_all_diffs = { en = "\n\n-- COMPATIBLE WITH ALL DIFFICULTIES --", es = "\n\n-- COMPATIBLE CON TODAS LAS DIFICULTADES --", - ["zh-cn"] = "\n\n-- 兼容所有难度 --\n", - ru = "\n\n-- СОВМЕСТИМО СО ВСЕМИ СЛОЖНОСТЯМИ --\n", - ja = "\n\n-- すべての難易度と互換性あり --\n", }, tooltip_conflicts = { en = "\n\n-- CONFLICTS --\n", es = "\n\n-- CONFLICTOS --\n", - ["zh-cn"] = "\n\n-- 冲突 --\n", - ru = "\n\n-- КОНФЛИКТЫ --\n", - ja = "\n\n-- 競合 --\n", }, tooltip_append_mutator = { en = " (mutator)", es = " (mutacion)", - ["zh-cn"] = "(突变)", - ru = " (мутатор)", - ja = " (ミューテーター)", }, tooltip_append_difficulty = { en = " (difficulty)", es = " (dificultad)", - ["zh-cn"] = "(难度)", - ru = " (сложность)", - ja = " (難易度)", }, } diff --git a/dmf/scripts/mods/dmf/modules/core/io.lua b/dmf/scripts/mods/dmf/modules/core/io.lua index 13a5880..1aa046e 100644 --- a/dmf/scripts/mods/dmf/modules/core/io.lua +++ b/dmf/scripts/mods/dmf/modules/core/io.lua @@ -7,9 +7,6 @@ if not _io.initialized then _io = dmf.deepcopy(Mods.lua.io) end --- Local backup of the loadstring function -local _loadstring = Mods.lua.loadstring - local _mod_directory = "./../mods" -- ##################################################################################################################### @@ -65,7 +62,7 @@ local function read_or_execute(file_path, args, return_type) -- Either execute the data or leave it unmodified if return_type == "exec_result" or return_type == "exec_boolean" then - local func = _loadstring(result, file_path) + local func = loadstring(result, file_path) result = func(args) end end diff --git a/dmf/scripts/mods/dmf/modules/core/keybindings.lua b/dmf/scripts/mods/dmf/modules/core/keybindings.lua index 3714424..f001b43 100644 --- a/dmf/scripts/mods/dmf/modules/core/keybindings.lua +++ b/dmf/scripts/mods/dmf/modules/core/keybindings.lua @@ -2,27 +2,197 @@ local dmf = get_mod("DMF") local InputUtils = require("scripts/managers/input/input_utils") -local MODIFIER_KEYS = { - ["keyboard_left shift"] = {160, "shift", "keyboard", 161}, - ["keyboard_right shift"] = {160, "shift", "keyboard", 161}, - ["keyboard_shift"] = {160, "shift", "keyboard", 161}, - ["keyboard_left ctrl"] = {162, "ctrl", "keyboard", 163}, - ["keyboard_right ctrl"] = {162, "ctrl", "keyboard", 163}, - ["keyboard_ctrl"] = {162, "ctrl", "keyboard", 163}, - ["keyboard_left alt"] = {164, "alt", "keyboard", 165}, - ["keyboard_right alt"] = {164, "alt", "keyboard", 165}, - ["keyboard_alt"] = {164, "alt", "keyboard", 165}, +local PRIMARY_BINDABLE_KEYS = { + ["keyboard"] = { + [8] = {"Backspace", "backspace"}, + [9] = {"Tab", "tab"}, + [13] = {"Enter", "enter"}, + [20] = {"Caps Lock", "caps lock"}, + [32] = {"Space", "space"}, + [33] = {"Page Up", "page up"}, + [34] = {"Page Down", "page down"}, + [35] = {"End", "end"}, + [36] = {"Home", "home"}, + [37] = {"Left", "left"}, + [38] = {"Up", "up"}, + [39] = {"Right", "right"}, + [40] = {"Down", "down"}, + [45] = {"Insert", "insert"}, + [46] = {"Delete", "delete"}, + [48] = {"0", "0"}, + [49] = {"1", "1"}, + [50] = {"2", "2"}, + [51] = {"3", "3"}, + [52] = {"4", "4"}, + [53] = {"5", "5"}, + [54] = {"6", "6"}, + [55] = {"7", "7"}, + [56] = {"8", "8"}, + [57] = {"9", "9"}, + [65] = {"A", "a"}, + [66] = {"B", "b"}, + [67] = {"C", "c"}, + [68] = {"D", "d"}, + [69] = {"E", "e"}, + [70] = {"F", "f"}, + [71] = {"G", "g"}, + [72] = {"H", "h"}, + [73] = {"I", "i"}, + [74] = {"J", "j"}, + [75] = {"K", "k"}, + [76] = {"L", "l"}, + [77] = {"M", "m"}, + [78] = {"N", "n"}, + [79] = {"O", "o"}, + [80] = {"P", "p"}, + [81] = {"Q", "q"}, + [82] = {"R", "r"}, + [83] = {"S", "s"}, + [84] = {"T", "t"}, + [85] = {"U", "u"}, + [86] = {"V", "v"}, + [87] = {"W", "w"}, + [88] = {"X", "x"}, + [89] = {"Y", "y"}, + [90] = {"Z", "z"}, + [91] = {"Win", "win"}, + [92] = {"RWin", "right win"}, + [96] = {"Num 0", "numpad 0"}, + [97] = {"Num 1", "numpad 1"}, + [98] = {"Num 2", "numpad 2"}, + [99] = {"Num 3", "numpad 3"}, + [100] = {"Num 4", "numpad 4"}, + [101] = {"Num 5", "numpad 5"}, + [102] = {"Num 6", "numpad 6"}, + [103] = {"Num 7", "numpad 7"}, + [104] = {"Num 8", "numpad 8"}, + [105] = {"Num 9", "numpad 9"}, + [106] = {"Num *", "numpad *"}, + [107] = {"Num +", "numpad +"}, + [109] = {"Num -", "numpad -"}, + [110] = {"Num .", "numpad ."}, + [111] = {"Num /", "numpad /"}, + [112] = {"F1", "f1"}, + [113] = {"F2", "f2"}, + [114] = {"F3", "f3"}, + [115] = {"F4", "f4"}, + [116] = {"F5", "f5"}, + [117] = {"F6", "f6"}, + [118] = {"F7", "f7"}, + [119] = {"F8", "f8"}, + [120] = {"F9", "f9"}, + [121] = {"F10", "f10"}, + [122] = {"F11", "f11"}, + [123] = {"F12", "f12"}, + [144] = {"Num Lock", "num lock"}, + [145] = {"Scroll Lock", "scroll lock"}, + [166] = {"Browser Back", "browser back"}, + [167] = {"Browser Forward", "browser forward"}, + [168] = {"Browser Refresh", "browser refresh"}, + [169] = {"Browser Stop", "browser stop"}, + [170] = {"Browser Search", "browser search"}, + [171] = {"Browser Favorites", "browser favorites"}, + [172] = {"Browser Home", "browser home"}, + [173] = {"Volume Mute", "volume mute"}, + [174] = {"Volume Down", "volume down"}, + [175] = {"Volume Up", "volume up"}, + [176] = {"Next Track", "next track"}, + [177] = {"Previous Track", "previous track"}, + [178] = {"Stop", "stop"}, + [179] = {"Play/Pause", "play pause"}, + [180] = {"Mail", "mail"}, + [181] = {"Media", "media"}, + [182] = {"Start Application 1", "start app 1"}, + [183] = {"Start Application 2", "start app 2"}, + [186] = {";", ";"}, + [187] = {"=", "="}, + [188] = {",", ","}, + [189] = {"-", "-"}, + [190] = {".", "."}, + [191] = {"/", "/"}, + [192] = {"`", "`"}, + [219] = {"[", "["}, + [220] = {"\\", "\\"}, + [221] = {"]", "]"}, + [222] = {"'", "'"}, + --?[226] = {"\", "oem_102 (> <)"}, + [256] = {"Num Enter", "numpad enter"} + }, + ["mouse"] = { + [0] = {"Mouse Left", "mouse left"}, + [1] = {"Mouse Right", "mouse right"}, + [2] = {"Mouse Middle", "mouse middle"}, + [3] = {"Mouse Extra 1", "mouse extra 1"}, + [4] = {"Mouse Extra 2", "mouse extra 2"}, + [10] = {"Mouse Wheel Up", "mouse wheel up"}, + [11] = {"Mouse Wheel Down", "mouse wheel down"}, + [12] = {"Mouse Wheel Left", "mouse wheel left"}, + [13] = {"Mouse Wheel Right", "mouse wheel right"} + }, + --[[ -- will work on this if it will be needed + ["gamepad"] = { + [0] = {"", "d_up"}, + [1] = {"", "d_down"}, + [2] = {"", "d_left"}, + [3] = {"", "d_right"}, + [4] = {"", "start"}, + [5] = {"", "back"}, + [6] = {"", "left_thumb"}, + [7] = {"", "right_thumb"}, + [8] = {"", "left_shoulder"}, + [9] = {"", "right_shoulder"}, + [10] = {"", "left_trigger"}, + [11] = {"", "right_trigger"}, + [12] = {"", "a"}, + [13] = {"", "b"}, + [14] = {"", "x"}, + [15] = {"", "y"}, + }]] } --- Both are treated equally in keybinds, but these global keys aren't localized -local MODIFIER_KEYS_LOC_ALIAS = { - keyboard_ctrl = "keyboard_left ctrl", - keyboard_alt = "keyboard_left alt", - keyboard_shift = "keyboard_left shift", +local OTHER_KEYS = { + -- modifier keys + ["left shift"] = {160, "Shift", "keyboard", 161}, + ["right shift"] = {160, "Shift", "keyboard", 161}, + ["shift"] = {160, "Shift", "keyboard", 161}, + ["left ctrl"] = {162, "Ctrl", "keyboard", 163}, + ["right ctrl"] = {162, "Ctrl", "keyboard", 163}, + ["ctrl"] = {162, "Ctrl", "keyboard", 163}, + ["left alt"] = {164, "Alt", "keyboard", 165}, + ["right alt"] = {164, "Alt", "keyboard", 165}, + ["alt"] = {164, "Alt", "keyboard", 165}, + -- hack for 'dmf.build_keybind_string' function + ["no_button"] = {-1, ""} +} + +local KEYS_INFO = {} + +-- Populate KEYS_INFO: Index, readable name, device name +for input_device_name, input_device_keys in pairs(PRIMARY_BINDABLE_KEYS) do + for key_index, key_info in pairs(input_device_keys) do + KEYS_INFO[key_info[2]] = {key_index, key_info[1], input_device_name} + end +end + +for key_id, key_data in pairs(OTHER_KEYS) do + KEYS_INFO[key_id] = key_data +end + +-- Can't use 'Device.released' because it will break keybinds if button is released when game window is not active. +local CHECK_INPUT_FUNCTIONS = { + keyboard = { + PRESSED = function(key_id) return Keyboard.pressed(KEYS_INFO[key_id][1]) end, + RELEASED = function(key_id) return Keyboard.button(KEYS_INFO[key_id][1]) == 0 end + }, + mouse = { + PRESSED = function(key_id) return Mouse.pressed(KEYS_INFO[key_id][1]) end, + RELEASED = function(key_id) return Mouse.button(KEYS_INFO[key_id][1]) == 0 end + } } local _raw_keybinds_data = {} local _keybinds = {} +local _pressed_key local ERRORS = { PREFIX = { @@ -33,17 +203,12 @@ local ERRORS = { } } -local SUPPORTED_DEVICES = { - "keyboard", - "mouse", -} - -- ##################################################################################################################### -- ##### Local functions ############################################################################################### -- ##################################################################################################################### --- @TODO: Link this input service to the player's input service and find some way to see if it's blocked local function is_dmf_input_service_active() + -- @TODO: Implement check for active DMF input service return true end @@ -74,261 +239,115 @@ local function perform_keybind_action(data, is_pressed) end end - --- ##################################################################################################################### --- ##### Input service functions ####################################################################################### --- ##################################################################################################################### - -local function is_modifier_pressed(modifier) - return (Keyboard.button(MODIFIER_KEYS[modifier][1]) + Keyboard.button(MODIFIER_KEYS[modifier][4])) > 0 -end - -local function default_boolean() - return false -end - -local function default_vector3() - return Vector3(0, 0, 0) -end - -local function default_float() - return 0 -end - -local function boolean_combine(value_one, value_two) - return value_one or value_two -end - -local function vector3_combine(value_one, value_two) - if Vector3.length(value_two) < Vector3.length(value_one) then - return value_one - else - return value_two - end -end - -local function float_combine(value_one, value_two) - return math.max(value_one, value_two) -end - -local ACTION_TYPES = { - pressed = { - device_func = "pressed", - type = "boolean", - default_device_func = default_boolean, - combine_func = boolean_combine - }, - held = { - device_func = "held", - type = "boolean", - default_device_func = default_boolean, - combine_func = boolean_combine - }, - released = { - device_func = "released", - type = "boolean", - default_device_func = default_boolean, - combine_func = boolean_combine - }, - axis = { - device_func = "axis", - type = "vector3", - default_device_func = default_vector3, - combine_func = vector3_combine - }, - button = { - device_func = "button", - type = "float", - default_device_func = default_float, - combine_func = float_combine - } -} - - -local function _enabler_func(cb, action_type, enablers) - for _, enabler in ipairs(enablers) do - if not enabler.device:held(enabler.index) then - return ACTION_TYPES[action_type].default_device_func() - end - end - - return cb() -end - - -local function _disabler_func(cb, action_type, disablers) - for _, disabler in ipairs(disablers) do - if disabler.device:held(disabler.index) then - return ACTION_TYPES[action_type].default_device_func() - end - end - - return cb() -end - - -local function get_corresponding_device(key_id) - for _, device_type in pairs(SUPPORTED_DEVICES) do - - local device = Managers.input:_find_active_device(device_type) - if device then - - local index = device:button_index(key_id) - if index then - return { - device = device, - index = index, - key_id = key_id, - } - end - - index = device:axis_index(key_id) - if index then - return { - device = device, - index = index, - key_id = key_id, - } - end - end - end -end - - -local function get_key_info(keybind) - local main = keybind.main - local e = keybind.enablers - local d = keybind.disablers - - local info = get_corresponding_device(main) - - if info then - if #e > 0 then - local enablers = {} - - for _, key in ipairs(e) do - local enabler = get_corresponding_device(key) - - if enabler then - enablers[#enablers + 1] = enabler - end - end - - info.enablers = enablers - end - - if #d > 0 then - local disablers = {} - - for _, key in ipairs(d) do - local disabler = get_corresponding_device(key) - - if disabler then - disablers[#disablers + 1] = disabler - end - end - - info.disablers = disablers - end - end - - return info -end - - -local function create_eval_func(keybind) - local info = get_key_info(keybind) - if info then - - local eval_func - if keybind.trigger == "held" then - eval_func = callback(info.device, keybind.trigger, info.index) - else - local function func(device, trigger, index) - return device[trigger](index) - end - - eval_func = callback(func, info.device:raw_device(), keybind.trigger, info.index) - end - - if info.enablers then - eval_func = callback(_enabler_func, eval_func, keybind.trigger, info.enablers) - end - - if info.disablers then - eval_func = callback(_disabler_func, eval_func, keybind.trigger, info.disablers) - end - - return eval_func - end -end - -- ##################################################################################################################### -- ##### DMF internal functions and variables ########################################################################## -- ##################################################################################################################### -- Checks for pressed and released keybinds, performs keybind actions. --- * Right and left key modifiers (ctrl, alt, shift) are checked separately. --- * If several mods bound the same keys, keybind action will be performed for all of them when pressed. --- * Keybind is considered released when it was previously pressed and is no longer. +-- * Checks for both right and left key modifiers (ctrl, alt, shift). +-- * If some keybind is pressed, won't check for other keybinds until this keybind is released. +-- * If several mods bound the same keys, keybind action will be performed for all of them, when keybind is pressed. +-- * Keybind is considered released, when its primary key is released. function dmf.check_keybinds() + local ctrl_pressed = (Keyboard.button(KEYS_INFO["ctrl"][1]) + Keyboard.button(KEYS_INFO["ctrl"][4])) > 0 + local alt_pressed = (Keyboard.button(KEYS_INFO["alt"][1]) + Keyboard.button(KEYS_INFO["alt"][4])) > 0 + local shift_pressed = (Keyboard.button(KEYS_INFO["shift"][1]) + Keyboard.button(KEYS_INFO["shift"][4])) > 0 - -- For every keybind - for _, keybind_data in ipairs(_keybinds) do + if not _pressed_key then + for primary_key, keybinds_data in pairs(_keybinds) do + if keybinds_data.check_pressed(primary_key) then + for _, keybind_data in ipairs(keybinds_data) do - -- If the keybind is pressed - if keybind_data.eval_func() then + local all_pressed = true + for enabler, _ in pairs(keybind_data.enablers) do - -- Peform the keybind action once - if (not keybind_data.pressed) and perform_keybind_action(keybind_data, true) then + -- Check that every enabler key is pressed + if OTHER_KEYS[enabler] and + ( + Keyboard.button(KEYS_INFO[enabler][1]) + + Keyboard.button(KEYS_INFO[enabler][4]) + ) <= 0 + or not (Keyboard.button(KEYS_INFO[enabler][1]) > 0) + then + all_pressed = false + break + end + end - -- Queue the release action if applicable - if keybind_data.trigger == "held" then - keybind_data.release_action = true + -- Check that no modifier keys are pressed that shouldn't be + if all_pressed and + (not keybind_data.ctrl and ctrl_pressed) and + (not keybind_data.alt and alt_pressed) and + (not keybind_data.shift and shift_pressed) + then + all_pressed = false + end + + -- Peform the keybind action if everything validates + if all_pressed then + if perform_keybind_action(keybind_data, true) then + if keybind_data.trigger == "held" then + keybind_data.release_action = true + end + _pressed_key = primary_key + end + end + end + if _pressed_key then + break end - - -- Prevent a repeat action - keybind_data.pressed = true end + end + end - -- If the keybind was previously but is no longer pressed - elseif keybind_data.pressed then - - -- Reactivate the keybind - keybind_data.pressed = nil - - -- Play the release action if applicable - if keybind_data.release_action then - perform_keybind_action(keybind_data, false) - keybind_data.release_action = nil + if _pressed_key then + if _keybinds[_pressed_key].check_released(_pressed_key) then + for _, keybind_data in ipairs(_keybinds[_pressed_key]) do + if keybind_data.release_action then + perform_keybind_action(keybind_data, false) + keybind_data.release_action = nil + end end + _pressed_key = nil end end end --- Converts manageable (raw) table of keybinds data to a table of callbacks for checking pressed and --- released keybinds. After initial call it must be called every time some keybind is added/removed. +-- Converts managable (raw) table of keybinds data to the table designed for the function checking for pressed and +-- released keybinds. After initial call requires to be called every time some keybind is added/removed. function dmf.generate_keybinds() _keybinds = {} for mod, mod_keybinds in pairs(_raw_keybinds_data) do for _, raw_keybind_data in pairs(mod_keybinds) do + local keys = raw_keybind_data.keys + local primary_key = keys[1] + local modifier_keys = {} + for i = 2, #keys do + modifier_keys[keys[i]] = true + end + local keybind_data = { - mod = mod, - global = raw_keybind_data.global, - trigger = raw_keybind_data.trigger, - type = raw_keybind_data.type, - eval_func = create_eval_func(raw_keybind_data), + mod = mod, + global = raw_keybind_data.global, + trigger = raw_keybind_data.trigger, + type = raw_keybind_data.type, + enablers = modifier_keys, + ctrl = modifier_keys["ctrl"] or modifier_keys["left ctrl"] or modifier_keys["right ctrl"], + alt = modifier_keys["alt"] or modifier_keys["left alt"] or modifier_keys["right alt"], + shift = modifier_keys["shift"] or modifier_keys["left shift"] or modifier_keys["right shift"], function_name = raw_keybind_data.function_name, view_name = raw_keybind_data.view_name } - if keybind_data.eval_func then - table.insert(_keybinds, keybind_data) - end + _keybinds[primary_key] = _keybinds[primary_key] or { + check_pressed = CHECK_INPUT_FUNCTIONS[KEYS_INFO[primary_key][3]].PRESSED, + check_released = CHECK_INPUT_FUNCTIONS[KEYS_INFO[primary_key][3]].RELEASED + } + table.insert(_keybinds[primary_key], keybind_data) end end end @@ -336,7 +355,7 @@ end -- Adds/removes keybinds. function dmf.add_mod_keybind(mod, setting_id, raw_keybind_data) - if raw_keybind_data.main then + if #raw_keybind_data.keys > 0 then _raw_keybinds_data[mod] = _raw_keybinds_data[mod] or {} _raw_keybinds_data[mod][setting_id] = raw_keybind_data elseif _raw_keybinds_data[mod] and _raw_keybinds_data[mod][setting_id] then @@ -352,32 +371,55 @@ end -- Creates DMF input service. It is required to know when non-global keybinds can be triggered. -- (Called every time a level is loaded, or on mods reload) --- @TODO: Link this input service to the player's input service and find some way to see if it's blocked function dmf.create_keybinds_input_service() - -- -- To create the DMF input service in Darktide - -- local input_manager = Managers.input - -- local service_type = "DMF" - -- input_manager:add_setting(service_type, aliases, raw_key_table, filter_table, default_devices) - -- input_manager:get_input_service(service_type) + -- @TODO: Link this input service to the player's input service and find some way to see if it's blocked + --[[ + -- To create the DMF input service in Darktide + local input_manager = Managers.input + local service_type = "DMF" + input_manager:add_setting(service_type, aliases, raw_key_table, filter_table, default_devices) + input_manager:get_input_service(service_type) + --]] end --- @TODO: So far it seems like any key can be a primary keybind, but is this actually true? +-- Converts key_index to readable key_id, which is used by DMF to identify keys. +-- (Used for capturing keybinds) +function dmf.get_key_id(device, key_index) + local key_info = PRIMARY_BINDABLE_KEYS[device][key_index] + return key_info and key_info[2] +end + + +-- Simply tells if key with key_id can be binded as primary key. +-- (Used for verifying keybind widgets) function dmf.can_bind_as_primary_key(key_id) - return true + return KEYS_INFO[key_id] and not OTHER_KEYS[key_id] end --- Translate keywatch result to array of local key names --- (Used in keybind widget for compatibility with legacy settings) -function dmf.keywatch_result_to_local_keys(keywatch_result) +-- Builds string with readable keys' names to look like "Primary Key + Ctrl + Alt + Shift". +-- (Used in keybind widget) +function dmf.build_keybind_string(keys) + local readable_key_names = {} + for _, key_id in ipairs(keys) do + table.insert(readable_key_names, KEYS_INFO[key_id][2]) + end + return table.concat(readable_key_names, " + ") +end + + +-- Translate key watch result to mod options keybind +-- (Used in keybind widget) +function dmf.keybind_result_to_keys(keybind_result) local keys = {} -- Get the local name of the main key - if keywatch_result.main then + if keybind_result.main then - local global_name = keywatch_result.main - local local_name = InputUtils.local_key_name(global_name, InputUtils.key_device_type(global_name)) + local global_name = keybind_result.main + local device_type = InputUtils.key_device_type(global_name) + local local_name = InputUtils.local_key_name(global_name, device_type) -- Check for a missing or unbindable primary key name if not local_name or not dmf.can_bind_as_primary_key(local_name) then @@ -388,9 +430,12 @@ function dmf.keywatch_result_to_local_keys(keywatch_result) end -- Add the enablers keys as additional keys - if keywatch_result.enablers then - for _, global_name in ipairs(keywatch_result.enablers) do - local local_name = InputUtils.local_key_name(global_name, InputUtils.key_device_type(global_name)) + if keybind_result.enablers then + for _, global_name in ipairs(keybind_result.enablers) do + + local device_type = InputUtils.key_device_type(global_name) + local local_name = InputUtils.local_key_name(global_name, device_type) + keys[#keys + 1] = local_name end end @@ -399,63 +444,41 @@ function dmf.keywatch_result_to_local_keys(keywatch_result) end --- Translate array of local key names to keywatch result --- (Used in keybind widget for compatibility with legacy settings) -function dmf.local_keys_to_keywatch_result(keys) - local keywatch_result = { +-- Translate mod options keybind to key watch result +-- (Used in keybind widget) +function dmf.keys_to_keybind_result(keys) + local keybind_result = { enablers = {}, disablers = {} } - if type(keys) ~= "table" or #keys == 0 then + if not keys or #keys == 0 then return nil end if keys[1] then local local_name = keys[1] - local global_name - - -- Check all supported devices for the global name - for _, device_type in ipairs(SUPPORTED_DEVICES) do - global_name = InputUtils.local_to_global_name(local_name, device_type) - if get_corresponding_device(global_name) then - break - end - end + local global_name = KEYS_INFO[local_name] and InputUtils.local_to_global_name(local_name, KEYS_INFO[local_name][3]) -- End early if our main key doesn't exist, and return an empty result if not global_name then return nil end - if MODIFIER_KEYS_LOC_ALIAS[global_name] then - global_name = MODIFIER_KEYS_LOC_ALIAS[global_name] - end - keywatch_result.main = global_name + keybind_result.main = global_name end -- Add all remaining keys to the enablers list for i = 2, #keys do local local_name = keys[i] - local global_name - - -- Check all supported devices for the global name - for _, device_type in ipairs(SUPPORTED_DEVICES) do - global_name = InputUtils.local_to_global_name(local_name,device_type) - if get_corresponding_device(global_name) then - break - end - end + local global_name = KEYS_INFO[local_name] and InputUtils.local_to_global_name(local_name, KEYS_INFO[local_name][3]) if global_name then - if MODIFIER_KEYS_LOC_ALIAS[global_name] then - global_name = MODIFIER_KEYS_LOC_ALIAS[global_name] - end - keywatch_result.enablers[#keywatch_result.enablers + 1] = global_name + keybind_result.enablers[#keybind_result.enablers + 1] = global_name end end - return keywatch_result + return keybind_result end -- ##################################################################################################################### diff --git a/dmf/scripts/mods/dmf/modules/core/localization.lua b/dmf/scripts/mods/dmf/modules/core/localization.lua index 00b8a46..27283b5 100644 --- a/dmf/scripts/mods/dmf/modules/core/localization.lua +++ b/dmf/scripts/mods/dmf/modules/core/localization.lua @@ -91,12 +91,13 @@ end -- ##### DMF internal functions and variables ######################################################################### -- #################################################################################################################### -dmf:hook(LocalizationManager, "localize", function (func, self, text_id, ...) +-- Handles the return of global localize text_ids +dmf:hook(_G, "Localize", function (func, text_id, ...) local text_translations = text_id and _global_localization_database[text_id] local message = get_translated_or_english_message(nil, text_translations, ...) - return message or func(self, text_id, ...) + return message or func(text_id, ...) end) -- #################################################################################################################### @@ -127,7 +128,7 @@ dmf.quick_localize = function (mod, text_id) if mod_localization_table then local text_translations = mod_localization_table[text_id] - + if text_translations then return text_translations[_language_id] or text_translations["en"] end diff --git a/dmf/scripts/mods/dmf/modules/core/options.lua b/dmf/scripts/mods/dmf/modules/core/options.lua index e8fbe82..58cc515 100644 --- a/dmf/scripts/mods/dmf/modules/core/options.lua +++ b/dmf/scripts/mods/dmf/modules/core/options.lua @@ -117,12 +117,11 @@ local function initialize_generic_widget_data(mod, data, localize) new_data.mod_name = mod:get_name() -- Defined in widget - new_data.type = data.type - new_data.setting_id = data.setting_id - new_data.title = data.title -- optional, if (localize == true) - new_data.tooltip = data.tooltip -- optional - new_data.default_value = data.default_value - new_data.require_restart = data.require_restart -- optional + new_data.type = data.type + new_data.setting_id = data.setting_id + new_data.title = data.title -- optional, if (localize == true) + new_data.tooltip = data.tooltip -- optional + new_data.default_value = data.default_value -- Overwrite global optons localization setting if widget defined it if data.localize == nil then @@ -301,6 +300,11 @@ local allowed_keybind_types = { view_toggle = true, mod_toggle = true } +local allowed_modifier_keys = { + ctrl = true, + alt = true, + shift = true +} local function validate_keybind_data(data) if data.keybind_global and type(data.keybind_global) ~= "boolean" then dmf.throw_error("[widget \"%s\" (keybind)]: 'keybind_global' field must have 'boolean' type", data.setting_id) @@ -339,6 +343,13 @@ local function validate_keybind_data(data) if default_value[1] and not dmf.can_bind_as_primary_key(default_value[1]) then dmf.throw_error("[widget \"%s\" (keybind)]: 'default_value[1]' must be a valid key name", data.setting_id) end + if default_value[2] and not allowed_modifier_keys[default_value[2]] or + default_value[3] and not allowed_modifier_keys[default_value[3]] or + default_value[4] and not allowed_modifier_keys[default_value[4]] + then + dmf.throw_error("[widget \"%s\" (keybind)]: 'default_value [2], [3] and [4]' can be only strings: \"ctrl\", " .. + "\"alt\" and \"shift\" (in no particular order)", data.setting_id) + end local used_keys = {} for _, key in ipairs(default_value) do @@ -534,23 +545,18 @@ local function initialize_default_settings_and_keybinds(mod, initialized_widgets mod:set(data.setting_id, data.default_value) end if data.type == "keybind" then - local keywatch_result = dmf.local_keys_to_keywatch_result(mod:get(data.setting_id)) - if keywatch_result and keywatch_result.main then - dmf.add_mod_keybind( - mod, - data.setting_id, - { - global = data.keybind_global, - trigger = data.keybind_trigger, - type = data.keybind_type, - main = keywatch_result.main, - enablers = keywatch_result.enablers, - disablers = keywatch_result.disablers, - function_name = data.function_name, - view_name = data.view_name - } - ) - end + dmf.add_mod_keybind( + mod, + data.setting_id, + { + global = data.keybind_global, + trigger = data.keybind_trigger, + type = data.keybind_type, + keys = mod:get(data.setting_id), + function_name = data.function_name, + view_name = data.view_name + } + ) end end end diff --git a/dmf/scripts/mods/dmf/modules/core/safe_calls.lua b/dmf/scripts/mods/dmf/modules/core/safe_calls.lua index 866aaeb..2b25193 100644 --- a/dmf/scripts/mods/dmf/modules/core/safe_calls.lua +++ b/dmf/scripts/mods/dmf/modules/core/safe_calls.lua @@ -87,7 +87,7 @@ function dmf.safe_call_dofile(mod, error_prefix_data, file_path) show_error(mod, error_prefix_data, "file path should be a string.") return false end - return dmf.safe_call(mod, error_prefix_data, dofile, file_path) + return dmf.safe_call(mod, error_prefix_data, dofile, mod, file_path) end diff --git a/dmf/scripts/mods/dmf/modules/debug/dev_console.lua b/dmf/scripts/mods/dmf/modules/debug/dev_console.lua index 1916438..bcc49a2 100644 --- a/dmf/scripts/mods/dmf/modules/debug/dev_console.lua +++ b/dmf/scripts/mods/dmf/modules/debug/dev_console.lua @@ -49,24 +49,16 @@ local function close_dev_console() CommandWindow.close() - -- CommandWindow won't close by itself, so it has to be closed through FFI - if _ffi then - dmf:pcall(function() - if _ffi then - _ffi.cdef([[ - void* FindWindowA(const char* lpClassName, const char* lpWindowName); - int64_t SendMessageA(void* hWnd, unsigned int Msg, uint64_t wParam, int64_t lParam); - ]]) - local WM_CLOSE = 0x10; - local hwnd = _ffi.C.FindWindowA("ConsoleWindowClass", "Developer console") - _ffi.C.SendMessageA(hwnd, WM_CLOSE, 0, 0) - end - end) - - -- Or manually closed by the user - else - dmf:warning(dmf:localize("dev_console_close_warning")) - end + -- CommandWindow won't close by itself, so it have to be closed manually + dmf:pcall(function() + _ffi.cdef([[ + void* FindWindowA(const char* lpClassName, const char* lpWindowName); + int64_t SendMessageA(void* hWnd, unsigned int Msg, uint64_t wParam, int64_t lParam); + ]]) + local WM_CLOSE = 0x10; + local hwnd = _ffi.C.FindWindowA("ConsoleWindowClass", "Developer console") + _ffi.C.SendMessageA(hwnd, WM_CLOSE, 0, 0) + end) _console_data.enabled = false end diff --git a/dmf/scripts/mods/dmf/modules/debug/table_dump.lua b/dmf/scripts/mods/dmf/modules/debug/table_dump.lua index 8ba3b2f..bce18d3 100644 --- a/dmf/scripts/mods/dmf/modules/debug/table_dump.lua +++ b/dmf/scripts/mods/dmf/modules/debug/table_dump.lua @@ -7,7 +7,7 @@ if not _io.initialized then _io = dmf.deepcopy(Mods.lua.io) end --- Local backup of the os library +-- Local backup of the io library local _os = dmf:persistent_table("_os") _os.initialized = _os.initialized or false if not _os.initialized then @@ -17,11 +17,6 @@ end -- Global backup of original print() method local print = __print -local function log_and_console_print(message, ...) - print(message, ...) - CommandWindow.print(message, ...) -end - local function table_dump(key, value, depth, max_depth) if max_depth < depth then return @@ -33,7 +28,7 @@ local function table_dump(key, value, depth, max_depth) if value_type == "table" then prefix = prefix .. ((key == nil and "") or " = ") - log_and_console_print(prefix .. "table") + print(prefix .. "table") for key_, value_ in pairs(value) do table_dump(key_, value_, depth + 1, max_depth) @@ -43,9 +38,9 @@ local function table_dump(key, value, depth, max_depth) if meta then if type(meta) == "boolean" then - log_and_console_print(prefix .. "protected metatable") + print(prefix .. "protected metatable") else - log_and_console_print(prefix .. "metatable") + print(prefix .. "metatable") for key_, value_ in pairs(meta) do if key_ ~= "__index" and key_ ~= "super" then table_dump(key_, value_, depth + 1, max_depth) @@ -54,28 +49,24 @@ local function table_dump(key, value, depth, max_depth) end end elseif value_type == "function" or value_type == "thread" or value_type == "userdata" or value == nil then - log_and_console_print(prefix .. " = " .. tostring(value)) + print(prefix .. " = " .. tostring(value)) else - log_and_console_print(prefix .. " = " .. tostring(value) .. " (" .. value_type .. ")") + print(prefix .. " = " .. tostring(value) .. " (" .. value_type .. ")") end end -DMFMod.dump = function (self, dumped_object, object_name, max_depth) - if dmf.check_wrong_argument_type(self, "dump", "dumped_object_name", object_name, "string", "nil") or - dmf.check_wrong_argument_type(self, "dump", "max_depth", max_depth, "number", "nil") +DMFMod.dump = function (self, dumped_object, dumped_object_name, max_depth) + + if dmf.check_wrong_argument_type(self, "dump", "dumped_object_name", dumped_object_name, "string", "nil") or + dmf.check_wrong_argument_type(self, "dump", "max_depth", max_depth, "number") then return end local object_type = type(dumped_object) - max_depth = max_depth or 1 if object_type ~= "table" then - local error_message = string.format( - '(dump): "%s" is not a table but of type "%s"', - object_name or "Dump object", - object_type - ) + local error_message = "(dump): \"object_name\" is not a table. It's " .. object_type if object_type ~= "nil" then error_message = error_message .. " (" .. tostring(dumped_object) .. ")" @@ -85,8 +76,13 @@ DMFMod.dump = function (self, dumped_object, object_name, max_depth) return end - if object_name then - log_and_console_print(string.format("<%s>", object_name)) + if dumped_object_name then + print(string.format("<%s>", dumped_object_name)) + end + + if not max_depth then + self:error("(dump): maximum depth is not specified") + return end local success, error_message = pcall(function() @@ -99,12 +95,17 @@ DMFMod.dump = function (self, dumped_object, object_name, max_depth) self:error("(dump): %s", tostring(error_message)) end - if object_name then - log_and_console_print(string.format("", object_name)) + if dumped_object_name then + print(string.format("", dumped_object_name)) end end + + + + + local function table_dump_to_file(dumped_table, dumped_table_name, max_depth) -- ##################### @@ -342,22 +343,17 @@ end DMFMod.dump_to_file = function (self, dumped_object, object_name, max_depth) - if dmf.check_wrong_argument_type(self, "dump_to_file", "object_name", object_name, "string", "nil") or - dmf.check_wrong_argument_type(self, "dump_to_file", "max_depth", max_depth, "number", "nil") + + if dmf.check_wrong_argument_type(self, "dump_to_file", "object_name", object_name, "string") or + dmf.check_wrong_argument_type(self, "dump_to_file", "max_depth", max_depth, "number") then return end local object_type = type(dumped_object) - object_name = object_name or "mod_dump_to_file" - max_depth = max_depth or 1 if object_type ~= "table" then - local error_message = string.format( - '(dump_to_file): "%s" is not a table but of type "%s"', - object_name or "Dump object", - object_type - ) + local error_message = "(dump_to_file): \"object_name\" is not a table. It's " .. object_type if object_type ~= "nil" then error_message = error_message .. " (" .. tostring(dumped_object) .. ")" diff --git a/dmf/scripts/mods/dmf/modules/dmf_mod_manager.lua b/dmf/scripts/mods/dmf/modules/dmf_mod_manager.lua index fe70f0b..54cd02c 100644 --- a/dmf/scripts/mods/dmf/modules/dmf_mod_manager.lua +++ b/dmf/scripts/mods/dmf/modules/dmf_mod_manager.lua @@ -169,7 +169,7 @@ function dmf.initialize_mod_data(mod, mod_data) end -- Mod's options initialization - if mod_data.options or (not mod_data.is_mutator and not mod_data.options_widgets) then + if mod_data.options or ((mod_data.is_togglable and not mod_data.is_mutator) and not mod_data.options_widgets) then local success, error_message = pcall(dmf.initialize_mod_options, mod, mod_data.options) if not success then mod:error(ERRORS.REGULAR.mod_options_initializing_failed, error_message) diff --git a/dmf/scripts/mods/dmf/modules/dmf_options.lua b/dmf/scripts/mods/dmf/modules/dmf_options.lua index c8ccf72..573c591 100644 --- a/dmf/scripts/mods/dmf/modules/dmf_options.lua +++ b/dmf/scripts/mods/dmf/modules/dmf_options.lua @@ -16,7 +16,7 @@ dmf_mod_data.options = { setting_id = "dmf_options_scrolling_speed", type = "numeric", default_value = 100, - range = {50, 500}, + range = {1, 1000}, unit_text = "percent" }, { @@ -38,16 +38,16 @@ dmf_mod_data.options = { keybind_type = "function_call", function_name = "toggle_developer_console" }, - -- { - -- setting_id = "show_network_debug_info", - -- type = "checkbox", - -- default_value = false - -- }, - -- { - -- setting_id = "log_ui_renderers_info", - -- type = "checkbox", - -- default_value = false - -- } + { + setting_id = "show_network_debug_info", + type = "checkbox", + default_value = false + }, + { + setting_id = "log_ui_renderers_info", + type = "checkbox", + default_value = false + } } }, { diff --git a/dmf/scripts/mods/dmf/modules/gui/custom_views.lua b/dmf/scripts/mods/dmf/modules/gui/custom_views.lua index 3ed848a..97b866f 100644 --- a/dmf/scripts/mods/dmf/modules/gui/custom_views.lua +++ b/dmf/scripts/mods/dmf/modules/gui/custom_views.lua @@ -7,8 +7,6 @@ local _custom_views_data = {} local _ingame_ui local _loaded_views = {} -local _key_watch = false - local ERRORS = { THROWABLE = { -- inject_view: @@ -314,13 +312,13 @@ end -- Track the creation of the view loader -dmf:hook_safe(CLASS.ViewLoader, "init", function() +dmf:hook_safe(ViewLoader, "init", function() _custom_view_persistent_data.loader_initialized = true end) -- Track the loading of views, set the loader flag if class selection is reached -dmf:hook_safe(CLASS.UIManager, "load_view", function(self, view_name) +dmf:hook_safe(UIManager, "load_view", function(self, view_name) if view_name == "class_selection_view" then _custom_view_persistent_data.loader_initialized = true end @@ -328,13 +326,13 @@ dmf:hook_safe(CLASS.UIManager, "load_view", function(self, view_name) end) -- Track the unloading of views -dmf:hook_safe(CLASS.UIManager, "unload_view", function(self, view_name) +dmf:hook_safe(UIManager, "unload_view", function(self, view_name) _loaded_views[view_name] = nil end) -- Store the view handler for later use and inject views -dmf:hook_safe(CLASS.UIViewHandler, "init", function(self) +dmf:hook_safe(UIViewHandler, "init", function(self) _ingame_ui = self for view_name, _ in pairs(_custom_views_data) do if not dmf.safe_call_nrc(self, {ERRORS.PREFIX.ingameui_hook_injection, view_name}, inject_view, view_name) then @@ -343,16 +341,6 @@ dmf:hook_safe(CLASS.UIViewHandler, "init", function(self) end end) --- Track the start of key watches -dmf:hook_safe(CLASS.InputManager, "start_key_watch", function(self) - _key_watch = true -end) - --- Track the end of key watches -dmf:hook_safe(CLASS.InputManager, "stop_key_watch", function(self) - _key_watch = false -end) - -- ##################################################################################################################### -- ##### DMF internal functions and variables ########################################################################## -- ##################################################################################################################### @@ -380,8 +368,8 @@ function dmf.keybind_toggle_view(mod, view_name, keybind_transition_data, can_pe -- If the view is open, this is a toggle close if Managers.ui:view_active(view_name) then - -- Don't close the view if it's already closing or we have an active key watch - if not Managers.ui:is_view_closing(view_name) and not _key_watch then + -- Don't close the view if it's already closing + if not Managers.ui:is_view_closing(view_name) then local force_close = true Managers.ui:close_view(view_name, force_close) end diff --git a/dmf/scripts/mods/dmf/modules/ui/chat/chat_actions.lua b/dmf/scripts/mods/dmf/modules/ui/chat/chat_actions.lua index 1778c19..eaa7fbc 100644 --- a/dmf/scripts/mods/dmf/modules/ui/chat/chat_actions.lua +++ b/dmf/scripts/mods/dmf/modules/ui/chat/chat_actions.lua @@ -80,6 +80,8 @@ end dmf:hook("ConstantElementChat", "_handle_active_chat_input", function(func, self, input_service, ui_renderer, ...) initialize_drawing_function() + local command_executed = false + _chat_message = get_chat_message(self) _chat_opened = true @@ -126,6 +128,8 @@ dmf:hook("ConstantElementChat", "_handle_active_chat_input", function(func, self set_chat_message(self, "") + command_executed = true + elseif string.sub(_chat_message, 1, 1) == "/" then dmf:notify(dmf:localize("chat_command_not_recognized") .. ": " .. _chat_message) set_chat_message(self, "") diff --git a/dmf/scripts/mods/dmf/modules/ui/chat/commands_list_gui.lua b/dmf/scripts/mods/dmf/modules/ui/chat/commands_list_gui.lua index a06f987..7aad8cf 100644 --- a/dmf/scripts/mods/dmf/modules/ui/chat/commands_list_gui.lua +++ b/dmf/scripts/mods/dmf/modules/ui/chat/commands_list_gui.lua @@ -5,12 +5,13 @@ local MULTISTRING_INDICATOR_TEXT = "[...]" local DEFAULT_HUD_SCALE = 100 local FONT_TYPE = "arial" +local FONT_MATERIAL = "content/ui/fonts/arial" local FONT_SIZE = 22 local MAX_COMMANDS_VISIBLE = 5 local STRING_HEIGHT = 25 -local STRING_Y_OFFSET = 2 +local STRING_Y_OFFSET = 7 local STRING_X_MARGIN = 10 local OFFSET_X = 10 @@ -56,7 +57,8 @@ local function get_hud_scale() end -local function get_text_size(text, font_data, font_size) +local function get_text_size(text, font_type, font_size) + local font_data = Managers.font:data_by_type(font_type) local font = font_data.path local additional_settings = { flags = font_data.render_flags or 0 @@ -79,11 +81,11 @@ local function get_text_width(text, font, font_size) end -local function get_scaled_font_size_by_width(text, font_data, font_size, max_width) +local function get_scaled_font_size_by_width(text, font_type, font_size, max_width) local scale = RESOLUTION_LOOKUP.scale local min_font_size = 1 local scaled_font_size = math.max(font_size * scale, 1) - local text_width = get_text_size(text, font_data, scaled_font_size) + local text_width = get_text_size(text, font_type, scaled_font_size) if max_width < text_width then repeat @@ -93,7 +95,7 @@ local function get_scaled_font_size_by_width(text, font_data, font_size, max_wid font_size = math.max(font_size - 1, min_font_size) scaled_font_size = math.max(font_size * scale, 1) - text_width = math.floor(get_text_size(text, font_data, scaled_font_size)) + text_width = math.floor(get_text_size(text, font_type, scaled_font_size)) until text_width <= max_width end @@ -113,14 +115,12 @@ end local function draw(commands_list, selected_command_index) - local font_data = Managers.font:data_by_type(FONT_TYPE) - local font = font_data.path create_gui() if not _gui then return end - + -- Apply additional HUD scaling local hud_scale = get_hud_scale() local should_scale = hud_scale ~= DEFAULT_HUD_SCALE @@ -152,30 +152,30 @@ local function draw(commands_list, selected_command_index) local font_size = FONT_SIZE for i, command in ipairs(displayed_commands) do - font_size = get_scaled_font_size_by_width(command.name, font_data, FONT_SIZE, BASE_COMMAND_TEXT_WIDTH) + font_size = get_scaled_font_size_by_width(command.name, FONT_TYPE, FONT_SIZE, BASE_COMMAND_TEXT_WIDTH) -- draw "/command_name" text local scaled_offet_x = (OFFSET_X + STRING_X_MARGIN) * scale local scaled_offset_y = (OFFSET_Y - STRING_HEIGHT * (i + selected_strings_number - 1) + STRING_Y_OFFSET) * scale local string_position = Vector3(scaled_offet_x, scaled_offset_y, OFFSET_Z + 2) - Gui.slug_text(_gui, command.name, font, font_size, string_position, nil, Color(255, 100, 255, 100)) + Gui.slug_text(_gui, command.name, FONT_MATERIAL, font_size, string_position, nil, Color(255, 100, 255, 100)) - local command_text_strings = word_wrap(command.full_text, font, font_size, BASE_COMMAND_TEXT_WIDTH) + local command_text_strings = word_wrap(command.full_text, FONT_MATERIAL, font_size, BASE_COMMAND_TEXT_WIDTH) local multistring = #command_text_strings > 1 local first_description_string if multistring then if command.selected then selected_strings_number = #command_text_strings else - local multistring_indicator_width = get_text_width(MULTISTRING_INDICATOR_TEXT, font, font_size) + local multistring_indicator_width = get_text_width(MULTISTRING_INDICATOR_TEXT, FONT_MATERIAL, font_size) local command_text_width = BASE_COMMAND_TEXT_WIDTH - (multistring_indicator_width / scale) - command_text_strings = word_wrap(command.full_text, font, font_size, command_text_width) + command_text_strings = word_wrap(command.full_text, FONT_MATERIAL, font_size, command_text_width) -- draw that [...] thing local multistring_offset_x = (OFFSET_X + WIDTH) * scale - multistring_indicator_width local multistring_indicator_position = Vector3(multistring_offset_x, string_position.y, string_position.z) - Gui.slug_text(_gui, MULTISTRING_INDICATOR_TEXT, font, font_size, + Gui.slug_text(_gui, MULTISTRING_INDICATOR_TEXT, FONT_MATERIAL, font_size, multistring_indicator_position, nil, Color(255, 100, 100, 100)) end first_description_string = string.sub(command_text_strings[1], #command.name + 2) @@ -184,18 +184,18 @@ local function draw(commands_list, selected_command_index) end -- draw command description text (1st string) - local first_description_string_width = get_text_width(command.name, font, font_size) + local first_description_string_width = get_text_width(command.name, FONT_MATERIAL, font_size) local first_description_pos_x = string_position.x + first_description_string_width local first_description_string_position = Vector3(first_description_pos_x, string_position.y, string_position.z) - Gui.slug_text(_gui, first_description_string, font, font_size, + Gui.slug_text(_gui, first_description_string, FONT_MATERIAL, font_size, first_description_string_position, nil, Color(255, 255, 255, 255)) -- draw command description text (2+ strings) if command.selected and multistring then - for j = selected_strings_number, 2, -1 do + for j = 2, selected_strings_number do string_position.y = string_position.y - STRING_HEIGHT * scale - Gui.slug_text(_gui, command_text_strings[j], font, font_size, + Gui.slug_text(_gui, command_text_strings[j], FONT_MATERIAL, font_size, string_position, nil, Color(255, 255, 255, 255)) end end @@ -227,11 +227,11 @@ local function draw(commands_list, selected_command_index) if selected_command_index > 0 then total_number_indicator = selected_command_index .. "/" .. total_number_indicator end - local total_number_indicator_width = get_text_width(total_number_indicator, font, font_size) + local total_number_indicator_width = get_text_width(total_number_indicator, FONT_MATERIAL, font_size) local total_number_indicator_x = (WIDTH) * scale - total_number_indicator_width local total_number_indicator_y = (OFFSET_Y + STRING_Y_OFFSET) * scale local total_number_indicator_position = Vector3(total_number_indicator_x, total_number_indicator_y, OFFSET_Z + 2) - Gui.slug_text(_gui, total_number_indicator, font, font_size, + Gui.slug_text(_gui, total_number_indicator, FONT_MATERIAL, font_size, total_number_indicator_position, nil, Color(255, 100, 100, 100)) end diff --git a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view.lua b/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view.lua index dec9be4..ddc073c 100644 --- a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view.lua +++ b/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view.lua @@ -7,14 +7,8 @@ local _widgets_by_name -- #################################################################################################################### local function load_scrolling_speed_setting() - if _widgets_by_name then - local dmf_scroll_speed = math.clamp((dmf:get("dmf_options_scrolling_speed") or 100) / 1000, 0.05, 0.5) - if _widgets_by_name["scrollbar"] then - _widgets_by_name["scrollbar"].content.scroll_amount = dmf_scroll_speed - end - if _widgets_by_name["settings_scrollbar"] then - _widgets_by_name["settings_scrollbar"].content.scroll_amount = dmf_scroll_speed - end + if dmf:get("dmf_options_scrolling_speed") and _widgets_by_name and _widgets_by_name["scrollbar"] then + _widgets_by_name["scrollbar"].content.scroll_speed = dmf:get("dmf_options_scrolling_speed") end end @@ -45,9 +39,6 @@ local ViewElementKeybindPopup = require("scripts/ui/view_elements/view_element_k local CATEGORIES_GRID = 1 local SETTINGS_GRID = 2 -local _last_selected_category_entry -local _last_selected_category_widget - local DMFOptionsView = class("DMFOptionsView", "BaseView") DMFOptionsView.init = function (self, settings) @@ -160,8 +151,6 @@ DMFOptionsView.cb_on_back_pressed = function (self) self._close_selected_setting = true elseif selected_navigation_column == SETTINGS_GRID then self:_change_navigation_column(selected_navigation_column - 1) - elseif self._require_restart then - self:_restart_popup_info() else local view_name = "dmf_options_view" Managers.ui:close_view(view_name) @@ -218,30 +207,6 @@ DMFOptionsView.cb_reset_category_to_default = function (self) end) end -DMFOptionsView._restart_popup_info = function (self) - local context = { - title_text = "loc_popup_settings_require_restart_header", - description_text = "loc_popup_settings_require_restart_description", - options = { - { - text = "loc_confirm", - close_on_pressed = true, - callback = callback(function () - self._popup_id = nil - local view_name = "dmf_options_view" - self._require_restart = false - - Managers.ui:close_view(view_name) - end) - } - } - } - - Managers.event:trigger("event_show_ui_popup", context, function (id) - self._popup_id = id - end) -end - DMFOptionsView._setup_input_legend = function (self) self._input_legend_element = self:_add_element(ViewElementInputLegend, "input_legend", 10) local legend_inputs = self._definitions.legend_inputs @@ -260,17 +225,8 @@ DMFOptionsView._setup_content_grid_scrollbar = function (self, grid, widget_id, load_scrolling_speed_setting() - grid:assign_scrollbar(scrollbar_widget, grid_pivot_scenegraph_id, grid_scenegraph_id, true) - - -- Scroll the category grid to the default category widget - if widget_id == "scrollbar" and _last_selected_category_widget then - local index = grid:index_by_widget(_last_selected_category_widget) - local scroll_progress = grid:get_scrollbar_percentage_by_index(index) - - grid:set_scrollbar_progress(scroll_progress) - else - grid:set_scrollbar_progress(0) - end + grid:assign_scrollbar(scrollbar_widget, grid_pivot_scenegraph_id, grid_scenegraph_id) + grid:set_scrollbar_progress(0) end DMFOptionsView._setup_offscreen_gui = function (self) @@ -336,11 +292,6 @@ DMFOptionsView._setup_content_widgets = function (self, content, scenegraph_id, alignment_list[#alignment_list + 1] = widget or { size = size } - - if entry.display_name == self._default_category then - _last_selected_category_entry = entry - _last_selected_category_widget = widget - end end end @@ -666,8 +617,9 @@ DMFOptionsView._update_grid_navigation_selection = function (self) end elseif navigation_widgets or self._settings_content_widgets then self:_set_default_navigation_widget() + elseif self._default_category then + self:present_category_widgets(self._default_category) end - -- Removed extra condition for default category - moved to on_view_load_complete end end @@ -677,8 +629,6 @@ DMFOptionsView.present_category_widgets = function (self, category) local grid_data = settings_category_widgets[category] if grid_data then - dmf:set("options_menu_last_selected", category) - local widgets = {} local alignment_widgets = {} @@ -694,7 +644,7 @@ DMFOptionsView.present_category_widgets = function (self, category) local scrollbar_widget_id = "settings_scrollbar" local grid_scenegraph_id = "settings_grid_background" local grid_pivot_scenegraph_id = "settings_grid_content_pivot" - local grid_spacing = _view_settings.settings_grid_spacing + local grid_spacing = _view_settings.grid_spacing self._settings_content_grid = self:_setup_grid(self._settings_content_widgets, self._settings_alignment_list, grid_scenegraph_id, grid_spacing, false) self:_setup_content_grid_scrollbar(self._settings_content_grid, scrollbar_widget_id, grid_scenegraph_id, grid_pivot_scenegraph_id) @@ -717,7 +667,7 @@ DMFOptionsView._setup_category_config = function (self, config) self._category_content_widgets = {} end - local config_categories = config.categories or {} + local config_categories = config.categories local entries = {} local reset_functions_by_category = {} local categories_by_display_name = {} @@ -756,23 +706,14 @@ DMFOptionsView._setup_category_config = function (self, config) end end - -- Retrieve default category from settings - local category_setting = dmf:get("options_menu_last_selected") - if category_setting and not categories_by_display_name[category_setting] then - category_setting = false - end - - self._default_category = category_setting or ( - config_categories[1] and config_categories[1].display_name - ) - + self._default_category = config_categories[1].display_name local scenegraph_id = "grid_content_pivot" local callback_name = "cb_on_category_pressed" self._category_content_widgets, self._category_alignment_list = self:_setup_content_widgets(entries, scenegraph_id, callback_name) local scrollbar_widget_id = "scrollbar" local grid_scenegraph_id = "background" local grid_pivot_scenegraph_id = "grid_content_pivot" - local grid_spacing = _view_settings.category_grid_spacing + local grid_spacing = _view_settings.grid_spacing self._category_content_grid = self:_setup_grid(self._category_content_widgets, self._category_alignment_list, grid_scenegraph_id, grid_spacing, true) self:_setup_content_grid_scrollbar(self._category_content_grid, scrollbar_widget_id, grid_scenegraph_id, grid_pivot_scenegraph_id) @@ -805,7 +746,6 @@ DMFOptionsView._setup_settings_config = function (self, config) local settings_default_values = {} local aligment_list = {} local callback_name = "cb_on_settings_pressed" - local changed_callback_name = "cb_on_settings_changed" for setting_index, setting in ipairs(config_settings) do local valid = self._validation_mapping[setting.category].settings[setting.display_name].validation_result @@ -828,7 +768,7 @@ DMFOptionsView._setup_settings_config = function (self, config) end local widget_suffix = "setting_" .. tostring(setting_index) - local widget, alignment_widget = self:_create_settings_widget_from_config(setting, category, widget_suffix, callback_name, changed_callback_name) + local widget, alignment_widget = self:_create_settings_widget_from_config(setting, category, widget_suffix, callback_name) category_widgets[category][#widgets + 1] = { widget = widget, alignment_widget = alignment_widget @@ -871,24 +811,19 @@ end DMFOptionsView._set_tooltip_data = function (self, widget) local current_widget = self._tooltip_data and self._tooltip_data.widget - local localized_text = nil + local display_text = nil local tooltip_text = widget.content.entry.tooltip_text local disabled_by_list = widget.content.entry.disabled_by if tooltip_text then - if type(tooltip_text) == "function" then - localized_text = tooltip_text() - else - -- Should already be localized in mod option generation - localized_text = tooltip_text - end + display_text = tooltip_text end if disabled_by_list then - localized_text = localized_text and string.format("%s\n", localized_text) + display_text = display_text and string.format("%s\n", display_text) for _, text in pairs(disabled_by_list) do - localized_text = localized_text and string.format("%s\n%s", localized_text, text) or text + display_text = display_text and string.format("%s\n%s", display_text, text) or text end end @@ -900,14 +835,14 @@ DMFOptionsView._set_tooltip_data = function (self, widget) if current_widget ~= widget or current_widget == widget and new_y ~= current_y then self._tooltip_data = { widget = widget, - text = localized_text + text = display_text } - self._widgets_by_name.tooltip.content.text = localized_text + self._widgets_by_name.tooltip.content.text = display_text local text_style = self._widgets_by_name.tooltip.style.text local x_pos = starting_point[1] + widget.offset[1] local width = widget.content.size[1] * 0.5 local text_options = UIFonts.get_font_options_by_style(text_style) - local _, text_height = self:_text_size(localized_text, text_style.font_type, text_style.font_size, { + local _, text_height = self:_text_size(display_text, text_style.font_type, text_style.font_size, { width, 0 }, text_options) @@ -917,7 +852,7 @@ DMFOptionsView._set_tooltip_data = function (self, widget) height } self._widgets_by_name.tooltip.offset[1] = x_pos - width * 0.8 - self._widgets_by_name.tooltip.offset[2] = math.max(new_y - height, 20) + self._widgets_by_name.tooltip.offset[2] = new_y - height self._widgets_by_name.tooltip.content.visible = true end end @@ -956,7 +891,7 @@ DMFOptionsView._update_settings_content_widgets = function (self, dt, t, input_s end end -DMFOptionsView._create_settings_widget_from_config = function (self, config, category, suffix, callback_name, changed_callback_name) +DMFOptionsView._create_settings_widget_from_config = function (self, config, category, suffix, callback_name) local scenegraph_id = "settings_grid_content_pivot" local default_value = config.default_value local default_value_type = type(default_value) @@ -1010,7 +945,7 @@ DMFOptionsView._create_settings_widget_from_config = function (self, config, cat local init = template.init if init then - init(self, widget, config, callback_name, changed_callback_name) + init(self, widget, config, callback_name) end end @@ -1144,27 +1079,6 @@ DMFOptionsView.cb_on_settings_pressed = function (self, widget, entry) end end -DMFOptionsView.cb_on_settings_changed = function (self, widget, entry, option_value) - if not self._require_restart then - - -- Entry supersedes option - if entry.require_restart then - self._require_restart = true - - -- Search by option value - elseif option_value then - for i = 1, #entry.options do - local option = entry.options[i] - - if option.value == option_value then - self._require_restart = option.require_restart - break - end - end - end - end -end - DMFOptionsView._enable_settings_overlay = function (self, enable) local widgets_by_name = self._widgets_by_name local settings_overlay_widget = widgets_by_name.settings_overlay @@ -1330,13 +1244,4 @@ DMFOptionsView._set_selected_grid_widget = function (self, widgets, widget_name) return selected_widget, selected_widget_index end --- Handles navigation to the last selected category widget -DMFOptionsView._on_view_load_complete = function (self, loaded) - DMFOptionsView.super._on_view_load_complete(self, loaded) - - if _last_selected_category_entry and _last_selected_category_widget then - self:cb_on_category_pressed(_last_selected_category_widget, _last_selected_category_entry) - end -end - return DMFOptionsView diff --git a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua b/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua index e1ef44a..d972841 100644 --- a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua +++ b/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_content_blueprints.lua @@ -23,9 +23,6 @@ local group_header_height = 80 local DEFAULT_NUM_DECIMALS = 0 -local _dropdown_deadzone = 0.25 -- 250ms delay before opening keybind popups -local _last_dropdown_pressed = -1 - local value_font_style = table.clone(UIFontSettings.list_button) value_font_style.offset = { settings_grid_width - settings_value_width + 25, @@ -56,7 +53,7 @@ local blueprints = { settings_value_height }, pass_template = ButtonPassTemplates.list_button, - init = function (parent, widget, entry, callback_name, changed_callback_name) + init = function (parent, widget, entry, callback_name) local content = widget.content local hotspot = content.hotspot @@ -81,7 +78,7 @@ local blueprints = { settings_value_height }, pass_template = ButtonPassTemplates.settings_button(settings_grid_width, settings_value_height, settings_value_width, true), - init = function (parent, widget, entry, callback_name, changed_callback_name) + init = function (parent, widget, entry, callback_name) local content = widget.content content.hotspot.pressed_callback = function () @@ -98,10 +95,6 @@ local blueprints = { content.text = display_name content.button_text = Localize("loc_settings_change") content.entry = entry - - entry.changed_callback = function (changed_value) - callback(parent, changed_callback_name, widget, entry)() - end end }, group_header = { @@ -117,7 +110,7 @@ local blueprints = { value = Localize("loc_settings_option_unavailable") } }, - init = function (parent, widget, entry, callback_name, changed_callback_name) + init = function (parent, widget, entry, callback_name) local content = widget.content local display_name = entry.display_name content.text = display_name @@ -131,9 +124,9 @@ local blueprints = { pass_template_function = function (parent, config, size) return CheckboxPassTemplates.settings_checkbox(size[1], settings_value_height, settings_value_width, 2, true) end, - init = function (parent, widget, entry, callback_name, changed_callback_name) + init = function (parent, widget, entry, callback_name) local content = widget.content - local display_name = entry.display_name or Managers.localization:localize("loc_settings_option_unavailable") + local display_name = entry.display_name or Localize("loc_settings_option_unavailable") content.text = display_name content.entry = entry @@ -141,11 +134,6 @@ local blueprints = { local widget_option_id = "option_" .. i content[widget_option_id] = i == 1 and Managers.localization:localize("loc_setting_checkbox_on") or Managers.localization:localize("loc_setting_checkbox_off") end - - entry.changed_callback = function (changed_value) - --callback(parent, callback_name, widget, entry)() - callback(parent, changed_callback_name, widget, entry)() - end end, update = function (parent, widget, input_service, dt, t) local content = widget.content @@ -158,7 +146,7 @@ local blueprints = { content.disabled = is_disabled local new_value = nil - if hotspot.on_pressed and not parent._navigation_column_changed_this_frame and not is_disabled then + if hotspot.on_pressed and not is_disabled then new_value = not value end @@ -171,15 +159,14 @@ local blueprints = { if new_value ~= nil and new_value ~= value then on_activated(new_value, entry) - entry.changed_callback(new_value) end end } } -local function slider_init_function(parent, widget, entry, callback_name, changed_callback_name) +local function slider_init_function(parent, widget, entry, callback_name) local content = widget.content - local display_name = entry.display_name or Managers.localization:localize("loc_settings_option_unavailable") + local display_name = entry.display_name or Localize("loc_settings_option_unavailable") content.text = display_name content.entry = entry content.area_length = settings_value_width @@ -196,7 +183,7 @@ local function slider_init_function(parent, widget, entry, callback_name, change content.previous_slider_value = value content.slider_value = value - entry.pressed_callback = function () + content.pressed_callback = function () local is_disabled = entry.is_disabled if is_disabled then @@ -205,10 +192,6 @@ local function slider_init_function(parent, widget, entry, callback_name, change callback(parent, callback_name, widget, entry)() end - - entry.changed_callback = function (changed_value) - callback(parent, changed_callback_name, widget, entry)() - end end blueprints.percent_slider = { @@ -219,8 +202,8 @@ blueprints.percent_slider = { pass_template_function = function (parent, config, size) return SliderPassTemplates.settings_percent_slider(size[1], settings_value_height, settings_value_width, true) end, - init = function (parent, widget, entry, callback_name, changed_callback_name) - slider_init_function(parent, widget, entry, callback_name, changed_callback_name) + init = function (parent, widget, entry, callback_name) + slider_init_function(parent, widget, entry, callback_name) end, update = function (parent, widget, input_service, dt, t) local content = widget.content @@ -277,8 +260,8 @@ blueprints.percent_slider = { if hotspot.on_pressed and not is_disabled then if focused then new_value = content.slider_value - elseif using_gamepad and entry.pressed_callback then - entry.pressed_callback() + elseif using_gamepad then + content.pressed_callback() end end @@ -292,7 +275,6 @@ blueprints.percent_slider = { if new_value then on_activated(new_value * 100, entry) - entry.changed_callback(new_value) content.slider_value = new_value content.previous_slider_value = new_value @@ -311,8 +293,8 @@ blueprints.value_slider = { pass_template_function = function (parent, config, size) return SliderPassTemplates.settings_value_slider(size[1], settings_value_height, settings_value_width, true) end, - init = function (parent, widget, entry, callback_name, changed_callback_name) - slider_init_function(parent, widget, entry, callback_name, changed_callback_name) + init = function (parent, widget, entry, callback_name) + slider_init_function(parent, widget, entry, callback_name) end, update = function (parent, widget, input_service, dt, t) local content = widget.content @@ -374,8 +356,8 @@ blueprints.value_slider = { if hotspot.on_pressed then if focused then new_normalized_value = content.slider_value - elseif using_gamepad and entry.pressed_callback then - entry.pressed_callback() + elseif using_gamepad then + content.pressed_callback() end end @@ -391,7 +373,6 @@ blueprints.value_slider = { local new_value = explode_function(new_normalized_value, entry) on_activated(new_value, entry) - entry.changed_callback(new_value) content.slider_value = new_normalized_value content.previous_slider_value = new_normalized_value @@ -410,9 +391,9 @@ blueprints.slider = { pass_template_function = function (parent, config, size) return SliderPassTemplates.settings_value_slider(size[1], settings_value_height, settings_value_width, true) end, - init = function (parent, widget, entry, callback_name, changed_callback_name) + init = function (parent, widget, entry, callback_name) local content = widget.content - local display_name = entry.display_name or Managers.localization:localize("loc_settings_option_unavailable") + local display_name = entry.display_name or Localize("loc_settings_option_unavailable") content.text = display_name content.entry = entry content.area_length = settings_value_width @@ -422,11 +403,7 @@ blueprints.slider = { local value, value_fraction = get_function(entry) content.previous_slider_value = value_fraction content.slider_value = value_fraction - entry.pressed_callback = callback(parent, callback_name, widget, entry) - - entry.changed_callback = function (changed_value) - callback(parent, changed_callback_name, widget, entry)() - end + content.pressed_callback = callback(parent, callback_name, widget, entry) end, update = function (parent, widget, input_service, dt, t) local content = widget.content @@ -486,7 +463,7 @@ blueprints.slider = { if focused then new_value_fraction = content.slider_value elseif not hotspot.is_hover then - entry.pressed_callback() + content.pressed_callback() end end @@ -502,7 +479,6 @@ blueprints.slider = { local new_value = math.lerp(entry.min_value, entry.max_value, new_value_fraction) on_activated(new_value, entry) - entry.changed_callback(new_value) content.slider_value = new_value_fraction content.previous_slider_value = new_value_fraction @@ -528,9 +504,9 @@ blueprints.dropdown = { return DropdownPassTemplates.settings_dropdown(size[1], settings_value_height, settings_value_width, num_visible_options, true) end, - init = function (parent, widget, entry, callback_name, changed_callback_name) + init = function (parent, widget, entry, callback_name) local content = widget.content - local display_name = entry.display_name or Managers.localization:localize("loc_settings_option_unavailable") + local display_name = entry.display_name or Localize("loc_settings_option_unavailable") content.text = display_name content.entry = entry local has_options_function = entry.options_function ~= nil @@ -572,10 +548,6 @@ blueprints.dropdown = { local scroll_amount = scroll_length > 0 and (size[2] + spacing) / scroll_length or 0 content.scroll_amount = scroll_amount local value = entry.get_function and entry:get_function() or entry.default_value - - entry.changed_callback = function (changed_value) - callback(parent, changed_callback_name, widget, entry, changed_value)() - end end, update = function (parent, widget, input_service, dt, t) local content = widget.content @@ -605,7 +577,7 @@ blueprints.dropdown = { if selected_index and focused then if using_gamepad and hotspot.on_pressed then - new_value = options[selected_index].value + new_value = options[selected_index].id end hotspot_style.on_pressed_sound = hotspot_style.on_pressed_fold_in_sound @@ -616,8 +588,8 @@ blueprints.dropdown = { value = entry.get_function and entry:get_function() or content.internal_value or "" local preview_option = options_by_value[value] - local preview_option_value = preview_option and preview_option.value - local preview_value = preview_option and preview_option.display_name or Managers.localization:localize("loc_settings_option_unavailable") + local preview_option_id = preview_option and preview_option.id + local preview_value = preview_option and preview_option.display_name or Localize("loc_settings_option_unavailable") content.value_text = preview_value @@ -628,7 +600,6 @@ blueprints.dropdown = { local scroll_area_height = parent:settings_grid_length() local dropdown_length = size[2] * (num_visible_options + 1) local grow_downwards = true - local always_keep_order = true if scroll_area_height <= offset[2] - scroll_amount + dropdown_length then grow_downwards = false @@ -641,7 +612,7 @@ blueprints.dropdown = { for i = 1, #options do local option = options[i] - if option.value == preview_option_value then + if option.id == preview_option_id then selected_index = i break @@ -653,13 +624,13 @@ blueprints.dropdown = { if selected_index and focused then if input_service:get("navigate_up_continuous") then - if grow_downwards or not grow_downwards and always_keep_order then + if grow_downwards then new_selection_index = math.max(selected_index - 1, 1) else new_selection_index = math.min(selected_index + 1, num_options) end elseif input_service:get("navigate_down_continuous") then - if grow_downwards or not grow_downwards and always_keep_order then + if grow_downwards then new_selection_index = math.min(selected_index + 1, num_options) else new_selection_index = math.max(selected_index - 1, 1) @@ -696,24 +667,18 @@ blueprints.dropdown = { local using_scrollbar = num_visible_options < num_options for i = start_index, end_index do - local actual_i = i - - if not grow_downwards and always_keep_order then - actual_i = end_index - i + start_index - end - local option_text_id = "option_text_" .. option_index local option_hotspot_id = "option_hotspot_" .. option_index local outline_style_id = "outline_" .. option_index local option_hotspot = content[option_hotspot_id] option_hovered = option_hovered or option_hotspot.is_hover - option_hotspot.is_selected = actual_i == selected_index - local option = options[actual_i] + option_hotspot.is_selected = i == selected_index + local option = options[i] if not new_value and focused and not using_gamepad and option_hotspot.on_pressed then option_hotspot.on_pressed = nil new_value = option.value - content.selected_index = actual_i + content.selected_index = i end local option_display_name = option.display_name @@ -729,13 +694,10 @@ blueprints.dropdown = { local value_changed = new_value ~= nil - if value_changed then - _last_dropdown_pressed = t - if new_value ~= value then - local on_activated = entry.on_activated - on_activated(new_value, entry) - entry.changed_callback(new_value) - end + if value_changed and new_value ~= value then + local on_activated = entry.on_activated + + on_activated(new_value, entry) end local scrollbar_hotspot = content.scrollbar_hotspot @@ -752,9 +714,9 @@ blueprints.keybind = { settings_value_height }, pass_template = KeybindPassTemplates.settings_keybind(settings_grid_width, settings_value_height, settings_value_width), - init = function (parent, widget, entry, callback_name, changed_callback_name) + init = function (parent, widget, entry, callback_name) local content = widget.content - local display_name = entry.display_name or parent:_localize("loc_settings_option_unavailable") + local display_name = entry.display_name or Localize("loc_settings_option_unavailable") content.text = display_name content.entry = entry content.key_unassigned_string = Managers.localization:localize("loc_keybind_unassigned") @@ -768,11 +730,7 @@ blueprints.keybind = { local hotspot = content.hotspot if hotspot.on_released then - if (t - _last_dropdown_pressed) > _dropdown_deadzone then - parent:show_keybind_popup(widget, entry, content.entry.cancel_keys) - else - _last_dropdown_pressed = -1 - end + parent:show_keybind_popup(widget, entry, content.entry.cancel_keys) end end } @@ -805,7 +763,8 @@ blueprints.description = { local content = widget.content local style = widget.style local text_style = style.text - local display_text = entry.display_name + local display_name = entry.display_name + local display_text = display_name local ui_renderer = parent._ui_renderer local size = content.size local text_options = UIFonts.get_font_options_by_style(text_style) diff --git a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua b/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua index d6e5069..b08d85e 100644 --- a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua +++ b/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_definitions.lua @@ -25,7 +25,6 @@ local settings_mask_size = { } local settings_grid_height = grid_height + mask_offset_y -local settings_grid_scroll_amount = math.clamp((dmf:get("dmf_options_scrolling_speed") or 100) / 1000, 0.05, 0.5) local tooltip_text_style = table.clone(UIFontSettings.body) tooltip_text_style.text_horizontal_alignment = "left" @@ -63,10 +62,9 @@ local scenegraph_definition = { grid_width, grid_height }, - -- Move the categories up and left to compensate for removed icons position = { - 140, - 190, + 180, + 240, 1 } }, @@ -387,10 +385,7 @@ local widget_definitions = { }, "tooltip", { visible = false }), - scrollbar = UIWidget.create_definition(ScrollbarPassTemplates.default_scrollbar, "scrollbar", { - scroll_speed = 10, - scroll_amount = settings_grid_scroll_amount, - }), + scrollbar = UIWidget.create_definition(ScrollbarPassTemplates.default_scrollbar, "scrollbar"), grid_mask = UIWidget.create_definition({ { value = "content/ui/materials/offscreen_masks/ui_overlay_offscreen_vertical_blur", @@ -411,10 +406,7 @@ local widget_definitions = { content_id = "hotspot" } }, "grid_interaction"), - settings_scrollbar = UIWidget.create_definition(ScrollbarPassTemplates.default_scrollbar, "settings_scrollbar", { - scroll_speed = 10, - scroll_amount = settings_grid_scroll_amount, - }), + settings_scrollbar = UIWidget.create_definition(ScrollbarPassTemplates.default_scrollbar, "settings_scrollbar"), settings_grid_mask = UIWidget.create_definition({ { value = "content/ui/materials/offscreen_masks/ui_overlay_offscreen_vertical_blur", diff --git a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings.lua b/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings.lua index 2af1d39..c2802aa 100644 --- a/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings.lua +++ b/dmf/scripts/mods/dmf/modules/ui/options/dmf_options_view_settings.lua @@ -5,13 +5,9 @@ local dmf_options_view_settings = { shading_environment = "content/shading_environments/ui/system_menu", grid_size = { 500, - 820 -- Increased to compensate for upshifted category grid + 800 }, - category_grid_spacing = { - 0, - 3 - }, - settings_grid_spacing = { + grid_spacing = { 0, 10 }, diff --git a/dmf/scripts/mods/dmf/modules/ui/options/mod_options.lua b/dmf/scripts/mods/dmf/modules/ui/options/mod_options.lua index 940eb24..9511fa0 100644 --- a/dmf/scripts/mods/dmf/modules/ui/options/mod_options.lua +++ b/dmf/scripts/mods/dmf/modules/ui/options/mod_options.lua @@ -6,22 +6,13 @@ local _type_template_map = {} local _devices = { "keyboard", - "mouse", + "mouse" } - local _cancel_keys = { "keyboard_esc" } - local _reserved_keys = {} -local ERRORS = { - REGULAR = { - invalid_widget_type = "[DMF Mod Options] (%s): \"%s\" is not a valid widget type " .. - "in this version of Darktide Mod Framework.", - }, -} - -- #################################################################################################################### -- ##### Local functions ############################################################################################## -- #################################################################################################################### @@ -62,21 +53,6 @@ local create_description_template = function (self, params) end _type_template_map["description"] = create_description_template --- ########################## --- ###### Group ############# --- ########################## - --- Create group template -local create_group_template = function(self, params) - local template = { - display_name = params.title, - widget_type = "group_header", - after = params.parent_index - } - return template -end -_type_template_map["group"] = create_group_template - -- ########################### -- ###### Percent Slider ##### -- ########################### @@ -160,7 +136,6 @@ local create_checkbox_template = function (self, params) default_value = params.default_value, display_name = params.title, indentation_level = params.depth, - require_restart = params.require_restart, tooltip_text = params.tooltip, value_type = "boolean", } @@ -188,11 +163,9 @@ local create_mod_toggle_template = function (self, params) after = params.after, category = params.category, default_value = true, - disabled = params.disabled, - display_name = params.readable_mod_name or params.mod_name, + display_name = dmf:localize("toggle_mod"), indentation_level = 0, - require_restart = params.require_restart, - tooltip_text = params.description, + tooltip_text = dmf:localize("toggle_mod_description"), value_type = "boolean", } @@ -230,7 +203,6 @@ local create_dropdown_template = function (self, params) indentation_level = params.depth, options = params.options, tooltip_text = params.tooltip, - require_restart = params.require_restart, widget_type = "dropdown", } template.on_activated = function(new_value) @@ -251,9 +223,7 @@ _type_template_map["dropdown"] = create_dropdown_template -- ######### Keybind ######### -- ########################### -local set_keybind = function (self, keybind_data, keywatch_result) - keybind_data.keys = keywatch_result - +local set_new_keybind = function (self, keybind_data) local mod = get_mod(keybind_data.mod_name) dmf.add_mod_keybind( mod, @@ -262,19 +232,18 @@ local set_keybind = function (self, keybind_data, keywatch_result) global = keybind_data.keybind_global, trigger = keybind_data.keybind_trigger, type = keybind_data.keybind_type, - main = keywatch_result.main, - enablers = keywatch_result.enablers, - disablers = keywatch_result.disablers, + keys = keybind_data.keys, function_name = keybind_data.function_name, view_name = keybind_data.view_name, } ) - mod:set(keybind_data.setting_id, dmf.keywatch_result_to_local_keys(keywatch_result), true) + mod:set(keybind_data.setting_id, keybind_data.keys, true) end -- Create keybind template local create_keybind_template = function (self, params) + local template = { widget_type = "keybind", service_type = "Ingame", @@ -290,31 +259,26 @@ local create_keybind_template = function (self, params) indentation_level = params.depth, mod_name = params.mod_name, setting_id = params.setting_id, - keys = dmf.local_keys_to_keywatch_result(params.keys), - default_value = dmf.local_keys_to_keywatch_result(params.default_value) or {}, + keys = dmf.keys_to_keybind_result(params.keys), on_activated = function (new_value, old_value) - -- Prevent unbinding the mod options menu - if params.setting_id ~= "open_dmf_options" then + for i = 1, #_cancel_keys do + local cancel_key = _cancel_keys[i] + if cancel_key == new_value.main then - -- Unbind the keybind if the new value is empty - if not (new_value and new_value.main) then - set_keybind(self, params, {}) - return true - end + -- Prevent unbinding the mod options menu + if params.setting_id ~= "open_dmf_options" then - -- Unbind the keybind if the new value matches a cancel key - for i = 1, #_cancel_keys do - local cancel_key = _cancel_keys[i] - if cancel_key == new_value.main then - set_keybind(self, params, {}) - return true + -- Unbind the keybind + params.keys = {} + set_new_keybind(self, params) end + + return true end end - -- Don't modify the keybind if the new value is a reserved key for i = 1, #_reserved_keys do local reserved_key = _reserved_keys[i] if reserved_key == new_value.main then @@ -322,23 +286,23 @@ local create_keybind_template = function (self, params) end end - -- Get the keys of the new value - local keys = dmf.keywatch_result_to_local_keys(new_value) + -- Get the new keybind + local keys = dmf.keybind_result_to_keys(new_value) - -- Set the new keybind unless it would unbind the mod options menu + -- Bind the new key and prevent unbinding the mod options menu if keys and #keys > 0 or params.setting_id ~= "open_dmf_options" then - set_keybind(self, params, new_value) - return true + params.keys = keys + set_new_keybind(self, params) end - return false + return true end, get_function = function (template) - local saved_keys = get_mod(template.mod_name):get(template.setting_id) - local keywatch_result = dmf.local_keys_to_keywatch_result(saved_keys) + local keys = get_mod(template.mod_name):get(template.setting_id) + local keybind_result = dmf.keys_to_keybind_result(keys) - return keywatch_result + return keybind_result end, } @@ -357,23 +321,11 @@ local function widget_data_to_template(self, data) return _type_template_map[data.type](self, data) else dmf:dump(data, "widget", 1) - dmf:error(ERRORS.REGULAR.invalid_widget_type, tostring(data.mod_name), tostring(data.type)) + dmf.throw_error("[widget \"%s\"]: 'type' field must contain valid widget type name.", data.setting_id) end end --- Add a category for toggling mods -local function create_toggle_category(self, categories) - local category = { - can_be_reset = false, - display_name = dmf:localize("toggle_mods"), - custom = true - } - categories[#categories + 1] = category - return category -end - - -- Add a mod category to the options view categories local function create_mod_category(self, categories, widget_data) local category = { @@ -398,63 +350,10 @@ local function create_option_template(self, widget_data, category_name, index_of end end --- Insert a new item into a table before any items that pass the item_tester function -local function insert_before(tbl, item_tester, new_item) - local copy = {} - for _, item in ipairs(tbl) do - if item_tester(item) then - table.insert(copy, new_item) - end - table.insert(copy, item) - end - return copy -end - - -- #################################################################################################################### -- ##### Hooks ######################################################################################################## -- #################################################################################################################### --- Add Mods Options title to global localization table --- so that the SystemView options menu can localize it -dmf:add_global_localize_strings({ - -- TODO: copied from dmf/localization/dmf.lua, figure out a better way - mods_options = { - en = "Mod Options", - es = "Configuración de mods", - ru = "Настройки модов", - ["zh-cn"] = "模组选项", - } -}) - -local dmf_option_definition = { - text = "mods_options", - type = "button", - icon = "content/ui/materials/icons/system/escape/settings", - trigger_function = function() - local context = { - can_exit = true, - } - local view_name = "dmf_options_view" - Managers.ui:open_view(view_name, nil, nil, nil, nil, context) - end, -} - -local function is_options_button(item) - return item.text == "loc_options_view_display_name" -end - --- Inject DMF Options button into the Esc menu -dmf:hook_require("scripts/ui/views/system_view/system_view_content_list", function(instance) - -- Don't re-inject if it's already there - if table.find_by_key(instance.default, "text", dmf_option_definition.text) then - return - end - - instance.default = insert_before(instance.default, is_options_button, dmf_option_definition) - instance.StateMainMenu = insert_before(instance.StateMainMenu, is_options_button, dmf_option_definition) -end) - -- #################################################################################################################### -- ##### DMF internal functions and variables ######################################################################### -- #################################################################################################################### @@ -464,102 +363,64 @@ dmf.create_mod_options_settings = function (self, options_templates) local categories = options_templates.categories local settings = options_templates.settings - -- Create the toggle category - local toggle_category = create_toggle_category(self, categories) - local toggle_index_offset = 0 - - -- Create the toggle category header - local toggle_header_data = { - type = "header", - category = toggle_category, - title = dmf:localize("toggle_mods"), - mod_name = "dmf", - tooltip = dmf:localize("toggle_mods"), - } - local toggle_header = create_option_template(self, toggle_header_data, toggle_category.display_name, toggle_index_offset) - if toggle_header then - settings[#settings + 1] = toggle_header - end - - -- Create the toggle category description - local desc_widget_data = { - mod_name = "dmf", - description = dmf:localize("toggle_mods_description"), - category = toggle_category.display_name, - display_name = toggle_category.display_name, - after = #settings, - type = "description" - } - local desc_template = create_option_template(self, desc_widget_data, toggle_category.display_name, toggle_index_offset) - - if desc_template then - settings[#settings + 1] = desc_template - toggle_index_offset = toggle_index_offset + 1 - end - - -- Create a toggle for each mod; non-toggleable mods' toggles are disabled + -- Create a category for every mod for _, mod_data in ipairs(dmf.options_widgets_data) do - local toggle_widget_data = { - mod_name = mod_data[1].mod_name, - readable_mod_name = mod_data[1].readable_mod_name or mod_data[1].title, - description = mod_data[1].description, - disabled = not mod_data[1].is_togglable, - category = toggle_category.display_name, - after = #settings, - type = "mod_toggle" - } + local category = create_mod_category(self, categories, mod_data[1]) - local toggle_template = create_option_template(self, toggle_widget_data, toggle_category.display_name, toggle_index_offset) - if toggle_template then - settings[#settings + 1] = toggle_template - toggle_index_offset = toggle_index_offset + 1 + local index_offset = 0 + + -- Create the category header + local template = create_option_template(self, mod_data[1], category.display_name, index_offset) + if template then + settings[#settings + 1] = template end - end - -- Create a category for every mod that has additional settings - for _, mod_data in ipairs(dmf.options_widgets_data) do - if #mod_data > 1 then - local category = create_mod_category(self, categories, mod_data[1]) + -- Create the mod description + if mod_data[1].description then + local desc_widget_data = { + mod_name = mod_data[1].mod_name, + description = mod_data[1].description, + category = category.display_name, + display_name = category.display_name, + after = #settings, + type = "description" + } + local desc_template = create_option_template(self, desc_widget_data, category.display_name, index_offset) - local index_offset = 0 + if desc_template then + settings[#settings + 1] = desc_template + index_offset = index_offset + 1 + end + end - -- Create the category header - local template = create_option_template(self, mod_data[1], category.display_name, index_offset) + -- Create a top-level toggle option if the mod is togglable + if mod_data[1].is_togglable then + local toggle_widget_data = { + mod_name = mod_data[1].mod_name, + category = category.display_name, + after = #settings, + type = "mod_toggle" + } + + local toggle_template = create_option_template(self, toggle_widget_data, category.display_name, index_offset) + if toggle_template then + settings[#settings + 1] = toggle_template + index_offset = index_offset + 1 + end + end + + -- Populate the category with options taken from the remaining options data + for i = 2, #mod_data do + local widget_data = mod_data[i] + + template = widget_data_to_template(self, widget_data) if template then + template.custom = true + template.category = category.display_name + template.after = template.after + index_offset + settings[#settings + 1] = template end - - -- Create the mod description - if mod_data[1].description then - local desc_widget_data = { - mod_name = mod_data[1].mod_name, - description = mod_data[1].description, - category = category.display_name, - display_name = category.display_name, - after = #settings, - type = "description" - } - local desc_template = create_option_template(self, desc_widget_data, category.display_name, index_offset) - - if desc_template then - settings[#settings + 1] = desc_template - index_offset = index_offset + 1 - end - end - - -- Populate the category with options taken from the remaining options data - for i = 2, #mod_data do - local widget_data = mod_data[i] - - template = widget_data_to_template(self, widget_data) - if template then - template.custom = true - template.category = category.display_name - template.after = template.after + index_offset - - settings[#settings + 1] = template - end - end end end diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index e69de29..0000000 diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index 8ad8858..0000000 --- a/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -dmf-docs.darkti.de \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 8723347..0000000 --- a/docs/index.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - DMF Docs - - - - - - - - -
- - - - - - - - diff --git a/docs/package-lock.json b/docs/package-lock.json deleted file mode 100644 index ab38ed0..0000000 --- a/docs/package-lock.json +++ /dev/null @@ -1,2024 +0,0 @@ -{ - "name": "dmf-docs", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "dmf-docs", - "dependencies": { - "docsify-cli": "^4.4.4" - } - }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "engines": { - "node": ">=6" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/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==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/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==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/boxen/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==" - }, - "node_modules/boxen/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/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==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/connect-livereload": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.6.1.tgz", - "integrity": "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==", - "engines": { - "node": "*" - } - }, - "node_modules/cp-file": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz", - "integrity": "sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw==", - "dependencies": { - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "nested-error-stacks": "^2.0.0", - "p-event": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/docsify": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/docsify/-/docsify-4.13.0.tgz", - "integrity": "sha512-dM2D0LZKrhK9e5cPwzOTO8FJ2l9IxgiSmTgLBIMjkBlTs1rAUT5camzekbk2AhH0Tw+5lzkNrSb7dmKFuTiLCA==", - "hasInstallScript": true, - "dependencies": { - "marked": "^1.2.9", - "medium-zoom": "^1.0.6", - "opencollective-postinstall": "^2.0.2", - "prismjs": "^1.27.0", - "strip-indent": "^3.0.0", - "tinydate": "^1.3.0", - "tweezer.js": "^1.4.0" - } - }, - "node_modules/docsify-cli": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/docsify-cli/-/docsify-cli-4.4.4.tgz", - "integrity": "sha512-NAZgg6b0BsDuq/Pe+P19Qb2J1d+ZVbS0eGkeCNxyu4F9/CQSsRqZqAvPJ9/0I+BCHn4sgftA2jluqhQVzKzrSA==", - "dependencies": { - "chalk": "^2.4.2", - "connect": "^3.6.0", - "connect-history-api-fallback": "^1.6.0", - "connect-livereload": "^0.6.0", - "cp-file": "^7.0.0", - "docsify": "^4.12.2", - "docsify-server-renderer": ">=4.10.0", - "enquirer": "^2.3.6", - "fs-extra": "^8.1.0", - "get-port": "^5.0.0", - "livereload": "^0.9.2", - "lru-cache": "^5.1.1", - "open": "^6.4.0", - "serve-static": "^1.12.1", - "update-notifier": "^4.1.0", - "yargonaut": "^1.1.2", - "yargs": "^15.3.0" - }, - "bin": { - "docsify": "bin/docsify" - }, - "engines": { - "node": ">= 10", - "npm": ">= 6" - } - }, - "node_modules/docsify-server-renderer": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/docsify-server-renderer/-/docsify-server-renderer-4.13.0.tgz", - "integrity": "sha512-dgJ+mYfkTLuePfTKMmdcRJMFw9YBhmqFS9SgdOc2Fw8emiCTcnOup23wnZ0VdmrEmlc+97K85kASiw/75w6PPQ==", - "dependencies": { - "debug": "^4.3.3", - "docsify": "^4.12.4", - "node-fetch": "^2.6.6", - "resolve-pathname": "^3.0.0" - } - }, - "node_modules/docsify-server-renderer/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/docsify-server-renderer/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/duplexer3": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "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==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/figlet": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.5.2.tgz", - "integrity": "sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.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==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", - "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", - "dependencies": { - "ini": "1.3.7" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", - "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", - "dependencies": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" - }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/livereload": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", - "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==", - "dependencies": { - "chokidar": "^3.5.0", - "livereload-js": "^3.3.1", - "opts": ">= 1.2.0", - "ws": "^7.4.3" - }, - "bin": { - "livereload": "bin/livereload.js" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/livereload-js": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.4.1.tgz", - "integrity": "sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==" - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/marked": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.9.tgz", - "integrity": "sha512-H8lIX2SvyitGX+TRdtS06m1jHMijKN/XjfH6Ooii9fvxMlh8QdqBfBDkGUpMWH2kQNrtixjzYUa3SH8ROTgRRw==", - "bin": { - "marked": "bin/marked" - }, - "engines": { - "node": ">= 8.16.2" - } - }, - "node_modules/medium-zoom": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.8.tgz", - "integrity": "sha512-CjFVuFq/IfrdqesAXfg+hzlDKu6A2n80ZIq0Kl9kWjoHh9j1N9Uvk5X0/MmN0hOfm5F9YBswlClhcwnmtwz7gA==" - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/nested-error-stacks": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz", - "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==" - }, - "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/open": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", - "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", - "dependencies": { - "is-wsl": "^1.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "bin": { - "opencollective-postinstall": "index.js" - } - }, - "node_modules/opts": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz", - "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==" - }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-event": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", - "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", - "dependencies": { - "p-timeout": "^3.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/parent-require": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz", - "integrity": "sha512-2MXDNZC4aXdkkap+rBBMv0lUsfJqvX5/2FiYYnfCnorZt3Pk06/IOR5KeaoghgS2w07MLWgjbsnyaq6PdHn2LQ==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/prismjs": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", - "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dependencies": { - "escape-goat": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", - "dependencies": { - "rc": "1.2.8" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "node_modules/resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/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==" - }, - "node_modules/send/node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } - }, - "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==", - "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==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tinydate": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz", - "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/tweezer.js": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/tweezer.js/-/tweezer.js-1.5.0.tgz", - "integrity": "sha512-aSiJz7rGWNAQq7hjMK9ZYDuEawXupcCWgl3woQQSoDP2Oh8O4srWb/uO1PzzHIsrPEOqrjJ2sUb9FERfzuBabQ==" - }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-notifier": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", - "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", - "dependencies": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/update-notifier/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==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier/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==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/update-notifier/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==" - }, - "node_modules/update-notifier/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/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==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/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==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/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==" - }, - "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==" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yargonaut": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/yargonaut/-/yargonaut-1.1.4.tgz", - "integrity": "sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA==", - "dependencies": { - "chalk": "^1.1.1", - "figlet": "^1.1.1", - "parent-require": "^1.0.0" - } - }, - "node_modules/yargonaut/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargonaut/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargonaut/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargonaut/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yargonaut/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - } - } -} diff --git a/docs/package.json b/docs/package.json deleted file mode 100644 index 0929aef..0000000 --- a/docs/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "dmf-docs", - "private": true, - "scripts": { - "start": "docsify serve ." - }, - "dependencies": { - "docsify-cli": "^4.4.4" - } -}