Skip to content

Commit

Permalink
docs: use CodeMirror instead of react-live in doc snippets (#2903)
Browse files Browse the repository at this point in the history
* chore: use CodeMirror instead of react-live in doc snippets

Co-authored-by: Savelii Novikov <[email protected]>
  • Loading branch information
haakonflatval-cognite and Savokr authored Jan 25, 2023
1 parent 764ee4c commit 53d98b7
Show file tree
Hide file tree
Showing 11 changed files with 526 additions and 214 deletions.
135 changes: 80 additions & 55 deletions documentation/docs/components/LiveCodeSnippet.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,42 @@
import * as React from 'react';
import { LiveProvider, LiveEditor, LiveError, LivePreview } from 'react-live';
import { PrismTheme } from 'prism-react-renderer';
import clsx from 'clsx';
import { useState } from 'react';

import CodeMirror from '@uiw/react-codemirror';
import { syntaxTree } from '@codemirror/language';
import { EditorView } from '@codemirror/view';
import { javascript } from '@codemirror/lang-javascript';
import { material } from '@uiw/codemirror-theme-material';
import styles from './styles.module.css';
import oceanicNext from 'prism-react-renderer/themes/oceanicNext';
import useBaseUrl from '@docusaurus/useBaseUrl';
const defaultCodeTheme = oceanicNext;
import clsx from 'clsx';

import { linter, Diagnostic } from "@codemirror/lint";


function createLintProvider(setHasError: (hasError: boolean) => void) {
function lintProvider(view: EditorView): readonly Diagnostic[] {
const diagnostics: Diagnostic[] = [];
let anyError = false;
syntaxTree(view.state).iterate({
enter: (node) => {
if (node.type.isError) {
anyError = true;
diagnostics.push({
from: node.from,
to: node.to,
severity: "error",
message: "Syntax error",
});
}
},
});

setHasError(anyError);

return diagnostics;
}

return lintProvider;
}

// Replacement for "import { customScope } from './customScope'" to avoid
// build issues with React Server-side Rendering
Expand All @@ -22,27 +52,8 @@ export type LiveCodeSnippetProps = {
children: string;
};

export function LiveCodeSnippet(props: LiveCodeSnippetProps) {
const scope = {
...customScope,
...Object.keys(customScope.urls).reduce((acc, key) => {
acc[key] = useBaseUrl(customScope.urls[key]);
return acc;
}, {} as any),
};

const { children } = props;
return (
<LiveProvider
code={children}
transpileOptions={{
transforms: {
classes: false,
asyncAwait: false
}
}}
transformCode={(code: string) => {
const fullCode = `
function transformCode(code: string): string {
return `
// make these things to be available in live-editor
const viewer = window.viewer;
const model = window.model;
Expand All @@ -64,32 +75,46 @@ export function LiveCodeSnippet(props: LiveCodeSnippetProps) {
}
// User code starts here!
${code}`;
return `
<button
type="button"
className="button button--primary button--lg"
onClick={() => \{${fullCode}\}}
>
Run
</button>
`;
}}
scope={{ ...scope }}
theme={defaultCodeTheme}
>
<div
className={clsx(
styles.codeSnippetHeader,
styles.codeSnippetEditorHeader
)}
>
Live Editor
</div>
<LiveEditor className={styles.codeSnippetEditor} />
<div className={styles.codeSnippetPreview}>
<LivePreview />
<LiveError />
</div>
</LiveProvider>
);
}

function onRunCode(code: string) {
const transformedCode = transformCode(code);
const customScopeNames = Object.keys(customScope);
const customScopeValues = Object.values(customScope);
new Function(...customScopeNames, transformedCode)(...customScopeValues);
}

export const LiveCodeSnippet = (props: LiveCodeSnippetProps) => {

let code: string = props.children;
function setCode(newCode: string) {
code = newCode;
}

let [buttonEnabled, setButtonEnabled] = useState(true);

const lintProvider = createLintProvider(v => setButtonEnabled(!v));

return (<>
<div className={clsx(styles.codeSnippetHeader,
styles.codeSnippetEditorHeader)}>
Live Editor
</div>
<CodeMirror
value={props.children}
theme={material}
onChange={setCode}
basicSetup={{ lineNumbers: false,
foldGutter: false,
autocompletion: false,
highlightActiveLine: false }}
className={styles.cmEditor}
extensions={[javascript({}), linter(lintProvider)]} />
<button type="button"
disabled={!buttonEnabled}
onClick={() => onRunCode(code)}
className={clsx("button button--primary button--lg", styles.runButton)}>
Run
</button>
</>);
};
20 changes: 6 additions & 14 deletions documentation/docs/components/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,12 @@
color: var(--ifm-color-content-inverse);
}

.codeSnippetPreviewHeader {
background: var(--ifm-color-emphasis-200);
color: var(--ifm-color-content);
.cmEditor {
font-size: 16px;
font-family: var(--ifm-font-family-monospace);
margin-bottom: 10px;
}

.codeSnippetEditor {
font-family: var(--ifm-font-family-monospace) !important;
}

.codeSnippetPreview {
margin-bottom: var(--ifm-leading);
border: 1px solid var(--ifm-color-emphasis-200);
border-bottom-left-radius: var(--ifm-global-radius);
border-bottom-right-radius: var(--ifm-global-radius);
position: relative;
padding: 1rem;
.runButton {
margin-bottom: 15px;
}
4 changes: 2 additions & 2 deletions documentation/docs/examples/cad-3dobjects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const skyBox = new THREE.Mesh(
new THREE.MeshBasicMaterial({
side: THREE.BackSide,
// Skybox texture from http://freepanorama.blogspot.com/2010/01/sky7-spherical.html
map: new THREE.TextureLoader().load(skyUrl),
map: new THREE.TextureLoader().load(urls.skyUrl),
})
);
skyBox.position.copy(modelCenterAtSeaLevel);
Expand Down Expand Up @@ -131,7 +131,7 @@ const skyBox = new THREE.Mesh(
new THREE.MeshBasicMaterial({
side: THREE.BackSide,
// Skybox texture from http://freepanorama.blogspot.com/2010/01/sky7-spherical.html
map: new THREE.TextureLoader().load(skyUrl),
map: new THREE.TextureLoader().load(urls.skyUrl),
})
);
skyBox.position.copy(modelCenterAtSeaLevel);
Expand Down
5 changes: 5 additions & 0 deletions documentation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@
},
"dependencies": {
"@azure/msal-browser": "2.32.2",
"@codemirror/lang-javascript": "6.1.2",
"@codemirror/language": "6.4.0",
"@codemirror/view": "6.7.3",
"@docusaurus/core": "2.2.0",
"@docusaurus/preset-classic": "2.2.0",
"@docusaurus/theme-live-codeblock": "2.2.0",
"@uiw/codemirror-theme-material": "4.19.7",
"@uiw/react-codemirror": "4.19.7",
"clsx": "1.2.1",
"cross-env": "7.0.3",
"ieee754": "1.2.1",
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 53d98b7

Please sign in to comment.