Skip to content

Commit f78bd68

Browse files
fix: update image regex to handle URLs with parentheses (#704)
* fix: update image regex to handle URLs with parentheses Co-Authored-By: Max Prilutskiy <maks.prilutskiy@gmail.com> * chore: add changeset for image regex fix Co-Authored-By: Max Prilutskiy <maks.prilutskiy@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Max Prilutskiy <maks.prilutskiy@gmail.com>
1 parent c5ccf81 commit f78bd68

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed

.changeset/angry-chairs-shave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"lingo.dev": patch
3+
---
4+
5+
Fix image regex in MDX2 loader to handle URLs with parentheses

packages/cli/src/cli/loaders/mdx2/code-placeholder.spec.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,4 +450,64 @@ describe("MDX Code Placeholder Loader", () => {
450450
expect(ruPushed).toBe("Примените `бар` функцию.");
451451
});
452452
});
453+
454+
describe("Image URLs with Parentheses", () => {
455+
it("should handle image URLs with parentheses", async () => {
456+
const md = dedent`
457+
Text above.
458+
459+
![](https://example.com/image(with)parentheses.jpg)
460+
461+
Text below.
462+
`;
463+
464+
const pulled = await loader.pull("en", md);
465+
const pushed = await loader.push("es", pulled);
466+
expect(pushed).toBe(md);
467+
});
468+
469+
it("should handle image URLs with nested parentheses", async () => {
470+
const md = dedent`
471+
Text above.
472+
473+
![Alt text](https://example.com/image(with(nested)parentheses).jpg)
474+
475+
Text below.
476+
`;
477+
478+
const pulled = await loader.pull("en", md);
479+
const pushed = await loader.push("es", pulled);
480+
expect(pushed).toBe(md);
481+
});
482+
483+
it("should handle image URLs with parentheses in blockquotes", async () => {
484+
const md = dedent`
485+
> ![Blockquote image](https://example.com/image(in)blockquote.jpg)
486+
`;
487+
488+
const pulled = await loader.pull("en", md);
489+
const pushed = await loader.push("es", pulled);
490+
expect(pushed).toBe(md);
491+
});
492+
493+
it("should handle image URLs with parentheses in JSX components", async () => {
494+
const md = dedent`
495+
<Component>
496+
![Component image](https://example.com/image(in)component.jpg)
497+
</Component>
498+
`;
499+
500+
const expected = dedent`
501+
<Component>
502+
503+
![Component image](https://example.com/image(in)component.jpg)
504+
505+
</Component>
506+
`;
507+
508+
const pulled = await loader.pull("en", md);
509+
const pushed = await loader.push("es", pulled);
510+
expect(pushed).toBe(expected);
511+
});
512+
});
453513
});

packages/cli/src/cli/loaders/mdx2/code-placeholder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const inlineCodeRegex = /(?<!`)`([^`\r\n]+?)`(?!`)/g;
88

99
// Matches markdown image tags, with optional alt text & parenthesis URL, possibly inside blockquotes
1010
// Captures patterns like ![](url) or ![alt](url), with optional leading '> ' for blockquotes
11-
const imageRegex = /([ \t]*)(^>\s*)?!\[[^\]]*?\]\([^\n\r]*?\)/gm;
11+
const imageRegex = /([ \t]*)(^>\s*)?!\[[^\]]*?\]\(([^()]*(\([^()]*\)[^()]*)*)\)/gm;
1212

1313
/**
1414
* Ensures that markdown image tags are surrounded by blank lines (\n\n) so that they are properly

0 commit comments

Comments
 (0)