@@ -2,32 +2,17 @@ import fs from 'fs';
22import path from 'path' ;
33import fm from "front-matter" ;
44import yaml from 'js-yaml' ;
5- import { chunkContent , getCharsPerPage , PaginationConfig } from './utils/markdown-chunker' ;
5+ import { chunkContent , getCharsPerPage , getLinesPerPage , buildMeasureFn , MeasureFn , PaginationConfig } from './utils/markdown-chunker' ;
66import { loadTheme } from './utils/theme-loader' ;
7+ import { installCanvasPolyfill } from './utils/canvas-polyfill' ;
8+ import { resolveFontSpec } from './utils/font-loader' ;
79
810const publicDir = path . join ( __dirname , '..' , 'public' ) ;
911const piecesPath = path . join ( publicDir , 'content' , 'pieces' ) ;
1012const pagesIndexPath = path . join ( publicDir , 'generated' , 'index' , 'pieces-pages.json' ) ;
1113const piecesIndexPath = path . join ( publicDir , 'generated' , 'index' , 'pieces.json' ) ;
1214const configPath = path . join ( publicDir , 'config.yaml' ) ;
1315
14- const configRaw = fs . readFileSync ( configPath , 'utf-8' ) ;
15- const config = yaml . load ( configRaw ) as any ;
16-
17- const themeName = config ?. ui ?. theme ?. preset || config ?. theme || 'journal' ;
18- const theme = loadTheme ( themeName ) ;
19- const themeScaleOverride = config ?. ui ?. theme ?. overrides ?. font ?. scale ;
20- const themeScale = themeScaleOverride ?? theme ?. font ?. scale ?? 1 ;
21-
22- const paginationConfig : PaginationConfig = {
23- columns : config ?. reader ?. columns ?? 2 ,
24- pagination : config ?. reader ?. pagination ,
25- } ;
26-
27- const CHARS_PER_PAGE = getCharsPerPage ( paginationConfig , themeScale ) ;
28-
29- console . log ( `[pagination]: theme=${ themeName } , scale=${ themeScale } , charsPerPage=${ CHARS_PER_PAGE } ` ) ;
30-
3116type PiecePage = {
3217 pieceSlug : string ;
3318 pageNumber : number ;
@@ -42,42 +27,76 @@ type PiecePageIndex = {
4227 } ;
4328} ;
4429
45- const piecesIndexRaw = fs . readFileSync ( piecesIndexPath , 'utf-8' ) ;
46- const piecesIndex = JSON . parse ( piecesIndexRaw ) ;
30+ async function main ( ) {
31+ const configRaw = fs . readFileSync ( configPath , 'utf-8' ) ;
32+ const config = yaml . load ( configRaw ) as any ;
4733
48- const pageIndex : PiecePageIndex = { } ;
34+ const themeName = config ?. ui ?. theme ?. preset || config ?. theme || 'journal' ;
35+ const theme = loadTheme ( themeName ) ;
36+ const themeScaleOverride = config ?. ui ?. theme ?. overrides ?. font ?. scale ;
37+ const themeScale = themeScaleOverride ?? theme ?. font ?. scale ?? 1 ;
4938
50- piecesIndex . forEach ( ( piece : any ) => {
51- const { slug } = piece ;
52- const filePath = path . join ( piecesPath , `${ slug } .md` ) ;
53-
54- if ( ! fs . existsSync ( filePath ) ) {
55- console . warn ( `[pagination]: file not found for slug: ${ slug } ` ) ;
56- return ;
57- }
58-
59- const raw = fs . readFileSync ( filePath , 'utf-8' ) ;
60- const parsed = fm ( raw ) ;
61- const content = parsed . body ;
62-
63- const chunks = chunkContent ( content , CHARS_PER_PAGE ) ;
64- const totalPages = chunks . length ;
65-
66- const pages : PiecePage [ ] = chunks . map ( ( chunk , index ) => ( {
67- pieceSlug : slug ,
68- pageNumber : index + 1 ,
69- content : chunk ,
70- totalPages
71- } ) ) ;
72-
73- pageIndex [ slug ] = {
74- totalPages,
75- pages
39+ const paginationConfig : PaginationConfig = {
40+ columns : config ?. reader ?. columns ?? 2 ,
41+ pagination : config ?. reader ?. pagination ,
7642 } ;
77-
78- console . log ( `[pagination]: ${ slug } : ${ totalPages } page(s)` ) ;
79- } ) ;
8043
81- fs . writeFileSync ( pagesIndexPath , JSON . stringify ( pageIndex , null , 2 ) ) ;
82- console . log ( `[pagination]: created pieces-pages.json with ${ Object . keys ( pageIndex ) . length } pieces` ) ;
44+ const p = paginationConfig . pagination ?? { } ;
45+ const columnWidth = p . columnWidth ?? 330 ;
46+ const lineHeight = p . lineHeight ?? 24 ;
47+ const avgCharWidth = p . avgCharWidth ?? 8 ;
48+
49+ const CHARS_PER_PAGE = getCharsPerPage ( paginationConfig , themeScale ) ;
50+
51+ await installCanvasPolyfill ( ) ;
52+
53+ let measureFn : MeasureFn | undefined ;
54+ let linesPerPage : number | undefined ;
55+
56+ if ( theme ) {
57+ const fontSpec = await resolveFontSpec ( theme , themeScale , lineHeight ) ;
58+ measureFn = await buildMeasureFn ( fontSpec . cssFontString , columnWidth , lineHeight * themeScale , avgCharWidth ) ;
59+ linesPerPage = getLinesPerPage ( paginationConfig , themeScale ) ;
60+ console . log ( `[pagination]: theme=${ themeName } , scale=${ themeScale } , linesPerPage=${ linesPerPage } , font=${ fontSpec . cssFontString } ` ) ;
61+ } else {
62+ console . log ( `[pagination]: theme=${ themeName } , scale=${ themeScale } , charsPerPage=${ CHARS_PER_PAGE } (no theme, char-based fallback)` ) ;
63+ }
64+
65+ const piecesIndexRaw = fs . readFileSync ( piecesIndexPath , 'utf-8' ) ;
66+ const piecesIndex = JSON . parse ( piecesIndexRaw ) ;
67+
68+ const pageIndex : PiecePageIndex = { } ;
69+
70+ for ( const piece of piecesIndex ) {
71+ const { slug } = piece ;
72+ const filePath = path . join ( piecesPath , `${ slug } .md` ) ;
73+
74+ if ( ! fs . existsSync ( filePath ) ) {
75+ console . warn ( `[pagination]: file not found for slug: ${ slug } ` ) ;
76+ continue ;
77+ }
78+
79+ const raw = fs . readFileSync ( filePath , 'utf-8' ) ;
80+ const parsed = fm ( raw ) ;
81+ const content = parsed . body ;
82+
83+ const chunks = chunkContent ( content , CHARS_PER_PAGE , measureFn , linesPerPage , columnWidth , avgCharWidth ) ;
84+ const totalPages = chunks . length ;
85+
86+ const pages : PiecePage [ ] = chunks . map ( ( chunk , index ) => ( {
87+ pieceSlug : slug ,
88+ pageNumber : index + 1 ,
89+ content : chunk ,
90+ totalPages
91+ } ) ) ;
92+
93+ pageIndex [ slug ] = { totalPages, pages } ;
94+
95+ console . log ( `[pagination]: ${ slug } : ${ totalPages } page(s)` ) ;
96+ }
97+
98+ fs . writeFileSync ( pagesIndexPath , JSON . stringify ( pageIndex , null , 2 ) ) ;
99+ console . log ( `[pagination]: created pieces-pages.json with ${ Object . keys ( pageIndex ) . length } pieces` ) ;
100+ }
83101
102+ main ( ) . catch ( err => { console . error ( err ) ; process . exit ( 1 ) ; } ) ;
0 commit comments