Browse Source

Merge pull request #15227 from nextcloud/fix/noid/eslint-p3

pull/15233/head
Maksim Sukharev 6 months ago
committed by GitHub
parent
commit
772b9d6be5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      .eslintignore
  2. 18
      .git-blame-ignore-revs
  3. 30
      eslint.config.mjs
  4. 74
      package-lock.json
  5. 1
      package.json
  6. 2
      src/components/MessagesList/MessagesGroup/Message/Message.spec.js
  7. 2
      src/components/MessagesList/MessagesGroup/Message/MessagePart/Mention.vue
  8. 2
      src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue
  9. 2
      src/services/certificateService.ts
  10. 92
      src/utils/__tests__/readableNumber.spec.js
  11. 6
      src/utils/debugTimer.ts
  12. 2
      src/utils/e2ee/JitsiE2EEContext.js
  13. 2
      src/utils/e2ee/JitsiEncryptionWorker.worker.js
  14. 4
      src/utils/e2ee/JitsiEncryptionWorkerContext.js
  15. 4
      src/utils/fileUpload.js
  16. 4
      src/utils/media/pipeline/MediaDevicesSource.spec.js
  17. 18
      src/utils/readableNumber.ts

8
.eslintignore

@ -1,8 +0,0 @@
# SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: CC0-1.0
/js/*
/src/types/openapi/*
/src/utils/e2ee/crypto-utils.js
/src/utils/e2ee/Jitsi*.js
/src/utils/media/effects/virtual-background/vendor/*
/tests/*

18
.git-blame-ignore-revs

@ -1,3 +1,21 @@
# .git-blame-ignore-revs
# Update to nextcloud/coding-standard 1.2.3
956a1ab00ffb25d87c0f5192333c9b66e56a63fe
# Update to nextcloud/eslint-config 9.0.0-rc.1
0cefd79e15c25c0be84efdd282db2fd7ed521d7e
5aa4668f98528580c445576b865b087d39a6e950
dc371de6124686747085e2fc7f68a89bd6eb7791
f361c6920b738ff8c6a7356bce141b4c60bd80de
4a67c5b7b48160419077413e789683069c15cb2d
770e38efe565dfd3a727a4956a823e0b2f17dcf8
6ed81e8ba3c767e381e23a70910d862c7ebb4bfc
ccfda0f407958c001598a234bbf0fc92ea04228e
1b3757bfacfa996d094773fd7e571fcdd53ab85b
dcfe2facab60f83e8c9581f785d41ed48c05adcd
777ffd9b0168795014552e85b264981c67ff83f2
5776a5fe6d5a2839e7313d94c2b743a40a469582
b48dfcc48441b0a6f26f2d1e6b3a6ddc262a04ab
08799ed75d4539239eddc9b897cba1b3931ebfe0
49957ae0af4e9c09ab956f4f0781e0dd48edb76c
20d3960b78da17a464a9cb7a120e435771d912b6
e0c0f74870124c7ab82da0150fb25e477b1362fb

30
eslint.config.mjs

@ -4,6 +4,7 @@
*/
import { recommendedVue2 } from '@nextcloud/eslint-config'
import globals from 'globals'
export default [
...recommendedVue2,
@ -11,6 +12,26 @@ export default [
{
ignores: ['src/types/openapi/*'],
},
// Global overrides
{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
IS_DESKTOP: 'readonly',
__webpack_public_path__: 'writable',
},
},
},
// Global overrides for Jest tests and utils
{
files: ['src/__mocks__/*.js', '**/*.spec.js', 'src/test-setup.js'],
languageOptions: {
globals: {
...globals.jest,
},
},
},
// Disabled rules from recommendedVue2 pack
{
rules: {
@ -20,7 +41,6 @@ export default [
'@typescript-eslint/no-unused-expressions': 'off', // non-fixable
'@typescript-eslint/no-unused-vars': 'off', // non-fixable
'@typescript-eslint/no-use-before-define': 'off', // non-fixable
eqeqeq: 'off', // non-fixable
'jsdoc/check-param-names': 'off', // need to respect JS
'jsdoc/check-tag-names': 'off', // need to respect JS
'jsdoc/check-types': 'off', // need to respect JS
@ -30,17 +50,9 @@ export default [
'jsdoc/require-param-description': 'off', // need to respect JS
'jsdoc/tag-lines': 'off', // need to respect JS
'no-console': 'off', // non-fixable
'no-constant-binary-expression': 'off', // non-fixable
'no-constant-condition': 'off', // non-fixable
'no-empty': 'off', // non-fixable
'no-redeclare': 'off', // non-fixable
'no-restricted-imports': 'off', // non-fixable
'no-undef': 'off', // non-fixable
'no-unused-vars': 'off', // non-fixable
'no-use-before-define': 'off', // non-fixable
'no-useless-concat': 'off', // non-fixable
'object-shorthand': 'off', // changes Vue watchers
'prefer-const': 'off', // non-fixable
'prefer-object-has-own': 'off', // changes Objet.prototype.hasOwnProperty
'prefer-object-spread': 'off', // changes Object.assign
'vue/first-attribute-linebreak': 'off', // changes all Vue files

74
package-lock.json

@ -83,6 +83,7 @@
"babel-loader-exclude-node-modules-except": "^1.2.1",
"esbuild-loader": "^4.3.0",
"flush-promises": "^1.0.2",
"globals": "^16.2.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-localstorage-mock": "^2.4.26",
@ -980,6 +981,16 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-transform-classes/node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/plugin-transform-computed-properties": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz",
@ -1828,6 +1839,16 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse/node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/types": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz",
@ -3790,19 +3811,6 @@
"fxparser": "src/cli/cli.js"
}
},
"node_modules/@nextcloud/eslint-config/node_modules/globals": {
"version": "16.1.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
"integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@nextcloud/eslint-config/node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
@ -10135,12 +10143,16 @@
}
},
"node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz",
"integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/globby": {
@ -21297,6 +21309,14 @@
"@babel/helper-replace-supers": "^7.27.1",
"@babel/traverse": "^7.27.1",
"globals": "^11.1.0"
},
"dependencies": {
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true
}
}
},
"@babel/plugin-transform-computed-properties": {
@ -21828,6 +21848,14 @@
"@babel/types": "^7.27.1",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
"dependencies": {
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true
}
}
},
"@babel/types": {
@ -23110,12 +23138,6 @@
"strnum": "^2.1.0"
}
},
"globals": {
"version": "16.1.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz",
"integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==",
"dev": true
},
"semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
@ -27876,9 +27898,9 @@
}
},
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz",
"integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==",
"dev": true
},
"globby": {

1
package.json

@ -99,6 +99,7 @@
"babel-loader-exclude-node-modules-except": "^1.2.1",
"esbuild-loader": "^4.3.0",
"flush-promises": "^1.0.2",
"globals": "^16.2.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-localstorage-mock": "^2.4.26",

2
src/components/MessagesList/MessagesGroup/Message/Message.spec.js

@ -426,7 +426,7 @@ describe('Message.vue', () => {
},
)
expect(messageEl.props('text')).toBe('{file}' + '\n\n' + caption)
expect(messageEl.props('text')).toBe('{file}\n\n' + caption)
})
test('renders deck cards', () => {

2
src/components/MessagesList/MessagesGroup/Message/MessagePart/Mention.vue

@ -148,7 +148,7 @@ export default {
},
mounted() {
this.size = parseInt(window.getComputedStyle(this.$refs.mention).fontSize, 10) * 4 / 3 ?? 20
this.size = parseInt(window.getComputedStyle(this.$refs.mention).fontSize ?? 15, 10) * 4 / 3
},
}
</script>

2
src/components/MessagesList/MessagesGroup/Message/MessagePart/MessageBody.vue

@ -245,7 +245,7 @@ export default {
renderedMessage() {
if (this.isFileShare && this.message.message !== '{file}') {
// Add a new line after file to split content into different paragraphs
return '{file}' + '\n\n' + this.message.message
return '{file}\n\n' + this.message.message
} else {
return this.message.message
}

2
src/services/certificateService.ts

@ -33,7 +33,7 @@ const isCertificateValid = async (host: certificateExpirationParams['host']): Pr
// Null if unable to retrieve the certificates expiration, otherwise the expiration in days (negative if already expired)
const expiration = response.data.ocs.data.expiration_in_days
if (expiration == null) {
if (expiration === null) {
console.warn('Unable to check certificate of', host)
return false
} else if (expiration < 0) {

92
src/utils/__tests__/readableNumber.spec.js

@ -6,60 +6,52 @@ import { readableNumber, stringChop } from '../readableNumber.ts'
describe('readableNumber', () => {
describe('stringChop', () => {
it('should return the correct array of numbers', () => {
const numbers = {
1: { number: '123456789', size: 3 },
2: { number: '12345678', size: 3 },
3: { number: '1234567', size: 3 },
4: { number: '123456', size: 2 },
5: { number: '123456', size: 1 },
6: { number: '123456', size: 0 },
7: { number: '123456', size: 6 },
8: { number: '123456', size: 7 },
9: { number: '', size: 3 },
}
const TEST_CASES = [
['123456789', 3, false, ['123', '456', '789']],
['12345678', 3, false, ['123', '456', '78']],
['1234567', 3, false, ['123', '456', '7']],
['123456', 2, false, ['12', '34', '56']],
['123456', 1, false, ['1', '2', '3', '4', '5', '6']],
['123456', 0, false, ['123456']],
['123456', 6, false, ['123456']],
['123456', 7, false, ['123456']],
['', 3, false, []],
['123456789', 3, true, ['123', '456', '789']],
['12345678', 3, true, ['12', '345', '678']],
['1234567', 3, true, ['1', '234', '567']],
['123456', 2, true, ['12', '34', '56']],
['123456', 1, true, ['1', '2', '3', '4', '5', '6']],
['123456', 0, true, ['123456']],
['123456', 6, true, ['123456']],
['123456', 7, true, ['123456']],
['', 3, true, []],
]
const outputTypes = {
1: ['123', '456', '789'],
2: ['123', '456', '78'],
3: ['123', '456', '7'],
4: ['12', '34', '56'],
5: ['1', '2', '3', '4', '5', '6'],
6: ['123456'],
7: ['123456'],
8: ['123456'],
9: [''],
}
for (const i in numbers) {
const output = i + ': ' + stringChop(numbers[i].number, numbers[i].size)
expect(output).toBe(i + ': ' + outputTypes[i])
}
})
it.each(TEST_CASES)(
'should return correct array for %s with chunk size %d',
(string, size, fromRight, output) => {
expect(output).toMatchObject(stringChop(string, size, fromRight))
},
)
})
describe('readableNumber', () => {
it('should return the correct readable number', () => {
const numbers = {
1: 123456789,
2: '123456789',
3: '12345678',
4: '1234567',
5: '',
}
const outputTypes = {
1: '123 456 789',
2: '123 456 789',
3: '123 456 78',
4: '123 4567',
5: '',
}
const TEST_CASES = [
[123456789, false, '123 456 789'],
['123456789', false, '123 456 789'],
['12345678', false, '123 456 78'],
['12345678', true, '12 345 678'],
['1234567', false, '123 4567'],
['1234567', true, '1 234 567'],
['', false, ''],
['', true, ''],
]
for (const i in numbers) {
const output = i + ': ' + readableNumber(numbers[i])
expect(output).toBe(i + ': ' + outputTypes[i])
}
})
it.each(TEST_CASES)(
'should return correct readable number for %s',
(string, fromRight, output) => {
expect(output).toBe(readableNumber(string, fromRight))
},
)
})
})

6
src/utils/debugTimer.ts

@ -2,6 +2,7 @@
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { readableNumber } from './readableNumber.ts'
const timersPool: Record<string, number> = {}
@ -10,9 +11,8 @@ const getReadable = (time: number) => {
return '--.-- ms'
}
try {
let [int, float] = time.toFixed(2).split('.')
int = int.replace(/\B(?=(\d{3})+(?!\d))/g, ' ')
return `${int}.${float} ms`
const [int, float] = time.toFixed(2).split('.')
return `${readableNumber(int, true)}.${float} ms`
} catch (e) {
console.error(e)
return '--.-- ms'

2
src/utils/e2ee/JitsiE2EEContext.js

@ -6,8 +6,6 @@
* the worker from Nextcloud.
*/
/* global RTCRtpScriptTransform */
import Worker from './JitsiEncryptionWorker.worker.js'
// Flag to set on senders / receivers to avoid setting up the encryption transform

2
src/utils/e2ee/JitsiEncryptionWorker.worker.js

@ -5,8 +5,6 @@
* Based on code from https://github.com/jitsi/jitsi-meet
*/
/* global TransformStream */
// Worker for E2EE/Insertable streams.
import { Context } from './JitsiEncryptionWorkerContext.js'

4
src/utils/e2ee/JitsiEncryptionWorkerContext.js

@ -5,9 +5,7 @@
* Based on code from https://github.com/jitsi/jitsi-meet
*/
/* global BigInt */
import { deriveKeys, importKey, ratchet } from './crypto-utils'
import { deriveKeys, importKey, ratchet } from './crypto-utils.js'
// We use a ringbuffer of keys so we can change them and still decode packets that were
// encrypted with an old key. We use a size of 16 which corresponds to the four bits

4
src/utils/fileUpload.js

@ -72,7 +72,9 @@ const findUniquePath = async function(client, userRoot, path, knownSuffix) {
const fileName = extractFileName(path)
// Loop until a unique path is found
for (let suffix = knownSuffix + 1 || getFileSuffix(path) + 1; true; suffix++) {
let suffix = knownSuffix || getFileSuffix(path)
while (true) {
suffix++
const uniquePath = fileName + ` (${suffix})` + fileExtension
if (await client.exists(userRoot + uniquePath) === false) {
return { uniquePath, suffix }

4
src/utils/media/pipeline/MediaDevicesSource.spec.js

@ -639,6 +639,7 @@ describe('MediaDevicesSource', () => {
try {
await mediaDevicesSource.start(retryNoVideoCallback)
} catch (exception) {
// expected Error: Audio and/or video is required
}
getUserMediaAudioTrack = newMediaStreamTrackMock('audio', 'audio', 'audio-device')
@ -661,6 +662,7 @@ describe('MediaDevicesSource', () => {
try {
await mediaDevicesSource.start(retryNoVideoCallback)
} catch (exception) {
// expected Error: Audio and/or video is required
}
jest.spyOn(mediaDevicesManager, 'getUserMedia').mockImplementationOnce(async (constraints) => {
@ -684,6 +686,7 @@ describe('MediaDevicesSource', () => {
try {
await mediaDevicesSource.start(retryNoVideoCallback)
} catch (exception) {
// expected Error: Audio and/or video is required
}
mediaDevicesSource.setAudioAllowed(false)
@ -928,6 +931,7 @@ describe('MediaDevicesSource', () => {
try {
await mediaDevicesSource.start(retryNoVideoCallback)
} catch (exception) {
// expected Error: Audio and/or video is required
}
mediaDevicesSource.stop()

18
src/utils/readableNumber.ts

@ -11,14 +11,21 @@
*
* @param str The string to chop
* @param size Size of the chunks
* @param fromRight Whether to parse chunks from right side (e.g. a thousand delimiter)
*/
function stringChop(str: string, size: number): string[] {
function stringChop(str: string, size: number, fromRight = false): string[] {
if (size <= 0) {
return [str]
}
const chunks: string[] = []
for (let i = 0; i < str.length; i += size) {
chunks.push(str.slice(i, i + size))
if (fromRight) {
for (let i = str.length; i > 0; i -= size) {
chunks.unshift(str.slice(Math.max(0, i - size), i))
}
} else {
for (let i = 0; i < str.length; i += size) {
chunks.push(str.slice(i, i + size))
}
}
return chunks
@ -33,9 +40,10 @@ function stringChop(str: string, size: number): string[] {
* 9432670284 => 943 267 0284
*
* @param number The number to make readable
* @param fromRight Whether to parse chunks from right side (e.g. a thousand delimiter)
*/
function readableNumber(number: string | number): string {
const chunks = stringChop(number.toString(), 3)
function readableNumber(number: string | number, fromRight = false): string {
const chunks = stringChop(number.toString(), 3, fromRight)
const lastChunk = chunks.pop()
const shouldConcatLastChunk = !lastChunk?.length || lastChunk.length <= 1

Loading…
Cancel
Save