@hailin-zheng/editor-core 2.1.0 → 2.1.1

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/index.js CHANGED
@@ -3,7 +3,6 @@ import moment from 'moment';
3
3
  import * as acor from 'acorn';
4
4
  import { generate } from 'astring';
5
5
  import estraverse from 'estraverse';
6
- import * as bwipjs from 'bwip-js';
7
6
  import JsBarcode from 'jsbarcode';
8
7
  import { toVNode, init as init$1, styleModule, classModule, attributesModule, eventListenersModule } from 'snabbdom';
9
8
 
@@ -1550,6 +1549,8 @@ class ViewOptions {
1550
1549
  ruleHeight = 30;
1551
1550
  //是否打印页眉页脚线
1552
1551
  printHeaderFooterLine = false;
1552
+ //显示段落回车符号
1553
+ showEnterSymbol = false;
1553
1554
  get fullPageView() {
1554
1555
  return this._fullPageView;
1555
1556
  }
@@ -4304,6 +4305,27 @@ class PSymbolRenderObject extends LeafRenderObject {
4304
4305
  }
4305
4306
  render.contentContext.drawText('↩', this.element.textProps, position.x, position.y, 20, this.rect.height);
4306
4307
  }
4308
+ exportHTML(event) {
4309
+ if (!event.options.showEnterSymbol || event.mode === 'print') {
4310
+ return null;
4311
+ }
4312
+ return {
4313
+ sel: 'text',
4314
+ text: '↵',
4315
+ data: {
4316
+ ns: "http://www.w3.org/2000/svg",
4317
+ attrs: {
4318
+ //"transform": `translate(0,${(height - props.fontSize) / 2})`,
4319
+ 'dominant-baseline': 'hanging',
4320
+ 'font-family': 'Courier',
4321
+ 'font-size': this.element.defaultHeight,
4322
+ x: this.rect.x,
4323
+ y: this.rect.y,
4324
+ fill: 'green'
4325
+ }
4326
+ },
4327
+ };
4328
+ }
4307
4329
  //绘制段落符号
4308
4330
  clone() {
4309
4331
  const render = new PSymbolRenderObject(this.element);
@@ -8193,30 +8215,13 @@ class DataElementBarcode extends DataElementLeaf {
8193
8215
  return this.props.text;
8194
8216
  }
8195
8217
  drawBarcode(renderCtx, pos) {
8196
- this.createBarcodeCache();
8197
8218
  renderCtx.contentContext.ctx.drawImage(this.barCodeCanvas, pos.x, pos.y, this.props.width, this.props.height);
8198
8219
  }
8199
- createBarcodeCache() {
8200
- if (this.cache) {
8201
- return;
8202
- }
8203
- this.cache = true;
8204
- if (!this.barCodeCanvas) {
8205
- this.barCodeCanvas = document.createElement('canvas');
8206
- }
8207
- this.barCodeCanvas = bwipjs.toCanvas(this.barCodeCanvas, {
8208
- bcid: this.props.type,
8209
- text: this.props.text || "0123456789",
8210
- height: 10,
8211
- includetext: true,
8212
- textxalign: "center", // Always good to set this
8213
- });
8214
- }
8215
8220
  }
8216
8221
  class DataElementBarcodeRenderObject extends ResizeLeafRenderObject {
8217
8222
  render(e) {
8218
- const barcodeEle = this.element;
8219
- barcodeEle.drawBarcode(e.render, e.position);
8223
+ // const barcodeEle = this.element as DataElementBarcode;
8224
+ // barcodeEle.drawBarcode(e.render, e.position);
8220
8225
  }
8221
8226
  clone() {
8222
8227
  const clone = new DataElementBarcodeRenderObject(this.element);
@@ -9090,6 +9095,27 @@ class BreakRenderObject extends LeafRenderObject {
9090
9095
  }
9091
9096
  render.contentContext.drawText('↓', this.element.textProps, position.x, position.y, 20, this.rect.height);
9092
9097
  }
9098
+ exportHTML(event) {
9099
+ if (!event.options.showEnterSymbol || event.mode === 'print') {
9100
+ return null;
9101
+ }
9102
+ return {
9103
+ sel: 'text',
9104
+ text: '↓',
9105
+ data: {
9106
+ ns: "http://www.w3.org/2000/svg",
9107
+ attrs: {
9108
+ //"transform": `translate(0,${(height - props.fontSize) / 2})`,
9109
+ 'dominant-baseline': 'hanging',
9110
+ 'font-family': 'Courier',
9111
+ 'font-size': this.rect.height,
9112
+ x: this.rect.x + 4,
9113
+ y: this.rect.y,
9114
+ fill: 'green'
9115
+ }
9116
+ },
9117
+ };
9118
+ }
9093
9119
  clone() {
9094
9120
  const render = new BreakRenderObject(this.element);
9095
9121
  render.rect = ElementUtil.cloneRect(this.rect);
@@ -9130,6 +9156,9 @@ class DataElementText extends DataElementInlineGroup {
9130
9156
  if (!this.startDecorate) {
9131
9157
  return;
9132
9158
  }
9159
+ if (val === null || val === undefined) {
9160
+ val = '';
9161
+ }
9133
9162
  if (this.getValue() === val) {
9134
9163
  return;
9135
9164
  }
@@ -12410,6 +12439,7 @@ class ElementUtil {
12410
12439
  };
12411
12440
  }
12412
12441
  static getMousePos(e, scale = 1) {
12442
+ //scale=1;
12413
12443
  const svgContainer = e.currentTarget;
12414
12444
  const parentRect = svgContainer.getBoundingClientRect();
12415
12445
  const localX = e.clientX - parentRect.x; //+ this.viewOptions.pageOffset.x;
@@ -16130,7 +16160,9 @@ class DocumentPaint {
16130
16160
  //文档容器总宽度等于内容宽度
16131
16161
  //单页模式,docContainer居中
16132
16162
  this.docContainer.rect.width = viewWidth;
16133
- let docLeft = Math.floor((viewWidth - contentWidth) / 2);
16163
+ //let docLeft = Math.floor((viewWidth - contentWidth) / 2);
16164
+ //处理由于缩放问题,transform-origin:left-top,因此需要提前计算需要偏移的位置
16165
+ let docLeft = Math.floor((viewWidth - contentWidth * (this.viewOptions.scale)) / 2);
16134
16166
  docLeft = docLeft < 0 ? 0 : docLeft;
16135
16167
  pages.forEach(item => item.rect.x = docLeft);
16136
16168
  this.docContainer.rect.x = 0;
@@ -19137,7 +19169,8 @@ class DocumentChange {
19137
19169
  if (!prevEle) {
19138
19170
  const nextEle = ElementUtil.getRecursionNextSiblingElement(control, true, true, this.viewOptions);
19139
19171
  if (nextEle) {
19140
- this.selectionState.resetRange(nextEle, 0);
19172
+ //this.selectionState.resetRange(nextEle, 0);
19173
+ this.setSelectionStateByDeleteEvent(nextEle, 0, control);
19141
19174
  control.remove();
19142
19175
  return;
19143
19176
  }
@@ -19145,24 +19178,48 @@ class DocumentChange {
19145
19178
  return;
19146
19179
  }
19147
19180
  if (ElementUtil.isInSameParagraph(control, prevEle)) {
19148
- this.selectionState.resetRange(prevEle, -1);
19181
+ //this.selectionState.resetRange(prevEle, -1);
19182
+ this.setSelectionStateByDeleteEvent(prevEle, -1, control);
19149
19183
  control.remove();
19150
19184
  return;
19151
19185
  }
19152
19186
  else {
19153
19187
  const nextEle = ElementUtil.getRecursionNextSiblingElement(control, true, true, this.viewOptions);
19154
19188
  if (nextEle && ElementUtil.getPrevSiblingElement(nextEle) === control) {
19155
- this.selectionState.resetRange(nextEle, 0);
19189
+ //this.selectionState.resetRange(nextEle, 0);
19190
+ this.setSelectionStateByDeleteEvent(nextEle, 0, control);
19156
19191
  control.remove();
19157
19192
  return;
19158
19193
  }
19159
19194
  else {
19160
- this.selectionState.resetRange(prevEle, -1);
19195
+ //this.selectionState.resetRange(prevEle, -1);
19196
+ this.setSelectionStateByDeleteEvent(prevEle, -1, control);
19161
19197
  control.remove();
19162
19198
  return;
19163
19199
  }
19164
19200
  }
19165
19201
  }
19202
+ /**
19203
+ * 处理在表单模式下光标定位的问题
19204
+ * @param target
19205
+ * @param targetOffset
19206
+ * @param deleteTarget
19207
+ * @private
19208
+ */
19209
+ setSelectionStateByDeleteEvent(target, targetOffset, deleteTarget) {
19210
+ if (this.viewOptions.docMode === DocMode.FormEdit) {
19211
+ const dataEle = ElementUtil.getParent(deleteTarget, (item) => item instanceof DataElementInlineGroup);
19212
+ if (dataEle && ElementUtil.getParent(target, (item) => item instanceof DataElementInlineGroup) === dataEle) {
19213
+ this.selectionState.resetRange(target, targetOffset);
19214
+ return;
19215
+ }
19216
+ if (dataEle) {
19217
+ this.selectionState.resetRange(dataEle.startDecorate, 1);
19218
+ return;
19219
+ }
19220
+ }
19221
+ this.selectionState.resetRange(target, targetOffset);
19222
+ }
19166
19223
  /**
19167
19224
  * 回车事件
19168
19225
  */
@@ -26142,6 +26199,7 @@ function createSignal(state) {
26142
26199
  * 渲染日历虚拟节点处理类
26143
26200
  */
26144
26201
  class EditorCalendarVNode {
26202
+ viewOptions;
26145
26203
  currYear;
26146
26204
  currMonth;
26147
26205
  currCalendarMode;
@@ -26150,7 +26208,8 @@ class EditorCalendarVNode {
26150
26208
  onSetValue = new Subject$1();
26151
26209
  currTime;
26152
26210
  selectedTime;
26153
- constructor() {
26211
+ constructor(viewOptions) {
26212
+ this.viewOptions = viewOptions;
26154
26213
  this.currYear = createSignal(new Date().getFullYear());
26155
26214
  //月份赋值是按照索引来的,所以要减1
26156
26215
  this.currMonth = createSignal(new Date().getMonth());
@@ -26218,36 +26277,49 @@ class EditorCalendarVNode {
26218
26277
  hook: {
26219
26278
  insert: (vnode) => {
26220
26279
  const elm = vnode.elm;
26221
- const parent = CommonUtil.findParent(elm, (item) => item.className === 'scroll-container');
26222
- if (parent) {
26223
- const parentRect = parent.getBoundingClientRect();
26224
- const elmRect = elm.getBoundingClientRect();
26225
- if (elmRect.top < parentRect.top) {
26226
- elm.style.top = (position.y - elmRect.height) + 'px';
26227
- }
26228
- if (elmRect.left < parentRect.left) {
26229
- elm.style.left = (position.x - 10) + 'px';
26230
- }
26231
- if (elmRect.right > parentRect.right) {
26232
- elm.style.left = (position.x - elmRect.width + 10) + 'px';
26233
- }
26234
- if (elmRect.top + elmRect.height > parentRect.top + parentRect.height) {
26235
- const newTop = position.y - position.height - elmRect.height;
26236
- const oldTop = position.y + 5 + position.height;
26237
- //计算前后的高度的差距,然后判断新的值是否在父元素的范围内,如果不在则使用旧的值
26238
- if (oldTop - newTop < elmRect.top - parentRect.top) {
26239
- elm.style.top = (position.y - position.height - elmRect.height) + 'px';
26240
- }
26241
- //elm.style.top = (top - (elmRect.top + elmRect.height - (parentRect.top + parentRect.height))) + 'px';
26242
- //elm.style.top = (position.y - position.height - elmRect.height) + 'px';
26243
- }
26244
- }
26280
+ this.resizePosition(elm, position);
26281
+ },
26282
+ update: (oldVnode, vnode) => {
26283
+ const elm = vnode.elm;
26284
+ this.resizePosition(elm, position);
26245
26285
  }
26246
26286
  },
26247
26287
  },
26248
26288
  children: []
26249
26289
  };
26250
26290
  }
26291
+ resizePosition(elm, position) {
26292
+ const parent = CommonUtil.findParent(elm, (item) => item.className === 'scroll-container');
26293
+ const scale = this.viewOptions.scale;
26294
+ if (parent) {
26295
+ const parentRect = parent.getBoundingClientRect();
26296
+ const elmRect = elm.getBoundingClientRect();
26297
+ // elmRect.width /= scale;
26298
+ // elmRect.height /= scale;
26299
+ // parentRect.width /= scale;
26300
+ // parentRect.height /= scale;
26301
+ if (elmRect.top < parentRect.top) {
26302
+ elm.style.top = (position.y - elmRect.height / scale) + 'px';
26303
+ }
26304
+ if (elmRect.left < parentRect.left) {
26305
+ elm.style.left = (position.x - 10) + 'px';
26306
+ }
26307
+ if (elmRect.right > parentRect.right) {
26308
+ elm.style.left = (position.x - elmRect.width / scale + 10) + 'px';
26309
+ //elm.style.left = parentRect.width - elmRect.width + 'px';
26310
+ }
26311
+ if (elmRect.top + elmRect.height > parentRect.top + parentRect.height) {
26312
+ const newTop = position.y - position.height - elmRect.height;
26313
+ const oldTop = position.y + 5 + position.height;
26314
+ //计算前后的高度的差距,然后判断新的值是否在父元素的范围内,如果不在则使用旧的值
26315
+ if (newTop > 0 && oldTop - newTop < elmRect.top - parentRect.top) {
26316
+ elm.style.top = (position.y - position.height - elmRect.height) + 'px';
26317
+ }
26318
+ //elm.style.top = (top - (elmRect.top + elmRect.height - (parentRect.top + parentRect.height))) + 'px';
26319
+ //elm.style.top = (position.y - position.height - elmRect.height) + 'px';
26320
+ }
26321
+ }
26322
+ }
26251
26323
  renderDay() {
26252
26324
  //获取当前月份需要渲染的天数集合
26253
26325
  const days = this.getDays();
@@ -27092,8 +27164,13 @@ class DocEditor {
27092
27164
  const listVNode = this.renderDataListVNode();
27093
27165
  const dropContainer = {
27094
27166
  sel: 'div.drop-container',
27095
- data: {},
27096
- children: [listVNode.render(), calendarFunc.render(), menuFunc.render()]
27167
+ data: {
27168
+ style: {
27169
+ 'transform-origin': '0 0',
27170
+ 'transform': `scale(${this.viewOptions.scale})`
27171
+ }
27172
+ },
27173
+ children: [inputVNode, listVNode.render(), calendarFunc.render(), menuFunc.render()]
27097
27174
  };
27098
27175
  return {
27099
27176
  sel: 'div.svg-container',
@@ -27131,18 +27208,7 @@ class DocEditor {
27131
27208
  }
27132
27209
  }
27133
27210
  },
27134
- children: [
27135
- {
27136
- sel: 'div.scale-container', data: {
27137
- style: {
27138
- transform: 'scale(' + this.viewOptions.scale + ')',
27139
- transformOrigin: 'right top',
27140
- width: this.viewOptions.docPageSettings.width + 'px',
27141
- }
27142
- },
27143
- children: [docContentVNode, inputVNode, dropContainer]
27144
- }
27145
- ]
27211
+ children: [docContentVNode, dropContainer]
27146
27212
  }, ruleFunc.refreshRuleSvg().render()
27147
27213
  ]
27148
27214
  };
@@ -27530,11 +27596,11 @@ class DocEditor {
27530
27596
  this.updateRenderCtx();
27531
27597
  this.flushToSchedule();
27532
27598
  this.documentPaint.layoutPages();
27533
- const sub = this.afterNodePatch.subscribe(() => {
27534
- sub.unsubscribe();
27535
- const scrollDOM = this.svgContainer.querySelector('.scroll-container');
27536
- scrollDOM.scrollLeft = (scrollDOM.scrollWidth - scrollDOM.getBoundingClientRect().width) / 2;
27537
- });
27599
+ // const sub = this.afterNodePatch.subscribe(() => {
27600
+ // sub.unsubscribe();
27601
+ // const scrollDOM = this.svgContainer.querySelector('.scroll-container') as HTMLElement;
27602
+ // scrollDOM.scrollLeft = (scrollDOM.scrollWidth - scrollDOM.getBoundingClientRect().width) / 2;
27603
+ // })
27538
27604
  return scale;
27539
27605
  }
27540
27606
  updateRenderCtx() {
@@ -28066,6 +28132,8 @@ class DocEditor {
28066
28132
  position: 'relative',
28067
28133
  width: '0px',
28068
28134
  'user-select': 'none',
28135
+ transform: 'scale(' + this.viewOptions.scale + ')',
28136
+ 'transform-origin': '0 0'
28069
28137
  },
28070
28138
  on: this.documentEvent.getEventListener()
28071
28139
  },
@@ -28244,30 +28312,11 @@ class DocEditor {
28244
28312
  hook: {
28245
28313
  insert: (vnode) => {
28246
28314
  const elm = vnode.elm;
28247
- const parent = CommonUtil.findParent(elm, (item) => item.className === 'scroll-container');
28248
- if (parent) {
28249
- const parentRect = parent.getBoundingClientRect();
28250
- const elmRect = elm.getBoundingClientRect();
28251
- if (elmRect.top < parentRect.top) {
28252
- elm.style.top = (position.y - elmRect.height) + 'px';
28253
- }
28254
- if (elmRect.left < parentRect.left) {
28255
- elm.style.left = (position.x - 10) + 'px';
28256
- }
28257
- if (elmRect.right > parentRect.right) {
28258
- elm.style.left = (position.x - elmRect.width + 10) + 'px';
28259
- }
28260
- if (elmRect.top + elmRect.height > parentRect.top + parentRect.height) {
28261
- const newTop = position.y - position.height - elmRect.height;
28262
- const oldTop = position.y + 5 + position.height;
28263
- //计算前后的高度的差距,然后判断新的值是否在父元素的范围内,如果不在则使用旧的值
28264
- if (oldTop - newTop < elmRect.top - parentRect.top) {
28265
- elm.style.top = (position.y - position.height - elmRect.height) + 'px';
28266
- }
28267
- //elm.style.top = (top - (elmRect.top + elmRect.height - (parentRect.top + parentRect.height))) + 'px';
28268
- //elm.style.top = (position.y - position.height - elmRect.height) + 'px';
28269
- }
28270
- }
28315
+ editor.resizePosition(elm, position);
28316
+ },
28317
+ update: (oldVnode, vnode) => {
28318
+ const elm = vnode.elm;
28319
+ editor.resizePosition(elm, position);
28271
28320
  }
28272
28321
  },
28273
28322
  },
@@ -28286,8 +28335,40 @@ class DocEditor {
28286
28335
  }
28287
28336
  };
28288
28337
  }
28338
+ resizePosition(elm, position) {
28339
+ const parent = CommonUtil.findParent(elm, (item) => item.className === 'scroll-container');
28340
+ const scale = this.viewOptions.scale;
28341
+ if (parent) {
28342
+ const parentRect = parent.getBoundingClientRect();
28343
+ const elmRect = elm.getBoundingClientRect();
28344
+ // elmRect.width /= scale;
28345
+ // elmRect.height /= scale;
28346
+ // parentRect.width /= scale;
28347
+ // parentRect.height /= scale;
28348
+ if (elmRect.top < parentRect.top) {
28349
+ elm.style.top = (position.y - elmRect.height / scale) + 'px';
28350
+ }
28351
+ if (elmRect.left < parentRect.left) {
28352
+ elm.style.left = (position.x - 10) + 'px';
28353
+ }
28354
+ if (elmRect.right > parentRect.right) {
28355
+ elm.style.left = (position.x - elmRect.width / scale + 10) + 'px';
28356
+ //elm.style.left = parentRect.width - elmRect.width + 'px';
28357
+ }
28358
+ if (elmRect.top + elmRect.height > parentRect.top + parentRect.height) {
28359
+ const newTop = position.y - position.height - elmRect.height;
28360
+ const oldTop = position.y + 5 + position.height;
28361
+ //计算前后的高度的差距,然后判断新的值是否在父元素的范围内,如果不在则使用旧的值
28362
+ if (newTop > 0 && oldTop - newTop < elmRect.top - parentRect.top) {
28363
+ elm.style.top = (position.y - position.height - elmRect.height) + 'px';
28364
+ }
28365
+ //elm.style.top = (top - (elmRect.top + elmRect.height - (parentRect.top + parentRect.height))) + 'px';
28366
+ //elm.style.top = (position.y - position.height - elmRect.height) + 'px';
28367
+ }
28368
+ }
28369
+ }
28289
28370
  renderCalendar() {
28290
- const calendar = new EditorCalendarVNode();
28371
+ const calendar = new EditorCalendarVNode(this.viewOptions);
28291
28372
  const editor = this;
28292
28373
  calendar.onSetValue.subscribe((value) => {
28293
28374
  const dataEle = editor.getCurrentDataElement();
@@ -28373,7 +28454,7 @@ class DocEditor {
28373
28454
  rule.setRuleOptions({ width: this.viewOptions.docPageSettings.width, pagePL, pagePR, docLeft });
28374
28455
  }
28375
28456
  version() {
28376
- return "2.1.0";
28457
+ return "2.1.1";
28377
28458
  }
28378
28459
  }
28379
28460