itube-specs 0.0.1029 → 0.0.1031

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/SITE_UPDATES.md CHANGED
@@ -11,6 +11,14 @@
11
11
  коммиты до бампа); `npm run patch` сам проставит ей номер версии. Формат пункта: что сделать и где,
12
12
  кому именно (всем / сайтам с N), что будет, если не сделать.
13
13
 
14
+ ## 0.0.1030 — 2026-10-13
15
+
16
+ - **Всем сайтам с плеером:** поднять `itube-modern-player` до `^0.15.0` (`npm install itube-modern-player@^0.15.0`).
17
+ Слой теперь отдаёт постеру ролика `fallback` — jpeg из `thumbUrls.jpeg` (его сохраняет `cleanVideoData`), и плеер
18
+ 0.15 рисует webp-постер через `<picture>` с jpeg для браузеров без webp. Не поднять — ничего не сломается, поле
19
+ молча игнорируется, фолбэка просто не будет. Сайтам с форком `components/player/core.vue` (hdsex-remaster,
20
+ videosection-redesign) — добавить `fallback` в постер, образец — коммит videosection-redesign.
21
+
14
22
  ## 0.0.1029 — 2026-10-13
15
23
 
16
24
  - **Сайтам с рекламными ссылками над контентом на мобиле (videosection-redesign):** новая вторая навигация —
@@ -1041,8 +1041,8 @@ $layout-second-nav-link-text: $color-white;
1041
1041
  $layout-second-nav-dot-bg: $color-green-400;
1042
1042
 
1043
1043
  // ─── Native card ───
1044
- $native-card-bg: $color-slate-800;
1045
- $native-card-primary: $color-gray-400;
1044
+ $native-card-bg: $color-white;
1045
+ $native-card-primary: $color-gray-900;
1046
1046
  $native-card-secondary: $color-gray-500;
1047
1047
 
1048
1048
  // ─── Adv: плашка «Реклама» поверх креатива ───
@@ -172,6 +172,8 @@ const currentSource = computed<VideoSource>(() => {
172
172
  const big = props.data.thumbUrls?.webp?.[ThumbSize.Big];
173
173
  const medium = props.data.thumbUrls?.webp?.[ThumbSize.Medium];
174
174
  const src = big || medium;
175
+ // jpeg — для браузеров без webp: плеер (0.15+) рисует <picture> с ним в <img>
176
+ const fallback = props.data.thumbUrls?.jpeg?.[ThumbSize.Big] || props.data.thumbUrls?.jpeg?.[ThumbSize.Medium];
175
177
 
176
178
  return {
177
179
  src: props.data.videoUrl,
@@ -181,6 +183,7 @@ const currentSource = computed<VideoSource>(() => {
181
183
  poster: src
182
184
  ? {
183
185
  src,
186
+ fallback,
184
187
  srcset: big && medium ? `${medium} 480w, ${big} 1280w` : undefined,
185
188
  sizes: big && medium ? '100vw' : undefined,
186
189
  width: 1280,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.1029",
4
+ "version": "0.0.1031",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {
@@ -19,7 +19,7 @@ describe('cleanVideoData', () => {
19
19
  channel: { name: 'Channel', avatar_url: 'https://img.com/ch.jpg' },
20
20
  url: '/video/1',
21
21
  preview_url: 'https://img.com/preview.mp4',
22
- thumb_urls: { webp: { '320x180': 'small' } },
22
+ thumb_urls: { webp: { '320x180': 'small' }, jpeg: { '320x180': 'small-jpeg' } },
23
23
  vtt_url: '/vtt',
24
24
  vtt_sprite_url: '/sprite',
25
25
  created: 1700000000,
@@ -32,7 +32,7 @@ describe('cleanVideoData', () => {
32
32
  const result = cleanVideoData(raw as any);
33
33
  expect(result.guid).toBe('v-1');
34
34
  expect(result.channelName).toBe('Channel');
35
- expect(result.thumbUrls).toEqual({ webp: { '320x180': 'small' } });
35
+ expect(result.thumbUrls).toEqual({ webp: { '320x180': 'small' }, jpeg: { '320x180': 'small-jpeg' } });
36
36
  expect(result.vttUrl).toBe('/vtt');
37
37
  expect(result.videoUrl).toBe('/stream');
38
38
  expect(result.isDeleted).toBe(false);
@@ -150,6 +150,11 @@ describe('cleanVideoData', () => {
150
150
  ]);
151
151
  });
152
152
 
153
+ it('тумбы без jpeg — без ключа jpeg', () => {
154
+ const result = cleanVideoData({ thumb_urls: { webp: { '320x180': 'small' } } } as any);
155
+ expect(result.thumbUrls).toEqual({ webp: { '320x180': 'small' } });
156
+ });
157
+
153
158
  it('пустые данные → дефолты', () => {
154
159
  const result = cleanVideoData({} as any);
155
160
  expect(result.guid).toBe('');
@@ -84,6 +84,7 @@ export const cleanVideoData = (data: IRawVideoData, theme?: string): IVideoData
84
84
  previewUrl: data.preview_url || '',
85
85
  thumbUrls: data.thumb_urls ? {
86
86
  webp: data.thumb_urls.webp,
87
+ ...(data.thumb_urls.jpeg ? { jpeg: data.thumb_urls.jpeg } : {}),
87
88
  } : undefined,
88
89
  vttUrl: data.vtt_url || '',
89
90
  vttSpriteUrl: data.vtt_sprite_url || '',
@@ -1,6 +1,7 @@
1
1
  import type { ThumbSize } from '../runtime/constants/thumb-size';
2
2
 
3
- /** Очищенные тумбы — только webp */
3
+ /** Очищенные тумбы: webp; jpeg — только у ролика целиком, фолбэк постера плеера. */
4
4
  export interface IThumbUrls {
5
5
  webp: Partial<Record<ThumbSize, string>>;
6
+ jpeg?: Partial<Record<ThumbSize, string>>;
6
7
  }