notes-to-strapi-export-article-ai 1.0.17 → 1.0.19
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/manifest.json +3 -3
- package/package.json +2 -2
- package/src/main.ts +6 -8
- package/src/settings.ts +33 -47
- package/src/utils/image-processor.ts +11 -13
- package/src/utils/strapi-uploader.ts +10 -8
- package/versions.json +3 -1
package/manifest.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "notes-to-strapi-export-article-ai",
|
|
3
|
-
"name": "Strapi Exporter
|
|
4
|
-
"version": "1.0.
|
|
3
|
+
"name": "Strapi Exporter AI",
|
|
4
|
+
"version": "1.0.19",
|
|
5
5
|
"minAppVersion": "1.5.0",
|
|
6
|
-
"description": "Effortlessly export your notes to Strapi CMS with AI-powered
|
|
6
|
+
"description": "Effortlessly export your notes to Strapi CMS with AI-powered handling and SEO optimization.",
|
|
7
7
|
"author": "Cinquin Andy",
|
|
8
8
|
"authorUrl": "https://andy.cinquin.com",
|
|
9
9
|
"isDesktopOnly": true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "notes-to-strapi-export-article-ai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"description": "Effortlessly export your Obsidian notes to Strapi CMS with AI-powered image handling and SEO optimization. Replace all the images in your notes by uploaded images in Strapi, and add SEO metadata to uploaded images.",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"scripts": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"keywords": [],
|
|
12
12
|
"author": "Cinquin Andy",
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@types/node": "20.12.
|
|
14
|
+
"@types/node": "20.12.4",
|
|
15
15
|
"@typescript-eslint/eslint-plugin": "7.5.0",
|
|
16
16
|
"@typescript-eslint/parser": "7.5.0",
|
|
17
17
|
"builtin-modules": "3.3.0",
|
package/src/main.ts
CHANGED
|
@@ -14,27 +14,25 @@ export default class StrapiExporterPlugin extends Plugin {
|
|
|
14
14
|
/**
|
|
15
15
|
* Add a ribbon icon to the Markdown view (the little icon on the left side bar)
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
this.addRibbonIcon(
|
|
18
18
|
'upload',
|
|
19
|
-
'Upload
|
|
20
|
-
async (
|
|
19
|
+
'Upload to Strapi and generate content with AI',
|
|
20
|
+
async () => {
|
|
21
21
|
await this.processMarkdownContent()
|
|
22
22
|
}
|
|
23
23
|
)
|
|
24
|
-
ribbonIconEl.addClass('strapi-exporter-ribbon-class')
|
|
25
24
|
|
|
26
25
|
/**
|
|
27
26
|
* Add a ribbon icon based on the settings (if enabled)
|
|
28
27
|
*/
|
|
29
28
|
if (this.settings.enableAdditionalApiCall) {
|
|
30
|
-
|
|
29
|
+
this.addRibbonIcon(
|
|
31
30
|
'link',
|
|
32
|
-
'Upload
|
|
33
|
-
async (
|
|
31
|
+
'Upload to Strapi and generate additional content with AI',
|
|
32
|
+
async () => {
|
|
34
33
|
await this.processMarkdownContent(true)
|
|
35
34
|
}
|
|
36
35
|
)
|
|
37
|
-
additionalRibbonIconEl.addClass('strapi-exporter-additional-ribbon-class')
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
this.addSettingTab(new StrapiExporterSettingTab(this.app, this))
|
package/src/settings.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { App,
|
|
1
|
+
import { App, PluginSettingTab, Setting } from 'obsidian'
|
|
2
2
|
import StrapiExporterPlugin from './main'
|
|
3
3
|
import { validateJsonTemplate } from './utils/validators'
|
|
4
4
|
|
|
@@ -11,17 +11,11 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
display(): void {
|
|
14
|
-
// Display settings fields
|
|
15
14
|
const { containerEl } = this
|
|
16
15
|
containerEl.empty()
|
|
17
16
|
|
|
18
|
-
/** ****************************************************************************
|
|
19
|
-
* Add the settings for the plugin
|
|
20
|
-
* *****************************************************************************
|
|
21
|
-
*/
|
|
22
|
-
containerEl.createEl('h1', { text: 'Strapi & OpenAI Settings' })
|
|
23
17
|
new Setting(containerEl)
|
|
24
|
-
.setName('Strapi API
|
|
18
|
+
.setName('Strapi API token')
|
|
25
19
|
.setDesc('Enter your Strapi API token')
|
|
26
20
|
.addText(text =>
|
|
27
21
|
text
|
|
@@ -34,7 +28,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
34
28
|
)
|
|
35
29
|
|
|
36
30
|
new Setting(containerEl)
|
|
37
|
-
.setName('OpenAI API
|
|
31
|
+
.setName('OpenAI API key')
|
|
38
32
|
.setDesc('Enter your OpenAI API key for GPT-3')
|
|
39
33
|
.addText(text =>
|
|
40
34
|
text
|
|
@@ -47,7 +41,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
47
41
|
)
|
|
48
42
|
|
|
49
43
|
new Setting(containerEl)
|
|
50
|
-
.setName('Additional
|
|
44
|
+
.setName('Additional prompt')
|
|
51
45
|
.setDesc(
|
|
52
46
|
'Enter an optional additional prompt to customize the article content generation'
|
|
53
47
|
)
|
|
@@ -61,7 +55,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
61
55
|
})
|
|
62
56
|
)
|
|
63
57
|
|
|
64
|
-
containerEl.
|
|
58
|
+
new Setting(containerEl).setName('Strapi settings - Call 1').setHeading()
|
|
65
59
|
|
|
66
60
|
new Setting(containerEl)
|
|
67
61
|
.setName('Strapi URL')
|
|
@@ -77,7 +71,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
77
71
|
)
|
|
78
72
|
|
|
79
73
|
new Setting(containerEl)
|
|
80
|
-
.setName('JSON
|
|
74
|
+
.setName('JSON template')
|
|
81
75
|
.setDesc('Enter the JSON template for the fields needed')
|
|
82
76
|
.addTextArea(text =>
|
|
83
77
|
text
|
|
@@ -87,17 +81,12 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
87
81
|
if (validateJsonTemplate(value)) {
|
|
88
82
|
this.plugin.settings.jsonTemplate = value
|
|
89
83
|
await this.plugin.saveSettings()
|
|
90
|
-
new Notice('JSON template saved successfully. (valid !)')
|
|
91
|
-
} else {
|
|
92
|
-
new Notice(
|
|
93
|
-
'Invalid JSON template. Please enter a valid JSON template.'
|
|
94
|
-
)
|
|
95
84
|
}
|
|
96
85
|
})
|
|
97
86
|
)
|
|
98
87
|
|
|
99
88
|
new Setting(containerEl)
|
|
100
|
-
.setName('JSON
|
|
89
|
+
.setName('JSON template description')
|
|
101
90
|
.setDesc('Enter the description for each field in the JSON template')
|
|
102
91
|
.addTextArea(text =>
|
|
103
92
|
text
|
|
@@ -110,7 +99,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
110
99
|
)
|
|
111
100
|
|
|
112
101
|
new Setting(containerEl)
|
|
113
|
-
.setName('Strapi
|
|
102
|
+
.setName('Strapi article create URL')
|
|
114
103
|
.setDesc('Enter the URL to create articles in Strapi')
|
|
115
104
|
.addText(text =>
|
|
116
105
|
text
|
|
@@ -123,7 +112,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
123
112
|
)
|
|
124
113
|
|
|
125
114
|
new Setting(containerEl)
|
|
126
|
-
.setName('Strapi
|
|
115
|
+
.setName('Strapi content attribute name')
|
|
127
116
|
.setDesc('Enter the attribute name for the content field in Strapi')
|
|
128
117
|
.addText(text =>
|
|
129
118
|
text
|
|
@@ -135,10 +124,10 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
135
124
|
})
|
|
136
125
|
)
|
|
137
126
|
|
|
138
|
-
containerEl.
|
|
127
|
+
new Setting(containerEl).setName('Main image settings').setHeading()
|
|
139
128
|
|
|
140
129
|
new Setting(containerEl)
|
|
141
|
-
.setName('Enable
|
|
130
|
+
.setName('Enable main image')
|
|
142
131
|
.setDesc('Toggle the main image')
|
|
143
132
|
.addToggle(toggle =>
|
|
144
133
|
toggle
|
|
@@ -151,7 +140,6 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
151
140
|
)
|
|
152
141
|
|
|
153
142
|
if (this.plugin.settings.mainButtonImageEnabled) {
|
|
154
|
-
// Display main image settings
|
|
155
143
|
containerEl.createEl('p', {
|
|
156
144
|
text: 'For the plugin to detect images and galleries, ensure the following folder structure:',
|
|
157
145
|
})
|
|
@@ -168,7 +156,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
168
156
|
})
|
|
169
157
|
|
|
170
158
|
new Setting(containerEl)
|
|
171
|
-
.setName('Main
|
|
159
|
+
.setName('Main image full path property')
|
|
172
160
|
.setDesc(
|
|
173
161
|
'Enter the full path property for the main image in the final call'
|
|
174
162
|
)
|
|
@@ -183,10 +171,10 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
183
171
|
)
|
|
184
172
|
}
|
|
185
173
|
|
|
186
|
-
containerEl.
|
|
174
|
+
new Setting(containerEl).setName('Main gallery settings').setHeading()
|
|
187
175
|
|
|
188
176
|
new Setting(containerEl)
|
|
189
|
-
.setName('Enable
|
|
177
|
+
.setName('Enable main gallery')
|
|
190
178
|
.setDesc('Toggle the main gallery')
|
|
191
179
|
.addToggle(toggle =>
|
|
192
180
|
toggle
|
|
@@ -215,7 +203,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
215
203
|
})
|
|
216
204
|
|
|
217
205
|
new Setting(containerEl)
|
|
218
|
-
.setName('Main
|
|
206
|
+
.setName('Main gallery full path property')
|
|
219
207
|
.setDesc(
|
|
220
208
|
'Enter the full path property for the main gallery in the final call'
|
|
221
209
|
)
|
|
@@ -230,15 +218,16 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
230
218
|
)
|
|
231
219
|
}
|
|
232
220
|
|
|
233
|
-
containerEl
|
|
234
|
-
|
|
235
|
-
|
|
221
|
+
new Setting(containerEl)
|
|
222
|
+
.setName('Strapi settings - Call 2 - Additional call')
|
|
223
|
+
.setHeading()
|
|
224
|
+
|
|
236
225
|
containerEl.createEl('p', {
|
|
237
226
|
text: `(Be careful, when enabling this feature, you'll need to restart Obsidian to see the additional button in the ribbon menu.)`,
|
|
238
227
|
})
|
|
239
228
|
|
|
240
229
|
new Setting(containerEl)
|
|
241
|
-
.setName('Enable
|
|
230
|
+
.setName('Enable additional call API')
|
|
242
231
|
.setDesc(
|
|
243
232
|
'Toggle the additional Call API, and display a new icon in the ribbon menu'
|
|
244
233
|
)
|
|
@@ -254,7 +243,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
254
243
|
|
|
255
244
|
if (this.plugin.settings.enableAdditionalApiCall) {
|
|
256
245
|
new Setting(containerEl)
|
|
257
|
-
.setName('Additional JSON
|
|
246
|
+
.setName('Additional JSON template')
|
|
258
247
|
.setDesc(
|
|
259
248
|
'Enter the JSON template for the fields needed for the additional api'
|
|
260
249
|
)
|
|
@@ -266,17 +255,12 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
266
255
|
if (validateJsonTemplate(value)) {
|
|
267
256
|
this.plugin.settings.additionalJsonTemplate = value
|
|
268
257
|
await this.plugin.saveSettings()
|
|
269
|
-
new Notice('JSON template saved successfully. (valid !)')
|
|
270
|
-
} else {
|
|
271
|
-
new Notice(
|
|
272
|
-
'Invalid additional JSON template. Please enter a valid JSON template.'
|
|
273
|
-
)
|
|
274
258
|
}
|
|
275
259
|
})
|
|
276
260
|
)
|
|
277
261
|
|
|
278
262
|
new Setting(containerEl)
|
|
279
|
-
.setName('Additional API JSON
|
|
263
|
+
.setName('Additional API JSON template description')
|
|
280
264
|
.setDesc(
|
|
281
265
|
'Enter the description for each field in the additional API JSON template'
|
|
282
266
|
)
|
|
@@ -304,7 +288,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
304
288
|
)
|
|
305
289
|
|
|
306
290
|
new Setting(containerEl)
|
|
307
|
-
.setName('Additional API
|
|
291
|
+
.setName('Additional API content attribute name')
|
|
308
292
|
.setDesc(
|
|
309
293
|
'Enter the attribute name for the content field for the additional API'
|
|
310
294
|
)
|
|
@@ -318,10 +302,12 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
318
302
|
})
|
|
319
303
|
)
|
|
320
304
|
|
|
321
|
-
containerEl
|
|
305
|
+
new Setting(containerEl)
|
|
306
|
+
.setName('Additional call API image settings')
|
|
307
|
+
.setHeading()
|
|
322
308
|
|
|
323
309
|
new Setting(containerEl)
|
|
324
|
-
.setName('Enable
|
|
310
|
+
.setName('Enable additional call API image')
|
|
325
311
|
.setDesc('Toggle the additional Call API image')
|
|
326
312
|
.addToggle(toggle =>
|
|
327
313
|
toggle
|
|
@@ -350,7 +336,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
350
336
|
})
|
|
351
337
|
|
|
352
338
|
new Setting(containerEl)
|
|
353
|
-
.setName('Additional
|
|
339
|
+
.setName('Additional call API image full path property')
|
|
354
340
|
.setDesc(
|
|
355
341
|
'Enter the full path property for the additional Call API image in the final call'
|
|
356
342
|
)
|
|
@@ -365,12 +351,12 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
365
351
|
)
|
|
366
352
|
}
|
|
367
353
|
|
|
368
|
-
containerEl
|
|
369
|
-
|
|
370
|
-
|
|
354
|
+
new Setting(containerEl)
|
|
355
|
+
.setName('Additional call API gallery settings')
|
|
356
|
+
.setHeading()
|
|
371
357
|
|
|
372
358
|
new Setting(containerEl)
|
|
373
|
-
.setName('Enable
|
|
359
|
+
.setName('Enable additional call API gallery')
|
|
374
360
|
.setDesc('Toggle the additional Call API gallery')
|
|
375
361
|
.addToggle(toggle =>
|
|
376
362
|
toggle
|
|
@@ -399,7 +385,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
399
385
|
})
|
|
400
386
|
|
|
401
387
|
new Setting(containerEl)
|
|
402
|
-
.setName('Additional
|
|
388
|
+
.setName('Additional call API gallery full path property')
|
|
403
389
|
.setDesc(
|
|
404
390
|
'Enter the full path property for the additional Call API gallery in the final call'
|
|
405
391
|
)
|
|
@@ -256,26 +256,24 @@ export async function processMarkdownContent(
|
|
|
256
256
|
|
|
257
257
|
new Notice('Article content generated successfully!')
|
|
258
258
|
try {
|
|
259
|
-
const response = await
|
|
260
|
-
useAdditionalCallAPI
|
|
259
|
+
const response = await this.app.requestUrl({
|
|
260
|
+
url: useAdditionalCallAPI
|
|
261
261
|
? settings.additionalUrl
|
|
262
262
|
: settings.strapiArticleCreateUrl,
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
)
|
|
263
|
+
method: 'POST',
|
|
264
|
+
headers: {
|
|
265
|
+
'Content-Type': 'application/json',
|
|
266
|
+
Authorization: `Bearer ${settings.strapiApiToken}`,
|
|
267
|
+
},
|
|
268
|
+
body: JSON.stringify(articleContent),
|
|
269
|
+
})
|
|
272
270
|
|
|
273
|
-
if (response.
|
|
271
|
+
if (response.status === 200) {
|
|
274
272
|
new Notice(
|
|
275
273
|
'Check your API content now, the article is created & uploaded! 🎉'
|
|
276
274
|
)
|
|
277
275
|
} else {
|
|
278
|
-
const errorData = await response.json
|
|
276
|
+
const errorData = await response.json
|
|
279
277
|
new Notice(
|
|
280
278
|
`Failed to create article in Strapi. Error: ${errorData.error.message}`
|
|
281
279
|
)
|
|
@@ -31,7 +31,8 @@ export async function uploadImagesToStrapi(
|
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
try {
|
|
34
|
-
const response = await
|
|
34
|
+
const response = await this.app.requestUrl({
|
|
35
|
+
url: `${settings.strapiUrl}/api/upload`,
|
|
35
36
|
method: 'POST',
|
|
36
37
|
headers: {
|
|
37
38
|
Authorization: `Bearer ${settings.strapiApiToken}`,
|
|
@@ -39,15 +40,15 @@ export async function uploadImagesToStrapi(
|
|
|
39
40
|
body: formData,
|
|
40
41
|
})
|
|
41
42
|
|
|
42
|
-
if (response.
|
|
43
|
-
const data = await response.json
|
|
43
|
+
if (response.status === 200) {
|
|
44
|
+
const data = await response.json
|
|
44
45
|
uploadedImages[imageDescription.name] = {
|
|
45
46
|
url: data[0].url,
|
|
46
47
|
data: data[0],
|
|
47
48
|
id: data[0].id,
|
|
48
49
|
}
|
|
49
50
|
} else {
|
|
50
|
-
const errorData = await response.json
|
|
51
|
+
const errorData = await response.json
|
|
51
52
|
new Notice(
|
|
52
53
|
`Failed to upload image: ${imageDescription.name}. Error: ${errorData.error.message}`
|
|
53
54
|
)
|
|
@@ -94,7 +95,8 @@ export async function uploadGalleryImagesToStrapi(
|
|
|
94
95
|
formData.append('files', imageBlob.blob, imageBlob.name)
|
|
95
96
|
|
|
96
97
|
try {
|
|
97
|
-
const response = await
|
|
98
|
+
const response = await this.app.requestUrl({
|
|
99
|
+
url: `${settings.strapiUrl}/api/upload`,
|
|
98
100
|
method: 'POST',
|
|
99
101
|
headers: {
|
|
100
102
|
Authorization: `Bearer ${settings.strapiApiToken}`,
|
|
@@ -102,15 +104,15 @@ export async function uploadGalleryImagesToStrapi(
|
|
|
102
104
|
body: formData,
|
|
103
105
|
})
|
|
104
106
|
|
|
105
|
-
if (response.
|
|
106
|
-
const data = await response.json
|
|
107
|
+
if (response.status === 200) {
|
|
108
|
+
const data = await response.json
|
|
107
109
|
uploadedImages[imageBlob.name] = {
|
|
108
110
|
url: data[0].url,
|
|
109
111
|
id: data[0].id,
|
|
110
112
|
data: data[0],
|
|
111
113
|
}
|
|
112
114
|
} else {
|
|
113
|
-
const errorData = await response.json
|
|
115
|
+
const errorData = await response.json
|
|
114
116
|
new Notice(
|
|
115
117
|
`Failed to upload gallery image: ${imageBlob.name}. Error: ${errorData.error.message}`
|
|
116
118
|
)
|