notes-to-strapi-export-article-ai 1.0.119 → 3.0.0
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
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface RouteConfig {
|
|
2
|
+
id: string
|
|
3
|
+
name: string
|
|
4
|
+
icon: string
|
|
5
|
+
enabled: boolean
|
|
6
|
+
url: string
|
|
7
|
+
|
|
8
|
+
// Content Configuration
|
|
9
|
+
contentType: string
|
|
10
|
+
contentField: string
|
|
11
|
+
description: string
|
|
12
|
+
subtitle: string
|
|
13
|
+
|
|
14
|
+
// Schema Configuration
|
|
15
|
+
schema: string
|
|
16
|
+
schemaDescription: string
|
|
17
|
+
generatedConfig: string
|
|
18
|
+
language: string
|
|
19
|
+
|
|
20
|
+
// Field Mappings
|
|
21
|
+
fieldMappings: Record<string, FieldMapping>
|
|
22
|
+
additionalInstructions?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface FieldMapping {
|
|
26
|
+
obsidianSource: 'frontmatter' | 'content'
|
|
27
|
+
frontmatterKey?: string
|
|
28
|
+
type?: string
|
|
29
|
+
format?: string
|
|
30
|
+
required?: boolean
|
|
31
|
+
transform?: string | ((value: any) => any) // Support des transformations fonction ou string
|
|
32
|
+
validation?: {
|
|
33
|
+
type: string
|
|
34
|
+
pattern?: string
|
|
35
|
+
min?: number
|
|
36
|
+
max?: number
|
|
37
|
+
}
|
|
38
|
+
value?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface RouteConfig {
|
|
42
|
+
id: string
|
|
43
|
+
name: string
|
|
44
|
+
schema: string
|
|
45
|
+
schemaDescription: string
|
|
46
|
+
generatedConfig: string
|
|
47
|
+
language: string
|
|
48
|
+
contentField: string
|
|
49
|
+
fieldMappings: Record<string, FieldMapping>
|
|
50
|
+
additionalInstructions?: string
|
|
51
|
+
}
|
package/src/types/settings.ts
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*/
|
|
1
|
+
import { RouteConfig } from './route'
|
|
2
|
+
|
|
4
3
|
export interface StrapiExporterSettings {
|
|
4
|
+
// API Settings
|
|
5
5
|
strapiUrl: string
|
|
6
6
|
strapiApiToken: string
|
|
7
|
+
forvoyezApiKey: string
|
|
7
8
|
openaiApiKey: string
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
additionalImageFullPathProperty: string
|
|
27
|
-
additionalGalleryFullPathProperty: string
|
|
9
|
+
|
|
10
|
+
// UI Settings
|
|
11
|
+
currentTab: string
|
|
12
|
+
|
|
13
|
+
// Routes Configuration
|
|
14
|
+
routes: RouteConfig[]
|
|
15
|
+
|
|
16
|
+
lastExport?: {
|
|
17
|
+
date: string
|
|
18
|
+
status: 'success' | 'failure'
|
|
19
|
+
message?: string
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AnalyzedContent {
|
|
24
|
+
[key: string]: any
|
|
25
|
+
content?: string
|
|
26
|
+
meta?: Record<string, any>
|
|
28
27
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { TFile, App } from 'obsidian'
|
|
2
|
+
import { RouteConfig, AnalyzedContent } from '../types'
|
|
3
|
+
import * as yaml from 'js-yaml'
|
|
4
|
+
|
|
5
|
+
export async function analyzeFile(
|
|
6
|
+
file: TFile,
|
|
7
|
+
app: App,
|
|
8
|
+
route: RouteConfig
|
|
9
|
+
): Promise<AnalyzedContent> {
|
|
10
|
+
try {
|
|
11
|
+
// Reading file content
|
|
12
|
+
const content = await app.vault.read(file)
|
|
13
|
+
|
|
14
|
+
// Extracting frontmatter and content
|
|
15
|
+
const { frontmatter, body } = extractFrontMatterAndContent(content)
|
|
16
|
+
|
|
17
|
+
// Initialize result with existing frontmatter
|
|
18
|
+
const result: AnalyzedContent = {
|
|
19
|
+
...frontmatter, // Copy all existing frontmatter fields
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Processing field mappings
|
|
23
|
+
for (const [strapiField, mapping] of Object.entries(route.fieldMappings)) {
|
|
24
|
+
// Only override if mapping exists and field is not already set
|
|
25
|
+
if (mapping.obsidianSource === 'frontmatter' && mapping.frontmatterKey) {
|
|
26
|
+
// Only set if not already present
|
|
27
|
+
if (result[strapiField] === undefined) {
|
|
28
|
+
result[strapiField] = frontmatter[mapping.frontmatterKey] ?? null
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Handle content fields
|
|
32
|
+
else if (mapping.obsidianSource === 'content') {
|
|
33
|
+
result[strapiField] = body
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Apply transformations
|
|
37
|
+
if (mapping.transform && result[strapiField] !== null) {
|
|
38
|
+
try {
|
|
39
|
+
result[strapiField] = await applyTransformation(
|
|
40
|
+
result[strapiField],
|
|
41
|
+
mapping.transform,
|
|
42
|
+
strapiField
|
|
43
|
+
)
|
|
44
|
+
} catch (error) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Failed to transform field ${strapiField}: ${error.message}`
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result
|
|
52
|
+
} catch (error) {
|
|
53
|
+
throw new Error(`File analysis failed: ${error.message}`)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function applyTransformation(
|
|
58
|
+
value: any,
|
|
59
|
+
transform: string | ((value: any) => any),
|
|
60
|
+
fieldName: string
|
|
61
|
+
): Promise<any> {
|
|
62
|
+
try {
|
|
63
|
+
if (typeof transform === 'function') {
|
|
64
|
+
return transform(value)
|
|
65
|
+
} else if (typeof transform === 'string') {
|
|
66
|
+
const transformFunction = new Function('value', `return ${transform}`)
|
|
67
|
+
return transformFunction(value)
|
|
68
|
+
}
|
|
69
|
+
return value
|
|
70
|
+
} catch (error) {
|
|
71
|
+
throw new Error(`Transformation failed: ${error.message}`)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function extractFrontMatterAndContent(fileContent: string): {
|
|
76
|
+
frontmatter: Record<string, any>
|
|
77
|
+
body: string
|
|
78
|
+
} {
|
|
79
|
+
const frontMatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/
|
|
80
|
+
const match = fileContent.match(frontMatterRegex)
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
if (match) {
|
|
84
|
+
const frontmatter = yaml.load(match[1]) as Record<string, any>
|
|
85
|
+
const body = match[2].trim()
|
|
86
|
+
|
|
87
|
+
return { frontmatter, body }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { frontmatter: {}, body: fileContent.trim() }
|
|
91
|
+
} catch (error) {
|
|
92
|
+
throw new Error(`Failed to parse frontmatter: ${error.message}`)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a debounced version of the provided function
|
|
3
|
+
* @param func The function to debounce
|
|
4
|
+
* @param waitFor The time to wait in milliseconds
|
|
5
|
+
* @returns A debounced version of the function that returns a promise
|
|
6
|
+
*/
|
|
7
|
+
export function debounce<F extends (...args: any[]) => any>(
|
|
8
|
+
func: F,
|
|
9
|
+
waitFor: number
|
|
10
|
+
): (...args: Parameters<F>) => Promise<ReturnType<F>> {
|
|
11
|
+
let timeout: ReturnType<typeof setTimeout> | null = null
|
|
12
|
+
|
|
13
|
+
return (...args: Parameters<F>): Promise<ReturnType<F>> => {
|
|
14
|
+
// Clear existing timeout if any
|
|
15
|
+
if (timeout) {
|
|
16
|
+
clearTimeout(timeout)
|
|
17
|
+
timeout = null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Create new promise
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
timeout = setTimeout(async () => {
|
|
23
|
+
try {
|
|
24
|
+
const result = await func(...args)
|
|
25
|
+
resolve(result)
|
|
26
|
+
} catch (error) {
|
|
27
|
+
reject(error)
|
|
28
|
+
} finally {
|
|
29
|
+
timeout = null
|
|
30
|
+
}
|
|
31
|
+
}, waitFor)
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
}
|