diff --git a/.stylelintrc.js b/.stylelintrc.js index 290cbe75..c79d5b56 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -14,7 +14,7 @@ module.exports = { // extending the kebab-case to accept ConverseJS class names. '^([a-z][a-z0-9]*)(-[a-z0-9]+)*((__|--)[a-z]+(-[a-z0-9]+)*)?$', { - message: 'Expected class selector to be kebab-case, or ConverseJS-style.', + message: 'Expected class selector to be kebab-case, or ConverseJS-style.' } ] } diff --git a/client/admin-plugin-client-plugin.ts b/client/admin-plugin-client-plugin.ts index 7b0f872b..3d4f719f 100644 --- a/client/admin-plugin-client-plugin.ts +++ b/client/admin-plugin-client-plugin.ts @@ -243,7 +243,10 @@ function register (clientOptions: RegisterClientOptions): void { } } catch (error: any) { console.error(error) - peertubeHelpers.notifier.error(error.toString(), await peertubeHelpers.translate(LOC_LOADING_ERROR)) + peertubeHelpers.notifier.error( + (error as Error).toString(), + await peertubeHelpers.translate(LOC_LOADING_ERROR) + ) } } }) diff --git a/client/common-client-plugin.ts b/client/common-client-plugin.ts index af7e1d46..05b4bc2c 100644 --- a/client/common-client-plugin.ts +++ b/client/common-client-plugin.ts @@ -46,7 +46,7 @@ async function register (clientOptions: RegisterClientOptions): Promise { ]) const webchatFieldOptions: RegisterClientFormFieldOptions = { name: 'livechat-active', - label: label, + label, descriptionHTML: description, type: 'input-checkbox', default: true, diff --git a/client/common/admin/firewall/elements/admin-firewall.ts b/client/common/admin/firewall/elements/admin-firewall.ts index aba28c90..067193f9 100644 --- a/client/common/admin/firewall/elements/admin-firewall.ts +++ b/client/common/admin/firewall/elements/admin-firewall.ts @@ -22,7 +22,7 @@ export class AdminFirewallElement extends LivechatElement { public validationError?: ValidationError @state() - public actionDisabled: boolean = false + public actionDisabled = false private _asyncTaskRender: Task @@ -101,7 +101,7 @@ export class AdminFirewallElement extends LivechatElement { }) } - public readonly getInputValidationClass = (propertyName: string): { [key: string]: boolean } => { + public readonly getInputValidationClass = (propertyName: string): Record => { const validationErrorTypes: ValidationErrorType[] | undefined = this.validationError?.properties[`${propertyName}`] return validationErrorTypes ? (validationErrorTypes.length ? { 'is-invalid': true } : { 'is-valid': true }) : {} diff --git a/client/common/admin/firewall/templates/admin-firewall.ts b/client/common/admin/firewall/templates/admin-firewall.ts index ffa430c9..46a266d8 100644 --- a/client/common/admin/firewall/templates/admin-firewall.ts +++ b/client/common/admin/firewall/templates/admin-firewall.ts @@ -2,6 +2,9 @@ // // SPDX-License-Identifier: AGPL-3.0-only +// FIXME: @stylistic/indent is buggy with strings literrals. +/* eslint-disable @stylistic/indent */ + import type { AdminFirewallElement } from '../elements/admin-firewall' import type { TemplateResult } from 'lit' import type { DynamicFormHeader, DynamicFormSchema } from '../../../lib/elements/dynamic-table-form' diff --git a/client/common/configuration/elements/channel-configuration.ts b/client/common/configuration/elements/channel-configuration.ts index 7e6edd66..01c5f812 100644 --- a/client/common/configuration/elements/channel-configuration.ts +++ b/client/common/configuration/elements/channel-configuration.ts @@ -32,7 +32,7 @@ export class ChannelConfigurationElement extends LivechatElement { public validationError?: ValidationError @state() - public actionDisabled: boolean = false + public actionDisabled = false private _asyncTaskRender: Task @@ -113,7 +113,7 @@ export class ChannelConfigurationElement extends LivechatElement { } } - public readonly getInputValidationClass = (propertyName: string): { [key: string]: boolean } => { + public readonly getInputValidationClass = (propertyName: string): Record => { const validationErrorTypes: ValidationErrorType[] | undefined = this.validationError?.properties[`${propertyName}`] return validationErrorTypes ? (validationErrorTypes.length ? { 'is-invalid': true } : { 'is-valid': true }) : {} diff --git a/client/common/configuration/elements/channel-emojis.ts b/client/common/configuration/elements/channel-emojis.ts index e7e09de8..d6957153 100644 --- a/client/common/configuration/elements/channel-emojis.ts +++ b/client/common/configuration/elements/channel-emojis.ts @@ -30,7 +30,7 @@ export class ChannelEmojisElement extends LivechatElement { public validationError?: ValidationError @state() - public actionDisabled: boolean = false + public actionDisabled = false private _asyncTaskRender: Task @@ -192,7 +192,7 @@ export class ChannelEmojisElement extends LivechatElement { throw new Error('Invalid data') } - const url = await this._convertImageToDataUrl(entry.url) + const url = await this._convertImageToDataUrl(entry.url as string) const sn = entry.sn as string const item: ChannelEmojisConfiguration['emojis']['customEmojis'][0] = { @@ -211,7 +211,7 @@ export class ChannelEmojisElement extends LivechatElement { await this.ptTranslate(LOC_ACTION_IMPORT_EMOJIS_INFO) ) } catch (err: any) { - this.ptNotifier.error(err.toString(), await this.ptTranslate(LOC_ERROR)) + this.ptNotifier.error((err as Error).toString(), await this.ptTranslate(LOC_ERROR)) } finally { this.actionDisabled = false } @@ -250,7 +250,7 @@ export class ChannelEmojisElement extends LivechatElement { a.remove() } catch (err: any) { this.logger.error(err) - this.ptNotifier.error(err.toString()) + this.ptNotifier.error((err as Error).toString()) } finally { this.actionDisabled = false } diff --git a/client/common/configuration/elements/channel-home.ts b/client/common/configuration/elements/channel-home.ts index 0a861ccc..e66c2b69 100644 --- a/client/common/configuration/elements/channel-home.ts +++ b/client/common/configuration/elements/channel-home.ts @@ -2,6 +2,9 @@ // // SPDX-License-Identifier: AGPL-3.0-only +// FIXME: @stylistic/indent is buggy with strings literrals. +/* eslint-disable @stylistic/indent */ + import { html } from 'lit' import { customElement, state } from 'lit/decorators.js' import { ptTr } from '../../lib/directives/translation' diff --git a/client/common/configuration/elements/channel-tabs.ts b/client/common/configuration/elements/channel-tabs.ts index 2470a315..ab31f80e 100644 --- a/client/common/configuration/elements/channel-tabs.ts +++ b/client/common/configuration/elements/channel-tabs.ts @@ -2,6 +2,9 @@ // // SPDX-License-Identifier: AGPL-3.0-only +// FIXME: @stylistic/indent is buggy with strings literrals. +/* eslint-disable @stylistic/indent */ + import { LivechatElement } from '../../lib/elements/livechat' import { ptTr } from '../../lib/directives/translation' import { html, TemplateResult } from 'lit' diff --git a/client/common/configuration/elements/templates/channel-configuration.ts b/client/common/configuration/elements/templates/channel-configuration.ts index 33453a4c..ecae85a3 100644 --- a/client/common/configuration/elements/templates/channel-configuration.ts +++ b/client/common/configuration/elements/templates/channel-configuration.ts @@ -2,6 +2,9 @@ // // SPDX-License-Identifier: AGPL-3.0-only +// FIXME: @stylistic/indent is buggy with strings literrals. +/* eslint-disable @stylistic/indent */ + import type { ChannelConfigurationElement } from '../channel-configuration' import type { DynamicFormHeader, DynamicFormSchema } from '../../../lib/elements/dynamic-table-form' import { ptTr } from '../../../lib/directives/translation' @@ -9,7 +12,7 @@ import { html, TemplateResult } from 'lit' import { classMap } from 'lit/directives/class-map.js' export function tplChannelConfiguration (el: ChannelConfigurationElement): TemplateResult { - const tableHeaderList: {[key: string]: DynamicFormHeader} = { + const tableHeaderList: Record = { forbiddenWords: { entries: { colName: ptTr(LOC_LIVECHAT_CONFIGURATION_CHANNEL_FORBIDDEN_WORDS_LABEL), @@ -57,7 +60,7 @@ export function tplChannelConfiguration (el: ChannelConfigurationElement): Templ } } } - const tableSchema: {[key: string]: DynamicFormSchema} = { + const tableSchema: Record = { forbiddenWords: { entries: { inputType: 'tags', diff --git a/client/common/configuration/elements/templates/channel-emojis.ts b/client/common/configuration/elements/templates/channel-emojis.ts index ae354500..8984f8ab 100644 --- a/client/common/configuration/elements/templates/channel-emojis.ts +++ b/client/common/configuration/elements/templates/channel-emojis.ts @@ -2,6 +2,9 @@ // // SPDX-License-Identifier: AGPL-3.0-only +// FIXME: @stylistic/indent is buggy with strings literrals. +/* eslint-disable @stylistic/indent */ + import type { ChannelEmojisElement } from '../channel-emojis' import type { DynamicFormHeader, DynamicFormSchema } from '../../../lib/elements/dynamic-table-form' import { maxEmojisPerChannel } from 'shared/lib/emojis' diff --git a/client/common/configuration/services/channel-details.ts b/client/common/configuration/services/channel-details.ts index 4c1695a7..21d3e5fd 100644 --- a/client/common/configuration/services/channel-details.ts +++ b/client/common/configuration/services/channel-details.ts @@ -162,7 +162,8 @@ export class ChannelDetailsService { } for (const channel of channels.data) { - channel.livechatConfigurationUri = '/p/livechat/configuration/channel?channelId=' + encodeURIComponent(channel.id) + channel.livechatConfigurationUri = + '/p/livechat/configuration/channel?channelId=' + encodeURIComponent(channel.id as string | number) // Note: since Peertube v6.0.0, channel.avatar is dropped, and we have to use channel.avatars. // So, if !channel.avatar, we will search a suitable one in channel.avatars, and fill channel.avatar. @@ -196,10 +197,11 @@ export class ChannelDetailsService { } public async fetchEmojisConfiguration (channelId: number): Promise { + const url = getBaseRoute(this._registerClientOptions) + + '/api/configuration/channel/emojis/' + + encodeURIComponent(channelId) const response = await fetch( - getBaseRoute(this._registerClientOptions) + - '/api/configuration/channel/emojis/' + - encodeURIComponent(channelId), + url, { method: 'GET', headers: this._headers @@ -311,10 +313,11 @@ export class ChannelDetailsService { channelId: number, channelEmojis: ChannelEmojis ): Promise { + const url = getBaseRoute(this._registerClientOptions) + + '/api/configuration/channel/emojis/' + + encodeURIComponent(channelId) const response = await fetch( - getBaseRoute(this._registerClientOptions) + - '/api/configuration/channel/emojis/' + - encodeURIComponent(channelId), + url, { method: 'POST', headers: this._headers, @@ -330,11 +333,12 @@ export class ChannelDetailsService { } public async enableEmojisOnlyModeOnAllRooms (channelId: number): Promise { + const url = getBaseRoute(this._registerClientOptions) + + '/api/configuration/channel/emojis/' + + encodeURIComponent(channelId) + + '/enable_emoji_only' const response = await fetch( - getBaseRoute(this._registerClientOptions) + - '/api/configuration/channel/emojis/' + - encodeURIComponent(channelId) + - '/enable_emoji_only', + url, { method: 'POST', headers: this._headers diff --git a/client/common/lib/buttons.ts b/client/common/lib/buttons.ts index 0cf9e11d..a51e8dff 100644 --- a/client/common/lib/buttons.ts +++ b/client/common/lib/buttons.ts @@ -4,7 +4,7 @@ // SPDX-License-Identifier: AGPL-3.0-only // This content comes from the file assets/images/plus-square.svg, from the Feather icons set https://feathericons.com/ -export const AddSVG: string = +export const AddSVG = `Testing...' ul.append(waiting) if ((typeof result.next) === 'function') { + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type const r: Result = (result.next as Function)() waiting.remove() await machine(r) diff --git a/client/utils/conversejs.ts b/client/utils/conversejs.ts index 758e14ee..de7ca7d6 100644 --- a/client/utils/conversejs.ts +++ b/client/utils/conversejs.ts @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2024 John Livingston // // SPDX-License-Identifier: AGPL-3.0-only +/* eslint-disable @typescript-eslint/no-unsafe-function-type */ import type { RegisterClientOptions } from '@peertube/peertube-types/client' import type { InitConverseJSParams, ChatPeertubeIncludeMode } from 'shared/lib/types' @@ -17,7 +18,7 @@ declare global { } } -let pollListenerInitiliazed: boolean = false +let pollListenerInitiliazed = false /** * load the ConverseJS CSS. @@ -152,10 +153,11 @@ async function displayConverseJS ( const authHeader = peertubeHelpers.getAuthHeader() + const url = getBaseRoute(clientOptions) + '/api/configuration/room/' + + encodeURIComponent(roomKey) + + (forceType ? '?forcetype=1' : '') const response = await fetch( - getBaseRoute(clientOptions) + '/api/configuration/room/' + - encodeURIComponent(roomKey) + - (forceType ? '?forcetype=1' : ''), + url, { method: 'GET', headers: authHeader diff --git a/client/utils/uri.ts b/client/utils/uri.ts index 600352ec..3def4c54 100644 --- a/client/utils/uri.ts +++ b/client/utils/uri.ts @@ -4,7 +4,7 @@ import type { RegisterClientOptions } from '@peertube/peertube-types/client' -function getBaseRoute ({ peertubeHelpers }: RegisterClientOptions, permanent: boolean = false): string { +function getBaseRoute ({ peertubeHelpers }: RegisterClientOptions, permanent = false): string { if (permanent) { return '/plugins/livechat/router' } diff --git a/eslint.config.mjs b/eslint.config.mjs index 91fa96de..aae805eb 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -2,23 +2,30 @@ // // SPDX-License-Identifier: AGPL-3.0-only +// FIXME: +// * lint shared +// * lint conversejs +// * use eslint-plugin-lit + import love from 'eslint-config-love' import eslint from '@eslint/js' import tseslint from 'typescript-eslint' import typescriptParser from '@typescript-eslint/parser' import stylistic from '@stylistic/eslint-plugin' +import eslintLit from 'eslint-plugin-lit' import globals from 'globals' export default tseslint.config( { ignores: [ - "node_modules/", "dist/", "webpack.config.js", - "build/", - "vendor/", - "support/documentation", "support", - "build-*js", + 'node_modules/', 'dist/', 'webpack.config.js', + 'build/', + 'vendor/', + 'support/documentation', 'support', + 'build-*js', - "shared", "client", "conversejs" + 'shared', + 'conversejs' ] }, eslint.configs.recommended, @@ -27,48 +34,57 @@ export default tseslint.config( ...love, files: ['**/*.ts'] }, + stylistic.configs.customize({ + quotes: 'single', + semi: false, + commaDangle: 'never', + blockSpacing: true, + braceStyle: '1tbs', + indent: 2, + quoteProps: 'as-needed' + }), { - plugins: { - '@stylistic': stylistic - }, rules: { - "@stylistic/semi": ["error", "never"] + '@stylistic/space-before-function-paren': ['error', { anonymous: 'always', asyncArrow: 'always', named: 'always' }], + '@stylistic/arrow-parens': 'off', + '@stylistic/operator-linebreak': ['error', 'after', { overrides: { '?': 'before', ':': 'before' } }], + '@stylistic/max-statements-per-line': ['error', { max: 2 }] } }, { files: ['**/*.ts'], rules: { - "@typescript-eslint/no-empty-function": ["error", {"allow": ["arrowFunctions"]}], - "@typescript-eslint/no-unused-vars": [2, {"argsIgnorePattern": "^_", "caughtErrorsIgnorePattern": "^_"}], - "@typescript-eslint/no-floating-promises": "error", - "@typescript-eslint/no-misused-promises": "error", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/strict-boolean-expressions": "off", - "@typescript-eslint/return-await": [2, "in-try-catch"], // FIXME: correct? - "@typescript-eslint/no-invalid-void-type": "off", - "@typescript-eslint/triple-slash-reference": "off", - "@typescript-eslint/no-explicit-any": "off", // FIXME: should be "error", and we should use 'unknown' in the code. - "init-declarations": "off", - "@typescript-eslint/init-declarations": "off", - "@typescript-eslint/consistent-type-imports": "off", - "@typescript-eslint/consistent-type-exports": "off", - "@typescript-eslint/no-require-imports": "off", - "@typescript-eslint/unbound-method": "off", - "@typescript-eslint/prefer-promise-reject-errors": "off", - "max-params": "off", - "@typescript-eslint/max-params": ["error", { "max": 8 }], // FIXME: this rules should use the default max value. - "@typescript-eslint/explicit-function-return-type": "error", - "@typescript-eslint/no-confusing-void-expression": "off", - "@typescript-eslint/class-methods-use-this": "off", - "@typescript-eslint/non-nullable-type-assertion-style": "off", - "max-len": [ - "error", + '@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }], + '@typescript-eslint/no-unused-vars': [2, { argsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' }], + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-misused-promises': ['error', { checksVoidReturn: false }], + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/strict-boolean-expressions': 'off', + '@typescript-eslint/return-await': [2, 'in-try-catch'], // FIXME: correct? + '@typescript-eslint/no-invalid-void-type': 'off', + '@typescript-eslint/triple-slash-reference': 'off', + '@typescript-eslint/no-explicit-any': 'off', // FIXME: should be "error", and we should use 'unknown' in the code. + 'init-declarations': 'off', + '@typescript-eslint/init-declarations': 'off', + '@typescript-eslint/consistent-type-imports': 'off', + '@typescript-eslint/consistent-type-exports': 'off', + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/unbound-method': 'off', + '@typescript-eslint/prefer-promise-reject-errors': 'off', + 'max-params': 'off', + '@typescript-eslint/max-params': ['error', { max: 8 }], // FIXME: this rules should use the default max value. + '@typescript-eslint/explicit-function-return-type': 'error', + '@typescript-eslint/no-confusing-void-expression': 'off', + '@typescript-eslint/class-methods-use-this': 'off', + '@typescript-eslint/non-nullable-type-assertion-style': 'off', + 'max-len': [ + 'error', { - "code": 120, - "comments": 120 + code: 120, + comments: 120 } ], - "no-unused-vars": "off" + 'no-unused-vars': 'off' } }, { @@ -90,5 +106,48 @@ export default tseslint.config( project: './server/tsconfig.json' } } + }, + { + files: ['shared/**/*.js', 'shared/**/*.ts'], // only ts? + languageOptions: { + ecmaVersion: 6, + globals: { + ...globals.es2016, + ...globals.browser + }, + parser: typescriptParser, + parserOptions: { + ecmaVersion: 2018, + project: [ + './server/tsconfig.json', + './client/tsconfig.json' + ], + projectService: { + allowDefaultProject: 'shared/**/*.ts', + defaultProject: './server/tsconfig.json' + } + } + } + }, + { + files: ['client/**/*.js', 'client/**/*.ts'], // only ts? + languageOptions: { + ecmaVersion: 6, + globals: { + ...globals.browser + }, + parser: typescriptParser, + parserOptions: { + ecmaVersion: 2018, + project: './client/tsconfig.json' + } + }, + // FIXME: not sure elintLit works. + plugins: { + ...eslintLit.configs['flat/recommended'].plugins + }, + rules: { + ...eslintLit.configs['flat/recommended'].rules + } } ) diff --git a/package-lock.json b/package-lock.json index 6579078e..6ceac724 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "esbuild": "^0.16.1", "eslint": "^8.57.0", "eslint-config-love": "^64.0.0", + "eslint-plugin-lit": "^1.15.0", "globals": "^15.9.0", "lit": "^2.4.0", "lit-analyzer": "^1.2.1", @@ -7045,6 +7046,23 @@ "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-lit": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.15.0.tgz", + "integrity": "sha512-Yhr2MYNz6Ln8megKcX503aVZQln8wsywCG49g0heiJ/Qr5UjkE4pGr4Usez2anNcc7NvlvHbQWMYwWcgH3XRKA==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "requireindex": "^1.2.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "eslint": ">= 5" + } + }, "node_modules/eslint-plugin-n": { "version": "17.10.2", "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.10.2.tgz", @@ -10954,6 +10972,21 @@ "parse-torrent": "bin/cmd.js" } }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -11587,6 +11620,15 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -19606,6 +19648,17 @@ } } }, + "eslint-plugin-lit": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.15.0.tgz", + "integrity": "sha512-Yhr2MYNz6Ln8megKcX503aVZQln8wsywCG49g0heiJ/Qr5UjkE4pGr4Usez2anNcc7NvlvHbQWMYwWcgH3XRKA==", + "dev": true, + "requires": { + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "requireindex": "^1.2.0" + } + }, "eslint-plugin-n": { "version": "17.10.2", "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.10.2.tgz", @@ -22304,6 +22357,21 @@ "simple-sha1": "^3.1.0" } }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "requires": { + "parse5": "^6.0.1" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -22753,6 +22821,12 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", diff --git a/package.json b/package.json index 368b7e2b..9b178d60 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "esbuild": "^0.16.1", "eslint": "^8.57.0", "eslint-config-love": "^64.0.0", + "eslint-plugin-lit": "^1.15.0", "globals": "^15.9.0", "lit": "^2.4.0", "lit-analyzer": "^1.2.1", @@ -106,8 +107,8 @@ "build": "npm-run-all -s clean:light build:languages check:client:tsc -s build:client build:server build:images build:styles build:avatars build:serverconverse build:prosodymodules build:converse build:prosody", "lint": "npm-run-all -s lint:script lint:lit lint:styles lint:reuse", "lint:fix": "npm-run-all -s lint:script:fix lint:styles:fix", - "lint:script": "npx eslint --ext .js --ext .ts .", - "lint:script:fix": "npx eslint --ext .js --ext .ts . --fix", + "lint:script": "npx eslint .", + "lint:script:fix": "npx eslint . --fix", "lint:lit": "npx lit-analyzer client/ conversejs/", "lint:styles": "stylelint 'conversejs/**/*.scss' 'assets/styles/**/*.scss'", "lint:styles:fix": "stylelint 'conversejs/**/*.scss' 'assets/styles/**/*.scss' --fix", diff --git a/server/lib/configuration/bot.ts b/server/lib/configuration/bot.ts index c55e88e7..08c574c0 100644 --- a/server/lib/configuration/bot.ts +++ b/server/lib/configuration/bot.ts @@ -13,7 +13,7 @@ let singleton: BotConfiguration | undefined type RoomConfCache = null // already loaded, but file does not exist - | RoomConf // loaded, and contains the room conf + | RoomConf // loaded, and contains the room conf type ChannelCommonRoomConf = Omit diff --git a/server/lib/configuration/channel/storage.ts b/server/lib/configuration/channel/storage.ts index 2be1f254..096700d0 100644 --- a/server/lib/configuration/channel/storage.ts +++ b/server/lib/configuration/channel/storage.ts @@ -187,8 +187,8 @@ function _getForbiddenWordsHandler ( } else { // Here we must add word-breaks and escape entries. // We join all entries in one Regexp (for the same reason as above). - rule.regexp = '(?:' + - forbiddenWords.entries.map(s => { + rule.regexp = '(?:' + forbiddenWords.entries.map( + s => { s = _stringToWordRegexp(s) // Must add the \b... // ... but... won't work if the first (or last) char is an emoji. @@ -201,7 +201,8 @@ function _getForbiddenWordsHandler ( } // FIXME: this solution wont work for non-latin charsets. return s - }).join(')|(?:') + ')' + } + ).join(')|(?:') + ')' } if (forbiddenWords.reason) { diff --git a/server/lib/conversejs/params.ts b/server/lib/conversejs/params.ts index fee81e86..e2b3641f 100644 --- a/server/lib/conversejs/params.ts +++ b/server/lib/conversejs/params.ts @@ -234,14 +234,14 @@ async function _connectionInfos ( params: GetConverseJSParamsParams, roomInfos: RoomInfos ): Promise<{ - prosodyDomain: string - localAnonymousJID: string - localBoshUri: string - localWsUri: string | null - remoteConnectionInfos: WCRemoteConnectionInfos | undefined - roomJID: string - customEmojisUrl?: string - } | InitConverseJSParamsError> { + prosodyDomain: string + localAnonymousJID: string + localBoshUri: string + localWsUri: string | null + remoteConnectionInfos: WCRemoteConnectionInfos | undefined + roomJID: string + customEmojisUrl?: string +} | InitConverseJSParamsError> { const { video, remoteChatInfos, channelId, roomKey } = roomInfos const prosodyDomain = await getProsodyDomain(options) diff --git a/server/lib/debug.ts b/server/lib/debug.ts index 0ba918f5..9fd39490 100644 --- a/server/lib/debug.ts +++ b/server/lib/debug.ts @@ -27,11 +27,11 @@ interface DebugContent { } type DebugNumericValue = 'renewCertCheckInterval' -| 'renewSelfSignedCertInterval' -| 'logRotateEvery' -| 'logRotateCheckInterval' -| 'remoteServerInfosMaxAge' -| 'externalAccountPruneInterval' + | 'renewSelfSignedCertInterval' + | 'logRotateEvery' + | 'logRotateCheckInterval' + | 'remoteServerInfosMaxAge' + | 'externalAccountPruneInterval' type DebugBooleanValue = 'alwaysPublishXMPPRoom' | 'enablePodcastChatTagForNonLive' | 'useOpenSSL' diff --git a/server/lib/diagnostic/prosody.ts b/server/lib/diagnostic/prosody.ts index a6c32b3a..9bf87646 100644 --- a/server/lib/diagnostic/prosody.ts +++ b/server/lib/diagnostic/prosody.ts @@ -48,7 +48,8 @@ export async function diagProsody (test: string, options: RegisterServerOptions) if (process.arch !== 'x64' && process.arch !== 'x86_64' && process.arch !== 'arm64') { result.messages.push({ level: 'error', - message: 'Error: your CPU is a ' + + message: + 'Error: your CPU is a ' + process.arch + ', ' + 'which is not compatible with the plugin. ' + 'Please read the plugin installation documentation for a workaround.' diff --git a/server/lib/diagnostic/utils.ts b/server/lib/diagnostic/utils.ts index a8d48a80..d4cec2f8 100644 --- a/server/lib/diagnostic/utils.ts +++ b/server/lib/diagnostic/utils.ts @@ -3,8 +3,8 @@ // SPDX-License-Identifier: AGPL-3.0-only type NextValue = 'backend' | 'debug' | 'webchat-video' | 'prosody' -| 'external-auth-custom-oidc' | 'external-auth-google-oidc' | 'external-auth-facebook-oidc' -| 'everything-ok' + | 'external-auth-custom-oidc' | 'external-auth-google-oidc' | 'external-auth-facebook-oidc' + | 'everything-ok' interface MessageWithLevel { level: 'info' | 'warning' | 'error' diff --git a/server/lib/emojis/emojis.ts b/server/lib/emojis/emojis.ts index e8092043..359edd20 100644 --- a/server/lib/emojis/emojis.ts +++ b/server/lib/emojis/emojis.ts @@ -78,12 +78,13 @@ export class Emojis { if (!await this.channelHasCustomEmojis(channelId)) { return undefined } + const route = getBaseRouterRoute(this.options) + + 'emojis/channel/' + + encodeURIComponent(channelId) + + '/definition' return canonicalizePluginUri( this.options, - getBaseRouterRoute(this.options) + - 'emojis/channel/' + - encodeURIComponent(channelId) + - '/definition', + route, { removePluginVersion: true } diff --git a/server/lib/federation/sanitize.ts b/server/lib/federation/sanitize.ts index 45c4bb10..35275e2a 100644 --- a/server/lib/federation/sanitize.ts +++ b/server/lib/federation/sanitize.ts @@ -289,7 +289,7 @@ function _sanitizePeertubeLiveChatInfosV0 ( logger.debug('We are have to migrate data from the old JSONLD format') if (chatInfos === false) { return false } - if (!_assertObjectType(chatInfos)) { return false} + if (!_assertObjectType(chatInfos)) { return false } if (chatInfos.type !== 'xmpp') { return false } if (typeof chatInfos.jid !== 'string') { return false } diff --git a/server/lib/settings.ts b/server/lib/settings.ts index 03805924..1e463809 100644 --- a/server/lib/settings.ts +++ b/server/lib/settings.ts @@ -529,7 +529,7 @@ function initThemingSettings ({ registerSetting }: RegisterServerOptions): void { value: 'peertube', label: loc('converse_theme_option_peertube') }, { value: 'default', label: loc('converse_theme_option_default') }, { value: 'cyberpunk', label: loc('converse_theme_option_cyberpunk') } - ] as Array<{value: ConverseJSTheme, label: string}>, + ] as Array<{ value: ConverseJSTheme, label: string }>, descriptionHTML: loc('converse_theme_description') })