9a11f55762
* 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
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
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
|
|
const matches = (text.match(regex) || []).map((match) =>
|
|
match.trim().substring(1).substring(0, MAX_TAG_LENGTH)
|
|
)
|
|
const tagSet = new Set()
|
|
const uniqueTags: string[] = []
|
|
// Keep casing of last tag.
|
|
matches.reverse()
|
|
for (const tag of matches) {
|
|
const lowercase = tag.toLowerCase()
|
|
if (!tagSet.has(lowercase)) {
|
|
tagSet.add(lowercase)
|
|
uniqueTags.push(tag)
|
|
}
|
|
}
|
|
uniqueTags.reverse()
|
|
return uniqueTags
|
|
}
|
|
|
|
export function parseWordsAsTags(text: string) {
|
|
const taggedText = text
|
|
.split(/\s+/)
|
|
.map((tag) => (tag.startsWith('#') ? tag : `#${tag}`))
|
|
.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)
|
|
}
|