chuijs 4.0.2 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +597 -0
- package/README.md +43 -644
- package/framework/appLayout/default/chui_app_layout.js +602 -496
- package/framework/appLayout/default/global_style.css +288 -97
- package/framework/appLayout/default/main_theme_style.css +188 -101
- package/framework/components/chui_accordion/accordion.js +38 -35
- package/framework/components/chui_accordion/styles.css +13 -12
- package/framework/components/chui_action_sheet/action_sheet.js +93 -64
- package/framework/components/chui_action_sheet/styles.css +12 -5
- package/framework/components/chui_actions_bar/actions_bar.js +338 -0
- package/framework/components/chui_actions_bar/styles.css +139 -0
- package/framework/components/chui_affix/affix.js +16 -11
- package/framework/components/chui_affix/styles.css +5 -0
- package/framework/components/chui_alert/alert.js +34 -19
- package/framework/components/chui_alert/styles.css +7 -0
- package/framework/components/chui_avatar/avatar.js +36 -35
- package/framework/components/chui_avatar/styles.css +1 -1
- package/framework/components/chui_avatar_group/avatar_group.js +25 -23
- package/framework/components/chui_avatar_group/styles.css +1 -1
- package/framework/components/chui_backtop/backtop.js +60 -21
- package/framework/components/chui_backtop/styles.css +21 -0
- package/framework/components/chui_badge/badge.js +30 -28
- package/framework/components/chui_badge/styles.css +6 -6
- package/framework/components/chui_banner/banner.js +222 -0
- package/framework/components/chui_banner/styles.css +170 -0
- package/framework/components/chui_breadcrumb/breadcrumb.js +15 -13
- package/framework/components/chui_breadcrumb/styles.css +1 -1
- package/framework/components/chui_button/button.js +52 -36
- package/framework/components/chui_button/styles.css +7 -7
- package/framework/components/chui_calendar/calendar.js +18 -16
- package/framework/components/chui_card/card.js +52 -32
- package/framework/components/chui_card_scroll/card_scroll.js +169 -0
- package/framework/components/chui_card_scroll/styles.css +86 -0
- package/framework/components/chui_chat/chat.js +140 -79
- package/framework/components/chui_chat/styles.css +18 -7
- package/framework/components/chui_clipboard_history/clipboard_history.js +53 -39
- package/framework/components/chui_clipboard_history/styles.css +13 -9
- package/framework/components/chui_code/code.js +10 -10
- package/framework/components/chui_code/styles.css +4 -4
- package/framework/components/chui_code_editor/code_editor.js +73 -57
- package/framework/components/chui_code_editor/styles.css +6 -5
- package/framework/components/chui_command_palette/command_palette.js +87 -64
- package/framework/components/chui_command_palette/styles.css +5 -5
- package/framework/components/chui_console/console.js +13 -13
- package/framework/components/chui_console/styles.css +6 -3
- package/framework/components/chui_content_block/content_block.js +35 -21
- package/framework/components/chui_content_block/styles.css +2 -2
- package/framework/components/chui_context_menu/context_menu.js +171 -58
- package/framework/components/chui_context_menu/styles.css +82 -8
- package/framework/components/chui_custom_element/custom_element.js +25 -18
- package/framework/components/chui_data_grid/data_grid.js +633 -471
- package/framework/components/chui_data_grid/styles.css +24 -22
- package/framework/components/chui_descriptions/descriptions.js +34 -17
- package/framework/components/chui_descriptions/styles.css +1 -1
- package/framework/components/chui_details/details.js +42 -36
- package/framework/components/chui_details/styles.css +12 -11
- package/framework/components/chui_diff_viewer/diff_viewer.js +172 -147
- package/framework/components/chui_diff_viewer/styles.css +10 -10
- package/framework/components/chui_divider/divider.js +19 -17
- package/framework/components/chui_divider/styles.css +2 -2
- package/framework/components/chui_drawer/drawer.js +63 -38
- package/framework/components/chui_drawer/styles.css +18 -4
- package/framework/components/chui_drop_zone/drop_zone.js +37 -27
- package/framework/components/chui_drop_zone/styles.css +10 -6
- package/framework/components/chui_empty_state/empty_state.js +20 -15
- package/framework/components/chui_fieldset/fieldset.js +40 -23
- package/framework/components/chui_fieldset/styles.css +6 -6
- package/framework/components/chui_file_explorer/file_explorer.js +260 -189
- package/framework/components/chui_file_explorer/styles.css +8 -7
- package/framework/components/chui_form/form.js +40 -28
- package/framework/components/chui_form/styles.css +1 -1
- package/framework/components/chui_gantt/gantt.js +102 -78
- package/framework/components/chui_gantt/styles.css +5 -5
- package/framework/components/chui_graphs/graphs.js +376 -239
- package/framework/components/chui_graphs/styles.css +27 -6
- package/framework/components/chui_hero/hero.js +98 -37
- package/framework/components/chui_hero/styles.css +176 -7
- package/framework/components/chui_html_block/html_block.js +8 -8
- package/framework/components/chui_html_block/styles.css +3 -3
- package/framework/components/chui_hx/hx.js +3 -3
- package/framework/components/chui_hx/styles.css +13 -6
- package/framework/components/chui_icons/icons.js +2115 -2115
- package/framework/components/chui_icons/styles.css +4 -3
- package/framework/components/chui_inputs/chui_check_box/check_box.js +31 -19
- package/framework/components/chui_inputs/chui_check_box/styles.css +30 -21
- package/framework/components/chui_inputs/chui_chips/chips.js +141 -70
- package/framework/components/chui_inputs/chui_chips/styles.css +32 -7
- package/framework/components/chui_inputs/chui_color_picker/color_picker.js +55 -38
- package/framework/components/chui_inputs/chui_color_picker/styles.css +7 -7
- package/framework/components/chui_inputs/chui_combo_box/combo_box.js +127 -109
- package/framework/components/chui_inputs/chui_combo_box/styles.css +23 -21
- package/framework/components/chui_inputs/chui_date/date.js +161 -127
- package/framework/components/chui_inputs/chui_date/styles.css +20 -19
- package/framework/components/chui_inputs/chui_date_range/date_range.js +61 -50
- package/framework/components/chui_inputs/chui_date_range/styles.css +3 -3
- package/framework/components/chui_inputs/chui_datetime/datetime.js +47 -39
- package/framework/components/chui_inputs/chui_datetime/styles.css +3 -3
- package/framework/components/chui_inputs/chui_email/email.js +48 -36
- package/framework/components/chui_inputs/chui_email/styles.css +11 -11
- package/framework/components/chui_inputs/chui_file/file.js +71 -44
- package/framework/components/chui_inputs/chui_file/styles.css +23 -19
- package/framework/components/chui_inputs/chui_hotkey/hotkey.js +101 -76
- package/framework/components/chui_inputs/chui_hotkey/styles.css +6 -6
- package/framework/components/chui_inputs/chui_masked/masked.js +83 -72
- package/framework/components/chui_inputs/chui_masked/styles.css +5 -5
- package/framework/components/chui_inputs/chui_mention/mention.js +87 -40
- package/framework/components/chui_inputs/chui_mention/styles.css +14 -8
- package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +242 -212
- package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +23 -15
- package/framework/components/chui_inputs/chui_number/number.js +84 -70
- package/framework/components/chui_inputs/chui_number/styles.css +13 -13
- package/framework/components/chui_inputs/chui_otp/otp.js +71 -62
- package/framework/components/chui_inputs/chui_otp/styles.css +5 -5
- package/framework/components/chui_inputs/chui_password/password.js +72 -56
- package/framework/components/chui_inputs/chui_password/styles.css +15 -15
- package/framework/components/chui_inputs/chui_radio_button/radio_button.js +37 -25
- package/framework/components/chui_inputs/chui_radio_button/styles.css +22 -22
- package/framework/components/chui_inputs/chui_rating/rating.js +54 -50
- package/framework/components/chui_inputs/chui_rating/styles.css +3 -3
- package/framework/components/chui_inputs/chui_select_box/select_box.js +132 -108
- package/framework/components/chui_inputs/chui_select_box/styles.css +21 -21
- package/framework/components/chui_inputs/chui_slider/slider.js +41 -38
- package/framework/components/chui_inputs/chui_slider/styles.css +7 -5
- package/framework/components/chui_inputs/chui_text/styles.css +14 -14
- package/framework/components/chui_inputs/chui_text/text.js +69 -52
- package/framework/components/chui_inputs/chui_text_area/styles.css +14 -14
- package/framework/components/chui_inputs/chui_text_area/text_area.js +59 -36
- package/framework/components/chui_inputs/chui_time/styles.css +18 -20
- package/framework/components/chui_inputs/chui_time/time.js +71 -49
- package/framework/components/chui_inputs/chui_toggle/styles.css +13 -6
- package/framework/components/chui_inputs/chui_toggle/toggle.js +27 -27
- package/framework/components/chui_json_editor/json_editor.js +137 -127
- package/framework/components/chui_json_editor/styles.css +5 -5
- package/framework/components/chui_json_viewer/json_viewer.js +133 -114
- package/framework/components/chui_json_viewer/styles.css +9 -8
- package/framework/components/chui_kanban/kanban.js +78 -60
- package/framework/components/chui_kanban/styles.css +8 -4
- package/framework/components/chui_kbd/kbd.js +12 -10
- package/framework/components/chui_kbd/styles.css +1 -1
- package/framework/components/chui_label/label.js +31 -29
- package/framework/components/chui_label/styles.css +3 -3
- package/framework/components/chui_link/link.js +36 -29
- package/framework/components/chui_link/styles.css +11 -4
- package/framework/components/chui_list/list.js +42 -38
- package/framework/components/chui_list/styles.css +4 -3
- package/framework/components/chui_markdown_editor/markdown_editor.js +125 -109
- package/framework/components/chui_markdown_editor/styles.css +5 -5
- package/framework/components/chui_media/audio.js +457 -364
- package/framework/components/chui_media/audio_styles.css +74 -37
- package/framework/components/chui_media/image.js +99 -64
- package/framework/components/chui_media/image_compare.js +86 -55
- package/framework/components/chui_media/image_compare_styles.css +5 -5
- package/framework/components/chui_media/image_styles.css +4 -4
- package/framework/components/chui_media/video.js +264 -171
- package/framework/components/chui_media/video_styles.css +57 -24
- package/framework/components/chui_menu_bar/menu_bar.js +67 -65
- package/framework/components/chui_menu_bar/styles.css +14 -12
- package/framework/components/chui_message_bar/message_bar.js +551 -0
- package/framework/components/chui_message_bar/styles.css +248 -0
- package/framework/components/chui_modal/modal.js +81 -56
- package/framework/components/chui_modal/styles.css +3 -2
- package/framework/components/chui_notification/notification.js +107 -69
- package/framework/components/chui_notification/notification_download.js +28 -77
- package/framework/components/chui_notification/notification_download_card.js +115 -0
- package/framework/components/chui_notification/notification_download_progress.css +5 -4
- package/framework/components/chui_notification/notification_download_progress.js +73 -105
- package/framework/components/chui_notification/notification_update.js +44 -37
- package/framework/components/chui_notification/status_plate.css +3 -3
- package/framework/components/chui_notification/status_plate.js +2 -2
- package/framework/components/chui_notification/styles.css +6 -1
- package/framework/components/chui_notification/styles_download.css +2 -2
- package/framework/components/chui_notification/styles_update.css +3 -3
- package/framework/components/chui_org_chart/org_chart.js +101 -62
- package/framework/components/chui_org_chart/styles.css +2 -2
- package/framework/components/chui_pagination/pagination.js +65 -30
- package/framework/components/chui_pagination/styles.css +1 -1
- package/framework/components/chui_paragraph/paragraph.js +2 -2
- package/framework/components/chui_paragraph/styles.css +3 -3
- package/framework/components/chui_popover/popover.js +77 -50
- package/framework/components/chui_popover/styles.css +1 -1
- package/framework/components/chui_popups/popups.js +210 -181
- package/framework/components/chui_popups/styles.css +7 -7
- package/framework/components/chui_print_button/print_button.js +48 -33
- package/framework/components/chui_progress_bar/progress_bar.js +49 -19
- package/framework/components/chui_progress_bar/styles.css +6 -6
- package/framework/components/chui_progress_ring/progress_ring.js +32 -30
- package/framework/components/chui_progress_ring/styles.css +1 -1
- package/framework/components/chui_qrcode/qrcode.js +85 -41
- package/framework/components/chui_query_builder/query_builder.js +263 -170
- package/framework/components/chui_query_builder/styles.css +4 -4
- package/framework/components/chui_radio_group/radio_group.js +36 -26
- package/framework/components/chui_radio_group/styles.css +2 -2
- package/framework/components/chui_result/result.js +41 -31
- package/framework/components/chui_result/styles.css +3 -3
- package/framework/components/chui_scheduler/scheduler.js +126 -104
- package/framework/components/chui_scheduler/styles.css +11 -7
- package/framework/components/chui_screen_spinner/screen_spinner.js +167 -0
- package/framework/components/chui_screen_spinner/styles.css +49 -0
- package/framework/components/chui_segmented_control/segmented_control.js +90 -27
- package/framework/components/chui_segmented_control/styles.css +32 -6
- package/framework/components/chui_settings/settings.js +160 -87
- package/framework/components/chui_settings/styles.css +4 -4
- package/framework/components/chui_shortcut_help/shortcut_help.js +82 -61
- package/framework/components/chui_sidebar_nav/sidebar_nav.js +132 -53
- package/framework/components/chui_sidebar_nav/styles.css +9 -3
- package/framework/components/chui_skeleton/skeleton.js +29 -24
- package/framework/components/chui_slideshow/slideshow.js +122 -103
- package/framework/components/chui_slideshow/styles.css +22 -16
- package/framework/components/chui_spinner/spinner.js +17 -17
- package/framework/components/chui_spinner/styles.css +0 -1
- package/framework/components/chui_split_button/split_button.js +53 -30
- package/framework/components/chui_split_button/styles.css +22 -6
- package/framework/components/chui_splitter/splitter.js +46 -39
- package/framework/components/chui_splitter/styles.css +2 -2
- package/framework/components/chui_statistic/statistic.js +111 -84
- package/framework/components/chui_status_bar/status_bar.js +11 -9
- package/framework/components/chui_status_bar/styles.css +2 -2
- package/framework/components/chui_stepper/stepper.js +230 -54
- package/framework/components/chui_stepper/styles.css +79 -14
- package/framework/components/chui_sticky_bar/sticky_bar.js +53 -17
- package/framework/components/chui_sticky_bar/styles.css +11 -7
- package/framework/components/chui_tabs/chui_tabs.js +100 -46
- package/framework/components/chui_tabs/styles.css +43 -15
- package/framework/components/chui_text_editor/styles.css +24 -23
- package/framework/components/chui_text_editor/text_editor.js +103 -79
- package/framework/components/chui_text_editor/text_editor_panel.js +428 -367
- package/framework/components/chui_theme_toggle/theme_toggle.js +46 -25
- package/framework/components/chui_timeline/styles.css +3 -1
- package/framework/components/chui_timeline/timeline.js +14 -12
- package/framework/components/chui_toast_queue/styles.css +11 -11
- package/framework/components/chui_toast_queue/toast_queue.js +82 -73
- package/framework/components/chui_toolbar/styles.css +2 -2
- package/framework/components/chui_toolbar/toolbar.js +20 -13
- package/framework/components/chui_tooltip/styles.css +2 -2
- package/framework/components/chui_tooltip/tooltip.js +40 -27
- package/framework/components/chui_tour/styles.css +12 -7
- package/framework/components/chui_tour/tour.js +132 -98
- package/framework/components/chui_transfer/styles.css +8 -7
- package/framework/components/chui_transfer/transfer.js +143 -123
- package/framework/components/chui_tree_table/styles.css +4 -4
- package/framework/components/chui_tree_table/tree_table.js +88 -74
- package/framework/components/chui_tree_view/styles.css +14 -10
- package/framework/components/chui_tree_view/tree_view.js +298 -253
- package/framework/components/chui_user_bar/styles.css +145 -0
- package/framework/components/chui_user_bar/user_bar.js +402 -0
- package/framework/components/chui_user_list_bar/styles.css +173 -0
- package/framework/components/chui_user_list_bar/user_list_bar.js +485 -0
- package/framework/components/chui_watermark/watermark.js +41 -33
- package/framework/components/chui_webview/styles.css +2 -2
- package/framework/components/chui_webview/webview.js +64 -52
- package/framework/components/chui_write_bar/styles.css +172 -0
- package/framework/components/chui_write_bar/write_bar.js +320 -0
- package/framework/main_window.js +1234 -0
- package/framework/modules/chui_a11y/chui_a11y.js +153 -123
- package/framework/modules/chui_animations/animations.js +105 -43
- package/framework/modules/chui_animations/motion.js +120 -0
- package/framework/modules/chui_animations/styles.css +37 -4
- package/framework/modules/chui_bridge/preload.js +36 -25
- package/framework/modules/chui_functions.js +69 -63
- package/framework/modules/chui_highlight/chui_highlight.js +25 -22
- package/framework/modules/chui_highlight/styles.css +13 -10
- package/framework/modules/chui_i18n/chui_i18n.js +12 -10
- package/framework/modules/chui_i18n/locales/a11y.js +5 -5
- package/framework/modules/chui_i18n/locales/app_layout.js +5 -5
- package/framework/modules/chui_i18n/locales/calendar.js +3 -3
- package/framework/modules/chui_i18n/locales/common.js +3 -3
- package/framework/modules/chui_i18n/locales/data.js +36 -26
- package/framework/modules/chui_i18n/locales/editors.js +40 -13
- package/framework/modules/chui_i18n/locales/feedback.js +65 -3
- package/framework/modules/chui_i18n/locales/forms.js +8 -8
- package/framework/modules/chui_i18n/locales/graphics.js +8 -8
- package/framework/modules/chui_i18n/locales/media.js +4 -4
- package/framework/modules/chui_i18n/locales/navigation.js +12 -8
- package/framework/modules/chui_i18n/locales/validate.js +3 -3
- package/framework/modules/chui_json/chui_json.js +11 -11
- package/framework/modules/chui_layout/chui_layout.js +12 -10
- package/framework/modules/chui_logger/chui_logger.js +47 -28
- package/framework/modules/chui_page/page.js +39 -33
- package/framework/modules/chui_palette/palette.js +61 -0
- package/framework/modules/chui_qr/chui_qr.js +179 -88
- package/framework/modules/chui_scrollbar/chui_scrollbar.js +79 -68
- package/framework/modules/chui_scrollbar/styles.css +4 -2
- package/framework/modules/chui_services/chui_channels.js +27 -13
- package/framework/modules/chui_services/chui_services.js +47 -39
- package/framework/modules/chui_services/desktop.js +108 -101
- package/framework/modules/chui_sortable/chui_sortable.js +33 -28
- package/framework/modules/chui_validate/chui_validate.js +10 -7
- package/framework/tray_bar/chui_menu_items.js +136 -46
- package/index.d.ts +5046 -0
- package/index.js +199 -1254
- package/package.json +81 -68
- package/framework/components/telegram_bot/chui_telegram_bot.js +0 -184
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const {setStyles} = require("../../modules/chui_functions");
|
|
2
|
-
const {I18n} = require("../../modules/chui_i18n/chui_i18n");
|
|
1
|
+
const { setStyles } = require("../../modules/chui_functions");
|
|
2
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
3
3
|
|
|
4
4
|
/** Типы строк модели сравнения */
|
|
5
5
|
const EQUAL = "equal";
|
|
@@ -46,8 +46,8 @@ const GAP = "gap";
|
|
|
46
46
|
* Слушателей вне своих узлов нет, поэтому `destroy()` не нужен.
|
|
47
47
|
*/
|
|
48
48
|
class DiffViewer {
|
|
49
|
-
static MODE = {SIDE_BY_SIDE: "side", UNIFIED: "unified"};
|
|
50
|
-
static ROW = {EQUAL: EQUAL, INSERT: INSERT, DELETE: DELETE, REPLACE: REPLACE, GAP: GAP};
|
|
49
|
+
static MODE = { SIDE_BY_SIDE: "side", UNIFIED: "unified" };
|
|
50
|
+
static ROW = { EQUAL: EQUAL, INSERT: INSERT, DELETE: DELETE, REPLACE: REPLACE, GAP: GAP };
|
|
51
51
|
/** Предел таблицы LCS (ячеек): больше — середина расхождения показывается одним блоком */
|
|
52
52
|
static LCS_LIMIT = 250000;
|
|
53
53
|
static #counter = 0;
|
|
@@ -56,65 +56,67 @@ class DiffViewer {
|
|
|
56
56
|
#title = document.createElement("diff_viewer_title");
|
|
57
57
|
#head = document.createElement("diff_viewer_head");
|
|
58
58
|
#stats = document.createElement("diff_viewer_stats");
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
59
|
+
#statRemoved = document.createElement("diff_viewer_stat");
|
|
60
|
+
#statAdded = document.createElement("diff_viewer_stat");
|
|
61
|
+
#statChanged = document.createElement("diff_viewer_stat");
|
|
62
62
|
#prev = document.createElement("button");
|
|
63
63
|
#next = document.createElement("button");
|
|
64
64
|
#grid = document.createElement("diff_viewer_grid");
|
|
65
|
-
#
|
|
65
|
+
#headRow = document.createElement("diff_viewer_head_row");
|
|
66
66
|
#body = document.createElement("diff_viewer_body");
|
|
67
67
|
#empty = document.createElement("diff_viewer_empty");
|
|
68
68
|
#status = document.createElement("diff_viewer_status");
|
|
69
69
|
#id = undefined;
|
|
70
70
|
#left = "";
|
|
71
71
|
#right = "";
|
|
72
|
-
#
|
|
73
|
-
#
|
|
72
|
+
#leftTitle = undefined;
|
|
73
|
+
#rightTitle = undefined;
|
|
74
74
|
#mode = DiffViewer.MODE.SIDE_BY_SIDE;
|
|
75
75
|
#context = 3;
|
|
76
|
-
#
|
|
76
|
+
#lineNumbers = true;
|
|
77
77
|
#height = "360px";
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
78
|
+
#titleText = undefined;
|
|
79
|
+
#labelText = undefined;
|
|
80
|
+
#emptyText = undefined;
|
|
81
81
|
#rows = [];
|
|
82
|
-
#
|
|
82
|
+
#statsData = { equal: 0, added: 0, removed: 0, changed: 0, groups: 0 };
|
|
83
83
|
#approximate = false;
|
|
84
84
|
#expanded = [];
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
constructor(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
85
|
+
#activeIndex = undefined;
|
|
86
|
+
#focusIndex = undefined;
|
|
87
|
+
|
|
88
|
+
constructor(
|
|
89
|
+
options = {
|
|
90
|
+
id: String(),
|
|
91
|
+
title: String(),
|
|
92
|
+
label: String(),
|
|
93
|
+
left: String(),
|
|
94
|
+
right: String(),
|
|
95
|
+
leftTitle: String(),
|
|
96
|
+
rightTitle: String(),
|
|
97
|
+
mode: String(),
|
|
98
|
+
context: Number(),
|
|
99
|
+
lineNumbers: Boolean(),
|
|
100
|
+
height: String(),
|
|
101
|
+
emptyText: String(),
|
|
102
|
+
}
|
|
103
|
+
) {
|
|
102
104
|
require("../../modules/chui_fonts").installMono();
|
|
103
105
|
setStyles(__dirname + "/styles.css", "chUiJS_DiffViewer");
|
|
104
106
|
DiffViewer.#counter += 1;
|
|
105
107
|
this.#id = options.id === undefined ? `chui_diff_viewer_${DiffViewer.#counter}` : options.id;
|
|
106
108
|
this.#root.id = this.#id;
|
|
107
109
|
this.#root.setAttribute("role", "group");
|
|
108
|
-
this.#
|
|
109
|
-
if (options.leftTitle !== undefined) this.#
|
|
110
|
-
else this.#
|
|
111
|
-
if (options.rightTitle !== undefined) this.#
|
|
112
|
-
else this.#
|
|
113
|
-
if (options.emptyText !== undefined) this.#
|
|
114
|
-
else this.#
|
|
110
|
+
this.#labelText = options.label;
|
|
111
|
+
if (options.leftTitle !== undefined) this.#leftTitle = String(options.leftTitle);
|
|
112
|
+
else this.#leftTitle = I18n.t("diffViewer.before");
|
|
113
|
+
if (options.rightTitle !== undefined) this.#rightTitle = String(options.rightTitle);
|
|
114
|
+
else this.#rightTitle = I18n.t("diffViewer.after");
|
|
115
|
+
if (options.emptyText !== undefined) this.#emptyText = String(options.emptyText);
|
|
116
|
+
else this.#emptyText = I18n.t("diffViewer.noChanges");
|
|
115
117
|
this.#mode = options.mode === DiffViewer.MODE.UNIFIED ? DiffViewer.MODE.UNIFIED : DiffViewer.MODE.SIDE_BY_SIDE;
|
|
116
118
|
this.#context = options.context === undefined ? this.#context : options.context;
|
|
117
|
-
this.#
|
|
119
|
+
this.#lineNumbers = options.lineNumbers !== false;
|
|
118
120
|
this.#title.className = "diff_viewer_title";
|
|
119
121
|
this.#title.id = `${this.#id}_title`;
|
|
120
122
|
this.#head.className = "diff_viewer_head";
|
|
@@ -123,8 +125,8 @@ class DiffViewer {
|
|
|
123
125
|
this.#stats.setAttribute("aria-hidden", "true");
|
|
124
126
|
this.#grid.className = "diff_viewer_grid";
|
|
125
127
|
this.#grid.setAttribute("role", "table");
|
|
126
|
-
this.#
|
|
127
|
-
this.#
|
|
128
|
+
this.#headRow.className = "diff_viewer_head_row";
|
|
129
|
+
this.#headRow.setAttribute("role", "row");
|
|
128
130
|
this.#body.className = "diff_viewer_body";
|
|
129
131
|
this.#body.setAttribute("role", "rowgroup");
|
|
130
132
|
this.#empty.className = "diff_viewer_empty";
|
|
@@ -134,14 +136,14 @@ class DiffViewer {
|
|
|
134
136
|
this.#buildHead();
|
|
135
137
|
this.#root.appendChild(this.#title);
|
|
136
138
|
this.#root.appendChild(this.#head);
|
|
137
|
-
this.#grid.appendChild(this.#
|
|
139
|
+
this.#grid.appendChild(this.#headRow);
|
|
138
140
|
this.#grid.appendChild(this.#body);
|
|
139
141
|
this.#root.appendChild(this.#grid);
|
|
140
142
|
this.#root.appendChild(this.#empty);
|
|
141
143
|
this.#root.appendChild(this.#status);
|
|
142
144
|
if (options.title !== undefined) this.setTitle(options.title);
|
|
143
145
|
else this.#title.hidden = true;
|
|
144
|
-
this.setLabel(this.#
|
|
146
|
+
this.setLabel(this.#labelText === undefined ? I18n.t("diffViewer.title") : this.#labelText);
|
|
145
147
|
// Высота из опций: без неё остаётся своя по умолчанию (360px, тело прокручивается)
|
|
146
148
|
this.setHeight(options.height === undefined ? this.#height : options.height);
|
|
147
149
|
this.setTexts(options.left === undefined ? "" : options.left, options.right === undefined ? "" : options.right);
|
|
@@ -156,12 +158,12 @@ class DiffViewer {
|
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
getTitle() {
|
|
159
|
-
return this.#
|
|
161
|
+
return this.#titleText;
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
/** Доступное имя компонента, заданное в `label` */
|
|
163
165
|
getLabel() {
|
|
164
|
-
return this.#
|
|
166
|
+
return this.#labelText;
|
|
165
167
|
}
|
|
166
168
|
|
|
167
169
|
getMode() {
|
|
@@ -177,11 +179,11 @@ class DiffViewer {
|
|
|
177
179
|
}
|
|
178
180
|
|
|
179
181
|
getLeftTitle() {
|
|
180
|
-
return this.#
|
|
182
|
+
return this.#leftTitle;
|
|
181
183
|
}
|
|
182
184
|
|
|
183
185
|
getRightTitle() {
|
|
184
|
-
return this.#
|
|
186
|
+
return this.#rightTitle;
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
/** Строки модели: `{type, left, right}` (у вставки нет левой строки, у удаления — правой) */
|
|
@@ -191,19 +193,21 @@ class DiffViewer {
|
|
|
191
193
|
|
|
192
194
|
/** Счёт изменений: `{equal, added, removed, changed, groups}` */
|
|
193
195
|
getStats() {
|
|
194
|
-
return Object.assign({}, this.#
|
|
196
|
+
return Object.assign({}, this.#statsData);
|
|
195
197
|
}
|
|
196
198
|
|
|
197
199
|
/** Строки с учётом свёрнутых участков: у пропуска `{type: "gap", from, to}` (индексы модели) */
|
|
198
200
|
getVisibleRows() {
|
|
199
|
-
return this.#visibleRows().map((entry) =>
|
|
200
|
-
? {type: GAP, from: entry.from, to: entry.to}
|
|
201
|
-
|
|
201
|
+
return this.#visibleRows().map((entry) =>
|
|
202
|
+
entry.type === GAP ? { type: GAP, from: entry.from, to: entry.to } : DiffViewer.#describe(entry.row)
|
|
203
|
+
);
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
/** Показан ли хоть один пропуск */
|
|
205
207
|
getGaps() {
|
|
206
|
-
return this.#visibleRows()
|
|
208
|
+
return this.#visibleRows()
|
|
209
|
+
.filter((entry) => entry.type === GAP)
|
|
210
|
+
.map((entry) => ({ from: entry.from, to: entry.to }));
|
|
207
211
|
}
|
|
208
212
|
|
|
209
213
|
getContext() {
|
|
@@ -211,7 +215,7 @@ class DiffViewer {
|
|
|
211
215
|
}
|
|
212
216
|
|
|
213
217
|
isLineNumbers() {
|
|
214
|
-
return this.#
|
|
218
|
+
return this.#lineNumbers;
|
|
215
219
|
}
|
|
216
220
|
|
|
217
221
|
getHeight() {
|
|
@@ -219,7 +223,7 @@ class DiffViewer {
|
|
|
219
223
|
}
|
|
220
224
|
|
|
221
225
|
getEmptyText() {
|
|
222
|
-
return this.#
|
|
226
|
+
return this.#emptyText;
|
|
223
227
|
}
|
|
224
228
|
|
|
225
229
|
/** Сработал ли предел алгоритма: середина расхождения показана одним блоком */
|
|
@@ -238,7 +242,7 @@ class DiffViewer {
|
|
|
238
242
|
|
|
239
243
|
/** Подпись над сравнением; `undefined` её убирает (имя тогда даёт `label`) */
|
|
240
244
|
setTitle(text = undefined) {
|
|
241
|
-
this.#
|
|
245
|
+
this.#titleText = text;
|
|
242
246
|
if (text === undefined || text === "") {
|
|
243
247
|
this.#title.hidden = true;
|
|
244
248
|
this.#title.innerText = "";
|
|
@@ -253,19 +257,19 @@ class DiffViewer {
|
|
|
253
257
|
|
|
254
258
|
/** Имя сравнения, когда подписи в разметке нет */
|
|
255
259
|
setLabel(text = undefined) {
|
|
256
|
-
this.#
|
|
260
|
+
this.#labelText = text;
|
|
257
261
|
this.#syncLabel();
|
|
258
262
|
return this;
|
|
259
263
|
}
|
|
260
264
|
|
|
261
265
|
setLeftTitle(text = String()) {
|
|
262
|
-
this.#
|
|
266
|
+
this.#leftTitle = String(text);
|
|
263
267
|
this.#render();
|
|
264
268
|
return this;
|
|
265
269
|
}
|
|
266
270
|
|
|
267
271
|
setRightTitle(text = String()) {
|
|
268
|
-
this.#
|
|
272
|
+
this.#rightTitle = String(text);
|
|
269
273
|
this.#render();
|
|
270
274
|
return this;
|
|
271
275
|
}
|
|
@@ -294,8 +298,8 @@ class DiffViewer {
|
|
|
294
298
|
this.#expanded = [];
|
|
295
299
|
this.#approximate = false;
|
|
296
300
|
this.#rows = this.#buildRows(DiffViewer.#split(this.#left), DiffViewer.#split(this.#right));
|
|
297
|
-
this.#
|
|
298
|
-
this.#
|
|
301
|
+
this.#statsData = this.#collectStats();
|
|
302
|
+
this.#activeIndex = undefined;
|
|
299
303
|
this.#render();
|
|
300
304
|
this.#announce();
|
|
301
305
|
return this;
|
|
@@ -317,14 +321,14 @@ class DiffViewer {
|
|
|
317
321
|
|
|
318
322
|
/** Раскрыть пропуск по индексам модели (как кнопка «Показать N строк») */
|
|
319
323
|
expandRange(from = Number(), to = Number()) {
|
|
320
|
-
this.#expanded.push({from: Number(from), to: Number(to)});
|
|
321
|
-
this.#
|
|
324
|
+
this.#expanded.push({ from: Number(from), to: Number(to) });
|
|
325
|
+
this.#focusIndex = Number(from);
|
|
322
326
|
this.#render();
|
|
323
327
|
return this;
|
|
324
328
|
}
|
|
325
329
|
|
|
326
330
|
setLineNumbers(shown = Boolean()) {
|
|
327
|
-
this.#
|
|
331
|
+
this.#lineNumbers = shown !== false;
|
|
328
332
|
this.#render();
|
|
329
333
|
return this;
|
|
330
334
|
}
|
|
@@ -343,7 +347,7 @@ class DiffViewer {
|
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
setEmptyText(text = String()) {
|
|
346
|
-
this.#
|
|
350
|
+
this.#emptyText = text === undefined ? "" : String(text);
|
|
347
351
|
this.#render();
|
|
348
352
|
return this;
|
|
349
353
|
}
|
|
@@ -380,9 +384,9 @@ class DiffViewer {
|
|
|
380
384
|
}
|
|
381
385
|
|
|
382
386
|
static #describe(row = Object()) {
|
|
383
|
-
const descriptor = {type: row.type};
|
|
384
|
-
if (row.left !== undefined) descriptor.left = {number: row.left.number, text: row.left.text};
|
|
385
|
-
if (row.right !== undefined) descriptor.right = {number: row.right.number, text: row.right.text};
|
|
387
|
+
const descriptor = { type: row.type };
|
|
388
|
+
if (row.left !== undefined) descriptor.left = { number: row.left.number, text: row.left.text };
|
|
389
|
+
if (row.right !== undefined) descriptor.right = { number: row.right.number, text: row.right.text };
|
|
386
390
|
return descriptor;
|
|
387
391
|
}
|
|
388
392
|
|
|
@@ -394,9 +398,10 @@ class DiffViewer {
|
|
|
394
398
|
const table = new Int32Array((rows + 1) * width);
|
|
395
399
|
for (let i = rows - 1; i >= 0; i -= 1) {
|
|
396
400
|
for (let j = columns - 1; j >= 0; j -= 1) {
|
|
397
|
-
table[i * width + j] =
|
|
398
|
-
|
|
399
|
-
|
|
401
|
+
table[i * width + j] =
|
|
402
|
+
left[i] === right[j]
|
|
403
|
+
? table[(i + 1) * width + (j + 1)] + 1
|
|
404
|
+
: Math.max(table[(i + 1) * width + j], table[i * width + (j + 1)]);
|
|
400
405
|
}
|
|
401
406
|
}
|
|
402
407
|
const pairs = [];
|
|
@@ -419,14 +424,14 @@ class DiffViewer {
|
|
|
419
424
|
let li = 0;
|
|
420
425
|
let ri = 0;
|
|
421
426
|
for (const [i, j] of DiffViewer.#pairs(left, right)) {
|
|
422
|
-
if (i > li) operations.push({type: DELETE, from: li, to: i});
|
|
423
|
-
if (j > ri) operations.push({type: INSERT, from: ri, to: j});
|
|
424
|
-
operations.push({type: EQUAL, i: i, j: j});
|
|
427
|
+
if (i > li) operations.push({ type: DELETE, from: li, to: i });
|
|
428
|
+
if (j > ri) operations.push({ type: INSERT, from: ri, to: j });
|
|
429
|
+
operations.push({ type: EQUAL, i: i, j: j });
|
|
425
430
|
li = i + 1;
|
|
426
431
|
ri = j + 1;
|
|
427
432
|
}
|
|
428
|
-
if (li < left.length) operations.push({type: DELETE, from: li, to: left.length});
|
|
429
|
-
if (ri < right.length) operations.push({type: INSERT, from: ri, to: right.length});
|
|
433
|
+
if (li < left.length) operations.push({ type: DELETE, from: li, to: left.length });
|
|
434
|
+
if (ri < right.length) operations.push({ type: INSERT, from: ri, to: right.length });
|
|
430
435
|
return operations;
|
|
431
436
|
}
|
|
432
437
|
|
|
@@ -435,24 +440,28 @@ class DiffViewer {
|
|
|
435
440
|
let prefix = 0;
|
|
436
441
|
while (prefix < left.length && prefix < right.length && left[prefix] === right[prefix]) prefix += 1;
|
|
437
442
|
let suffix = 0;
|
|
438
|
-
while (
|
|
439
|
-
|
|
443
|
+
while (
|
|
444
|
+
suffix < left.length - prefix &&
|
|
445
|
+
suffix < right.length - prefix &&
|
|
446
|
+
left[left.length - 1 - suffix] === right[right.length - 1 - suffix]
|
|
447
|
+
)
|
|
448
|
+
suffix += 1;
|
|
440
449
|
const rows = [];
|
|
441
450
|
for (let i = 0; i < prefix; i += 1) rows.push(DiffViewer.#equalRow(left[i], i + 1, right[i], i + 1));
|
|
442
|
-
const
|
|
443
|
-
const
|
|
444
|
-
if (
|
|
451
|
+
const middleLeft = left.slice(prefix, left.length - suffix);
|
|
452
|
+
const middleRight = right.slice(prefix, right.length - suffix);
|
|
453
|
+
if (middleLeft.length > 0 || middleRight.length > 0) {
|
|
445
454
|
let operations;
|
|
446
|
-
if (
|
|
455
|
+
if (middleLeft.length * middleRight.length > DiffViewer.LCS_LIMIT) {
|
|
447
456
|
// Предел алгоритма: вместо честного (но не помещающегося) LCS показываем один блок
|
|
448
457
|
this.#approximate = true;
|
|
449
458
|
operations = [];
|
|
450
|
-
if (
|
|
451
|
-
if (
|
|
459
|
+
if (middleLeft.length > 0) operations.push({ type: DELETE, from: 0, to: middleLeft.length });
|
|
460
|
+
if (middleRight.length > 0) operations.push({ type: INSERT, from: 0, to: middleRight.length });
|
|
452
461
|
} else {
|
|
453
|
-
operations = DiffViewer.#operations(
|
|
462
|
+
operations = DiffViewer.#operations(middleLeft, middleRight);
|
|
454
463
|
}
|
|
455
|
-
for (const row of DiffViewer.#middleRows(operations,
|
|
464
|
+
for (const row of DiffViewer.#middleRows(operations, middleLeft, middleRight, prefix)) rows.push(row);
|
|
456
465
|
}
|
|
457
466
|
for (let k = 0; k < suffix; k += 1) {
|
|
458
467
|
const li = left.length - suffix + k;
|
|
@@ -462,11 +471,11 @@ class DiffViewer {
|
|
|
462
471
|
return rows;
|
|
463
472
|
}
|
|
464
473
|
|
|
465
|
-
static #equalRow(
|
|
474
|
+
static #equalRow(leftText = String(), leftNumber = Number(), rightText = String(), rightNumber = Number()) {
|
|
466
475
|
return {
|
|
467
476
|
type: EQUAL,
|
|
468
|
-
left: {number:
|
|
469
|
-
right: {number:
|
|
477
|
+
left: { number: leftNumber, text: leftText },
|
|
478
|
+
right: { number: rightNumber, text: rightText },
|
|
470
479
|
};
|
|
471
480
|
}
|
|
472
481
|
|
|
@@ -481,32 +490,41 @@ class DiffViewer {
|
|
|
481
490
|
for (let k = 0; k < pairs; k += 1) {
|
|
482
491
|
const li = operation.from + k;
|
|
483
492
|
const ri = next.from + k;
|
|
484
|
-
const
|
|
485
|
-
const
|
|
493
|
+
const hasLeft = li < operation.to;
|
|
494
|
+
const hasRight = ri < next.to;
|
|
486
495
|
rows.push({
|
|
487
|
-
type:
|
|
488
|
-
left:
|
|
489
|
-
right:
|
|
496
|
+
type: hasLeft && hasRight ? REPLACE : hasLeft ? DELETE : INSERT,
|
|
497
|
+
left: hasLeft ? { number: offset + li + 1, text: left[li] } : undefined,
|
|
498
|
+
right: hasRight ? { number: offset + ri + 1, text: right[ri] } : undefined,
|
|
490
499
|
});
|
|
491
500
|
}
|
|
492
501
|
index += 1;
|
|
493
502
|
continue;
|
|
494
503
|
}
|
|
495
504
|
if (operation.type === EQUAL) {
|
|
496
|
-
rows.push(
|
|
505
|
+
rows.push(
|
|
506
|
+
DiffViewer.#equalRow(
|
|
507
|
+
left[operation.i],
|
|
508
|
+
offset + operation.i + 1,
|
|
509
|
+
right[operation.j],
|
|
510
|
+
offset + operation.j + 1
|
|
511
|
+
)
|
|
512
|
+
);
|
|
497
513
|
continue;
|
|
498
514
|
}
|
|
499
515
|
for (let i = operation.from; i < operation.to; i += 1) {
|
|
500
|
-
rows.push(
|
|
501
|
-
|
|
502
|
-
|
|
516
|
+
rows.push(
|
|
517
|
+
operation.type === DELETE
|
|
518
|
+
? { type: DELETE, left: { number: offset + i + 1, text: left[i] }, right: undefined }
|
|
519
|
+
: { type: INSERT, left: undefined, right: { number: offset + i + 1, text: right[i] } }
|
|
520
|
+
);
|
|
503
521
|
}
|
|
504
522
|
}
|
|
505
523
|
return rows;
|
|
506
524
|
}
|
|
507
525
|
|
|
508
526
|
#collectStats() {
|
|
509
|
-
const stats = {equal: 0, added: 0, removed: 0, changed: 0, groups: 0};
|
|
527
|
+
const stats = { equal: 0, added: 0, removed: 0, changed: 0, groups: 0 };
|
|
510
528
|
for (const row of this.#rows) {
|
|
511
529
|
if (row.type === EQUAL) stats.equal += 1;
|
|
512
530
|
if (row.type === INSERT) stats.added += 1;
|
|
@@ -537,8 +555,9 @@ class DiffViewer {
|
|
|
537
555
|
#visibleRows() {
|
|
538
556
|
const total = this.#rows.length;
|
|
539
557
|
const list = [];
|
|
540
|
-
if (this.#context === Infinity || this.#
|
|
541
|
-
for (let index = 0; index < total; index += 1)
|
|
558
|
+
if (this.#context === Infinity || this.#statsData.groups === 0) {
|
|
559
|
+
for (let index = 0; index < total; index += 1)
|
|
560
|
+
list.push({ type: this.#rows[index].type, row: this.#rows[index], index: index });
|
|
542
561
|
return list;
|
|
543
562
|
}
|
|
544
563
|
const context = Number.isFinite(this.#context) ? Math.max(0, Math.floor(this.#context)) : 0;
|
|
@@ -553,29 +572,29 @@ class DiffViewer {
|
|
|
553
572
|
for (let index = 0; index < total; index += 1) {
|
|
554
573
|
if (keep[index] || this.#isExpanded(index)) {
|
|
555
574
|
if (gap !== undefined) {
|
|
556
|
-
list.push({type: GAP, from: gap.from, to: gap.to});
|
|
575
|
+
list.push({ type: GAP, from: gap.from, to: gap.to });
|
|
557
576
|
gap = undefined;
|
|
558
577
|
}
|
|
559
|
-
list.push({type: this.#rows[index].type, row: this.#rows[index], index: index});
|
|
578
|
+
list.push({ type: this.#rows[index].type, row: this.#rows[index], index: index });
|
|
560
579
|
continue;
|
|
561
580
|
}
|
|
562
|
-
if (gap === undefined) gap = {from: index, to: index};
|
|
581
|
+
if (gap === undefined) gap = { from: index, to: index };
|
|
563
582
|
else gap.to = index;
|
|
564
583
|
}
|
|
565
|
-
if (gap !== undefined) list.push({type: GAP, from: gap.from, to: gap.to});
|
|
584
|
+
if (gap !== undefined) list.push({ type: GAP, from: gap.from, to: gap.to });
|
|
566
585
|
return list;
|
|
567
586
|
}
|
|
568
587
|
|
|
569
588
|
#accessibleName() {
|
|
570
|
-
if (this.#
|
|
571
|
-
if (this.#
|
|
589
|
+
if (this.#titleText !== undefined && this.#titleText !== "") return this.#titleText;
|
|
590
|
+
if (this.#labelText !== undefined && this.#labelText !== "") return this.#labelText;
|
|
572
591
|
return I18n.t("diffViewer.title");
|
|
573
592
|
}
|
|
574
593
|
|
|
575
594
|
// Имя компонента: видимая подпись — через aria-labelledby, скрытая — через aria-label.
|
|
576
595
|
// Таблица внутри получает то же имя: у неё своя роль, и без имени она читалась бы безымянной
|
|
577
596
|
#syncLabel() {
|
|
578
|
-
if (this.#
|
|
597
|
+
if (this.#titleText !== undefined && this.#titleText !== "") {
|
|
579
598
|
this.#root.setAttribute("aria-labelledby", this.#title.id);
|
|
580
599
|
this.#root.removeAttribute("aria-label");
|
|
581
600
|
} else {
|
|
@@ -588,12 +607,12 @@ class DiffViewer {
|
|
|
588
607
|
|
|
589
608
|
#buildHead() {
|
|
590
609
|
this.#stats.innerHTML = "";
|
|
591
|
-
this.#
|
|
592
|
-
this.#
|
|
593
|
-
this.#
|
|
594
|
-
this.#stats.appendChild(this.#
|
|
595
|
-
this.#stats.appendChild(this.#
|
|
596
|
-
this.#stats.appendChild(this.#
|
|
610
|
+
this.#statRemoved.className = "diff_viewer_stat diff_viewer_stat_removed";
|
|
611
|
+
this.#statAdded.className = "diff_viewer_stat diff_viewer_stat_added";
|
|
612
|
+
this.#statChanged.className = "diff_viewer_stat diff_viewer_stat_changed";
|
|
613
|
+
this.#stats.appendChild(this.#statRemoved);
|
|
614
|
+
this.#stats.appendChild(this.#statAdded);
|
|
615
|
+
this.#stats.appendChild(this.#statChanged);
|
|
597
616
|
this.#prev.type = "button";
|
|
598
617
|
this.#prev.className = "diff_viewer_move diff_viewer_move_prev";
|
|
599
618
|
this.#prev.setAttribute("aria-label", I18n.t("diffViewer.previousChange"));
|
|
@@ -612,9 +631,9 @@ class DiffViewer {
|
|
|
612
631
|
|
|
613
632
|
// Вид изменения словами: номер строки берётся из «своей» версии текста
|
|
614
633
|
#rowLabel(row = Object()) {
|
|
615
|
-
if (row.type === INSERT) return I18n.t("diffViewer.lineAdded", {number: row.right.number});
|
|
616
|
-
if (row.type === DELETE) return I18n.t("diffViewer.lineRemoved", {number: row.left.number});
|
|
617
|
-
if (row.type === REPLACE) return I18n.t("diffViewer.lineChanged", {number: row.left.number});
|
|
634
|
+
if (row.type === INSERT) return I18n.t("diffViewer.lineAdded", { number: row.right.number });
|
|
635
|
+
if (row.type === DELETE) return I18n.t("diffViewer.lineRemoved", { number: row.left.number });
|
|
636
|
+
if (row.type === REPLACE) return I18n.t("diffViewer.lineChanged", { number: row.left.number });
|
|
618
637
|
return undefined;
|
|
619
638
|
}
|
|
620
639
|
|
|
@@ -639,7 +658,7 @@ class DiffViewer {
|
|
|
639
658
|
const number = document.createElement("span");
|
|
640
659
|
number.className = "diff_viewer_number";
|
|
641
660
|
number.setAttribute("aria-hidden", "true");
|
|
642
|
-
number.innerText = this.#
|
|
661
|
+
number.innerText = this.#lineNumbers && line !== undefined ? String(line.number) : "";
|
|
643
662
|
const text = document.createElement("span");
|
|
644
663
|
text.className = "diff_viewer_text";
|
|
645
664
|
text.innerText = line === undefined ? "" : line.text;
|
|
@@ -658,7 +677,7 @@ class DiffViewer {
|
|
|
658
677
|
const label = this.#rowLabel(row);
|
|
659
678
|
if (label !== undefined) node.setAttribute("aria-label", label);
|
|
660
679
|
if (row.type !== EQUAL) node.classList.add(`diff_viewer_row_${row.type}`);
|
|
661
|
-
node.classList.toggle("diff_viewer_row_no_numbers", this.#
|
|
680
|
+
node.classList.toggle("diff_viewer_row_no_numbers", this.#lineNumbers === false);
|
|
662
681
|
for (const cell of this.#cells(row)) node.appendChild(cell);
|
|
663
682
|
return node;
|
|
664
683
|
}
|
|
@@ -696,17 +715,17 @@ class DiffViewer {
|
|
|
696
715
|
button.className = "diff_viewer_expand";
|
|
697
716
|
button.dataset.from = String(entry.from);
|
|
698
717
|
button.dataset.to = String(entry.to);
|
|
699
|
-
button.innerText = I18n.t("diffViewer.showLines", {count: count});
|
|
718
|
+
button.innerText = I18n.t("diffViewer.showLines", { count: count });
|
|
700
719
|
cell.appendChild(button);
|
|
701
720
|
node.appendChild(cell);
|
|
702
721
|
return node;
|
|
703
722
|
}
|
|
704
723
|
|
|
705
724
|
#applyStats() {
|
|
706
|
-
const stats = this.#
|
|
707
|
-
this.#
|
|
708
|
-
this.#
|
|
709
|
-
this.#
|
|
725
|
+
const stats = this.#statsData;
|
|
726
|
+
this.#statRemoved.innerText = `−${stats.removed}`;
|
|
727
|
+
this.#statAdded.innerText = `+${stats.added}`;
|
|
728
|
+
this.#statChanged.innerText = `~${stats.changed}`;
|
|
710
729
|
const empty = stats.groups === 0;
|
|
711
730
|
this.#prev.disabled = empty;
|
|
712
731
|
this.#next.disabled = empty;
|
|
@@ -714,13 +733,16 @@ class DiffViewer {
|
|
|
714
733
|
}
|
|
715
734
|
|
|
716
735
|
#announce() {
|
|
717
|
-
const stats = this.#
|
|
736
|
+
const stats = this.#statsData;
|
|
718
737
|
if (stats.groups === 0) {
|
|
719
738
|
this.#status.innerText = I18n.t("diffViewer.noChanges");
|
|
720
739
|
return this;
|
|
721
740
|
}
|
|
722
741
|
this.#status.innerText = I18n.t("diffViewer.summary", {
|
|
723
|
-
groups: stats.groups,
|
|
742
|
+
groups: stats.groups,
|
|
743
|
+
added: stats.added,
|
|
744
|
+
removed: stats.removed,
|
|
745
|
+
changed: stats.changed,
|
|
724
746
|
});
|
|
725
747
|
return this;
|
|
726
748
|
}
|
|
@@ -729,27 +751,29 @@ class DiffViewer {
|
|
|
729
751
|
// Строки пересобираются, а фокус живёт на строке: запоминаем её до перерисовки
|
|
730
752
|
const active = document.activeElement;
|
|
731
753
|
const focused = active === null || !this.#grid.contains(active) ? null : active.closest(".diff_viewer_row");
|
|
732
|
-
if (focused !== null && focused.dataset.index !== undefined) this.#
|
|
733
|
-
this.#
|
|
754
|
+
if (focused !== null && focused.dataset.index !== undefined) this.#focusIndex = Number(focused.dataset.index);
|
|
755
|
+
this.#headRow.innerHTML = "";
|
|
734
756
|
this.#body.innerHTML = "";
|
|
735
|
-
const titles =
|
|
736
|
-
|
|
737
|
-
|
|
757
|
+
const titles =
|
|
758
|
+
this.#mode === DiffViewer.MODE.UNIFIED
|
|
759
|
+
? [I18n.t("diffViewer.changes")]
|
|
760
|
+
: [this.#leftTitle, this.#rightTitle];
|
|
738
761
|
for (const title of titles) {
|
|
739
762
|
const cell = document.createElement("div");
|
|
740
763
|
cell.className = "diff_viewer_head_cell";
|
|
741
764
|
cell.setAttribute("role", "columnheader");
|
|
742
765
|
cell.innerText = title;
|
|
743
|
-
this.#
|
|
766
|
+
this.#headRow.appendChild(cell);
|
|
744
767
|
}
|
|
745
768
|
this.#grid.setAttribute("aria-colcount", String(titles.length));
|
|
746
769
|
this.#grid.classList.toggle("diff_viewer_grid_unified", this.#mode === DiffViewer.MODE.UNIFIED);
|
|
747
770
|
const list = this.#visibleRows();
|
|
748
|
-
for (const entry of list)
|
|
771
|
+
for (const entry of list)
|
|
772
|
+
this.#body.appendChild(entry.type === GAP ? this.#gapNode(entry) : this.#rowNode(entry));
|
|
749
773
|
this.#grid.setAttribute("aria-rowcount", String(list.length + 1));
|
|
750
774
|
this.#grid.hidden = this.#rows.length === 0;
|
|
751
|
-
this.#empty.hidden = this.#
|
|
752
|
-
this.#empty.innerText = this.#
|
|
775
|
+
this.#empty.hidden = this.#statsData.groups !== 0;
|
|
776
|
+
this.#empty.innerText = this.#emptyText;
|
|
753
777
|
this.#applyStats();
|
|
754
778
|
this.#applyStop();
|
|
755
779
|
return this;
|
|
@@ -760,14 +784,14 @@ class DiffViewer {
|
|
|
760
784
|
const list = [...this.#body.querySelectorAll(".diff_viewer_row")];
|
|
761
785
|
if (list.length === 0) return;
|
|
762
786
|
const stop =
|
|
763
|
-
list.find((row) => Number(row.dataset.index) === this.#
|
|
764
|
-
list.find((row) => Number(row.dataset.index) === this.#
|
|
787
|
+
list.find((row) => Number(row.dataset.index) === this.#activeIndex) ??
|
|
788
|
+
list.find((row) => Number(row.dataset.index) === this.#focusIndex) ??
|
|
765
789
|
list[0];
|
|
766
|
-
this.#
|
|
790
|
+
this.#activeIndex = Number(stop.dataset.index);
|
|
767
791
|
for (const row of list) row.setAttribute("tabindex", row === stop ? "0" : "-1");
|
|
768
792
|
// Фокус возвращаем, только если он был в теле: иначе перерисовка его бы украла
|
|
769
|
-
if (this.#
|
|
770
|
-
this.#
|
|
793
|
+
if (this.#focusIndex !== undefined && Number(stop.dataset.index) === this.#focusIndex) {
|
|
794
|
+
this.#focusIndex = undefined;
|
|
771
795
|
stop.focus();
|
|
772
796
|
}
|
|
773
797
|
return this;
|
|
@@ -775,7 +799,7 @@ class DiffViewer {
|
|
|
775
799
|
|
|
776
800
|
#focusRow(row = undefined) {
|
|
777
801
|
if (row === undefined || row === null) return this;
|
|
778
|
-
this.#
|
|
802
|
+
this.#activeIndex = Number(row.dataset.index);
|
|
779
803
|
for (const other of this.#body.querySelectorAll(".diff_viewer_row")) {
|
|
780
804
|
other.setAttribute("tabindex", other === row ? "0" : "-1");
|
|
781
805
|
}
|
|
@@ -784,11 +808,12 @@ class DiffViewer {
|
|
|
784
808
|
}
|
|
785
809
|
|
|
786
810
|
#focusIndexAt(index = Number()) {
|
|
787
|
-
const row = [...this.#body.querySelectorAll(".diff_viewer_row")]
|
|
788
|
-
|
|
811
|
+
const row = [...this.#body.querySelectorAll(".diff_viewer_row")].find(
|
|
812
|
+
(node) => Number(node.dataset.index) === Number(index)
|
|
813
|
+
);
|
|
789
814
|
if (row === undefined) return this;
|
|
790
815
|
this.#focusRow(row);
|
|
791
|
-
row.scrollIntoView({block: "nearest"});
|
|
816
|
+
row.scrollIntoView({ block: "nearest" });
|
|
792
817
|
return this;
|
|
793
818
|
}
|
|
794
819
|
|
|
@@ -814,7 +839,7 @@ class DiffViewer {
|
|
|
814
839
|
#goToChange(direction = Number()) {
|
|
815
840
|
const groups = this.#changeGroups();
|
|
816
841
|
if (groups.length === 0) return this;
|
|
817
|
-
const current = this.#
|
|
842
|
+
const current = this.#activeIndex;
|
|
818
843
|
const forward = direction > 0;
|
|
819
844
|
let target;
|
|
820
845
|
if (current === undefined) target = forward ? groups[0] : groups[groups.length - 1];
|
|
@@ -834,7 +859,7 @@ class DiffViewer {
|
|
|
834
859
|
#onFocusIn = (event) => {
|
|
835
860
|
const row = event.target instanceof Element ? event.target.closest(".diff_viewer_row") : null;
|
|
836
861
|
if (row === null || row.dataset.index === undefined) return;
|
|
837
|
-
this.#
|
|
862
|
+
this.#activeIndex = Number(row.dataset.index);
|
|
838
863
|
};
|
|
839
864
|
|
|
840
865
|
#onKeyDown = (event) => {
|
|
@@ -864,4 +889,4 @@ class DiffViewer {
|
|
|
864
889
|
};
|
|
865
890
|
}
|
|
866
891
|
|
|
867
|
-
exports.DiffViewer = DiffViewer
|
|
892
|
+
exports.DiffViewer = DiffViewer;
|