More precise

This commit is contained in:
Dan Abramov
2024-04-24 06:15:44 +01:00
parent 01be351693
commit 21405442f1
3 changed files with 32 additions and 29 deletions
@@ -134,8 +134,7 @@ export const TextInput = forwardRef(function TextInputImpl(
addLinkCardIfNecessary({
uri: feature.uri,
newText,
cursorLocation,
textBeforeCursor: newText.slice(0, cursorLocation),
mayBePaste,
onNewLink,
prevAddedLinks: prevAddedLinks.current,
@@ -185,7 +185,7 @@ export const TextInput = React.forwardRef(function TextInputImpl(
},
onUpdate({editor: editorProp}) {
const json = editorProp.getJSON()
const newText = editorJsonToText(json).trimEnd() // Otherwise we have \n\n at the end
const newText = editorJsonToText(json)
const mayBePaste = window.event?.type === 'paste'
const newRt = new RichText({text: newText})
@@ -196,15 +196,13 @@ export const TextInput = React.forwardRef(function TextInputImpl(
for (const facet of newRt.facets) {
for (const feature of facet.features) {
if (AppBskyRichtextFacet.isLink(feature)) {
// The TipTap editor shows the position as being one character ahead, as if the start index is 1.
// Subtracting 1 from the pos gives us the same behavior as the native impl.
let cursorLocation = editor?.state.selection.$anchor.pos ?? 1
cursorLocation -= 1
addLinkCardIfNecessary({
uri: feature.uri,
newText,
cursorLocation,
textBeforeCursor: editorJsonToText(
editorProp.state.doc
.cut(0, editorProp.state.selection.$anchor.pos)
.toJSON(),
),
mayBePaste,
onNewLink,
prevAddedLinks: prevAddedLinks.current,
@@ -279,15 +277,29 @@ export const TextInput = React.forwardRef(function TextInputImpl(
)
})
function editorJsonToText(json: JSONContent): string {
function editorJsonToText(
json: JSONContent,
isLastDocumentChild: boolean = false,
): string {
let text = ''
if (json.type === 'doc' || json.type === 'paragraph') {
if (json.type === 'doc') {
if (json.content?.length) {
for (const node of json.content) {
for (let i = 0; i < json.content.length; i++) {
const node = json.content[i]
const isLastNode = i === json.content.length - 1
text += editorJsonToText(node, isLastNode)
}
}
} else if (json.type === 'paragraph') {
if (json.content?.length) {
for (let i = 0; i < json.content.length; i++) {
const node = json.content[i]
text += editorJsonToText(node)
}
}
text += '\n'
if (!isLastDocumentChild) {
text += '\n'
}
} else if (json.type === 'hardBreak') {
text += '\n'
} else if (json.type === 'text') {
@@ -1,32 +1,24 @@
export function addLinkCardIfNecessary({
uri,
newText,
cursorLocation,
textBeforeCursor,
mayBePaste,
onNewLink,
prevAddedLinks,
endIndex,
}: {
uri: string
newText: string
cursorLocation: number
textBeforeCursor: string
mayBePaste: boolean
onNewLink: (uri: string) => void
prevAddedLinks: Set<string>
endIndex: number
}) {
newText = newText + ' '
const isLeavingLink =
endIndex === textBeforeCursor.length - 2 ||
(endIndex === textBeforeCursor.length - 1 &&
/[^.,;!?]\s$/m.test(textBeforeCursor))
let toAdd = 2
const backOne = newText.charAt(cursorLocation - 1)
const backTwo = newText.charAt(cursorLocation - 2)
if (backOne === ' ' && /[^.!?]/.test(backTwo)) {
toAdd = 1
}
if (!mayBePaste && endIndex + toAdd !== cursorLocation) {
if (!mayBePaste && !isLeavingLink) {
return
}