@moonwave99/goffre 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,141 @@
1
+ import { MarkedExtension, RendererObject } from "marked";
2
+ import { HelperOptions } from "handlebars";
3
+
4
+ //#region lib/goffre.d.ts
5
+ type Page = {
6
+ slug: string;
7
+ link?: string;
8
+ template?: string;
9
+ layout?: string | null;
10
+ content?: string;
11
+ extname?: string;
12
+ };
13
+ declare function getSlug(slug: string, params: Record<string, unknown>): string;
14
+ type GetTemplateParams = {
15
+ page: Page;
16
+ templates: string[];
17
+ defaultTemplate?: string;
18
+ };
19
+ declare function getTemplate({
20
+ page,
21
+ templates,
22
+ defaultTemplate
23
+ }: GetTemplateParams): string;
24
+ type LoadParams = {
25
+ dataPath?: string;
26
+ };
27
+ declare function load({
28
+ dataPath
29
+ }?: LoadParams): Promise<{
30
+ json: {};
31
+ pages: {
32
+ excerpt: string;
33
+ slug: string;
34
+ description: any;
35
+ content: string;
36
+ }[];
37
+ }>;
38
+ declare function loadJSON(cwd: string): Promise<{}>;
39
+ declare function loadMarkdown(cwd: string): Promise<{
40
+ excerpt: string;
41
+ slug: string;
42
+ description: any;
43
+ content: string;
44
+ }[]>;
45
+ type GetSorterParams = {
46
+ sortBy: string;
47
+ order: "asc" | "desc";
48
+ };
49
+ declare function getSorter<T extends Record<string, unknown>>({
50
+ sortBy,
51
+ order
52
+ }: GetSorterParams): (a: T, b: T) => number;
53
+ type RenderParams = {
54
+ pages: Page[];
55
+ viewsPath?: string;
56
+ buildPath?: string;
57
+ blockSeparator?: string;
58
+ domain?: string;
59
+ uglyUrls?: boolean;
60
+ logLevel?: "silent" | "verbose" | "normal";
61
+ locals: Record<string, unknown>;
62
+ sitemap?: {
63
+ generate?: boolean;
64
+ template?: string;
65
+ };
66
+ env?: Record<string, unknown>;
67
+ handlebars?: {
68
+ extname?: string;
69
+ helpers?: Record<string, unknown>;
70
+ };
71
+ markdown?: {
72
+ middleware?: (MarkedExtension | (() => MarkedExtension))[];
73
+ renderer?: RendererObject;
74
+ };
75
+ };
76
+ declare function render({
77
+ pages,
78
+ viewsPath,
79
+ buildPath,
80
+ blockSeparator,
81
+ domain,
82
+ uglyUrls,
83
+ logLevel,
84
+ locals,
85
+ markdown,
86
+ handlebars,
87
+ sitemap,
88
+ env
89
+ }: RenderParams): Promise<unknown[]>;
90
+ type PaginateParams<T extends Page> = {
91
+ collection: T[];
92
+ size?: number;
93
+ sortBy?: keyof T;
94
+ order?: "asc" | "desc";
95
+ };
96
+ type PaginatedResult<T extends Page> = {
97
+ pagination: {
98
+ page: number;
99
+ prev: number | null;
100
+ next: number | null;
101
+ total: number;
102
+ };
103
+ items: T[];
104
+ };
105
+ declare function paginate<T extends Page>({
106
+ collection,
107
+ size,
108
+ sortBy,
109
+ order
110
+ }: PaginateParams<T>): PaginatedResult<T>[];
111
+ declare namespace helpers_d_exports {
112
+ export { getAsset, getExcerpt, getLink, getNavClass, getParamLink, getSitemapLink, list, markdown$1 as markdown, nextItem, prevItem };
113
+ }
114
+ type Context = {
115
+ data: {
116
+ root: {
117
+ options?: {
118
+ domain?: string;
119
+ env?: {
120
+ mode?: string;
121
+ };
122
+ };
123
+ };
124
+ };
125
+ };
126
+ type HelperContext = Context & Omit<HelperOptions, "fn" | "inverse">;
127
+ type BlockContext = Context & HelperOptions;
128
+ declare const markdown$1: (text: string) => string | Promise<string>;
129
+ declare function getExcerpt(content: string): Promise<string>;
130
+ declare const getParamLink: (url: string, options: HelperContext) => string;
131
+ declare const getAsset: (asset: string, context: Omit<HelperContext, "hash">) => string;
132
+ declare const getSitemapLink: (page: Page, context: HelperContext) => string;
133
+ declare const getLink: (page: Page, context: HelperContext) => string;
134
+ declare const getNavClass: ({
135
+ slug
136
+ }: Page, currentPage: Page) => string;
137
+ declare const list: (context: Page[], options: BlockContext) => string;
138
+ declare const nextItem: (context: Page, options: Pick<BlockContext, "hash" | "fn">) => string | undefined;
139
+ declare const prevItem: (context: Page, options: Pick<BlockContext, "hash" | "fn">) => string | undefined;
140
+ //#endregion
141
+ export { Page, getSlug, getSorter, getTemplate, helpers_d_exports as helpers, load, loadJSON, loadMarkdown, paginate, render };
package/dist/index.mjs ADDED
@@ -0,0 +1,280 @@
1
+ import { t as __exportAll } from "./chunk-DQk6qfdC.mjs";
2
+ import path from "path";
3
+ import { globby } from "globby";
4
+ import { marked } from "marked";
5
+ import matter from "gray-matter";
6
+ import { createRequire } from "module";
7
+ import fs from "fs-extra";
8
+ import express from "express";
9
+ import { engine } from "express-handlebars";
10
+ import chalk from "chalk";
11
+ import slugify from "slugify";
12
+ import { stripHtml } from "string-strip-html";
13
+
14
+ //#region lib/helpers.ts
15
+ var helpers_exports = /* @__PURE__ */ __exportAll({
16
+ getAsset: () => getAsset,
17
+ getExcerpt: () => getExcerpt,
18
+ getLink: () => getLink,
19
+ getNavClass: () => getNavClass,
20
+ getParamLink: () => getParamLink,
21
+ getSitemapLink: () => getSitemapLink,
22
+ list: () => list,
23
+ markdown: () => markdown,
24
+ nextItem: () => nextItem,
25
+ prevItem: () => prevItem
26
+ });
27
+ const markdown = (text) => marked(text);
28
+ async function getExcerpt(content) {
29
+ const firstParagraph = content.split("\n").filter(Boolean).at(0);
30
+ if (!firstParagraph) return "";
31
+ return stripHtml(await marked(firstParagraph)).result;
32
+ }
33
+ const getParamLink = (url, options) => {
34
+ return getAsset(getSlug(url, options.hash), options);
35
+ };
36
+ const getAsset = (asset, context) => {
37
+ const { options, env } = context.data.root;
38
+ return env.mode === "prod" && options.domain ? `${options.domain}${asset.startsWith("/") ? "" : "/"}${asset}` : asset;
39
+ };
40
+ const getSitemapLink = (page, context) => {
41
+ const { options } = context.data.root;
42
+ return `${options.domain}${getLink(page, context)}`;
43
+ };
44
+ const getLink = (page, context) => {
45
+ const base = page.link || `${page.slug.startsWith("/") ? "" : "/"}${page.slug}`;
46
+ const { uglyUrls } = context.data.root.options;
47
+ if (uglyUrls) return getAsset(`${base === "/" ? "/index" : base}.html`, context);
48
+ return getAsset(base.replace(/^\/index/, "/"), context);
49
+ };
50
+ const getNavClass = ({ slug }, currentPage) => {
51
+ const cleanSlug = slug && slug[0] === "/" ? slug.slice(1) : slug;
52
+ return currentPage.slug.startsWith(cleanSlug) ? `${cleanSlug} current` : cleanSlug;
53
+ };
54
+ const list = (context, options) => {
55
+ const offset = parseInt(options.hash.offset, 10) || 0;
56
+ const limit = parseInt(options.hash.limit, 10) || 100;
57
+ const sortBy = options.hash.sortBy || "slug";
58
+ const order = options.hash.order || "asc";
59
+ let output = "";
60
+ let i;
61
+ const data = context.toSorted(getSorter({
62
+ sortBy,
63
+ order
64
+ }));
65
+ if (offset < 0) i = -offset < data.length ? data.length - -offset : 0;
66
+ else i = offset < data.length ? offset : 0;
67
+ const j = limit + i < data.length ? limit + i : data.length;
68
+ for (; i < j; i++) output += options.fn(data[i]);
69
+ return output;
70
+ };
71
+ const nextItem = (context, options) => {
72
+ const { list } = options.hash;
73
+ const next = list[list.findIndex((x) => x.slug === context.slug) + 1];
74
+ if (!next) return;
75
+ return options.fn(next);
76
+ };
77
+ const prevItem = (context, options) => {
78
+ const { list } = options.hash;
79
+ const prev = list[list.findIndex((x) => x.slug === context.slug) - 1];
80
+ if (!prev) return;
81
+ return options.fn(prev);
82
+ };
83
+
84
+ //#endregion
85
+ //#region lib/goffre.ts
86
+ const require = createRequire(import.meta.url);
87
+ const { readFile, outputFile } = fs;
88
+ const DEFAULT_DATA_PATH = path.join(process.cwd(), "data");
89
+ const DEFAULT_VIEWS_PATH = path.join(process.cwd(), "src", "views");
90
+ const DEFAULT_BUILD_PATH = path.join(process.cwd(), "dist");
91
+ const MAX_SLUG_LOG_LENGTH = 40;
92
+ const DEFAULT_BLOCK_SEPARATOR = "<!-- block -->";
93
+ const thisYear = (/* @__PURE__ */ new Date()).getFullYear();
94
+ function log(...args) {
95
+ console.log.apply(null, ["[goffre]", ...args].map((x) => chalk.cyan(x)));
96
+ }
97
+ function getEnv() {
98
+ return { mode: process.env.MODE || "dev" };
99
+ }
100
+ function stringify(token) {
101
+ if (token instanceof Date) return token.toISOString().split("T")[0];
102
+ return `${token}`;
103
+ }
104
+ function getSlug(slug, params) {
105
+ return slug.split("/").reduce((memo, x) => {
106
+ if (!x.startsWith(":")) return [...memo, x];
107
+ const param = x.slice(1);
108
+ const value = params[param];
109
+ if (!value) throw new Error(`No value found for parameter: ${param}`);
110
+ return [...memo, slugify(stringify(value), {
111
+ lower: true,
112
+ strict: true
113
+ })];
114
+ }, []).join("/");
115
+ }
116
+ function getTemplate({ page, templates = [], defaultTemplate = "_default" }) {
117
+ if (templates.find((x) => x === `${page.template}.handlebars`)) return page.template;
118
+ if (templates.find((x) => x.startsWith(page.slug))) return page.slug;
119
+ return defaultTemplate;
120
+ }
121
+ function renderPage({ app, templates, buildPath, maxSlugLogLength, blockSeparator, sitemapLink, ...page }) {
122
+ return new Promise((resolve, reject) => {
123
+ const template = getTemplate({
124
+ page,
125
+ templates
126
+ });
127
+ switch (app.locals.options.logLevel) {
128
+ case "silent": break;
129
+ case "verbose":
130
+ log(`Generating ${chalk.yellow(page.slug.padEnd(maxSlugLogLength || MAX_SLUG_LOG_LENGTH, " "))} with template ${chalk.green(template)}...`);
131
+ break;
132
+ default: log(`Generating ${chalk.yellow(page.slug)}...`);
133
+ }
134
+ app.render(template, {
135
+ ...page,
136
+ sitemapLink,
137
+ thisYear,
138
+ layout: typeof page.layout === "undefined" ? "main" : page.layout,
139
+ content: page.content ? marked.parse(page.content) : null,
140
+ blocks: getPageBlocks(page.content, blockSeparator || DEFAULT_BLOCK_SEPARATOR)
141
+ }, async (error, html) => {
142
+ if (error) {
143
+ reject(error);
144
+ return;
145
+ }
146
+ const outputFileName = `${page.slug}${page.extname || ".html"}`;
147
+ await outputFile(path.join(buildPath, outputFileName), html);
148
+ resolve({
149
+ ...page,
150
+ outputFileName
151
+ });
152
+ });
153
+ });
154
+ }
155
+ function getPageBlocks(content = "", separator) {
156
+ if (!content.includes(separator)) return [];
157
+ return content.split(separator).map((x) => marked.parse(x)).filter(Boolean);
158
+ }
159
+ async function load({ dataPath } = {}) {
160
+ return {
161
+ json: await loadJSON(dataPath || DEFAULT_DATA_PATH),
162
+ pages: await loadMarkdown(dataPath || DEFAULT_DATA_PATH)
163
+ };
164
+ }
165
+ async function loadJSON(cwd) {
166
+ return (await globby("**/*.json", { cwd })).reduce((memo, x) => ({
167
+ ...memo,
168
+ [path.basename(x, ".json")]: require(path.join(cwd, x))
169
+ }), {});
170
+ }
171
+ async function loadMarkdown(cwd) {
172
+ const files = await globby("**/*.md", { cwd });
173
+ return Promise.all(files.map(async (fileName) => {
174
+ const parsed = matter(await readFile(path.join(cwd, fileName), "utf-8"));
175
+ const outputFileName = fileName.replace(".md", "");
176
+ const slug = !parsed.data.slug ? outputFileName : getSlug(parsed.data.slug, parsed.data);
177
+ return {
178
+ ...parsed.data,
179
+ excerpt: await getExcerpt(parsed.content),
180
+ slug,
181
+ description: parsed.data.description || parsed.excerpt,
182
+ content: parsed.content
183
+ };
184
+ }));
185
+ }
186
+ function getSorter({ sortBy, order }) {
187
+ return (a, b) => {
188
+ let output;
189
+ const valA = a[sortBy];
190
+ const valB = b[sortBy];
191
+ if (valA instanceof Date && valB instanceof Date) output = Number(new Date(valA)) - Number(new Date(valB));
192
+ else output = Number(valA) - Number(valB);
193
+ return order === "desc" ? -output : output;
194
+ };
195
+ }
196
+ async function render({ pages, viewsPath = DEFAULT_VIEWS_PATH, buildPath = DEFAULT_BUILD_PATH, blockSeparator = DEFAULT_BLOCK_SEPARATOR, domain, uglyUrls = false, logLevel = "normal", locals = {}, markdown = {}, handlebars = {}, sitemap = {}, env = {} }) {
197
+ const extname = handlebars.extname || ".handlebars";
198
+ const app = express();
199
+ app.engine(extname, engine({
200
+ ...handlebars,
201
+ helpers: {
202
+ ...helpers_exports,
203
+ ...handlebars.helpers
204
+ }
205
+ }));
206
+ app.set("view engine", "handlebars");
207
+ app.set("layoutsDir", path.join(viewsPath, "layouts"));
208
+ app.set("views", viewsPath);
209
+ const templates = await globby(`**/*${extname}`, { cwd: viewsPath });
210
+ app.locals = {
211
+ ...app.locals,
212
+ ...locals,
213
+ options: {
214
+ domain,
215
+ uglyUrls,
216
+ logLevel
217
+ },
218
+ env: {
219
+ ...getEnv(),
220
+ ...env
221
+ }
222
+ };
223
+ if (markdown.middleware) markdown.middleware.forEach((x) => marked.use(typeof x === "function" ? x() : x));
224
+ marked.use(markdown);
225
+ switch (logLevel) {
226
+ case "silent": break;
227
+ default: log(`Start generation...`);
228
+ }
229
+ const results = await Promise.all(pages.map((x) => renderPage({
230
+ ...x,
231
+ buildPath,
232
+ app,
233
+ templates,
234
+ sitemapLink: sitemap.generate ? `${domain}/sitemap.xml` : "",
235
+ blockSeparator,
236
+ maxSlugLogLength: Math.min(Math.max.call(null, ...pages.map((x) => x.slug.length)), MAX_SLUG_LOG_LENGTH)
237
+ })));
238
+ switch (logLevel) {
239
+ case "silent": break;
240
+ default: log(`Generated ${results.length} pages`);
241
+ }
242
+ if (sitemap.generate) renderPage({
243
+ slug: "sitemap",
244
+ template: sitemap.template || "sitemap",
245
+ extname: ".xml",
246
+ layout: null,
247
+ pages: results,
248
+ buildPath,
249
+ app,
250
+ templates
251
+ });
252
+ return results;
253
+ }
254
+ function paginate({ collection, size = 10, sortBy = "slug", order = "asc" }) {
255
+ const total = Math.ceil(collection.length / size);
256
+ return collection.toSorted(getSorter({
257
+ sortBy,
258
+ order
259
+ })).reduce((memo, x, index) => {
260
+ if (index % size === 0) {
261
+ const page = Math.floor(index / size) + 1;
262
+ return [...memo, {
263
+ pagination: {
264
+ page,
265
+ prev: page > 1 ? page - 1 : null,
266
+ next: page < total ? page + 1 : null,
267
+ total
268
+ },
269
+ items: [x]
270
+ }];
271
+ }
272
+ return [...memo.slice(0, -1), {
273
+ ...memo[memo.length - 1],
274
+ items: [...memo[memo.length - 1].items, x]
275
+ }];
276
+ }, []);
277
+ }
278
+
279
+ //#endregion
280
+ export { getSlug, getSorter, getTemplate, helpers_exports as helpers, load, loadJSON, loadMarkdown, paginate, render };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moonwave99/goffre",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Mini static site generator",
5
5
  "author": {
6
6
  "name": "Diego Caponera",
@@ -47,6 +47,7 @@
47
47
  "fs-extra": "^10.0.0",
48
48
  "globby": "^12.0.2",
49
49
  "gray-matter": "^4.0.3",
50
+ "handlebars": "^4.7.8",
50
51
  "marked": "^17.0.3",
51
52
  "slugify": "^1.6.2",
52
53
  "string-strip-html": "^13.5.3"
@@ -72,13 +73,13 @@
72
73
  "js-yaml": "^4.1.1",
73
74
  "rimraf": "^6.1.3",
74
75
  "sinon": "^21.0.1",
76
+ "tsdown": "^0.20.3",
75
77
  "tsimp": "^2.0.12",
76
- "tsup": "^8.5.1",
77
78
  "typescript": "^5.9.3"
78
79
  },
79
80
  "scripts": {
80
- "build": "tsup",
81
- "dev": "tsup --watch",
81
+ "build": "tsdown",
82
+ "dev": "tsdown --watch",
82
83
  "test": "ava **/*.test.ts",
83
84
  "lint": "pnpm eslint ./lib --ext .js,.jsx,.ts,.tsx"
84
85
  }
package/dist/index.d.ts DELETED
@@ -1,188 +0,0 @@
1
- import { MarkedExtension, RendererObject } from 'marked';
2
- import { HelperOptions } from 'handlebars';
3
-
4
- type Page = {
5
- slug: string;
6
- link?: string;
7
- template?: string;
8
- layout?: string | null;
9
- content?: string;
10
- extname?: string;
11
- };
12
- declare function getSlug(slug: string, params: Record<string, unknown>): string;
13
- type GetTemplateParams = {
14
- page: Page;
15
- templates: string[];
16
- defaultTemplate?: string;
17
- };
18
- declare function getTemplate({ page, templates, defaultTemplate, }: GetTemplateParams): string;
19
- type LoadParams = {
20
- dataPath?: string;
21
- };
22
- declare function load({ dataPath }?: LoadParams): Promise<{
23
- json: {};
24
- pages: {
25
- excerpt: string;
26
- slug: string;
27
- description: any;
28
- content: string;
29
- }[];
30
- }>;
31
- declare function loadJSON(cwd: string): Promise<{}>;
32
- declare function loadMarkdown(cwd: string): Promise<{
33
- excerpt: string;
34
- slug: string;
35
- description: any;
36
- content: string;
37
- }[]>;
38
- type GetSorterParams = {
39
- sortBy: string;
40
- order: "asc" | "desc";
41
- };
42
- declare function getSorter<T extends Record<string, unknown>>({ sortBy, order, }: GetSorterParams): (a: T, b: T) => number;
43
- type RenderParams = {
44
- pages: Page[];
45
- viewsPath?: string;
46
- buildPath?: string;
47
- blockSeparator?: string;
48
- domain?: string;
49
- uglyUrls?: boolean;
50
- logLevel?: "silent" | "verbose" | "normal";
51
- locals: Record<string, unknown>;
52
- sitemap?: {
53
- generate?: boolean;
54
- template?: string;
55
- };
56
- env?: Record<string, unknown>;
57
- handlebars?: {
58
- extname?: string;
59
- helpers?: Record<string, unknown>;
60
- };
61
- markdown?: {
62
- middleware?: (MarkedExtension | (() => MarkedExtension))[];
63
- renderer?: RendererObject;
64
- };
65
- };
66
- declare function render({ pages, viewsPath, buildPath, blockSeparator, domain, uglyUrls, logLevel, locals, markdown, handlebars, sitemap, env, }: RenderParams): Promise<unknown[]>;
67
- type PaginateParams<T extends Page> = {
68
- collection: T[];
69
- size?: number;
70
- sortBy?: keyof T;
71
- order?: "asc" | "desc";
72
- };
73
- type PaginatedResult<T extends Page> = {
74
- pagination: {
75
- page: number;
76
- prev: number | null;
77
- next: number | null;
78
- total: number;
79
- };
80
- items: T[];
81
- };
82
- declare function paginate<T extends Page>({ collection, size, sortBy, order, }: PaginateParams<T>): PaginatedResult<T>[];
83
-
84
- type Context = {
85
- data: {
86
- root: {
87
- options?: {
88
- domain?: string;
89
- env?: {
90
- mode?: string;
91
- };
92
- };
93
- };
94
- };
95
- };
96
- type HelperContext = Context & Omit<HelperOptions, "fn" | "inverse">;
97
- type BlockContext = Context & HelperOptions;
98
- declare const markdown: (text: string) => string | Promise<string>;
99
- declare function getExcerpt(content: string): Promise<string>;
100
- declare const getParamLink: (url: string, options: HelperContext) => string;
101
- declare const getAsset: (asset: string, context: Omit<HelperContext, "hash">) => string;
102
- declare const getSitemapLink: (page: Page, context: HelperContext) => string;
103
- declare const getLink: (page: Page, context: HelperContext) => string;
104
- declare const getNavClass: ({ slug }: Page, currentPage: Page) => string;
105
- declare const list: (context: Page[], options: BlockContext) => string;
106
- declare const nextItem: (context: Page, options: Pick<BlockContext, "hash" | "fn">) => string | undefined;
107
- declare const prevItem: (context: Page, options: Pick<BlockContext, "hash" | "fn">) => string | undefined;
108
-
109
- declare const helpers_getAsset: typeof getAsset;
110
- declare const helpers_getExcerpt: typeof getExcerpt;
111
- declare const helpers_getLink: typeof getLink;
112
- declare const helpers_getNavClass: typeof getNavClass;
113
- declare const helpers_getParamLink: typeof getParamLink;
114
- declare const helpers_getSitemapLink: typeof getSitemapLink;
115
- declare const helpers_list: typeof list;
116
- declare const helpers_markdown: typeof markdown;
117
- declare const helpers_nextItem: typeof nextItem;
118
- declare const helpers_prevItem: typeof prevItem;
119
- declare namespace helpers {
120
- export { helpers_getAsset as getAsset, helpers_getExcerpt as getExcerpt, helpers_getLink as getLink, helpers_getNavClass as getNavClass, helpers_getParamLink as getParamLink, helpers_getSitemapLink as getSitemapLink, helpers_list as list, helpers_markdown as markdown, helpers_nextItem as nextItem, helpers_prevItem as prevItem };
121
- }
122
-
123
- declare function getRandomProjectNames(length: number): string[];
124
- type WriteOutputParams = {
125
- basePath: string;
126
- fileName: string;
127
- output: string;
128
- };
129
- declare function writeOutput({ basePath, fileName, output, }: WriteOutputParams): Promise<void>;
130
- declare function toMarkdownFile({ content, ...frontMatter }: {
131
- content: string;
132
- frontMatter: Record<string, unknown>;
133
- }): string;
134
- type GeneratePostParams = {
135
- index: number;
136
- template?: string;
137
- slug?: string;
138
- withBlocks?: boolean;
139
- };
140
- declare function generatePost({ index, template, slug, withBlocks, }: GeneratePostParams): {
141
- title: string;
142
- template: string;
143
- created_at: Date;
144
- slug: string;
145
- cover: {
146
- url: string;
147
- caption: string;
148
- attribution: {
149
- text: string;
150
- link: string;
151
- };
152
- };
153
- fileName: string;
154
- content: string;
155
- };
156
- declare function generateProject({ name, index, }: {
157
- name: string;
158
- index: number;
159
- }): {
160
- title: string;
161
- slug: string;
162
- template: string;
163
- work_date: Date;
164
- homepage: string;
165
- demo: string;
166
- technologies: string[];
167
- cover: {
168
- url: string;
169
- caption: string;
170
- attribution: {
171
- text: string;
172
- link: string;
173
- };
174
- };
175
- fileName: string;
176
- content: string;
177
- };
178
-
179
- declare const generator_generatePost: typeof generatePost;
180
- declare const generator_generateProject: typeof generateProject;
181
- declare const generator_getRandomProjectNames: typeof getRandomProjectNames;
182
- declare const generator_toMarkdownFile: typeof toMarkdownFile;
183
- declare const generator_writeOutput: typeof writeOutput;
184
- declare namespace generator {
185
- export { generator_generatePost as generatePost, generator_generateProject as generateProject, generator_getRandomProjectNames as getRandomProjectNames, generator_toMarkdownFile as toMarkdownFile, generator_writeOutput as writeOutput };
186
- }
187
-
188
- export { type Page, generator, getSlug, getSorter, getTemplate, helpers, load, loadJSON, loadMarkdown, paginate, render };