ontowave 1.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/LICENSE +21 -0
- package/README.md +0 -0
- package/README.md.backup +260 -0
- package/dist/ontowave.js +3057 -0
- package/dist/ontowave.min.js +1278 -0
- package/package.json +98 -0
package/dist/ontowave.js
ADDED
|
@@ -0,0 +1,3057 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OntoWave - Documentation Interactive Package
|
|
3
|
+
* Version: 1.0.0
|
|
4
|
+
* URL: https://github.com/stephanedenis/OntoWave
|
|
5
|
+
*
|
|
6
|
+
* Usage simple:
|
|
7
|
+
* <script src="https://cdn.jsdelivr.net/npm/ontowave@latest/dist/ontowave.min.js"></script>
|
|
8
|
+
* <script type="application/json" id="ontowave-config">
|
|
9
|
+
* {
|
|
10
|
+
* "title": "Ma Documentation",
|
|
11
|
+
* "baseUrl": "/",
|
|
12
|
+
* "defaultPage": "index.md",
|
|
13
|
+
* "mermaid": { "theme": "default" },
|
|
14
|
+
* "plantuml": { "server": "https://www.plantuml.com/plantuml" }
|
|
15
|
+
* }
|
|
16
|
+
* </script>
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
(function(window) {
|
|
20
|
+
'use strict';
|
|
21
|
+
|
|
22
|
+
// Traductions pour l'interface
|
|
23
|
+
const TRANSLATIONS = {
|
|
24
|
+
fr: {
|
|
25
|
+
// Menu
|
|
26
|
+
menuHome: "Accueil",
|
|
27
|
+
menuGallery: "Galerie",
|
|
28
|
+
menuConfiguration: "Configuration",
|
|
29
|
+
|
|
30
|
+
// Panneau de configuration
|
|
31
|
+
configTitle: "OntoWave - Configuration Complète",
|
|
32
|
+
configGeneral: "Général",
|
|
33
|
+
configSiteTitle: "Titre du site :",
|
|
34
|
+
configDefaultPage: "Page par défaut :",
|
|
35
|
+
configBaseUrl: "URL de base :",
|
|
36
|
+
configLanguages: "Langues et Localisation",
|
|
37
|
+
configSupportedLanguages: "Langues supportées (séparées par des virgules) :",
|
|
38
|
+
configFallbackLanguage: "Langue de fallback :",
|
|
39
|
+
configNavigation: "Navigation et Interface",
|
|
40
|
+
configShowGallery: "Afficher la galerie d'exemples",
|
|
41
|
+
configHomeButton: "Bouton Accueil",
|
|
42
|
+
configBreadcrumb: "Fil d'Ariane (breadcrumb)",
|
|
43
|
+
configToc: "Table des matières",
|
|
44
|
+
configMermaid: "Diagrammes Mermaid",
|
|
45
|
+
configMermaidTheme: "Thème Mermaid :",
|
|
46
|
+
configMermaidAuto: "Démarrage automatique",
|
|
47
|
+
configMermaidMaxWidth: "Utiliser la largeur maximale",
|
|
48
|
+
configPlantuml: "Diagrammes PlantUML",
|
|
49
|
+
configPlantumlServer: "Serveur PlantUML :",
|
|
50
|
+
configPlantumlFormat: "Format de sortie :",
|
|
51
|
+
configPrism: "Coloration Syntaxique (Prism.js)",
|
|
52
|
+
configPrismTheme: "Thème Prism :",
|
|
53
|
+
configPrismAutoload: "Chargement automatique",
|
|
54
|
+
configUI: "Interface Utilisateur",
|
|
55
|
+
configUITheme: "Thème de l'interface :",
|
|
56
|
+
configUIResponsive: "Design responsive",
|
|
57
|
+
configUIAnimations: "Animations et transitions",
|
|
58
|
+
configApply: "Appliquer Configuration",
|
|
59
|
+
configDownloadHTML: "Télécharger HTML",
|
|
60
|
+
configDownloadJS: "Télécharger ontowave.min.js",
|
|
61
|
+
configReset: "Réinitialiser",
|
|
62
|
+
configLanguageNote: "Laissez vide pour un site monolingue"
|
|
63
|
+
},
|
|
64
|
+
en: {
|
|
65
|
+
// Menu
|
|
66
|
+
menuHome: "Home",
|
|
67
|
+
menuGallery: "Gallery",
|
|
68
|
+
menuConfiguration: "Configuration",
|
|
69
|
+
|
|
70
|
+
// Configuration Panel
|
|
71
|
+
configTitle: "OntoWave - Complete Configuration",
|
|
72
|
+
configGeneral: "General",
|
|
73
|
+
configSiteTitle: "Site title:",
|
|
74
|
+
configDefaultPage: "Default page:",
|
|
75
|
+
configBaseUrl: "Base URL:",
|
|
76
|
+
configLanguages: "Languages and Localization",
|
|
77
|
+
configSupportedLanguages: "Supported languages (comma separated):",
|
|
78
|
+
configFallbackLanguage: "Fallback language:",
|
|
79
|
+
configNavigation: "Navigation and Interface",
|
|
80
|
+
configShowGallery: "Show examples gallery",
|
|
81
|
+
configHomeButton: "Home button",
|
|
82
|
+
configBreadcrumb: "Breadcrumb navigation",
|
|
83
|
+
configToc: "Table of contents",
|
|
84
|
+
configMermaid: "Mermaid Diagrams",
|
|
85
|
+
configMermaidTheme: "Mermaid theme:",
|
|
86
|
+
configMermaidAuto: "Auto start",
|
|
87
|
+
configMermaidMaxWidth: "Use maximum width",
|
|
88
|
+
configPlantuml: "PlantUML Diagrams",
|
|
89
|
+
configPlantumlServer: "PlantUML server:",
|
|
90
|
+
configPlantumlFormat: "Output format:",
|
|
91
|
+
configPrism: "Syntax Highlighting (Prism.js)",
|
|
92
|
+
configPrismTheme: "Prism theme:",
|
|
93
|
+
configPrismAutoload: "Auto loading",
|
|
94
|
+
configUI: "User Interface",
|
|
95
|
+
configUITheme: "Interface theme:",
|
|
96
|
+
configUIResponsive: "Responsive design",
|
|
97
|
+
configUIAnimations: "Animations and transitions",
|
|
98
|
+
configApply: "Apply Configuration",
|
|
99
|
+
configDownloadHTML: "Download HTML",
|
|
100
|
+
configDownloadJS: "Download ontowave.min.js",
|
|
101
|
+
configReset: "Reset",
|
|
102
|
+
configLanguageNote: "Leave empty for monolingual site"
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Configuration par défaut
|
|
107
|
+
const DEFAULT_CONFIG = {
|
|
108
|
+
title: "OntoWave Documentation",
|
|
109
|
+
baseUrl: "/",
|
|
110
|
+
defaultPage: "index.md",
|
|
111
|
+
containerId: "ontowave-container",
|
|
112
|
+
locales: ["fr", "en"], // Langues supportées par défaut
|
|
113
|
+
fallbackLocale: "en",
|
|
114
|
+
showGallery: false, // Gallerie désactivée par défaut
|
|
115
|
+
mermaid: {
|
|
116
|
+
theme: "default",
|
|
117
|
+
startOnLoad: true,
|
|
118
|
+
flowchart: { useMaxWidth: true },
|
|
119
|
+
sequence: { useMaxWidth: true },
|
|
120
|
+
gantt: { useMaxWidth: true },
|
|
121
|
+
journey: { useMaxWidth: true }
|
|
122
|
+
},
|
|
123
|
+
plantuml: {
|
|
124
|
+
server: "https://www.plantuml.com/plantuml",
|
|
125
|
+
format: "svg"
|
|
126
|
+
},
|
|
127
|
+
prism: {
|
|
128
|
+
theme: "default",
|
|
129
|
+
autoload: true
|
|
130
|
+
},
|
|
131
|
+
navigation: {
|
|
132
|
+
showHome: true,
|
|
133
|
+
showBreadcrumb: true,
|
|
134
|
+
showToc: true
|
|
135
|
+
},
|
|
136
|
+
ui: {
|
|
137
|
+
theme: "default",
|
|
138
|
+
responsive: true,
|
|
139
|
+
animations: true,
|
|
140
|
+
languageButtons: "menu" // "fixed", "menu", "both"
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// Styles CSS intégrés
|
|
145
|
+
const CSS_STYLES = `
|
|
146
|
+
.ontowave-container {
|
|
147
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
|
|
148
|
+
line-height: 1.6;
|
|
149
|
+
color: #24292e;
|
|
150
|
+
background: #fff;
|
|
151
|
+
margin: 0;
|
|
152
|
+
padding: 20px;
|
|
153
|
+
min-height: 100vh;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* Menu flottant minimal déplaçable */
|
|
157
|
+
.ontowave-floating-menu {
|
|
158
|
+
position: fixed;
|
|
159
|
+
top: 20px;
|
|
160
|
+
left: 20px;
|
|
161
|
+
z-index: 1000;
|
|
162
|
+
background: rgba(255, 255, 255, 0.95);
|
|
163
|
+
backdrop-filter: blur(10px);
|
|
164
|
+
border: 1px solid #e1e4e8;
|
|
165
|
+
border-radius: 44px;
|
|
166
|
+
padding: 10px;
|
|
167
|
+
box-shadow: 0 4px 12px rgba(27,31,35,0.15);
|
|
168
|
+
cursor: move;
|
|
169
|
+
transition: all 0.3s ease;
|
|
170
|
+
font-size: 1.2em;
|
|
171
|
+
user-select: none;
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
gap: 0;
|
|
175
|
+
width: 44px;
|
|
176
|
+
height: 44px;
|
|
177
|
+
overflow: visible;
|
|
178
|
+
white-space: nowrap;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.ontowave-floating-menu.no-drag {
|
|
182
|
+
cursor: default;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.ontowave-floating-menu.expanded {
|
|
186
|
+
width: auto;
|
|
187
|
+
height: auto;
|
|
188
|
+
min-height: 44px;
|
|
189
|
+
border-radius: 22px;
|
|
190
|
+
padding: 10px 18px;
|
|
191
|
+
gap: 10px;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.ontowave-floating-menu:hover {
|
|
195
|
+
transform: scale(1.05);
|
|
196
|
+
box-shadow: 0 6px 20px rgba(27,31,35,0.25);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Désactiver le zoom quand le panneau de configuration est ouvert */
|
|
200
|
+
.ontowave-floating-menu.has-config-panel:hover {
|
|
201
|
+
transform: none;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.ontowave-menu-icon {
|
|
205
|
+
cursor: pointer;
|
|
206
|
+
transition: transform 0.3s ease;
|
|
207
|
+
flex-shrink: 0;
|
|
208
|
+
width: 30px;
|
|
209
|
+
height: 30px;
|
|
210
|
+
display: flex;
|
|
211
|
+
align-items: center;
|
|
212
|
+
justify-content: center;
|
|
213
|
+
font-size: 1.4em;
|
|
214
|
+
text-align: center;
|
|
215
|
+
line-height: 1;
|
|
216
|
+
margin: 0 auto;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.ontowave-menu-icon:hover {
|
|
220
|
+
transform: scale(1.2);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.ontowave-menu-content {
|
|
224
|
+
display: flex;
|
|
225
|
+
align-items: center;
|
|
226
|
+
gap: 15px;
|
|
227
|
+
opacity: 0;
|
|
228
|
+
width: 0;
|
|
229
|
+
overflow: hidden;
|
|
230
|
+
transition: all 0.3s ease;
|
|
231
|
+
white-space: nowrap;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.ontowave-floating-menu.expanded .ontowave-menu-content {
|
|
235
|
+
opacity: 1;
|
|
236
|
+
width: auto;
|
|
237
|
+
overflow: visible;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.ontowave-menu-brand {
|
|
241
|
+
font-weight: 600;
|
|
242
|
+
color: #0969da;
|
|
243
|
+
text-decoration: none;
|
|
244
|
+
cursor: pointer;
|
|
245
|
+
font-size: 0.9em;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.ontowave-menu-brand:hover {
|
|
249
|
+
color: #0550ae;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.org-suffix {
|
|
253
|
+
font-size: 0.7em;
|
|
254
|
+
opacity: 0.7;
|
|
255
|
+
font-weight: normal;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.ontowave-menu-options {
|
|
259
|
+
display: flex;
|
|
260
|
+
gap: 8px;
|
|
261
|
+
flex-wrap: nowrap;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.ontowave-menu-option {
|
|
265
|
+
padding: 6px 10px;
|
|
266
|
+
background: #f8f9fa;
|
|
267
|
+
border: 1px solid #d0d7de;
|
|
268
|
+
border-radius: 15px;
|
|
269
|
+
font-size: 0.75em;
|
|
270
|
+
cursor: pointer;
|
|
271
|
+
transition: all 0.2s ease;
|
|
272
|
+
white-space: nowrap;
|
|
273
|
+
pointer-events: auto;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.ontowave-menu-option:hover {
|
|
277
|
+
background: #e2e8f0;
|
|
278
|
+
transform: translateY(-1px);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.ontowave-menu-option.selected {
|
|
282
|
+
background: #0969da;
|
|
283
|
+
color: white;
|
|
284
|
+
border-color: #0969da;
|
|
285
|
+
box-shadow: 0 2px 8px rgba(9, 105, 218, 0.3);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.ontowave-menu-option.selected:hover {
|
|
289
|
+
background: #0550ae;
|
|
290
|
+
border-color: #0550ae;
|
|
291
|
+
transform: translateY(-1px);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* Styles pour les boutons de langue */
|
|
295
|
+
.ontowave-lang-btn {
|
|
296
|
+
font-weight: bold;
|
|
297
|
+
font-size: 11px;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.ontowave-lang-btn.active {
|
|
301
|
+
background: #28a745;
|
|
302
|
+
color: white;
|
|
303
|
+
border-color: #28a745;
|
|
304
|
+
box-shadow: 0 2px 8px rgba(40, 167, 69, 0.3);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.ontowave-lang-btn.active:hover {
|
|
308
|
+
background: #1e7e34;
|
|
309
|
+
border-color: #1e7e34;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/* Boutons de langue fixés - nouveaux styles */
|
|
313
|
+
.ontowave-fixed-lang-buttons {
|
|
314
|
+
position: fixed;
|
|
315
|
+
top: 20px;
|
|
316
|
+
right: 20px;
|
|
317
|
+
z-index: 999;
|
|
318
|
+
display: flex;
|
|
319
|
+
gap: 8px;
|
|
320
|
+
background: rgba(255, 255, 255, 0.95);
|
|
321
|
+
padding: 8px 12px;
|
|
322
|
+
border-radius: 25px;
|
|
323
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
324
|
+
backdrop-filter: blur(10px);
|
|
325
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/* Responsive : adaptation mobile */
|
|
329
|
+
@media (max-width: 768px) {
|
|
330
|
+
.ontowave-fixed-lang-buttons {
|
|
331
|
+
top: 10px;
|
|
332
|
+
right: 10px;
|
|
333
|
+
padding: 6px 8px;
|
|
334
|
+
gap: 4px;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.ontowave-fixed-lang-btn {
|
|
339
|
+
background: linear-gradient(135deg, #6c757d 0%, #495057 100%);
|
|
340
|
+
color: white;
|
|
341
|
+
border: none;
|
|
342
|
+
padding: 6px 12px;
|
|
343
|
+
border-radius: 15px;
|
|
344
|
+
font-size: 12px;
|
|
345
|
+
font-weight: bold;
|
|
346
|
+
cursor: pointer;
|
|
347
|
+
transition: all 0.3s ease;
|
|
348
|
+
text-decoration: none;
|
|
349
|
+
display: flex;
|
|
350
|
+
align-items: center;
|
|
351
|
+
gap: 4px;
|
|
352
|
+
min-width: 40px;
|
|
353
|
+
justify-content: center;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/* Responsive : boutons plus petits sur mobile */
|
|
357
|
+
@media (max-width: 768px) {
|
|
358
|
+
.ontowave-fixed-lang-btn {
|
|
359
|
+
padding: 4px 8px;
|
|
360
|
+
font-size: 11px;
|
|
361
|
+
min-width: 35px;
|
|
362
|
+
gap: 2px;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.ontowave-fixed-lang-btn:hover {
|
|
367
|
+
background: linear-gradient(135deg, #5a6268 0%, #343a40 100%);
|
|
368
|
+
transform: translateY(-2px);
|
|
369
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.ontowave-fixed-lang-btn.active {
|
|
373
|
+
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
|
|
374
|
+
box-shadow: 0 4px 12px rgba(40, 167, 69, 0.4);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.ontowave-fixed-lang-btn.active:hover {
|
|
378
|
+
background: linear-gradient(135deg, #1e7e34 0%, #198754 100%);
|
|
379
|
+
transform: translateY(-2px);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/* Pas d'en-tête - supprimé */
|
|
383
|
+
.ontowave-header {
|
|
384
|
+
display: none;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.ontowave-nav {
|
|
388
|
+
background: #f8f9fa;
|
|
389
|
+
border: 1px solid #e1e4e8;
|
|
390
|
+
border-radius: 8px;
|
|
391
|
+
padding: 1.5rem;
|
|
392
|
+
margin-bottom: 2rem;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.ontowave-nav h3 {
|
|
396
|
+
margin: 0 0 1rem 0;
|
|
397
|
+
color: #24292e;
|
|
398
|
+
display: flex;
|
|
399
|
+
align-items: center;
|
|
400
|
+
gap: 0.5rem;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.ontowave-nav-grid {
|
|
404
|
+
display: grid;
|
|
405
|
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
406
|
+
gap: 1rem;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.ontowave-nav-item {
|
|
410
|
+
padding: 1rem;
|
|
411
|
+
background: white;
|
|
412
|
+
border: 1px solid #d0d7de;
|
|
413
|
+
border-radius: 6px;
|
|
414
|
+
text-decoration: none;
|
|
415
|
+
color: #24292e;
|
|
416
|
+
display: flex;
|
|
417
|
+
align-items: center;
|
|
418
|
+
gap: 0.5rem;
|
|
419
|
+
transition: all 0.2s ease;
|
|
420
|
+
font-weight: 500;
|
|
421
|
+
cursor: pointer;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.ontowave-nav-item:hover {
|
|
425
|
+
background: #f3f4f6;
|
|
426
|
+
border-color: #0969da;
|
|
427
|
+
transform: translateY(-2px);
|
|
428
|
+
box-shadow: 0 4px 12px rgba(27,31,35,0.15);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.ontowave-content {
|
|
432
|
+
background: white;
|
|
433
|
+
padding: 2rem;
|
|
434
|
+
border-radius: 8px;
|
|
435
|
+
box-shadow: 0 2px 8px rgba(27,31,35,0.15);
|
|
436
|
+
border: 1px solid #e1e4e8;
|
|
437
|
+
margin-bottom: 2rem;
|
|
438
|
+
min-height: 300px;
|
|
439
|
+
max-width: 1200px;
|
|
440
|
+
margin-left: auto;
|
|
441
|
+
margin-right: auto;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/* Headers corrigés */
|
|
445
|
+
.ontowave-content h1 {
|
|
446
|
+
color: #24292e;
|
|
447
|
+
border-bottom: 2px solid #e1e4e8;
|
|
448
|
+
padding-bottom: 8px;
|
|
449
|
+
margin-bottom: 16px;
|
|
450
|
+
font-size: 2em;
|
|
451
|
+
font-weight: 600;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.ontowave-content h2 {
|
|
455
|
+
color: #24292e;
|
|
456
|
+
margin-top: 24px;
|
|
457
|
+
margin-bottom: 16px;
|
|
458
|
+
font-size: 1.5em;
|
|
459
|
+
font-weight: 600;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.ontowave-content h3 {
|
|
463
|
+
color: #24292e;
|
|
464
|
+
margin-top: 20px;
|
|
465
|
+
margin-bottom: 12px;
|
|
466
|
+
font-size: 1.25em;
|
|
467
|
+
font-weight: 600;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.ontowave-content h4 {
|
|
471
|
+
color: #24292e;
|
|
472
|
+
margin-top: 16px;
|
|
473
|
+
margin-bottom: 10px;
|
|
474
|
+
font-size: 1.1em;
|
|
475
|
+
font-weight: 600;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.ontowave-content h5 {
|
|
479
|
+
color: #24292e;
|
|
480
|
+
margin-top: 14px;
|
|
481
|
+
margin-bottom: 8px;
|
|
482
|
+
font-size: 1em;
|
|
483
|
+
font-weight: 600;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.ontowave-content h6 {
|
|
487
|
+
color: #24292e;
|
|
488
|
+
margin-top: 12px;
|
|
489
|
+
margin-bottom: 6px;
|
|
490
|
+
font-size: 0.9em;
|
|
491
|
+
font-weight: 600;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/* Séparateurs hr */
|
|
495
|
+
.ontowave-content hr {
|
|
496
|
+
border: none;
|
|
497
|
+
border-top: 1px solid #e1e4e8;
|
|
498
|
+
margin: 24px 0;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/* Mermaid diagrams */
|
|
502
|
+
.ontowave-mermaid {
|
|
503
|
+
margin: 20px 0;
|
|
504
|
+
padding: 20px;
|
|
505
|
+
background: #f8f9fa;
|
|
506
|
+
border: 1px solid #e1e4e8;
|
|
507
|
+
border-radius: 8px;
|
|
508
|
+
text-align: center;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.ontowave-loading {
|
|
512
|
+
text-align: center;
|
|
513
|
+
color: #666;
|
|
514
|
+
padding: 2rem;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.ontowave-error {
|
|
518
|
+
color: #d73a49;
|
|
519
|
+
text-align: center;
|
|
520
|
+
padding: 2rem;
|
|
521
|
+
background: #ffeef0;
|
|
522
|
+
border: 1px solid #fdaeb7;
|
|
523
|
+
border-radius: 6px;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.ontowave-mermaid {
|
|
527
|
+
background: #f6f8fa;
|
|
528
|
+
border: 1px solid #d0d7de;
|
|
529
|
+
border-radius: 6px;
|
|
530
|
+
padding: 1rem;
|
|
531
|
+
margin: 1rem 0;
|
|
532
|
+
text-align: center;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
.ontowave-plantuml {
|
|
536
|
+
background: #f6f8fa;
|
|
537
|
+
border: 1px solid #d0d7de;
|
|
538
|
+
border-radius: 6px;
|
|
539
|
+
padding: 1rem;
|
|
540
|
+
margin: 1rem 0;
|
|
541
|
+
text-align: center;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
.ontowave-plantuml img {
|
|
545
|
+
max-width: 100%;
|
|
546
|
+
height: auto;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
.ontowave-code {
|
|
550
|
+
background: #f6f8fa;
|
|
551
|
+
border: 1px solid #d0d7de;
|
|
552
|
+
border-radius: 6px;
|
|
553
|
+
padding: 1rem;
|
|
554
|
+
margin: 1rem 0;
|
|
555
|
+
overflow-x: auto;
|
|
556
|
+
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.ontowave-breadcrumb {
|
|
560
|
+
padding: 0.5rem 0;
|
|
561
|
+
margin-bottom: 1rem;
|
|
562
|
+
border-bottom: 1px solid #e1e4e8;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.ontowave-breadcrumb a {
|
|
566
|
+
color: #0969da;
|
|
567
|
+
text-decoration: none;
|
|
568
|
+
margin-right: 0.5rem;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.ontowave-breadcrumb a:hover {
|
|
572
|
+
text-decoration: underline;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.ontowave-breadcrumb span {
|
|
576
|
+
color: #656d76;
|
|
577
|
+
margin-right: 0.5rem;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.ontowave-status {
|
|
581
|
+
background: #d4edda;
|
|
582
|
+
border: 1px solid #c3e6cb;
|
|
583
|
+
border-radius: 8px;
|
|
584
|
+
padding: 1rem;
|
|
585
|
+
margin-top: 2rem;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.ontowave-status h4 {
|
|
589
|
+
margin: 0 0 0.5rem 0;
|
|
590
|
+
color: #155724;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.ontowave-status ul {
|
|
594
|
+
margin: 0;
|
|
595
|
+
padding-left: 1.5rem;
|
|
596
|
+
color: #155724;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
@media (max-width: 768px) {
|
|
600
|
+
.ontowave-header {
|
|
601
|
+
padding: 1rem;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.ontowave-header h1 {
|
|
605
|
+
font-size: 2em;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
.ontowave-nav-grid {
|
|
609
|
+
grid-template-columns: 1fr;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.ontowave-content {
|
|
613
|
+
padding: 1rem;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
`;
|
|
617
|
+
|
|
618
|
+
class OntoWave {
|
|
619
|
+
constructor(config = {}) {
|
|
620
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
621
|
+
|
|
622
|
+
// Support pour le format i18n (compatibilité avec config.json)
|
|
623
|
+
if (config.i18n) {
|
|
624
|
+
if (config.i18n.supported) {
|
|
625
|
+
this.config.locales = config.i18n.supported;
|
|
626
|
+
}
|
|
627
|
+
if (config.i18n.default) {
|
|
628
|
+
this.config.fallbackLocale = config.i18n.default;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
this.container = null;
|
|
633
|
+
this.mermaidLoaded = false;
|
|
634
|
+
this.prismLoaded = false;
|
|
635
|
+
this.currentPage = null;
|
|
636
|
+
this.currentLanguage = null; // Langue courante stockée
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Détecte la langue actuelle de l'interface
|
|
641
|
+
*/
|
|
642
|
+
getCurrentLanguage() {
|
|
643
|
+
// Si une langue a été explicitement définie, l'utiliser
|
|
644
|
+
if (this.currentLanguage) {
|
|
645
|
+
return this.currentLanguage;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// Vérifier s'il y a une langue sélectionnée dans l'interface
|
|
649
|
+
const langFr = document.getElementById('lang-fr');
|
|
650
|
+
const langEn = document.getElementById('lang-en');
|
|
651
|
+
|
|
652
|
+
if (langFr && langEn) {
|
|
653
|
+
// Système multilingue détecté - vérifier les classes visible/hidden
|
|
654
|
+
if (langFr.classList.contains('visible') || (!langFr.classList.contains('hidden') && langFr.style.display !== 'none')) {
|
|
655
|
+
return 'fr';
|
|
656
|
+
} else if (langEn.classList.contains('visible') || (!langEn.classList.contains('hidden') && langEn.style.display !== 'none')) {
|
|
657
|
+
return 'en';
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// Fallback - vérifier les boutons actifs
|
|
662
|
+
const btnFr = document.getElementById('btn-fr');
|
|
663
|
+
const btnEn = document.getElementById('btn-en');
|
|
664
|
+
|
|
665
|
+
if (btnFr && btnEn) {
|
|
666
|
+
if (btnFr.classList.contains('active')) {
|
|
667
|
+
return 'fr';
|
|
668
|
+
} else if (btnEn.classList.contains('active')) {
|
|
669
|
+
return 'en';
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Fallback sur les préférences du navigateur
|
|
674
|
+
return this.resolveLocale() || 'en';
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Obtient une traduction pour une langue spécifique ou la langue actuelle
|
|
679
|
+
*/
|
|
680
|
+
t(key, locale = null) {
|
|
681
|
+
const targetLang = locale || this.getCurrentLanguage();
|
|
682
|
+
const translations = TRANSLATIONS[targetLang] || TRANSLATIONS['en'];
|
|
683
|
+
return translations[key] || key;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Met à jour tous les textes de l'interface selon une langue spécifique
|
|
688
|
+
*/
|
|
689
|
+
updateInterfaceTexts(locale = null) {
|
|
690
|
+
const targetLang = locale || this.getCurrentLanguage();
|
|
691
|
+
console.log('🌐 Interface texts updating for language:', targetLang);
|
|
692
|
+
|
|
693
|
+
// Mettre à jour les textes du menu
|
|
694
|
+
const homeOption = document.querySelector('.ontowave-menu-option[onclick*="goHome"]');
|
|
695
|
+
if (homeOption) {
|
|
696
|
+
homeOption.innerHTML = `🏠 ${this.t('menuHome', targetLang)}`;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
const galleryOption = document.querySelector('.ontowave-menu-option[onclick*="gallery.html"]');
|
|
700
|
+
if (galleryOption) {
|
|
701
|
+
galleryOption.innerHTML = `🎨 ${this.t('menuGallery', targetLang)}`;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
const configOption = document.querySelector('.ontowave-menu-option[onclick*="toggleConfigurationPanel"]');
|
|
705
|
+
if (configOption) {
|
|
706
|
+
configOption.innerHTML = `⚙️ ${this.t('menuConfiguration', targetLang)}`;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// Si le panneau de configuration est ouvert, le recréer avec les nouveaux textes
|
|
710
|
+
const configPanel = document.getElementById('ontowave-config-panel');
|
|
711
|
+
if (configPanel) {
|
|
712
|
+
// Sauvegarder l'état des champs avant de recréer le panneau
|
|
713
|
+
const titleValue = document.getElementById('config-title-full')?.value || this.config.title;
|
|
714
|
+
const defaultPageValue = document.getElementById('config-defaultPage-full')?.value || this.config.defaultPage;
|
|
715
|
+
const baseUrlValue = document.getElementById('config-baseUrl-full')?.value || this.config.baseUrl;
|
|
716
|
+
|
|
717
|
+
// Fermer et rouvrir le panneau pour le mettre à jour
|
|
718
|
+
configPanel.remove();
|
|
719
|
+
const configButton = document.querySelector('.ontowave-menu-option[onclick*="toggleConfigurationPanel"]');
|
|
720
|
+
if (configButton) {
|
|
721
|
+
configButton.classList.remove('selected');
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// Rouvrir avec les nouvelles traductions et la langue spécifiée
|
|
725
|
+
setTimeout(() => {
|
|
726
|
+
this.toggleConfigurationPanel(null, targetLang);
|
|
727
|
+
|
|
728
|
+
// Restaurer les valeurs des champs
|
|
729
|
+
setTimeout(() => {
|
|
730
|
+
const titleField = document.getElementById('config-title-full');
|
|
731
|
+
const defaultPageField = document.getElementById('config-defaultPage-full');
|
|
732
|
+
const baseUrlField = document.getElementById('config-baseUrl-full');
|
|
733
|
+
|
|
734
|
+
if (titleField) titleField.value = titleValue;
|
|
735
|
+
if (defaultPageField) defaultPageField.value = defaultPageValue;
|
|
736
|
+
if (baseUrlField) baseUrlField.value = baseUrlValue;
|
|
737
|
+
}, 100);
|
|
738
|
+
}, 50);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
console.log('🌐 Interface texts updated for language:', targetLang);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Change la langue de l'interface et recharge le contenu approprié
|
|
746
|
+
*/
|
|
747
|
+
switchLanguage(targetLang) {
|
|
748
|
+
// Stocker la langue courante
|
|
749
|
+
this.currentLanguage = targetLang;
|
|
750
|
+
|
|
751
|
+
// Mettre à jour l'état des boutons de langue
|
|
752
|
+
this.updateLanguageButtonsState(targetLang);
|
|
753
|
+
|
|
754
|
+
// Mettre à jour l'interface
|
|
755
|
+
this.updateInterfaceTexts(targetLang);
|
|
756
|
+
|
|
757
|
+
// Recharger la page avec la bonne langue
|
|
758
|
+
const sources = this.config.sources || {};
|
|
759
|
+
const targetPage = sources[targetLang] || this.config.defaultPage;
|
|
760
|
+
|
|
761
|
+
if (targetPage) {
|
|
762
|
+
this.loadPage(targetPage);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Met à jour l'état visuel des boutons de langue pour refléter la langue actuelle
|
|
768
|
+
*/
|
|
769
|
+
updateLanguageButtonsState(currentLang = null) {
|
|
770
|
+
const lang = currentLang || this.getCurrentLanguage();
|
|
771
|
+
|
|
772
|
+
// Mettre à jour les boutons de langue dans le menu
|
|
773
|
+
document.querySelectorAll('.ontowave-lang-btn').forEach(btn => {
|
|
774
|
+
btn.classList.remove('active');
|
|
775
|
+
if (btn.textContent.includes(lang.toUpperCase())) {
|
|
776
|
+
btn.classList.add('active');
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
// Mettre à jour les boutons de langue fixés
|
|
781
|
+
document.querySelectorAll('.ontowave-fixed-lang-btn').forEach(btn => {
|
|
782
|
+
btn.classList.remove('active');
|
|
783
|
+
if (btn.textContent.includes(lang.toUpperCase())) {
|
|
784
|
+
btn.classList.add('active');
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
console.log('🌐 État des boutons de langue mis à jour pour:', lang);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Charge la page d'accueil dans la langue courante
|
|
793
|
+
*/
|
|
794
|
+
goHome() {
|
|
795
|
+
const currentLang = this.getCurrentLanguage();
|
|
796
|
+
const sources = this.config.sources || {};
|
|
797
|
+
const homePage = sources[currentLang] || this.config.defaultPage;
|
|
798
|
+
this.loadPage(homePage);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Résout les langues du navigateur par ordre de préférence
|
|
803
|
+
*/
|
|
804
|
+
getBrowserLocales() {
|
|
805
|
+
const languages = [];
|
|
806
|
+
|
|
807
|
+
// navigator.languages (préférences utilisateur)
|
|
808
|
+
if (navigator.languages) {
|
|
809
|
+
languages.push(...navigator.languages);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// Fallbacks
|
|
813
|
+
if (navigator.language) {
|
|
814
|
+
languages.push(navigator.language);
|
|
815
|
+
}
|
|
816
|
+
if (navigator.userLanguage) {
|
|
817
|
+
languages.push(navigator.userLanguage);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return [...new Set(languages)]; // Enlever doublons
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Trouve la meilleure correspondance entre langues navigateur et config
|
|
825
|
+
* Priorise maintenant le contexte de la page, puis les préférences du navigateur
|
|
826
|
+
*/
|
|
827
|
+
resolveLocale() {
|
|
828
|
+
const browserLocales = this.getBrowserLocales();
|
|
829
|
+
const supportedLocales = this.config.locales || [];
|
|
830
|
+
const defaultLocale = this.config.defaultLocale || this.config.fallbackLocale;
|
|
831
|
+
|
|
832
|
+
console.log('🌐 Browser locales:', browserLocales);
|
|
833
|
+
console.log('🌐 Supported locales:', supportedLocales);
|
|
834
|
+
console.log('🌐 Default locale:', defaultLocale);
|
|
835
|
+
|
|
836
|
+
if (supportedLocales.length === 0) {
|
|
837
|
+
return null; // Mode monolingue
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// PRIORITÉ 1 : Détecter la langue depuis l'URL actuelle
|
|
841
|
+
const currentUrl = window.location.hash || window.location.pathname;
|
|
842
|
+
console.log('🔍 Current URL:', currentUrl);
|
|
843
|
+
|
|
844
|
+
for (const locale of supportedLocales) {
|
|
845
|
+
// Rechercher des patterns comme index.fr.md, about.en.md, etc.
|
|
846
|
+
const langPattern = new RegExp(`\\.${locale}\\.(md|html)`);
|
|
847
|
+
if (langPattern.test(currentUrl)) {
|
|
848
|
+
console.log('🎯 Page language detected from URL:', locale, 'in', currentUrl);
|
|
849
|
+
return locale;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// PRIORITÉ 2 : Recherche exacte dans les langues navigateur
|
|
854
|
+
for (const browserLang of browserLocales) {
|
|
855
|
+
if (supportedLocales.includes(browserLang)) {
|
|
856
|
+
console.log('🎯 Exact browser match found:', browserLang);
|
|
857
|
+
return browserLang;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// PRIORITÉ 2 : Recherche par préfixe (fr-CA -> fr)
|
|
862
|
+
for (const browserLang of browserLocales) {
|
|
863
|
+
const prefix = browserLang.split('-')[0];
|
|
864
|
+
|
|
865
|
+
// PRIORITÉ 3 : Recherche par préfixe (fr-CA -> fr)
|
|
866
|
+
for (const browserLang of browserLocales) {
|
|
867
|
+
const prefix = browserLang.split('-')[0];
|
|
868
|
+
const match = supportedLocales.find(locale => locale.startsWith(prefix));
|
|
869
|
+
if (match) {
|
|
870
|
+
console.log('🎯 Prefix match found:', browserLang, '->', match);
|
|
871
|
+
return match;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// PRIORITÉ 4 : Utiliser defaultLocale si défini et supporté
|
|
876
|
+
if (defaultLocale && supportedLocales.includes(defaultLocale)) {
|
|
877
|
+
console.log('🎯 Using configured default locale:', defaultLocale);
|
|
878
|
+
return defaultLocale;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// PRIORITÉ 5 : Fallback sur la première langue supportée
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// PRIORITÉ 4 : Fallback sur la première langue supportée
|
|
885
|
+
const fallback = supportedLocales[0];
|
|
886
|
+
console.log('🎯 Using fallback locale:', fallback);
|
|
887
|
+
return fallback;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Détermine si OntoWave est en mode multilingue
|
|
892
|
+
*/
|
|
893
|
+
isMultilingualMode() {
|
|
894
|
+
return this.config.locales && this.config.locales.length > 0 && this.config.sources;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* Génère la liste des fichiers à essayer pour une page donnée
|
|
899
|
+
*/
|
|
900
|
+
generatePageCandidates(basePage) {
|
|
901
|
+
const resolvedLocale = this.resolveLocale();
|
|
902
|
+
const candidates = [];
|
|
903
|
+
|
|
904
|
+
if (!resolvedLocale) {
|
|
905
|
+
// Mode monolingue - essayer la page directement
|
|
906
|
+
candidates.push(basePage);
|
|
907
|
+
return candidates;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
const pageName = basePage.replace(/\.md$/, '');
|
|
911
|
+
|
|
912
|
+
// Essayer avec la locale résolue
|
|
913
|
+
candidates.push(`${pageName}.${resolvedLocale}.md`);
|
|
914
|
+
|
|
915
|
+
// Si c'est une locale composée (fr-CA), essayer le préfixe
|
|
916
|
+
if (resolvedLocale.includes('-')) {
|
|
917
|
+
const prefix = resolvedLocale.split('-')[0];
|
|
918
|
+
candidates.push(`${pageName}.${prefix}.md`);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// Fallback sur la page de base
|
|
922
|
+
candidates.push(basePage);
|
|
923
|
+
|
|
924
|
+
console.log('📄 Page candidates for', basePage, ':', candidates);
|
|
925
|
+
return candidates;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
async init() {
|
|
929
|
+
try {
|
|
930
|
+
// Charger la configuration depuis le script JSON si disponible
|
|
931
|
+
await this.loadConfigFromScript();
|
|
932
|
+
|
|
933
|
+
// Injecter les styles CSS
|
|
934
|
+
this.injectStyles();
|
|
935
|
+
|
|
936
|
+
// Charger Mermaid si nécessaire
|
|
937
|
+
await this.loadMermaid();
|
|
938
|
+
|
|
939
|
+
// Charger Prism si nécessaire
|
|
940
|
+
await this.loadPrism();
|
|
941
|
+
|
|
942
|
+
// Créer l'interface
|
|
943
|
+
this.createInterface();
|
|
944
|
+
|
|
945
|
+
// Initialiser la langue courante
|
|
946
|
+
this.currentLanguage = this.resolveLocale();
|
|
947
|
+
|
|
948
|
+
// Initialiser la navigation
|
|
949
|
+
this.initializeNavigation();
|
|
950
|
+
|
|
951
|
+
// Mettre à jour l'état des boutons de langue après la création du menu
|
|
952
|
+
this.updateLanguageButtonsState();
|
|
953
|
+
|
|
954
|
+
// Charger la page initiale
|
|
955
|
+
await this.loadInitialPage();
|
|
956
|
+
|
|
957
|
+
console.log('✅ OntoWave successfully initialized');
|
|
958
|
+
|
|
959
|
+
} catch (error) {
|
|
960
|
+
console.error('❌ OntoWave initialization failed:', error);
|
|
961
|
+
this.showError('Erreur d\'initialisation OntoWave: ' + error.message);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
async loadConfigFromScript() {
|
|
966
|
+
// Priorité 1: Chercher dans window.ontoWaveConfig
|
|
967
|
+
if (window.ontoWaveConfig) {
|
|
968
|
+
this.config = { ...this.config, ...window.ontoWaveConfig };
|
|
969
|
+
console.log('📄 Configuration loaded from window.ontoWaveConfig');
|
|
970
|
+
console.log('📄 Final config:', this.config);
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
// Priorité 2: Chercher dans script tag
|
|
975
|
+
const configScript = document.getElementById('ontowave-config');
|
|
976
|
+
if (configScript && configScript.type === 'application/json') {
|
|
977
|
+
try {
|
|
978
|
+
const userConfig = JSON.parse(configScript.textContent);
|
|
979
|
+
this.config = { ...this.config, ...userConfig };
|
|
980
|
+
console.log('📄 Configuration loaded from script tag');
|
|
981
|
+
console.log('📄 Final config:', this.config);
|
|
982
|
+
} catch (error) {
|
|
983
|
+
console.warn('⚠️ Invalid JSON in ontowave-config script tag:', error);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
injectStyles() {
|
|
989
|
+
const styleElement = document.createElement('style');
|
|
990
|
+
styleElement.textContent = CSS_STYLES;
|
|
991
|
+
document.head.appendChild(styleElement);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
async loadMermaid() {
|
|
995
|
+
return new Promise((resolve) => {
|
|
996
|
+
if (window.mermaid) {
|
|
997
|
+
this.mermaidLoaded = true;
|
|
998
|
+
this.initializeMermaid();
|
|
999
|
+
resolve();
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
const script = document.createElement('script');
|
|
1004
|
+
script.src = 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js';
|
|
1005
|
+
script.onload = () => {
|
|
1006
|
+
this.mermaidLoaded = true;
|
|
1007
|
+
this.initializeMermaid();
|
|
1008
|
+
resolve();
|
|
1009
|
+
};
|
|
1010
|
+
script.onerror = () => {
|
|
1011
|
+
console.warn('⚠️ Failed to load Mermaid library');
|
|
1012
|
+
resolve();
|
|
1013
|
+
};
|
|
1014
|
+
document.head.appendChild(script);
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
initializeMermaid() {
|
|
1019
|
+
if (window.mermaid) {
|
|
1020
|
+
window.mermaid.initialize(this.config.mermaid);
|
|
1021
|
+
console.log('🎨 Mermaid initialized');
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
async loadPrism() {
|
|
1026
|
+
return new Promise((resolve) => {
|
|
1027
|
+
if (window.Prism) {
|
|
1028
|
+
this.prismLoaded = true;
|
|
1029
|
+
console.log('🎨 Prism already loaded');
|
|
1030
|
+
return resolve();
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
// Charger CSS Prism
|
|
1034
|
+
const cssLink = document.createElement('link');
|
|
1035
|
+
cssLink.rel = 'stylesheet';
|
|
1036
|
+
cssLink.href = 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css';
|
|
1037
|
+
document.head.appendChild(cssLink);
|
|
1038
|
+
|
|
1039
|
+
// Charger JS Prism
|
|
1040
|
+
const script = document.createElement('script');
|
|
1041
|
+
script.src = 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js';
|
|
1042
|
+
script.onload = () => {
|
|
1043
|
+
console.log('🎨 Prism core loaded');
|
|
1044
|
+
|
|
1045
|
+
// Charger les langages essentiels et attendre leur chargement
|
|
1046
|
+
const essentialLanguages = ['markup', 'css', 'javascript'];
|
|
1047
|
+
let loadedCount = 0;
|
|
1048
|
+
|
|
1049
|
+
const checkComplete = () => {
|
|
1050
|
+
loadedCount++;
|
|
1051
|
+
console.log(`🔤 Essential language loaded: ${loadedCount}/${essentialLanguages.length}`);
|
|
1052
|
+
if (loadedCount >= essentialLanguages.length) {
|
|
1053
|
+
// HTML est un alias de markup dans Prism
|
|
1054
|
+
if (window.Prism.languages.markup) {
|
|
1055
|
+
window.Prism.languages.html = window.Prism.languages.markup;
|
|
1056
|
+
console.log('🔤 HTML alias created from markup');
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
this.prismLoaded = true;
|
|
1060
|
+
console.log('✅ Prism ready with essential languages');
|
|
1061
|
+
resolve();
|
|
1062
|
+
|
|
1063
|
+
// Charger les langages supplémentaires en arrière-plan
|
|
1064
|
+
const additionalLanguages = ['python', 'java', 'bash', 'json', 'yaml', 'typescript'];
|
|
1065
|
+
additionalLanguages.forEach(lang => {
|
|
1066
|
+
const langScript = document.createElement('script');
|
|
1067
|
+
langScript.src = `https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-${lang}.min.js`;
|
|
1068
|
+
langScript.onload = () => {
|
|
1069
|
+
console.log(`🔤 Additional Prism language loaded: ${lang}`);
|
|
1070
|
+
};
|
|
1071
|
+
langScript.onerror = () => {
|
|
1072
|
+
console.warn(`⚠️ Failed to load Prism language: ${lang}`);
|
|
1073
|
+
};
|
|
1074
|
+
document.head.appendChild(langScript);
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
};
|
|
1078
|
+
|
|
1079
|
+
essentialLanguages.forEach(lang => {
|
|
1080
|
+
const langScript = document.createElement('script');
|
|
1081
|
+
langScript.src = `https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-${lang}.min.js`;
|
|
1082
|
+
langScript.onload = checkComplete;
|
|
1083
|
+
langScript.onerror = () => {
|
|
1084
|
+
console.warn(`⚠️ Failed to load essential Prism language: ${lang}`);
|
|
1085
|
+
checkComplete(); // Continue même en cas d'erreur
|
|
1086
|
+
};
|
|
1087
|
+
document.head.appendChild(langScript);
|
|
1088
|
+
});
|
|
1089
|
+
};
|
|
1090
|
+
script.onerror = () => {
|
|
1091
|
+
console.warn('⚠️ Failed to load Prism library');
|
|
1092
|
+
resolve();
|
|
1093
|
+
};
|
|
1094
|
+
document.head.appendChild(script);
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
createInterface(locale = null) {
|
|
1099
|
+
// Trouver ou créer le conteneur
|
|
1100
|
+
this.container = document.getElementById(this.config.containerId);
|
|
1101
|
+
if (!this.container) {
|
|
1102
|
+
this.container = document.createElement('div');
|
|
1103
|
+
this.container.id = this.config.containerId;
|
|
1104
|
+
document.body.appendChild(this.container);
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
this.container.className = 'ontowave-container';
|
|
1108
|
+
|
|
1109
|
+
// Créer les options du menu selon la configuration
|
|
1110
|
+
const galleryOption = this.config.showGallery ?
|
|
1111
|
+
`<span class="ontowave-menu-option" onclick="window.location.href='gallery.html'">🎨 ${this.t('menuGallery', locale)}</span>` : '';
|
|
1112
|
+
|
|
1113
|
+
// Créer les boutons de langue si multilingue et selon la configuration
|
|
1114
|
+
const languageButtonsMode = this.config.ui?.languageButtons || "menu";
|
|
1115
|
+
const shouldCreateMenuButtons = (languageButtonsMode === "menu" || languageButtonsMode === "both");
|
|
1116
|
+
|
|
1117
|
+
const languageButtons = this.config.locales && this.config.locales.length > 1 && shouldCreateMenuButtons ?
|
|
1118
|
+
this.config.locales.map(lang => {
|
|
1119
|
+
const isActive = (locale || this.getCurrentLanguage()) === lang;
|
|
1120
|
+
const activeClass = isActive ? ' active' : '';
|
|
1121
|
+
return `<span class="ontowave-menu-option ontowave-lang-btn${activeClass}" onclick="event.stopPropagation(); window.OntoWave.instance.switchLanguage('${lang}');">🌐 ${lang.toUpperCase()}</span>`;
|
|
1122
|
+
}).join('') : '';
|
|
1123
|
+
|
|
1124
|
+
// Créer la structure HTML minimaliste
|
|
1125
|
+
this.container.innerHTML = `
|
|
1126
|
+
<div class="ontowave-floating-menu" id="ontowave-floating-menu" title="OntoWave Menu">
|
|
1127
|
+
<span class="ontowave-menu-icon" id="ontowave-menu-icon">🌊</span>
|
|
1128
|
+
<div class="ontowave-menu-content" id="ontowave-menu-content">
|
|
1129
|
+
<a href="https://ontowave.org/" target="_blank" class="ontowave-menu-brand">OntoWave<span class="org-suffix">.org</span></a>
|
|
1130
|
+
<div class="ontowave-menu-options">
|
|
1131
|
+
<span class="ontowave-menu-option" onclick="window.OntoWave.instance.goHome()">🏠 ${this.t('menuHome', locale)}</span>
|
|
1132
|
+
${galleryOption}
|
|
1133
|
+
${languageButtons}
|
|
1134
|
+
<span class="ontowave-menu-option" onclick="event.stopPropagation(); window.OntoWave.instance.toggleConfigurationPanel(event, '${locale || this.getCurrentLanguage()}');">⚙️ ${this.t('menuConfiguration', locale)}</span>
|
|
1135
|
+
</div>
|
|
1136
|
+
</div>
|
|
1137
|
+
</div>
|
|
1138
|
+
|
|
1139
|
+
<div class="ontowave-content" id="ontowave-content">
|
|
1140
|
+
<div class="ontowave-loading">⏳ Chargement du contenu...</div>
|
|
1141
|
+
</div>
|
|
1142
|
+
|
|
1143
|
+
<div class="ontowave-status" style="display: none;">
|
|
1144
|
+
<h4>✅ OntoWave Package Actif</h4>
|
|
1145
|
+
<ul>
|
|
1146
|
+
<li><strong>Chargement rapide:</strong> Système intégré</li>
|
|
1147
|
+
<li><strong>Mermaid:</strong> ${this.mermaidLoaded ? 'Chargé' : 'Non disponible'}</li>
|
|
1148
|
+
<li><strong>Prism:</strong> ${this.prismLoaded ? 'Chargé' : 'Non disponible'}</li>
|
|
1149
|
+
<li><strong>PlantUML:</strong> Support intégré</li>
|
|
1150
|
+
<li><strong>Navigation:</strong> Hash préservé</li>
|
|
1151
|
+
</ul>
|
|
1152
|
+
</div>
|
|
1153
|
+
`;
|
|
1154
|
+
|
|
1155
|
+
// Créer les boutons de langue fixés si multilingue
|
|
1156
|
+
this.createFixedLanguageButtons(locale);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
createFixedLanguageButtons(locale = null) {
|
|
1160
|
+
// Supprimer les boutons existants s'ils existent
|
|
1161
|
+
const existingButtons = document.getElementById('ontowave-fixed-lang-buttons');
|
|
1162
|
+
if (existingButtons) {
|
|
1163
|
+
existingButtons.remove();
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
// Créer les boutons de langue fixés seulement si multilingue et si configuré
|
|
1167
|
+
const languageButtonsMode = this.config.ui?.languageButtons || "menu";
|
|
1168
|
+
const shouldCreateFixed = (languageButtonsMode === "fixed" || languageButtonsMode === "both");
|
|
1169
|
+
|
|
1170
|
+
if (this.config.locales && this.config.locales.length > 1 && shouldCreateFixed) {
|
|
1171
|
+
const currentLang = locale || this.getCurrentLanguage();
|
|
1172
|
+
|
|
1173
|
+
const fixedLangContainer = document.createElement('div');
|
|
1174
|
+
fixedLangContainer.id = 'ontowave-fixed-lang-buttons';
|
|
1175
|
+
fixedLangContainer.className = 'ontowave-fixed-lang-buttons';
|
|
1176
|
+
|
|
1177
|
+
// Créer les boutons pour chaque langue
|
|
1178
|
+
const buttonsHtml = this.config.locales.map(lang => {
|
|
1179
|
+
const isActive = currentLang === lang;
|
|
1180
|
+
const activeClass = isActive ? ' active' : '';
|
|
1181
|
+
const flag = this.getLanguageFlag(lang);
|
|
1182
|
+
return `<button class="ontowave-fixed-lang-btn${activeClass}" onclick="window.OntoWave.instance.switchLanguage('${lang}')" title="Changer en ${lang.toUpperCase()}">${flag} ${lang.toUpperCase()}</button>`;
|
|
1183
|
+
}).join('');
|
|
1184
|
+
|
|
1185
|
+
fixedLangContainer.innerHTML = buttonsHtml;
|
|
1186
|
+
document.body.appendChild(fixedLangContainer);
|
|
1187
|
+
|
|
1188
|
+
console.log('🌐 Boutons de langue fixés créés:', this.config.locales, 'Mode:', languageButtonsMode);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
getLanguageFlag(lang) {
|
|
1193
|
+
const flags = {
|
|
1194
|
+
'fr': '🇫🇷',
|
|
1195
|
+
'en': '🇬🇧',
|
|
1196
|
+
'es': '🇪🇸',
|
|
1197
|
+
'de': '🇩🇪',
|
|
1198
|
+
'it': '🇮🇹',
|
|
1199
|
+
'pt': '🇵🇹',
|
|
1200
|
+
'zh': '🇨🇳',
|
|
1201
|
+
'ja': '🇯🇵',
|
|
1202
|
+
'ko': '🇰🇷',
|
|
1203
|
+
'ru': '🇷🇺'
|
|
1204
|
+
};
|
|
1205
|
+
return flags[lang] || '🌐';
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
initializeNavigation() {
|
|
1209
|
+
// Gestion des changements de hash
|
|
1210
|
+
window.addEventListener('hashchange', () => {
|
|
1211
|
+
const hash = location.hash.replace('#', '') || this.config.defaultPage;
|
|
1212
|
+
this.loadPage(hash);
|
|
1213
|
+
});
|
|
1214
|
+
|
|
1215
|
+
// Navigation par défaut
|
|
1216
|
+
this.createDefaultNavigation();
|
|
1217
|
+
|
|
1218
|
+
// Initialiser le menu flottant interactif
|
|
1219
|
+
this.initializeFloatingMenu();
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
initializeFloatingMenu() {
|
|
1223
|
+
const menu = document.getElementById('ontowave-floating-menu');
|
|
1224
|
+
const menuIcon = document.getElementById('ontowave-menu-icon');
|
|
1225
|
+
|
|
1226
|
+
if (!menu || !menuIcon) return;
|
|
1227
|
+
|
|
1228
|
+
let isExpanded = false;
|
|
1229
|
+
let isDragging = false;
|
|
1230
|
+
let dragOffset = { x: 0, y: 0 };
|
|
1231
|
+
|
|
1232
|
+
// Fonction pour mettre à jour l'état de déplacement
|
|
1233
|
+
function updateDragState() {
|
|
1234
|
+
const canDrag = !isExpanded && !document.querySelector('.ontowave-config-panel');
|
|
1235
|
+
if (canDrag) {
|
|
1236
|
+
menu.classList.remove('no-drag');
|
|
1237
|
+
} else {
|
|
1238
|
+
menu.classList.add('no-drag');
|
|
1239
|
+
// Sécurité : forcer l'arrêt du drag
|
|
1240
|
+
isDragging = false;
|
|
1241
|
+
document.body.style.userSelect = '';
|
|
1242
|
+
document.body.style.cursor = '';
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
// Stocker la référence globalement pour les panneaux de configuration
|
|
1247
|
+
window.ontowaveUpdateDragState = updateDragState;
|
|
1248
|
+
|
|
1249
|
+
// Toggle menu au clic sur l'icône
|
|
1250
|
+
menuIcon.addEventListener('click', (e) => {
|
|
1251
|
+
e.stopPropagation();
|
|
1252
|
+
isExpanded = !isExpanded;
|
|
1253
|
+
|
|
1254
|
+
if (isExpanded) {
|
|
1255
|
+
menu.classList.add('expanded');
|
|
1256
|
+
} else {
|
|
1257
|
+
menu.classList.remove('expanded');
|
|
1258
|
+
}
|
|
1259
|
+
updateDragState();
|
|
1260
|
+
});
|
|
1261
|
+
|
|
1262
|
+
// Fermer le menu au clic en dehors
|
|
1263
|
+
document.addEventListener('click', (e) => {
|
|
1264
|
+
if (!menu.contains(e.target) && isExpanded) {
|
|
1265
|
+
isExpanded = false;
|
|
1266
|
+
menu.classList.remove('expanded');
|
|
1267
|
+
updateDragState();
|
|
1268
|
+
}
|
|
1269
|
+
});
|
|
1270
|
+
|
|
1271
|
+
// Drag & Drop functionality
|
|
1272
|
+
menu.addEventListener('mousedown', (e) => {
|
|
1273
|
+
// Ne pas démarrer le drag si le menu est étendu ou si un panneau de config est ouvert
|
|
1274
|
+
if (isExpanded || document.querySelector('.ontowave-config-panel')) {
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
// Ne pas démarrer le drag si on clique sur les liens/boutons
|
|
1279
|
+
if (e.target.closest('a, .ontowave-menu-option')) return;
|
|
1280
|
+
|
|
1281
|
+
isDragging = true;
|
|
1282
|
+
const rect = menu.getBoundingClientRect();
|
|
1283
|
+
dragOffset.x = e.clientX - rect.left;
|
|
1284
|
+
dragOffset.y = e.clientY - rect.top;
|
|
1285
|
+
|
|
1286
|
+
menu.style.cursor = 'grabbing';
|
|
1287
|
+
document.body.style.userSelect = 'none';
|
|
1288
|
+
|
|
1289
|
+
// Empêcher l'interception des événements par d'autres éléments
|
|
1290
|
+
e.preventDefault();
|
|
1291
|
+
e.stopPropagation();
|
|
1292
|
+
});
|
|
1293
|
+
|
|
1294
|
+
document.addEventListener('mousemove', (e) => {
|
|
1295
|
+
if (!isDragging) return;
|
|
1296
|
+
|
|
1297
|
+
const x = e.clientX - dragOffset.x;
|
|
1298
|
+
const y = e.clientY - dragOffset.y;
|
|
1299
|
+
|
|
1300
|
+
// Contraintes pour rester dans la fenêtre
|
|
1301
|
+
const maxX = window.innerWidth - menu.offsetWidth;
|
|
1302
|
+
const maxY = window.innerHeight - menu.offsetHeight;
|
|
1303
|
+
|
|
1304
|
+
menu.style.left = Math.max(0, Math.min(maxX, x)) + 'px';
|
|
1305
|
+
menu.style.top = Math.max(0, Math.min(maxY, y)) + 'px';
|
|
1306
|
+
});
|
|
1307
|
+
|
|
1308
|
+
document.addEventListener('mouseup', () => {
|
|
1309
|
+
if (isDragging) {
|
|
1310
|
+
isDragging = false;
|
|
1311
|
+
menu.style.cursor = 'move';
|
|
1312
|
+
document.body.style.userSelect = '';
|
|
1313
|
+
}
|
|
1314
|
+
});
|
|
1315
|
+
|
|
1316
|
+
// Solution de sécurité : Remettre l'état normal après un délai
|
|
1317
|
+
function resetDragState() {
|
|
1318
|
+
isDragging = false;
|
|
1319
|
+
menu.style.cursor = 'move';
|
|
1320
|
+
document.body.style.userSelect = '';
|
|
1321
|
+
document.body.style.cursor = '';
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
// Reset automatique après perte de focus ou changement de page
|
|
1325
|
+
document.addEventListener('visibilitychange', resetDragState);
|
|
1326
|
+
window.addEventListener('blur', resetDragState);
|
|
1327
|
+
window.addEventListener('focus', resetDragState);
|
|
1328
|
+
|
|
1329
|
+
// Fonction globale accessible pour reset manuel
|
|
1330
|
+
window.resetOntoWaveDragState = resetDragState;
|
|
1331
|
+
|
|
1332
|
+
// Support tactile pour mobile
|
|
1333
|
+
menu.addEventListener('touchstart', (e) => {
|
|
1334
|
+
if (e.target.closest('a, .ontowave-menu-option')) return;
|
|
1335
|
+
|
|
1336
|
+
const touch = e.touches[0];
|
|
1337
|
+
const rect = menu.getBoundingClientRect();
|
|
1338
|
+
dragOffset.x = touch.clientX - rect.left;
|
|
1339
|
+
dragOffset.y = touch.clientY - rect.top;
|
|
1340
|
+
isDragging = true;
|
|
1341
|
+
});
|
|
1342
|
+
|
|
1343
|
+
document.addEventListener('touchmove', (e) => {
|
|
1344
|
+
if (!isDragging) return;
|
|
1345
|
+
e.preventDefault();
|
|
1346
|
+
|
|
1347
|
+
const touch = e.touches[0];
|
|
1348
|
+
const x = touch.clientX - dragOffset.x;
|
|
1349
|
+
const y = touch.clientY - dragOffset.y;
|
|
1350
|
+
|
|
1351
|
+
const maxX = window.innerWidth - menu.offsetWidth;
|
|
1352
|
+
const maxY = window.innerHeight - menu.offsetHeight;
|
|
1353
|
+
|
|
1354
|
+
menu.style.left = Math.max(0, Math.min(maxX, x)) + 'px';
|
|
1355
|
+
menu.style.top = Math.max(0, Math.min(maxY, y)) + 'px';
|
|
1356
|
+
});
|
|
1357
|
+
|
|
1358
|
+
document.addEventListener('touchend', () => {
|
|
1359
|
+
isDragging = false;
|
|
1360
|
+
});
|
|
1361
|
+
|
|
1362
|
+
// Initialiser l'état de déplacement
|
|
1363
|
+
updateDragState();
|
|
1364
|
+
|
|
1365
|
+
// Améliorer la gestion des clics sur les options du menu
|
|
1366
|
+
this.enhanceMenuOptionClicks();
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
enhanceMenuOptionClicks() {
|
|
1370
|
+
// Ajouter des gestionnaires d'événements robustes pour les options du menu
|
|
1371
|
+
const configOption = document.querySelector('.ontowave-menu-option[onclick*="toggleConfigurationPanel"]');
|
|
1372
|
+
if (configOption) {
|
|
1373
|
+
configOption.addEventListener('click', (e) => {
|
|
1374
|
+
e.preventDefault();
|
|
1375
|
+
e.stopPropagation();
|
|
1376
|
+
console.log('Configuration button clicked via event listener');
|
|
1377
|
+
this.toggleConfigurationPanel(e);
|
|
1378
|
+
}, { capture: true });
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
createDefaultNavigation() {
|
|
1383
|
+
const navGrid = document.getElementById('ontowave-nav-grid');
|
|
1384
|
+
if (!navGrid) return;
|
|
1385
|
+
|
|
1386
|
+
const defaultNavItems = [
|
|
1387
|
+
{ href: 'index.md', icon: '🏠', label: 'Accueil' },
|
|
1388
|
+
{ href: 'en/index.md', icon: '🇬🇧', label: 'English' },
|
|
1389
|
+
{ href: 'fr/index.md', icon: '🇫🇷', label: 'Français' },
|
|
1390
|
+
{ href: 'demo/mermaid.md', icon: '🧜♀️', label: 'Démo Mermaid' },
|
|
1391
|
+
{ href: 'demo/plantuml.md', icon: '🏭', label: 'PlantUML' },
|
|
1392
|
+
{ href: 'demo/advanced-shapes.md', icon: '🎯', label: 'Formes Avancées' }
|
|
1393
|
+
];
|
|
1394
|
+
|
|
1395
|
+
navGrid.innerHTML = defaultNavItems.map(item => `
|
|
1396
|
+
<a href="#${item.href}" class="ontowave-nav-item" onclick="window.OntoWave.loadPage('${item.href}')">
|
|
1397
|
+
${item.icon} ${item.label}
|
|
1398
|
+
</a>
|
|
1399
|
+
`).join('');
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
async loadInitialPage() {
|
|
1403
|
+
const currentHash = location.hash.replace('#', '');
|
|
1404
|
+
|
|
1405
|
+
// Mode multilingue : redirection automatique si pas de hash
|
|
1406
|
+
if (this.isMultilingualMode() && !currentHash) {
|
|
1407
|
+
const defaultSource = this.config.sources[this.config.defaultLocale];
|
|
1408
|
+
console.log('🌐 Multilingual mode detected');
|
|
1409
|
+
console.log('🌐 Default locale:', this.config.defaultLocale);
|
|
1410
|
+
console.log('🌐 Default source:', defaultSource);
|
|
1411
|
+
console.log('🌐 Sources config:', this.config.sources);
|
|
1412
|
+
|
|
1413
|
+
if (defaultSource) {
|
|
1414
|
+
console.log('🌐 Multilingual mode: redirecting to', defaultSource);
|
|
1415
|
+
location.hash = '#' + defaultSource;
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
const initialPage = currentHash || this.config.defaultPage;
|
|
1421
|
+
|
|
1422
|
+
// Si on n'a pas de fichier index, afficher la configuration
|
|
1423
|
+
if (initialPage === 'index.md') {
|
|
1424
|
+
const candidates = this.generatePageCandidates(initialPage);
|
|
1425
|
+
let found = false;
|
|
1426
|
+
|
|
1427
|
+
for (const candidate of candidates) {
|
|
1428
|
+
try {
|
|
1429
|
+
const response = await fetch(this.config.baseUrl + candidate, { method: 'HEAD' });
|
|
1430
|
+
if (response.ok) {
|
|
1431
|
+
await this.loadPage(candidate);
|
|
1432
|
+
found = true;
|
|
1433
|
+
break;
|
|
1434
|
+
}
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
// Continue avec le candidat suivant
|
|
1437
|
+
continue;
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
if (!found) {
|
|
1442
|
+
console.log('📄 No index file found, showing configuration');
|
|
1443
|
+
this.showConfigurationInterface();
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
} else {
|
|
1447
|
+
await this.loadPage(initialPage);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
async loadPage(pagePath) {
|
|
1452
|
+
const contentDiv = document.getElementById('ontowave-content');
|
|
1453
|
+
if (!contentDiv) return;
|
|
1454
|
+
|
|
1455
|
+
console.log('📄 Loading page:', pagePath);
|
|
1456
|
+
this.currentPage = pagePath;
|
|
1457
|
+
|
|
1458
|
+
// Sécurité : Reset de l'état de drag au changement de page
|
|
1459
|
+
if (window.resetOntoWaveDragState) {
|
|
1460
|
+
window.resetOntoWaveDragState();
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
// Mettre à jour le hash
|
|
1464
|
+
if (location.hash !== '#' + pagePath) {
|
|
1465
|
+
location.hash = '#' + pagePath;
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
// Mettre à jour le breadcrumb
|
|
1469
|
+
this.updateBreadcrumb(pagePath);
|
|
1470
|
+
|
|
1471
|
+
// Afficher le loading
|
|
1472
|
+
contentDiv.innerHTML = '<div class="ontowave-loading">⏳ Chargement de ' + pagePath + '...</div>';
|
|
1473
|
+
|
|
1474
|
+
try {
|
|
1475
|
+
const response = await fetch(this.config.baseUrl + pagePath);
|
|
1476
|
+
|
|
1477
|
+
if (!response.ok) {
|
|
1478
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
const markdown = await response.text();
|
|
1482
|
+
console.log('✅ Content loaded:', markdown.length, 'characters');
|
|
1483
|
+
|
|
1484
|
+
// Rendre le markdown
|
|
1485
|
+
const html = await this.renderMarkdown(markdown);
|
|
1486
|
+
contentDiv.innerHTML = html;
|
|
1487
|
+
|
|
1488
|
+
// Traiter les diagrammes
|
|
1489
|
+
await this.processDiagrams(contentDiv);
|
|
1490
|
+
|
|
1491
|
+
// Traiter la coloration syntaxique
|
|
1492
|
+
await this.processPrism(contentDiv);
|
|
1493
|
+
|
|
1494
|
+
} catch (error) {
|
|
1495
|
+
console.error('❌ Failed to load page:', error);
|
|
1496
|
+
this.showError(`Impossible de charger ${pagePath}: ${error.message}`);
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
updateBreadcrumb(pagePath) {
|
|
1501
|
+
const breadcrumbDiv = document.getElementById('ontowave-breadcrumb');
|
|
1502
|
+
if (!breadcrumbDiv || !this.config.navigation.showBreadcrumb) return;
|
|
1503
|
+
|
|
1504
|
+
const parts = pagePath.split('/');
|
|
1505
|
+
const breadcrumbs = ['<a href="#' + this.config.defaultPage + '">🏠 Accueil</a>'];
|
|
1506
|
+
|
|
1507
|
+
let currentPath = '';
|
|
1508
|
+
parts.forEach((part, index) => {
|
|
1509
|
+
if (index === parts.length - 1) {
|
|
1510
|
+
// Dernier élément (page actuelle)
|
|
1511
|
+
breadcrumbs.push('<span>' + part.replace('.md', '') + '</span>');
|
|
1512
|
+
} else {
|
|
1513
|
+
currentPath += (currentPath ? '/' : '') + part;
|
|
1514
|
+
breadcrumbs.push('<a href="#' + currentPath + '/index.md">' + part + '</a>');
|
|
1515
|
+
}
|
|
1516
|
+
});
|
|
1517
|
+
|
|
1518
|
+
breadcrumbDiv.innerHTML = breadcrumbs.join(' <span>›</span> ');
|
|
1519
|
+
breadcrumbDiv.style.display = 'block';
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
async renderMarkdown(markdown) {
|
|
1523
|
+
// Rendu markdown corrigé avec support complet
|
|
1524
|
+
let html = markdown;
|
|
1525
|
+
|
|
1526
|
+
// Traiter les blocs de code AVANT les autres transformations
|
|
1527
|
+
const codeBlocks = [];
|
|
1528
|
+
html = html.replace(/```(\w+)([\s\S]*?)```/g, (match, language, content) => {
|
|
1529
|
+
const trimmedContent = content.trim();
|
|
1530
|
+
const placeholder = `__CODE_BLOCK_${codeBlocks.length}__`;
|
|
1531
|
+
|
|
1532
|
+
if (language === 'mermaid') {
|
|
1533
|
+
const id = 'mermaid-' + Math.random().toString(36).substr(2, 9);
|
|
1534
|
+
codeBlocks.push(`<div class="ontowave-mermaid">
|
|
1535
|
+
<div style="margin-bottom: 8px; font-weight: bold; color: #586069;">🧜♀️ Diagramme Mermaid</div>
|
|
1536
|
+
<div class="mermaid" id="${id}">${trimmedContent}</div>
|
|
1537
|
+
</div>`);
|
|
1538
|
+
} else if (language === 'plantuml') {
|
|
1539
|
+
const id = 'plantuml-' + Math.random().toString(36).substr(2, 9);
|
|
1540
|
+
|
|
1541
|
+
// Fonction d'encodage PlantUML avec support UTF-8
|
|
1542
|
+
function encodePlantUML(text) {
|
|
1543
|
+
// Encoder le texte en UTF-8 puis en hexadécimal
|
|
1544
|
+
const utf8Encoder = new TextEncoder();
|
|
1545
|
+
const utf8Bytes = utf8Encoder.encode(text);
|
|
1546
|
+
let hex = '';
|
|
1547
|
+
for (let i = 0; i < utf8Bytes.length; i++) {
|
|
1548
|
+
hex += utf8Bytes[i].toString(16).padStart(2, '0');
|
|
1549
|
+
}
|
|
1550
|
+
return 'h' + hex; // Le préfixe ~h sera ajouté dans l'URL
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
const encodedContent = encodePlantUML(trimmedContent);
|
|
1554
|
+
const plantUMLUrl = `${this.config.plantuml.server}/${this.config.plantuml.format}/~${encodedContent}`;
|
|
1555
|
+
codeBlocks.push(`<div class="ontowave-plantuml" id="${id}">
|
|
1556
|
+
<div style="margin-bottom: 8px; font-weight: bold; color: #586069;">🏭 Diagramme PlantUML</div>
|
|
1557
|
+
<img src="${plantUMLUrl}" alt="Diagramme PlantUML" style="max-width: 100%; height: auto;"
|
|
1558
|
+
onerror="this.parentElement.innerHTML='<div style=\\'color: #d73a49; padding: 20px;\\'>❌ Erreur de rendu PlantUML</div>'" />
|
|
1559
|
+
</div>`);
|
|
1560
|
+
} else {
|
|
1561
|
+
const codeClass = this.prismLoaded ? `language-${language}` : '';
|
|
1562
|
+
console.log(`📝 Processing code block: language="${language}", prismLoaded=${this.prismLoaded}, class="${codeClass}"`);
|
|
1563
|
+
|
|
1564
|
+
// Échapper le HTML pour que Prism puisse le colorer correctement
|
|
1565
|
+
const escapedContent = trimmedContent
|
|
1566
|
+
.replace(/&/g, '&')
|
|
1567
|
+
.replace(/</g, '<')
|
|
1568
|
+
.replace(/>/g, '>')
|
|
1569
|
+
.replace(/"/g, '"')
|
|
1570
|
+
.replace(/'/g, ''');
|
|
1571
|
+
|
|
1572
|
+
codeBlocks.push(`<pre class="ontowave-code"><code class="${codeClass}">${escapedContent}</code></pre>`);
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
return placeholder;
|
|
1576
|
+
});
|
|
1577
|
+
|
|
1578
|
+
// Transformations markdown principales
|
|
1579
|
+
html = html
|
|
1580
|
+
// Headers - corriger l'ordre et la syntaxe (du plus spécifique au plus général)
|
|
1581
|
+
.replace(/^###### (.+)$/gm, '<h6>$1</h6>')
|
|
1582
|
+
.replace(/^##### (.+)$/gm, '<h5>$1</h5>')
|
|
1583
|
+
.replace(/^#### (.+)$/gm, '<h4>$1</h4>')
|
|
1584
|
+
.replace(/^### (.+)$/gm, '<h3>$1</h3>')
|
|
1585
|
+
.replace(/^## (.+)$/gm, '<h2>$1</h2>')
|
|
1586
|
+
.replace(/^# (.+)$/gm, '<h1>$1</h1>')
|
|
1587
|
+
// Séparateurs HR
|
|
1588
|
+
.replace(/^---+$/gm, '<hr>')
|
|
1589
|
+
// Images markdown - avant les liens
|
|
1590
|
+
.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1">')
|
|
1591
|
+
// Liens - traitement différent pour HTML vs MD
|
|
1592
|
+
.replace(/\[([^\]]+)\]\(([^)]+\.html[^)]*)\)/g, '<a href="$2">$1</a>')
|
|
1593
|
+
// Liens externes (http/https) - ne pas ajouter de hash
|
|
1594
|
+
.replace(/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g, '<a href="$2" target="_blank">$1</a>')
|
|
1595
|
+
// Fichiers téléchargeables - liens directs sans hash
|
|
1596
|
+
.replace(/\[([^\]]+)\]\(([^)]+\.(tar\.gz|zip|pdf|doc|docx|xls|xlsx|ppt|pptx|txt|csv|json|xml|js|css|png|jpg|jpeg|gif|svg|webp)[^)]*)\)/g, '<a href="$2" download>$1</a>')
|
|
1597
|
+
// Liens internes - ajouter hash et navigation OntoWave
|
|
1598
|
+
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="#$2" onclick="window.OntoWave.loadPage(\'$2\')">$1</a>')
|
|
1599
|
+
// Formatage
|
|
1600
|
+
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
|
|
1601
|
+
.replace(/\*(.+?)\*/g, '<em>$1</em>')
|
|
1602
|
+
// Code inline
|
|
1603
|
+
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
1604
|
+
// Paragraphes
|
|
1605
|
+
.split('\n\n')
|
|
1606
|
+
.map(para => para.trim())
|
|
1607
|
+
.filter(para => para.length > 0)
|
|
1608
|
+
.map(para => {
|
|
1609
|
+
// Ne pas encapsuler dans <p> si c'est déjà un élément HTML
|
|
1610
|
+
if (para.match(/^<(h[1-6]|hr|div|pre)/)) {
|
|
1611
|
+
return para;
|
|
1612
|
+
}
|
|
1613
|
+
return `<p>${para.replace(/\n/g, '<br>')}</p>`;
|
|
1614
|
+
})
|
|
1615
|
+
.join('\n');
|
|
1616
|
+
|
|
1617
|
+
// Remettre les blocs de code
|
|
1618
|
+
codeBlocks.forEach((block, index) => {
|
|
1619
|
+
html = html.replace(`__CODE_BLOCK_${index}__`, block);
|
|
1620
|
+
});
|
|
1621
|
+
|
|
1622
|
+
return html;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
async processDiagrams(container) {
|
|
1626
|
+
if (!this.mermaidLoaded || !window.mermaid) return;
|
|
1627
|
+
|
|
1628
|
+
const mermaidElements = container.querySelectorAll('.mermaid');
|
|
1629
|
+
if (mermaidElements.length === 0) return;
|
|
1630
|
+
|
|
1631
|
+
console.log('🎨 Processing', mermaidElements.length, 'Mermaid diagrams');
|
|
1632
|
+
|
|
1633
|
+
try {
|
|
1634
|
+
// Nettoyer les éléments déjà traités
|
|
1635
|
+
mermaidElements.forEach(el => {
|
|
1636
|
+
el.removeAttribute('data-processed');
|
|
1637
|
+
});
|
|
1638
|
+
|
|
1639
|
+
await window.mermaid.run();
|
|
1640
|
+
console.log('✅ Mermaid diagrams rendered successfully');
|
|
1641
|
+
|
|
1642
|
+
// Vérification post-rendu
|
|
1643
|
+
setTimeout(() => {
|
|
1644
|
+
const svgElements = container.querySelectorAll('.mermaid svg');
|
|
1645
|
+
console.log('🎨 SVG elements found:', svgElements.length);
|
|
1646
|
+
|
|
1647
|
+
if (svgElements.length === 0 && mermaidElements.length > 0) {
|
|
1648
|
+
console.log('⚠️ Retrying Mermaid rendering...');
|
|
1649
|
+
mermaidElements.forEach(el => {
|
|
1650
|
+
el.removeAttribute('data-processed');
|
|
1651
|
+
});
|
|
1652
|
+
window.mermaid.init(undefined, mermaidElements);
|
|
1653
|
+
}
|
|
1654
|
+
}, 1000);
|
|
1655
|
+
|
|
1656
|
+
} catch (error) {
|
|
1657
|
+
console.error('❌ Mermaid rendering error:', error);
|
|
1658
|
+
// Fallback: afficher le code brut
|
|
1659
|
+
mermaidElements.forEach(el => {
|
|
1660
|
+
if (!el.querySelector('svg')) {
|
|
1661
|
+
el.innerHTML = `<div style="color: #d73a49; padding: 10px;">❌ Erreur de rendu Mermaid: ${error.message}</div><pre style="background: #f8f8f8; padding: 10px; margin-top: 10px; border-radius: 4px;"><code>${el.textContent}</code></pre>`;
|
|
1662
|
+
}
|
|
1663
|
+
});
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
async processPrism(container) {
|
|
1668
|
+
console.log('🔍 processPrism called - prismLoaded:', this.prismLoaded, 'window.Prism:', !!window.Prism);
|
|
1669
|
+
|
|
1670
|
+
if (!window.Prism) {
|
|
1671
|
+
console.log('🎨 Prism not available, skipping syntax highlighting');
|
|
1672
|
+
return;
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
try {
|
|
1676
|
+
// Vérifier les langages disponibles
|
|
1677
|
+
console.log('🔤 Available Prism languages:', window.Prism.languages ? Object.keys(window.Prism.languages) : 'none');
|
|
1678
|
+
|
|
1679
|
+
// Trouver tous les blocs de code avec des classes de langue
|
|
1680
|
+
const codeElements = container.querySelectorAll('code[class*="language-"]');
|
|
1681
|
+
console.log('🎨 Found', codeElements.length, 'code blocks with language classes');
|
|
1682
|
+
|
|
1683
|
+
// Debug détaillé de chaque bloc de code
|
|
1684
|
+
codeElements.forEach((el, i) => {
|
|
1685
|
+
console.log(`🔍 Code block ${i}:`);
|
|
1686
|
+
console.log(` - class: "${el.className}"`);
|
|
1687
|
+
console.log(` - content length: ${el.textContent?.length}`);
|
|
1688
|
+
console.log(` - content preview: "${el.textContent?.substring(0, 50)}..."`);
|
|
1689
|
+
console.log(` - parent visible: ${window.getComputedStyle(el.parentElement).display !== 'none'}`);
|
|
1690
|
+
console.log(` - element visible: ${window.getComputedStyle(el).display !== 'none'}`);
|
|
1691
|
+
});
|
|
1692
|
+
|
|
1693
|
+
// Aussi chercher les blocs sans classe pour debug
|
|
1694
|
+
const allCodeElements = container.querySelectorAll('code');
|
|
1695
|
+
console.log('📝 Total code blocks found:', allCodeElements.length);
|
|
1696
|
+
|
|
1697
|
+
if (codeElements.length > 0) {
|
|
1698
|
+
// Tenter manuellement sur le premier élément pour debug
|
|
1699
|
+
const firstElement = codeElements[0];
|
|
1700
|
+
console.log('🧪 Testing manual highlighting on first element...');
|
|
1701
|
+
|
|
1702
|
+
// Vérifier le langage
|
|
1703
|
+
const classList = firstElement.className.split(' ');
|
|
1704
|
+
const langClass = classList.find(cls => cls.startsWith('language-'));
|
|
1705
|
+
const lang = langClass ? langClass.replace('language-', '') : 'unknown';
|
|
1706
|
+
console.log(`🔤 Language detected: "${lang}"`);
|
|
1707
|
+
console.log(`🔤 Language available in Prism: ${!!(window.Prism.languages && window.Prism.languages[lang])}`);
|
|
1708
|
+
|
|
1709
|
+
// Test manuel
|
|
1710
|
+
if (window.Prism.languages && window.Prism.languages[lang]) {
|
|
1711
|
+
console.log('🧪 Attempting manual highlight...');
|
|
1712
|
+
const originalContent = firstElement.textContent;
|
|
1713
|
+
try {
|
|
1714
|
+
const highlighted = window.Prism.highlight(originalContent, window.Prism.languages[lang], lang);
|
|
1715
|
+
console.log(`🎨 Manual highlight result length: ${highlighted.length}`);
|
|
1716
|
+
console.log(`🎨 Manual highlight preview: "${highlighted.substring(0, 100)}..."`);
|
|
1717
|
+
|
|
1718
|
+
// Appliquer le résultat
|
|
1719
|
+
firstElement.innerHTML = highlighted;
|
|
1720
|
+
console.log('✅ Manual highlight applied');
|
|
1721
|
+
} catch (manualError) {
|
|
1722
|
+
console.error('❌ Manual highlight failed:', manualError);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
// Puis essayer la méthode normale
|
|
1727
|
+
window.Prism.highlightAllUnder(container);
|
|
1728
|
+
console.log('✅ Prism syntax highlighting applied to', codeElements.length, 'blocks');
|
|
1729
|
+
|
|
1730
|
+
// Vérifier que la coloration a fonctionné
|
|
1731
|
+
const tokenElements = container.querySelectorAll('.token');
|
|
1732
|
+
console.log('🎨 Tokens created after highlighting:', tokenElements.length);
|
|
1733
|
+
|
|
1734
|
+
// Debug des tokens créés
|
|
1735
|
+
if (tokenElements.length > 0) {
|
|
1736
|
+
tokenElements.forEach((token, i) => {
|
|
1737
|
+
console.log(`Token ${i}: "${token.textContent}" (class: ${token.className})`);
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
} else {
|
|
1741
|
+
console.log('⚠️ No code blocks with language classes found for Prism');
|
|
1742
|
+
}
|
|
1743
|
+
} catch (error) {
|
|
1744
|
+
console.error('❌ Prism highlighting error:', error);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
showConfigurationInterface() {
|
|
1749
|
+
const contentDiv = document.getElementById('ontowave-content');
|
|
1750
|
+
if (!contentDiv) return;
|
|
1751
|
+
|
|
1752
|
+
const currentConfigString = JSON.stringify(this.config, null, 2)
|
|
1753
|
+
.replace(/"/g, '"')
|
|
1754
|
+
.replace(/</g, '<')
|
|
1755
|
+
.replace(/>/g, '>');
|
|
1756
|
+
|
|
1757
|
+
contentDiv.innerHTML = `
|
|
1758
|
+
<div class="ontowave-config-interface">
|
|
1759
|
+
<div class="config-header">
|
|
1760
|
+
<h1>🌊 OntoWave Configuration</h1>
|
|
1761
|
+
<p>Aucun fichier index trouvé. Configurez OntoWave pour votre projet :</p>
|
|
1762
|
+
</div>
|
|
1763
|
+
|
|
1764
|
+
<div class="config-content">
|
|
1765
|
+
<div class="config-form">
|
|
1766
|
+
<h2>📝 Configuration</h2>
|
|
1767
|
+
|
|
1768
|
+
<div class="form-group">
|
|
1769
|
+
<label for="config-title">Titre du site :</label>
|
|
1770
|
+
<input type="text" id="config-title" />
|
|
1771
|
+
</div>
|
|
1772
|
+
|
|
1773
|
+
<div class="form-group">
|
|
1774
|
+
<label for="config-defaultPage">Page par défaut :</label>
|
|
1775
|
+
<input type="text" id="config-defaultPage" />
|
|
1776
|
+
</div>
|
|
1777
|
+
|
|
1778
|
+
<div class="form-group">
|
|
1779
|
+
<label for="config-locales">Langues supportées (séparées par des virgules) :</label>
|
|
1780
|
+
<input type="text" id="config-locales" placeholder="fr-CA, fr, en" />
|
|
1781
|
+
</div>
|
|
1782
|
+
|
|
1783
|
+
<div class="form-group">
|
|
1784
|
+
<label>
|
|
1785
|
+
<input type="checkbox" id="config-showGallery" />
|
|
1786
|
+
Afficher la galerie d'exemples
|
|
1787
|
+
</label>
|
|
1788
|
+
</div>
|
|
1789
|
+
|
|
1790
|
+
<div class="form-group">
|
|
1791
|
+
<label for="config-mermaidTheme">Thème Mermaid :</label>
|
|
1792
|
+
<select id="config-mermaidTheme">
|
|
1793
|
+
<option value="default">Default</option>
|
|
1794
|
+
<option value="dark">Dark</option>
|
|
1795
|
+
<option value="forest">Forest</option>
|
|
1796
|
+
<option value="neutral">Neutral</option>
|
|
1797
|
+
</select>
|
|
1798
|
+
</div>
|
|
1799
|
+
|
|
1800
|
+
<div class="form-actions">
|
|
1801
|
+
<button onclick="window.OntoWave.instance.updateConfigFromForm()">✅ Appliquer</button>
|
|
1802
|
+
<button onclick="window.OntoWave.instance.downloadConfig()">💾 Télécharger HTML</button>
|
|
1803
|
+
<button onclick="window.OntoWave.instance.resetConfig()">🔄 Reset</button>
|
|
1804
|
+
</div>
|
|
1805
|
+
</div>
|
|
1806
|
+
|
|
1807
|
+
<div class="config-code">
|
|
1808
|
+
<h2>💻 Code HTML généré</h2>
|
|
1809
|
+
<div class="code-preview">
|
|
1810
|
+
<pre><code id="generated-html"><!DOCTYPE html>
|
|
1811
|
+
<html>
|
|
1812
|
+
<head>
|
|
1813
|
+
<meta charset="UTF-8">
|
|
1814
|
+
<title>${this.config.title}</title>
|
|
1815
|
+
</head>
|
|
1816
|
+
<body>
|
|
1817
|
+
<script src="ontowave.min.js"></script>
|
|
1818
|
+
<script type="application/json" id="ontowave-config">
|
|
1819
|
+
${currentConfigString}
|
|
1820
|
+
</script>
|
|
1821
|
+
</body>
|
|
1822
|
+
</html></code></pre>
|
|
1823
|
+
</div>
|
|
1824
|
+
|
|
1825
|
+
<div class="usage-info">
|
|
1826
|
+
<h3>📋 Instructions d'utilisation</h3>
|
|
1827
|
+
<ol>
|
|
1828
|
+
<li>Configurez les options dans le formulaire</li>
|
|
1829
|
+
<li>Cliquez sur "Télécharger HTML" pour obtenir votre fichier</li>
|
|
1830
|
+
<li>Placez vos fichiers .md dans le même dossier</li>
|
|
1831
|
+
<li>Ouvrez le fichier HTML dans votre navigateur</li>
|
|
1832
|
+
</ol>
|
|
1833
|
+
|
|
1834
|
+
<h3>🌐 Gestion des langues</h3>
|
|
1835
|
+
<ul>
|
|
1836
|
+
<li><strong>Monolingue :</strong> Laissez "Langues supportées" vide</li>
|
|
1837
|
+
<li><strong>Multilingue :</strong> Ajoutez les codes de langue (ex: fr, en, fr-CA)</li>
|
|
1838
|
+
<li><strong>Fichiers :</strong> index.fr.md, index.en.md, etc.</li>
|
|
1839
|
+
<li><strong>Fallback :</strong> index.md si aucune langue trouvée</li>
|
|
1840
|
+
</ul>
|
|
1841
|
+
</div>
|
|
1842
|
+
</div>
|
|
1843
|
+
</div>
|
|
1844
|
+
</div>
|
|
1845
|
+
`;
|
|
1846
|
+
|
|
1847
|
+
// Ajouter les styles pour l'interface de configuration
|
|
1848
|
+
this.addConfigStyles();
|
|
1849
|
+
|
|
1850
|
+
// Remplir les valeurs des champs après génération du HTML (une seule fois)
|
|
1851
|
+
this.populateConfigForm();
|
|
1852
|
+
|
|
1853
|
+
// Générer le code HTML initial
|
|
1854
|
+
this.updateGeneratedCode();
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
// Méthode pour remplir les valeurs du formulaire
|
|
1858
|
+
populateConfigForm() {
|
|
1859
|
+
const titleField = document.getElementById('config-title');
|
|
1860
|
+
const defaultPageField = document.getElementById('config-defaultPage');
|
|
1861
|
+
const localesField = document.getElementById('config-locales');
|
|
1862
|
+
const showGalleryField = document.getElementById('config-showGallery');
|
|
1863
|
+
const mermaidThemeField = document.getElementById('config-mermaidTheme');
|
|
1864
|
+
|
|
1865
|
+
if (titleField) titleField.value = this.config.title;
|
|
1866
|
+
if (defaultPageField) defaultPageField.value = this.config.defaultPage;
|
|
1867
|
+
if (localesField) localesField.value = this.config.locales.join(', ');
|
|
1868
|
+
if (showGalleryField) showGalleryField.checked = this.config.showGallery;
|
|
1869
|
+
if (mermaidThemeField) mermaidThemeField.value = this.config.mermaid.theme;
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
addConfigStyles() {
|
|
1873
|
+
if (document.getElementById('ontowave-config-styles')) return;
|
|
1874
|
+
|
|
1875
|
+
const style = document.createElement('style');
|
|
1876
|
+
style.id = 'ontowave-config-styles';
|
|
1877
|
+
style.textContent = `
|
|
1878
|
+
.ontowave-config-interface {
|
|
1879
|
+
max-width: 1200px;
|
|
1880
|
+
margin: 0 auto;
|
|
1881
|
+
padding: 20px;
|
|
1882
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
.config-header {
|
|
1886
|
+
text-align: center;
|
|
1887
|
+
margin-bottom: 40px;
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
.config-header h1 {
|
|
1891
|
+
color: #0969da;
|
|
1892
|
+
margin-bottom: 10px;
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
.config-content {
|
|
1896
|
+
display: grid;
|
|
1897
|
+
grid-template-columns: 1fr 1fr;
|
|
1898
|
+
gap: 40px;
|
|
1899
|
+
align-items: start;
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
.config-form {
|
|
1903
|
+
background: #f8f9fa;
|
|
1904
|
+
padding: 30px;
|
|
1905
|
+
border-radius: 12px;
|
|
1906
|
+
border: 1px solid #e1e4e8;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
.config-code {
|
|
1910
|
+
background: #ffffff;
|
|
1911
|
+
padding: 30px;
|
|
1912
|
+
border-radius: 12px;
|
|
1913
|
+
border: 1px solid #e1e4e8;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
.form-group {
|
|
1917
|
+
margin-bottom: 20px;
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
.form-group label {
|
|
1921
|
+
display: block;
|
|
1922
|
+
font-weight: 600;
|
|
1923
|
+
margin-bottom: 8px;
|
|
1924
|
+
color: #24292e;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
.form-group input, .form-group select {
|
|
1928
|
+
width: 100%;
|
|
1929
|
+
padding: 10px;
|
|
1930
|
+
border: 1px solid #d0d7de;
|
|
1931
|
+
border-radius: 6px;
|
|
1932
|
+
font-size: 14px;
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
.form-group input[type="checkbox"] {
|
|
1936
|
+
width: auto;
|
|
1937
|
+
margin-right: 8px;
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
.form-actions {
|
|
1941
|
+
display: flex;
|
|
1942
|
+
gap: 10px;
|
|
1943
|
+
margin-top: 30px;
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
.form-actions button {
|
|
1947
|
+
flex: 1;
|
|
1948
|
+
padding: 12px 20px;
|
|
1949
|
+
border: none;
|
|
1950
|
+
border-radius: 6px;
|
|
1951
|
+
font-weight: 600;
|
|
1952
|
+
cursor: pointer;
|
|
1953
|
+
transition: all 0.2s ease;
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
.form-actions button:first-child {
|
|
1957
|
+
background: #28a745;
|
|
1958
|
+
color: white;
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
.form-actions button:nth-child(2) {
|
|
1962
|
+
background: #0969da;
|
|
1963
|
+
color: white;
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
.form-actions button:last-child {
|
|
1967
|
+
background: #6c757d;
|
|
1968
|
+
color: white;
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
.form-actions button:hover {
|
|
1972
|
+
transform: translateY(-1px);
|
|
1973
|
+
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
.code-preview {
|
|
1977
|
+
background: #f6f8fa;
|
|
1978
|
+
border: 1px solid #e1e4e8;
|
|
1979
|
+
border-radius: 6px;
|
|
1980
|
+
padding: 16px;
|
|
1981
|
+
overflow-x: auto;
|
|
1982
|
+
margin-bottom: 20px;
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
.code-preview pre {
|
|
1986
|
+
margin: 0;
|
|
1987
|
+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
1988
|
+
font-size: 13px;
|
|
1989
|
+
line-height: 1.4;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
.usage-info h3 {
|
|
1993
|
+
color: #0969da;
|
|
1994
|
+
margin-top: 25px;
|
|
1995
|
+
margin-bottom: 10px;
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
.usage-info ul, .usage-info ol {
|
|
1999
|
+
padding-left: 20px;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
.usage-info li {
|
|
2003
|
+
margin-bottom: 5px;
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
@media (max-width: 768px) {
|
|
2007
|
+
.config-content {
|
|
2008
|
+
grid-template-columns: 1fr;
|
|
2009
|
+
gap: 20px;
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
`;
|
|
2013
|
+
|
|
2014
|
+
document.head.appendChild(style);
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
updateConfigFromForm() {
|
|
2018
|
+
// Mettre à jour la configuration depuis le formulaire
|
|
2019
|
+
const title = document.getElementById('config-title').value;
|
|
2020
|
+
const defaultPage = document.getElementById('config-defaultPage').value;
|
|
2021
|
+
const locales = document.getElementById('config-locales').value
|
|
2022
|
+
.split(',')
|
|
2023
|
+
.map(l => l.trim())
|
|
2024
|
+
.filter(l => l.length > 0);
|
|
2025
|
+
const showGallery = document.getElementById('config-showGallery').checked;
|
|
2026
|
+
const mermaidTheme = document.getElementById('config-mermaidTheme').value;
|
|
2027
|
+
|
|
2028
|
+
this.config.title = title;
|
|
2029
|
+
this.config.defaultPage = defaultPage;
|
|
2030
|
+
this.config.locales = locales;
|
|
2031
|
+
this.config.showGallery = showGallery;
|
|
2032
|
+
this.config.mermaid.theme = mermaidTheme;
|
|
2033
|
+
|
|
2034
|
+
console.log('📝 Configuration updated:', this.config);
|
|
2035
|
+
|
|
2036
|
+
// Mettre à jour le titre de la page
|
|
2037
|
+
document.title = this.config.title;
|
|
2038
|
+
|
|
2039
|
+
// Régénérer le code HTML
|
|
2040
|
+
this.updateGeneratedCode();
|
|
2041
|
+
|
|
2042
|
+
// Afficher notification
|
|
2043
|
+
this.showNotification('✅ Configuration mise à jour');
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
updateGeneratedCode() {
|
|
2047
|
+
// Créer une config simplifiée pour l'affichage
|
|
2048
|
+
const simpleConfig = {
|
|
2049
|
+
title: this.config.title,
|
|
2050
|
+
baseUrl: this.config.baseUrl,
|
|
2051
|
+
defaultPage: this.config.defaultPage,
|
|
2052
|
+
locales: this.config.locales,
|
|
2053
|
+
fallbackLocale: this.config.fallbackLocale,
|
|
2054
|
+
showGallery: this.config.showGallery,
|
|
2055
|
+
mermaid: {
|
|
2056
|
+
theme: this.config.mermaid.theme
|
|
2057
|
+
}
|
|
2058
|
+
};
|
|
2059
|
+
|
|
2060
|
+
const configString = JSON.stringify(simpleConfig, null, 2)
|
|
2061
|
+
.replace(/"/g, '"')
|
|
2062
|
+
.replace(/</g, '<')
|
|
2063
|
+
.replace(/>/g, '>');
|
|
2064
|
+
|
|
2065
|
+
const htmlCode = `<!DOCTYPE html>
|
|
2066
|
+
<html>
|
|
2067
|
+
<head>
|
|
2068
|
+
<meta charset="UTF-8">
|
|
2069
|
+
<title>${this.config.title}</title>
|
|
2070
|
+
</head>
|
|
2071
|
+
<body>
|
|
2072
|
+
<script src="ontowave.min.js"></script>
|
|
2073
|
+
<script type="application/json" id="ontowave-config">
|
|
2074
|
+
${configString}
|
|
2075
|
+
</script>
|
|
2076
|
+
</body>
|
|
2077
|
+
</html>`;
|
|
2078
|
+
|
|
2079
|
+
const codeElement = document.getElementById('generated-html');
|
|
2080
|
+
if (codeElement) {
|
|
2081
|
+
codeElement.innerHTML = htmlCode;
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
downloadConfig() {
|
|
2086
|
+
// Utiliser la config simplifiée pour le téléchargement aussi
|
|
2087
|
+
const simpleConfig = {
|
|
2088
|
+
title: this.config.title,
|
|
2089
|
+
baseUrl: this.config.baseUrl,
|
|
2090
|
+
defaultPage: this.config.defaultPage,
|
|
2091
|
+
locales: this.config.locales,
|
|
2092
|
+
fallbackLocale: this.config.fallbackLocale,
|
|
2093
|
+
showGallery: this.config.showGallery,
|
|
2094
|
+
mermaid: {
|
|
2095
|
+
theme: this.config.mermaid.theme
|
|
2096
|
+
}
|
|
2097
|
+
};
|
|
2098
|
+
|
|
2099
|
+
const configString = JSON.stringify(simpleConfig, null, 2);
|
|
2100
|
+
|
|
2101
|
+
const htmlContent = `<!DOCTYPE html>
|
|
2102
|
+
<html>
|
|
2103
|
+
<head>
|
|
2104
|
+
<meta charset="UTF-8">
|
|
2105
|
+
<title>${this.config.title}</title>
|
|
2106
|
+
</head>
|
|
2107
|
+
<body>
|
|
2108
|
+
<script src="ontowave.min.js"></script>
|
|
2109
|
+
<script type="application/json" id="ontowave-config">
|
|
2110
|
+
${configString}
|
|
2111
|
+
</script>
|
|
2112
|
+
</body>
|
|
2113
|
+
</html>`;
|
|
2114
|
+
|
|
2115
|
+
const blob = new Blob([htmlContent], { type: 'text/html' });
|
|
2116
|
+
const url = URL.createObjectURL(blob);
|
|
2117
|
+
|
|
2118
|
+
const a = document.createElement('a');
|
|
2119
|
+
a.href = url;
|
|
2120
|
+
a.download = 'index.html';
|
|
2121
|
+
document.body.appendChild(a);
|
|
2122
|
+
a.click();
|
|
2123
|
+
document.body.removeChild(a);
|
|
2124
|
+
URL.revokeObjectURL(url);
|
|
2125
|
+
|
|
2126
|
+
this.showNotification('💾 Fichier HTML téléchargé');
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
resetConfig() {
|
|
2130
|
+
this.config = { ...DEFAULT_CONFIG };
|
|
2131
|
+
this.showConfigurationInterface();
|
|
2132
|
+
this.showNotification('🔄 Configuration réinitialisée');
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
showNotification(message) {
|
|
2136
|
+
// Créer une notification temporaire
|
|
2137
|
+
const notification = document.createElement('div');
|
|
2138
|
+
notification.style.cssText = `
|
|
2139
|
+
position: fixed;
|
|
2140
|
+
top: 20px;
|
|
2141
|
+
right: 20px;
|
|
2142
|
+
background: #28a745;
|
|
2143
|
+
color: white;
|
|
2144
|
+
padding: 12px 20px;
|
|
2145
|
+
border-radius: 6px;
|
|
2146
|
+
z-index: 10000;
|
|
2147
|
+
font-weight: 600;
|
|
2148
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
2149
|
+
animation: slideIn 0.3s ease;
|
|
2150
|
+
`;
|
|
2151
|
+
notification.textContent = message;
|
|
2152
|
+
|
|
2153
|
+
// Ajouter animation CSS
|
|
2154
|
+
if (!document.getElementById('notification-styles')) {
|
|
2155
|
+
const style = document.createElement('style');
|
|
2156
|
+
style.id = 'notification-styles';
|
|
2157
|
+
style.textContent = `
|
|
2158
|
+
@keyframes slideIn {
|
|
2159
|
+
from { transform: translateX(100%); opacity: 0; }
|
|
2160
|
+
to { transform: translateX(0); opacity: 1; }
|
|
2161
|
+
}
|
|
2162
|
+
`;
|
|
2163
|
+
document.head.appendChild(style);
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
document.body.appendChild(notification);
|
|
2167
|
+
|
|
2168
|
+
setTimeout(() => {
|
|
2169
|
+
notification.style.animation = 'slideIn 0.3s ease reverse';
|
|
2170
|
+
setTimeout(() => {
|
|
2171
|
+
if (notification.parentNode) {
|
|
2172
|
+
notification.parentNode.removeChild(notification);
|
|
2173
|
+
}
|
|
2174
|
+
}, 300);
|
|
2175
|
+
}, 3000);
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2178
|
+
showError(message) {
|
|
2179
|
+
const contentDiv = document.getElementById('ontowave-content');
|
|
2180
|
+
if (contentDiv) {
|
|
2181
|
+
contentDiv.innerHTML = `<div class="ontowave-error">❌ ${message}</div>`;
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
// Panneau de configuration dans le menu flottant
|
|
2186
|
+
toggleConfigurationPanel(event, locale = null) {
|
|
2187
|
+
if (event) {
|
|
2188
|
+
event.preventDefault();
|
|
2189
|
+
event.stopPropagation();
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
const targetLang = locale || this.getCurrentLanguage();
|
|
2193
|
+
console.log('⚙️ Opening config panel with locale:', targetLang);
|
|
2194
|
+
|
|
2195
|
+
const menuContent = document.querySelector('.ontowave-menu-content');
|
|
2196
|
+
if (!menuContent) {
|
|
2197
|
+
console.error('Menu content not found');
|
|
2198
|
+
return;
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
// Trouver le bouton Configuration
|
|
2202
|
+
const configButton = document.querySelector('.ontowave-menu-option[onclick*="toggleConfigurationPanel"]');
|
|
2203
|
+
|
|
2204
|
+
// Vérifier si le panneau existe déjà
|
|
2205
|
+
let configPanel = document.getElementById('ontowave-config-panel');
|
|
2206
|
+
|
|
2207
|
+
if (configPanel) {
|
|
2208
|
+
// Si le panneau existe, le supprimer (toggle off)
|
|
2209
|
+
configPanel.remove();
|
|
2210
|
+
if (configButton) {
|
|
2211
|
+
configButton.classList.remove('selected');
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
// Supprimer la classe pour réactiver le zoom au survol
|
|
2215
|
+
const floatingMenu = document.getElementById('ontowave-floating-menu');
|
|
2216
|
+
if (floatingMenu) {
|
|
2217
|
+
floatingMenu.classList.remove('has-config-panel');
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2220
|
+
// Mettre à jour l'état de déplacement après fermeture du panneau
|
|
2221
|
+
if (typeof window.ontowaveUpdateDragState === 'function') {
|
|
2222
|
+
window.ontowaveUpdateDragState();
|
|
2223
|
+
}
|
|
2224
|
+
console.log('Config panel closed');
|
|
2225
|
+
return;
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
// Marquer le bouton comme sélectionné
|
|
2229
|
+
if (configButton) {
|
|
2230
|
+
configButton.classList.add('selected');
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
// Créer le panneau de configuration
|
|
2234
|
+
configPanel = document.createElement('div');
|
|
2235
|
+
configPanel.id = 'ontowave-config-panel';
|
|
2236
|
+
configPanel.className = 'ontowave-config-panel';
|
|
2237
|
+
|
|
2238
|
+
configPanel.innerHTML = `
|
|
2239
|
+
<div class="config-panel-content">
|
|
2240
|
+
<div class="config-full-panel">
|
|
2241
|
+
<h3>🌊 ${this.t('configTitle', targetLang)}</h3>
|
|
2242
|
+
|
|
2243
|
+
<!-- Section Général -->
|
|
2244
|
+
<div class="config-section">
|
|
2245
|
+
<h4>📖 ${this.t('configGeneral', targetLang)}</h4>
|
|
2246
|
+
<div class="config-row">
|
|
2247
|
+
<div class="form-group-full">
|
|
2248
|
+
<label for="config-title-full">${this.t('configSiteTitle', targetLang)}</label>
|
|
2249
|
+
<input type="text" id="config-title-full" value="${this.config.title}" />
|
|
2250
|
+
</div>
|
|
2251
|
+
<div class="form-group-full">
|
|
2252
|
+
<label for="config-defaultPage-full">${this.t('configDefaultPage', targetLang)}</label>
|
|
2253
|
+
<input type="text" id="config-defaultPage-full" value="${this.config.defaultPage}" placeholder="index.md" />
|
|
2254
|
+
</div>
|
|
2255
|
+
</div>
|
|
2256
|
+
<div class="form-group-full">
|
|
2257
|
+
<label for="config-baseUrl-full">${this.t('configBaseUrl', targetLang)}</label>
|
|
2258
|
+
<input type="text" id="config-baseUrl-full" value="${this.config.baseUrl}" placeholder="/" />
|
|
2259
|
+
</div>
|
|
2260
|
+
</div>
|
|
2261
|
+
|
|
2262
|
+
<!-- Section Langues et Localisation -->
|
|
2263
|
+
<div class="config-section">
|
|
2264
|
+
<h4>🌍 ${this.t('configLanguages', targetLang)}</h4>
|
|
2265
|
+
<div class="config-row">
|
|
2266
|
+
<div class="form-group-full">
|
|
2267
|
+
<label for="config-locales-full">${this.t('configSupportedLanguages', targetLang)}</label>
|
|
2268
|
+
<input type="text" id="config-locales-full" value="${this.config.locales.join(', ')}" placeholder="fr-CA, fr, en" />
|
|
2269
|
+
<small>${this.t('configLanguageNote', targetLang)}</small>
|
|
2270
|
+
</div>
|
|
2271
|
+
<div class="form-group-full">
|
|
2272
|
+
<label for="config-fallbackLocale-full">${this.t('configFallbackLanguage', targetLang)}</label>
|
|
2273
|
+
<select id="config-fallbackLocale-full">
|
|
2274
|
+
<option value="en" ${this.config.fallbackLocale === 'en' ? 'selected' : ''}>English (en)</option>
|
|
2275
|
+
<option value="fr" ${this.config.fallbackLocale === 'fr' ? 'selected' : ''}>Français (fr)</option>
|
|
2276
|
+
<option value="es" ${this.config.fallbackLocale === 'es' ? 'selected' : ''}>Español (es)</option>
|
|
2277
|
+
<option value="de" ${this.config.fallbackLocale === 'de' ? 'selected' : ''}>Deutsch (de)</option>
|
|
2278
|
+
</select>
|
|
2279
|
+
</div>
|
|
2280
|
+
</div>
|
|
2281
|
+
</div>
|
|
2282
|
+
|
|
2283
|
+
<!-- Section Navigation et Interface -->
|
|
2284
|
+
<div class="config-section">
|
|
2285
|
+
<h4>🧭 ${this.t('configNavigation', targetLang)}</h4>
|
|
2286
|
+
<div class="config-row">
|
|
2287
|
+
<div class="form-group-checkbox">
|
|
2288
|
+
<label>
|
|
2289
|
+
<input type="checkbox" id="config-showGallery-full" ${this.config.showGallery ? 'checked' : ''} />
|
|
2290
|
+
🎨 ${this.t('configShowGallery', targetLang)}
|
|
2291
|
+
</label>
|
|
2292
|
+
</div>
|
|
2293
|
+
<div class="form-group-checkbox">
|
|
2294
|
+
<label>
|
|
2295
|
+
<input type="checkbox" id="config-navHome-full" ${this.config.navigation?.showHome !== false ? 'checked' : ''} />
|
|
2296
|
+
🏠 ${this.t('configHomeButton', targetLang)}
|
|
2297
|
+
</label>
|
|
2298
|
+
</div>
|
|
2299
|
+
</div>
|
|
2300
|
+
<div class="config-row">
|
|
2301
|
+
<div class="form-group-checkbox">
|
|
2302
|
+
<label>
|
|
2303
|
+
<input type="checkbox" id="config-navBreadcrumb-full" ${this.config.navigation?.showBreadcrumb !== false ? 'checked' : ''} />
|
|
2304
|
+
📍 ${this.t('configBreadcrumb', targetLang)}
|
|
2305
|
+
</label>
|
|
2306
|
+
</div>
|
|
2307
|
+
<div class="form-group-checkbox">
|
|
2308
|
+
<label>
|
|
2309
|
+
<input type="checkbox" id="config-navToc-full" ${this.config.navigation?.showToc !== false ? 'checked' : ''} />
|
|
2310
|
+
📑 ${this.t('configToc', targetLang)}
|
|
2311
|
+
</label>
|
|
2312
|
+
</div>
|
|
2313
|
+
</div>
|
|
2314
|
+
</div>
|
|
2315
|
+
|
|
2316
|
+
<!-- Section Diagrammes Mermaid -->
|
|
2317
|
+
<div class="config-section">
|
|
2318
|
+
<h4>📊 ${this.t('configMermaid', targetLang)}</h4>
|
|
2319
|
+
<div class="config-row">
|
|
2320
|
+
<div class="form-group-full">
|
|
2321
|
+
<label for="config-mermaidTheme-full">${this.t('configMermaidTheme', targetLang)}</label>
|
|
2322
|
+
<select id="config-mermaidTheme-full">
|
|
2323
|
+
<option value="default" ${this.config.mermaid?.theme === 'default' ? 'selected' : ''}>Default (clair)</option>
|
|
2324
|
+
<option value="dark" ${this.config.mermaid?.theme === 'dark' ? 'selected' : ''}>Dark (sombre)</option>
|
|
2325
|
+
<option value="forest" ${this.config.mermaid?.theme === 'forest' ? 'selected' : ''}>Forest (vert)</option>
|
|
2326
|
+
<option value="neutral" ${this.config.mermaid?.theme === 'neutral' ? 'selected' : ''}>Neutral (neutre)</option>
|
|
2327
|
+
</select>
|
|
2328
|
+
</div>
|
|
2329
|
+
<div class="form-group-checkbox">
|
|
2330
|
+
<label>
|
|
2331
|
+
<input type="checkbox" id="config-mermaidStart-full" ${this.config.mermaid?.startOnLoad !== false ? 'checked' : ''} />
|
|
2332
|
+
🚀 ${this.t('configMermaidAuto', targetLang)}
|
|
2333
|
+
</label>
|
|
2334
|
+
</div>
|
|
2335
|
+
</div>
|
|
2336
|
+
<div class="config-row">
|
|
2337
|
+
<div class="form-group-checkbox">
|
|
2338
|
+
<label>
|
|
2339
|
+
<input type="checkbox" id="config-mermaidMaxWidth-full" ${this.config.mermaid?.flowchart?.useMaxWidth !== false ? 'checked' : ''} />
|
|
2340
|
+
📐 ${this.t('configMermaidMaxWidth', targetLang)}
|
|
2341
|
+
</label>
|
|
2342
|
+
</div>
|
|
2343
|
+
</div>
|
|
2344
|
+
</div>
|
|
2345
|
+
|
|
2346
|
+
<!-- Section PlantUML -->
|
|
2347
|
+
<div class="config-section">
|
|
2348
|
+
<h4>🌿 ${this.t('configPlantuml', targetLang)}</h4>
|
|
2349
|
+
<div class="config-row">
|
|
2350
|
+
<div class="form-group-full">
|
|
2351
|
+
<label for="config-plantumlServer-full">${this.t('configPlantumlServer', targetLang)}</label>
|
|
2352
|
+
<input type="text" id="config-plantumlServer-full" value="${this.config.plantuml?.server || 'https://www.plantuml.com/plantuml'}" />
|
|
2353
|
+
</div>
|
|
2354
|
+
<div class="form-group-full">
|
|
2355
|
+
<label for="config-plantumlFormat-full">${this.t('configPlantumlFormat', targetLang)}</label>
|
|
2356
|
+
<select id="config-plantumlFormat-full">
|
|
2357
|
+
<option value="svg" ${this.config.plantuml?.format === 'svg' ? 'selected' : ''}>SVG (vectoriel)</option>
|
|
2358
|
+
<option value="png" ${this.config.plantuml?.format === 'png' ? 'selected' : ''}>PNG (bitmap)</option>
|
|
2359
|
+
</select>
|
|
2360
|
+
</div>
|
|
2361
|
+
</div>
|
|
2362
|
+
</div>
|
|
2363
|
+
|
|
2364
|
+
<!-- Section Coloration Syntaxique -->
|
|
2365
|
+
<div class="config-section">
|
|
2366
|
+
<h4>🎨 ${this.t('configPrism', targetLang)}</h4>
|
|
2367
|
+
<div class="config-row">
|
|
2368
|
+
<div class="form-group-full">
|
|
2369
|
+
<label for="config-prismTheme-full">${this.t('configPrismTheme', targetLang)}</label>
|
|
2370
|
+
<select id="config-prismTheme-full">
|
|
2371
|
+
<option value="default" ${this.config.prism?.theme === 'default' ? 'selected' : ''}>Default (clair)</option>
|
|
2372
|
+
<option value="dark" ${this.config.prism?.theme === 'dark' ? 'selected' : ''}>Dark (sombre)</option>
|
|
2373
|
+
<option value="twilight" ${this.config.prism?.theme === 'twilight' ? 'selected' : ''}>Twilight</option>
|
|
2374
|
+
</select>
|
|
2375
|
+
</div>
|
|
2376
|
+
<div class="form-group-checkbox">
|
|
2377
|
+
<label>
|
|
2378
|
+
<input type="checkbox" id="config-prismAutoload-full" ${this.config.prism?.autoload !== false ? 'checked' : ''} />
|
|
2379
|
+
🔄 ${this.t('configPrismAutoload', targetLang)}
|
|
2380
|
+
</label>
|
|
2381
|
+
</div>
|
|
2382
|
+
</div>
|
|
2383
|
+
</div>
|
|
2384
|
+
|
|
2385
|
+
<!-- Section Interface Utilisateur -->
|
|
2386
|
+
<div class="config-section">
|
|
2387
|
+
<h4>💻 ${this.t('configUI', targetLang)}</h4>
|
|
2388
|
+
<div class="config-row">
|
|
2389
|
+
<div class="form-group-full">
|
|
2390
|
+
<label for="config-uiTheme-full">${this.t('configUITheme', targetLang)}</label>
|
|
2391
|
+
<select id="config-uiTheme-full">
|
|
2392
|
+
<option value="default" ${this.config.ui?.theme === 'default' ? 'selected' : ''}>Default (clair)</option>
|
|
2393
|
+
<option value="dark" ${this.config.ui?.theme === 'dark' ? 'selected' : ''}>Dark (sombre)</option>
|
|
2394
|
+
<option value="auto" ${this.config.ui?.theme === 'auto' ? 'selected' : ''}>Auto (système)</option>
|
|
2395
|
+
</select>
|
|
2396
|
+
</div>
|
|
2397
|
+
<div class="form-group-checkbox">
|
|
2398
|
+
<label>
|
|
2399
|
+
<input type="checkbox" id="config-uiResponsive-full" ${this.config.ui?.responsive !== false ? 'checked' : ''} />
|
|
2400
|
+
📱 ${this.t('configUIResponsive', targetLang)}
|
|
2401
|
+
</label>
|
|
2402
|
+
</div>
|
|
2403
|
+
</div>
|
|
2404
|
+
<div class="config-row">
|
|
2405
|
+
<div class="form-group-checkbox">
|
|
2406
|
+
<label>
|
|
2407
|
+
<input type="checkbox" id="config-uiAnimations-full" ${this.config.ui?.animations !== false ? 'checked' : ''} />
|
|
2408
|
+
✨ ${this.t('configUIAnimations', targetLang)}
|
|
2409
|
+
</label>
|
|
2410
|
+
</div>
|
|
2411
|
+
</div>
|
|
2412
|
+
</div>
|
|
2413
|
+
|
|
2414
|
+
<!-- Actions -->
|
|
2415
|
+
<div class="form-actions-full">
|
|
2416
|
+
<button onclick="window.OntoWave.instance.updateConfigFromFullPanel()" class="btn-primary">✅ ${this.t('configApply', targetLang)}</button>
|
|
2417
|
+
<button onclick="window.OntoWave.instance.downloadConfigFromPanel()" class="btn-secondary">💾 ${this.t('configDownloadHTML', targetLang)}</button>
|
|
2418
|
+
<button onclick="window.OntoWave.instance.downloadOntoWaveScript()" class="btn-secondary">📥 ${this.t('configDownloadJS', targetLang)}</button>
|
|
2419
|
+
<button onclick="window.OntoWave.instance.resetConfigToDefaults()" class="btn-warning">🔄 ${this.t('configReset', targetLang)}</button>
|
|
2420
|
+
</div>
|
|
2421
|
+
</div>
|
|
2422
|
+
</div>
|
|
2423
|
+
`;
|
|
2424
|
+
|
|
2425
|
+
// Ajouter les styles du panneau
|
|
2426
|
+
this.addConfigPanelStyles();
|
|
2427
|
+
|
|
2428
|
+
// Insérer le panneau après le menu
|
|
2429
|
+
menuContent.appendChild(configPanel);
|
|
2430
|
+
|
|
2431
|
+
// Ajouter la classe pour désactiver le zoom au survol
|
|
2432
|
+
const floatingMenu = document.getElementById('ontowave-floating-menu');
|
|
2433
|
+
if (floatingMenu) {
|
|
2434
|
+
floatingMenu.classList.add('has-config-panel');
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2437
|
+
// Mettre à jour l'état de déplacement après ouverture du panneau
|
|
2438
|
+
if (typeof window.ontowaveUpdateDragState === 'function') {
|
|
2439
|
+
window.ontowaveUpdateDragState();
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
// Générer le code HTML initial
|
|
2443
|
+
this.updateGeneratedCodeMini();
|
|
2444
|
+
|
|
2445
|
+
console.log('Config panel opened');
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
// Méthodes pour le panneau complet
|
|
2449
|
+
updateConfigFromFullPanel() {
|
|
2450
|
+
// Général
|
|
2451
|
+
const title = document.getElementById('config-title-full')?.value || this.config.title;
|
|
2452
|
+
const defaultPage = document.getElementById('config-defaultPage-full')?.value || this.config.defaultPage;
|
|
2453
|
+
const baseUrl = document.getElementById('config-baseUrl-full')?.value || this.config.baseUrl;
|
|
2454
|
+
|
|
2455
|
+
// Langues
|
|
2456
|
+
const locales = document.getElementById('config-locales-full')?.value
|
|
2457
|
+
.split(',')
|
|
2458
|
+
.map(l => l.trim())
|
|
2459
|
+
.filter(l => l.length > 0) || this.config.locales;
|
|
2460
|
+
const fallbackLocale = document.getElementById('config-fallbackLocale-full')?.value || this.config.fallbackLocale;
|
|
2461
|
+
|
|
2462
|
+
// Navigation
|
|
2463
|
+
const showGallery = document.getElementById('config-showGallery-full')?.checked || false;
|
|
2464
|
+
const showHome = document.getElementById('config-navHome-full')?.checked !== false;
|
|
2465
|
+
const showBreadcrumb = document.getElementById('config-navBreadcrumb-full')?.checked !== false;
|
|
2466
|
+
const showToc = document.getElementById('config-navToc-full')?.checked !== false;
|
|
2467
|
+
|
|
2468
|
+
// Mermaid
|
|
2469
|
+
const mermaidTheme = document.getElementById('config-mermaidTheme-full')?.value || 'default';
|
|
2470
|
+
const mermaidStart = document.getElementById('config-mermaidStart-full')?.checked !== false;
|
|
2471
|
+
const mermaidMaxWidth = document.getElementById('config-mermaidMaxWidth-full')?.checked !== false;
|
|
2472
|
+
|
|
2473
|
+
// PlantUML
|
|
2474
|
+
const plantumlServer = document.getElementById('config-plantumlServer-full')?.value || 'https://www.plantuml.com/plantuml';
|
|
2475
|
+
const plantumlFormat = document.getElementById('config-plantumlFormat-full')?.value || 'svg';
|
|
2476
|
+
|
|
2477
|
+
// Prism
|
|
2478
|
+
const prismTheme = document.getElementById('config-prismTheme-full')?.value || 'default';
|
|
2479
|
+
const prismAutoload = document.getElementById('config-prismAutoload-full')?.checked !== false;
|
|
2480
|
+
|
|
2481
|
+
// UI
|
|
2482
|
+
const uiTheme = document.getElementById('config-uiTheme-full')?.value || 'default';
|
|
2483
|
+
const uiResponsive = document.getElementById('config-uiResponsive-full')?.checked !== false;
|
|
2484
|
+
const uiAnimations = document.getElementById('config-uiAnimations-full')?.checked !== false;
|
|
2485
|
+
|
|
2486
|
+
// Mettre à jour la configuration
|
|
2487
|
+
this.config.title = title;
|
|
2488
|
+
this.config.defaultPage = defaultPage;
|
|
2489
|
+
this.config.baseUrl = baseUrl;
|
|
2490
|
+
this.config.locales = locales;
|
|
2491
|
+
this.config.fallbackLocale = fallbackLocale;
|
|
2492
|
+
this.config.showGallery = showGallery;
|
|
2493
|
+
|
|
2494
|
+
this.config.navigation = {
|
|
2495
|
+
showHome: showHome,
|
|
2496
|
+
showBreadcrumb: showBreadcrumb,
|
|
2497
|
+
showToc: showToc
|
|
2498
|
+
};
|
|
2499
|
+
|
|
2500
|
+
this.config.mermaid = {
|
|
2501
|
+
theme: mermaidTheme,
|
|
2502
|
+
startOnLoad: mermaidStart,
|
|
2503
|
+
flowchart: { useMaxWidth: mermaidMaxWidth },
|
|
2504
|
+
sequence: { useMaxWidth: mermaidMaxWidth },
|
|
2505
|
+
gantt: { useMaxWidth: mermaidMaxWidth },
|
|
2506
|
+
journey: { useMaxWidth: mermaidMaxWidth }
|
|
2507
|
+
};
|
|
2508
|
+
|
|
2509
|
+
this.config.plantuml = {
|
|
2510
|
+
server: plantumlServer,
|
|
2511
|
+
format: plantumlFormat
|
|
2512
|
+
};
|
|
2513
|
+
|
|
2514
|
+
this.config.prism = {
|
|
2515
|
+
theme: prismTheme,
|
|
2516
|
+
autoload: prismAutoload
|
|
2517
|
+
};
|
|
2518
|
+
|
|
2519
|
+
this.config.ui = {
|
|
2520
|
+
theme: uiTheme,
|
|
2521
|
+
responsive: uiResponsive,
|
|
2522
|
+
animations: uiAnimations
|
|
2523
|
+
};
|
|
2524
|
+
|
|
2525
|
+
// Mettre à jour le titre de la page
|
|
2526
|
+
document.title = this.config.title;
|
|
2527
|
+
|
|
2528
|
+
// Afficher une notification
|
|
2529
|
+
this.showNotification('Configuration appliquée avec succès ! 🎉');
|
|
2530
|
+
|
|
2531
|
+
console.log('Configuration mise à jour:', this.config);
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
resetConfigToDefaults() {
|
|
2535
|
+
if (confirm('Voulez-vous vraiment réinitialiser toute la configuration aux valeurs par défaut ?')) {
|
|
2536
|
+
// Réinitialiser avec les valeurs par défaut
|
|
2537
|
+
Object.assign(this.config, {
|
|
2538
|
+
title: "OntoWave Documentation",
|
|
2539
|
+
baseUrl: "/",
|
|
2540
|
+
defaultPage: "index.md",
|
|
2541
|
+
locales: [],
|
|
2542
|
+
fallbackLocale: "en",
|
|
2543
|
+
showGallery: false,
|
|
2544
|
+
mermaid: {
|
|
2545
|
+
theme: "default",
|
|
2546
|
+
startOnLoad: true,
|
|
2547
|
+
flowchart: { useMaxWidth: true },
|
|
2548
|
+
sequence: { useMaxWidth: true },
|
|
2549
|
+
gantt: { useMaxWidth: true },
|
|
2550
|
+
journey: { useMaxWidth: true }
|
|
2551
|
+
},
|
|
2552
|
+
plantuml: {
|
|
2553
|
+
server: "https://www.plantuml.com/plantuml",
|
|
2554
|
+
format: "svg"
|
|
2555
|
+
},
|
|
2556
|
+
prism: {
|
|
2557
|
+
theme: "default",
|
|
2558
|
+
autoload: true
|
|
2559
|
+
},
|
|
2560
|
+
navigation: {
|
|
2561
|
+
showHome: true,
|
|
2562
|
+
showBreadcrumb: true,
|
|
2563
|
+
showToc: true
|
|
2564
|
+
},
|
|
2565
|
+
ui: {
|
|
2566
|
+
theme: "default",
|
|
2567
|
+
responsive: true,
|
|
2568
|
+
animations: true
|
|
2569
|
+
}
|
|
2570
|
+
});
|
|
2571
|
+
|
|
2572
|
+
// Fermer et rouvrir le panneau pour actualiser les valeurs
|
|
2573
|
+
const configPanel = document.getElementById('ontowave-config-panel');
|
|
2574
|
+
if (configPanel) {
|
|
2575
|
+
configPanel.remove();
|
|
2576
|
+
// Mettre à jour l'état de déplacement après suppression du panneau
|
|
2577
|
+
if (typeof window.ontowaveUpdateDragState === 'function') {
|
|
2578
|
+
window.ontowaveUpdateDragState();
|
|
2579
|
+
}
|
|
2580
|
+
setTimeout(() => this.toggleConfigurationPanel(), 100);
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
this.showNotification('Configuration réinitialisée ! 🔄');
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
// Méthodes pour le panneau compact (compatibilité)
|
|
2588
|
+
updateConfigFromPanel() {
|
|
2589
|
+
const title = document.getElementById('config-title-mini')?.value || this.config.title;
|
|
2590
|
+
const locales = document.getElementById('config-locales-mini')?.value
|
|
2591
|
+
.split(',')
|
|
2592
|
+
.map(l => l.trim())
|
|
2593
|
+
.filter(l => l.length > 0) || this.config.locales;
|
|
2594
|
+
const showGallery = document.getElementById('config-showGallery-mini')?.checked || this.config.showGallery;
|
|
2595
|
+
|
|
2596
|
+
this.config.title = title;
|
|
2597
|
+
this.config.locales = locales;
|
|
2598
|
+
this.config.showGallery = showGallery;
|
|
2599
|
+
|
|
2600
|
+
// Mettre à jour le titre de la page
|
|
2601
|
+
document.title = this.config.title;
|
|
2602
|
+
|
|
2603
|
+
// Régénérer le code HTML
|
|
2604
|
+
this.updateGeneratedCodeMini();
|
|
2605
|
+
|
|
2606
|
+
this.showNotification('✅ Configuration mise à jour');
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
downloadConfigFromPanel() {
|
|
2610
|
+
// Utiliser la config simplifiée pour le téléchargement
|
|
2611
|
+
const simpleConfig = {
|
|
2612
|
+
title: this.config.title,
|
|
2613
|
+
baseUrl: this.config.baseUrl,
|
|
2614
|
+
defaultPage: this.config.defaultPage,
|
|
2615
|
+
locales: this.config.locales,
|
|
2616
|
+
fallbackLocale: this.config.fallbackLocale,
|
|
2617
|
+
showGallery: this.config.showGallery,
|
|
2618
|
+
mermaid: {
|
|
2619
|
+
theme: this.config.mermaid.theme
|
|
2620
|
+
}
|
|
2621
|
+
};
|
|
2622
|
+
|
|
2623
|
+
const configString = JSON.stringify(simpleConfig, null, 2);
|
|
2624
|
+
|
|
2625
|
+
const htmlContent = `<!DOCTYPE html>
|
|
2626
|
+
<html>
|
|
2627
|
+
<head>
|
|
2628
|
+
<meta charset="UTF-8">
|
|
2629
|
+
<title>${this.config.title}</title>
|
|
2630
|
+
</head>
|
|
2631
|
+
<body>
|
|
2632
|
+
<script src="ontowave.min.js"></script>
|
|
2633
|
+
<script type="application/json" id="ontowave-config">
|
|
2634
|
+
${configString}
|
|
2635
|
+
</script>
|
|
2636
|
+
</body>
|
|
2637
|
+
</html>`;
|
|
2638
|
+
|
|
2639
|
+
const blob = new Blob([htmlContent], { type: 'text/html' });
|
|
2640
|
+
const url = URL.createObjectURL(blob);
|
|
2641
|
+
|
|
2642
|
+
const a = document.createElement('a');
|
|
2643
|
+
a.href = url;
|
|
2644
|
+
a.download = 'index.html';
|
|
2645
|
+
document.body.appendChild(a);
|
|
2646
|
+
a.click();
|
|
2647
|
+
document.body.removeChild(a);
|
|
2648
|
+
URL.revokeObjectURL(url);
|
|
2649
|
+
|
|
2650
|
+
this.showNotification('💾 Fichier HTML téléchargé');
|
|
2651
|
+
}
|
|
2652
|
+
|
|
2653
|
+
downloadOntoWaveScript() {
|
|
2654
|
+
// Créer un lien de téléchargement vers le fichier ontowave.min.js
|
|
2655
|
+
const a = document.createElement('a');
|
|
2656
|
+
a.href = 'ontowave.min.js';
|
|
2657
|
+
a.download = 'ontowave.min.js';
|
|
2658
|
+
document.body.appendChild(a);
|
|
2659
|
+
a.click();
|
|
2660
|
+
document.body.removeChild(a);
|
|
2661
|
+
|
|
2662
|
+
this.showNotification('📥 Fichier ontowave.min.js téléchargé');
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
updateGeneratedCodeMini() {
|
|
2666
|
+
// Créer une config simplifiée pour l'affichage
|
|
2667
|
+
const simpleConfig = {
|
|
2668
|
+
title: this.config.title,
|
|
2669
|
+
baseUrl: this.config.baseUrl,
|
|
2670
|
+
defaultPage: this.config.defaultPage,
|
|
2671
|
+
locales: this.config.locales,
|
|
2672
|
+
fallbackLocale: this.config.fallbackLocale,
|
|
2673
|
+
showGallery: this.config.showGallery,
|
|
2674
|
+
mermaid: {
|
|
2675
|
+
theme: this.config.mermaid.theme
|
|
2676
|
+
}
|
|
2677
|
+
};
|
|
2678
|
+
|
|
2679
|
+
const configString = JSON.stringify(simpleConfig, null, 2)
|
|
2680
|
+
.replace(/"/g, '"')
|
|
2681
|
+
.replace(/</g, '<')
|
|
2682
|
+
.replace(/>/g, '>');
|
|
2683
|
+
|
|
2684
|
+
const htmlCode = `<!DOCTYPE html>
|
|
2685
|
+
<html>
|
|
2686
|
+
<head>
|
|
2687
|
+
<meta charset="UTF-8">
|
|
2688
|
+
<title>${this.config.title}</title>
|
|
2689
|
+
</head>
|
|
2690
|
+
<body>
|
|
2691
|
+
<script src="ontowave.min.js"></script>
|
|
2692
|
+
<script type="application/json" id="ontowave-config">
|
|
2693
|
+
${configString}
|
|
2694
|
+
</script>
|
|
2695
|
+
</body>
|
|
2696
|
+
</html>`;
|
|
2697
|
+
|
|
2698
|
+
const codeElement = document.getElementById('generated-html-mini');
|
|
2699
|
+
if (codeElement) {
|
|
2700
|
+
codeElement.innerHTML = htmlCode;
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
addConfigPanelStyles() {
|
|
2705
|
+
if (document.getElementById('ontowave-config-panel-styles')) return;
|
|
2706
|
+
|
|
2707
|
+
const style = document.createElement('style');
|
|
2708
|
+
style.id = 'ontowave-config-panel-styles';
|
|
2709
|
+
style.textContent = `
|
|
2710
|
+
/* Panneau de configuration étendu */
|
|
2711
|
+
.ontowave-config-panel {
|
|
2712
|
+
position: absolute;
|
|
2713
|
+
top: 100%;
|
|
2714
|
+
left: 0;
|
|
2715
|
+
right: 0;
|
|
2716
|
+
background: white;
|
|
2717
|
+
border: 1px solid #e1e4e8;
|
|
2718
|
+
border-radius: 12px;
|
|
2719
|
+
box-shadow: 0 16px 48px rgba(0,0,0,0.15);
|
|
2720
|
+
z-index: 1001;
|
|
2721
|
+
margin-top: 12px;
|
|
2722
|
+
max-height: 90vh;
|
|
2723
|
+
overflow-y: auto;
|
|
2724
|
+
min-width: 90vw;
|
|
2725
|
+
max-width: 95vw;
|
|
2726
|
+
width: auto;
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
.config-panel-content {
|
|
2730
|
+
padding: 0;
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
.config-full-panel {
|
|
2734
|
+
padding: 32px;
|
|
2735
|
+
max-width: none;
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
.config-full-panel h3 {
|
|
2739
|
+
margin: 0 0 32px 0;
|
|
2740
|
+
color: #0969da;
|
|
2741
|
+
font-size: 24px;
|
|
2742
|
+
font-weight: 700;
|
|
2743
|
+
text-align: center;
|
|
2744
|
+
padding-bottom: 16px;
|
|
2745
|
+
border-bottom: 2px solid #f6f8fa;
|
|
2746
|
+
}
|
|
2747
|
+
|
|
2748
|
+
/* Sections de configuration */
|
|
2749
|
+
.config-section {
|
|
2750
|
+
margin-bottom: 32px;
|
|
2751
|
+
padding: 24px;
|
|
2752
|
+
background: #f6f8fa;
|
|
2753
|
+
border-radius: 8px;
|
|
2754
|
+
border-left: 4px solid #0969da;
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
.config-section h4 {
|
|
2758
|
+
margin: 0 0 20px 0;
|
|
2759
|
+
color: #24292e;
|
|
2760
|
+
font-size: 18px;
|
|
2761
|
+
font-weight: 600;
|
|
2762
|
+
display: flex;
|
|
2763
|
+
align-items: center;
|
|
2764
|
+
gap: 8px;
|
|
2765
|
+
}
|
|
2766
|
+
|
|
2767
|
+
/* Disposition en lignes */
|
|
2768
|
+
.config-row {
|
|
2769
|
+
display: grid;
|
|
2770
|
+
grid-template-columns: 1fr 1fr;
|
|
2771
|
+
gap: 20px;
|
|
2772
|
+
margin-bottom: 16px;
|
|
2773
|
+
}
|
|
2774
|
+
|
|
2775
|
+
.config-row:last-child {
|
|
2776
|
+
margin-bottom: 0;
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
/* Groupes de formulaire */
|
|
2780
|
+
.form-group-full {
|
|
2781
|
+
margin-bottom: 0;
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2784
|
+
.form-group-full label {
|
|
2785
|
+
display: block;
|
|
2786
|
+
font-weight: 600;
|
|
2787
|
+
margin-bottom: 8px;
|
|
2788
|
+
color: #24292e;
|
|
2789
|
+
font-size: 14px;
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
.form-group-full input,
|
|
2793
|
+
.form-group-full select {
|
|
2794
|
+
width: 100%;
|
|
2795
|
+
padding: 12px;
|
|
2796
|
+
border: 2px solid #d0d7de;
|
|
2797
|
+
border-radius: 6px;
|
|
2798
|
+
font-size: 14px;
|
|
2799
|
+
transition: border-color 0.2s ease;
|
|
2800
|
+
}
|
|
2801
|
+
|
|
2802
|
+
.form-group-full input:focus,
|
|
2803
|
+
.form-group-full select:focus {
|
|
2804
|
+
outline: none;
|
|
2805
|
+
border-color: #0969da;
|
|
2806
|
+
box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.1);
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2809
|
+
.form-group-full small {
|
|
2810
|
+
display: block;
|
|
2811
|
+
margin-top: 4px;
|
|
2812
|
+
font-size: 12px;
|
|
2813
|
+
color: #656d76;
|
|
2814
|
+
font-style: italic;
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2817
|
+
/* Checkboxes */
|
|
2818
|
+
.form-group-checkbox {
|
|
2819
|
+
display: flex;
|
|
2820
|
+
align-items: center;
|
|
2821
|
+
margin-bottom: 0;
|
|
2822
|
+
}
|
|
2823
|
+
|
|
2824
|
+
.form-group-checkbox label {
|
|
2825
|
+
display: flex;
|
|
2826
|
+
align-items: center;
|
|
2827
|
+
font-weight: 500;
|
|
2828
|
+
color: #24292e;
|
|
2829
|
+
font-size: 14px;
|
|
2830
|
+
cursor: pointer;
|
|
2831
|
+
margin: 0;
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
.form-group-checkbox input[type="checkbox"] {
|
|
2835
|
+
width: auto;
|
|
2836
|
+
margin: 0 8px 0 0;
|
|
2837
|
+
transform: scale(1.2);
|
|
2838
|
+
accent-color: #0969da;
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2841
|
+
/* Actions du formulaire */
|
|
2842
|
+
.form-actions-full {
|
|
2843
|
+
display: flex;
|
|
2844
|
+
gap: 16px;
|
|
2845
|
+
justify-content: center;
|
|
2846
|
+
margin-top: 40px;
|
|
2847
|
+
padding-top: 24px;
|
|
2848
|
+
border-top: 2px solid #f6f8fa;
|
|
2849
|
+
flex-wrap: wrap;
|
|
2850
|
+
}
|
|
2851
|
+
|
|
2852
|
+
.form-actions-full button {
|
|
2853
|
+
padding: 12px 24px;
|
|
2854
|
+
border: none;
|
|
2855
|
+
border-radius: 8px;
|
|
2856
|
+
font-size: 14px;
|
|
2857
|
+
font-weight: 600;
|
|
2858
|
+
cursor: pointer;
|
|
2859
|
+
transition: all 0.2s ease;
|
|
2860
|
+
min-width: 180px;
|
|
2861
|
+
display: flex;
|
|
2862
|
+
align-items: center;
|
|
2863
|
+
justify-content: center;
|
|
2864
|
+
gap: 8px;
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
.btn-primary {
|
|
2868
|
+
background: #0969da;
|
|
2869
|
+
color: white;
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
.btn-primary:hover {
|
|
2873
|
+
background: #0550ae;
|
|
2874
|
+
transform: translateY(-1px);
|
|
2875
|
+
box-shadow: 0 4px 12px rgba(9, 105, 218, 0.3);
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
.btn-secondary {
|
|
2879
|
+
background: #6f7782;
|
|
2880
|
+
color: white;
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
.btn-secondary:hover {
|
|
2884
|
+
background: #57606a;
|
|
2885
|
+
transform: translateY(-1px);
|
|
2886
|
+
box-shadow: 0 4px 12px rgba(111, 119, 130, 0.3);
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2889
|
+
.btn-warning {
|
|
2890
|
+
background: #d73a49;
|
|
2891
|
+
color: white;
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2894
|
+
.btn-warning:hover {
|
|
2895
|
+
background: #b31d28;
|
|
2896
|
+
transform: translateY(-1px);
|
|
2897
|
+
box-shadow: 0 4px 12px rgba(215, 58, 73, 0.3);
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2900
|
+
/* Responsive pour petits écrans */
|
|
2901
|
+
@media (max-width: 768px) {
|
|
2902
|
+
.ontowave-config-panel {
|
|
2903
|
+
min-width: 95vw;
|
|
2904
|
+
margin-top: 8px;
|
|
2905
|
+
}
|
|
2906
|
+
|
|
2907
|
+
.config-full-panel {
|
|
2908
|
+
padding: 20px;
|
|
2909
|
+
}
|
|
2910
|
+
|
|
2911
|
+
.config-row {
|
|
2912
|
+
grid-template-columns: 1fr;
|
|
2913
|
+
gap: 16px;
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
.form-actions-full {
|
|
2917
|
+
flex-direction: column;
|
|
2918
|
+
align-items: stretch;
|
|
2919
|
+
}
|
|
2920
|
+
|
|
2921
|
+
.form-actions-full button {
|
|
2922
|
+
min-width: auto;
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
/* Styles pour compatibilité avec l'ancien panneau compact */
|
|
2927
|
+
.config-form-compact h3,
|
|
2928
|
+
.config-preview-compact h3 {
|
|
2929
|
+
margin: 0 0 16px 0;
|
|
2930
|
+
color: #0969da;
|
|
2931
|
+
font-size: 16px;
|
|
2932
|
+
font-weight: 600;
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2935
|
+
.form-group-compact {
|
|
2936
|
+
margin-bottom: 16px;
|
|
2937
|
+
}
|
|
2938
|
+
|
|
2939
|
+
.form-group-compact label {
|
|
2940
|
+
display: block;
|
|
2941
|
+
font-weight: 600;
|
|
2942
|
+
margin-bottom: 6px;
|
|
2943
|
+
color: #24292e;
|
|
2944
|
+
font-size: 13px;
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2947
|
+
.form-group-compact input {
|
|
2948
|
+
width: 100%;
|
|
2949
|
+
padding: 8px;
|
|
2950
|
+
border: 1px solid #d0d7de;
|
|
2951
|
+
border-radius: 4px;
|
|
2952
|
+
font-size: 13px;
|
|
2953
|
+
}
|
|
2954
|
+
|
|
2955
|
+
.form-group-compact input[type="checkbox"] {
|
|
2956
|
+
width: auto;
|
|
2957
|
+
margin-right: 6px;
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2960
|
+
.form-actions-compact {
|
|
2961
|
+
display: flex;
|
|
2962
|
+
gap: 10px;
|
|
2963
|
+
margin-top: 20px;
|
|
2964
|
+
flex-wrap: wrap;
|
|
2965
|
+
}
|
|
2966
|
+
|
|
2967
|
+
.form-actions-compact button {
|
|
2968
|
+
flex: 1;
|
|
2969
|
+
padding: 10px 16px;
|
|
2970
|
+
border: none;
|
|
2971
|
+
border-radius: 6px;
|
|
2972
|
+
background: #0969da;
|
|
2973
|
+
color: white;
|
|
2974
|
+
font-size: 13px;
|
|
2975
|
+
font-weight: 600;
|
|
2976
|
+
cursor: pointer;
|
|
2977
|
+
transition: background 0.2s ease;
|
|
2978
|
+
min-width: 120px;
|
|
2979
|
+
}
|
|
2980
|
+
|
|
2981
|
+
.form-actions-compact button:hover {
|
|
2982
|
+
background: #0550ae;
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
.config-preview-compact {
|
|
2986
|
+
background: #f6f8fa;
|
|
2987
|
+
border-radius: 6px;
|
|
2988
|
+
padding: 16px;
|
|
2989
|
+
}
|
|
2990
|
+
|
|
2991
|
+
.code-preview-mini {
|
|
2992
|
+
background: #24292e;
|
|
2993
|
+
color: #f6f8fa;
|
|
2994
|
+
padding: 12px;
|
|
2995
|
+
border-radius: 4px;
|
|
2996
|
+
font-family: 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace;
|
|
2997
|
+
font-size: 11px;
|
|
2998
|
+
line-height: 1.4;
|
|
2999
|
+
overflow-x: auto;
|
|
3000
|
+
max-height: 300px;
|
|
3001
|
+
overflow-y: auto;
|
|
3002
|
+
}
|
|
3003
|
+
`;
|
|
3004
|
+
document.head.appendChild(style);
|
|
3005
|
+
}
|
|
3006
|
+
|
|
3007
|
+
// API publique
|
|
3008
|
+
navigate(page) {
|
|
3009
|
+
this.loadPage(page);
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
getConfig() {
|
|
3013
|
+
return { ...this.config };
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
updateConfig(newConfig) {
|
|
3017
|
+
this.config = { ...this.config, ...newConfig };
|
|
3018
|
+
console.log('📝 Configuration updated');
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
|
|
3022
|
+
// Fonction pour charger la configuration depuis config.json
|
|
3023
|
+
async function loadConfigFromFile() {
|
|
3024
|
+
try {
|
|
3025
|
+
const response = await fetch('./config.json');
|
|
3026
|
+
if (response.ok) {
|
|
3027
|
+
const config = await response.json();
|
|
3028
|
+
console.log('📁 Configuration chargée depuis config.json:', config);
|
|
3029
|
+
return config;
|
|
3030
|
+
}
|
|
3031
|
+
} catch (error) {
|
|
3032
|
+
console.log('📁 Pas de config.json trouvé, utilisation de la configuration par défaut');
|
|
3033
|
+
}
|
|
3034
|
+
return {};
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
// Initialisation automatique au chargement de la page
|
|
3038
|
+
document.addEventListener('DOMContentLoaded', async () => {
|
|
3039
|
+
// Utiliser window.OntoWaveConfig si disponible, sinon charger depuis config.json
|
|
3040
|
+
let config = window.OntoWaveConfig || {};
|
|
3041
|
+
if (!window.OntoWaveConfig) {
|
|
3042
|
+
config = await loadConfigFromFile();
|
|
3043
|
+
} else {
|
|
3044
|
+
// Merger avec config.json si les deux existent
|
|
3045
|
+
const fileConfig = await loadConfigFromFile();
|
|
3046
|
+
config = { ...fileConfig, ...window.OntoWaveConfig };
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
window.OntoWave = { instance: new OntoWave(config) };
|
|
3050
|
+
await window.OntoWave.instance.init();
|
|
3051
|
+
console.log('🌊 OntoWave initialisé automatiquement');
|
|
3052
|
+
});
|
|
3053
|
+
|
|
3054
|
+
// Export pour utilisation manuelle si nécessaire
|
|
3055
|
+
window.OntoWaveClass = OntoWave;
|
|
3056
|
+
|
|
3057
|
+
})(window);
|