@hailin-zheng/editor-core 2.0.4 → 2.0.6

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-cjs.js CHANGED
@@ -8,6 +8,7 @@ var acor = require('acorn');
8
8
  var astring = require('astring');
9
9
  var estraverse = require('estraverse');
10
10
  var bwipjs = require('bwip-js');
11
+ var JsBarcode = require('jsbarcode');
11
12
  var snabbdom = require('snabbdom');
12
13
 
13
14
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -34,6 +35,7 @@ var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
34
35
  var acor__namespace = /*#__PURE__*/_interopNamespace(acor);
35
36
  var estraverse__default = /*#__PURE__*/_interopDefaultLegacy(estraverse);
36
37
  var bwipjs__namespace = /*#__PURE__*/_interopNamespace(bwipjs);
38
+ var JsBarcode__default = /*#__PURE__*/_interopDefaultLegacy(JsBarcode);
37
39
 
38
40
  /**
39
41
  * 元素事件
@@ -513,7 +515,23 @@ class CommonUtil {
513
515
  const { width, height } = rect;
514
516
  const x = 0;
515
517
  const y = 0;
516
- const points = [{ x, y, type: 'left-top' }, { x: x + width, y, type: 'right-top' }, { x: x + (Math.floor(width / 2)), y: y, type: 'top-middle' }, { x, y: y + Math.floor(height / 2), type: 'left-middle' }, { x, y: y + height, type: 'left-bottom' }, { x: width, y: Math.floor(height / 2), type: 'right-middle' }, { x: x + width, y: y + height, type: 'right-bottom' }, { x: x + (Math.floor(width / 2)), y: y + height, type: 'bottom-middle' }];
518
+ const points = [{ x, y, type: 'left-top' }, {
519
+ x: x + width,
520
+ y,
521
+ type: 'right-top'
522
+ }, { x: x + (Math.floor(width / 2)), y: y, type: 'top-middle' }, {
523
+ x,
524
+ y: y + Math.floor(height / 2),
525
+ type: 'left-middle'
526
+ }, { x, y: y + height, type: 'left-bottom' }, {
527
+ x: width,
528
+ y: Math.floor(height / 2),
529
+ type: 'right-middle'
530
+ }, { x: x + width, y: y + height, type: 'right-bottom' }, {
531
+ x: x + (Math.floor(width / 2)),
532
+ y: y + height,
533
+ type: 'bottom-middle'
534
+ }];
517
535
  for (let i = 0; i < points.length; i++) {
518
536
  const point = points[i];
519
537
  const { x: px, y: py } = point;
@@ -524,11 +542,11 @@ class CommonUtil {
524
542
  return null;
525
543
  }
526
544
  /**
527
- * 整形符合连线要求
528
- * @param points
529
- * @param width
530
- * @param strokeColor
531
- */
545
+ * 整形符合连线要求
546
+ * @param points
547
+ * @param width
548
+ * @param strokeColor
549
+ */
532
550
  static resharpPoints(points) {
533
551
  let prevPoint = points[0];
534
552
  const array = [];
@@ -650,6 +668,11 @@ class CommonUtil {
650
668
  return [item];
651
669
  }
652
670
  }
671
+ static removeChild(ele) {
672
+ while (ele.firstChild) {
673
+ ele.removeChild(ele.firstChild);
674
+ }
675
+ }
653
676
  }
654
677
 
655
678
  const docOpsMap = new Map();
@@ -3435,7 +3458,7 @@ class DocumentRenderObject extends BlockContainerRenderObject {
3435
3458
  };
3436
3459
  pageCorner.children?.push(ElementUtil.getStrokeSvgPath(`M ${paddingPos.x - lineWidth} ${paddingPos.y} L ${paddingPos.x} ${paddingPos.y} L ${paddingPos.x} ${paddingPos.y - lineWidth}`, "grey", drawLineWidth));
3437
3460
  paddingPos = { x: docWidth - padding.right, y: padding.top };
3438
- pageCorner.children?.push(ElementUtil.getStrokeSvgPath(`M ${paddingPos.x + lineWidth} ${paddingPos.y} L ${paddingPos.x} ${paddingPos.y} L ${paddingPos.x} ${paddingPos.y + lineWidth}`, "grey", drawLineWidth));
3461
+ pageCorner.children?.push(ElementUtil.getStrokeSvgPath(`M ${paddingPos.x + lineWidth} ${paddingPos.y} L ${paddingPos.x} ${paddingPos.y} L ${paddingPos.x} ${paddingPos.y - lineWidth}`, "grey", drawLineWidth));
3439
3462
  paddingPos = { x: padding.left, y: docHeight - this.padding.bottom };
3440
3463
  pageCorner.children?.push(ElementUtil.getStrokeSvgPath(`M ${paddingPos.x - lineWidth} ${paddingPos.y} L ${paddingPos.x} ${paddingPos.y} L ${paddingPos.x} ${paddingPos.y + lineWidth}`, "grey", drawLineWidth));
3441
3464
  paddingPos = { x: docWidth - padding.left, y: docHeight - this.padding.bottom };
@@ -3832,7 +3855,7 @@ function drawDecorator(e, r) {
3832
3855
  function exportDecoratorHTML(event, r) {
3833
3856
  const canPaint = r.element.isMouseenter || r.element.isFocused;
3834
3857
  if (canPaint && r.element.paintRenders.indexOf(r) === 0) {
3835
- const strokeColor = r.element.isMouseenter ? '#ff0000' : '#0050b3';
3858
+ const strokeColor = '#0050b3';
3836
3859
  const verOffset = 0;
3837
3860
  const renderPosMap = getCurrentParaGroupRenders(r).map(item => ({ pos: getRenderPosToDoc(item), render: item }));
3838
3861
  if (renderPosMap.length > 1) {
@@ -9577,6 +9600,858 @@ class ValidateRenderObject extends CommContentBaseRenderObject {
9577
9600
  }
9578
9601
  }
9579
9602
 
9603
+ /*
9604
+ * QR Code generator library (TypeScript)
9605
+ *
9606
+ * Copyright (c) Project Nayuki. (MIT License)
9607
+ * https://www.nayuki.io/page/qr-code-generator-library
9608
+ *
9609
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
9610
+ * this software and associated documentation files (the "Software"), to deal in
9611
+ * the Software without restriction, including without limitation the rights to
9612
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9613
+ * the Software, and to permit persons to whom the Software is furnished to do so,
9614
+ * subject to the following conditions:
9615
+ * - The above copyright notice and this permission notice shall be included in
9616
+ * all copies or substantial portions of the Software.
9617
+ * - The Software is provided "as is", without warranty of any kind, express or
9618
+ * implied, including but not limited to the warranties of merchantability,
9619
+ * fitness for a particular purpose and noninfringement. In no event shall the
9620
+ * authors or copyright holders be liable for any claim, damages or other
9621
+ * liability, whether in an action of contract, tort or otherwise, arising from,
9622
+ * out of or in connection with the Software or the use or other dealings in the
9623
+ * Software.
9624
+ */
9625
+ var qrcodegen;
9626
+ (function (qrcodegen) {
9627
+ /*---- QR Code symbol class ----*/
9628
+ /*
9629
+ * A QR Code symbol, which is a type of two-dimension barcode.
9630
+ * Invented by Denso Wave and described in the ISO/IEC 18004 standard.
9631
+ * Instances of this class represent an immutable square grid of dark and light cells.
9632
+ * The class provides static factory functions to create a QR Code from text or binary data.
9633
+ * The class covers the QR Code Model 2 specification, supporting all versions (sizes)
9634
+ * from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
9635
+ *
9636
+ * Ways to create a QR Code object:
9637
+ * - High level: Take the payload data and call QrCode.encodeText() or QrCode.encodeBinary().
9638
+ * - Mid level: Custom-make the list of segments and call QrCode.encodeSegments().
9639
+ * - Low level: Custom-make the array of data codeword bytes (including
9640
+ * segment headers and final padding, excluding error correction codewords),
9641
+ * supply the appropriate version number, and call the QrCode() constructor.
9642
+ * (Note that all ways require supplying the desired error correction level.)
9643
+ */
9644
+ class QrCode {
9645
+ version;
9646
+ errorCorrectionLevel;
9647
+ /*-- Static factory functions (high level) --*/
9648
+ // Returns a QR Code representing the given Unicode text string at the given error correction level.
9649
+ // As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer
9650
+ // Unicode code points (not UTF-16 code units) if the low error correction level is used. The smallest possible
9651
+ // QR Code version is automatically chosen for the output. The ECC level of the result may be higher than the
9652
+ // ecl argument if it can be done without increasing the version.
9653
+ static encodeText(text, ecl) {
9654
+ const segs = qrcodegen.QrSegment.makeSegments(text);
9655
+ return QrCode.encodeSegments(segs, ecl);
9656
+ }
9657
+ // Returns a QR Code representing the given binary data at the given error correction level.
9658
+ // This function always encodes using the binary segment mode, not any text mode. The maximum number of
9659
+ // bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
9660
+ // The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
9661
+ static encodeBinary(data, ecl) {
9662
+ const seg = qrcodegen.QrSegment.makeBytes(data);
9663
+ return QrCode.encodeSegments([seg], ecl);
9664
+ }
9665
+ /*-- Static factory functions (mid level) --*/
9666
+ // Returns a QR Code representing the given segments with the given encoding parameters.
9667
+ // The smallest possible QR Code version within the given range is automatically
9668
+ // chosen for the output. Iff boostEcl is true, then the ECC level of the result
9669
+ // may be higher than the ecl argument if it can be done without increasing the
9670
+ // version. The mask number is either between 0 to 7 (inclusive) to force that
9671
+ // mask, or -1 to automatically choose an appropriate mask (which may be slow).
9672
+ // This function allows the user to create a custom sequence of segments that switches
9673
+ // between modes (such as alphanumeric and byte) to encode text in less space.
9674
+ // This is a mid-level API; the high-level API is encodeText() and encodeBinary().
9675
+ static encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) {
9676
+ if (!(QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= QrCode.MAX_VERSION)
9677
+ || mask < -1 || mask > 7)
9678
+ throw new RangeError("Invalid value");
9679
+ // Find the minimal version number to use
9680
+ let version;
9681
+ let dataUsedBits;
9682
+ for (version = minVersion;; version++) {
9683
+ const dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8; // Number of data bits available
9684
+ const usedBits = QrSegment.getTotalBits(segs, version);
9685
+ if (usedBits <= dataCapacityBits) {
9686
+ dataUsedBits = usedBits;
9687
+ break; // This version number is found to be suitable
9688
+ }
9689
+ if (version >= maxVersion) // All versions in the range could not fit the given data
9690
+ throw new RangeError("Data too long");
9691
+ }
9692
+ // Increase the error correction level while the data still fits in the current version number
9693
+ for (const newEcl of [QrCode.Ecc.MEDIUM, QrCode.Ecc.QUARTILE, QrCode.Ecc.HIGH]) { // From low to high
9694
+ if (boostEcl && dataUsedBits <= QrCode.getNumDataCodewords(version, newEcl) * 8)
9695
+ ecl = newEcl;
9696
+ }
9697
+ // Concatenate all segments to create the data bit string
9698
+ let bb = [];
9699
+ for (const seg of segs) {
9700
+ appendBits(seg.mode.modeBits, 4, bb);
9701
+ appendBits(seg.numChars, seg.mode.numCharCountBits(version), bb);
9702
+ for (const b of seg.getData())
9703
+ bb.push(b);
9704
+ }
9705
+ assert(bb.length == dataUsedBits);
9706
+ // Add terminator and pad up to a byte if applicable
9707
+ const dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8;
9708
+ assert(bb.length <= dataCapacityBits);
9709
+ appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb);
9710
+ appendBits(0, (8 - bb.length % 8) % 8, bb);
9711
+ assert(bb.length % 8 == 0);
9712
+ // Pad with alternating bytes until data capacity is reached
9713
+ for (let padByte = 0xEC; bb.length < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
9714
+ appendBits(padByte, 8, bb);
9715
+ // Pack bits into bytes in big endian
9716
+ let dataCodewords = [];
9717
+ while (dataCodewords.length * 8 < bb.length)
9718
+ dataCodewords.push(0);
9719
+ bb.forEach((b, i) => dataCodewords[i >>> 3] |= b << (7 - (i & 7)));
9720
+ // Create the QR Code object
9721
+ return new QrCode(version, ecl, dataCodewords, mask);
9722
+ }
9723
+ /*-- Fields --*/
9724
+ // The width and height of this QR Code, measured in modules, between
9725
+ // 21 and 177 (inclusive). This is equal to version * 4 + 17.
9726
+ size;
9727
+ // The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
9728
+ // Even if a QR Code is created with automatic masking requested (mask = -1),
9729
+ // the resulting object still has a mask value between 0 and 7.
9730
+ mask;
9731
+ // The modules of this QR Code (false = light, true = dark).
9732
+ // Immutable after constructor finishes. Accessed through getModule().
9733
+ modules = [];
9734
+ // Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
9735
+ isFunction = [];
9736
+ /*-- Constructor (low level) and fields --*/
9737
+ // Creates a new QR Code with the given version number,
9738
+ // error correction level, data codeword bytes, and mask number.
9739
+ // This is a low-level API that most users should not use directly.
9740
+ // A mid-level API is the encodeSegments() function.
9741
+ constructor(
9742
+ // The version number of this QR Code, which is between 1 and 40 (inclusive).
9743
+ // This determines the size of this barcode.
9744
+ version,
9745
+ // The error correction level used in this QR Code.
9746
+ errorCorrectionLevel, dataCodewords, msk) {
9747
+ this.version = version;
9748
+ this.errorCorrectionLevel = errorCorrectionLevel;
9749
+ // Check scalar arguments
9750
+ if (version < QrCode.MIN_VERSION || version > QrCode.MAX_VERSION)
9751
+ throw new RangeError("Version value out of range");
9752
+ if (msk < -1 || msk > 7)
9753
+ throw new RangeError("Mask value out of range");
9754
+ this.size = version * 4 + 17;
9755
+ // Initialize both grids to be size*size arrays of Boolean false
9756
+ let row = [];
9757
+ for (let i = 0; i < this.size; i++)
9758
+ row.push(false);
9759
+ for (let i = 0; i < this.size; i++) {
9760
+ this.modules.push(row.slice()); // Initially all light
9761
+ this.isFunction.push(row.slice());
9762
+ }
9763
+ // Compute ECC, draw modules
9764
+ this.drawFunctionPatterns();
9765
+ const allCodewords = this.addEccAndInterleave(dataCodewords);
9766
+ this.drawCodewords(allCodewords);
9767
+ // Do masking
9768
+ if (msk == -1) { // Automatically choose best mask
9769
+ let minPenalty = 1000000000;
9770
+ for (let i = 0; i < 8; i++) {
9771
+ this.applyMask(i);
9772
+ this.drawFormatBits(i);
9773
+ const penalty = this.getPenaltyScore();
9774
+ if (penalty < minPenalty) {
9775
+ msk = i;
9776
+ minPenalty = penalty;
9777
+ }
9778
+ this.applyMask(i); // Undoes the mask due to XOR
9779
+ }
9780
+ }
9781
+ assert(0 <= msk && msk <= 7);
9782
+ this.mask = msk;
9783
+ this.applyMask(msk); // Apply the final choice of mask
9784
+ this.drawFormatBits(msk); // Overwrite old format bits
9785
+ this.isFunction = [];
9786
+ }
9787
+ /*-- Accessor methods --*/
9788
+ // Returns the color of the module (pixel) at the given coordinates, which is false
9789
+ // for light or true for dark. The top left corner has the coordinates (x=0, y=0).
9790
+ // If the given coordinates are out of bounds, then false (light) is returned.
9791
+ getModule(x, y) {
9792
+ return 0 <= x && x < this.size && 0 <= y && y < this.size && this.modules[y][x];
9793
+ }
9794
+ /*-- Private helper methods for constructor: Drawing function modules --*/
9795
+ // Reads this object's version field, and draws and marks all function modules.
9796
+ drawFunctionPatterns() {
9797
+ // Draw horizontal and vertical timing patterns
9798
+ for (let i = 0; i < this.size; i++) {
9799
+ this.setFunctionModule(6, i, i % 2 == 0);
9800
+ this.setFunctionModule(i, 6, i % 2 == 0);
9801
+ }
9802
+ // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
9803
+ this.drawFinderPattern(3, 3);
9804
+ this.drawFinderPattern(this.size - 4, 3);
9805
+ this.drawFinderPattern(3, this.size - 4);
9806
+ // Draw numerous alignment patterns
9807
+ const alignPatPos = this.getAlignmentPatternPositions();
9808
+ const numAlign = alignPatPos.length;
9809
+ for (let i = 0; i < numAlign; i++) {
9810
+ for (let j = 0; j < numAlign; j++) {
9811
+ // Don't draw on the three finder corners
9812
+ if (!(i == 0 && j == 0 || i == 0 && j == numAlign - 1 || i == numAlign - 1 && j == 0))
9813
+ this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j]);
9814
+ }
9815
+ }
9816
+ // Draw configuration data
9817
+ this.drawFormatBits(0); // Dummy mask value; overwritten later in the constructor
9818
+ this.drawVersion();
9819
+ }
9820
+ // Draws two copies of the format bits (with its own error correction code)
9821
+ // based on the given mask and this object's error correction level field.
9822
+ drawFormatBits(mask) {
9823
+ // Calculate error correction code and pack bits
9824
+ const data = this.errorCorrectionLevel.formatBits << 3 | mask; // errCorrLvl is uint2, mask is uint3
9825
+ let rem = data;
9826
+ for (let i = 0; i < 10; i++)
9827
+ rem = (rem << 1) ^ ((rem >>> 9) * 0x537);
9828
+ const bits = (data << 10 | rem) ^ 0x5412; // uint15
9829
+ assert(bits >>> 15 == 0);
9830
+ // Draw first copy
9831
+ for (let i = 0; i <= 5; i++)
9832
+ this.setFunctionModule(8, i, getBit(bits, i));
9833
+ this.setFunctionModule(8, 7, getBit(bits, 6));
9834
+ this.setFunctionModule(8, 8, getBit(bits, 7));
9835
+ this.setFunctionModule(7, 8, getBit(bits, 8));
9836
+ for (let i = 9; i < 15; i++)
9837
+ this.setFunctionModule(14 - i, 8, getBit(bits, i));
9838
+ // Draw second copy
9839
+ for (let i = 0; i < 8; i++)
9840
+ this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i));
9841
+ for (let i = 8; i < 15; i++)
9842
+ this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i));
9843
+ this.setFunctionModule(8, this.size - 8, true); // Always dark
9844
+ }
9845
+ // Draws two copies of the version bits (with its own error correction code),
9846
+ // based on this object's version field, iff 7 <= version <= 40.
9847
+ drawVersion() {
9848
+ if (this.version < 7)
9849
+ return;
9850
+ // Calculate error correction code and pack bits
9851
+ let rem = this.version; // version is uint6, in the range [7, 40]
9852
+ for (let i = 0; i < 12; i++)
9853
+ rem = (rem << 1) ^ ((rem >>> 11) * 0x1F25);
9854
+ const bits = this.version << 12 | rem; // uint18
9855
+ assert(bits >>> 18 == 0);
9856
+ // Draw two copies
9857
+ for (let i = 0; i < 18; i++) {
9858
+ const color = getBit(bits, i);
9859
+ const a = this.size - 11 + i % 3;
9860
+ const b = Math.floor(i / 3);
9861
+ this.setFunctionModule(a, b, color);
9862
+ this.setFunctionModule(b, a, color);
9863
+ }
9864
+ }
9865
+ // Draws a 9*9 finder pattern including the border separator,
9866
+ // with the center module at (x, y). Modules can be out of bounds.
9867
+ drawFinderPattern(x, y) {
9868
+ for (let dy = -4; dy <= 4; dy++) {
9869
+ for (let dx = -4; dx <= 4; dx++) {
9870
+ const dist = Math.max(Math.abs(dx), Math.abs(dy)); // Chebyshev/infinity norm
9871
+ const xx = x + dx;
9872
+ const yy = y + dy;
9873
+ if (0 <= xx && xx < this.size && 0 <= yy && yy < this.size)
9874
+ this.setFunctionModule(xx, yy, dist != 2 && dist != 4);
9875
+ }
9876
+ }
9877
+ }
9878
+ // Draws a 5*5 alignment pattern, with the center module
9879
+ // at (x, y). All modules must be in bounds.
9880
+ drawAlignmentPattern(x, y) {
9881
+ for (let dy = -2; dy <= 2; dy++) {
9882
+ for (let dx = -2; dx <= 2; dx++)
9883
+ this.setFunctionModule(x + dx, y + dy, Math.max(Math.abs(dx), Math.abs(dy)) != 1);
9884
+ }
9885
+ }
9886
+ // Sets the color of a module and marks it as a function module.
9887
+ // Only used by the constructor. Coordinates must be in bounds.
9888
+ setFunctionModule(x, y, isDark) {
9889
+ this.modules[y][x] = isDark;
9890
+ this.isFunction[y][x] = true;
9891
+ }
9892
+ /*-- Private helper methods for constructor: Codewords and masking --*/
9893
+ // Returns a new byte string representing the given data with the appropriate error correction
9894
+ // codewords appended to it, based on this object's version and error correction level.
9895
+ addEccAndInterleave(data) {
9896
+ const ver = this.version;
9897
+ const ecl = this.errorCorrectionLevel;
9898
+ if (data.length != QrCode.getNumDataCodewords(ver, ecl))
9899
+ throw new RangeError("Invalid argument");
9900
+ // Calculate parameter numbers
9901
+ const numBlocks = QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
9902
+ const blockEccLen = QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver];
9903
+ const rawCodewords = Math.floor(QrCode.getNumRawDataModules(ver) / 8);
9904
+ const numShortBlocks = numBlocks - rawCodewords % numBlocks;
9905
+ const shortBlockLen = Math.floor(rawCodewords / numBlocks);
9906
+ // Split data into blocks and append ECC to each block
9907
+ let blocks = [];
9908
+ const rsDiv = QrCode.reedSolomonComputeDivisor(blockEccLen);
9909
+ for (let i = 0, k = 0; i < numBlocks; i++) {
9910
+ let dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1));
9911
+ k += dat.length;
9912
+ const ecc = QrCode.reedSolomonComputeRemainder(dat, rsDiv);
9913
+ if (i < numShortBlocks)
9914
+ dat.push(0);
9915
+ blocks.push(dat.concat(ecc));
9916
+ }
9917
+ // Interleave (not concatenate) the bytes from every block into a single sequence
9918
+ let result = [];
9919
+ for (let i = 0; i < blocks[0].length; i++) {
9920
+ blocks.forEach((block, j) => {
9921
+ // Skip the padding byte in short blocks
9922
+ if (i != shortBlockLen - blockEccLen || j >= numShortBlocks)
9923
+ result.push(block[i]);
9924
+ });
9925
+ }
9926
+ assert(result.length == rawCodewords);
9927
+ return result;
9928
+ }
9929
+ // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
9930
+ // data area of this QR Code. Function modules need to be marked off before this is called.
9931
+ drawCodewords(data) {
9932
+ if (data.length != Math.floor(QrCode.getNumRawDataModules(this.version) / 8))
9933
+ throw new RangeError("Invalid argument");
9934
+ let i = 0; // Bit index into the data
9935
+ // Do the funny zigzag scan
9936
+ for (let right = this.size - 1; right >= 1; right -= 2) { // Index of right column in each column pair
9937
+ if (right == 6)
9938
+ right = 5;
9939
+ for (let vert = 0; vert < this.size; vert++) { // Vertical counter
9940
+ for (let j = 0; j < 2; j++) {
9941
+ const x = right - j; // Actual x coordinate
9942
+ const upward = ((right + 1) & 2) == 0;
9943
+ const y = upward ? this.size - 1 - vert : vert; // Actual y coordinate
9944
+ if (!this.isFunction[y][x] && i < data.length * 8) {
9945
+ this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7));
9946
+ i++;
9947
+ }
9948
+ // If this QR Code has any remainder bits (0 to 7), they were assigned as
9949
+ // 0/false/light by the constructor and are left unchanged by this method
9950
+ }
9951
+ }
9952
+ }
9953
+ assert(i == data.length * 8);
9954
+ }
9955
+ // XORs the codeword modules in this QR Code with the given mask pattern.
9956
+ // The function modules must be marked and the codeword bits must be drawn
9957
+ // before masking. Due to the arithmetic of XOR, calling applyMask() with
9958
+ // the same mask value a second time will undo the mask. A final well-formed
9959
+ // QR Code needs exactly one (not zero, two, etc.) mask applied.
9960
+ applyMask(mask) {
9961
+ if (mask < 0 || mask > 7)
9962
+ throw new RangeError("Mask value out of range");
9963
+ for (let y = 0; y < this.size; y++) {
9964
+ for (let x = 0; x < this.size; x++) {
9965
+ let invert;
9966
+ switch (mask) {
9967
+ case 0:
9968
+ invert = (x + y) % 2 == 0;
9969
+ break;
9970
+ case 1:
9971
+ invert = y % 2 == 0;
9972
+ break;
9973
+ case 2:
9974
+ invert = x % 3 == 0;
9975
+ break;
9976
+ case 3:
9977
+ invert = (x + y) % 3 == 0;
9978
+ break;
9979
+ case 4:
9980
+ invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 == 0;
9981
+ break;
9982
+ case 5:
9983
+ invert = x * y % 2 + x * y % 3 == 0;
9984
+ break;
9985
+ case 6:
9986
+ invert = (x * y % 2 + x * y % 3) % 2 == 0;
9987
+ break;
9988
+ case 7:
9989
+ invert = ((x + y) % 2 + x * y % 3) % 2 == 0;
9990
+ break;
9991
+ default: throw new Error("Unreachable");
9992
+ }
9993
+ if (!this.isFunction[y][x] && invert)
9994
+ this.modules[y][x] = !this.modules[y][x];
9995
+ }
9996
+ }
9997
+ }
9998
+ // Calculates and returns the penalty score based on state of this QR Code's current modules.
9999
+ // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
10000
+ getPenaltyScore() {
10001
+ let result = 0;
10002
+ // Adjacent modules in row having same color, and finder-like patterns
10003
+ for (let y = 0; y < this.size; y++) {
10004
+ let runColor = false;
10005
+ let runX = 0;
10006
+ let runHistory = [0, 0, 0, 0, 0, 0, 0];
10007
+ for (let x = 0; x < this.size; x++) {
10008
+ if (this.modules[y][x] == runColor) {
10009
+ runX++;
10010
+ if (runX == 5)
10011
+ result += QrCode.PENALTY_N1;
10012
+ else if (runX > 5)
10013
+ result++;
10014
+ }
10015
+ else {
10016
+ this.finderPenaltyAddHistory(runX, runHistory);
10017
+ if (!runColor)
10018
+ result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
10019
+ runColor = this.modules[y][x];
10020
+ runX = 1;
10021
+ }
10022
+ }
10023
+ result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * QrCode.PENALTY_N3;
10024
+ }
10025
+ // Adjacent modules in column having same color, and finder-like patterns
10026
+ for (let x = 0; x < this.size; x++) {
10027
+ let runColor = false;
10028
+ let runY = 0;
10029
+ let runHistory = [0, 0, 0, 0, 0, 0, 0];
10030
+ for (let y = 0; y < this.size; y++) {
10031
+ if (this.modules[y][x] == runColor) {
10032
+ runY++;
10033
+ if (runY == 5)
10034
+ result += QrCode.PENALTY_N1;
10035
+ else if (runY > 5)
10036
+ result++;
10037
+ }
10038
+ else {
10039
+ this.finderPenaltyAddHistory(runY, runHistory);
10040
+ if (!runColor)
10041
+ result += this.finderPenaltyCountPatterns(runHistory) * QrCode.PENALTY_N3;
10042
+ runColor = this.modules[y][x];
10043
+ runY = 1;
10044
+ }
10045
+ }
10046
+ result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * QrCode.PENALTY_N3;
10047
+ }
10048
+ // 2*2 blocks of modules having same color
10049
+ for (let y = 0; y < this.size - 1; y++) {
10050
+ for (let x = 0; x < this.size - 1; x++) {
10051
+ const color = this.modules[y][x];
10052
+ if (color == this.modules[y][x + 1] &&
10053
+ color == this.modules[y + 1][x] &&
10054
+ color == this.modules[y + 1][x + 1])
10055
+ result += QrCode.PENALTY_N2;
10056
+ }
10057
+ }
10058
+ // Balance of dark and light modules
10059
+ let dark = 0;
10060
+ for (const row of this.modules)
10061
+ dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark);
10062
+ const total = this.size * this.size; // Note that size is odd, so dark/total != 1/2
10063
+ // Compute the smallest integer k >= 0 such that (45-5k)% <= dark/total <= (55+5k)%
10064
+ const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1;
10065
+ assert(0 <= k && k <= 9);
10066
+ result += k * QrCode.PENALTY_N4;
10067
+ assert(0 <= result && result <= 2568888); // Non-tight upper bound based on default values of PENALTY_N1, ..., N4
10068
+ return result;
10069
+ }
10070
+ /*-- Private helper functions --*/
10071
+ // Returns an ascending list of positions of alignment patterns for this version number.
10072
+ // Each position is in the range [0,177), and are used on both the x and y axes.
10073
+ // This could be implemented as lookup table of 40 variable-length lists of integers.
10074
+ getAlignmentPatternPositions() {
10075
+ if (this.version == 1)
10076
+ return [];
10077
+ else {
10078
+ const numAlign = Math.floor(this.version / 7) + 2;
10079
+ const step = (this.version == 32) ? 26 :
10080
+ Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2;
10081
+ let result = [6];
10082
+ for (let pos = this.size - 7; result.length < numAlign; pos -= step)
10083
+ result.splice(1, 0, pos);
10084
+ return result;
10085
+ }
10086
+ }
10087
+ // Returns the number of data bits that can be stored in a QR Code of the given version number, after
10088
+ // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
10089
+ // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
10090
+ static getNumRawDataModules(ver) {
10091
+ if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION)
10092
+ throw new RangeError("Version number out of range");
10093
+ let result = (16 * ver + 128) * ver + 64;
10094
+ if (ver >= 2) {
10095
+ const numAlign = Math.floor(ver / 7) + 2;
10096
+ result -= (25 * numAlign - 10) * numAlign - 55;
10097
+ if (ver >= 7)
10098
+ result -= 36;
10099
+ }
10100
+ assert(208 <= result && result <= 29648);
10101
+ return result;
10102
+ }
10103
+ // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
10104
+ // QR Code of the given version number and error correction level, with remainder bits discarded.
10105
+ // This stateless pure function could be implemented as a (40*4)-cell lookup table.
10106
+ static getNumDataCodewords(ver, ecl) {
10107
+ return Math.floor(QrCode.getNumRawDataModules(ver) / 8) -
10108
+ QrCode.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver] *
10109
+ QrCode.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver];
10110
+ }
10111
+ // Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
10112
+ // implemented as a lookup table over all possible parameter values, instead of as an algorithm.
10113
+ static reedSolomonComputeDivisor(degree) {
10114
+ if (degree < 1 || degree > 255)
10115
+ throw new RangeError("Degree out of range");
10116
+ // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
10117
+ // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array [255, 8, 93].
10118
+ let result = [];
10119
+ for (let i = 0; i < degree - 1; i++)
10120
+ result.push(0);
10121
+ result.push(1); // Start off with the monomial x^0
10122
+ // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
10123
+ // and drop the highest monomial term which is always 1x^degree.
10124
+ // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
10125
+ let root = 1;
10126
+ for (let i = 0; i < degree; i++) {
10127
+ // Multiply the current product by (x - r^i)
10128
+ for (let j = 0; j < result.length; j++) {
10129
+ result[j] = QrCode.reedSolomonMultiply(result[j], root);
10130
+ if (j + 1 < result.length)
10131
+ result[j] ^= result[j + 1];
10132
+ }
10133
+ root = QrCode.reedSolomonMultiply(root, 0x02);
10134
+ }
10135
+ return result;
10136
+ }
10137
+ // Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
10138
+ static reedSolomonComputeRemainder(data, divisor) {
10139
+ let result = divisor.map(_ => 0);
10140
+ for (const b of data) { // Polynomial division
10141
+ const factor = b ^ result.shift();
10142
+ result.push(0);
10143
+ divisor.forEach((coef, i) => result[i] ^= QrCode.reedSolomonMultiply(coef, factor));
10144
+ }
10145
+ return result;
10146
+ }
10147
+ // Returns the product of the two given field elements modulo GF(2^8/0x11D). The arguments and result
10148
+ // are unsigned 8-bit integers. This could be implemented as a lookup table of 256*256 entries of uint8.
10149
+ static reedSolomonMultiply(x, y) {
10150
+ if (x >>> 8 != 0 || y >>> 8 != 0)
10151
+ throw new RangeError("Byte out of range");
10152
+ // Russian peasant multiplication
10153
+ let z = 0;
10154
+ for (let i = 7; i >= 0; i--) {
10155
+ z = (z << 1) ^ ((z >>> 7) * 0x11D);
10156
+ z ^= ((y >>> i) & 1) * x;
10157
+ }
10158
+ assert(z >>> 8 == 0);
10159
+ return z;
10160
+ }
10161
+ // Can only be called immediately after a light run is added, and
10162
+ // returns either 0, 1, or 2. A helper function for getPenaltyScore().
10163
+ finderPenaltyCountPatterns(runHistory) {
10164
+ const n = runHistory[1];
10165
+ assert(n <= this.size * 3);
10166
+ const core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n;
10167
+ return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0)
10168
+ + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0);
10169
+ }
10170
+ // Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
10171
+ finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) {
10172
+ if (currentRunColor) { // Terminate dark run
10173
+ this.finderPenaltyAddHistory(currentRunLength, runHistory);
10174
+ currentRunLength = 0;
10175
+ }
10176
+ currentRunLength += this.size; // Add light border to final run
10177
+ this.finderPenaltyAddHistory(currentRunLength, runHistory);
10178
+ return this.finderPenaltyCountPatterns(runHistory);
10179
+ }
10180
+ // Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
10181
+ finderPenaltyAddHistory(currentRunLength, runHistory) {
10182
+ if (runHistory[0] == 0)
10183
+ currentRunLength += this.size; // Add light border to initial run
10184
+ runHistory.pop();
10185
+ runHistory.unshift(currentRunLength);
10186
+ }
10187
+ /*-- Constants and tables --*/
10188
+ // The minimum version number supported in the QR Code Model 2 standard.
10189
+ static MIN_VERSION = 1;
10190
+ // The maximum version number supported in the QR Code Model 2 standard.
10191
+ static MAX_VERSION = 40;
10192
+ // For use in getPenaltyScore(), when evaluating which mask is best.
10193
+ static PENALTY_N1 = 3;
10194
+ static PENALTY_N2 = 3;
10195
+ static PENALTY_N3 = 40;
10196
+ static PENALTY_N4 = 10;
10197
+ static ECC_CODEWORDS_PER_BLOCK = [
10198
+ // Version: (note that index 0 is for padding, and is set to an illegal value)
10199
+ //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
10200
+ [-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
10201
+ [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28],
10202
+ [-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
10203
+ [-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], // High
10204
+ ];
10205
+ static NUM_ERROR_CORRECTION_BLOCKS = [
10206
+ // Version: (note that index 0 is for padding, and is set to an illegal value)
10207
+ //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
10208
+ [-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25],
10209
+ [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49],
10210
+ [-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68],
10211
+ [-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81], // High
10212
+ ];
10213
+ }
10214
+ qrcodegen.QrCode = QrCode;
10215
+ // Appends the given number of low-order bits of the given value
10216
+ // to the given buffer. Requires 0 <= len <= 31 and 0 <= val < 2^len.
10217
+ function appendBits(val, len, bb) {
10218
+ if (len < 0 || len > 31 || val >>> len != 0)
10219
+ throw new RangeError("Value out of range");
10220
+ for (let i = len - 1; i >= 0; i--) // Append bit by bit
10221
+ bb.push((val >>> i) & 1);
10222
+ }
10223
+ // Returns true iff the i'th bit of x is set to 1.
10224
+ function getBit(x, i) {
10225
+ return ((x >>> i) & 1) != 0;
10226
+ }
10227
+ // Throws an exception if the given condition is false.
10228
+ function assert(cond) {
10229
+ if (!cond)
10230
+ throw new Error("Assertion error");
10231
+ }
10232
+ /*---- Data segment class ----*/
10233
+ /*
10234
+ * A segment of character/binary/control data in a QR Code symbol.
10235
+ * Instances of this class are immutable.
10236
+ * The mid-level way to create a segment is to take the payload data
10237
+ * and call a static factory function such as QrSegment.makeNumeric().
10238
+ * The low-level way to create a segment is to custom-make the bit buffer
10239
+ * and call the QrSegment() constructor with appropriate values.
10240
+ * This segment class imposes no length restrictions, but QR Codes have restrictions.
10241
+ * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
10242
+ * Any segment longer than this is meaningless for the purpose of generating QR Codes.
10243
+ */
10244
+ class QrSegment {
10245
+ mode;
10246
+ numChars;
10247
+ bitData;
10248
+ /*-- Static factory functions (mid level) --*/
10249
+ // Returns a segment representing the given binary data encoded in
10250
+ // byte mode. All input byte arrays are acceptable. Any text string
10251
+ // can be converted to UTF-8 bytes and encoded as a byte mode segment.
10252
+ static makeBytes(data) {
10253
+ let bb = [];
10254
+ for (const b of data)
10255
+ appendBits(b, 8, bb);
10256
+ return new QrSegment(QrSegment.Mode.BYTE, data.length, bb);
10257
+ }
10258
+ // Returns a segment representing the given string of decimal digits encoded in numeric mode.
10259
+ static makeNumeric(digits) {
10260
+ if (!QrSegment.isNumeric(digits))
10261
+ throw new RangeError("String contains non-numeric characters");
10262
+ let bb = [];
10263
+ for (let i = 0; i < digits.length;) { // Consume up to 3 digits per iteration
10264
+ const n = Math.min(digits.length - i, 3);
10265
+ appendBits(parseInt(digits.substring(i, i + n), 10), n * 3 + 1, bb);
10266
+ i += n;
10267
+ }
10268
+ return new QrSegment(QrSegment.Mode.NUMERIC, digits.length, bb);
10269
+ }
10270
+ // Returns a segment representing the given text string encoded in alphanumeric mode.
10271
+ // The characters allowed are: 0 to 9, A to Z (uppercase only), space,
10272
+ // dollar, percent, asterisk, plus, hyphen, period, slash, colon.
10273
+ static makeAlphanumeric(text) {
10274
+ if (!QrSegment.isAlphanumeric(text))
10275
+ throw new RangeError("String contains unencodable characters in alphanumeric mode");
10276
+ let bb = [];
10277
+ let i;
10278
+ for (i = 0; i + 2 <= text.length; i += 2) { // Process groups of 2
10279
+ let temp = QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45;
10280
+ temp += QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1));
10281
+ appendBits(temp, 11, bb);
10282
+ }
10283
+ if (i < text.length) // 1 character remaining
10284
+ appendBits(QrSegment.ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb);
10285
+ return new QrSegment(QrSegment.Mode.ALPHANUMERIC, text.length, bb);
10286
+ }
10287
+ // Returns a new mutable list of zero or more segments to represent the given Unicode text string.
10288
+ // The result may use various segment modes and switch modes to optimize the length of the bit stream.
10289
+ static makeSegments(text) {
10290
+ // Select the most efficient segment encoding automatically
10291
+ if (text == "")
10292
+ return [];
10293
+ else if (QrSegment.isNumeric(text))
10294
+ return [QrSegment.makeNumeric(text)];
10295
+ else if (QrSegment.isAlphanumeric(text))
10296
+ return [QrSegment.makeAlphanumeric(text)];
10297
+ else
10298
+ return [QrSegment.makeBytes(QrSegment.toUtf8ByteArray(text))];
10299
+ }
10300
+ // Returns a segment representing an Extended Channel Interpretation
10301
+ // (ECI) designator with the given assignment value.
10302
+ static makeEci(assignVal) {
10303
+ let bb = [];
10304
+ if (assignVal < 0)
10305
+ throw new RangeError("ECI assignment value out of range");
10306
+ else if (assignVal < (1 << 7))
10307
+ appendBits(assignVal, 8, bb);
10308
+ else if (assignVal < (1 << 14)) {
10309
+ appendBits(0b10, 2, bb);
10310
+ appendBits(assignVal, 14, bb);
10311
+ }
10312
+ else if (assignVal < 1000000) {
10313
+ appendBits(0b110, 3, bb);
10314
+ appendBits(assignVal, 21, bb);
10315
+ }
10316
+ else
10317
+ throw new RangeError("ECI assignment value out of range");
10318
+ return new QrSegment(QrSegment.Mode.ECI, 0, bb);
10319
+ }
10320
+ // Tests whether the given string can be encoded as a segment in numeric mode.
10321
+ // A string is encodable iff each character is in the range 0 to 9.
10322
+ static isNumeric(text) {
10323
+ return QrSegment.NUMERIC_REGEX.test(text);
10324
+ }
10325
+ // Tests whether the given string can be encoded as a segment in alphanumeric mode.
10326
+ // A string is encodable iff each character is in the following set: 0 to 9, A to Z
10327
+ // (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
10328
+ static isAlphanumeric(text) {
10329
+ return QrSegment.ALPHANUMERIC_REGEX.test(text);
10330
+ }
10331
+ /*-- Constructor (low level) and fields --*/
10332
+ // Creates a new QR Code segment with the given attributes and data.
10333
+ // The character count (numChars) must agree with the mode and the bit buffer length,
10334
+ // but the constraint isn't checked. The given bit buffer is cloned and stored.
10335
+ constructor(
10336
+ // The mode indicator of this segment.
10337
+ mode,
10338
+ // The length of this segment's unencoded data. Measured in characters for
10339
+ // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
10340
+ // Always zero or positive. Not the same as the data's bit length.
10341
+ numChars,
10342
+ // The data bits of this segment. Accessed through getData().
10343
+ bitData) {
10344
+ this.mode = mode;
10345
+ this.numChars = numChars;
10346
+ this.bitData = bitData;
10347
+ if (numChars < 0)
10348
+ throw new RangeError("Invalid argument");
10349
+ this.bitData = bitData.slice(); // Make defensive copy
10350
+ }
10351
+ /*-- Methods --*/
10352
+ // Returns a new copy of the data bits of this segment.
10353
+ getData() {
10354
+ return this.bitData.slice(); // Make defensive copy
10355
+ }
10356
+ // (Package-private) Calculates and returns the number of bits needed to encode the given segments at
10357
+ // the given version. The result is infinity if a segment has too many characters to fit its length field.
10358
+ static getTotalBits(segs, version) {
10359
+ let result = 0;
10360
+ for (const seg of segs) {
10361
+ const ccbits = seg.mode.numCharCountBits(version);
10362
+ if (seg.numChars >= (1 << ccbits))
10363
+ return Infinity; // The segment's length doesn't fit the field's bit width
10364
+ result += 4 + ccbits + seg.bitData.length;
10365
+ }
10366
+ return result;
10367
+ }
10368
+ // Returns a new array of bytes representing the given string encoded in UTF-8.
10369
+ static toUtf8ByteArray(str) {
10370
+ str = encodeURI(str);
10371
+ let result = [];
10372
+ for (let i = 0; i < str.length; i++) {
10373
+ if (str.charAt(i) != "%")
10374
+ result.push(str.charCodeAt(i));
10375
+ else {
10376
+ result.push(parseInt(str.substring(i + 1, i + 3), 16));
10377
+ i += 2;
10378
+ }
10379
+ }
10380
+ return result;
10381
+ }
10382
+ /*-- Constants --*/
10383
+ // Describes precisely all strings that are encodable in numeric mode.
10384
+ static NUMERIC_REGEX = /^[0-9]*$/;
10385
+ // Describes precisely all strings that are encodable in alphanumeric mode.
10386
+ static ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+.\/:-]*$/;
10387
+ // The set of all legal characters in alphanumeric mode,
10388
+ // where each character value maps to the index in the string.
10389
+ static ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
10390
+ }
10391
+ qrcodegen.QrSegment = QrSegment;
10392
+ })(qrcodegen || (qrcodegen = {}));
10393
+ /*---- Public helper enumeration ----*/
10394
+ (function (qrcodegen) {
10395
+ (function (QrCode) {
10396
+ /*
10397
+ * The error correction level in a QR Code symbol. Immutable.
10398
+ */
10399
+ class Ecc {
10400
+ ordinal;
10401
+ formatBits;
10402
+ /*-- Constants --*/
10403
+ static LOW = new Ecc(0, 1); // The QR Code can tolerate about 7% erroneous codewords
10404
+ static MEDIUM = new Ecc(1, 0); // The QR Code can tolerate about 15% erroneous codewords
10405
+ static QUARTILE = new Ecc(2, 3); // The QR Code can tolerate about 25% erroneous codewords
10406
+ static HIGH = new Ecc(3, 2); // The QR Code can tolerate about 30% erroneous codewords
10407
+ /*-- Constructor and fields --*/
10408
+ constructor(
10409
+ // In the range 0 to 3 (unsigned 2-bit integer).
10410
+ ordinal,
10411
+ // (Package-private) In the range 0 to 3 (unsigned 2-bit integer).
10412
+ formatBits) {
10413
+ this.ordinal = ordinal;
10414
+ this.formatBits = formatBits;
10415
+ }
10416
+ }
10417
+ QrCode.Ecc = Ecc;
10418
+ })(qrcodegen.QrCode || (qrcodegen.QrCode = {}));
10419
+ })(qrcodegen || (qrcodegen = {}));
10420
+ /*---- Public helper enumeration ----*/
10421
+ (function (qrcodegen) {
10422
+ (function (QrSegment) {
10423
+ /*
10424
+ * Describes how a segment's data bits are interpreted. Immutable.
10425
+ */
10426
+ class Mode {
10427
+ modeBits;
10428
+ numBitsCharCount;
10429
+ /*-- Constants --*/
10430
+ static NUMERIC = new Mode(0x1, [10, 12, 14]);
10431
+ static ALPHANUMERIC = new Mode(0x2, [9, 11, 13]);
10432
+ static BYTE = new Mode(0x4, [8, 16, 16]);
10433
+ static KANJI = new Mode(0x8, [8, 10, 12]);
10434
+ static ECI = new Mode(0x7, [0, 0, 0]);
10435
+ /*-- Constructor and fields --*/
10436
+ constructor(
10437
+ // The mode indicator bits, which is a uint4 value (range 0 to 15).
10438
+ modeBits,
10439
+ // Number of character count bits for three different version ranges.
10440
+ numBitsCharCount) {
10441
+ this.modeBits = modeBits;
10442
+ this.numBitsCharCount = numBitsCharCount;
10443
+ }
10444
+ /*-- Method --*/
10445
+ // (Package-private) Returns the bit width of the character count field for a segment in
10446
+ // this mode in a QR Code at the given version number. The result is in the range [0, 16].
10447
+ numCharCountBits(ver) {
10448
+ return this.numBitsCharCount[Math.floor((ver + 7) / 17)];
10449
+ }
10450
+ }
10451
+ QrSegment.Mode = Mode;
10452
+ })(qrcodegen.QrSegment || (qrcodegen.QrSegment = {}));
10453
+ })(qrcodegen || (qrcodegen = {}));
10454
+
9580
10455
  class DataElementBarcode extends DataElementLeaf {
9581
10456
  resizeable = true;
9582
10457
  barCodeCanvas;
@@ -9591,6 +10466,11 @@ class DataElementBarcode extends DataElementLeaf {
9591
10466
  this.cache = false;
9592
10467
  });
9593
10468
  }
10469
+ //伸缩的模式,auto:可以任意伸缩高度和宽度,scale:只能等比例伸缩高度宽度
10470
+ //resizeMode:'auto'|'scale'='auto';
10471
+ get resizeMode() {
10472
+ return this.props.type === 'qrcode';
10473
+ }
9594
10474
  createRenderObject() {
9595
10475
  const render = new DataElementBarcodeRenderObject(this);
9596
10476
  render.rect.width = this.props.width + 2;
@@ -9672,6 +10552,62 @@ class DataElementBarcodeRenderObject extends ResizeLeafRenderObject {
9672
10552
  ctxNative.fill();
9673
10553
  ctxNative.restore();
9674
10554
  }
10555
+ exportHTML(event) {
10556
+ const t = super.exportHTML(event);
10557
+ if (this.element.props.type === 'qrcode') {
10558
+ const QRC = qrcodegen.QrCode;
10559
+ const qr0 = QRC.encodeText(this.element.props.text, QRC.Ecc.MEDIUM);
10560
+ t.children = [this.toSvgString(qr0, 2, '#000', '#000')];
10561
+ }
10562
+ else {
10563
+ const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
10564
+ JsBarcode__default["default"](svg, this.element.props.text);
10565
+ const vNode = snabbdom.toVNode(svg);
10566
+ t.children = [vNode];
10567
+ }
10568
+ return t;
10569
+ }
10570
+ toSvgString(qr, border, lightColor, darkColor) {
10571
+ let parts = [];
10572
+ for (let y = 0; y < qr.size; y++) {
10573
+ for (let x = 0; x < qr.size; x++) {
10574
+ if (qr.getModule(x, y))
10575
+ parts.push(`M${x + border},${y + border}h1v1h-1z`);
10576
+ }
10577
+ }
10578
+ return {
10579
+ sel: 'svg',
10580
+ data: {
10581
+ ns: 'http://www.w3.org/2000/svg',
10582
+ attrs: {
10583
+ viewBox: `0 0 ${qr.size + border * 2} ${qr.size + border * 2}`,
10584
+ width: this.element.props.width,
10585
+ height: this.element.props.height,
10586
+ stroke: 'none'
10587
+ }
10588
+ },
10589
+ children: [{
10590
+ sel: 'rect',
10591
+ data: {
10592
+ ns: 'http://www.w3.org/2000/svg',
10593
+ attrs: {
10594
+ width: '100%',
10595
+ height: '100%',
10596
+ fill: '#fff'
10597
+ }
10598
+ }
10599
+ }, {
10600
+ sel: 'path',
10601
+ data: {
10602
+ ns: 'http://www.w3.org/2000/svg',
10603
+ attrs: {
10604
+ d: parts.join(" "),
10605
+ fill: '#000'
10606
+ }
10607
+ }
10608
+ }]
10609
+ };
10610
+ }
9675
10611
  }
9676
10612
  class DataElementBarcodeFactory extends ElementFactory {
9677
10613
  match(type) {
@@ -10366,6 +11302,57 @@ class DataElementListFactory extends DataElementBaseFactory {
10366
11302
  }
10367
11303
  }
10368
11304
 
11305
+ class BreakElement extends LeafElement {
11306
+ textProps;
11307
+ constructor() {
11308
+ super('br');
11309
+ this.textProps = new TextProps();
11310
+ this.textProps.fontSize = 14;
11311
+ this.textProps.fontName = '宋体';
11312
+ this.textProps.color = '#595959';
11313
+ }
11314
+ createRenderObject() {
11315
+ const symbol = new BreakRenderObject(this);
11316
+ symbol.rect.height = 14;
11317
+ symbol.rect.width = 7;
11318
+ return symbol;
11319
+ }
11320
+ serialize() {
11321
+ return {
11322
+ type: 'br',
11323
+ props: {}
11324
+ };
11325
+ }
11326
+ clone() {
11327
+ const clone = new BreakElement();
11328
+ //clone.renderCtx = this.renderCtx;
11329
+ return clone;
11330
+ }
11331
+ }
11332
+ class BreakRenderObject extends LeafRenderObject {
11333
+ render(e) {
11334
+ const { render, position } = e;
11335
+ if (render.drawMode === 'print') {
11336
+ return;
11337
+ }
11338
+ render.contentContext.drawText('↓', this.element.textProps, position.x, position.y, 20, this.rect.height);
11339
+ }
11340
+ clone() {
11341
+ const render = new BreakRenderObject(this.element);
11342
+ render.rect = ElementUtil.cloneRect(this.rect);
11343
+ return render;
11344
+ }
11345
+ }
11346
+ class BreakFactory extends ElementFactory {
11347
+ match(type) {
11348
+ return type === 'br';
11349
+ }
11350
+ createElement(data) {
11351
+ const ele = new BreakElement();
11352
+ return ele;
11353
+ }
11354
+ }
11355
+
10369
11356
  class DataElementText extends DataElementInlineGroup {
10370
11357
  //props: DataEleBaseTextProps;
10371
11358
  constructor() {
@@ -10396,10 +11383,19 @@ class DataElementText extends DataElementInlineGroup {
10396
11383
  this.pubOnChange('self');
10397
11384
  this.clearInnerItems();
10398
11385
  if (val) {
10399
- const valueText = new TextGroupElement();
10400
- this.props.valueTextProps.clone(valueText.props);
10401
- valueText.text = val + '';
10402
- this.addChild(valueText, this.length - 1);
11386
+ const items = val.split('<br/>');
11387
+ if (items.length) {
11388
+ items.forEach((item, index) => {
11389
+ const valueText = new TextGroupElement();
11390
+ this.props.valueTextProps.clone(valueText.props);
11391
+ valueText.text = item + '';
11392
+ this.addChild(valueText, this.length - 1);
11393
+ if (index < items.length - 1) {
11394
+ const brElement = new BreakElement();
11395
+ this.addChild(brElement, this.length - 1);
11396
+ }
11397
+ });
11398
+ }
10403
11399
  }
10404
11400
  this.onChangedValidate();
10405
11401
  }
@@ -11116,57 +12112,6 @@ class RadioBoxRenderObject extends LeafRenderObject {
11116
12112
  }
11117
12113
  }
11118
12114
 
11119
- class BreakElement extends LeafElement {
11120
- textProps;
11121
- constructor() {
11122
- super('br');
11123
- this.textProps = new TextProps();
11124
- this.textProps.fontSize = 14;
11125
- this.textProps.fontName = '宋体';
11126
- this.textProps.color = '#595959';
11127
- }
11128
- createRenderObject() {
11129
- const symbol = new BreakRenderObject(this);
11130
- symbol.rect.height = 14;
11131
- symbol.rect.width = 7;
11132
- return symbol;
11133
- }
11134
- serialize() {
11135
- return {
11136
- type: 'br',
11137
- props: {}
11138
- };
11139
- }
11140
- clone() {
11141
- const clone = new BreakElement();
11142
- //clone.renderCtx = this.renderCtx;
11143
- return clone;
11144
- }
11145
- }
11146
- class BreakRenderObject extends LeafRenderObject {
11147
- render(e) {
11148
- const { render, position } = e;
11149
- if (render.drawMode === 'print') {
11150
- return;
11151
- }
11152
- render.contentContext.drawText('↓', this.element.textProps, position.x, position.y, 20, this.rect.height);
11153
- }
11154
- clone() {
11155
- const render = new BreakRenderObject(this.element);
11156
- render.rect = ElementUtil.cloneRect(this.rect);
11157
- return render;
11158
- }
11159
- }
11160
- class BreakFactory extends ElementFactory {
11161
- match(type) {
11162
- return type === 'br';
11163
- }
11164
- createElement(data) {
11165
- const ele = new BreakElement();
11166
- return ele;
11167
- }
11168
- }
11169
-
11170
12115
  class ColumnPatchUtil {
11171
12116
  static getPatchPacks(cols, splitCols) {
11172
12117
  const oldLinePointMap = this.getLinePointMap(cols);
@@ -15991,7 +16936,7 @@ class DocumentEvent {
15991
16936
  //如果单元格中包含图片等可缩放的元素,并且元素的大小超过单元格,则当前图片的某一部分就无法缩放
15992
16937
  if (!this.ismousedown && this.focusedElement && this.focusedRect && this.focusedElement['resizeable']) {
15993
16938
  const relativePos = { x: mousePos.x - this.focusedRect.x, y: mousePos.y - this.focusedRect.y };
15994
- const isInCellBorder = CommonUtil.isInPictureResizePoint(this.focusedRect, relativePos, 4);
16939
+ let isInCellBorder = CommonUtil.isInPictureResizePoint(this.focusedRect, relativePos, 4);
15995
16940
  if (isInCellBorder) {
15996
16941
  cursorType = ElementUtil.getBorderCursor(isInCellBorder.borderType);
15997
16942
  if (isInCellBorder?.borderType === 'none') {
@@ -16593,6 +17538,7 @@ class DocumentEvent {
16593
17538
  const mousedownPos = this.edgeRenderInfo.mousedownPos;
16594
17539
  let moveDistanceX = this.currentPos.x - mousedownPos.x;
16595
17540
  let moveDistanceY = this.currentPos.y - mousedownPos.y;
17541
+ const isScale = imgElement['resizeMode'] === 'scale' || e.shift;
16596
17542
  if (['left-top', 'left-middle', 'left-bottom', 'right-top', 'right-middle', 'right-bottom', 'top-middle', 'bottom-middle'].indexOf(border) >= 0) {
16597
17543
  if (['left-middle', 'right-middle'].indexOf(border) >= 0) {
16598
17544
  moveDistanceY = 0;
@@ -16601,7 +17547,7 @@ class DocumentEvent {
16601
17547
  moveDistanceX = 0;
16602
17548
  }
16603
17549
  //shift键按比例缩放
16604
- if (e.shift && ['left-top', 'right-top', 'left-bottom', 'right-bottom'].indexOf(border) >= 0) {
17550
+ if (isScale || ['left-top', 'right-top', 'left-bottom', 'right-bottom'].indexOf(border) >= 0) {
16605
17551
  let scale = 1;
16606
17552
  if (Math.abs(moveDistanceX) > Math.abs(moveDistanceY)) {
16607
17553
  scale = moveDistanceX / imgElement.props.width;
@@ -16963,55 +17909,6 @@ class DocumentInput {
16963
17909
  onTabKeyEvent = new Subject$1();
16964
17910
  constructor(docCtx) {
16965
17911
  this.docCtx = docCtx;
16966
- // const os = ElementUtil.getOSPlatform();
16967
- // this.bindInput(node);
16968
- // node.addEventListener('keydown', evt => {
16969
- // const keyEvent = new KeyboradElementEvent(this.docCtx);
16970
- // keyEvent.sourceEvent = evt;
16971
- // if (DocumentEvent.invokeEvent('ElementKeyDown', this.docCtx.selectionState.startControl as LeafElement, keyEvent, 'All')) {
16972
- // return;
16973
- // }
16974
- // if (evt.keyCode === 8) {
16975
- // this.onBackspaceEvent.next(evt);
16976
- // } else if (evt.keyCode === 13 && !evt.shiftKey) {
16977
- // this.onEnterEvent.next();
16978
- // } else if (evt.keyCode === 37) {
16979
- // this.onLeftEvent.next();
16980
- // } else if (evt.keyCode === 39) {
16981
- // this.onRightEvent.next();
16982
- // } else if (evt.keyCode === 38) {
16983
- // this.onUpEvent.next();
16984
- // } else if (evt.keyCode === 40) {
16985
- // this.onDownEvent.next();
16986
- // } else if (evt.keyCode === 9) {
16987
- // evt.preventDefault();
16988
- // this.onTabKeyEvent.next();
16989
- // } else if (evt.keyCode === 13 && evt.shiftKey) {
16990
- // evt.preventDefault();
16991
- // this.onInsertBr.next();
16992
- // } else if (evt.keyCode === 46) {
16993
- // this.onDeleteEvent.next(evt);
16994
- // } else if (evt.ctrlKey && evt.keyCode === 65 && os !== 'Mac') {
16995
- // evt.preventDefault();
16996
- // this.onSelectAllEvent.next();
16997
- // } else if (evt.metaKey && evt.keyCode === 65 && os === 'Mac') {
16998
- // evt.preventDefault();
16999
- // this.onSelectAllEvent.next();
17000
- // } else if (evt.keyCode === 36) {
17001
- // this.onHomeEvent.next();
17002
- // } else if (evt.keyCode === 35) {
17003
- // this.onEndEvent.next();
17004
- // }
17005
- // });
17006
- // node.addEventListener('copy', evt => {
17007
- // this.onCopyEvent.next(evt);
17008
- // });
17009
- // node.addEventListener('paste', evt => {
17010
- // this.onPasteEvent.next(evt);
17011
- // })
17012
- // node.addEventListener('cut', evt => {
17013
- // this.onCutEvent.next(evt);
17014
- // })
17015
17912
  }
17016
17913
  getEventListener() {
17017
17914
  const os = ElementUtil.getOSPlatform();
@@ -18680,6 +19577,9 @@ function createPrintTemplate({ width, height, orient }) {
18680
19577
  box-sizing: border-box;
18681
19578
  -moz-box-sizing: border-box;
18682
19579
  }
19580
+ body *{
19581
+ white-space: pre;
19582
+ }
18683
19583
  @page {
18684
19584
  size: ${orient};
18685
19585
  margin: 0;
@@ -18750,6 +19650,18 @@ function printNodes(printNodes, options, printEvent = null) {
18750
19650
  }
18751
19651
  printIFrame.onload = () => {
18752
19652
  setTimeout(() => {
19653
+ printIFrame.contentWindow?.window.matchMedia('print').addListener(function (query) {
19654
+ if (!query.matches) {
19655
+ console.log('用户已经打印');
19656
+ // 执行打印完成后需要执行的代码
19657
+ }
19658
+ });
19659
+ printIFrame.contentWindow?.window.matchMedia('screen').addListener(function (query) {
19660
+ if (!query.matches) {
19661
+ console.log('用户已经打印');
19662
+ // 执行打印完成后需要执行的代码
19663
+ }
19664
+ });
18753
19665
  printIFrame.contentWindow?.print();
18754
19666
  printIFrame.parentNode?.removeChild(printIFrame);
18755
19667
  }, 0);
@@ -24622,18 +25534,12 @@ class DocumentPrintOffscreenBase {
24622
25534
  const docSvgHelper = new DocumentSvg(this.viewOptions, new Map(), this.renderCtx); //.getHTMLVNode(docRenders) as Array<EditorVNodeObject>;
24623
25535
  docSvgHelper.mode = 'print';
24624
25536
  const pageSvgVNodes = docRenders.filter((item, index) => !printRanges || printRanges.indexOf(index) >= 0).map(item => docSvgHelper.getPageSvgVNode(item));
24625
- ({
24626
- sel: 'div#docContent',
24627
- data: {},
24628
- children: [...pageSvgVNodes]
24629
- });
24630
25537
  const patch = init([
24631
25538
  modules.class,
24632
25539
  modules.props,
24633
25540
  modules.attributes,
24634
25541
  modules.style
24635
25542
  ]);
24636
- new DOMParser();
24637
25543
  const domNodes = pageSvgVNodes.map(item => patch(item)); //.map(item => docParser.parseFromString(item, 'text/html').firstChild) as Array<HTMLElement>;
24638
25544
  return domNodes;
24639
25545
  }
@@ -24693,12 +25599,16 @@ class EditorCalendarVNode {
24693
25599
  selectedDate;
24694
25600
  currentDate = '';
24695
25601
  onSetValue = new Subject$1();
25602
+ currTime;
25603
+ selectedTime;
24696
25604
  constructor() {
24697
25605
  this.currYear = createSignal(new Date().getFullYear());
24698
25606
  //月份赋值是按照索引来的,所以要减1
24699
25607
  this.currMonth = createSignal(new Date().getMonth());
24700
25608
  this.currCalendarMode = createSignal('day');
24701
25609
  this.selectedDate = createSignal(null);
25610
+ this.currTime = createSignal(null);
25611
+ this.selectedTime = createSignal(null);
24702
25612
  }
24703
25613
  reset() {
24704
25614
  this.currYear.value = new Date().getFullYear();
@@ -24707,6 +25617,8 @@ class EditorCalendarVNode {
24707
25617
  this.currCalendarMode.value = 'day';
24708
25618
  this.selectedDate.value = moment__default["default"]().format('YYYY-MM-DD');
24709
25619
  this.currentDate = '';
25620
+ this.currTime.value = null;
25621
+ this.selectedTime.value = null;
24710
25622
  }
24711
25623
  render(position, dataValue) {
24712
25624
  if (!this.currentDate && dataValue) {
@@ -24718,6 +25630,10 @@ class EditorCalendarVNode {
24718
25630
  if (!this.currentDate) {
24719
25631
  this.currentDate = moment__default["default"]().format('YYYY-MM-DD');
24720
25632
  }
25633
+ if (!this.currTime.value) {
25634
+ this.currTime.value = moment__default["default"]().format('HH:mm:ss');
25635
+ this.selectedTime.value = this.currTime.value;
25636
+ }
24721
25637
  const container = this.renderDropContainer(position);
24722
25638
  let viewNode;
24723
25639
  if (this.currCalendarMode.value === 'day') {
@@ -24844,6 +25760,31 @@ class EditorCalendarVNode {
24844
25760
  sel: 'div.editor-calendar-footer',
24845
25761
  data: {},
24846
25762
  children: [{
25763
+ sel: 'div.editor-calendar-footer-left',
25764
+ data: {},
25765
+ children: [
25766
+ {
25767
+ sel: 'input.editor-calendar-footer-left-time',
25768
+ data: {
25769
+ attrs: {
25770
+ value: this.currTime.value
25771
+ },
25772
+ on: {
25773
+ change: (event) => {
25774
+ if (moment__default["default"](event.target.value, 'HH:mm:ss').isValid()) {
25775
+ this.selectedTime = event.target.value;
25776
+ }
25777
+ else {
25778
+ event.target.value = this.currTime.value;
25779
+ this.currTime.onChange();
25780
+ }
25781
+ }
25782
+ }
25783
+ }
25784
+ }
25785
+ ]
25786
+ },
25787
+ {
24847
25788
  sel: 'div.editor-calendar-footer-right',
24848
25789
  data: {},
24849
25790
  children: [{
@@ -24855,7 +25796,7 @@ class EditorCalendarVNode {
24855
25796
  this.onSetValue.next(new Date());
24856
25797
  }
24857
25798
  else {
24858
- this.onSetValue.next(moment__default["default"](this.selectedDate.value).toDate());
25799
+ this.onSetValue.next(moment__default["default"](this.selectedDate.value + ' ' + this.selectedTime.value).toDate());
24859
25800
  }
24860
25801
  }
24861
25802
  }
@@ -25898,12 +26839,18 @@ class DocEditor {
25898
26839
  */
25899
26840
  getCurrentDataElement() {
25900
26841
  const selectionState = this.documentSelection.selectionState;
25901
- const { startControl } = selectionState;
26842
+ const { startControl, startOffset } = selectionState;
25902
26843
  if (startControl) {
25903
26844
  if (!ElementUtil.verifyHitable(startControl)) {
25904
26845
  return null;
25905
26846
  }
25906
- return ElementUtil.getParent(startControl, validateDataEle);
26847
+ const dataEle = ElementUtil.getParent(startControl, validateDataEle);
26848
+ if (IsInSideDataElement(startControl, startOffset)) {
26849
+ return dataEle;
26850
+ }
26851
+ else {
26852
+ return null;
26853
+ }
25907
26854
  }
25908
26855
  return null;
25909
26856
  }
@@ -26486,7 +27433,7 @@ class DocEditor {
26486
27433
  const vNodeFunc = this.renderRoot();
26487
27434
  setActiveEditorContext(null);
26488
27435
  const render = () => {
26489
- console.time('patch');
27436
+ //console.time('patch');
26490
27437
  setActiveEditorContext(this);
26491
27438
  const vNode = vNodeFunc.render();
26492
27439
  setActiveEditorContext(null);
@@ -26498,7 +27445,7 @@ class DocEditor {
26498
27445
  this.vNodeDocContent = this.nodePatch(this.svgContainer, vNode);
26499
27446
  }
26500
27447
  this.afterNodePatch.next();
26501
- console.timeEnd('patch');
27448
+ //console.timeEnd('patch');
26502
27449
  };
26503
27450
  render();
26504
27451
  this.onShouldRender.subscribe(() => {
@@ -26590,8 +27537,10 @@ class DocEditor {
26590
27537
  }
26591
27538
  getHtml() {
26592
27539
  const offPrint = new DocumentPrintOffscreen();
26593
- offPrint.beforePrint.subscribe(() => { });
26594
- offPrint.afterPrint.subscribe(() => { });
27540
+ offPrint.beforePrint.subscribe(() => {
27541
+ });
27542
+ offPrint.afterPrint.subscribe(() => {
27543
+ });
26595
27544
  const html = offPrint.getSvgNodes(this.docCtx.document.paintRenders);
26596
27545
  console.log(html);
26597
27546
  }
@@ -26647,6 +27596,9 @@ class DocEditor {
26647
27596
  const values = options.filter(item => item.checked).map(item => item.code);
26648
27597
  dataEle.setValue(values);
26649
27598
  editor.setDataElemEndFocus(dataEle);
27599
+ if (!multiSelect) {
27600
+ editor.selectionState.clear();
27601
+ }
26650
27602
  };
26651
27603
  const itemsVNode = options.map(item => {
26652
27604
  const ckbVNode = {
@@ -26843,11 +27795,18 @@ const deleteCurrentParagraph = (evt) => {
26843
27795
  selectionState.clear();
26844
27796
  const psymbol = ElementUtil.getLastLeafElement(currentElement);
26845
27797
  const nextFocusableEle = ElementUtil.getRecursionNextSiblingElement(psymbol, false, true, viewOptions);
27798
+ const parentContainer = currentElement.parent;
26846
27799
  if (nextFocusableEle) {
26847
- selectionState.resetRange(nextFocusableEle, 0);
27800
+ if (nextFocusableEle.parent === parentContainer) {
27801
+ selectionState.resetRange(nextFocusableEle, 0);
27802
+ }
27803
+ else {
27804
+ selectionState.resetRange(parentContainer, 0);
27805
+ }
26848
27806
  }
26849
27807
  else {
26850
- selectionState.clear();
27808
+ selectionState.resetRange(parentContainer, 0);
27809
+ //selectionState.clear();
26851
27810
  }
26852
27811
  currentElement.remove();
26853
27812
  currentElement.destroy();