summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLouis Chemineau <louis@chmn.me>2023-01-16 10:14:51 +0100
committerLouis Chemineau <louis@chmn.me>2023-01-16 10:57:30 +0100
commit5980519712a5b0f081826650a6d8bfda2d858695 (patch)
tree58d675471f7d311a5097a40a4a34b5945db4a266
parentb7423e9cbb30a4695f332fbc76bf619bd648abe6 (diff)
Add workflow for es and style lint
Signed-off-by: Louis Chemineau <louis@chmn.me>
-rw-r--r--.eslintrc.js8
-rw-r--r--.github/workflows/lint-eslint.yml46
-rw-r--r--.github/workflows/lint-stylelint.yml46
-rw-r--r--src/components/Composer/Composer.vue2
-rw-r--r--src/components/Emoji.vue7
-rw-r--r--src/components/MessageContent.js52
-rw-r--r--src/components/TimelinePost.vue4
-rw-r--r--src/directives/focusOnCreate.js8
-rw-r--r--src/main.js2
-rw-r--r--src/mixins/accountMixins.js12
-rw-r--r--src/mixins/serverData.js26
-rw-r--r--src/oauth.js3
-rw-r--r--src/router.js2
-rw-r--r--src/store/account.js18
-rw-r--r--src/store/index.js8
-rw-r--r--src/store/settings.js3
-rw-r--r--src/store/timeline.js6
-rw-r--r--src/views/OAuth2Authorize.vue2
-rw-r--r--src/views/Timeline.vue2
19 files changed, 184 insertions, 73 deletions
diff --git a/.eslintrc.js b/.eslintrc.js
index 89bcc517..e1468702 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,8 +1,8 @@
module.exports = {
extends: [
- '@nextcloud'
+ '@nextcloud',
],
globals: {
- appName: true
- }
-};
+ appName: true,
+ },
+}
diff --git a/.github/workflows/lint-eslint.yml b/.github/workflows/lint-eslint.yml
new file mode 100644
index 00000000..c08763ea
--- /dev/null
+++ b/.github/workflows/lint-eslint.yml
@@ -0,0 +1,46 @@
+# This workflow is provided via the organization template repository
+#
+# https://github.com/nextcloud/.github
+# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
+
+name: Lint
+
+on: pull_request
+
+permissions:
+ contents: read
+
+concurrency:
+ group: lint-eslint-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ name: eslint
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Read package.json node and npm engines version
+ uses: skjnldsv/read-package-engines-version-actions@v1.2
+ id: versions
+ with:
+ fallbackNode: '^12'
+ fallbackNpm: '^6'
+
+ - name: Set up node ${{ steps.versions.outputs.nodeVersion }}
+ uses: actions/setup-node@v3
+ with:
+ node-version: ${{ steps.versions.outputs.nodeVersion }}
+
+ - name: Set up npm ${{ steps.versions.outputs.npmVersion }}
+ run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Lint
+ run: npm run lint
diff --git a/.github/workflows/lint-stylelint.yml b/.github/workflows/lint-stylelint.yml
new file mode 100644
index 00000000..17b7aebb
--- /dev/null
+++ b/.github/workflows/lint-stylelint.yml
@@ -0,0 +1,46 @@
+# This workflow is provided via the organization template repository
+#
+# https://github.com/nextcloud/.github
+# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
+
+name: Lint
+
+on: pull_request
+
+permissions:
+ contents: read
+
+concurrency:
+ group: lint-stylelint-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ name: stylelint
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+
+ - name: Read package.json node and npm engines version
+ uses: skjnldsv/read-package-engines-version-actions@v1.2
+ id: versions
+ with:
+ fallbackNode: '^12'
+ fallbackNpm: '^6'
+
+ - name: Set up node ${{ steps.versions.outputs.nodeVersion }}
+ uses: actions/setup-node@v3
+ with:
+ node-version: ${{ steps.versions.outputs.nodeVersion }}
+
+ - name: Set up npm ${{ steps.versions.outputs.npmVersion }}
+ run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Lint
+ run: npm run stylelint
diff --git a/src/components/Composer/Composer.vue b/src/components/Composer/Composer.vue
index fc33ac23..c5bb230c 100644
--- a/src/components/Composer/Composer.vue
+++ b/src/components/Composer/Composer.vue
@@ -126,7 +126,7 @@
<template #icon>
<Send title="" :size="22" decorative />
</template>
- <template>{{ postTo }}</template>
+ {{ postTo }}
</NcButton>
</div>
</form>
diff --git a/src/components/Emoji.vue b/src/components/Emoji.vue
index 9964413f..a4eab5ae 100644
--- a/src/components/Emoji.vue
+++ b/src/components/Emoji.vue
@@ -22,12 +22,19 @@ export default {
return {}
},
computed: {
+ /**
+ * @return {string}
+ */
icon() {
return twemoji.convert.toCodePoint(this.emoji.indexOf(U200D) < 0
? this.emoji.replace(UFE0Fg, '')
: this.emoji
)
},
+
+ /**
+ * @return {string}
+ */
emojiUrl() {
return generateFilePath('social', 'img', 'twemoji/' + this.icon + '.svg')
},
diff --git a/src/components/MessageContent.js b/src/components/MessageContent.js
index c297c8d3..ff8ccbac 100644
--- a/src/components/MessageContent.js
+++ b/src/components/MessageContent.js
@@ -1,6 +1,12 @@
import Vue from 'vue'
import Emoji from './Emoji.vue'
+/**
+ * @typedef {object} MessageSource
+ * @property {Array} tag
+ * @property {string} content
+ */
+
export default Vue.component('MessageContent', {
props: {
source: {
@@ -23,8 +29,8 @@ export default Vue.component('MessageContent', {
*
* All attributes other than `href` for links are stripped from the source
*
- * @param createElement
- * @param source
+ * @param {Function} createElement
+ * @param {MessageSource} source
*/
export function formatMessage(createElement, source) {
if (!source.tag) {
@@ -42,9 +48,9 @@ export function formatMessage(createElement, source) {
/**
*
- * @param createElement
- * @param node
- * @param context
+ * @param {Function} createElement
+ * @param {HTMLElement} node
+ * @param {object} context
*/
function domToVue(createElement, node, context) {
switch (node.tagName) {
@@ -55,9 +61,10 @@ function domToVue(createElement, node, context) {
case 'SPAN':
return cleanCopy(createElement, node, context)
case 'A':
+ // @ts-ignore - if tagName === 'A' then node is instance of HTMLLinkElement
return cleanLink(createElement, node, context)
default:
- return transformText(createElement, node.textContent)
+ return transformText(createElement, node.textContent ?? '')
}
}
@@ -66,8 +73,8 @@ const hashTagRegex = /(\W|^)(#\w+)/i
/**
*
- * @param createElement
- * @param text
+ * @param {Function} createElement
+ * @param {string} text
*/
function transformText(createElement, text) {
return transformTextRegex(text, [
@@ -124,9 +131,9 @@ function transformText(createElement, text) {
/**
* copy a node without any attributes and cleaning all children
*
- * @param createElement
- * @param node
- * @param context
+ * @param {Function} createElement
+ * @param {HTMLElement} node
+ * @param {object} context
*/
function cleanCopy(createElement, node, context) {
const children = Array.from(node.childNodes).map(node => domToVue(createElement, node, context))
@@ -135,17 +142,18 @@ function cleanCopy(createElement, node, context) {
/**
*
- * @param createElement
- * @param node
- * @param context
+ * @param {Function} createElement
+ * @param {HTMLLinkElement} node
+ * @param {object} context
+ * @param {Array} context.mentions
*/
function cleanLink(createElement, node, context) {
const type = getLinkType(node.className)
const attributes = {}
+ const tag = matchMention(context.mentions, node.getAttribute('href') ?? '', node.textContent ?? '')
switch (type) {
case 'mention':
- var tag = matchMention(context.mentions, node.getAttribute('href'), node.textContent)
if (tag) {
attributes.rel = 'nofollow noopener noreferrer'
attributes.target = '_blank'
@@ -163,7 +171,7 @@ function cleanLink(createElement, node, context) {
props: {
to: {
name: 'tags',
- params: { tag: node.textContent.slice(1) },
+ params: { tag: node.textContent?.slice(1) },
},
},
},
@@ -180,7 +188,7 @@ function cleanLink(createElement, node, context) {
/**
*
- * @param className
+ * @param {string} className
*/
function getLinkType(className) {
const parts = className.split(' ')
@@ -195,9 +203,9 @@ function getLinkType(className) {
/**
*
- * @param tags
- * @param mentionHref
- * @param mentionText
+ * @param {Array} tags
+ * @param {string} mentionHref
+ * @param {string} mentionText
*/
function matchMention(tags, mentionHref, mentionText) {
const mentionUrl = new URL(mentionHref)
@@ -225,8 +233,8 @@ const emojiRe = /(?:\ud83d\udc68\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68
/**
*
- * @param text
- * @param handlers
+ * @param {string} text
+ * @param {Array} handlers
*/
function transformTextRegex(text, handlers) {
const parts = []
diff --git a/src/components/TimelinePost.vue b/src/components/TimelinePost.vue
index ccbd06fb..05809747 100644
--- a/src/components/TimelinePost.vue
+++ b/src/components/TimelinePost.vue
@@ -91,7 +91,6 @@ import HeartOutline from 'vue-material-design-icons/HeartOutline.vue'
import logger from '../services/logger.js'
import moment from '@nextcloud/moment'
import { generateUrl } from '@nextcloud/router'
-import RichText from '@nextcloud/vue-richtext'
import MessageContent from './MessageContent.js'
export default {
@@ -105,7 +104,6 @@ export default {
Reply,
Heart,
HeartOutline,
- RichText,
MessageContent,
},
mixins: [currentUser],
@@ -154,7 +152,7 @@ export default {
},
methods: {
/**
- * @param e
+ * @param {MouseEvent} e - The click event
* @function getSinglePostTimeline
* @description Opens the timeline of the post clicked
*/
diff --git a/src/directives/focusOnCreate.js b/src/directives/focusOnCreate.js
index c68568bd..e61b6fdc 100644
--- a/src/directives/focusOnCreate.js
+++ b/src/directives/focusOnCreate.js
@@ -1,9 +1,9 @@
-/*
+/**
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
- * @license GNU AGPL version 3 or any later version
+ * @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -20,11 +20,11 @@
*
*/
-import Vue from 'vue'
+import { nextTick } from 'vue'
export default {
bind(el) {
- Vue.nextTick(() => {
+ nextTick(() => {
el.focus()
})
},
diff --git a/src/main.js b/src/main.js
index deee8a7c..979e8e7b 100644
--- a/src/main.js
+++ b/src/main.js
@@ -3,7 +3,7 @@
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
- * @license GNU AGPL version 3 or any later version
+ * @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
diff --git a/src/mixins/accountMixins.js b/src/mixins/accountMixins.js
index a4805860..238eb97e 100644
--- a/src/mixins/accountMixins.js
+++ b/src/mixins/accountMixins.js
@@ -1,9 +1,9 @@
-/*
+/**
* @copyright Copyright (c) 2019 Cyrille Bollu <cyrpub@bollu.be>
*
* @author Cyrille Bollu <cyrpub@bollu.be>
*
- * @license GNU AGPL version 3 or any later version
+ * @license AGPL-3.0-or-later
*
* @file provides global account related methods
*
@@ -31,16 +31,18 @@ export default {
serverData,
],
computed: {
- /** @function Returns the complete account name */
+ /** @return {string} the complete account name */
profileAccount() {
return (this.uid.indexOf('@') === -1) ? this.uid + '@' + this.hostname : this.uid
},
- /** @functions Returns detailed information about an account (account must be loaded in the store first) */
+
+ /** @return detailed information about an account (account must be loaded in the store first) */
accountInfo() {
return this.$store.getters.getAccount(this.profileAccount)
},
+
/**
- * @function Somewhat duplicate with accountInfo(), but needed (for some reason) to avoid glitches
+ * Somewhat duplicate with accountInfo(), but needed (for some reason) to avoid glitches
* where components would first show "user not found" before display an account's account info
*/
accountLoaded() {
diff --git a/src/mixins/serverData.js b/src/mixins/serverData.js
index d0b60bda..d7bebb2b 100644
--- a/src/mixins/serverData.js
+++ b/src/mixins/serverData.js
@@ -1,4 +1,4 @@
-/*
+/**
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
*
* @file Provides global methods for using the serverData structure.
@@ -7,7 +7,7 @@
*
* @author Julius Härtl <jus@bitgrid.net>
*
- * @license GNU AGPL version 3 or any later version
+ * @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -24,18 +24,22 @@
*
*/
+/**
+ * @typedef {object} ServerData
+ * @property {string} account - The account that the user wants to follow (Only in 'OStatus.vue')
+ * @property {string} cliUrl
+ * @property {string} cloudAddress
+ * @property {boolean} firstrun
+ * @property {boolean} isAdmin
+ * @property {string} local - The local part of the account that the user wants to follow
+ * @property {boolean} public - False when the page is accessed by an authenticated user. True otherwise
+ * @property setup
+ */
+
export default {
computed: {
/**
- * @description Returns the serverData object
- * @property {string} account - The account that the user wants to follow (Only in 'OStatus.vue')
- * @property cliUrl
- * @property cloudAddress
- * @property firstrun
- * @property isAdmin
- * @property {string} local - The local part of the account that the user wants to follow
- * @property {boolean} public - False when the page is accessed by an authenticated user. True otherwise
- * @property setup
+ * @return {Partial<ServerData>} Returns the serverData object
*/
serverData() {
if (!this.$store) {
diff --git a/src/oauth.js b/src/oauth.js
index 7138183e..9d4120a3 100644
--- a/src/oauth.js
+++ b/src/oauth.js
@@ -1,6 +1,7 @@
/**
* @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- * @license GNU AGPL version 3 or any later version
+ *
+ * @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
diff --git a/src/router.js b/src/router.js
index ab82bbfd..08af4fef 100644
--- a/src/router.js
+++ b/src/router.js
@@ -5,7 +5,7 @@
* @author Julius Härtl <jus@bitgrid.net>
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
- * @license GNU AGPL version 3 or any later version
+ * @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
diff --git a/src/store/account.js b/src/store/account.js
index 7f35e00a..a4dee30f 100644
--- a/src/store/account.js
+++ b/src/store/account.js
@@ -1,9 +1,9 @@
-/*
+/**
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
- * @license GNU AGPL version 3 or any later version
+ * @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -21,7 +21,7 @@
*/
import axios from '@nextcloud/axios'
-import Vue from 'vue'
+import { set } from 'vue'
import { generateUrl } from '@nextcloud/router'
const state = {
@@ -30,7 +30,7 @@ const state = {
accountIdMap: {},
}
const addAccount = (state, { actorId, data }) => {
- Vue.set(state.accounts, actorId, Object.assign({
+ set(state.accounts, actorId, Object.assign({
followersList: [],
followingList: [],
details: {
@@ -38,7 +38,7 @@ const addAccount = (state, { actorId, data }) => {
follower: false,
},
}, state.accounts[actorId], data))
- Vue.set(state.accountIdMap, data.account, data.id)
+ set(state.accountIdMap, data.account, data.id)
}
const _getActorIdForAccount = (account) => state.accountIdMap[account]
@@ -61,7 +61,7 @@ const mutations = {
})
}
}
- Vue.set(state.accounts[_getActorIdForAccount(account)], 'followersList', users)
+ set(state.accounts[_getActorIdForAccount(account)], 'followersList', users)
},
addFollowing(state, { account, data }) {
const users = []
@@ -75,13 +75,13 @@ const mutations = {
})
}
}
- Vue.set(state.accounts[_getActorIdForAccount(account)], 'followingList', users)
+ set(state.accounts[_getActorIdForAccount(account)], 'followingList', users)
},
followAccount(state, accountToFollow) {
- Vue.set(state.accounts[_getActorIdForAccount(accountToFollow)].details, 'following', true)
+ set(state.accounts[_getActorIdForAccount(accountToFollow)].details, 'following', true)
},
unfollowAccount(state, accountToUnfollow) {
- Vue.set(state.accounts[_getActorIdForAccount(accountToUnfollow)].details, 'following', false)
+ set(state.accounts[_getActorIdForAccount(accountToUnfollow)].details, 'following', false)
},
}
diff --git a/src/store/index.js b/src/store/index.js
index c51e562e..40b51949 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,10 +1,10 @@
-/*
+/**
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
* @author Julius Härtl <jus@bitgrid.net>
*
- * @license GNU AGPL version 3 or any later version
+ * @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -22,7 +22,7 @@
*/
import Vue from 'vue'
-import Vuex from 'vuex'
+import Vuex, { Store } from 'vuex'
import timeline from './timeline.js'
import account from './account.js'
import settings from './settings.js'
@@ -31,7 +31,7 @@ Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production'
-export default new Vuex.Store({
+export default new Store({
modules: {
timeline,
account,
diff --git a/src/store/settings.js b/src/store/settings.js
index 87c66e8b..8616e5cc 100644
--- a/src/store/settings.js
+++ b/src/store/settings.js
@@ -36,6 +36,5 @@ const getters = {
return state.serverData
},
}
-const actions = {}
-export default { state, mutations, getters, actions }
+export default { state, mutations, getters }
diff --git a/src/store/timeline.js b/src/store/timeline.js
index 9ea012ed..0a14fe98 100644
--- a/src/store/timeline.js
+++ b/src/store/timeline.js
@@ -1,4 +1,4 @@
-/*
+/**
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
*
* @file Timeline related store
@@ -6,7 +6,7 @@
* @author Julius Härtl <jus@bitgrid.net>
* @author Jonas Sulzer <jonas@violoncello.ch>
*
- * @license GNU AGPL version 3 or any later version
+ * @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -30,7 +30,7 @@ import { generateUrl } from '@nextcloud/router'
/**
* @property {object} timeline - The posts' collection
- * @property {int} since - Time (EPOCH) of the most recent post
+ * @property {number} since - Time (EPOCH) of the most recent post
* @property {string} type - Timeline's type: 'home', 'single-post',...
* @property {object} params - Timeline's parameters
* @property {string} account -
diff --git a/src/views/OAuth2Authorize.vue b/src/views/OAuth2Authorize.vue
index 01041d5a..7ce535d9 100644
--- a/src/views/OAuth2Authorize.vue
+++ b/src/views/OAuth2Authorize.vue
@@ -28,7 +28,7 @@
name="requesttoken"
:value="OC.requestToken">
<div class="button-row">
- <NcButton type="primary" nativeType="submit">
+ <NcButton type="primary" native-type="submit">
{{ t('social', 'Authorize') }}
</NcButton>
<NcButton type="error" :href="homeUrl">
diff --git a/src/views/Timeline.vue b/src/views/Timeline.vue
index 8e4585e8..1dcf9dd3 100644
--- a/src/views/Timeline.vue
+++ b/src/views/Timeline.vue
@@ -4,7 +4,7 @@
<div v-if="showInfo" class="social__welcome">
<a class="close icon-close" href="#" @click="hideInfo()">
<span class="hidden-visually">
- Close
+ {{ t('social', 'Close') }}
</span>
</a>
<h2>🎉 {{ t('social', 'Nextcloud becomes part of the federated social networks!') }}</h2>