client: set post title if text pasted w/o title set
This commit is contained in:
parent
c55ca681b4
commit
7ca0cbac4c
8 changed files with 61 additions and 27 deletions
|
@ -2,11 +2,12 @@ import type { Document } from "@lib/types"
|
|||
import DocumentComponent from "@components/edit-document"
|
||||
import { ChangeEvent, memo, useCallback } from "react"
|
||||
|
||||
const DocumentList = ({ docs, removeDoc, updateDocContent, updateDocTitle }: {
|
||||
const DocumentList = ({ docs, removeDoc, updateDocContent, updateDocTitle, onPaste }: {
|
||||
docs: Document[],
|
||||
updateDocTitle: (i: number) => (title: string) => void
|
||||
updateDocContent: (i: number) => (content: string) => void
|
||||
removeDoc: (i: number) => () => void
|
||||
onPaste: (e: any) => void
|
||||
}) => {
|
||||
const handleOnChange = useCallback((i) => (e: ChangeEvent<HTMLTextAreaElement>) => {
|
||||
updateDocContent(i)(e.target.value)
|
||||
|
@ -16,6 +17,7 @@ const DocumentList = ({ docs, removeDoc, updateDocContent, updateDocTitle }: {
|
|||
docs.map(({ content, id, title }, i) => {
|
||||
return (
|
||||
<DocumentComponent
|
||||
onPaste={onPaste}
|
||||
key={id}
|
||||
remove={removeDoc(i)}
|
||||
setContent={updateDocContent(i)}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.card {
|
||||
max-width: var(--main-content);
|
||||
margin: var(--gap) auto;
|
||||
padding: 2;
|
||||
padding: var(--gap);
|
||||
border: 1px solid var(--light-gray);
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
.input {
|
||||
|
|
|
@ -21,9 +21,10 @@ type Props = {
|
|||
initialTab?: "edit" | "preview"
|
||||
skeleton?: boolean
|
||||
remove?: () => void
|
||||
onPaste?: (e: any) => void
|
||||
}
|
||||
|
||||
const Document = ({ remove, title, content, setTitle, setContent, initialTab = 'edit', skeleton, handleOnContentChange }: Props) => {
|
||||
const Document = ({ onPaste, remove, title, content, setTitle, setContent, initialTab = 'edit', skeleton, handleOnContentChange }: Props) => {
|
||||
const codeEditorRef = useRef<HTMLTextAreaElement>(null)
|
||||
const [tab, setTab] = useState(initialTab)
|
||||
// const height = editable ? "500px" : '100%'
|
||||
|
@ -54,7 +55,7 @@ const Document = ({ remove, title, content, setTitle, setContent, initialTab = '
|
|||
if (skeleton) {
|
||||
return <>
|
||||
<Spacer height={1} />
|
||||
<Card marginBottom={'var(--gap)'} marginTop={'var(--gap)'} style={{ maxWidth: 'var(--main-content)', margin: "0 auto" }}>
|
||||
<div className={styles.card}>
|
||||
<div className={styles.fileNameContainer}>
|
||||
<Skeleton width={275} height={36} />
|
||||
{remove && <Skeleton width={36} height={36} />}
|
||||
|
@ -63,7 +64,7 @@ const Document = ({ remove, title, content, setTitle, setContent, initialTab = '
|
|||
<div style={{ flexDirection: 'row', display: 'flex' }}><Skeleton width={125} height={36} /></div>
|
||||
<Skeleton width={'100%'} height={350} />
|
||||
</div >
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
|
@ -90,8 +91,9 @@ const Document = ({ remove, title, content, setTitle, setContent, initialTab = '
|
|||
<Tabs onChange={handleTabChange} initialValue={initialTab} hideDivider leftSpace={0}>
|
||||
<Tabs.Item label={"Edit"} value="edit">
|
||||
{/* <textarea className={styles.lineCounter} wrap='off' readOnly ref={lineNumberRef}>1.</textarea> */}
|
||||
<div style={{ marginTop: 'var(--gap)', display: 'flex', flexDirection: 'column' }}>
|
||||
<div style={{ marginTop: 'var(--gap-half)', display: 'flex', flexDirection: 'column' }}>
|
||||
<Textarea
|
||||
onPaste={onPaste ? onPaste : undefined}
|
||||
ref={codeEditorRef}
|
||||
placeholder=""
|
||||
value={content}
|
||||
|
@ -105,7 +107,9 @@ const Document = ({ remove, title, content, setTitle, setContent, initialTab = '
|
|||
</div>
|
||||
</Tabs.Item>
|
||||
<Tabs.Item label="Preview" value="preview">
|
||||
<div style={{ marginTop: 'var(--gap-half)', }}>
|
||||
<Preview height={height} title={title} content={content} />
|
||||
</div>
|
||||
</Tabs.Item>
|
||||
</Tabs>
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import Cookies from 'js-cookie'
|
|||
import type { PostVisibility, Document as DocumentType } from '@lib/types';
|
||||
import PasswordModal from './password';
|
||||
import getPostPath from '@lib/get-post-path';
|
||||
import DocumentList from '@components/edit-document-list';
|
||||
import EditDocumentList from '@components/edit-document-list';
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
const Post = () => {
|
||||
|
@ -109,11 +109,31 @@ const Post = () => {
|
|||
else setDocs((docs) => [...docs, ...files])
|
||||
}, [docs, title])
|
||||
|
||||
// pasted files
|
||||
// const files = e.clipboardData.files as File[]
|
||||
// if (files.length) {
|
||||
// const docs = Array.from(files).map((file) => ({
|
||||
// title: file.name,
|
||||
// content: '',
|
||||
// id: generateUUID()
|
||||
// }))
|
||||
// }
|
||||
|
||||
const onPaste = useCallback((e: any) => {
|
||||
const pastedText = (e.clipboardData).getData('text')
|
||||
|
||||
if (pastedText) {
|
||||
if (!title) {
|
||||
setTitle("Pasted text")
|
||||
}
|
||||
}
|
||||
}, [title])
|
||||
|
||||
return (
|
||||
<div style={{ marginBottom: 150 }}>
|
||||
<Title title={title} onChange={onChangeTitle} />
|
||||
<FileDropzone setDocs={uploadDocs} />
|
||||
<DocumentList docs={docs} updateDocTitle={updateDocTitle} updateDocContent={updateDocContent} removeDoc={removeDoc} />
|
||||
<EditDocumentList onPaste={onPaste} docs={docs} updateDocTitle={updateDocTitle} updateDocContent={updateDocContent} removeDoc={removeDoc} />
|
||||
<div className={styles.buttons}>
|
||||
<Button
|
||||
className={styles.button}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { Document } from "@lib/types"
|
||||
import DocumentComponent from "@components/edit-document"
|
||||
import { ChangeEvent, memo, useCallback } from "react"
|
||||
import { memo, } from "react"
|
||||
|
||||
const DocumentList = ({ docs }: {
|
||||
docs: Document[],
|
||||
|
|
|
@ -68,7 +68,7 @@ const Document = ({ content, title, initialTab = 'edit', skeleton, id }: Props)
|
|||
if (skeleton) {
|
||||
return <>
|
||||
<Spacer height={1} />
|
||||
<Card marginBottom={'var(--gap)'} marginTop={'var(--gap)'} style={{ maxWidth: 980, margin: "0 auto" }}>
|
||||
<div className={styles.card}>
|
||||
<div className={styles.fileNameContainer}>
|
||||
<Skeleton width={275} height={36} />
|
||||
</div>
|
||||
|
@ -76,7 +76,7 @@ const Document = ({ content, title, initialTab = 'edit', skeleton, id }: Props)
|
|||
<div style={{ flexDirection: 'row', display: 'flex' }}><Skeleton width={125} height={36} /></div>
|
||||
<Skeleton width={'100%'} height={350} />
|
||||
</div >
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ const Document = ({ content, title, initialTab = 'edit', skeleton, id }: Props)
|
|||
<Tabs onChange={handleTabChange} initialValue={initialTab} hideDivider leftSpace={0}>
|
||||
<Tabs.Item label={"Raw"} value="edit">
|
||||
{/* <textarea className={styles.lineCounter} wrap='off' readOnly ref={lineNumberRef}>1.</textarea> */}
|
||||
<div style={{ marginTop: 'var(--gap)', display: 'flex', flexDirection: 'column' }}>
|
||||
<div style={{ marginTop: 'var(--gap-half)', display: 'flex', flexDirection: 'column' }}>
|
||||
<Textarea
|
||||
readOnly
|
||||
ref={codeEditorRef}
|
||||
|
@ -116,7 +116,10 @@ const Document = ({ content, title, initialTab = 'edit', skeleton, id }: Props)
|
|||
</div>
|
||||
</Tabs.Item>
|
||||
<Tabs.Item label="Preview" value="preview">
|
||||
<div style={{ marginTop: 'var(--gap-half)', }}>
|
||||
|
||||
<HtmlPreview height={height} fileId={id} />
|
||||
</div>
|
||||
</Tabs.Item>
|
||||
</Tabs>
|
||||
|
||||
|
|
|
@ -2,16 +2,14 @@ import { marked, Lexer } from 'marked'
|
|||
import Highlight, { defaultProps, Language, } from 'prism-react-renderer'
|
||||
import { renderToStaticMarkup } from 'react-dom/server'
|
||||
|
||||
|
||||
|
||||
// image sizes. DDoS Safe?
|
||||
const imageSizeLink = /^!?\[((?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?)\]\(\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f()\\]*\)|[^\s\x00-\x1f()\\])*?(?:\s+=(?:[\w%]+)?x(?:[\w%]+)?)?)(?:\s+("(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)))?\s*\)/;
|
||||
//@ts-ignore
|
||||
Lexer.rules.inline.normal.link = imageSizeLink;
|
||||
//@ts-ignore
|
||||
Lexer.rules.inline.gfm.link = imageSizeLink;
|
||||
//@ts-ignore
|
||||
Lexer.rules.inline.breaks.link = imageSizeLink;
|
||||
// // image sizes. DDoS Safe?
|
||||
// const imageSizeLink = /^!?\[((?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?)\]\(\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f()\\]*\)|[^\s\x00-\x1f()\\])*?(?:\s+=(?:[\w%]+)?x(?:[\w%]+)?)?)(?:\s+("(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)))?\s*\)/;
|
||||
// //@ts-ignore
|
||||
// Lexer.rules.inline.normal.link = imageSizeLink;
|
||||
// //@ts-ignore
|
||||
// Lexer.rules.inline.gfm.link = imageSizeLink;
|
||||
// //@ts-ignore
|
||||
// Lexer.rules.inline.breaks.link = imageSizeLink;
|
||||
|
||||
//@ts-ignore
|
||||
delete defaultProps.theme
|
||||
|
|
|
@ -2,6 +2,15 @@ import { marked } from 'marked'
|
|||
import Highlight, { defaultProps, Language, } from 'prism-react-renderer'
|
||||
import { renderToStaticMarkup } from 'react-dom/server'
|
||||
|
||||
// // image sizes. DDoS Safe?
|
||||
// const imageSizeLink = /^!?\[((?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?)\]\(\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f()\\]*\)|[^\s\x00-\x1f()\\])*?(?:\s+=(?:[\w%]+)?x(?:[\w%]+)?)?)(?:\s+("(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)))?\s*\)/;
|
||||
// //@ts-ignore
|
||||
// Lexer.rules.inline.normal.link = imageSizeLink;
|
||||
// //@ts-ignore
|
||||
// Lexer.rules.inline.gfm.link = imageSizeLink;
|
||||
// //@ts-ignore
|
||||
// Lexer.rules.inline.breaks.link = imageSizeLink;
|
||||
|
||||
//@ts-ignore
|
||||
delete defaultProps.theme
|
||||
// import linkStyles from '../components/link/link.module.css'
|
||||
|
@ -12,8 +21,6 @@ renderer.heading = (text, level, _, slugger) => {
|
|||
const id = slugger.slug(text)
|
||||
const Component = `h${level}`
|
||||
|
||||
|
||||
|
||||
return renderToStaticMarkup(
|
||||
//@ts-ignore
|
||||
<Component>
|
||||
|
|
Loading…
Reference in a new issue