diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4aadeded..1469b477 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -6,7 +6,7 @@ on: pull_request: branches: [ "main" ] schedule: - - cron: '0 6 * * 1' # Every Monday 06:00 UTC + - cron: '0 6 * * 1' workflow_dispatch: concurrency: @@ -30,11 +30,11 @@ jobs: matrix: include: - language: csharp - build-mode: autobuild # Best for .NET + build-mode: manual - language: javascript-typescript - build-mode: none # For gulp / package.json / Playwright + build-mode: none - language: actions - build-mode: none # For .github/workflows/*.yml + build-mode: none steps: - name: Checkout repository @@ -47,15 +47,35 @@ jobs: with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - # Uncomment if you want extra queries later: - # queries: security-extended,security-and-quality - # Only needed when build-mode is "manual" - - name: Manual build (csharp) + - name: Setup .NET + if: matrix.language == 'csharp' + uses: actions/setup-dotnet@v6 + with: + dotnet-version: | + 8.x + 9.x + 10.x + + - name: Setup Node.js + if: matrix.language == 'csharp' + uses: actions/setup-node@v7 + with: + node-version: '22' + cache: 'npm' + + - name: Install npm dependencies + if: matrix.language == 'csharp' + run: npm ci --no-fund --no-audit + + - name: Build C# code for CodeQL if: matrix.build-mode == 'manual' + working-directory: ./src run: | dotnet restore ./Syncfusion.Blazor.Toolkit.slnx - dotnet build ./Syncfusion.Blazor.Toolkit.slnx -c Release --no-restore + dotnet build ./Syncfusion.Blazor.Toolkit.slnx \ + --configuration Release \ + --no-restore - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 diff --git a/gulpfile.js b/gulpfile.js index e6ca7e97..fd535592 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,7 +1,8 @@ var fs = global.fs = global.fs || require('fs'); +var path = require('path'); var shelljs = global.shelljs = global.shelljs || require('shelljs'); var gulp = global.gulp = global.gulp || require('gulp'); -const glob = require('glob'); +const { globSync } = require('glob'); const sass = require('gulp-sass')(require('sass')); const rename = require('gulp-rename'); @@ -60,29 +61,41 @@ function removeCustomUse(fileContent) { } // Task to generate single SCSS files for Blazor toolkit. +function findComponentScss(componentFiles, themeOrder) { + const expected = themeOrder + '.scss'; + return componentFiles.find((file) => path.basename(file) === expected); +} + gulp.task('combined-scss', function (done) { - // Get the all components scss files' path - var componentFiles = glob.sync(`./src/wwwroot/styles/*.scss`); + const componentFiles = globSync('./src/wwwroot/styles/*.scss'); shelljs.mkdir('-p', './src/wwwroot/styles/combined-scss/'); - var getFluentScss = ''; - // Place component styles as per styles order - for (var themeOrder of componentThemeOrder) { - var paths = componentFiles.filter((value) => { - return value.indexOf('styles/' + themeOrder) !== -1; - }); - if (paths.length) { - getFluentScss += stripBom(fs.readFileSync(paths[0], 'utf8')); + + let getFluentScss = ''; + for (const themeOrder of componentThemeOrder) { + const filePath = findComponentScss(componentFiles, themeOrder); + if (filePath) { + const content = stripBom(fs.readFileSync(filePath, 'utf8')); + getFluentScss += content + '\n'; } } getFluentScss = removeCustomUse(getFluentScss); - fs.writeFileSync('./src/wwwroot/styles/combined-scss/fluent.scss', reorderUseRules(getFluentScss), 'utf8'); - var hcBody = ''; - for (var hcOrder of componentThemeOrder) { - var hcPaths = componentFiles.filter((value) => { return value.indexOf('styles/' + hcOrder) !== -1; }); - if (!hcPaths.length) continue; - var content = stripBom(fs.readFileSync(hcPaths[0], 'utf8')); - if (hcOrder === 'base') content = stripRootScopes(content); - hcBody += '\n' + content; + fs.writeFileSync( + './src/wwwroot/styles/combined-scss/fluent.scss', + reorderUseRules(getFluentScss), + 'utf8' + ); + + let hcBody = ''; + for (const hcOrder of componentThemeOrder) { + const filePath = findComponentScss(componentFiles, hcOrder); + if (!filePath) { + continue; + } + let content = stripBom(fs.readFileSync(filePath, 'utf8')); + if (hcOrder === 'base') { + content = stripRootScopes(content); + } + hcBody += '\n' + content + '\n'; } hcBody = removeCustomUse(hcBody); hcBody = reorderUseRules(hcBody); @@ -180,15 +193,17 @@ gulp.task('scss-to-css', function (done) { './src/wwwroot/styles/combined-scss/_highcontrast-tokens.scss' ] } ) - .pipe(sass({ outputStyle: 'compressed' }).on('error', function (error) { - fs.appendFileSync('./gulp_error.log', 'Failed scss-to-css task\n' + error.message + '\n'); - console.error('Sass Compilation Error:', error.messageFormatted); - process.exit(1); - })) + .pipe(sass({ outputStyle: 'compressed' }).on('error', function (error) { + const message = error.formatted || error.messageFormatted || error.message || String(error); + console.error('Sass compilation failed:\n' + message); + try { + fs.appendFileSync('./gulp_error.log', 'Failed scss-to-css task\n' + message + '\n'); + } catch (_) { /* ignore */ } + process.exit(1); + })) .pipe(rename({ suffix: '.min' })) .pipe(gulp.dest('./src/wwwroot/styles')) .on('end', cleanup) - .on('error', cleanup); }); gulp.task('blazor-toolkit-themes', gulp.series('combined-scss', 'scss-to-css')); @@ -246,7 +261,7 @@ function isXSSAllowlisted(file, line) { gulp.task('security-xss-scan', function (done) { let allFiles = []; for (const pattern of XSS_SCAN_GLOBS) { - allFiles = allFiles.concat(glob.sync(pattern, { + allFiles = allFiles.concat(globSync(pattern, { nodir: true, ignore: [ '**/bin/**', @@ -327,4 +342,4 @@ gulp.task('security-xss-scan', function (done) { done(); }); -gulp.task('security', gulp.series('security-xss-scan')); \ No newline at end of file +gulp.task('security', gulp.series('security-xss-scan')); diff --git a/package-lock.json b/package-lock.json index a353f6c3..2c28a499 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "@playwright/test": "^1.63.0", "eslint": "^10.10.0", "eslint-plugin-security": "^4.0.1", - "glob": "^7.2.3", + "glob": "^13.0.6", "globals": "^17.12.0", "gulp": "^5.0.1", "gulp-clean-css": "^4.3.0", @@ -452,9 +452,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -476,9 +473,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -500,9 +494,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -524,9 +515,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -548,9 +536,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -572,9 +557,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1381,13 +1363,6 @@ "dev": true, "license": "MIT" }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -1990,13 +1965,6 @@ "node": ">=10.13.0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2046,22 +2014,18 @@ } }, "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" }, "engines": { - "node": "*" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2114,37 +2078,6 @@ "node": ">= 10.13.0" } }, - "node_modules/glob/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", @@ -2450,18 +2383,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -2794,6 +2715,16 @@ "dev": true, "license": "MIT" }, + "node_modules/lru-cache": { + "version": "11.5.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.3.tgz", + "integrity": "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -2861,6 +2792,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3069,16 +3010,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -3119,6 +3050,23 @@ "node": ">=0.10.0" } }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", diff --git a/package.json b/package.json index e47a4518..1b59106d 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "@playwright/test": "^1.63.0", "eslint": "^10.10.0", "eslint-plugin-security": "^4.0.1", - "glob": "^7.2.3", + "glob": "^13.0.6", "globals": "^17.12.0", "gulp": "^5.0.1", "gulp-clean-css": "^4.3.0", diff --git a/src/Syncfusion.Blazor.Toolkit.csproj b/src/Syncfusion.Blazor.Toolkit.csproj index 6207e08e..6e07bae1 100644 --- a/src/Syncfusion.Blazor.Toolkit.csproj +++ b/src/Syncfusion.Blazor.Toolkit.csproj @@ -92,9 +92,12 @@ - - - - - + + + +