From 65833171037dfe0786611fe62d8d16368d60ca77 Mon Sep 17 00:00:00 2001 From: mathis-m Date: Mon, 11 Oct 2021 18:06:51 +0200 Subject: [PATCH] feat(syntax-highlight): move highlight into plugin --- src/core/components/curl.jsx | 8 +- src/core/components/example.jsx | 2 +- src/core/components/highlight-code.jsx | 25 ++-- src/core/components/live-response.jsx | 2 +- src/core/components/model-example.jsx | 2 +- src/core/components/param-body.jsx | 12 +- src/core/components/response-body.jsx | 2 +- src/core/components/response.jsx | 2 +- .../request-snippets/request-snippets.jsx | 118 +++++++++--------- src/core/plugins/syntax-highlight/fn.js | 20 +++ src/core/plugins/syntax-highlight/index.js | 9 ++ .../syntax-highlight/syntax-highlight.js} | 20 +-- src/core/presets/base.js | 4 +- 13 files changed, 125 insertions(+), 101 deletions(-) create mode 100644 src/core/plugins/syntax-highlight/fn.js create mode 100644 src/core/plugins/syntax-highlight/index.js rename src/core/{syntax-highlighting.js => plugins/syntax-highlight/syntax-highlight.js} (56%) diff --git a/src/core/components/curl.jsx b/src/core/components/curl.jsx index 44f3b15e657..266c36b3369 100644 --- a/src/core/components/curl.jsx +++ b/src/core/components/curl.jsx @@ -1,28 +1,30 @@ import React from "react" import PropTypes from "prop-types" import { CopyToClipboard } from "react-copy-to-clipboard" -import {SyntaxHighlighter, getStyle} from "core/syntax-highlighting" import get from "lodash/get" import { requestSnippetGenerator_curl_bash } from "../plugins/request-snippets/fn" export default class Curl extends React.Component { static propTypes = { getConfigs: PropTypes.func.isRequired, + getComponent: PropTypes.func.isRequired, + fn: PropTypes.object.isRequired, request: PropTypes.object.isRequired } render() { - let { request, getConfigs } = this.props + let { request, getConfigs, fn, getComponent } = this.props let curl = requestSnippetGenerator_curl_bash(request) const config = getConfigs() + const SyntaxHighlighter = getComponent("SyntaxHighlighter") const curlBlock = get(config, "syntaxHighlight.activated") ? {curl} diff --git a/src/core/components/example.jsx b/src/core/components/example.jsx index ad6ad8cf9a0..c66b4c80445 100644 --- a/src/core/components/example.jsx +++ b/src/core/components/example.jsx @@ -11,7 +11,7 @@ export default function Example(props) { const { example, showValue, getComponent, getConfigs } = props const Markdown = getComponent("Markdown", true) - const HighlightCode = getComponent("highlightCode") + const HighlightCode = getComponent("highlightCode", true) if(!example) return null diff --git a/src/core/components/highlight-code.jsx b/src/core/components/highlight-code.jsx index 465a0cd6ee8..6494be31723 100644 --- a/src/core/components/highlight-code.jsx +++ b/src/core/components/highlight-code.jsx @@ -1,14 +1,16 @@ import React, { Component } from "react" import PropTypes from "prop-types" -import {SyntaxHighlighter, getStyle} from "core/syntax-highlighting" import get from "lodash/get" import saveAs from "js-file-download" import { CopyToClipboard } from "react-copy-to-clipboard" +import ReactDOM from "react-dom" export default class HighlightCode extends Component { static propTypes = { value: PropTypes.string.isRequired, + fn: PropTypes.object.isRequired, getConfigs: PropTypes.func.isRequired, + getComponent: PropTypes.func.isRequired, className: PropTypes.string, downloadable: PropTypes.bool, fileName: PropTypes.string, @@ -26,10 +28,10 @@ export default class HighlightCode extends Component { preventYScrollingBeyondElement = (e) => { const target = e.target - var deltaY = e.nativeEvent.deltaY - var contentHeight = target.scrollHeight - var visibleHeight = target.offsetHeight - var scrollTop = target.scrollTop + const deltaY = e.deltaY + const contentHeight = target.scrollHeight + const visibleHeight = target.offsetHeight + const scrollTop = target.scrollTop const scrollOffset = visibleHeight + scrollTop @@ -42,29 +44,32 @@ export default class HighlightCode extends Component { } } + componentDidMount() { + const extractAddEventListener = (el) => (el?.addEventListener || ReactDOM.findDOMNode(el)?.addEventListener || (() => {})) [this.#syntaxHighlighter, this.#pre] - .map(element => element?.addEventListener("mousewheel", this.preventYScrollingBeyondElement, { passive: false })) + .map((el) => extractAddEventListener(el)("mousewheel", this.preventYScrollingBeyondElement, { passive: false })) } componentWillUnmount() { + const extractRemoveEventListener = (el) => (el?.removeEventListener || ReactDOM.findDOMNode(el)?.removeEventListener || (() => {})) [this.#syntaxHighlighter, this.#pre] - .map(element => element?.removeEventListener("mousewheel", this.preventYScrollingBeyondElement)) + .map((el) => extractRemoveEventListener(el)("mousewheel", this.preventYScrollingBeyondElement)) } render () { - let { value, className, downloadable, getConfigs, canCopy, language } = this.props + let { value, className, downloadable, getConfigs, canCopy, language, fn, getComponent } = this.props const config = getConfigs ? getConfigs() : {syntaxHighlight: {activated: true, theme: "agate"}} className = className || "" - + const SyntaxHighlighter = getComponent("SyntaxHighlighter") const codeBlock = get(config, "syntaxHighlight.activated") ? this.#syntaxHighlighter = elem} language={language} className={className + " microlight"} - style={getStyle(get(config, "syntaxHighlight.theme"))} + style={fn.getStyle(get(config, "syntaxHighlight.theme"))} > {value} diff --git a/src/core/components/live-response.jsx b/src/core/components/live-response.jsx index 11375b55b80..a1283cbc9fb 100644 --- a/src/core/components/live-response.jsx +++ b/src/core/components/live-response.jsx @@ -70,7 +70,7 @@ export default class LiveResponse extends React.Component { const hasHeaders = returnObject.length !== 0 const Markdown = getComponent("Markdown", true) const RequestSnippets = getComponent("RequestSnippets", true) - const Curl = getComponent("curl") + const Curl = getComponent("curl", true) return (
diff --git a/src/core/components/model-example.jsx b/src/core/components/model-example.jsx index f3c9836bdbb..e93602eba00 100644 --- a/src/core/components/model-example.jsx +++ b/src/core/components/model-example.jsx @@ -59,7 +59,7 @@ export default class ModelExample extends React.Component { let { getComponent, specSelectors, schema, example, isExecute, getConfigs, specPath, includeReadOnly, includeWriteOnly } = this.props let { defaultModelExpandDepth } = getConfigs() const ModelWrapper = getComponent("ModelWrapper") - const HighlightCode = getComponent("highlightCode") + const HighlightCode = getComponent("highlightCode", true) const exampleTabId = randomBytes(5).toString("base64") const examplePanelId = randomBytes(5).toString("base64") const modelTabId = randomBytes(5).toString("base64") diff --git a/src/core/components/param-body.jsx b/src/core/components/param-body.jsx index c440ebfb823..37744a9cd44 100644 --- a/src/core/components/param-body.jsx +++ b/src/core/components/param-body.jsx @@ -104,7 +104,7 @@ export default class ParamBody extends PureComponent { const Button = getComponent("Button") const TextArea = getComponent("TextArea") - const HighlightCode = getComponent("highlightCode") + const HighlightCode = getComponent("highlightCode", true) const ContentType = getComponent("contentType") // for domains where specSelectors not passed let parameter = specSelectors ? specSelectors.parameterWithMetaByIdentity(pathMethod, param) : param @@ -140,11 +140,11 @@ export default class ParamBody extends PureComponent { }
diff --git a/src/core/components/response-body.jsx b/src/core/components/response-body.jsx index 86f1933fa10..58c797ad70b 100644 --- a/src/core/components/response-body.jsx +++ b/src/core/components/response-body.jsx @@ -53,7 +53,7 @@ export default class ResponseBody extends React.PureComponent { render() { let { content, contentType, url, headers={}, getConfigs, getComponent } = this.props const { parsedContent } = this.state - const HighlightCode = getComponent("highlightCode") + const HighlightCode = getComponent("highlightCode", true) const downloadName = "response_" + new Date().getTime() let body, bodyEl url = url || "" diff --git a/src/core/components/response.jsx b/src/core/components/response.jsx index 767382a6abe..5ecd408f27a 100644 --- a/src/core/components/response.jsx +++ b/src/core/components/response.jsx @@ -102,7 +102,7 @@ export default class Response extends React.Component { let links = response.get("links") const ResponseExtension = getComponent("ResponseExtension") const Headers = getComponent("headers") - const HighlightCode = getComponent("highlightCode") + const HighlightCode = getComponent("highlightCode", true) const ModelExample = getComponent("modelExample") const Markdown = getComponent("Markdown", true) const OperationLink = getComponent("operationLink") diff --git a/src/core/plugins/request-snippets/request-snippets.jsx b/src/core/plugins/request-snippets/request-snippets.jsx index 22b2ffe179c..8b523f23fd9 100644 --- a/src/core/plugins/request-snippets/request-snippets.jsx +++ b/src/core/plugins/request-snippets/request-snippets.jsx @@ -2,7 +2,6 @@ import React from "react" import { CopyToClipboard } from "react-copy-to-clipboard" import PropTypes from "prop-types" import get from "lodash/get" -import {SyntaxHighlighter, getStyle} from "core/syntax-highlighting" export class RequestSnippets extends React.Component { constructor() { @@ -17,69 +16,72 @@ export class RequestSnippets extends React.Component { request: PropTypes.object.isRequired, requestSnippetsSelectors: PropTypes.object.isRequired, getConfigs: PropTypes.object.isRequired, + getComponent: PropTypes.object.isRequired, requestSnippetsActions: PropTypes.object.isRequired, + fn: PropTypes.object.isRequired, } render() { - const {request, getConfigs, requestSnippetsSelectors } = this.props - const snippetGenerators = requestSnippetsSelectors.getSnippetGenerators() - const activeLanguage = this.state.activeLanguage || snippetGenerators.keySeq().first() - const activeGenerator = snippetGenerators.get(activeLanguage) - const snippet = activeGenerator.get("fn")(request) - const onGenChange = (key) => { - const needsChange = activeLanguage !== key - if(needsChange) { - this.setState({ - activeLanguage: key - }) - } + const {request, getConfigs, requestSnippetsSelectors, fn, getComponent } = this.props + const snippetGenerators = requestSnippetsSelectors.getSnippetGenerators() + const activeLanguage = this.state.activeLanguage || snippetGenerators.keySeq().first() + const activeGenerator = snippetGenerators.get(activeLanguage) + const snippet = activeGenerator.get("fn")(request) + const onGenChange = (key) => { + const needsChange = activeLanguage !== key + if(needsChange) { + this.setState({ + activeLanguage: key + }) } - const style = { - cursor: "pointer", - lineHeight: 1, - display: "inline-flex", - backgroundColor: "rgb(250, 250, 250)", - paddingBottom: "0", - paddingTop: "0", - border: "1px solid rgb(51, 51, 51)", - borderRadius: "4px 4px 0 0", - boxShadow: "none", - borderBottom: "none" - } - const activeStyle = { - cursor: "pointer", - lineHeight: 1, - display: "inline-flex", - backgroundColor: "rgb(51, 51, 51)", - boxShadow: "none", - border: "1px solid rgb(51, 51, 51)", - paddingBottom: "0", - paddingTop: "0", - borderRadius: "4px 4px 0 0", - marginTop: "-5px", - marginRight: "-5px", - marginLeft: "-5px", - zIndex: "9999", - borderBottom: "none" - } - const getBtnStyle = (key) => { - if (key === activeLanguage) { - return activeStyle - } - return style + } + const style = { + cursor: "pointer", + lineHeight: 1, + display: "inline-flex", + backgroundColor: "rgb(250, 250, 250)", + paddingBottom: "0", + paddingTop: "0", + border: "1px solid rgb(51, 51, 51)", + borderRadius: "4px 4px 0 0", + boxShadow: "none", + borderBottom: "none" + } + const activeStyle = { + cursor: "pointer", + lineHeight: 1, + display: "inline-flex", + backgroundColor: "rgb(51, 51, 51)", + boxShadow: "none", + border: "1px solid rgb(51, 51, 51)", + paddingBottom: "0", + paddingTop: "0", + borderRadius: "4px 4px 0 0", + marginTop: "-5px", + marginRight: "-5px", + marginLeft: "-5px", + zIndex: "9999", + borderBottom: "none" + } + const getBtnStyle = (key) => { + if (key === activeLanguage) { + return activeStyle } - const config = getConfigs() + return style + } + const config = getConfigs() + const SyntaxHighlighter = getComponent("SyntaxHighlighter") - const SnippetComponent = config?.syntaxHighlight?.activated - ? - {snippet} - - : - + const SnippetComponent = config?.syntaxHighlight?.activated + ? + {snippet} + + : + const expanded = this.state.expanded === undefined ? this.props?.requestSnippetsSelectors?.getDefaultExpanded() : this.state.expanded return ( diff --git a/src/core/plugins/syntax-highlight/fn.js b/src/core/plugins/syntax-highlight/fn.js new file mode 100644 index 00000000000..aceac65b202 --- /dev/null +++ b/src/core/plugins/syntax-highlight/fn.js @@ -0,0 +1,20 @@ +import agate from "react-syntax-highlighter/dist/cjs/styles/hljs/agate" +import arta from "react-syntax-highlighter/dist/cjs/styles/hljs/arta" +import monokai from "react-syntax-highlighter/dist/cjs/styles/hljs/monokai" +import nord from "react-syntax-highlighter/dist/cjs/styles/hljs/nord" +import obsidian from "react-syntax-highlighter/dist/cjs/styles/hljs/obsidian" +import tomorrowNight from "react-syntax-highlighter/dist/cjs/styles/hljs/tomorrow-night" + +const internalStylePreset = {agate, arta, monokai, nord, obsidian, "tomorrow-night": tomorrowNight} + +export default system => ({ + getAvailableStyles: () => internalStylePreset, + getStyle: name => { + const styles = system.getSystem().fn.getAvailableStyles() + if (!Object.keys(styles).includes(name)) { + console.warn(`Request style '${name}' is not available, returning default instead`) + return agate + } + return styles[name] + } +}) diff --git a/src/core/plugins/syntax-highlight/index.js b/src/core/plugins/syntax-highlight/index.js new file mode 100644 index 00000000000..4a7bf7039cb --- /dev/null +++ b/src/core/plugins/syntax-highlight/index.js @@ -0,0 +1,9 @@ +import buildFn from "./fn" +import { SyntaxHighlighter } from "./syntax-highlight" + +export default (system) => ({ + components: { + SyntaxHighlighter + }, + fn: buildFn(system), +}) diff --git a/src/core/syntax-highlighting.js b/src/core/plugins/syntax-highlight/syntax-highlight.js similarity index 56% rename from src/core/syntax-highlighting.js rename to src/core/plugins/syntax-highlight/syntax-highlight.js index 25e7c31185b..75cd98c87b3 100644 --- a/src/core/syntax-highlighting.js +++ b/src/core/plugins/syntax-highlight/syntax-highlight.js @@ -9,13 +9,6 @@ import http from "react-syntax-highlighter/dist/esm/languages/hljs/http" import powershell from "react-syntax-highlighter/dist/esm/languages/hljs/powershell" import javascript from "react-syntax-highlighter/dist/esm/languages/hljs/javascript" -import agate from "react-syntax-highlighter/dist/esm/styles/hljs/agate" -import arta from "react-syntax-highlighter/dist/esm/styles/hljs/arta" -import monokai from "react-syntax-highlighter/dist/esm/styles/hljs/monokai" -import nord from "react-syntax-highlighter/dist/esm/styles/hljs/nord" -import obsidian from "react-syntax-highlighter/dist/esm/styles/hljs/obsidian" -import tomorrowNight from "react-syntax-highlighter/dist/esm/styles/hljs/tomorrow-night" - SyntaxHighlighter.registerLanguage("json", json) SyntaxHighlighter.registerLanguage("js", js) SyntaxHighlighter.registerLanguage("xml", xml) @@ -25,15 +18,6 @@ SyntaxHighlighter.registerLanguage("bash", bash) SyntaxHighlighter.registerLanguage("powershell", powershell) SyntaxHighlighter.registerLanguage("javascript", javascript) -const styles = {agate, arta, monokai, nord, obsidian, "tomorrow-night": tomorrowNight} -export const availableStyles = Object.keys(styles) - -export const getStyle = name => { - if (!availableStyles.includes(name)) { - console.warn(`Request style '${name}' is not available, returning default instead`) - return agate - } - return styles[name] +export { + SyntaxHighlighter } - -export {SyntaxHighlighter, styles} diff --git a/src/core/presets/base.js b/src/core/presets/base.js index 95e7329dd07..fe649c79047 100644 --- a/src/core/presets/base.js +++ b/src/core/presets/base.js @@ -4,6 +4,7 @@ import spec from "core/plugins/spec" import view from "core/plugins/view" import samples from "core/plugins/samples" import requestSnippets from "core/plugins/request-snippets" +import syntaxHighlight from "core/plugins/syntax-highlight" import logs from "core/plugins/logs" import swaggerJs from "core/plugins/swagger-js" import auth from "core/plugins/auth" @@ -193,6 +194,7 @@ export default function() { deepLinkingPlugin, filter, onComplete, - requestSnippets + requestSnippets, + syntaxHighlight ] }