Skip to content

Commit 19b38e5

Browse files
committed
fix: list spread across multiple slide steps were not properly parsed
1 parent 6868cbd commit 19b38e5

2 files changed

Lines changed: 66 additions & 1 deletion

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { Parser } from '../mdeck/parser.js';
3+
import { Slideshow } from '../mdeck/models/slideshow.js';
4+
import { convertMarkdown } from '../mdeck/converter.js';
5+
import type { Dom } from '../mdeck/dom.js';
6+
import EventEmitter from 'eventemitter3';
7+
8+
function makeDom(): Dom {
9+
return {
10+
getHTMLElement: () => document.documentElement,
11+
getBodyElement: () => document.body as HTMLBodyElement,
12+
getElementById: () => null,
13+
getLocationHash: () => '',
14+
setLocationHash: () => {},
15+
XMLHttpRequest: class {
16+
open() {}
17+
send() {}
18+
onload?: () => void;
19+
readyState = 0;
20+
status = 0;
21+
responseText = '';
22+
} as unknown as typeof XMLHttpRequest,
23+
} as unknown as Dom;
24+
}
25+
26+
describe('incremental list items', () => {
27+
const src = `# Agenda
28+
29+
- Testing Integrations
30+
--
31+
- OpenAPI
32+
--
33+
- Pact
34+
--
35+
- Conclusions
36+
--
37+
- Questions`;
38+
39+
it('parses into 5 slides', () => {
40+
const parser = new Parser();
41+
expect(parser.parse(src)).toHaveLength(5);
42+
});
43+
44+
it('renders each incremental slide with the correct number of list items', () => {
45+
const slideshow = new Slideshow(new EventEmitter(), makeDom(), {});
46+
slideshow.loadFromString(src);
47+
const slides = slideshow.getSlides();
48+
49+
slides.forEach((slide, i) => {
50+
const html = convertMarkdown(slide.content);
51+
const liCount = (html.match(/<li>/g) || []).length;
52+
expect(liCount).toBe(i + 1);
53+
});
54+
});
55+
});

src/mdeck/models/slide.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,17 @@ function inheritContent(slide: Slide, template: Slide) {
7878
deepCopyContent(slide, template.content);
7979
const expanded = slide.expandVariables(true);
8080
if (expanded.content === undefined) {
81-
slide.content = slide.content.concat(slide.properties.content as unknown as ContentItem[]);
81+
const slideContent = slide.properties.content as unknown as ContentItem[];
82+
// Ensure newline separator between inherited template content and new slide content,
83+
// otherwise markdown fragments run together and break list items, headings, etc.
84+
if (slideContent.length > 0 && slide.content.length > 0) {
85+
const last = slide.content[slide.content.length - 1];
86+
const first = slideContent[0];
87+
if (typeof last === 'string' && typeof first === 'string') {
88+
slideContent[0] = '\n' + first;
89+
}
90+
}
91+
slide.content = slide.content.concat(slideContent);
8292
}
8393
delete slide.properties.content;
8494
}

0 commit comments

Comments
 (0)