notes-to-strapi-export-article-ai 1.0.18 → 1.0.20
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 +1 -1
- package/src/main.ts +6 -8
- package/src/settings.ts +58 -72
- 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.20",
|
|
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.20",
|
|
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": {
|
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,20 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
77
71
|
)
|
|
78
72
|
|
|
79
73
|
new Setting(containerEl)
|
|
80
|
-
.setName('
|
|
74
|
+
.setName('Strapi article create URL')
|
|
75
|
+
.setDesc('Enter the URL to create articles in Strapi')
|
|
76
|
+
.addText(text =>
|
|
77
|
+
text
|
|
78
|
+
.setPlaceholder('https://your-strapi-url/api/articles')
|
|
79
|
+
.setValue(this.plugin.settings.strapiArticleCreateUrl)
|
|
80
|
+
.onChange(async value => {
|
|
81
|
+
this.plugin.settings.strapiArticleCreateUrl = value
|
|
82
|
+
await this.plugin.saveSettings()
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
new Setting(containerEl)
|
|
87
|
+
.setName('JSON template')
|
|
81
88
|
.setDesc('Enter the JSON template for the fields needed')
|
|
82
89
|
.addTextArea(text =>
|
|
83
90
|
text
|
|
@@ -87,17 +94,12 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
87
94
|
if (validateJsonTemplate(value)) {
|
|
88
95
|
this.plugin.settings.jsonTemplate = value
|
|
89
96
|
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
97
|
}
|
|
96
98
|
})
|
|
97
99
|
)
|
|
98
100
|
|
|
99
101
|
new Setting(containerEl)
|
|
100
|
-
.setName('JSON
|
|
102
|
+
.setName('JSON template description')
|
|
101
103
|
.setDesc('Enter the description for each field in the JSON template')
|
|
102
104
|
.addTextArea(text =>
|
|
103
105
|
text
|
|
@@ -110,20 +112,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
110
112
|
)
|
|
111
113
|
|
|
112
114
|
new Setting(containerEl)
|
|
113
|
-
.setName('Strapi
|
|
114
|
-
.setDesc('Enter the URL to create articles in Strapi')
|
|
115
|
-
.addText(text =>
|
|
116
|
-
text
|
|
117
|
-
.setPlaceholder('https://your-strapi-url/api/articles')
|
|
118
|
-
.setValue(this.plugin.settings.strapiArticleCreateUrl)
|
|
119
|
-
.onChange(async value => {
|
|
120
|
-
this.plugin.settings.strapiArticleCreateUrl = value
|
|
121
|
-
await this.plugin.saveSettings()
|
|
122
|
-
})
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
new Setting(containerEl)
|
|
126
|
-
.setName('Strapi Content Attribute Name')
|
|
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,20 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
254
243
|
|
|
255
244
|
if (this.plugin.settings.enableAdditionalApiCall) {
|
|
256
245
|
new Setting(containerEl)
|
|
257
|
-
.setName('Additional
|
|
246
|
+
.setName('Additional API URL')
|
|
247
|
+
.setDesc('Enter the URL to create content for the additional API')
|
|
248
|
+
.addText(text =>
|
|
249
|
+
text
|
|
250
|
+
.setPlaceholder('https://your-strapi-url/api/additional-content')
|
|
251
|
+
.setValue(this.plugin.settings.additionalUrl)
|
|
252
|
+
.onChange(async value => {
|
|
253
|
+
this.plugin.settings.additionalUrl = value
|
|
254
|
+
await this.plugin.saveSettings()
|
|
255
|
+
})
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
new Setting(containerEl)
|
|
259
|
+
.setName('Additional JSON template')
|
|
258
260
|
.setDesc(
|
|
259
261
|
'Enter the JSON template for the fields needed for the additional api'
|
|
260
262
|
)
|
|
@@ -266,17 +268,12 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
266
268
|
if (validateJsonTemplate(value)) {
|
|
267
269
|
this.plugin.settings.additionalJsonTemplate = value
|
|
268
270
|
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
271
|
}
|
|
275
272
|
})
|
|
276
273
|
)
|
|
277
274
|
|
|
278
275
|
new Setting(containerEl)
|
|
279
|
-
.setName('Additional API JSON
|
|
276
|
+
.setName('Additional API JSON template description')
|
|
280
277
|
.setDesc(
|
|
281
278
|
'Enter the description for each field in the additional API JSON template'
|
|
282
279
|
)
|
|
@@ -291,20 +288,7 @@ export class StrapiExporterSettingTab extends PluginSettingTab {
|
|
|
291
288
|
)
|
|
292
289
|
|
|
293
290
|
new Setting(containerEl)
|
|
294
|
-
.setName('Additional API
|
|
295
|
-
.setDesc('Enter the URL to create content for the additional API')
|
|
296
|
-
.addText(text =>
|
|
297
|
-
text
|
|
298
|
-
.setPlaceholder('https://your-strapi-url/api/additional-content')
|
|
299
|
-
.setValue(this.plugin.settings.additionalUrl)
|
|
300
|
-
.onChange(async value => {
|
|
301
|
-
this.plugin.settings.additionalUrl = value
|
|
302
|
-
await this.plugin.saveSettings()
|
|
303
|
-
})
|
|
304
|
-
)
|
|
305
|
-
|
|
306
|
-
new Setting(containerEl)
|
|
307
|
-
.setName('Additional API Content Attribute Name')
|
|
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
|
)
|