Files
outline/shared/editor/nodes/CheckboxList.ts
huiseo 9ec5c473f1 fix: prevent list conversion inside heading nodes (#10462)
* fix: prevent list conversion inside heading nodes

Fixes a bug where typing list syntax (e.g., "1. ", "* ", "[ ]")
inside heading nodes would incorrectly trigger list conversion.

Previously, when a user selected H1 from the "/" menu and typed
"1. " followed by a space, the OrderedList inputRule would attempt
to convert the heading into an ordered list, causing a conflict
since headings can only contain inline content.

Changes:
- Add isInHeading utility to detect if selection is inside a heading
- Create safeWrappingInputRule wrapper that prevents list conversion
  when inside heading nodes
- Apply the fix to OrderedList, BulletList, and CheckboxList nodes

This ensures that list markdown syntax is preserved as plain text
when typed within headings, matching expected editor behavior.

* refactor: extract listWrappingInputRule to shared helper

Refactored duplicated safeWrappingInputRule implementations across
BulletList, OrderedList, and CheckboxList into a single shared helper
function named listWrappingInputRule in shared/editor/lib/listInputRule.ts.

This reduces code duplication and follows the same pattern as other
input rule helpers like markInputRule.

Changes:
- Create shared/editor/lib/listInputRule.ts with listWrappingInputRule
- Update BulletList.ts to use shared helper
- Update OrderedList.ts to use shared helper
- Update CheckboxList.ts to use shared helper
- Restore .env.development file

Co-Authored-By: huiseo <hui.seo@gmail.com>
2025-10-23 20:23:47 -04:00

52 lines
1.2 KiB
TypeScript

import {
NodeSpec,
NodeType,
Schema,
Node as ProsemirrorNode,
} from "prosemirror-model";
import toggleList from "../commands/toggleList";
import { MarkdownSerializerState } from "../lib/markdown/serializer";
import { listWrappingInputRule } from "../lib/listInputRule";
import Node from "./Node";
export default class CheckboxList extends Node {
get name() {
return "checkbox_list";
}
get schema(): NodeSpec {
return {
group: "block list",
content: "checkbox_item+",
toDOM: () => ["ul", { class: this.name }, 0],
parseDOM: [
{
tag: `[class="${this.name}"]`,
},
],
};
}
keys({ type, schema }: { type: NodeType; schema: Schema }) {
return {
"Shift-Ctrl-7": toggleList(type, schema.nodes.checkbox_item),
};
}
commands({ type, schema }: { type: NodeType; schema: Schema }) {
return () => toggleList(type, schema.nodes.checkbox_item);
}
inputRules({ type }: { type: NodeType }) {
return [listWrappingInputRule(/^-?\s*(\[ \])\s$/i, type)];
}
toMarkdown(state: MarkdownSerializerState, node: ProsemirrorNode) {
state.renderList(node, " ", () => "- ");
}
parseMarkdown() {
return { block: "checkbox_list" };
}
}