Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/core/src/extensions/SideMenu/SideMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ export class SideMenuView<
if (this.editor.isEditable) {
const blockContentBoundingBox = block.node.getBoundingClientRect();
const column = block.node.closest("[data-node-type=column]");
const blockNodeElement = block.node;
const tableElement = blockNodeElement.querySelector("[data-node-type=tableContent]");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify that [data-node-type=tableContent] selector matches the tbody structure used by TableHandles

# Search for table content rendering to understand the DOM structure
rg -nP --type=ts -C3 'data-node-type.*tableContent' --iglob '*table*.ts*'

# Search for table body structure in table block definitions
rg -nP --type=ts -C3 'tbody.*contentDOM|contentDOM.*tbody' --iglob '*table*.ts*'

Repository: TypeCellOS/BlockNote

Length of output: 46


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Locate the referenced files
echo "== Files =="
fd -t f "SideMenu.ts" packages/core/src/extensions/SideMenu -a || true
fd -t f "TableHandles.ts" packages -a || true

# 2) Inspect SideMenu selector usage around the referenced line
echo
echo "== SideMenu.ts: selector usage =="
sidelines=$(rg -n "data-node-type=tableContent" packages/core/src/extensions/SideMenu/SideMenu.ts || true)
echo "$sidelines"
if [ -n "${sidelines:-}" ]; then
  line=$(echo "$sidelines" | head -n1 | cut -d: -f1)
  start=$((line-20)); end=$((line+20))
  sed -n "${start},${end}p" packages/core/src/extensions/SideMenu/SideMenu.ts
fi

# 3) Inspect TableHandles tbody usage and surrounding context
echo
echo "== TableHandles.ts: tbody usage =="
tlines=$(rg -n "querySelector\\(\"tbody\"\\)" packages -S || true)
echo "$tlines"
tfile=$(echo "$tlines" | head -n1 | cut -d: -f1)
if [ -n "${tfile:-}" ]; then
  line=$(echo "$tlines" | head -n1 | cut -d: -f2)
  start=$((line-30)); end=$((line+30))
  sed -n "${start},${end}p" "$tfile"
fi

# 4) Find where data-node-type=tableContent is set/rendered
echo
echo "== Where data-node-type=tableContent is set =="
fd -t f "*.ts" packages | wc -l
rg -n "data-node-type\\s*=\\s*['\"]tableContent['\"]|data-node-type=tableContent|data-node-type.*tableContent" packages -S || true

# 5) Find any table rendering that uses <tbody> directly
echo
echo "== Table rendering: <tbody> or tbody query sites =="
rg -n "<tbody|createElement\\(['\"]tbody['\"]\\)|querySelector\\(['\"]tbody['\"]\\)" packages -S || true

Repository: TypeCellOS/BlockNote

Length of output: 4449


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Find exact attribute occurrences =="
rg -n --fixed-strings 'data-node-type="tableContent"' packages -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n --fixed-strings 'data-node-type=tableContent' packages -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Find any render code mentioning tableContent =="
rg -n "tableContent" packages -S --glob '*.{ts,tsx,js,jsx}' --max-count 50 || true

echo
echo "== Find DOM nodes with data-node-type in table-related code =="
rg -n "data-node-type" packages -S --glob '*.{ts,tsx,js,jsx}' | rg "table|Table" --max-count 50 || true

echo
echo "== Find where <tbody> is created in table rendering code =="
rg -n "querySelector\\(\"tbody\"\\)|closest\\(\"tbody\"\\)|<tbody|createElement\\(['\"]tbody['\"]\\)" packages -S --glob '*.{ts,tsx,js,jsx}' --max-count 50 || true

Repository: TypeCellOS/BlockNote

Length of output: 7768


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== SideMenu.ts: inspect around the selector =="
sed -n '230,270p' packages/core/src/extensions/SideMenu/SideMenu.ts

echo
echo "== TableHandles.ts: inspect around tbodyNode query usages =="
sed -n '90,160p' packages/core/src/extensions/TableHandles/TableHandles.ts

echo
echo "== TableHandles.ts: inspect around tableBody.querySelector('tbody') =="
sed -n '540,620p' packages/core/src/extensions/TableHandles/TableHandles.ts

echo
echo "== Find any 'data-node-type' attribute creation/usage =="
rg -n --fixed-strings 'data-node-type' packages/core -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Find where table DOM is generated/serialized (tableContent -> nodes / DOM) =="
rg -n "tableContentToNodes|blockToNode|nodeView|toDOM|table.*content" packages/core/src/blocks/Table packages/core/src/api/nodeConversions packages/core/src/ -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Inspect Table block implementation notes for DOM mapping =="
sed -n '1,220p' packages/core/src/blocks/Table/block.ts

Repository: TypeCellOS/BlockNote

Length of output: 45786


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect further in Table block file to find how tableContent is parsed/rendered
echo "== packages/core/src/blocks/Table/block.ts: find parseTableContent and render of tableContent =="
rg -n "function parseTableContent|parseTableContent\\(|tableContentTo|tableContent.*renderHTML|renderHTML\\(\\{|data-node-type.*tableContent" packages/core/src/blocks/Table/block.ts

echo
echo "== Show parseTableContent implementation and its toDOM/renderHTML usage =="
# Print from around likely parseTableContent location (no assumptions: use rg to get line, then sed window)
line=$(rg -n "parseTableContent" packages/core/src/blocks/Table/block.ts | head -n1 | cut -d: -f1)
start=$((line-60)); end=$((line+160))
sed -n "${start},${end}p" packages/core/src/blocks/Table/block.ts

echo
echo "== Find any mention of 'tableContent' node render/toDOM in Table/block.ts =="
rg -n "name: \"tableContent\"|group: \"tableContent\"|type: \"tableContent\"|isInGroup\\(\"tableContent\"\\)" packages/core/src/blocks/Table/block.ts

echo
echo "== Locate the tableContent node spec implementation in schema =="
rg -n "name: \"tableContent\"|group: \"tableContent\"|renderHTML\\(.*tableContent|tableContent\\b.*Node\\.create" packages/core/src/schema/blocks -S

echo
echo "== Show schema/blocks/types.ts relevant tableContent definitions =="
sed -n '260,360p' packages/core/src/schema/blocks/types.ts
sed -n '380,460p' packages/core/src/schema/blocks/types.ts

Repository: TypeCellOS/BlockNote

Length of output: 6537


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect parseTableContent body (where tableContent DOM mapping might happen)
echo "== Table/block.ts: inspect parseTableContent implementation =="
line=$(rg -n "function parseTableContent\\(" packages/core/src/blocks/Table/block.ts | head -n1 | cut -d: -f1)
start=$((line-40)); end=$((line+120))
sed -n "${start},${end}p" packages/core/src/blocks/Table/block.ts

echo
# 2) Inspect schema/blocks/types.ts where tableContent is defined
echo "== schema/blocks/types.ts: inspect around data for tableContent =="
rg -n 'type: "tableContent"|group: "tableContent"' packages/core/src/schema/blocks/types.ts
# show relevant regions around the first two hits we saw earlier (~315 and ~402)
sed -n '280,340p' packages/core/src/schema/blocks/types.ts
sed -n '360,440p' packages/core/src/schema/blocks/types.ts

echo
# 3) Inspect Table block/table node view for DOM structure around tbody/tableContent
echo "== Table/block.ts: inspect further down where BlockNoteTableView wraps TableView =="
# continue further down after earlier snippet; search for "tbody" or "table" references
rg -n "tbody|TableView|tableWrapper|data-node-type|data-content-type" packages/core/src/blocks/Table/block.ts
sed -n '220,520p' packages/core/src/blocks/Table/block.ts

Repository: TypeCellOS/BlockNote

Length of output: 17166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Find all references to tableParagraph node =="
rg -n "tableParagraph" packages/core -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Find all references to group: \"tableContent\" =="
rg -n "group:\\s*\"tableContent\"|tableContent\\+|tableContent\\b" packages/core/src/blocks/Table/block.ts packages/core/src/schema -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Where are data-node-type attributes set generically? =="
rg -n "data-node-type" packages/core/src/schema packages/core/src/pm-nodes packages/core/src/editor packages/core/src/ -S --glob '*.{ts,tsx,js,jsx}' | head -n 200

echo
echo "== Inspect createSpec/wrapping logic that assigns data-node-type =="
# Look for the code path that uses createDefaultBlockDOMOutputSpec or wrapInBlockStructure
rg -n "createDefaultBlockDOMOutputSpec|wrapInBlockStructure|setAttribute\\(\"data-node-type\"|data-node-type\\s*=\\s*\" \\+" packages/core/src/schema/blocks/createSpec.ts packages/core/src/schema/blocks -S || true

echo
echo "== Inspect createSpec.ts around data-node-type assignment (if present) =="
file="packages/core/src/schema/blocks/createSpec.ts"
if [ -f "$file" ]; then
  rg -n "data-node-type" "$file" -S || true
  # show a chunk around any match
  matchline=$(rg -n "data-node-type" "$file" -S | head -n1 | cut -d: -f1 || true)
  if [ -n "${matchline:-}" ]; then
    start=$((matchline-60)); end=$((matchline+60))
    sed -n "${start},${end}p" "$file"
  fi
fi

Repository: TypeCellOS/BlockNote

Length of output: 7782


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for node/view specs with name: \"tableContent\" =="
rg -n 'name:\s*["'\'']tableContent["'\'']' packages/core/src -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Search for data-node-type=tableContent assignment (setAttribute or template strings) =="
rg -n --fixed-strings 'data-node-type="tableContent"' packages/core/src -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n --fixed-strings 'data-node-type=tableContent' packages/core/src -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== Search for tableContent within pm-nodes / block wrappers =="
rg -n "tableContent" packages/core/src/pm-nodes -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n "tableContent" packages/core/src/schema/blocks -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n "tableContent" packages/core/src/schema -S --glob '*.{ts,tsx,js,jsx}' | head -n 100

echo
echo "== Inspect SideMenu logic to see what block.node corresponds to for tables =="
# Print a larger region around where the selector is used
sed -n '180,270p' packages/core/src/extensions/SideMenu/SideMenu.ts

echo
echo "== Inspect TableHandles logic to see how tableElement is determined =="
sed -n '1,220p' packages/core/src/extensions/TableHandles/TableHandles.ts

Repository: TypeCellOS/BlockNote

Length of output: 9726


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== SideMenu.ts: find where referencePos is used =="
rg -n "referencePos" packages/core/src/extensions/SideMenu/SideMenu.ts

echo
echo "== SideMenu.ts: inspect around referencePos usage =="
# show a couple windows around matches
while IFS=: read -r file line rest; do
  start=$((line-40)); end=$((line+80))
  echo "--- $file:$line ---"
  sed -n "${start},${end}p" "$file"
  echo
done < <(rg -n "referencePos" packages/core/src/extensions/SideMenu/SideMenu.ts | head -n 5)

echo "== Confirm no other data-node-type=tableContent occurrences in repo =="
rg -n --fixed-strings 'data-node-type=tableContent' packages/core -S --glob '*.{ts,tsx,js,jsx}' || true
rg -n --fixed-strings 'data-node-type=\"tableContent\"' packages/core -S --glob '*.{ts,tsx,js,jsx}' || true

echo
echo "== TableHandles.ts: find referencePosTable usage =="
rg -n "referencePosTable" packages/core/src/extensions/TableHandles/TableHandles.ts
sed -n '220,320p' packages/core/src/extensions/TableHandles/TableHandles.ts

echo
echo "== TableHandles.ts: inspect around where referencePosTable is used to position widgets =="
line=$(rg -n "referencePosTable" packages/core/src/extensions/TableHandles/TableHandles.ts | head -n1 | cut -d: -f1 || true)
if [ -n "${line:-}" ]; then
  start=$((line-60)); end=$((line+120))
  sed -n "${start},${end}p" packages/core/src/extensions/TableHandles/TableHandles.ts
fi

Repository: TypeCellOS/BlockNote

Length of output: 284


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect tableContentToNodes
echo "== blockToNode.ts: locate tableContentToNodes =="
rg -n "function tableContentToNodes|tableContentToNodes\\(" packages/core/src/api/nodeConversions/blockToNode.ts

line=$(rg -n "export function tableContentToNodes" packages/core/src/api/nodeConversions/blockToNode.ts | head -n1 | cut -d: -f1)
start=$((line-80)); end=$((line+200))
echo
echo "== blockToNode.ts: tableContentToNodes implementation =="
sed -n "${start},${end}p" packages/core/src/api/nodeConversions/blockToNode.ts

# Search for data-node-type mention in nodeConversions around table nodes
echo
echo "== Search: data-node-type in nodeConversions =="
rg -n "data-node-type" packages/core/src/api/nodeConversions -S || true

# Inspect how BlockNote wraps block content for node views (createSpec.ts)
echo
echo "== createSpec.ts: inspect wrapInBlockStructure / data-node-type assignment =="
file="packages/core/src/schema/blocks/createSpec.ts"
rg -n "wrapInBlockStructure|data-node-type" "$file" -S || true
# show small windows around the first occurrences
for l in $(rg -n "wrapInBlockStructure|data-node-type" "$file" -S | head -n 3 | cut -d: -f1); do
  start=$((l-60)); end=$((l+80))
  echo
  echo "---- $file:$l ----"
  sed -n "${start},${end}p" "$file"
done

# Inspect wrapInBlockStructure helper implementation
echo
echo "== schema/blocks/internal.ts: inspect wrapInBlockStructure =="
file2="packages/core/src/schema/blocks/internal.ts"
rg -n "function wrapInBlockStructure|wrapInBlockStructure" "$file2" -S || true
line2=$(rg -n "function wrapInBlockStructure" "$file2" -S | head -n1 | cut -d: -f1)
start=$((line2-80)); end=$((line2+200))
sed -n "${start},${end}p" "$file2"

# Inspect TableView node view in Table/block.ts: does it add data-node-type for tableParagraph?
echo
echo "== Table/block.ts: search within file for tableContent-related DOM attributes =="
rg -n "tableParagraph|data-node-type|data-content-type|data-content-type.*table" packages/core/src/blocks/Table/block.ts -S

Repository: TypeCellOS/BlockNote

Length of output: 10763


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect packages/core/src/pm-nodes/BlockContainer.ts data-node-type logic =="
sed -n '1,120p' packages/core/src/pm-nodes/BlockContainer.ts
echo
sed -n '120,240p' packages/core/src/pm-nodes/BlockContainer.ts
echo
echo "== Inspect packages/core/src/pm-nodes/BlockGroup.ts data-node-type logic =="
sed -n '1,120p' packages/core/src/pm-nodes/BlockGroup.ts

echo
echo "== Inspect packages/core/src/schema/blocks/internal.ts wrapInBlockStructure =="
sed -n '1,220p' packages/core/src/schema/blocks/internal.ts

echo
echo "== Inspect packages/core/src/schema/blocks/createSpec.ts around wrapInBlockStructure usage =="
file="packages/core/src/schema/blocks/createSpec.ts"
rg -n "wrapInBlockStructure" "$file" -S
first=$(rg -n "wrapInBlockStructure" "$file" -S | head -n1 | cut -d: -f1)
start=$((first-80)); if [ "$start" -lt 1 ]; then start=1; fi
end=$((first+140))
sed -n "${start},${end}p" "$file"

echo
echo "== Search in createSpec.ts for explicit data-node-type mention =="
rg -n --fixed-strings "data-node-type" "$file" -S || true

Repository: TypeCellOS/BlockNote

Length of output: 16129


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "referencePosTable" packages/core/src/extensions/TableHandles/TableHandles.ts
line=$(rg -n "referencePosTable" packages/core/src/extensions/TableHandles/TableHandles.ts | head -n1 | cut -d: -f1)
start=$((line-80)); end=$((line+140))
sed -n "${start},${end}p" packages/core/src/extensions/TableHandles/TableHandles.ts

Repository: TypeCellOS/BlockNote

Length of output: 2352


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Repo-wide search for data-node-type=tableContent =="
rg -n --fixed-strings 'data-node-type="tableContent"' . -S || true
rg -n --fixed-strings 'data-node-type=tableContent' . -S || true

Repository: TypeCellOS/BlockNote

Length of output: 273


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# SideMenu: inspect where `block.node` comes from (getBlockFromMousePos) + what it contains.
echo "== SideMenu: inspect getBlockFromMousePos usage vicinity =="
rg -n "getBlockFromMousePos\\(" packages/core/src/extensions/SideMenu/SideMenu.ts
sed -n '1,200p' packages/core/src/extensions/SideMenu/SideMenu.ts

echo
echo "== Find definition of getBlockFromMousePos =="
file=$(rg -n "function getBlockFromMousePos|export function getBlockFromMousePos" packages/core/src -S --glob '*.{ts,tsx}' | head -n1 | cut -d: -f1)
line=$(rg -n "function getBlockFromMousePos|export function getBlockFromMousePos" "$file" -S --glob '*.{ts,tsx}' | head -n1 | cut -d: -f2)
start=$((line-60)); end=$((line+180))
sed -n "${start},${end}p" "$file"

echo
echo "== SideMenu: show around the selector and yPos computation =="
sed -n '220,280p' packages/core/src/extensions/SideMenu/SideMenu.ts

# TableHandles: inspect how `this.tableElement` is set and used to query tbody
echo
echo "== TableHandles: locate where this.tableElement is assigned =="
rg -n "this\\.tableElement\\s*=" packages/core/src/extensions/TableHandles/TableHandles.ts
line=$(rg -n "this\\.tableElement\\s*=" packages/core/src/extensions/TableHandles/TableHandles.ts | head -n1 | cut -d: -f1)
start=$((line-80)); end=$((line+160))
sed -n "${start},${end}p" packages/core/src/extensions/TableHandles/TableHandles.ts

echo
echo "== TableHandles: show around referencePosTable computation with tbody =="
# use the existing known line region around the earlier match
sed -n '540,620p' packages/core/src/extensions/TableHandles/TableHandles.ts

Repository: TypeCellOS/BlockNote

Length of output: 5709


Fix table side menu alignment: [data-node-type=tableContent] doesn’t match TableHandles’ <tbody>

SideMenu.ts (line 246) looks for blockNodeElement.querySelector("[data-node-type=tableContent]"), but the only occurrence of data-node-type="tableContent" in the repo is this line—table rendering doesn’t set that attribute. TableHandles.ts measures alignment from the real table body via this.tableElement!.querySelector("tbody") and referencePosTable = tableBody.getBoundingClientRect(), so the side menu’s y positioning won’t be based on the same element.

Update SideMenu to use the same DOM element as TableHandles (e.g., derive y from the table’s <tbody>/table wrapper) instead of [data-node-type=tableContent].

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/extensions/SideMenu/SideMenu.ts` at line 246, SideMenu is
querying a non-existent selector "[data-node-type=tableContent]" for table
positioning; update the logic in SideMenu.ts (where tableElement is set) to use
the same DOM node TableHandles uses (e.g., find the table element and then its
<tbody> via tableElement.querySelector("tbody") or the same table wrapper) and
derive the y-position from that element's getBoundingClientRect() (matching
referencePosTable calculation). Ensure you replace the
querySelector("[data-node-type=tableContent]") usage with a lookup for the real
table/<tbody> element and use that element for the side menu alignment
calculations so both SideMenu and TableHandles measure from the same node.

const yPos = tableElement
? blockContentBoundingBox.y + (tableElement.getBoundingClientRect().top - blockContentBoundingBox.top) / 2
: blockContentBoundingBox.y;
Comment on lines +245 to +249
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent use of .y and .top properties.

Line 248 mixes blockContentBoundingBox.y and blockContentBoundingBox.top in the same expression. While DOMRect.y and DOMRect.top are identical properties, mixing them reduces clarity and risks confusion during future refactoring.

♻️ Suggested refactor for consistency and clarity
-      const blockNodeElement = block.node;
-      const tableElement = blockNodeElement.querySelector("[data-node-type=tableContent]");      
-      const yPos = tableElement
-        ? blockContentBoundingBox.y + (tableElement.getBoundingClientRect().top - blockContentBoundingBox.top) / 2
-        : blockContentBoundingBox.y;
+      const blockNodeElement = block.node;
+      const tableElement = blockNodeElement.querySelector("[data-node-type=tableContent]");      
+      const yPos = tableElement
+        ? (blockContentBoundingBox.y + tableElement.getBoundingClientRect().y) / 2
+        : blockContentBoundingBox.y;

This algebraically equivalent form uses .y consistently and is clearer: the average of the two y-coordinates.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/extensions/SideMenu/SideMenu.ts` around lines 245 - 249,
The code in SideMenu.ts mixes DOMRect.y and DOMRect.top when computing yPos (see
blockContentBoundingBox, tableElement, and yPos), which reduces clarity; update
the expression to use the same property consistently (use .y throughout) and
compute the average of blockContentBoundingBox.y and
tableElement.getBoundingClientRect().top as needed so the math is clear and
algebraically equivalent, ensuring references remain to blockContentBoundingBox
and tableElement in the yPos calculation.

this.state = {
show: true,
referencePos: new DOMRect(
Expand All @@ -254,7 +259,7 @@ export class SideMenuView<
: (
this.pmView.dom.firstChild as HTMLElement
).getBoundingClientRect().x,
blockContentBoundingBox.y,
yPos,
blockContentBoundingBox.width,
blockContentBoundingBox.height,
),
Expand Down