-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
122 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import {type Note} from '../../../functions/src/presentation'; | ||
import {importNotes, exportNotes} from './parse-notes'; | ||
|
||
let expectedNotes: Note[]; | ||
let expectedMarkdown: string; | ||
|
||
beforeEach(() => { | ||
expectedNotes = [ | ||
{pageIndices: [0], markdown: 'abc'}, | ||
{pageIndices: [1], markdown: ''}, | ||
{ | ||
pageIndices: [2, 3], | ||
markdown: 'def', | ||
}, | ||
]; | ||
|
||
expectedMarkdown = `<!-- +0+1 --> | ||
abc | ||
<!-- +2+2 --> | ||
def | ||
`; | ||
}); | ||
|
||
describe('note', () => { | ||
it('exports notes', async () => { | ||
const input = expectedNotes; | ||
|
||
const output = exportNotes(input); | ||
|
||
expect(output).toEqual(expectedMarkdown); | ||
}); | ||
|
||
it('imports notes', async () => { | ||
const input = expectedMarkdown; | ||
|
||
const output = importNotes(input); | ||
|
||
expect(output).toEqual(expectedNotes); | ||
}); | ||
|
||
it('imports what was exported', () => { | ||
expect(importNotes(exportNotes(expectedNotes))).toEqual(expectedNotes); | ||
}); | ||
|
||
it('exports what was imported', () => { | ||
expect(exportNotes(importNotes(expectedMarkdown))).toEqual( | ||
expectedMarkdown, | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,86 @@ | ||
export default function parseNotes(markdown: string) { | ||
const noteSections = markdown.split(/\n*(<!-- \+\d+(?:\.\.\+\d+)? -->)\n+/); | ||
const slideNotes = new Map<number, string>(); | ||
let lastSlideIndex = -1; | ||
import {type Note} from '../../../functions/src/presentation'; | ||
|
||
export function importNotes(markdown: string): Note[] { | ||
// We ensure a capture group around the entire expression so that it is still included in the String.split results | ||
const noteSections = markdown.split(/\n*(<!-- \+\d+(?:\+\d+)? -->)\n+/); | ||
const notes: Note[] = []; | ||
let currentPageIndex = 0; | ||
|
||
for ( | ||
let sectionIndex = 0; | ||
sectionIndex < noteSections.length; | ||
sectionIndex++ | ||
) { | ||
const magicCommentRegEx = | ||
/<!-- \+(?<offset>\d+)(?:\+(?<rangeOffset>\d+))? -->/; | ||
const noteSection = noteSections[sectionIndex]; | ||
const match = | ||
/<!-- \+(?<offset>\d+)(?:\.\.\+(?<rangeOffset>\d+))? -->/.exec( | ||
noteSection, | ||
); | ||
const match = magicCommentRegEx.exec(noteSection); | ||
|
||
if (match === null) { | ||
slideNotes.set(lastSlideIndex + 1, noteSection); | ||
lastSlideIndex++; | ||
// Not matching at the start is the result of using String.split() | ||
// This indicates there was white space before the first magic comment in the markdown | ||
if (sectionIndex !== 0) { | ||
notes.push({pageIndices: [currentPageIndex], markdown: noteSection}); | ||
currentPageIndex++; | ||
} | ||
|
||
continue; | ||
} | ||
|
||
const firstIndex = | ||
lastSlideIndex + Number.parseInt(match.groups!.offset, 10); | ||
const range = match.groups?.rangeOffset | ||
? Number.parseInt(match.groups.rangeOffset, 10) | ||
: 1; | ||
const slideNote = noteSections[sectionIndex + 1]; | ||
// Keep the index sync'ed since we are reading ahead | ||
sectionIndex++; | ||
currentPageIndex + Number.parseInt(match.groups!.offset, 10); | ||
|
||
// Backfill any missing notes with empty notes, 1 note per index | ||
for ( | ||
let slideIndex = firstIndex; | ||
slideIndex < firstIndex + range; | ||
slideIndex++ | ||
let emptyIndex = currentPageIndex + 1; | ||
emptyIndex < firstIndex; | ||
emptyIndex++ | ||
) { | ||
slideNotes.set(slideIndex, slideNote); | ||
notes.push({pageIndices: [emptyIndex], markdown: ''}); | ||
currentPageIndex++; | ||
} | ||
|
||
lastSlideIndex = firstIndex + range - 1; | ||
const pageLength = match.groups?.rangeOffset | ||
? Number.parseInt(match.groups.rangeOffset, 10) | ||
: 1; | ||
|
||
// Generate the sequential indices between the firstIndex and the pageLength | ||
const pageIndices = Array.from({length: pageLength}).map( | ||
(_, index) => firstIndex + index, | ||
) as [number, ...number[]]; | ||
|
||
let markdown = ''; | ||
// Grab the next section, but make sure it isn't a magic comment | ||
if (!magicCommentRegEx.test(noteSections[sectionIndex + 1])) { | ||
markdown = noteSections[sectionIndex + 1]; | ||
// Skip the next section | ||
sectionIndex++; | ||
} | ||
|
||
notes.push({pageIndices, markdown: markdown.trim()}); | ||
|
||
// Update the pageIndices index for the next note | ||
currentPageIndex += pageLength - 1; | ||
} | ||
|
||
return slideNotes; | ||
return notes; | ||
} | ||
|
||
export function exportNotes(notes: Note[]): string { | ||
let currentOffset = 0; | ||
return notes | ||
.map((note) => { | ||
// Remove empty notes | ||
if (note.markdown.trim().length === 0) { | ||
return undefined; | ||
} | ||
|
||
const startIndex = currentOffset + note.pageIndices[0]; | ||
const noteLength = note.pageIndices.length; | ||
currentOffset += noteLength - 1; | ||
|
||
return `<!-- +${startIndex}+${noteLength} -->\n${note.markdown}\n`; | ||
}) | ||
.filter((note) => note !== undefined) | ||
.join('\n'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters