Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/src/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export const builtInValidationFunctions: Record<string, ValidationFunction> = {
*/
numeric: (value: unknown) => {
if (typeof value === "number") return !isNaN(value);
if (typeof value === "string") return !isNaN(parseFloat(value));
if (typeof value === "string") return !isNaN(Number(value)) && isFinite(Number(value));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (typeof value === "string") return !isNaN(Number(value)) && isFinite(Number(value));
if (typeof value === "string") {
const trimmed = value.trim();
if (trimmed === "") return false;
return !isNaN(Number(trimmed)) && isFinite(Number(trimmed));
}

The numeric validator accepts empty and whitespace-only strings as valid numbers because Number("") and Number(" ") both evaluate to a finite 0.

Fix on Vercel

return false;
},

Expand Down
2 changes: 1 addition & 1 deletion packages/directives/src/truncate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export const truncateDirective = defineDirective({
const suffix = raw.suffix ?? "...";

if (text.length <= maxLength) return text;
return text.slice(0, maxLength) + suffix;
return text.slice(0, maxLength - suffix.length) + suffix;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$truncate uses text.slice(0, maxLength - suffix.length) without clamping the start index, so a suffix longer than maxLength yields a negative index that slices from the end and returns nearly the whole string; the same change also broke 3 existing tests that encoded the old contract.

Fix on Vercel

},
});