From 21449eeea8781e6f98d153239ece97dbe8a32ab4 Mon Sep 17 00:00:00 2001 From: Waylan Limberg Date: Fri, 13 Jul 2018 14:37:53 -0400 Subject: [PATCH] Don't conflict with accessibility shortcuts. In both built-in themes, the default next/prev shortcut keys were changed from arrows to n/p as the arrows conflict with common browser accessibility extensions. In the mkdocs theme, users can now configure the shortcuts to whatever they want. Note that these config options are theme specific. The readthedocs theme does not get these options as they are not available on the parent theme. Fixes #1502 --- docs/about/release-notes.md | 2 + docs/user-guide/styling-your-docs.md | 45 ++++++-- mkdocs/tests/config/config_tests.py | 6 +- mkdocs/tests/theme_tests.py | 3 +- mkdocs/themes/mkdocs/base.html | 5 +- mkdocs/themes/mkdocs/js/base.js | 131 ++++++++++++++++++++++- mkdocs/themes/mkdocs/keyboard-modal.html | 15 ++- mkdocs/themes/mkdocs/mkdocs_theme.yml | 6 ++ mkdocs/themes/readthedocs/js/theme.js | 4 +- 9 files changed, 188 insertions(+), 29 deletions(-) diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md index a78859ca..eb996f51 100644 --- a/docs/about/release-notes.md +++ b/docs/about/release-notes.md @@ -238,6 +238,8 @@ value to the `theme.custom_dir` option and a warning was issued. As of version ### Other Changes and Additions to Version 1.0 +* Keyboard shortcuts changed to not conflict with commonly used accessibility + shortcuts (#1502.) * User friendly YAML parse errors (#1543). * Officially support Python 3.7. * A missing theme configuration file now raises an error. diff --git a/docs/user-guide/styling-your-docs.md b/docs/user-guide/styling-your-docs.md index 1663e006..b485b5b1 100644 --- a/docs/user-guide/styling-your-docs.md +++ b/docs/user-guide/styling-your-docs.md @@ -26,8 +26,12 @@ the [Customizing a Theme][customize] section below. The default theme, which was built as a custom [Bootstrap] theme, supports most every feature of MkDocs. It only officially supports two levels in the -navigation (see #1107). In addition to the default [theme configuration -options], the `mkdocs` theme supports the following options: +navigation (see #1107). + +![mkdocs](../img/mkdocs.png) + +In addition to the default [theme configuration options], the `mkdocs` theme +supports the following options: * __`highlightjs`__: Enables highlighting of source code in code blocks using the [highlight.js] JavaScript library. Default: `True`. @@ -35,16 +39,35 @@ options], the `mkdocs` theme supports the following options: * __`hljs_languages`__: By default, highlight.js only supports 23 common languages. List additional languages here to include support for them. -```yaml -theme: - name: mkdocs - highlightjs: true - hljs_languages: - - yaml - - rust -``` + theme: + name: mkdocs + highlightjs: true + hljs_languages: + - yaml + - rust -![mkdocs](../img/mkdocs.png) +* __`shortcuts`__: Defines keyboard shortcut keys. + + theme: + name: mkdocs + shortcuts: + help: 191 # ? + next: 78 # n + previous: 80 # p + search: 83 # s + + All values much be numeric key codes. It is best to use keys which are + available on all keyboards. You may use to determine + the key code for a given key. + + * __`help`__: Display a help modal which lists the keyboard shortcuts. + Default: `191` (?) + + * __`next`__: Navigate to the "next" page. Default: `78` (n) + + * __`previous`__: Navigate to the "previous" page. Default: `80` (p) + + * __`search`__: Display the search modal. Default: `83` (s) ### readthedocs diff --git a/mkdocs/tests/config/config_tests.py b/mkdocs/tests/config/config_tests.py index 4e224173..8f5fe08d 100644 --- a/mkdocs/tests/config/config_tests.py +++ b/mkdocs/tests/config/config_tests.py @@ -130,7 +130,8 @@ class ConfigTests(unittest.TestCase): 'include_search_page': False, 'search_index_only': False, 'highlightjs': True, - 'hljs_languages': [] + 'hljs_languages': [], + 'shortcuts': {'help': 191, 'next': 78, 'previous': 80, 'search': 83} } }, { 'dirs': [os.path.join(theme_dir, 'readthedocs'), mkdocs_templates_dir], @@ -172,7 +173,8 @@ class ConfigTests(unittest.TestCase): 'include_search_page': False, 'search_index_only': False, 'highlightjs': True, - 'hljs_languages': [] + 'hljs_languages': [], + 'shortcuts': {'help': 191, 'next': 78, 'previous': 80, 'search': 83} } } ) diff --git a/mkdocs/tests/theme_tests.py b/mkdocs/tests/theme_tests.py index d06b3c15..39e32a07 100644 --- a/mkdocs/tests/theme_tests.py +++ b/mkdocs/tests/theme_tests.py @@ -32,7 +32,8 @@ class ThemeTests(unittest.TestCase): 'include_search_page': False, 'search_index_only': False, 'highlightjs': True, - 'hljs_languages': [] + 'hljs_languages': [], + 'shortcuts': {'help': 191, 'next': 78, 'previous': 80, 'search': 83} }) def test_custom_dir(self): diff --git a/mkdocs/themes/mkdocs/base.html b/mkdocs/themes/mkdocs/base.html index 5b4854ac..a8fef736 100644 --- a/mkdocs/themes/mkdocs/base.html +++ b/mkdocs/themes/mkdocs/base.html @@ -191,7 +191,10 @@ {%- block scripts %} - + {%- for path in config['extra_javascript'] %} diff --git a/mkdocs/themes/mkdocs/js/base.js b/mkdocs/themes/mkdocs/js/base.js index b7cd6a68..4755f434 100644 --- a/mkdocs/themes/mkdocs/js/base.js +++ b/mkdocs/themes/mkdocs/js/base.js @@ -35,25 +35,32 @@ $(document).ready(function() { } }); + // Populate keyboard modal with proper Keys + $keyboard_modal.find('.help.shortcut kbd')[0].innerHTML = keyCodes[shortcuts.help]; + $keyboard_modal.find('.prev.shortcut kbd')[0].innerHTML = keyCodes[shortcuts.previous]; + $keyboard_modal.find('.next.shortcut kbd')[0].innerHTML = keyCodes[shortcuts.next]; + $keyboard_modal.find('.search.shortcut kbd')[0].innerHTML = keyCodes[shortcuts.search]; + // Keyboard navigation document.addEventListener("keydown", function(e) { if ($(e.target).is(':input')) return true; var key = e.which || e.keyCode || window.event && window.event.keyCode; var page; switch (key) { - case 39: // right arrow + case shortcuts.next: page = $('[role="navigation"] a:contains(Next):first').prop('href'); break; - case 37: // left arrow + case shortcuts.previous: page = $('[role="navigation"] a:contains(Previous):first').prop('href'); break; - case 83: // s + case shortcuts.search: e.preventDefault(); $keyboard_modal.modal('hide'); $search_modal.modal('show'); $search_modal.find('#mkdocs-search-query').focus(); break; - case 191: // ? + case shortcuts.help: + $search_modal.modal('hide'); $keyboard_modal.modal('show'); break; default: break; @@ -91,3 +98,119 @@ $('body').scrollspy({ $("li.disabled a").click(function() { event.preventDefault(); }); + +// See https://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes +// We only list common keys below. Obscure keys are omited and their use is discouraged. +var keyCodes = { + 8: 'backspace', + 9: 'tab', + 13: 'enter', + 16: 'shift', + 17: 'ctrl', + 18: 'alt', + 19: 'pause/break', + 20: 'caps lock', + 27: 'escape', + 32: 'spacebar', + 33: 'page up', + 34: 'page down', + 35: 'end', + 36: 'home', + 37: '←', + 38: '↑', + 39: '→', + 40: '↓', + 45: 'insert', + 46: 'delete', + 48: '0', + 49: '1', + 50: '2', + 51: '3', + 52: '4', + 53: '5', + 54: '6', + 55: '7', + 56: '8', + 57: '9', + 65: 'a', + 66: 'b', + 67: 'c', + 68: 'd', + 69: 'e', + 70: 'f', + 71: 'g', + 72: 'h', + 73: 'i', + 74: 'j', + 75: 'k', + 76: 'l', + 77: 'm', + 78: 'n', + 79: 'o', + 80: 'p', + 81: 'q', + 82: 'r', + 83: 's', + 84: 't', + 85: 'u', + 86: 'v', + 87: 'w', + 88: 'x', + 89: 'y', + 90: 'z', + 91: 'Left Windows Key / Left ⌘', + 92: 'Right Windows Key', + 93: 'Windows Menu / Right ⌘', + 96: 'numpad 0', + 97: 'numpad 1', + 98: 'numpad 2', + 99: 'numpad 3', + 100: 'numpad 4', + 101: 'numpad 5', + 102: 'numpad 6', + 103: 'numpad 7', + 104: 'numpad 8', + 105: 'numpad 9', + 106: 'multiply', + 107: 'add', + 109: 'subtract', + 110: 'decimal point', + 111: 'divide', + 112: 'f1', + 113: 'f2', + 114: 'f3', + 115: 'f4', + 116: 'f5', + 117: 'f6', + 118: 'f7', + 119: 'f8', + 120: 'f9', + 121: 'f10', + 122: 'f11', + 123: 'f12', + 124: 'f13', + 125: 'f14', + 126: 'f15', + 127: 'f16', + 128: 'f17', + 129: 'f18', + 130: 'f19', + 131: 'f20', + 132: 'f21', + 133: 'f22', + 134: 'f23', + 135: 'f24', + 144: 'num lock', + 145: 'scroll lock', + 186: ';', + 187: '=', + 188: ',', + 189: '‐', + 190: '.', + 191: '?', + 192: '`', + 219: '[', + 220: '\', + 221: ']', + 222: ''', +}; diff --git a/mkdocs/themes/mkdocs/keyboard-modal.html b/mkdocs/themes/mkdocs/keyboard-modal.html index f903ddf8..eb9e09c8 100644 --- a/mkdocs/themes/mkdocs/keyboard-modal.html +++ b/mkdocs/themes/mkdocs/keyboard-modal.html @@ -15,19 +15,19 @@ - ? + ? Open this help - - Previous page - - - + n Next page - s + p + Previous page + + + s Search @@ -38,4 +38,3 @@ - diff --git a/mkdocs/themes/mkdocs/mkdocs_theme.yml b/mkdocs/themes/mkdocs/mkdocs_theme.yml index 5ba0caa5..d6109c23 100644 --- a/mkdocs/themes/mkdocs/mkdocs_theme.yml +++ b/mkdocs/themes/mkdocs/mkdocs_theme.yml @@ -8,3 +8,9 @@ search_index_only: false highlightjs: true hljs_languages: [] + +shortcuts: + help: 191 # ? + next: 78 # n + previous: 80 # p + search: 83 # s diff --git a/mkdocs/themes/readthedocs/js/theme.js b/mkdocs/themes/readthedocs/js/theme.js index 1a30ccea..c3801dc4 100644 --- a/mkdocs/themes/readthedocs/js/theme.js +++ b/mkdocs/themes/readthedocs/js/theme.js @@ -17,10 +17,10 @@ $( document ).ready(function() { var key = e.which || e.keyCode || window.event && window.event.keyCode; var page; switch (key) { - case 39: // right arrow + case 78: // n page = $('[role="navigation"] a:contains(Next):first').prop('href'); break; - case 37: // left arrow + case 80: // p page = $('[role="navigation"] a:contains(Previous):first').prop('href'); break; default: break;