testomatio-editor-blocks 0.4.32 → 0.4.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- const IMAGE_MARKDOWN_REGEX = /!\[([^\]]*)\]\(([^)]+)\)/g;
1
+ const IMAGE_MARKDOWN_REGEX = /!\[([^\]]*)\]\(([^)]+?)(?:\s+=\d+x(?:\d+|\*))?\)/g;
2
2
  const MARKDOWN_ESCAPE_REGEX = /([*_\\])/g;
3
3
  const INLINE_SEGMENT_REGEX = /(\*\*\*[^*]+\*\*\*|___[^_]+___|\*\*[^*]+\*\*|__[^_]+__|\*[^*]+\*|_[^_]+_|<u>[^<]+<\/u>)/;
4
4
  export function escapeHtml(text) {
@@ -262,8 +262,10 @@ function serializeBlock(block, ctx, orderedIndex, stepIndex) {
262
262
  case "image": {
263
263
  const url = block.props.url || "";
264
264
  const caption = block.props.caption || "";
265
+ const width = block.props.previewWidth;
265
266
  if (url) {
266
- lines.push(`![${caption}](${url})`);
267
+ const size = width ? ` =${width}x*` : "";
268
+ lines.push(`![${caption}](${url}${size})`);
267
269
  }
268
270
  return flattenWithBlankLine(lines, true);
269
271
  }
@@ -1239,14 +1241,16 @@ export function markdownToBlocks(markdown) {
1239
1241
  index += 1;
1240
1242
  continue;
1241
1243
  }
1242
- const imageMatch = line.trim().match(/^!\[([^\]]*)\]\(([^)]+)\)$/);
1244
+ const imageMatch = line.trim().match(/^!\[([^\]]*)\]\(([^)]+?)(?:\s+=(\d+)x(\d+|\*))?\)$/);
1243
1245
  if (imageMatch) {
1246
+ const width = imageMatch[3] ? parseInt(imageMatch[3], 10) : undefined;
1244
1247
  blocks.push({
1245
1248
  type: "image",
1246
1249
  props: {
1247
1250
  url: imageMatch[2],
1248
1251
  caption: imageMatch[1] || "",
1249
1252
  name: "",
1253
+ ...(width ? { previewWidth: width } : {}),
1250
1254
  },
1251
1255
  children: [],
1252
1256
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testomatio-editor-blocks",
3
- "version": "0.4.32",
3
+ "version": "0.4.33",
4
4
  "description": "Custom BlockNote schema, markdown conversion helpers, and UI for Testomatio-style test cases and steps.",
5
5
  "type": "module",
6
6
  "main": "./package/index.js",
@@ -1,4 +1,4 @@
1
- const IMAGE_MARKDOWN_REGEX = /!\[([^\]]*)\]\(([^)]+)\)/g;
1
+ const IMAGE_MARKDOWN_REGEX = /!\[([^\]]*)\]\(([^)]+?)(?:\s+=\d+x(?:\d+|\*))?\)/g;
2
2
  const MARKDOWN_ESCAPE_REGEX = /([*_\\])/g;
3
3
  const INLINE_SEGMENT_REGEX =
4
4
  /(\*\*\*[^*]+\*\*\*|___[^_]+___|\*\*[^*]+\*\*|__[^_]+__|\*[^*]+\*|_[^_]+_|<u>[^<]+<\/u>)/;
@@ -1430,6 +1430,70 @@ describe("markdownToBlocks", () => {
1430
1430
  expect(roundTripMarkdown).toContain("![](/attachments/test.png)");
1431
1431
  });
1432
1432
 
1433
+ it("parses image with size suffix =WIDTHxHEIGHT", () => {
1434
+ const markdown = "![caption](http://localhost:3000/attachments/img.png =200x100)";
1435
+ const blocks = markdownToBlocks(markdown);
1436
+
1437
+ const imageBlocks = blocks.filter(block => block.type === "image");
1438
+ expect(imageBlocks.length).toBe(1);
1439
+ expect((imageBlocks[0].props as any).url).toBe("http://localhost:3000/attachments/img.png");
1440
+ expect((imageBlocks[0].props as any).caption).toBe("caption");
1441
+ expect((imageBlocks[0].props as any).previewWidth).toBe(200);
1442
+ });
1443
+
1444
+ it("parses image with size suffix =WIDTHx*", () => {
1445
+ const markdown = "![](http://localhost:3000/attachments/img.png =150x*)";
1446
+ const blocks = markdownToBlocks(markdown);
1447
+
1448
+ const imageBlocks = blocks.filter(block => block.type === "image");
1449
+ expect(imageBlocks.length).toBe(1);
1450
+ expect((imageBlocks[0].props as any).url).toBe("http://localhost:3000/attachments/img.png");
1451
+ expect((imageBlocks[0].props as any).previewWidth).toBe(150);
1452
+ });
1453
+
1454
+ it("serializes image block with previewWidth to =WIDTHx*", () => {
1455
+ const blocks: any[] = [
1456
+ {
1457
+ type: "image",
1458
+ props: {
1459
+ url: "/attachments/test.png",
1460
+ caption: "test",
1461
+ name: "",
1462
+ previewWidth: 300,
1463
+ },
1464
+ content: [],
1465
+ children: [],
1466
+ },
1467
+ ];
1468
+ const markdown = blocksToMarkdown(blocks as CustomEditorBlock[]);
1469
+ expect(markdown).toContain("![test](/attachments/test.png =300x*)");
1470
+ });
1471
+
1472
+ it("serializes image block without previewWidth normally", () => {
1473
+ const blocks: any[] = [
1474
+ {
1475
+ type: "image",
1476
+ props: {
1477
+ url: "/attachments/test.png",
1478
+ caption: "",
1479
+ name: "",
1480
+ },
1481
+ content: [],
1482
+ children: [],
1483
+ },
1484
+ ];
1485
+ const markdown = blocksToMarkdown(blocks as CustomEditorBlock[]);
1486
+ expect(markdown).toContain("![](/attachments/test.png)");
1487
+ expect(markdown).not.toContain("=");
1488
+ });
1489
+
1490
+ it("round-trips image with size preserving width", () => {
1491
+ const markdown = "![photo](/attachments/photo.png =400x250)";
1492
+ const blocks = markdownToBlocks(markdown);
1493
+ const roundTripMarkdown = blocksToMarkdown(blocks as CustomEditorBlock[]);
1494
+ expect(roundTripMarkdown).toContain("![photo](/attachments/photo.png =400x*)");
1495
+ });
1496
+
1433
1497
  it("removes malformed image blocks through post-processing", () => {
1434
1498
  // Simulate the malformed blocks you're seeing
1435
1499
  const malformedBlocks: any[] = [
@@ -340,8 +340,10 @@ function serializeBlock(
340
340
  case "image": {
341
341
  const url = (block.props as any).url || "";
342
342
  const caption = (block.props as any).caption || "";
343
+ const width = (block.props as any).previewWidth;
343
344
  if (url) {
344
- lines.push(`![${caption}](${url})`);
345
+ const size = width ? ` =${width}x*` : "";
346
+ lines.push(`![${caption}](${url}${size})`);
345
347
  }
346
348
  return flattenWithBlankLine(lines, true);
347
349
  }
@@ -1482,14 +1484,16 @@ export function markdownToBlocks(markdown: string): CustomPartialBlock[] {
1482
1484
  continue;
1483
1485
  }
1484
1486
 
1485
- const imageMatch = line.trim().match(/^!\[([^\]]*)\]\(([^)]+)\)$/);
1487
+ const imageMatch = line.trim().match(/^!\[([^\]]*)\]\(([^)]+?)(?:\s+=(\d+)x(\d+|\*))?\)$/);
1486
1488
  if (imageMatch) {
1489
+ const width = imageMatch[3] ? parseInt(imageMatch[3], 10) : undefined;
1487
1490
  blocks.push({
1488
1491
  type: "image",
1489
1492
  props: {
1490
1493
  url: imageMatch[2],
1491
1494
  caption: imageMatch[1] || "",
1492
1495
  name: "",
1496
+ ...(width ? { previewWidth: width } : {}),
1493
1497
  },
1494
1498
  children: [],
1495
1499
  } as CustomPartialBlock);