itube-specs 0.0.847 → 0.0.849

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.
@@ -161,6 +161,16 @@ function isWarning(value: string) {
161
161
  .info-grid__item.--link .info-grid__item-value {
162
162
  background-color: $info-grid-item-value-bg--link;
163
163
  color: $info-grid-item-value--link;
164
+
165
+ @include from-br(sm) {
166
+ transition: var(--transition) background-color;
167
+ }
168
+ }
169
+
170
+ .info-grid__item.--link:is(:hover, :focus-visible) .info-grid__item-value {
171
+ @include from-br(sm) {
172
+ background-color: $info-grid-item-value-link-bg--hover;
173
+ }
164
174
  }
165
175
 
166
176
  .info-grid__item:not(.--link) .info-grid__item-value {
@@ -1,13 +1,29 @@
1
+ /** Минимум элементов в листинге, при котором страницу ещё имеет смысл индексировать. */
2
+ export const MIN_INDEXABLE_ITEMS = 5;
3
+
1
4
  /**
2
5
  * Помечает страницу как noindex для поисковиков (ссылки при этом проходятся — follow).
3
- * Для приватных/служебных страниц и результатов внутреннего поиска.
6
+ * Для приватных/служебных страниц, результатов внутреннего поиска и «тонких» листингов.
7
+ * Условие реактивное: пока оно false, тег не выпускается и hreflang-кластер остаётся.
8
+ */
9
+ export function useNoindex(when: MaybeRefOrGetter<boolean> = true) {
10
+ const isNoindex = computed(() => toValue(when));
11
+
12
+ useHead(() => ({
13
+ meta: isNoindex.value
14
+ ? [{ name: 'robots', content: 'noindex, follow' }]
15
+ : [],
16
+ }));
17
+
18
+ useSetSeoOverride(() => ({ noindex: isNoindex.value }));
19
+ }
20
+
21
+ /**
22
+ * Закрывает от индексации «тонкий» листинг — страницу, где основных элементов
23
+ * (роликов, а на листинге моделей — моделей) меньше порога. Считается по фактически
24
+ * выданным на этом URL элементам, поэтому хвост пагинации и пустые выборки
25
+ * по фильтрам тоже уходят в noindex.
4
26
  */
5
- export function useNoindex() {
6
- useHead({
7
- meta: [
8
- { name: 'robots', content: 'noindex, follow' },
9
- ],
10
- });
11
-
12
- useSetSeoOverride(() => ({ noindex: true }));
27
+ export function useNoindexThinListing(count: MaybeRefOrGetter<number | undefined>) {
28
+ useNoindex(() => (toValue(count) ?? 0) < MIN_INDEXABLE_ITEMS);
13
29
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.847",
4
+ "version": "0.0.849",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {
@@ -127,8 +127,6 @@ const featureFlags = useRuntimeConfig().public.featureFlags;
127
127
 
128
128
  const slug = useSlug();
129
129
 
130
- useNoindex();
131
-
132
130
  const [
133
131
  { data: modelsData },
134
132
  { data: categoriesData },
@@ -140,6 +138,8 @@ const [
140
138
  useFetchVideosSearchByNiche(VideosApiService.getSearchByNiche),
141
139
  useFetchRelatedSearch(SearchApiService.getPhrases),
142
140
  ]);
141
+
142
+ useNoindexThinListing(() => videosData.value?.items?.length);
143
143
  const { t } = useI18n();
144
144
  const { generateLink } = useGenerateLink();
145
145
 
@@ -26,8 +26,6 @@ import { sortModels } from '../../../lib';
26
26
 
27
27
  const slug = useSlug();
28
28
 
29
- useNoindex();
30
-
31
29
  const { t } = useI18n();
32
30
  const pagePureName = useGetPureRouteName();
33
31
 
@@ -37,6 +35,8 @@ const [
37
35
  useFetchModelsByPhrases(ModelsApiService.getModelsSearchFiltered(slug.value)),
38
36
  ]);
39
37
 
38
+ useNoindexThinListing(() => modelsData.value?.items?.length);
39
+
40
40
  const metaTitle = computed(() => convertString().toCapitalize(slug.value));
41
41
 
42
42
  const { meta, h1 } = useMeta(t, pagePureName, useAppConfig().brandName, sortModels, metaTitle);
@@ -28,8 +28,6 @@ import { sortItemsDefault } from '../../../lib';
28
28
 
29
29
  const slug = useSlug();
30
30
 
31
- useNoindex();
32
-
33
31
  const { t } = useI18n();
34
32
 
35
33
  const [
@@ -38,6 +36,8 @@ const [
38
36
  useFetchVideos(VideosApiService.getSearchByNicheFiltered(slug.value)),
39
37
  ]);
40
38
 
39
+ useNoindexThinListing(() => videosData.value?.items?.length);
40
+
41
41
  const pagePureName = useGetPureRouteName();
42
42
  const metaTitle = computed(() => convertString().toCapitalize(slug.value));
43
43
 
@@ -42,6 +42,8 @@ const [
42
42
  useFetchModelsByTag(ModelsApiService.getListByTag, 100),
43
43
  ]);
44
44
 
45
+ useNoindexThinListing(() => data.value?.items?.length);
46
+
45
47
  const route = useRoute();
46
48
  const slug = computed(() => String(route.params[ 'tag' ]));
47
49