aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Mehri <[email protected]>2020-05-23 09:53:02 -0600
committerGitHub <[email protected]>2020-05-23 09:53:02 -0600
commit128ed6ef43d960becfeaef96615aa06e16932195 (patch)
treed81289bc118b006ddec2e9f7162f188e0d8f8ec8
parentMerge pull request #29 from jackyzha0/order-langs (diff)
parentfix weird padding (diff)
downloadctrl-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.json2
-rw-r--r--frontend/src/components/Inputs.js1
-rw-r--r--frontend/src/components/NewPaste.js128
-rw-r--r--frontend/src/components/PasteInfo.js6
-rw-r--r--frontend/src/components/modals/PasteModal.js3
-rw-r--r--frontend/src/components/renderers/Code.js23
-rw-r--r--frontend/src/components/renderers/Latex.js38
-rw-r--r--frontend/src/components/renderers/Raw.js21
-rw-r--r--frontend/src/css/index.css14
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 {