sculp-js 1.0.0 → 1.1.0
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/README.md +106 -9
- package/lib/cjs/array.js +116 -16
- package/lib/cjs/async.js +1 -1
- package/lib/cjs/clipboard.js +1 -1
- package/lib/cjs/cookie.js +1 -1
- package/lib/cjs/date.js +1 -1
- package/lib/cjs/dom.js +1 -1
- package/lib/cjs/download.js +1 -1
- package/lib/cjs/easing.js +1 -1
- package/lib/cjs/file.js +1 -1
- package/lib/cjs/func.js +1 -1
- package/lib/cjs/index.js +6 -3
- package/lib/cjs/number.js +1 -1
- package/lib/cjs/object.js +1 -1
- package/lib/cjs/path.js +1 -1
- package/lib/cjs/qs.js +1 -1
- package/lib/cjs/random.js +1 -1
- package/lib/cjs/string.js +1 -1
- package/lib/cjs/tooltip.js +118 -0
- package/lib/cjs/type.js +1 -1
- package/lib/cjs/unique.js +1 -1
- package/lib/cjs/url.js +1 -1
- package/lib/cjs/watermark.js +1 -1
- package/lib/es/array.js +114 -15
- package/lib/es/async.js +1 -1
- package/lib/es/clipboard.js +1 -1
- package/lib/es/cookie.js +1 -1
- package/lib/es/date.js +1 -1
- package/lib/es/dom.js +1 -1
- package/lib/es/download.js +1 -1
- package/lib/es/easing.js +1 -1
- package/lib/es/file.js +1 -1
- package/lib/es/func.js +1 -1
- package/lib/es/index.js +3 -2
- package/lib/es/number.js +1 -1
- package/lib/es/object.js +1 -1
- package/lib/es/path.js +1 -1
- package/lib/es/qs.js +1 -1
- package/lib/es/random.js +1 -1
- package/lib/es/string.js +1 -1
- package/lib/es/tooltip.js +116 -0
- package/lib/es/type.js +1 -1
- package/lib/es/unique.js +1 -1
- package/lib/es/url.js +1 -1
- package/lib/es/watermark.js +1 -1
- package/lib/index.d.ts +77 -8
- package/lib/tsdoc-metadata.json +11 -0
- package/lib/umd/index.js +224 -16
- package/package.json +7 -6
package/lib/umd/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.0.
|
|
2
|
+
* sculp-js v1.0.1
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -277,26 +277,32 @@
|
|
|
277
277
|
return objectHas(any, 'length');
|
|
278
278
|
}
|
|
279
279
|
/**
|
|
280
|
-
* 遍历数组,返回 false 中断遍历
|
|
280
|
+
* 遍历数组,返回 false 中断遍历(支持continue和break操作)
|
|
281
281
|
*
|
|
282
282
|
* @param {ArrayLike<V>} array
|
|
283
|
-
* @param {(val: V, idx: number) => any} iterator
|
|
284
|
-
* @param
|
|
283
|
+
* @param {(val: V, idx: number) => any} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
|
|
284
|
+
* @param {boolean} reverse 是否倒序
|
|
285
285
|
* @returns {*}
|
|
286
286
|
*/
|
|
287
287
|
function arrayEach(array, iterator, reverse = false) {
|
|
288
288
|
if (reverse) {
|
|
289
289
|
for (let idx = array.length - 1; idx >= 0; idx--) {
|
|
290
290
|
const val = array[idx];
|
|
291
|
-
|
|
291
|
+
const re = iterator(val, idx, array);
|
|
292
|
+
if (re === false)
|
|
292
293
|
break;
|
|
294
|
+
else if (re === true)
|
|
295
|
+
continue;
|
|
293
296
|
}
|
|
294
297
|
}
|
|
295
298
|
else {
|
|
296
299
|
for (let idx = 0; idx < array.length; idx++) {
|
|
297
300
|
const val = array[idx];
|
|
298
|
-
|
|
301
|
+
const re = iterator(val, idx, array);
|
|
302
|
+
if (re === false)
|
|
299
303
|
break;
|
|
304
|
+
else if (re === true)
|
|
305
|
+
continue;
|
|
300
306
|
}
|
|
301
307
|
}
|
|
302
308
|
}
|
|
@@ -358,21 +364,25 @@
|
|
|
358
364
|
/**
|
|
359
365
|
* 自定义深度优先遍历函数(支持continue和break操作)
|
|
360
366
|
* @param {ArrayLike<V>} tree 树形数据
|
|
361
|
-
* @param {Function} iterator
|
|
367
|
+
* @param {Function} iterator 迭代函数, 返回值为true时continue, 返回值为false时break
|
|
362
368
|
* @param {string} children 定制子元素的key
|
|
363
369
|
* @param {boolean} isReverse 是否反向遍历
|
|
364
370
|
* @returns {*}
|
|
365
371
|
*/
|
|
366
|
-
function
|
|
367
|
-
let level = 0;
|
|
372
|
+
function forEachDeep(tree, iterator, children = 'children', isReverse = false) {
|
|
373
|
+
let level = 0, isBreak = false;
|
|
368
374
|
const walk = (arr, parent) => {
|
|
369
375
|
if (isReverse) {
|
|
370
376
|
for (let i = arr.length - 1; i >= 0; i--) {
|
|
377
|
+
if (isBreak) {
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
371
380
|
const re = iterator(arr[i], i, tree, parent, level);
|
|
372
|
-
if (re ===
|
|
381
|
+
if (re === false) {
|
|
382
|
+
isBreak = true;
|
|
373
383
|
break;
|
|
374
384
|
}
|
|
375
|
-
else if (re ===
|
|
385
|
+
else if (re === true) {
|
|
376
386
|
continue;
|
|
377
387
|
}
|
|
378
388
|
// @ts-ignore
|
|
@@ -385,11 +395,15 @@
|
|
|
385
395
|
}
|
|
386
396
|
else {
|
|
387
397
|
for (let i = 0; i < arr.length; i++) {
|
|
398
|
+
if (isBreak) {
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
388
401
|
const re = iterator(arr[i], i, tree, parent, level);
|
|
389
|
-
if (re ===
|
|
402
|
+
if (re === false) {
|
|
403
|
+
isBreak = true;
|
|
390
404
|
break;
|
|
391
405
|
}
|
|
392
|
-
else if (re ===
|
|
406
|
+
else if (re === true) {
|
|
393
407
|
continue;
|
|
394
408
|
}
|
|
395
409
|
// @ts-ignore
|
|
@@ -411,7 +425,7 @@
|
|
|
411
425
|
* @param {ITreeConf} config - 迭代配置项
|
|
412
426
|
* @returns {[IdLike[], ITreeItem<V>[]]} - 由parentId...childId, parentObject-childObject组成的二维数组
|
|
413
427
|
*/
|
|
414
|
-
function
|
|
428
|
+
function searchTreeById(tree, nodeId, config) {
|
|
415
429
|
const { children = 'children', id = 'id' } = config || {};
|
|
416
430
|
const toFlatArray = (tree, parentId, parent) => {
|
|
417
431
|
return tree.reduce((t, _) => {
|
|
@@ -436,6 +450,91 @@
|
|
|
436
450
|
};
|
|
437
451
|
return getIds(toFlatArray(tree));
|
|
438
452
|
}
|
|
453
|
+
/**
|
|
454
|
+
* 使用迭代函数转换数组
|
|
455
|
+
* @param {T} array
|
|
456
|
+
* @param {Function} callback 迭代函数
|
|
457
|
+
* @return {Array}
|
|
458
|
+
*/
|
|
459
|
+
function flatMap(array, callback) {
|
|
460
|
+
const result = [];
|
|
461
|
+
array.forEach((value, index) => {
|
|
462
|
+
result.push(...callback(value, index, array));
|
|
463
|
+
});
|
|
464
|
+
return result;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* 根据 idProp 与 parentIdProp 从对象数组中构建对应的树
|
|
468
|
+
* 当 A[parentIdProp] === B[idProp] 时,对象A会被移动到对象B的children。
|
|
469
|
+
* 当一个对象的 parentIdProp 不与其他对象的 idProp 字段相等时,该对象被作为树的顶层节点
|
|
470
|
+
* @param {string} idProp 元素ID
|
|
471
|
+
* @param {string} parentIdProp 父元素ID
|
|
472
|
+
* @param {object[]} items 一维数组
|
|
473
|
+
* @returns {WithChildren<T>[]} 树
|
|
474
|
+
* @example
|
|
475
|
+
* const array = [
|
|
476
|
+
* { id: 'node-1', parent: 'root' },
|
|
477
|
+
* { id: 'node-2', parent: 'root' },
|
|
478
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
479
|
+
* { id: 'node-4', parent: 'node-2' },
|
|
480
|
+
* { id: 'node-5', parent: 'node-4' },
|
|
481
|
+
* ]
|
|
482
|
+
* const tree = buildTree('id', 'parent', array)
|
|
483
|
+
* expect(tree).toEqual([
|
|
484
|
+
* { id: 'node-1', parent: 'root' },
|
|
485
|
+
* {
|
|
486
|
+
* id: 'node-2',
|
|
487
|
+
* parent: 'root',
|
|
488
|
+
* children: [
|
|
489
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
490
|
+
* {
|
|
491
|
+
* id: 'node-4',
|
|
492
|
+
* parent: 'node-2',
|
|
493
|
+
* children: [{ id: 'node-5', parent: 'node-4' }],
|
|
494
|
+
* },
|
|
495
|
+
* ],
|
|
496
|
+
* },
|
|
497
|
+
* ])
|
|
498
|
+
*/
|
|
499
|
+
function buildTree(idProp, parentIdProp, items) {
|
|
500
|
+
const wrapperMap = new Map();
|
|
501
|
+
const ensure = (id) => {
|
|
502
|
+
if (wrapperMap.has(id)) {
|
|
503
|
+
return wrapperMap.get(id);
|
|
504
|
+
}
|
|
505
|
+
//@ts-ignore
|
|
506
|
+
const wrapper = { id, parent: null, item: null, children: [] };
|
|
507
|
+
wrapperMap.set(id, wrapper);
|
|
508
|
+
return wrapper;
|
|
509
|
+
};
|
|
510
|
+
for (const item of items) {
|
|
511
|
+
const parentWrapper = ensure(item[parentIdProp]);
|
|
512
|
+
const itemWrapper = ensure(item[idProp]);
|
|
513
|
+
//@ts-ignore
|
|
514
|
+
itemWrapper.parent = parentWrapper;
|
|
515
|
+
//@ts-ignore
|
|
516
|
+
parentWrapper.children.push(itemWrapper);
|
|
517
|
+
//@ts-ignore
|
|
518
|
+
itemWrapper.item = item;
|
|
519
|
+
}
|
|
520
|
+
const topLevelWrappers = flatMap(Array.from(wrapperMap.values()).filter(wrapper => wrapper.parent === null), wrapper => wrapper.children);
|
|
521
|
+
return unwrapRecursively(topLevelWrappers);
|
|
522
|
+
function unwrapRecursively(wrapperArray) {
|
|
523
|
+
const result = [];
|
|
524
|
+
for (const wrapper of wrapperArray) {
|
|
525
|
+
if (wrapper.children.length === 0) {
|
|
526
|
+
result.push(wrapper.item);
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
result.push({
|
|
530
|
+
...wrapper.item,
|
|
531
|
+
children: unwrapRecursively(wrapper.children)
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return result;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
439
538
|
|
|
440
539
|
// @ref https://cubic-bezier.com/
|
|
441
540
|
const easingDefines = {
|
|
@@ -1791,6 +1890,113 @@
|
|
|
1791
1890
|
return uniqueString;
|
|
1792
1891
|
};
|
|
1793
1892
|
|
|
1893
|
+
/**
|
|
1894
|
+
* @title tooltip
|
|
1895
|
+
* @Desc 自定义的tooltip方法, 支持拖动悬浮提示
|
|
1896
|
+
* Created by chendeqiao on 2017/5/8.
|
|
1897
|
+
* @example
|
|
1898
|
+
* <span onmouseleave="handleMouseLeave('#root')" onmousemove="handleMouseEnter({rootElId: '#root', title: 'title content', event: event})"
|
|
1899
|
+
* onmouseenter="handleMouseEnter({'#root', title: 'title content', event: event})">title content </span>
|
|
1900
|
+
*/
|
|
1901
|
+
/**
|
|
1902
|
+
* 自定义title提示功能的mouseenter事件句柄
|
|
1903
|
+
* @param {ITooltipParams} param1
|
|
1904
|
+
* @returns {*}
|
|
1905
|
+
*/
|
|
1906
|
+
function handleMouseEnter({ rootElId = '#root', title, event }) {
|
|
1907
|
+
try {
|
|
1908
|
+
const $rootEl = document.querySelector(rootElId);
|
|
1909
|
+
console.assert($rootEl !== null, `未找到id为 ${rootElId} 的dom元素`);
|
|
1910
|
+
let $customTitle = null;
|
|
1911
|
+
// 动态创建class样式,并加入到head中
|
|
1912
|
+
if (!document.querySelector('.tooltip-inner1494304949567')) {
|
|
1913
|
+
const tooltipWrapperClass = document.createElement('style');
|
|
1914
|
+
tooltipWrapperClass.type = 'text/css';
|
|
1915
|
+
tooltipWrapperClass.innerHTML = `
|
|
1916
|
+
.tooltip-inner1494304949567 {
|
|
1917
|
+
max-width: 250px;
|
|
1918
|
+
padding: 3px 8px;
|
|
1919
|
+
color: #fff;
|
|
1920
|
+
text-decoration: none;
|
|
1921
|
+
border-radius: 4px;
|
|
1922
|
+
text-align: left;
|
|
1923
|
+
}
|
|
1924
|
+
`;
|
|
1925
|
+
document.querySelector('head').appendChild(tooltipWrapperClass);
|
|
1926
|
+
}
|
|
1927
|
+
if (document.querySelector('#customTitle1494304949567')) {
|
|
1928
|
+
$customTitle = document.querySelector('#customTitle1494304949567');
|
|
1929
|
+
mouseenter($customTitle, title, event);
|
|
1930
|
+
}
|
|
1931
|
+
else {
|
|
1932
|
+
const $contentContainer = document.createElement('div');
|
|
1933
|
+
$contentContainer.className = 'customTitle';
|
|
1934
|
+
$contentContainer.id = 'customTitle1494304949567';
|
|
1935
|
+
$contentContainer.className = 'tooltip';
|
|
1936
|
+
$contentContainer.style.cssText = 'z-index: 99999999; visibility: hidden;';
|
|
1937
|
+
$contentContainer.innerHTML =
|
|
1938
|
+
'<div class="tooltip-inner1494304949567" style="word-wrap: break-word; max-width: 44px;">皮肤</div>';
|
|
1939
|
+
$rootEl.appendChild($contentContainer);
|
|
1940
|
+
$customTitle = document.querySelector('#customTitle1494304949567');
|
|
1941
|
+
if (title) {
|
|
1942
|
+
//判断div显示的内容是否为空
|
|
1943
|
+
mouseenter($customTitle, title, event);
|
|
1944
|
+
$customTitle.style.visibility = 'visible';
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
catch (e) {
|
|
1949
|
+
console.error(e.message);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
/**
|
|
1953
|
+
* 提示文案dom渲染的处理函数
|
|
1954
|
+
* @param {HTMLDivElement} customTitle
|
|
1955
|
+
* @param {string} title 提示的字符串
|
|
1956
|
+
* @param {PointerEvent} e 事件对象
|
|
1957
|
+
* @returns {*}
|
|
1958
|
+
*/
|
|
1959
|
+
function mouseenter($customTitle, title, e) {
|
|
1960
|
+
let diffValueX = 200 + 50; //默认设置弹出div的宽度为250px
|
|
1961
|
+
let x = 13;
|
|
1962
|
+
const y = 23;
|
|
1963
|
+
const $contentEle = $customTitle.children[0];
|
|
1964
|
+
if (getStrWidthPx(title, 12) < 180 + 50) {
|
|
1965
|
+
//【弹出div自适应字符串宽度】若显示的字符串占用宽度小于180,则设置弹出div的宽度为“符串占用宽度”+20
|
|
1966
|
+
$contentEle.style.maxWidth = getStrWidthPx(title, 12) + 20 + 50 + 'px';
|
|
1967
|
+
diffValueX = e.clientX + (getStrWidthPx(title, 12) + 50) - document.body.offsetWidth;
|
|
1968
|
+
}
|
|
1969
|
+
else {
|
|
1970
|
+
$contentEle.style.maxWidth = '250px';
|
|
1971
|
+
diffValueX = e.clientX + 230 - document.body.offsetWidth; //计算div水平方向显示的内容超出屏幕多少宽度
|
|
1972
|
+
}
|
|
1973
|
+
$contentEle.innerHTML = title; //html方法可解析内容中换行标签,text方法不能
|
|
1974
|
+
if (diffValueX > 0) {
|
|
1975
|
+
//水平方向超出可见区域时
|
|
1976
|
+
x -= diffValueX;
|
|
1977
|
+
}
|
|
1978
|
+
$customTitle.style.top = e.clientY + y + 'px';
|
|
1979
|
+
$customTitle.style.left = e.clientX + x + 'px';
|
|
1980
|
+
$customTitle.style.maxWidth = '250px';
|
|
1981
|
+
const diffValueY = $customTitle.getBoundingClientRect().top + $contentEle.offsetHeight - document.body.offsetHeight;
|
|
1982
|
+
if (diffValueY > 0) {
|
|
1983
|
+
//垂直方向超出可见区域时
|
|
1984
|
+
$customTitle.style.top = e.clientY - diffValueY + 'px';
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
/**
|
|
1988
|
+
* 移除提示文案dom的事件句柄
|
|
1989
|
+
* @param {string} rootElId
|
|
1990
|
+
* @returns {*}
|
|
1991
|
+
*/
|
|
1992
|
+
function handleMouseLeave(rootElId = '#root') {
|
|
1993
|
+
const rootEl = document.querySelector(rootElId), titleEl = document.querySelector('#customTitle1494304949567');
|
|
1994
|
+
if (rootEl && titleEl) {
|
|
1995
|
+
rootEl.removeChild(titleEl);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
const tooltipEvent = { handleMouseEnter, handleMouseLeave };
|
|
1999
|
+
|
|
1794
2000
|
exports.HEX_POOL = HEX_POOL;
|
|
1795
2001
|
exports.STRING_ARABIC_NUMERALS = STRING_ARABIC_NUMERALS;
|
|
1796
2002
|
exports.STRING_LOWERCASE_ALPHA = STRING_LOWERCASE_ALPHA;
|
|
@@ -1804,6 +2010,7 @@
|
|
|
1804
2010
|
exports.arrayLike = arrayLike;
|
|
1805
2011
|
exports.arrayRemove = arrayRemove;
|
|
1806
2012
|
exports.asyncMap = asyncMap;
|
|
2013
|
+
exports.buildTree = buildTree;
|
|
1807
2014
|
exports.calculateDate = calculateDate;
|
|
1808
2015
|
exports.calculateDateTime = calculateDateTime;
|
|
1809
2016
|
exports.chooseLocalFile = chooseLocalFile;
|
|
@@ -1816,11 +2023,11 @@
|
|
|
1816
2023
|
exports.dateToEnd = dateToEnd;
|
|
1817
2024
|
exports.dateToStart = dateToStart;
|
|
1818
2025
|
exports.debounce = debounce;
|
|
1819
|
-
exports.deepTraversal = deepTraversal;
|
|
1820
2026
|
exports.downloadBlob = downloadBlob;
|
|
1821
2027
|
exports.downloadData = downloadData;
|
|
1822
2028
|
exports.downloadHref = downloadHref;
|
|
1823
2029
|
exports.downloadURL = downloadURL;
|
|
2030
|
+
exports.forEachDeep = forEachDeep;
|
|
1824
2031
|
exports.formatDate = formatDate;
|
|
1825
2032
|
exports.formatNumber = formatNumber;
|
|
1826
2033
|
exports.genCanvasWM = genCanvasWM;
|
|
@@ -1828,7 +2035,6 @@
|
|
|
1828
2035
|
exports.getGlobal = getGlobal;
|
|
1829
2036
|
exports.getStrWidthPx = getStrWidthPx;
|
|
1830
2037
|
exports.getStyle = getStyle;
|
|
1831
|
-
exports.getTreeIds = getTreeIds;
|
|
1832
2038
|
exports.hasClass = hasClass;
|
|
1833
2039
|
exports.isArray = isArray;
|
|
1834
2040
|
exports.isBigInt = isBigInt;
|
|
@@ -1870,6 +2076,7 @@
|
|
|
1870
2076
|
exports.randomString = randomString;
|
|
1871
2077
|
exports.randomUuid = randomUuid;
|
|
1872
2078
|
exports.removeClass = removeClass;
|
|
2079
|
+
exports.searchTreeById = searchTreeById;
|
|
1873
2080
|
exports.setGlobal = setGlobal;
|
|
1874
2081
|
exports.setStyle = setStyle;
|
|
1875
2082
|
exports.smoothScroll = smoothScroll;
|
|
@@ -1880,6 +2087,7 @@
|
|
|
1880
2087
|
exports.stringFormat = stringFormat;
|
|
1881
2088
|
exports.stringKebabCase = stringKebabCase;
|
|
1882
2089
|
exports.throttle = throttle;
|
|
2090
|
+
exports.tooltipEvent = tooltipEvent;
|
|
1883
2091
|
exports.typeIs = typeIs;
|
|
1884
2092
|
exports.uniqueNumber = uniqueNumber;
|
|
1885
2093
|
exports.uniqueString = uniqueString;
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sculp-js",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"packageManager": "npm@8.19.2",
|
|
5
5
|
"description": "js工具库",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"prepare": "husky install",
|
|
8
|
-
"build": "
|
|
8
|
+
"build": "rollup --bundleConfigAsCjs --config rollup.config.js",
|
|
9
9
|
"build:terser": "node scripts/build.js",
|
|
10
10
|
"test:unit": "jest",
|
|
11
11
|
"test": "jest --coverage",
|
|
12
|
+
"coveralls": "jest --coverage --coverageReporters=text-lcov | coveralls",
|
|
12
13
|
"lint": "eslint ./src --ext .vue,.js,jsx,.ts,tsx",
|
|
13
14
|
"lint:fix": "eslint --fix ./src --ext .vue,.js,jsx,.ts,tsx",
|
|
14
15
|
"prettier": "prettier -c --write \"**/*.{vue,ts,js,jsx,css,less,scss,json}\"",
|
|
@@ -35,11 +36,11 @@
|
|
|
35
36
|
"lib"
|
|
36
37
|
],
|
|
37
38
|
"keywords": [
|
|
38
|
-
"
|
|
39
|
-
"utils"
|
|
39
|
+
"typescript",
|
|
40
|
+
"js-utils"
|
|
40
41
|
],
|
|
41
42
|
"engines": {
|
|
42
|
-
"node": ">=
|
|
43
|
+
"node": ">=16"
|
|
43
44
|
},
|
|
44
45
|
"repository": "git@github.com:chandq/sculp-js.git",
|
|
45
46
|
"dependencies": {
|