Skip to content

Commit 994a04a

Browse files
Merge pull request #25 from DimwitLabs/development
Feat: add configurable pagination options and improve markdown handling
2 parents 7ed8e31 + 3ef965e commit 994a04a

9 files changed

Lines changed: 312 additions & 49 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.4.6] - 2026-03-06
9+
10+
### Added
11+
12+
- Configurable characters per page in reader mode via `reader.charsPerPage` in `config.yaml`. Users may not need to change this at all. But the idea is to keep it configurable in case there are some visual artifacts in the reader mode. This is responsible for splitting the pages for the reader mode.
13+
14+
### Fixed
15+
16+
- Reader mode now correctly paginates lists, code blocks, and blockquotes instead of truncating them mid-element.
17+
- Body of Work page now appears on first deploy when using a custom slug; reliably.
18+
819
## [1.4.5] - 2026-03-05
920

1021
### Fixed

build/defaults/config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ exclude:
3434
pieces:
3535
-
3636
reader:
37+
charsPerPage: 2200
3738
order:
3839
default: descending
3940
rss:

build/generate-body-of-work.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const config = yaml.load(fs.readFileSync(configPath, 'utf-8')) as {
1515
};
1616
};
1717

18+
const bodyOfWorkSlug = config?.bodyOfWork?.slug || 'body-of-work';
19+
1820
type Piece = {
1921
slug: string;
2022
title: string;
@@ -73,7 +75,6 @@ const sortedKeys = Object.keys(grouped).sort((a, b) => {
7375
});
7476

7577
const bodyOfWorkTitle = config?.bodyOfWork?.title || 'Body of Work';
76-
const bodyOfWorkSlug = config?.bodyOfWork?.slug || 'body-of-work';
7778
const bodyOfWorkFilePath = path.join(publicDir, 'content', 'pages', `${bodyOfWorkSlug}.md`);
7879

7980
let markdown = '---\n';

build/paginate-pieces.ts

Lines changed: 7 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
import fs from 'fs';
22
import path from 'path';
33
import fm from "front-matter";
4+
import yaml from 'js-yaml';
5+
import { chunkContent } from './utils/markdown-chunker';
46

57
const publicDir = path.join(__dirname, '..', 'public');
68
const piecesPath = path.join(publicDir, 'content', 'pieces');
79
const pagesIndexPath = path.join(publicDir, 'generated', 'index', 'pieces-pages.json');
810
const piecesIndexPath = path.join(publicDir, 'generated', 'index', 'pieces.json');
11+
const configPath = path.join(publicDir, 'config.yaml');
912

10-
const CHARS_PER_PAGE = 2200;
13+
const configRaw = fs.readFileSync(configPath, 'utf-8');
14+
const config = yaml.load(configRaw) as any;
15+
const CHARS_PER_PAGE = config?.reader?.charsPerPage ?? 2200;
1116

1217
type PiecePage = {
1318
pieceSlug: string;
@@ -23,49 +28,6 @@ type PiecePageIndex = {
2328
};
2429
};
2530

26-
function chunkContent(content: string, charsPerPage: number): string[] {
27-
const chunks: string[] = [];
28-
const paragraphs = content.split('\n\n');
29-
30-
let currentChunk = '';
31-
32-
for (const paragraph of paragraphs) {
33-
const trimmedParagraph = paragraph.trim();
34-
if (!trimmedParagraph) continue;
35-
36-
if (currentChunk.length > 0 && (currentChunk.length + trimmedParagraph.length + 2) > charsPerPage) {
37-
chunks.push(currentChunk.trim());
38-
currentChunk = '';
39-
}
40-
41-
if (trimmedParagraph.length > charsPerPage) {
42-
const sentences = trimmedParagraph.match(/[^.!?]+[.!?]+/g) || [trimmedParagraph];
43-
44-
for (const sentence of sentences) {
45-
if (currentChunk.length > 0 && (currentChunk.length + sentence.length) > charsPerPage) {
46-
chunks.push(currentChunk.trim());
47-
currentChunk = sentence;
48-
} else {
49-
currentChunk += sentence;
50-
}
51-
}
52-
currentChunk += '\n\n';
53-
} else {
54-
currentChunk += trimmedParagraph + '\n\n';
55-
}
56-
}
57-
58-
if (currentChunk.trim()) {
59-
chunks.push(currentChunk.trim());
60-
}
61-
62-
if (chunks.length === 0) {
63-
chunks.push(content);
64-
}
65-
66-
return chunks;
67-
}
68-
6931
const piecesIndexRaw = fs.readFileSync(piecesIndexPath, 'utf-8');
7032
const piecesIndex = JSON.parse(piecesIndexRaw);
7133

@@ -104,3 +66,4 @@ piecesIndex.forEach((piece: any) => {
10466

10567
fs.writeFileSync(pagesIndexPath, JSON.stringify(pageIndex, null, 2));
10668
console.log(`[pagination]: created pieces-pages.json with ${Object.keys(pageIndex).length} pieces`);
69+

0 commit comments

Comments
 (0)