fix: Allow indenting image blocks in lists with Tab#2781
Conversation
|
Someone is attempting to deploy a commit to the TypeCell Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughThe PR expands node-type predicates in ChangesList item nesting and unnesting support
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with 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.
Inline comments:
In `@packages/core/src/api/blockManipulation/commands/nestBlock/nestBlock.ts`:
- Line 28: The sink/lift predicates in nestBlock (used in the nestBlock command)
currently check for node.type.name === "listItem", which doesn't exist in our
BlockNote schema; update the predicate expressions in nestBlock (both
occurrences used to compute sink/lift ranges) to check for the actual list-item
node names like "bulletListItem" | "numberedListItem" | "checkListItem" |
"toggleListItem" or simply allow their wrapper nodes such as "blockContainer" /
"blockGroup" depending on intended behavior; modify the condition (e.g. replace
node.type.name === "listItem") to compare against the correct node names or
include an OR for the wrapper node names so list indentation (Tab/Shift+Tab)
works with BlockNote list types.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7307f433-3692-4e35-8090-eb06b882574e
📒 Files selected for processing (1)
packages/core/src/api/blockManipulation/commands/nestBlock/nestBlock.ts
| (node) => | ||
| node.childCount > 0 && | ||
| (node.type.name === "blockGroup" || node.type.name === "column"), // change 1 | ||
| (node.type.name === "blockGroup" || node.type.name === "column" || node.type.name === "listItem"), // change 1 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify listItem schema definition supports blockGroup/blockContainer children
# Search for listItem schema definition
echo "=== Searching for listItem schema definition ==="
rg -n -A 10 -B 2 'listItem.*spec|content.*listItem' --type=ts
# Search for blockGroup and blockContainer schema definitions
echo -e "\n=== Searching for blockGroup/blockContainer schema definitions ==="
rg -n -A 5 'blockGroup.*spec|blockContainer.*spec' --type=ts
# Look for schema files that might define node relationships
echo -e "\n=== Searching for schema definition files ==="
fd -e ts -e js schema --exec echo {} \; --exec head -50 {}Repository: TypeCellOS/BlockNote
Length of output: 15686
🏁 Script executed:
#!/bin/bash
# Find the actual ProseMirror node spec for "listItem" and inspect its "content" / children model.
set -euo pipefail
echo "=== Locate listItem node spec (node name / spec) ==="
rg -n --hidden --no-ignore-vcs '"listItem"|\\blistItem\\b' packages/core/src -S
echo -e "\n=== Look for ProseMirror NodeSpec definitions mentioning listItem ==="
rg -n --hidden --no-ignore-vcs 'NodeSpec|content:|group:|draggable:|isolating:|definitelyTyped|addAttributes|parseDOM|toDOM' packages/core/src/blocks/ListItem -S || true
echo -e "\n=== Inspect ListItem block implementation files ==="
fd -t f -e ts packages/core/src/blocks/ListItem -0 | xargs -0 -n1 echo
echo -e "\n=== Show getListItemContent.ts (where it assumes blockGroup children) ==="
sed -n '1,220p' packages/core/src/blocks/ListItem/getListItemContent.ts
echo -e "\n=== Find where the listItem node is created in schema/spec ==="
rg -n --hidden --no-ignore-vcs 'getListItemContent|listItemNode|schema\.nodes\["listItem"\]|schema\.nodes\[name\]' packages/core/src/blocks/ListItem -S
echo -e "\n=== Search for the listItem ProseMirror spec file under schema/ ==="
fd -t f -e ts packages/core/src/schema packages/core/src/blocks -0 | \
xargs -0 rg -n --hidden --no-ignore-vcs 'listItem' -S | head -n 200Repository: TypeCellOS/BlockNote
Length of output: 8594
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Open getListItemContent.ts (lines near earlier matches) ==="
sed -n '1,220p' packages/core/src/blocks/ListItem/getListItemContent.ts
echo -e "\n=== Search for actual ProseMirror node name/spec for 'listItem' in core schema code ==="
rg -n --hidden --no-ignore-vcs 'name:\s*["'\'']listItem["'\'']|nodeType.*listItem|schema\.nodes\[\s*["'\'']listItem["'\'']\s*\]|listItem\s*:\s*\{' packages/core/src -S
echo -e "\n=== Search for node spec content model referencing listItem ==="
rg -n --hidden --no-ignore-vcs 'listItem.*content:|content:.*listItem|prosemirror.*listItem|NodeSpec.*listItem' packages/core/src -S
echo -e "\n=== Inspect list item block spec files that might wrap/produce the ProseMirror listItem node ==="
for f in $(fd -t f packages/core/src/blocks/ListItem -0 --full-path | tr '\0' '\n' | head -n 50); do
echo "---- $f ----"
head -n 80 "$f"
doneRepository: TypeCellOS/BlockNote
Length of output: 5917
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Inspect nestBlock.ts around the predicate and structure creation ==="
sed -n '1,260p' packages/core/src/api/blockManipulation/commands/nestBlock/nestBlock.ts
echo -e "\n=== Inspect list item block specs (content model) ==="
for f in \
packages/core/src/blocks/ListItem/BulletListItem/block.ts \
packages/core/src/blocks/ListItem/NumberedListItem/block.ts \
packages/core/src/blocks/ListItem/CheckListItem/block.ts \
packages/core/src/blocks/ListItem/ToggleListItem/block.ts
do
echo -e "\n---- $f ----"
sed -n '1,120p' "$f"
done
echo -e "\n=== Search for ProseMirror node 'blockGroup'/'blockContainer' content models ==="
rg -n --hidden --no-ignore-vcs 'name:\s*["'\'']blockGroup["'\'']|name:\s*["'\'']blockContainer["'\'']' packages/core/src/blocks packages/core/src/schema -SRepository: TypeCellOS/BlockNote
Length of output: 20942
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Search for where ProseMirror node 'listItem' is defined in schema ==="
rg -n --hidden --no-ignore-vcs '"listItem"\s*:' packages/core/src/schema packages/core/src -S || true
rg -n --hidden --no-ignore-vcs 'pmSchema\.nodes\["listItem"\]|nodes\["listItem"\]|name:\s*["'"'"']listItem["'"'"']' packages/core/src -S || true
rg -n --hidden --no-ignore-vcs 'prosemirror-schema-list|schema-list' packages/core/src -S || true
echo -e "\n=== Search for building blocks / node specs that mention listItem as a node name ==="
rg -n --hidden --no-ignore-vcs 'listItem.*(content|group|blockGroup|blockContainer|child)' packages/core/src -S || true
echo -e "\n=== List files likely responsible for ProseMirror schema construction ==="
fd -t f --full-path packages/core/src/schema | head -n 200Repository: TypeCellOS/BlockNote
Length of output: 2984
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Find how createBlockConfig/content: 'inline' maps to ProseMirror node content model ==="
rg -n --hidden --no-ignore-vcs 'content:\s*["'\'']inline["'\'']|content:\s*{|\binline['\'"]' packages/core/src/schema -S
rg -n --hidden --no-ignore-vcs 'createBlockConfig|createBlockSpec|contentType|BlockSpec|content:' packages/core/src/schema/blocks packages/core/src/schema -S
echo -e "\n=== Inspect schema spec builder for blocks ==="
rg -n --hidden --no-ignore-vcs 'content.*inline|inline.*content|addToEnd|blockGroup|blockContainer' packages/core/src/schema/blocks -S || true
echo -e "\n=== Inspect createSpec.ts / internal.ts where node content is set ==="
for f in packages/core/src/schema/blocks/createSpec.ts packages/core/src/schema/blocks/internal.ts packages/core/src/schema/blocks/types.ts packages/core/src/schema/blocks/internal.ts; do
if [ -f "$f" ]; then
echo -e "\n---- $f ----"
sed -n '1,240p' "$f"
fi
doneRepository: TypeCellOS/BlockNote
Length of output: 244
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Find how createBlockConfig/content: 'inline' maps to ProseMirror node content model ==="
rg -n --hidden --no-ignore-vcs "content:\s*['\"]inline['\"]" packages/core/src/schema -S || true
rg -n --hidden --no-ignore-vcs "content:\s*inline" packages/core/src/schema -S || true
echo -e "\n=== Inspect schema spec builder for blocks ==="
rg -n --hidden --no-ignore-vcs "createBlockConfig|createBlockSpec|content:\s*|contentType|contentSpec|BlockSpec|blockGroup|blockContainer" packages/core/src/schema/blocks -S || true
echo -e "\n=== Inspect createSpec.ts / internal.ts where node content is set ==="
for f in \
packages/core/src/schema/blocks/createSpec.ts \
packages/core/src/schema/blocks/internal.ts \
packages/core/src/schema/blocks/types.ts
do
echo -e "\n---- $f ----"
sed -n '1,260p' "$f"
doneRepository: TypeCellOS/BlockNote
Length of output: 28252
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Search node specs for blockGroup and blockContainer (content + group) ==="
rg -n --hidden --no-ignore-vcs 'name:\s*["'\'']blockGroup["'\'']|name:\s*["'\'']blockContainer["'\'']|blockGroup:\s*\{|blockContainer:\s*\{' packages/core/src/schema packages/core/src -S || true
echo -e "\n=== Search for group definitions involving 'inline' ==="
rg -n --hidden --no-ignore-vcs 'group:\s*["'\'']inline["'\'']' packages/core/src/schema packages/core/src -S || true
echo -e "\n=== Search for node specs where listItem node might be customized ==="
rg -n --hidden --no-ignore-vcs 'listItem.*(content|group|parseHTML|renderHTML|addAttributes|isolating|defining)|name:\s*["'\'']listItem["'\'']' packages/core/src/schema packages/core/src -S || true
echo -e "\n=== Inspect schema/blocks/internal or schema/blocks/types for blockContainer/blockGroup content wiring ==="
rg -n --hidden --no-ignore-vcs 'blockGroup|blockContainer' packages/core/src/schema/schema.ts packages/core/src/schema/blocks -S | head -n 200 || trueRepository: TypeCellOS/BlockNote
Length of output: 1868
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Inspect pm-nodes/BlockGroup.ts ==="
sed -n '1,220p' packages/core/src/pm-nodes/BlockGroup.ts
echo -e "\n=== Inspect pm-nodes/BlockContainer.ts ==="
sed -n '1,260p' packages/core/src/pm-nodes/BlockContainer.ts
echo -e "\n=== Search for ProseMirror pm-nodes named listItem ==="
rg -n --hidden --no-ignore-vcs 'name:\s*["'\'']listItem["'\'']|listItem' packages/core/src/pm-nodes packages/core/src/schema packages/core/src/blocks -S || true
echo -e "\n=== List files in pm-nodes to locate potential list nodes ==="
ls -1 packages/core/src/pm-nodesRepository: TypeCellOS/BlockNote
Length of output: 6620
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Global search for ProseMirror node name \"listItem\" ==="
rg -n --hidden --no-ignore-vcs 'name:\s*["'\'']listItem["'\'']|nodes\[\s*["'\'']listItem["'\'']\]|"listItem"' packages/core/src -S || true
echo -e "\n=== Search for any Node.create(... name: \"listItem\" ) patterns ==="
rg -n --hidden --no-ignore-vcs 'Node\.create<[^>]*>|Node\.create\(|name:\s*["'\'']listItem["'\'']' packages/core/src -S | head -n 200
echo -e "\n=== Search for list container/pair nodes (bulletList/numberedList) in core blocks ==="
rg -n --hidden --no-ignore-vcs 'type:\s*["'\''](bulletList|numberedList|orderedList|unorderedList|list)[^"'\'']*["'\'']|create.*List' packages/core/src/blocks packages/core/src -S || true
echo -e "\n=== Search for 'li' parsing utilities that might create PM 'listItem' ==="
rg -n --hidden --no-ignore-vcs 'prosemirror.*listItem|schema-list|listItem.*insert|listItem.*create' packages/core/src -S || trueRepository: TypeCellOS/BlockNote
Length of output: 23234
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Search for Tiptap list extension usage in packages/core/src ==="
rg -n --hidden --no-ignore-vcs '`@tiptap/`(extension-)?list|ExtensionList|listItem|orderedList|bulletList' packages/core/src -S || true
echo -e "\n=== Inspect where pmSchema is constructed/extended ==="
rg -n --hidden --no-ignore-vcs 'pmSchema|prosemirror schema|new Schema|Schema\.create|schema\.nodes' packages/core/src/editor packages/core/src/schema packages/core/src -S | head -n 200
echo -e "\n=== List pm-nodes index.ts exports ==="
sed -n '1,200p' packages/core/src/pm-nodes/index.tsRepository: TypeCellOS/BlockNote
Length of output: 34675
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Inspect BlockNoteEditor.ts around pmSchema creation/initialization ==="
sed -n '420,720p' packages/core/src/editor/BlockNoteEditor.ts
echo -e "\n=== Search for list-related tiptap extensions imports/usages in BlockNoteEditor.ts ==="
rg -n --hidden --no-ignore-vcs 'listItem|ExtensionList|orderedList|bulletList|tiptap-extensions/.*list|`@tiptap/`(extension-)?list' packages/core/src/editor/BlockNoteEditor.ts packages/core/src/editor -S || trueRepository: TypeCellOS/BlockNote
Length of output: 14719
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Inspect ExtensionManager.getTiptapExtensions implementation ==="
rg -n --hidden --no-ignore-vcs 'class ExtensionManager|getTiptapExtensions' packages/core/src/editor packages/core/src -S
rg -n --hidden --no-ignore-vcs 'getTiptapExtensions\(' packages/core/src/editor packages/core/src -S
echo -e "\n=== Open ExtensionManager file(s) around getTiptapExtensions ==="
f=$(rg -l --hidden --no-ignore-vcs 'getTiptapExtensions' packages/core/src/editor | head -n 20)
echo "Files: $f"
for x in $f; do
echo -e "\n---- $x ----"
sed -n '1,260p' "$x"
done
echo -e "\n=== Search for tiptap list extension in ExtensionManager and related files ==="
rg -n --hidden --no-ignore-vcs '`@tiptap/extension-`(bullet|ordered|list|list-item)|ExtensionList|listItem' packages/core/src/editor packages/core/src -S || trueRepository: TypeCellOS/BlockNote
Length of output: 23430
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== List ExtensionManager extensions files ==="
ls -1 packages/core/src/editor/managers/ExtensionManager
echo -e "\n=== Inspect extensions.js (default extension lists) ==="
sed -n '1,260p' packages/core/src/editor/managers/ExtensionManager/extensions.js
echo -e "\n=== Search default tiptap extensions for listItem/list extension ==="
rg -n --hidden --no-ignore-vcs 'listItem|extension-list|bulletList|orderedList|list-item|tiptap.*list' packages/core/src/editor/managers/ExtensionManager/extensions.js packages/core/src/editor/managers/ExtensionManager -S || true
echo -e "\n=== Inspect getDefaultTiptapExtensions definition usages ==="
rg -n --hidden --no-ignore-vcs 'getDefaultTiptapExtensions|getDefaultExtensions' packages/core/src/editor/managers/ExtensionManager -SRepository: TypeCellOS/BlockNote
Length of output: 327
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Inspect ExtensionManager/extensions.ts ==="
sed -n '1,260p' packages/core/src/editor/managers/ExtensionManager/extensions.ts
echo -e "\n=== Search within extensions.ts for list-related tiptap extensions ==="
rg -n --hidden --no-ignore-vcs '(listItem|extension-list|orderedList|bulletList|list-item|tiptap.*list)' packages/core/src/editor/managers/ExtensionManager/extensions.ts packages/core/src/editor/managers/ExtensionManager -S || true
echo -e "\n=== Inspect ExtensionManager/index.ts for getDefaultTiptapExtensions usage ==="
rg -n --hidden --no-ignore-vcs 'getDefaultTiptapExtensions|getDefaultExtensions' packages/core/src/editor/managers/ExtensionManager/index.ts
sed -n '260,420p' packages/core/src/editor/managers/ExtensionManager/index.tsRepository: TypeCellOS/BlockNote
Length of output: 12325
Fix nestBlock predicates to use BlockNote list-item node names (not ProseMirror listItem)
nestBlock.ts adds node.type.name === "listItem" to the sink/lift range predicates (lines 28 and 172), but this BlockNote schema does not define any ProseMirror node named listItem (default tiptap nodes are doc, blockGroup, and blockContainer; list-item blocks are bulletListItem / numberedListItem / checkListItem / toggleListItem, each with content: "inline"). As written, the listItem predicate won’t match anything, so list indentation for nested blocks won’t rely on schema hierarchy here.
Update the predicate(s) to target the actual list-item node types (or the correct wrapper nodes, e.g. the surrounding blockContainer / blockGroup) that should be allowed as nesting parents for Tab/Shift+Tab.
🤖 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/api/blockManipulation/commands/nestBlock/nestBlock.ts` at
line 28, The sink/lift predicates in nestBlock (used in the nestBlock command)
currently check for node.type.name === "listItem", which doesn't exist in our
BlockNote schema; update the predicate expressions in nestBlock (both
occurrences used to compute sink/lift ranges) to check for the actual list-item
node names like "bulletListItem" | "numberedListItem" | "checkListItem" |
"toggleListItem" or simply allow their wrapper nodes such as "blockContainer" /
"blockGroup" depending on intended behavior; modify the condition (e.g. replace
node.type.name === "listItem") to compare against the correct node names or
include an OR for the wrapper node names so list indentation (Tab/Shift+Tab)
works with BlockNote list types.
Fixes #2545
Expands BlockNote nesting range check to include listItem nodes.
Summary by CodeRabbit