Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion lib/configs/codeStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import type { Linter } from 'eslint'
import type { ConfigOptions } from '../types.d.ts'

Expand All @@ -20,7 +21,11 @@ import l10nPlugin from '../plugins/l10n/index.ts'
*
* @param options options defining the config preset flavor
*/
export function codeStyle(options: ConfigOptions): (Linter.Config | Linter.BaseConfig)[] {
export function codeStyle(options: ConfigOptions): Linter.Config[] {
if (options.formatting === false) {
return []
}

return [
// Nextcloud code style
{
Expand Down
5 changes: 5 additions & 0 deletions lib/configs/documentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import type { Linter } from 'eslint'
import type { Settings } from 'eslint-plugin-jsdoc/iterateJsdoc.js'
import type { ConfigOptions } from '../types.d.ts'
Expand Down Expand Up @@ -41,6 +42,10 @@ const SHARED_JSDOC_SETTINGS: Partial<Settings> = {
* @param options options defining the config preset flavor
*/
export function documentation(options: ConfigOptions): Linter.Config[] {
if (options.linting === false) {
return []
}

return [
{
...jsdoc({
Expand Down
39 changes: 22 additions & 17 deletions lib/configs/filesystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,31 @@
*/

import type { Linter } from 'eslint'
import type { ConfigOptions } from '../types.d.ts'

import gitignore from 'eslint-config-flat-gitignore'

/**
* General config to exclude known non-source directories from linting
*
* @param options - Configuration options
*/
export const filesystem: Linter.Config[] = [
{
...gitignore(),
name: 'nextcloud/filesystem/gitignore',
},
{
name: 'nextcloud/filesystem/ignores',
ignores: [
'dist/',
'js/',
'l10n/',
'vendor/',
'vendor-bin/',
'**/package-lock.json',
],
},
]
export function filesystem(options: ConfigOptions): Linter.Config[] { // eslint-disable-line @typescript-eslint/no-unused-vars
return [
{
...gitignore(),
name: 'nextcloud/filesystem/gitignore',
},
{
name: 'nextcloud/filesystem/ignores',
ignores: [
'dist/',
'js/',
'l10n/',
'vendor/',
'vendor-bin/',
'**/package-lock.json',
],
},
]
}
130 changes: 69 additions & 61 deletions lib/configs/imports.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { Linter } from 'eslint'
/*!
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import type { Linter } from 'eslint'
import type { ConfigOptions } from '../types.d.ts'

import perfectionist from 'eslint-plugin-perfectionist'
Expand All @@ -18,14 +19,76 @@ import importExtensions from '../plugins/import-extensions/index.ts'
*
* @param options - Configuration options
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function imports(options: ConfigOptions): Linter.Config[] {
const lintingRules: Partial<Linter.RulesRecord> = {
// Require file extensions
'import-extensions/extensions': 'error',
}

const formattingRules: Partial<Linter.RulesRecord> = {
// Sorting of imports
'sort-imports': 'off' as const,
'perfectionist/sort-imports': [
'error',
{
type: 'natural',
newlinesBetween: 'never',
groups: [
// type first
'external-type',
'type',
{ newlinesBetween: 'always' },
// external things
[
'builtin',
'external',
'object',
],
// Vue components
'vue', // external modules (e.g. nextcloud-vue)
'internalVue', // internal local vue components
// everything else which is everything internal
'unknown',
{ newlinesBetween: 'always' },
// side effect only: import 'sideeffect.js'
'side-effect',
// import style from 'my.module.css'
'style',
],
customGroups: [
{
groupName: 'vue',
selector: 'external',
modifiers: ['value'],
elementNamePattern: [
'\\.vue$',
'@nextcloud/vue/components/',
],
},
{
groupName: 'internalVue',
modifiers: ['value'],
elementNamePattern: ['\\.vue$'],
},
],
},
],
'perfectionist/sort-named-exports': [
'error',
createSortingConfig('export'),
],
'perfectionist/sort-named-imports': [
'error',
createSortingConfig('import'),
],
}

return [
{
name: 'nextcloud/imports/setup',
plugins: {
perfectionist,
'import-extensions': importExtensions,
...(options.formatting ? { perfectionist } : {}),
...(options.linting ? { 'import-extensions': importExtensions } : {}),
},
},
{
Expand All @@ -36,63 +99,8 @@ export function imports(options: ConfigOptions): Linter.Config[] {
...GLOB_FILES_VUE,
],
rules: {
// Require file extensions
'import-extensions/extensions': 'error',
// Sorting of imports
'sort-imports': 'off',
'perfectionist/sort-imports': [
'error',
{
type: 'natural',
newlinesBetween: 'never',
groups: [
// type first
'external-type',
'type',
{ newlinesBetween: 'always' },
// external things
[
'builtin',
'external',
'object',
],
// Vue components
'vue', // external modules (e.g. nextcloud-vue)
'internalVue', // internal local vue components
// everything else which is everything internal
'unknown',
{ newlinesBetween: 'always' },
// side effect only: import 'sideeffect.js'
'side-effect',
// import style from 'my.module.css'
'style',
],
customGroups: [
{
groupName: 'vue',
selector: 'external',
modifiers: ['value'],
elementNamePattern: [
'\\.vue$',
'@nextcloud/vue/components/',
],
},
{
groupName: 'internalVue',
modifiers: ['value'],
elementNamePattern: ['\\.vue$'],
},
],
},
],
'perfectionist/sort-named-exports': [
'error',
createSortingConfig('export'),
],
'perfectionist/sort-named-imports': [
'error',
createSortingConfig('import'),
],
...(options.linting ? lintingRules : {}),
...(options.formatting ? formattingRules : {}),
},
},
]
Expand Down
92 changes: 92 additions & 0 deletions lib/configs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*!
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { ConfigOptions } from '../types.d.ts'

import { codeStyle } from './codeStyle.ts'
import { documentation } from './documentation.ts'
import { filesystem } from './filesystem.ts'
import { imports } from './imports.ts'
import { javascript } from './javascript.ts'
import { json } from './json.ts'
import { node } from './node.ts'
import { typescript } from './typescript.ts'
import { vue2 } from './vue2.ts'
import { vue3 } from './vue3.ts'

/**
* Nextcloud shared configuration for projects using Vue 2 with Javascript <script> blocks
*/
export const recommendedVue2Javascript = createConfig({
isLibrary: false,
vue2: true,
vueIsTypescript: false,
})

/**
* Nextcloud shared configuration for projects using Vue 2 with Typescript <script> blocks
*/
export const recommendedVue2 = createConfig({
isLibrary: false,
vue2: true,
vueIsTypescript: true,
})

/**
* Nextcloud shared configuration for projects using Vue 3 with Javascript <script> blocks
*/
export const recommendedJavascript = createConfig({
isLibrary: false,
vueIsTypescript: false,
})

/**
* Nextcloud shared configuration for projects using Vue 3 with Typescript <script> blocks
*/
export const recommended = createConfig({
isLibrary: false,
vueIsTypescript: true,
})

/**
* Nextcloud shared configuration for projects using Vue 3 with Typescript <script> blocks
*/
export const recommendedLibrary = createConfig({
isLibrary: true,
vueIsTypescript: true,
})

/**
* Nextcloud shared configuration for projects using Vue 3 with Typescript <script> blocks
*/
export const recommendedVue2Library = createConfig({
isLibrary: true,
vue2: true,
vueIsTypescript: true,
})

/**
* Generate a configuration based on given options
*
* @param options - Configuration options
*/
export function createConfig(options: ConfigOptions & { vue2?: boolean }) {
options = { formatting: true, linting: true, vue2: false, ...options }

return [
...filesystem(options),
...javascript(options),
...json(options),
...node(options),
...typescript(options),
...(
options.vue2
? vue2(options)
: vue3(options)
),
...documentation(options),
...imports(options),
...codeStyle(options),
]
}
4 changes: 4 additions & 0 deletions lib/configs/javascript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import nextcloudPlugin from '../plugins/nextcloud/index.ts'
* @param options - Configuration options
*/
export function javascript(options: ConfigOptions): Linter.Config[] {
if (options.linting === false) {
return []
}

return [
{
name: 'nextcloud/javascript/setup',
Expand Down
Loading
Loading