summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2025-01-13 00:44:49 +0100
committerpolo <ordipolo@gmx.fr>2025-01-13 00:44:49 +0100
commite9a5da044f63851aa37d401ef37c8102b08ae274 (patch)
tree12ebf8a0aefd7a63d6d7dcbe4ad7d74e6ee3bb92 /lib
parent0023ec83932beddb0f1c604f3c210189113c9b7a (diff)
downloadckeditor5-e9a5da044f63851aa37d401ef37c8102b08ae274.zip
chemins changés, dossier integration
Diffstat (limited to 'lib')
-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.php173
5 files changed, 0 insertions, 337 deletions
diff --git a/lib/ckeditor5/article_hors_editeur.css b/lib/ckeditor5/article_hors_editeur.css
deleted file mode 100644
index a38b384..0000000
--- a/lib/ckeditor5/article_hors_editeur.css
+++ /dev/null
@@ -1,38 +0,0 @@
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
deleted file mode 100644
index 5d00532..0000000
--- a/lib/ckeditor5/clean_html.php
+++ /dev/null
@@ -1,46 +0,0 @@
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
deleted file mode 100644
index d62f893..0000000
--- a/lib/ckeditor5/create.php
+++ /dev/null
@@ -1,16 +0,0 @@
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
deleted file mode 100644
index 607be1b..0000000
--- a/lib/ckeditor5/image_upload.php
+++ /dev/null
@@ -1,64 +0,0 @@
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
deleted file mode 100644
index e592a73..0000000
--- a/lib/ckeditor5/view.php
+++ /dev/null
@@ -1,173 +0,0 @@
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 licenseKey: 'GPL',
48
49 plugins: [ Essentials, Heading, Paragraph, Alignment, List,
50 BlockQuote, HorizontalLine, Underline, Strikethrough,
51 Bold, Italic, Font, FontFamily, Highlight, FontBackgroundColor, SimpleUploadAdapter,
52 Image, ImageInsert, ImageToolbar, ImageStyle, ImageCaption, LinkImage,
53 Link, Table, TableColumnResize, TableToolbar, TableProperties, TableCellProperties, TextPartLanguage],
54
55 toolbar: {
56 items: [
57 'undo', 'redo', 'selectAll', '|', 'heading', '|', 'alignment', 'bulletedList', 'numberedList',
58 //'todoList',// marche pas, ne crée pas de HTML
59 'blockQuote', 'horizontalLine', '|', 'textPartLanguage', '-', 'bold', 'italic', 'underline', 'strikethrough', '|',
60 'fontFamily', // polices microsoft uniquement
61 'fontColor', 'fontSize', 'highlight', 'fontBackgroundColor', // un peu comme highlight
62 '|', 'imageInsert', 'link',
63 //'htmlEmbed', // marche pas, ne crée pas de HTML
64 //'mediaEmbed',
65 'insertTable',
66 ],
67 // multiligne automatique (le '-' dans la liste permet de choisir l'endroit où couper)
68 // pour les plugins indiqués "marche pas", envoient-ils un requête AJAX quelque part?
69
70 shouldNotGroupWhenFull: true
71 },
72
73 language: '<?= $toolbar_language ?>',
74 translations: [coreTranslations],
75
76 // barre d'outils dans une image
77 image: {
78 toolbar: [
79 //'imageStyle:full', //inutile?
80 'imageStyle:block',
81 'imageStyle:inline', // complexe, on peut aussi placer l'image à la souris
82 'imageStyle:side',
83 /*'imageStyle:align-left',
84 'imageStyle:align-right',*/
85 //'imageResize', // optionnel? on a les poignées dans les coins de l'image
86 'linkImage',
87 'toggleImageCaption',
88 'imageTextAlternative'
89 ]
90 },
91
92 // barre d'outils dans un tableau
93 table: {
94 contentToolbar: [
95 'tableColumn', // manipulation sur les colonnes et lignes
96 'tableRow',
97 'mergeTableCells',
98 'tableProperties', // style sur la table
99 'tableCellProperties' // style sur une cellule
100 ]
101 },
102
103 // langues dispo pour TextPartLanguage
104 language: {
105 textPartLanguage: [
106 { title: 'Arabic', languageCode: 'ar' },
107 { title: 'English', languageCode: 'en' },
108 { title: 'French', languageCode: 'fr' },
109 { title: 'German', languageCode: 'de' },
110 { title: 'Hebrew', languageCode: 'he' },
111 { title: 'Spanish', languageCode: 'es' }
112 ]
113 },
114
115 // plugin code HTML
116 // voir doc
117
118 // media embarqué (audio, vidéo, carte)
119 //mediaEmbed: {
120 //previewsInData: true,
121 // vaut "false" par defaut, on crée la balise non standard <oembed url="" > // https://oembed.com/
122 // qui nécessite un traitement (en JS ou côté serveur) en utilisant le lien à l'intérieur
123 // avec "true", on crée la balise <iframe> qui sert à insérer une page HTML dans une autre,
124 // notre "embarquement de média" devrait donc réussir quelque soit le site
125 // c'est plus simple, il ne reste plus qu'à ajuster le contenu avec du CSS (important)
126 // 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
127
128 // en outre, le plugin mediaEmbed (dans l'éditeur), tout comme la balise "iframe" (hors éditeur),
129 // permettent d'afficher un aperçu (preview): une image avec un bouton lecture dessus
130 // cette image est envoyée imédiatement par le serveur, et le contenu après un clic dessus
131 //
132 //},
133
134 // images
135 // le plugin "simple upload adapter" communique avec le serveur au moyen de requêtes AJAX
136 // il attend du serveur une réponse au format .json contenant l'adresse où est stockée l'image:
137 // {"url": "https://example.com/images/foo.jpg"}
138 simpleUpload: {
139 uploadUrl: upload_url,
140
141 // Headers supplémentaires envoyés avec la requête
142 // c'est ici qu'on installe les mécanismes de sécurités comme l'authentification et la protection au CSRF
143 headers: {
144 //'X-CSRF-TOKEN': 'CSRF-Token',
145 //Authorization: 'Bearer <JSON Web Token>'
146 }
147 },
148 // formats acceptés par défaut: jpeg, png, gif, bmp, webp, tiff
149 // 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
150
151 // plugin autosave
152 // voir doc
153 } )
154 .then( newEditor => {
155 editor = newEditor;
156 // fin de ClassicEditor
157
158 // obtenir la liste des éléments disponibles pour la barre d'outils
159 //alert(Array.from( editor.ui.componentFactory.names() ));
160 // obtenir la liste des plugins disponibles:
161 //alert(ClassicEditor.builtinPlugins.map( plugin => plugin.pluginName ));
162
163 // insertion du HTML existant
164 editor.setData(html_existant);
165 } )
166 .catch( error => {
167 console.error( error );
168 } );
169 </script>
170 </form>
171</div>
172<?php
173$editeurHTML = ob_get_clean();