Skip to content

Commit ad8c8eb

Browse files
committed
feat: notion-to-utils formatNotionImageUrl add
1 parent d8f0805 commit ad8c8eb

File tree

4 files changed

+300
-4
lines changed

4 files changed

+300
-4
lines changed

apps/storybook/src/sample-data/notionBlocks.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@
6868
"caption": [],
6969
"type": "file",
7070
"file": {
71-
"url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/566f127b-9e73-491d-bee6-5afd075653a2/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466STLNN5SA%2F20250309%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250309T131205Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjECsaCXVzLXdlc3QtMiJGMEQCIG94TkWa3mK1%2B5nVswsMblZQyl7j7VaT%2BqotVsKeSggXAiAQYbbvAf2NGeiVYD52%2FaNMKZ4YTg1%2BWJpH3%2Bmpc9xspir%2FAwh0EAAaDDYzNzQyMzE4MzgwNSIM%2F1rPCZwhKhp3eLk6KtwDZy4%2B20E51YbCCaXojGLfYiQw9vPtTNXK6tdO8gaTMKtEi5Nywg04k%2B9Jek8QTwgn1IM420f%2Bd%2B7ZeQxkGCZgYidrz1sKcxbWajR2%2B%2BsfabgkHxJePiFy5I%2FOxbBXdvwVrt5jDSn7KwwK9e1qUM40iTf3aDS1TBiTHdYFqed%2BE7vUg0%2Ffy7Qxo1huc%2BV0l0zWCzkqIykzPOJlFayl55TLK7%2B%2FXjcUD6ofLoCFQSXa6LvNMDcfSWKWbVMC05tnE9yBGsgKh23njD6DcbvtBFZM3NL4N0%2FCvxY2KuegsVlCY4598rhoogs%2BK%2B9GhXaCqnylT3iC8aR3ce3PNpEdO%2FUUnv1H1KZiFZh9tYblBdGcRocUnItGTq%2BPQJy89ooWIYkO0cfkPZiOtkVkhvc8JFHDRMsafTi92RLimnHP9pS%2FobUcQ5sLaLse96pISiT%2BdBJCTLJ%2FkK%2BmLHAb4deSmonck3VFr28Gdg33O8k0hlrlVDKnRYyhW%2BBrTg4R7VJkd6S9wOLvCgCNwBiwpPNy3gKNwTdnegDxLca5VV7EzC%2BeUWvCwCUxztpwyssi8SKks98Nib20n37ZbGamMWHLVzBfUtIhUvbwNCTqnug1uZEoe85mAFVMNvKDbJFH9CYw0tq1vgY6pgG1EFVVrhMNjCsu4q1c8btf3gVyMiqDnyPKQVm%2BGFD9CMIGHOQzTnYYdek5JJDDlQHzf5YxMVmDj9xFwb70UvCTf0NETvihF8T8s04Aik2m5t0%2FpSeKZbsZFoPvv16QeSS5BI9gaJJp7%2F1wDciv2yWG02uAxgp0kTlBZzYwCmsbAoBJhzuqppOnQ7MNLPOhPYtJCye%2BOjzgHukv19fC4vyZQCMcOof6&X-Amz-Signature=16278af11d7907fbb4ac58410f358cfce25f65b020be49ddfca13828dc47c7e9&X-Amz-SignedHeaders=host&x-id=GetObject",
72-
"expiry_time": "2025-03-09T14:12:04.810Z"
71+
"url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/566f127b-9e73-491d-bee6-5afd075653a2/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB4667ZOXY2Y6%2F20250319%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250319T125545Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEBwaCXVzLXdlc3QtMiJIMEYCIQCo971xkAkpOezG800JUV1AJkAZ1%2BJ4GHc%2BXUmLgc%2B5PwIhAIfB6MFIuO9ESgtes%2Bvf%2Fehjzj%2BkvnaSGdAaBVY138ooKv8DCHUQABoMNjM3NDIzMTgzODA1Igwi4apJDc%2Bqo22dqecq3AP%2BDHeGuvT8rmtUsxYlp9NJ6tFdB1ACasA9X5yJmZihnP9hSw3j%2FZA%2Fr8Z5GQ%2FhfYNLtPooN2yczm5Wv%2F7uCSjB2Fj8HL9InG3FkjuSxnBbktd80L0LNbmriYZhEwkcLJ3MtZCxy0IyGzu%2Bxobsj9QVKaaP7Tj716vfx19xo%2BBSqZ1vOelZgdKeQ0o1MiFYkwbZ9fWsTw8QklGdK5%2Bp840vrP2LUoU2sh0YsTLrgnVu2NdG18MKUCVUOL6yLb%2BxFFsvk%2Bff3vcO%2BHKQ7U2F%2FcZclBOgKfUOL0QUZRiYHJIcPq1XrkF8o2KkxKxkJfTeJMdyifwO0zIf9Dzzb6dLj6hfG6wJ1DwDJVCQKi9cIPrnDbcyBOJ7Z3PD7mme6jueP1anVq8%2FIt6uYD%2FKgE40FkJjFLCOPYdFAH1erRiwG3w2jxWq45bl2b29Qs7tMGmVuaync79S3F1RGLZdnLYGGJZYBCmRgua1wKaJ4P3dM0hniTkh8cWlkER6xZdu8Hs4akAuCs4ySm%2FRaBwow%2BspV%2BkZ%2F%2BwYE9dpTCGeRtAIPCvmVYSmuRPmKNPpX6gGmmQJwDzFLFPqALc3GLYxpryP%2Fjh%2Fgwqw%2Bog2%2BeSp6iDZ7rLkOPwZ4wk8h5PYSuWVhjDi4Oq%2BBjqkAUIe5ZKyHXXBq%2BiJp%2BU35TAMenQbIlEE6oJrqlwkBQ7nV4Mfbh8YxETPph9LetG8fm90uJmS9%2BbR73AP6LJYrcVWvrZp%2BcyBKtYFCa7TFD9luj7iSwL0C1rOukxu3VslsBc%2FWKnXlndYtCAT%2FumdsC9PH84%2B1QqruASGJZZ9R2a%2BqFRkCJg5maGTFkq30RZkW%2F9i7%2FLVSVp62IonNMyAocrnuO84&X-Amz-Signature=ec0b1f90dce03602b54b49c1459d830e8aef008221f67ff79439afe6364cd9c2&X-Amz-SignedHeaders=host&x-id=GetObject",
72+
"expiry_time": "2025-03-19T13:55:45.348Z"
7373
}
7474
}
7575
},
@@ -4560,8 +4560,8 @@
45604560
"caption": [],
45614561
"type": "file",
45624562
"file": {
4563-
"url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/10d9f59d-d3e2-429a-ad72-c8b15b1f536b/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466STLNN5SA%2F20250309%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250309T131205Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjECsaCXVzLXdlc3QtMiJGMEQCIG94TkWa3mK1%2B5nVswsMblZQyl7j7VaT%2BqotVsKeSggXAiAQYbbvAf2NGeiVYD52%2FaNMKZ4YTg1%2BWJpH3%2Bmpc9xspir%2FAwh0EAAaDDYzNzQyMzE4MzgwNSIM%2F1rPCZwhKhp3eLk6KtwDZy4%2B20E51YbCCaXojGLfYiQw9vPtTNXK6tdO8gaTMKtEi5Nywg04k%2B9Jek8QTwgn1IM420f%2Bd%2B7ZeQxkGCZgYidrz1sKcxbWajR2%2B%2BsfabgkHxJePiFy5I%2FOxbBXdvwVrt5jDSn7KwwK9e1qUM40iTf3aDS1TBiTHdYFqed%2BE7vUg0%2Ffy7Qxo1huc%2BV0l0zWCzkqIykzPOJlFayl55TLK7%2B%2FXjcUD6ofLoCFQSXa6LvNMDcfSWKWbVMC05tnE9yBGsgKh23njD6DcbvtBFZM3NL4N0%2FCvxY2KuegsVlCY4598rhoogs%2BK%2B9GhXaCqnylT3iC8aR3ce3PNpEdO%2FUUnv1H1KZiFZh9tYblBdGcRocUnItGTq%2BPQJy89ooWIYkO0cfkPZiOtkVkhvc8JFHDRMsafTi92RLimnHP9pS%2FobUcQ5sLaLse96pISiT%2BdBJCTLJ%2FkK%2BmLHAb4deSmonck3VFr28Gdg33O8k0hlrlVDKnRYyhW%2BBrTg4R7VJkd6S9wOLvCgCNwBiwpPNy3gKNwTdnegDxLca5VV7EzC%2BeUWvCwCUxztpwyssi8SKks98Nib20n37ZbGamMWHLVzBfUtIhUvbwNCTqnug1uZEoe85mAFVMNvKDbJFH9CYw0tq1vgY6pgG1EFVVrhMNjCsu4q1c8btf3gVyMiqDnyPKQVm%2BGFD9CMIGHOQzTnYYdek5JJDDlQHzf5YxMVmDj9xFwb70UvCTf0NETvihF8T8s04Aik2m5t0%2FpSeKZbsZFoPvv16QeSS5BI9gaJJp7%2F1wDciv2yWG02uAxgp0kTlBZzYwCmsbAoBJhzuqppOnQ7MNLPOhPYtJCye%2BOjzgHukv19fC4vyZQCMcOof6&X-Amz-Signature=0b6ab1f158ebad0d10a5b604d79f9a916effea79013e4b9e7926dfc69f4c912e&X-Amz-SignedHeaders=host&x-id=GetObject",
4564-
"expiry_time": "2025-03-09T14:12:05.218Z"
4563+
"url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/10d9f59d-d3e2-429a-ad72-c8b15b1f536b/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB4667ZOXY2Y6%2F20250319%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250319T125545Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEBwaCXVzLXdlc3QtMiJIMEYCIQCo971xkAkpOezG800JUV1AJkAZ1%2BJ4GHc%2BXUmLgc%2B5PwIhAIfB6MFIuO9ESgtes%2Bvf%2Fehjzj%2BkvnaSGdAaBVY138ooKv8DCHUQABoMNjM3NDIzMTgzODA1Igwi4apJDc%2Bqo22dqecq3AP%2BDHeGuvT8rmtUsxYlp9NJ6tFdB1ACasA9X5yJmZihnP9hSw3j%2FZA%2Fr8Z5GQ%2FhfYNLtPooN2yczm5Wv%2F7uCSjB2Fj8HL9InG3FkjuSxnBbktd80L0LNbmriYZhEwkcLJ3MtZCxy0IyGzu%2Bxobsj9QVKaaP7Tj716vfx19xo%2BBSqZ1vOelZgdKeQ0o1MiFYkwbZ9fWsTw8QklGdK5%2Bp840vrP2LUoU2sh0YsTLrgnVu2NdG18MKUCVUOL6yLb%2BxFFsvk%2Bff3vcO%2BHKQ7U2F%2FcZclBOgKfUOL0QUZRiYHJIcPq1XrkF8o2KkxKxkJfTeJMdyifwO0zIf9Dzzb6dLj6hfG6wJ1DwDJVCQKi9cIPrnDbcyBOJ7Z3PD7mme6jueP1anVq8%2FIt6uYD%2FKgE40FkJjFLCOPYdFAH1erRiwG3w2jxWq45bl2b29Qs7tMGmVuaync79S3F1RGLZdnLYGGJZYBCmRgua1wKaJ4P3dM0hniTkh8cWlkER6xZdu8Hs4akAuCs4ySm%2FRaBwow%2BspV%2BkZ%2F%2BwYE9dpTCGeRtAIPCvmVYSmuRPmKNPpX6gGmmQJwDzFLFPqALc3GLYxpryP%2Fjh%2Fgwqw%2Bog2%2BeSp6iDZ7rLkOPwZ4wk8h5PYSuWVhjDi4Oq%2BBjqkAUIe5ZKyHXXBq%2BiJp%2BU35TAMenQbIlEE6oJrqlwkBQ7nV4Mfbh8YxETPph9LetG8fm90uJmS9%2BbR73AP6LJYrcVWvrZp%2BcyBKtYFCa7TFD9luj7iSwL0C1rOukxu3VslsBc%2FWKnXlndYtCAT%2FumdsC9PH84%2B1QqruASGJZZ9R2a%2BqFRkCJg5maGTFkq30RZkW%2F9i7%2FLVSVp62IonNMyAocrnuO84&X-Amz-Signature=f4f7a75350d15a03ee3beaf213bda4485d8734443f3dcf1dfbb92b7a09ea6941&X-Amz-SignedHeaders=host&x-id=GetObject",
4564+
"expiry_time": "2025-03-19T13:55:45.591Z"
45654565
}
45664566
}
45674567
},
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2+
import {
3+
formatNotionImageUrl,
4+
getFormattedImageUrlFromBlock,
5+
} from './formatNotionImageUrl';
6+
7+
describe('formatNotionImageUrl', () => {
8+
// 콘솔 에러 메시지 출력 방지
9+
const originalConsoleError = console.error;
10+
beforeEach(() => {
11+
console.error = vi.fn();
12+
});
13+
14+
afterEach(() => {
15+
console.error = originalConsoleError;
16+
vi.restoreAllMocks();
17+
});
18+
19+
it('유효한 S3 URL을 노션 이미지 URL로 변환해야 함', () => {
20+
const s3Url =
21+
'https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/566f127b-9e73-491d-bee6-5afd075653a2/image.png';
22+
const expected = `https://www.notion.so/image/${encodeURIComponent(s3Url)}?cache=v2`;
23+
24+
const result = formatNotionImageUrl(s3Url);
25+
26+
expect(result).toBe(expected);
27+
});
28+
29+
it('블록 ID와 사용자 ID를 포함한 URL로 변환해야 함', () => {
30+
const s3Url =
31+
'https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/566f127b-9e73-491d-bee6-5afd075653a2/image.png';
32+
const blockId = '17f9c6bf-2b17-8016-bf79-dc83ab79fb78';
33+
const userId = '5146391e-8b65-47f2-83b6-2bfe81194f32';
34+
35+
const expected = `https://www.notion.so/image/${encodeURIComponent(s3Url)}?table=block&id=${blockId}&userId=${userId}&cache=v2`;
36+
37+
const result = formatNotionImageUrl(s3Url, blockId, userId);
38+
39+
expect(result).toBe(expected);
40+
});
41+
42+
it('블록 ID만 포함한 URL로 변환해야 함', () => {
43+
const s3Url =
44+
'https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/566f127b-9e73-491d-bee6-5afd075653a2/image.png';
45+
const blockId = '17f9c6bf-2b17-8016-bf79-dc83ab79fb78';
46+
47+
const expected = `https://www.notion.so/image/${encodeURIComponent(s3Url)}?table=block&id=${blockId}&cache=v2`;
48+
49+
const result = formatNotionImageUrl(s3Url, blockId);
50+
51+
expect(result).toBe(expected);
52+
});
53+
54+
it('이미 노션 이미지 URL 형식인 경우 그대로 반환해야 함', () => {
55+
const notionUrl =
56+
'https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Fcd7314a5-d906-43b0-81e7-42eff82c02a3%2F566f127b-9e73-491d-bee6-5afd075653a2%2Fimage.png?table=block&id=17f9c6bf-2b17-8016-bf79-dc83ab79fb78&cache=v2';
57+
58+
const result = formatNotionImageUrl(notionUrl);
59+
60+
expect(result).toBe(notionUrl);
61+
});
62+
63+
it('빈 URL이나 유효하지 않은 URL은 그대로 반환해야 함', () => {
64+
expect(formatNotionImageUrl('')).toBe('');
65+
expect(formatNotionImageUrl('invalid-url')).toBe('invalid-url');
66+
expect(formatNotionImageUrl('http://example.com')).toBe(
67+
'http://example.com'
68+
);
69+
});
70+
71+
it('URL 변환 중 오류가 발생하면 원래 URL을 반환해야 함', () => {
72+
const mockUrl = 'https://example.com/image.jpg';
73+
74+
// encodeURIComponent에서 오류가 발생하도록 모킹
75+
const originalEncodeURIComponent = global.encodeURIComponent;
76+
global.encodeURIComponent = vi.fn(() => {
77+
throw new Error('인코딩 오류');
78+
});
79+
80+
const result = formatNotionImageUrl(mockUrl);
81+
82+
expect(console.error).toHaveBeenCalled();
83+
expect(result).toBe(mockUrl);
84+
85+
// 원래 함수로 복원
86+
global.encodeURIComponent = originalEncodeURIComponent;
87+
});
88+
});
89+
90+
describe('getFormattedImageUrlFromBlock', () => {
91+
// 콘솔 에러 메시지 출력 방지
92+
const originalConsoleError = console.error;
93+
beforeEach(() => {
94+
console.error = vi.fn();
95+
});
96+
97+
afterEach(() => {
98+
console.error = originalConsoleError;
99+
});
100+
101+
it('이미지 블록에서 URL을 추출하고 포맷팅해야 함', () => {
102+
const mockBlock = {
103+
id: '17f9c6bf-2b17-8016-bf79-dc83ab79fb78',
104+
type: 'image',
105+
image: {
106+
file: {
107+
url: 'https://prod-files-secure.s3.us-west-2.amazonaws.com/cd7314a5-d906-43b0-81e7-42eff82c02a3/566f127b-9e73-491d-bee6-5afd075653a2/image.png',
108+
},
109+
},
110+
last_edited_by: {
111+
id: '5146391e-8b65-47f2-83b6-2bfe81194f32',
112+
},
113+
};
114+
115+
const expectedUrl = formatNotionImageUrl(
116+
mockBlock.image.file.url,
117+
mockBlock.id,
118+
mockBlock.last_edited_by.id
119+
);
120+
121+
const result = getFormattedImageUrlFromBlock(mockBlock);
122+
123+
expect(result).toBe(expectedUrl);
124+
});
125+
126+
it('external URL이 있는 이미지 블록도 처리해야 함', () => {
127+
const mockBlock = {
128+
id: '17f9c6bf-2b17-8016-bf79-dc83ab79fb78',
129+
type: 'image',
130+
image: {
131+
external: {
132+
url: 'https://example.com/image.jpg',
133+
},
134+
},
135+
last_edited_by: {
136+
id: '5146391e-8b65-47f2-83b6-2bfe81194f32',
137+
},
138+
};
139+
140+
const expectedUrl = formatNotionImageUrl(
141+
mockBlock.image.external.url,
142+
mockBlock.id,
143+
mockBlock.last_edited_by.id
144+
);
145+
146+
const result = getFormattedImageUrlFromBlock(mockBlock);
147+
148+
expect(result).toBe(expectedUrl);
149+
});
150+
151+
it('이미지 블록이 아닌 경우 null을 반환해야 함', () => {
152+
const mockBlock = {
153+
id: '17f9c6bf-2b17-8016-bf79-dc83ab79fb78',
154+
type: 'paragraph',
155+
paragraph: {
156+
rich_text: [],
157+
},
158+
};
159+
160+
const result = getFormattedImageUrlFromBlock(mockBlock);
161+
162+
expect(result).toBeNull();
163+
});
164+
165+
it('URL이 없는 이미지 블록은 null을 반환해야 함', () => {
166+
const mockBlock = {
167+
id: '17f9c6bf-2b17-8016-bf79-dc83ab79fb78',
168+
type: 'image',
169+
image: {},
170+
};
171+
172+
const result = getFormattedImageUrlFromBlock(mockBlock);
173+
174+
expect(result).toBeNull();
175+
});
176+
177+
it('블록이 null이면 null을 반환해야 함', () => {
178+
expect(getFormattedImageUrlFromBlock(null)).toBeNull();
179+
});
180+
181+
it('처리 중 오류가 발생하면 null을 반환해야 함', () => {
182+
const mockBlock = {
183+
id: '17f9c6bf-2b17-8016-bf79-dc83ab79fb78',
184+
type: 'image',
185+
image: {
186+
file: {
187+
get url() {
188+
throw new Error('액세스 오류');
189+
}
190+
},
191+
},
192+
};
193+
194+
// 콘솔 에러 스파이 설정
195+
vi.spyOn(console, 'error').mockImplementation(() => {});
196+
197+
const result = getFormattedImageUrlFromBlock(mockBlock);
198+
199+
expect(console.error).toHaveBeenCalled();
200+
expect(result).toBeNull();
201+
});
202+
});
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* 노션 이미지 URL을 깔끔한 형태로 변환하는 함수
3+
*
4+
* S3 URL 형식의 노션 이미지 URL을 notion.so/image/ 형식으로 변환합니다.
5+
*
6+
* @param url - 변환할 S3 이미지 URL
7+
* @param blockId - 블록 ID (선택적)
8+
* @param userId - 사용자 ID (선택적)
9+
* @returns 변환된 노션 스타일 이미지 URL
10+
*
11+
* @example
12+
* const formattedUrl = formatNotionImageUrl('https://prod-files-secure.s3.us-west-2.amazonaws.com/...');
13+
* // 결과: https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F...
14+
*/
15+
export const formatNotionImageUrl = (
16+
url: string,
17+
blockId?: string,
18+
userId?: string
19+
): string => {
20+
// URL이 없거나 유효하지 않은 경우 원래 URL 반환
21+
if (!url || !url.startsWith('https://')) {
22+
return url;
23+
}
24+
25+
try {
26+
// 이미 notion.so 형식인 경우 그대로 반환
27+
if (url.includes('notion.so/image/')) {
28+
return url;
29+
}
30+
31+
// URL 인코딩
32+
const encodedUrl = encodeURIComponent(url);
33+
34+
// 기본 노션 이미지 URL 형식
35+
let formattedUrl = `https://www.notion.so/image/${encodedUrl}`;
36+
37+
// 추가 파라미터 설정
38+
const params: string[] = [];
39+
40+
// 블록 ID가 있는 경우 추가
41+
if (blockId) {
42+
params.push(`table=block&id=${blockId}`);
43+
}
44+
45+
// 사용자 ID가 있는 경우 추가
46+
if (userId) {
47+
params.push(`userId=${userId}`);
48+
}
49+
50+
// 추가 파라미터가 있는 경우 URL에 추가
51+
if (params.length > 0) {
52+
formattedUrl += `?${params.join('&')}`;
53+
}
54+
55+
// 캐시 버스팅 파라미터 추가
56+
formattedUrl += formattedUrl.includes('?') ? '&' : '?';
57+
formattedUrl += 'cache=v2';
58+
59+
return formattedUrl;
60+
} catch (error) {
61+
console.error('이미지 URL 변환 중 오류 발생:', error);
62+
return url; // 오류 발생 시 원래 URL 반환
63+
}
64+
};
65+
66+
/**
67+
* 노션 블록에서 이미지 URL을 추출하고 포맷팅하는 함수
68+
*
69+
* @param block - 노션 블록 객체
70+
* @returns 포맷팅된 이미지 URL 또는 null
71+
*/
72+
export const getFormattedImageUrlFromBlock = (block: any): string | null => {
73+
if (!block) return null;
74+
75+
try {
76+
// 이미지 블록인 경우
77+
if (block.type === 'image') {
78+
const imageData = block.image;
79+
const url = imageData.file?.url || imageData.external?.url;
80+
81+
if (url) {
82+
return formatNotionImageUrl(url, block.id, block.last_edited_by?.id);
83+
}
84+
}
85+
86+
return null;
87+
} catch (error) {
88+
console.error('블록에서 이미지 URL 추출 중 오류 발생:', error);
89+
return null;
90+
}
91+
};

packages/notion-to-utils/src/client/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { ClientOptions } from '@notionhq/client/build/src/Client';
33
import { getPageProperties as getPagePropertiesFunc } from './getPageProperties';
44
import { getFileUrl as getFileUrlFunc } from './getFileUrl';
55
import { getPageBlocks as getPageBlocksFunc } from './getPageBlocks';
6+
import { formatNotionImageUrl as formatNotionImageUrlFunc } from './formatNotionImageUrl';
67

78
export class Client extends NotionClient {
89
constructor(options: ClientOptions = {}) {
@@ -14,6 +15,8 @@ export class Client extends NotionClient {
1415
getFileUrl = (pageId: string, propertyKey: string) =>
1516
getFileUrlFunc(this, pageId, propertyKey);
1617
getPageBlocks = (pageId: string) => getPageBlocksFunc(this, pageId);
18+
formatNotionImageUrl = (url: string, blockId?: string, userId?: string) =>
19+
formatNotionImageUrlFunc(url, blockId, userId);
1720
}
1821

1922
export default Client;

0 commit comments

Comments
 (0)