@logicflow/extension 2.1.4 → 2.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleAttributes = exports.lfJson2Xml = void 0;
3
+ exports.escapeXml = exports.handleAttributes = exports.lfJson2Xml = void 0;
4
4
  function type(obj) {
5
5
  return Object.prototype.toString.call(obj);
6
6
  }
@@ -28,6 +28,30 @@ function handleAttributes(o) {
28
28
  return t;
29
29
  }
30
30
  exports.handleAttributes = handleAttributes;
31
+ /**
32
+ * 将普通文本中的一些特殊字符进行转移,保障文本安全地嵌入 XML:
33
+ * - 空值(`null/undefined`)返回空字符串,避免输出非法字面量;
34
+ * - 按顺序转义 XML 保留字符:`&`, `<`, `>`, `"`, `'`;
35
+ * 注意优先转义 `&`,避免后续生成的实体被再次转义。
36
+ * @param text 原始文本
37
+ * @returns 已完成 XML 转义的字符串
38
+ */
39
+ function escapeXml(text) {
40
+ // 空值直接返回空字符串,防止在 XML 中出现 "null"/"undefined"
41
+ if (text == null)
42
+ return '';
43
+ return (text
44
+ .toString()
45
+ // & 必须先转义,避免影响后续 < > " ' 的实体
46
+ .replace(/&/g, '&amp;')
47
+ // 小于号与大于号,用于标签边界
48
+ .replace(/</g, '&lt;')
49
+ .replace(/>/g, '&gt;')
50
+ // 双引号与单引号,用于属性值的包裹
51
+ .replace(/"/g, '&quot;')
52
+ .replace(/'/g, '&apos;'));
53
+ }
54
+ exports.escapeXml = escapeXml;
31
55
  function getAttributes(obj) {
32
56
  var tmp = obj;
33
57
  try {
@@ -38,7 +62,8 @@ function getAttributes(obj) {
38
62
  catch (error) {
39
63
  tmp = JSON.stringify(handleAttributes(obj)).replace(/"/g, "'");
40
64
  }
41
- return tmp;
65
+ // 确保属性值中的特殊字符被正确转义
66
+ return escapeXml(String(tmp));
42
67
  }
43
68
  var tn = '\t\n';
44
69
  // @see issue https://github.com/didi/LogicFlow/issues/718, refactoring of function toXml
@@ -50,7 +75,7 @@ function toXml(obj, name, depth) {
50
75
  }
51
76
  var str = '';
52
77
  if (name === '#text') {
53
- return tn + frontSpace + obj;
78
+ return tn + frontSpace + escapeXml(String(obj));
54
79
  }
55
80
  else if (name === '#cdata-section') {
56
81
  return tn + frontSpace + '<![CDATA[' + obj + ']]>';
@@ -82,7 +107,7 @@ function toXml(obj, name, depth) {
82
107
  (children_1 !== '' ? ">".concat(children_1).concat(tn + frontSpace, "</").concat(name, ">") : ' />');
83
108
  }
84
109
  else {
85
- str += tn + frontSpace + "<".concat(name, ">").concat(obj.toString(), "</").concat(name, ">");
110
+ str += tn + frontSpace + "<".concat(name, ">").concat(escapeXml(String(obj)), "</").concat(name, ">");
86
111
  }
87
112
  }
88
113
  return str;
@@ -5,6 +5,7 @@ exports.lfXml2Json = void 0;
5
5
  // ========================================================================
6
6
  // XML.ObjTree -- XML source code from/to JavaScript object like E4X
7
7
  // ========================================================================
8
+ var json2xml_1 = require("./json2xml");
8
9
  var XML = function () { };
9
10
  // constructor
10
11
  XML.ObjTree = function () {
@@ -293,13 +294,7 @@ XML.ObjTree.prototype.scalar_to_xml = function (name, text) {
293
294
  }
294
295
  };
295
296
  // method: xml_escape( text )
296
- XML.ObjTree.prototype.xml_escape = function (text) {
297
- return text
298
- .replace(/&/g, '&')
299
- .replace(/</g, '<')
300
- .replace(/>/g, '>')
301
- .replace(/"/g, '"');
302
- };
297
+ XML.ObjTree.prototype.xml_escape = json2xml_1.escapeXml;
303
298
  /*
304
299
  // ========================================================================
305
300
 
@@ -98,8 +98,10 @@ var MiniMap = /** @class */ (function () {
98
98
  */
99
99
  this.show = function (left, top) {
100
100
  if (!_this.isShow) {
101
+ _this.initMiniMap();
102
+ _this.lf.on('graph:resize', _this.onGraphResize);
101
103
  _this.createMiniMap(left, top);
102
- _this.setView();
104
+ _this.setView(true);
103
105
  }
104
106
  _this.isShow = true;
105
107
  };
@@ -108,6 +110,13 @@ var MiniMap = /** @class */ (function () {
108
110
  */
109
111
  this.hide = function () {
110
112
  if (_this.isShow) {
113
+ // 隐藏小地图时摧毁实例
114
+ (0, vue_node_registry_1.destroyTeleportContainer)(_this.lfMap.graphModel.flowId);
115
+ _this.lf.off('graph:resize', _this.onGraphResize);
116
+ _this.lfMap.destroy();
117
+ // 保证重新创建实例时,小地图中内容偏移正确
118
+ _this.translateX = 0;
119
+ _this.translateY = 0;
111
120
  _this.removeMiniMap();
112
121
  _this.lf.emit('miniMap:close', {});
113
122
  }
@@ -236,8 +245,6 @@ var MiniMap = /** @class */ (function () {
236
245
  this.bounds = boundsInit;
237
246
  this.elementAreaBounds = boundsInit;
238
247
  this.viewPortBounds = boundsInit;
239
- this.initMiniMap();
240
- lf.on('graph:resize', this.onGraphResize);
241
248
  }
242
249
  /**
243
250
  * 初始化小地图的配置
@@ -6,10 +6,18 @@ export type ProximityConnectProps = {
6
6
  distance: number;
7
7
  reverseDirection: boolean;
8
8
  virtualEdgeStyle: Record<string, unknown>;
9
+ /**
10
+ * proximityConnect 类型:
11
+ * - 'node': 节点-节点连接
12
+ * - 'anchor': 锚点-锚点连接
13
+ * - 'default': 节点-锚点连接
14
+ */
15
+ type: 'node' | 'anchor' | 'default';
9
16
  };
10
17
  export declare class ProximityConnect {
11
18
  static pluginName: string;
12
19
  enable: boolean;
20
+ type: 'node' | 'anchor' | 'default';
13
21
  lf: LogicFlow;
14
22
  closestNode?: BaseNodeModel;
15
23
  currentDistance: number;
@@ -18,6 +18,7 @@ var ProximityConnect = /** @class */ (function () {
18
18
  function ProximityConnect(_a) {
19
19
  var lf = _a.lf, options = _a.options;
20
20
  this.enable = true;
21
+ this.type = 'default';
21
22
  this.currentDistance = Infinity; // 当前间距
22
23
  this.thresholdDistance = 100; // 节点-节点连接距离阈值
23
24
  this.reverseDirection = false; // 节点-节点连线方向,默认是拖拽节点连向最近节点
@@ -37,6 +38,8 @@ var ProximityConnect = /** @class */ (function () {
37
38
  // 节点开始拖拽事件
38
39
  this.lf.graphModel.eventCenter.on('node:dragstart', function (_a) {
39
40
  var data = _a.data;
41
+ if (_this.type === 'anchor')
42
+ return;
40
43
  if (!_this.enable)
41
44
  return;
42
45
  var graphModel = _this.lf.graphModel;
@@ -45,12 +48,14 @@ var ProximityConnect = /** @class */ (function () {
45
48
  });
46
49
  // 节点拖拽事件
47
50
  this.lf.graphModel.eventCenter.on('node:drag', function () {
51
+ if (_this.type === 'anchor')
52
+ return;
48
53
  _this.handleNodeDrag();
49
54
  });
50
55
  // 锚点开始拖拽事件
51
56
  this.lf.graphModel.eventCenter.on('anchor:dragstart', function (_a) {
52
57
  var data = _a.data, nodeModel = _a.nodeModel;
53
- if (!_this.enable)
58
+ if (!_this.enable || _this.type === 'node')
54
59
  return;
55
60
  _this.currentNode = nodeModel;
56
61
  _this.currentAnchor = data;
@@ -58,20 +63,20 @@ var ProximityConnect = /** @class */ (function () {
58
63
  // 锚点拖拽事件
59
64
  this.lf.graphModel.eventCenter.on('anchor:drag', function (_a) {
60
65
  var _b = _a.e, clientX = _b.clientX, clientY = _b.clientY;
61
- if (!_this.enable)
66
+ if (!_this.enable || _this.type === 'node')
62
67
  return;
63
68
  _this.handleAnchorDrag(clientX, clientY);
64
69
  });
65
70
  // 节点、锚点拖拽结束事件
66
71
  this.lf.graphModel.eventCenter.on('node:drop', function () {
67
- if (!_this.enable)
72
+ if (!_this.enable || _this.type === 'anchor')
68
73
  return;
69
74
  _this.handleDrop();
70
75
  });
71
76
  // 锚点拖拽需要单独判断一下当前拖拽终点是否在某个锚点上,如果是,就不触发插件的连线,以免出现创建了两条连线的问题,表现见 issue 2140
72
77
  this.lf.graphModel.eventCenter.on('anchor:dragend', function (_a) {
73
78
  var e = _a.e, edgeModel = _a.edgeModel;
74
- if (!_this.enable)
79
+ if (!_this.enable || _this.type === 'node')
75
80
  return;
76
81
  var _b = _this.lf.graphModel.getPointByClient({
77
82
  x: e.clientX,
@@ -32,6 +32,14 @@ export type ToImageOptions = {
32
32
  * - `true`:只导出画面区域内的可见元素
33
33
  */
34
34
  partial?: boolean;
35
+ /**
36
+ * 导出图片时的安全系数,用于确保导出的图片能够容纳所有元素,默认值为 1.1
37
+ */
38
+ safetyFactor?: number;
39
+ /**
40
+ * 导出图片时的安全边距,用于确保导出的图片能够容纳所有元素,默认值为 40
41
+ */
42
+ safetyMargin?: number;
35
43
  };
36
44
  export type SnapshotResponse = {
37
45
  data: Blob | string;
@@ -407,7 +407,7 @@ var Snapshot = /** @class */ (function () {
407
407
  graphModel = this.lf.graphModel;
408
408
  transformModel = graphModel.transformModel;
409
409
  SCALE_X = transformModel.SCALE_X, SCALE_Y = transformModel.SCALE_Y, TRANSLATE_X = transformModel.TRANSLATE_X, TRANSLATE_Y = transformModel.TRANSLATE_Y;
410
- safetyFactor = 1.1 // 安全系数,增加20%的空间
410
+ safetyFactor = toImageOptions.safetyFactor || 1.1 // 安全系数,增加10%的空间
411
411
  ;
412
412
  actualWidth = (bbox.width / SCALE_X) * safetyFactor;
413
413
  actualHeight = (bbox.height / SCALE_Y) * safetyFactor;
@@ -416,7 +416,7 @@ var Snapshot = /** @class */ (function () {
416
416
  canvas = document.createElement('canvas');
417
417
  canvas.style.width = "".concat(bboxWidth, "px");
418
418
  canvas.style.height = "".concat(bboxHeight, "px");
419
- safetyMargin = 40 // 额外的安全边距
419
+ safetyMargin = toImageOptions.safetyMargin || 40 // 额外的安全边距
420
420
  ;
421
421
  _b = this.getCanvasDimensionsByBrowser(), maxCanvasDimension = _b.maxCanvasDimension, otherMaxCanvasDimension = _b.otherMaxCanvasDimension;
422
422
  MAX_CANVAS_DIMENSION = maxCanvasDimension;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logicflow/extension",
3
- "version": "2.1.4",
3
+ "version": "2.1.5",
4
4
  "description": "LogicFlow Extensions",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -20,8 +20,8 @@
20
20
  "author": "Logicflow-Team",
21
21
  "license": "Apache-2.0",
22
22
  "peerDependencies": {
23
- "@logicflow/vue-node-registry": "1.1.3",
24
- "@logicflow/core": "2.1.2"
23
+ "@logicflow/vue-node-registry": "1.1.4",
24
+ "@logicflow/core": "2.1.3"
25
25
  },
26
26
  "dependencies": {
27
27
  "@antv/hierarchy": "^0.6.11",
@@ -32,8 +32,8 @@
32
32
  "preact": "^10.17.1",
33
33
  "rangy": "^1.3.1",
34
34
  "vanilla-picker": "^2.12.3",
35
- "@logicflow/core": "2.1.2",
36
- "@logicflow/vue-node-registry": "1.1.3"
35
+ "@logicflow/core": "2.1.3",
36
+ "@logicflow/vue-node-registry": "1.1.4"
37
37
  },
38
38
  "devDependencies": {
39
39
  "less": "^4.1.1",