@link-assistant/web-capture 1.7.20 → 1.7.21
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.21
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b8ad97d: Number consecutive top-level `<ol>`s continuously across the document (1, 2, 3, ... N) so JS and Rust HTML→Markdown converters agree. `<ol start="N">` resets the counter and is honoured by both implementations. Nested ordered lists keep their own per-list numbering.
|
|
8
|
+
|
|
3
9
|
## 1.7.20
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/package.json
CHANGED
package/src/gdocs-preprocess.js
CHANGED
|
@@ -245,6 +245,12 @@ function renderNestedListGroup($, group, classStyles) {
|
|
|
245
245
|
const openTags = [];
|
|
246
246
|
const itemOpen = [];
|
|
247
247
|
|
|
248
|
+
const topLevelStart =
|
|
249
|
+
group[0]?.tagName?.toLowerCase() === 'ol'
|
|
250
|
+
? $(group[0]).attr('start')
|
|
251
|
+
: undefined;
|
|
252
|
+
let topLevelOpened = false;
|
|
253
|
+
|
|
248
254
|
const closeItem = (level) => {
|
|
249
255
|
if (itemOpen[level]) {
|
|
250
256
|
html += '</li>';
|
|
@@ -261,7 +267,21 @@ function renderNestedListGroup($, group, classStyles) {
|
|
|
261
267
|
const openList = (level, tagName) => {
|
|
262
268
|
openTags[level] = tagName;
|
|
263
269
|
itemOpen[level] = false;
|
|
264
|
-
|
|
270
|
+
if (
|
|
271
|
+
level === 0 &&
|
|
272
|
+
!topLevelOpened &&
|
|
273
|
+
tagName === 'ol' &&
|
|
274
|
+
topLevelStart !== undefined &&
|
|
275
|
+
topLevelStart !== ''
|
|
276
|
+
) {
|
|
277
|
+
html += `<ol start="${topLevelStart}">`;
|
|
278
|
+
topLevelOpened = true;
|
|
279
|
+
} else {
|
|
280
|
+
if (level === 0) {
|
|
281
|
+
topLevelOpened = true;
|
|
282
|
+
}
|
|
283
|
+
html += `<${tagName}>`;
|
|
284
|
+
}
|
|
265
285
|
};
|
|
266
286
|
|
|
267
287
|
for (const list of group) {
|
package/src/lib.js
CHANGED
|
@@ -59,6 +59,10 @@ export function convertHtmlToMarkdown(html, baseUrl) {
|
|
|
59
59
|
// Demoting avoids ATX heading prefix, leaving the sub-number on a clean line.
|
|
60
60
|
preserveLeadingHeadingNumbering($);
|
|
61
61
|
|
|
62
|
+
// Number consecutive top-level <ol>s continuously across the document
|
|
63
|
+
// (1, 2, 3 ... N) so JS and Rust agree. <ol start="N"> resets the counter.
|
|
64
|
+
applyContinuousOrderedListNumbering($);
|
|
65
|
+
|
|
62
66
|
// Remove <a> tags with no direct text content (including only whitespace or only child elements)
|
|
63
67
|
$('a').each(function () {
|
|
64
68
|
// Get all text nodes directly under this <a>
|
|
@@ -228,6 +232,28 @@ function preserveLeadingHeadingNumbering($) {
|
|
|
228
232
|
});
|
|
229
233
|
}
|
|
230
234
|
|
|
235
|
+
// Walk every top-level <ol> in document order and assign a `start` attribute
|
|
236
|
+
// so consecutive lists number continuously (1, 2, 3, ... N). An explicit
|
|
237
|
+
// `start="N"` resets the running counter to N and is preserved.
|
|
238
|
+
//
|
|
239
|
+
// Top-level here means "not inside another <ol> or <ul>" — nested ordered
|
|
240
|
+
// lists keep their own numbering and Turndown's per-list start handling.
|
|
241
|
+
function applyContinuousOrderedListNumbering($) {
|
|
242
|
+
let counter = 1;
|
|
243
|
+
$('ol').each(function () {
|
|
244
|
+
if ($(this).parents('ol, ul').length > 0) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const explicitStart = parseInt($(this).attr('start') ?? '', 10);
|
|
248
|
+
if (Number.isFinite(explicitStart)) {
|
|
249
|
+
counter = explicitStart;
|
|
250
|
+
} else {
|
|
251
|
+
$(this).attr('start', String(counter));
|
|
252
|
+
}
|
|
253
|
+
counter += $(this).children('li').length;
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
231
257
|
function stripLeadingTextFromHeading($, $heading, prefixLen) {
|
|
232
258
|
// Walk text nodes from the start of the heading and remove prefixLen characters.
|
|
233
259
|
let remaining = prefixLen;
|
|
@@ -506,6 +532,9 @@ export function convertHtmlToMarkdownEnhanced(html, baseUrl, options = {}) {
|
|
|
506
532
|
// Preserve hierarchical heading numbering (see convertHtmlToMarkdown).
|
|
507
533
|
preserveLeadingHeadingNumbering($);
|
|
508
534
|
|
|
535
|
+
// Continuous numbering across consecutive top-level <ol>s (see convertHtmlToMarkdown).
|
|
536
|
+
applyContinuousOrderedListNumbering($);
|
|
537
|
+
|
|
509
538
|
// Remove empty links (same logic as convertHtmlToMarkdown)
|
|
510
539
|
$('a').each(function () {
|
|
511
540
|
const directText = $(this)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<ol>
|
|
2
|
+
<li><strong>First</strong></li>
|
|
3
|
+
<li><strong>Second</strong></li>
|
|
4
|
+
</ol>
|
|
5
|
+
<p>Some prose between lists.</p>
|
|
6
|
+
<ol>
|
|
7
|
+
<li><strong>Third</strong></li>
|
|
8
|
+
<li><strong>Fourth</strong></li>
|
|
9
|
+
</ol>
|
|
10
|
+
<ol start="13">
|
|
11
|
+
<li><strong>Top-level numbered heading.</strong></li>
|
|
12
|
+
</ol>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { convertHtmlToMarkdown } from '../../src/lib.js';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
const HTML = fs.readFileSync(
|
|
9
|
+
path.join(__dirname, '..', 'fixtures', 'ol-continuous-numbering.html'),
|
|
10
|
+
'utf8'
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
it('numbers consecutive top-level ordered lists continuously', () => {
|
|
14
|
+
const md = convertHtmlToMarkdown(HTML);
|
|
15
|
+
expect(md).toMatch(/^\s*1\.\s+\*\*First\*\*/m);
|
|
16
|
+
expect(md).toMatch(/^\s*2\.\s+\*\*Second\*\*/m);
|
|
17
|
+
expect(md).toMatch(/^\s*3\.\s+\*\*Third\*\*/m);
|
|
18
|
+
expect(md).toMatch(/^\s*4\.\s+\*\*Fourth\*\*/m);
|
|
19
|
+
expect(md).toMatch(/^\s*13\.\s+\*\*Top-level/m);
|
|
20
|
+
});
|