diff --git a/docs/framework/contributing/code-style.md b/docs/framework/contributing/code-style.md index 656f07a37dc..7505f7f48fa 100644 --- a/docs/framework/contributing/code-style.md +++ b/docs/framework/contributing/code-style.md @@ -1224,3 +1224,7 @@ import { AIAssistant } from 'ckeditor5-premium-features'; ### SVG imports only in the `@ckeditor/ckeditor5-icons` package This rule ensures that SVG files are imported and exported only in the `@ckeditor/ckeditor5-icons` package. This package should include all icons used in CKEditor 5. + +### Valid changelog entries + +This rule ensures that changelog entry files are populated with proper data and a clear description of the change. For a full guide on how to populate changelog entries, see the {@link framework/contributing/changelog-entries Changelog entries} guide. diff --git a/eslint.config.mjs b/eslint.config.mjs index 138a4d6f836..66b33d9add2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -3,23 +3,29 @@ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options */ +import { readdirSync } from 'fs'; import globals from 'globals'; import { defineConfig } from 'eslint/config'; import ckeditor5Rules from 'eslint-plugin-ckeditor5-rules'; import ckeditor5Config from 'eslint-config-ckeditor5'; import ts from 'typescript-eslint'; import eslintPluginImport from 'eslint-plugin-import'; - import rootPkgJson from './package.json' with { type: 'json' }; +import { CKEDITOR5_PACKAGES_PATH } from './scripts/constants.mjs'; const disallowedImports = Object.keys( rootPkgJson.devDependencies ).filter( pkgName => { return pkgName.match( /^(@ckeditor\/)?ckeditor5-(?!dev-)/ ); } ); +const projectPackages = readdirSync( CKEDITOR5_PACKAGES_PATH, { withFileTypes: true } ) + .filter( dirent => dirent.isDirectory() ) + .map( dirent => dirent.name ); + export default defineConfig( [ { ignores: [ '.*/', + '!.changelog/', 'build/**', 'coverage/**', 'dist/**', @@ -179,5 +185,24 @@ export default defineConfig( [ rules: { 'ckeditor5-rules/ckeditor-imports': 'off' } + }, + { + extends: ckeditor5Config, + + files: [ '.changelog/**/*.md' ], + + plugins: { + 'ckeditor5-rules': ckeditor5Rules + }, + + rules: { + 'ckeditor5-rules/validate-changelog-entry': [ 'error', { + allowedScopes: [ + ...projectPackages, + 'ckeditor5' + ], + repositoryType: 'mono' + } ] + } } ] ); diff --git a/scripts/constants.mjs b/scripts/constants.mjs index d9e7e5360f2..4a810c3bd93 100644 --- a/scripts/constants.mjs +++ b/scripts/constants.mjs @@ -4,14 +4,13 @@ */ import upath from 'upath'; -import { fileURLToPath } from 'url'; import { PACKAGES_DIRECTORY } from './release/utils/constants.mjs'; -const __filename = fileURLToPath( import.meta.url ); -const __dirname = upath.dirname( __filename ); -export const CKEDITOR5_ROOT_PATH = upath.join( __dirname, '..' ); +export const CKEDITOR5_ROOT_PATH = upath.join( import.meta.dirname, '..' ); +export const CKEDITOR5_PACKAGES_PATH = upath.join( CKEDITOR5_ROOT_PATH, PACKAGES_DIRECTORY ); export const CKEDITOR5_COMMERCIAL_PATH = upath.join( CKEDITOR5_ROOT_PATH, 'external', 'ckeditor5-commercial' ); -export const CKEDITOR5_PREMIUM_FEATURES_PATH = upath.join( CKEDITOR5_COMMERCIAL_PATH, PACKAGES_DIRECTORY, 'ckeditor5-premium-features' ); +export const CKEDITOR5_COMMERCIAL_PACKAGES_PATH = upath.join( CKEDITOR5_COMMERCIAL_PATH, PACKAGES_DIRECTORY ); +export const CKEDITOR5_PREMIUM_FEATURES_PATH = upath.join( CKEDITOR5_COMMERCIAL_PACKAGES_PATH, 'ckeditor5-premium-features' ); export const CKEDITOR5_INDEX = upath.join( CKEDITOR5_ROOT_PATH, 'src', 'index.ts' ); export const CKEDITOR5_PREMIUM_FEATURES_INDEX = upath.join( CKEDITOR5_PREMIUM_FEATURES_PATH, 'src', 'index.ts' );