@md2do/core 0.2.2 → 0.2.3

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/coverage/coverage-final.json +9 -9
  3. package/coverage/index.html +14 -14
  4. package/coverage/lcov-report/index.html +14 -14
  5. package/coverage/lcov-report/src/filters/index.html +1 -1
  6. package/coverage/lcov-report/src/filters/index.ts.html +1 -1
  7. package/coverage/lcov-report/src/index.html +1 -1
  8. package/coverage/lcov-report/src/index.ts.html +1 -1
  9. package/coverage/lcov-report/src/parser/index.html +9 -9
  10. package/coverage/lcov-report/src/parser/index.ts.html +334 -124
  11. package/coverage/lcov-report/src/parser/patterns.ts.html +1 -1
  12. package/coverage/lcov-report/src/scanner/index.html +7 -7
  13. package/coverage/lcov-report/src/scanner/index.ts.html +208 -70
  14. package/coverage/lcov-report/src/sorting/index.html +1 -1
  15. package/coverage/lcov-report/src/sorting/index.ts.html +1 -1
  16. package/coverage/lcov-report/src/utils/dates.ts.html +21 -21
  17. package/coverage/lcov-report/src/utils/id.ts.html +8 -8
  18. package/coverage/lcov-report/src/utils/index.html +1 -1
  19. package/coverage/lcov-report/src/writer/index.html +1 -1
  20. package/coverage/lcov-report/src/writer/index.ts.html +1 -1
  21. package/coverage/lcov.info +479 -342
  22. package/coverage/src/filters/index.html +1 -1
  23. package/coverage/src/filters/index.ts.html +1 -1
  24. package/coverage/src/index.html +1 -1
  25. package/coverage/src/index.ts.html +1 -1
  26. package/coverage/src/parser/index.html +9 -9
  27. package/coverage/src/parser/index.ts.html +334 -124
  28. package/coverage/src/parser/patterns.ts.html +1 -1
  29. package/coverage/src/scanner/index.html +7 -7
  30. package/coverage/src/scanner/index.ts.html +208 -70
  31. package/coverage/src/sorting/index.html +1 -1
  32. package/coverage/src/sorting/index.ts.html +1 -1
  33. package/coverage/src/utils/dates.ts.html +21 -21
  34. package/coverage/src/utils/id.ts.html +8 -8
  35. package/coverage/src/utils/index.html +1 -1
  36. package/coverage/src/writer/index.html +1 -1
  37. package/coverage/src/writer/index.ts.html +1 -1
  38. package/dist/index.js +88 -0
  39. package/dist/index.mjs +88 -0
  40. package/package.json +1 -1
  41. package/src/parser/index.ts +70 -0
  42. package/src/scanner/index.ts +46 -0
  43. package/tests/parser/index.test.ts +107 -1
  44. package/tests/scanner/index.test.ts +94 -4
@@ -25,14 +25,14 @@
25
25
  <div class='fl pad1y space-right2'>
26
26
  <span class="strong">100% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>145/145</span>
28
+ <span class='fraction'>191/191</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
33
  <span class="strong">100% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>17/17</span>
35
+ <span class='fraction'>23/23</span>
36
36
  </div>
37
37
 
38
38
 
@@ -46,7 +46,7 @@
46
46
  <div class='fl pad1y space-right2'>
47
47
  <span class="strong">100% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>145/145</span>
49
+ <span class='fraction'>191/191</span>
50
50
  </div>
51
51
 
52
52
 
@@ -84,13 +84,13 @@
84
84
  <div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
85
85
  </td>
86
86
  <td data-value="100" class="pct high">100%</td>
87
- <td data-value="145" class="abs high">145/145</td>
87
+ <td data-value="191" class="abs high">191/191</td>
88
88
  <td data-value="100" class="pct high">100%</td>
89
- <td data-value="17" class="abs high">17/17</td>
89
+ <td data-value="23" class="abs high">23/23</td>
90
90
  <td data-value="100" class="pct high">100%</td>
91
91
  <td data-value="4" class="abs high">4/4</td>
92
92
  <td data-value="100" class="pct high">100%</td>
93
- <td data-value="145" class="abs high">145/145</td>
93
+ <td data-value="191" class="abs high">191/191</td>
94
94
  </tr>
95
95
 
96
96
  </tbody>
@@ -101,7 +101,7 @@
101
101
  <div class='footer quiet pad2 space-top1 center small'>
102
102
  Code coverage generated by
103
103
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
104
- at 2026-01-22T01:16:22.209Z
104
+ at 2026-01-26T03:50:53.066Z
105
105
  </div>
106
106
  <script src="../../prettify.js"></script>
107
107
  <script>
@@ -25,14 +25,14 @@
25
25
  <div class='fl pad1y space-right2'>
26
26
  <span class="strong">100% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>145/145</span>
28
+ <span class='fraction'>191/191</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
33
  <span class="strong">100% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>17/17</span>
35
+ <span class='fraction'>23/23</span>
36
36
  </div>
37
37
 
38
38
 
@@ -46,7 +46,7 @@
46
46
  <div class='fl pad1y space-right2'>
47
47
  <span class="strong">100% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>145/145</span>
49
+ <span class='fraction'>191/191</span>
50
50
  </div>
51
51
 
52
52
 
@@ -208,7 +208,53 @@
208
208
  <a name='L143'></a><a href='#L143'>143</a>
209
209
  <a name='L144'></a><a href='#L144'>144</a>
210
210
  <a name='L145'></a><a href='#L145'>145</a>
211
- <a name='L146'></a><a href='#L146'>146</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
212
258
  <span class="cline-any cline-yes">1x</span>
213
259
  <span class="cline-any cline-yes">1x</span>
214
260
  <span class="cline-any cline-yes">1x</span>
@@ -226,9 +272,9 @@
226
272
  <span class="cline-any cline-yes">1x</span>
227
273
  <span class="cline-any cline-yes">1x</span>
228
274
  <span class="cline-any cline-yes">1x</span>
229
- <span class="cline-any cline-yes">43x</span>
230
- <span class="cline-any cline-yes">43x</span>
231
- <span class="cline-any cline-yes">43x</span>
275
+ <span class="cline-any cline-yes">51x</span>
276
+ <span class="cline-any cline-yes">51x</span>
277
+ <span class="cline-any cline-yes">51x</span>
232
278
  <span class="cline-any cline-yes">1x</span>
233
279
  <span class="cline-any cline-yes">1x</span>
234
280
  <span class="cline-any cline-yes">1x</span>
@@ -244,11 +290,11 @@
244
290
  <span class="cline-any cline-yes">1x</span>
245
291
  <span class="cline-any cline-yes">1x</span>
246
292
  <span class="cline-any cline-yes">1x</span>
247
- <span class="cline-any cline-yes">42x</span>
248
- <span class="cline-any cline-yes">42x</span>
249
- <span class="cline-any cline-yes">42x</span>
250
- <span class="cline-any cline-yes">42x</span>
251
- <span class="cline-any cline-yes">42x</span>
293
+ <span class="cline-any cline-yes">50x</span>
294
+ <span class="cline-any cline-yes">50x</span>
295
+ <span class="cline-any cline-yes">50x</span>
296
+ <span class="cline-any cline-yes">50x</span>
297
+ <span class="cline-any cline-yes">50x</span>
252
298
  <span class="cline-any cline-yes">1x</span>
253
299
  <span class="cline-any cline-yes">1x</span>
254
300
  <span class="cline-any cline-yes">1x</span>
@@ -275,58 +321,106 @@
275
321
  <span class="cline-any cline-yes">1x</span>
276
322
  <span class="cline-any cline-yes">1x</span>
277
323
  <span class="cline-any cline-yes">1x</span>
278
- <span class="cline-any cline-yes">36x</span>
279
- <span class="cline-any cline-yes">36x</span>
280
- <span class="cline-any cline-yes">36x</span>
281
- <span class="cline-any cline-yes">36x</span>
282
- <span class="cline-any cline-yes">36x</span>
283
- <span class="cline-any cline-yes">36x</span>
284
- <span class="cline-any cline-yes">36x</span>
285
- <span class="cline-any cline-yes">36x</span>
286
- <span class="cline-any cline-yes">36x</span>
287
- <span class="cline-any cline-yes">36x</span>
288
- <span class="cline-any cline-yes">36x</span>
289
- <span class="cline-any cline-yes">36x</span>
290
- <span class="cline-any cline-yes">36x</span>
291
- <span class="cline-any cline-yes">36x</span>
292
- <span class="cline-any cline-yes">36x</span>
293
- <span class="cline-any cline-yes">36x</span>
294
- <span class="cline-any cline-yes">36x</span>
295
- <span class="cline-any cline-yes">36x</span>
296
- <span class="cline-any cline-yes">36x</span>
297
- <span class="cline-any cline-yes">36x</span>
298
- <span class="cline-any cline-yes">36x</span>
299
- <span class="cline-any cline-yes">36x</span>
300
- <span class="cline-any cline-yes">116x</span>
301
- <span class="cline-any cline-yes">116x</span>
302
- <span class="cline-any cline-yes">88x</span>
303
- <span class="cline-any cline-yes">88x</span>
304
- <span class="cline-any cline-yes">88x</span>
305
- <span class="cline-any cline-yes">88x</span>
306
- <span class="cline-any cline-yes">88x</span>
307
- <span class="cline-any cline-yes">116x</span>
324
+ <span class="cline-any cline-yes">44x</span>
325
+ <span class="cline-any cline-yes">44x</span>
326
+ <span class="cline-any cline-yes">44x</span>
327
+ <span class="cline-any cline-yes">44x</span>
328
+ <span class="cline-any cline-yes">44x</span>
329
+ <span class="cline-any cline-yes">44x</span>
330
+ <span class="cline-any cline-yes">44x</span>
331
+ <span class="cline-any cline-yes">44x</span>
332
+ <span class="cline-any cline-yes">44x</span>
333
+ <span class="cline-any cline-yes">44x</span>
334
+ <span class="cline-any cline-yes">44x</span>
335
+ <span class="cline-any cline-yes">44x</span>
336
+ <span class="cline-any cline-yes">44x</span>
337
+ <span class="cline-any cline-yes">44x</span>
338
+ <span class="cline-any cline-yes">44x</span>
339
+ <span class="cline-any cline-yes">44x</span>
340
+ <span class="cline-any cline-yes">44x</span>
341
+ <span class="cline-any cline-yes">44x</span>
342
+ <span class="cline-any cline-yes">44x</span>
343
+ <span class="cline-any cline-yes">44x</span>
344
+ <span class="cline-any cline-yes">44x</span>
345
+ <span class="cline-any cline-yes">44x</span>
346
+ <span class="cline-any cline-yes">44x</span>
347
+ <span class="cline-any cline-yes">44x</span>
348
+ <span class="cline-any cline-yes">44x</span>
349
+ <span class="cline-any cline-yes">133x</span>
350
+ <span class="cline-any cline-yes">133x</span>
351
+ <span class="cline-any cline-yes">105x</span>
352
+ <span class="cline-any cline-yes">105x</span>
353
+ <span class="cline-any cline-yes">105x</span>
354
+ <span class="cline-any cline-yes">105x</span>
355
+ <span class="cline-any cline-yes">105x</span>
356
+ <span class="cline-any cline-yes">133x</span>
308
357
  <span class="cline-any cline-yes">13x</span>
309
358
  <span class="cline-any cline-yes">13x</span>
310
359
  <span class="cline-any cline-yes">13x</span>
311
360
  <span class="cline-any cline-yes">13x</span>
361
+ <span class="cline-any cline-yes">92x</span>
362
+ <span class="cline-any cline-yes">92x</span>
363
+ <span class="cline-any cline-yes">92x</span>
364
+ <span class="cline-any cline-yes">92x</span>
365
+ <span class="cline-any cline-yes">133x</span>
312
366
  <span class="cline-any cline-yes">75x</span>
313
367
  <span class="cline-any cline-yes">75x</span>
314
368
  <span class="cline-any cline-yes">75x</span>
315
369
  <span class="cline-any cline-yes">75x</span>
316
- <span class="cline-any cline-yes">116x</span>
317
- <span class="cline-any cline-yes">58x</span>
318
- <span class="cline-any cline-yes">58x</span>
370
+ <span class="cline-any cline-yes">18x</span>
371
+ <span class="cline-any cline-yes">18x</span>
372
+ <span class="cline-any cline-yes">5x</span>
373
+ <span class="cline-any cline-yes">5x</span>
374
+ <span class="cline-any cline-yes">5x</span>
375
+ <span class="cline-any cline-yes">5x</span>
376
+ <span class="cline-any cline-yes">5x</span>
377
+ <span class="cline-any cline-yes">5x</span>
378
+ <span class="cline-any cline-yes">18x</span>
379
+ <span class="cline-any cline-yes">13x</span>
380
+ <span class="cline-any cline-yes">13x</span>
381
+ <span class="cline-any cline-yes">13x</span>
382
+ <span class="cline-any cline-yes">13x</span>
383
+ <span class="cline-any cline-yes">13x</span>
384
+ <span class="cline-any cline-yes">18x</span>
319
385
  <span class="cline-any cline-yes">75x</span>
320
- <span class="cline-any cline-yes">116x</span>
321
- <span class="cline-any cline-yes">3x</span>
322
- <span class="cline-any cline-yes">3x</span>
323
- <span class="cline-any cline-yes">116x</span>
324
- <span class="cline-any cline-yes">36x</span>
325
- <span class="cline-any cline-yes">36x</span>
326
- <span class="cline-any cline-yes">36x</span>
386
+ <span class="cline-any cline-yes">92x</span>
387
+ <span class="cline-any cline-yes">133x</span>
388
+ <span class="cline-any cline-yes">34x</span>
389
+ <span class="cline-any cline-yes">34x</span>
390
+ <span class="cline-any cline-yes">133x</span>
391
+ <span class="cline-any cline-yes">44x</span>
392
+ <span class="cline-any cline-yes">44x</span>
393
+ <span class="cline-any cline-yes">44x</span>
394
+ <span class="cline-any cline-yes">1x</span>
395
+ <span class="cline-any cline-yes">1x</span>
396
+ <span class="cline-any cline-yes">1x</span>
397
+ <span class="cline-any cline-yes">1x</span>
398
+ <span class="cline-any cline-yes">1x</span>
399
+ <span class="cline-any cline-yes">1x</span>
400
+ <span class="cline-any cline-yes">1x</span>
401
+ <span class="cline-any cline-yes">1x</span>
327
402
  <span class="cline-any cline-yes">1x</span>
328
403
  <span class="cline-any cline-yes">1x</span>
329
404
  <span class="cline-any cline-yes">1x</span>
405
+ <span class="cline-any cline-yes">5x</span>
406
+ <span class="cline-any cline-yes">5x</span>
407
+ <span class="cline-any cline-yes">5x</span>
408
+ <span class="cline-any cline-yes">5x</span>
409
+ <span class="cline-any cline-yes">5x</span>
410
+ <span class="cline-any cline-yes">5x</span>
411
+ <span class="cline-any cline-yes">5x</span>
412
+ <span class="cline-any cline-yes">5x</span>
413
+ <span class="cline-any cline-yes">5x</span>
414
+ <span class="cline-any cline-yes">5x</span>
415
+ <span class="cline-any cline-yes">9x</span>
416
+ <span class="cline-any cline-yes">9x</span>
417
+ <span class="cline-any cline-yes">9x</span>
418
+ <span class="cline-any cline-yes">9x</span>
419
+ <span class="cline-any cline-yes">9x</span>
420
+ <span class="cline-any cline-yes">9x</span>
421
+ <span class="cline-any cline-yes">9x</span>
422
+ <span class="cline-any cline-yes">2x</span>
423
+ <span class="cline-any cline-yes">2x</span>
330
424
  <span class="cline-any cline-yes">1x</span>
331
425
  <span class="cline-any cline-yes">1x</span>
332
426
  <span class="cline-any cline-yes">1x</span>
@@ -335,23 +429,21 @@
335
429
  <span class="cline-any cline-yes">1x</span>
336
430
  <span class="cline-any cline-yes">1x</span>
337
431
  <span class="cline-any cline-yes">1x</span>
338
- <span class="cline-any cline-yes">4x</span>
339
- <span class="cline-any cline-yes">4x</span>
340
- <span class="cline-any cline-yes">4x</span>
341
- <span class="cline-any cline-yes">4x</span>
342
- <span class="cline-any cline-yes">4x</span>
343
- <span class="cline-any cline-yes">4x</span>
344
- <span class="cline-any cline-yes">4x</span>
345
- <span class="cline-any cline-yes">7x</span>
346
- <span class="cline-any cline-yes">7x</span>
347
- <span class="cline-any cline-yes">7x</span>
348
- <span class="cline-any cline-yes">7x</span>
349
- <span class="cline-any cline-yes">4x</span>
350
- <span class="cline-any cline-yes">4x</span>
351
- <span class="cline-any cline-yes">4x</span>
352
- <span class="cline-any cline-yes">4x</span>
353
- <span class="cline-any cline-yes">4x</span>
354
- <span class="cline-any cline-yes">4x</span>
432
+ <span class="cline-any cline-yes">1x</span>
433
+ <span class="cline-any cline-yes">1x</span>
434
+ <span class="cline-any cline-yes">1x</span>
435
+ <span class="cline-any cline-yes">1x</span>
436
+ <span class="cline-any cline-yes">1x</span>
437
+ <span class="cline-any cline-yes">1x</span>
438
+ <span class="cline-any cline-yes">2x</span>
439
+ <span class="cline-any cline-yes">9x</span>
440
+ <span class="cline-any cline-yes">9x</span>
441
+ <span class="cline-any cline-yes">5x</span>
442
+ <span class="cline-any cline-yes">5x</span>
443
+ <span class="cline-any cline-yes">5x</span>
444
+ <span class="cline-any cline-yes">5x</span>
445
+ <span class="cline-any cline-yes">5x</span>
446
+ <span class="cline-any cline-yes">5x</span>
355
447
  <span class="cline-any cline-yes">1x</span>
356
448
  <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import type { Task, ParsingContext, Warning } from '../types/index.js';
357
449
  import { parseTask } from '../parser/index.js';
@@ -428,6 +520,9 @@ export class MarkdownScanner {
428
520
  } {
429
521
  const tasks: Task[] = [];
430
522
  const warnings: Warning[] = [];
523
+ &nbsp;
524
+ // Track Todoist IDs to detect duplicates
525
+ const todoistIds = new Map&lt;string, { file: string; line: number }&gt;();
431
526
  &nbsp;
432
527
  // Initialize context from file path
433
528
  const context: ParsingContext = {};
@@ -460,6 +555,24 @@ export class MarkdownScanner {
460
555
  &nbsp;
461
556
  if (result.task) {
462
557
  tasks.push(result.task);
558
+ &nbsp;
559
+ // Check for duplicate Todoist IDs
560
+ if (result.task.todoistId) {
561
+ const existing = todoistIds.get(result.task.todoistId);
562
+ if (existing) {
563
+ warnings.push({
564
+ file: filePath,
565
+ line: lineNumber,
566
+ text: result.task.text,
567
+ reason: `Duplicate Todoist ID [todoist:${result.task.todoistId}]. Also found at ${existing.file}:${existing.line}.`,
568
+ });
569
+ } else {
570
+ todoistIds.set(result.task.todoistId, {
571
+ file: filePath,
572
+ line: lineNumber,
573
+ });
574
+ }
575
+ }
463
576
  }
464
577
  &nbsp;
465
578
  if (result.warnings.length &gt; 0) {
@@ -485,11 +598,36 @@ export class MarkdownScanner {
485
598
  } {
486
599
  const allTasks: Task[] = [];
487
600
  const allWarnings: Warning[] = [];
601
+ &nbsp;
602
+ // Track Todoist IDs across all files
603
+ const todoistIds = new Map&lt;string, { file: string; line: number }&gt;();
488
604
  &nbsp;
489
605
  for (const file of files) {
490
606
  const result = this.scanFile(file.path, file.content);
491
607
  allTasks.push(...result.tasks);
492
608
  allWarnings.push(...result.warnings);
609
+ &nbsp;
610
+ // Check for duplicate Todoist IDs across files
611
+ for (const task of result.tasks) {
612
+ if (task.todoistId) {
613
+ const existing = todoistIds.get(task.todoistId);
614
+ if (existing &amp;&amp; existing.file !== task.file) {
615
+ // Only add warning if duplicate is in a different file
616
+ // (same-file duplicates are already caught by scanFile)
617
+ allWarnings.push({
618
+ file: task.file,
619
+ line: task.line,
620
+ text: task.text,
621
+ reason: `Duplicate Todoist ID [todoist:${task.todoistId}] across files. Also found at ${existing.file}:${existing.line}.`,
622
+ });
623
+ } else if (!existing) {
624
+ todoistIds.set(task.todoistId, {
625
+ file: task.file,
626
+ line: task.line,
627
+ });
628
+ }
629
+ }
630
+ }
493
631
  }
494
632
  &nbsp;
495
633
  return {
@@ -505,7 +643,7 @@ export class MarkdownScanner {
505
643
  <div class='footer quiet pad2 space-top1 center small'>
506
644
  Code coverage generated by
507
645
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
508
- at 2026-01-22T01:16:22.209Z
646
+ at 2026-01-26T03:50:53.066Z
509
647
  </div>
510
648
  <script src="../../prettify.js"></script>
511
649
  <script>
@@ -101,7 +101,7 @@
101
101
  <div class='footer quiet pad2 space-top1 center small'>
102
102
  Code coverage generated by
103
103
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
104
- at 2026-01-22T01:16:22.209Z
104
+ at 2026-01-26T03:50:53.066Z
105
105
  </div>
106
106
  <script src="../../prettify.js"></script>
107
107
  <script>
@@ -721,7 +721,7 @@ export function reverse(comparator: TaskComparator): TaskComparator {
721
721
  <div class='footer quiet pad2 space-top1 center small'>
722
722
  Code coverage generated by
723
723
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
724
- at 2026-01-22T01:16:22.209Z
724
+ at 2026-01-26T03:50:53.066Z
725
725
  </div>
726
726
  <script src="../../prettify.js"></script>
727
727
  <script>
@@ -223,19 +223,19 @@
223
223
  <span class="cline-any cline-yes">1x</span>
224
224
  <span class="cline-any cline-yes">1x</span>
225
225
  <span class="cline-any cline-yes">1x</span>
226
- <span class="cline-any cline-yes">80x</span>
227
- <span class="cline-any cline-yes">80x</span>
228
- <span class="cline-any cline-yes">80x</span>
229
- <span class="cline-any cline-yes">80x</span>
230
- <span class="cline-any cline-yes">80x</span>
226
+ <span class="cline-any cline-yes">100x</span>
227
+ <span class="cline-any cline-yes">100x</span>
228
+ <span class="cline-any cline-yes">100x</span>
229
+ <span class="cline-any cline-yes">100x</span>
230
+ <span class="cline-any cline-yes">100x</span>
231
231
  <span class="cline-any cline-yes">31x</span>
232
232
  <span class="cline-any cline-yes">31x</span>
233
233
  <span class="cline-any cline-yes">31x</span>
234
- <span class="cline-any cline-yes">72x</span>
234
+ <span class="cline-any cline-yes">74x</span>
235
235
  <span class="cline-any cline-yes">8x</span>
236
236
  <span class="cline-any cline-yes">8x</span>
237
237
  <span class="cline-any cline-yes">8x</span>
238
- <span class="cline-any cline-yes">61x</span>
238
+ <span class="cline-any cline-yes">63x</span>
239
239
  <span class="cline-any cline-yes">5x</span>
240
240
  <span class="cline-any cline-yes">5x</span>
241
241
  <span class="cline-any cline-yes">5x</span>
@@ -295,23 +295,23 @@
295
295
  <span class="cline-any cline-yes">1x</span>
296
296
  <span class="cline-any cline-yes">1x</span>
297
297
  <span class="cline-any cline-yes">1x</span>
298
- <span class="cline-any cline-yes">130x</span>
299
- <span class="cline-any cline-yes">130x</span>
300
- <span class="cline-any cline-yes">130x</span>
298
+ <span class="cline-any cline-yes">147x</span>
299
+ <span class="cline-any cline-yes">147x</span>
300
+ <span class="cline-any cline-yes">147x</span>
301
301
  <span class="cline-any cline-yes">17x</span>
302
302
  <span class="cline-any cline-yes">17x</span>
303
303
  <span class="cline-any cline-yes">17x</span>
304
- <span class="cline-any cline-yes">113x</span>
305
- <span class="cline-any cline-yes">113x</span>
306
- <span class="cline-any cline-yes">113x</span>
307
304
  <span class="cline-any cline-yes">130x</span>
305
+ <span class="cline-any cline-yes">130x</span>
306
+ <span class="cline-any cline-yes">130x</span>
307
+ <span class="cline-any cline-yes">147x</span>
308
308
  <span class="cline-any cline-yes">5x</span>
309
309
  <span class="cline-any cline-yes">5x</span>
310
310
  <span class="cline-any cline-yes">5x</span>
311
- <span class="cline-any cline-yes">108x</span>
312
- <span class="cline-any cline-yes">108x</span>
313
- <span class="cline-any cline-yes">108x</span>
314
- <span class="cline-any cline-yes">130x</span>
311
+ <span class="cline-any cline-yes">125x</span>
312
+ <span class="cline-any cline-yes">125x</span>
313
+ <span class="cline-any cline-yes">125x</span>
314
+ <span class="cline-any cline-yes">147x</span>
315
315
  <span class="cline-any cline-yes">30x</span>
316
316
  <span class="cline-any cline-yes">30x</span>
317
317
  <span class="cline-any cline-yes">30x</span>
@@ -336,9 +336,9 @@
336
336
  <span class="cline-any cline-yes">30x</span>
337
337
  <span class="cline-any cline-yes">30x</span>
338
338
  <span class="cline-any cline-yes">30x</span>
339
- <span class="cline-any cline-yes">78x</span>
340
- <span class="cline-any cline-yes">78x</span>
341
- <span class="cline-any cline-yes">78x</span>
339
+ <span class="cline-any cline-yes">95x</span>
340
+ <span class="cline-any cline-yes">95x</span>
341
+ <span class="cline-any cline-yes">95x</span>
342
342
  <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import {
343
343
  parse,
344
344
  isValid,
@@ -484,7 +484,7 @@ export function extractDateFromHeading(line: string): Date | null {
484
484
  <div class='footer quiet pad2 space-top1 center small'>
485
485
  Code coverage generated by
486
486
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
487
- at 2026-01-22T01:16:22.209Z
487
+ at 2026-01-26T03:50:53.066Z
488
488
  </div>
489
489
  <script src="../../prettify.js"></script>
490
490
  <script>
@@ -112,13 +112,13 @@
112
112
  <span class="cline-any cline-yes">1x</span>
113
113
  <span class="cline-any cline-yes">1x</span>
114
114
  <span class="cline-any cline-yes">1x</span>
115
- <span class="cline-any cline-yes">225x</span>
116
- <span class="cline-any cline-yes">225x</span>
117
- <span class="cline-any cline-yes">225x</span>
118
- <span class="cline-any cline-yes">225x</span>
119
- <span class="cline-any cline-yes">225x</span>
120
- <span class="cline-any cline-yes">225x</span>
121
- <span class="cline-any cline-yes">225x</span>
115
+ <span class="cline-any cline-yes">248x</span>
116
+ <span class="cline-any cline-yes">248x</span>
117
+ <span class="cline-any cline-yes">248x</span>
118
+ <span class="cline-any cline-yes">248x</span>
119
+ <span class="cline-any cline-yes">248x</span>
120
+ <span class="cline-any cline-yes">248x</span>
121
+ <span class="cline-any cline-yes">248x</span>
122
122
  <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import { createHash } from 'crypto';
123
123
  &nbsp;
124
124
  /**
@@ -154,7 +154,7 @@ export function generateTaskId(
154
154
  <div class='footer quiet pad2 space-top1 center small'>
155
155
  Code coverage generated by
156
156
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
157
- at 2026-01-22T01:16:22.209Z
157
+ at 2026-01-26T03:50:53.066Z
158
158
  </div>
159
159
  <script src="../../prettify.js"></script>
160
160
  <script>
@@ -116,7 +116,7 @@
116
116
  <div class='footer quiet pad2 space-top1 center small'>
117
117
  Code coverage generated by
118
118
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
119
- at 2026-01-22T01:16:22.209Z
119
+ at 2026-01-26T03:50:53.066Z
120
120
  </div>
121
121
  <script src="../../prettify.js"></script>
122
122
  <script>
@@ -101,7 +101,7 @@
101
101
  <div class='footer quiet pad2 space-top1 center small'>
102
102
  Code coverage generated by
103
103
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
104
- at 2026-01-22T01:16:22.209Z
104
+ at 2026-01-26T03:50:53.066Z
105
105
  </div>
106
106
  <script src="../../prettify.js"></script>
107
107
  <script>
@@ -1078,7 +1078,7 @@ export async function addTask(
1078
1078
  <div class='footer quiet pad2 space-top1 center small'>
1079
1079
  Code coverage generated by
1080
1080
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1081
- at 2026-01-22T01:16:22.209Z
1081
+ at 2026-01-26T03:50:53.066Z
1082
1082
  </div>
1083
1083
  <script src="../../prettify.js"></script>
1084
1084
  <script>