// ==UserScript==
// @name 沉浸阅读(for微信读书)
// @version 0.5.0
// @author GinWU
// @contributor !Sylas;SimonDW;Li_MIxdown;hubzy;xvusrmqj;LossJ;JackieZheng;das2m;harmonyLife;yehuda
// @namespace https://screw-hand.com/
// @description 微信读书的阅读字体修改为苍耳今楷,加减宽度,鼠标离开显示隐藏导航栏、功能栏、滚动条,多档滚动速度,自动翻页,自定义宽度和主题(与原生深/浅主题互斥),仅适配weread.qq.com站点
// @match https://weread.qq.com/web/reader/*
// @icon https://weread.qq.com/favicon.ico
// @grant GM_addStyle
// @grant unsafeWindow
// @license MIT
// ==/UserScript==
/**
* fork from https://greasyfork.org/zh-CN/scripts/490065-%E5%BE%AE%E4%BF%A1%E8%AF%BB%E4%B9%A6weread%E9%98%85%E8%AF%BB%E7%BB%BC%E5%90%88%E5%8A%9F%E8%83%BD%E7%89%88
* and so as https://greasyfork.org/zh-CN/scripts/458095-%E5%BE%AE%E4%BF%A1%E8%AF%BB%E4%B9%A6%E5%8A%A0%E5%AE%BD%E5%8F%AF%E8%A7%86%E8%8C%83%E5%9B%B4%E5%92%8C%E5%87%A0%E4%B8%AA%E7%99%BD%E8%89%B2%E4%B8%BB%E9%A2%98%E7%9A%84%E6%8A%A4%E7%9C%BC%E6%A8%A1%E5%BC%8F
*/
GM_addStyle(`
* {
font-family: SourceHanSerifCN-Bold !important;
}
.readerControls {
height: 433px; margin-left: 0; left: initial; right: 20px; display: flex; flex-wrap: wrap; flex-direction: column; width: initial; right: 10px; bottom: 20px; padding-left: 200px;
}
.readerTopBar, .readerControls {
opacity: 0; transition: opacity 1s;
}
.readerControls_item, .readerControls_fontSize {
margin-top: 25px; margin-right: 10px; color:#6a6c6c; cursor:pointer;
}
.readerChapterContent { margin-left: 30px !important; margin-right: 30px !important; }
.readerControls:hover, .readerTopBar:hover {
opacity: 1;
}
.readerCatalog {
right: 125px; left: initial;
}
.readerAIChatPanel {
right: 125px; left: initial;
}
.readerAIChatPanel_header {
display: grid;
grid-template-columns: 1fr auto;
grid-template-rows: auto auto;
grid-template-areas:
"title button_full"
"subtitle button_close";
align-items: center;
column-gap: 15px;
padding: 8px 15px;
}
.readerAIChatPanel_header_title {
grid-area: title;
justify-self: start;
}
.readerAIChatPanel_header_subtitle {
grid-area: subtitle;
justify-self: start;
}
.readerAIChatPanel_header_btn_full,
.readerAIChatPanel_header_btn_close {
margin: 4px 0;
padding: 0 20px;
background: #3a3a3a;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.readerAIChatPanel_header_btn_full {
grid-area: button_full;
}
.readerAIChatPanel_header_btn_close {
grid-area: button_close;
}
.readerAIChatPanel_fullscreen {
z-index: 9999 !important;
left: 0 !important;
top: 0 !important;
right: 0 !important;
bottom: 0 !important;
width: 100vw !important;
height: 100vh !important;
margin: 0 !important;
border-radius: 0 !important;
max-width: 100vw !important;
max-height: 100vh !important;
}
`);
const colors = [
{ bg: 'rgba(236, 217, 172, 0.4)', rbg: 'rgba(243, 227, 188, 1)', bgb: 'rgba(251, 239, 209, 0.5)', bgbBar: '#dbdbdb', white: true },
{
bg: 'rgba(102, 128, 102, 0.1)',
rbg: 'rgba(65, 94, 62, 1)',
bgb: 'rgba(102, 128, 102, 0.25)',
bgbBar: '#dbdbdb',
white: true
},
{ bg: '#b5b5b5', rbg: '#c5c5c5', bgb: '#dbdbdb', bgbBar: '#dbdbdb', white: true }
];
const ElementUtils = {
cssGet: (tar_elm, property) => {
/**
* 获取 css 属性
*
* tar_elm: elementNode
* property: string
*/
return window.getComputedStyle(tar_elm).getPropertyValue(property);
},
cssSet: (tar_elm, property, value, priority) => {
/**
* 设置 css 属性
*
* tar_elm: node
* property: string
* value: string | number | null
* priority: string | null
*/
return tar_elm.style.setProperty(property, value, priority);
},
htmlGet: (tar_elm, is_out) => {
/**
* 获取 HTML 代码
*
* tar_elm: node
* is_in: bool
*/
if (is_out) {
return tar_elm.outerHTML;
}
return tar_elm.innerHTML;
},
insertHtml: (tar_elm, ins_html, position) => {
/**
* 在目标元素指定位置插入 HTML 代码
*
* tar_elm: node
* ins_html: string
* position: string -> 可选项:beforeBegin、afterBegin、beforeEnd、afterEnd
*/
position = typeof position === "undefined" ? "beforeEnd" : position;
tar_elm.insertAdjacentHTML(position, ins_html);
},
insertElement: (tar_elm, ins_elm, position) => {
/**
* 在目标元素指定位置插入元素
*
* tar_elm: node
* ins_elm: node
* position: string -> 可选项:beforeBegin、afterBegin、beforeEnd、afterEnd
*/
position = typeof position === "undefined" ? "beforeEnd" : position;
tar_elm.insertAdjacentElement(position, ins_elm);
},
};
let div_body = $css("body");
let div_content = $css(".app_content");
let div_controls = $css(".readerControls");
let div_top_bar = $css(".readerTopBar");
let btn_width_add = $css("#width-add");
let btn_width_dev = $css("#width-dev");
let btn_scroll_on = $css("#scroll-on");
let btn_scroll_off = $css("#scroll-off");
let btn_turn_tips = $css("#turn-page-tips");
let scroll_speed = 0;
let styleElementForCustomTheme = null;
function getStyleStr_customTheme() {
let style = `
/* 通用样式覆盖,确保在任何情况下均优先显示自定义主题 */
html body.wr-mode-0, html body.wr-mode-1, html body.wr-mode-2 {
transition: background-color 0.3s ease-in-out !important;
}
`;
for (let i = 0; i < colors.length; i++) {
const color = colors[i];
style += `
html body.wr-mode-${i} {
background-color:${color.bg} !important;
}
html body.wr-mode-${i} .readerTopBar {
background-color:${color.rbg} !important;
}
html body.wr-mode-${i} .readerControls_item,
html body.wr-mode-${i} .readerControls_fontSize,
html body.wr-mode-${i} .app_content,
html body.wr-mode-${i} #custom-theme-toggle-btn /* 确保自定义按钮也应用背景 */
{
background-color:${color.bgb} !important;
}
html body.wr-mode-${i} .readerCatalog {
background-color:${color.bgbBar} !important;
}
html body.wr-mode-${i} .chapterItem_link {
border: dashed #2a2a2a !important;
border-width: 0 0 2px !important;
}
html body.wr-mode-${i} .chapterItem_text {
font-size: 18px !important;
}
html body.wr-mode-${i} .readerNotePanel {
background-color:${color.bgbBar} !important;
}
html body.wr-mode-${i} .sectionListItem_divider {
border: dashed #2a2a2a !important;
border-width: 0 0 2px !important;
}
html body.wr-mode-${i} .readerNotePanelBottomBar {
border: solid ${color.bgbBar} !important;
border-width: 0 0 2px !important;
background-color:${color.rbg} !important;
}
/* 阅读区域内容样式 */
html body.wr-mode-${i} .readerChapterContent {
color: ${color.white ? '#333333' : '#e8e8e8'} !important;
}
/* 章节标题样式 */
html body.wr-mode-${i} .readerChapterContent .chapterTitle {
color: ${color.white ? '#000000' : '#ffffff'} !important;
}
`;
if (color.white) {
style += `
html body.wr-mode-${i} .readerFooter_button,
html body.wr-mode-${i} .readerFooter_button:hover,
html body.wr-mode-${i} #custom-theme-toggle-btn /* 自定义按钮文字颜色 */
{
color:#2a2a2a !important;
}
html body.wr-mode-${i} .readerFooter_button {
background-color:${color.bg} !important;
}
`;
} else {
style += `
html body.wr-mode-${i} #custom-theme-toggle-btn /* 自定义按钮文字颜色 */
{
color:#b9b9ba !important;
}
`;
}
}
return style;
}
function applyCustomThemeStyles() {
const styleContent = getStyleStr_customTheme();
if (!styleElementForCustomTheme) {
styleElementForCustomTheme = document.createElement('style');
styleElementForCustomTheme.id = 'custom-weread-styles-by-yehuda';
styleElementForCustomTheme.setAttribute('data-priority', 'highest');
document.head.appendChild(styleElementForCustomTheme);
}
styleElementForCustomTheme.textContent = styleContent;
document.head.appendChild(styleElementForCustomTheme);
console.log("自定义主题样式已应用,共计样式规则数量:" +
(styleElementForCustomTheme.sheet ? styleElementForCustomTheme.sheet.cssRules.length : "未知"));
}
function removeCustomStyles() {
const body = $css("body");
if (!body) return;
colors.forEach((color, index) => {
body.classList.remove('wr-mode-' + index);
});
if (localStorage.getItem('wr-custom-mode')) {
localStorage.removeItem('wr-custom-mode');
}
body.removeAttribute('data-custom-color-mode');
// 可选:如果想在移除时也移除style标签内容,但通常保留规则让切换回来更快
if (styleElementForCustomTheme) {
styleElementForCustomTheme.textContent = '';
}
}
function changeCustomThemeMode(modeIndexStr, currentModeIndexStr = null) {
const body = $css("body");
if(!body) return;
const modeIndex = parseInt(modeIndexStr);
colors.forEach((_, index) => body.classList.remove('wr-mode-' + index));
body.classList.remove('wr_darkTheme');
if (!isNaN(modeIndex) && colors[modeIndex]) {
body.classList.add('wr-mode-' + modeIndex);
body.setAttribute('data-custom-color-mode', modeIndex.toString());
localStorage.setItem('wr-custom-mode', modeIndex.toString());
console.log(`已应用自定义主题 ${modeIndex},当前body类: ${body.classList.toString()}`);
document.documentElement.style.display = 'none';
void document.documentElement.offsetHeight;
document.documentElement.style.display = '';
} else {
console.warn(`微信读书脚本:无效的自定义模式索引: ${modeIndexStr}`);
removeCustomStyles();
}
}
function loadCustomThemeFeature() {
if (!div_controls) {
console.warn("微信读书脚本:.readerControls 未找到,无法添加自定义主题按钮。");
return;
}
applyCustomThemeStyles();
const customThemeButton = createElement('button', {
title: '切换自定义主题',
id: 'custom-theme-toggle-btn',
class: 'readerControls_item'
});
customThemeButton.textContent = '主题';
const NATIVE_WHITE_THEME_CLASS = 'wr_whiteTheme';
customThemeButton.onclick = async () => {
const body = $css("body");
if (!body) {
console.warn("微信读书脚本:未找到 body 元素。");
return;
}
customThemeButton.style.transform = "scale(1.1)";
customThemeButton.style.transition = "transform 0.2s";
setTimeout(() => {
customThemeButton.style.transform = "";
}, 200);
if (!body.classList.contains(NATIVE_WHITE_THEME_CLASS)) {
console.log(`深色主题不支持自定义主题切换。当前类: ${body.classList.toString()}`);
alert("请先手动切换为原生浅色主题,再使用自定义主题功能。");
return;
}
let nextCustomModeIndex = 0;
const currentAppliedCustomModeStr = body.getAttribute('data-custom-color-mode');
if (currentAppliedCustomModeStr !== null) {
const currentAppliedIndex = parseInt(currentAppliedCustomModeStr);
if (!isNaN(currentAppliedIndex) && currentAppliedIndex >= 0 && currentAppliedIndex < colors.length) {
nextCustomModeIndex = (currentAppliedIndex + 1) % colors.length;
} else {
console.warn(`Invalid 'data-custom-color-mode' value: ${currentAppliedCustomModeStr}. Resetting to first custom theme.`);
nextCustomModeIndex = 0;
}
} else {
console.log("No prior custom theme applied (data-custom-color-mode is null). Applying first custom theme.");
nextCustomModeIndex = 0;
}
applyCustomThemeStyles();
changeCustomThemeMode(nextCustomModeIndex.toString(), currentAppliedCustomModeStr);
};
div_controls.appendChild(customThemeButton);
// 定义统一的原生主题按钮点击处理函数,以便复用和移除/添加监听器
const nativeThemeButtonClickHandler = () => {
console.log("原生主题按钮点击,移除自定义主题样式。");
removeCustomStyles();
};
setTimeout(() => {
const initialNativeDarkButton = document.querySelector('[title="深色"]');
const initialNativeLightButton = document.querySelector('[title="浅色"]');
// 当原生"切换到深色"按钮被点击(即从浅色变为深色)时,移除自定义主题
if (initialNativeDarkButton) {
initialNativeDarkButton.addEventListener('click', nativeThemeButtonClickHandler);
console.log("Added click listener to initialNativeDarkButton");
}
// 当原生"切换到浅色"按钮被点击(即从深色变为浅色)时,移除自定义主题
if (initialNativeLightButton) {
initialNativeLightButton.addEventListener('click', nativeThemeButtonClickHandler);
console.log("Added click listener to initialNativeLightButton");
}
}, 500);
// 从 localStorage 初始化主题
const localMode = localStorage.getItem('wr-custom-mode');
if (localMode !== null && colors[parseInt(localMode)]) {
changeCustomThemeMode(localMode);
}
}
async function init() {
"use strict";
// 最多等待 30 秒页面加载完成
let book = await waitElement(".wr_canvasContainer canvas", 30000);
if (!book) {
alert("书本内容加载失败,请手动刷新页面!");
return;
}
div_body = $css("body");
div_controls = $css(".readerControls");
div_top_bar = $css(".readerTopBar");
// 添加功能按键;
div_controls.insertHtml(`
<button title="等待翻页" id='turn-page-tips' class='readerControls_item'>等待翻页</button>
<button title="加宽" id='width-add' class='readerControls_item'>加宽</button>
<button title="减宽" id='width-dev' class='readerControls_item'>减宽</button>
<button title="播放X0" id='scroll-on' class='readerControls_item'>播放X0</button>
<button title="停止播放" id='scroll-off' class='readerControls_item'>停止播放</button>
`);
btn_width_add = $css("#width-add");
btn_width_dev = $css("#width-dev");
btn_scroll_on = $css("#scroll-on");
btn_scroll_off = $css("#scroll-off");
btn_turn_tips = $css("#turn-page-tips");
// 额外功能按钮功能实现
btn_width_add.onclick = () => changeWidth(true);
btn_width_dev.onclick = () => changeWidth(false);
btn_scroll_on.onclick = () => {
scroll_speed++;
if (scroll_speed == 1) {
autoScroll();
}
btn_scroll_on.innerHTML = "播放X" + scroll_speed;
};
btn_scroll_off.onclick = () => {
scroll_speed = 0;
btn_scroll_on.innerHTML = "播放X0";
};
// 应用localStorage中的宽度设置
setWidth(window.localStorage.getItem('setWidth'));
// 加载自定义主题相关功能
loadCustomThemeFeature();
let header = await waitElement(".readerAIChatPanel_header", 30000);
if (!header) {
console.warn('.readerAIChatPanel_header" not found, cannot add buttons.');
}
// 全屏按钮
let btnFull = createElement('button');
btnFull.innerText = '全屏';
btnFull.className = 'readerAIChatPanel_header_btn_full'; // 类名用于grid-area
btnFull.onclick = function() {
let panel = $css('.readerAIChatPanel .readerAIChatPanel');
if(panel) {
panel.classList.toggle('readerAIChatPanel_fullscreen');
if(panel.classList.contains('readerAIChatPanel_fullscreen')) {
btnFull.innerText = '还原';
} else {
btnFull.innerText = '全屏';
}
}
};
// 关闭按钮
let btnClose = createElement('button');
btnClose.innerText = '关闭';
btnClose.className = 'readerAIChatPanel_header_btn_close'; // 类名用于grid-area
btnClose.onclick = function() {
let mask = $css('.wr_mask.wr_mask_Show');
if(mask) mask.click();
};
// 只有当 header 存在时才添加按钮
if (header) {
header.appendChild(btnFull);
header.appendChild(btnClose);
}
}; // init 函数结束括号
init();
function changeWidth(isAdd, step) {
step = typeof step === "undefined" ? 60 : step
let currentMaxWidth = $css(".app_content").cssGet("max-width");
let width = 0;
if (currentMaxWidth && currentMaxWidth !== "none" && currentMaxWidth.endsWith("px")) {
width = Number(currentMaxWidth.replace("px", ""));
} else {
const appContentDiv = $css(".app_content");
if (appContentDiv) {
width = appContentDiv.clientWidth;
}
if (!width || width <=0) width = 1000;
}
if (isAdd) {
width += step;
} else {
width -= step;
}
setWidth(width);
}
function setWidth(width) {
if (!width) {
return;
}
const numericWidth = parseFloat(width);
if (isNaN(numericWidth) || numericWidth <= 0) {
console.warn("setWidth: 无效的宽度值", width);
return;
}
let div_content_el = $css(".app_content");
let div_top_bar_el = $css(".readerTopBar");
if (div_content_el) {
div_content_el.cssSet("max-width", numericWidth + "px");
}
if (div_top_bar_el) {
div_top_bar_el.cssSet("max-width", numericWidth + "px");
}
window.localStorage.setItem('setWidth', numericWidth.toString());
let resize_event = new Event("resize");
window.dispatchEvent(resize_event);
}
// 滑动屏幕,滚至页面底部
async function autoScroll(step, delay) {
step = typeof step === "undefined" ? 1 : step;
delay = typeof delay === "undefined" ? 1000 : delay;
while (scroll_speed > 0) {
window.scrollBy(0, step);
if (isPageBottom()) {
await nextPage();
}
await sleep(delay / scroll_speed / scroll_speed);
if (isShowInView($css(".readerFooter_ending"))) {
scroll_speed = 0;
btn_scroll_on.innerHTML = "播放X0";
}
}
}
async function nextPage(sleep_time) {
sleep_time = typeof sleep_time === "undefined" ? 6000 : sleep_time;
let btn_turn = document.querySelector(".readerFooter_button");
while (true) {
if (isShowInView(btn_turn) && scroll_speed > 0) {
console.log(`wait ${sleep_time / 1000} seconds. turn page.`);
let last_time = sleep_time / 1000;
while (last_time > 0) {
btn_turn_tips.innerHTML = `${last_time}s翻页`;
last_time--;
await sleep(1000);
}
pressKey("right");
await sleep(3000);
btn_turn_tips.innerHTML = `等待翻页`;
break;
}
}
}
/** ------ 常用函数 ------ **/
function initElement(elements) {
/**
* 初始化元素属性和函数
*
* element: elementNode
*/
if (!Array.isArray(elements)) {
elements = [elements];
}
for (let element of elements) {
for (let fn_name in ElementUtils) {
element[fn_name] = (...args) => {
return ElementUtils[fn_name](element, ...args);
};
}
}
}
function $css(query) {
/**
* css 选择器,单元素
*
* query: string
*/
let elm = document.querySelector(query);
if (!elm) {
return;
}
initElement(elm);
return elm;
}
function $cssAll(query) {
/**
* css 选择器,单元素
*
* query: string
*/
let elms = Array.apply(null, document.querySelectorAll(query));
if (elms.length === 0) {
return;
}
initElement(elms);
return elms;
}
function $xpa(query, node) {
/**
* xpath 选择器,单元素
*
* query: string
* node: elementNode
*/
node = typeof node === "undefined" ? document : node;
let elm = document.evaluate(query, node).iterateNext();
if (!elm) {
return;
}
initElement(elm);
return elm;
}
function $xpaAll(query, node) {
/**
* xpath 选择器,多元素
*
* query: string
* node: elementNode
*/
node = typeof node === "undefined" ? document : node;
let elm_list = [];
let elm_box = document.evaluate(query, document);
let elm = elm_box.iterateNext();
if (!elm) {
return;
}
while (elm) {
elm_list.push(elm);
elm = elm_box.iterateNext();
}
initElement(elm_list);
return elm_list;
}
function sleep(ms) {
ms = typeof ms === "undefined" ? 1000 : ms;
/**
* 休眠函数,单位:ms
* 使用方法:
* sleep(500).then(() => { Do something after the sleep! });
* 或者
* await sleep(500); Do something after the sleep!
*/
return new Promise((resolve) => setTimeout(resolve, ms));
}
function isShowInView(element) {
/**
* 判断元素是否出现在视窗中
*/
if (element === null || element === undefined) {
return false;
}
let documentHeight = Math.max(
document.documentElement.scrollHeight,
document.documentElement.offsetHeight,
document.documentElement.clientHeight
);
let screenHeight = window.innerHeight || documentHeight;
let screenWidth = window.innerWidth || document.documentElement.clientWidth;
let { top, right, bottom, left } = element.getBoundingClientRect();
return (
top >= 0 && left >= 0 && right <= screenWidth && bottom <= screenHeight
);
}
function isExistElement(css_selector) {
/**
* 判断指定元素是否存在页面中
*/
if ($css(css_selector)) {
return true;
}
return false;
}
function createElement(tagName, attributes) {
const elm = document.createElement(tagName);
for (const attr in attributes) {
elm.setAttribute(attr, attributes[attr]);
}
return elm;
}
async function waitElement(css_selector, max_wait_ms) {
/**
* 等待指定元素出现
*/
max_wait_ms = typeof max_wait_ms === "undefined" ? 3000 : max_wait_ms;
let start_time = new Date().getTime();
let elm = $css(css_selector);
while (!elm && start_time + max_wait_ms >= new Date().getTime()) {
await sleep(300);
elm = $css(css_selector);
if (elm) {
break;
}
}
return elm;
}
function getScrollTop() {
/**
* 滚动条在Y轴上已经滚动的距离
*/
return document.documentElement.scrollTop || document.body.scrollTop;
}
function getScrollHeight() {
/**
* 整个页面的高度
*/
return document.documentElement.scrollHeight || document.body.scrollHeight;
}
function getWindowHeight() {
/**
* 浏览器可视窗口高度
*/
return document.documentElement.clientHeight || document.body.clientHeight;
}
function isPageBottom(deviation_value) {
/**
* 判断页面是否滚动到底,默认允许3个像素的误差,大部分情况下总是会差0.3-0.8像素
*/
deviation_value =
typeof deviation_value === "undefined" ? 3 : deviation_value;
if (
getScrollHeight() - getScrollTop() - getWindowHeight() <
deviation_value
) {
return true;
}
return false;
}
function pressKeyByCode(code) {
/**
* 按键触发,根据传入的按键编号
*
* code: Number
*/
return document.dispatchEvent(
new KeyboardEvent("keydown", {
bubbles: true,
cancelable: true,
keyCode: code,
})
);
}
function pressKey(name) {
/**
* 按键触发,根据传入的按键名
*
* name: string
*/
const KeyNameToCode = {
back: 8,
tab: 9,
clear: 12,
enter: 13,
shift: 16,
ctrl: 17,
alt: 18,
capelock: 20,
esc: 27,
space: 32,
pageup: 33,
pagedown: 34,
end: 35,
home: 36,
left: 37,
up: 38,
right: 39,
down: 40,
insert: 45,
delete: 46,
0: 48,
1: 49,
2: 50,
3: 51,
4: 52,
5: 53,
6: 54,
7: 55,
8: 56,
9: 57,
a: 65,
b: 66,
c: 67,
d: 68,
e: 69,
f: 70,
g: 71,
h: 72,
i: 73,
j: 74,
k: 75,
l: 76,
m: 77,
n: 78,
o: 79,
p: 80,
q: 81,
r: 82,
s: 83,
t: 84,
u: 85,
v: 86,
w: 87,
x: 88,
y: 89,
z: 90,
f1: 112,
f2: 113,
f3: 114,
f4: 115,
f5: 116,
f6: 117,
f7: 118,
f8: 119,
f9: 120,
f10: 121,
f11: 122,
f12: 123,
// 数字小键盘部分
n0: 96,
n1: 97,
n2: 98,
n3: 99,
n4: 100,
n5: 101,
n6: 102,
n7: 103,
n8: 104,
n9: 105,
"n*": 106,
"n+": 107,
nenter: 108,
"n-": 109,
"n.": 110,
"n/": 111,
numlock: 144,
";": 186,
":": 186,
"=": 187,
"+": 187,
",": 188,
"<": 188,
"-": 189,
_: 189,
".": 190,
">": 190,
"/": 191,
"?": 191,
"`": 192,
"~": 192,
"[": 219,
"{": 219,
"\\": 220,
"|": 220,
"]": 221,
"}": 221,
"'": 222,
'"': 222,
};
return pressKeyByCode(KeyNameToCode[name.toLowerCase()]);
}