diff options
| author | Ryan Mehri <[email protected]> | 2020-05-23 09:53:02 -0600 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-05-23 09:53:02 -0600 |
| commit | 128ed6ef43d960becfeaef96615aa06e16932195 (patch) | |
| tree | d81289bc118b006ddec2e9f7162f188e0d8f8ec8 | |
| parent | Merge pull request #29 from jackyzha0/order-langs (diff) | |
| parent | fix weird padding (diff) | |
| download | ctrl-v-128ed6ef43d960becfeaef96615aa06e16932195.tar.xz ctrl-v-128ed6ef43d960becfeaef96615aa06e16932195.zip | |
Merge pull request #30 from jackyzha0/latex-renderer
latex renderer live preview
| -rw-r--r-- | frontend/package.json | 2 | ||||
| -rw-r--r-- | frontend/src/components/Inputs.js | 1 | ||||
| -rw-r--r-- | frontend/src/components/NewPaste.js | 128 | ||||
| -rw-r--r-- | frontend/src/components/PasteInfo.js | 6 | ||||
| -rw-r--r-- | frontend/src/components/modals/PasteModal.js | 3 | ||||
| -rw-r--r-- | frontend/src/components/renderers/Code.js | 23 | ||||
| -rw-r--r-- | frontend/src/components/renderers/Latex.js | 38 | ||||
| -rw-r--r-- | frontend/src/components/renderers/Raw.js | 21 | ||||
| -rw-r--r-- | frontend/src/css/index.css | 14 |
9 files changed, 183 insertions, 53 deletions
diff --git a/frontend/package.json b/frontend/package.json index 4139f4b..383fecc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,12 +9,12 @@ "axios": "^0.19.2", "d3-scale": "^3.2.1", "file-saver": "^2.0.2", - "html-to-image": "^0.1.1", "rc-slider": "^9.2.4", "react": "^16.13.1", "react-component-export-image": "^0.1.4", "react-dom": "^16.13.1", "react-dropdown": "^1.7.0", + "react-katex": "^2.0.2", "react-modal": "^3.11.2", "react-render-html": "^0.6.0", "react-router-dom": "^5.2.0", diff --git a/frontend/src/components/Inputs.js b/frontend/src/components/Inputs.js index b96ceb0..872afd7 100644 --- a/frontend/src/components/Inputs.js +++ b/frontend/src/components/Inputs.js @@ -7,6 +7,7 @@ import { LANGS, THEMES } from './renderers/Code'; const RelPositioning = styled.div` position: relative; + height: calc(100% - 4em); ` const FlexChild = styled.div` diff --git a/frontend/src/components/NewPaste.js b/frontend/src/components/NewPaste.js index 6e1b507..8012b99 100644 --- a/frontend/src/components/NewPaste.js +++ b/frontend/src/components/NewPaste.js @@ -5,6 +5,34 @@ import Error from './Err' import { PostNewPaste } from '../helpers/httpHelper' import PasteModal from './modals/PasteModal' import { LANGS } from './renderers/Code' +import styled from 'styled-components' +import CodeRenderer from './renderers/Code' +import Latex from './renderers/Latex' + +const Button = styled.button` + margin-right: 0 !important; + margin-left: 2em !important; + height: calc(16px + 1.6em + 2px); +` + +const Flex = styled.div` + display: flex; + flex-direction: row; +` + +const FlexLeft = styled.div` + flex: 0 0 50%; +` + +const FlexRight = styled.div` + flex: 0 0 50%; + max-width: calc(50% - 1em + 2px); + margin-left: 2em; +` + +const LatexWrapper = styled.div` + margin: 2em; +` class NewPaste extends React.Component { constructor(props) { @@ -17,10 +45,13 @@ class NewPaste extends React.Component { expiry: '', hash: '', error: '', + preview: false, }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); + this.togglePreview = this.togglePreview.bind(this); + this.renderPreview = this.renderPreview.bind(this); this.ErrorLabel = React.createRef(); } @@ -41,46 +72,99 @@ class NewPaste extends React.Component { }); } + togglePreview() { + const state = this.state.preview + this.setState({ preview: !state }) + } + handleSubmit(event) { event.preventDefault(); - PostNewPaste(this.state) - .then((response) => { - // on success, redir - this.setState({ hash: response.data.hash }) - }).catch((error) => { - const resp = error.response - - // some weird err - if (resp !== undefined) { - const errTxt = `${resp.statusText}: ${resp.data}` - this.ErrorLabel.current.showMessage(errTxt) - } else { - // some weird err (e.g. network) - this.ErrorLabel.current.showMessage(error) - } - }); + + // prevent resubmission + if (!this.state.hash) { + PostNewPaste(this.state) + .then((response) => { + // on success, redir + this.setState({ hash: response.data.hash }) + }).catch((error) => { + const resp = error.response + + // some weird err + if (resp !== undefined) { + const errTxt = `${resp.statusText}: ${resp.data}` + this.ErrorLabel.current.showMessage(errTxt) + } else { + // some weird err (e.g. network) + this.ErrorLabel.current.showMessage(error) + } + }); + } + } + + renderPreview() { + const pasteInput = <PasteInput + onChange={this.handleChange} + content={this.state.content} + maxLength="100000" + id="pasteInput" /> + + var preview + switch (this.state.language) { + case 'latex': + preview = + <LatexWrapper> + <Latex + content={this.state.content} /> + </LatexWrapper> + break + default: + preview = + <CodeRenderer + lang={this.state.language} + theme='atom' + content={this.state.content} /> + } + + if (this.state.preview) { + return ( + <Flex> + <FlexLeft> + {pasteInput} + </FlexLeft> + <FlexRight className='preview' > + {preview} + </FlexRight> + </Flex> + ); + } else { + return ( + pasteInput + ); + } } render() { return ( <form onSubmit={this.handleSubmit}> <PasteModal hash={this.state.hash} /> - <TitleInput + <TitleInput onChange={this.handleChange} value={this.state.title} maxLength="100" id="titleInput" /> - <PasteInput - onChange={this.handleChange} - content={this.state.content} - maxLength="100000" - id="pasteInput" /> + {this.renderPreview()} <OptionsContainer pass={this.state.pass} expiry={this.state.expiry} lang={this.state.language} onChange={this.handleChange} /> <input className="lt-button lt-shadow lt-hover" type="submit" value="new paste" /> + <Button + className="lt-shadow lt-hover" + type="button" + onClick={this.togglePreview} > + preview + </Button> <Error ref={this.ErrorLabel} /> </form> ); diff --git a/frontend/src/components/PasteInfo.js b/frontend/src/components/PasteInfo.js index 28141ac..9cf4da3 100644 --- a/frontend/src/components/PasteInfo.js +++ b/frontend/src/components/PasteInfo.js @@ -37,9 +37,7 @@ const PasteInfo = (props) => { history.push(redirUrl); } - const redirRender = () => { - const redirUrl = `/render/${props.hash}` - history.push(redirUrl); + const render = () => { } const renderable = () => { @@ -48,7 +46,7 @@ const PasteInfo = (props) => { <Button className="lt-shadow lt-hover" type="button" - onClick={redirRender} + onClick={render} > render </Button> diff --git a/frontend/src/components/modals/PasteModal.js b/frontend/src/components/modals/PasteModal.js index 75c28a8..48ea372 100644 --- a/frontend/src/components/modals/PasteModal.js +++ b/frontend/src/components/modals/PasteModal.js @@ -22,7 +22,8 @@ const PasteModal = (props) => { const clipboard = useClipboard({ copiedTimeout: 3000 }); Modal.setAppElement('body'); - const redir = () => { + const redir = (e) => { + e.preventDefault(); const redirUrl = `/${props.hash}` history.push(redirUrl); } diff --git a/frontend/src/components/renderers/Code.js b/frontend/src/components/renderers/Code.js index 02c1cc6..9e7521b 100644 --- a/frontend/src/components/renderers/Code.js +++ b/frontend/src/components/renderers/Code.js @@ -1,6 +1,7 @@ import React from 'react'; import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'; import { atomOneLight, ascetic, atomOneDark, dracula, ocean } from 'react-syntax-highlighter/dist/esm/styles/hljs'; +import styled from 'styled-components' export const THEMES = Object.freeze({ 'atom': atomOneLight, @@ -34,16 +35,32 @@ export const LANGS = Object.freeze({ 'yaml': 'yaml' }) +const StyledPre = styled.pre` + padding: calc(0.8em - 1px) !important; + margin: 0; +` + +const CodeBlock = styled.div` + width: 100%; + font-size: 0.8em; + min-height: 1.2em; + border-radius: 3px; + border: 1px solid #565656; + outline: none; + margin: 1.7em 0; + padding-right: calc(1.6em - 2px); +` + const CodeRenderer = React.forwardRef((props, ref) => { const Pre = (props) => { return ( - <pre {...props} ref={ref} /> + <StyledPre {...props} ref={ref} /> ); } return ( - <div className="lt-shadow codeBlock"> + <CodeBlock className="lt-shadow"> <SyntaxHighlighter ref={ref} language={props.lang} @@ -52,7 +69,7 @@ const CodeRenderer = React.forwardRef((props, ref) => { PreTag={Pre}> {props.content} </SyntaxHighlighter> - </div> + </CodeBlock> ); }); diff --git a/frontend/src/components/renderers/Latex.js b/frontend/src/components/renderers/Latex.js new file mode 100644 index 0000000..c5dd57c --- /dev/null +++ b/frontend/src/components/renderers/Latex.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { BlockMath, InlineMath } from 'react-katex'; +import 'katex/dist/katex.min.css'; +import styled from 'styled-components' + +const StyledInlineLatex = styled.div` + display: block; + margin-bottom: 0.5em; +` + +class Latex extends React.Component { + render() { + // split by line break chars (\\, \newline, \break) + const els = this.props.content.split(/\\\\|\\newline|\\break/) + + // if <=1 lines, just render block + if (els.length <= 1) { + return ( + <BlockMath> + {this.props.content} + </BlockMath> + ); + } else { + // new inline block for every line + const blocks = els.map(line => + <StyledInlineLatex> + <InlineMath> + {line} + </InlineMath> + </StyledInlineLatex> + ) + + return blocks; + } + } +} + +export default Latex
\ No newline at end of file diff --git a/frontend/src/components/renderers/Raw.js b/frontend/src/components/renderers/Raw.js index a8d0e31..7f8e7c1 100644 --- a/frontend/src/components/renderers/Raw.js +++ b/frontend/src/components/renderers/Raw.js @@ -1,6 +1,15 @@ import React from 'react'; +import styled from 'styled-components' import { FetchPaste } from '../../helpers/httpHelper' +const RawText = styled.pre` + word-wrap: break-word; + white-space: pre-wrap; + line-height: initial; + font-size: 0.8em; + padding: 0 1em; +` + class Raw extends React.Component { constructor(props) { @@ -11,18 +20,10 @@ class Raw extends React.Component { } render() { - const styles = { - wordWrap: "break-word", - whiteSpace: "pre-wrap", - lineHeight: "initial", - fontSize: "0.8em", - padding: "0 1em" - } - return ( - <pre style={styles}> + <RawText> {this.state.content} - </pre> + </RawText> ); } diff --git a/frontend/src/css/index.css b/frontend/src/css/index.css index c1b1813..9aa48e1 100644 --- a/frontend/src/css/index.css +++ b/frontend/src/css/index.css @@ -25,16 +25,6 @@ textarea, input[type=text], input[type=password], .Dropdown-root { margin: 1.7em 0; } -.codeBlock { - width: 100%; - font-size: 0.8em; - padding: calc(0.8em - 1px) !important; - border-radius: 3px; - border: 1px solid #565656; - outline: none; - margin: 1.7em 0; -} - .codeBlock code:first-child { margin-right: 10px; border-radius: 0; @@ -101,9 +91,9 @@ input[type=password] { } textarea { - height: 45vh; + height: max(45vh, 100%); resize: vertical; - min-height: 2em; + min-height: 45vh; } a { |