bug(deeplinking): escaping breaks whitespaces & underscored tags/ids (via #4953)
* add tests for operation lacking an operationId * add deep linking tests for tags/operationIds with underscores * migrate from `_` to `%20` for deeplink hash whitespace escaping * add backwards compatibility for `_` whitespace escaping * update util unit tests
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import { getList } from "core/utils"
|
||||
import { getExtensions, sanitizeUrl, createDeepLinkPath } from "core/utils"
|
||||
import { getExtensions, sanitizeUrl, escapeDeepLinkPath } from "core/utils"
|
||||
import { Iterable, List } from "immutable"
|
||||
import ImPropTypes from "react-immutable-proptypes"
|
||||
|
||||
@@ -112,7 +112,7 @@ export default class Operation extends PureComponent {
|
||||
let onChangeKey = [ path, method ] // Used to add values to _this_ operation ( indexed by path and method )
|
||||
|
||||
return (
|
||||
<div className={deprecated ? "opblock opblock-deprecated" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={createDeepLinkPath(isShownKey.join("-"))} >
|
||||
<div className={deprecated ? "opblock opblock-deprecated" : isShown ? `opblock opblock-${method} is-open` : `opblock opblock-${method}`} id={escapeDeepLinkPath(isShownKey.join("-"))} >
|
||||
<OperationSummary operationProps={operationProps} toggleShown={toggleShown} getComponent={getComponent} authActions={authActions} authSelectors={authSelectors} specPath={specPath} />
|
||||
<Collapse isOpened={isShown}>
|
||||
<div className="opblock-body">
|
||||
|
||||
@@ -73,18 +73,35 @@ export const parseDeepLinkHash = (rawHash) => ({ layoutActions, layoutSelectors,
|
||||
hash = hash.slice(1)
|
||||
}
|
||||
|
||||
const hashArray = hash.split("/").map(val => (val || "").replace(/_/g, " "))
|
||||
const hashArray = hash.split("/").map(val => (val || "").replace(/%20/g, " "))
|
||||
|
||||
const isShownKey = layoutSelectors.isShownKeyFromUrlHashArray(hashArray)
|
||||
|
||||
const [type, tagId] = isShownKey
|
||||
const [type, tagId, maybeOperationId] = isShownKey
|
||||
|
||||
if(type === "operations") {
|
||||
// we're going to show an operation, so we need to expand the tag as well
|
||||
layoutActions.show(layoutSelectors.isShownKeyFromUrlHashArray([tagId]))
|
||||
const tagIsShownKey = layoutSelectors.isShownKeyFromUrlHashArray([tagId])
|
||||
layoutActions.show(tagIsShownKey)
|
||||
|
||||
// If an `_` is present, trigger the legacy escaping behavior to be safe
|
||||
// TODO: remove this in v4.0, it is deprecated
|
||||
if(tagId.indexOf("_") > -1) {
|
||||
console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead.")
|
||||
layoutActions.show(tagIsShownKey.map(val => val.replace(/_/g, " ")), true)
|
||||
}
|
||||
}
|
||||
|
||||
layoutActions.show(isShownKey, true) // TODO: 'show' operation tag
|
||||
layoutActions.show(isShownKey, true)
|
||||
|
||||
// If an `_` is present, trigger the legacy escaping behavior to be safe
|
||||
// TODO: remove this in v4.0, it is deprecated
|
||||
if (tagId.indexOf("_") > -1 || maybeOperationId.indexOf("_") > -1) {
|
||||
console.warn("Warning: escaping deep link whitespace with `_` will be unsupported in v4.0, use `%20` instead.")
|
||||
layoutActions.show(isShownKey.map(val => val.replace(/_/g, " ")), true)
|
||||
}
|
||||
|
||||
// Scroll to the newly expanded entity
|
||||
layoutActions.scrollTo(isShownKey)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -733,8 +733,10 @@ export function getAcceptControllingResponse(responses) {
|
||||
return suitable2xxResponse || suitableDefaultResponse
|
||||
}
|
||||
|
||||
export const createDeepLinkPath = (str) => typeof str == "string" || str instanceof String ? str.trim().replace(/\s/g, "_") : ""
|
||||
export const escapeDeepLinkPath = (str) => cssEscape( createDeepLinkPath(str) )
|
||||
// suitable for use in URL fragments
|
||||
export const createDeepLinkPath = (str) => typeof str == "string" || str instanceof String ? str.trim().replace(/\s/g, "%20") : ""
|
||||
// suitable for use in CSS classes and ids
|
||||
export const escapeDeepLinkPath = (str) => cssEscape( createDeepLinkPath(str).replace(/%20/g, "_") )
|
||||
|
||||
export const getExtensions = (defObj) => defObj.filter((v, k) => /^x-/.test(k))
|
||||
export const getCommonExtensions = (defObj) => defObj.filter((v, k) => /^pattern|maxLength|minLength|maximum|minimum/.test(k))
|
||||
|
||||
Reference in New Issue
Block a user