Repository: platers/obsidian-linter (ts)

Issue:
Bug: re-index-footnotes & move-footnotes-to-the-bottom can cause Obsidian freeze with footnote wrapping
- [x] I have verified that I am on the latest version of the Linter 

## Describe the Bug

Linting a file with re-index-footnotes or move-footnotes-to-the-bottom will cause Obsidian to freeze, I think indefinitely, if a reference is wrapped in two of its footnotes -- at least that's as far as I've been able to zoom into the cause. It didn't spit out any logs when it happened.

## How to Reproduce

Steps to reproduce the behavior:

1. Create a new file in a vault with contents:

```markdown
[^2]: a

a[^2]

[^2]: b
```

2. On macOS (I haven't tested elsewhere), open the file in the Obsidian app
3. Lint the file with re-index-footnotes or move-footnotes-to-the-bottom enabled  
4. Notice that Obsidian freezes

## Expected Behavior

If re-index-footnotes is enabled: user notification that re-index-footnotes doesn't work if there is more than one footnote for a key.

If move-footnotes-to-the-bottom is enabled: footnotes are moved to the bottom of the file as expected.

## Device

- [x] Desktop
- [ ] Mobile


Pull request:
Fix an Infinite Loop for `re-index-footnotes` and `move-footnote-to-the-bottom`
Fixes #784 

Changes Made:
- Accounted for starting a file with a footnote reference in the while loops which was caused by the condition being greater than -1 when it should be 0 since that is the lowest valid value that we should stop looking after we find
- Added a test to `move-footnote-to-the-bottom` to make sure the issue does not get reintroduced

Patch:
diff --git a/src/utils/mdast.ts b/src/utils/mdast.ts
index 283e090..cc6ae9f 100644
--- a/src/utils/mdast.ts
+++ b/src/utils/mdast.ts
@@ -161,7 +161,7 @@ export function moveFootnotesToEnd(text: string): string {
       footnoteReferenceLocations.push(footnoteReferenceLocation);
 
       startOfFootnoteReferenceSearch = footnoteReferenceLocation - 1;
-    } while (footnoteReferenceLocation > -1);
+    } while (footnoteReferenceLocation > 0);
 
     const keyInfo: footnoteKeyInfo = {
       key: footnoteReference,
@@ -243,7 +243,7 @@ export function reIndexFootnotes(text: string): string {
       footnoteReferenceLocationInfo.push({key: footnoteReference, position: footnoteReferenceLocation});
       firstFootnoteReferenceIndex = footnoteReferenceLocation;
       startOfFootnoteReferenceSearch = footnoteReferenceLocation - 1;
-    } while (footnoteReferenceLocation > -1);
+    } while (footnoteReferenceLocation > 0);
 
     footnoteKeys.add(footnoteReference);
 


Test patch:
diff --git a/__tests__/move-footnotes-to-the-bottom.test.ts b/__tests__/move-footnotes-to-the-bottom.test.ts
index 91780a3..79e5e99 100644
--- a/__tests__/move-footnotes-to-the-bottom.test.ts
+++ b/__tests__/move-footnotes-to-the-bottom.test.ts
@@ -188,5 +188,21 @@ ruleTest({
         [^2]: Second reference
       `,
     },
+    { // accounts for https://github.com/platers/obsidian-linter/issues/784
+      testName: 'A footnote reference wrapped by 2 references with one at the start of a file should not cause an infinite loop and should move each reference to the end of the file',
+      before: dedent`
+        [^2]: a
+        ${''}
+        a[^2]
+        ${''}
+        [^2]: b
+      `,
+      after: dedent`
+        a[^2]
+        ${''}
+        [^2]: a
+        [^2]: b
+      `,
+    },
   ],
 });