mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-24 20:26:08 +00:00
fixes #69655
This commit is contained in:
@@ -20,22 +20,8 @@ import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
|
||||
function createMenuMnemonicRegExp() {
|
||||
try {
|
||||
return new RegExp('\\(&([^\\s&])\\)|(?<!&)&([^\\s&])');
|
||||
} catch (err) {
|
||||
return new RegExp('\uFFFF'); // never match please
|
||||
}
|
||||
}
|
||||
export const MENU_MNEMONIC_REGEX = createMenuMnemonicRegExp();
|
||||
function createMenuEscapedMnemonicRegExp() {
|
||||
try {
|
||||
return new RegExp('(?<!&)(?:&)([^\\s&])');
|
||||
} catch (err) {
|
||||
return new RegExp('\uFFFF'); // never match please
|
||||
}
|
||||
}
|
||||
export const MENU_ESCAPED_MNEMONIC_REGEX: RegExp = createMenuEscapedMnemonicRegExp();
|
||||
export const MENU_MNEMONIC_REGEX = /\(&([^\s&])\)|(^|[^&])&([^\s&])/;
|
||||
export const MENU_ESCAPED_MNEMONIC_REGEX = /(&)?(&)([^\s&])/g;
|
||||
|
||||
export interface IMenuOptions {
|
||||
context?: any;
|
||||
@@ -391,7 +377,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
|
||||
if (label) {
|
||||
let matches = MENU_MNEMONIC_REGEX.exec(label);
|
||||
if (matches) {
|
||||
this.mnemonic = (!!matches[1] ? matches[1] : matches[2]).toLocaleLowerCase();
|
||||
this.mnemonic = (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,9 +466,23 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
|
||||
const matches = MENU_MNEMONIC_REGEX.exec(label);
|
||||
|
||||
if (matches) {
|
||||
label = strings.escape(label).replace(MENU_ESCAPED_MNEMONIC_REGEX, '<u aria-hidden="true">$1</u>');
|
||||
label = strings.escape(label);
|
||||
|
||||
// This is global, reset it
|
||||
MENU_ESCAPED_MNEMONIC_REGEX.lastIndex = 0;
|
||||
let escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);
|
||||
|
||||
// We can't use negative lookbehind so if we match our negative and skip
|
||||
while (escMatch && escMatch[1]) {
|
||||
escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(label);
|
||||
}
|
||||
|
||||
if (escMatch) {
|
||||
label = `${label.substr(0, escMatch.index)}<u aria-hidden="true">${escMatch[3]}</u>${label.substr(escMatch.index + escMatch[0].length)}`;
|
||||
}
|
||||
|
||||
label = label.replace(/&&/g, '&');
|
||||
this.item.setAttribute('aria-keyshortcuts', (!!matches[1] ? matches[1] : matches[2]).toLocaleLowerCase());
|
||||
this.item.setAttribute('aria-keyshortcuts', (!!matches[1] ? matches[1] : matches[3]).toLocaleLowerCase());
|
||||
} else {
|
||||
label = label.replace(/&&/g, '&');
|
||||
}
|
||||
@@ -815,7 +815,7 @@ export function cleanMnemonic(label: string): string {
|
||||
return label;
|
||||
}
|
||||
|
||||
const mnemonicInText = matches[0].charAt(0) === '&';
|
||||
const mnemonicInText = !matches[1];
|
||||
|
||||
return label.replace(regex, mnemonicInText ? '$2' : '').trim();
|
||||
return label.replace(regex, mnemonicInText ? '$2$3' : '').trim();
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ export class MenuBar extends Disposable {
|
||||
|
||||
// Register mnemonics
|
||||
if (mnemonicMatches) {
|
||||
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[2];
|
||||
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[3];
|
||||
|
||||
this.registerMnemonic(this.menuCache.length, mnemonic);
|
||||
}
|
||||
@@ -472,15 +472,34 @@ export class MenuBar extends Disposable {
|
||||
const cleanMenuLabel = cleanMnemonic(label);
|
||||
|
||||
// Update the button label to reflect mnemonics
|
||||
titleElement.innerHTML = this.options.enableMnemonics ?
|
||||
strings.escape(label).replace(MENU_ESCAPED_MNEMONIC_REGEX, '<mnemonic aria-hidden="true">$1</mnemonic>').replace(/&&/g, '&') :
|
||||
cleanMenuLabel.replace(/&&/g, '&');
|
||||
|
||||
if (this.options.enableMnemonics) {
|
||||
let innerHtml = strings.escape(label);
|
||||
|
||||
// This is global so reset it
|
||||
MENU_ESCAPED_MNEMONIC_REGEX.lastIndex = 0;
|
||||
let escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(innerHtml);
|
||||
|
||||
// We can't use negative lookbehind so we match our negative and skip
|
||||
while (escMatch && escMatch[1]) {
|
||||
escMatch = MENU_ESCAPED_MNEMONIC_REGEX.exec(innerHtml);
|
||||
}
|
||||
|
||||
if (escMatch) {
|
||||
innerHtml = `${innerHtml.substr(0, escMatch.index)}<mnemonic aria-hidden="true">${escMatch[3]}</mnemonic>${innerHtml.substr(escMatch.index + escMatch[0].length)}`;
|
||||
}
|
||||
|
||||
innerHtml = innerHtml.replace(/&&/g, '&');
|
||||
titleElement.innerHTML = innerHtml;
|
||||
} else {
|
||||
titleElement.innerHTML = cleanMenuLabel.replace(/&&/g, '&');
|
||||
}
|
||||
|
||||
let mnemonicMatches = MENU_MNEMONIC_REGEX.exec(label);
|
||||
|
||||
// Register mnemonics
|
||||
if (mnemonicMatches) {
|
||||
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[2];
|
||||
let mnemonic = !!mnemonicMatches[1] ? mnemonicMatches[1] : mnemonicMatches[3];
|
||||
|
||||
if (this.options.enableMnemonics) {
|
||||
buttonElement.setAttribute('aria-keyshortcuts', 'Alt+' + mnemonic.toLocaleLowerCase());
|
||||
@@ -1012,4 +1031,4 @@ class ModifierKeyEmitter extends Emitter<IModifierKeyStatus> {
|
||||
super.dispose();
|
||||
this._subscriptions.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user