@hufe921/canvas-editor 0.9.125 → 0.9.127

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ ## [0.9.127](https://github.com/Hufe921/canvas-editor/compare/v0.9.126...v0.9.127) (2026-02-18)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * format elements error in executeComputeElementListHeight api #1356 ([6fe3e70](https://github.com/Hufe921/canvas-editor/commit/6fe3e70d801a34337814e936ebe83349fe8d2684)), closes [#1356](https://github.com/Hufe921/canvas-editor/issues/1356)
7
+ * move cursor to the visible range boundary error ([2c01b92](https://github.com/Hufe921/canvas-editor/commit/2c01b929be8bd58560bb3c1c99292f0b4fff4eae))
8
+
9
+
10
+
11
+ ## [0.9.126](https://github.com/Hufe921/canvas-editor/compare/v0.9.125...v0.9.126) (2026-02-12)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * adjusted image rowFlex when converting HTML to elements #1354 ([3fe395e](https://github.com/Hufe921/canvas-editor/commit/3fe395e7c0e669d5d93bca673f9429faa20e2aeb)), closes [#1354](https://github.com/Hufe921/canvas-editor/issues/1354)
17
+ * cursor positioning when clicking control postfix #1353 ([ea650f6](https://github.com/Hufe921/canvas-editor/commit/ea650f6520b194d76458fbe33b88b01f901db4bc)), closes [#1353](https://github.com/Hufe921/canvas-editor/issues/1353)
18
+ * restore titleId when splitting/merging title #921 #1337 ([0b659ef](https://github.com/Hufe921/canvas-editor/commit/0b659ef9ff9d9562880dedba86e0c0540ea90c65)), closes [#921](https://github.com/Hufe921/canvas-editor/issues/921) [#1337](https://github.com/Hufe921/canvas-editor/issues/1337)
19
+
20
+
21
+ ### Chores
22
+
23
+ * add claude settings ([99de4e4](https://github.com/Hufe921/canvas-editor/commit/99de4e416e16b970b23d770319f278a9071ec4e7))
24
+ * update README.md ([afa05b2](https://github.com/Hufe921/canvas-editor/commit/afa05b2272d1c093ac02f948375e707291be5439))
25
+
26
+
27
+ ### Features
28
+
29
+ * add compute elements height and remaining page height api #1213 ([f5e80f9](https://github.com/Hufe921/canvas-editor/commit/f5e80f99f8505c57bf36f8b9c8e948a0b29cf6d8)), closes [#1213](https://github.com/Hufe921/canvas-editor/issues/1213)
30
+ * implement list number style inheritance with config option #727 ([0b99406](https://github.com/Hufe921/canvas-editor/commit/0b994068723c85bff504e04470ae82ee241b894e)), closes [#727](https://github.com/Hufe921/canvas-editor/issues/727)
31
+
32
+
33
+
1
34
  ## [0.9.125](https://github.com/Hufe921/canvas-editor/compare/v0.9.124...v0.9.125) (2026-02-07)
2
35
 
3
36
 
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  <h1 align="center">canvas-editor</h1>
2
2
 
3
+ <p align="center">
4
+ <a href="https://trendshift.io/repositories/8401" target="_blank"><img src="https://trendshift.io/api/badge/repositories/8401" alt="Hufe921%2Fcanvas-editor | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
5
+ </p>
6
+
3
7
  <p align="center">
4
8
  <a href="https://www.npmjs.com/package/@hufe921/canvas-editor" target="_blank"><img src="https://img.shields.io/npm/v/@hufe921/canvas-editor.svg?sanitize=true" alt="Version"></a>
5
9
  <a href="https://github.com/hufe921/canvas-editor/actions" target="_blank">
@@ -23,7 +23,7 @@ var __publicField = (obj, key, value) => {
23
23
  return value;
24
24
  };
25
25
  var index = "";
26
- const version = "0.9.125";
26
+ const version = "0.9.127";
27
27
  var MaxHeightRatio;
28
28
  (function(MaxHeightRatio2) {
29
29
  MaxHeightRatio2["HALF"] = "half";
@@ -463,163 +463,6 @@ function scrollIntoView(container, selected) {
463
463
  container.scrollTop = bottom - container.clientHeight;
464
464
  }
465
465
  }
466
- var browser = { exports: {} };
467
- var process = browser.exports = {};
468
- var cachedSetTimeout;
469
- var cachedClearTimeout;
470
- function defaultSetTimout() {
471
- throw new Error("setTimeout has not been defined");
472
- }
473
- function defaultClearTimeout() {
474
- throw new Error("clearTimeout has not been defined");
475
- }
476
- (function() {
477
- try {
478
- if (typeof setTimeout === "function") {
479
- cachedSetTimeout = setTimeout;
480
- } else {
481
- cachedSetTimeout = defaultSetTimout;
482
- }
483
- } catch (e) {
484
- cachedSetTimeout = defaultSetTimout;
485
- }
486
- try {
487
- if (typeof clearTimeout === "function") {
488
- cachedClearTimeout = clearTimeout;
489
- } else {
490
- cachedClearTimeout = defaultClearTimeout;
491
- }
492
- } catch (e) {
493
- cachedClearTimeout = defaultClearTimeout;
494
- }
495
- })();
496
- function runTimeout(fun) {
497
- if (cachedSetTimeout === setTimeout) {
498
- return setTimeout(fun, 0);
499
- }
500
- if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
501
- cachedSetTimeout = setTimeout;
502
- return setTimeout(fun, 0);
503
- }
504
- try {
505
- return cachedSetTimeout(fun, 0);
506
- } catch (e) {
507
- try {
508
- return cachedSetTimeout.call(null, fun, 0);
509
- } catch (e2) {
510
- return cachedSetTimeout.call(this, fun, 0);
511
- }
512
- }
513
- }
514
- function runClearTimeout(marker) {
515
- if (cachedClearTimeout === clearTimeout) {
516
- return clearTimeout(marker);
517
- }
518
- if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
519
- cachedClearTimeout = clearTimeout;
520
- return clearTimeout(marker);
521
- }
522
- try {
523
- return cachedClearTimeout(marker);
524
- } catch (e) {
525
- try {
526
- return cachedClearTimeout.call(null, marker);
527
- } catch (e2) {
528
- return cachedClearTimeout.call(this, marker);
529
- }
530
- }
531
- }
532
- var queue = [];
533
- var draining = false;
534
- var currentQueue;
535
- var queueIndex = -1;
536
- function cleanUpNextTick() {
537
- if (!draining || !currentQueue) {
538
- return;
539
- }
540
- draining = false;
541
- if (currentQueue.length) {
542
- queue = currentQueue.concat(queue);
543
- } else {
544
- queueIndex = -1;
545
- }
546
- if (queue.length) {
547
- drainQueue();
548
- }
549
- }
550
- function drainQueue() {
551
- if (draining) {
552
- return;
553
- }
554
- var timeout = runTimeout(cleanUpNextTick);
555
- draining = true;
556
- var len = queue.length;
557
- while (len) {
558
- currentQueue = queue;
559
- queue = [];
560
- while (++queueIndex < len) {
561
- if (currentQueue) {
562
- currentQueue[queueIndex].run();
563
- }
564
- }
565
- queueIndex = -1;
566
- len = queue.length;
567
- }
568
- currentQueue = null;
569
- draining = false;
570
- runClearTimeout(timeout);
571
- }
572
- process.nextTick = function(fun) {
573
- var args = new Array(arguments.length - 1);
574
- if (arguments.length > 1) {
575
- for (var i = 1; i < arguments.length; i++) {
576
- args[i - 1] = arguments[i];
577
- }
578
- }
579
- queue.push(new Item(fun, args));
580
- if (queue.length === 1 && !draining) {
581
- runTimeout(drainQueue);
582
- }
583
- };
584
- function Item(fun, array) {
585
- this.fun = fun;
586
- this.array = array;
587
- }
588
- Item.prototype.run = function() {
589
- this.fun.apply(null, this.array);
590
- };
591
- process.title = "browser";
592
- process.browser = true;
593
- process.env = {};
594
- process.argv = [];
595
- process.version = "";
596
- process.versions = {};
597
- function noop() {
598
- }
599
- process.on = noop;
600
- process.addListener = noop;
601
- process.once = noop;
602
- process.off = noop;
603
- process.removeListener = noop;
604
- process.removeAllListeners = noop;
605
- process.emit = noop;
606
- process.prependListener = noop;
607
- process.prependOnceListener = noop;
608
- process.listeners = function(name) {
609
- return [];
610
- };
611
- process.binding = function(name) {
612
- throw new Error("process.binding is not supported");
613
- };
614
- process.cwd = function() {
615
- return "/";
616
- };
617
- process.chdir = function(dir) {
618
- throw new Error("process.chdir is not supported");
619
- };
620
- process.umask = function() {
621
- return 0;
622
- };
623
466
  const CURSOR_AGENT_OFFSET_HEIGHT = 12;
624
467
  const defaultCursorOption = {
625
468
  width: 1,
@@ -4095,6 +3938,9 @@ var ListStyle;
4095
3938
  ListStyle2["DECIMAL"] = "decimal";
4096
3939
  ListStyle2["CHECKBOX"] = "checkbox";
4097
3940
  })(ListStyle || (ListStyle = {}));
3941
+ const defaultListOption = {
3942
+ inheritStyle: false
3943
+ };
4098
3944
  const ulStyleMapping = {
4099
3945
  [UlStyle.DISC]: "\u2022",
4100
3946
  [UlStyle.CIRCLE]: "\u25E6",
@@ -4480,6 +4326,7 @@ function mergeOption(options = {}) {
4480
4326
  const graffitiOptions = __spreadValues(__spreadValues({}, defaultGraffitiOption), options.graffiti);
4481
4327
  const labelOptions = __spreadValues(__spreadValues({}, defaultLabelOption), options.label);
4482
4328
  const imgCaptionOptions = __spreadValues(__spreadValues({}, defaultImgCaptionOption), options.imgCaption);
4329
+ const listOptions = __spreadValues(__spreadValues({}, defaultListOption), options.list);
4483
4330
  const modeRuleOption = {
4484
4331
  print: __spreadValues(__spreadValues({}, defaultModeRuleOption.print), (_a = options.modeRule) == null ? void 0 : _a.print),
4485
4332
  readonly: __spreadValues(__spreadValues({}, defaultModeRuleOption.readonly), (_b = options.modeRule) == null ? void 0 : _b.readonly),
@@ -4555,7 +4402,8 @@ function mergeOption(options = {}) {
4555
4402
  modeRule: modeRuleOption,
4556
4403
  graffiti: graffitiOptions,
4557
4404
  label: labelOptions,
4558
- imgCaption: imgCaptionOptions
4405
+ imgCaption: imgCaptionOptions,
4406
+ list: listOptions
4559
4407
  });
4560
4408
  }
4561
4409
  function unzipElementList(elementList) {
@@ -5743,7 +5591,8 @@ function getElementListByHTML(htmlText, options) {
5743
5591
  width,
5744
5592
  height,
5745
5593
  value: src,
5746
- type: ElementType.IMAGE
5594
+ type: ElementType.IMAGE,
5595
+ rowFlex: convertTextAlignToRowFlex(node.parentElement)
5747
5596
  });
5748
5597
  }
5749
5598
  } else if (node.nodeName === "VIDEO") {
@@ -6410,7 +6259,7 @@ class Cursor {
6410
6259
  } else {
6411
6260
  this._clearBlinkTimeout();
6412
6261
  }
6413
- browser.exports.nextTick(() => {
6262
+ nextTick(() => {
6414
6263
  this.moveCursorToVisible({
6415
6264
  cursorPosition,
6416
6265
  direction: parseInt(oldTop) > cursorTop ? MoveDirection.UP : MoveDirection.DOWN
@@ -6426,10 +6275,6 @@ class Cursor {
6426
6275
  if (!cursorPosition || !direction)
6427
6276
  return;
6428
6277
  const { pageNo, coordinate: { leftTop, leftBottom } } = cursorPosition;
6429
- const prePageY = pageNo * (this.draw.getHeight() + this.draw.getPageGap()) + this.container.getBoundingClientRect().top;
6430
- const isUp = direction === MoveDirection.UP;
6431
- const x = leftBottom[0];
6432
- const y = isUp ? leftTop[1] + prePageY : leftBottom[1] + prePageY;
6433
6278
  const scrollContainer = findScrollContainer(this.container);
6434
6279
  const rect = {
6435
6280
  left: 0,
@@ -6437,7 +6282,8 @@ class Cursor {
6437
6282
  top: 0,
6438
6283
  bottom: 0
6439
6284
  };
6440
- if (scrollContainer === document.documentElement) {
6285
+ const isDocumentScroll = scrollContainer === document.documentElement;
6286
+ if (isDocumentScroll) {
6441
6287
  rect.right = window.innerWidth;
6442
6288
  rect.bottom = window.innerHeight;
6443
6289
  } else {
@@ -6447,6 +6293,10 @@ class Cursor {
6447
6293
  rect.top = top;
6448
6294
  rect.bottom = bottom;
6449
6295
  }
6296
+ const prePageY = pageNo * (this.draw.getHeight() + this.draw.getPageGap()) + this.container.getBoundingClientRect().top;
6297
+ const isUp = direction === MoveDirection.UP;
6298
+ const x = leftBottom[0] + (isDocumentScroll ? 0 : rect.left);
6299
+ const y = isUp ? leftTop[1] + prePageY : leftBottom[1] + prePageY;
6450
6300
  const { maskMargin } = this.options;
6451
6301
  rect.top += maskMargin[0];
6452
6302
  rect.bottom -= maskMargin[2];
@@ -7238,6 +7088,7 @@ function backspaceHideElement(host) {
7238
7088
  }
7239
7089
  }
7240
7090
  function backspace(evt, host) {
7091
+ var _a;
7241
7092
  const draw = host.getDraw();
7242
7093
  if (draw.isReadonly())
7243
7094
  return;
@@ -7292,12 +7143,23 @@ function backspace(evt, host) {
7292
7143
  if (isCollapsed && startElement.rowFlex && startElement.value === ZERO) {
7293
7144
  const rowFlexElementList = rangeManager.getRangeRowElementList();
7294
7145
  if (rowFlexElementList) {
7295
- const preElement = elementList[startIndex - 1];
7146
+ const preElement2 = elementList[startIndex - 1];
7296
7147
  rowFlexElementList.forEach((element) => {
7297
- element.rowFlex = preElement == null ? void 0 : preElement.rowFlex;
7148
+ element.rowFlex = preElement2 == null ? void 0 : preElement2.rowFlex;
7298
7149
  });
7299
7150
  }
7300
7151
  }
7152
+ const preElement = startElement.value === ZERO ? elementList[startIndex - 1] : startElement;
7153
+ const nextElement = elementList[endIndex + 1];
7154
+ if ((preElement == null ? void 0 : preElement.titleId) && (nextElement == null ? void 0 : nextElement.titleId) && preElement.level === nextElement.level && preElement.titleId !== nextElement.titleId) {
7155
+ const preTitleId = preElement.titleId;
7156
+ const nextTitleId = nextElement.titleId;
7157
+ let nextIndex = endIndex + 1;
7158
+ while (nextIndex < elementList.length && ((_a = elementList[nextIndex]) == null ? void 0 : _a.titleId) === nextTitleId) {
7159
+ elementList[nextIndex].titleId = preTitleId;
7160
+ nextIndex++;
7161
+ }
7162
+ }
7301
7163
  if (!isCollapsed) {
7302
7164
  draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex);
7303
7165
  } else {
@@ -7420,7 +7282,7 @@ function del(evt, host) {
7420
7282
  }
7421
7283
  }
7422
7284
  function enter(evt, host) {
7423
- var _a, _b, _c, _d, _e;
7285
+ var _a, _b, _c, _d, _e, _f, _g;
7424
7286
  const draw = host.getDraw();
7425
7287
  if (draw.isReadonly())
7426
7288
  return;
@@ -7478,6 +7340,14 @@ function enter(evt, host) {
7478
7340
  const { index: index2 } = cursorPosition;
7479
7341
  if (isCollapsed) {
7480
7342
  draw.spliceElementList(elementList, index2 + 1, 0, [enterText]);
7343
+ if (endElement.titleId && ((_f = elementList[index2 + 2]) == null ? void 0 : _f.titleId) === endElement.titleId) {
7344
+ const newTitleId = getUUID();
7345
+ let nextIndex = index2 + 2;
7346
+ while (nextIndex < elementList.length && ((_g = elementList[nextIndex]) == null ? void 0 : _g.titleId) === endElement.titleId) {
7347
+ elementList[nextIndex].titleId = newTitleId;
7348
+ nextIndex++;
7349
+ }
7350
+ }
7481
7351
  } else {
7482
7352
  draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex, [enterText]);
7483
7353
  }
@@ -14609,6 +14479,12 @@ class Control {
14609
14479
  newElement: elementList[startIndex - 1]
14610
14480
  };
14611
14481
  }
14482
+ if (startIndex === elementList.length - 1) {
14483
+ return {
14484
+ newIndex: startIndex,
14485
+ newElement: elementList[startIndex]
14486
+ };
14487
+ }
14612
14488
  startIndex++;
14613
14489
  }
14614
14490
  } else if (element.controlComponent === ControlComponent.PREFIX || element.controlComponent === ControlComponent.PRE_TEXT) {
@@ -17285,6 +17161,26 @@ class ListParticle {
17285
17161
  }
17286
17162
  return listStyleMap;
17287
17163
  }
17164
+ findStyledElement(elementList) {
17165
+ let styleElement = elementList[0];
17166
+ for (let i = 1; i < elementList.length; i++) {
17167
+ const element = elementList[i];
17168
+ if (element.font || element.size || element.bold || element.italic) {
17169
+ styleElement = element;
17170
+ break;
17171
+ }
17172
+ }
17173
+ return styleElement;
17174
+ }
17175
+ getListFontStyle(elementList, scale) {
17176
+ if (this.options.list.inheritStyle) {
17177
+ const styleElement = this.findStyledElement(elementList);
17178
+ return this.draw.getElementFont(styleElement, scale);
17179
+ } else {
17180
+ const { defaultFont, defaultSize } = this.options;
17181
+ return `${defaultSize * scale}px ${defaultFont}`;
17182
+ }
17183
+ }
17288
17184
  getListStyleWidth(ctx, listElementList) {
17289
17185
  const { scale, checkbox } = this.options;
17290
17186
  const startElement = listElementList[0];
@@ -17302,8 +17198,11 @@ class ListParticle {
17302
17198
  }, 0);
17303
17199
  if (!count)
17304
17200
  return 0;
17201
+ ctx.save();
17202
+ ctx.font = this.getListFontStyle(listElementList, scale);
17305
17203
  const text = `${this.MEASURE_BASE_TEXT.repeat(String(count).length)}${KeyMap.PERIOD}`;
17306
17204
  const textMetrics = ctx.measureText(text);
17205
+ ctx.restore();
17307
17206
  return Math.ceil((textMetrics.width + this.LIST_GAP) * scale);
17308
17207
  }
17309
17208
  drawListStyle(ctx, row, position) {
@@ -17313,7 +17212,7 @@ class ListParticle {
17313
17212
  if (startElement.value !== ZERO || startElement.listWrap)
17314
17213
  return;
17315
17214
  let tabWidth = 0;
17316
- const { defaultTabWidth, scale, defaultFont, defaultSize } = this.options;
17215
+ const { defaultTabWidth, scale } = this.options;
17317
17216
  for (let i = 1; i < elementList.length; i++) {
17318
17217
  const element = elementList[i];
17319
17218
  if ((element == null ? void 0 : element.type) !== ElementType.TAB)
@@ -17353,7 +17252,7 @@ class ListParticle {
17353
17252
  if (!text)
17354
17253
  return;
17355
17254
  ctx.save();
17356
- ctx.font = `${defaultSize * scale}px ${defaultFont}`;
17255
+ ctx.font = this.getListFontStyle(elementList, scale);
17357
17256
  ctx.fillText(text, x, y);
17358
17257
  ctx.restore();
17359
17258
  }
@@ -21238,6 +21137,7 @@ class Command {
21238
21137
  __publicField(this, "executeUpdateOptions");
21239
21138
  __publicField(this, "executeInsertTitle");
21240
21139
  __publicField(this, "executeFocus");
21140
+ __publicField(this, "executeComputeElementListHeight");
21241
21141
  __publicField(this, "getCatalog");
21242
21142
  __publicField(this, "getImage");
21243
21143
  __publicField(this, "getOptions");
@@ -21248,6 +21148,7 @@ class Command {
21248
21148
  __publicField(this, "getText");
21249
21149
  __publicField(this, "getWordCount");
21250
21150
  __publicField(this, "getCursorPosition");
21151
+ __publicField(this, "getRemainingContentHeight");
21251
21152
  __publicField(this, "getRange");
21252
21153
  __publicField(this, "getRangeText");
21253
21154
  __publicField(this, "getRangeContext");
@@ -21370,6 +21271,7 @@ class Command {
21370
21271
  this.executeUpdateOptions = adapt.updateOptions.bind(adapt);
21371
21272
  this.executeInsertTitle = adapt.insertTitle.bind(adapt);
21372
21273
  this.executeFocus = adapt.focus.bind(adapt);
21274
+ this.executeComputeElementListHeight = adapt.computeElementListHeight.bind(adapt);
21373
21275
  this.getImage = adapt.getImage.bind(adapt);
21374
21276
  this.getOptions = adapt.getOptions.bind(adapt);
21375
21277
  this.getValue = adapt.getValue.bind(adapt);
@@ -21378,6 +21280,7 @@ class Command {
21378
21280
  this.getText = adapt.getText.bind(adapt);
21379
21281
  this.getWordCount = adapt.getWordCount.bind(adapt);
21380
21282
  this.getCursorPosition = adapt.getCursorPosition.bind(adapt);
21283
+ this.getRemainingContentHeight = adapt.getRemainingContentHeight.bind(adapt);
21381
21284
  this.getRange = adapt.getRange.bind(adapt);
21382
21285
  this.getRangeText = adapt.getRangeText.bind(adapt);
21383
21286
  this.getRangeContext = adapt.getRangeContext.bind(adapt);
@@ -22707,6 +22610,37 @@ class CommandAdapt {
22707
22610
  getCursorPosition() {
22708
22611
  return this.position.getCursorPosition();
22709
22612
  }
22613
+ getRemainingContentHeight() {
22614
+ if (!this.draw.getIsPagingMode())
22615
+ return 0;
22616
+ const pageRowList = this.draw.getPageRowList();
22617
+ const lastPageIndex = pageRowList.length - 1;
22618
+ const rowList = pageRowList[lastPageIndex] || [];
22619
+ const usedHeight = rowList.reduce((pre, cur) => pre + cur.height + (cur.offsetY || 0), 0);
22620
+ const height = this.draw.getHeight();
22621
+ const mainOuterHeight = this.draw.getMainOuterHeight();
22622
+ const remaining = height - (mainOuterHeight + usedHeight);
22623
+ return remaining > 0 ? remaining : 0;
22624
+ }
22625
+ computeElementListHeight(elementList) {
22626
+ if (!elementList.length)
22627
+ return 0;
22628
+ const innerWidth = this.draw.getInnerWidth();
22629
+ if (innerWidth <= 0)
22630
+ return 0;
22631
+ const targetElementList = deepClone(elementList);
22632
+ formatElementList(targetElementList, {
22633
+ isHandleFirstElement: false,
22634
+ editorOptions: this.options
22635
+ });
22636
+ const surroundElementList = pickSurroundElementList(targetElementList);
22637
+ const rowList = this.draw.computeRowList({
22638
+ innerWidth,
22639
+ elementList: targetElementList,
22640
+ surroundElementList
22641
+ });
22642
+ return rowList.reduce((pre, cur) => pre + cur.height + (cur.offsetY || 0), 0);
22643
+ }
22710
22644
  getRange() {
22711
22645
  return deepClone(this.range.getRange());
22712
22646
  }