Compare commits
10 Commits
2c245afa1f
...
3d14baefda
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d14baefda | ||
|
|
408d8daef1 | ||
|
|
9683aa6d44 | ||
|
|
375eea2bdd | ||
|
|
3fd8287965 | ||
|
|
39a39d63b3 | ||
|
|
61eff6d4fb | ||
|
|
3efe7b5b61 | ||
|
|
c844e6dcbe | ||
|
|
864ab22583 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.idea/
|
||||||
*.pem
|
*.pem
|
||||||
*.tgz
|
*.tgz
|
||||||
|
|
||||||
|
|||||||
8
.npmignore
Normal file
8
.npmignore
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
*.tgz
|
||||||
|
.idea
|
||||||
|
.github
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
/techradar/
|
||||||
|
/data/about.json
|
||||||
|
/data/data.json
|
||||||
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,5 +1,31 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Version v4.6.1 (2025-03-26)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- define user's config as DeepPartial (9683aa6d)
|
||||||
|
|
||||||
|
### Chores and tidying
|
||||||
|
|
||||||
|
- **deps:** update next to 15.2.4 and eslint to 9.23.0 (375eea2b)
|
||||||
|
- release v4.6.0 (3fd82879)
|
||||||
|
|
||||||
|
## Version v4.6.0 (2025-03-14)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- add strict mode for data building (3efe7b5b)
|
||||||
|
- add configuration options for fuse (c844e6dc)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- forward flags to `npm run build` and adjust README.md (61eff6d4)
|
||||||
|
|
||||||
|
### Chores and tidying
|
||||||
|
|
||||||
|
- start new 4.6.0-rc.1 release (864ab225)
|
||||||
|
|
||||||
## Version v4.5.0 (2025-03-04)
|
## Version v4.5.0 (2025-03-04)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
48
README.md
48
README.md
@@ -45,7 +45,7 @@ file like the following and adapt to your needs:
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "techradar build",
|
"build": "techradar build --strict",
|
||||||
"serve": "techradar serve"
|
"serve": "techradar serve"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -58,6 +58,8 @@ Run `npm install` to install the dependencies and run `npm run build` to create
|
|||||||
This will also create a basic bootstrap of all required files, including the `config.json` and
|
This will also create a basic bootstrap of all required files, including the `config.json` and
|
||||||
the `about.md` if they do not exist yet.
|
the `about.md` if they do not exist yet.
|
||||||
|
|
||||||
|
Note: The `--strict` flag will break the build process if there are any errors in the markdown files. If you do not care about errors, you can remove the `--strict` flag.
|
||||||
|
|
||||||
### Step 2: Change logo and the favicon
|
### Step 2: Change logo and the favicon
|
||||||
|
|
||||||
Place your `logo.svg` and `favicon.ico` in the `public` folder next to the `package.json`.
|
Place your `logo.svg` and `favicon.ico` in the `public` folder next to the `package.json`.
|
||||||
@@ -70,24 +72,25 @@ file as `logoFile` inside the `config.json`. e.g. `"logoFile": "acme-logo.png"`
|
|||||||
|
|
||||||
Open the `config.json` file and configure the radar to your needs.
|
Open the `config.json` file and configure the radar to your needs.
|
||||||
|
|
||||||
| Attribute | Description |
|
| Attribute | Description |
|
||||||
| --------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
| ----------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| basePath | Set if hosting under a sub-path, otherwise set it to `/`. Default is `/techradar` |
|
| basePath | Set if hosting under a sub-path, otherwise set it to `/`. Default is `/techradar` |
|
||||||
| baseUrl | Set to the full URL, where the radar will be hosted. Will be used for sitemap.xml. `https://www.aoe.com/techradar` |
|
| baseUrl | Set to the full URL, where the radar will be hosted. Will be used for sitemap.xml. `https://www.aoe.com/techradar` |
|
||||||
| logoFile | (optional) Filepath in public folder. Default is `logo.svg` |
|
| logoFile | (optional) Filepath in public folder. Default is `logo.svg` |
|
||||||
| jsFile | (optional) Filepath in public folder or URL to enable include of custom script |
|
| jsFile | (optional) Filepath in public folder or URL to enable include of custom script |
|
||||||
| toggles | (optional) Modify the behaviour and contents of the radar. See config below. |
|
| toggles | (optional) Modify the behaviour and contents of the radar. See config below. |
|
||||||
| sections | (optional) Modify the order of sections (`radar`, `tags`, `list`) |
|
| sections | (optional) Modify the order of sections (`radar`, `tags`, `list`) |
|
||||||
| colors | A map of colors for the radar. Can be any valid CSS color value |
|
| fuzzySearch | (optional) Modify the fuse.js options (https://www.fusejs.io/api/options.html) |
|
||||||
| quadrants | Config of the 4 quadrants of the radar. See config below. |
|
| colors | A map of colors for the radar. Can be any valid CSS color value |
|
||||||
| rings | Config of the rings of the radar. See config below. |
|
| quadrants | Config of the 4 quadrants of the radar. See config below. |
|
||||||
| flags | Config of the flags of the radar. See config below |
|
| rings | Config of the rings of the radar. See config below. |
|
||||||
| chart | If you hava a lot of items, you can increase the `size` to scale down the radar |
|
| flags | Config of the flags of the radar. See config below |
|
||||||
| social | Social links in the footer. See config below |
|
| chart | If you hava a lot of items, you can increase the `size` to scale down the radar |
|
||||||
| imprint | URL to the legal information |
|
| social | Social links in the footer. See config below |
|
||||||
| labels | Configure the labels to change the texts and labels of the radar |
|
| imprint | URL to the legal information |
|
||||||
| tags | (optional) Use to render only items, which contain at least one of the specified tags. e.g `["frontend", "backend"]` |
|
| labels | Configure the labels to change the texts and labels of the radar |
|
||||||
| editUrl | (optional) If set, an edit button will be shown next to the revision.<br/> You can use placeholders for `{id}` and `{release}` |
|
| tags | (optional) Use to render only items, which contain at least one of the specified tags. e.g `["frontend", "backend"]` |
|
||||||
|
| editUrl | (optional) If set, an edit button will be shown next to the revision.<br/> You can use placeholders for `{id}` and `{release}` |
|
||||||
|
|
||||||
#### `config.toggles`
|
#### `config.toggles`
|
||||||
|
|
||||||
@@ -103,6 +106,10 @@ Open the `config.json` file and configure the radar to your needs.
|
|||||||
|
|
||||||
An array with of `radar`, `tags`, `list` in order you want them to appear on the page.
|
An array with of `radar`, `tags`, `list` in order you want them to appear on the page.
|
||||||
|
|
||||||
|
#### `config.fuzzySearch`
|
||||||
|
|
||||||
|
An object that represents the fuse.js options, which is used to search the radar.
|
||||||
|
|
||||||
#### `config.quadrants`
|
#### `config.quadrants`
|
||||||
|
|
||||||
| Attribute | Description |
|
| Attribute | Description |
|
||||||
@@ -262,4 +269,5 @@ If you want to change core functionality of the radar, you can clone this reposi
|
|||||||
radar's markdown-files, config.json and about.md in the `data` folder. Run `npm run build:data` to
|
radar's markdown-files, config.json and about.md in the `data` folder. Run `npm run build:data` to
|
||||||
parse the markdown files and create a `data.json` and then run `npm run dev` to start the
|
parse the markdown files and create a `data.json` and then run `npm run dev` to start the
|
||||||
development server, which will be available at `http://localhost:3000/techradar` or the path
|
development server, which will be available at `http://localhost:3000/techradar` or the path
|
||||||
you specified via `basePath`.
|
you specified via `basePath`. Run `npm run build:data -- --strict` to break the build process
|
||||||
|
when encountering errors.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const SOURCE_DIR = path.join(CWD, "node_modules", "aoe_technology_radar");
|
|||||||
const HASH_FILE = path.join(BUILDER_DIR, "hash");
|
const HASH_FILE = path.join(BUILDER_DIR, "hash");
|
||||||
|
|
||||||
const PARAMETER = process.argv[2]; // "build" or "serve"
|
const PARAMETER = process.argv[2]; // "build" or "serve"
|
||||||
|
const FLAGS = process.argv.slice(3).join(" ");
|
||||||
|
|
||||||
function info(message) {
|
function info(message) {
|
||||||
console.log(`\x1b[32m${message}\x1b[0m`);
|
console.log(`\x1b[32m${message}\x1b[0m`);
|
||||||
@@ -146,7 +147,9 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
info("Building data");
|
info("Building data");
|
||||||
execSync("npm run build:data", { stdio: "inherit" });
|
execSync(`npm run build:data -- ${FLAGS}`, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
|
||||||
if (PARAMETER === "serve") {
|
if (PARAMETER === "serve") {
|
||||||
info("Starting techradar");
|
info("Starting techradar");
|
||||||
|
|||||||
@@ -137,5 +137,11 @@
|
|||||||
"pageSearch": "Search",
|
"pageSearch": "Search",
|
||||||
"searchPlaceholder": "What are you looking for?",
|
"searchPlaceholder": "What are you looking for?",
|
||||||
"metaDescription": ""
|
"metaDescription": ""
|
||||||
|
},
|
||||||
|
"fuzzySearch": {
|
||||||
|
"threshold": 0.4,
|
||||||
|
"distance": 600,
|
||||||
|
"ignoreLocation": false,
|
||||||
|
"includeScore": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1972
package-lock.json
generated
1972
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "aoe_technology_radar",
|
"name": "aoe_technology_radar",
|
||||||
"version": "4.5.0",
|
"version": "4.7.0-rc.1",
|
||||||
"bin": {
|
"bin": {
|
||||||
"techradar": "./bin/techradar.js"
|
"techradar": "bin/techradar.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
@@ -16,23 +16,23 @@
|
|||||||
"postinstall": "npm run build:icons"
|
"postinstall": "npm run build:icons"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.7.1",
|
"@commitlint/cli": "^19.8.0",
|
||||||
"@commitlint/config-conventional": "^19.7.1",
|
"@commitlint/config-conventional": "^19.8.0",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||||
"@types/node": "^22",
|
"@types/node": "^22",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"eslint": "^9.21.0",
|
"eslint": "^9.23.0",
|
||||||
"eslint-config-next": "15.2.1",
|
"eslint-config-next": "15.2.4",
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"lint-staged": "^15.4.3",
|
"lint-staged": "^15.5.0",
|
||||||
"marked": "^15.0.7",
|
"marked": "^15.0.7",
|
||||||
"marked-highlight": "^2.2.1",
|
"marked-highlight": "^2.2.1",
|
||||||
"next": "15.2.1",
|
"next": "15.2.4",
|
||||||
"postcss-nested": "^7.0.2",
|
"postcss-nested": "^7.0.2",
|
||||||
"postcss-preset-env": "^10.1.5",
|
"postcss-preset-env": "^10.1.5",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import path from "path";
|
|||||||
|
|
||||||
import nextConfig from "../next.config.js";
|
import nextConfig from "../next.config.js";
|
||||||
import config from "../src/lib/config";
|
import config from "../src/lib/config";
|
||||||
|
import ErrorHandler, { ErrorType, TextColor } from "./errorHandler.js";
|
||||||
import Positioner from "./positioner";
|
import Positioner from "./positioner";
|
||||||
|
|
||||||
import { Flag, Item } from "@/lib/types";
|
import { Flag, Item } from "@/lib/types";
|
||||||
@@ -21,6 +22,7 @@ const quadrants = config.quadrants.map((q, i) => ({ ...q, position: i + 1 }));
|
|||||||
const quadrantIds = quadrants.map((q) => q.id);
|
const quadrantIds = quadrants.map((q) => q.id);
|
||||||
const tags = (config as { tags?: string[] }).tags || [];
|
const tags = (config as { tags?: string[] }).tags || [];
|
||||||
const positioner = new Positioner(size, quadrants, rings);
|
const positioner = new Positioner(size, quadrants, rings);
|
||||||
|
const errorHandler = new ErrorHandler(quadrants, rings);
|
||||||
|
|
||||||
const marked = new Marked(
|
const marked = new Marked(
|
||||||
markedHighlight({
|
markedHighlight({
|
||||||
@@ -170,17 +172,25 @@ function postProcessItems(items: Item[]): {
|
|||||||
const filteredItems = items.filter((item) => {
|
const filteredItems = items.filter((item) => {
|
||||||
// check if the items' quadrant and ring are valid
|
// check if the items' quadrant and ring are valid
|
||||||
if (!item.quadrant || !item.ring) {
|
if (!item.quadrant || !item.ring) {
|
||||||
console.warn(`Item ${item.id} has no quadrant or ring`);
|
errorHandler.processBuildErrors(ErrorType.NoQuadrant, item.id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!quadrantIds.includes(item.quadrant)) {
|
if (!quadrantIds.includes(item.quadrant)) {
|
||||||
console.warn(`Item ${item.id} has invalid quadrant ${item.quadrant}`);
|
errorHandler.processBuildErrors(
|
||||||
|
ErrorType.InvalidQuadrant,
|
||||||
|
item.id,
|
||||||
|
item.quadrant,
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ringIds.includes(item.ring)) {
|
if (!ringIds.includes(item.ring)) {
|
||||||
console.warn(`Item ${item.id} has invalid ring ${item.ring}`);
|
errorHandler.processBuildErrors(
|
||||||
|
ErrorType.InvalidRing,
|
||||||
|
item.id,
|
||||||
|
item.ring,
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +203,8 @@ function postProcessItems(items: Item[]): {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
errorHandler.checkForBuildErrors();
|
||||||
|
|
||||||
const releases = getUniqueReleases(filteredItems);
|
const releases = getUniqueReleases(filteredItems);
|
||||||
const uniqueTags = getUniqueTags(filteredItems);
|
const uniqueTags = getUniqueTags(filteredItems);
|
||||||
const processedItems = filteredItems.map((item) => {
|
const processedItems = filteredItems.map((item) => {
|
||||||
@@ -230,21 +242,30 @@ function postProcessItems(items: Item[]): {
|
|||||||
return { releases, tags: uniqueTags, items: processedItems };
|
return { releases, tags: uniqueTags, items: processedItems };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the data and write radar data to JSON file
|
async function main() {
|
||||||
parseDirectory(dataPath("radar")).then((items) => {
|
// Parse the data and write radar data to JSON file
|
||||||
|
const items = await parseDirectory(dataPath("radar"));
|
||||||
const data = postProcessItems(items);
|
const data = postProcessItems(items);
|
||||||
|
|
||||||
if (data.items.length === 0) {
|
if (data.items.length === 0) {
|
||||||
console.error("No valid radar items found.");
|
errorHandler.processBuildErrors(ErrorType.NoRadarItems);
|
||||||
console.log("Please check the markdown files in the `radar` directory.");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errorHandler.checkForBuildErrors(true);
|
||||||
|
|
||||||
const json = JSON.stringify(data, null, 2);
|
const json = JSON.stringify(data, null, 2);
|
||||||
fs.writeFileSync(dataPath("data.json"), json);
|
fs.writeFileSync(dataPath("data.json"), json);
|
||||||
});
|
|
||||||
|
|
||||||
// write about data to JSON file
|
// write about data to JSON file
|
||||||
const about = readMarkdownFile(dataPath("about.md"));
|
const about = readMarkdownFile(dataPath("about.md"));
|
||||||
fs.writeFileSync(dataPath("about.json"), JSON.stringify(about, null, 2));
|
fs.writeFileSync(dataPath("about.json"), JSON.stringify(about, null, 2));
|
||||||
console.log("ℹ️ Data written to data/data.json and data/about.json");
|
console.log(
|
||||||
|
"ℹ️ Data written to data/data.json and data/about.json\n\n" +
|
||||||
|
errorHandler.colorizeBackground(
|
||||||
|
" Build was successfull ",
|
||||||
|
TextColor.Green,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|||||||
108
scripts/errorHandler.ts
Normal file
108
scripts/errorHandler.ts
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import { Quadrant, Ring } from "@/lib/types";
|
||||||
|
|
||||||
|
export enum ErrorType {
|
||||||
|
NoQuadrant = "Item {0} has no quadrant or ring",
|
||||||
|
InvalidQuadrant = "Item {0} has invalid quadrant {1}\n\tvalid quadrants are: {2}",
|
||||||
|
InvalidRing = "Item {0} has invalid ring {1}\n\tvalid rings are: {2}",
|
||||||
|
NoRadarItems = "No valid radar items found. Please check the markdown files in the `radar` directory.",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TextColor {
|
||||||
|
Default = 0,
|
||||||
|
Black,
|
||||||
|
Red = 31,
|
||||||
|
Green = 32,
|
||||||
|
Yellow = 33,
|
||||||
|
Blue = 34,
|
||||||
|
Mangenta = 35,
|
||||||
|
Cyan = 36,
|
||||||
|
White = 37,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ErrorHandler {
|
||||||
|
private buildErrors: string[] = [];
|
||||||
|
private quadrants: Quadrant[];
|
||||||
|
private rings: Ring[];
|
||||||
|
private isStrict: boolean;
|
||||||
|
private supportsColor: boolean;
|
||||||
|
|
||||||
|
constructor(quadrants: Quadrant[], rings: Ring[]) {
|
||||||
|
this.isStrict = process.argv.slice(2).includes("--strict");
|
||||||
|
this.supportsColor = process.stdout.isTTY && process.env.TERM !== "dumb";
|
||||||
|
this.quadrants = quadrants;
|
||||||
|
this.rings = rings;
|
||||||
|
console.log(`ℹ️ Build is${this.isStrict ? "" : " not"} in strict mode\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public processBuildErrors(errorType: ErrorType, ...args: string[]) {
|
||||||
|
const errorHint = this.getErrorHint(errorType);
|
||||||
|
const errorMsg = this.formatString(
|
||||||
|
errorType.toString(),
|
||||||
|
errorHint ? [...args, errorHint] : args,
|
||||||
|
);
|
||||||
|
this.buildErrors.push(errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public checkForBuildErrors(exitOnErr: boolean = false) {
|
||||||
|
if (this.buildErrors.length > 0) {
|
||||||
|
console.warn(
|
||||||
|
this.colorizeBackground(
|
||||||
|
`There ${this.buildErrors.length > 1 ? "are" : "is"} ${this.buildErrors.length} error${this.buildErrors.length > 1 ? "s" : ""} in your data build`,
|
||||||
|
TextColor.Red,
|
||||||
|
) +
|
||||||
|
"\n\n" +
|
||||||
|
this.buildErrors
|
||||||
|
.map((error, index) => `${index + 1}. ${error}`)
|
||||||
|
.join("\n") +
|
||||||
|
"\n",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (this.isStrict || exitOnErr) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.buildErrors = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getErrorHint(errorType: ErrorType) {
|
||||||
|
switch (errorType) {
|
||||||
|
case ErrorType.InvalidQuadrant:
|
||||||
|
return this.quadrants.map((quadrant) => quadrant.id).join(", ");
|
||||||
|
case ErrorType.InvalidRing:
|
||||||
|
return this.rings.map((ring) => ring.id).join(", ");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public colorizeBackground(str: string, backgroundColor: TextColor) {
|
||||||
|
if (this.supportsColor) {
|
||||||
|
return `\x1b[${backgroundColor + 10}m${str}\x1b[${TextColor.Default}m`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatString(msg: string, inserts: string[]) {
|
||||||
|
return inserts.reduce(
|
||||||
|
(acc, cur, index) =>
|
||||||
|
acc.replaceAll(
|
||||||
|
`{${index}}`,
|
||||||
|
this.colorizeString(
|
||||||
|
cur,
|
||||||
|
index === 2 ? TextColor.Green : TextColor.Red,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
msg,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private colorizeString(str: string, textColor: TextColor) {
|
||||||
|
if (this.supportsColor) {
|
||||||
|
return `\x1b[${textColor}m${str}\x1b[${TextColor.Default}m`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,17 @@
|
|||||||
import defaultConfig from "../../data/config.default.json";
|
import defaultConfig from "../../data/config.default.json";
|
||||||
import _userConfig from "../../data/config.json";
|
import _userConfig from "../../data/config.json";
|
||||||
|
|
||||||
const userConfig = _userConfig as typeof defaultConfig;
|
type DeepPartial<T> = T extends object
|
||||||
const config = { ...defaultConfig, ...userConfig };
|
? {
|
||||||
|
[P in keyof T]?: DeepPartial<T[P]>;
|
||||||
|
}
|
||||||
|
: T;
|
||||||
|
|
||||||
|
type Config = typeof defaultConfig;
|
||||||
|
type UserConfig = DeepPartial<typeof defaultConfig>;
|
||||||
|
|
||||||
|
const userConfig = _userConfig as UserConfig;
|
||||||
|
const config = { ...defaultConfig, ...userConfig } as Config;
|
||||||
|
|
||||||
if (userConfig.colors)
|
if (userConfig.colors)
|
||||||
config.colors = { ...defaultConfig.colors, ...userConfig.colors };
|
config.colors = { ...defaultConfig.colors, ...userConfig.colors };
|
||||||
@@ -13,4 +22,10 @@ if (userConfig.labels)
|
|||||||
if (userConfig.toggles)
|
if (userConfig.toggles)
|
||||||
config.toggles = { ...defaultConfig.toggles, ...userConfig.toggles };
|
config.toggles = { ...defaultConfig.toggles, ...userConfig.toggles };
|
||||||
|
|
||||||
|
if (userConfig.fuzzySearch)
|
||||||
|
config.fuzzySearch = {
|
||||||
|
...defaultConfig.fuzzySearch,
|
||||||
|
...userConfig.fuzzySearch,
|
||||||
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ export function getFlag(flag: Flag) {
|
|||||||
return config.flags[flag];
|
return config.flags[flag];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getFuzzySearchConfig = () => {
|
||||||
|
return config.fuzzySearch;
|
||||||
|
};
|
||||||
|
|
||||||
export function getRings(): Ring[] {
|
export function getRings(): Ring[] {
|
||||||
return config.rings;
|
return config.rings;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useCallback, useMemo } from "react";
|
|||||||
import { Filter } from "@/components/Filter/Filter";
|
import { Filter } from "@/components/Filter/Filter";
|
||||||
import { ItemList } from "@/components/ItemList/ItemList";
|
import { ItemList } from "@/components/ItemList/ItemList";
|
||||||
import { getItems, getLabel } from "@/lib/data";
|
import { getItems, getLabel } from "@/lib/data";
|
||||||
|
import { getFuzzySearchConfig } from "@/lib/data";
|
||||||
import { formatTitle } from "@/lib/format";
|
import { formatTitle } from "@/lib/format";
|
||||||
import { CustomPage } from "@/pages/_app";
|
import { CustomPage } from "@/pages/_app";
|
||||||
|
|
||||||
@@ -32,9 +33,7 @@ const Overview: CustomPage = () => {
|
|||||||
const { items, index } = useMemo(() => {
|
const { items, index } = useMemo(() => {
|
||||||
const items = getItems().filter((item) => !ring || item.ring === ring);
|
const items = getItems().filter((item) => !ring || item.ring === ring);
|
||||||
const index = new Fuse(items, {
|
const index = new Fuse(items, {
|
||||||
threshold: 0.4,
|
...getFuzzySearchConfig(),
|
||||||
distance: 600,
|
|
||||||
includeScore: true,
|
|
||||||
keys: [
|
keys: [
|
||||||
{
|
{
|
||||||
name: "title",
|
name: "title",
|
||||||
|
|||||||
Reference in New Issue
Block a user