Rich content (#620)
* Add TipTap editor and renderer components * Change market description editor to rich text * Type description as JSON, fix string-based logic - Delete make-predictions.tsx - Delete feed logic that showed descriptions * wip Fix API validation * fix type error * fix extension import (backend) In firebase, typescript compiles imports into common js imports like `const StarterKit = require("@tiptap/starter-kit")` Even though StarterKit is exported from the cjs file, it gets imported as undefined. But it magically works if we import * If you're reading this in the future, consider replacing StarterKit with the entire list of extensions. * Stop load on fail create market, improve warning * Refactor editor as hook / fix infinite submit bug Move state of editor back up to parent We have to do this later anyways to allow parent to edit * Add images - display, paste + uploading * add uploading state of image * Fix placeholder, misc styling min height, quote * Fix appending to description * code review fixes: rename, refactor, chop carets * Add hint & upload button on new lines - bump to Tailwind 3.1 for arbitrary variants * clean up, run prettier * rename FileButton to FileUploadButton * add image extension as functions dependency
This commit is contained in:
parent
83d8f18bd7
commit
9a11f55762
|
@ -1,5 +1,6 @@
|
|||
import { Answer } from './answer'
|
||||
import { Fees } from './fees'
|
||||
import { JSONContent } from '@tiptap/core'
|
||||
|
||||
export type AnyMechanism = DPM | CPMM
|
||||
export type AnyOutcomeType = Binary | PseudoNumeric | FreeResponse | Numeric
|
||||
|
@ -20,7 +21,7 @@ export type Contract<T extends AnyContractType = AnyContractType> = {
|
|||
creatorAvatarUrl?: string
|
||||
|
||||
question: string
|
||||
description: string // More info about what the contract is about
|
||||
description: string | JSONContent // More info about what the contract is about
|
||||
tags: string[]
|
||||
lowercaseTags: string[]
|
||||
visibility: 'public' | 'unlisted'
|
||||
|
|
|
@ -10,8 +10,9 @@ import {
|
|||
PseudoNumeric,
|
||||
} from './contract'
|
||||
import { User } from './user'
|
||||
import { parseTags } from './util/parse'
|
||||
import { parseTags, richTextToString } from './util/parse'
|
||||
import { removeUndefinedProps } from './util/object'
|
||||
import { JSONContent } from '@tiptap/core'
|
||||
|
||||
export function getNewContract(
|
||||
id: string,
|
||||
|
@ -19,7 +20,7 @@ export function getNewContract(
|
|||
creator: User,
|
||||
question: string,
|
||||
outcomeType: outcomeType,
|
||||
description: string,
|
||||
description: JSONContent,
|
||||
initialProb: number,
|
||||
ante: number,
|
||||
closeTime: number,
|
||||
|
@ -32,7 +33,11 @@ export function getNewContract(
|
|||
isLogScale: boolean
|
||||
) {
|
||||
const tags = parseTags(
|
||||
`${question} ${description} ${extraTags.map((tag) => `#${tag}`).join(' ')}`
|
||||
[
|
||||
question,
|
||||
richTextToString(description),
|
||||
...extraTags.map((tag) => `#${tag}`),
|
||||
].join(' ')
|
||||
)
|
||||
const lowercaseTags = tags.map((tag) => tag.toLowerCase())
|
||||
|
||||
|
@ -56,7 +61,7 @@ export function getNewContract(
|
|||
creatorAvatarUrl: creator.avatarUrl,
|
||||
|
||||
question: question.trim(),
|
||||
description: description.trim(),
|
||||
description,
|
||||
tags,
|
||||
lowercaseTags,
|
||||
visibility: 'public',
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
},
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"@tiptap/extension-image": "2.0.0-beta.30",
|
||||
"@tiptap/starter-kit": "2.0.0-beta.190",
|
||||
"lodash": "4.17.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -1,4 +1,24 @@
|
|||
import { MAX_TAG_LENGTH } from '../contract'
|
||||
import { generateText, JSONContent } from '@tiptap/core'
|
||||
// Tiptap starter extensions
|
||||
import { Blockquote } from '@tiptap/extension-blockquote'
|
||||
import { Bold } from '@tiptap/extension-bold'
|
||||
import { BulletList } from '@tiptap/extension-bullet-list'
|
||||
import { Code } from '@tiptap/extension-code'
|
||||
import { CodeBlock } from '@tiptap/extension-code-block'
|
||||
import { Document } from '@tiptap/extension-document'
|
||||
import { HardBreak } from '@tiptap/extension-hard-break'
|
||||
import { Heading } from '@tiptap/extension-heading'
|
||||
import { History } from '@tiptap/extension-history'
|
||||
import { HorizontalRule } from '@tiptap/extension-horizontal-rule'
|
||||
import { Italic } from '@tiptap/extension-italic'
|
||||
import { ListItem } from '@tiptap/extension-list-item'
|
||||
import { OrderedList } from '@tiptap/extension-ordered-list'
|
||||
import { Paragraph } from '@tiptap/extension-paragraph'
|
||||
import { Strike } from '@tiptap/extension-strike'
|
||||
import { Text } from '@tiptap/extension-text'
|
||||
// other tiptap extensions
|
||||
import { Image } from '@tiptap/extension-image'
|
||||
|
||||
export function parseTags(text: string) {
|
||||
const regex = /(?:^|\s)(?:[#][a-z0-9_]+)/gi
|
||||
|
@ -27,3 +47,30 @@ export function parseWordsAsTags(text: string) {
|
|||
.join(' ')
|
||||
return parseTags(taggedText)
|
||||
}
|
||||
|
||||
// can't just do [StarterKit, Image...] because it doesn't work with cjs imports
|
||||
export const exhibitExts = [
|
||||
Blockquote,
|
||||
Bold,
|
||||
BulletList,
|
||||
Code,
|
||||
CodeBlock,
|
||||
Document,
|
||||
HardBreak,
|
||||
Heading,
|
||||
History,
|
||||
HorizontalRule,
|
||||
Italic,
|
||||
ListItem,
|
||||
OrderedList,
|
||||
Paragraph,
|
||||
Strike,
|
||||
Text,
|
||||
|
||||
Image,
|
||||
]
|
||||
// export const exhibitExts = [StarterKit as unknown as Extension, Image]
|
||||
|
||||
export function richTextToString(text?: JSONContent) {
|
||||
return !text ? '' : generateText(text, exhibitExts)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
"dependencies": {
|
||||
"@amplitude/node": "1.10.0",
|
||||
"@google-cloud/functions-framework": "3.1.2",
|
||||
"@tiptap/core": "2.0.0-beta.181",
|
||||
"@tiptap/extension-image": "2.0.0-beta.30",
|
||||
"@tiptap/starter-kit": "2.0.0-beta.190",
|
||||
"firebase-admin": "10.0.0",
|
||||
"firebase-functions": "3.21.2",
|
||||
"lodash": "4.17.21",
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
CPMMBinaryContract,
|
||||
Contract,
|
||||
FreeResponseContract,
|
||||
MAX_DESCRIPTION_LENGTH,
|
||||
MAX_QUESTION_LENGTH,
|
||||
MAX_TAG_LENGTH,
|
||||
NumericContract,
|
||||
|
@ -29,10 +28,34 @@ import { NUMERIC_BUCKET_COUNT } from '../../common/numeric-constants'
|
|||
import { User } from '../../common/user'
|
||||
import { Group, MAX_ID_LENGTH } from '../../common/group'
|
||||
import { getPseudoProbability } from '../../common/pseudo-numeric'
|
||||
import { JSONContent } from '@tiptap/core'
|
||||
|
||||
const descScehma: z.ZodType<JSONContent> = z.lazy(() =>
|
||||
z.intersection(
|
||||
z.record(z.any()),
|
||||
z.object({
|
||||
type: z.string().optional(),
|
||||
attrs: z.record(z.any()).optional(),
|
||||
content: z.array(descScehma).optional(),
|
||||
marks: z
|
||||
.array(
|
||||
z.intersection(
|
||||
z.record(z.any()),
|
||||
z.object({
|
||||
type: z.string(),
|
||||
attrs: z.record(z.any()).optional(),
|
||||
})
|
||||
)
|
||||
)
|
||||
.optional(),
|
||||
text: z.string().optional(),
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
const bodySchema = z.object({
|
||||
question: z.string().min(1).max(MAX_QUESTION_LENGTH),
|
||||
description: z.string().max(MAX_DESCRIPTION_LENGTH),
|
||||
description: descScehma.optional(),
|
||||
tags: z.array(z.string().min(1).max(MAX_TAG_LENGTH)).optional(),
|
||||
closeTime: zTimestamp().refine(
|
||||
(date) => date.getTime() > new Date().getTime(),
|
||||
|
@ -131,7 +154,7 @@ export const createmarket = newEndpoint({}, async (req, auth) => {
|
|||
user,
|
||||
question,
|
||||
outcomeType,
|
||||
description,
|
||||
description ?? {},
|
||||
initialProb ?? 0,
|
||||
ante,
|
||||
closeTime.getTime(),
|
||||
|
|
|
@ -2,6 +2,8 @@ import * as functions from 'firebase-functions'
|
|||
import { getUser } from './utils'
|
||||
import { createNotification } from './create-notification'
|
||||
import { Contract } from '../../common/contract'
|
||||
import { richTextToString } from '../../common/util/parse'
|
||||
import { JSONContent } from '@tiptap/core'
|
||||
|
||||
export const onCreateContract = functions.firestore
|
||||
.document('contracts/{contractId}')
|
||||
|
@ -18,7 +20,7 @@ export const onCreateContract = functions.firestore
|
|||
'created',
|
||||
contractCreator,
|
||||
eventId,
|
||||
contract.description,
|
||||
richTextToString(contract.description as JSONContent),
|
||||
contract
|
||||
)
|
||||
})
|
||||
|
|
|
@ -5,12 +5,13 @@ import Textarea from 'react-expanding-textarea'
|
|||
import { CATEGORY_LIST } from '../../../common/categories'
|
||||
|
||||
import { Contract } from 'common/contract'
|
||||
import { parseTags } from 'common/util/parse'
|
||||
import { parseTags, exhibitExts } from 'common/util/parse'
|
||||
import { useAdmin } from 'web/hooks/use-admin'
|
||||
import { updateContract } from 'web/lib/firebase/contracts'
|
||||
import { Row } from '../layout/row'
|
||||
import { Linkify } from '../linkify'
|
||||
import { TagsList } from '../tags-list'
|
||||
import { Content } from '../editor'
|
||||
import { Editor } from '@tiptap/react'
|
||||
|
||||
export function ContractDescription(props: {
|
||||
contract: Contract
|
||||
|
@ -21,22 +22,31 @@ export function ContractDescription(props: {
|
|||
const descriptionTimestamp = () => `${dayjs().format('MMM D, h:mma')}: `
|
||||
const isAdmin = useAdmin()
|
||||
|
||||
const desc = contract.description ?? ''
|
||||
|
||||
// Append the new description (after a newline)
|
||||
async function saveDescription(newText: string) {
|
||||
const newDescription = `${contract.description}\n\n${newText}`.trim()
|
||||
const editor = new Editor({ content: desc, extensions: exhibitExts })
|
||||
editor
|
||||
.chain()
|
||||
.focus('end')
|
||||
.insertContent('<br /><br />')
|
||||
.insertContent(newText.trim())
|
||||
.run()
|
||||
|
||||
const tags = parseTags(
|
||||
`${newDescription} ${contract.tags.map((tag) => `#${tag}`).join(' ')}`
|
||||
`${editor.getText()} ${contract.tags.map((tag) => `#${tag}`).join(' ')}`
|
||||
)
|
||||
const lowercaseTags = tags.map((tag) => tag.toLowerCase())
|
||||
|
||||
await updateContract(contract.id, {
|
||||
description: newDescription,
|
||||
description: editor.getJSON(),
|
||||
tags,
|
||||
lowercaseTags,
|
||||
})
|
||||
}
|
||||
|
||||
if (!isCreator && !contract.description.trim()) return null
|
||||
if (!isCreator) return null
|
||||
|
||||
const { tags } = contract
|
||||
const categories = tags.filter((tag) =>
|
||||
|
@ -50,7 +60,7 @@ export function ContractDescription(props: {
|
|||
className
|
||||
)}
|
||||
>
|
||||
<Linkify text={contract.description} />
|
||||
<Content content={desc} />
|
||||
|
||||
{categories.length > 0 && (
|
||||
<div className="mt-4">
|
||||
|
|
|
@ -31,6 +31,8 @@ import { DAY_MS } from 'common/util/time'
|
|||
import { useGroupsWithContract } from 'web/hooks/use-group'
|
||||
import { ShareIconButton } from 'web/components/share-icon-button'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { Editor } from '@tiptap/react'
|
||||
import { exhibitExts } from 'common/util/parse'
|
||||
|
||||
export type ShowTime = 'resolve-date' | 'close-date'
|
||||
|
||||
|
@ -268,13 +270,20 @@ function EditableCloseDate(props: {
|
|||
const newCloseTime = dayjs(closeDate).valueOf()
|
||||
if (newCloseTime === closeTime) setIsEditingCloseTime(false)
|
||||
else if (newCloseTime > Date.now()) {
|
||||
const { description } = contract
|
||||
const content = contract.description
|
||||
const formattedCloseDate = dayjs(newCloseTime).format('YYYY-MM-DD h:mm a')
|
||||
const newDescription = `${description}\n\nClose date updated to ${formattedCloseDate}`
|
||||
|
||||
const editor = new Editor({ content, extensions: exhibitExts })
|
||||
editor
|
||||
.chain()
|
||||
.focus('end')
|
||||
.insertContent('<br /><br />')
|
||||
.insertContent(`Close date updated to ${formattedCloseDate}`)
|
||||
.run()
|
||||
|
||||
updateContract(contract.id, {
|
||||
closeTime: newCloseTime,
|
||||
description: newDescription,
|
||||
description: editor.getJSON(),
|
||||
})
|
||||
|
||||
setIsEditingCloseTime(false)
|
||||
|
|
152
web/components/editor.tsx
Normal file
152
web/components/editor.tsx
Normal file
|
@ -0,0 +1,152 @@
|
|||
import CharacterCount from '@tiptap/extension-character-count'
|
||||
import Placeholder from '@tiptap/extension-placeholder'
|
||||
import {
|
||||
useEditor,
|
||||
EditorContent,
|
||||
FloatingMenu,
|
||||
JSONContent,
|
||||
Content,
|
||||
Editor,
|
||||
} from '@tiptap/react'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import { Image } from '@tiptap/extension-image'
|
||||
import clsx from 'clsx'
|
||||
import { useEffect } from 'react'
|
||||
import { Linkify } from './linkify'
|
||||
import { uploadImage } from 'web/lib/firebase/storage'
|
||||
import { useMutation } from 'react-query'
|
||||
import { exhibitExts } from 'common/util/parse'
|
||||
import { FileUploadButton } from './file-upload-button'
|
||||
|
||||
const proseClass =
|
||||
'prose prose-sm prose-p:my-0 prose-li:my-0 prose-blockquote:not-italic max-w-none'
|
||||
|
||||
export function useTextEditor(props: {
|
||||
placeholder?: string
|
||||
max?: number
|
||||
defaultValue?: Content
|
||||
disabled?: boolean
|
||||
}) {
|
||||
const { placeholder, max, defaultValue = '', disabled } = props
|
||||
|
||||
const editorClass = clsx(
|
||||
proseClass,
|
||||
'box-content min-h-[6em] textarea textarea-bordered'
|
||||
)
|
||||
|
||||
const editor = useEditor({
|
||||
editorProps: { attributes: { class: editorClass } },
|
||||
extensions: [
|
||||
StarterKit.configure({
|
||||
heading: { levels: [1, 2, 3] },
|
||||
}),
|
||||
Placeholder.configure({
|
||||
placeholder,
|
||||
emptyEditorClass:
|
||||
'before:content-[attr(data-placeholder)] before:text-slate-500 before:float-left before:h-0',
|
||||
}),
|
||||
CharacterCount.configure({ limit: max }),
|
||||
Image,
|
||||
],
|
||||
content: defaultValue,
|
||||
})
|
||||
|
||||
const upload = useUploadMutation(editor)
|
||||
|
||||
editor?.setOptions({
|
||||
editorProps: {
|
||||
handlePaste(view, event) {
|
||||
const imageFiles = Array.from(event.clipboardData?.files ?? []).filter(
|
||||
(file) => file.type.startsWith('image')
|
||||
)
|
||||
|
||||
if (!imageFiles.length) {
|
||||
return // if no files pasted, use default paste handler
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
upload.mutate(imageFiles)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
editor?.setEditable(!disabled)
|
||||
}, [editor, disabled])
|
||||
|
||||
return { editor, upload }
|
||||
}
|
||||
|
||||
export function TextEditor(props: {
|
||||
editor: Editor | null
|
||||
upload: ReturnType<typeof useUploadMutation>
|
||||
}) {
|
||||
const { editor, upload } = props
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* hide placeholder when focused */}
|
||||
<div className="w-full [&:focus-within_p.is-empty]:before:content-none">
|
||||
{editor && (
|
||||
<FloatingMenu
|
||||
editor={editor}
|
||||
className="w-full text-sm text-slate-300"
|
||||
>
|
||||
Type <em>*anything*</em> or even paste or{' '}
|
||||
<FileUploadButton
|
||||
className="link text-blue-300"
|
||||
onFiles={upload.mutate}
|
||||
>
|
||||
upload an image
|
||||
</FileUploadButton>
|
||||
</FloatingMenu>
|
||||
)}
|
||||
<EditorContent editor={editor} />
|
||||
</div>
|
||||
{upload.isLoading && <span className="text-xs">Uploading image...</span>}
|
||||
{upload.isError && (
|
||||
<span className="text-error text-xs">Error uploading image :(</span>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const useUploadMutation = (editor: Editor | null) =>
|
||||
useMutation(
|
||||
(files: File[]) =>
|
||||
Promise.all(files.map((file) => uploadImage('default', file))),
|
||||
{
|
||||
onSuccess(urls) {
|
||||
if (!editor) return
|
||||
let trans = editor.view.state.tr
|
||||
urls.forEach((src: any) => {
|
||||
const node = editor.view.state.schema.nodes.image.create({ src })
|
||||
trans = trans.insert(editor.view.state.selection.to, node)
|
||||
})
|
||||
editor.view.dispatch(trans)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
function RichContent(props: { content: JSONContent }) {
|
||||
const { content } = props
|
||||
const editor = useEditor({
|
||||
editorProps: { attributes: { class: proseClass } },
|
||||
extensions: exhibitExts,
|
||||
content,
|
||||
editable: false,
|
||||
})
|
||||
useEffect(() => void editor?.commands?.setContent(content), [editor, content])
|
||||
|
||||
return <EditorContent editor={editor} />
|
||||
}
|
||||
|
||||
// backwards compatibility: we used to store content as strings
|
||||
export function Content(props: { content: JSONContent | string }) {
|
||||
const { content } = props
|
||||
return typeof content === 'string' ? (
|
||||
<Linkify text={content} />
|
||||
) : (
|
||||
<RichContent content={content} />
|
||||
)
|
||||
}
|
|
@ -37,7 +37,6 @@ export type DescriptionItem = BaseActivityItem & {
|
|||
|
||||
export type QuestionItem = BaseActivityItem & {
|
||||
type: 'question'
|
||||
showDescription: boolean
|
||||
contractPath?: string
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ import { FeedAnswerCommentGroup } from 'web/components/feed/feed-answer-comment-
|
|||
import {
|
||||
FeedCommentThread,
|
||||
CommentInput,
|
||||
TruncatedComment,
|
||||
} from 'web/components/feed/feed-comments'
|
||||
import { FeedBet } from 'web/components/feed/feed-bets'
|
||||
import { CPMMBinaryContract, NumericContract } from 'common/contract'
|
||||
|
@ -104,10 +103,9 @@ export function FeedItem(props: { item: ActivityItem }) {
|
|||
|
||||
export function FeedQuestion(props: {
|
||||
contract: Contract
|
||||
showDescription: boolean
|
||||
contractPath?: string
|
||||
}) {
|
||||
const { contract, showDescription } = props
|
||||
const { contract } = props
|
||||
const {
|
||||
creatorName,
|
||||
creatorUsername,
|
||||
|
@ -163,13 +161,6 @@ export function FeedQuestion(props: {
|
|||
/>
|
||||
)}
|
||||
</Col>
|
||||
{showDescription && (
|
||||
<TruncatedComment
|
||||
comment={contract.description}
|
||||
moreHref={contractPath(contract)}
|
||||
shouldTruncate
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
26
web/components/file-upload-button.tsx
Normal file
26
web/components/file-upload-button.tsx
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { useRef } from 'react'
|
||||
|
||||
/** button that opens file upload window */
|
||||
export function FileUploadButton(props: {
|
||||
onFiles: (files: File[]) => void
|
||||
className?: string
|
||||
children?: React.ReactNode
|
||||
}) {
|
||||
const { onFiles, className, children } = props
|
||||
const ref = useRef<HTMLInputElement>(null)
|
||||
return (
|
||||
<>
|
||||
<button className={className} onClick={() => ref.current?.click()}>
|
||||
{children}
|
||||
</button>
|
||||
<input
|
||||
ref={ref}
|
||||
type="file"
|
||||
accept=".gif,.jpg,.jpeg,.png,.webp, image/*"
|
||||
multiple
|
||||
className="hidden"
|
||||
onChange={(e) => onFiles(Array.from(e.target.files || []))}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -7,6 +7,7 @@ import {
|
|||
|
||||
const storage = getStorage()
|
||||
|
||||
// TODO: compress large images
|
||||
export const uploadImage = async (
|
||||
username: string,
|
||||
file: File,
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
"@nivo/core": "0.74.0",
|
||||
"@nivo/line": "0.74.0",
|
||||
"@react-query-firebase/firestore": "0.4.2",
|
||||
"@tiptap/extension-character-count": "2.0.0-beta.31",
|
||||
"@tiptap/extension-image": "2.0.0-beta.30",
|
||||
"@tiptap/extension-placeholder": "2.0.0-beta.53",
|
||||
"@tiptap/react": "2.0.0-beta.114",
|
||||
"@tiptap/starter-kit": "2.0.0-beta.190",
|
||||
"algoliasearch": "4.13.0",
|
||||
"clsx": "1.1.1",
|
||||
"cors": "2.8.5",
|
||||
|
@ -61,7 +66,7 @@
|
|||
"next-sitemap": "^2.5.14",
|
||||
"postcss": "8.3.5",
|
||||
"prettier-plugin-tailwindcss": "^0.1.5",
|
||||
"tailwindcss": "3.0.1",
|
||||
"tailwindcss": "3.1.6",
|
||||
"tsc-files": "1.1.3"
|
||||
},
|
||||
"lint-staged": {
|
||||
|
|
|
@ -45,6 +45,7 @@ import { useTracking } from 'web/hooks/use-tracking'
|
|||
import { CommentTipMap, useTipTxns } from 'web/hooks/use-tip-txns'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useLiquidity } from 'web/hooks/use-liquidity'
|
||||
import { richTextToString } from 'common/util/parse'
|
||||
|
||||
export const getStaticProps = fromPropz(getStaticPropz)
|
||||
export async function getStaticPropz(props: {
|
||||
|
@ -396,15 +397,18 @@ const getOpenGraphProps = (contract: Contract) => {
|
|||
creatorUsername,
|
||||
outcomeType,
|
||||
creatorAvatarUrl,
|
||||
description: desc,
|
||||
} = contract
|
||||
const probPercent =
|
||||
outcomeType === 'BINARY' ? getBinaryProbPercent(contract) : undefined
|
||||
|
||||
const stringDesc = typeof desc === 'string' ? desc : richTextToString(desc)
|
||||
|
||||
const description = resolution
|
||||
? `Resolved ${resolution}. ${contract.description}`
|
||||
? `Resolved ${resolution}. ${stringDesc}`
|
||||
: probPercent
|
||||
? `${probPercent} chance. ${contract.description}`
|
||||
: contract.description
|
||||
? `${probPercent} chance. ${stringDesc}`
|
||||
: stringDesc
|
||||
|
||||
return {
|
||||
question,
|
||||
|
|
|
@ -6,6 +6,7 @@ import { Contract } from 'common/contract'
|
|||
import { User } from 'common/user'
|
||||
import { removeUndefinedProps } from 'common/util/object'
|
||||
import { ENV_CONFIG } from 'common/envs/constants'
|
||||
import { JSONContent } from '@tiptap/core'
|
||||
|
||||
export type LiteMarket = {
|
||||
// Unique identifer for this market
|
||||
|
@ -20,7 +21,7 @@ export type LiteMarket = {
|
|||
// Market attributes. All times are in milliseconds since epoch
|
||||
closeTime?: number
|
||||
question: string
|
||||
description: string
|
||||
description: string | JSONContent
|
||||
tags: string[]
|
||||
url: string
|
||||
outcomeType: string
|
||||
|
|
|
@ -36,7 +36,6 @@ export default function ContractSearchFirestore(props: {
|
|||
let matches = (contracts ?? []).filter(
|
||||
(c) =>
|
||||
check(c.question) ||
|
||||
check(c.description) ||
|
||||
check(c.creatorName) ||
|
||||
check(c.creatorUsername) ||
|
||||
check(c.lowercaseTags.map((tag) => `#${tag}`).join(' ')) ||
|
||||
|
|
|
@ -26,6 +26,7 @@ import { useWarnUnsavedChanges } from 'web/hooks/use-warn-unsaved-changes'
|
|||
import { track } from 'web/lib/service/analytics'
|
||||
import { GroupSelector } from 'web/components/groups/group-selector'
|
||||
import { User } from 'common/user'
|
||||
import { TextEditor, useTextEditor } from 'web/components/editor'
|
||||
|
||||
type NewQuestionParams = {
|
||||
groupId?: string
|
||||
|
@ -101,13 +102,11 @@ export function NewContract(props: {
|
|||
(params?.outcomeType as outcomeType) ?? 'BINARY'
|
||||
)
|
||||
const [initialProb] = useState(50)
|
||||
const [bottomRef, setBottomRef] = useState<HTMLDivElement | null>(null)
|
||||
const [minString, setMinString] = useState(params?.min ?? '')
|
||||
const [maxString, setMaxString] = useState(params?.max ?? '')
|
||||
const [isLogScale, setIsLogScale] = useState<boolean>(!!params?.isLogScale)
|
||||
const [initialValueString, setInitialValueString] = useState(initValue)
|
||||
|
||||
const [description, setDescription] = useState(params?.description ?? '')
|
||||
useEffect(() => {
|
||||
if (groupId && creator)
|
||||
getGroup(groupId).then((group) => {
|
||||
|
@ -152,9 +151,6 @@ export function NewContract(props: {
|
|||
// get days from today until the end of this year:
|
||||
const daysLeftInTheYear = dayjs().endOf('year').diff(dayjs(), 'day')
|
||||
|
||||
const hasUnsavedChanges = !isSubmitting && Boolean(question || description)
|
||||
useWarnUnsavedChanges(hasUnsavedChanges)
|
||||
|
||||
const isValid =
|
||||
(outcomeType === 'BINARY' ? initialProb >= 5 && initialProb <= 95 : true) &&
|
||||
question.length > 0 &&
|
||||
|
@ -175,6 +171,20 @@ export function NewContract(props: {
|
|||
min < initialValue &&
|
||||
initialValue < max))
|
||||
|
||||
const descriptionPlaceholder =
|
||||
outcomeType === 'BINARY'
|
||||
? `e.g. This question resolves to "YES" if they receive the majority of votes...`
|
||||
: `e.g. I will choose the answer according to...`
|
||||
|
||||
const { editor, upload } = useTextEditor({
|
||||
max: MAX_DESCRIPTION_LENGTH,
|
||||
placeholder: descriptionPlaceholder,
|
||||
disabled: isSubmitting,
|
||||
})
|
||||
|
||||
const isEditorFilled = editor != null && !editor.isEmpty
|
||||
useWarnUnsavedChanges(!isSubmitting && (Boolean(question) || isEditorFilled))
|
||||
|
||||
function setCloseDateInDays(days: number) {
|
||||
const newCloseDate = dayjs().add(days, 'day').format('YYYY-MM-DD')
|
||||
setCloseDate(newCloseDate)
|
||||
|
@ -183,14 +193,13 @@ export function NewContract(props: {
|
|||
async function submit() {
|
||||
// TODO: Tell users why their contract is invalid
|
||||
if (!creator || !isValid) return
|
||||
|
||||
setIsSubmitting(true)
|
||||
try {
|
||||
const result = await createMarket(
|
||||
removeUndefinedProps({
|
||||
question,
|
||||
outcomeType,
|
||||
description,
|
||||
description: editor?.getJSON(),
|
||||
initialProb,
|
||||
ante,
|
||||
closeTime,
|
||||
|
@ -213,15 +222,11 @@ export function NewContract(props: {
|
|||
|
||||
await router.push(contractPath(result as Contract))
|
||||
} catch (e) {
|
||||
console.log('error creating contract', e)
|
||||
console.error('error creating contract', e, (e as any).details)
|
||||
setIsSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
const descriptionPlaceholder =
|
||||
outcomeType === 'BINARY'
|
||||
? `e.g. This question resolves to "YES" if they receive the majority of votes...`
|
||||
: `e.g. I will choose the answer according to...`
|
||||
|
||||
if (!creator) return <></>
|
||||
|
||||
return (
|
||||
|
@ -396,25 +401,12 @@ export function NewContract(props: {
|
|||
|
||||
<Spacer h={6} />
|
||||
|
||||
<div className="form-control mb-1 items-start">
|
||||
<label className="label mb-1 gap-2">
|
||||
<div className="form-control mb-1 items-start gap-1">
|
||||
<label className="label gap-2">
|
||||
<span className="mb-1">Description</span>
|
||||
<InfoTooltip text="Optional. Describe how you will resolve this question." />
|
||||
</label>
|
||||
<Textarea
|
||||
className="textarea textarea-bordered w-full resize-none"
|
||||
rows={3}
|
||||
maxLength={MAX_DESCRIPTION_LENGTH}
|
||||
placeholder={descriptionPlaceholder}
|
||||
value={description}
|
||||
disabled={isSubmitting}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onChange={(e) => {
|
||||
setDescription(e.target.value || '')
|
||||
bottomRef?.scrollIntoView()
|
||||
}}
|
||||
/>
|
||||
<div ref={setBottomRef} />
|
||||
<TextEditor editor={editor} upload={upload} />
|
||||
</div>
|
||||
|
||||
<Spacer h={6} />
|
||||
|
@ -451,7 +443,7 @@ export function NewContract(props: {
|
|||
'btn btn-primary normal-case',
|
||||
isSubmitting && 'loading disabled'
|
||||
)}
|
||||
disabled={isSubmitting || !isValid}
|
||||
disabled={isSubmitting || !isValid || upload.isLoading}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
submit()
|
||||
|
|
|
@ -159,7 +159,6 @@ export default function GroupPage(props: {
|
|||
? contracts.filter(
|
||||
(c) =>
|
||||
checkAgainstQuery(query, c.question) ||
|
||||
checkAgainstQuery(query, c.description || '') ||
|
||||
checkAgainstQuery(query, c.creatorName) ||
|
||||
checkAgainstQuery(query, c.creatorUsername)
|
||||
)
|
||||
|
|
|
@ -1,292 +0,0 @@
|
|||
import clsx from 'clsx'
|
||||
import dayjs from 'dayjs'
|
||||
import Link from 'next/link'
|
||||
import { useState } from 'react'
|
||||
import Textarea from 'react-expanding-textarea'
|
||||
|
||||
import { getProbability } from 'common/calculate'
|
||||
import { BinaryContract } from 'common/contract'
|
||||
import { parseWordsAsTags } from 'common/util/parse'
|
||||
import { BuyAmountInput } from 'web/components/amount-input'
|
||||
import { InfoTooltip } from 'web/components/info-tooltip'
|
||||
import { Col } from 'web/components/layout/col'
|
||||
import { Row } from 'web/components/layout/row'
|
||||
import { Spacer } from 'web/components/layout/spacer'
|
||||
import { Linkify } from 'web/components/linkify'
|
||||
import { Page } from 'web/components/page'
|
||||
import { Title } from 'web/components/title'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { createMarket } from 'web/lib/firebase/api'
|
||||
import { contractPath } from 'web/lib/firebase/contracts'
|
||||
|
||||
type Prediction = {
|
||||
question: string
|
||||
description: string
|
||||
initialProb: number
|
||||
createdUrl?: string
|
||||
}
|
||||
|
||||
function toPrediction(contract: BinaryContract): Prediction {
|
||||
const startProb = getProbability(contract)
|
||||
return {
|
||||
question: contract.question,
|
||||
description: contract.description,
|
||||
initialProb: startProb * 100,
|
||||
createdUrl: contractPath(contract),
|
||||
}
|
||||
}
|
||||
|
||||
function PredictionRow(props: { prediction: Prediction }) {
|
||||
const { prediction } = props
|
||||
return (
|
||||
<Row className="justify-between gap-4 p-4 hover:bg-gray-300">
|
||||
<Col className="justify-between">
|
||||
<div className="mb-2 font-medium text-indigo-700">
|
||||
<Linkify text={prediction.question} />
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">{prediction.description}</div>
|
||||
</Col>
|
||||
{/* Initial probability */}
|
||||
<div className="ml-auto">
|
||||
<div className="text-3xl">
|
||||
<div className="text-primary">
|
||||
{prediction.initialProb.toFixed(0)}%
|
||||
<div className="text-lg">chance</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Current probability; hidden for now */}
|
||||
{/* <div>
|
||||
<div className="text-3xl">
|
||||
<div className="text-primary">
|
||||
{prediction.initialProb}%<div className="text-lg">chance</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
|
||||
function PredictionList(props: { predictions: Prediction[] }) {
|
||||
const { predictions } = props
|
||||
return (
|
||||
<Col className="divide-y divide-gray-300 rounded-md border border-gray-300">
|
||||
{predictions.map((prediction) =>
|
||||
prediction.createdUrl ? (
|
||||
<Link href={prediction.createdUrl}>
|
||||
<a>
|
||||
<PredictionRow
|
||||
key={prediction.question}
|
||||
prediction={prediction}
|
||||
/>
|
||||
</a>
|
||||
</Link>
|
||||
) : (
|
||||
<PredictionRow key={prediction.question} prediction={prediction} />
|
||||
)
|
||||
)}
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
|
||||
const TEST_VALUE = `1. Biden approval rating (as per 538) is greater than 50%: 80%
|
||||
2. Court packing is clearly going to happen (new justices don't have to be appointed by end of year): 5%
|
||||
3. Yang is New York mayor: 80%
|
||||
4. Newsom recalled as CA governor: 5%
|
||||
5. At least $250 million in damage from BLM protests this year: 30%
|
||||
6. Significant capital gains tax hike (above 30% for highest bracket): 20%`
|
||||
|
||||
export default function MakePredictions() {
|
||||
const user = useUser()
|
||||
const [predictionsString, setPredictionsString] = useState('')
|
||||
const [description, setDescription] = useState('')
|
||||
const [tags, setTags] = useState('')
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const [createdContracts, setCreatedContracts] = useState<BinaryContract[]>([])
|
||||
|
||||
const [ante, setAnte] = useState<number | undefined>(100)
|
||||
const [anteError, setAnteError] = useState<string | undefined>()
|
||||
// By default, close the market a week from today
|
||||
const weekFromToday = dayjs().add(7, 'day').format('YYYY-MM-DDT23:59')
|
||||
const [closeDate, setCloseDate] = useState<undefined | string>(weekFromToday)
|
||||
|
||||
const closeTime = closeDate ? dayjs(closeDate).valueOf() : undefined
|
||||
|
||||
const bulkPlaceholder = `e.g.
|
||||
${TEST_VALUE}
|
||||
...
|
||||
`
|
||||
|
||||
const predictions: Prediction[] = []
|
||||
|
||||
// Parse bulkContracts, then run createContract for each
|
||||
const lines = predictionsString ? predictionsString.split('\n') : []
|
||||
for (const line of lines) {
|
||||
// Parse line with regex
|
||||
const matches = line.match(/^(.*):\s*(\d+)%\s*$/) || ['', '', '']
|
||||
const [_, question, prob] = matches
|
||||
|
||||
if (!question || !prob) {
|
||||
console.error('Invalid prediction: ', line)
|
||||
continue
|
||||
}
|
||||
|
||||
predictions.push({
|
||||
question,
|
||||
description,
|
||||
initialProb: parseInt(prob),
|
||||
})
|
||||
}
|
||||
|
||||
async function createMarkets() {
|
||||
if (!user) {
|
||||
// TODO: Convey error with snackbar/toast
|
||||
console.error('You need to be signed in!')
|
||||
return
|
||||
}
|
||||
setIsSubmitting(true)
|
||||
for (const prediction of predictions) {
|
||||
const contract = (await createMarket({
|
||||
question: prediction.question,
|
||||
description: prediction.description,
|
||||
initialProb: prediction.initialProb,
|
||||
ante,
|
||||
closeTime,
|
||||
tags: parseWordsAsTags(tags),
|
||||
})) as BinaryContract
|
||||
|
||||
setCreatedContracts((prev) => [...prev, contract])
|
||||
}
|
||||
setPredictionsString('')
|
||||
setIsSubmitting(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Title text="Make Predictions" />
|
||||
<div className="w-full rounded-lg bg-gray-100 px-6 py-4 shadow-xl">
|
||||
<form>
|
||||
<div className="form-control">
|
||||
<label className="label">
|
||||
<span className="label-text">Prediction</span>
|
||||
<div className="ml-1 text-sm text-gray-500">
|
||||
One prediction per line, each formatted like "The sun will rise
|
||||
tomorrow: 99%"
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<textarea
|
||||
className="textarea textarea-bordered h-60"
|
||||
placeholder={bulkPlaceholder}
|
||||
value={predictionsString}
|
||||
onChange={(e) => setPredictionsString(e.target.value || '')}
|
||||
></textarea>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<Spacer h={4} />
|
||||
|
||||
<div className="form-control w-full">
|
||||
<label className="label">
|
||||
<span className="label-text">Description</span>
|
||||
</label>
|
||||
|
||||
<Textarea
|
||||
placeholder="e.g. This market is part of the ACX predictions for 2022..."
|
||||
className="input resize-none"
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value || '')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="form-control w-full">
|
||||
<label className="label">
|
||||
<span className="label-text">Tags</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
placeholder="e.g. ACX2021 World"
|
||||
className="input"
|
||||
value={tags}
|
||||
onChange={(e) => setTags(e.target.value || '')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="form-control mb-1 items-start">
|
||||
<label className="label mb-1 gap-2">
|
||||
<span>Market close</span>
|
||||
<InfoTooltip text="Trading will be halted after this time (local timezone)." />
|
||||
</label>
|
||||
<input
|
||||
type="datetime-local"
|
||||
className="input input-bordered"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onChange={(e) => setCloseDate(e.target.value || '')}
|
||||
min={Date.now()}
|
||||
disabled={isSubmitting}
|
||||
value={closeDate}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Spacer h={4} />
|
||||
|
||||
<div className="form-control mb-1 items-start">
|
||||
<label className="label mb-1 gap-2">
|
||||
<span>Market ante</span>
|
||||
<InfoTooltip
|
||||
text={`Subsidize your market to encourage trading. Ante bets are set to match your initial probability.
|
||||
You earn ${0.01 * 100}% of trading volume.`}
|
||||
/>
|
||||
</label>
|
||||
<BuyAmountInput
|
||||
amount={ante}
|
||||
minimumAmount={10}
|
||||
onChange={setAnte}
|
||||
error={anteError}
|
||||
setError={setAnteError}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{predictions.length > 0 && (
|
||||
<div>
|
||||
<Spacer h={4} />
|
||||
<label className="label">
|
||||
<span className="label-text">Preview</span>
|
||||
</label>
|
||||
<PredictionList predictions={predictions} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Spacer h={4} />
|
||||
|
||||
<div className="my-4 flex justify-end">
|
||||
<button
|
||||
type="submit"
|
||||
className={clsx('btn btn-primary', {
|
||||
loading: isSubmitting,
|
||||
})}
|
||||
disabled={predictions.length === 0 || isSubmitting}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
createMarkets()
|
||||
}}
|
||||
>
|
||||
Create all
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{createdContracts.length > 0 && (
|
||||
<>
|
||||
<Spacer h={16} />
|
||||
<Title text="Created Predictions" />
|
||||
<div className="w-full rounded-lg bg-gray-100 px-6 py-4 shadow-xl">
|
||||
<PredictionList predictions={createdContracts.map(toPrediction)} />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Page>
|
||||
)
|
||||
}
|
404
yarn.lock
404
yarn.lock
|
@ -2588,6 +2588,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
|
||||
integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
|
||||
|
||||
"@popperjs/core@^2.9.0":
|
||||
version "2.11.5"
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64"
|
||||
integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==
|
||||
|
||||
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
|
||||
|
@ -2860,6 +2865,193 @@
|
|||
lodash.isplainobject "^4.0.6"
|
||||
lodash.merge "^4.6.2"
|
||||
|
||||
"@tiptap/core@2.0.0-beta.181", "@tiptap/core@^2.0.0-beta.181":
|
||||
version "2.0.0-beta.181"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.181.tgz#07aeea26336814ab82eb7f4199b17538187c6fbb"
|
||||
integrity sha512-tbwRqjTVvY9v31TNAH6W0Njhr/OVwI28zWXmH55/USrwyU2CB1iCVfXktZKOhB+8WyvOaBv1JA5YplMIhstYTw==
|
||||
dependencies:
|
||||
prosemirror-commands "1.3.0"
|
||||
prosemirror-keymap "1.2.0"
|
||||
prosemirror-model "1.18.1"
|
||||
prosemirror-schema-list "1.2.0"
|
||||
prosemirror-state "1.4.1"
|
||||
prosemirror-transform "1.6.0"
|
||||
prosemirror-view "1.26.2"
|
||||
|
||||
"@tiptap/extension-blockquote@^2.0.0-beta.29":
|
||||
version "2.0.0-beta.29"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.29.tgz#6f1c4b17efa6457c7776f32d0807e96d848d4389"
|
||||
integrity sha512-zMYT5TtpKWav9VhTn4JLyMvXmhEdbD6on0MdhcTjRm0I5ugyR4ZbJwh2aelM7G9DZVYzB8jZU18OSDJmo7Af7w==
|
||||
|
||||
"@tiptap/extension-bold@^2.0.0-beta.28":
|
||||
version "2.0.0-beta.28"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.28.tgz#cf67c264a80434ffb2368f3dd37cf357ae0c2064"
|
||||
integrity sha512-DY8GOzw9xjmTFrnvTbgHUNxTnDfKrkDgrhe0SUvdkT2udntWp8umPdhPiD3vczLgHOJw6tX68qMRjbsR1ZPcHQ==
|
||||
|
||||
"@tiptap/extension-bubble-menu@^2.0.0-beta.61":
|
||||
version "2.0.0-beta.61"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.61.tgz#cc61ce8b094fdbcec58f44f0fa39172a726c024c"
|
||||
integrity sha512-T3Yx+y1sUnXAJjK1CUfsQewSxOpDca9KzKqN2H9c9RZ9UlorR9XmZg6YYW7m9a7adeihj+o3cCO9jRd8dV+nnA==
|
||||
dependencies:
|
||||
prosemirror-state "1.4.1"
|
||||
prosemirror-view "1.26.2"
|
||||
tippy.js "^6.3.7"
|
||||
|
||||
"@tiptap/extension-bullet-list@^2.0.0-beta.29":
|
||||
version "2.0.0-beta.29"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.29.tgz#640883e4fffc1a86c7cbd78792688e7edee5ee41"
|
||||
integrity sha512-R8VB2l1ZB6VeGWx/t/04nBS5Wg3qjIDEZCpPihj2fccJOw99Lu0Ub2UJg/SfdGmeNNpBh4ZYYFv1g/XjyzlXKg==
|
||||
|
||||
"@tiptap/extension-character-count@2.0.0-beta.31":
|
||||
version "2.0.0-beta.31"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-character-count/-/extension-character-count-2.0.0-beta.31.tgz#fac9ba809ddc38cf67c8a05a42d94e062a1967d2"
|
||||
integrity sha512-NNA9MN1IjZe+yYQLuYVAg9RNG/3RonYrHiM5mL6vsegd+PF4uMqyZLgsM0/9dMhxh9K/pDPaCRxhuDoZC8V1wA==
|
||||
dependencies:
|
||||
prosemirror-model "1.18.1"
|
||||
prosemirror-state "1.4.1"
|
||||
|
||||
"@tiptap/extension-code-block@^2.0.0-beta.42":
|
||||
version "2.0.0-beta.42"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.42.tgz#2abfd92eb22399fa542aafb3b76dddfb41d87ab5"
|
||||
integrity sha512-4wzLup4mI8w9ypIceekUV/8g41cQIPn31qs1iC9u1/JuTkjMj/tA+TFUyp6IMugLxoI/P2DlTztU6/6m7n9DyQ==
|
||||
dependencies:
|
||||
prosemirror-state "1.4.1"
|
||||
|
||||
"@tiptap/extension-code@^2.0.0-beta.28":
|
||||
version "2.0.0-beta.28"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.28.tgz#a22c0e873497ac0bbcd77e4a855322f8591f954e"
|
||||
integrity sha512-QPJ2Gwb1+3NgcC1ZIhvVcb+FsnWWDu5VZXTKXM4mz892i9V2x48uHg5anPiUV6pcolXsW1F5VNbXIHGTUUO6CQ==
|
||||
|
||||
"@tiptap/extension-document@^2.0.0-beta.17":
|
||||
version "2.0.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.17.tgz#ded4182dd860762bcf41c588f712d83908c472a3"
|
||||
integrity sha512-L6sg0FNchbtIpQkCSjMmItVGs3/vep8Fq56WRtDc1wBSGUSmtHaxQG7F2FZLnNIUMuvzVMRD81m2vYG73WkY6A==
|
||||
|
||||
"@tiptap/extension-dropcursor@^2.0.0-beta.29":
|
||||
version "2.0.0-beta.29"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.29.tgz#9ccc9d82cb9f8fa28a59ffc061c4c83ee059a12c"
|
||||
integrity sha512-I+joyoFB8pfdXUPLMqdNO08nlB5m2lbu0VQ5dpqdi/HzgVThMZPZA1cW0X8vAUvrALs5/JFRiFoR9hrLN5R5ng==
|
||||
dependencies:
|
||||
prosemirror-dropcursor "1.5.0"
|
||||
|
||||
"@tiptap/extension-floating-menu@^2.0.0-beta.56":
|
||||
version "2.0.0-beta.56"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.56.tgz#c7428d9109d215bdbd9033f69782c4aadb2aabec"
|
||||
integrity sha512-j/evHE/6UPGkIgXny9IGcAh0IrcnQmg0b2NBYebs2mqx9xYKYoe+0jVgNdLp/0M3MRgQCzyWTyatBDBFOUR2mw==
|
||||
dependencies:
|
||||
prosemirror-state "1.4.1"
|
||||
prosemirror-view "1.26.2"
|
||||
tippy.js "^6.3.7"
|
||||
|
||||
"@tiptap/extension-gapcursor@^2.0.0-beta.39":
|
||||
version "2.0.0-beta.39"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.39.tgz#b8585d2936df7ca90446758c3af90b46d552a1fb"
|
||||
integrity sha512-oCyz5WEeQXrEIoa1WXaD52yf1EwMFCXaK1cVzFgUj8lkXJ+nJj+O/Zp0Mg+9/MVR0LYu/kifqVorKNXM4AFA/g==
|
||||
dependencies:
|
||||
prosemirror-gapcursor "1.3.0"
|
||||
|
||||
"@tiptap/extension-hard-break@^2.0.0-beta.33":
|
||||
version "2.0.0-beta.33"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.33.tgz#e2f355a22aaaec6e831cf2880c52aa5b0b860573"
|
||||
integrity sha512-41xf0vSV9hcyTFd01ItLq/CjhjgmOFLCrO3UWN/P2E/cIxuDTyXcvjTE/KXeqRCOV3OYd9fVr0wO91hc8Ij1Yg==
|
||||
|
||||
"@tiptap/extension-heading@^2.0.0-beta.29":
|
||||
version "2.0.0-beta.29"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.29.tgz#d017d216c0fd1962c266f6f61a335093f9749862"
|
||||
integrity sha512-q92jYcsT5bPhvuQaB0h44Z9r+Ii22tDYo082KMVnR4+tknHT/3xx+p4JC8KHjh+/5W8Quyafqy6mS8L8VX0zsQ==
|
||||
|
||||
"@tiptap/extension-history@^2.0.0-beta.26":
|
||||
version "2.0.0-beta.26"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.0-beta.26.tgz#ae4c0ee8d19b3530e72d99cb5d0f69aefcf96d04"
|
||||
integrity sha512-ly19uwvdmXG8Fw1KcavXIHi3Qx6JBASOR7394zghOEpW3atpY8nd/8I373rZ8eDUcGOClfaF7bCx2xvIotAAnw==
|
||||
dependencies:
|
||||
prosemirror-history "1.3.0"
|
||||
|
||||
"@tiptap/extension-horizontal-rule@^2.0.0-beta.36":
|
||||
version "2.0.0-beta.36"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.36.tgz#daf8e2d0f30b210a90fdb8f015646653661cfa04"
|
||||
integrity sha512-o+Zp7dcn3zAQhtlhZiFB69mTHuH3ZRbGEF7Cbf1D3uX1izotni5zIZbPaFFUT4r6OmVe/vDDt/nopfcGc10ktQ==
|
||||
dependencies:
|
||||
prosemirror-state "1.4.1"
|
||||
|
||||
"@tiptap/extension-image@2.0.0-beta.30":
|
||||
version "2.0.0-beta.30"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.30.tgz#60c6cfd09bfd017a3d8b1feaf0931462ffd71a60"
|
||||
integrity sha512-VhEmgiKkZMiKR7hbpJgIlIUS/QNjSGI5ER7mKDAbuV1IB5yb6nGjZ6o3Exrr2/CaTaW5hQarBC1z2Xgdu05EGg==
|
||||
|
||||
"@tiptap/extension-italic@^2.0.0-beta.28":
|
||||
version "2.0.0-beta.28"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.28.tgz#bf88ecae64c8f2f69f1f508b802c1efd7454a84e"
|
||||
integrity sha512-/pKRiCfewh7nqiXRD3N4hQHfGrGNOiWPFYZfY35bSpvTms7PDb/MF7xT1CWW23hSpY31BBS+R/a66vlR/gqu7Q==
|
||||
|
||||
"@tiptap/extension-list-item@^2.0.0-beta.23":
|
||||
version "2.0.0-beta.23"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.23.tgz#6d1ac7235462b0bcee196f42bb1871669480b843"
|
||||
integrity sha512-AkzvdELz3ZnrlZM0r9+ritBDOnAjXHR/8zCZhW0ZlWx4zyKPMsNG5ygivY+xr4QT65NEGRT8P8b2zOhXrMjjMQ==
|
||||
|
||||
"@tiptap/extension-ordered-list@^2.0.0-beta.30":
|
||||
version "2.0.0-beta.30"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.30.tgz#1f656b664302d90272c244b2e478d7056203f2a8"
|
||||
integrity sha512-GRxGQdq1u0Rp5N8TjthCqoZ//460m343A0HCN7UwfQOnX7Ipv0UJemwNkSHWrl7Pexym9vy3yPWgrn7oRRmgEw==
|
||||
|
||||
"@tiptap/extension-paragraph@^2.0.0-beta.26":
|
||||
version "2.0.0-beta.26"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.26.tgz#5199c8cedb9c076347a2e15cc67442ef7c3c3fbb"
|
||||
integrity sha512-WcYsuUa7LLfk0vi7I1dVjdMRu53B52FMMqd+UL1qPdDKVkU3DBsZVwPj+yyfQyqN8Mc/xyg9VacGaiKFLmWNDg==
|
||||
|
||||
"@tiptap/extension-placeholder@2.0.0-beta.53":
|
||||
version "2.0.0-beta.53"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-placeholder/-/extension-placeholder-2.0.0-beta.53.tgz#df29d813044da9a0e30bf8409335e77f6857c2b2"
|
||||
integrity sha512-NGU/a+GvcJVBjFqb2vI45+rNa3Cjsq/M+R/2xg9olb1w/HBr17NKf/5WSoqcc1S2cdnmMH6rB0/mVhG7Ciur+Q==
|
||||
dependencies:
|
||||
prosemirror-model "1.18.1"
|
||||
prosemirror-state "1.4.1"
|
||||
prosemirror-view "1.26.2"
|
||||
|
||||
"@tiptap/extension-strike@^2.0.0-beta.29":
|
||||
version "2.0.0-beta.29"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.29.tgz#7004d0c5d126b0517fa78efc5a333a4b8e3334bf"
|
||||
integrity sha512-zqFuY7GfNmZ/KClt6kxQ+msGo3syqucP/Xnlihxi+/h/G+oTvEwyOIXCtDOltvxcsWH/TUsdr5vzLp0j+Mdc6Q==
|
||||
|
||||
"@tiptap/extension-text@^2.0.0-beta.17":
|
||||
version "2.0.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.17.tgz#4fdd1bdf62c82c1af6feef91c689906a8f5b171e"
|
||||
integrity sha512-OyKL+pqWJEtjyd9/mrsuY1kZh2b3LWpOQDWKtd4aWR4EA0efmQG+7FPwcIeAVEh7ZoqM+/ABCnPjN6IjzIrSfg==
|
||||
|
||||
"@tiptap/react@2.0.0-beta.114":
|
||||
version "2.0.0-beta.114"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/react/-/react-2.0.0-beta.114.tgz#fa2b3fcdf379bf7ee25388c0eddbda49249977d5"
|
||||
integrity sha512-9JbRE+16WM6RxbBxzY74SrJtLodvjeRBnEbWxuhxVgGKxMunRj6r8oED87ODJgqLmkpofwE0KFHTPGdEXfdcKA==
|
||||
dependencies:
|
||||
"@tiptap/extension-bubble-menu" "^2.0.0-beta.61"
|
||||
"@tiptap/extension-floating-menu" "^2.0.0-beta.56"
|
||||
prosemirror-view "1.26.2"
|
||||
|
||||
"@tiptap/starter-kit@2.0.0-beta.190":
|
||||
version "2.0.0-beta.190"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/starter-kit/-/starter-kit-2.0.0-beta.190.tgz#fe0021e29d070fc5707722513a398c8884e15f71"
|
||||
integrity sha512-jaFMkE6mjCHmCJsXUyLiXGYRVDcHF+PbH/5hEu1riUIAT0Hmm7uak5TYsPeuoCVN7P/tmDEBbBRASZ5CzEQpvw==
|
||||
dependencies:
|
||||
"@tiptap/core" "^2.0.0-beta.181"
|
||||
"@tiptap/extension-blockquote" "^2.0.0-beta.29"
|
||||
"@tiptap/extension-bold" "^2.0.0-beta.28"
|
||||
"@tiptap/extension-bullet-list" "^2.0.0-beta.29"
|
||||
"@tiptap/extension-code" "^2.0.0-beta.28"
|
||||
"@tiptap/extension-code-block" "^2.0.0-beta.42"
|
||||
"@tiptap/extension-document" "^2.0.0-beta.17"
|
||||
"@tiptap/extension-dropcursor" "^2.0.0-beta.29"
|
||||
"@tiptap/extension-gapcursor" "^2.0.0-beta.39"
|
||||
"@tiptap/extension-hard-break" "^2.0.0-beta.33"
|
||||
"@tiptap/extension-heading" "^2.0.0-beta.29"
|
||||
"@tiptap/extension-history" "^2.0.0-beta.26"
|
||||
"@tiptap/extension-horizontal-rule" "^2.0.0-beta.36"
|
||||
"@tiptap/extension-italic" "^2.0.0-beta.28"
|
||||
"@tiptap/extension-list-item" "^2.0.0-beta.23"
|
||||
"@tiptap/extension-ordered-list" "^2.0.0-beta.30"
|
||||
"@tiptap/extension-paragraph" "^2.0.0-beta.26"
|
||||
"@tiptap/extension-strike" "^2.0.0-beta.29"
|
||||
"@tiptap/extension-text" "^2.0.0-beta.17"
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
|
@ -3425,7 +3617,7 @@ acorn-jsx@^5.3.2:
|
|||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||
|
||||
acorn-node@^1.6.1:
|
||||
acorn-node@^1.8.2:
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
|
||||
integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
|
||||
|
@ -3623,11 +3815,16 @@ anymatch@~3.1.2:
|
|||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
arg@^5.0.0, arg@^5.0.1:
|
||||
arg@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb"
|
||||
integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==
|
||||
|
||||
arg@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
|
||||
integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
|
@ -4174,7 +4371,7 @@ cheerio@^1.0.0-rc.10:
|
|||
parse5-htmlparser2-tree-adapter "^7.0.0"
|
||||
tslib "^2.4.0"
|
||||
|
||||
chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3:
|
||||
chokidar@^3.4.2, chokidar@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||
|
@ -5017,14 +5214,14 @@ detect-port@^1.3.0:
|
|||
address "^1.0.1"
|
||||
debug "^2.6.0"
|
||||
|
||||
detective@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b"
|
||||
integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==
|
||||
detective@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034"
|
||||
integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==
|
||||
dependencies:
|
||||
acorn-node "^1.6.1"
|
||||
acorn-node "^1.8.2"
|
||||
defined "^1.0.0"
|
||||
minimist "^1.1.1"
|
||||
minimist "^1.2.6"
|
||||
|
||||
dicer@^0.3.0:
|
||||
version "0.3.1"
|
||||
|
@ -5745,7 +5942,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
|||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
||||
fast-glob@^3.2.7, fast-glob@^3.2.9:
|
||||
fast-glob@^3.2.11, fast-glob@^3.2.7, fast-glob@^3.2.9:
|
||||
version "3.2.11"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
|
||||
integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
|
||||
|
@ -8026,7 +8223,7 @@ minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
|
|||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
|
||||
minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
||||
|
@ -8259,11 +8456,6 @@ object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1:
|
|||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
object-hash@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
|
||||
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
|
||||
|
||||
object-hash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
|
||||
|
@ -8398,6 +8590,11 @@ optionator@^0.9.1:
|
|||
type-check "^0.4.0"
|
||||
word-wrap "^1.2.3"
|
||||
|
||||
orderedmap@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-2.0.0.tgz#12ff5ef6ea9d12d6430b80c701b35475e1c9ff34"
|
||||
integrity sha512-buf4PoAMlh45b8a8gsGy/X6w279TSqkyAS0C0wdTSJwFSU+ljQFJON5I8NfjLHoCXwpSROIo2wr0g33T+kQshQ==
|
||||
|
||||
p-cancelable@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
|
||||
|
@ -8683,6 +8880,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
|
|||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
pify@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||
integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
|
||||
|
||||
pkg-dir@^4.1.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
||||
|
@ -8750,15 +8952,23 @@ postcss-discard-unused@^5.1.0:
|
|||
dependencies:
|
||||
postcss-selector-parser "^6.0.5"
|
||||
|
||||
postcss-js@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-3.0.3.tgz#2f0bd370a2e8599d45439f6970403b5873abda33"
|
||||
integrity sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw==
|
||||
postcss-import@^14.1.0:
|
||||
version "14.1.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0"
|
||||
integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==
|
||||
dependencies:
|
||||
postcss-value-parser "^4.0.0"
|
||||
read-cache "^1.0.0"
|
||||
resolve "^1.1.7"
|
||||
|
||||
postcss-js@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00"
|
||||
integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==
|
||||
dependencies:
|
||||
camelcase-css "^2.0.1"
|
||||
postcss "^8.1.6"
|
||||
|
||||
postcss-load-config@^3.1.0:
|
||||
postcss-load-config@^3.1.4:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
|
||||
integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
|
||||
|
@ -8961,7 +9171,7 @@ postcss-reduce-transforms@^5.1.0:
|
|||
dependencies:
|
||||
postcss-value-parser "^4.2.0"
|
||||
|
||||
postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
|
||||
postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
|
||||
version "6.0.10"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
|
||||
integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
|
||||
|
@ -8991,7 +9201,7 @@ postcss-unique-selectors@^5.1.1:
|
|||
dependencies:
|
||||
postcss-selector-parser "^6.0.5"
|
||||
|
||||
postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
|
||||
postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
@ -9019,7 +9229,7 @@ postcss@8.4.5:
|
|||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.1"
|
||||
|
||||
postcss@^8.1.6, postcss@^8.3.11, postcss@^8.3.5, postcss@^8.3.7, postcss@^8.4.7:
|
||||
postcss@^8.3.11, postcss@^8.3.5, postcss@^8.3.7, postcss@^8.4.14, postcss@^8.4.7:
|
||||
version "8.4.14"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf"
|
||||
integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==
|
||||
|
@ -9134,6 +9344,91 @@ property-information@^5.0.0, property-information@^5.3.0:
|
|||
dependencies:
|
||||
xtend "^4.0.0"
|
||||
|
||||
prosemirror-commands@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.3.0.tgz#361b2e2b2a347ce7453386459f97c3f549a1113b"
|
||||
integrity sha512-BwBbZ5OAScPcm0x7H8SPbqjuEJnCU2RJT9LDyOiiIl/3NbL1nJZI4SFNHwU2e/tRr2Xe7JsptpzseqvZvToLBQ==
|
||||
dependencies:
|
||||
prosemirror-model "^1.0.0"
|
||||
prosemirror-state "^1.0.0"
|
||||
prosemirror-transform "^1.0.0"
|
||||
|
||||
prosemirror-dropcursor@1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.5.0.tgz#edbc61d6f71f9f924130eec8e85b0861357957c9"
|
||||
integrity sha512-vy7i77ddKyXlu8kKBB3nlxLBnsWyKUmQIPB5x8RkYNh01QNp/qqGmdd5yZefJs0s3rtv5r7Izfu2qbtr+tYAMQ==
|
||||
dependencies:
|
||||
prosemirror-state "^1.0.0"
|
||||
prosemirror-transform "^1.1.0"
|
||||
prosemirror-view "^1.1.0"
|
||||
|
||||
prosemirror-gapcursor@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.0.tgz#e07c22ad959b86ec0c4cfc590cc5f484dd984d56"
|
||||
integrity sha512-9Tdx83xB2W4Oqchm12FtCkSizbqvi64cjs1I9TRPblqdA5TUWoVZ4ZI+t71Jh6HSEh4cDMPzx3UwfryJtKlb/w==
|
||||
dependencies:
|
||||
prosemirror-keymap "^1.0.0"
|
||||
prosemirror-model "^1.0.0"
|
||||
prosemirror-state "^1.0.0"
|
||||
prosemirror-view "^1.0.0"
|
||||
|
||||
prosemirror-history@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-history/-/prosemirror-history-1.3.0.tgz#bf5a1ff7759aca759ddf0c722c2fa5b14fb0ddc1"
|
||||
integrity sha512-qo/9Wn4B/Bq89/YD+eNWFbAytu6dmIM85EhID+fz9Jcl9+DfGEo8TTSrRhP15+fFEoaPqpHSxlvSzSEbmlxlUA==
|
||||
dependencies:
|
||||
prosemirror-state "^1.2.2"
|
||||
prosemirror-transform "^1.0.0"
|
||||
rope-sequence "^1.3.0"
|
||||
|
||||
prosemirror-keymap@1.2.0, prosemirror-keymap@^1.0.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.2.0.tgz#d5cc9da9b712020690a994b50b92a0e448a60bf5"
|
||||
integrity sha512-TdSfu+YyLDd54ufN/ZeD1VtBRYpgZnTPnnbY+4R08DDgs84KrIPEPbJL8t1Lm2dkljFx6xeBE26YWH3aIzkPKg==
|
||||
dependencies:
|
||||
prosemirror-state "^1.0.0"
|
||||
w3c-keyname "^2.2.0"
|
||||
|
||||
prosemirror-model@1.18.1, prosemirror-model@^1.0.0, prosemirror-model@^1.16.0:
|
||||
version "1.18.1"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.18.1.tgz#1d5d6b6de7b983ee67a479dc607165fdef3935bd"
|
||||
integrity sha512-IxSVBKAEMjD7s3n8cgtwMlxAXZrC7Mlag7zYsAKDndAqnDScvSmp/UdnRTV/B33lTCVU3CCm7dyAn/rVVD0mcw==
|
||||
dependencies:
|
||||
orderedmap "^2.0.0"
|
||||
|
||||
prosemirror-schema-list@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.2.0.tgz#1932268593a7396c0ac168cbe31f28187406ce24"
|
||||
integrity sha512-8PT/9xOx1HHdC7fDNNfhQ50Z8Mzu7nKyA1KCDltSpcZVZIbB0k7KtsHrnXyuIhbLlScoymBiLZ00c5MH6wdFsA==
|
||||
dependencies:
|
||||
prosemirror-model "^1.0.0"
|
||||
prosemirror-state "^1.0.0"
|
||||
prosemirror-transform "^1.0.0"
|
||||
|
||||
prosemirror-state@1.4.1, prosemirror-state@^1.0.0, prosemirror-state@^1.2.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-state/-/prosemirror-state-1.4.1.tgz#f6e26c7b6a7e11206176689eb6ebbf91870953e1"
|
||||
integrity sha512-U/LBDW2gNmVa07sz/D229XigSdDQ5CLFwVB1Vb32MJbAHHhWe/6pOc721faI17tqw4pZ49i1xfY/jEZ9tbIhPg==
|
||||
dependencies:
|
||||
prosemirror-model "^1.0.0"
|
||||
prosemirror-transform "^1.0.0"
|
||||
|
||||
prosemirror-transform@1.6.0, prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.6.0.tgz#8162dbfaf124f9253a7ab28605a9460411a96a53"
|
||||
integrity sha512-MAp7AjsjEGEqQY0sSMufNIUuEyB1ZR9Fqlm8dTwwWwpEJRv/plsKjWXBbx52q3Ml8MtaMcd7ic14zAHVB3WaMw==
|
||||
dependencies:
|
||||
prosemirror-model "^1.0.0"
|
||||
|
||||
prosemirror-view@1.26.2, prosemirror-view@^1.0.0, prosemirror-view@^1.1.0:
|
||||
version "1.26.2"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.26.2.tgz#e673894ecf26aea330b727622d561c51b41d31eb"
|
||||
integrity sha512-CGKw+GadkfSBEwRAJTHCEKJ4DlV6/3IhAdjpwGyZHUHtbP7jX4Ol4zmi7xa2c6GOabDlIJLYXJydoNYLX7lNeQ==
|
||||
dependencies:
|
||||
prosemirror-model "^1.16.0"
|
||||
prosemirror-state "^1.0.0"
|
||||
prosemirror-transform "^1.1.0"
|
||||
|
||||
proto3-json-serializer@^0.1.8:
|
||||
version "0.1.9"
|
||||
resolved "https://registry.yarnpkg.com/proto3-json-serializer/-/proto3-json-serializer-0.1.9.tgz#705ddb41b009dd3e6fcd8123edd72926abf65a34"
|
||||
|
@ -9545,6 +9840,13 @@ react@17.0.2, react@^17.0.1:
|
|||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
read-cache@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
|
||||
integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
|
||||
dependencies:
|
||||
pify "^2.3.0"
|
||||
|
||||
read-pkg-up@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
|
||||
|
@ -9868,7 +10170,7 @@ resolve@^1.1.6, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.3.
|
|||
path-parse "^1.0.7"
|
||||
supports-preserve-symlinks-flag "^1.0.0"
|
||||
|
||||
resolve@^1.10.0:
|
||||
resolve@^1.1.7, resolve@^1.10.0, resolve@^1.22.1:
|
||||
version "1.22.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
||||
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
|
||||
|
@ -9917,6 +10219,11 @@ rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2:
|
|||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rope-sequence@^1.3.0:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.3.tgz#3f67fc106288b84b71532b4a5fd9d4881e4457f0"
|
||||
integrity sha512-85aZYCxweiD5J8yTEbw+E6A27zSnLPNDL0WfPdw3YYodq7WjnTKo0q4dtyQ2gz23iPT8Q9CUyJtAaUNcTxRf5Q==
|
||||
|
||||
rtl-detect@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6"
|
||||
|
@ -10628,32 +10935,33 @@ svgo@^2.5.0, svgo@^2.7.0:
|
|||
picocolors "^1.0.0"
|
||||
stable "^0.1.8"
|
||||
|
||||
tailwindcss@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.1.tgz#bef72ff45d5cfed79bb648d30da952e521e98da4"
|
||||
integrity sha512-EVDXVZkcueZ77/zfOJw7XkzCuxe5TCiT/S9pw9P183oRzSuwMZ7WO+W/L76jbJQA5qxGeUBJOVOLVBuAUfeZ3g==
|
||||
tailwindcss@3.1.6:
|
||||
version "3.1.6"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.1.6.tgz#bcb719357776c39e6376a8d84e9834b2b19a49f1"
|
||||
integrity sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==
|
||||
dependencies:
|
||||
arg "^5.0.1"
|
||||
chalk "^4.1.2"
|
||||
chokidar "^3.5.2"
|
||||
arg "^5.0.2"
|
||||
chokidar "^3.5.3"
|
||||
color-name "^1.1.4"
|
||||
cosmiconfig "^7.0.1"
|
||||
detective "^5.2.0"
|
||||
detective "^5.2.1"
|
||||
didyoumean "^1.2.2"
|
||||
dlv "^1.1.3"
|
||||
fast-glob "^3.2.7"
|
||||
fast-glob "^3.2.11"
|
||||
glob-parent "^6.0.2"
|
||||
is-glob "^4.0.3"
|
||||
lilconfig "^2.0.5"
|
||||
normalize-path "^3.0.0"
|
||||
object-hash "^2.2.0"
|
||||
postcss-js "^3.0.3"
|
||||
postcss-load-config "^3.1.0"
|
||||
object-hash "^3.0.0"
|
||||
picocolors "^1.0.0"
|
||||
postcss "^8.4.14"
|
||||
postcss-import "^14.1.0"
|
||||
postcss-js "^4.0.0"
|
||||
postcss-load-config "^3.1.4"
|
||||
postcss-nested "5.0.6"
|
||||
postcss-selector-parser "^6.0.6"
|
||||
postcss-selector-parser "^6.0.10"
|
||||
postcss-value-parser "^4.2.0"
|
||||
quick-lru "^5.1.1"
|
||||
resolve "^1.20.0"
|
||||
tmp "^0.2.1"
|
||||
resolve "^1.22.1"
|
||||
|
||||
tapable@^1.0.0:
|
||||
version "1.1.3"
|
||||
|
@ -10722,6 +11030,13 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3:
|
|||
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
||||
|
||||
tippy.js@^6.3.7:
|
||||
version "6.3.7"
|
||||
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c"
|
||||
integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.9.0"
|
||||
|
||||
tmp@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
|
||||
|
@ -11198,6 +11513,11 @@ vfile@^4.0.0:
|
|||
unist-util-stringify-position "^2.0.0"
|
||||
vfile-message "^2.0.0"
|
||||
|
||||
w3c-keyname@^2.2.0:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.4.tgz#4ade6916f6290224cdbd1db8ac49eab03d0eef6b"
|
||||
integrity sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==
|
||||
|
||||
wait-on@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.1.tgz#16bbc4d1e4ebdd41c5b4e63a2e16dbd1f4e5601e"
|
||||
|
|
Loading…
Reference in New Issue
Block a user