Skip to content

Commit

Permalink
feat: allow edit code inside playground (#205)
Browse files Browse the repository at this point in the history
* feat(docz): fetch data on documents
* feat(rehype-docz): add dependencies scope on Playground
* feat(docz-theme-default): add codemirror as editor
* chore(rehype-docz): use replace instead of split join
  • Loading branch information
pedronauck committed Aug 9, 2018
1 parent fa4ff40 commit 4f948f7
Show file tree
Hide file tree
Showing 25 changed files with 961 additions and 796 deletions.
7 changes: 2 additions & 5 deletions packages/docz-theme-default/librc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@ const internal = [
]

const depsExternal = [
're-resizable',
'@mdx-js/tag',
'react-dom/server',
'polished/lib/color/rgba',
'polished/lib/color/lighten',
'polished/lib/color/darken',
'react-syntax-highlighter',
'react-syntax-highlighter/prism',
'react-syntax-highlighter/prism-light',
'react-feather/dist/icons/edit-2',
'react-feather/dist/icons/chevron-down',
'react-feather/dist/icons/search',
Expand All @@ -36,7 +33,7 @@ const external = Object.keys(pkg.dependencies)
.filter(dep => internal.indexOf(dep) === -1)

module.exports = {
external,
sourcemap: false,
plugins: [svg()],
external,
}
4 changes: 3 additions & 1 deletion packages/docz-theme-default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"tslint": "tslint --project ."
},
"dependencies": {
"codemirror": "^5.39.2",
"copy-text-to-clipboard": "^1.0.4",
"docz": "^0.9.6",
"emotion": "^9.2.6",
Expand All @@ -36,12 +37,13 @@
"react": "^16.4.2",
"react-adopt": "^0.6.0",
"react-breakpoints": "^3.0.0",
"react-codemirror": "^1.0.0",
"react-dom": "^16.4.2",
"react-emotion": "^9.2.6",
"react-feather": "^1.1.1",
"react-lightweight-tooltip": "^1.0.0",
"react-live": "^1.11.0",
"react-powerplug": "^1.0.0-rc.1",
"react-syntax-highlighter": "^8.0.1",
"webfontloader": "^1.6.28"
},
"peerDependencies": {
Expand Down
164 changes: 100 additions & 64 deletions packages/docz-theme-default/src/components/ui/Pre.tsx
Original file line number Diff line number Diff line change
@@ -1,65 +1,92 @@
import * as React from 'react'
import { SFC, Component, Fragment } from 'react'
import { SFC, Component } from 'react'
import { ThemeConfig } from 'docz'
import styled, { cx } from 'react-emotion'
import styled, { injectGlobal } from 'react-emotion'
import rgba from 'polished/lib/color/rgba'
import lighten from 'polished/lib/color/lighten'
import darken from 'polished/lib/color/darken'
import BaseCheck from 'react-feather/dist/icons/check'
import SyntaxHighlighter from 'react-syntax-highlighter/prism-light'
import Clipboard from 'react-feather/dist/icons/clipboard'
import Codemirror from 'react-codemirror'
import copy from 'copy-text-to-clipboard'
import get from 'lodash.get'

import { ButtonSwap } from './ButtonSwap'
import { ButtonLink } from './Button'
import * as themes from '../../styles/codemirror'

const TOP_PADDING = '15px'
// tslint:disable
declare var require: any
require('codemirror/mode/markdown/markdown')
require('codemirror/mode/javascript/javascript')
require('codemirror/mode/jsx/jsx')
require('codemirror/mode/css/css')
require('codemirror/addon/edit/matchbrackets')

const PrismTheme = styled('pre')`
${p => p.theme.docz.prismTheme};
${p => p.theme.docz.mq(p.theme.docz.styles.pre)};
overflow-y: hidden;
padding: ${TOP_PADDING} 20px;
margin: 0;
flex: 1;
`

const getChildren = (children: any) =>
children && typeof children !== 'string' ? children.props.children : children
injectGlobal(`
@import url('https://unpkg.com/codemirror@5.39.2/lib/codemirror.css');
`)

const getLanguage = (children: any) => {
const defaultLanguage = 'language-jsx'
const defaultLanguage = 'jsx'
if (typeof children === 'string') return defaultLanguage
return get(children, 'props.props.className') || defaultLanguage
const language = get(children, 'props.props.className') || defaultLanguage
return language.replace('language-', '')
}

const getCode = (content: any): SFC => ({ children }) => {
const className = cx('react-prism', getLanguage(content))
return <PrismTheme className={className}>{children}</PrismTheme>
}
const getChildren = (children: any) =>
children && typeof children !== 'string' ? children.props.children : children

const Wrapper = styled('div')`
display: flex;
margin: 30px 0;
position: relative;
border: 1px solid ${p => p.theme.docz.colors.border};
border-radius: 5px;
background: ${p => darken(0.01, p.theme.docz.colors.preBg)};
`

const Editor = styled(Codemirror)`
${themes.dark()};
${themes.light()};
${p => p.theme.docz.mq(p.theme.docz.styles.pre)};
position: relative;
border-radius: 5px;
border: 1px solid ${p => p.theme.docz.colors.border};
overflow-y: auto;
flex: 1;
.CodeMirror {
max-width: 100%;
height: auto;
}
.CodeMirror pre {
${p => p.theme.docz.mq(p.theme.docz.styles.pre)};
}
.CodeMirror-gutters {
left: 1px !important;
}
.CodeMirror-lines {
padding: 10px 0;
}
.react-syntax-highlighter-line-number {
display: block;
.CodeMirror-line {
padding: 0 10px;
opacity: 0.3;
text-align: right;
}
.CodeMirror-linenumber {
padding: 0 7px 0 5px;
opacity: 0.7;
}
`

const Actions = styled('div')`
z-index: 999;
position: absolute;
top: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
padding: 5px 10px;
background: transparent;
`

export const ActionButton = styled(ButtonSwap)`
Expand Down Expand Up @@ -98,49 +125,58 @@ export const ClipboardAction: SFC<ClipboardActionProps> = ({
</ActionButton>
)

const Nullable: SFC = ({ children }) => <Fragment>{children}</Fragment>

const linesStyle = ({ mode, colors }: any) => ({
padding: `${TOP_PADDING} 3px`,
borderRight: `1px solid ${colors.border}`,
background:
mode === 'light'
? lighten(0.13, colors.border)
: darken(0.04, colors.border),
left: 0,
})

interface PreProps {
children: any
className?: string
editorClassName?: string
actions?: React.ReactNode
readOnly?: boolean
mode?: string
matchBrackets?: boolean
indentUnit?: number
onChange?: (code: string) => any
}

export class Pre extends Component<PreProps> {
public static defaultProps = {
readOnly: true,
mode: 'jsx',
matchBrackets: true,
indentUnit: 2,
}

public render(): JSX.Element {
const { children, className, actions } = this.props
const content = getChildren(children)
const { children, actions, onChange, ...props } = this.props
const code = getChildren(this.props.children)
const language = getLanguage(children)
const mode = language || this.props.mode

const options = {
...props,
mode,
gutter: true,
lineNumbers: true,
tabSize: 2,
theme: 'docz-light',
}

return (
<ThemeConfig>
{config => (
<Wrapper className={className}>
<SyntaxHighlighter
language="javascript"
showLineNumbers
useInlineStyles={false}
lineNumberContainerStyle={linesStyle(config.themeConfig)}
PreTag={Nullable}
CodeTag={getCode(children)}
>
{getChildren(content)}
</SyntaxHighlighter>
<Actions>
{actions || <ClipboardAction content={content} />}
</Actions>
</Wrapper>
)}
</ThemeConfig>
<Wrapper className={this.props.className}>
<ThemeConfig>
{config => (
<Editor
onChange={onChange}
className={this.props.editorClassName}
value={code}
options={{
...options,
theme: config.themeConfig.codemirrorTheme,
}}
/>
)}
</ThemeConfig>
<Actions>{actions || <ClipboardAction content={code} />}</Actions>
</Wrapper>
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { withLive } from 'react-live'

export const LiveConsumer = withLive<any>(({ live, children }) =>
children(live)
)
Loading

0 comments on commit 4f948f7

Please sign in to comment.