From 4730a30c3d6ef4732989ce8e5f6f96b065a6f5c4 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Thu, 20 Feb 2025 12:51:59 -0500 Subject: [PATCH] Fix lint errors --- .../components/library/GenresItemsContainer.tsx | 1 + src/apps/experimental/components/library/UpcomingView.tsx | 1 + src/apps/stable/features/playback/types/callbacks.ts | 1 + src/components/MarkdownBox.tsx | 1 + src/components/cardbuilder/Card/CardText.tsx | 1 + src/components/cardbuilder/Card/cardHelper.ts | 4 ++-- src/components/cardbuilder/cardBuilder.js | 2 ++ src/components/dashboard/users/AccessScheduleList.tsx | 2 +- src/components/favoriteitems.js | 7 ++++--- src/components/fetchhelper.js | 1 + src/components/focusManager.js | 1 + src/components/htmlMediaHelper.js | 3 ++- src/components/listview/listview.js | 1 + src/components/mediainfo/MediaInfoItem.tsx | 1 + src/components/playback/playbackmanager.js | 2 ++ src/components/playback/skipsegment.ts | 2 ++ src/components/sanitizeFilename.js | 6 +++++- src/controllers/favorites.js | 6 +++--- src/controllers/itemDetails/index.js | 2 ++ src/controllers/session/addServer/index.js | 1 + src/controllers/session/login/index.js | 1 + src/elements/emby-collapse/emby-collapse.js | 6 ++++-- src/elements/emby-slider/emby-slider.js | 1 + src/lib/legacy/htmlMediaElement.js | 1 + src/lib/scroller/index.js | 1 + src/scripts/browser.js | 6 +++--- src/scripts/browserDeviceProfile.js | 8 ++++---- src/scripts/clipboard.js | 5 ++--- webpack.common.js | 1 + 29 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/apps/experimental/components/library/GenresItemsContainer.tsx b/src/apps/experimental/components/library/GenresItemsContainer.tsx index ee77eeef2a..3885c77ece 100644 --- a/src/apps/experimental/components/library/GenresItemsContainer.tsx +++ b/src/apps/experimental/components/library/GenresItemsContainer.tsx @@ -17,6 +17,7 @@ const GenresItemsContainer: FC = ({ parentId, collectionType, itemType +// eslint-disable-next-line sonarjs/function-return-type }) => { const { isLoading, data: genresResult } = useGetGenres(itemType, parentId); diff --git a/src/apps/experimental/components/library/UpcomingView.tsx b/src/apps/experimental/components/library/UpcomingView.tsx index bef4fc36bc..af11d267af 100644 --- a/src/apps/experimental/components/library/UpcomingView.tsx +++ b/src/apps/experimental/components/library/UpcomingView.tsx @@ -6,6 +6,7 @@ import SectionContainer from 'components/common/SectionContainer'; import { CardShape } from 'utils/card'; import type { LibraryViewProps } from 'types/library'; +// eslint-disable-next-line sonarjs/function-return-type const UpcomingView: FC = ({ parentId }) => { const { isLoading, data: groupsUpcomingEpisodes } = useGetGroupsUpcomingEpisodes(parentId); diff --git a/src/apps/stable/features/playback/types/callbacks.ts b/src/apps/stable/features/playback/types/callbacks.ts index 1bede1b2c0..4eb039a71e 100644 --- a/src/apps/stable/features/playback/types/callbacks.ts +++ b/src/apps/stable/features/playback/types/callbacks.ts @@ -17,6 +17,7 @@ export interface MovedItem { playlistItemId: string } +// eslint-disable-next-line sonarjs/redundant-type-aliases export type PlayerErrorCode = string; export interface PlayerStopInfo { diff --git a/src/components/MarkdownBox.tsx b/src/components/MarkdownBox.tsx index b5023ce1eb..5274b7e796 100644 --- a/src/components/MarkdownBox.tsx +++ b/src/components/MarkdownBox.tsx @@ -16,6 +16,7 @@ const MarkdownBox: FC = ({ = ({ className, textLine }) => { const { title, titleAction } = textLine; + // eslint-disable-next-line sonarjs/function-return-type const renderCardText = () => { if (titleAction) { return ( diff --git a/src/components/cardbuilder/Card/cardHelper.ts b/src/components/cardbuilder/Card/cardHelper.ts index e64e7bfdd1..6ad1952d56 100644 --- a/src/components/cardbuilder/Card/cardHelper.ts +++ b/src/components/cardbuilder/Card/cardHelper.ts @@ -323,7 +323,7 @@ function shouldShowMediaTitle( } function shouldShowExtraType(itemExtraType: NullableString) { - return itemExtraType && itemExtraType !== 'Unknown'; + return !!(itemExtraType && itemExtraType !== 'Unknown'); } function shouldShowSeriesYearOrYear( @@ -351,7 +351,7 @@ function shouldShowPersonRoleOrType( showPersonRoleOrType: boolean | undefined, item: ItemDto ) { - return showPersonRoleOrType && (item as BaseItemPerson).Role; + return !!(showPersonRoleOrType && (item as BaseItemPerson).Role); } function shouldShowParentTitle( diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index bdcc0f8aea..7cbc33ace3 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -195,6 +195,7 @@ function buildCardsHtmlInternal(items, options) { if (isVertical) { html += ''; } + // eslint-disable-next-line sonarjs/no-dead-store hasOpenSection = false; } @@ -215,6 +216,7 @@ function buildCardsHtmlInternal(items, options) { if (options.rows && itemsInRow === 0) { if (hasOpenRow) { html += ''; + // eslint-disable-next-line sonarjs/no-dead-store hasOpenRow = false; } diff --git a/src/components/dashboard/users/AccessScheduleList.tsx b/src/components/dashboard/users/AccessScheduleList.tsx index 91a789017f..a88a6c61b5 100644 --- a/src/components/dashboard/users/AccessScheduleList.tsx +++ b/src/components/dashboard/users/AccessScheduleList.tsx @@ -4,7 +4,7 @@ import globalize from '../../../lib/globalize'; import IconButtonElement from '../../../elements/IconButtonElement'; type AccessScheduleListProps = { - index: number; + index?: number; DayOfWeek?: string; StartHour?: number ; EndHour?: number; diff --git a/src/components/favoriteitems.js b/src/components/favoriteitems.js index 8a1b5c4738..e3e33be2f3 100644 --- a/src/components/favoriteitems.js +++ b/src/components/favoriteitems.js @@ -3,7 +3,6 @@ import globalize from 'lib/globalize'; import { getBackdropShape, getPortraitShape, getSquareShape } from 'utils/card'; import { getParameterByName } from 'utils/url'; -import { appHost } from './apphost'; import cardBuilder from './cardbuilder/cardBuilder'; import imageLoader from './images/imageLoader'; import layoutManager from './layoutManager'; @@ -160,8 +159,10 @@ function loadSection(elem, userId, topParentId, section, isSingleSection) { html += '
'; } - let cardLayout = appHost.preferVisualCards && section.autoCardLayout && section.showTitle; - cardLayout = false; + // NOTE: Why is card layout always disabled? + // let cardLayout = appHost.preferVisualCards && section.autoCardLayout && section.showTitle; + const cardLayout = false; + html += cardBuilder.getCardsHtml(result.Items, { preferThumb: section.preferThumb, shape: section.shape, diff --git a/src/components/fetchhelper.js b/src/components/fetchhelper.js index f63fa62ced..9de1dd7e3e 100644 --- a/src/components/fetchhelper.js +++ b/src/components/fetchhelper.js @@ -74,6 +74,7 @@ function fetchWithTimeout(url, options, timeoutMs) { */ function paramsToString(params) { return Object.entries(params) + // eslint-disable-next-line sonarjs/different-types-comparison .filter(([, v]) => v !== null && v !== undefined && v !== '') .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`) .join('&'); diff --git a/src/components/focusManager.js b/src/components/focusManager.js index 8dd0f6dd51..dc58fcc584 100644 --- a/src/components/focusManager.js +++ b/src/components/focusManager.js @@ -389,6 +389,7 @@ function intersectsInternal(a1, a2, b1, b2) { } function intersects(a1, a2, b1, b2) { + // eslint-disable-next-line sonarjs/arguments-order return intersectsInternal(a1, a2, b1, b2) || intersectsInternal(b1, b2, a1, a2); } diff --git a/src/components/htmlMediaHelper.js b/src/components/htmlMediaHelper.js index ab1a215656..f876568ce4 100644 --- a/src/components/htmlMediaHelper.js +++ b/src/components/htmlMediaHelper.js @@ -80,7 +80,7 @@ export function handleHlsJsMediaError(instance, reject) { let now = Date.now(); if (window.performance?.now) { - now = performance.now(); // eslint-disable-line compat/compat + now = performance.now(); } if (!recoverDecodingErrorDate || (now - recoverDecodingErrorDate) > 3000) { @@ -373,6 +373,7 @@ export function getBufferedRanges(instance, elem) { start = 0; } if (!isValidDuration(end)) { + // eslint-disable-next-line sonarjs/no-dead-store end = 0; continue; } diff --git a/src/components/listview/listview.js b/src/components/listview/listview.js index 8240ee047b..916b9a44a1 100644 --- a/src/components/listview/listview.js +++ b/src/components/listview/listview.js @@ -417,6 +417,7 @@ export function getListViewHtml(options) { } if (enableOverview && item.Overview) { + // eslint-disable-next-line sonarjs/disabled-auto-escaping const overview = DOMPurify.sanitize(markdownIt({ html: true }).render(item.Overview || '')); html += '
'; html += '' + overview + ''; diff --git a/src/components/mediainfo/MediaInfoItem.tsx b/src/components/mediainfo/MediaInfoItem.tsx index 35159ddfc6..58ce9952c2 100644 --- a/src/components/mediainfo/MediaInfoItem.tsx +++ b/src/components/mediainfo/MediaInfoItem.tsx @@ -13,6 +13,7 @@ interface MediaInfoItemProps { const MediaInfoItem: FC = ({ className, miscInfo }) => { const { text, textAction, cssClass, type } = miscInfo; + // eslint-disable-next-line sonarjs/function-return-type const renderText = () => { if (textAction) { return ( diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index de0c50e57d..f4e8ec02c1 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -208,6 +208,7 @@ function getMimeType(type, container) { } function getParam(name, url) { + // eslint-disable-next-line sonarjs/single-char-in-character-classes name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]'); const regexS = '[\\?&]' + name + '=([^&#]*)'; const regex = new RegExp(regexS, 'i'); @@ -2115,6 +2116,7 @@ export class PlaybackManager { if (!state) { playerStates[player.name] = {}; + // eslint-disable-next-line sonarjs/no-dead-store state = playerStates[player.name]; } diff --git a/src/components/playback/skipsegment.ts b/src/components/playback/skipsegment.ts index b73576c721..a6d3373b10 100644 --- a/src/components/playback/skipsegment.ts +++ b/src/components/playback/skipsegment.ts @@ -90,6 +90,7 @@ class SkipSegment extends PlaybackSubscriber { elem.classList.remove('no-transition'); } + // eslint-disable-next-line sonarjs/void-use void elem.offsetWidth; const hasFocus = document.activeElement && focusManager.isCurrentlyFocusable(document.activeElement); @@ -111,6 +112,7 @@ class SkipSegment extends PlaybackSubscriber { const elem = this.skipElement; if (elem) { elem.classList.remove('no-transition'); + // eslint-disable-next-line sonarjs/void-use void elem.offsetWidth; requestAnimationFrame(() => { diff --git a/src/components/sanitizeFilename.js b/src/components/sanitizeFilename.js index 77e06d359c..d0e32164f3 100644 --- a/src/components/sanitizeFilename.js +++ b/src/components/sanitizeFilename.js @@ -1,11 +1,14 @@ // TODO: Check if needed and move to external dependency // From https://github.com/parshap/node-sanitize-filename +// eslint-disable-next-line sonarjs/duplicates-in-character-class const illegalRe = /[/?<>\\:*|":]/g; -// eslint-disable-next-line no-control-regex +// eslint-disable-next-line no-control-regex, sonarjs/no-control-regex const controlRe = /[\x00-\x1f\x80-\x9f]/g; const reservedRe = /^\.+$/; +// eslint-disable-next-line sonarjs/concise-regex const windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i; +// eslint-disable-next-line sonarjs/slow-regex const windowsTrailingRe = /[. ]+$/; function isHighSurrogate(codePoint) { @@ -64,6 +67,7 @@ function truncate(string, byteLength) { segment = string[i]; if (isHighSurrogate(codePoint) && isLowSurrogate(string.charCodeAt(i + 1))) { + // eslint-disable-next-line sonarjs/updated-loop-counter i += 1; segment += string[i]; } diff --git a/src/controllers/favorites.js b/src/controllers/favorites.js index 6a6be74600..ccc689fc24 100644 --- a/src/controllers/favorites.js +++ b/src/controllers/favorites.js @@ -1,4 +1,3 @@ -import { appHost } from 'components/apphost'; import cardBuilder from 'components/cardbuilder/cardBuilder'; import focusManager from 'components/focusManager'; import layoutManager from 'components/layoutManager'; @@ -202,8 +201,9 @@ function getRouteUrl(section, serverId) { function getItemsHtmlFn(section) { return function (items) { - let cardLayout = appHost.preferVisualCards && section.autoCardLayout && section.showTitle; - cardLayout = false; + // NOTE: Why is card layout always disabled? + // let cardLayout = appHost.preferVisualCards && section.autoCardLayout && section.showTitle; + const cardLayout = false; const serverId = this.apiClient.serverId(); const leadingButtons = layoutManager.tv ? [{ name: globalize.translate('All'), diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index bdb5a9fe08..344b316210 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -877,6 +877,7 @@ function renderOverview(page, item) { const overviewElements = page.querySelectorAll('.overview'); if (overviewElements.length > 0) { + // eslint-disable-next-line sonarjs/disabled-auto-escaping const overview = DOMPurify.sanitize(markdownIt({ html: true }).render(item.Overview || '')); if (overview) { @@ -1378,6 +1379,7 @@ function renderChildren(page, item) { if (item.Type == 'MusicAlbum') { let showArtist = false; for (const track of result.Items) { + // eslint-disable-next-line sonarjs/no-alphabetical-sort if (!isEqual(track.ArtistItems.map(x => x.Id).sort(), track.AlbumArtists.map(x => x.Id).sort())) { showArtist = true; break; diff --git a/src/controllers/session/addServer/index.js b/src/controllers/session/addServer/index.js index d7c02947f8..068fc6134d 100644 --- a/src/controllers/session/addServer/index.js +++ b/src/controllers/session/addServer/index.js @@ -36,6 +36,7 @@ function handleConnectionResult(page, result) { function submitServer(page) { loading.show(); + // eslint-disable-next-line sonarjs/slow-regex const host = page.querySelector('#txtServerHost').value.replace(/\/+$/, ''); ServerConnections.connectToAddress(host, { enableAutoLogin: appSettings.enableAutoLogin() diff --git a/src/controllers/session/login/index.js b/src/controllers/session/login/index.js index 93f8e03de0..2b61fb6e2b 100644 --- a/src/controllers/session/login/index.js +++ b/src/controllers/session/login/index.js @@ -292,6 +292,7 @@ export default function (view, params) { apiClient.getJSON(apiClient.getUrl('Branding/Configuration')).then(function (options) { const loginDisclaimer = view.querySelector('.loginDisclaimer'); + // eslint-disable-next-line sonarjs/disabled-auto-escaping loginDisclaimer.innerHTML = DOMPurify.sanitize(markdownIt({ html: true }).render(options.LoginDisclaimer || '')); for (const elem of loginDisclaimer.querySelectorAll('a')) { diff --git a/src/elements/emby-collapse/emby-collapse.js b/src/elements/emby-collapse/emby-collapse.js index bf281d1257..1f47db55b1 100644 --- a/src/elements/emby-collapse/emby-collapse.js +++ b/src/elements/emby-collapse/emby-collapse.js @@ -13,7 +13,8 @@ function slideDownToShow(button, elem) { elem.style.height = '0'; // trigger reflow // TODO: Find a better way to do this - const newHeight = elem.offsetHeight; /* eslint-disable-line no-unused-vars */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars, sonarjs/no-unused-vars, sonarjs/no-dead-store + const newHeight = elem.offsetHeight; elem.style.height = height; setTimeout(function () { @@ -35,7 +36,8 @@ function slideUpToHide(button, elem) { elem.style.height = elem.offsetHeight + 'px'; // trigger reflow // TODO: Find a better way to do this - const newHeight = elem.offsetHeight; /* eslint-disable-line no-unused-vars */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars, sonarjs/no-unused-vars, sonarjs/no-dead-store + const newHeight = elem.offsetHeight; elem.classList.remove('expanded'); elem.style.height = '0'; diff --git a/src/elements/emby-slider/emby-slider.js b/src/elements/emby-slider/emby-slider.js index 474fd430c2..e4575ecaff 100644 --- a/src/elements/emby-slider/emby-slider.js +++ b/src/elements/emby-slider/emby-slider.js @@ -161,6 +161,7 @@ function updateValues(isValueSet) { if (!!isValueSet && !supportsValueAutoSnap) { const value = snapValue(this, parseFloat(this.value)).toString(); + // eslint-disable-next-line sonarjs/different-types-comparison if (this.value !== value) { this.value = value; diff --git a/src/lib/legacy/htmlMediaElement.js b/src/lib/legacy/htmlMediaElement.js index b01389fded..9c76389168 100644 --- a/src/lib/legacy/htmlMediaElement.js +++ b/src/lib/legacy/htmlMediaElement.js @@ -11,6 +11,7 @@ const realPlay = HTMLMediaElementPrototype.play; HTMLMediaElementPrototype.play = function () { + // eslint-disable-next-line sonarjs/no-try-promise try { const promise = realPlay.apply(this, arguments); diff --git a/src/lib/scroller/index.js b/src/lib/scroller/index.js index 0292cb5688..d84cffc7b9 100644 --- a/src/lib/scroller/index.js +++ b/src/lib/scroller/index.js @@ -24,6 +24,7 @@ function type(value) { } if (typeof value === 'object' || typeof value === 'function') { + // eslint-disable-next-line sonarjs/prefer-regexp-exec return Object.prototype.toString.call(value).match(/\s([a-z]+)/i)[1].toLowerCase() || 'object'; } diff --git a/src/scripts/browser.js b/src/scripts/browser.js index e2f593e70b..d93b91dded 100644 --- a/src/scripts/browser.js +++ b/src/scripts/browser.js @@ -86,7 +86,7 @@ function iOSversion() { /Version\/(\d+)/ ]; for (const test of tests) { - const matches = (navigator.appVersion).match(test); + const matches = RegExp(test).exec(navigator.appVersion); if (matches) { return [ parseInt(matches[1], 10), @@ -163,6 +163,7 @@ function supportsCssAnimation(allowPrefix) { const domPrefixes = ['Webkit', 'O', 'Moz']; const elm = document.createElement('div'); + // eslint-disable-next-line sonarjs/different-types-comparison if (elm.style.animationName !== undefined) { animation = true; } @@ -298,7 +299,7 @@ if (browser.web0s) { delete browser.chrome; delete browser.safari; } else if (browser.tizen) { - const v = (navigator.appVersion).match(/Tizen (\d+).(\d+)/); + const v = RegExp(/Tizen (\d+).(\d+)/).exec(navigator.appVersion); browser.tizenVersion = parseInt(v[1], 10); // UserAgent string contains 'Chrome' and 'Safari', but we only want 'tizen' to be true @@ -319,7 +320,6 @@ if (browser.mobile || browser.tv) { browser.slow = true; } -/* eslint-disable-next-line compat/compat */ if (typeof document !== 'undefined' && ('ontouchstart' in window) || (navigator.maxTouchPoints > 0)) { browser.touch = true; } diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js index f051d4a122..4370edaeaf 100644 --- a/src/scripts/browserDeviceProfile.js +++ b/src/scripts/browserDeviceProfile.js @@ -230,7 +230,8 @@ function supportsVc1(videoTestElement) { } function supportsHdr10(options) { - return options.supportsHdr10 ?? (false // eslint-disable-line sonarjs/no-redundant-boolean + // eslint-disable-next-line no-constant-binary-expression, sonarjs/no-redundant-boolean + return options.supportsHdr10 ?? (false || browser.vidaa || browser.tizen || browser.web0s @@ -253,7 +254,8 @@ function supportsHlg(options) { } function supportsDolbyVision(options) { - return options.supportsDolbyVision ?? (false // eslint-disable-line sonarjs/no-redundant-boolean + // eslint-disable-next-line no-constant-binary-expression, sonarjs/no-redundant-boolean + return options.supportsDolbyVision ?? (false || browser.safari && ((browser.iOS && browser.iOSVersion >= 13) || browser.osx) ); } @@ -512,10 +514,8 @@ export default function (options) { } } - /* eslint-disable compat/compat */ let maxVideoWidth = browser.xboxOne ? window.screen?.width : null; - /* eslint-enable compat/compat */ if (options.maxVideoWidth) { maxVideoWidth = options.maxVideoWidth; } diff --git a/src/scripts/clipboard.js b/src/scripts/clipboard.js index 7e7170b7a1..79bee57f18 100644 --- a/src/scripts/clipboard.js +++ b/src/scripts/clipboard.js @@ -33,7 +33,7 @@ function textAreaCopy(text) { } else { ret = Promise.reject(); } - } catch (_) { + } catch { ret = Promise.reject(); } @@ -48,11 +48,10 @@ function textAreaCopy(text) { * @returns {Promise} Promise. */ export function copy(text) { - /* eslint-disable-next-line compat/compat */ + // eslint-disable-next-line sonarjs/different-types-comparison if (navigator.clipboard === undefined) { return textAreaCopy(text); } else { - /* eslint-disable-next-line compat/compat */ return navigator.clipboard.writeText(text).catch(() => { return textAreaCopy(text); }); diff --git a/webpack.common.js b/webpack.common.js index bce07af984..0a4f543a2d 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -23,6 +23,7 @@ const DEV_MODE = process.env.NODE_ENV !== 'production'; let COMMIT_SHA = ''; try { COMMIT_SHA = require('child_process') + // eslint-disable-next-line sonarjs/no-os-command-from-path .execSync('git describe --always --dirty') .toString() .trim();