Skip to content

Commit 94113e0

Browse files
fix: use last 2 parts of file uri for rule names
1 parent 96f0cfd commit 94113e0

File tree

2 files changed

+137
-10
lines changed

2 files changed

+137
-10
lines changed

packages/config-yaml/src/markdown/markdownToRule.test.ts

Lines changed: 114 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PackageIdentifier } from "../browser.js";
2-
import { markdownToRule } from "./markdownToRule.js";
2+
import { getRuleName, markdownToRule } from "./markdownToRule.js";
33

44
describe("markdownToRule", () => {
55
// Use a mock PackageIdentifier for testing
@@ -36,7 +36,7 @@ This is a test rule.`;
3636
const result = markdownToRule(content, mockId);
3737
expect(result.globs).toBe("**/test/**/*.kt");
3838
expect(result.rule).toBe("# Test Rule\n\nThis is a test rule.");
39-
expect(result.name).toBe("/path/to/file"); // Should use packageIdentifierToDisplayName result
39+
expect(result.name).toBe("to/file"); // Should use last two path segments
4040
});
4141

4242
it("should handle missing frontmatter", () => {
@@ -47,7 +47,7 @@ This is a test rule without frontmatter.`;
4747
const result = markdownToRule(content, mockId);
4848
expect(result.globs).toBeUndefined();
4949
expect(result.rule).toBe(content);
50-
expect(result.name).toBe("/path/to/file"); // Should use packageIdentifierToDisplayName result
50+
expect(result.name).toBe("to/file"); // Should use last two path segments
5151
});
5252

5353
it("should handle empty frontmatter", () => {
@@ -63,7 +63,7 @@ This is a test rule with empty frontmatter.`;
6363
expect(result.rule).toBe(
6464
"# Test Rule\n\nThis is a test rule with empty frontmatter.",
6565
);
66-
expect(result.name).toBe("/path/to/file"); // Should use packageIdentifierToDisplayName result
66+
expect(result.name).toBe("to/file"); // Should use last two path segments
6767
});
6868

6969
it("should handle frontmatter with whitespace", () => {
@@ -78,7 +78,7 @@ This is a test rule.`;
7878
const result = markdownToRule(content, mockId);
7979
expect(result.globs).toBe("**/test/**/*.kt");
8080
expect(result.rule).toBe("# Test Rule\n\nThis is a test rule.");
81-
expect(result.name).toBe("/path/to/file"); // Should use packageIdentifierToDisplayName result
81+
expect(result.name).toBe("to/file"); // Should use last two path segments
8282
});
8383

8484
it("should handle Windows line endings (CRLF)", () => {
@@ -95,7 +95,7 @@ This is a test rule.`;
9595
expect(result.globs).toBe("**/test/**/*.kt");
9696
// The result should be normalized to \n
9797
expect(result.rule).toBe("# Test Rule\n\nThis is a test rule.");
98-
expect(result.name).toBe("/path/to/file"); // Should use packageIdentifierToDisplayName result
98+
expect(result.name).toBe("to/file"); // Should use last two path segments
9999
});
100100

101101
it("should handle malformed frontmatter", () => {
@@ -112,7 +112,7 @@ This is a test rule.`;
112112
const result = markdownToRule(content, mockId);
113113
expect(result.globs).toBeUndefined();
114114
expect(result.rule).toBe(content);
115-
expect(result.name).toBe("/path/to/file"); // Should use packageIdentifierToDisplayName result
115+
expect(result.name).toBe("to/file"); // Should use last two path segments
116116
});
117117

118118
it("should use packageIdentifierToDisplayName if no heading or frontmatter name", () => {
@@ -125,7 +125,7 @@ globs: "**/test/**/*.kt"
125125
This is a test rule.`;
126126

127127
const result = markdownToRule(content, mockId);
128-
expect(result.name).toBe("/path/to/file"); // Should use packageIdentifierToDisplayName result
128+
expect(result.name).toBe("to/file"); // Should use last two path segments
129129
});
130130

131131
it("should use packageIdentifierToDisplayName if no heading or frontmatter name (no heading)", () => {
@@ -136,7 +136,7 @@ globs: "**/test/**/*.kt"
136136
This is a test rule without a heading.`;
137137

138138
const result = markdownToRule(content, mockId);
139-
expect(result.name).toBe("/path/to/file"); // Should use packageIdentifierToDisplayName result
139+
expect(result.name).toBe("to/file"); // Should use last two path segments
140140
});
141141

142142
it("should include description from frontmatter", () => {
@@ -171,3 +171,108 @@ This is a rule with alwaysApply explicitly set to false.`;
171171
expect(result.alwaysApply).toBe(false);
172172
});
173173
});
174+
175+
describe("getRuleName", () => {
176+
it("should return frontmatter name when provided", () => {
177+
const frontmatter = { name: "Custom Rule Name" };
178+
const id: PackageIdentifier = {
179+
uriType: "file",
180+
filePath: "/path/to/my-rule.md",
181+
};
182+
183+
const result = getRuleName(frontmatter, id);
184+
expect(result).toBe("Custom Rule Name");
185+
});
186+
187+
it("should return last two path segments for file identifier when no name", () => {
188+
const frontmatter = {};
189+
const id: PackageIdentifier = {
190+
uriType: "file",
191+
filePath: "/long/path/to/rules/my-rule.md",
192+
};
193+
194+
const result = getRuleName(frontmatter, id);
195+
expect(result).toBe("rules/my-rule.md");
196+
});
197+
198+
it("should handle file paths with backslashes", () => {
199+
const frontmatter = {};
200+
const id: PackageIdentifier = {
201+
uriType: "file",
202+
filePath: "C:\\long\\path\\to\\rules\\my-rule.md",
203+
};
204+
205+
const result = getRuleName(frontmatter, id);
206+
expect(result).toBe("rules/my-rule.md");
207+
});
208+
209+
it("should handle mixed forward and back slashes", () => {
210+
const frontmatter = {};
211+
const id: PackageIdentifier = {
212+
uriType: "file",
213+
filePath: "/path/to\\rules/my-rule.md",
214+
};
215+
216+
const result = getRuleName(frontmatter, id);
217+
expect(result).toBe("rules/my-rule.md");
218+
});
219+
220+
it("should handle single segment path", () => {
221+
const frontmatter = {};
222+
const id: PackageIdentifier = {
223+
uriType: "file",
224+
filePath: "my-rule.md",
225+
};
226+
227+
const result = getRuleName(frontmatter, id);
228+
expect(result).toBe("my-rule.md");
229+
});
230+
231+
it("should handle two segment path", () => {
232+
const frontmatter = {};
233+
const id: PackageIdentifier = {
234+
uriType: "file",
235+
filePath: "rules/my-rule.md",
236+
};
237+
238+
const result = getRuleName(frontmatter, id);
239+
expect(result).toBe("rules/my-rule.md");
240+
});
241+
242+
it("should return display name for non-file identifiers", () => {
243+
const frontmatter = {};
244+
const id: PackageIdentifier = {
245+
uriType: "slug",
246+
fullSlug: {
247+
ownerSlug: "test-owner",
248+
packageSlug: "my-rule-package",
249+
versionSlug: "v1.0.0",
250+
},
251+
};
252+
253+
const result = getRuleName(frontmatter, id);
254+
expect(result).toBe("my-rule-package"); // packageIdentifierToDisplayName returns just the packageSlug
255+
});
256+
257+
it("should prioritize frontmatter name over file path", () => {
258+
const frontmatter = { name: "Override Name" };
259+
const id: PackageIdentifier = {
260+
uriType: "file",
261+
filePath: "/very/long/path/to/rules/original-name.md",
262+
};
263+
264+
const result = getRuleName(frontmatter, id);
265+
expect(result).toBe("Override Name");
266+
});
267+
268+
it("should handle empty string name in frontmatter by falling back to path", () => {
269+
const frontmatter = { name: "" };
270+
const id: PackageIdentifier = {
271+
uriType: "file",
272+
filePath: "/path/to/rules/my-rule.md",
273+
};
274+
275+
const result = getRuleName(frontmatter, id);
276+
expect(result).toBe("rules/my-rule.md"); // Empty string is falsy, so falls back to path logic
277+
});
278+
});

packages/config-yaml/src/markdown/markdownToRule.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,36 @@ export function parseMarkdownRule(content: string): {
4646
return { frontmatter: {}, markdown: normalizedContent };
4747
}
4848

49+
export function getRuleName(
50+
frontmatter: RuleFrontmatter,
51+
id: PackageIdentifier,
52+
): string {
53+
if (frontmatter.name) {
54+
return frontmatter.name;
55+
}
56+
57+
const displayName = packageIdentifierToDisplayName(id);
58+
59+
// If it's a file identifier, extract the last two parts of the file path
60+
if (id.uriType === "file") {
61+
// Handle both forward slashes and backslashes, get the last two segments
62+
const segments = displayName.split(/[/\\]/);
63+
const lastTwoParts = segments.slice(-2);
64+
return lastTwoParts.join("/");
65+
}
66+
67+
// Otherwise return the display name as-is (for slug identifiers)
68+
return displayName;
69+
}
70+
4971
export function markdownToRule(
5072
rule: string,
5173
id: PackageIdentifier,
5274
): RuleObject {
5375
const { frontmatter, markdown } = parseMarkdownRule(rule);
5476

5577
return {
56-
name: frontmatter.name ?? packageIdentifierToDisplayName(id),
78+
name: getRuleName(frontmatter, id),
5779
rule: markdown,
5880
globs: frontmatter.globs,
5981
description: frontmatter.description,

0 commit comments

Comments
 (0)