denwa-web-shared 1.0.46 → 1.0.48

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.
@@ -46,6 +46,20 @@ const CITY_MASK = {
46
46
  CITY_REGION: "{{CITY_REGION}}",
47
47
  CITY_REGION_DECL: "{{CITY_REGION_DECL}}"
48
48
  };
49
+ const getImageData = (basePath, filename, ext) => ({
50
+ image1x: `${basePath}/${filename}.${ext}`,
51
+ image2x: `${basePath}/${filename}_2x.${ext}`,
52
+ image1xWebp: `${basePath}/${filename}.webp`,
53
+ image2xWebp: `${basePath}/${filename}_2x.webp`,
54
+ image1xAvif: `${basePath}/${filename}.avif`,
55
+ image2xAvif: `${basePath}/${filename}_2x.avif`,
56
+ mobileImage1x: `${basePath}/${filename}_mobile.${ext}`,
57
+ mobileImage2x: `${basePath}/${filename}_mobile_2x.${ext}`,
58
+ mobileImage1xWebp: `${basePath}/${filename}_mobile.webp`,
59
+ mobileImage2xWebp: `${basePath}/${filename}_mobile_2x.webp`,
60
+ mobileImage1xAvif: `${basePath}/${filename}_mobile.avif`,
61
+ mobileImage2xAvif: `${basePath}/${filename}_mobile_2x.avif`
62
+ });
49
63
  const getNumberFormatter = (locale, options) => {
50
64
  return new Intl.NumberFormat(locale, options);
51
65
  };
@@ -410,6 +424,81 @@ const hslToHex = (h, s, l) => {
410
424
  };
411
425
  return `#${toHex(r2)}${toHex(g)}${toHex(b)}`;
412
426
  };
427
+ const uuidToStringId = (uuid2, length = 18) => {
428
+ const cleanUuid = uuid2.replace(/-/g, "");
429
+ return cleanUuid.slice(-length);
430
+ };
431
+ const uuidToNumericId = (uuid2, maxDigits = 18) => {
432
+ const hex = uuid2.replace(/-/g, "");
433
+ const safeHex = hex.slice(-14);
434
+ const num = parseInt(safeHex, 16);
435
+ let numStr = num.toString();
436
+ if (numStr.length < maxDigits) {
437
+ numStr = numStr.padStart(maxDigits, "0");
438
+ } else if (numStr.length > maxDigits) {
439
+ numStr = numStr.slice(-maxDigits);
440
+ }
441
+ return numStr;
442
+ };
443
+ const escapeXml = (str) => {
444
+ if (!str) return "";
445
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
446
+ };
447
+ const generateYandexFeedXML = ({
448
+ shopName,
449
+ shopCompany,
450
+ delivery,
451
+ categoriesData,
452
+ offersData,
453
+ host
454
+ }) => {
455
+ const url = `https://${host}`;
456
+ const offersXml = offersData.map((item) => {
457
+ var _a;
458
+ const id = typeof item.id === "number" ? item.id : uuidToNumericId(item.id);
459
+ const categoryId = typeof item.categoryId === "number" ? item.categoryId : uuidToNumericId(item.categoryId);
460
+ return `
461
+ <offer id="${id}" available="true">
462
+ <url>${escapeXml(`${url}${item.href}`)}</url>
463
+ <price>${item.price}</price>
464
+ <currencyId>RUR</currencyId>
465
+ <categoryId>${categoryId}</categoryId>
466
+ ${item.images.length ? item.images.map((item2) => `<picture>${escapeXml(item2.image1x)}</picture>`).join("") : ""}
467
+ <name>${escapeXml(item.name)}</name>
468
+ <vendor>${escapeXml(item.vendor)}</vendor>
469
+ <description>${escapeXml(item.description)}</description>
470
+ <vendorCode>${escapeXml(item.vendorCode)}</vendorCode>
471
+ <pickup>${item.pickup}</pickup>
472
+ ${(_a = item.params) == null ? void 0 : _a.map((item2) => {
473
+ return `<param name="${item2.name}">${escapeXml(item2.value)}</param>`;
474
+ })}
475
+ </offer>
476
+ `;
477
+ }).join("");
478
+ const categoriesXml = categoriesData.map((item) => {
479
+ const id = typeof item.id === "number" ? item.id : uuidToNumericId(item.id);
480
+ return `<category id="${id}">${escapeXml(item.name)}</category>`;
481
+ }).join("");
482
+ return `<?xml version="1.0" encoding="UTF-8"?>
483
+ <!DOCTYPE yml_catalog SYSTEM "shops.dtd">
484
+ <yml_catalog date="${(/* @__PURE__ */ new Date()).toISOString()}">
485
+ <shop>
486
+ <name>${escapeXml(shopName)}</name>
487
+ <company>${escapeXml(shopCompany)}</company>
488
+ <url>${url}</url>
489
+ <delivery>${delivery}</delivery>
490
+ <currencies>
491
+ <currency id="RUR" rate="1"/>
492
+ </currencies>
493
+ <categories>
494
+ ${categoriesXml}
495
+ </categories>
496
+ <offers>
497
+ ${offersXml}
498
+ </offers>
499
+ </shop>
500
+ </yml_catalog>`;
501
+ };
413
502
  function r(e) {
414
503
  var t, f, n = "";
415
504
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -6992,10 +7081,13 @@ exports.checkCorrectImageObject = checkCorrectImageObject;
6992
7081
  exports.cn = cn;
6993
7082
  exports.convertPhoneMask = convertPhoneMask;
6994
7083
  exports.createCityLink = createCityLink;
7084
+ exports.escapeXml = escapeXml;
6995
7085
  exports.generatePaginationArray = generatePaginationArray;
6996
7086
  exports.generatePlaceholderColor = generatePlaceholderColor;
7087
+ exports.generateYandexFeedXML = generateYandexFeedXML;
6997
7088
  exports.getByKey = getByKey;
6998
7089
  exports.getDateFormatter = getDateFormatter;
7090
+ exports.getImageData = getImageData;
6999
7091
  exports.getImagePrefix = getImagePrefix;
7000
7092
  exports.getLocaleField = getLocaleField;
7001
7093
  exports.getNumberFormatter = getNumberFormatter;
@@ -7015,3 +7107,5 @@ exports.responseSchema = responseSchema;
7015
7107
  exports.serverFileSchema = serverFileSchema;
7016
7108
  exports.serverImageSchema = serverImageSchema;
7017
7109
  exports.updateTextByTemplate = updateTextByTemplate;
7110
+ exports.uuidToNumericId = uuidToNumericId;
7111
+ exports.uuidToStringId = uuidToStringId;
@@ -44,6 +44,20 @@ const CITY_MASK = {
44
44
  CITY_REGION: "{{CITY_REGION}}",
45
45
  CITY_REGION_DECL: "{{CITY_REGION_DECL}}"
46
46
  };
47
+ const getImageData = (basePath, filename, ext) => ({
48
+ image1x: `${basePath}/${filename}.${ext}`,
49
+ image2x: `${basePath}/${filename}_2x.${ext}`,
50
+ image1xWebp: `${basePath}/${filename}.webp`,
51
+ image2xWebp: `${basePath}/${filename}_2x.webp`,
52
+ image1xAvif: `${basePath}/${filename}.avif`,
53
+ image2xAvif: `${basePath}/${filename}_2x.avif`,
54
+ mobileImage1x: `${basePath}/${filename}_mobile.${ext}`,
55
+ mobileImage2x: `${basePath}/${filename}_mobile_2x.${ext}`,
56
+ mobileImage1xWebp: `${basePath}/${filename}_mobile.webp`,
57
+ mobileImage2xWebp: `${basePath}/${filename}_mobile_2x.webp`,
58
+ mobileImage1xAvif: `${basePath}/${filename}_mobile.avif`,
59
+ mobileImage2xAvif: `${basePath}/${filename}_mobile_2x.avif`
60
+ });
47
61
  const getNumberFormatter = (locale, options) => {
48
62
  return new Intl.NumberFormat(locale, options);
49
63
  };
@@ -408,6 +422,81 @@ const hslToHex = (h, s, l) => {
408
422
  };
409
423
  return `#${toHex(r2)}${toHex(g)}${toHex(b)}`;
410
424
  };
425
+ const uuidToStringId = (uuid2, length = 18) => {
426
+ const cleanUuid = uuid2.replace(/-/g, "");
427
+ return cleanUuid.slice(-length);
428
+ };
429
+ const uuidToNumericId = (uuid2, maxDigits = 18) => {
430
+ const hex = uuid2.replace(/-/g, "");
431
+ const safeHex = hex.slice(-14);
432
+ const num = parseInt(safeHex, 16);
433
+ let numStr = num.toString();
434
+ if (numStr.length < maxDigits) {
435
+ numStr = numStr.padStart(maxDigits, "0");
436
+ } else if (numStr.length > maxDigits) {
437
+ numStr = numStr.slice(-maxDigits);
438
+ }
439
+ return numStr;
440
+ };
441
+ const escapeXml = (str) => {
442
+ if (!str) return "";
443
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
444
+ };
445
+ const generateYandexFeedXML = ({
446
+ shopName,
447
+ shopCompany,
448
+ delivery,
449
+ categoriesData,
450
+ offersData,
451
+ host
452
+ }) => {
453
+ const url = `https://${host}`;
454
+ const offersXml = offersData.map((item) => {
455
+ var _a;
456
+ const id = typeof item.id === "number" ? item.id : uuidToNumericId(item.id);
457
+ const categoryId = typeof item.categoryId === "number" ? item.categoryId : uuidToNumericId(item.categoryId);
458
+ return `
459
+ <offer id="${id}" available="true">
460
+ <url>${escapeXml(`${url}${item.href}`)}</url>
461
+ <price>${item.price}</price>
462
+ <currencyId>RUR</currencyId>
463
+ <categoryId>${categoryId}</categoryId>
464
+ ${item.images.length ? item.images.map((item2) => `<picture>${escapeXml(item2.image1x)}</picture>`).join("") : ""}
465
+ <name>${escapeXml(item.name)}</name>
466
+ <vendor>${escapeXml(item.vendor)}</vendor>
467
+ <description>${escapeXml(item.description)}</description>
468
+ <vendorCode>${escapeXml(item.vendorCode)}</vendorCode>
469
+ <pickup>${item.pickup}</pickup>
470
+ ${(_a = item.params) == null ? void 0 : _a.map((item2) => {
471
+ return `<param name="${item2.name}">${escapeXml(item2.value)}</param>`;
472
+ })}
473
+ </offer>
474
+ `;
475
+ }).join("");
476
+ const categoriesXml = categoriesData.map((item) => {
477
+ const id = typeof item.id === "number" ? item.id : uuidToNumericId(item.id);
478
+ return `<category id="${id}">${escapeXml(item.name)}</category>`;
479
+ }).join("");
480
+ return `<?xml version="1.0" encoding="UTF-8"?>
481
+ <!DOCTYPE yml_catalog SYSTEM "shops.dtd">
482
+ <yml_catalog date="${(/* @__PURE__ */ new Date()).toISOString()}">
483
+ <shop>
484
+ <name>${escapeXml(shopName)}</name>
485
+ <company>${escapeXml(shopCompany)}</company>
486
+ <url>${url}</url>
487
+ <delivery>${delivery}</delivery>
488
+ <currencies>
489
+ <currency id="RUR" rate="1"/>
490
+ </currencies>
491
+ <categories>
492
+ ${categoriesXml}
493
+ </categories>
494
+ <offers>
495
+ ${offersXml}
496
+ </offers>
497
+ </shop>
498
+ </yml_catalog>`;
499
+ };
411
500
  function r(e) {
412
501
  var t, f, n = "";
413
502
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -6991,10 +7080,13 @@ export {
6991
7080
  cn,
6992
7081
  convertPhoneMask,
6993
7082
  createCityLink,
7083
+ escapeXml,
6994
7084
  generatePaginationArray,
6995
7085
  generatePlaceholderColor,
7086
+ generateYandexFeedXML,
6996
7087
  getByKey,
6997
7088
  getDateFormatter,
7089
+ getImageData,
6998
7090
  getImagePrefix,
6999
7091
  getLocaleField,
7000
7092
  getNumberFormatter,
@@ -7013,5 +7105,7 @@ export {
7013
7105
  responseSchema,
7014
7106
  serverFileSchema,
7015
7107
  serverImageSchema,
7016
- updateTextByTemplate
7108
+ updateTextByTemplate,
7109
+ uuidToNumericId,
7110
+ uuidToStringId
7017
7111
  };
@@ -1,4 +1,13 @@
1
- import { IPaginate, PaginationResult } from '../types';
1
+ import { IPaginate, IPreparedServerImageWithAlt, PaginationResult } from '../types';
2
+ import { PictureData } from '../types/picture-data';
3
+ /**
4
+ * @description Хелпер для генерации путей к адаптивным статичным изображениям (PictureData)
5
+ * @param basePath - Базовый путь к директории (например, '/compressed/cta')
6
+ * @param filename - Имя файла без расширения (например, 'cta-arrow')
7
+ * @param ext - Расширение исходного fallback-файла (по умолчанию 'jpg')
8
+ * @return Объект PictureData со всеми нужными форматами
9
+ */
10
+ export declare const getImageData: (basePath: string, filename: string, ext: "jpg" | "png") => PictureData;
2
11
  /**
3
12
  * @description Получить Intl для нужного языка
4
13
  * @param locale - Локаль
@@ -185,3 +194,58 @@ export declare const generatePlaceholderColor: (seed?: number | string) => strin
185
194
  * @returns Цвет в формате HEX (#RRGGBB)
186
195
  */
187
196
  export declare const hslToHex: (h: number, s: number, l: number) => string;
197
+ /**
198
+ * Преобразует UUID в короткий ID
199
+ * @param {string} uuid - UUID v4 строка (с дефисами или без)
200
+ * @param {number} length - нужная длина (по умолчанию 18)
201
+ * @returns {string} короткий ID без дефисов
202
+ */
203
+ export declare const uuidToStringId: (uuid: string, length?: number) => string;
204
+ /**
205
+ * Преобразует UUID в числовой ID
206
+ * @param {string} uuid - UUID v4 строка (с дефисами или без)
207
+ * @param {number} maxDigits - максимальное количество цифр в результате (по умолчанию 18)
208
+ * @returns {string} числовой ID в виде строки
209
+ */
210
+ export declare const uuidToNumericId: (uuid: string, maxDigits?: number) => string;
211
+ /**
212
+ * @description Экранирует XML-специальные символы в строке.
213
+ * @param str - Строка
214
+ */
215
+ export declare const escapeXml: (str: string) => string;
216
+ /**
217
+ * @description Генерирует XML-фид для яндекс товаров.
218
+ * @param shopName - Название магазина
219
+ * @param shopCompany - Компания
220
+ * @param delivery - Доставка
221
+ * @param categoriesData - Категории
222
+ * @param offersData - Товары
223
+ * @param host - Хост
224
+ * @response Готовый xml фид товаров
225
+ */
226
+ export declare const generateYandexFeedXML: ({ shopName, shopCompany, delivery, categoriesData, offersData, host, }: {
227
+ shopName: string;
228
+ shopCompany: string;
229
+ host: string;
230
+ delivery: boolean;
231
+ categoriesData: {
232
+ id: string | number;
233
+ name: string;
234
+ }[];
235
+ offersData: {
236
+ id: string | number;
237
+ categoryId: string | number;
238
+ name: string;
239
+ vendor: string;
240
+ vendorCode: string;
241
+ description: string;
242
+ href: string;
243
+ images: IPreparedServerImageWithAlt[];
244
+ price: number;
245
+ pickup: boolean;
246
+ params?: {
247
+ name: string;
248
+ value: string;
249
+ }[];
250
+ }[];
251
+ }) => string;
@@ -0,0 +1,14 @@
1
+ export interface PictureData {
2
+ image1x: string;
3
+ image2x: string;
4
+ image1xWebp: string;
5
+ image2xWebp: string;
6
+ image1xAvif: string;
7
+ image2xAvif: string;
8
+ mobileImage1x: string;
9
+ mobileImage2x: string;
10
+ mobileImage1xWebp: string;
11
+ mobileImage2xWebp: string;
12
+ mobileImage1xAvif: string;
13
+ mobileImage2xAvif: string;
14
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "denwa-web-shared",
3
3
  "private": false,
4
- "version": "1.0.46",
4
+ "version": "1.0.48",
5
5
  "type": "module",
6
6
  "author": "Denwa",
7
7
  "main": "dist/denwa-web-shared.cjs.js",