diff --git a/CHANGELOG.md b/CHANGELOG.md index 03c1bf5..777fa0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ### Version 5.3.0 (Unreleased) -- Fixed text-only Todo parsing so item ranges no longer access unavailable VS Code document APIs. +- Fixed embedded todo scanning and external-search result parsing for files and tool output that use classic Mac carriage-return line endings. - Fixed dependency indexing so one unreadable or removed Todo file no longer hides dependencies from other workspace files. - Fixed embedded todo parsing for file paths that start with a number. - Fixed date-sorted archiving so consecutive finished todos are ordered by their own completion dates. diff --git a/src/utils/ackmate.ts b/src/utils/ackmate.ts index e0a7186..fba5665 100644 --- a/src/utils/ackmate.ts +++ b/src/utils/ackmate.ts @@ -1,7 +1,8 @@ +import { splitLines } from './line-splitting'; + /* ACKMATE */ const Ackmate = { - newLineRe: /\r?\n/g, filePathRe: /^:?([^]+)$/, matchLineRe: /^(\d+)(?:;\d+ \d+)?:([^]*)$/, @@ -10,7 +11,7 @@ const Ackmate = { }, parse(str) { - const lines = str.split(Ackmate.newLineRe); + const lines = splitLines(str); let filePath, match; diff --git a/src/utils/embedded/providers/abstract.ts b/src/utils/embedded/providers/abstract.ts index 24dc0b0..fdc4db0 100644 --- a/src/utils/embedded/providers/abstract.ts +++ b/src/utils/embedded/providers/abstract.ts @@ -12,6 +12,7 @@ import Consts from '../../../consts'; import { hasConditionalExcludeGlobs, isFileIncluded } from '../../file-globs'; import { getWorkspaceExcludeRules } from '../../workspace-excludes'; import { getFollowingContext } from '../context'; +import { splitLines } from '../../line-splitting'; import { parseEmbeddedMatches } from '../regex'; /* ABSTRACT */ @@ -200,7 +201,7 @@ class Abstract { parseContent(filePath: string, content: string) { const data = [], - lines = content.split(/\r?\n/); + lines = splitLines(content); if (!content) return data; diff --git a/src/utils/embedded/providers/ag.ts b/src/utils/embedded/providers/ag.ts index e043922..4777837 100644 --- a/src/utils/embedded/providers/ag.ts +++ b/src/utils/embedded/providers/ag.ts @@ -10,6 +10,7 @@ import File from '../../file'; import Folder from '../../folder'; import { flatMapFulfilled } from '../../promises'; import { getWorkspaceExcludeGlobs } from '../../workspace-excludes'; +import { splitLines } from '../../line-splitting'; import { parseEmbeddedMatches } from '../regex'; import Abstract from './abstract'; @@ -106,7 +107,7 @@ class AG extends Abstract { const content = await File.read(filePath); if (content !== undefined) { - contextLines[filePath] = content.split(/\r?\n/); + contextLines[filePath] = splitLines(content); } } ) diff --git a/src/utils/embedded/regex.ts b/src/utils/embedded/regex.ts index 422450a..3c1686c 100644 --- a/src/utils/embedded/regex.ts +++ b/src/utils/embedded/regex.ts @@ -1,5 +1,6 @@ import * as _ from 'lodash'; import stringMatches from 'string-matches'; +import { splitLines } from '../line-splitting'; export const parseEmbeddedMatches = (line: string, regex: RegExp) => stringMatches(line, regex).map((match) => ({ @@ -12,7 +13,7 @@ export const parseEmbeddedMatches = (line: string, regex: RegExp) => export const hasEmbeddedMatch = (content: string, regex: RegExp): boolean => { const matcher = new RegExp(regex.source, regex.flags); - return content.split(/\r?\n/).some((line) => { + return splitLines(content).some((line) => { matcher.lastIndex = 0; return matcher.test(_.trimStart(line)); diff --git a/src/utils/line-splitting.ts b/src/utils/line-splitting.ts new file mode 100644 index 0000000..7b701a4 --- /dev/null +++ b/src/utils/line-splitting.ts @@ -0,0 +1 @@ +export const splitLines = (text: string): string[] => text.split(/\r\n?|\n/); diff --git a/test/ackmate.spec.ts b/test/ackmate.spec.ts index fbb3b5a..9b2901f 100644 --- a/test/ackmate.spec.ts +++ b/test/ackmate.spec.ts @@ -29,4 +29,19 @@ describe('Ackmate parser', () => { }, ]); }); + + it('parses records separated by classic Mac line endings', () => { + expect(Ackmate.parse('TODO.md\r2:TODO first\r3:FIXME second')).to.deep.equal([ + { + filePath: 'TODO.md', + lineNr: 1, + line: 'TODO first', + }, + { + filePath: 'TODO.md', + lineNr: 2, + line: 'FIXME second', + }, + ]); + }); }); diff --git a/test/embedded-regex.spec.ts b/test/embedded-regex.spec.ts index 8fa69cb..357a998 100644 --- a/test/embedded-regex.spec.ts +++ b/test/embedded-regex.spec.ts @@ -74,6 +74,12 @@ describe('Embedded todo scan pre-check', () => { expect(hasEmbeddedMatch(content, regex)).to.equal(true); expect(hasEmbeddedMatch('// TODO ignored', regex)).to.equal(false); }); + + it('recognizes embedded todos in files with classic Mac line endings', () => { + const regex = /^\/\/\s*(TASK):?\s*(.*)$/gi; + + expect(hasEmbeddedMatch('const ready = true;\r // TASK ship it', regex)).to.equal(true); + }); }); describe('Embedded todo line parsing', () => {