@link-assistant/web-capture 1.7.18 → 1.7.19

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @link-assistant/web-capture
2
2
 
3
+ ## 1.7.19
4
+
5
+ ### Patch Changes
6
+
7
+ - 3a483aa: Fix Google Docs public-export Markdown for multi-paragraph table cells.
8
+
3
9
  ## 1.7.18
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/web-capture",
3
- "version": "1.7.18",
3
+ "version": "1.7.19",
4
4
  "description": "CLI and microservice to render web pages as HTML, Markdown, or PNG",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -379,7 +379,7 @@ function inlineTableCellHtml($, cell) {
379
379
  parts.push(this.data);
380
380
  }
381
381
  });
382
- return parts.join('<br>');
382
+ return parts.join('<br><br>');
383
383
  }
384
384
 
385
385
  function hasBoldStyle(style) {
package/src/lib.js CHANGED
@@ -166,11 +166,34 @@ export function convertHtmlToMarkdown(html, baseUrl) {
166
166
  style: false,
167
167
  });
168
168
  turndown.use(turndownPluginGfm.gfm);
169
+ preserveTableCellLineBreaks(turndown);
169
170
  // Decode HTML entities to unicode after markdown conversion
170
171
  // Preserve non-breaking spaces as &nbsp; entities for clear marking
171
172
  return he.decode(turndown.turndown($.html())).replace(/\u00A0/g, '&nbsp;');
172
173
  }
173
174
 
175
+ function preserveTableCellLineBreaks(turndown) {
176
+ turndown.addRule('tableCellLineBreak', {
177
+ filter(node) {
178
+ return node.nodeName === 'BR' && hasAncestorNode(node, ['TD', 'TH']);
179
+ },
180
+ replacement() {
181
+ return '<br>';
182
+ },
183
+ });
184
+ }
185
+
186
+ function hasAncestorNode(node, nodeNames) {
187
+ let current = node.parentNode;
188
+ while (current) {
189
+ if (nodeNames.includes(current.nodeName)) {
190
+ return true;
191
+ }
192
+ current = current.parentNode;
193
+ }
194
+ return false;
195
+ }
196
+
174
197
  function selectedHtml($, selector) {
175
198
  if (!selector) {
176
199
  return null;
@@ -531,6 +554,7 @@ export function convertHtmlToMarkdownEnhanced(html, baseUrl, options = {}) {
531
554
  style: false,
532
555
  });
533
556
  turndown.use(turndownPluginGfm.gfm);
557
+ preserveTableCellLineBreaks(turndown);
534
558
 
535
559
  // Decode HTML entities to unicode after markdown conversion
536
560
  // Normalize non-breaking spaces to regular spaces in Markdown text
@@ -0,0 +1,36 @@
1
+ import {
2
+ normalizeGoogleDocsExportMarkdown,
3
+ preprocessGoogleDocsExportHtml,
4
+ } from '../../src/gdocs.js';
5
+ import { convertHtmlToMarkdown } from '../../src/lib.js';
6
+
7
+ describe('preprocessGoogleDocsExportHtml', () => {
8
+ it('keeps multi-paragraph table cells on one GFM row (issue #110)', () => {
9
+ const html = `
10
+ <table>
11
+ <tr><td><p>Feature</p></td><td><p>Notes</p></td></tr>
12
+ <tr>
13
+ <td>
14
+ <p>First paragraph.</p>
15
+ <p>Second paragraph.</p>
16
+ <p>Third paragraph.</p>
17
+ </td>
18
+ <td><p>x</p></td>
19
+ </tr>
20
+ </table>
21
+ `;
22
+
23
+ const preprocessed = preprocessGoogleDocsExportHtml(html);
24
+ const markdown = normalizeGoogleDocsExportMarkdown(
25
+ convertHtmlToMarkdown(preprocessed.html)
26
+ );
27
+
28
+ expect(preprocessed.html).toContain(
29
+ '<td>First paragraph.<br><br>Second paragraph.<br><br>Third paragraph.</td>'
30
+ );
31
+ expect(markdown).toContain(
32
+ '| First paragraph.<br><br>Second paragraph.<br><br>Third paragraph. | x |'
33
+ );
34
+ expect(markdown).not.toContain('First paragraph. \n');
35
+ });
36
+ });