Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ Text alignment in `plain` documents switches from justified to start-aligned on

Captions for figures and tables in `plain` and `docs` documents now use a smaller font size on small screens.

#### Upgraded to Reveal.js 6

Upgraded Reveal.js, the library powering `slides` documents, to v6.0.0.
No breaking changes are expected in the rendered output.

### Fixed

#### Split paragraphs in `paged` documents now justify the last line correctly
Expand Down
1,946 changes: 797 additions & 1,149 deletions quarkdown-html/package-lock.json

Large diffs are not rendered by default.

9 changes: 4 additions & 5 deletions quarkdown-html/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,17 @@
"test:e2e:ui": "playwright test --ui"
},
"devDependencies": {
"esbuild": "^0.25.10",
"reveal.js": "^5.2.1",
"@types/reveal.js": "^5.2.1",
"esbuild": "^0.27.4",
"reveal.js": "^6.0.0",
"pagedjs": "^0.4.3",
"katex": "^0.16.23",
"@types/katex": "^0.16.3",
"highlight.js": "^11.11.1",
"mermaid": "^11.12.0",
"minisearch": "^7.2.0",
"vitest": "^3.2.4",
"vitest": "^4.1.2",
"happy-dom": "^20.0.2",
"@types/node": "^24.7.2",
"@types/node": "^25.5.0",
"@playwright/test": "^1.57.0",
"romans": "^3.1.0"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,11 @@ class HtmlDocumentBuilder(
/** Loads Reveal.js scripts and styles for slide documents. No-op for other document types. */
private fun HEAD.slidesScripts() {
if (document.type != DocumentType.SLIDES) return
script(src = "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/5.2.1/reveal.js") {}
script(src = "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/5.2.1/plugin/notes/notes.js") {}
link(rel = "stylesheet", href = "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/5.2.1/reset.css")
link(rel = "stylesheet", href = "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/5.2.1/reveal.css")
link(rel = "stylesheet", href = "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/5.2.1/theme/white.css")
script(src = "https://cdn.jsdelivr.net/npm/reveal.js@6.0.0/dist/reveal.js") {}
script(src = "https://cdn.jsdelivr.net/npm/reveal.js@6.0.0/dist/plugin/notes.js") {}
link(rel = "stylesheet", href = "https://cdn.jsdelivr.net/npm/reveal.js@6.0.0/dist/reset.css")
link(rel = "stylesheet", href = "https://cdn.jsdelivr.net/npm/reveal.js@6.0.0/dist/reveal.css")
link(rel = "stylesheet", href = "https://cdn.jsdelivr.net/npm/reveal.js@6.0.0/dist/theme/white.css")
}

private fun HEAD.iconLibrary() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {PageNumbers} from "../handlers/page-numbers";
import {PagedLikeQuarkdownDocument, QuarkdownPage} from "../paged-like-quarkdown-document";
import {PersistentHeadings} from "../handlers/persistent-headings";

declare const Reveal: typeof import("reveal.js"); // global Reveal at runtime
declare const RevealNotes: typeof import("reveal.js/plugin/notes/notes");
type RevealType = typeof import("reveal.js").default;
declare const Reveal: RevealType;
declare const RevealNotes: typeof import("reveal.js/dist/plugin/notes").default;

const SLIDE_SELECTOR = ".reveal .slides > :is(section, .pdf-page)";
const BACKGROUND_SELECTOR = ".reveal :is(.backgrounds, .slides > .pdf-page) > .slide-background";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Slide 1

.speakernote
hello

# Slide 2

.speakernote
**Formatted** speaker note

- Bullet 1
- Bullet 2
- Bullet 3

# Slide 3
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {suite} from "../../../quarkdown";

const {testMatrix, expect} = suite(__dirname);

testMatrix(
"speaker notes are accessible in the speaker view",
["slides"],
async (page) => {
// Inline .speaker-notes should be empty when showNotes is not enabled
const speakerNotes = page.locator(".speaker-notes");
await expect(speakerNotes).toBeEmpty();

// Open speaker view by pressing S
const popupPromise = page.context().waitForEvent("page");
await page.keyboard.press("s");
const speakerPage = await popupPromise;
await speakerPage.waitForLoadState("domcontentloaded");

const notesContainer = speakerPage.locator(".speaker-controls-notes");
await expect(notesContainer).toBeVisible({timeout: 10000});

// The speaker view shows the current slide's notes
await expect(notesContainer).toContainText("hello");
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.slides speakernotes:{yes}

# Slide 1

.speakernote
hello

# Slide 2

.speakernote
**Formatted** speaker note

- Bullet 1
- Bullet 2
- Bullet 3

# Slide 3
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {Locator} from "@playwright/test";
import {suite} from "../../../quarkdown";

const {testMatrix, expect} = suite(__dirname);

async function assertNoteContent(note: Locator) {
await expect(note).toContainText("Formatted");
const bullets = note.locator("li");
await expect(bullets).toHaveCount(3);
await expect(bullets.nth(0)).toHaveText("Bullet 1");
await expect(bullets.nth(1)).toHaveText("Bullet 2");
await expect(bullets.nth(2)).toHaveText("Bullet 3");
}

testMatrix(
"speaker notes are visible on each slide",
["slides", "slides-print"],
async (page, docType) => {
const notes = page.locator(".speaker-notes");

if (docType === "slides-print") {
// In print mode, each slide has its own .speaker-notes element
await expect(notes).toHaveCount(3);

await expect(notes.nth(0)).toContainText("hello");
await assertNoteContent(notes.nth(1));

// Slide 3 has no speaker note
await expect(notes.nth(2)).toBeEmpty();
} else {
// In regular slides mode, .speaker-notes shows the current slide's note
await expect(notes).toContainText("hello");

await page.keyboard.press("ArrowRight");
await assertNoteContent(notes);

// Slide 3 has no speaker note
await page.keyboard.press("ArrowRight");
await expect(notes).toContainText("No notes on this slide.");
}
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {suite} from "../../../quarkdown";
import {getTransitionConfig} from "../transition-config";

const {testMatrix, expect} = suite(__dirname);

testMatrix(
"applies custom transition configuration",
["slides"],
async (page) => {
const config = await getTransitionConfig(page);
expect(config.transition).toBe("fade");
expect(config.transitionSpeed).toBe("fast");

// Navigate and verify the slide changes with custom transition
await expect(page.locator(".reveal .slides > section.present h1")).toHaveText("Slide 1");
await page.keyboard.press("ArrowRight");
await expect(page.locator(".reveal .slides > section.present h1")).toHaveText("Slide 2");
}
);
9 changes: 9 additions & 0 deletions quarkdown-html/src/test/e2e/slides/transition/custom/main.qd
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.slides transition:{fade} speed:{fast}

# Slide 1

Hello

# Slide 2

World
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {suite} from "../../../quarkdown";
import {getTransitionConfig} from "../transition-config";

const {testMatrix, expect} = suite(__dirname);

testMatrix(
"uses default slide transition",
["slides"],
async (page) => {
const config = await getTransitionConfig(page);
expect(config.transition).toBe("slide");
expect(config.transitionSpeed).toBe("default");

// Navigate and verify the slide changes
await expect(page.locator(".reveal .slides > section.present h1")).toHaveText("Slide 1");
await page.keyboard.press("ArrowRight");
await expect(page.locator(".reveal .slides > section.present h1")).toHaveText("Slide 2");
}
);
7 changes: 7 additions & 0 deletions quarkdown-html/src/test/e2e/slides/transition/default/main.qd
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Slide 1

Hello

# Slide 2

World
11 changes: 11 additions & 0 deletions quarkdown-html/src/test/e2e/slides/transition/transition-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {Page} from "@playwright/test";

/**
* Retrieves the Reveal.js transition configuration from the page.
*/
export async function getTransitionConfig(page: Page) {
return page.evaluate(() => {
const config = (window as any).Reveal.getConfig();
return {transition: config.transition as string, transitionSpeed: config.transitionSpeed as string};
});
}
Loading