summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2024-10-27 13:34:13 +0100
committerpolo <ordipolo@gmx.fr>2024-10-27 13:34:13 +0100
commit5b455dbf1474a3c7c839cd129fd470f1fdae6b0c (patch)
tree85200f78a951a5ff8ac8f105bce5834c162ab717
downloadckeditor5-5b455dbf1474a3c7c839cd129fd470f1fdae6b0c.zip
v2 avec NPM et composer, customizable et plus facile à intégrer
-rw-r--r--config.php19
-rw-r--r--data/page/html/article.html1
-rw-r--r--data/page/images/chirurgien jaune.jpgbin0 -> 137915 bytes
-rw-r--r--index.php50
-rw-r--r--installation dans une application PHP.txt95
-rw-r--r--lib/ckeditor5/article_hors_editeur.css38
-rw-r--r--lib/ckeditor5/clean_html.php46
-rw-r--r--lib/ckeditor5/create.php16
-rw-r--r--lib/ckeditor5/image_upload.php64
-rw-r--r--lib/ckeditor5/view.php171
-rw-r--r--src/templates/page.php15
11 files changed, 515 insertions, 0 deletions
diff --git a/config.php b/config.php
new file mode 100644
index 0000000..9cd5ff2
--- /dev/null
+++ b/config.php
@@ -0,0 +1,19 @@
1<?php
2// config.php
3
4$server_root = $_SERVER['SERVER_NAME'] . '/ckeditor5-new/';
5// pour l'importmap: j'ai modifié la version "installation avec CDN de la doc pour utiliser les fichiers locaux
6// l'"importmap" permet d'utiliser "import" (ça ressemble pas mal au python) dans le navigateur comme n'importe quel langage de programmation normal
7
8$previous_page = 'index.php';
9$open_editor_link = 'index.php?page=editor';
10$form_action_file = 'index.php?action=submit';
11$upload_ajax_url = 'index.php?action=upload_image';
12
13$toolbar_language = 'fr';
14
15$storage = 'files'; // choisir 'files' ou 'database'
16$page = 'page';
17$nom_article = "article";
18
19$php_ini_max_size = ini_get('upload_max_filesize'); // = 2M par défaut dans le php.ini
diff --git a/data/page/html/article.html b/data/page/html/article.html
new file mode 100644
index 0000000..3f0058d
--- /dev/null
+++ b/data/page/html/article.html
@@ -0,0 +1 @@
<figure class="image image-style-side"><img src="data/page/images/chirurgien jaune.jpg" alt="image" /><figcaption>image</figcaption></figure><h2>hello</h2><figure class="table"><table><tbody><tr><td>ok</td><td>ah oui</td><td>bon</td></tr><tr><td><p>c'est pas</p><p>grave</p></td><td><p>on verra</p><p>plus tard</p></td><td>salut</td></tr></tbody></table></figure><p><i><mark class="marker-green">goodbye</mark></i></p> \ No newline at end of file
diff --git a/data/page/images/chirurgien jaune.jpg b/data/page/images/chirurgien jaune.jpg
new file mode 100644
index 0000000..295bce2
--- /dev/null
+++ b/data/page/images/chirurgien jaune.jpg
Binary files differ
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..d3e2d1e
--- /dev/null
+++ b/index.php
@@ -0,0 +1,50 @@
1<?php
2// index.php
3//
4// routeur
5
6require 'config.php';
7
8if(isset($_GET['action']) && $_GET['action'] === 'upload_image') // image insérée dans l'éditeur => requête AJAX
9{
10 require 'lib/ckeditor5/image_upload.php';
11}
12elseif(isset($_GET['action']) && $_GET['action'] === 'submit') // HTML envoyé par l'éditeur
13{
14 require 'lib/ckeditor5/clean_html.php';
15 $html_from_editor = getAndCleanEditorOutput(); // manipule $_POST['contenu'];
16
17 // enregistrement des données
18 //var_dump($html_from_editor);
19 echo "enregistrer les données et supprimer cette ligne dans index.php"; die;
20
21 header('Location: ' . $previous_page);
22 die;
23}
24elseif(isset($_GET['page']) && $_GET['page'] === 'editor') // ouvrir l'éditeur
25{
26 require 'lib/ckeditor5/create.php';
27}
28else // $previous_page, affichage sans l'article
29{
30 // contrôleur
31
32 // modèle
33 if($storage === 'database')
34 {}
35 elseif($storage === 'files')
36 {
37 $texte = file_get_contents('data/' . $page . '/html/' . $nom_article . '.html');
38 $texte = trim(addcslashes($texte, "'")); // échappe seulement les simples quotes
39 }
40
41 // vue
42 $css_editeur = '';
43 $contenu = '<div class="conteneur_article" >' . $texte . '</div>
44 <p><a href="' . $open_editor_link . '">ouvrir l\'éditeur</a></p>';
45}
46
47// vue
48require 'src/templates/page.php';
49
50// fin du script
diff --git a/installation dans une application PHP.txt b/installation dans une application PHP.txt
new file mode 100644
index 0000000..210902c
--- /dev/null
+++ b/installation dans une application PHP.txt
@@ -0,0 +1,95 @@
11/ installation
2
3cd "mon projet"
4git clone git@ordipolo.fr:ckeditor5
5copier tout son contenu (sauf le .git) dans le dossier racine, attention quand un index.php existe déjà
6rm -r ckeditor5 --interactive=never
7
8npm install ckeditor5
9composer require htmlawed/htmlawed
10
11les 11 fichiers récupérés par le git clone:
12lib/ckeditor5/create.php
13lib/ckeditor5/clean_html.php
14lib/ckeditor5/view.php
15lib/ckeditor5/image_upload.php
16lib/ckeditor5/articles_hors_editeur.css
17config.php
18installation dans une application PHP.txt
19index.php (appel des contrôleurs)
20src/templates/page.php (HTML principal de la page web)
21data/page/html/articles.html
22data/page/images/chirurgien jaune.jpg
23
24
252/ à vérifier:
26créer un lien symbolique comme ceci (commande pour debian):
27ln -s /var/www/ckeditor5/node_modules/ckeditor5/dist/translations /var/www/ckeditor5/node_modules/ckeditor5/dist/browser/
28
29ça régle un problème de chemin rencontré à la ligne: import coreTranslations from 'ckeditor5/translations/fr.js'; dans lib/ckeditor5/template.php
30gràce à un lien symbolique, le programme s'attend à trouver un dossier "translations" dans "browser"
31
32
333/ essai
34les paramètres dans config.php et les fichiers dans data permettent normalement
35- d'ouvrir l'éditeur
36- de lire des données dans des fichiers et de les insérer dans l'éditeur pour modification
37
38la sortie au "submit" est nettoyée puis se retrouve dans $html_from_editor
39
40
413/ intégration à un projet
42
43a) index.php et src/templates/page.php sont à remplacer en fonction de notre application
44regarder à l'intérieur et adapter son propre code
45
46b) config.php est à personnaliser et/ou à copier ailleurs,
47du moment que les variables à l'intérieur restent disponibles
48
49c) le dossier data et ses sous-dossiers ont besoin de droits en écriture
50
51a) adapter le routeur dans index.php
52
53b) adapter ce qui suit "// modèle" dans index.php et lib/ckeditor5/create.php pour obtenir les données souhaitées (BDD, fichiers)
54
55c) adapter le fichier config.php (vérifier les chemins)
56
57d) ajouter <?= $css_editeur ?> dans le <head>
58ajouter aussi <?= $contenu ?> dans le <body> pour afficher l'éditeur ou du HTML créé par l'éditeur
59
60e) insérer dans chaque page affichant des données créées avec l'éditeur:
61<link rel="stylesheet" href="lib/ckeditor5/article_hors_editeur.css" />
62l'éditeur ne génère pas de CSS mais seulement du HTML basique, ce CSS imite le rendu à l'intérieur de l'éditeur
63
64normalement c'est bon fini, ce qui suit est de l'information utile si on souhaite partir de zéro avec NPM et la doc
65
66
67
68
69
705/ explication et choix des plugins
71tout ça est déjà fait, mais vous pouvez toujours personnaliser l'éditeur en choisissant des plugins différents
72
73voici ce que j'ai fait dans: lib/ckeditor5/template.php
74
75a) créer une importmap avec les chemins des fichiers
76<script type="importmap">
77{
78 "imports": {
79 "ckeditor5": "http://<?= $server_root ?>node_modules/ckeditor5/dist/browser/ckeditor5.js",
80 "ckeditor5/": "http://<?= $server_root ?>node_modules/ckeditor5/dist/browser/"
81 }
82}
83</script>
84
85b) charger une liste de plugins façon python
86import { "liste de plugins" } from "ckeditor5";
87
88c) rechoisir les plugins dans ClassicEditor.create():
89plugins: [ "liste de plugins" ] ...
90
91d) choisir les élément de la toolbar
92toolbar; { items: [ "éléments" ], ...
93
94e) autres éléments:
95toolbar des images et des tables, sécurité des envois AJAX
diff --git a/lib/ckeditor5/article_hors_editeur.css b/lib/ckeditor5/article_hors_editeur.css
new file mode 100644
index 0000000..a38b384
--- /dev/null
+++ b/lib/ckeditor5/article_hors_editeur.css
@@ -0,0 +1,38 @@
1.conteneur_article{width: 630px;}
2.conteneur_article:after{content: ""; display: block; clear: both;}
3
4img{vertical-align: bottom;}
5@media screen and (max-width: 1000px)
6{img{max-width: 900px;}}
7
8.text-tiny{font-size: x-small;}
9.text-small{font-size: small;}
10.text-big{font-size: large;}
11.text-huge{font-size: x-large;}
12
13blockquote{border-left: 5px #cccccc solid; margin: 14px 0px; padding: 2px 25px; font-style: italic;}
14
15.marker-yellow{background-color: #fdfd77;}
16.marker-green{background-color: #62f962;}
17.marker-pink{background-color: #fc7899;}
18.marker-blue{background-color: #72ccfd;}
19.pen-red{background-color: white; color: red;}
20.pen-green{background-color: white; color: green;}
21
22ul{padding-left: 10px;}
23.todo-list>li{list-style-type : none;}
24input[type=checkbox]{-webkit-appearance: none;-moz-appearance: none;-ms-appearance: none;
25height: 16px; width: 16px; border: 1px solid black; border-radius: 2px; position: relative; top: 5px; margin-right: 10px;}
26input[type="checkbox"]:checked{border: none; background: #26ab33;}
27
28.table>table{border-collapse: collapse;}
29.table td{border: 1px grey solid; padding: 7px; min-width: 30px;}
30td p{margin: 0px;}
31
32.image{margin: 0px; text-align: center; display: inline-block;}
33.image-style-side{float: right;}
34.image img{max-width: 630px;}
35.image-style-side img{max-width: 315px;}
36.image>figcaption{margin: 0px 10px; padding: 7px; text-align: center; font-size: small; background-color: #f7f7f7;}
37
38iframe{min-width: 400px; min-height: 300px; max-width: 1200px; max-height: 900px;}
diff --git a/lib/ckeditor5/clean_html.php b/lib/ckeditor5/clean_html.php
new file mode 100644
index 0000000..5d00532
--- /dev/null
+++ b/lib/ckeditor5/clean_html.php
@@ -0,0 +1,46 @@
1<?php
2// lib/ckeditor5/clean_html.php
3
4function getAndCleanEditorOutput(): string
5{
6 // bugs possibles sans trim() lorsqu'on insère le HTML dans l'éditeur
7 $html = trim($_POST["contenu"]);
8
9
10 // pour debugguer ou tester des paramètres avec htmlawed
11
12 //~ $nom_fichier = "avant.html";
13 //~ $fichier = fopen('data/' . $page . '/' . $nom_fichier, 'w'); // w peut créer un fichier, si il existe déjà, il est effacé par le nouveau contenu
14 //~ fputs($fichier, $html);
15 //~ fclose($fichier);
16 //~ chmod('data/' . $page . '/' . $nom_fichier, 0666);
17
18
19 // sécurisation du HTML (faille XSS)
20 require 'vendor/htmlawed/htmlawed/htmLawed.php';
21 $configHtmLawed = array(
22 'safe'=>1, // protection contre les élements et attributs dangereux
23
24 // balises autorisées
25 'elements'=>'h2, h3, h4, p, span, i, strong, u, s, mark, blockquote, li, ol, ul, a, figure, hr, img, figcaption, table, tbody, tr, td',
26 // note: change <s></s> en <span style="text-decoration: line-through;"></span>
27
28 // attributs interdits
29 'deny_attribute'=>'id', // 'class' et 'style' sont conservés pour le ckeditor
30 );
31 $specHtmLawed = ''; // optionnel: faire qu'un certain élément puisse n'avoir que certains attributs
32 $html = htmLawed($html, $configHtmLawed, $specHtmLawed);
33
34
35 //~ $nom_fichier = "après.html";
36 //~ $fichier = fopen('data/' . $page . '/' . $nom_fichier, 'w'); // w peut créer un fichier, si il existe déjà, il est effacé par le nouveau contenu
37 //~ fputs($fichier, $html);
38 //~ fclose($fichier);
39 //~ chmod('data/' . $page . '/' . $nom_fichier, 0666);
40
41
42 return $html;
43}
44
45
46
diff --git a/lib/ckeditor5/create.php b/lib/ckeditor5/create.php
new file mode 100644
index 0000000..d62f893
--- /dev/null
+++ b/lib/ckeditor5/create.php
@@ -0,0 +1,16 @@
1<?php
2// lib/ckeditor5/create.php
3
4// modèle
5if($storage === 'database')
6{}
7elseif($storage === 'files')
8{
9 // modèle
10 $texte = file_get_contents('data/' . $page . '/html/' . $nom_article . '.html');
11 $texte = trim(addcslashes($texte, "'")); // échappe seulement les simples quotes
12}
13
14// vue
15require 'lib/ckeditor5/view.php'; // html + JS
16$contenu = $editeurHTML;
diff --git a/lib/ckeditor5/image_upload.php b/lib/ckeditor5/image_upload.php
new file mode 100644
index 0000000..607be1b
--- /dev/null
+++ b/lib/ckeditor5/image_upload.php
@@ -0,0 +1,64 @@
1<?php
2// lib/ckeditor5/image_upload.php
3
4// script récupérant les images téléchargée en AJAX par l'éditeur et c'est tout
5// on récupère les données, on renvoie au navigateur la réponse qu'il attend et stop!
6
7// le "simple upload adapter" envoie un POST appelé: $_FILES['upload']
8// en retour il attend impérativement des données au format JSON du genre: {"url": "data/page/images/monfichier.jpg"}
9// cette adresse doit permettre à l'éditeur de télécharger l'image afficher de manière normale: <img scr="data/page/images/monfichier.jpg">
10
11// pour voir cette réponse, les messages d'erreur ou tout affichage avec echo ou var_dump:
12// outils de développement (F12) => réseau => trouver la requête (xhr) => cliquer dessus puis sur réponse
13
14// rappel: le téléchargement de fichier avec PHP nécessite un dossier temporaire et que le serveur y soit autorisé en écriture
15
16
17$erreur = '';
18if(isset($_FILES['upload']) AND $_FILES['upload']['error'] == 0) // 0 signifie ok
19{
20 if($_FILES['upload']['size'] <= $php_ini_max_size )
21 {
22 $infos = pathinfo ($_FILES['upload']['name']);
23 $extension = $infos['extension'];
24 $extautorisées = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'tiff'];
25 // on prend la même liste que celle côté javascript, le SVG est bloqué pour raison de sécurité (javascript à l'intérieur)
26 if(in_array($extension, $extautorisées))
27 {
28 move_uploaded_file ($_FILES['upload']['tmp_name'], 'data/' . $page . '/images/' . $_FILES['upload']['name']);
29 chmod('data/' . $page . '/images/' . $_FILES['upload']['name'], 0666);
30 }
31 else
32 {
33 $erreur = 'mauvais format, veuillez utiliser une image comportant un de ces formats: jpg ou jpeg, png, gif, bmp, webp, tiff<br />le format svg n\'est pas supporté';
34 }
35 }
36 else
37 {
38 $erreur = 'fichier trop lourd';
39 }
40}
41else
42{
43 $erreur = $_FILES['upload']['error'];
44}
45/* les erreurs retournées avec $_FILES['upload']['error']:
460 pas d'erreur
471 taille du fichier supérieure à la valeur de upload_max_filesize dans le fichier php.ini (par défaut = 2 MO)
482 taille du fichier supérieure à la valeur de MAX_FILE_SIZE dans le formulaire HTML
493 fichier partiellement téléchargé
504 pas de fichier du tout
516 pas de dossier temporaire pour mettre le fichier
527 echec de l'écriture sur le DD
538 envoi arrêté par une extension de PHP mais on ne nous dit pas pourquoi => diagnostic avec la fonction phpinfo() */
54
55if(empty($erreur))
56{
57 $chemin = '{"url": "data/' . $page . '/images/' . $_FILES['upload']['name'] . '"}';
58 echo $chemin;
59}
60else
61{
62 echo $erreur;
63}
64die;
diff --git a/lib/ckeditor5/view.php b/lib/ckeditor5/view.php
new file mode 100644
index 0000000..6d6c961
--- /dev/null
+++ b/lib/ckeditor5/view.php
@@ -0,0 +1,171 @@
1<?php
2// lib/ckeditor5/view.php
3
4//$css_editeur = '<link rel="stylesheet" href="node_modules/ckeditor5/dist/ckeditor5.css" />'; // version normale aérée et commentée
5$css_editeur = '<link rel="stylesheet" href="node_modules/ckeditor5/dist/browser/ckeditor5.css" />'; // version "minifiée"
6
7ob_start();
8?>
9<div class="conteneur_article" >
10 <form action="<?= $form_action_file ?>" method="POST" enctype="multipart/form-data" >
11 <textarea id="editor" name="contenu" ></textarea>
12 <input class="boutonSubmitEditeur" type="submit" value="Valider">
13 <a class="boutonAnnuler" href="<?= $previous_page ?>" >
14 <input type="button" value="Annuler"></a>
15 <script type="importmap">
16 {
17 "imports": {
18 "ckeditor5": "http://<?= $server_root ?>node_modules/ckeditor5/dist/browser/ckeditor5.js",
19 "ckeditor5/": "http://<?= $server_root ?>node_modules/ckeditor5/dist/browser/"
20 }
21 }
22 </script>
23 <script type="module">
24 import { // nécessite type="module"
25 ClassicEditor, Essentials, Heading, Paragraph, Alignment, List,
26 BlockQuote, HorizontalLine, Bold, Italic, Underline, Strikethrough,
27 Font, FontFamily, Highlight, FontBackgroundColor, SimpleUploadAdapter,
28 Image, ImageInsert, ImageToolbar, ImageStyle, ImageCaption, LinkImage,
29 Link, Table, TableColumnResize, TableToolbar, TableProperties, TableCellProperties, TextPartLanguage
30 } from "ckeditor5";
31
32 import coreTranslations from 'ckeditor5/translations/<?= $toolbar_language ?>.js';
33 // n'utilise pas le bon chemin à cause d'un bug? solution = créer un lien symbolique à l'endroit attendu:
34 // ln -s /srv/http/ckeditor5/node_modules/ckeditor5/dist/translations /srv/http/ckeditor5/node_modules/ckeditor5/dist/browser/
35
36 //import 'ckeditor5/ckeditor5.css'; // marche pas chez moi
37
38 let editor;
39 let html_existant = '<?= $texte ?>'; // $texte doit avoir été sécurisé: simple quotes échappées au minimum
40 let upload_url = '<?= $upload_ajax_url ?>';
41
42 // ATTENTION: si l'éditeur ne fonctionne pas, empêcher qu'on puisse cliquer sur Valider!
43 // Il y a aussi des paramètres dans le fichier de config: ckeditor/webpack.config.js
44 ClassicEditor
45 .create( document.querySelector( '#editor' ),{
46
47 plugins: [ Essentials, Heading, Paragraph, Alignment, List,
48 BlockQuote, HorizontalLine, Underline, Strikethrough,
49 Bold, Italic, Font, FontFamily, Highlight, FontBackgroundColor, SimpleUploadAdapter,
50 Image, ImageInsert, ImageToolbar, ImageStyle, ImageCaption, LinkImage,
51 Link, Table, TableColumnResize, TableToolbar, TableProperties, TableCellProperties, TextPartLanguage],
52
53 toolbar: {
54 items: [
55 'undo', 'redo', 'selectAll', '|', 'heading', '|', 'alignment', 'bulletedList', 'numberedList',
56 //'todoList',// marche pas, ne crée pas de HTML
57 'blockQuote', 'horizontalLine', '|', 'textPartLanguage', '-', 'bold', 'italic', 'underline', 'strikethrough', '|',
58 'fontFamily', // polices microsoft uniquement
59 'fontColor', 'fontSize', 'highlight', 'fontBackgroundColor', // un peu comme highlight
60 '|', 'imageInsert', 'link',
61 //'htmlEmbed', // marche pas, ne crée pas de HTML
62 //'mediaEmbed',
63 'insertTable',
64 ],
65 // multiligne automatique (le '-' dans la liste permet de choisir l'endroit où couper)
66 // pour les plugins indiqués "marche pas", envoient-ils un requête AJAX quelque part?
67
68 shouldNotGroupWhenFull: true
69 },
70
71 language: '<?= $toolbar_language ?>',
72 translations: [coreTranslations],
73
74 // barre d'outils dans une image
75 image: {
76 toolbar: [
77 //'imageStyle:full', //inutile?
78 'imageStyle:block',
79 'imageStyle:inline', // complexe, on peut aussi placer l'image à la souris
80 'imageStyle:side',
81 /*'imageStyle:align-left',
82 'imageStyle:align-right',*/
83 //'imageResize', // optionnel? on a les poignées dans les coins de l'image
84 'linkImage',
85 'toggleImageCaption',
86 'imageTextAlternative'
87 ]
88 },
89
90 // barre d'outils dans un tableau
91 table: {
92 contentToolbar: [
93 'tableColumn', // manipulation sur les colonnes et lignes
94 'tableRow',
95 'mergeTableCells',
96 'tableProperties', // style sur la table
97 'tableCellProperties' // style sur une cellule
98 ]
99 },
100
101 // langues dispo pour TextPartLanguage
102 language: {
103 textPartLanguage: [
104 { title: 'Arabic', languageCode: 'ar' },
105 { title: 'English', languageCode: 'en' },
106 { title: 'French', languageCode: 'fr' },
107 { title: 'German', languageCode: 'de' },
108 { title: 'Hebrew', languageCode: 'he' },
109 { title: 'Spanish', languageCode: 'es' }
110 ]
111 },
112
113 // plugin code HTML
114 // voir doc
115
116 // media embarqué (audio, vidéo, carte)
117 //mediaEmbed: {
118 //previewsInData: true,
119 // vaut "false" par defaut, on crée la balise non standard <oembed url="" > // https://oembed.com/
120 // qui nécessite un traitement (en JS ou côté serveur) en utilisant le lien à l'intérieur
121 // avec "true", on crée la balise <iframe> qui sert à insérer une page HTML dans une autre,
122 // notre "embarquement de média" devrait donc réussir quelque soit le site
123 // c'est plus simple, il ne reste plus qu'à ajuster le contenu avec du CSS (important)
124 // on doit supprimer le positionnement absolu qui fait que l'iframe se place par dessus le reste et adapter la taille de l'élément
125
126 // en outre, le plugin mediaEmbed (dans l'éditeur), tout comme la balise "iframe" (hors éditeur),
127 // permettent d'afficher un aperçu (preview): une image avec un bouton lecture dessus
128 // cette image est envoyée imédiatement par le serveur, et le contenu après un clic dessus
129 //
130 //},
131
132 // images
133 // le plugin "simple upload adapter" communique avec le serveur au moyen de requêtes AJAX
134 // il attend du serveur une réponse au format .json contenant l'adresse où est stockée l'image:
135 // {"url": "https://example.com/images/foo.jpg"}
136 simpleUpload: {
137 uploadUrl: upload_url,
138
139 // Headers supplémentaires envoyés avec la requête
140 // c'est ici qu'on installe les mécanismes de sécurités comme l'authentification et la protection au CSRF
141 headers: {
142 //'X-CSRF-TOKEN': 'CSRF-Token',
143 //Authorization: 'Bearer <JSON Web Token>'
144 }
145 },
146 // formats acceptés par défaut: jpeg, png, gif, bmp, webp, tiff
147 // le svg n'est pas dans la liste, pour raison de sécurité apparemment, il parait qu'on peut mettre du javascript à l'intérieur
148
149 // plugin autosave
150 // voir doc
151 } )
152 .then( newEditor => {
153 editor = newEditor;
154 // fin de ClassicEditor
155
156 // obtenir la liste des éléments disponibles pour la barre d'outils
157 //alert(Array.from( editor.ui.componentFactory.names() ));
158 // obtenir la liste des plugins disponibles:
159 //alert(ClassicEditor.builtinPlugins.map( plugin => plugin.pluginName ));
160
161 // insertion du HTML existant
162 editor.setData(html_existant);
163 } )
164 .catch( error => {
165 console.error( error );
166 } );
167 </script>
168 </form>
169</div>
170<?php
171$editeurHTML = ob_get_clean();
diff --git a/src/templates/page.php b/src/templates/page.php
new file mode 100644
index 0000000..98e7979
--- /dev/null
+++ b/src/templates/page.php
@@ -0,0 +1,15 @@
1<!DOCTYPE html>
2<html lang="fr">
3<head>
4 <meta charset="utf-8">
5 <title></title>
6 <link rel="icon" type="image/png" href="">
7 <link rel="stylesheet" href="lib/ckeditor5/article_hors_editeur.css" />
8 <?= $css_editeur ?>
9</head>
10<body>
11 <div>
12 <?= $contenu ?>
13 </div>
14</body>
15</html>