Fix extractRegion() matching region names that are substrings of others

The `extractRegion()` function in `sync-snippets.ts` used `indexOf()` to
find region markers like `//#region persistData`. This caused incorrect
matching when one region name was a prefix of another—searching for
`persistData` would match `//#region persistDataServer` first if it
appeared earlier in the file.

The fix detects the file's line ending style and appends it to region
markers, ensuring exact matches:
- `//#region persistData\n` no longer matches `//#region persistDataServer\n`

This corrects `docs/patterns.md` where the `persistData` code fence was
incorrectly showing server-side code instead of client-side localStorage
helpers.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jonathan Hefner 2026-01-27 12:56:28 -06:00
commit 1215bf33c3
No known key found for this signature in database
GPG key ID: 0DA40AFD21043691
2 changed files with 42 additions and 9 deletions

View file

@ -345,14 +345,46 @@ return {
<!-- prettier-ignore -->
```tsx source="./patterns.tsx#persistData"
// In your tool callback, include viewUUID in the result metadata.
return {
content: [{ type: "text", text: `Displaying PDF viewer for "${title}"` }],
structuredContent: { url, title, pageCount, initialPage: 1 },
_meta: {
viewUUID: randomUUID(),
},
// Store the viewUUID received from the server
let viewUUID: string | undefined;
// Helper to save state to localStorage
function saveState<T>(state: T): void {
if (!viewUUID) return;
try {
localStorage.setItem(viewUUID, JSON.stringify(state));
} catch (err) {
console.error("Failed to save view state:", err);
}
}
// Helper to load state from localStorage
function loadState<T>(): T | null {
if (!viewUUID) return null;
try {
const saved = localStorage.getItem(viewUUID);
return saved ? (JSON.parse(saved) as T) : null;
} catch (err) {
console.error("Failed to load view state:", err);
return null;
}
}
// Receive viewUUID from the tool result
app.ontoolresult = (result) => {
viewUUID = result._meta?.viewUUID
? String(result._meta.viewUUID)
: undefined;
// Restore any previously saved state
const savedState = loadState<{ currentPage: number }>();
if (savedState) {
// Apply restored state to your UI...
}
};
// Call saveState() whenever your view state changes
// e.g., saveState({ currentPage: 5 });
```
_See [`examples/map-server/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/map-server) for a full implementation of this pattern._

View file

@ -254,8 +254,9 @@ function extractRegion(
);
}
const regionStart = `//#region ${regionName}`;
const regionEnd = `//#endregion ${regionName}`;
const lineEnding = exampleContent.includes("\r\n") ? "\r\n" : "\n";
const regionStart = `//#region ${regionName}${lineEnding}`;
const regionEnd = `//#endregion ${regionName}${lineEnding}`;
const startIndex = exampleContent.indexOf(regionStart);
if (startIndex === -1) {