@blankdotpage/cake 0.1.51 → 0.1.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/heading/heading.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,oBAAoB,CAAC;AAiV5B,eAAO,MAAM,gBAAgB,EAAE,aA2M9B,CAAC"}
1
+ {"version":3,"file":"heading.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/heading/heading.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,oBAAoB,CAAC;AA2W5B,eAAO,MAAM,gBAAgB,EAAE,aAwM9B,CAAC"}
@@ -157,10 +157,10 @@ function handleMultilineInsertInHeading(state, text) {
157
157
  },
158
158
  };
159
159
  }
160
- function shouldExitHeadingOnLineBreak(state) {
161
- const { source, selection, map } = state;
160
+ function handleLineBreakInHeading(state) {
161
+ const { source, selection, map, runtime } = state;
162
162
  if (selection.start !== selection.end) {
163
- return false;
163
+ return null;
164
164
  }
165
165
  const cursorPos = selection.start;
166
166
  const sourcePos = map.cursorToSource(cursorPos, "forward");
@@ -172,11 +172,33 @@ function shouldExitHeadingOnLineBreak(state) {
172
172
  const lineContent = source.slice(lineStart, lineEnd);
173
173
  const match = lineContent.match(HEADING_PATTERN);
174
174
  if (!match) {
175
- return false;
175
+ return null;
176
176
  }
177
177
  const marker = match[0];
178
178
  const contentStart = lineStart + marker.length;
179
- return sourcePos >= contentStart && sourcePos <= lineEnd;
179
+ if (sourcePos < contentStart || sourcePos > lineEnd) {
180
+ return null;
181
+ }
182
+ // Enter at the visual start of a heading should create a paragraph above
183
+ // the heading, not leave an empty heading wrapper behind.
184
+ const beforeCursor = source.slice(contentStart, sourcePos);
185
+ if (beforeCursor.trim().length === 0) {
186
+ const nextSource = source.slice(0, lineStart) + "\n" + source.slice(lineStart);
187
+ const next = runtime.createState(nextSource);
188
+ // Match native textarea behavior when pressing Enter at line start:
189
+ // insert a newline above and keep the caret with the moved line.
190
+ const caretSourcePos = lineStart + 1;
191
+ const caretCursor = next.map.sourceToCursor(caretSourcePos, "forward");
192
+ return {
193
+ source: nextSource,
194
+ selection: {
195
+ start: caretCursor.cursorOffset,
196
+ end: caretCursor.cursorOffset,
197
+ affinity: caretCursor.affinity,
198
+ },
199
+ };
200
+ }
201
+ return { type: "exit-block-wrapper" };
180
202
  }
181
203
  function handleToggleHeading(state, targetLevel) {
182
204
  const { source, selection, map, runtime } = state;
@@ -272,10 +294,7 @@ export const headingExtension = (editor) => {
272
294
  return handleDeleteBackward(state);
273
295
  }
274
296
  if (command.type === "insert-line-break") {
275
- if (shouldExitHeadingOnLineBreak(state)) {
276
- return { type: "exit-block-wrapper" };
277
- }
278
- return null;
297
+ return handleLineBreakInHeading(state);
279
298
  }
280
299
  if (command.type === "insert") {
281
300
  const multiline = handleMultilineInsertInHeading(state, command.text);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blankdotpage/cake",
3
- "version": "0.1.51",
3
+ "version": "0.1.53",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",