Skip to content

blocknote TextSelection endpoint not pointing into a node with inline content (doc) #1606

Description

@DineshCodeFlow

Describe the bug
I started using y-sweet in my project for realtime update, and this error has started coming:
TextSelection endpoint not pointing into a node with inline content (doc)
however this a warning but still clears the content from the document

To Reproduce

Package.json:

{
  "name": "@blocknote/example-liveblocks",
  "description": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
  "private": true,
  "version": "0.12.4",
  "scripts": {
    "start": "vite",
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "lint": "eslint . --max-warnings 0"
  },
  "engines": {
    "node": "^18.19.1"
  },
  "dependencies": {
    "@blocknote/ariakit": "latest",
    "@blocknote/core": "latest",
    "@blocknote/mantine": "latest",
    "@blocknote/react": "latest",
    "@blocknote/shadcn": "latest",
    "@liveblocks/yjs": "^1.10.0",
    "@y-sweet/react": "^0.8.2",
    "fs": "^0.0.1-security",
    "path": "^0.12.7",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "sweetalert2": "^11.17.2",
    "yjs": "^13.6.19"
  },
  "devDependencies": {
    "@types/node": "^22.7.4",
    "@types/react": "^18.0.25",
    "@types/react-dom": "^18.0.9",
    "@vitejs/plugin-react": "^4.3.1",
    "eslint": "^8.10.0",
    "vite": "^5.3.4"
  },
  "eslintConfig": {
    "extends": [
      "../../../.eslintrc.js"
    ]
  },
  "eslintIgnore": [
    "dist"
  ]
}

my App.jsx:

"use client";

import { useEffect, useState } from "react";
import { YDocProvider, useYDoc, useYjsProvider } from "@y-sweet/react";
import { useCreateBlockNote, DefaultReactSuggestionItem, SuggestionMenuController } from "@blocknote/react";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import "./common.css";

import { BlockNoteSchema, defaultInlineContentSpecs, filterSuggestionItems } from "@blocknote/core";
import Swal from "sweetalert2";

import {
  fetchWikiData,
  frontEndPoint,
  getArtifactDetails,
  getInitiativeDetails,
  getRandomColorFromSet,
  handleRedirections,
  saveToStorage,
  setSubscriptionAndInitiativeId,
  uploadFile
} from "./common";

import { Mention } from "./Mention";

// 🔐 Extract encoded data
const search = window.location.search;
const urlParams = new URLSearchParams(search);
const encodedData = urlParams.get("data");

let jsonData = {
  alias: "",
  initiativeId: "",
  id: 0,
  userName: "",
  subscriptionId: "",
  teamId: 0,
  isAssociatedWithWorkItem: false,
  environmentName: "dev",
  userId: 0,
};

if (encodedData) {
  const decodedData = atob(encodedData);
  const {
    alias,
    initiativeId,
    id,
    subscriptionId,
    userName,
    teamId = 0,
    isAssociatedWithWorkItem = false,
    environmentName,
    userId = 0,
  } = JSON.parse(decodedData);

  if (!alias || !initiativeId || !id || !subscriptionId || !userName) {
    handleRedirections();
  }

  jsonData = {
    alias,
    initiativeId,
    id,
    subscriptionId,
    userName,
    teamId,
    isAssociatedWithWorkItem,
    environmentName,
    userId,
  };
} else {
  handleRedirections();
}

if (!jsonData.subscriptionId || !jsonData.initiativeId) {
  //@ts-ignore
  Swal.fire({
    icon: "warning",
    title: "Not Logged In",
    text: "You are not logged in. Please log in to continue.",
    showConfirmButton: false,
    timer: null,
    backdrop: false,
    allowOutsideClick: false,
    allowEscapeKey: false,
    allowEnterKey: false,
    showClass: { popup: "" },
    hideClass: { popup: "" },
  });

  throw new Error("You are not logged in. Please log in to continue.");
}

// 🧠 Set default state
setSubscriptionAndInitiativeId(jsonData);

// 📜 Define schema with mention
const schema = BlockNoteSchema.create({
  inlineContentSpecs: {
    ...defaultInlineContentSpecs,
    mention: Mention,
  },
});

// 🌟 Top-level component with YDocProvider
export default function App() {
  const docId = `${jsonData.subscriptionId}_${jsonData.initiativeId}_${jsonData.id}`;

  return (
    <YDocProvider
      docId={docId}
      authEndpoint="https://live.example.com/api/auth"
    >
      <Document />
    </YDocProvider>
  );
}

// 📄 Main editor document component
let initiativeDetails: any = [];
let artifactDetails: any = [];

function Document() {
  const provider = useYjsProvider();
  const doc = useYDoc();
  const [loading, setLoading] = useState(true);

  const editor = useCreateBlockNote({
    schema,
    collaboration: {
      provider,
      fragment: doc.getXmlFragment("blocknote"),
      user: {
        name: jsonData.userName,
        color: getRandomColorFromSet(),
      },
    },
    uploadFile,
    trailingBlock: false,
  });

  useEffect(() => {
    const init = async () => {
      if (!provider.synced || !editor) return;

      const isEditorEmpty =
        editor.document.length === 1 &&
        editor.document[0]?.type === "paragraph" &&
        editor.document[0]?.content?.length === 0;

      // Only populate if there's no remote content synced
      if (isEditorEmpty) {
        await fetchWikiData(jsonData, editor);
      }

      initiativeDetails = await getInitiativeDetails();
      artifactDetails = await getArtifactDetails();

      setLoading(false);
    };

    provider.on("sync", init);
    return () => provider.off("sync", init);
  }, [provider, editor]);
  if (loading) return <div>Loading...</div>;

  const getMentionMenuItems = (): DefaultReactSuggestionItem[] => {
    const users = initiativeDetails.map((item: any) => item.user.firstName);
    return users.map((user: any) => ({
      title: user,
      onItemClick: () =>
        editor.insertInlineContent([
          {
            type: "mention",
            props: { user },
          },
          " ",
        ]),
    }));
  };

  const getArtifactMenuItems = (): DefaultReactSuggestionItem[] => {
    return artifactDetails.map((artifact: any) => ({
      title: `${artifact.externalKey} ${artifact.text}`,
      onItemClick: () => {
        editor.createLink(`${frontEndPoint}${artifact.path}`, artifact.text);
      },
    }));
  };

  return (
    <BlockNoteView
      editor={editor}
      theme="light"
      onChange={() => {
        //@ts-ignore
        saveToStorage(editor, editor.document, jsonData);
      }}
    >
      <SuggestionMenuController
        triggerCharacter={"@"}
        getItems={async (query) =>
          //@ts-ignore
          filterSuggestionItems(getMentionMenuItems(), query)
        }
      />
      <SuggestionMenuController
        triggerCharacter={"#"}
        getItems={async (query) =>
          //@ts-ignore
          filterSuggestionItems(getArtifactMenuItems(), query)
        }
      />
    </BlockNoteView>
  );
}

As soon as I run the project, I see the content coming in the doc. but withing seconds it goes with a console warning:
TextSelection endpoint not pointing into a node with inline content (doc)

Misc

  • Node version: 18.19.1

Any help is highly appreciated!!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions