Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,30 @@ export const AWESOME_CLAUDE_CONTENT_SPEC: ContentRepoSpec = {
"submittedByUrl",
"sourceSubmissionNumber",
"sourceSubmissionUrl",
// snake_case aliases, matching urlFields/sourceUrlFields's pairing convention (#7445, same divergence class as
// #7250): protectedFrontmatterChanges compares before[field]/after[field] by the literal parsed key, so a
// protected field written in the legitimately-accepted snake_case convention (e.g. `download_url`) was invisible
// to this gate — a real protected-close bypass. `author`, `category`, `disclosure`, `slug` are single
// all-lowercase words (camelCase and snake_case are byte-identical), so no separate alias is needed for them.
"affiliate_url",
"author_profile_url",
"claim_status",
"claim_url",
"date_added",
"download_url",
"import_pr_number",
"import_pr_url",
"package_url",
"package_verified",
"pricing_model",
"reviewed_at",
"reviewed_by",
"reviewed_pr_number",
"submitted_at",
"submitted_by",
"submitted_by_url",
"source_submission_number",
"source_submission_url",
]),
urlFields: new Set([
"documentationUrl",
Expand Down
18 changes: 18 additions & 0 deletions test/unit/content-lane-duplicates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,24 @@ describe("protectedFrontmatterChanges", () => {
const after = mdx({ title: "T", slug: "a", author: "Alice" });
expect(protectedFrontmatterChanges(before, after)).toEqual([]);
});

it("flags a changed protected field written in the snake_case alias (e.g. download_url), matching the camelCase behavior (#7445)", () => {
// Before #7445, protectedFrontmatterFields listed only downloadUrl (camelCase), so an entry using the
// legitimately-accepted snake_case key was invisible to this gate even though urlFields already treats
// download_url as an equally-valid alias for duplicate detection.
const before = mdx({ title: "T", slug: "a", download_url: "https://example.com/old.zip" });
const after = mdx({ title: "T", slug: "a", download_url: "https://example.com/new.zip" });
expect(protectedFrontmatterChanges(before, after)).toEqual(["download_url"]);
});

it("every multi-word camelCase protectedFrontmatterFields member has its snake_case alias present too (#7445, mirrors #7250's urlFields pairing assertion)", () => {
const singleLowercaseWords = new Set(["author", "category", "disclosure", "slug"]);
const toSnakeCase = (field: string): string => field.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
for (const field of AWESOME_CLAUDE_CONTENT_SPEC.protectedFrontmatterFields) {
if (singleLowercaseWords.has(field) || field.includes("_")) continue;
expect(AWESOME_CLAUDE_CONTENT_SPEC.protectedFrontmatterFields.has(toSnakeCase(field))).toBe(true);
}
});
});

describe("extractContentDuplicateSignals + strict match", () => {
Expand Down