notes-to-strapi-export-article-ai 1.0.119 → 3.0.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/.eslintrc +30 -22
- package/README.md +98 -143
- package/images/img.png +0 -0
- package/images/img_1.png +0 -0
- package/images/img_10.png +0 -0
- package/images/img_11.png +0 -0
- package/images/img_12.png +0 -0
- package/images/img_13.png +0 -0
- package/images/img_2.png +0 -0
- package/images/img_3.png +0 -0
- package/images/img_4.png +0 -0
- package/images/img_5.png +0 -0
- package/images/img_6.png +0 -0
- package/images/img_7.png +0 -0
- package/images/img_8.png +0 -0
- package/images/img_9.png +0 -0
- package/manifest.json +2 -2
- package/package.json +29 -26
- package/src/components/APIKeys.ts +219 -0
- package/src/components/Configuration.ts +663 -0
- package/src/components/Dashboard.ts +184 -0
- package/src/components/ImageSelectionModal.ts +58 -0
- package/src/components/Routes.ts +279 -0
- package/src/constants.ts +22 -61
- package/src/main.ts +177 -34
- package/src/services/configuration-generator.ts +172 -0
- package/src/services/field-analyzer.ts +84 -0
- package/src/services/frontmatter.ts +329 -0
- package/src/services/strapi-export.ts +436 -0
- package/src/settings/UnifiedSettingsTab.ts +206 -0
- package/src/types/image.ts +27 -16
- package/src/types/index.ts +3 -0
- package/src/types/route.ts +51 -0
- package/src/types/settings.ts +22 -23
- package/src/utils/analyse-file.ts +94 -0
- package/src/utils/debounce.ts +34 -0
- package/src/utils/image-processor.ts +124 -400
- package/src/utils/preview-modal.ts +265 -0
- package/src/utils/process-file.ts +122 -0
- package/src/utils/strapi-uploader.ts +120 -119
- package/src/settings.ts +0 -404
- package/src/types/article.ts +0 -8
- package/src/utils/openai-generator.ts +0 -139
- package/src/utils/validators.ts +0 -8
- package/version-bump.mjs +0 -14
- package/versions.json +0 -119
|
@@ -1,442 +1,166 @@
|
|
|
1
|
-
import { App,
|
|
2
|
-
import { OpenAI } from 'openai'
|
|
3
|
-
import { StrapiExporterSettings } from '../types/settings'
|
|
1
|
+
import { App, TFile } from 'obsidian'
|
|
4
2
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import {
|
|
3
|
+
ImageDescription,
|
|
4
|
+
ImageProcessingResult,
|
|
5
|
+
StrapiExporterSettings,
|
|
6
|
+
} from '../types'
|
|
7
|
+
import { uploadImageToStrapi } from './strapi-uploader'
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
|
-
* Process
|
|
13
|
-
* @param app
|
|
14
|
-
* @param settings
|
|
15
|
-
* @param useAdditionalCallAPI
|
|
10
|
+
* Process images in markdown content and handle uploads to Strapi
|
|
16
11
|
*/
|
|
17
|
-
export async function
|
|
12
|
+
export async function processImages(
|
|
18
13
|
app: App,
|
|
19
14
|
settings: StrapiExporterSettings,
|
|
20
|
-
|
|
21
|
-
) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
new Notice('No active Markdown view')
|
|
25
|
-
return
|
|
26
|
-
}
|
|
15
|
+
content: string
|
|
16
|
+
): Promise<ImageProcessingResult> {
|
|
17
|
+
try {
|
|
18
|
+
const imageRefs = extractImageReferences(content)
|
|
27
19
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (!settings.strapiUrl || !settings.strapiApiToken) {
|
|
33
|
-
new Notice(
|
|
34
|
-
'Please configure Strapi URL and API token in the plugin settings'
|
|
20
|
+
const processedImages = await processImageReferences(
|
|
21
|
+
app,
|
|
22
|
+
settings,
|
|
23
|
+
imageRefs
|
|
35
24
|
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
new Notice('Please configure OpenAI API key in the plugin settings')
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (useAdditionalCallAPI) {
|
|
45
|
-
if (!settings.additionalJsonTemplate) {
|
|
46
|
-
new Notice(
|
|
47
|
-
'Please configure the additional call api JSON template in the plugin settings'
|
|
48
|
-
)
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (!settings.additionalJsonTemplateDescription) {
|
|
53
|
-
new Notice(
|
|
54
|
-
'Please configure the additional call api JSON template description in the plugin settings'
|
|
55
|
-
)
|
|
56
|
-
return
|
|
25
|
+
const updatedContent = updateImageReferences(content, processedImages)
|
|
26
|
+
return {
|
|
27
|
+
content: updatedContent,
|
|
28
|
+
processedImages,
|
|
57
29
|
}
|
|
30
|
+
} catch (error) {
|
|
31
|
+
throw new Error(`Image processing failed: ${error.message}`)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
58
34
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
35
|
+
interface ImageReference {
|
|
36
|
+
fullMatch: string
|
|
37
|
+
path: string
|
|
38
|
+
altText: string
|
|
39
|
+
type: 'wikilink' | 'markdown'
|
|
40
|
+
}
|
|
65
41
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
} else {
|
|
73
|
-
if (!settings.jsonTemplate) {
|
|
74
|
-
new Notice('Please configure JSON template in the plugin settings')
|
|
75
|
-
return
|
|
76
|
-
}
|
|
42
|
+
/**
|
|
43
|
+
* Extract image references from content
|
|
44
|
+
*/
|
|
45
|
+
function extractImageReferences(content: string): ImageReference[] {
|
|
46
|
+
const references: ImageReference[] = []
|
|
77
47
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
48
|
+
try {
|
|
49
|
+
// Wiki-style image links (![[image.png]])
|
|
50
|
+
const wikiLinkRegex = /!\[\[([^\]]+\.(png|jpe?g|gif|svg|bmp|webp))\]\]/gi
|
|
51
|
+
let match
|
|
52
|
+
|
|
53
|
+
while ((match = wikiLinkRegex.exec(content)) !== null) {
|
|
54
|
+
references.push({
|
|
55
|
+
fullMatch: match[0],
|
|
56
|
+
path: match[1],
|
|
57
|
+
altText: '',
|
|
58
|
+
type: 'wikilink',
|
|
59
|
+
})
|
|
83
60
|
}
|
|
84
61
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
62
|
+
// Markdown-style image links ()
|
|
63
|
+
const markdownLinkRegex =
|
|
64
|
+
/!\[([^\]]*)\]\(([^)]+\.(png|jpe?g|gif|svg|bmp|webp))\)/gi
|
|
65
|
+
while ((match = markdownLinkRegex.exec(content)) !== null) {
|
|
66
|
+
references.push({
|
|
67
|
+
fullMatch: match[0],
|
|
68
|
+
path: match[2],
|
|
69
|
+
altText: match[1],
|
|
70
|
+
type: 'markdown',
|
|
71
|
+
})
|
|
90
72
|
}
|
|
91
73
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
)
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
new Notice('All settings are ok, processing Markdown content...')
|
|
101
|
-
|
|
102
|
-
// Initialize OpenAI API
|
|
103
|
-
const openai = new OpenAI({
|
|
104
|
-
apiKey: settings.openaiApiKey,
|
|
105
|
-
dangerouslyAllowBrowser: true,
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
/** ****************************************************************************
|
|
109
|
-
* Process the markdown content
|
|
110
|
-
* *****************************************************************************
|
|
111
|
-
*/
|
|
112
|
-
const file = activeView.file
|
|
113
|
-
let content = ''
|
|
114
|
-
if (!file) {
|
|
115
|
-
new Notice('No file found in active view...')
|
|
116
|
-
return
|
|
74
|
+
return references
|
|
75
|
+
} catch (error) {
|
|
76
|
+
throw new Error(`Failed to extract image references: ${error.message}`)
|
|
117
77
|
}
|
|
78
|
+
}
|
|
118
79
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Process image references and upload to Strapi
|
|
82
|
+
*/
|
|
83
|
+
async function processImageReferences(
|
|
84
|
+
app: App,
|
|
85
|
+
settings: StrapiExporterSettings,
|
|
86
|
+
references: ImageReference[]
|
|
87
|
+
): Promise<ImageDescription[]> {
|
|
88
|
+
const processedImages: ImageDescription[] = []
|
|
89
|
+
|
|
90
|
+
for (const ref of references) {
|
|
91
|
+
try {
|
|
92
|
+
if (isExternalUrl(ref.path)) {
|
|
93
|
+
processedImages.push({
|
|
94
|
+
url: ref.path,
|
|
95
|
+
name: ref.path,
|
|
96
|
+
path: ref.path,
|
|
97
|
+
description: {
|
|
98
|
+
name: ref.path,
|
|
99
|
+
alternativeText: ref.altText,
|
|
100
|
+
caption: ref.altText,
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
continue
|
|
142
104
|
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
105
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (Object.keys(galleryMetadata).length > 0) {
|
|
151
|
-
galleryUploadedImageIds = Object.values(galleryMetadata).map(
|
|
152
|
-
(item: any) => item.data.id
|
|
153
|
-
)
|
|
154
|
-
}
|
|
155
|
-
}
|
|
106
|
+
const file = app.vault.getAbstractFileByPath(ref.path)
|
|
107
|
+
if (!(file instanceof TFile)) {
|
|
108
|
+
continue
|
|
109
|
+
}
|
|
156
110
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (imageBlob) {
|
|
161
|
-
const imageDescription = await getImageDescription(imageBlob.blob, openai)
|
|
162
|
-
const uploadedImage: any = await uploadImagesToStrapi(
|
|
163
|
-
[{ ...imageBlob, description: imageDescription }],
|
|
111
|
+
const uploadResult = await uploadImageToStrapi(
|
|
112
|
+
file,
|
|
113
|
+
file.name,
|
|
164
114
|
settings,
|
|
165
115
|
app,
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
imageBlob.id = uploadedImage[imageBlob.name].id
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (galleryUploadedImageIds.length === 0) {
|
|
174
|
-
const galleryImageBlobs = await getGalleryImageBlobs(app, galleryFolderPath)
|
|
175
|
-
galleryUploadedImageIds = await uploadGalleryImagesToStrapi(
|
|
176
|
-
galleryImageBlobs,
|
|
177
|
-
settings,
|
|
178
|
-
app,
|
|
179
|
-
galleryFolderPath
|
|
180
|
-
)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
content = await app.vault.read(file)
|
|
184
|
-
|
|
185
|
-
const flag = hasUnexportedImages(content)
|
|
186
|
-
|
|
187
|
-
/** ****************************************************************************
|
|
188
|
-
* Process the images
|
|
189
|
-
* *****************************************************************************
|
|
190
|
-
*/
|
|
191
|
-
if (flag) {
|
|
192
|
-
const imagePaths = extractImagePaths(content)
|
|
193
|
-
const imageBlobs = await getImageBlobs(app, imagePaths)
|
|
194
|
-
|
|
195
|
-
new Notice('Getting image descriptions...')
|
|
196
|
-
const imageDescriptions = await Promise.all(
|
|
197
|
-
imageBlobs.map(async imageBlob => {
|
|
198
|
-
const description = await getImageDescription(imageBlob.blob, openai)
|
|
199
|
-
return {
|
|
200
|
-
blob: imageBlob.blob,
|
|
201
|
-
name: imageBlob.name,
|
|
202
|
-
path: imageBlob.path,
|
|
203
|
-
description,
|
|
116
|
+
{
|
|
117
|
+
alternativeText: ref.altText || file.basename,
|
|
118
|
+
caption: ref.altText || file.basename,
|
|
204
119
|
}
|
|
205
|
-
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
new Notice('Uploading images to Strapi...')
|
|
209
|
-
const uploadedImages = await uploadImagesToStrapi(
|
|
210
|
-
imageDescriptions,
|
|
211
|
-
settings
|
|
212
|
-
)
|
|
213
|
-
|
|
214
|
-
new Notice('Replacing image paths...')
|
|
215
|
-
content = replaceImagePaths(content, uploadedImages)
|
|
216
|
-
await app.vault.modify(file, content)
|
|
217
|
-
new Notice('Images uploaded and links updated successfully!')
|
|
218
|
-
} else {
|
|
219
|
-
new Notice(
|
|
220
|
-
'No local images found in the content... Skip the image processing...'
|
|
221
|
-
)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/** ****************************************************************************
|
|
225
|
-
* Generate article content
|
|
226
|
-
* *****************************************************************************
|
|
227
|
-
*/
|
|
228
|
-
new Notice('Generating article content...')
|
|
229
|
-
const articleContent = await generateArticleContent(
|
|
230
|
-
content,
|
|
231
|
-
openai,
|
|
232
|
-
settings,
|
|
233
|
-
useAdditionalCallAPI
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
/** ****************************************************************************
|
|
237
|
-
* Add the content, image, and gallery to the article content based on the settings
|
|
238
|
-
* *****************************************************************************
|
|
239
|
-
*/
|
|
240
|
-
const imageFullPathProperty = useAdditionalCallAPI
|
|
241
|
-
? settings.additionalImageFullPathProperty
|
|
242
|
-
: settings.mainImageFullPathProperty
|
|
243
|
-
const galleryFullPathProperty = useAdditionalCallAPI
|
|
244
|
-
? settings.additionalGalleryFullPathProperty
|
|
245
|
-
: settings.mainGalleryFullPathProperty
|
|
246
|
-
|
|
247
|
-
articleContent.data = {
|
|
248
|
-
...articleContent.data,
|
|
249
|
-
...(imageBlob &&
|
|
250
|
-
imageFullPathProperty && { [imageFullPathProperty]: imageBlob.id }),
|
|
251
|
-
...(galleryUploadedImageIds.length > 0 &&
|
|
252
|
-
galleryFullPathProperty && {
|
|
253
|
-
[galleryFullPathProperty]: galleryUploadedImageIds,
|
|
254
|
-
}),
|
|
255
|
-
}
|
|
120
|
+
)
|
|
256
121
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const response = await fetch(
|
|
260
|
-
useAdditionalCallAPI
|
|
261
|
-
? settings.additionalUrl
|
|
262
|
-
: settings.strapiArticleCreateUrl,
|
|
263
|
-
{
|
|
264
|
-
method: 'POST',
|
|
265
|
-
headers: {
|
|
266
|
-
'Content-Type': 'application/json',
|
|
267
|
-
Authorization: `Bearer ${settings.strapiApiToken}`,
|
|
268
|
-
},
|
|
269
|
-
body: JSON.stringify(articleContent),
|
|
122
|
+
if (uploadResult) {
|
|
123
|
+
processedImages.push(uploadResult)
|
|
270
124
|
}
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
if (response.ok) {
|
|
274
|
-
new Notice(
|
|
275
|
-
'Check your API content now, the article is created & uploaded! 🎉'
|
|
276
|
-
)
|
|
277
|
-
} else {
|
|
278
|
-
const errorData = await response.json()
|
|
279
|
-
new Notice(
|
|
280
|
-
`Failed to create article in Strapi. Error: ${errorData.error.message}`
|
|
281
|
-
)
|
|
125
|
+
} catch (error) {
|
|
126
|
+
throw new Error(`Failed to process image ${ref.path}: ${error.message}`)
|
|
282
127
|
}
|
|
283
|
-
} catch (error) {
|
|
284
|
-
new Notice(`Error creating article in Strapi. Error: ${error.message}`)
|
|
285
128
|
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Extract image paths from the markdown content
|
|
290
|
-
* @param content
|
|
291
|
-
*/
|
|
292
|
-
export function extractImagePaths(content: string): string[] {
|
|
293
|
-
const imageRegex = /!\[\[([^\[\]]*\.(png|jpe?g|gif|bmp|webp))\]\]/gi
|
|
294
|
-
const imagePaths: string[] = []
|
|
295
|
-
let match
|
|
296
|
-
|
|
297
|
-
while ((match = imageRegex.exec(content)) !== null) {
|
|
298
|
-
imagePaths.push(match[1])
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return imagePaths
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Check if the markdown content has unexported images
|
|
306
|
-
* @param content
|
|
307
|
-
*/
|
|
308
|
-
export function hasUnexportedImages(content: string): boolean {
|
|
309
|
-
const imageRegex = /!\[\[([^\[\]]*\.(png|jpe?g|gif|bmp|webp))\]\]/gi
|
|
310
|
-
return imageRegex.test(content)
|
|
311
|
-
}
|
|
312
129
|
|
|
313
|
-
|
|
314
|
-
* Get the image blobs from the image paths
|
|
315
|
-
* @param app
|
|
316
|
-
* @param imagePaths
|
|
317
|
-
*/
|
|
318
|
-
export async function getImageBlobs(
|
|
319
|
-
app: App,
|
|
320
|
-
imagePaths: string[]
|
|
321
|
-
): Promise<{ path: string; blob: Blob; name: string }[]> {
|
|
322
|
-
const files = app.vault.getAllLoadedFiles()
|
|
323
|
-
const fileNames = files.map(file => file.name)
|
|
324
|
-
const imageFiles = imagePaths.filter(path => fileNames.includes(path))
|
|
325
|
-
return await Promise.all(
|
|
326
|
-
imageFiles.map(async path => {
|
|
327
|
-
const file = files.find(file => file.name === path)
|
|
328
|
-
if (file instanceof TFile) {
|
|
329
|
-
const blob = await app.vault.readBinary(file)
|
|
330
|
-
return {
|
|
331
|
-
name: path,
|
|
332
|
-
blob: new Blob([blob], { type: 'image/png' }),
|
|
333
|
-
path: file.path,
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return {
|
|
337
|
-
name: '',
|
|
338
|
-
blob: new Blob(),
|
|
339
|
-
path: '',
|
|
340
|
-
}
|
|
341
|
-
})
|
|
342
|
-
)
|
|
130
|
+
return processedImages
|
|
343
131
|
}
|
|
344
132
|
|
|
345
133
|
/**
|
|
346
|
-
*
|
|
347
|
-
* @param app
|
|
348
|
-
* @param imageFolderPath
|
|
134
|
+
* Update image references in content with uploaded URLs
|
|
349
135
|
*/
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
):
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const file = files[0]
|
|
367
|
-
|
|
368
|
-
const blob = await app.vault.readBinary(file)
|
|
369
|
-
return {
|
|
370
|
-
name: file.name,
|
|
371
|
-
blob: new Blob([blob], { type: 'image/png' }),
|
|
372
|
-
path: file.path,
|
|
136
|
+
function updateImageReferences(
|
|
137
|
+
content: string,
|
|
138
|
+
processedImages: ImageDescription[]
|
|
139
|
+
): string {
|
|
140
|
+
try {
|
|
141
|
+
let updatedContent = content
|
|
142
|
+
for (const image of processedImages) {
|
|
143
|
+
if (image.url) {
|
|
144
|
+
const imageRegex = new RegExp(
|
|
145
|
+
`!\\[([^\\]]*)\\]\\(${image.path}\\)|!\\[\\[${image.path}\\]\\]`,
|
|
146
|
+
'g'
|
|
147
|
+
)
|
|
148
|
+
updatedContent = updatedContent.replace(
|
|
149
|
+
imageRegex,
|
|
150
|
+
``
|
|
151
|
+
)
|
|
373
152
|
}
|
|
374
153
|
}
|
|
375
|
-
} else {
|
|
376
|
-
new Notice(
|
|
377
|
-
'Image folder not found. Please create an "image" folder next to your article file.'
|
|
378
|
-
)
|
|
379
|
-
}
|
|
380
|
-
return null
|
|
381
|
-
}
|
|
382
154
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
* @param galleryFolderPath
|
|
387
|
-
*/
|
|
388
|
-
export async function getGalleryImageBlobs(
|
|
389
|
-
app: App,
|
|
390
|
-
galleryFolderPath: string
|
|
391
|
-
): Promise<{ path: string; blob: Blob; name: string }[]> {
|
|
392
|
-
const folder = app.vault.getAbstractFileByPath(galleryFolderPath)
|
|
393
|
-
if (folder instanceof TFolder) {
|
|
394
|
-
const files = folder.children.filter(
|
|
395
|
-
file =>
|
|
396
|
-
file instanceof TFile &&
|
|
397
|
-
file.extension.match(/^(jpg|jpeg|png|gif|bmp|webp)$/i)
|
|
398
|
-
)
|
|
399
|
-
return Promise.all(
|
|
400
|
-
files.map(async file => {
|
|
401
|
-
// check the TFILE type, and not cast it to TFILE
|
|
402
|
-
if (!(file instanceof TFile)) {
|
|
403
|
-
return {
|
|
404
|
-
name: '',
|
|
405
|
-
blob: new Blob(),
|
|
406
|
-
path: '',
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
const blob = await app.vault.readBinary(file)
|
|
410
|
-
return {
|
|
411
|
-
name: file.name,
|
|
412
|
-
blob: new Blob([blob], { type: 'image/png' }),
|
|
413
|
-
path: file.path,
|
|
414
|
-
}
|
|
415
|
-
})
|
|
416
|
-
)
|
|
417
|
-
} else {
|
|
418
|
-
new Notice(
|
|
419
|
-
'Gallery folder not found. Please create a "gallery" folder next to your article file.'
|
|
420
|
-
)
|
|
155
|
+
return updatedContent
|
|
156
|
+
} catch (error) {
|
|
157
|
+
throw new Error(`Failed to update image references: ${error.message}`)
|
|
421
158
|
}
|
|
422
|
-
return []
|
|
423
159
|
}
|
|
424
160
|
|
|
425
161
|
/**
|
|
426
|
-
*
|
|
427
|
-
* @param content
|
|
428
|
-
* @param uploadedImages
|
|
162
|
+
* Check if a path is an external URL
|
|
429
163
|
*/
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
uploadedImages: { [key: string]: { url: string; data: any } }
|
|
433
|
-
): string {
|
|
434
|
-
for (const [localPath, imageData] of Object.entries(uploadedImages)) {
|
|
435
|
-
const markdownImageRegex = new RegExp(`!\\[\\[${localPath}\\]\\]`, 'g')
|
|
436
|
-
content = content.replace(
|
|
437
|
-
markdownImageRegex,
|
|
438
|
-
``
|
|
439
|
-
)
|
|
440
|
-
}
|
|
441
|
-
return content
|
|
164
|
+
function isExternalUrl(path: string): boolean {
|
|
165
|
+
return path.startsWith('http://') || path.startsWith('https://')
|
|
442
166
|
}
|