import { merge } from "../core/utils.ts";
import type { Site } from "../core.ts";
export interface PaginateOptions { size: number;
url: (page: number) => string;
each?: (page: PaginateResult<unknown>) => void;}
export type Paginator = <T>( results: T[], userOptions?: Partial<PaginateOptions>,) => PaginateResult<T>[];
export interface PaginationInfo { page: number;
totalPages: number;
totalResults: number;
previous: string | null;
next: string | null;}
export interface PaginateResult<T> { url: string;
results: T[];
pagination: PaginationInfo;
[key: string]: unknown;}
export interface Options { name: string;
options: PaginateOptions;}
export const defaults: Options = { name: "paginate", options: { size: 10, url: () => "", },};
export default function (userOptions?: Partial<Options>) { const options = merge(defaults, userOptions);
return (site: Site) => { if (!userOptions?.options?.url) { const ext = site.options.prettyUrls ? "/index.html" : ".html"; options.options.url = (page: number) => `./page-${page}${ext}`; }
site.data(options.name, createPaginator(options.options)); };}
export function createPaginator(defaults: PaginateOptions): Paginator { return function paginate<T>( results: T[], userOptions: Partial<PaginateOptions> = {}, ) { const options = merge(defaults, userOptions); const totalResults = results.length; const totalPages = Math.ceil(results.length / options.size);
const result: PaginateResult<T>[] = []; let page = 0;
while (++page <= totalPages) { const data = createPageData(page); const from = (page - 1) * options.size; const to = from + options.size; data.results = results.slice(from, to);
if (options.each) { options.each(data); }
result.push(data); }
return result;
function createPageData(page: number): PaginateResult<T> { return { url: options.url(page), results: [], pagination: { page, totalPages, totalResults, previous: page > 1 ? options.url(page - 1) : null, next: totalPages > page ? options.url(page + 1) : null, }, }; } };}