@tmagic/utils 1.8.0-beta.2 → 1.8.0-beta.21

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/dist/es/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, DATA_SOURCE_SET_DATA_METHOD_NAME } from "./const.js";
2
2
  import { addClassName, asyncLoadCss, asyncLoadJs, calcValueByFontsize, createDiv, getDocument, getElById, getIdFromEl, injectStyle, removeClassName, removeClassNameByClassName, setDslDomRelateConfig, setIdToEl } from "./dom.js";
3
- import { cloneDeep, set } from "lodash-es";
3
+ import { cloneDeep, get, set } from "lodash-es";
4
4
  import { NodeType } from "@tmagic/schema";
5
5
  //#region packages/utils/src/index.ts
6
6
  var _globalThis;
@@ -20,47 +20,48 @@ var emptyFn = () => void 0;
20
20
  * @param {Array} data 要查找的根容器节点
21
21
  * @return {Array} 组件在data中的子孙路径
22
22
  */
23
- var getNodePath = (id, data = []) => {
23
+ var getNodePath = (id, data = [], skip) => {
24
24
  const path = [];
25
- const get = function(id, data) {
25
+ const targetId = `${id}`;
26
+ const get = function(data) {
26
27
  if (!Array.isArray(data)) return null;
27
28
  for (let i = 0, l = data.length; i < l; i++) {
28
29
  const item = data[i];
29
30
  path.push(item);
30
- if (`${item.id}` === `${id}`) return item;
31
- if (item.items) {
32
- const node = get(id, item.items);
31
+ if (`${item.id}` === targetId) return item;
32
+ if (item.items && item !== skip) {
33
+ const node = get(item.items);
33
34
  if (node) return node;
34
35
  }
35
36
  path.pop();
36
37
  }
37
38
  return null;
38
39
  };
39
- get(id, data);
40
+ get(data);
40
41
  return path;
41
42
  };
42
- var getNodeInfo = (id, root) => {
43
+ var getNodeInfo = (id, root, skip) => {
43
44
  const info = {
44
45
  node: null,
45
46
  parent: null,
46
- page: null
47
+ page: null,
48
+ path: []
47
49
  };
48
50
  if (!root) return info;
49
51
  if (id === root.id) {
50
52
  info.node = root;
51
53
  return info;
52
54
  }
53
- const path = getNodePath(id, root.items);
55
+ const path = getNodePath(id, root.items, skip);
56
+ info.path = path;
54
57
  if (!path.length) return info;
55
58
  path.unshift(root);
56
59
  info.node = path[path.length - 1];
57
60
  info.parent = path[path.length - 2];
58
- path.forEach((item) => {
59
- if (isPage(item) || isPageFragment(item)) {
60
- info.page = item;
61
- return;
62
- }
63
- });
61
+ for (const item of path) if (isPageOrFragment(item)) {
62
+ info.page = item;
63
+ break;
64
+ }
64
65
  return info;
65
66
  };
66
67
  var filterXSS = (str) => str.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
@@ -142,6 +143,8 @@ var isPageFragment = (node) => {
142
143
  if (!node) return false;
143
144
  return Boolean(node.type?.toLowerCase() === NodeType.PAGE_FRAGMENT);
144
145
  };
146
+ /** 是否为页面或页面片 */
147
+ var isPageOrFragment = (node) => isPage(node) || isPageFragment(node);
145
148
  var isNumber = (value) => typeof value === "number" && !isNaN(value) || /^(-?\d+)(\.\d+)?$/.test(`${value}`);
146
149
  var getHost = (targetUrl) => targetUrl.match(/\/\/([^/]+)/)?.[1];
147
150
  var isSameDomain = (targetUrl = "", source = globalThis.location.host) => {
@@ -158,6 +161,12 @@ var guid = (digit = 8) => "x".repeat(digit).replace(/[xy]/g, (c) => {
158
161
  return (c === "x" ? r : r & 3 | 8).toString(16);
159
162
  });
160
163
  var getKeysArray = (keys) => `${keys}`.replace(/\[(\d+)\]/g, ".$1").split(".");
164
+ /**
165
+ * 判断某一层 key 是否为数组下标(纯数字)
166
+ * @param key 单层 key
167
+ * @returns 是否为数组下标
168
+ */
169
+ var isArrayIndex = (key) => /^\d+$/.test(`${key}`);
161
170
  var getValueByKeyPath = (keys = "", data = {}) => {
162
171
  return (Array.isArray(keys) ? keys : getKeysArray(keys)).reduce((accumulator, currentValue) => {
163
172
  if (isObject(accumulator)) return accumulator[currentValue];
@@ -165,7 +174,18 @@ var getValueByKeyPath = (keys = "", data = {}) => {
165
174
  throw new Error(`${data}中不存在${keys}`);
166
175
  }, data);
167
176
  };
168
- var setValueByKeyPath = (keys, value, data = {}) => set(data, keys, value);
177
+ var setValueByKeyPath = (keys, value, data = {}) => {
178
+ if (typeof value === "undefined") {
179
+ const keyArray = getKeysArray(keys);
180
+ const lastKey = keyArray[keyArray.length - 1];
181
+ if (keyArray.length > 1 && isArrayIndex(lastKey)) {
182
+ const parentPath = keyArray.slice(0, -1).join(".");
183
+ if (typeof get(data, parentPath) === "undefined") set(data, parentPath, []);
184
+ return data;
185
+ }
186
+ }
187
+ return set(data, keys, value);
188
+ };
169
189
  var getNodes = (ids, data = []) => {
170
190
  const nodes = [];
171
191
  const get = function(ids, data) {
@@ -356,4 +376,4 @@ var isValueIncludeDataSource = (value) => {
356
376
  };
357
377
  var removeDataSourceFieldPrefix = (id) => id?.replace("ds-field::", "") || "";
358
378
  //#endregion
359
- export { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, DATA_SOURCE_SET_DATA_METHOD_NAME, DSL_NODE_KEY_COPY_PREFIX, IS_DSL_NODE_KEY, PAGE_FRAGMENT_CONTAINER_ID_KEY, addClassName, addParamToUrl, asyncLoadCss, asyncLoadJs, calcValueByFontsize, calculatePercentage, compiledCond, compiledNode, convertToNumber, createDiv, dataSourceTemplateRegExp, delQueStr, emptyFn, filterXSS, getDefaultValueFromFields, getDepKeys, getDepNodeIds, getDocument, getElById, getGlobalThis, getHost, getIdFromEl, getKeys, getKeysArray, getNodeInfo, getNodePath, getNodes, getSearchObj, getUrlParam, getValueByKeyPath, guid, injectStyle, isDslNode, isNumber, isObject, isPage, isPageFragment, isPercentage, isPop, isSameDomain, isValueIncludeDataSource, removeClassName, removeClassNameByClassName, removeDataSourceFieldPrefix, replaceChildNode, setDslDomRelateConfig, setIdToEl, setUrlParam, setValueByKeyPath, sleep, toHump, toLine, traverseNode };
379
+ export { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, DATA_SOURCE_SET_DATA_METHOD_NAME, DSL_NODE_KEY_COPY_PREFIX, IS_DSL_NODE_KEY, PAGE_FRAGMENT_CONTAINER_ID_KEY, addClassName, addParamToUrl, asyncLoadCss, asyncLoadJs, calcValueByFontsize, calculatePercentage, compiledCond, compiledNode, convertToNumber, createDiv, dataSourceTemplateRegExp, delQueStr, emptyFn, filterXSS, getDefaultValueFromFields, getDepKeys, getDepNodeIds, getDocument, getElById, getGlobalThis, getHost, getIdFromEl, getKeys, getKeysArray, getNodeInfo, getNodePath, getNodes, getSearchObj, getUrlParam, getValueByKeyPath, guid, injectStyle, isArrayIndex, isDslNode, isNumber, isObject, isPage, isPageFragment, isPageOrFragment, isPercentage, isPop, isSameDomain, isValueIncludeDataSource, removeClassName, removeClassNameByClassName, removeDataSourceFieldPrefix, replaceChildNode, setDslDomRelateConfig, setIdToEl, setUrlParam, setValueByKeyPath, sleep, toHump, toLine, traverseNode };
@@ -68,7 +68,8 @@
68
68
  //#endregion
69
69
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseGetTag.js
70
70
  /** `Object#toString` result references. */
71
- var nullTag = "[object Null]", undefinedTag = "[object Undefined]";
71
+ var nullTag = "[object Null]";
72
+ var undefinedTag = "[object Undefined]";
72
73
  /** Built-in value references. */
73
74
  var symToStringTag = Symbol ? Symbol.toStringTag : void 0;
74
75
  /**
@@ -182,7 +183,8 @@
182
183
  /** Used as references for various `Number` constants. */
183
184
  var INFINITY$1 = Infinity;
184
185
  /** Used to convert symbols to primitives and strings. */
185
- var symbolProto$1 = Symbol ? Symbol.prototype : void 0, symbolToString = symbolProto$1 ? symbolProto$1.toString : void 0;
186
+ var symbolProto$1 = Symbol ? Symbol.prototype : void 0;
187
+ var symbolToString = symbolProto$1 ? symbolProto$1.toString : void 0;
186
188
  /**
187
189
  * The base implementation of `_.toString` which doesn't convert nullish
188
190
  * values to empty strings.
@@ -232,7 +234,10 @@
232
234
  //#endregion
233
235
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isFunction.js
234
236
  /** `Object#toString` result references. */
235
- var asyncTag = "[object AsyncFunction]", funcTag$2 = "[object Function]", genTag$1 = "[object GeneratorFunction]", proxyTag = "[object Proxy]";
237
+ var asyncTag = "[object AsyncFunction]";
238
+ var funcTag$2 = "[object Function]";
239
+ var genTag$1 = "[object GeneratorFunction]";
240
+ var proxyTag = "[object Proxy]";
236
241
  /**
237
242
  * Checks if `value` is classified as a `Function` object.
238
243
  *
@@ -308,7 +313,8 @@
308
313
  /** Used to detect host constructors (Safari). */
309
314
  var reIsHostCtor = /^\[object .+?Constructor\]$/;
310
315
  /** Used for built-in method references. */
311
- var funcProto = Function.prototype, objectProto$2 = Object.prototype;
316
+ var funcProto = Function.prototype;
317
+ var objectProto$2 = Object.prototype;
312
318
  /** Used to resolve the decompiled source of functions. */
313
319
  var funcToString = funcProto.toString;
314
320
  /** Used to check objects for own properties. */
@@ -726,8 +732,30 @@
726
732
  //#endregion
727
733
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIsTypedArray.js
728
734
  /** `Object#toString` result references. */
729
- var argsTag$1 = "[object Arguments]", arrayTag$1 = "[object Array]", boolTag$2 = "[object Boolean]", dateTag$2 = "[object Date]", errorTag$1 = "[object Error]", funcTag$1 = "[object Function]", mapTag$4 = "[object Map]", numberTag$2 = "[object Number]", objectTag$2 = "[object Object]", regexpTag$2 = "[object RegExp]", setTag$4 = "[object Set]", stringTag$2 = "[object String]", weakMapTag$2 = "[object WeakMap]";
730
- var arrayBufferTag$2 = "[object ArrayBuffer]", dataViewTag$3 = "[object DataView]", float32Tag$2 = "[object Float32Array]", float64Tag$2 = "[object Float64Array]", int8Tag$2 = "[object Int8Array]", int16Tag$2 = "[object Int16Array]", int32Tag$2 = "[object Int32Array]", uint8Tag$2 = "[object Uint8Array]", uint8ClampedTag$2 = "[object Uint8ClampedArray]", uint16Tag$2 = "[object Uint16Array]", uint32Tag$2 = "[object Uint32Array]";
735
+ var argsTag$1 = "[object Arguments]";
736
+ var arrayTag$1 = "[object Array]";
737
+ var boolTag$2 = "[object Boolean]";
738
+ var dateTag$2 = "[object Date]";
739
+ var errorTag$1 = "[object Error]";
740
+ var funcTag$1 = "[object Function]";
741
+ var mapTag$4 = "[object Map]";
742
+ var numberTag$2 = "[object Number]";
743
+ var objectTag$2 = "[object Object]";
744
+ var regexpTag$2 = "[object RegExp]";
745
+ var setTag$4 = "[object Set]";
746
+ var stringTag$2 = "[object String]";
747
+ var weakMapTag$2 = "[object WeakMap]";
748
+ var arrayBufferTag$2 = "[object ArrayBuffer]";
749
+ var dataViewTag$3 = "[object DataView]";
750
+ var float32Tag$2 = "[object Float32Array]";
751
+ var float64Tag$2 = "[object Float64Array]";
752
+ var int8Tag$2 = "[object Int8Array]";
753
+ var int16Tag$2 = "[object Int16Array]";
754
+ var int32Tag$2 = "[object Int32Array]";
755
+ var uint8Tag$2 = "[object Uint8Array]";
756
+ var uint8ClampedTag$2 = "[object Uint8ClampedArray]";
757
+ var uint16Tag$2 = "[object Uint16Array]";
758
+ var uint32Tag$2 = "[object Uint32Array]";
731
759
  /** Used to identify `toStringTag` values of typed arrays. */
732
760
  var typedArrayTags = {};
733
761
  typedArrayTags[float32Tag$2] = typedArrayTags[float64Tag$2] = typedArrayTags[int8Tag$2] = typedArrayTags[int16Tag$2] = typedArrayTags[int32Tag$2] = typedArrayTags[uint8Tag$2] = typedArrayTags[uint8ClampedTag$2] = typedArrayTags[uint16Tag$2] = typedArrayTags[uint32Tag$2] = true;
@@ -942,7 +970,8 @@
942
970
  //#endregion
943
971
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isKey.js
944
972
  /** Used to match property names within property paths. */
945
- var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/;
973
+ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/;
974
+ var reIsPlainProp = /^\w*$/;
946
975
  /**
947
976
  * Checks if `value` is a property name and not a property path.
948
977
  *
@@ -1482,6 +1511,53 @@
1482
1511
  return result == "0" && 1 / value == -INFINITY ? "-0" : result;
1483
1512
  }
1484
1513
  //#endregion
1514
+ //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseGet.js
1515
+ /**
1516
+ * The base implementation of `_.get` without support for default values.
1517
+ *
1518
+ * @private
1519
+ * @param {Object} object The object to query.
1520
+ * @param {Array|string} path The path of the property to get.
1521
+ * @returns {*} Returns the resolved value.
1522
+ */
1523
+ function baseGet(object, path) {
1524
+ path = castPath(path, object);
1525
+ var index = 0, length = path.length;
1526
+ while (object != null && index < length) object = object[toKey(path[index++])];
1527
+ return index && index == length ? object : void 0;
1528
+ }
1529
+ //#endregion
1530
+ //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/get.js
1531
+ /**
1532
+ * Gets the value at `path` of `object`. If the resolved value is
1533
+ * `undefined`, the `defaultValue` is returned in its place.
1534
+ *
1535
+ * @static
1536
+ * @memberOf _
1537
+ * @since 3.7.0
1538
+ * @category Object
1539
+ * @param {Object} object The object to query.
1540
+ * @param {Array|string} path The path of the property to get.
1541
+ * @param {*} [defaultValue] The value returned for `undefined` resolved values.
1542
+ * @returns {*} Returns the resolved value.
1543
+ * @example
1544
+ *
1545
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
1546
+ *
1547
+ * _.get(object, 'a[0].b.c');
1548
+ * // => 3
1549
+ *
1550
+ * _.get(object, ['a', '0', 'b', 'c']);
1551
+ * // => 3
1552
+ *
1553
+ * _.get(object, 'a.b.c', 'default');
1554
+ * // => 'default'
1555
+ */
1556
+ function get(object, path, defaultValue) {
1557
+ var result = object == null ? void 0 : baseGet(object, path);
1558
+ return result === void 0 ? defaultValue : result;
1559
+ }
1560
+ //#endregion
1485
1561
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayPush.js
1486
1562
  /**
1487
1563
  * Appends the elements of `values` to `array`.
@@ -1639,7 +1715,8 @@
1639
1715
  /** Detect free variable `module`. */
1640
1716
  var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module;
1641
1717
  /** Built-in value references. */
1642
- var Buffer = freeModule && freeModule.exports === freeExports ? root.Buffer : void 0, allocUnsafe = Buffer ? Buffer.allocUnsafe : void 0;
1718
+ var Buffer = freeModule && freeModule.exports === freeExports ? root.Buffer : void 0;
1719
+ var allocUnsafe = Buffer ? Buffer.allocUnsafe : void 0;
1643
1720
  /**
1644
1721
  * Creates a clone of `buffer`.
1645
1722
  *
@@ -1812,10 +1889,18 @@
1812
1889
  //#endregion
1813
1890
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_getTag.js
1814
1891
  /** `Object#toString` result references. */
1815
- var mapTag$3 = "[object Map]", objectTag$1 = "[object Object]", promiseTag = "[object Promise]", setTag$3 = "[object Set]", weakMapTag$1 = "[object WeakMap]";
1892
+ var mapTag$3 = "[object Map]";
1893
+ var objectTag$1 = "[object Object]";
1894
+ var promiseTag = "[object Promise]";
1895
+ var setTag$3 = "[object Set]";
1896
+ var weakMapTag$1 = "[object WeakMap]";
1816
1897
  var dataViewTag$2 = "[object DataView]";
1817
1898
  /** Used to detect maps, sets, and weakmaps. */
1818
- var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map$1), promiseCtorString = toSource(Promise$1), setCtorString = toSource(Set$1), weakMapCtorString = toSource(WeakMap);
1899
+ var dataViewCtorString = toSource(DataView);
1900
+ var mapCtorString = toSource(Map$1);
1901
+ var promiseCtorString = toSource(Promise$1);
1902
+ var setCtorString = toSource(Set$1);
1903
+ var weakMapCtorString = toSource(WeakMap);
1819
1904
  /**
1820
1905
  * Gets the `toStringTag` of `value`.
1821
1906
  *
@@ -1906,7 +1991,8 @@
1906
1991
  //#endregion
1907
1992
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_cloneSymbol.js
1908
1993
  /** Used to convert symbols to primitives and strings. */
1909
- var symbolProto = Symbol ? Symbol.prototype : void 0, symbolValueOf = symbolProto ? symbolProto.valueOf : void 0;
1994
+ var symbolProto = Symbol ? Symbol.prototype : void 0;
1995
+ var symbolValueOf = symbolProto ? symbolProto.valueOf : void 0;
1910
1996
  /**
1911
1997
  * Creates a clone of the `symbol` object.
1912
1998
  *
@@ -1934,8 +2020,25 @@
1934
2020
  //#endregion
1935
2021
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_initCloneByTag.js
1936
2022
  /** `Object#toString` result references. */
1937
- var boolTag$1 = "[object Boolean]", dateTag$1 = "[object Date]", mapTag$2 = "[object Map]", numberTag$1 = "[object Number]", regexpTag$1 = "[object RegExp]", setTag$2 = "[object Set]", stringTag$1 = "[object String]", symbolTag$1 = "[object Symbol]";
1938
- var arrayBufferTag$1 = "[object ArrayBuffer]", dataViewTag$1 = "[object DataView]", float32Tag$1 = "[object Float32Array]", float64Tag$1 = "[object Float64Array]", int8Tag$1 = "[object Int8Array]", int16Tag$1 = "[object Int16Array]", int32Tag$1 = "[object Int32Array]", uint8Tag$1 = "[object Uint8Array]", uint8ClampedTag$1 = "[object Uint8ClampedArray]", uint16Tag$1 = "[object Uint16Array]", uint32Tag$1 = "[object Uint32Array]";
2023
+ var boolTag$1 = "[object Boolean]";
2024
+ var dateTag$1 = "[object Date]";
2025
+ var mapTag$2 = "[object Map]";
2026
+ var numberTag$1 = "[object Number]";
2027
+ var regexpTag$1 = "[object RegExp]";
2028
+ var setTag$2 = "[object Set]";
2029
+ var stringTag$1 = "[object String]";
2030
+ var symbolTag$1 = "[object Symbol]";
2031
+ var arrayBufferTag$1 = "[object ArrayBuffer]";
2032
+ var dataViewTag$1 = "[object DataView]";
2033
+ var float32Tag$1 = "[object Float32Array]";
2034
+ var float64Tag$1 = "[object Float64Array]";
2035
+ var int8Tag$1 = "[object Int8Array]";
2036
+ var int16Tag$1 = "[object Int16Array]";
2037
+ var int32Tag$1 = "[object Int32Array]";
2038
+ var uint8Tag$1 = "[object Uint8Array]";
2039
+ var uint8ClampedTag$1 = "[object Uint8ClampedArray]";
2040
+ var uint16Tag$1 = "[object Uint16Array]";
2041
+ var uint32Tag$1 = "[object Uint32Array]";
1939
2042
  /**
1940
2043
  * Initializes an object clone based on its `toStringTag`.
1941
2044
  *
@@ -2057,10 +2160,36 @@
2057
2160
  //#endregion
2058
2161
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseClone.js
2059
2162
  /** Used to compose bitmasks for cloning. */
2060
- var CLONE_DEEP_FLAG$1 = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG$1 = 4;
2163
+ var CLONE_DEEP_FLAG$1 = 1;
2164
+ var CLONE_FLAT_FLAG = 2;
2165
+ var CLONE_SYMBOLS_FLAG$1 = 4;
2061
2166
  /** `Object#toString` result references. */
2062
- var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", weakMapTag = "[object WeakMap]";
2063
- var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]";
2167
+ var argsTag = "[object Arguments]";
2168
+ var arrayTag = "[object Array]";
2169
+ var boolTag = "[object Boolean]";
2170
+ var dateTag = "[object Date]";
2171
+ var errorTag = "[object Error]";
2172
+ var funcTag = "[object Function]";
2173
+ var genTag = "[object GeneratorFunction]";
2174
+ var mapTag = "[object Map]";
2175
+ var numberTag = "[object Number]";
2176
+ var objectTag = "[object Object]";
2177
+ var regexpTag = "[object RegExp]";
2178
+ var setTag = "[object Set]";
2179
+ var stringTag = "[object String]";
2180
+ var symbolTag = "[object Symbol]";
2181
+ var weakMapTag = "[object WeakMap]";
2182
+ var arrayBufferTag = "[object ArrayBuffer]";
2183
+ var dataViewTag = "[object DataView]";
2184
+ var float32Tag = "[object Float32Array]";
2185
+ var float64Tag = "[object Float64Array]";
2186
+ var int8Tag = "[object Int8Array]";
2187
+ var int16Tag = "[object Int16Array]";
2188
+ var int32Tag = "[object Int32Array]";
2189
+ var uint8Tag = "[object Uint8Array]";
2190
+ var uint8ClampedTag = "[object Uint8ClampedArray]";
2191
+ var uint16Tag = "[object Uint16Array]";
2192
+ var uint32Tag = "[object Uint32Array]";
2064
2193
  /** Used to identify `toStringTag` values supported by `_.clone`. */
2065
2194
  var cloneableTags = {};
2066
2195
  cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
@@ -2124,7 +2253,8 @@
2124
2253
  //#endregion
2125
2254
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/cloneDeep.js
2126
2255
  /** Used to compose bitmasks for cloning. */
2127
- var CLONE_DEEP_FLAG = 1, CLONE_SYMBOLS_FLAG = 4;
2256
+ var CLONE_DEEP_FLAG = 1;
2257
+ var CLONE_SYMBOLS_FLAG = 4;
2128
2258
  /**
2129
2259
  * This method is like `_.clone` except that it recursively clones `value`.
2130
2260
  *
@@ -2345,47 +2475,48 @@
2345
2475
  * @param {Array} data 要查找的根容器节点
2346
2476
  * @return {Array} 组件在data中的子孙路径
2347
2477
  */
2348
- var getNodePath = (id, data = []) => {
2478
+ var getNodePath = (id, data = [], skip) => {
2349
2479
  const path = [];
2350
- const get = function(id, data) {
2480
+ const targetId = `${id}`;
2481
+ const get = function(data) {
2351
2482
  if (!Array.isArray(data)) return null;
2352
2483
  for (let i = 0, l = data.length; i < l; i++) {
2353
2484
  const item = data[i];
2354
2485
  path.push(item);
2355
- if (`${item.id}` === `${id}`) return item;
2356
- if (item.items) {
2357
- const node = get(id, item.items);
2486
+ if (`${item.id}` === targetId) return item;
2487
+ if (item.items && item !== skip) {
2488
+ const node = get(item.items);
2358
2489
  if (node) return node;
2359
2490
  }
2360
2491
  path.pop();
2361
2492
  }
2362
2493
  return null;
2363
2494
  };
2364
- get(id, data);
2495
+ get(data);
2365
2496
  return path;
2366
2497
  };
2367
- var getNodeInfo = (id, root) => {
2498
+ var getNodeInfo = (id, root, skip) => {
2368
2499
  const info = {
2369
2500
  node: null,
2370
2501
  parent: null,
2371
- page: null
2502
+ page: null,
2503
+ path: []
2372
2504
  };
2373
2505
  if (!root) return info;
2374
2506
  if (id === root.id) {
2375
2507
  info.node = root;
2376
2508
  return info;
2377
2509
  }
2378
- const path = getNodePath(id, root.items);
2510
+ const path = getNodePath(id, root.items, skip);
2511
+ info.path = path;
2379
2512
  if (!path.length) return info;
2380
2513
  path.unshift(root);
2381
2514
  info.node = path[path.length - 1];
2382
2515
  info.parent = path[path.length - 2];
2383
- path.forEach((item) => {
2384
- if (isPage(item) || isPageFragment(item)) {
2385
- info.page = item;
2386
- return;
2387
- }
2388
- });
2516
+ for (const item of path) if (isPageOrFragment(item)) {
2517
+ info.page = item;
2518
+ break;
2519
+ }
2389
2520
  return info;
2390
2521
  };
2391
2522
  var filterXSS = (str) => str.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
@@ -2467,6 +2598,8 @@
2467
2598
  if (!node) return false;
2468
2599
  return Boolean(node.type?.toLowerCase() === _tmagic_schema.NodeType.PAGE_FRAGMENT);
2469
2600
  };
2601
+ /** 是否为页面或页面片 */
2602
+ var isPageOrFragment = (node) => isPage(node) || isPageFragment(node);
2470
2603
  var isNumber = (value) => typeof value === "number" && !isNaN(value) || /^(-?\d+)(\.\d+)?$/.test(`${value}`);
2471
2604
  var getHost = (targetUrl) => targetUrl.match(/\/\/([^/]+)/)?.[1];
2472
2605
  var isSameDomain = (targetUrl = "", source = globalThis.location.host) => {
@@ -2483,6 +2616,12 @@
2483
2616
  return (c === "x" ? r : r & 3 | 8).toString(16);
2484
2617
  });
2485
2618
  var getKeysArray = (keys) => `${keys}`.replace(/\[(\d+)\]/g, ".$1").split(".");
2619
+ /**
2620
+ * 判断某一层 key 是否为数组下标(纯数字)
2621
+ * @param key 单层 key
2622
+ * @returns 是否为数组下标
2623
+ */
2624
+ var isArrayIndex = (key) => /^\d+$/.test(`${key}`);
2486
2625
  var getValueByKeyPath = (keys = "", data = {}) => {
2487
2626
  return (Array.isArray(keys) ? keys : getKeysArray(keys)).reduce((accumulator, currentValue) => {
2488
2627
  if (isObject(accumulator)) return accumulator[currentValue];
@@ -2490,7 +2629,18 @@
2490
2629
  throw new Error(`${data}中不存在${keys}`);
2491
2630
  }, data);
2492
2631
  };
2493
- var setValueByKeyPath = (keys, value, data = {}) => set(data, keys, value);
2632
+ var setValueByKeyPath = (keys, value, data = {}) => {
2633
+ if (typeof value === "undefined") {
2634
+ const keyArray = getKeysArray(keys);
2635
+ const lastKey = keyArray[keyArray.length - 1];
2636
+ if (keyArray.length > 1 && isArrayIndex(lastKey)) {
2637
+ const parentPath = keyArray.slice(0, -1).join(".");
2638
+ if (typeof get(data, parentPath) === "undefined") set(data, parentPath, []);
2639
+ return data;
2640
+ }
2641
+ }
2642
+ return set(data, keys, value);
2643
+ };
2494
2644
  var getNodes = (ids, data = []) => {
2495
2645
  const nodes = [];
2496
2646
  const get = function(ids, data) {
@@ -2719,11 +2869,13 @@
2719
2869
  exports.getValueByKeyPath = getValueByKeyPath;
2720
2870
  exports.guid = guid;
2721
2871
  exports.injectStyle = injectStyle;
2872
+ exports.isArrayIndex = isArrayIndex;
2722
2873
  exports.isDslNode = isDslNode;
2723
2874
  exports.isNumber = isNumber;
2724
2875
  exports.isObject = isObject;
2725
2876
  exports.isPage = isPage;
2726
2877
  exports.isPageFragment = isPageFragment;
2878
+ exports.isPageOrFragment = isPageOrFragment;
2727
2879
  exports.isPercentage = isPercentage;
2728
2880
  exports.isPop = isPop;
2729
2881
  exports.isSameDomain = isSameDomain;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.0-beta.2",
2
+ "version": "1.8.0-beta.21",
3
3
  "name": "@tmagic/utils",
4
4
  "type": "module",
5
5
  "sideEffects": false,
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "peerDependencies": {
37
37
  "typescript": "^6.0.3",
38
- "@tmagic/schema": "1.8.0-beta.2"
38
+ "@tmagic/schema": "1.8.0-beta.21"
39
39
  },
40
40
  "peerDependenciesMeta": {
41
41
  "typescript": {
package/src/index.ts CHANGED
@@ -17,13 +17,12 @@
17
17
  * limitations under the License.
18
18
  */
19
19
 
20
- import { cloneDeep, set as objectSet } from 'lodash-es';
20
+ import { cloneDeep, get as objectGet, set as objectSet } from 'lodash-es';
21
21
 
22
22
  import type {
23
23
  DataSchema,
24
24
  DataSourceDeps,
25
25
  Id,
26
- MApp,
27
26
  MComponent,
28
27
  MContainer,
29
28
  MNode,
@@ -80,10 +79,12 @@ export const emptyFn = (): any => undefined;
80
79
  * @param {Array} data 要查找的根容器节点
81
80
  * @return {Array} 组件在data中的子孙路径
82
81
  */
83
- export const getNodePath = (id: Id, data: MNode[] = []): MNode[] => {
82
+ export const getNodePath = (id: Id, data: MNode[] = [], skip?: MNode | null): MNode[] => {
84
83
  const path: MNode[] = [];
84
+ // 目标 id 字符串只计算一次,避免在递归遍历中对每个节点重复拼接
85
+ const targetId = `${id}`;
85
86
 
86
- const get = function (id: number | string, data: MNode[]): MNode | null {
87
+ const get = function (data: MNode[]): MNode | null {
87
88
  if (!Array.isArray(data)) {
88
89
  return null;
89
90
  }
@@ -92,12 +93,13 @@ export const getNodePath = (id: Id, data: MNode[] = []): MNode[] => {
92
93
  const item = data[i];
93
94
 
94
95
  path.push(item);
95
- if (`${item.id}` === `${id}`) {
96
+ if (`${item.id}` === targetId) {
96
97
  return item;
97
98
  }
98
99
 
99
- if (item.items) {
100
- const node = get(id, item.items);
100
+ // skip 用于跳过已经搜索过的子树(如已优先搜索过的当前页面),避免重复遍历
101
+ if (item.items && item !== skip) {
102
+ const node = get(item.items);
101
103
  if (node) {
102
104
  return node;
103
105
  }
@@ -109,16 +111,17 @@ export const getNodePath = (id: Id, data: MNode[] = []): MNode[] => {
109
111
  return null;
110
112
  };
111
113
 
112
- get(id, data);
114
+ get(data);
113
115
 
114
116
  return path;
115
117
  };
116
118
 
117
- export const getNodeInfo = (id: Id, root: Pick<MApp, 'id' | 'items'> | null) => {
119
+ export const getNodeInfo = (id: Id, root: { id: Id; items?: MNode[] } | null, skip?: MNode | null) => {
118
120
  const info: EditorNodeInfo = {
119
121
  node: null,
120
122
  parent: null,
121
123
  page: null,
124
+ path: [],
122
125
  };
123
126
 
124
127
  if (!root) return info;
@@ -128,7 +131,8 @@ export const getNodeInfo = (id: Id, root: Pick<MApp, 'id' | 'items'> | null) =>
128
131
  return info;
129
132
  }
130
133
 
131
- const path = getNodePath(id, root.items);
134
+ const path = getNodePath(id, root.items, skip);
135
+ info.path = path;
132
136
 
133
137
  if (!path.length) return info;
134
138
 
@@ -137,12 +141,12 @@ export const getNodeInfo = (id: Id, root: Pick<MApp, 'id' | 'items'> | null) =>
137
141
  info.node = path[path.length - 1] as MComponent;
138
142
  info.parent = path[path.length - 2] as MContainer;
139
143
 
140
- path.forEach((item) => {
141
- if (isPage(item) || isPageFragment(item)) {
144
+ for (const item of path) {
145
+ if (isPageOrFragment(item)) {
142
146
  info.page = item as MPage | MPageFragment;
143
- return;
147
+ break;
144
148
  }
145
- });
149
+ }
146
150
 
147
151
  return info;
148
152
  };
@@ -275,6 +279,10 @@ export const isPageFragment = (node?: Pick<MComponent, 'type'> | null): boolean
275
279
  return Boolean(node.type?.toLowerCase() === NodeType.PAGE_FRAGMENT);
276
280
  };
277
281
 
282
+ /** 是否为页面或页面片 */
283
+ export const isPageOrFragment = (node?: Pick<MComponent, 'type'> | null): boolean =>
284
+ isPage(node) || isPageFragment(node);
285
+
278
286
  export const isNumber = (value: any) =>
279
287
  (typeof value === 'number' && !isNaN(value)) || /^(-?\d+)(\.\d+)?$/.test(`${value}`);
280
288
 
@@ -304,6 +312,13 @@ export const getKeysArray = (keys: string | number) =>
304
312
  // 将 array[0] 转成 array.0
305
313
  `${keys}`.replace(/\[(\d+)\]/g, '.$1').split('.');
306
314
 
315
+ /**
316
+ * 判断某一层 key 是否为数组下标(纯数字)
317
+ * @param key 单层 key
318
+ * @returns 是否为数组下标
319
+ */
320
+ export const isArrayIndex = (key: string | number): boolean => /^\d+$/.test(`${key}`);
321
+
307
322
  export const getValueByKeyPath = (
308
323
  keys: number | string | string[] = '',
309
324
  data: Record<string | number, any> = {},
@@ -323,8 +338,23 @@ export const getValueByKeyPath = (
323
338
  }, data);
324
339
  };
325
340
 
326
- export const setValueByKeyPath = (keys: string | number, value: any, data: Record<string | number, any> = {}): any =>
327
- objectSet(data, keys, value);
341
+ export const setValueByKeyPath = (keys: string | number, value: any, data: Record<string | number, any> = {}): any => {
342
+ if (typeof value === 'undefined') {
343
+ // 仅数组下标场景需要特殊处理:lodash 的 set 会把 undefined 写入数组得到 [undefined],
344
+ // 此处改为只创建父级空数组,避免出现 [undefined]。对象属性场景 undefined 会被 JSON 自然丢弃,保持原行为。
345
+ // 注意:这里将「数字型末级 key」统一按数组下标处理,无法区分数字型对象 key,属于预期内的取舍。
346
+ const keyArray = getKeysArray(keys);
347
+ const lastKey = keyArray[keyArray.length - 1];
348
+ if (keyArray.length > 1 && isArrayIndex(lastKey)) {
349
+ const parentPath = keyArray.slice(0, -1).join('.');
350
+ if (typeof objectGet(data, parentPath) === 'undefined') {
351
+ objectSet(data, parentPath, []);
352
+ }
353
+ return data;
354
+ }
355
+ }
356
+ return objectSet(data, keys, value);
357
+ };
328
358
 
329
359
  export const getNodes = (ids: Id[], data: MNode[] = []): MNode[] => {
330
360
  const nodes: MNode[] = [];
package/types/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { DataSchema, DataSourceDeps, Id, MApp, MComponent, MNode, MNodeInstance } from "@tmagic/schema";
1
+ import { DataSchema, DataSourceDeps, Id, MComponent, MNode, MNodeInstance } from "@tmagic/schema";
2
2
  import { MContainer, MNode as MNode$1, MPage, MPageFragment } from "@tmagic/core";
3
3
 
4
4
  //#region temp/packages/editor/src/type.d.ts
@@ -6,6 +6,7 @@ interface EditorNodeInfo {
6
6
  node: MNode$1 | null;
7
7
  parent: MContainer | null;
8
8
  page: MPage | MPageFragment | null;
9
+ path: MNode$1[];
9
10
  }
10
11
  //#endregion
11
12
  //#region temp/packages/utils/src/dom.d.ts
@@ -51,8 +52,11 @@ declare const emptyFn: () => any;
51
52
  * @param {Array} data 要查找的根容器节点
52
53
  * @return {Array} 组件在data中的子孙路径
53
54
  */
54
- declare const getNodePath: (id: Id, data?: MNode[]) => MNode[];
55
- declare const getNodeInfo: (id: Id, root: Pick<MApp, "id" | "items"> | null) => EditorNodeInfo;
55
+ declare const getNodePath: (id: Id, data?: MNode[], skip?: MNode | null) => MNode[];
56
+ declare const getNodeInfo: (id: Id, root: {
57
+ id: Id;
58
+ items?: MNode[];
59
+ } | null, skip?: MNode | null) => EditorNodeInfo;
56
60
  declare const filterXSS: (str: string) => string;
57
61
  declare const getUrlParam: (param: string, url?: string) => string;
58
62
  /**
@@ -73,6 +77,8 @@ declare const isObject: (obj: any) => boolean;
73
77
  declare const isPop: (node: Pick<MComponent, "type"> | null) => boolean;
74
78
  declare const isPage: (node?: Pick<MComponent, "type"> | null) => boolean;
75
79
  declare const isPageFragment: (node?: Pick<MComponent, "type"> | null) => boolean;
80
+ /** 是否为页面或页面片 */
81
+ declare const isPageOrFragment: (node?: Pick<MComponent, "type"> | null) => boolean;
76
82
  declare const isNumber: (value: any) => boolean;
77
83
  declare const getHost: (targetUrl: string) => string | undefined;
78
84
  declare const isSameDomain: (targetUrl?: string, source?: string) => boolean;
@@ -83,6 +89,12 @@ declare const isSameDomain: (targetUrl?: string, source?: string) => boolean;
83
89
  */
84
90
  declare const guid: (digit?: number) => string;
85
91
  declare const getKeysArray: (keys: string | number) => string[];
92
+ /**
93
+ * 判断某一层 key 是否为数组下标(纯数字)
94
+ * @param key 单层 key
95
+ * @returns 是否为数组下标
96
+ */
97
+ declare const isArrayIndex: (key: string | number) => boolean;
86
98
  declare const getValueByKeyPath: (keys?: number | string | string[], data?: Record<string | number, any>) => any;
87
99
  declare const setValueByKeyPath: (keys: string | number, value: any, data?: Record<string | number, any>) => any;
88
100
  declare const getNodes: (ids: Id[], data?: MNode[]) => MNode[];
@@ -122,4 +134,4 @@ declare const traverseNode: <T extends NodeItem = NodeItem>(node: T, cb: (node:
122
134
  declare const isValueIncludeDataSource: (value: any) => boolean;
123
135
  declare const removeDataSourceFieldPrefix: (id?: string) => string;
124
136
  //#endregion
125
- export { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, DATA_SOURCE_SET_DATA_METHOD_NAME, DSL_NODE_KEY_COPY_PREFIX, IS_DSL_NODE_KEY, NodeItem, PAGE_FRAGMENT_CONTAINER_ID_KEY, addClassName, addParamToUrl, asyncLoadCss, asyncLoadJs, calcValueByFontsize, calculatePercentage, compiledCond, compiledNode, convertToNumber, createDiv, dataSourceTemplateRegExp, delQueStr, emptyFn, filterXSS, getDefaultValueFromFields, getDepKeys, getDepNodeIds, getDocument, getElById, getGlobalThis, getHost, getIdFromEl, getKeys, getKeysArray, getNodeInfo, getNodePath, getNodes, getSearchObj, getUrlParam, getValueByKeyPath, guid, injectStyle, isDslNode, isNumber, isObject, isPage, isPageFragment, isPercentage, isPop, isSameDomain, isValueIncludeDataSource, removeClassName, removeClassNameByClassName, removeDataSourceFieldPrefix, replaceChildNode, setDslDomRelateConfig, setIdToEl, setUrlParam, setValueByKeyPath, sleep, toHump, toLine, traverseNode };
137
+ export { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, DATA_SOURCE_SET_DATA_METHOD_NAME, DSL_NODE_KEY_COPY_PREFIX, IS_DSL_NODE_KEY, NodeItem, PAGE_FRAGMENT_CONTAINER_ID_KEY, addClassName, addParamToUrl, asyncLoadCss, asyncLoadJs, calcValueByFontsize, calculatePercentage, compiledCond, compiledNode, convertToNumber, createDiv, dataSourceTemplateRegExp, delQueStr, emptyFn, filterXSS, getDefaultValueFromFields, getDepKeys, getDepNodeIds, getDocument, getElById, getGlobalThis, getHost, getIdFromEl, getKeys, getKeysArray, getNodeInfo, getNodePath, getNodes, getSearchObj, getUrlParam, getValueByKeyPath, guid, injectStyle, isArrayIndex, isDslNode, isNumber, isObject, isPage, isPageFragment, isPageOrFragment, isPercentage, isPop, isSameDomain, isValueIncludeDataSource, removeClassName, removeClassNameByClassName, removeDataSourceFieldPrefix, replaceChildNode, setDslDomRelateConfig, setIdToEl, setUrlParam, setValueByKeyPath, sleep, toHump, toLine, traverseNode };