From ba9ccb95921d0c84cebe9e2c775513335512e040 Mon Sep 17 00:00:00 2001
From: "codspeed-hq[bot]" <117304815+codspeed-hq[bot]@users.noreply.github.com>
Date: Mon, 9 Feb 2026 04:08:00 +0000
Subject: [PATCH] Setup CodSpeed for continuous performance testing
- Install @codspeed/vitest-plugin@5.1.0 for benchmark instrumentation
- Create vitest benchmark configuration with CodSpeed plugin integration
- Add example benchmarks for array utilities (unique, flatten, sortBy, groupBy, intersection, difference)
- Add example benchmarks for string utilities (kebabToCamel, camelToKebab, capitalize, truncate, escapeHTML)
- Configure GitHub Actions workflow with OIDC authentication
- Use simulation mode for consistent performance measurements
- Add CodSpeed badge to README for performance tracking visibility
---
.github/workflows/codspeed.yml | 50 +++++
README.md | 1 +
benchmarks/arrays.bench.js | 92 +++++++++
benchmarks/strings.bench.js | 86 +++++++++
package-lock.json | 337 +++++++++++++++++++++++++++++++++
package.json | 1 +
vitest.bench.config.js | 15 ++
7 files changed, 582 insertions(+)
create mode 100644 .github/workflows/codspeed.yml
create mode 100644 benchmarks/arrays.bench.js
create mode 100644 benchmarks/strings.bench.js
create mode 100644 vitest.bench.config.js
diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml
new file mode 100644
index 000000000..63145fb80
--- /dev/null
+++ b/.github/workflows/codspeed.yml
@@ -0,0 +1,50 @@
+name: CodSpeed
+
+on:
+ push:
+ branches:
+ - main
+ - next/*
+ - feat/*
+ - fix/*
+ - perf/*
+ - v1
+ - v1.*
+ pull_request:
+ branches:
+ - main
+ - next/*
+ - feat/*
+ - fix/*
+ - perf/*
+ - v1
+ - v1.*
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ id-token: write
+
+jobs:
+ benchmarks:
+ name: Run Benchmarks
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+ steps:
+ - name: Checkout Repo
+ uses: actions/checkout@v4
+
+ - name: Install Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: ".node-version"
+ cache: "npm"
+
+ - name: Install NPM Dependencies
+ run: npm ci
+
+ - name: Run Benchmarks with CodSpeed
+ uses: CodSpeedHQ/action@v4
+ with:
+ mode: simulation
+ run: npx vitest bench --run --config vitest.bench.config.js
diff --git a/README.md b/README.md
index a1c7a348d..f3cbb706c 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
[](https://github.com/Semantic-Org/Semantic-Next/actions/workflows/ci.yml)
[](https://github.com/Semantic-Org/Semantic-Next/actions/workflows/ci.yml)
[](https://github.com/Semantic-Org/Semantic-Next/actions/workflows/ci.yml)
+[](https://codspeed.io/Semantic-Org/Semantic-Next?utm_source=badge)
A modern, lightweight UI framework built with Web Components.
diff --git a/benchmarks/arrays.bench.js b/benchmarks/arrays.bench.js
new file mode 100644
index 000000000..05143a604
--- /dev/null
+++ b/benchmarks/arrays.bench.js
@@ -0,0 +1,92 @@
+import { bench, describe } from 'vitest';
+import {
+ difference,
+ flatten,
+ groupBy,
+ intersection,
+ range,
+ sortBy,
+ unique,
+ uniqueItems,
+} from '../packages/utils/src/arrays.js';
+
+describe('array utilities', () => {
+ const smallArray = range(0, 20);
+ const mediumArray = range(0, 100);
+ const largeArray = range(0, 500);
+
+ bench('unique - small array', () => {
+ unique([...smallArray, ...smallArray]);
+ });
+
+ bench('unique - medium array', () => {
+ unique([...mediumArray, ...mediumArray]);
+ });
+
+ bench('flatten - nested arrays', () => {
+ const nested = [[1, 2], [3, 4], [[5, 6], [7, 8]], [9, 10]];
+ flatten(nested);
+ });
+
+ bench('flatten - deeply nested', () => {
+ const nested = [[[[[1, 2]]], [[3, 4]]], [[[5, 6]], [[7, 8]]]];
+ flatten(nested);
+ });
+
+ bench('sortBy - numeric property', () => {
+ const data = mediumArray.map((i) => ({ id: i, value: Math.random() }));
+ sortBy(data, 'value');
+ });
+
+ bench('sortBy - multiple keys', () => {
+ const data = mediumArray.map((i) => ({
+ category: i % 5,
+ priority: i % 3,
+ value: Math.random(),
+ }));
+ sortBy(data, ['category', 'priority', 'value']);
+ });
+
+ bench('groupBy - small dataset', () => {
+ const data = smallArray.map((i) => ({ category: i % 5, value: i }));
+ groupBy(data, 'category');
+ });
+
+ bench('groupBy - large dataset', () => {
+ const data = largeArray.map((i) => ({ category: i % 10, value: i }));
+ groupBy(data, 'category');
+ });
+
+ bench('intersection - small arrays', () => {
+ const arr1 = range(0, 20);
+ const arr2 = range(10, 30);
+ const arr3 = range(15, 35);
+ intersection(arr1, arr2, arr3);
+ });
+
+ bench('intersection - largearrays', () => {
+ const arr1 = range(0, 200);
+ const arr2 = range(100, 300);
+ const arr3 = range(150, 350);
+ intersection(arr1, arr2, arr3);
+ });
+
+ bench('difference - small arrays', () => {
+ const arr1 = range(0, 20);
+ const arr2 = range(10, 30);
+ difference(arr1, arr2);
+ });
+
+ bench('difference - large arrays', () => {
+ const arr1 = range(0, 200);
+ const arr2 = range(100, 300);
+ difference(arr1, arr2);
+ });
+
+ bench('uniqueItems - multiple arrays', () => {
+ const arr1 = range(0, 30);
+ const arr2 = range(20, 50);
+ const arr3 = range(40, 70);
+ uniqueItems(arr1, arr2, arr3);
+ });
+});
diff --git a/benchmarks/strings.bench.js b/benchmarks/strings.bench.js
new file mode 100644
index 000000000..ce9454f33
--- /dev/null
+++ b/benchmarks/strings.bench.js
@@ -0,0 +1,86 @@
+import { bench, describe } from 'vitest';
+import {
+ camelToKebab,
+ capitalize,
+ capitalizeWords,
+ escapeHTML,
+ getArticle,
+ joinWords,
+ kebabToCamel,
+ toTitleCase,
+ truncate,
+} from '../packages/utils/src/strings.js';
+
+describe('string utilities', () => {
+ const shortString = 'hello world';
+ const longString = 'the quick brown fox jumps over the lazy dog '.repeat(10);
+ const htmlString = ' &
content
';
+ const kebabString = 'this-is-a-kebab-case-string-with-many-words';
+ const camelString = 'thisIsACamelCaseStringWithManyWords';
+
+ bench('kebabToCamel - short string', () => {
+ kebabToCamel('hello-world');
+ });
+
+ bench('kebabToCamel - long string', () => {
+ kebabToCamel(kebabString);
+ });
+
+ bench('camelToKebab - short string', () => {
+ camelToKebab('helloWorld');
+ });
+
+ bench('camelToKebab - long string', () => {
+ camelToKebab(camelString);
+ });
+
+ bench('capitalize', () => {
+ capitalize(shortString);
+ });
+
+ bench('capitalizeWords', () => {
+ capitalizeWords(longString);
+ });
+
+ bench('toTitleCase - short', () => {
+ toTitleCase('the quick brown fox');
+ });
+
+ bench('toTitleCase - long', () => {
+ toTitleCase(longString);
+ });
+
+ bench('joinWords - small list', () => {
+ joinWords(['apple', 'banana', 'cherry']);
+ });
+
+ bench('joinWords - large list with options', () => {
+ const words = Array.from({ length: 20 }, (_, i) => `item${i}`);
+ joinWords(words, { oxford: true, quotes: true });
+ });
+
+ bench('getArticle', () => {
+ getArticle('umbrella');
+ getArticle('house');
+ });
+
+ bench('truncate - short text', () => {
+ truncate(shortString, 50);
+ });
+
+ bench('truncate - long text with word boundary', () => {
+ truncate(longString, 100, { wordBoundary: true });
+ });
+
+ bench('truncate - long text without word boundary', () => {
+ truncate(longString, 100, { wordBoundary: false });
+ });
+
+ bench('escapeHTML - simple', () => {
+ escapeHTML('test
');
+ });
+
+ bench('escapeHTML - complex', () => {
+ escapeHTML(htmlString);
+ });
+});
diff --git a/package-lock.json b/package-lock.json
index a94cf0dbf..714ce0b18 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,6 +21,7 @@
"@semantic-ui/specs": "^0.17.0"
},
"devDependencies": {
+ "@codspeed/vitest-plugin": "^5.1.0",
"@commitlint/cli": "^19.8.1",
"@commitlint/config-conventional": "^19.8.1",
"@types/node": "^24.3.0",
@@ -467,6 +468,51 @@
"node": ">=18"
}
},
+ "node_modules/@codspeed/core": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@codspeed/core/-/core-5.1.0.tgz",
+ "integrity": "sha512-DFO8c7/wd42QbabBdTYR7UsO8g77eHWE9Q4Eyr6yUJSoWhb1qaSoXiqX77RtN3Sbw8RGhhXiwaUC+vVr08+OMg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "axios": "^1.4.0",
+ "find-up": "^6.3.0",
+ "form-data": "^4.0.4",
+ "node-gyp-build": "^4.6.0"
+ }
+ },
+ "node_modules/@codspeed/core/node_modules/find-up": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
+ "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^7.1.0",
+ "path-exists": "^5.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@codspeed/vitest-plugin": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@codspeed/vitest-plugin/-/vitest-plugin-5.1.0.tgz",
+ "integrity": "sha512-rA+8DdsbAYxO7lo49K8ZBJqEk7b14Uztpz47ZKm6k8RJcTijffk7OjpG3kOJVUWWta2BVI1bPVj9ENmdfUwrfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@codspeed/core": "^5.1.0"
+ },
+ "peerDependencies": {
+ "tinybench": ">=2.9.0",
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0",
+ "vitest": "^3.2 || ^4"
+ }
+ },
"node_modules/@commitlint/cli": {
"version": "19.8.1",
"resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.8.1.tgz",
@@ -3525,6 +3571,25 @@
"node": ">=12"
}
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.13.5",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
+ "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.11",
+ "form-data": "^4.0.5",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -3620,6 +3685,20 @@
"node": ">=8"
}
},
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -3860,6 +3939,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/compare-func": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
@@ -4084,6 +4176,16 @@
"license": "MIT",
"peer": true
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -4158,6 +4260,21 @@
"@dprint/win32-x64": "0.50.1"
}
},
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -4226,6 +4343,26 @@
"is-arrayish": "^0.2.1"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/es-module-lexer": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
@@ -4233,6 +4370,35 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/esbuild": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
@@ -4854,6 +5020,27 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@@ -4871,6 +5058,23 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@@ -4886,6 +5090,16 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -4906,6 +5120,45 @@
"node": "6.* || 8.* || >= 10.*"
}
},
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/git-raw-commits": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz",
@@ -5020,6 +5273,19 @@
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
"license": "MIT"
},
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -5044,6 +5310,48 @@
"node": ">=8"
}
},
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/html-encoding-sniffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
@@ -5819,6 +6127,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/meow": {
"version": "12.1.1",
"resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz",
@@ -5997,6 +6315,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/node-gyp-build": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
+ "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "node-gyp-build": "bin.js",
+ "node-gyp-build-optional": "optional.js",
+ "node-gyp-build-test": "build-test.js"
+ }
+ },
"node_modules/node-releases": {
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
@@ -6314,6 +6644,13 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
diff --git a/package.json b/package.json
index d06ee05ac..8b8eca34f 100755
--- a/package.json
+++ b/package.json
@@ -233,6 +233,7 @@
"@pagefind/modular-ui": "^1.3.0"
},
"devDependencies": {
+ "@codspeed/vitest-plugin": "^5.1.0",
"@commitlint/cli": "^19.8.1",
"@commitlint/config-conventional": "^19.8.1",
"@types/node": "^24.3.0",
diff --git a/vitest.bench.config.js b/vitest.bench.config.js
new file mode 100644
index 000000000..7611a3044
--- /dev/null
+++ b/vitest.bench.config.js
@@ -0,0 +1,15 @@
+import codspeedPlugin from '@codspeed/vitest-plugin';
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+ plugins: [codspeedPlugin()],
+ test: {
+ benchmark: {
+ include: ['**/*.bench.{js,ts}'],
+ },
+ },
+ server: {
+ host: '127.0.0.1',
+ hmr: false,
+ },
+});