itube-specs 0.0.719 → 0.0.721

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.
Files changed (47) hide show
  1. package/package.json +1 -1
  2. package/runtime/utils/check-device-width.ts +4 -0
  3. package/runtime/utils/cleaners/clean-category-card.ts +1 -0
  4. package/runtime/utils/cleaners/clean-category-info.ts +1 -0
  5. package/runtime/utils/cleaners/clean-channel-card.ts +1 -0
  6. package/runtime/utils/cleaners/clean-channel-info.ts +1 -0
  7. package/runtime/utils/cleaners/clean-mini-category-card.ts +1 -0
  8. package/runtime/utils/cleaners/clean-model-card.ts +1 -0
  9. package/runtime/utils/cleaners/clean-model-info.ts +1 -0
  10. package/runtime/utils/cleaners/clean-playlist-card.ts +1 -0
  11. package/runtime/utils/cleaners/clean-playlist-data.ts +1 -0
  12. package/runtime/utils/cleaners/clean-playlist-video.ts +1 -0
  13. package/runtime/utils/cleaners/clean-profile-data.ts +1 -0
  14. package/runtime/utils/cleaners/clean-user-playlists-card.ts +1 -0
  15. package/runtime/utils/cleaners/clean-video-card.ts +1 -0
  16. package/runtime/utils/cleaners/clean-video-data.ts +1 -0
  17. package/runtime/utils/compress-image.ts +6 -0
  18. package/runtime/utils/converters/convert-categories-to-chips.ts +1 -1
  19. package/runtime/utils/converters/convert-categories-to-footer.ts +1 -1
  20. package/runtime/utils/converters/convert-channel-to-round-card.ts +1 -0
  21. package/runtime/utils/converters/convert-date-to-timestamp.ts +1 -7
  22. package/runtime/utils/converters/convert-model-card-to-chips.ts +1 -1
  23. package/runtime/utils/converters/convert-model-to-round-card.ts +1 -0
  24. package/runtime/utils/converters/convert-query-categories.ts +1 -3
  25. package/runtime/utils/converters/convert-snake-keys-to-camel.ts +1 -0
  26. package/runtime/utils/converters/convert-string-array-to-chips.ts +1 -0
  27. package/runtime/utils/converters/convert-string.ts +7 -0
  28. package/runtime/utils/converters/group-categories-by-first-letter.ts +7 -1
  29. package/runtime/utils/converters/group-objects-by-first-letter.ts +6 -1
  30. package/runtime/utils/format-date.ts +1 -0
  31. package/runtime/utils/format-number.ts +2 -2
  32. package/runtime/utils/format-time-ago.ts +5 -0
  33. package/runtime/utils/format-time.ts +1 -0
  34. package/runtime/utils/get-duration.ts +2 -2
  35. package/runtime/utils/get-month.ts +4 -2
  36. package/runtime/utils/get-multiple-query.ts +7 -0
  37. package/runtime/utils/get-selected-query.ts +1 -0
  38. package/runtime/utils/is-mobile-device.ts +1 -0
  39. package/runtime/utils/normalize-url.ts +1 -0
  40. package/runtime/utils/on-backdrop-click.ts +1 -0
  41. package/runtime/utils/scroll-lock.ts +1 -0
  42. package/runtime/utils/validate-email.ts +1 -0
  43. package/runtime/utils/validate-password.ts +1 -0
  44. package/runtime/utils/validate-phone.ts +1 -0
  45. package/runtime/utils/validate-username.ts +1 -0
  46. package/runtime/utils/video-data-add-model-icon.ts +5 -0
  47. package/runtime/utils/vtt-helper.ts +7 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.719",
4
+ "version": "0.0.721",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {
@@ -13,6 +13,10 @@ function breakpoints(breakpoints: Record<CssBreakpoints, number>) {
13
13
  )
14
14
  }
15
15
 
16
+ /**
17
+ * Возвращает реактивные флаги isMobile и isTablet на основе переданных breakpoints.
18
+ * @param projectBreakpoints - набор брейкпоинтов проекта (xs, sm, md, lg, xl) в пикселях
19
+ */
16
20
  export const checkDeviceWidth = (projectBreakpoints: Record<CssBreakpoints, number>) => {
17
21
  const isMobile = breakpoints(projectBreakpoints).smaller('sm');
18
22
  const isTablet = breakpoints(projectBreakpoints).smaller('md');
@@ -1,6 +1,7 @@
1
1
  import type { IRawCategoryCard, ICategoryCard } from '../../../types';
2
2
  import { ThumbSize } from '../../enums/thumb-size';
3
3
 
4
+ /** Нормализует сырую карточку категории к типу ICategoryCard. */
4
5
  export const cleanCategoryCard = (card: IRawCategoryCard): ICategoryCard => ({
5
6
  name: card.name || '',
6
7
  title: card.title || '',
@@ -2,6 +2,7 @@ import type { IRawCategoryInfo, ICardInfo } from '../../../types';
2
2
  import { ThumbSize } from '../../enums/thumb-size';
3
3
  import { convertCategoriesToChips } from '../converters/convert-categories-to-chips';
4
4
 
5
+ /** Нормализует сырые данные страницы категории к типу ICardInfo. */
5
6
  export const cleanCategoryInfo = (card: IRawCategoryInfo): ICardInfo => ({
6
7
  guid: card.guid || '',
7
8
  title: card.title || '',
@@ -1,6 +1,7 @@
1
1
  import type { IChannelCard, IRawChannelCard } from '../../../types';
2
2
  import { ThumbSize } from '../../enums/thumb-size';
3
3
 
4
+ /** Нормализует сырую карточку канала к типу IChannelCard. */
4
5
  export const cleanChannelCard = (card: IRawChannelCard): IChannelCard => ({
5
6
  guid: card.guid || '',
6
7
  name: card.name || '',
@@ -1,6 +1,7 @@
1
1
  import type { IRawChannelInfo, ICardInfo } from '../../../types';
2
2
  import { ThumbSize } from '../../enums/thumb-size';
3
3
 
4
+ /** Нормализует сырые данные страницы канала к типу ICardInfo. */
4
5
  export const cleanChannelInfo = (card: IRawChannelInfo): ICardInfo => ({
5
6
  guid: card.guid || '',
6
7
  title: card.name || '',
@@ -1,5 +1,6 @@
1
1
  import type { IRawCategoryCard, IMiniCategoryCard } from '../../../types';
2
2
 
3
+ /** Нормализует сырую карточку категории к компактному типу IMiniCategoryCard. */
3
4
  export const cleanMiniCategoryCard = (card: IRawCategoryCard): IMiniCategoryCard => ({
4
5
  name: card.name || '',
5
6
  title: card.title || '',
@@ -4,6 +4,7 @@ import { ThumbSize } from '../../enums/thumb-size';
4
4
  const parameterNames = ['height_cm', 'weight_kg'];
5
5
  const age = (card: IRawModelCard) => card.parameters.find(item => item.name === 'age')?.values[0].title;
6
6
 
7
+ /** Нормализует сырую карточку модели к типу IModelCard, включая параметры (возраст, рост, вес) и страну. */
7
8
  export const cleanModelCard = (card: IRawModelCard): IModelCard => ({
8
9
  title: card.title || '',
9
10
  videosCount: card.videos_count || 0,
@@ -1,6 +1,7 @@
1
1
  import type { IRawModelInfo, ICardInfo } from '../../../types';
2
2
  import { ThumbSize } from '../../enums/thumb-size';
3
3
 
4
+ /** Нормализует сырые данные страницы модели к типу ICardInfo. */
4
5
  export const cleanModelInfo = (card: IRawModelInfo): ICardInfo => ({
5
6
  title: card.title || '',
6
7
  description: card.description || '',
@@ -1,6 +1,7 @@
1
1
  import type { IRawPlaylistCard, IPlaylistCard } from '../../../types';
2
2
  import { ThumbSize } from '../../enums/thumb-size';
3
3
 
4
+ /** Нормализует сырую карточку плейлиста к типу IPlaylistCard. */
4
5
  export const cleanPlaylistCard = (card: IRawPlaylistCard): IPlaylistCard => ({
5
6
  created: card.created || 0,
6
7
  id: card.id || '',
@@ -1,5 +1,6 @@
1
1
  import type { IRawPlaylistData, IPlaylistData } from '../../../types';
2
2
 
3
+ /** Нормализует сырые данные плейлиста к типу IPlaylistData. */
3
4
  export const cleanPlaylistData = (card: IRawPlaylistData): IPlaylistData => ({
4
5
  updated: card.updated || 0,
5
6
  id: card.id || '',
@@ -1,6 +1,7 @@
1
1
  import type { IRawPlaylistVideo, IVideoCard } from '../../../types';
2
2
  import { ThumbSize } from '../../../runtime';
3
3
 
4
+ /** Нормализует сырое видео из плейлиста к типу IVideoCard. */
4
5
  export const cleanPlaylistVideo = (card: IRawPlaylistVideo): IVideoCard => ({
5
6
  guid: card.guid || '',
6
7
  duration: card.duration || 0,
@@ -1,5 +1,6 @@
1
1
  import type { IRawProfileData, IProfileData } from '../../../types';
2
2
 
3
+ /** Нормализует сырые данные профиля пользователя к типу IProfileData. */
3
4
  export const cleanProfileData = (data: IRawProfileData): IProfileData => ({
4
5
  username: data.username || '',
5
6
  email: data.email || '',
@@ -1,6 +1,7 @@
1
1
  import type { IRawPlaylistsUser, IPlaylistCard } from '../../../types';
2
2
  import { ThumbSize } from '../../enums/thumb-size';
3
3
 
4
+ /** Нормализует сырую карточку плейлиста пользователя к типу IPlaylistCard. */
4
5
  export const cleanUserPlaylistCard = (card: IRawPlaylistsUser): IPlaylistCard => ({
5
6
  created: card.created || 0,
6
7
  id: card.id || '',
@@ -1,6 +1,7 @@
1
1
  import type { IRawVideoCard, IVideoCard } from '../../../types';
2
2
  import { ThumbSize } from '../../enums/thumb-size';
3
3
 
4
+ /** Нормализует сырую карточку видео к типу IVideoCard. */
4
5
  export const cleanVideoCard = (card: IRawVideoCard): IVideoCard => ({
5
6
  guid: card.guid || '',
6
7
  quality: card.quality || '',
@@ -1,5 +1,6 @@
1
1
  import type { IRawVideoData, IVideoData } from '../../../types';
2
2
 
3
+ /** Нормализует сырые данные видео к типу IVideoData. */
3
4
  export const cleanVideoData = (data: IRawVideoData): IVideoData => ({
4
5
  guid: data.guid || '',
5
6
  md5: data.md5 || '',
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Сжимает изображение до maxSize px по наибольшей стороне и возвращает Blob в формате JPEG.
3
+ * @param blob - исходное изображение
4
+ * @param maxSize - максимальный размер стороны в px (по умолчанию 512)
5
+ * @param quality - качество JPEG от 0 до 1 (по умолчанию 0.8)
6
+ */
1
7
  export const compressImage = (blob: Blob, maxSize = 512, quality = 0.8): Promise<Blob> => {
2
8
  return new Promise((resolve, reject) => {
3
9
  const img = new Image();
@@ -1,6 +1,6 @@
1
1
  import type { IRawCategoryCard, IChipsItem } from '../../../types';
2
2
 
3
- /** Конвертирует обьекты категорий в чипсы */
3
+ /** Конвертирует массив категорий в чипсы IChipsItem для фильтров. */
4
4
  export function convertCategoriesToChips(
5
5
  items: Array<IRawCategoryCard>,
6
6
  prefix: string
@@ -1,6 +1,6 @@
1
1
  import type { IRawCategoryCard, ILinkItem } from '../../../types';
2
2
 
3
- /** Конвертирует обьекты категорий в футер категории */
3
+ /** Конвертирует массив категорий в ссылки ILinkItem для футера. */
4
4
  export function convertCategoriesToFooter(
5
5
  items: Array<IRawCategoryCard>,
6
6
  ): Array<ILinkItem> {
@@ -1,6 +1,7 @@
1
1
  import type { IChannelCard, IRoundCard } from '../../../types';
2
2
  import { convertString } from './convert-string';
3
3
 
4
+ /** Конвертирует карточку канала к формату IRoundCard для отображения в круглой карточке. */
4
5
  export function convertChannelToRoundCard(channel: IChannelCard): IRoundCard {
5
6
  return {
6
7
  title: channel.name,
@@ -1,6 +1,4 @@
1
- /**
2
- * Преобразует строку вида "дд.мм.гггг" в Unix timestamp (в секундах)
3
- */
1
+ /** Возвращает функции для конвертации дат: toUnix ("yyyy-MM-dd" → timestamp) и fromUnix (timestamp → "yyyy-MM-dd"). */
4
2
  export const convertDateToTimestamp = () => {
5
3
  const toUnix = (dateStr: string): number | null => {
6
4
  const [year, month, day] = dateStr.split('-').map(Number);
@@ -16,10 +14,6 @@ export const convertDateToTimestamp = () => {
16
14
  return Math.floor(date.getTime() / 1000);
17
15
  };
18
16
 
19
- /**
20
- * Преобразует Unix timestamp в строку "yyyy-MM-dd"
21
- * (то, что понимает input[type="date"])
22
- */
23
17
  const fromUnix = (timestamp: number): string => {
24
18
  const date = new Date(timestamp * 1000);
25
19
 
@@ -1,7 +1,7 @@
1
1
  import type { IRawModelCard, IChipsItem } from '../../../types';
2
2
  import { ThumbSize } from '../../enums/thumb-size';
3
3
 
4
- /** Конвертация карточки модели в chips */
4
+ /** Конвертирует массив карточек моделей в чипсы IChipsItem с иконкой превью. */
5
5
  export function convertModelCardToChips(
6
6
  items: Array<IRawModelCard>,
7
7
  ): Array<IChipsItem> {
@@ -1,6 +1,7 @@
1
1
  import type { IModelCard, IRoundCard } from '../../../types';
2
2
  import { convertString } from './convert-string';
3
3
 
4
+ /** Конвертирует карточку модели к формату IRoundCard для отображения в круглой карточке. */
4
5
  export function convertModelToRoundCard(model: IModelCard): IRoundCard {
5
6
  return {
6
7
  title: model.title,
@@ -1,7 +1,5 @@
1
1
  import type { RouteLocationNormalizedLoaded } from 'vue-router';
2
- /**
3
- * конвертирует список категорий из фильтра страниц с видео роликами из query в одну строку, все слова с заглавной буквы
4
- */
2
+ /** Конвертирует категории из query-параметра в читаемую строку с заглавными буквами (до 3 категорий). */
5
3
  export function convertQueryCategories(route: RouteLocationNormalizedLoaded) {
6
4
  const MAX_CATEGORIES = 3;
7
5
  return String(route.query[ 'categories' ])?.split(',').map(item => item.split('_')[ 1 ]).map(item => item?.charAt(0).toUpperCase() + item?.slice(1)).slice(0, MAX_CATEGORIES).join(', ');
@@ -2,6 +2,7 @@ function snakeToCamel(str: string): string {
2
2
  return str.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
3
3
  }
4
4
 
5
+ /** Рекурсивно преобразует все ключи объекта из snake_case в camelCase. */
5
6
  export function convertSnakeKeysToCamel<T = any>(input: any): T {
6
7
  if (Array.isArray(input)) {
7
8
  return input.map(item => convertSnakeKeysToCamel(item)) as T;
@@ -1,5 +1,6 @@
1
1
  import type { IChipsItem } from '../../../types';
2
2
 
3
+ /** Конвертирует массив строк в чипсы IChipsItem; строку '#' заменяет на 'post'. */
3
4
  export function convertStringArrayToChips(array: string[], prefix: string, resetPath: string): IChipsItem[] {
4
5
  return array.map((item) => ({
5
6
  title: item.toLowerCase() === '#' ? 'post' : item,
@@ -1,6 +1,8 @@
1
1
  import type { IChipsItem } from '../../../types';
2
2
 
3
+ /** Утилиты для преобразования строк: slug, snake_case, kebab-case, chips, capitalize. */
3
4
  export const convertString = () => {
5
+ /** Преобразует строку в URL-slug: пробелы → дефисы, _ → ~, исходные дефисы сохраняются. */
4
6
  const toSlug = (input: string): string => {
5
7
  return input
6
8
  .toLowerCase()
@@ -10,6 +12,7 @@ export const convertString = () => {
10
12
  .replace(/\u0000/g, '_');
11
13
  };
12
14
 
15
+ /** Восстанавливает исходную строку из slug. */
13
16
  const fromSlug = (slug: string): string => {
14
17
  return slug
15
18
  .replace(/_/g, '\u0000') // временно убираем "_" (разделители)
@@ -18,6 +21,7 @@ export const convertString = () => {
18
21
  .replace(/~/g, '_'); // в конце восстанавливаем "_"
19
22
  };
20
23
 
24
+ /** Преобразует строку в snake_case. */
21
25
  const toSnakeCase = (slug: string): string => {
22
26
  return slug
23
27
  .replace(/([a-z])([A-Z])/g, '$1_$2')
@@ -26,6 +30,7 @@ export const convertString = () => {
26
30
  .toLowerCase();
27
31
  };
28
32
 
33
+ /** Преобразует строку в kebab-case. */
29
34
  const toKebabCase = (str: string): string => {
30
35
  return str
31
36
  .replace(/([a-z])([A-Z])/g, '$1-$2')
@@ -35,6 +40,7 @@ export const convertString = () => {
35
40
  .toLowerCase();
36
41
  };
37
42
 
43
+ /** Создаёт объект IChipsItem из строки и префикса. */
38
44
  const toChips = (string: string, prefix: string): IChipsItem => {
39
45
  return {
40
46
  title: string,
@@ -43,6 +49,7 @@ export const convertString = () => {
43
49
  }
44
50
  }
45
51
 
52
+ /** Делает первую букву каждого слова заглавной. */
46
53
  const toCapitalize = (string: string): string => {
47
54
  return string.split(' ').map(i => i.charAt(0).toUpperCase() + i.slice(1)).join(' ');
48
55
  }
@@ -1,6 +1,12 @@
1
1
  import type { IRawCategoryCard, ICategoryCard } from '../../../types';
2
2
 
3
- /** Метод для группировки мини категорий по первой букве свойства */
3
+ /**
4
+ * Группирует категории по первой букве указанного свойства, сортируя по локали; нелитерные значения — под ключом nonLetterKey.
5
+ * @param items - массив категорий
6
+ * @param prop - свойство для группировки (например 'title')
7
+ * @param locale - локаль для сортировки
8
+ * @param nonLetterKey - ключ для нелитерных значений (по умолчанию 'POST')
9
+ */
4
10
  export function groupCategoriesByFirstLetter(
5
11
  items: Array<IRawCategoryCard>,
6
12
  prop: string,
@@ -1,4 +1,9 @@
1
- /** Метод для группировки категорий по первой букве свойства */
1
+ /**
2
+ * Группирует объекты по первой букве указанного свойства; нелитерные значения — под ключом nonLetterKey.
3
+ * @param items - массив объектов
4
+ * @param prop - свойство для группировки
5
+ * @param nonLetterKey - ключ для нелитерных значений (по умолчанию 'POST')
6
+ */
2
7
  export function groupObjectsByFirstLetter<T>(
3
8
  items: Array<T>,
4
9
  prop: string,
@@ -1,3 +1,4 @@
1
+ /** Форматирует Unix timestamp (в секундах) в строку вида ДД.ММ.ГГГГ. */
1
2
  export function formatDate(seconds: number): string {
2
3
  const date = new Date(1000 * seconds);
3
4
 
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Форматирует число в короткий формат 10400 => 10.4K
3
- * @param {number} number - число
2
+ * Форматирует число в короткий формат: 10400 10.4K.
3
+ * @param number - исходное число
4
4
  */
5
5
 
6
6
  export function formatNumber (number: number) {
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Форматирует Unix timestamp (в секундах) в относительную строку: «сегодня», «вчера», «3 дня назад» и т.д.
3
+ * @param date - Unix timestamp в секундах
4
+ * @param t - функция перевода (i18n)
5
+ */
1
6
  export function formatTimeAgo(date: number, t) {
2
7
  const pastDate = new Date(date * 1000);
3
8
  const now = new Date();
@@ -1,3 +1,4 @@
1
+ /** Форматирует секунды в строку мм:сс, или чч:мм:сс если есть часы. */
1
2
  export function formatTime(seconds: number): string {
2
3
  const h = Math.floor(seconds / 3600);
3
4
  const m = Math.floor((seconds % 3600) / 60);
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Возвращает продолжительность по переданным секундам в формате hh:mm:ss
3
- * @param {seconds} number - число секунды
2
+ * Возвращает продолжительность по переданным секундам в формате [чч:]мм:сс.
3
+ * @param seconds - количество секунд
4
4
  */
5
5
  export function getDuration (seconds: number) {
6
6
  const date = new Date(0);
@@ -1,6 +1,8 @@
1
1
  /**
2
- * возвращает название месяца по цифре
3
- */
2
+ * Возвращает локализованное название месяца по его номеру (0-based).
3
+ * @param t - функция перевода (i18n)
4
+ * @param number - номер месяца от 0 (январь) до 11 (декабрь)
5
+ */
4
6
  export function getMonth(t: (key: string) => string, number?: number) {
5
7
  const months = [
6
8
  'january',
@@ -2,6 +2,13 @@ import type { RouteLocationNormalizedLoaded } from 'vue-router';
2
2
  import type { IChipsItem, ISelectItem } from '../../types';
3
3
  import { getSelectedQuery } from '../utils/get-selected-query';
4
4
 
5
+ /**
6
+ * Возвращает query-объект для диапазонного фильтра (min/max) на основе текущего маршрута.
7
+ * @param route - текущий маршрут Vue Router
8
+ * @param items - список элементов фильтра
9
+ * @param minKey - ключ минимального значения в query
10
+ * @param maxKey - ключ максимального значения в query
11
+ */
5
12
  export function getMultipleQuery (
6
13
  route: RouteLocationNormalizedLoaded,
7
14
  items: ISelectItem[] | IChipsItem[],
@@ -1,6 +1,7 @@
1
1
  import type { RouteLocation } from 'vue-router';
2
2
  import type { IChipsItem, ISelectItem } from '../../types';
3
3
 
4
+ /** Возвращает значение query выбранного элемента из items, совпадающего с текущим маршрутом. */
4
5
  export function getSelectedQuery(route: RouteLocation, items: IChipsItem[] | ISelectItem[]) {
5
6
  return items.find(item => item.value === route.query[item.key || ''])?.query;
6
7
  }
@@ -1,3 +1,4 @@
1
+ /** Возвращает true если userAgent соответствует мобильному устройству. */
1
2
  export const isMobileDevice = (userAgent: string) => {
2
3
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(userAgent)
3
4
  }
@@ -1,3 +1,4 @@
1
+ /** Нормализует URL: убирает page=1, sort=trending, пустые query, приводит к нижнему регистру, заменяет пробелы на дефисы. */
1
2
  export function normalizeUrl(to: { path: string; query: Record<string, any> }) {
2
3
  let path = to.path
3
4
  let query = { ...to.query }
@@ -1,3 +1,4 @@
1
+ /** Вызывает callback если клик пришёл непосредственно по элементу <dialog> (backdrop), а не по его содержимому. */
1
2
  export function onBackdropClick(target: HTMLDialogElement, callback: () => void) {
2
3
  if (target?.nodeName === 'DIALOG') {
3
4
  callback();
@@ -1,3 +1,4 @@
1
+ /** Возвращает функции lockScroll/unlockScroll для блокировки прокрутки страницы через overflow: hidden. */
1
2
  const lockScroll = () => {
2
3
  document.body.style.overflow = 'hidden';
3
4
  };
@@ -1,3 +1,4 @@
1
+ /** Возвращает true если строка является валидным email-адресом. */
1
2
  export function validateEmail(value: string) {
2
3
  const re = /^[\w&*+-]+(?:\.[\w&*+-]+)*@(?:[\da-z-]+\.)+[a-z]{2,}$/gi;
3
4
  return value?.length !== 0 && re.test(String(value).toLowerCase());
@@ -1,3 +1,4 @@
1
+ /** Возвращает true если пароль длиннее 4 символов. */
1
2
  export function validatePassword(value: string) {
2
3
  return value.length > 4;
3
4
  };
@@ -1,3 +1,4 @@
1
+ /** Возвращает true если строка является валидным номером телефона (7–20 цифр, опциональные +, пробелы, скобки и дефисы). */
1
2
  export function validatePhone (value: string) {
2
3
  const re = /^\+?[0-9\s\-().]{7,20}$/;
3
4
  return value?.length !== 0 && re.test(String(value).trim());
@@ -1,3 +1,4 @@
1
+ /** Возвращает true если имя пользователя состоит из 2–20 символов (латиница, цифры, _ и -). */
1
2
  export function validateUsername (value: string) {
2
3
  const re = /^[a-zA-Z0-9_-]{2,20}$/;
3
4
  return value.length !== 0 && re.test(String(value).toLowerCase());
@@ -1,5 +1,10 @@
1
1
  import type { IRawModelCard, IRawVideoData } from '../../types';
2
2
 
3
+ /**
4
+ * Добавляет поле icon из modelsData в каждую модель videoData.models по совпадению guid.
5
+ * @param videoData - сырые данные видео
6
+ * @param modelsData - массив карточек моделей с primary_image_url
7
+ */
3
8
  export function videoDataAddModelIcon(videoData: IRawVideoData, modelsData: Array<IRawModelCard>): IRawVideoData {
4
9
  const transformedData = { ...videoData };
5
10
 
@@ -4,6 +4,7 @@ export interface IVttItem {
4
4
  coords: { x: number; y: number; w: number; h: number };
5
5
  }
6
6
 
7
+ /** Загружает и парсит VTT-файл с тайм-кодами и координатами спрайтов превью видео. */
7
8
  export class VttHelper {
8
9
  private readonly vttUrl: string;
9
10
  public hasInited: boolean;
@@ -15,6 +16,7 @@ export class VttHelper {
15
16
  this.vttData = null;
16
17
  }
17
18
 
19
+ /** Загружает и парсит VTT-файл по url из конструктора. Устанавливает hasInited = true после успешной загрузки. */
18
20
  async init(): Promise<void> {
19
21
  const vttContent: Response = await fetch(this.vttUrl);
20
22
 
@@ -71,6 +73,11 @@ export class VttHelper {
71
73
  return hh * 3600 + mm * 60 + ss;
72
74
  }
73
75
 
76
+ /**
77
+ * Возвращает координаты спрайта превью для указанного времени воспроизведения.
78
+ * @param time - время в секундах
79
+ * @param vttData - данные VTT (по умолчанию загруженные через init)
80
+ */
74
81
  getCoordsByTime(time: number, vttData: Array<IVttItem> | null = this.vttData):
75
82
  { x: number; y: number; w: number; h: number } | string {
76
83
  if (!this.hasInited || !vttData) {