@snabcentr/client-core 3.9.1 → 3.11.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.
@@ -2,7 +2,7 @@ import * as i1 from 'rxjs';
2
2
  import { of, startWith as startWith$1, Subject, ReplaySubject, partition, combineLatest, map as map$1, debounceTime, switchMap, tap, filter, shareReplay, distinctUntilChanged, BehaviorSubject, materialize, dematerialize, merge, distinctUntilKeyChanged, skip, first, catchError as catchError$1, throwError, expand, takeWhile, toArray, EMPTY, take, defaultIfEmpty, concatMap, finalize, takeUntil, interval, share, scan } from 'rxjs';
3
3
  import { map, startWith, catchError } from 'rxjs/operators';
4
4
  import { parseISO, parse, isValid, format } from 'date-fns';
5
- import { isString, isNil, isMatch, isArray, get } from 'lodash-es';
5
+ import { isString, isNil, isMatch, isArray, omit, get } from 'lodash-es';
6
6
  import * as i0 from '@angular/core';
7
7
  import { InjectionToken, inject, PLATFORM_ID, Injectable, Inject, Optional, EventEmitter, DestroyRef, LOCALE_ID, Pipe, RendererFactory2 } from '@angular/core';
8
8
  import { WA_LOCAL_STORAGE, WA_USER_AGENT, WA_WINDOW } from '@ng-web-apis/common';
@@ -7675,36 +7675,36 @@ class SchemaOrgFactory {
7675
7675
  *
7676
7676
  * @param product Данные о продукте.
7677
7677
  * @param productPath Url путь к товару. В пути должен присутствовать шаблон ':id', обозначающий идентификатор товара для подстановки.
7678
+ * @param id Необязательный идентификатор сущности для поля `@id` в JSON-LD.
7678
7679
  */
7679
- generateForProductItem(product, productPath) {
7680
+ generateForProductItem(product, productPath, id) {
7680
7681
  const productUrl = `${this.urls.siteUrl}${productPath.replace(':id', this.idOrSlugPipe.transform(product).toString())}`;
7681
7682
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
7682
- const image = this.mediaImageTransformerPipe.transform(product?.getImagePreview() ?? product.image, true);
7683
+ const image = this.mediaImageTransformerPipe.transform(product?.getImagePreview?.() ?? product.image, true);
7683
7684
  const description = product.properties?.description;
7684
7685
  const priceValidUntil = this.normalizePriceValidUntil(product.discount?.expiredAt);
7685
7686
  return {
7686
7687
  '@context': 'https://schema.org',
7687
7688
  '@type': 'Product',
7689
+ ...(id && { '@id': id }),
7688
7690
  name: product.name,
7689
7691
  ...(image && { image }),
7690
7692
  ...(description && { description }),
7691
7693
  mpn: product.code,
7692
7694
  url: productUrl,
7693
- offers: [
7694
- {
7695
- '@type': 'Offer',
7696
- priceCurrency: 'RUB',
7697
- ...(priceValidUntil && { priceValidUntil }),
7698
- price: product.costRub,
7699
- availability: this.getAvailability(product),
7700
- itemCondition: 'https://schema.org/NewCondition',
7701
- seller: {
7702
- '@type': 'Organization',
7703
- name: this.companyInfo.name,
7704
- },
7705
- url: productUrl,
7695
+ offers: {
7696
+ '@type': 'Offer',
7697
+ priceCurrency: 'RUB',
7698
+ ...(priceValidUntil && { priceValidUntil }),
7699
+ price: product.costRub,
7700
+ availability: this.getAvailability(product),
7701
+ itemCondition: 'https://schema.org/NewCondition',
7702
+ seller: {
7703
+ '@type': 'Organization',
7704
+ name: this.companyInfo.name,
7706
7705
  },
7707
- ],
7706
+ url: productUrl,
7707
+ },
7708
7708
  };
7709
7709
  }
7710
7710
  /**
@@ -7715,13 +7715,15 @@ class SchemaOrgFactory {
7715
7715
  * @param categoryPath Url путь к категориям товаров. В пути должен присутствовать шаблон ':id', обозначающий идентификатор категории для подстановки.
7716
7716
  * @param productPath Url путь к товару. В пути должен присутствовать шаблон ':id', обозначающий идентификатор товара для подстановки.
7717
7717
  * @param breadcrumbs Данные о хлебных крошках для категории.
7718
+ * @param id Необязательный идентификатор сущности для поля `@id` в JSON-LD.
7718
7719
  */
7719
- generateForCategoryItem(category, products, categoryPath, productPath, breadcrumbs) {
7720
+ generateForCategoryItem(category, products, categoryPath, productPath, breadcrumbs, id) {
7720
7721
  const description = category.seo?.description ?? category.properties?.description;
7721
7722
  const image = this.mediaImageTransformerPipe.transform(category.image, true);
7722
7723
  return {
7723
7724
  '@context': 'https://schema.org',
7724
7725
  '@type': 'CollectionPage',
7726
+ ...(id && { '@id': id }),
7725
7727
  name: category.seo?.title ?? category.name,
7726
7728
  ...(description && { description }),
7727
7729
  url: this.getCategoryCanonicalUrl(category, categoryPath),
@@ -7739,12 +7741,6 @@ class SchemaOrgFactory {
7739
7741
  name: category.name,
7740
7742
  ...(description && { description }),
7741
7743
  },
7742
- // Информация о сайте.
7743
- isPartOf: {
7744
- '@type': 'WebSite',
7745
- name: this.companyInfo.name,
7746
- url: this.urls.siteUrl,
7747
- },
7748
7744
  // Связанные страницы.
7749
7745
  relatedLink: [
7750
7746
  `${this.urls.siteUrl}${categoryPath.replace(':id', '')}`,
@@ -7785,6 +7781,223 @@ class SchemaOrgFactory {
7785
7781
  ],
7786
7782
  };
7787
7783
  }
7784
+ /**
7785
+ * Генерирует и возвращает схему данных OnlineStore на основе данных компании из окружения.
7786
+ */
7787
+ // eslint-disable-next-line sonarjs/function-return-type
7788
+ generateForOrganization() {
7789
+ const postalAddress = this.createPostalAddress(this.companyInfo.address);
7790
+ return {
7791
+ '@context': 'https://schema.org',
7792
+ '@type': 'OnlineStore',
7793
+ '@id': `${this.urls.siteUrl}#organization`,
7794
+ name: this.companyInfo.name,
7795
+ legalName: this.companyInfo.name,
7796
+ url: this.urls.siteUrl,
7797
+ logo: this.urls.logoUrl,
7798
+ image: this.urls.logoUrl,
7799
+ email: this.companyInfo.mail,
7800
+ telephone: this.companyInfo.phone,
7801
+ ...(postalAddress && { address: postalAddress }),
7802
+ legalAddress: this.createPostalAddress({ streetAddress: this.companyInfo.legalAddress }),
7803
+ // TODO: Перечислить все розничные магазины.
7804
+ // hasPOS: [],
7805
+ taxID: this.companyInfo.inn,
7806
+ identifier: {
7807
+ '@type': 'PropertyValue',
7808
+ propertyID: 'OGRN',
7809
+ value: this.companyInfo.ogrn,
7810
+ },
7811
+ contactPoint: this.createOrganizationContactPoints(),
7812
+ ...(this.companyInfo.warehouseAddress.length > 0 && {
7813
+ location: this.companyInfo.warehouseAddress.map((warehouseAddress) => ({
7814
+ '@type': 'Place',
7815
+ name: `${this.companyInfo.name} — склад самовывоза`,
7816
+ address: warehouseAddress,
7817
+ })),
7818
+ }),
7819
+ };
7820
+ }
7821
+ /**
7822
+ * Генерирует и возвращает схему данных для указанной новости.
7823
+ *
7824
+ * @param news Данные о новости.
7825
+ * @param newsPath Url путь к новости. В пути должен присутствовать шаблон ':id', обозначающий идентификатор новости для подстановки.
7826
+ * @param id Необязательный идентификатор сущности для поля `@id` в JSON-LD.
7827
+ */
7828
+ generateForNewsArticle(news, newsPath, id) {
7829
+ const newsUrl = `${this.urls.siteUrl}${newsPath.replace(':id', news.id.toString())}`;
7830
+ const image = this.mediaImageTransformerPipe.transform(news.image, true);
7831
+ const headline = news.seo?.title ?? news.subject;
7832
+ const description = news.seo?.description;
7833
+ const datePublished = this.normalizeSchemaDate(news.createdAt);
7834
+ const articleBody = news.text ? this.stripHtml(news.text) : undefined;
7835
+ return {
7836
+ '@context': 'https://schema.org',
7837
+ '@type': 'NewsArticle',
7838
+ ...(id && { '@id': id }),
7839
+ headline,
7840
+ ...(description && { description }),
7841
+ ...(image && { image }),
7842
+ ...(datePublished && { datePublished }),
7843
+ ...(articleBody && { articleBody }),
7844
+ url: newsUrl,
7845
+ mainEntityOfPage: newsUrl,
7846
+ author: {
7847
+ '@type': 'Organization',
7848
+ name: this.companyInfo.name,
7849
+ url: this.urls.siteUrl,
7850
+ },
7851
+ publisher: {
7852
+ '@type': 'Organization',
7853
+ name: this.companyInfo.name,
7854
+ logo: {
7855
+ '@type': 'ImageObject',
7856
+ url: this.urls.logoUrl,
7857
+ },
7858
+ },
7859
+ };
7860
+ }
7861
+ /**
7862
+ * Генерирует и возвращает схему данных FAQPage для страницы с вопросами и ответами.
7863
+ *
7864
+ * @param items Список вопросов и ответов.
7865
+ * @param pagePath Url путь к странице FAQ.
7866
+ * @param pageName Необязательное название страницы.
7867
+ * @param id Необязательный идентификатор сущности для поля `@id` в JSON-LD.
7868
+ */
7869
+ generateForFaqPage(items, pagePath, pageName, id) {
7870
+ const pageUrl = `${this.urls.siteUrl}${pagePath}`;
7871
+ return {
7872
+ '@context': 'https://schema.org',
7873
+ '@type': 'FAQPage',
7874
+ ...(id && { '@id': id }),
7875
+ ...(pageName && { name: pageName }),
7876
+ url: pageUrl,
7877
+ mainEntity: items.map((item) => ({
7878
+ '@type': 'Question',
7879
+ name: item.question,
7880
+ acceptedAnswer: {
7881
+ '@type': 'Answer',
7882
+ text: this.stripHtml(item.answer),
7883
+ },
7884
+ })),
7885
+ };
7886
+ }
7887
+ /**
7888
+ * Объединяет несколько JSON-LD сущностей в один документ с `@graph`.
7889
+ *
7890
+ * @param data Массив JSON-LD сущностей для объединения.
7891
+ */
7892
+ // eslint-disable-next-line class-methods-use-this,sonarjs/function-return-type
7893
+ merge(data) {
7894
+ return {
7895
+ '@context': 'https://schema.org',
7896
+ '@graph': data.map((item) => omit(item, '@context')),
7897
+ };
7898
+ }
7899
+ /**
7900
+ * Формирует PostalAddress из структурированного адреса компании.
7901
+ *
7902
+ * @param address Структурированный адрес компании.
7903
+ */
7904
+ // eslint-disable-next-line class-methods-use-this
7905
+ createPostalAddress(address) {
7906
+ const streetAddress = [address.streetAddress, address.extendedAddress].filter(Boolean).join(', ');
7907
+ if (!streetAddress && !address.locality && !address.region && !address.postalCode && !address.country) {
7908
+ return undefined;
7909
+ }
7910
+ return {
7911
+ '@type': 'PostalAddress',
7912
+ ...(streetAddress && { streetAddress }),
7913
+ ...(address.locality && { addressLocality: address.locality }),
7914
+ ...(address.region && { addressRegion: address.region }),
7915
+ ...(address.postalCode && { postalCode: address.postalCode }),
7916
+ ...(address.country && { addressCountry: address.country }),
7917
+ };
7918
+ }
7919
+ /**
7920
+ * Формирует список ContactPoint для Organization.
7921
+ */
7922
+ createOrganizationContactPoints() {
7923
+ const contactPoints = [
7924
+ {
7925
+ '@type': 'ContactPoint',
7926
+ contactType: 'customer service',
7927
+ telephone: this.companyInfo.phone,
7928
+ email: this.companyInfo.mail,
7929
+ areaServed: 'RU',
7930
+ availableLanguage: 'Russian',
7931
+ },
7932
+ ];
7933
+ if (this.companyInfo.secondaryPhone) {
7934
+ contactPoints.push({
7935
+ '@type': 'ContactPoint',
7936
+ contactType: 'customer service',
7937
+ telephone: this.companyInfo.secondaryPhone,
7938
+ areaServed: 'RU',
7939
+ availableLanguage: 'Russian',
7940
+ });
7941
+ }
7942
+ if (this.companyInfo.hr) {
7943
+ contactPoints.push({
7944
+ '@type': 'ContactPoint',
7945
+ contactType: 'HR',
7946
+ telephone: this.companyInfo.hr.phone,
7947
+ email: this.companyInfo.hr.mail,
7948
+ areaServed: 'RU',
7949
+ availableLanguage: 'Russian',
7950
+ });
7951
+ }
7952
+ return contactPoints;
7953
+ }
7954
+ /**
7955
+ * Удаляет HTML-разметку из текста.
7956
+ *
7957
+ * @param html Текст с HTML-разметкой.
7958
+ */
7959
+ // eslint-disable-next-line class-methods-use-this
7960
+ stripHtml(html) {
7961
+ const withoutTags = html
7962
+ .split('<')
7963
+ .map((part, index) => {
7964
+ if (index === 0) {
7965
+ return part;
7966
+ }
7967
+ const closeTagIndex = part.indexOf('>');
7968
+ return closeTagIndex === -1 ? part : ` ${part.slice(closeTagIndex + 1)}`;
7969
+ })
7970
+ .join('');
7971
+ return withoutTags
7972
+ .replaceAll(/\s+/g, ' ')
7973
+ .replaceAll(/ ([.,!?;:])/g, '$1')
7974
+ .trim();
7975
+ }
7976
+ /**
7977
+ * Нормализует дату в формат Schema.org (ISO 8601).
7978
+ *
7979
+ * @param dateValue Дата для нормализации.
7980
+ */
7981
+ // eslint-disable-next-line class-methods-use-this
7982
+ normalizeSchemaDate(dateValue) {
7983
+ if (!dateValue) {
7984
+ return undefined;
7985
+ }
7986
+ if (/^\d{4}-\d{2}-\d{2}/.test(dateValue)) {
7987
+ return dateValue;
7988
+ }
7989
+ const withTimeMatch = /^(\d{2})\.(\d{2})\.(\d{4}) (\d{2}):(\d{2})$/.exec(dateValue);
7990
+ if (withTimeMatch) {
7991
+ const [, day, month, year, hours, minutes] = withTimeMatch;
7992
+ return `${year}-${month}-${day}T${hours}:${minutes}:00`;
7993
+ }
7994
+ const dateOnlyMatch = /^(\d{2})\.(\d{2})\.(\d{4})$/.exec(dateValue);
7995
+ if (!dateOnlyMatch) {
7996
+ return undefined;
7997
+ }
7998
+ const [, day, month, year] = dateOnlyMatch;
7999
+ return `${year}-${month}-${day}`;
8000
+ }
7788
8001
  /**
7789
8002
  * Нормализует дату окончания цены в формат Schema.org (YYYY-MM-DD).
7790
8003
  *
@@ -7806,9 +8019,9 @@ class SchemaOrgFactory {
7806
8019
  // eslint-disable-next-line class-methods-use-this
7807
8020
  getAvailability(product) {
7808
8021
  if (product.onOrder) {
7809
- return 'PreOrder';
8022
+ return 'https://schema.org/PreOrder';
7810
8023
  }
7811
- return product.stockCount?.length ? 'InStock' : 'OutOfStock';
8024
+ return product.stockCount?.length ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock';
7812
8025
  }
7813
8026
  /**
7814
8027
  * Проверяет, является ли категория виртуальной.
@@ -7852,21 +8065,19 @@ class SchemaOrgFactory {
7852
8065
  url: productUrl,
7853
8066
  ...(image && { image }),
7854
8067
  ...(description && { description }),
7855
- offers: [
7856
- {
7857
- '@type': 'Offer',
7858
- priceCurrency: 'RUB',
7859
- ...(priceValidUntil && { priceValidUntil }),
7860
- price: product.costRub,
7861
- availability: this.getAvailability(product),
7862
- itemCondition: 'https://schema.org/NewCondition',
7863
- seller: {
7864
- '@type': 'Organization',
7865
- name: this.companyInfo.name,
7866
- },
7867
- url: productUrl,
8068
+ offers: {
8069
+ '@type': 'Offer',
8070
+ priceCurrency: 'RUB',
8071
+ ...(priceValidUntil && { priceValidUntil }),
8072
+ price: product.costRub,
8073
+ availability: this.getAvailability(product),
8074
+ itemCondition: 'https://schema.org/NewCondition',
8075
+ seller: {
8076
+ '@type': 'Organization',
8077
+ name: this.companyInfo.name,
7868
8078
  },
7869
- ],
8079
+ url: productUrl,
8080
+ },
7870
8081
  },
7871
8082
  };
7872
8083
  }
@@ -7888,14 +8099,21 @@ class SchemaOrgFactory {
7888
8099
  itemListOrder: 'https://schema.org/ItemListUnordered',
7889
8100
  itemListElement: [
7890
8101
  // Добавляем подкатегории в начало списка.
7891
- ...childCategories.slice(0, 5).map((subCategory, index) => ({
7892
- '@type': 'ListItem',
7893
- position: index + 1,
7894
- name: subCategory.name,
7895
- url: this.getCategoryCanonicalUrl(subCategory, categoryPath),
7896
- image: this.mediaImageTransformerPipe.transform(subCategory.image, true),
7897
- description: subCategory.seo?.description ?? subCategory.properties?.description,
7898
- })),
8102
+ ...childCategories.slice(0, 5).map((subCategory, index) => {
8103
+ const image = this.mediaImageTransformerPipe.transform(subCategory.image, true);
8104
+ const description = subCategory.seo?.description ?? subCategory.properties?.description;
8105
+ return {
8106
+ '@type': 'ListItem',
8107
+ position: index + 1,
8108
+ item: {
8109
+ '@type': 'CollectionPage',
8110
+ name: subCategory.name,
8111
+ url: this.getCategoryCanonicalUrl(subCategory, categoryPath),
8112
+ ...(image && { image }),
8113
+ ...(description && { description }),
8114
+ },
8115
+ };
8116
+ }),
7899
8117
  // Добавляем товары после подкатегорий.
7900
8118
  ...products.slice(0, 10).map((product, index) => this.createProductsListItem(product, childCategories.length + index + 1, productPath)),
7901
8119
  ],
@@ -7908,37 +8126,46 @@ class SchemaOrgFactory {
7908
8126
  * @param categoryPath Url путь к категориям товаров. В пути должен присутствовать шаблон ':id', обозначающий идентификатор категории для подстановки.
7909
8127
  */
7910
8128
  createCatalogBreadcrumbsList(breadcrumbs, categoryPath) {
8129
+ const catalogUrl = `${this.urls.siteUrl}${categoryPath.replace(':id', '')}`;
7911
8130
  const breadcrumbItems = [
7912
8131
  // Всегда добавляем главную страницу.
7913
- {
7914
- '@type': 'ListItem',
7915
- position: 1,
7916
- name: 'Главная',
7917
- item: this.urls.siteUrl,
7918
- },
8132
+ this.createBreadcrumbListItem(1, 'Главная', this.urls.siteUrl),
7919
8133
  // Добавляем каталог.
7920
- {
7921
- '@type': 'ListItem',
7922
- position: 2,
7923
- name: 'Каталог',
7924
- item: `${this.urls.siteUrl}/${categoryPath}`,
7925
- },
8134
+ this.createBreadcrumbListItem(2, 'Каталог', catalogUrl),
7926
8135
  ];
7927
8136
  // Добавляем существующие breadcrumbs с корректировкой позиций.
7928
8137
  breadcrumbs.forEach((item, index) => {
7929
8138
  const link = isArray(item.routerLink) ? item.routerLink.join('/') : item.routerLink;
7930
- breadcrumbItems.push({
7931
- '@type': 'ListItem',
7932
- position: index + 3, // Начинаем с позиции 3 (после Главная и Каталог).
7933
- name: item.label,
7934
- item: link ? `${this.urls.siteUrl}/${link}` : undefined,
7935
- });
8139
+ breadcrumbItems.push(this.createBreadcrumbListItem(index + 3, item.label, link ? `${this.urls.siteUrl}/${link}` : undefined));
7936
8140
  });
7937
8141
  return {
7938
8142
  '@type': 'BreadcrumbList',
8143
+ itemListOrder: 'https://schema.org/ItemListOrderAscending',
7939
8144
  itemListElement: breadcrumbItems,
7940
8145
  };
7941
8146
  }
8147
+ /**
8148
+ * Создаёт элемент BreadcrumbList в формате, рекомендованном Schema.org.
8149
+ *
8150
+ * @param position Позиция элемента в цепочке.
8151
+ * @param name Название элемента.
8152
+ * @param url URL элемента.
8153
+ */
8154
+ // eslint-disable-next-line class-methods-use-this
8155
+ createBreadcrumbListItem(position, name, url) {
8156
+ return {
8157
+ '@type': 'ListItem',
8158
+ position,
8159
+ ...(url
8160
+ ? {
8161
+ item: {
8162
+ '@id': url,
8163
+ name,
8164
+ },
8165
+ }
8166
+ : { name }),
8167
+ };
8168
+ }
7942
8169
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SchemaOrgFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
7943
8170
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SchemaOrgFactory, providedIn: 'root' }); }
7944
8171
  }
@@ -7994,6 +8221,10 @@ class ScSeoService {
7994
8221
  * Объект {@link Document}, предоставляющий доступ к DOM страницы.
7995
8222
  */
7996
8223
  this.document = inject(DOCUMENT);
8224
+ /**
8225
+ * Фабрика для создания данных Schema.org.
8226
+ */
8227
+ this.schemaOrgFactory = inject(SchemaOrgFactory);
7997
8228
  /**
7998
8229
  * Фабрика для создания экземпляров {@link Renderer2}.
7999
8230
  */
@@ -8009,8 +8240,9 @@ class ScSeoService {
8009
8240
  * @param resource Ресурс на основе которого необходимо установить мета-теги.
8010
8241
  * @param img Изображение. Если не пришло, то будет установлено значение по умолчанию.
8011
8242
  * @param robots Список robots-тегов для страницы.
8243
+ * @param schemaOrgData Данные Schema.org для встраивания на странице.
8012
8244
  */
8013
- setFromResource(resource, img = this.urls.logoUrl, robots = ['index', 'follow']) {
8245
+ setFromResource(resource, img, robots, schemaOrgData) {
8014
8246
  const updatedResource = {
8015
8247
  title: this.replaceTemplates(resource?.title ?? this.defaultSeo.title, resource?.instanceData ?? {}),
8016
8248
  description: this.replaceTemplates(resource?.description ?? this.defaultSeo.description, resource?.instanceData ?? {}),
@@ -8018,21 +8250,24 @@ class ScSeoService {
8018
8250
  meta: resource?.meta ?? [],
8019
8251
  };
8020
8252
  const url = `${this.urls.siteUrl}${this.router.url}`;
8021
- this.setMetaTags(updatedResource.title, updatedResource.description, updatedResource.keywords, updatedResource.meta, robots);
8022
- this.setOpenGraphMetaTags(updatedResource.title, updatedResource.description, url, img);
8253
+ this.setMetaTags(updatedResource.title, updatedResource.description, updatedResource.keywords, updatedResource.meta, robots ?? ['index', 'follow']);
8254
+ this.setOpenGraphMetaTags(updatedResource.title, updatedResource.description, url, img ?? this.urls.logoUrl);
8023
8255
  this.setCanonicalLink(url);
8256
+ // Устанавливаем Schema.org параметры.
8257
+ this.setSchemaOrgData(this.schemaOrgFactory.merge([this.schemaOrgFactory.generateForOrganization(), ...(schemaOrgData ? [schemaOrgData] : [])]));
8024
8258
  }
8025
8259
  /**
8026
8260
  * Устанавливает seo параметры со значением по умолчанию.
8027
8261
  *
8028
8262
  * @param title Заголовок страницы.
8029
8263
  * @param robots Список robots тегов для страницы.
8264
+ * @param schemaOrgData Данные Schema.org для встраивания на странице.
8030
8265
  */
8031
- setByDefault(title, robots = ['index', 'follow']) {
8266
+ setByDefault(title, robots, schemaOrgData) {
8032
8267
  this.setFromResource({
8033
8268
  title: `${title ?? this.defaultSeo.title} - ${this.companyInfo.name}`,
8034
8269
  description: title ? `${title}, ${this.defaultSeo.description}` : this.defaultSeo.description,
8035
- }, this.urls.logoUrl, robots);
8270
+ }, this.urls.logoUrl, robots ?? ['index', 'follow'], schemaOrgData);
8036
8271
  }
8037
8272
  /**
8038
8273
  * Устанавливает seo параметры со значением по умолчанию. Устанавливает значение "не индексировать" для поисковых роботов.
@@ -8063,9 +8298,7 @@ class ScSeoService {
8063
8298
  this.setOpenGraphMetaTags(title, description, url, this.mediaImageTransformerPipe.transform(item.image, true));
8064
8299
  this.setCanonicalLink(url);
8065
8300
  // Устанавливаем Schema.org параметры.
8066
- if (schemaOrgData) {
8067
- this.setSchemaOrgData(schemaOrgData);
8068
- }
8301
+ this.setSchemaOrgData(this.schemaOrgFactory.merge([this.schemaOrgFactory.generateForOrganization(), ...(schemaOrgData ? [schemaOrgData] : [])]));
8069
8302
  }
8070
8303
  /**
8071
8304
  * Заменяет шаблоны в тексте на значения из объекта.