Remove lower casing -- preserving prior behavior

This commit is contained in:
Devin Robison
2026-03-23 17:10:08 -06:00
committed by Peter Steinberger
parent a339d706c1
commit 003752b9b3
2 changed files with 28 additions and 3 deletions

View File

@@ -151,6 +151,18 @@ describe("skills-clawhub", () => {
});
});
it("rejects Unicode that case-folds to ASCII (Kelvin sign U+212A)", async () => {
// "\u212A" (Kelvin sign) lowercases to "k" — must be caught before lowercasing
const result = await installSkillFromClawHub({
workspaceDir: "/tmp/workspace",
slug: "\u212Aalendar",
});
expect(result).toMatchObject({
ok: false,
error: expect.stringContaining("Invalid skill slug"),
});
});
it("rejects slug starting with a hyphen", async () => {
const result = await installSkillFromClawHub({
workspaceDir: "/tmp/workspace",
@@ -173,7 +185,15 @@ describe("skills-clawhub", () => {
});
});
it("accepts valid ASCII slugs", async () => {
it("accepts uppercase ASCII slugs (preserves original casing behavior)", async () => {
const result = await installSkillFromClawHub({
workspaceDir: "/tmp/workspace",
slug: "React",
});
expect(result).toMatchObject({ ok: true });
});
it("accepts valid lowercase ASCII slugs", async () => {
const result = await installSkillFromClawHub({
workspaceDir: "/tmp/workspace",
slug: "calendar-2",

View File

@@ -62,10 +62,15 @@ type Logger = {
info?: (message: string) => void;
};
const VALID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
const VALID_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i;
// eslint-disable-next-line no-control-regex -- detects any character outside printable ASCII
const NON_ASCII_PATTERN = /[^\x00-\x7F]/;
function normalizeSlug(raw: string): string {
const slug = raw.trim().toLowerCase();
const slug = raw.trim();
if (NON_ASCII_PATTERN.test(slug)) {
throw new Error(`Invalid skill slug: ${raw}`);
}
if (!slug || !VALID_SLUG_PATTERN.test(slug)) {
throw new Error(`Invalid skill slug: ${raw}`);
}