refactor(syntax-highlighting): use component wrapping for syntax highlighting activation (#9784)

This commit is contained in:
Vladimír Gorej
2024-04-06 00:16:00 +02:00
committed by GitHub
parent 7260005bd8
commit ac0d2a3cc8
15 changed files with 143 additions and 112 deletions

View File

@@ -289,12 +289,9 @@ const RequestBody = ({
schema={mediaTypeValue.get("schema")}
specPath={specPath.push("content", contentType)}
example={
<HighlightCode
className="body-param__example"
getConfigs={getConfigs}
language={language}
value={stringify(requestBodyValue) || sampleRequestBody}
/>
<HighlightCode className="body-param__example" language={language}>
{stringify(requestBodyValue) || sampleRequestBody}
</HighlightCode>
}
includeWriteOnly={true}
/>

View File

@@ -1,7 +1,5 @@
import React, { useRef, useEffect, useState } from "react"
import PropTypes from "prop-types"
import get from "lodash/get"
import isFunction from "lodash/isFunction"
import { CopyToClipboard } from "react-copy-to-clipboard"
const style = {
@@ -34,9 +32,7 @@ const activeStyle = {
borderBottom: "none"
}
const RequestSnippets = ({ request, requestSnippetsSelectors, getConfigs, getComponent }) => {
const config = isFunction(getConfigs) ? getConfigs() : null
const canSyntaxHighlight = get(config, "syntaxHighlight") !== false && get(config, "syntaxHighlight.activated", true)
const RequestSnippets = ({ request, requestSnippetsSelectors, getComponent }) => {
const rootRef = useRef(null)
const ArrowIcon = getComponent("ArrowUpIcon")
@@ -45,24 +41,6 @@ const RequestSnippets = ({ request, requestSnippetsSelectors, getConfigs, getCom
const [activeLanguage, setActiveLanguage] = useState(requestSnippetsSelectors.getSnippetGenerators()?.keySeq().first())
const [isExpanded, setIsExpanded] = useState(requestSnippetsSelectors?.getDefaultExpanded())
useEffect(() => {
const doIt = () => {
}
doIt()
}, [])
useEffect(() => {
const childNodes = Array
.from(rootRef.current.childNodes)
.filter(node => !!node.nodeType && node.classList?.contains("curl-command"))
// eslint-disable-next-line no-use-before-define
childNodes.forEach(node => node.addEventListener("mousewheel", handlePreventYScrollingBeyondElement, { passive: false }))
return () => {
// eslint-disable-next-line no-use-before-define
childNodes.forEach(node => node.removeEventListener("mousewheel", handlePreventYScrollingBeyondElement))
}
}, [request])
const snippetGenerators = requestSnippetsSelectors.getSnippetGenerators()
const activeGenerator = snippetGenerators.get(activeLanguage)
@@ -99,16 +77,25 @@ const RequestSnippets = ({ request, requestSnippetsSelectors, getConfigs, getCom
}
}
const SnippetComponent = canSyntaxHighlight ? (
<SyntaxHighlighter
language={activeGenerator.get("syntax")}
className="curl microlight"
>
{snippet}
</SyntaxHighlighter>
) : (
<textarea readOnly={true} className="curl" value={snippet}></textarea>
)
useEffect(() => {
const doIt = () => {
}
doIt()
}, [])
useEffect(() => {
const childNodes = Array
.from(rootRef.current.childNodes)
.filter(node => !!node.nodeType && node.classList?.contains("curl-command"))
// eslint-disable-next-line no-use-before-define
childNodes.forEach(node => node.addEventListener("mousewheel", handlePreventYScrollingBeyondElement, { passive: false }))
return () => {
// eslint-disable-next-line no-use-before-define
childNodes.forEach(node => node.removeEventListener("mousewheel", handlePreventYScrollingBeyondElement))
}
}, [request])
return (
<div className="request-snippets" ref={rootRef}>
@@ -142,7 +129,15 @@ const RequestSnippets = ({ request, requestSnippetsSelectors, getConfigs, getCom
</CopyToClipboard>
</div>
<div>
{SnippetComponent}
<SyntaxHighlighter
language={activeGenerator.get("syntax")}
className="curl microlight"
renderPlainText={({ children, PlainTextViewer }) => (
<PlainTextViewer className="curl">{children}</PlainTextViewer>
)}
>
{snippet}
</SyntaxHighlighter>
</div>
</div>
}
@@ -153,7 +148,6 @@ const RequestSnippets = ({ request, requestSnippetsSelectors, getConfigs, getCom
RequestSnippets.propTypes = {
request: PropTypes.object.isRequired,
requestSnippetsSelectors: PropTypes.object.isRequired,
getConfigs: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
requestSnippetsActions: PropTypes.object,
}

View File

@@ -4,30 +4,23 @@
import React, { useRef, useEffect } from "react"
import PropTypes from "prop-types"
import classNames from "classnames"
import get from "lodash/get"
import saveAs from "js-file-download"
import { CopyToClipboard } from "react-copy-to-clipboard"
const HighlightCode = ({
value,
fileName = "response.txt",
className,
downloadable,
getConfigs,
getComponent,
canCopy,
language,
children,
}) => {
const config = getConfigs()
const canSyntaxHighlight =
get(config, "syntaxHighlight") !== false &&
get(config, "syntaxHighlight.activated", true)
const rootRef = useRef(null)
const SyntaxHighlighter = getComponent("SyntaxHighlighter", true)
const handleDownload = () => {
saveAs(value, fileName)
saveAs(children, fileName)
}
const handlePreventYScrollingBeyondElement = (e) => {
@@ -70,13 +63,13 @@ const HighlightCode = ({
)
)
}
}, [value, className, language])
}, [children, className, language])
return (
<div className="highlight-code" ref={rootRef}>
{canCopy && (
<div className="copy-to-clipboard">
<CopyToClipboard text={value}>
<CopyToClipboard text={children}>
<button />
</CopyToClipboard>
</div>
@@ -88,29 +81,27 @@ const HighlightCode = ({
</button>
)}
{canSyntaxHighlight ? (
<SyntaxHighlighter
language={language}
className={classNames(className, "microlight")}
>
{value}
</SyntaxHighlighter>
) : (
<pre className={classNames(className, "microlight")}>{value}</pre>
)}
<SyntaxHighlighter
language={language}
className={classNames(className, "microlight")}
renderPlainText={({ children, PlainTextViewer }) => (
<PlainTextViewer className={className}>{children}</PlainTextViewer>
)}
>
{children}
</SyntaxHighlighter>
</div>
)
}
HighlightCode.propTypes = {
value: PropTypes.string.isRequired,
getConfigs: PropTypes.func.isRequired,
getComponent: PropTypes.func.isRequired,
className: PropTypes.string,
downloadable: PropTypes.bool,
fileName: PropTypes.string,
language: PropTypes.string,
canCopy: PropTypes.bool,
children: PropTypes.string.isRequired,
}
export default HighlightCode

View File

@@ -0,0 +1,17 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
import classNames from "classnames"
const PlainTextViewer = ({ className = "", children }) => (
<pre className={classNames("microlight", className)}>{children}</pre>
)
PlainTextViewer.propTypes = {
className: PropTypes.string,
children: PropTypes.string.isRequired,
}
export default PlainTextViewer

View File

@@ -11,7 +11,7 @@ const SyntaxHighlighter = ({
className = "",
getConfigs,
syntaxHighlighting = {},
children = null,
children = "",
}) => {
const configs = getConfigs()
const theme = get(configs, "syntaxHighlight.theme")
@@ -37,7 +37,8 @@ SyntaxHighlighter.propTypes = {
styles: PropTypes.object,
defaultStyle: PropTypes.object,
}),
children: PropTypes.node,
renderPlainText: PropTypes.func,
children: PropTypes.string,
}
export default SyntaxHighlighter

View File

@@ -5,8 +5,10 @@ import afterLoad from "./after-load"
import { styles, defaultStyle } from "./root-injects"
import SyntaxHighlighter from "./components/SyntaxHighlighter"
import HighlightCode from "./components/HighlightCode"
import PlainTextViewer from "./components/PlainTextViewer"
import SyntaxHighlighterWrapper from "./wrap-components/SyntaxHighlighter"
const SyntaxHighlightingPlugin = () => ({
const SyntaxHighlightingPlugin1 = () => ({
afterLoad,
rootInjects: {
syntaxHighlighting: { styles, defaultStyle },
@@ -14,7 +16,19 @@ const SyntaxHighlightingPlugin = () => ({
components: {
SyntaxHighlighter,
HighlightCode,
PlainTextViewer,
},
})
const SyntaxHighlightingPlugin2 = () => ({
wrapComponents: {
SyntaxHighlighter: SyntaxHighlighterWrapper,
},
})
const SyntaxHighlightingPlugin = () => [
SyntaxHighlightingPlugin1,
SyntaxHighlightingPlugin2,
]
export default SyntaxHighlightingPlugin

View File

@@ -0,0 +1,33 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
import get from "lodash/get"
const SyntaxHighlighterWrapper = (Original, system) => {
const SyntaxHighlighter = ({ renderPlainText, children, ...rest }) => {
const configs = system.getConfigs()
const canSyntaxHighlight = !!get(configs, "syntaxHighlight.activated")
const PlainTextViewer = system.getComponent("PlainTextViewer")
if (!canSyntaxHighlight && typeof renderPlainText === "function") {
return renderPlainText({ children, PlainTextViewer })
}
if (!canSyntaxHighlight) {
return <PlainTextViewer>{children}</PlainTextViewer>
}
return <Original {...rest}>{children}</Original>
}
SyntaxHighlighter.propTypes = {
...Original.propTypes,
renderPlainText: PropTypes.func,
children: PropTypes.string.isRequired,
}
return SyntaxHighlighter
}
export default SyntaxHighlighterWrapper