Merge remote-tracking branch 'origin/farm/ae7a5593/ttsr-inline-regex-flags-and-scope-quoting'
This commit is contained in:
@@ -40,6 +40,9 @@
|
||||
### Fixed
|
||||
|
||||
- Fixed child shell environment filtering to drop launch-directory `.env.local` values that Bun auto-loaded before OMP starts command shells. ([#4723](https://github.com/can1357/oh-my-pi/issues/4723))
|
||||
### Fixed
|
||||
|
||||
- Fixed `parseFrontmatter`'s malformed-YAML fallback corrupting sibling values: one unparseable line (e.g. `scope: "text","thinking"`) forced every value through a raw key/value split that kept literal quotes. Each value is now reparsed independently as YAML, falling back to the raw trimmed string only for the lines that genuinely don't parse ([#4796](https://github.com/can1357/oh-my-pi/issues/4796)).
|
||||
|
||||
## [16.3.10] - 2026-07-06
|
||||
|
||||
|
||||
@@ -149,12 +149,25 @@ export function parseFrontmatter(
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Simple YAML parsing - just key: value pairs
|
||||
// Simple key: value fallback. Reparse each value on its own so one
|
||||
// malformed line (e.g. `scope: "text","thinking"`) can't leave sibling
|
||||
// values wrapped in literal quotes; values that don't parse as YAML fall
|
||||
// back to the raw trimmed string (issue #4796).
|
||||
for (const line of metadata.split("\n")) {
|
||||
const match = line.match(/^([\w-]+):\s*(.*)$/);
|
||||
if (match) {
|
||||
frontmatter[match[1]] = match[2].trim();
|
||||
if (!match) continue;
|
||||
const raw = match[2].trim();
|
||||
let value: unknown = raw;
|
||||
if (raw.length > 0) {
|
||||
try {
|
||||
const parsed = YAML.parse(raw);
|
||||
if (parsed !== null && typeof parsed !== "object") value = parsed;
|
||||
else if (Array.isArray(parsed)) value = parsed;
|
||||
} catch {
|
||||
// keep the raw string
|
||||
}
|
||||
}
|
||||
frontmatter[match[1]] = value;
|
||||
}
|
||||
|
||||
return { frontmatter: normalizeKeys(frontmatter) as Record<string, unknown>, body };
|
||||
|
||||
@@ -43,4 +43,26 @@ Body content`;
|
||||
expect.objectContaining({ err: expect.stringContaining("broken.md") }),
|
||||
);
|
||||
});
|
||||
|
||||
it("reparses each fallback value so one malformed line can't corrupt its siblings", () => {
|
||||
// `scope: "text","thinking"` is not valid YAML, forcing the line-by-line
|
||||
// fallback. The sibling `condition` value must not inherit literal quotes,
|
||||
// and `enabled` must reparse to a boolean (issue #4796).
|
||||
const warnSpy = vi.spyOn(logger, "warn").mockImplementation(() => {});
|
||||
const content = `---
|
||||
condition: "(?i)pre.existing"
|
||||
scope: "text","thinking"
|
||||
enabled: true
|
||||
---
|
||||
Body`;
|
||||
|
||||
const result = parseFrontmatter(content, { source: "rule.md" });
|
||||
|
||||
expect(result.frontmatter.condition).toBe("(?i)pre.existing");
|
||||
expect(result.frontmatter.enabled).toBe(true);
|
||||
// The unrecoverable line survives as its raw trimmed string.
|
||||
expect(result.frontmatter.scope).toBe('"text","thinking"');
|
||||
expect(result.body).toBe("Body");
|
||||
expect(warnSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user