testomatio-editor-blocks 0.4.60 → 0.4.61

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.
@@ -22,7 +22,7 @@ const headingPrefixes = {
22
22
  5: "#####",
23
23
  6: "######",
24
24
  };
25
- const SPECIAL_CHAR_REGEX = /([*_`~()<\\])/g;
25
+ const SPECIAL_CHAR_REGEX = /([*_`~()\\])/g;
26
26
  const HTML_COMMENT_REGEX = /<!--[\s\S]*?-->/g;
27
27
  const HTML_SPAN_REGEX = /<\/?span[^>]*>/g;
28
28
  const HTML_UNDERLINE_REGEX = /<\/?u>/g;
@@ -157,6 +157,7 @@ function applyTextStyles(text, styles) {
157
157
  return wrapped.join("\n");
158
158
  }
159
159
  function inlineToMarkdown(content) {
160
+ var _a;
160
161
  if (!content || !Array.isArray(content)) {
161
162
  return "";
162
163
  }
@@ -174,7 +175,9 @@ function inlineToMarkdown(content) {
174
175
  i += 2;
175
176
  continue;
176
177
  }
177
- result.push(applyTextStyles(escapeMarkdown(item.text), item.styles));
178
+ const isCode = ((_a = item.styles) === null || _a === void 0 ? void 0 : _a.code) === true;
179
+ const rendered = isCode ? item.text : escapeMarkdown(item.text);
180
+ result.push(applyTextStyles(rendered, item.styles));
178
181
  i += 1;
179
182
  continue;
180
183
  }
@@ -261,7 +264,7 @@ function serializeBlock(block, ctx, orderedIndex, stepIndex) {
261
264
  case "codeBlock": {
262
265
  const language = block.props.language || "";
263
266
  const fence = "```" + language;
264
- const body = inlineToMarkdown(block.content);
267
+ const body = inlineContentToPlainText(block.content);
265
268
  lines.push(fence);
266
269
  if (body.length > 0) {
267
270
  lines.push(body);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testomatio-editor-blocks",
3
- "version": "0.4.60",
3
+ "version": "0.4.61",
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",
@@ -62,7 +62,7 @@ describe("blocksToMarkdown", () => {
62
62
  expect(blocksToMarkdown(blocks)).toBe("<!-- ai/agent generated description -->");
63
63
  });
64
64
 
65
- it("preserves HTML comments inline among text and still escapes stray angle brackets", () => {
65
+ it("preserves HTML comments inline among text without escaping stray angle brackets", () => {
66
66
  const blocks: CustomEditorBlock[] = [
67
67
  {
68
68
  id: "c2",
@@ -75,7 +75,98 @@ describe("blocksToMarkdown", () => {
75
75
  },
76
76
  ];
77
77
 
78
- expect(blocksToMarkdown(blocks)).toBe("before <!-- note --> after \\<div>");
78
+ expect(blocksToMarkdown(blocks)).toBe("before <!-- note --> after <div>");
79
+ });
80
+
81
+ it("does not escape `<` in plain text (e.g. comparison operators)", () => {
82
+ const blocks: CustomEditorBlock[] = [
83
+ {
84
+ id: "p_lt",
85
+ type: "paragraph",
86
+ props: baseProps,
87
+ content: [
88
+ { type: "text", text: "< 768px is mobile", styles: {} },
89
+ ],
90
+ children: [],
91
+ },
92
+ ];
93
+
94
+ expect(blocksToMarkdown(blocks)).toBe("< 768px is mobile");
95
+ });
96
+
97
+ it("does not escape `<` in table cells (viewport breakpoints case)", () => {
98
+ const markdown = [
99
+ "| Viewport Width | Layout Expected | Nav Behavior |",
100
+ "| --- | --- | --- |",
101
+ "| < 768px | Single column | Hamburger menu |",
102
+ "| 768px – 1024px | Two column | Collapsed sidebar |",
103
+ "| > 1024px | Full desktop layout | Full nav visible |",
104
+ ].join("\n");
105
+
106
+ const blocks = markdownToBlocks(markdown);
107
+ const out = blocksToMarkdown(blocks as CustomEditorBlock[]);
108
+ expect(out).toBe(markdown);
109
+ expect(out).not.toContain("\\<");
110
+ });
111
+
112
+ it("does not escape markdown chars inside inline code", () => {
113
+ const blocks: CustomEditorBlock[] = [
114
+ {
115
+ id: "p_code",
116
+ type: "paragraph",
117
+ props: baseProps,
118
+ content: [
119
+ { type: "text", text: "**bold**", styles: { code: true } },
120
+ ],
121
+ children: [],
122
+ },
123
+ ];
124
+
125
+ expect(blocksToMarkdown(blocks)).toBe("`**bold**`");
126
+ });
127
+
128
+ it("does not escape markdown chars inside inline code in a table (syntax/rendered case)", () => {
129
+ const markdown = [
130
+ "| Syntax | Rendered As |",
131
+ "| --- | --- |",
132
+ "| `**bold**` | **bold** |",
133
+ "| `*italic*` | _italic_ |",
134
+ "| `~~strike~~` | ~~strike~~ |",
135
+ ].join("\n");
136
+
137
+ const blocks = markdownToBlocks(markdown);
138
+ const out = blocksToMarkdown(blocks as CustomEditorBlock[]);
139
+ expect(out).toBe(markdown);
140
+ expect(out).not.toMatch(/\\[*_~]/);
141
+ });
142
+
143
+ it("does not escape markdown chars inside fenced code blocks", () => {
144
+ const markdown = [
145
+ "```",
146
+ "**bold** _italic_ ~~strike~~ <div>",
147
+ "```",
148
+ ].join("\n");
149
+
150
+ const blocks = markdownToBlocks(markdown);
151
+ const out = blocksToMarkdown(blocks as CustomEditorBlock[]);
152
+ expect(out).toBe(markdown);
153
+ expect(out).not.toMatch(/\\[*_~<]/);
154
+ });
155
+
156
+ it("still escapes literal backticks inside inline code", () => {
157
+ const blocks: CustomEditorBlock[] = [
158
+ {
159
+ id: "p_tick",
160
+ type: "paragraph",
161
+ props: baseProps,
162
+ content: [
163
+ { type: "text", text: "a`b", styles: { code: true } },
164
+ ],
165
+ children: [],
166
+ },
167
+ ];
168
+
169
+ expect(blocksToMarkdown(blocks)).toBe("`a\\`b`");
79
170
  });
80
171
 
81
172
  it("places bold markers outside leading/trailing spaces", () => {
@@ -60,7 +60,7 @@ const headingPrefixes: Record<number, string> = {
60
60
  6: "######",
61
61
  };
62
62
 
63
- const SPECIAL_CHAR_REGEX = /([*_`~()<\\])/g;
63
+ const SPECIAL_CHAR_REGEX = /([*_`~()\\])/g;
64
64
  const HTML_COMMENT_REGEX = /<!--[\s\S]*?-->/g;
65
65
  const HTML_SPAN_REGEX = /<\/?span[^>]*>/g;
66
66
  const HTML_UNDERLINE_REGEX = /<\/?u>/g;
@@ -234,7 +234,9 @@ function inlineToMarkdown(content: CustomEditorBlock["content"]): string {
234
234
  i += 2;
235
235
  continue;
236
236
  }
237
- result.push(applyTextStyles(escapeMarkdown(item.text), item.styles));
237
+ const isCode = (item.styles as any)?.code === true;
238
+ const rendered = isCode ? item.text : escapeMarkdown(item.text);
239
+ result.push(applyTextStyles(rendered, item.styles));
238
240
  i += 1;
239
241
  continue;
240
242
  }
@@ -334,7 +336,7 @@ function serializeBlock(
334
336
  case "codeBlock": {
335
337
  const language = (block.props as any).language || "";
336
338
  const fence = "```" + language;
337
- const body = inlineToMarkdown(block.content);
339
+ const body = inlineContentToPlainText(block.content);
338
340
  lines.push(fence);
339
341
  if (body.length > 0) {
340
342
  lines.push(body);