@uniformdev/canvas 19.159.0 → 19.159.1-alpha.27

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/index.mjs CHANGED
@@ -4,6 +4,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __typeError = (msg) => {
8
+ throw TypeError(msg);
9
+ };
7
10
  var __commonJS = (cb, mod) => function __require() {
8
11
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
12
  };
@@ -23,19 +26,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
26
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
27
  mod
25
28
  ));
26
- var __accessCheck = (obj, member, msg) => {
27
- if (!member.has(obj))
28
- throw TypeError("Cannot " + msg);
29
- };
30
- var __privateGet = (obj, member, getter) => {
31
- __accessCheck(obj, member, "read from private field");
32
- return getter ? getter.call(obj) : member.get(obj);
33
- };
34
- var __privateAdd = (obj, member, value) => {
35
- if (member.has(obj))
36
- throw TypeError("Cannot add the same private member more than once");
37
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
38
- };
29
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
30
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
31
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
39
32
 
40
33
  // ../../node_modules/.pnpm/retry@0.13.1/node_modules/retry/lib/retry_operation.js
41
34
  var require_retry_operation = __commonJS({
@@ -1050,8 +1043,7 @@ function walkNodeTree(node, visitor, options) {
1050
1043
  const childContexts = /* @__PURE__ */ new Map();
1051
1044
  do {
1052
1045
  const currentQueueEntry = componentQueue.pop();
1053
- if (!currentQueueEntry)
1054
- continue;
1046
+ if (!currentQueueEntry) continue;
1055
1047
  const currentComponent = currentQueueEntry.ancestorsAndSelf[0];
1056
1048
  let visitDescendants = true;
1057
1049
  let descendantContext = (_a = childContexts.get(currentComponent.node)) != null ? _a : currentQueueEntry.context;
@@ -1262,8 +1254,7 @@ function walkNodeTree(node, visitor, options) {
1262
1254
  const propertyEntries = Object.entries(properties);
1263
1255
  for (let propIndex = propertyEntries.length - 1; propIndex >= 0; propIndex--) {
1264
1256
  const [propKey, propObject] = propertyEntries[propIndex];
1265
- if (!isNestedNodeType(propObject.type))
1266
- continue;
1257
+ if (!isNestedNodeType(propObject.type)) continue;
1267
1258
  const blocks = (_b = propObject.value) != null ? _b : [];
1268
1259
  for (let blockIndex = blocks.length - 1; blockIndex >= 0; blockIndex--) {
1269
1260
  const enqueueingBlock = blocks[blockIndex];
@@ -1608,6 +1599,174 @@ function findParameterInNodeTree(data, predicate) {
1608
1599
  return results;
1609
1600
  }
1610
1601
 
1602
+ // src/enhancement/visibility/evaluateVisibilityCriteriaGroup.ts
1603
+ function evaluateVisibilityCriteriaGroup(options) {
1604
+ const { criteriaGroup, simplifyCriteria } = options;
1605
+ const earlyExitResult = criteriaGroup.op === "&" || !criteriaGroup.op ? false : true;
1606
+ let hasIndeterminateClauses = false;
1607
+ for (let index = criteriaGroup.clauses.length - 1; index >= 0; index--) {
1608
+ const clause = criteriaGroup.clauses[index];
1609
+ const criteriaResult = evaluateCriterion(clause, options);
1610
+ if (criteriaResult === null) {
1611
+ hasIndeterminateClauses = true;
1612
+ } else if (criteriaResult === earlyExitResult) {
1613
+ return earlyExitResult;
1614
+ } else if (criteriaResult !== null && simplifyCriteria) {
1615
+ criteriaGroup.clauses.splice(index, 1);
1616
+ }
1617
+ }
1618
+ return hasIndeterminateClauses ? null : !earlyExitResult;
1619
+ }
1620
+ function evaluateCriterion(clause, rootOptions) {
1621
+ if ("clauses" in clause) {
1622
+ return evaluateVisibilityCriteriaGroup({
1623
+ ...rootOptions,
1624
+ criteriaGroup: clause
1625
+ });
1626
+ }
1627
+ const rule = rootOptions.rules[clause.rule];
1628
+ if (rule) {
1629
+ return rule(clause);
1630
+ }
1631
+ return null;
1632
+ }
1633
+
1634
+ // src/enhancement/visibility/types.ts
1635
+ var CANVAS_VIZ_CONTROL_PARAM = "$viz";
1636
+
1637
+ // src/enhancement/visibility/evaluateNodeVisibility.ts
1638
+ function evaluateNodeVisibility({
1639
+ node,
1640
+ ...evaluateGroupOptions
1641
+ }) {
1642
+ var _a;
1643
+ const properties = getPropertiesValue(node);
1644
+ const vizCriteria = (_a = properties == null ? void 0 : properties[CANVAS_VIZ_CONTROL_PARAM]) == null ? void 0 : _a.value;
1645
+ if (vizCriteria == null ? void 0 : vizCriteria.explicitlyHidden) {
1646
+ return false;
1647
+ }
1648
+ if (!(vizCriteria == null ? void 0 : vizCriteria.criteria)) {
1649
+ return true;
1650
+ }
1651
+ const result = evaluateVisibilityCriteriaGroup({
1652
+ ...evaluateGroupOptions,
1653
+ criteriaGroup: vizCriteria.criteria
1654
+ });
1655
+ if (vizCriteria.criteria.clauses.length === 0 && evaluateGroupOptions.simplifyCriteria) {
1656
+ properties == null ? true : delete properties[CANVAS_VIZ_CONTROL_PARAM];
1657
+ }
1658
+ return result;
1659
+ }
1660
+
1661
+ // src/enhancement/visibility/evaluateWalkTreeVisibility.ts
1662
+ function evaluateWalkTreeVisibility({
1663
+ rules,
1664
+ showIndeterminate,
1665
+ context
1666
+ }) {
1667
+ const { type, node, actions } = context;
1668
+ if (type !== "component") {
1669
+ return;
1670
+ }
1671
+ const result = evaluateNodeVisibility({ node, rules, simplifyCriteria: true });
1672
+ if (result === null && !showIndeterminate || result === false) {
1673
+ actions.remove();
1674
+ return false;
1675
+ }
1676
+ return true;
1677
+ }
1678
+
1679
+ // src/enhancement/visibility/rules/evaluateStringMatch.ts
1680
+ var isEvaluator = (criteria, matchValue) => {
1681
+ if (Array.isArray(criteria)) {
1682
+ return criteria.includes(matchValue);
1683
+ }
1684
+ return criteria === matchValue;
1685
+ };
1686
+ var containsEvaluator = (criteria, matchValue) => {
1687
+ if (Array.isArray(criteria)) {
1688
+ return criteria.some((criterion) => matchValue.includes(criterion));
1689
+ }
1690
+ return matchValue.includes(criteria);
1691
+ };
1692
+ var startsWithEvaluator = (criteria, matchValue) => {
1693
+ if (Array.isArray(criteria)) {
1694
+ return criteria.some((criterion) => matchValue.startsWith(criterion));
1695
+ }
1696
+ return matchValue.startsWith(criteria);
1697
+ };
1698
+ var endsWithEvaluator = (criteria, matchValue) => {
1699
+ if (Array.isArray(criteria)) {
1700
+ return criteria.some((criterion) => matchValue.endsWith(criterion));
1701
+ }
1702
+ return matchValue.endsWith(criteria);
1703
+ };
1704
+ var emptyEvaluator = (_, matchValue) => {
1705
+ return matchValue === "";
1706
+ };
1707
+ var stringOperatorEvaluators = {
1708
+ is: isEvaluator,
1709
+ has: containsEvaluator,
1710
+ startswith: startsWithEvaluator,
1711
+ endswith: endsWithEvaluator,
1712
+ empty: emptyEvaluator
1713
+ };
1714
+ function evaluateStringMatch(criteria, matchValue, allow) {
1715
+ const { op, value } = criteria;
1716
+ if (allow && !allow.has(op)) {
1717
+ return null;
1718
+ }
1719
+ let opMatch = op;
1720
+ const negation = op.startsWith("!");
1721
+ if (negation) {
1722
+ opMatch = opMatch.slice(1);
1723
+ }
1724
+ const evaluator = stringOperatorEvaluators[opMatch];
1725
+ if (!evaluator) {
1726
+ return null;
1727
+ }
1728
+ const result = evaluator(value, matchValue);
1729
+ return negation ? !result : result;
1730
+ }
1731
+
1732
+ // src/enhancement/visibility/rules/dynamicInputVisibilityRule.ts
1733
+ var dynamicInputVisibilityOperators = /* @__PURE__ */ new Set([
1734
+ "is",
1735
+ "!is",
1736
+ "has",
1737
+ "!has",
1738
+ "startswith",
1739
+ "!startswith",
1740
+ "endswith",
1741
+ "!endswith",
1742
+ "empty",
1743
+ "!empty"
1744
+ ]);
1745
+ var CANVAS_VIZ_DI_RULE = "$di";
1746
+ function createDynamicInputVisibilityRule(dynamicInputs) {
1747
+ return {
1748
+ [CANVAS_VIZ_DI_RULE]: (criterion) => {
1749
+ const { source } = criterion;
1750
+ const diValue = source ? dynamicInputs[source] : void 0;
1751
+ return evaluateStringMatch(criterion, diValue != null ? diValue : "", dynamicInputVisibilityOperators);
1752
+ }
1753
+ };
1754
+ }
1755
+
1756
+ // src/enhancement/visibility/rules/localeVisibilityRule.ts
1757
+ var localeVisibilityOperators = /* @__PURE__ */ new Set(["is", "!is"]);
1758
+ var CANVAS_VIZ_LOCALE_RULE = "$locale";
1759
+ function createLocaleVisibilityRule(currentLocale) {
1760
+ return {
1761
+ [CANVAS_VIZ_LOCALE_RULE]: (criterion) => {
1762
+ if (!currentLocale) {
1763
+ return false;
1764
+ }
1765
+ return evaluateStringMatch(criterion, currentLocale, localeVisibilityOperators);
1766
+ }
1767
+ };
1768
+ }
1769
+
1611
1770
  // src/enhancement/localize.ts
1612
1771
  function extractLocales({ component }) {
1613
1772
  var _a;
@@ -1626,17 +1785,29 @@ function extractLocales({ component }) {
1626
1785
  function localize(options) {
1627
1786
  const nodes = "nodes" in options ? options.nodes : options.composition;
1628
1787
  const locale = options.locale;
1629
- walkNodeTree(nodes, ({ type, node, actions }) => {
1788
+ const isUsingModernOptions = typeof locale === "string";
1789
+ const vizControlLocaleRule = isUsingModernOptions ? createLocaleVisibilityRule(locale) : {};
1790
+ walkNodeTree(nodes, (context) => {
1791
+ const { type, node, actions } = context;
1630
1792
  if (type !== "component") {
1631
- if (typeof locale === "string") {
1793
+ if (isUsingModernOptions) {
1632
1794
  localizeProperties(node.fields, locale);
1633
1795
  }
1634
1796
  return;
1635
1797
  }
1636
- const shouldRunPropertyLocalization = typeof locale === "string";
1798
+ if (isUsingModernOptions) {
1799
+ const result = evaluateWalkTreeVisibility({
1800
+ context,
1801
+ rules: vizControlLocaleRule,
1802
+ showIndeterminate: true
1803
+ });
1804
+ if (!result) {
1805
+ return;
1806
+ }
1807
+ }
1637
1808
  if (node.type === CANVAS_LOCALIZATION_TYPE) {
1638
1809
  const locales = extractLocales({ component: node });
1639
- const resolvedLocale = typeof locale === "string" ? locale : locale == null ? void 0 : locale({ component: node, locales });
1810
+ const resolvedLocale = isUsingModernOptions ? locale : locale == null ? void 0 : locale({ component: node, locales });
1640
1811
  let replaceComponent;
1641
1812
  if (resolvedLocale) {
1642
1813
  replaceComponent = locales[resolvedLocale];
@@ -1644,7 +1815,7 @@ function localize(options) {
1644
1815
  if (replaceComponent == null ? void 0 : replaceComponent.length) {
1645
1816
  replaceComponent.forEach((component) => {
1646
1817
  removeLocaleProperty(component);
1647
- if (shouldRunPropertyLocalization) {
1818
+ if (isUsingModernOptions) {
1648
1819
  localizeProperties(getPropertiesValue(component), locale);
1649
1820
  }
1650
1821
  });
@@ -1656,7 +1827,7 @@ function localize(options) {
1656
1827
  } else {
1657
1828
  actions.remove();
1658
1829
  }
1659
- } else if (shouldRunPropertyLocalization) {
1830
+ } else if (isUsingModernOptions) {
1660
1831
  localizeProperties(getPropertiesValue(node), locale);
1661
1832
  }
1662
1833
  });
@@ -1735,8 +1906,7 @@ function walkComponentTree(component, visitor, initialContext) {
1735
1906
  const childContexts = /* @__PURE__ */ new Map();
1736
1907
  do {
1737
1908
  const currentQueueEntry = componentQueue.pop();
1738
- if (!currentQueueEntry)
1739
- continue;
1909
+ if (!currentQueueEntry) continue;
1740
1910
  const currentComponent = currentQueueEntry.ancestorsAndSelf[0];
1741
1911
  let visitDescendants = true;
1742
1912
  let descendantContext = (_a = childContexts.get(currentComponent.component)) != null ? _a : currentQueueEntry.context;
@@ -1841,10 +2011,25 @@ function walkComponentTree(component, visitor, initialContext) {
1841
2011
  } while (componentQueue.length > 0);
1842
2012
  }
1843
2013
 
1844
- // src/LocaleClient.ts
2014
+ // src/EntityReleasesClient.ts
1845
2015
  import { ApiClient as ApiClient6 } from "@uniformdev/context/api";
2016
+ var releaseContentsUrl = "/api/v1/entity-releases";
2017
+ var EntityReleasesClient = class extends ApiClient6 {
2018
+ constructor(options) {
2019
+ super(options);
2020
+ }
2021
+ /** Fetches entity across all releases (and base) */
2022
+ async get(options) {
2023
+ const { projectId } = this.options;
2024
+ const fetchUri = this.createUrl(releaseContentsUrl, { ...options, projectId });
2025
+ return await this.apiClient(fetchUri);
2026
+ }
2027
+ };
2028
+
2029
+ // src/LocaleClient.ts
2030
+ import { ApiClient as ApiClient7 } from "@uniformdev/context/api";
1846
2031
  var localesUrl = "/api/v1/locales";
1847
- var LocaleClient = class extends ApiClient6 {
2032
+ var LocaleClient = class extends ApiClient7 {
1848
2033
  constructor(options) {
1849
2034
  super(options);
1850
2035
  }
@@ -2262,9 +2447,9 @@ function subscribeToComposition({
2262
2447
  }
2263
2448
 
2264
2449
  // src/PromptClient.ts
2265
- import { ApiClient as ApiClient7 } from "@uniformdev/context/api";
2450
+ import { ApiClient as ApiClient8 } from "@uniformdev/context/api";
2266
2451
  var PromptsUrl = "/api/v1/prompts";
2267
- var PromptClient = class extends ApiClient7 {
2452
+ var PromptClient = class extends ApiClient8 {
2268
2453
  constructor(options) {
2269
2454
  super(options);
2270
2455
  }
@@ -2295,9 +2480,9 @@ var PromptClient = class extends ApiClient7 {
2295
2480
  };
2296
2481
 
2297
2482
  // src/RelationshipClient.ts
2298
- import { ApiClient as ApiClient8 } from "@uniformdev/context/api";
2483
+ import { ApiClient as ApiClient9 } from "@uniformdev/context/api";
2299
2484
  var RELATIONSHIPS_URL = "/api/v1/relationships";
2300
- var RelationshipClient = class extends ApiClient8 {
2485
+ var RelationshipClient = class extends ApiClient9 {
2301
2486
  constructor(options) {
2302
2487
  super(options);
2303
2488
  this.get = async (options) => {
@@ -2309,9 +2494,9 @@ var RelationshipClient = class extends ApiClient8 {
2309
2494
  };
2310
2495
 
2311
2496
  // src/ReleaseClient.ts
2312
- import { ApiClient as ApiClient9 } from "@uniformdev/context/api";
2497
+ import { ApiClient as ApiClient10 } from "@uniformdev/context/api";
2313
2498
  var releasesUrl = "/api/v1/releases";
2314
- var ReleaseClient = class extends ApiClient9 {
2499
+ var ReleaseClient = class extends ApiClient10 {
2315
2500
  constructor(options) {
2316
2501
  super(options);
2317
2502
  }
@@ -2351,21 +2536,21 @@ var ReleaseClient = class extends ApiClient9 {
2351
2536
  };
2352
2537
 
2353
2538
  // src/ReleaseContentsClient.ts
2354
- import { ApiClient as ApiClient10 } from "@uniformdev/context/api";
2355
- var releaseContentsUrl = "/api/v1/release-contents";
2356
- var ReleaseContentsClient = class extends ApiClient10 {
2539
+ import { ApiClient as ApiClient11 } from "@uniformdev/context/api";
2540
+ var releaseContentsUrl2 = "/api/v1/release-contents";
2541
+ var ReleaseContentsClient = class extends ApiClient11 {
2357
2542
  constructor(options) {
2358
2543
  super(options);
2359
2544
  }
2360
2545
  /** Fetches all entities added to a release */
2361
2546
  async get(options) {
2362
2547
  const { projectId } = this.options;
2363
- const fetchUri = this.createUrl(releaseContentsUrl, { ...options, projectId });
2548
+ const fetchUri = this.createUrl(releaseContentsUrl2, { ...options, projectId });
2364
2549
  return await this.apiClient(fetchUri);
2365
2550
  }
2366
2551
  /** Removes a release content from a release */
2367
2552
  async remove(body) {
2368
- const fetchUri = this.createUrl(releaseContentsUrl);
2553
+ const fetchUri = this.createUrl(releaseContentsUrl2);
2369
2554
  await this.apiClient(fetchUri, {
2370
2555
  method: "DELETE",
2371
2556
  body: JSON.stringify({ ...body, projectId: this.options.projectId }),
@@ -2375,9 +2560,9 @@ var ReleaseContentsClient = class extends ApiClient10 {
2375
2560
  };
2376
2561
 
2377
2562
  // src/RouteClient.ts
2378
- import { ApiClient as ApiClient11 } from "@uniformdev/context/api";
2563
+ import { ApiClient as ApiClient12 } from "@uniformdev/context/api";
2379
2564
  var ROUTE_URL = "/api/v1/route";
2380
- var RouteClient = class extends ApiClient11 {
2565
+ var RouteClient = class extends ApiClient12 {
2381
2566
  constructor(options) {
2382
2567
  var _a;
2383
2568
  if (!options.limitPolicy) {
@@ -2488,8 +2673,7 @@ var isSystemComponentDefinition = (componentType) => {
2488
2673
 
2489
2674
  // src/utils/mapSlotToPersonalizedVariations.ts
2490
2675
  function mapSlotToPersonalizedVariations(slot) {
2491
- if (!slot)
2492
- return [];
2676
+ if (!slot) return [];
2493
2677
  return slot.map((v, i) => {
2494
2678
  var _a, _b;
2495
2679
  const contextTag = (_b = (_a = v.parameters) == null ? void 0 : _a[CANVAS_PERSONALIZATION_PARAM]) == null ? void 0 : _b.value;
@@ -2504,8 +2688,7 @@ function mapSlotToPersonalizedVariations(slot) {
2504
2688
 
2505
2689
  // src/utils/mapSlotToTestVariations.ts
2506
2690
  function mapSlotToTestVariations(slot) {
2507
- if (!slot)
2508
- return [];
2691
+ if (!slot) return [];
2509
2692
  return slot.map((v, i) => {
2510
2693
  var _a, _b, _c;
2511
2694
  const contextTag = (_b = (_a = v.parameters) == null ? void 0 : _a[CANVAS_TEST_VARIANT_PARAM]) == null ? void 0 : _b.value;
@@ -2747,9 +2930,9 @@ function handleRichTextNodeBinding(object, options) {
2747
2930
  import { ApiClientError as ApiClientError2 } from "@uniformdev/context/api";
2748
2931
 
2749
2932
  // src/WorkflowClient.ts
2750
- import { ApiClient as ApiClient12 } from "@uniformdev/context/api";
2933
+ import { ApiClient as ApiClient13 } from "@uniformdev/context/api";
2751
2934
  var workflowsUrl = "/api/v1/workflows";
2752
- var WorkflowClient = class extends ApiClient12 {
2935
+ var WorkflowClient = class extends ApiClient13 {
2753
2936
  constructor(options) {
2754
2937
  super(options);
2755
2938
  }
@@ -2810,6 +2993,9 @@ export {
2810
2993
  CANVAS_TEST_SLOT,
2811
2994
  CANVAS_TEST_TYPE,
2812
2995
  CANVAS_TEST_VARIANT_PARAM,
2996
+ CANVAS_VIZ_CONTROL_PARAM,
2997
+ CANVAS_VIZ_DI_RULE,
2998
+ CANVAS_VIZ_LOCALE_RULE,
2813
2999
  CanvasClient,
2814
3000
  CanvasClientError,
2815
3001
  CategoryClient,
@@ -2823,6 +3009,7 @@ export {
2823
3009
  EDGE_MIN_CACHE_TTL,
2824
3010
  EMPTY_COMPOSITION,
2825
3011
  EnhancerBuilder,
3012
+ EntityReleasesClient,
2826
3013
  IN_CONTEXT_EDITOR_COMPONENT_END_ROLE,
2827
3014
  IN_CONTEXT_EDITOR_COMPONENT_START_ROLE,
2828
3015
  IN_CONTEXT_EDITOR_CONFIG_CHECK_QUERY_STRING_PARAM,
@@ -2851,11 +3038,15 @@ export {
2851
3038
  convertEntryToPutEntry,
2852
3039
  createBatchEnhancer,
2853
3040
  createCanvasChannel,
3041
+ createDynamicInputVisibilityRule,
2854
3042
  createEventBus,
2855
3043
  createLimitPolicy,
3044
+ createLocaleVisibilityRule,
2856
3045
  createUniformApiEnhancer,
2857
3046
  createVariableReference,
2858
3047
  enhance,
3048
+ evaluateVisibilityCriteriaGroup,
3049
+ evaluateWalkTreeVisibility,
2859
3050
  extractLocales,
2860
3051
  findParameterInNodeTree,
2861
3052
  flattenValues,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/canvas",
3
- "version": "19.159.0",
3
+ "version": "19.159.1-alpha.27+344f3d36db",
4
4
  "description": "Common functionality and types for Uniform Canvas",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./dist/index.js",
@@ -38,8 +38,8 @@
38
38
  "pusher-js": "8.2.0"
39
39
  },
40
40
  "dependencies": {
41
- "@uniformdev/assets": "19.159.0",
42
- "@uniformdev/context": "19.159.0",
41
+ "@uniformdev/assets": "19.159.1-alpha.27+344f3d36db",
42
+ "@uniformdev/context": "19.159.1-alpha.27+344f3d36db",
43
43
  "immer": "10.0.4"
44
44
  },
45
45
  "files": [
@@ -48,5 +48,5 @@
48
48
  "publishConfig": {
49
49
  "access": "public"
50
50
  },
51
- "gitHead": "49ed8744113d885f24c96d819a6e1dd1896b6ce0"
51
+ "gitHead": "344f3d36dba87d4e2340a1687c20b163be1d2c83"
52
52
  }