diff --git a/.circleci/template.yml b/.circleci/template.yml index e9f0501b7bb..46d57cd1cb2 100644 --- a/.circleci/template.yml +++ b/.circleci/template.yml @@ -148,6 +148,11 @@ jobs: when: always name: Check if all packages are exported in the "ckeditor5" package command: yarn run check-exports + - run: + when: always + name: Check if all editor icon SVGs are properly defined + working_directory: external/ckeditor5-commercial + command: yarn run validate-svg-icons cke5_coverage: machine: true diff --git a/package.json b/package.json index c9f6b77531e..0e7fceb6466 100644 --- a/package.json +++ b/package.json @@ -212,6 +212,7 @@ "release:clean": "node ./scripts/release/clean.mjs", "clean-up-svg-icons": "node ./scripts/clean-up-svg-icons.mjs", "collect-svg-icons": "node scripts/collect-svg-icons.mjs", + "validate-svg-icons": "node scripts/ci/validate-svg-icons.mjs", "check-dependencies": "ckeditor5-dev-dependency-checker", "check-dependencies:versions-match": "node ./scripts/ci/check-dependencies-versions-match.mjs", "check-theme-lark-imports": "node ./scripts/check-theme-lark-imports.mjs", diff --git a/scripts/ci/validate-svg-icons.mjs b/scripts/ci/validate-svg-icons.mjs new file mode 100644 index 00000000000..acfa9c7c10d --- /dev/null +++ b/scripts/ci/validate-svg-icons.mjs @@ -0,0 +1,59 @@ +#!/usr/bin/env node + +/** + * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options + */ + +/* eslint-env node */ + +// This script aims to verify whether all editor SVG icons are valid. Current criteria are: +// - SVG icon should have a defined `viewBox` +// - double quotation marks (") are enforced over single ones (') + +import fs from 'fs-extra'; +import upath from 'upath'; +import { glob } from 'glob'; + +const svgPaths = glob.sync( upath.join( process.cwd(), 'packages', '*', 'theme', 'icons', '*.svg' ) ).sort(); + +const singleQuotationMarksUsed = []; +const missingViewBox = []; + +svgPaths.forEach( path => { + const file = fs.readFileSync( path, 'utf-8' ); + + const SVGs = file.match( //g ); + + if ( SVGs.length === 0 ) { + throw new Error( `No SVG defined in file: ${ path }` ); + } + + if ( SVGs.length > 1 ) { + throw new Error( `Multiple SVGs defined in file: ${ path }` ); + } + + const SVG = SVGs[ 0 ]; + + if ( SVG.match( '\'' ) ) { + singleQuotationMarksUsed.push( path ); + } + + if ( !SVG.match( 'viewBox=' ) ) { + missingViewBox.push( path ); + } +} ); + +if ( singleQuotationMarksUsed.length ) { + console.log( '\nFollowing editor icons have used single quotation marks instead of double ones:' ); + console.log( singleQuotationMarksUsed.map( path => ` - ${ path }` ).join( '\n' ) ); +} + +if ( missingViewBox.length ) { + console.log( '\nFollowing editor icons are missing `viewBox`:' ); + console.log( missingViewBox.map( path => ` - ${ path }` ).join( '\n' ) ); +} + +if ( [ ...singleQuotationMarksUsed, ...missingViewBox ].length ) { + process.exit( 1 ); +}