Skip to content

Commit

Permalink
add note import export logic
Browse files Browse the repository at this point in the history
  • Loading branch information
codyzu committed Jul 12, 2023
1 parent 4c5bb85 commit 823d243
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 29 deletions.
10 changes: 5 additions & 5 deletions functions/src/presentation.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ export type Doc = {
id: string;
};

export type Note = {
pageIndices: [number, ...number[]];
markdown: string;
};

// TODO: use this when uploading
export type PresentationData = {
title: string;
Expand All @@ -15,8 +20,3 @@ export type PresentationData = {
thumbIndex?: number;
};
export type PresentationDoc = Doc & PresentationData;

export type Note = {
pageIndices: number[];
markdown: string;
};
51 changes: 51 additions & 0 deletions src/components/slides/notes.test.ts
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,
);
});
});
88 changes: 65 additions & 23 deletions src/components/slides/parse-notes.ts
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');
}
2 changes: 1 addition & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export default defineConfig(({command, mode}) => {
globals: true,
environment: 'jsdom',
setupFiles: './src/test/setup.ts',
include: ['src/**/*.Test.tsx'],
include: ['src/**/*.[Tt]est.ts?(x)'],
coverage: {
// Src: [`${process.cwd()}/src`],
all: true,
Expand Down

0 comments on commit 823d243

Please sign in to comment.