From 863c88dfb0569f7c829602acee2404e1c840097e Mon Sep 17 00:00:00 2001 From: noahamac <56001784+noahamac@users.noreply.github.com> Date: Tue, 20 Apr 2021 15:05:48 -0700 Subject: [PATCH] feat: introduces prism-editor package; implements read-only usage (#588) * adds prism editor package and implements in runit * changes package name * adds codedisplay util test * adds tests and minor improvements * fixes editor font * removes unused files --- packages/api-explorer/package.json | 2 +- .../src/components/DocCode/DocCode.tsx | 4 +- packages/code-display/LICENSE | 21 ++++++ packages/code-display/jest.config.js | 36 +++++++++ packages/code-display/package.json | 57 +++++++++++++++ .../code-display/src/CodeDisplay.spec.tsx | 73 +++++++++++++++++++ .../src/CodeDisplay.tsx} | 60 +++++++-------- packages/code-display/src/index.ts | 26 +++++++ packages/code-display/src/utils/index.ts | 26 +++++++ packages/code-display/src/utils/utils.spec.ts | 42 +++++++++++ packages/code-display/src/utils/utils.ts | 63 ++++++++++++++++ packages/code-display/tsconfig.build.json | 8 ++ packages/run-it/package.json | 1 + packages/run-it/src/RunIt.tsx | 8 +- .../components/DocSdkCalls/DocMultiCall.tsx | 4 +- .../components/DocSdkCalls/DocSingleCall.tsx | 4 +- .../components/ShowResponse/responseUtils.tsx | 10 +-- 17 files changed, 395 insertions(+), 50 deletions(-) create mode 100644 packages/code-display/LICENSE create mode 100644 packages/code-display/jest.config.js create mode 100644 packages/code-display/package.json create mode 100644 packages/code-display/src/CodeDisplay.spec.tsx rename packages/{api-explorer/src/components/DocCode/PrismEditor.tsx => code-display/src/CodeDisplay.tsx} (69%) create mode 100644 packages/code-display/src/index.ts create mode 100644 packages/code-display/src/utils/index.ts create mode 100644 packages/code-display/src/utils/utils.spec.ts create mode 100644 packages/code-display/src/utils/utils.ts create mode 100644 packages/code-display/tsconfig.build.json diff --git a/packages/api-explorer/package.json b/packages/api-explorer/package.json index ec4e2027d..ac97b581d 100644 --- a/packages/api-explorer/package.json +++ b/packages/api-explorer/package.json @@ -59,7 +59,7 @@ "@looker/sdk-codegen": "^21.0.12", "@looker/sdk-rtl": "^21.0.12", "ace": "^1.3.0", - "prism-react-renderer": "^1.2.0", + "@looker/code-display": "^0.0.1", "ace-builds": "^1.4.11", "history": "^4.10.1", "lodash": "^4.17.19", diff --git a/packages/api-explorer/src/components/DocCode/DocCode.tsx b/packages/api-explorer/src/components/DocCode/DocCode.tsx index f1f5db75f..fbee21bd0 100644 --- a/packages/api-explorer/src/components/DocCode/DocCode.tsx +++ b/packages/api-explorer/src/components/DocCode/DocCode.tsx @@ -27,9 +27,9 @@ import React, { FC, useContext } from 'react' import AceEditor from 'react-ace' import { findGenerator } from '@looker/sdk-codegen' +import { CodeDisplay } from '@looker/code-display' import { SearchContext } from '../../context/search' import { highlightSourceCode } from './utils' -import { PrismEditor } from './PrismEditor' // TODO Use webpack resolver instead. /* eslint-disable @typescript-eslint/ban-ts-comment,@typescript-eslint/no-unused-vars,@typescript-eslint/no-var-requires,import/no-extraneous-dependencies */ @@ -92,6 +92,6 @@ export const DocCode: FC = ({ }} /> ) : ( - + ) } diff --git a/packages/code-display/LICENSE b/packages/code-display/LICENSE new file mode 100644 index 000000000..a93d2c01a --- /dev/null +++ b/packages/code-display/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Looker Data Sciences, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/code-display/jest.config.js b/packages/code-display/jest.config.js new file mode 100644 index 000000000..92fe32ce0 --- /dev/null +++ b/packages/code-display/jest.config.js @@ -0,0 +1,36 @@ +/* + + MIT License + + Copyright (c) 2021 Looker Data Sciences, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + */ + +const base = require('../../jest.config') +const packageName = require('./package.json').name.split('/')[1] + +module.exports = { + ...base, + displayName: packageName, + name: packageName, + rootDir: '../..', + testMatch: [`/packages/${packageName}/**/*.(spec|test).(ts|js)?(x)`], +} diff --git a/packages/code-display/package.json b/packages/code-display/package.json new file mode 100644 index 000000000..e203ccc33 --- /dev/null +++ b/packages/code-display/package.json @@ -0,0 +1,57 @@ +{ + "name": "@looker/code-display", + "version": "0.0.1", + "description": "A syntax highlighter for Looker apps.", + "main": "lib/esm/index.js", + "typings": "lib/index.d.ts", + "files": [ + "lib" + ], + "author": "Looker", + "license": "MIT", + "private": true, + "repository": { + "type": "git", + "url": "git+https://github.com/looker-open-source/sdk-codegen.git", + "directory": "packages/code-display" + }, + "homepage": "https://github.com/looker-open-source/sdk-codegen/tree/main/packages/code-display", + "bugs": { + "url": "https://github.com/looker-open-source/sdk-codegen/issues" + }, + "scripts": { + "test": "jest", + "watch": "yarn lerna exec --scope @looker/code-display --stream 'BABEL_ENV=build babel src --root-mode upward --out-dir lib/esm --source-maps --extensions .ts,.tsx --no-comments --watch'" + }, + "devDependencies": { + "@looker/components-test-utils": "^0.9.29", + "@testing-library/jest-dom": "^5.11.6", + "@testing-library/react": "^11.2.2", + "@testing-library/user-event": "^12.6.0", + "@types/lodash": "^4.14.157", + "@types/react": "^16.14.2", + "@types/react-dom": "^16.9.6", + "@types/react-router": "^5.1.11", + "@types/react-router-dom": "^5.1.5", + "@types/react-test-renderer": "^17.0.0", + "@types/styled-components": "^5.1.7", + "enzyme": "^3.11.0", + "jest-config": "^25.3.0", + "react-router-dom": "^5.2.0", + "react-test-renderer": "^17.0.1", + "style-loader": "^1.1.3", + "webpack-cli": "^3.3.11", + "webpack-dev-server": "^3.10.3" + }, + "dependencies": { + "@looker/components": "^0.9.30", + "@looker/design-tokens": "0.9.27", + "@looker/sdk-codegen": "^21.0.11", + "prism-react-renderer": "^1.2.0", + "lodash": "^4.17.19", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-is": "^16.13.1", + "styled-components": "^5.2.1" + } +} diff --git a/packages/code-display/src/CodeDisplay.spec.tsx b/packages/code-display/src/CodeDisplay.spec.tsx new file mode 100644 index 000000000..d18fbb731 --- /dev/null +++ b/packages/code-display/src/CodeDisplay.spec.tsx @@ -0,0 +1,73 @@ +/* + + MIT License + + Copyright (c) 2021 Looker Data Sciences, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + */ +import React from 'react' +import { screen } from '@testing-library/react' +import { renderWithTheme } from '@looker/components-test-utils' + +import { CodeDisplay } from './CodeDisplay' + +describe('CodeDisplay', () => { + const code = ` + # GET /lookml_models -> Sequence[models.LookmlModel] + def all_lookml_models( + self, + # Requested fields. + fields: Optional[str] = None, + transport_options: Optional[transport.TransportOptions] = None, + ) -> Sequence[models.LookmlModel]: + """Get All LookML Models""" + response = self.get( + f"/lookml_models", + Sequence[models.LookmlModel], + query_params={"fields": fields}, + transport_options=transport_options + ) + assert isinstance(response, list) + return response + ` + test('it syntax highlights', () => { + renderWithTheme() + expect(screen.getByText('all_lookml_models').closest('span')).toHaveClass( + 'function' + ) + expect(screen.getByText('def').closest('span')).toHaveClass('keyword') + expect( + screen + .getByText('# GET /lookml_models -> Sequence[models.LookmlModel]') + .closest('span') + ).toHaveClass('comment') + }) + + test('it highlights text matching search pattern', () => { + const highlightPattern = 'lookml_models' + renderWithTheme( + + ) + expect(screen.getByText('all_lookml_models').closest('span')).toHaveClass( + 'match' + ) + }) +}) diff --git a/packages/api-explorer/src/components/DocCode/PrismEditor.tsx b/packages/code-display/src/CodeDisplay.tsx similarity index 69% rename from packages/api-explorer/src/components/DocCode/PrismEditor.tsx rename to packages/code-display/src/CodeDisplay.tsx index f3e68c608..d64169fad 100644 --- a/packages/api-explorer/src/components/DocCode/PrismEditor.tsx +++ b/packages/code-display/src/CodeDisplay.tsx @@ -26,31 +26,41 @@ import React, { FC } from 'react' import styled from 'styled-components' -import Highlight, { defaultProps, Language } from 'prism-react-renderer' +import { Span } from '@looker/components' +import Highlight, { defaultProps } from 'prism-react-renderer' // import { Prism } from "prism-react-renderer" -import dracula from 'prism-react-renderer/themes/dracula' - +import { getPrismLanguage, getOverridenTheme } from './utils' +// TODO enable kotlin, csharp, swift highlighting // (typeof global !== "undefined" ? global : window).Prism = Prism // require("prismjs/components/prism-kotlin") // require("prismjs/components/prism-csharp") // require("prismjs/components/prism-swift") interface PrismEditorProps { - language: string + /** SDK programming language */ + language?: string + /** Code blob to be highlighted */ code: string - pattern: string + /** Pattern to be search (if applicable) */ + pattern?: string } const Pre = styled.pre` padding: 1rem; overflow: auto; + white-space: pre-wrap; + + .match { + border: 1px yellow solid; + border-radius: 4px; + } ` const Line = styled.div` display: table-row; ` -const LineNo = styled.span` +const LineNo = styled(Span)` display: table-cell; text-align: right; padding-right: 1em; @@ -58,48 +68,40 @@ const LineNo = styled.span` opacity: 0.5; ` -const LineContent = styled.span` +const LineContent = styled(Span)` display: table-cell; + font-family: monospace; ` -export const PrismEditor: FC = ({ - language, +/** + * The PrismEditor provides a useful implementation of prism-react-renderer + * for Looker apps. Syntax highlighting is available for all supported SDK languages. + * TODO: LookML syntax highlighting + */ +export const CodeDisplay: FC = ({ + language = 'json', code, - pattern, + pattern = '', }) => { - const getPrismLanguage = (language: string) => { - const unstyled = ['kotlin', 'csharp', 'swift'] - // TODO revert back to `go` in generator language definitions instead of using this - if (language === 'golang') { - return 'go' - } else if (unstyled.includes(language)) { - return 'clike' - } - return language as Language - } - + const highlighterLang = getPrismLanguage(language) return ( {({ className, style, tokens, getLineProps, getTokenProps }) => (
           {tokens.map((line, i) => (
             
-              {i + 1}
+              {language === 'json' || {i + 1}}
               
                 {line.map((token, key) => {
                   const tokenProps = getTokenProps({ token, key })
                   const text = tokenProps.children
                   if (pattern !== '' && text.includes(pattern)) {
-                    tokenProps.style = {
-                      ...tokenProps.style,
-                      border: '1px yellow solid',
-                      borderRadius: '4px',
-                    }
+                    tokenProps.className += ' match'
                   }
                   return 
                 })}
diff --git a/packages/code-display/src/index.ts b/packages/code-display/src/index.ts
new file mode 100644
index 000000000..00b9621d2
--- /dev/null
+++ b/packages/code-display/src/index.ts
@@ -0,0 +1,26 @@
+/*
+
+ MIT License
+
+ Copyright (c) 2021 Looker Data Sciences, Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ */
+export { CodeDisplay } from './CodeDisplay'
diff --git a/packages/code-display/src/utils/index.ts b/packages/code-display/src/utils/index.ts
new file mode 100644
index 000000000..63d983f7f
--- /dev/null
+++ b/packages/code-display/src/utils/index.ts
@@ -0,0 +1,26 @@
+/*
+
+ MIT License
+
+ Copyright (c) 2021 Looker Data Sciences, Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ */
+export { getPrismLanguage, getOverridenTheme } from './utils'
diff --git a/packages/code-display/src/utils/utils.spec.ts b/packages/code-display/src/utils/utils.spec.ts
new file mode 100644
index 000000000..ddbf2f6a9
--- /dev/null
+++ b/packages/code-display/src/utils/utils.spec.ts
@@ -0,0 +1,42 @@
+/*
+
+ MIT License
+
+ Copyright (c) 2021 Looker Data Sciences, Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ */
+import { codeGenerators } from '@looker/sdk-codegen'
+
+import { getPrismLanguage } from './utils'
+
+describe('CodeDisplay utils', () => {
+  const allSdkLanguages: string[] = codeGenerators.map((gen) => gen.language)
+
+  test.each([...allSdkLanguages, 'html', 'json'])(
+    'it can syntax highlight all supported sdk langs',
+    (sdkLanguage) => {
+      expect(getPrismLanguage(sdkLanguage)).toBeTruthy()
+    }
+  )
+  test('it highlights as json for unsupported/undefined language', () => {
+    expect(getPrismLanguage('foobar-lang')).toEqual('json')
+  })
+})
diff --git a/packages/code-display/src/utils/utils.ts b/packages/code-display/src/utils/utils.ts
new file mode 100644
index 000000000..b11c907f8
--- /dev/null
+++ b/packages/code-display/src/utils/utils.ts
@@ -0,0 +1,63 @@
+/*
+
+ MIT License
+
+ Copyright (c) 2021 Looker Data Sciences, Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ */
+import { theme } from '@looker/components'
+import { Language, Prism } from 'prism-react-renderer'
+import prismTheme from 'prism-react-renderer/themes/vsDark'
+
+/**
+ * checks whether object is Language
+ * @param object any object to be tested
+ * @returns boolean
+ */
+function instanceOfPrismLanguage(object: any): boolean {
+  return Object.keys(Prism.languages).includes(object)
+}
+
+/**
+ * gets highlighter language type for input language name
+ * @param language sdk language to be highlighted
+ * @returns prism language if it exists
+ */
+export const getPrismLanguage = (language: string): Language => {
+  language = language.toLowerCase()
+  const unstyled = ['kotlin', 'csharp', 'swift']
+  // TODO revert back to `go` in generator language definitions instead of using this
+  if (language === 'golang') {
+    language = 'go'
+  } else if (unstyled.includes(language)) {
+    language = 'clike'
+  }
+  return instanceOfPrismLanguage(language) ? (language as Language) : 'json'
+}
+
+/**
+ * applies package overrides to the default vsCode prism theme
+ * @returns modified prism theme object
+ */
+export function getOverridenTheme() {
+  prismTheme.plain.backgroundColor = theme.colors.text
+  return prismTheme
+}
diff --git a/packages/code-display/tsconfig.build.json b/packages/code-display/tsconfig.build.json
new file mode 100644
index 000000000..51db2ccb4
--- /dev/null
+++ b/packages/code-display/tsconfig.build.json
@@ -0,0 +1,8 @@
+{
+  "extends": "../../tsconfig.build.json",
+  "compilerOptions": {
+    "rootDir": "./src",
+    "outDir": "./lib"
+  },
+  "include": ["src/**/*"]
+}
diff --git a/packages/run-it/package.json b/packages/run-it/package.json
index bf4f71f9a..a2cca6dab 100644
--- a/packages/run-it/package.json
+++ b/packages/run-it/package.json
@@ -57,6 +57,7 @@
     "@looker/sdk": "^21.4.1",
     "@looker/sdk-codegen": "^21.0.12",
     "@looker/sdk-codegen-utils": "^21.0.11",
+    "@looker/code-display": "^0.0.1",
     "@looker/sdk-rtl": "^21.0.12",
     "@types/readable-stream": "^2.3.5",
     "lodash": "^4.17.19",
diff --git a/packages/run-it/src/RunIt.tsx b/packages/run-it/src/RunIt.tsx
index 4b0d73492..45d9afc8d 100644
--- a/packages/run-it/src/RunIt.tsx
+++ b/packages/run-it/src/RunIt.tsx
@@ -199,13 +199,7 @@ export const RunIt: FC = ({
         {isExtension ? <> : Performance}
         Code
       
-      
+      
         
           {!needsAuth && hasConfig && (
             > = ({
           const code = gen.makeTheCall(method, inputs)
           return (
             
-              
+              
             
           )
         })}
diff --git a/packages/run-it/src/components/DocSdkCalls/DocSingleCall.tsx b/packages/run-it/src/components/DocSdkCalls/DocSingleCall.tsx
index fab7e5a4c..309a220ed 100644
--- a/packages/run-it/src/components/DocSdkCalls/DocSingleCall.tsx
+++ b/packages/run-it/src/components/DocSdkCalls/DocSingleCall.tsx
@@ -25,8 +25,8 @@
  */
 import React, { FC } from 'react'
 import { getCodeGenerator } from '@looker/sdk-codegen'
+import { CodeDisplay } from '@looker/code-display'
 
-import { CodeStructure } from '../CodeStructure'
 import { DocSdkCallsProps } from './DocSdkCalls'
 
 /**
@@ -41,5 +41,5 @@ export const DocSingleCall: FC = ({
   const generator = getCodeGenerator(sdkLanguage, api)
   const code = generator!.makeTheCall(method, inputs)
 
-  return 
+  return 
 }
diff --git a/packages/run-it/src/components/ShowResponse/responseUtils.tsx b/packages/run-it/src/components/ShowResponse/responseUtils.tsx
index e332bd56a..8435380e8 100644
--- a/packages/run-it/src/components/ShowResponse/responseUtils.tsx
+++ b/packages/run-it/src/components/ShowResponse/responseUtils.tsx
@@ -26,8 +26,8 @@
 import React, { ReactElement } from 'react'
 import { IRawResponse, ResponseMode, responseMode } from '@looker/sdk-rtl'
 import { Paragraph, CodeBlock } from '@looker/components'
+import { CodeDisplay } from '@looker/code-display'
 
-import { CodeStructure } from '../CodeStructure'
 import { DataGrid, parseCsv, parseJson } from '../DataGrid'
 
 /**
@@ -70,11 +70,7 @@ const ShowJSON = (response: IRawResponse) => {
   const data = parseJson(content)
   const showGrid = isColumnar(data.data)
   const raw = (
-    
+    
   )
   if (!showGrid) return raw
   return 
@@ -117,7 +113,7 @@ const ShowImage = (response: IRawResponse) => {
 
 /** A handler for HTTP type responses */
 const ShowHTML = (response: IRawResponse) => (
-  
+  
 )
 
 /**