Skip to content

Commit

Permalink
Creates separate files for duplicate headings #84
Browse files Browse the repository at this point in the history
  • Loading branch information
lynchjames committed Sep 18, 2023
1 parent 9f8661d commit 7505c0a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 13 deletions.
12 changes: 12 additions & 0 deletions src/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { NoteRefactorSettings } from './settings';
import MomentDateRegex from './moment-date-regex'

export default class NRFile {

private settings: NoteRefactorSettings;
private momentDateRegex: MomentDateRegex;

Expand All @@ -21,4 +22,15 @@ export default class NRFile {
fileNamePrefix(): string {
return this.settings.fileNamePrefix ? this.momentDateRegex.replace(this.settings.fileNamePrefix) : '';
}

ensureUniqueFileNames(headingNotes: string[][]): string[] {
const fileNames:string[] = [];
const deduped = headingNotes.map((hn) => {
const fileName = this.sanitisedFileName(hn[0]);
const duplicates = fileNames.filter(fn => fn == fileName);
fileNames.push(fileName);
return duplicates.length >= 1 ? `${fileName}${duplicates.length + 1}` : fileName;
});
return deduped;
}
}
13 changes: 7 additions & 6 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ export default class NoteRefactor extends Plugin {
const mdView = this.app.workspace.activeLeaf.view as MarkdownView;
const doc = mdView.editor;
const headingNotes = this.NRDoc.contentSplitByHeading(doc, headingLevel);
headingNotes.forEach(hn => this.createNoteWithFirstLineAsFileName(hn, mdView, doc, 'replace-headings', true));
const dedupedFileNames = this.file.ensureUniqueFileNames(headingNotes);
headingNotes.forEach((hn, i) => this.createNoteWithFirstLineAsFileName(dedupedFileNames[i], hn, mdView, doc, 'replace-headings', true));
}

async extractSelectionFirstLine(mode: ReplaceMode): Promise<void> {
Expand All @@ -127,7 +128,7 @@ export default class NoteRefactor extends Plugin {
const selectedContent = mode === 'split' ? this.NRDoc.noteRemainder(doc) : this.NRDoc.selectedContent(doc);
if(selectedContent.length <= 0) { return }

await this.createNoteWithFirstLineAsFileName(selectedContent, mdView, doc, mode, false);
await this.createNoteWithFirstLineAsFileName(selectedContent[0], selectedContent, mdView, doc, mode, false);
}

async extractSelectionAutogenerate(mode: ReplaceMode): Promise<void> {
Expand Down Expand Up @@ -162,11 +163,11 @@ export default class NoteRefactor extends Plugin {
}
}

private async createNoteWithFirstLineAsFileName(selectedContent: string[], mdView: MarkdownView, doc: Editor, mode: ReplaceMode, isMultiple: boolean) {
const [header, ...contentArr] = selectedContent;
private async createNoteWithFirstLineAsFileName(dedupedHeader: string, selectedContent: string[], mdView: MarkdownView, doc: Editor, mode: ReplaceMode, isMultiple: boolean) {
const [originalHeader, ...contentArr] = selectedContent;

const fileName = this.file.sanitisedFileName(header);
const originalNote = this.NRDoc.noteContent(header, contentArr);
const fileName = this.file.sanitisedFileName(dedupedHeader);
const originalNote = this.NRDoc.noteContent(originalHeader, contentArr);
let note = originalNote;
const filePath = await this.obsFile.createOrAppendFile(fileName, '');

Expand Down
59 changes: 52 additions & 7 deletions tests/file.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {describe, expect, beforeAll, afterAll} from '@jest/globals';
import { mockDate} from './mocks/date';
import { describe, expect, beforeAll, afterAll } from '@jest/globals';
import { mockDate } from './mocks/date';
import NRFile from '../src/file';
import { NoteRefactorSettings } from '../src/settings';

Expand All @@ -8,9 +8,9 @@ const date = new Date(2020, 11, 25, 11, 17, 52);


describe("File Name Prefix", () => {
let resetDateMock:() => void;
let resetDateMock: () => void;
let settings = new NoteRefactorSettings();

beforeAll(async () => {
file = new NRFile(settings);
resetDateMock = mockDate(date);
Expand All @@ -21,7 +21,7 @@ describe("File Name Prefix", () => {
const prefix = file.fileNamePrefix();
expect(prefix).toBe('202012251117-');
});

it("Correct prefix for YYYYMMDDHHmmss", () => {
settings.fileNamePrefix = '{{date:YYYYMMDDHHmmss}}-';
const prefix = file.fileNamePrefix();
Expand Down Expand Up @@ -59,7 +59,7 @@ describe("File Name Prefix", () => {

describe("File Name Sanitisation", () => {
let fileName = '';
let resetDateMock:() => void;
let resetDateMock: () => void;
let settings = new NoteRefactorSettings();

beforeAll(async () => {
Expand Down Expand Up @@ -92,7 +92,7 @@ describe("File Name Sanitisation", () => {
});

it("Illegal file path character sanitisation (*\"\/<>:|?", () => {
fileName = '**This has**\\/ "a lot" of <illegal>: |characters??|' ;
fileName = '**This has**\\/ "a lot" of <illegal>: |characters??|';
const sanitised = file.sanitisedFileName(fileName);
expect(sanitised).toBe('This has a lot of illegal characters');
});
Expand All @@ -117,4 +117,49 @@ describe("File Name Sanitisation", () => {
afterAll(() => {
resetDateMock();
});
});

describe("Regression - Issue #84 - File Name Duplication Protection", () => {
let fileNames = [
["## Duplicate Heading", "Some text"],
["#### Some other heading", "Paragraph text", "", "Another paragraph"],
["### Test", "", "Sentence 7"],
["### Another test", "", "Sentence text"],
["## Duplicate Heading", "", "More text under heading"],
["# Test", "", "Testing"],
];
let resetDateMock: () => void;
let settings = new NoteRefactorSettings();

beforeAll(async () => {
file = new NRFile(settings);
resetDateMock = mockDate(date);
});

it("Should return expected count", () => {
const deduped = file.ensureUniqueFileNames(fileNames);
expect(deduped.length).toBe(6);
});

it("Should sanitised filenames", () => {
const deduped = file.ensureUniqueFileNames(fileNames);
const includingHash = deduped.filter(d => d[0].includes("#"));
expect(includingHash.length).toBe(0);
});

it("First duplicate should have unchanged filename", () => {
const deduped = file.ensureUniqueFileNames(fileNames);
expect(deduped[0]).toBe("Duplicate Heading");
});

it("Second duplicate should have filename with incremented number", () => {
const deduped = file.ensureUniqueFileNames(fileNames);
expect(deduped[4]).toBe("Duplicate Heading2");
});

it("Duplicate should have filename with incremented number regardless of heading level", () => {
const deduped = file.ensureUniqueFileNames(fileNames);
expect(deduped[5]).toBe("Test2");
});

});

0 comments on commit 7505c0a

Please sign in to comment.