mirror of https://github.com/zulip/zulip.git
mac_shortcuts: Render shortcuts with `Fn` key correctly.
Updates the `adjusts_mac_shortcuts` function to render shortcuts with the `Fn` key as a separate html element (e.g. `Fn` + `arrow`) instead of rendering the shortcut as one block (e.g. `Fn + arrow`). Also, because keyboard shortcuts should be rendered with each key as a separate html element, updates `adjusts_mac_shortcuts` to only change html elements that are an exact match to a keyboard key. Html elements with whitespace will be ignored (e.g. `Enter` becomes `Return`, but `Enter or Backspace` is not changed though it previously would have been changed to `Return or Delete`). Fixes #22112 (in combination with #22273).
This commit is contained in:
parent
22c4763a61
commit
24d1d08553
|
@ -88,22 +88,27 @@ run_test("adjust_mac_shortcuts non-mac", ({override_rewire}) => {
|
||||||
common.adjust_mac_shortcuts("selector-that-does-not-exist");
|
common.adjust_mac_shortcuts("selector-that-does-not-exist");
|
||||||
});
|
});
|
||||||
|
|
||||||
run_test("adjust_mac_shortcuts mac", ({override_rewire}) => {
|
// Test non-default values of adjust_mac_shortcuts boolean parameters:
|
||||||
|
// `kbd_elem = false`, and `require_cmd_style = true`.
|
||||||
|
run_test("adjust_mac_shortcuts mac non-defaults", ({override_rewire}) => {
|
||||||
const keys_to_test_mac = new Map([
|
const keys_to_test_mac = new Map([
|
||||||
["Backspace", "Delete"],
|
["Backspace", "Delete"],
|
||||||
["Enter", "Return"],
|
["Enter", "Return"],
|
||||||
["Home", "Fn + ←"],
|
["Home", "←"],
|
||||||
["End", "Fn + →"],
|
["End", "→"],
|
||||||
["PgUp", "Fn + ↑"],
|
["PgUp", "↑"],
|
||||||
["PgDn", "Fn + ↓"],
|
["PgDn", "↓"],
|
||||||
|
["Ctrl", "⌘"],
|
||||||
["X + Shift", "X + Shift"],
|
["X + Shift", "X + Shift"],
|
||||||
["⌘ + Return", "⌘ + Return"],
|
["⌘ + Return", "⌘ + Return"],
|
||||||
["Enter or Backspace", "Return or Delete"],
|
["Enter or Backspace", "Enter or Backspace"],
|
||||||
["Ctrl", "⌘"],
|
["#stream_name", "#stream_name"],
|
||||||
["Ctrl + Shift", "⌘ + Shift"],
|
["Ctrl+K", "Ctrl+K"],
|
||||||
["Ctrl + Backspace + End", "⌘ + Delete + Fn + →"],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const fn_shortcuts = new Set(["Home", "End", "PgUp", "PgDn"]);
|
||||||
|
const inserted_fn_key = "<code>Fn</code> + ";
|
||||||
|
|
||||||
override_rewire(common, "has_mac_keyboard", () => true);
|
override_rewire(common, "has_mac_keyboard", () => true);
|
||||||
|
|
||||||
const test_items = [];
|
const test_items = [];
|
||||||
|
@ -114,9 +119,14 @@ run_test("adjust_mac_shortcuts mac", ({override_rewire}) => {
|
||||||
const $stub = $.create("hotkey_" + key_no);
|
const $stub = $.create("hotkey_" + key_no);
|
||||||
$stub.text(old_key);
|
$stub.text(old_key);
|
||||||
assert.equal($stub.hasClass("mac-cmd-key"), false);
|
assert.equal($stub.hasClass("mac-cmd-key"), false);
|
||||||
|
if (fn_shortcuts.has(old_key)) {
|
||||||
|
$stub.before = ($elem) => {
|
||||||
|
assert.equal($elem, inserted_fn_key);
|
||||||
|
};
|
||||||
|
}
|
||||||
test_item.$stub = $stub;
|
test_item.$stub = $stub;
|
||||||
test_item.mac_key = mac_key;
|
test_item.mac_key = mac_key;
|
||||||
test_item.is_cmd_key = old_key.includes("Ctrl");
|
test_item.is_cmd_key = old_key === "Ctrl";
|
||||||
test_items.push(test_item);
|
test_items.push(test_item);
|
||||||
key_no += 1;
|
key_no += 1;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +136,8 @@ run_test("adjust_mac_shortcuts mac", ({override_rewire}) => {
|
||||||
$.create(".markdown_content", {children});
|
$.create(".markdown_content", {children});
|
||||||
|
|
||||||
const require_cmd = true;
|
const require_cmd = true;
|
||||||
common.adjust_mac_shortcuts(".markdown_content", require_cmd);
|
const kbd_element = false;
|
||||||
|
common.adjust_mac_shortcuts(".markdown_content", kbd_element, require_cmd);
|
||||||
|
|
||||||
for (const test_item of test_items) {
|
for (const test_item of test_items) {
|
||||||
assert.equal(test_item.$stub.hasClass("mac-cmd-key"), test_item.is_cmd_key);
|
assert.equal(test_item.$stub.hasClass("mac-cmd-key"), test_item.is_cmd_key);
|
||||||
|
@ -134,6 +145,57 @@ run_test("adjust_mac_shortcuts mac", ({override_rewire}) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Test default values of adjust_mac_shortcuts boolean parameters:
|
||||||
|
// `kbd_elem = true`, and `require_cmd_style = false`.
|
||||||
|
run_test("adjust_mac_shortcuts mac defaults", ({override_rewire}) => {
|
||||||
|
const keys_to_test_mac = new Map([
|
||||||
|
["Backspace", "Delete"],
|
||||||
|
["Enter", "Return"],
|
||||||
|
["Home", "←"],
|
||||||
|
["End", "→"],
|
||||||
|
["PgUp", "↑"],
|
||||||
|
["PgDn", "↓"],
|
||||||
|
["Ctrl", "⌘"],
|
||||||
|
["[", "["],
|
||||||
|
["X", "X"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const fn_shortcuts = new Set(["Home", "End", "PgUp", "PgDn"]);
|
||||||
|
const inserted_fn_key = "<kbd>Fn</kbd> + ";
|
||||||
|
|
||||||
|
override_rewire(common, "has_mac_keyboard", () => true);
|
||||||
|
|
||||||
|
const test_items = [];
|
||||||
|
let key_no = 1;
|
||||||
|
|
||||||
|
for (const [old_key, mac_key] of keys_to_test_mac) {
|
||||||
|
const test_item = {};
|
||||||
|
const $stub = $.create("hotkey_" + key_no);
|
||||||
|
$stub.text(old_key);
|
||||||
|
assert.equal($stub.hasClass("mac-cmd-key"), false);
|
||||||
|
if (fn_shortcuts.has(old_key)) {
|
||||||
|
$stub.before = ($elem) => {
|
||||||
|
assert.equal($elem, inserted_fn_key);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
test_item.$stub = $stub;
|
||||||
|
test_item.mac_key = mac_key;
|
||||||
|
test_items.push(test_item);
|
||||||
|
key_no += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const children = test_items.map((test_item) => ({to_$: () => test_item.$stub}));
|
||||||
|
|
||||||
|
$.create(".hotkeys_table kbd", {children});
|
||||||
|
|
||||||
|
common.adjust_mac_shortcuts(".hotkeys_table kbd");
|
||||||
|
|
||||||
|
for (const test_item of test_items) {
|
||||||
|
assert.equal(test_item.$stub.hasClass("mac-cmd-key"), false);
|
||||||
|
assert.equal(test_item.$stub.text(), test_item.mac_key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
run_test("show password", () => {
|
run_test("show password", () => {
|
||||||
const password_selector = "#id_password ~ .password_visibility_toggle";
|
const password_selector = "#id_password ~ .password_visibility_toggle";
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,11 @@ export function has_mac_keyboard(): boolean {
|
||||||
return /mac/i.test(navigator.platform);
|
return /mac/i.test(navigator.platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function adjust_mac_shortcuts(key_elem_class: string, require_cmd_style = false): void {
|
export function adjust_mac_shortcuts(
|
||||||
|
key_elem_class: string,
|
||||||
|
kbd_elem = true,
|
||||||
|
require_cmd_style = false,
|
||||||
|
): void {
|
||||||
if (!has_mac_keyboard()) {
|
if (!has_mac_keyboard()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -56,28 +60,44 @@ export function adjust_mac_shortcuts(key_elem_class: string, require_cmd_style =
|
||||||
const keys_map = new Map([
|
const keys_map = new Map([
|
||||||
["Backspace", "Delete"],
|
["Backspace", "Delete"],
|
||||||
["Enter", "Return"],
|
["Enter", "Return"],
|
||||||
["Home", "Fn + ←"],
|
["Home", "←"],
|
||||||
["End", "Fn + →"],
|
["End", "→"],
|
||||||
["PgUp", "Fn + ↑"],
|
["PgUp", "↑"],
|
||||||
["PgDn", "Fn + ↓"],
|
["PgDn", "↓"],
|
||||||
["Ctrl", "⌘"],
|
["Ctrl", "⌘"],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const fn_shortcuts = new Set(["Home", "End", "PgUp", "PgDn"]);
|
||||||
|
|
||||||
$(key_elem_class).each(function () {
|
$(key_elem_class).each(function () {
|
||||||
let key_text = $(this).text();
|
let key_text = $(this).text();
|
||||||
const keys = key_text.match(/[^\s+]+/g) || [];
|
|
||||||
|
|
||||||
if (key_text.includes("Ctrl") && require_cmd_style) {
|
// There may be matches to `key_elem_class` that are not
|
||||||
|
// keyboard shortcuts. Since keyboard shortcuts should be an
|
||||||
|
// exact match to the text on a physical key of a keyboard,
|
||||||
|
// none of which have spaces, we check and return early for
|
||||||
|
// any matched element's text that contains whitespace.
|
||||||
|
if (/\s/.test(key_text)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_text === "Ctrl" && require_cmd_style) {
|
||||||
$(this).addClass("mac-cmd-key");
|
$(this).addClass("mac-cmd-key");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const key of keys) {
|
if (fn_shortcuts.has(key_text)) {
|
||||||
const replace_key = keys_map.get(key);
|
if (kbd_elem) {
|
||||||
if (replace_key !== undefined) {
|
$(this).before("<kbd>Fn</kbd> + ");
|
||||||
key_text = key_text.replace(key, replace_key);
|
} else {
|
||||||
|
$(this).before("<code>Fn</code> + ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const replace_key = keys_map.get(key_text);
|
||||||
|
if (replace_key !== undefined) {
|
||||||
|
key_text = replace_key;
|
||||||
|
}
|
||||||
|
|
||||||
$(this).text(key_text);
|
$(this).text(key_text);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ function render_code_sections() {
|
||||||
|
|
||||||
highlight_current_article();
|
highlight_current_article();
|
||||||
|
|
||||||
common.adjust_mac_shortcuts(".markdown .content code", true);
|
common.adjust_mac_shortcuts(".markdown .content code", false, true);
|
||||||
|
|
||||||
$("table").each(function () {
|
$("table").each(function () {
|
||||||
$(this).addClass("table table-striped");
|
$(this).addClass("table table-striped");
|
||||||
|
|
Loading…
Reference in New Issue