mirror of
https://github.com/gethomepage/homepage.git
synced 2026-05-18 19:40:58 +08:00
Improvement: better handle highlighting with units (#6318)
Some checks failed
Crowdin Action / Crowdin Sync (push) Has been cancelled
Docker CI / Linting Checks (push) Has been cancelled
Docker CI / Docker Build & Push (push) Has been cancelled
Tests / vitest (1) (push) Has been cancelled
Tests / vitest (2) (push) Has been cancelled
Tests / vitest (3) (push) Has been cancelled
Tests / vitest (4) (push) Has been cancelled
Repository Maintenance / Stale (push) Has been cancelled
Repository Maintenance / Lock Old Threads (push) Has been cancelled
Repository Maintenance / Close Answered Discussions (push) Has been cancelled
Repository Maintenance / Close Outdated Discussions (push) Has been cancelled
Repository Maintenance / Close Unsupported Feature Requests (push) Has been cancelled
Some checks failed
Crowdin Action / Crowdin Sync (push) Has been cancelled
Docker CI / Linting Checks (push) Has been cancelled
Docker CI / Docker Build & Push (push) Has been cancelled
Tests / vitest (1) (push) Has been cancelled
Tests / vitest (2) (push) Has been cancelled
Tests / vitest (3) (push) Has been cancelled
Tests / vitest (4) (push) Has been cancelled
Repository Maintenance / Stale (push) Has been cancelled
Repository Maintenance / Lock Old Threads (push) Has been cancelled
Repository Maintenance / Close Answered Discussions (push) Has been cancelled
Repository Maintenance / Close Outdated Discussions (push) Has been cancelled
Repository Maintenance / Close Unsupported Feature Requests (push) Has been cancelled
This commit is contained in:
@@ -74,6 +74,21 @@ const toNumber = (value) => {
|
|||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const extractNumericToken = (value) => {
|
||||||
|
if (typeof value !== "string") return undefined;
|
||||||
|
const match = value.match(/[-+]?\d[\d\s.,]*/);
|
||||||
|
if (!match) return undefined;
|
||||||
|
|
||||||
|
const token = match[0].trim();
|
||||||
|
if (!token) return undefined;
|
||||||
|
|
||||||
|
const prefix = value.slice(0, match.index).trim();
|
||||||
|
const suffix = value.slice((match.index ?? 0) + match[0].length).trim();
|
||||||
|
if (/\d/.test(prefix) || /\d/.test(suffix)) return undefined;
|
||||||
|
|
||||||
|
return token;
|
||||||
|
};
|
||||||
|
|
||||||
const parseNumericValue = (value) => {
|
const parseNumericValue = (value) => {
|
||||||
if (value === null || value === undefined) return undefined;
|
if (value === null || value === undefined) return undefined;
|
||||||
if (typeof value === "number" && Number.isFinite(value)) return value;
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
||||||
@@ -85,7 +100,9 @@ const parseNumericValue = (value) => {
|
|||||||
const direct = Number(trimmed);
|
const direct = Number(trimmed);
|
||||||
if (!Number.isNaN(direct)) return direct;
|
if (!Number.isNaN(direct)) return direct;
|
||||||
|
|
||||||
const compact = trimmed.replace(/\s+/g, "");
|
const candidate = extractNumericToken(trimmed);
|
||||||
|
const numericString = candidate ?? trimmed;
|
||||||
|
const compact = numericString.replace(/\s+/g, "");
|
||||||
if (!compact || !/^[-+]?[0-9.,]+$/.test(compact)) return undefined;
|
if (!compact || !/^[-+]?[0-9.,]+$/.test(compact)) return undefined;
|
||||||
|
|
||||||
const commaCount = (compact.match(/,/g) || []).length;
|
const commaCount = (compact.match(/,/g) || []).length;
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ describe("utils/highlights", () => {
|
|||||||
const cfg = buildHighlightConfig(null, {
|
const cfg = buildHighlightConfig(null, {
|
||||||
// string numeric rule values go through toNumber()
|
// string numeric rule values go through toNumber()
|
||||||
gt: { numeric: { when: "gt", value: "5", level: "warn" } },
|
gt: { numeric: { when: "gt", value: "5", level: "warn" } },
|
||||||
|
withUnitSuffix: { numeric: { when: "gt", value: 5, level: "warn" } },
|
||||||
|
withUnitPrefix: { numeric: { when: "gt", value: 5, level: "warn" } },
|
||||||
|
localizedUnitSuffix: { numeric: { when: "gt", value: 0.5, level: "warn" } },
|
||||||
commaGrouped: { numeric: { when: "eq", value: 1234, level: "good" } },
|
commaGrouped: { numeric: { when: "eq", value: 1234, level: "good" } },
|
||||||
commaDecimal: { numeric: { when: "eq", value: 12.34, level: "good" } },
|
commaDecimal: { numeric: { when: "eq", value: 12.34, level: "good" } },
|
||||||
dotDecimal: { numeric: { when: "eq", value: 12.34, level: "good" } },
|
dotDecimal: { numeric: { when: "eq", value: 12.34, level: "good" } },
|
||||||
@@ -143,6 +146,12 @@ describe("utils/highlights", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(evaluateHighlight("gt", "6", cfg)).toMatchObject({ level: "warn", source: "numeric" });
|
expect(evaluateHighlight("gt", "6", cfg)).toMatchObject({ level: "warn", source: "numeric" });
|
||||||
|
expect(evaluateHighlight("withUnitSuffix", "5.2 ms", cfg)).toMatchObject({ level: "warn", source: "numeric" });
|
||||||
|
expect(evaluateHighlight("withUnitPrefix", "ms 5.2", cfg)).toMatchObject({ level: "warn", source: "numeric" });
|
||||||
|
expect(evaluateHighlight("localizedUnitSuffix", "0,71\u202Fms", cfg)).toMatchObject({
|
||||||
|
level: "warn",
|
||||||
|
source: "numeric",
|
||||||
|
});
|
||||||
expect(evaluateHighlight("commaGrouped", "1,234", cfg)).toMatchObject({ level: "good", source: "numeric" });
|
expect(evaluateHighlight("commaGrouped", "1,234", cfg)).toMatchObject({ level: "good", source: "numeric" });
|
||||||
expect(evaluateHighlight("commaDecimal", "12,34", cfg)).toMatchObject({ level: "good", source: "numeric" });
|
expect(evaluateHighlight("commaDecimal", "12,34", cfg)).toMatchObject({ level: "good", source: "numeric" });
|
||||||
// Include a space so Number(trimmed) fails and we exercise the dot parsing branch.
|
// Include a space so Number(trimmed) fails and we exercise the dot parsing branch.
|
||||||
@@ -161,6 +170,9 @@ describe("utils/highlights", () => {
|
|||||||
// "1.2.3" is not a valid grouped or decimal number for our parser.
|
// "1.2.3" is not a valid grouped or decimal number for our parser.
|
||||||
expect(evaluateHighlight("num", "1.2.3", cfg)).toBeNull();
|
expect(evaluateHighlight("num", "1.2.3", cfg)).toBeNull();
|
||||||
|
|
||||||
|
// Multiple numbers in one string should not be treated as a single numeric value.
|
||||||
|
expect(evaluateHighlight("num", "5/10 ms", cfg)).toBeNull();
|
||||||
|
|
||||||
// JSX-ish values should not be treated as numeric.
|
// JSX-ish values should not be treated as numeric.
|
||||||
expect(evaluateHighlight("num", { props: { children: "x" } }, cfg)).toBeNull();
|
expect(evaluateHighlight("num", { props: { children: "x" } }, cfg)).toBeNull();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user