gatsby-source-notion-churnotion 1.1.27 → 1.1.29
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/dist/api/getPages.js +229 -214
- package/dist/api/service/index.d.ts +1 -0
- package/dist/api/service/index.js +17 -0
- package/dist/api/service/notionService.d.ts +37 -0
- package/dist/api/service/notionService.js +105 -0
- package/dist/util/blocks/blockProcessor.d.ts +35 -0
- package/dist/util/blocks/blockProcessor.js +44 -0
- package/dist/util/blocks/blockProcessorRegistry.d.ts +10 -0
- package/dist/util/blocks/blockProcessorRegistry.js +40 -0
- package/dist/util/blocks/imageBlockProcessor.d.ts +6 -0
- package/dist/util/blocks/imageBlockProcessor.js +113 -0
- package/dist/util/blocks/index.d.ts +6 -0
- package/dist/util/blocks/index.js +22 -0
- package/dist/util/blocks/mediaBlockProcessor.d.ts +6 -0
- package/dist/util/blocks/mediaBlockProcessor.js +48 -0
- package/dist/util/blocks/structureBlockProcessor.d.ts +6 -0
- package/dist/util/blocks/structureBlockProcessor.js +81 -0
- package/dist/util/blocks/textBlockProcessor.d.ts +6 -0
- package/dist/util/blocks/textBlockProcessor.js +23 -0
- package/dist/util/fetchData.js +0 -6
- package/dist/util/processor.js +35 -149
- package/dist/util/timeLimit.d.ts +8 -0
- package/dist/util/timeLimit.js +25 -1
- package/package.json +2 -1
package/dist/util/processor.js
CHANGED
@@ -1,14 +1,8 @@
|
|
1
1
|
"use strict";
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
-
};
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
3
|
exports.processor = void 0;
|
7
|
-
const gatsby_source_filesystem_1 = require("gatsby-source-filesystem");
|
8
4
|
const metadataProcessor_1 = require("./metadataProcessor");
|
9
|
-
const
|
10
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
11
|
-
const path_1 = __importDefault(require("path"));
|
5
|
+
const blocks_1 = require("./blocks");
|
12
6
|
const processor = async (blocks, actions, getCache, createNodeId, reporter, cache) => {
|
13
7
|
const { thumbnail, tableOfContents, updatedBlocks, rawText } = await processBlocksForContent(blocks, actions, getCache, createNodeId, reporter, cache);
|
14
8
|
await (0, metadataProcessor_1.processMetadata)(blocks, actions, createNodeId, reporter, cache);
|
@@ -16,154 +10,46 @@ const processor = async (blocks, actions, getCache, createNodeId, reporter, cach
|
|
16
10
|
};
|
17
11
|
exports.processor = processor;
|
18
12
|
const processBlocksForContent = async (blocks, actions, getCache, createNodeId, reporter, cache) => {
|
13
|
+
const context = {
|
14
|
+
actions,
|
15
|
+
getCache,
|
16
|
+
createNodeId,
|
17
|
+
reporter,
|
18
|
+
cache,
|
19
|
+
};
|
20
|
+
// 블록 프로세서 레지스트리 생성
|
21
|
+
const processorRegistry = new blocks_1.BlockProcessorRegistry(context);
|
19
22
|
const tableOfContents = [];
|
20
23
|
let thumbnail = null;
|
21
24
|
let rawText = "";
|
22
25
|
const updatedBlocks = [];
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
if (isImageBlock(block)) {
|
47
|
-
const updatedBlock = await processImageBlock(block, actions, getCache, createNodeId, reporter, cache);
|
48
|
-
updatedBlocks[index] = updatedBlock || block;
|
26
|
+
// 첫 번째 이미지 블록을 찾아 썸네일로 사용
|
27
|
+
let firstImageIndex = blocks.findIndex((block) => block.type === "image");
|
28
|
+
// 블록 처리
|
29
|
+
const processResults = await Promise.all(blocks.map(async (block, index) => {
|
30
|
+
const result = await processorRegistry.processBlock(block);
|
31
|
+
// 썸네일 처리
|
32
|
+
if (index === firstImageIndex && result.thumbnail) {
|
33
|
+
thumbnail = result.thumbnail;
|
34
|
+
}
|
35
|
+
// 텍스트 데이터 추가
|
36
|
+
if (result.plainText) {
|
37
|
+
rawText += result.plainText + " ";
|
38
|
+
}
|
39
|
+
// 목차 데이터 추가
|
40
|
+
if (result.tableOfContents) {
|
41
|
+
tableOfContents.push(...result.tableOfContents);
|
42
|
+
}
|
43
|
+
return result;
|
44
|
+
}));
|
45
|
+
// 업데이트된 블록 적용
|
46
|
+
processResults.forEach((result, index) => {
|
47
|
+
if (result.updatedBlock) {
|
48
|
+
updatedBlocks[index] = result.updatedBlock;
|
49
49
|
}
|
50
50
|
else {
|
51
|
-
updatedBlocks[index] =
|
51
|
+
updatedBlocks[index] = blocks[index];
|
52
52
|
}
|
53
|
-
})
|
53
|
+
});
|
54
54
|
return { thumbnail, tableOfContents, updatedBlocks, rawText };
|
55
55
|
};
|
56
|
-
const isTextContentBlock = (block) => {
|
57
|
-
return [
|
58
|
-
"paragraph",
|
59
|
-
"heading_1",
|
60
|
-
"heading_2",
|
61
|
-
"heading_3",
|
62
|
-
"quote",
|
63
|
-
"bulleted_list_item",
|
64
|
-
"numbered_list_item",
|
65
|
-
"callout",
|
66
|
-
"code",
|
67
|
-
].includes(block.type);
|
68
|
-
};
|
69
|
-
const extractPlainText = (block) => {
|
70
|
-
if (isTextContentBlock(block)) {
|
71
|
-
const richTextArray = block[block.type]?.rich_text || [];
|
72
|
-
return richTextArray
|
73
|
-
.map((text) => block.type === "code" // code의 \n 제거
|
74
|
-
? text.plain_text.replace(/\\n/g, "")
|
75
|
-
: text.plain_text)
|
76
|
-
.join(" ");
|
77
|
-
}
|
78
|
-
return null;
|
79
|
-
};
|
80
|
-
const isImageBlock = (block) => {
|
81
|
-
return block.type === "image" && "image" in block;
|
82
|
-
};
|
83
|
-
const processImageBlock = async (block, actions, getCache, createNodeId, reporter, cache) => {
|
84
|
-
const { createNode } = actions;
|
85
|
-
if (block.type === "image" && "image" in block) {
|
86
|
-
const imageSourceType = block.image.type;
|
87
|
-
const imageUrl = imageSourceType === `external`
|
88
|
-
? block.image.external?.url
|
89
|
-
: block.image?.file?.url;
|
90
|
-
if (!imageUrl)
|
91
|
-
return null;
|
92
|
-
// GIF 파일 처리
|
93
|
-
if (imageUrl.endsWith(".gif")) {
|
94
|
-
const staticDir = path_1.default.join(process.cwd(), "static"); // Gatsby의 static 디렉토리
|
95
|
-
const gifFileName = path_1.default.basename(imageUrl); // 파일 이름 추출
|
96
|
-
const gifFilePath = path_1.default.join(staticDir, gifFileName);
|
97
|
-
// 이미 static 디렉토리에 파일이 있는지 확인
|
98
|
-
if (!fs_extra_1.default.existsSync(gifFilePath)) {
|
99
|
-
try {
|
100
|
-
reporter.info(`[GIF PROCESSING] Downloading GIF: ${imageUrl}`);
|
101
|
-
const response = await fetch(imageUrl);
|
102
|
-
if (!response.ok) {
|
103
|
-
throw new Error(`Failed to download GIF: ${response.statusText}`);
|
104
|
-
}
|
105
|
-
const arrayBuffer = await response.arrayBuffer();
|
106
|
-
const buffer = Buffer.from(arrayBuffer);
|
107
|
-
await fs_extra_1.default.ensureDir(staticDir); // static 디렉토리 생성
|
108
|
-
await fs_extra_1.default.writeFile(gifFilePath, buffer); // GIF 파일 저장
|
109
|
-
reporter.info(`[GIF SUCCESS] Saved GIF to static: ${gifFilePath}`);
|
110
|
-
}
|
111
|
-
catch (error) {
|
112
|
-
reporter.warn(`[GIF WARNING] Failed to process GIF: ${imageUrl}`);
|
113
|
-
return null;
|
114
|
-
}
|
115
|
-
}
|
116
|
-
else {
|
117
|
-
reporter.info(`[GIF CACHE HIT] GIF already exists: ${gifFilePath}`);
|
118
|
-
}
|
119
|
-
// GIF 파일을 정적 파일로 추가
|
120
|
-
const updatedBlock = {
|
121
|
-
...block,
|
122
|
-
image: {
|
123
|
-
fileId: gifFileName, // static 경로를 기준으로 참조
|
124
|
-
caption: block.image.caption,
|
125
|
-
},
|
126
|
-
};
|
127
|
-
return updatedBlock;
|
128
|
-
}
|
129
|
-
// GIF가 아닌 경우 기존 로직 유지
|
130
|
-
const cacheKey = `${imageUrl}-post-image`;
|
131
|
-
const cachedFileNodeId = await cache.get(cacheKey);
|
132
|
-
if (cachedFileNodeId) {
|
133
|
-
reporter.info(`[CACHE HIT] Image already processed: ${imageUrl}`);
|
134
|
-
const updatedBlock = {
|
135
|
-
...block,
|
136
|
-
image: {
|
137
|
-
fileId: cachedFileNodeId,
|
138
|
-
caption: block.image.caption,
|
139
|
-
},
|
140
|
-
};
|
141
|
-
return updatedBlock;
|
142
|
-
}
|
143
|
-
try {
|
144
|
-
const fileNode = await (0, gatsby_source_filesystem_1.createRemoteFileNode)({
|
145
|
-
url: imageUrl,
|
146
|
-
parentNodeId: block.id,
|
147
|
-
getCache,
|
148
|
-
createNode,
|
149
|
-
createNodeId,
|
150
|
-
});
|
151
|
-
if (fileNode) {
|
152
|
-
const updatedBlock = {
|
153
|
-
...block,
|
154
|
-
image: {
|
155
|
-
fileId: fileNode.id,
|
156
|
-
caption: block.image.caption,
|
157
|
-
},
|
158
|
-
};
|
159
|
-
reporter.info(`[SUCCESS] Image processed: ${fileNode.id}`);
|
160
|
-
await cache.set(cacheKey, fileNode.id);
|
161
|
-
return updatedBlock;
|
162
|
-
}
|
163
|
-
}
|
164
|
-
catch (error) {
|
165
|
-
reporter.warn(`[WARNING] Failed to download image: ${imageUrl}`);
|
166
|
-
}
|
167
|
-
}
|
168
|
-
return null;
|
169
|
-
};
|
package/dist/util/timeLimit.d.ts
CHANGED
@@ -3,3 +3,11 @@
|
|
3
3
|
* @param {number} ms - Milliseconds to sleep
|
4
4
|
*/
|
5
5
|
export declare const sleep: (ms: number) => Promise<unknown>;
|
6
|
+
/**
|
7
|
+
* Promise에 타임아웃을 적용하는 도우미 함수
|
8
|
+
* @param promise 제한할 Promise
|
9
|
+
* @param ms 시간 제한 (밀리초)
|
10
|
+
* @param errorMessage 타임아웃 오류 메시지
|
11
|
+
* @returns 원래 Promise 또는 타임아웃 오류가 발생한 Promise
|
12
|
+
*/
|
13
|
+
export declare const timeLimit: <T>(promise: Promise<T>, ms: number, errorMessage?: string) => Promise<T>;
|
package/dist/util/timeLimit.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.sleep = void 0;
|
3
|
+
exports.timeLimit = exports.sleep = void 0;
|
4
4
|
/**
|
5
5
|
* Sleep for a given number of milliseconds
|
6
6
|
* @param {number} ms - Milliseconds to sleep
|
@@ -9,3 +9,27 @@ const sleep = (ms) => {
|
|
9
9
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
10
10
|
};
|
11
11
|
exports.sleep = sleep;
|
12
|
+
/**
|
13
|
+
* Promise에 타임아웃을 적용하는 도우미 함수
|
14
|
+
* @param promise 제한할 Promise
|
15
|
+
* @param ms 시간 제한 (밀리초)
|
16
|
+
* @param errorMessage 타임아웃 오류 메시지
|
17
|
+
* @returns 원래 Promise 또는 타임아웃 오류가 발생한 Promise
|
18
|
+
*/
|
19
|
+
const timeLimit = (promise, ms, errorMessage = "Operation timed out") => {
|
20
|
+
return new Promise((resolve, reject) => {
|
21
|
+
const timeoutId = setTimeout(() => {
|
22
|
+
reject(new Error(errorMessage));
|
23
|
+
}, ms);
|
24
|
+
promise
|
25
|
+
.then((result) => {
|
26
|
+
clearTimeout(timeoutId);
|
27
|
+
resolve(result);
|
28
|
+
})
|
29
|
+
.catch((error) => {
|
30
|
+
clearTimeout(timeoutId);
|
31
|
+
reject(error);
|
32
|
+
});
|
33
|
+
});
|
34
|
+
};
|
35
|
+
exports.timeLimit = timeLimit;
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "gatsby-source-notion-churnotion",
|
3
3
|
"description": "Gatsby plugin that can connect with One Notion Database RECURSIVELY using official API",
|
4
|
-
"version": "1.1.
|
4
|
+
"version": "1.1.29",
|
5
5
|
"skipLibCheck": true,
|
6
6
|
"license": "0BSD",
|
7
7
|
"main": "./dist/gatsby-node.js",
|
@@ -51,6 +51,7 @@
|
|
51
51
|
"natural": "^8.0.1",
|
52
52
|
"notion-to-md": "^3.1.1",
|
53
53
|
"notion-types": "^7.1.5",
|
54
|
+
"p-limit": "^6.2.0",
|
54
55
|
"typescript": "^5.7.2"
|
55
56
|
},
|
56
57
|
"devDependencies": {
|