Fix issue with navigation when operationId contains backslash

This commit is contained in:
Oleksandr Strakhov 2021-03-07 19:25:59 +02:00
parent 4846259de3
commit 44cc1194e2
4 changed files with 22 additions and 6 deletions

9
package-lock.json generated
View File

@ -1869,6 +1869,12 @@
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
},
"@types/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-4mBnOrTpVKn+tYzlnMO7cwDkDa6wlQ2bBXW+79/6ahMd36GF216kxWYxgz+S4d5Ev1ByFbnQbPGxV4P5BSL8MA==",
"dev": true
},
"@types/dompurify": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.0.2.tgz",
@ -5212,8 +5218,7 @@
"cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
},
"cssom": {
"version": "0.4.4",

View File

@ -60,6 +60,7 @@
"@cypress/webpack-preprocessor": "^5.4.2",
"@hot-loader/react-dom": "^16.12.0",
"@types/chai": "^4.2.12",
"@types/cssesc": "^3.0.0",
"@types/dompurify": "^2.0.2",
"@types/enzyme": "^3.10.5",
"@types/enzyme-to-json": "^1.5.3",
@ -137,6 +138,7 @@
"@redocly/react-dropdown-aria": "^2.0.11",
"@types/node": "^13.11.1",
"classnames": "^2.2.6",
"cssesc": "^3.0.0",
"decko": "^1.2.0",
"dompurify": "^2.0.12",
"eventemitter3": "^4.0.4",

View File

@ -1,5 +1,5 @@
import { action, observable, makeObservable } from 'mobx';
import { querySelector } from '../utils/dom';
import { escapeSelectorValue, querySelector } from '../utils/dom';
import { SpecStore } from './models';
import { history as historyInst, HistoryService } from './HistoryService';
@ -162,7 +162,7 @@ export class MenuStore {
*/
getElementAt(idx: number): Element | null {
const item = this.flatItems[idx];
return (item && querySelector(`[${SECTION_ATTR}="${item.id}"]`)) || null;
return (item && querySelector(`[${SECTION_ATTR}="${escapeSelectorValue(item.id)}"]`)) || null;
}
/**
@ -174,7 +174,7 @@ export class MenuStore {
if (item && item.type === 'group') {
item = item.items[0];
}
return (item && querySelector(`[${SECTION_ATTR}="${item.id}"]`)) || null;
return (item && querySelector(`[${SECTION_ATTR}="${escapeSelectorValue(item.id)}"]`)) || null;
}
/**
@ -222,7 +222,7 @@ export class MenuStore {
this.activeItemIdx = item.absoluteIdx!;
if (updateLocation) {
this.history.replace(item.id, rewriteHistory);
this.history.replace(encodeURI(item.id), rewriteHistory);
}
item.activate();

View File

@ -1,3 +1,5 @@
import * as cssesc from 'cssesc';
export const IS_BROWSER = typeof window !== 'undefined' && 'HTMLElement' in window;
export function querySelector(selector: string): Element | null {
@ -7,6 +9,13 @@ export function querySelector(selector: string): Element | null {
return null;
}
export function escapeSelectorValue(
value: string,
options: Readonly<Partial<cssesc.Options>> = { quotes: 'double' },
): string {
return cssesc(value, options);
}
/**
* Drop everything inside <...> (i.e., tags/elements), and keep the text.
* Unlike browser innerText, this removes newlines; it also doesn't handle