noblog 0.2.3 → 0.3.0-beta.2
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.
- package/README.md +280 -121
- package/dist/client-CzKR81Or.js +551 -0
- package/dist/client-CzKR81Or.js.map +1 -0
- package/dist/config-check.impl-C5FM7uWi.js +14 -0
- package/dist/config-check.impl-C5FM7uWi.js.map +1 -0
- package/dist/config-csbquMhF.js +21 -0
- package/dist/config-csbquMhF.js.map +1 -0
- package/dist/config-file-C07nmm45.js +27 -0
- package/dist/config-file-C07nmm45.js.map +1 -0
- package/dist/defaults-RGOB9tfi.js +10 -0
- package/dist/defaults-RGOB9tfi.js.map +1 -0
- package/dist/errors-BCRhKbgG.js +73 -0
- package/dist/errors-BCRhKbgG.js.map +1 -0
- package/dist/frontmatter-fields-BkXq38CO.js +71 -0
- package/dist/frontmatter-fields-BkXq38CO.js.map +1 -0
- package/dist/generate.d.ts +1 -0
- package/dist/generate.impl-ChFrtwtC.js +34 -0
- package/dist/generate.impl-ChFrtwtC.js.map +1 -0
- package/dist/generate.js +198 -940
- package/dist/generate.js.map +1 -1
- package/dist/index.d.ts +213 -18
- package/dist/index.js +5 -0
- package/package.json +32 -17
- package/schema/config.json +178 -0
- package/skills/noblog-config/SKILL.md +40 -0
- package/skills/noblog-config/assets/nobloger.yaml +30 -0
- package/skills/noblog-config/assets/thought-lite.yaml +47 -0
- package/skills/noblog-config/references/config-schema.md +110 -0
- package/skills/noblog-config/references/notion-property-types.md +42 -0
- package/skills/noblog-config/references/theme-examples.md +41 -0
- package/dist/cmds/generate.d.ts +0 -3
- package/dist/cmds/generate.d.ts.map +0 -1
- package/dist/generate.cjs +0 -970
- package/dist/generate.cjs.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/noblog/format.d.ts +0 -24
- package/dist/lib/noblog/format.d.ts.map +0 -1
- package/dist/lib/noblog/noblog.d.ts +0 -31
- package/dist/lib/noblog/noblog.d.ts.map +0 -1
- package/dist/lib/noblog/utils.d.ts +0 -36
- package/dist/lib/noblog/utils.d.ts.map +0 -1
- package/dist/lib/notion/client.d.ts +0 -8
- package/dist/lib/notion/client.d.ts.map +0 -1
package/dist/generate.cjs
DELETED
|
@@ -1,970 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
var path = require('path');
|
|
5
|
-
var fs = require('fs/promises');
|
|
6
|
-
var fetch = require('node-fetch');
|
|
7
|
-
var markdownTable = require('markdown-table');
|
|
8
|
-
require('dotenv/config');
|
|
9
|
-
var retry = require('async-retry');
|
|
10
|
-
var client$1 = require('@notionhq/client');
|
|
11
|
-
var fs$1 = require('fs');
|
|
12
|
-
var url = require('url');
|
|
13
|
-
|
|
14
|
-
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
15
|
-
function _interopNamespaceDefault(e) {
|
|
16
|
-
var n = Object.create(null);
|
|
17
|
-
if (e) {
|
|
18
|
-
Object.keys(e).forEach(function (k) {
|
|
19
|
-
if (k !== 'default') {
|
|
20
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
21
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
get: function () { return e[k]; }
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
n.default = e;
|
|
29
|
-
return Object.freeze(n);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
33
|
-
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
34
|
-
|
|
35
|
-
const suffixInlineCode = "`";
|
|
36
|
-
const prefixInlineCode = "`";
|
|
37
|
-
const suffixBold = "**";
|
|
38
|
-
const prefixBold = "**";
|
|
39
|
-
const suffixItalic = "_";
|
|
40
|
-
const prefixItalic = "_";
|
|
41
|
-
const suffixStrikethrough = "~~";
|
|
42
|
-
const prefixStrikethrough = "~~";
|
|
43
|
-
const suffixUnderline = "<u>";
|
|
44
|
-
const prefixUnderline = "</u>";
|
|
45
|
-
function GetPrefixSuffix(type) {
|
|
46
|
-
switch (type) {
|
|
47
|
-
case "code":
|
|
48
|
-
return [prefixInlineCode, suffixInlineCode];
|
|
49
|
-
case "bold":
|
|
50
|
-
return [prefixBold, suffixBold];
|
|
51
|
-
case "italic":
|
|
52
|
-
return [prefixItalic, suffixItalic];
|
|
53
|
-
case "strikethrough":
|
|
54
|
-
return [prefixStrikethrough, suffixStrikethrough];
|
|
55
|
-
case "underline":
|
|
56
|
-
return [prefixUnderline, suffixUnderline];
|
|
57
|
-
default:
|
|
58
|
-
return ["", ""];
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
const inlineEquation = (text) => {
|
|
62
|
-
return `$${text}$`;
|
|
63
|
-
};
|
|
64
|
-
const link = (text, href) => {
|
|
65
|
-
return `[${text}](${href})`;
|
|
66
|
-
};
|
|
67
|
-
const codeBlock = (text, language) => {
|
|
68
|
-
if (language === "plain text")
|
|
69
|
-
language = "text";
|
|
70
|
-
return `\`\`\`${language}
|
|
71
|
-
${text}
|
|
72
|
-
\`\`\``;
|
|
73
|
-
};
|
|
74
|
-
const equation = (text) => {
|
|
75
|
-
return `$$
|
|
76
|
-
${text}
|
|
77
|
-
$$`;
|
|
78
|
-
};
|
|
79
|
-
const heading1 = (text) => {
|
|
80
|
-
return `# ${text}`;
|
|
81
|
-
};
|
|
82
|
-
const heading2 = (text) => {
|
|
83
|
-
return `## ${text}`;
|
|
84
|
-
};
|
|
85
|
-
const heading3 = (text) => {
|
|
86
|
-
return `### ${text}`;
|
|
87
|
-
};
|
|
88
|
-
const quote = (text) => {
|
|
89
|
-
// the replace is done to handle multiple lines
|
|
90
|
-
return `> ${text.replace(/\n/g, " \n> ")}`;
|
|
91
|
-
};
|
|
92
|
-
const callout = (text, icon) => {
|
|
93
|
-
let emoji;
|
|
94
|
-
if (icon?.type === "emoji") {
|
|
95
|
-
emoji = icon.emoji;
|
|
96
|
-
}
|
|
97
|
-
// the replace is done to handle multiple lines
|
|
98
|
-
return `> ${emoji ? emoji + " " : ""}${text.replace(/\n/g, " \n> ")}`;
|
|
99
|
-
};
|
|
100
|
-
const bullet = (text, count) => {
|
|
101
|
-
const renderText = text.trim();
|
|
102
|
-
return count ? `${count}. ${renderText}` : `- ${renderText}`;
|
|
103
|
-
};
|
|
104
|
-
const todo = (text, checked) => {
|
|
105
|
-
return checked ? `- [x] ${text}` : `- [ ] ${text}`;
|
|
106
|
-
};
|
|
107
|
-
const image = async (alt, href, convertToBase64 = false) => {
|
|
108
|
-
// In case the user does not want to convert the images to Base64
|
|
109
|
-
// or the image is already base64
|
|
110
|
-
if (!convertToBase64 || href.startsWith("data:")) {
|
|
111
|
-
if (href.startsWith("data:")) {
|
|
112
|
-
// Extract base64 data, i.e. the string after 'data:mime/type;base64,'
|
|
113
|
-
const base64 = href.split(",").pop();
|
|
114
|
-
// This overrides incorrect data: string format to png
|
|
115
|
-
// so that browsers can correctly render the data
|
|
116
|
-
return ``;
|
|
117
|
-
}
|
|
118
|
-
return ``;
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
// Otherwise, download the image and convert it to base64
|
|
122
|
-
const res = await fetch(href);
|
|
123
|
-
const buf = await res.arrayBuffer();
|
|
124
|
-
const base64 = Buffer.from(buf).toString("base64");
|
|
125
|
-
return ``;
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
const addTabSpace = (text, n = 0) => {
|
|
129
|
-
const tab = " ";
|
|
130
|
-
for (let i = 0; i < n; i++) {
|
|
131
|
-
if (text.includes("\n")) {
|
|
132
|
-
const multiLineText = text.split(/(?:^|\n)/).join(`\n${tab}`);
|
|
133
|
-
text = tab + multiLineText;
|
|
134
|
-
}
|
|
135
|
-
else
|
|
136
|
-
text = tab + text;
|
|
137
|
-
}
|
|
138
|
-
return text;
|
|
139
|
-
};
|
|
140
|
-
const divider = () => {
|
|
141
|
-
return "---";
|
|
142
|
-
};
|
|
143
|
-
const toggle = (summary, children) => {
|
|
144
|
-
if (!summary)
|
|
145
|
-
return children || "";
|
|
146
|
-
return `<details>
|
|
147
|
-
<summary>${summary}</summary>
|
|
148
|
-
${children || ""}
|
|
149
|
-
</details>\n\n`;
|
|
150
|
-
};
|
|
151
|
-
const table = (cells) => {
|
|
152
|
-
return markdownTable.markdownTable(cells);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const NOTION_API_SECRET = process.env.NOTION_API_SECRET ?? "";
|
|
156
|
-
const NOBLOG_DATABASE_ID = process.env.NOBLOG_DATABASE_ID ?? "";
|
|
157
|
-
const client = new client$1.Client({
|
|
158
|
-
auth: NOTION_API_SECRET,
|
|
159
|
-
});
|
|
160
|
-
const numberOfRetry = 2;
|
|
161
|
-
async function ListPages() {
|
|
162
|
-
const respDatabase = (await client.databases.retrieve({
|
|
163
|
-
database_id: NOBLOG_DATABASE_ID,
|
|
164
|
-
}));
|
|
165
|
-
const reqDataSources = respDatabase.data_sources.map((source) => ({
|
|
166
|
-
data_source_id: source.id,
|
|
167
|
-
filter: {
|
|
168
|
-
and: [
|
|
169
|
-
{
|
|
170
|
-
property: "publish",
|
|
171
|
-
checkbox: { equals: true },
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
},
|
|
175
|
-
sorts: [
|
|
176
|
-
{
|
|
177
|
-
property: "date",
|
|
178
|
-
direction: "descending",
|
|
179
|
-
},
|
|
180
|
-
],
|
|
181
|
-
page_size: 100,
|
|
182
|
-
}));
|
|
183
|
-
let results = [];
|
|
184
|
-
for (const req of reqDataSources) {
|
|
185
|
-
let params = req;
|
|
186
|
-
while (true) {
|
|
187
|
-
const resp = await retry(async (bail) => {
|
|
188
|
-
try {
|
|
189
|
-
return client.dataSources.query(params);
|
|
190
|
-
}
|
|
191
|
-
catch (error) {
|
|
192
|
-
if (client$1.isNotionClientError(error)) {
|
|
193
|
-
bail(error);
|
|
194
|
-
}
|
|
195
|
-
throw error;
|
|
196
|
-
}
|
|
197
|
-
}, { retries: numberOfRetry });
|
|
198
|
-
results = results.concat(resp.results);
|
|
199
|
-
if (!resp.has_more) {
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
params.start_cursor = resp.next_cursor;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return results;
|
|
206
|
-
}
|
|
207
|
-
async function GetPage(page_id) {
|
|
208
|
-
const result = await retry(async (bail) => {
|
|
209
|
-
try {
|
|
210
|
-
return (await client.pages.retrieve({
|
|
211
|
-
page_id: page_id,
|
|
212
|
-
}));
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
if (client$1.isNotionClientError(error)) {
|
|
216
|
-
bail(error);
|
|
217
|
-
}
|
|
218
|
-
throw error;
|
|
219
|
-
}
|
|
220
|
-
}, { retries: numberOfRetry });
|
|
221
|
-
return result;
|
|
222
|
-
}
|
|
223
|
-
async function GetBlockChildren(block_id, totalPage = 100) {
|
|
224
|
-
const results = [];
|
|
225
|
-
let pageCount = 0;
|
|
226
|
-
let start_cursor = undefined;
|
|
227
|
-
do {
|
|
228
|
-
const response = (await client.blocks.children.list({
|
|
229
|
-
start_cursor: start_cursor,
|
|
230
|
-
block_id: block_id,
|
|
231
|
-
}));
|
|
232
|
-
results.push(...response.results);
|
|
233
|
-
start_cursor = response?.next_cursor;
|
|
234
|
-
pageCount += 1;
|
|
235
|
-
} while (start_cursor != null &&
|
|
236
|
-
(totalPage == null || pageCount < totalPage));
|
|
237
|
-
ModifyNumberedListObject(results);
|
|
238
|
-
return results;
|
|
239
|
-
}
|
|
240
|
-
function ModifyNumberedListObject(blocks) {
|
|
241
|
-
let numberedListIndex = 0;
|
|
242
|
-
for (const block of blocks) {
|
|
243
|
-
if ("type" in block && block.type === "numbered_list_item") {
|
|
244
|
-
// add numbers
|
|
245
|
-
// @ts-ignore
|
|
246
|
-
block.numbered_list_item.number = ++numberedListIndex;
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
numberedListIndex = 0;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const BLOCK_TO_DO = "to_do";
|
|
255
|
-
const BLOCK_TOGGLE = "toggle";
|
|
256
|
-
const BLOCK_CALLOUT = "callout";
|
|
257
|
-
const BLOCK_CHILD_PAGE = "child_page";
|
|
258
|
-
const BLOCK_UNSUPPORTED = "supported";
|
|
259
|
-
const BLOCK_SYNCED_BLOCK = "synced_block";
|
|
260
|
-
const BLOCK_NUMBERED_LIST_ITEM = "numbered_list_item";
|
|
261
|
-
const BLOCK_BULLETED_LIST_ITEM = "bulleted_list_item";
|
|
262
|
-
const BLOCK_IMAGE = "image";
|
|
263
|
-
const BLOCK_DIVIDER = "divider";
|
|
264
|
-
const BLOCK_EQUATION = "equation";
|
|
265
|
-
const BLOCK_PDF = "pdf";
|
|
266
|
-
const BLOCK_FILE = "file";
|
|
267
|
-
const BLOCK_VIDEO = "video";
|
|
268
|
-
const BLOCK_EMBED = "embed";
|
|
269
|
-
const BLOCK_BOOKMARK = "bookmark";
|
|
270
|
-
const BLOCK_LINK_PREVIEW = "link_preview";
|
|
271
|
-
const BLOCK_LINK_TO_PAGE = "link_to_page";
|
|
272
|
-
const BLOCK_CHILD_DATABASE = "child_database";
|
|
273
|
-
const BLOCK_TABLE = "table";
|
|
274
|
-
const BLOCK_CODE = "code";
|
|
275
|
-
const BLOCK_HEADING_1 = "heading_1";
|
|
276
|
-
const BLOCK_HEADING_2 = "heading_2";
|
|
277
|
-
const BLOCK_HEADING_3 = "heading_3";
|
|
278
|
-
const BLOCK_QUOTE = "quote";
|
|
279
|
-
const BLOCK_PARAGRAPH = "paragraph";
|
|
280
|
-
const LINEWRAP_NULL = "";
|
|
281
|
-
const LINEWRAP_NEWLINE = "\n";
|
|
282
|
-
|
|
283
|
-
async function SaveJelly(fname, dir, jelly, dry_run = false) {
|
|
284
|
-
if (jelly === undefined)
|
|
285
|
-
return `failed: ${fname} has empty jelly: `;
|
|
286
|
-
try {
|
|
287
|
-
if (dry_run) {
|
|
288
|
-
console.log(jelly.content);
|
|
289
|
-
return `success: ${fname} saved to ${dir}`;
|
|
290
|
-
}
|
|
291
|
-
await fs__namespace.mkdir(dir, { recursive: true });
|
|
292
|
-
const filePath = path__namespace.join(dir, fname);
|
|
293
|
-
await fs__namespace.writeFile(filePath, jelly.content, "utf-8");
|
|
294
|
-
return `success: ${fname} saved to ${filePath}`;
|
|
295
|
-
}
|
|
296
|
-
catch (error) {
|
|
297
|
-
if (error instanceof Error) {
|
|
298
|
-
return `failed: ${fname} - ${error.message}`;
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
return "failed: an unknown error occurred";
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
class Noblog {
|
|
306
|
-
Posts = [];
|
|
307
|
-
CurrPage = "";
|
|
308
|
-
SavePath = "./src/pages/posts/";
|
|
309
|
-
ChildPath = "nob_children/";
|
|
310
|
-
LayoutPath = "../../layouts/MarkdownPostLayout.astro";
|
|
311
|
-
MdCollection = {};
|
|
312
|
-
CustomTransformers = {};
|
|
313
|
-
constructor(posts, save_path, child_path, layout_path) {
|
|
314
|
-
this.Posts = posts;
|
|
315
|
-
if (child_path != undefined) {
|
|
316
|
-
this.ChildPath = child_path;
|
|
317
|
-
}
|
|
318
|
-
if (save_path != undefined) {
|
|
319
|
-
this.SavePath = save_path;
|
|
320
|
-
}
|
|
321
|
-
if (layout_path != undefined) {
|
|
322
|
-
this.LayoutPath = layout_path;
|
|
323
|
-
}
|
|
324
|
-
this.CustomTransformers[BLOCK_CHILD_PAGE] = async (block) => {
|
|
325
|
-
const page = block;
|
|
326
|
-
if (!page?.id) {
|
|
327
|
-
return false;
|
|
328
|
-
}
|
|
329
|
-
// if (curr_page.id in this.Post) and (page.id in this.Post) ||
|
|
330
|
-
// (curr_page.id not in this.Post) and (page.id not in this.Post)
|
|
331
|
-
// * path should be "../pageid"
|
|
332
|
-
// if (curr_page.id in this.Post) and (page.id not in this.Post)
|
|
333
|
-
// * path should be "../save_path/pageid"
|
|
334
|
-
// if (curr_page.id not in this.Post) and (page.id in this.Post)
|
|
335
|
-
// * path should be "../../pageid"
|
|
336
|
-
let sub_path;
|
|
337
|
-
const parent_surface = this.Posts.filter((post) => post.id === this.CurrPage).length > 0;
|
|
338
|
-
const child_surface = this.Posts.filter((post) => post.id === page.id).length > 0;
|
|
339
|
-
if (parent_surface === child_surface) {
|
|
340
|
-
sub_path = "";
|
|
341
|
-
}
|
|
342
|
-
else if (parent_surface) {
|
|
343
|
-
sub_path = this.ChildPath;
|
|
344
|
-
}
|
|
345
|
-
else {
|
|
346
|
-
sub_path = "..";
|
|
347
|
-
}
|
|
348
|
-
const full_path = path__namespace.join("../", sub_path, page.id);
|
|
349
|
-
return `(」゚ロ゚)」 [${page.child_page.title}](${full_path})`;
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
// Collect converts all pages in database to markdown files
|
|
353
|
-
async Collect(recursive = true) {
|
|
354
|
-
const save_dir = this.SavePath;
|
|
355
|
-
const sub_dir = path__namespace.join(save_dir, this.ChildPath);
|
|
356
|
-
for (const page of this.Posts) {
|
|
357
|
-
await this.FromPageId(page.id, recursive);
|
|
358
|
-
}
|
|
359
|
-
try {
|
|
360
|
-
for (const page_id of Object.keys(this.MdCollection)) {
|
|
361
|
-
let fpath = sub_dir;
|
|
362
|
-
if (this.Posts.find((page) => page.id === page_id))
|
|
363
|
-
fpath = save_dir;
|
|
364
|
-
await SaveJelly(page_id + ".md", fpath, this.MdCollection[page_id]);
|
|
365
|
-
}
|
|
366
|
-
console.log(`success: finish dump all files to "${save_dir}"`);
|
|
367
|
-
}
|
|
368
|
-
catch (error) {
|
|
369
|
-
if (error instanceof Error) {
|
|
370
|
-
console.log(`failed: consider run verbose with v=true - ${error.message}`);
|
|
371
|
-
}
|
|
372
|
-
else {
|
|
373
|
-
console.log("failed: an unknown error occurred");
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
// RenderJelly converts blocks fetched from notion api to
|
|
378
|
-
// rendered chunk (which is called jelly). Content in jelly
|
|
379
|
-
// will be collected to form the final markdown. If recursive
|
|
380
|
-
// is true, it will also fetch child pages exists in the given
|
|
381
|
-
// blocks.
|
|
382
|
-
async RenderJelly(blocks, recursive) {
|
|
383
|
-
const jelly = { content: "", children: [] };
|
|
384
|
-
for (const block of blocks) {
|
|
385
|
-
const subjelly = await this.RenderJelly(block.children, recursive);
|
|
386
|
-
let line_wrap = LINEWRAP_NULL;
|
|
387
|
-
if (block.type !== BLOCK_TO_DO &&
|
|
388
|
-
block.type !== BLOCK_BULLETED_LIST_ITEM &&
|
|
389
|
-
block.type !== BLOCK_NUMBERED_LIST_ITEM) {
|
|
390
|
-
line_wrap = LINEWRAP_NEWLINE;
|
|
391
|
-
}
|
|
392
|
-
switch (block.type) {
|
|
393
|
-
case BLOCK_TOGGLE:
|
|
394
|
-
jelly.content += toggle(block.parent, subjelly.content);
|
|
395
|
-
jelly.children = [...jelly.children, ...subjelly.children];
|
|
396
|
-
continue;
|
|
397
|
-
default:
|
|
398
|
-
jelly.content +=
|
|
399
|
-
line_wrap + `${addTabSpace(block.parent, 0)}\n` + line_wrap;
|
|
400
|
-
}
|
|
401
|
-
if (block.type === BLOCK_CHILD_PAGE) {
|
|
402
|
-
jelly.children = [...jelly.children, block.blockId];
|
|
403
|
-
if (recursive)
|
|
404
|
-
await this.FromPageId(block.blockId, recursive);
|
|
405
|
-
}
|
|
406
|
-
else {
|
|
407
|
-
jelly.content += subjelly.content;
|
|
408
|
-
jelly.children = [...jelly.children, ...subjelly.children];
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
return jelly;
|
|
412
|
-
}
|
|
413
|
-
// FromPageid converts a page id to rendered chunk (which is
|
|
414
|
-
// called jelly). Content in jelly will be collected to form
|
|
415
|
-
// the final markdown. If recursive is true, it will also
|
|
416
|
-
// fetch child pages exists in the given page.
|
|
417
|
-
async FromPageId(page_id, recursive = true) {
|
|
418
|
-
// preserve the curr page info
|
|
419
|
-
const prev_page = this.CurrPage;
|
|
420
|
-
this.CurrPage = page_id;
|
|
421
|
-
if (this.MdCollection.hasOwnProperty(page_id)) {
|
|
422
|
-
return this.MdCollection[page_id];
|
|
423
|
-
}
|
|
424
|
-
const blocks = await this.ConvPage(page_id);
|
|
425
|
-
const jelly = await this.RenderJelly(blocks, recursive);
|
|
426
|
-
const astro_meta = await this.AssembleAstroFrontmatter(await GetPage(page_id));
|
|
427
|
-
jelly.content = astro_meta + jelly.content;
|
|
428
|
-
this.MdCollection[page_id] = jelly;
|
|
429
|
-
// restore the prev page info
|
|
430
|
-
this.CurrPage = prev_page;
|
|
431
|
-
return jelly;
|
|
432
|
-
}
|
|
433
|
-
async ConvPage(id) {
|
|
434
|
-
if (!client) {
|
|
435
|
-
throw new Error("notion client is not provided");
|
|
436
|
-
}
|
|
437
|
-
const blocks = await GetBlockChildren(id);
|
|
438
|
-
const parsedData = await this.ConvBlocks(blocks);
|
|
439
|
-
return parsedData;
|
|
440
|
-
}
|
|
441
|
-
async ConvBlocks(blocks, mdBlocks = []) {
|
|
442
|
-
if (!client) {
|
|
443
|
-
throw new Error("notion client is not provided");
|
|
444
|
-
}
|
|
445
|
-
if (!blocks)
|
|
446
|
-
return mdBlocks;
|
|
447
|
-
for (const block of blocks) {
|
|
448
|
-
// @ts-ignore
|
|
449
|
-
if (block.type === BLOCK_UNSUPPORTED) {
|
|
450
|
-
continue;
|
|
451
|
-
}
|
|
452
|
-
if (!("has_children" in block) || !block.has_children) {
|
|
453
|
-
mdBlocks.push({
|
|
454
|
-
// @ts-ignore
|
|
455
|
-
type: block.type,
|
|
456
|
-
blockId: block.id,
|
|
457
|
-
children: [],
|
|
458
|
-
parent: await this.RenderBlock(block),
|
|
459
|
-
});
|
|
460
|
-
continue;
|
|
461
|
-
}
|
|
462
|
-
const block_id = block.type == BLOCK_SYNCED_BLOCK &&
|
|
463
|
-
block.synced_block?.synced_from?.block_id
|
|
464
|
-
? block.synced_block.synced_from.block_id
|
|
465
|
-
: block.id;
|
|
466
|
-
// Get children of this block.
|
|
467
|
-
const child_blocks = await GetBlockChildren(block_id);
|
|
468
|
-
// Push this block to mdBlocks.
|
|
469
|
-
mdBlocks.push({
|
|
470
|
-
type: block.type,
|
|
471
|
-
blockId: block.id,
|
|
472
|
-
parent: await this.RenderBlock(block),
|
|
473
|
-
children: [],
|
|
474
|
-
});
|
|
475
|
-
if (block.type === BLOCK_CALLOUT) {
|
|
476
|
-
continue;
|
|
477
|
-
}
|
|
478
|
-
if (!(block.type in this.CustomTransformers)) {
|
|
479
|
-
continue;
|
|
480
|
-
}
|
|
481
|
-
// Recursively call BlocksToMarkdown to collect children. check for custom transformer before parsing child
|
|
482
|
-
if (mdBlocks !== undefined) {
|
|
483
|
-
await this.ConvBlocks(child_blocks, mdBlocks[mdBlocks.length - 1]?.children);
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
return mdBlocks;
|
|
487
|
-
}
|
|
488
|
-
async RenderBlock(block) {
|
|
489
|
-
if (typeof block !== "object" || !("type" in block))
|
|
490
|
-
return "";
|
|
491
|
-
let renderedData = "";
|
|
492
|
-
const { type } = block;
|
|
493
|
-
if (type in this.CustomTransformers && !!this.CustomTransformers[type]) {
|
|
494
|
-
const transformer = this.CustomTransformers[type];
|
|
495
|
-
const customTransformerValue = await transformer(block);
|
|
496
|
-
if (typeof customTransformerValue === "string")
|
|
497
|
-
return customTransformerValue;
|
|
498
|
-
}
|
|
499
|
-
switch (type) {
|
|
500
|
-
case BLOCK_IMAGE:
|
|
501
|
-
const blockContent = block.image;
|
|
502
|
-
let image_title = "image";
|
|
503
|
-
const image_caption_plain = blockContent.caption
|
|
504
|
-
.map((item) => item.plain_text)
|
|
505
|
-
.join("");
|
|
506
|
-
let link$1 = "";
|
|
507
|
-
const image_type = blockContent.type;
|
|
508
|
-
if (image_type === "external") {
|
|
509
|
-
link$1 = blockContent.external.url;
|
|
510
|
-
}
|
|
511
|
-
if (image_type === "file") {
|
|
512
|
-
link$1 = blockContent.file.url;
|
|
513
|
-
}
|
|
514
|
-
// image caption with high priority
|
|
515
|
-
if (image_caption_plain.trim().length > 0) {
|
|
516
|
-
image_title = image_caption_plain;
|
|
517
|
-
}
|
|
518
|
-
else if (image_type === "file" || image_type === "external") {
|
|
519
|
-
const matches = link$1.match(/[^\/\\&\?]+\.\w{3,4}(?=([\?&].*$|$))/);
|
|
520
|
-
image_title = matches ? matches[0] : image_title;
|
|
521
|
-
}
|
|
522
|
-
return await image(image_title, link$1, false);
|
|
523
|
-
case BLOCK_DIVIDER:
|
|
524
|
-
return divider();
|
|
525
|
-
case BLOCK_EQUATION:
|
|
526
|
-
return equation(block.equation.expression);
|
|
527
|
-
case BLOCK_PDF:
|
|
528
|
-
case BLOCK_FILE:
|
|
529
|
-
case BLOCK_VIDEO:
|
|
530
|
-
{
|
|
531
|
-
let blockContent;
|
|
532
|
-
let title = type;
|
|
533
|
-
if (type === BLOCK_PDF)
|
|
534
|
-
blockContent = block.pdf;
|
|
535
|
-
if (type === BLOCK_FILE)
|
|
536
|
-
blockContent = block.file;
|
|
537
|
-
if (type === BLOCK_VIDEO)
|
|
538
|
-
blockContent = block.video;
|
|
539
|
-
const caption = blockContent?.caption
|
|
540
|
-
.map((item) => item.plain_text)
|
|
541
|
-
.join("");
|
|
542
|
-
if (blockContent) {
|
|
543
|
-
const file_type = blockContent.type;
|
|
544
|
-
let link$1 = "";
|
|
545
|
-
if (file_type === "file")
|
|
546
|
-
link$1 = blockContent.file.url;
|
|
547
|
-
if (file_type === "external")
|
|
548
|
-
link$1 = blockContent.external.url;
|
|
549
|
-
if (caption && caption.trim().length > 0) {
|
|
550
|
-
title = caption;
|
|
551
|
-
}
|
|
552
|
-
else if (link$1) {
|
|
553
|
-
const matches = link$1.match(/[^\/\\&\?]+\.\w{3,4}(?=([\?&].*$|$))/);
|
|
554
|
-
title = matches ? matches[0] : type;
|
|
555
|
-
}
|
|
556
|
-
return link(title, link$1);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
break;
|
|
560
|
-
case BLOCK_EMBED:
|
|
561
|
-
case BLOCK_BOOKMARK:
|
|
562
|
-
case BLOCK_LINK_PREVIEW:
|
|
563
|
-
case BLOCK_LINK_TO_PAGE:
|
|
564
|
-
{
|
|
565
|
-
let blockContent;
|
|
566
|
-
const title = type;
|
|
567
|
-
if (type === BLOCK_EMBED)
|
|
568
|
-
blockContent = block.embed;
|
|
569
|
-
if (type === BLOCK_BOOKMARK)
|
|
570
|
-
blockContent = block.bookmark;
|
|
571
|
-
if (type === BLOCK_LINK_PREVIEW)
|
|
572
|
-
blockContent = block.link_preview;
|
|
573
|
-
if (type === BLOCK_LINK_TO_PAGE &&
|
|
574
|
-
block.link_to_page.type === "page_id") {
|
|
575
|
-
blockContent = {
|
|
576
|
-
url: `https://www.notion.so/${block.link_to_page.page_id}`,
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
if (blockContent)
|
|
580
|
-
return link(title, blockContent.url);
|
|
581
|
-
}
|
|
582
|
-
break;
|
|
583
|
-
case BLOCK_CHILD_PAGE: {
|
|
584
|
-
const pageTitle = block.child_page.title;
|
|
585
|
-
return heading2(pageTitle);
|
|
586
|
-
}
|
|
587
|
-
case BLOCK_CHILD_DATABASE: {
|
|
588
|
-
const pageTitle = block.child_database.title || `child_database`;
|
|
589
|
-
return heading2(pageTitle);
|
|
590
|
-
}
|
|
591
|
-
case BLOCK_TABLE: {
|
|
592
|
-
const { id, has_children } = block;
|
|
593
|
-
const tableArr = [];
|
|
594
|
-
if (has_children) {
|
|
595
|
-
const tableRows = await GetBlockChildren(id);
|
|
596
|
-
const rowsPromise = tableRows?.map(async (row) => {
|
|
597
|
-
const { type } = row;
|
|
598
|
-
const cells = row[type]["cells"];
|
|
599
|
-
/**
|
|
600
|
-
* this is more like a hack since matching the type text was
|
|
601
|
-
* difficult. So converting each cell to paragraph type to
|
|
602
|
-
* reuse the BlockToMarkdown function
|
|
603
|
-
*/
|
|
604
|
-
const cellStringPromise = cells.map(async (cell) => await this.RenderBlock({
|
|
605
|
-
type: BLOCK_PARAGRAPH,
|
|
606
|
-
paragraph: { rich_text: cell },
|
|
607
|
-
}));
|
|
608
|
-
const cellStringArr = await Promise.all(cellStringPromise);
|
|
609
|
-
tableArr.push(cellStringArr);
|
|
610
|
-
});
|
|
611
|
-
await Promise.all(rowsPromise || []);
|
|
612
|
-
}
|
|
613
|
-
return table(tableArr);
|
|
614
|
-
}
|
|
615
|
-
// Rest of the types:
|
|
616
|
-
// "paragraph" "heading_1" "heading_2" "heading_3"
|
|
617
|
-
// "bulleted_list_item" "numbered_list_item"
|
|
618
|
-
// "quote" "to_do" "template" "synced_block"
|
|
619
|
-
// "child_page" "child_database" "code" "callout" "breadcrumb"
|
|
620
|
-
// "table_of_contents" "link_to_page" "audio" "unsupported"
|
|
621
|
-
default: {
|
|
622
|
-
// @ts-ignore
|
|
623
|
-
const blockContent = block[type].text || block[type].rich_text || [];
|
|
624
|
-
const bucket = [];
|
|
625
|
-
const code_range = [];
|
|
626
|
-
const bold_range = [];
|
|
627
|
-
const italic_range = [];
|
|
628
|
-
const underline_range = [];
|
|
629
|
-
const strikethrough_range = [];
|
|
630
|
-
const push_or_merge = (arr, idx) => {
|
|
631
|
-
if (arr.length == 0) {
|
|
632
|
-
return;
|
|
633
|
-
}
|
|
634
|
-
// @ts-ignore
|
|
635
|
-
if (arr[arr.length - 1][1] === idx) {
|
|
636
|
-
// @ts-ignore
|
|
637
|
-
arr[arr.length - 1][1] += 1;
|
|
638
|
-
}
|
|
639
|
-
else {
|
|
640
|
-
arr.push([idx, idx + 1]);
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
for (let i = 0; i < blockContent.length; i++) {
|
|
644
|
-
const content = blockContent[i];
|
|
645
|
-
if (content.type === "equation") {
|
|
646
|
-
bucket.push(inlineEquation(content.equation.expression));
|
|
647
|
-
continue;
|
|
648
|
-
}
|
|
649
|
-
let plain_text = content.plain_text;
|
|
650
|
-
if (content["href"])
|
|
651
|
-
plain_text = link(plain_text, content["href"]);
|
|
652
|
-
bucket.push(plain_text);
|
|
653
|
-
const annotations = content.annotations;
|
|
654
|
-
if (annotations.code)
|
|
655
|
-
push_or_merge(code_range, i);
|
|
656
|
-
if (annotations.bold)
|
|
657
|
-
push_or_merge(bold_range, i);
|
|
658
|
-
if (annotations.italic)
|
|
659
|
-
push_or_merge(italic_range, i);
|
|
660
|
-
if (annotations.underline)
|
|
661
|
-
push_or_merge(underline_range, i);
|
|
662
|
-
if (annotations.strikethrough)
|
|
663
|
-
push_or_merge(strikethrough_range, i);
|
|
664
|
-
}
|
|
665
|
-
const annoed_bucket = [];
|
|
666
|
-
for (const range of code_range)
|
|
667
|
-
annoed_bucket.push({ range: range, type: "code" });
|
|
668
|
-
for (const range of bold_range)
|
|
669
|
-
annoed_bucket.push({ range: range, type: "bold" });
|
|
670
|
-
for (const range of italic_range)
|
|
671
|
-
annoed_bucket.push({ range: range, type: "italic" });
|
|
672
|
-
for (const range of underline_range)
|
|
673
|
-
annoed_bucket.push({ range: range, type: "underline" });
|
|
674
|
-
for (const range of strikethrough_range)
|
|
675
|
-
annoed_bucket.push({ range: range, type: "strikethrough" });
|
|
676
|
-
annoed_bucket.sort(
|
|
677
|
-
// @ts-ignore
|
|
678
|
-
(a, b) => a.range[1] - a.range[0] - (b.range[1] - b.range[0]));
|
|
679
|
-
for (const annoed of annoed_bucket) {
|
|
680
|
-
const type = annoed.type;
|
|
681
|
-
const [from, to] = annoed.range;
|
|
682
|
-
let panno, sanno = GetPrefixSuffix(type);
|
|
683
|
-
// @ts-ignore
|
|
684
|
-
bucket[from] = panno + bucket[from];
|
|
685
|
-
// @ts-ignore
|
|
686
|
-
bucket[to - 1] = bucket[to - 1] + sanno;
|
|
687
|
-
}
|
|
688
|
-
bucket.forEach((x) => (renderedData += x));
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
switch (type) {
|
|
692
|
-
case BLOCK_CODE:
|
|
693
|
-
renderedData = codeBlock(renderedData, block[type].language);
|
|
694
|
-
break;
|
|
695
|
-
case BLOCK_HEADING_1:
|
|
696
|
-
renderedData = heading1(renderedData);
|
|
697
|
-
break;
|
|
698
|
-
case BLOCK_HEADING_2:
|
|
699
|
-
renderedData = heading2(renderedData);
|
|
700
|
-
break;
|
|
701
|
-
case BLOCK_HEADING_3:
|
|
702
|
-
renderedData = heading3(renderedData);
|
|
703
|
-
break;
|
|
704
|
-
case BLOCK_QUOTE:
|
|
705
|
-
renderedData = quote(renderedData);
|
|
706
|
-
break;
|
|
707
|
-
case BLOCK_TO_DO:
|
|
708
|
-
renderedData = todo(renderedData, block.to_do.checked);
|
|
709
|
-
break;
|
|
710
|
-
case BLOCK_CALLOUT:
|
|
711
|
-
if (!block.has_children) {
|
|
712
|
-
return callout(renderedData, block.callout.icon);
|
|
713
|
-
}
|
|
714
|
-
const callout_children = await this.ConvBlocks(await GetBlockChildren(block.id));
|
|
715
|
-
const callout_string = `${renderedData}\n` +
|
|
716
|
-
(await this.RenderJelly(callout_children, true)).content;
|
|
717
|
-
console.log(callout_string);
|
|
718
|
-
renderedData = callout(callout_string.trim(), block.callout.icon);
|
|
719
|
-
break;
|
|
720
|
-
case BLOCK_BULLETED_LIST_ITEM:
|
|
721
|
-
if (!block.has_children) {
|
|
722
|
-
return bullet(renderedData);
|
|
723
|
-
}
|
|
724
|
-
const bullet_children = await this.ConvBlocks(await GetBlockChildren(block.id));
|
|
725
|
-
const bullet_string = `${renderedData}\n` +
|
|
726
|
-
(await this.RenderJelly(bullet_children, true)).content;
|
|
727
|
-
renderedData = bullet(bullet_string);
|
|
728
|
-
break;
|
|
729
|
-
case BLOCK_NUMBERED_LIST_ITEM:
|
|
730
|
-
if (!block.has_children) {
|
|
731
|
-
return bullet(renderedData, block.numbered_list_item.number);
|
|
732
|
-
}
|
|
733
|
-
const numbered_children = await this.ConvBlocks(await GetBlockChildren(block.id));
|
|
734
|
-
const numbered_string = `${renderedData}\n` +
|
|
735
|
-
(await this.RenderJelly(numbered_children, true)).content;
|
|
736
|
-
renderedData = bullet(numbered_string, block.numbered_list_item.number);
|
|
737
|
-
break;
|
|
738
|
-
}
|
|
739
|
-
return renderedData;
|
|
740
|
-
}
|
|
741
|
-
async AssembleAstroFrontmatter(page) {
|
|
742
|
-
let frontmatter = "";
|
|
743
|
-
// Default layout
|
|
744
|
-
const ischild = this.Posts.filter((post) => post.id === page.id).length > 0 ? "" : "../";
|
|
745
|
-
frontmatter += "layout: " + ischild + this.LayoutPath + "\n";
|
|
746
|
-
let title = "";
|
|
747
|
-
let description = "";
|
|
748
|
-
let tags = [];
|
|
749
|
-
let pubDate = "";
|
|
750
|
-
let archived = "";
|
|
751
|
-
Object.entries(page.properties).forEach(([key, property]) => {
|
|
752
|
-
switch (property.type) {
|
|
753
|
-
case "title": // Get title
|
|
754
|
-
title = property.title
|
|
755
|
-
?.map((title) => title.plain_text)
|
|
756
|
-
.reduce((a, b) => a + b, "");
|
|
757
|
-
break;
|
|
758
|
-
case "multi_select": // Get tags
|
|
759
|
-
tags = property.multi_select?.map((tag) => tag.name);
|
|
760
|
-
break;
|
|
761
|
-
case "date": // Get date
|
|
762
|
-
pubDate =
|
|
763
|
-
property.date?.start ?? new Date().toISOString().split("T")[0];
|
|
764
|
-
break;
|
|
765
|
-
default: // Customized properties from the template given in the Github repo
|
|
766
|
-
switch (key) {
|
|
767
|
-
case "archived": // Get archived
|
|
768
|
-
archived =
|
|
769
|
-
property.type === "checkbox" && property.checkbox
|
|
770
|
-
? "true"
|
|
771
|
-
: "false";
|
|
772
|
-
break;
|
|
773
|
-
case "description": // Get description
|
|
774
|
-
description =
|
|
775
|
-
property.type === "rich_text"
|
|
776
|
-
? property.rich_text
|
|
777
|
-
?.map((text) => text.plain_text)
|
|
778
|
-
.reduce((a, b) => a + b, "")
|
|
779
|
-
: "";
|
|
780
|
-
break;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
});
|
|
784
|
-
frontmatter += "title: " + JSON.stringify(title) + "\n";
|
|
785
|
-
frontmatter += "description: " + JSON.stringify(description) + "\n";
|
|
786
|
-
frontmatter += "tags: " + JSON.stringify(tags) + "\n";
|
|
787
|
-
frontmatter += "pubDate: " + JSON.stringify(pubDate) + "\n";
|
|
788
|
-
frontmatter += "archived: " + JSON.stringify(archived) + "\n";
|
|
789
|
-
return "---\n" + frontmatter + "---\n";
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
function getVersion() {
|
|
794
|
-
try {
|
|
795
|
-
const __filename = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('generate.cjs', document.baseURI).href)));
|
|
796
|
-
const __dirname = path.dirname(__filename);
|
|
797
|
-
const packagePath = path.join(__dirname, "../../package.json");
|
|
798
|
-
const packageJson = JSON.parse(fs$1.readFileSync(packagePath, "utf-8"));
|
|
799
|
-
return packageJson.version;
|
|
800
|
-
}
|
|
801
|
-
catch {
|
|
802
|
-
return "unknown";
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
function help() {
|
|
806
|
-
console.log(`
|
|
807
|
-
noblog - Generate static blog content from Notion.so
|
|
808
|
-
|
|
809
|
-
Usage: noblog [command] [options] [SAVE_PATH] [SUB_PATH]
|
|
810
|
-
|
|
811
|
-
Options:
|
|
812
|
-
-v, --verbose Print more messages for debugging
|
|
813
|
-
-h, --help Show help message
|
|
814
|
-
--version Show version information
|
|
815
|
-
--layout PATH Custom layout path (default: ../../layouts/MarkdownPostLayout.astro)
|
|
816
|
-
|
|
817
|
-
Commands:
|
|
818
|
-
help Show this help message
|
|
819
|
-
version Show version information
|
|
820
|
-
generate Generate blog content (default command)
|
|
821
|
-
|
|
822
|
-
Options:
|
|
823
|
-
-v, --verbose Print more messages for debugging
|
|
824
|
-
-h, --help Show help message
|
|
825
|
-
--version Show version information
|
|
826
|
-
|
|
827
|
-
Arguments:
|
|
828
|
-
SAVE_PATH Directory to save main posts (default: ./src/pages/posts/)
|
|
829
|
-
SUB_PATH Subdirectory for nested content (default: nob_children/)
|
|
830
|
-
|
|
831
|
-
Layout Options:
|
|
832
|
-
--layout PATH Custom layout path relative to save directory (default: ../../layouts/MarkdownPostLayout.astro)
|
|
833
|
-
|
|
834
|
-
Examples:
|
|
835
|
-
noblog help
|
|
836
|
-
noblog version
|
|
837
|
-
noblog generate
|
|
838
|
-
noblog -v
|
|
839
|
-
noblog src/pages/posts/ nob_children/
|
|
840
|
-
noblog --layout ../../layouts/BlogLayout.astro
|
|
841
|
-
noblog src/posts/ children/ --layout ../../../layouts/CustomLayout.astro -v
|
|
842
|
-
|
|
843
|
-
Environment Variables:
|
|
844
|
-
NOTION_API_SECRET Your Notion API secret
|
|
845
|
-
NOBLOG_DATABASE_ID Your Notion database ID
|
|
846
|
-
`);
|
|
847
|
-
}
|
|
848
|
-
function parseArgs(argv) {
|
|
849
|
-
const options = {
|
|
850
|
-
verbose: false,
|
|
851
|
-
help: false,
|
|
852
|
-
version: false,
|
|
853
|
-
savePath: "./src/pages/posts/",
|
|
854
|
-
subPath: "nob_children/",
|
|
855
|
-
layoutPath: "../../layouts/MarkdownPostLayout.astro",
|
|
856
|
-
};
|
|
857
|
-
const positionalArgs = [];
|
|
858
|
-
for (let i = 0; i < argv.length; i++) {
|
|
859
|
-
const arg = argv[i];
|
|
860
|
-
switch (arg) {
|
|
861
|
-
case "-v":
|
|
862
|
-
case "--verbose":
|
|
863
|
-
options.verbose = true;
|
|
864
|
-
break;
|
|
865
|
-
case "-h":
|
|
866
|
-
case "--help":
|
|
867
|
-
case "help":
|
|
868
|
-
options.help = true;
|
|
869
|
-
break;
|
|
870
|
-
case "--version":
|
|
871
|
-
case "version":
|
|
872
|
-
options.version = true;
|
|
873
|
-
break;
|
|
874
|
-
case "--layout":
|
|
875
|
-
if (i + 1 < argv.length && !argv[i + 1].startsWith("-")) {
|
|
876
|
-
options.layoutPath = argv[++i];
|
|
877
|
-
}
|
|
878
|
-
else {
|
|
879
|
-
console.error("Error: --layout requires a path argument");
|
|
880
|
-
help();
|
|
881
|
-
process.exit(1);
|
|
882
|
-
}
|
|
883
|
-
break;
|
|
884
|
-
case "generate":
|
|
885
|
-
// Explicit generate command, skip it
|
|
886
|
-
break;
|
|
887
|
-
default:
|
|
888
|
-
if (arg.startsWith("-")) {
|
|
889
|
-
console.error(`Unknown option: ${arg}`);
|
|
890
|
-
help();
|
|
891
|
-
process.exit(1);
|
|
892
|
-
}
|
|
893
|
-
positionalArgs.push(arg);
|
|
894
|
-
break;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
// Handle positional arguments
|
|
898
|
-
if (positionalArgs.length > 0) {
|
|
899
|
-
options.savePath = positionalArgs[0];
|
|
900
|
-
}
|
|
901
|
-
if (positionalArgs.length > 1) {
|
|
902
|
-
options.subPath = positionalArgs[1];
|
|
903
|
-
}
|
|
904
|
-
if (positionalArgs.length > 2) {
|
|
905
|
-
console.error("Error: Too many arguments.");
|
|
906
|
-
help();
|
|
907
|
-
process.exit(1);
|
|
908
|
-
}
|
|
909
|
-
return options;
|
|
910
|
-
}
|
|
911
|
-
async function generateBlog(options) {
|
|
912
|
-
try {
|
|
913
|
-
if (options.verbose) {
|
|
914
|
-
console.log("Fetching posts from Notion...");
|
|
915
|
-
}
|
|
916
|
-
const pages = await ListPages();
|
|
917
|
-
if (options.verbose) {
|
|
918
|
-
console.log(`Found ${pages.length} pages`);
|
|
919
|
-
console.log(`Save path: ${options.savePath}`);
|
|
920
|
-
console.log(`Sub path: ${options.subPath}`);
|
|
921
|
-
console.log(`Layout path: ${options.layoutPath}`);
|
|
922
|
-
}
|
|
923
|
-
const nob = new Noblog(pages, options.savePath, options.subPath, options.layoutPath);
|
|
924
|
-
await nob.Collect(true);
|
|
925
|
-
console.log(`✅ Successfully generated blog content`);
|
|
926
|
-
}
|
|
927
|
-
catch (error) {
|
|
928
|
-
console.error(`❌ Error generating blog content:`);
|
|
929
|
-
if (error instanceof Error) {
|
|
930
|
-
console.error(` ${error.message}`);
|
|
931
|
-
if (options.verbose) {
|
|
932
|
-
console.error(error.stack);
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
else {
|
|
936
|
-
console.error(` An unknown error occurred`);
|
|
937
|
-
}
|
|
938
|
-
process.exit(1);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
async function main() {
|
|
942
|
-
const argv = process.argv.slice(2);
|
|
943
|
-
if (argv.length === 0) {
|
|
944
|
-
// Default behavior: generate with default options
|
|
945
|
-
await generateBlog({
|
|
946
|
-
verbose: false,
|
|
947
|
-
help: false,
|
|
948
|
-
version: false,
|
|
949
|
-
savePath: "./src/pages/posts/",
|
|
950
|
-
subPath: "nob_children/",
|
|
951
|
-
layoutPath: "../../layouts/MarkdownPostLayout.astro",
|
|
952
|
-
});
|
|
953
|
-
return;
|
|
954
|
-
}
|
|
955
|
-
const options = parseArgs(argv);
|
|
956
|
-
if (options.help) {
|
|
957
|
-
help();
|
|
958
|
-
return;
|
|
959
|
-
}
|
|
960
|
-
if (options.version) {
|
|
961
|
-
console.log(`noblog v${getVersion()}`);
|
|
962
|
-
return;
|
|
963
|
-
}
|
|
964
|
-
await generateBlog(options);
|
|
965
|
-
}
|
|
966
|
-
main().catch((error) => {
|
|
967
|
-
console.error(`❌ Unexpected error:`, error);
|
|
968
|
-
process.exit(1);
|
|
969
|
-
});
|
|
970
|
-
//# sourceMappingURL=generate.cjs.map
|