Fix @mention 500 error and can't close market bug (#1021)
* Fix @mention 500 error. Refactor text concat exts * lint
This commit is contained in:
parent
c46c384d1d
commit
8bb9885aee
|
@ -52,7 +52,7 @@ export function parseMentions(data: JSONContent): string[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
// can't just do [StarterKit, Image...] because it doesn't work with cjs imports
|
// can't just do [StarterKit, Image...] because it doesn't work with cjs imports
|
||||||
export const exhibitExts = [
|
const stringParseExts = [
|
||||||
Blockquote,
|
Blockquote,
|
||||||
Bold,
|
Bold,
|
||||||
BulletList,
|
BulletList,
|
||||||
|
@ -72,7 +72,8 @@ export const exhibitExts = [
|
||||||
|
|
||||||
Image,
|
Image,
|
||||||
Link,
|
Link,
|
||||||
Mention.extend({ name: 'contract-mention' }),
|
Mention, // user @mention
|
||||||
|
Mention.extend({ name: 'contract-mention' }), // market %mention
|
||||||
Iframe,
|
Iframe,
|
||||||
TiptapTweet,
|
TiptapTweet,
|
||||||
TiptapSpoiler,
|
TiptapSpoiler,
|
||||||
|
@ -96,7 +97,7 @@ export function richTextToString(text?: JSONContent) {
|
||||||
current.type = 'text'
|
current.type = 'text'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return generateText(newText, exhibitExts)
|
return generateText(newText, stringParseExts)
|
||||||
}
|
}
|
||||||
|
|
||||||
const dfs = (data: JSONContent, f: (current: JSONContent) => any) => {
|
const dfs = (data: JSONContent, f: (current: JSONContent) => any) => {
|
||||||
|
|
|
@ -2,13 +2,16 @@ import clsx from 'clsx'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Contract, MAX_DESCRIPTION_LENGTH } from 'common/contract'
|
import { Contract, MAX_DESCRIPTION_LENGTH } from 'common/contract'
|
||||||
import { exhibitExts } from 'common/util/parse'
|
|
||||||
import { useAdmin } from 'web/hooks/use-admin'
|
import { useAdmin } from 'web/hooks/use-admin'
|
||||||
import { useUser } from 'web/hooks/use-user'
|
import { useUser } from 'web/hooks/use-user'
|
||||||
import { updateContract } from 'web/lib/firebase/contracts'
|
import { updateContract } from 'web/lib/firebase/contracts'
|
||||||
import { Row } from '../layout/row'
|
import { Row } from '../layout/row'
|
||||||
import { Content } from '../editor'
|
import { Content } from '../editor'
|
||||||
import { TextEditor, useTextEditor } from 'web/components/editor'
|
import {
|
||||||
|
TextEditor,
|
||||||
|
editorExtensions,
|
||||||
|
useTextEditor,
|
||||||
|
} from 'web/components/editor'
|
||||||
import { Button } from '../button'
|
import { Button } from '../button'
|
||||||
import { Spacer } from '../layout/spacer'
|
import { Spacer } from '../layout/spacer'
|
||||||
import { Editor, Content as ContentType } from '@tiptap/react'
|
import { Editor, Content as ContentType } from '@tiptap/react'
|
||||||
|
@ -118,7 +121,10 @@ function EditQuestion(props: {
|
||||||
}
|
}
|
||||||
|
|
||||||
function joinContent(oldContent: ContentType, newContent: string) {
|
function joinContent(oldContent: ContentType, newContent: string) {
|
||||||
const editor = new Editor({ content: oldContent, extensions: exhibitExts })
|
const editor = new Editor({
|
||||||
|
content: oldContent,
|
||||||
|
extensions: editorExtensions(),
|
||||||
|
})
|
||||||
editor.commands.focus('end')
|
editor.commands.focus('end')
|
||||||
insertContent(editor, newContent)
|
insertContent(editor, newContent)
|
||||||
return editor.getJSON()
|
return editor.getJSON()
|
||||||
|
|
|
@ -8,7 +8,6 @@ import clsx from 'clsx'
|
||||||
import { Editor } from '@tiptap/react'
|
import { Editor } from '@tiptap/react'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
import { Row } from '../layout/row'
|
import { Row } from '../layout/row'
|
||||||
import { formatMoney } from 'common/util/format'
|
import { formatMoney } from 'common/util/format'
|
||||||
import { Contract, updateContract } from 'web/lib/firebase/contracts'
|
import { Contract, updateContract } from 'web/lib/firebase/contracts'
|
||||||
|
@ -20,7 +19,6 @@ import NewContractBadge from '../new-contract-badge'
|
||||||
import { MiniUserFollowButton } from '../follow-button'
|
import { MiniUserFollowButton } from '../follow-button'
|
||||||
import { DAY_MS } from 'common/util/time'
|
import { DAY_MS } from 'common/util/time'
|
||||||
import { useUser, useUserById } from 'web/hooks/use-user'
|
import { useUser, useUserById } from 'web/hooks/use-user'
|
||||||
import { exhibitExts } from 'common/util/parse'
|
|
||||||
import { Button } from 'web/components/button'
|
import { Button } from 'web/components/button'
|
||||||
import { Modal } from 'web/components/layout/modal'
|
import { Modal } from 'web/components/layout/modal'
|
||||||
import { Col } from 'web/components/layout/col'
|
import { Col } from 'web/components/layout/col'
|
||||||
|
@ -41,6 +39,7 @@ import {
|
||||||
BountiedContractSmallBadge,
|
BountiedContractSmallBadge,
|
||||||
} from 'web/components/contract/bountied-contract-badge'
|
} from 'web/components/contract/bountied-contract-badge'
|
||||||
import { Input } from '../input'
|
import { Input } from '../input'
|
||||||
|
import { editorExtensions } from '../editor'
|
||||||
|
|
||||||
export type ShowTime = 'resolve-date' | 'close-date'
|
export type ShowTime = 'resolve-date' | 'close-date'
|
||||||
|
|
||||||
|
@ -421,7 +420,7 @@ function EditableCloseDate(props: {
|
||||||
const content = contract.description
|
const content = contract.description
|
||||||
const formattedCloseDate = dayjs(newCloseTime).format('YYYY-MM-DD h:mm a')
|
const formattedCloseDate = dayjs(newCloseTime).format('YYYY-MM-DD h:mm a')
|
||||||
|
|
||||||
const editor = new Editor({ content, extensions: exhibitExts })
|
const editor = new Editor({ content, extensions: editorExtensions() })
|
||||||
editor.commands.focus('end')
|
editor.commands.focus('end')
|
||||||
insertContent(
|
insertContent(
|
||||||
editor,
|
editor,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
Content,
|
Content,
|
||||||
Editor,
|
Editor,
|
||||||
mergeAttributes,
|
mergeAttributes,
|
||||||
|
Extensions,
|
||||||
} from '@tiptap/react'
|
} from '@tiptap/react'
|
||||||
import StarterKit from '@tiptap/starter-kit'
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
import { Image } from '@tiptap/extension-image'
|
import { Image } from '@tiptap/extension-image'
|
||||||
|
@ -19,9 +20,7 @@ import { uploadImage } from 'web/lib/firebase/storage'
|
||||||
import { useMutation } from 'react-query'
|
import { useMutation } from 'react-query'
|
||||||
import { FileUploadButton } from './file-upload-button'
|
import { FileUploadButton } from './file-upload-button'
|
||||||
import { linkClass } from './site-link'
|
import { linkClass } from './site-link'
|
||||||
import { mentionSuggestion } from './editor/mention-suggestion'
|
|
||||||
import { DisplayMention } from './editor/mention'
|
import { DisplayMention } from './editor/mention'
|
||||||
import { contractMentionSuggestion } from './editor/contract-mention-suggestion'
|
|
||||||
import { DisplayContractMention } from './editor/contract-mention'
|
import { DisplayContractMention } from './editor/contract-mention'
|
||||||
import Iframe from 'common/util/tiptap-iframe'
|
import Iframe from 'common/util/tiptap-iframe'
|
||||||
import TiptapTweet from './editor/tiptap-tweet'
|
import TiptapTweet from './editor/tiptap-tweet'
|
||||||
|
@ -64,6 +63,22 @@ const DisplayLink = Link.extend({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const editorExtensions = (simple = false): Extensions => [
|
||||||
|
StarterKit.configure({
|
||||||
|
heading: simple ? false : { levels: [1, 2, 3] },
|
||||||
|
horizontalRule: simple ? false : {},
|
||||||
|
}),
|
||||||
|
simple ? DisplayImage : Image,
|
||||||
|
DisplayLink,
|
||||||
|
DisplayMention,
|
||||||
|
DisplayContractMention,
|
||||||
|
Iframe,
|
||||||
|
TiptapTweet,
|
||||||
|
TiptapSpoiler.configure({
|
||||||
|
spoilerOpenClass: 'rounded-sm bg-greyscale-2',
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
const proseClass = clsx(
|
const proseClass = clsx(
|
||||||
'prose prose-p:my-0 prose-ul:my-0 prose-ol:my-0 prose-li:my-0 prose-blockquote:not-italic max-w-none prose-quoteless leading-relaxed',
|
'prose prose-p:my-0 prose-ul:my-0 prose-ol:my-0 prose-li:my-0 prose-blockquote:not-italic max-w-none prose-quoteless leading-relaxed',
|
||||||
'font-light prose-a:font-light prose-blockquote:font-light'
|
'font-light prose-a:font-light prose-blockquote:font-light'
|
||||||
|
@ -89,29 +104,13 @@ export function useTextEditor(props: {
|
||||||
const editor = useEditor({
|
const editor = useEditor({
|
||||||
editorProps: { attributes: { class: editorClass } },
|
editorProps: { attributes: { class: editorClass } },
|
||||||
extensions: [
|
extensions: [
|
||||||
StarterKit.configure({
|
...editorExtensions(simple),
|
||||||
heading: simple ? false : { levels: [1, 2, 3] },
|
|
||||||
horizontalRule: simple ? false : {},
|
|
||||||
}),
|
|
||||||
Placeholder.configure({
|
Placeholder.configure({
|
||||||
placeholder,
|
placeholder,
|
||||||
emptyEditorClass:
|
emptyEditorClass:
|
||||||
'before:content-[attr(data-placeholder)] before:text-slate-500 before:float-left before:h-0 cursor-text',
|
'before:content-[attr(data-placeholder)] before:text-slate-500 before:float-left before:h-0 cursor-text',
|
||||||
}),
|
}),
|
||||||
CharacterCount.configure({ limit: max }),
|
CharacterCount.configure({ limit: max }),
|
||||||
simple ? DisplayImage : Image,
|
|
||||||
DisplayLink,
|
|
||||||
DisplayMention.configure({
|
|
||||||
suggestion: mentionSuggestion,
|
|
||||||
}),
|
|
||||||
DisplayContractMention.configure({
|
|
||||||
suggestion: contractMentionSuggestion,
|
|
||||||
}),
|
|
||||||
Iframe,
|
|
||||||
TiptapTweet,
|
|
||||||
TiptapSpoiler.configure({
|
|
||||||
spoilerOpenClass: 'rounded-sm bg-greyscale-2',
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
content: defaultValue,
|
content: defaultValue,
|
||||||
})
|
})
|
||||||
|
@ -334,10 +333,7 @@ export function RichContent(props: {
|
||||||
smallImage ? DisplayImage : Image,
|
smallImage ? DisplayImage : Image,
|
||||||
DisplayLink.configure({ openOnClick: false }), // stop link opening twice (browser still opens)
|
DisplayLink.configure({ openOnClick: false }), // stop link opening twice (browser still opens)
|
||||||
DisplayMention,
|
DisplayMention,
|
||||||
DisplayContractMention.configure({
|
DisplayContractMention,
|
||||||
// Needed to set a different PluginKey for Prosemirror
|
|
||||||
suggestion: contractMentionSuggestion,
|
|
||||||
}),
|
|
||||||
Iframe,
|
Iframe,
|
||||||
TiptapTweet,
|
TiptapTweet,
|
||||||
TiptapSpoiler.configure({
|
TiptapSpoiler.configure({
|
||||||
|
|
|
@ -8,6 +8,7 @@ import clsx from 'clsx'
|
||||||
import { useContract } from 'web/hooks/use-contract'
|
import { useContract } from 'web/hooks/use-contract'
|
||||||
import { ContractMention } from 'web/components/contract/contract-mention'
|
import { ContractMention } from 'web/components/contract/contract-mention'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { contractMentionSuggestion } from './contract-mention-suggestion'
|
||||||
|
|
||||||
const name = 'contract-mention-component'
|
const name = 'contract-mention-component'
|
||||||
|
|
||||||
|
@ -42,4 +43,4 @@ export const DisplayContractMention = Mention.extend({
|
||||||
parseHTML: () => [{ tag: name }],
|
parseHTML: () => [{ tag: name }],
|
||||||
renderHTML: ({ HTMLAttributes }) => [name, mergeAttributes(HTMLAttributes)],
|
renderHTML: ({ HTMLAttributes }) => [name, mergeAttributes(HTMLAttributes)],
|
||||||
addNodeView: () => ReactNodeViewRenderer(ContractMentionComponent),
|
addNodeView: () => ReactNodeViewRenderer(ContractMentionComponent),
|
||||||
})
|
}).configure({ suggestion: contractMentionSuggestion })
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
} from '@tiptap/react'
|
} from '@tiptap/react'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { Linkify } from '../linkify'
|
import { Linkify } from '../linkify'
|
||||||
|
import { mentionSuggestion } from './mention-suggestion'
|
||||||
|
|
||||||
const name = 'mention-component'
|
const name = 'mention-component'
|
||||||
|
|
||||||
|
@ -27,4 +28,4 @@ export const DisplayMention = Mention.extend({
|
||||||
renderHTML: ({ HTMLAttributes }) => [name, mergeAttributes(HTMLAttributes)],
|
renderHTML: ({ HTMLAttributes }) => [name, mergeAttributes(HTMLAttributes)],
|
||||||
addNodeView: () =>
|
addNodeView: () =>
|
||||||
ReactNodeViewRenderer(MentionComponent, { className: 'inline-block' }),
|
ReactNodeViewRenderer(MentionComponent, { className: 'inline-block' }),
|
||||||
})
|
}).configure({ suggestion: mentionSuggestion })
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
|
"lint-fix": "next lint --fix",
|
||||||
"format": "npx prettier --write .",
|
"format": "npx prettier --write .",
|
||||||
"verify": "(cd .. && yarn verify)",
|
"verify": "(cd .. && yarn verify)",
|
||||||
"verify:dir": "npx prettier --check .; yarn lint --max-warnings 0; tsc --pretty --project tsconfig.json --noEmit"
|
"verify:dir": "npx prettier --check .; yarn lint --max-warnings 0; tsc --pretty --project tsconfig.json --noEmit"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user