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:
Lauryn Menard 2022-06-21 17:58:02 +02:00 committed by Tim Abbott
parent 22c4763a61
commit 24d1d08553
3 changed files with 105 additions and 23 deletions

View File

@ -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";

View File

@ -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);
}); });
} }

View File

@ -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");