├── .gitignore ├── LICENSE ├── README.md ├── drime.sql ├── exemples ├── Panoryma │ ├── index.html │ ├── panoryma.js │ └── poetify.js └── Parolyma │ ├── getRandomSong.php │ ├── getSong.php │ ├── helpers.php │ ├── index.html │ ├── parolyma.js │ └── poetify.js ├── getPoem.php ├── getRimes.php ├── index.html └── poetify.js /.gitignore: -------------------------------------------------------------------------------- 1 | dbinfo.php 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 WhiteFangs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PoetifyJS 2 | ========= 3 | 4 | PoetifyJS est une boîte à outils Javascript pour la poésie. 5 | ------- 6 | 7 | PoetifyJS comprend plusieurs fonctions utiles pour travailler sur des poèmes en français. 8 | Il contient deux types de fonctions, celles en Javascript pour travailler sur le texte, et celles en PHP pour effectuer les requêtes aux services appropriés que sont Wikisource et la base de données Drime. 9 | 10 | Fonctions 11 | ---- 12 | 13 | ### Syllabify (js) 14 | 15 | **Fonction pour compter le nombre de syllabes d'un mot donné** 16 | 17 | - Renvoie également un tableau contenant les syllabes décomposées 18 | - Gère les diérèses grâce à une variable donnant un maximum de syllabes possibles 19 | 20 | ### Elisioner (js) 21 | 22 | **Fonction pour appliquer les règles d'élision à un tableau de mots** 23 | 24 | - Gère l'élision en fin de vers (fin de tableau) 25 | - Gère l'élision du 'h' // A revoir et à améliorer 26 | 27 | ### Metrify (js) 28 | 29 | **Fonction pour compter le nombre de syllabes des vers d'un poème** 30 | 31 | - Parse le poème pour son exploitation efficace 32 | - Décompose le poème en tableau de vers, puis les vers en tableau de mots 33 | - Utilise Elisioner pour les règles d'élision dans un vers 34 | 35 | ### Rimify (js) 36 | 37 | **Fonction pour récupérer les rimes possibles d'un mot donné avec diverses contraintes** 38 | 39 | - Les rimes ont le même nombre de syllabes que le mot donné 40 | - Les rimes ont la même nature que le mot donné 41 | 42 | ### GetRimesQuery (PHP) 43 | 44 | **Fonction exécutant une requête vers la base de données pour les rimes d'un mot donné** 45 | 46 | - Peut exécuter un callback avec le tableau de rimes obtenu 47 | - Classe les rimes selon l'ordre suivant: similarité phonétique, similarité graphique, fréquence 48 | 49 | ### GetPoem (PHP) 50 | 51 | **Fonction pour, comme son nom l'indique, récupérer un poème sur [Wikisource]** 52 | 53 | - Récupère le texte du poème, le titre, l'auteur et l'URL 54 | - Utilise PHP et gère la majorité des formats de pages de poèmes 55 | 56 | Utilisation 57 | ---- 58 | 59 | ### Base de données 60 | 61 | La base de données utilisée a été générée séparément à partir de l'application Drime ([drime.a3nm.net] basée sur [Lexique]). 62 | **Le fichier drime.sql (~8 Mo) est fourni pour être importée directement.** 63 | La base ne contient pas de noms propres, le résultat d'une requête GetWordQuery est donc nul pour celle-ci, à la différence de l'application Drime qui est capable de déterminer la prononciation de mots inconnus. 64 | Cette fonctionnalité pourra éventuellement être implémentée ultérieurement. 65 | 66 | ### Installation 67 | 68 | Pour installer PoetifyJS, il faut posséder un serveur PHP avec une base SQL dans laquelle il faut importer la base de données Drime grâce au fichier drime.sql. Il suffit ensuite de préciser les informations de connexion à la base dans un fichier dbinfo.php et d'initialiser Poetify en Javascript en spécifiant la route relative pour accéder aux fichiers PHP à appeler (voir les exemples). 69 | 70 | PoetifyJS est sous **licence MIT** (cf le fichier LICENCE) 71 | 72 | N'hésitez pas à faire des remarques ou contribuer ! 73 | 74 | Exemples 75 | ----- 76 | 77 | PoetifyJS est utilisé dans plusieurs applications sur mon site [Louphole] 78 | 79 | ### Panoryma 80 | 81 | **Panoryma est une application qui permet de modifier les mots d’un poème en les remplaçant par des paronymes, c’est-à-dire des mots à la sonorité proche, presque homonymes.** 82 | En quelques clics, un poème peut donc radicalement changer de sens tout en restant étrangement familier. 83 | 84 | - Utilise toutes les fonctions de la boîte à outils PoetifyJS 85 | - L’algorithme recherche les rimes du mot choisi et conserve la métrique 86 | 87 | **[Tester Panoryma]** 88 | 89 | ### Parolyma 90 | 91 | **Parolyma est l'équivalent de Panoryma mais pour les paroles de chansons.** 92 | En quelques clics, les paroles de chansons peuvent donc radicalement changer de sens tout en restant étrangement familières. 93 | 94 | **[Tester Parolyma]** 95 | 96 | [Wikisource]:http://fr.wikisource.org/ 97 | [drime.a3nm.net]:http://drime.a3nm.net/ 98 | [Lexique]:http://www.lexique.org/ 99 | [Louphole]: http://www.louphole.com 100 | [Tester Panoryma]: http://www.louphole.com/applications/panoryma 101 | [Tester Parolyma]: http://www.louphole.com/applications/parolyma 102 | -------------------------------------------------------------------------------- /exemples/Panoryma/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | 16 | 17 | 18 |
19 |
20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /exemples/Panoryma/panoryma.js: -------------------------------------------------------------------------------- 1 | var poet = new poetify("../../"); 2 | 3 | window.onload = function() { 4 | var poemsUrl = ['http://fr.wikisource.org/wiki/Les_Fleurs_du_mal/1861/L%E2%80%99Albatros', 5 | 'http://fr.wikisource.org/wiki/El_Desdichado', 6 | 'http://fr.wikisource.org/wiki/Po%C3%A8mes_saturniens/Mon_r%C3%AAve_familier', 7 | 'http://fr.wikisource.org/wiki/Le_Pont_Mirabeau', 8 | 'https://fr.wikisource.org/wiki/Po%C3%A9sies_(Rimbaud)/%C3%A9d._Vanier,_1895/Le_Dormeur_du_val', 9 | 'http://fr.wikisource.org/wiki/%C2%AB_Demain,_d%C3%A8s_l%E2%80%99aube,_%C3%A0_l%E2%80%99heure_o%C3%B9_blanchit_la_campagne_%C2%BB', 10 | 'http://fr.wikisource.org/wiki/%C2%AB_Mignonne,_allons_voir_si_la_rose_%C2%BB', 11 | 'http://fr.wikisource.org/wiki/Nuit_rh%C3%A9nane', 12 | 'http://fr.wikisource.org/wiki/Le_Bateau_ivre/%C3%89dition_Vanier_1895', 13 | 'http://fr.wikisource.org/wiki/Vers_dor%C3%A9s_(Nerval)', 14 | 'http://fr.wikisource.org/wiki/%C2%AB_Quand_vous_serez_bien_vieille,_au_soir,_%C3%A0_la_chandelle_%C2%BB']; 15 | var poemUrl = poemsUrl[Math.floor(Math.random() * poemsUrl.length)]; 16 | poet.motsArray = []; // Variable globale des rimes chargées 17 | getPanorymaPoem(poemUrl); 18 | }; 19 | 20 | function autoRandomizer(counter){ 21 | document.getElementById("autoRandomizer").value = "Transformation en cours..."; 22 | document.getElementById("autoRandomizer").disabled = true; 23 | var mots = document.getElementsByClassName("mot1"); 24 | mots = [].slice.call(mots); 25 | mots = mots.filter(function (a) {return a.innerText.length > 4;}); 26 | if(counter < mots.length && counter < 80){ 27 | mots[counter].click(); 28 | var currentMotsArray = poet.motsArray; 29 | waiter(currentMotsArray, counter, 0); 30 | }else{ 31 | document.getElementById("autoRandomizer").value = "Je suis paresseux, je préfère qu'un automate clique partout pour moi !"; 32 | document.getElementById("autoRandomizer").disabled = false; 33 | poet.charged = true; 34 | } 35 | } 36 | 37 | function waiter(currentMotsArray, counter, looping){ 38 | if(poet.charged !== true && poet.motsArray.equals(currentMotsArray) && looping < 10){ 39 | setTimeout(function (){waiter(currentMotsArray, counter, ++looping);}, 50); 40 | }else{ 41 | autoRandomizer(++counter); 42 | } 43 | } 44 | 45 | Array.prototype.equals = function (array) { 46 | // if the other array is a falsy value, return 47 | if (!array) 48 | return false; 49 | 50 | // compare lengths - can save a lot of time 51 | if (this.length != array.length) 52 | return false; 53 | 54 | for (var i = 0, l=this.length; i < l; i++) { 55 | // Check if we have nested arrays 56 | if (this[i] instanceof Array && array[i] instanceof Array) { 57 | // recurse into the nested arrays 58 | if (!this[i].equals(array[i])) 59 | return false; 60 | } 61 | else if (this[i] != array[i]) { 62 | // Warning - two different object instances will never be equal: {x:20} != {x:20} 63 | return false; 64 | } 65 | } 66 | return true; 67 | }; 68 | 69 | function getPanorymaPoem(poemUrl){ 70 | poet.getPoem(poemUrl); 71 | if (document.body.addEventListener) { 72 | document.body.addEventListener('click', rimifyBinder, false); 73 | } 74 | else { 75 | document.body.attachEvent('onclick', rimifyBinder); //pour IE 76 | } 77 | } 78 | 79 | // Parse les mots et vers, vérifie le chargement des rimes et appelle le traitement des rimes 80 | function rimifyBinder(e) 81 | { 82 | e = e || window.event; 83 | var target = e.target || e.srcElement; 84 | if (target.className == "mot1") 85 | { 86 | document.body.style.cursor = "progress"; 87 | var mot = e.target.innerHTML.replace('', '').replace('', ''); 88 | var vers = e.target.parentNode.innerHTML; 89 | vers = poet.unparsePoemFromHTML(vers); 90 | mot = mot.split(/[\.,…\/#!$%\^&\*;\?:{}=\_`~()]/g)[0];// Si il y a de la ponctuation on la coupe du mot 91 | var premot; 92 | if (mot.indexOf("’") > -1) { 93 | premot = mot.split("’")[0]; 94 | mot = mot.split("’")[1]; 95 | } 96 | var capitalize = mot.charAt(0) === mot.charAt(0).toUpperCase(); 97 | mot = mot.toLowerCase(); 98 | vers = vers.toLowerCase(); 99 | var rimes, k = 0, isFem; 100 | for (var i = 0; i < poet.motsArray.length; i++) { // Vérifier si les rimes du mot ne sont pas déjà chargées 101 | if (poet.motsArray[i].rimes.indexOf(mot) > -1) { 102 | rimes = poet.motsArray[i].rimes; 103 | k = poet.motsArray[i].rimes.indexOf(mot); 104 | isFem = poet.motsArray[i].isFem; 105 | k++; 106 | if (k == rimes.length) { 107 | k = 0; 108 | } 109 | i = poet.motsArray.length; 110 | } 111 | } 112 | if (rimes === undefined) { // Si les rimes n'ont pas été chargées, on les charge et on les traite 113 | poet.rimify(mot, true, function(rimesObj) { 114 | if (rimesObj.rimes.length !== 0) { 115 | traitementRimes(k, vers, mot, rimesObj.rimes, e.target, premot, rimesObj.isFem, true, capitalize); 116 | }else{ 117 | document.body.style.cursor = "default"; 118 | poet.motsArray = poet.motsArray.concat({rime: mot, rimes: [mot], index: 0, isFem: false}); 119 | return false; 120 | } 121 | }, function(){ 122 | document.body.style.cursor = "default"; 123 | }); 124 | } else { // Sinon on les traite 125 | traitementRimes(k, vers, mot, rimes, e.target, premot, isFem, false, capitalize); 126 | } 127 | } 128 | } 129 | 130 | // Pour le mot donné, cherche la première rime appropriée, puis remplace dans le poème et actualise le tableau des rimes chargées 131 | function traitementRimes(k, vers, mot, rimes, node, premot, isFem, isNew, isCapitalized) { 132 | var index = k, position; 133 | if (premot !== undefined) { 134 | position = vers.indexOf(premot + "’" + mot); 135 | } else { 136 | position = vers.indexOf(mot); 137 | } 138 | var metrique = poet.metrify(vers), metriqueRime, versRime, premotRime; 139 | do { 140 | if (premot !== undefined) { 141 | premotRime = genrifyPremot(premot, rimes[k % rimes.length], isFem); 142 | versRime = vers.replaceBetween(position, position + (premot + mot).length + 1, premotRime + rimes[k % rimes.length]); 143 | } else { 144 | versRime = vers.replaceBetween(position, position + mot.length, rimes[k % rimes.length]); 145 | } 146 | metriqueRime = poet.metrify(versRime); 147 | if (metriqueRime.nbsyllabes[0].nb == metrique.nbsyllabes[0].nb && metriqueRime.nbsyllabes[0].max == metrique.nbsyllabes[0].max && mot != rimes[k % rimes.length]) { 148 | if (isNew) { 149 | if (rimes.indexOf(mot) < 0) { 150 | rimes = rimes.concat(mot); 151 | } 152 | poet.motsArray = poet.motsArray.concat({rime: rimes[k % rimes.length], rimes: rimes, index: k % rimes.length, isFem: isFem}); 153 | } else { 154 | for (var i = 0; i < poet.motsArray.length; i++) { 155 | if (poet.motsArray[i].rimes.indexOf(mot) > -1) { 156 | poet.motsArray[i].rime = rimes[k % rimes.length]; 157 | poet.motsArray[i].index = k % rimes.length; 158 | } 159 | } 160 | } 161 | var rime = rimes[k % rimes.length]; 162 | if (premot !== undefined) { 163 | if (vers.charAt(position - 2) == '.' || vers.charAt(position - 2) == '!' || vers.charAt(position - 2) == '?' || vers.charAt(position - 2) == '…') { 164 | premot = premot.charAt(0).toUpperCase() + premot.slice(1); 165 | } 166 | node.innerHTML = node.innerHTML.toLowerCase().replace(premot + "'", premotRime); 167 | } else if (vers.charAt(position - 2) == '.' || vers.charAt(position - 2) == '!' || vers.charAt(position - 2) == '?' || vers.charAt(position - 2) == '…') { 168 | rime = rimes[k % rimes.length].charAt(0).toUpperCase() + rimes[k % rimes.length].slice(1); 169 | } 170 | node.innerHTML = node.innerHTML.toLowerCase().replace(mot, isCapitalized ? rime.capitalizeFirstLetter() : rime); 171 | var poeme = node.parentNode.parentNode.innerHTML; 172 | poeme = poet.unparsePoemFromHTML(poeme); 173 | poet.parsePoemToHTML(poeme, node.parentNode.parentNode); 174 | k = index + rimes.length; 175 | } else { 176 | k++; 177 | } 178 | } while (k % rimes.length != index); 179 | document.body.style.cursor = "default"; 180 | return poet.motsArray; 181 | } 182 | 183 | // Adapte le premot au genre du nouveau mot qui le suit (la nouvelle rime) 184 | function genrifyPremot(premot, rime, isFem) { 185 | var elision = ['a', 'A', 'á', 'Á', 'à', 'À', 'â', 'Â', 'e', 'E', 'é', 'É', 'è', 'È', 'ê', 'Ê', 'í', 'Í', 'o', 'ó', 'O', 'Ó', 'ô', 'Ô', 'ú', 'Ú', 'i', 'I', 'u', 'U', 'ü', 'Ü', 'û', 'Û', 'ï', 'Ï', 'î', 'Î', 'h', 'H']; 186 | if (elision.indexOf(rime.charAt(0)) > -1) { 187 | return premot + "'"; 188 | } 189 | if (premot.toLowerCase() == "d") { 190 | if (isFem) { 191 | return premot + "e la "; 192 | } else { 193 | return premot + "u "; 194 | } 195 | } 196 | if (premot.toLowerCase() == "l") { 197 | if (isFem) { 198 | return premot + "a "; 199 | } else { 200 | return premot + "e "; 201 | } 202 | } 203 | if (premot.toLowerCase() == "j" || premot.toLowerCase() == "n" || premot.toLowerCase() == "m" || premot.toLowerCase() == "s") { 204 | return premot + "e "; 205 | } 206 | if (premot.toLowerCase() == "t") { 207 | return premot + "u "; 208 | } 209 | if (premot.toLowerCase() == "c") { 210 | return premot + "ela "; 211 | } 212 | return premot + "'"; 213 | } 214 | 215 | function getPoemText(poemText) { 216 | var poemDIV = document.getElementById("poem"); 217 | document.getElementById("meta").innerHTML = ''; 218 | poet.parsePoemToHTML(poemText, poemDIV); 219 | if (document.body.addEventListener) { 220 | document.body.addEventListener('click', rimifyBinder, false); 221 | } 222 | else { 223 | document.body.attachEvent('onclick', rimifyBinder); //pour IE 224 | } 225 | } 226 | 227 | // Parse correctement un string en RegExp 228 | function escapeRegExp(str) { 229 | return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 230 | } 231 | // Replace toutes les occurrences dans un string 232 | function replaceAll(find, replace, str) { 233 | return str.replace(new RegExp(escapeRegExp(find), 'g'), replace); 234 | } 235 | 236 | // Remplace une partie d'un string dont la position est définie par les indices 237 | String.prototype.replaceBetween = function(start, end, replace) { 238 | return this.substring(0, start) + replace + this.substring(end); 239 | }; 240 | 241 | String.prototype.capitalizeFirstLetter = function() { 242 | return this.charAt(0).toUpperCase() + this.slice(1); 243 | }; 244 | -------------------------------------------------------------------------------- /exemples/Panoryma/poetify.js: -------------------------------------------------------------------------------- 1 | var poetify = function (phpDirectory){ 2 | 3 | var self = this; 4 | 5 | // Comptage et découpage d'un mot en syllabes avec les possibilités de diérèses gérées par la variable max 6 | self.syllabify = function (s) { 7 | if (s.toLowerCase() == "pays") { // Exception pour ce mot ingérable autrement 8 | return ({syllabes: ["pa", "ys"], nb: 2, max: 2}); 9 | } 10 | if (!s.trim().match(/[a-zA-Z]/g)) { 11 | return {syllabes: [], nb: 0, max: 0}; 12 | } 13 | var consonnes = ['b', 'B', 'c', 'C', 'ç', 'Ç', 'd', 'D', 'f', 'F', 'g', 'G', 'h', 'H', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'ñ', 'Ñ', 'p', 'P', 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'v', 'V', 'w', 'W', 'x', 'X', 'y', 'Y', 'z', 'Z', '-']; 14 | var voyellesFortes = ['a', 'A', 'á', 'Á', 'à', 'À', 'â', 'Â', 'e', 'E', 'é', 'É', 'è', 'È', 'ê', 'Ê', 'í', 'Í', 'o', 'ó', 'O', 'Ó', 'ô', 'Ô', 'ú', 'Ú']; 15 | var voyellesFaibles = ['i', 'I', 'u', 'U', 'ü', 'Ü', 'ï', 'Ï', 'î', 'Î', 'û', 'Û']; 16 | var voyelles = voyellesFortes.concat(voyellesFaibles, ['y', 'Y']); 17 | var nb, coupure, voy; 18 | var j = 0, max = 0; 19 | var n = s.length - 1; 20 | var i = 0; 21 | var syllabes = []; 22 | while (i <= n) { 23 | coupure = 0; // Ne coupe pas 24 | if (consonnes.indexOf(s.charAt(i)) > -1) { 25 | if (voyelles.indexOf(s.charAt(i + 1)) > -1) { 26 | if (s.toLowerCase().charAt(i) == 'y') { // diérèse possible du y utilisé comme consonne 27 | max++; 28 | } 29 | if (voyelles.indexOf(s.charAt(i - 1)) > -1) { 30 | coupure = 1; 31 | } 32 | } else if ((['s', 'S'].indexOf(s.charAt(i)) > -1) && (['n', 'N'].indexOf(s.charAt(i - 1)) > -1) && (consonnes.indexOf(s.charAt(i + 1)) > -1)) { 33 | coupure = 2; 34 | } else if ((consonnes.indexOf(s.charAt(i + 1)) > -1) && (voyelles.indexOf(s.charAt(i - 1)) > -1)) { 35 | if (['r', 'R'].indexOf(s.charAt(i + 1)) > -1) { 36 | if (['b', 'B', 'c', 'C', 'd', 'D', 'f', 'F', 'g', 'G', 'k', 'K', 'p', 'P', 'r', 'R', 't', 'T', 'v', 'V'].indexOf(s.charAt(i)) > -1) { 37 | coupure = 1; 38 | } else { 39 | coupure = 2; 40 | } 41 | } else if (['l', 'L'].indexOf(s.charAt(i + 1)) > -1) { 42 | if (['b', 'B', 'c', 'C', 'd', 'D', 'f', 'F', 'g', 'G', 'k', 'K', 'l', 'L', 'p', 'P', 't', 'T', 'v', 'V'].indexOf(s.charAt(i)) > -1) { 43 | coupure = 1; 44 | } else { 45 | coupure = 2; 46 | } 47 | } else if (['h', 'H'].indexOf(s.charAt(i + 1)) > -1) { 48 | if (['c', 'C', 's', 'S', 'p', 'P'].indexOf(s.charAt(i)) > -1) { 49 | coupure = 1; 50 | } else { 51 | coupure = 2; 52 | } 53 | } else if ((['t', 'T', 'p', 'P'].indexOf(s.charAt(i + 1)) > -1) && (['s', 'S'].indexOf(s.charAt(i + 2)) > -1)) { // pour des mots comme "verts" ou "corps" 54 | coupure = 0; 55 | } else { 56 | coupure = 2; 57 | } 58 | } 59 | } else if (voyellesFortes.indexOf(s.charAt(i)) > -1) { 60 | if ((voyellesFortes.indexOf(s.charAt(i - 1)) > -1) && 61 | (s.substring(i - 2, i).toLowerCase() != 'ge') && 62 | (s.substring(i - 1, i + 2).toLowerCase() != 'eau') && 63 | (s.substring(i - 1, i + 1).toLowerCase() != 'oe') && 64 | ((s.substring(i - 1, i + 2).toLowerCase() != 'ée') && (s.substring(i + 1, i + 2).toLowerCase() != 'ées') && (s.substring(i + 1, i + 4).toLowerCase() != 'éent'))) { 65 | coupure = 1; 66 | } 67 | } else if (voyellesFaibles.indexOf(s.charAt(i)) > -1 && (s.substring(i - 1, i + 1).toLowerCase() != 'qu') && (s.substring(i - 1, i + 1).toLowerCase() != 'gu')) { // Gestion de la diérèse éventuelle, sauf pour les cas avec "qu" / "gu" 68 | if ((voyelles.indexOf(s.charAt(i + 1)) > -1) && 69 | (consonnes.indexOf(s.charAt(i - 1)) > -1) && 70 | (consonnes.indexOf(s.charAt(i - 2)) > -1) && 71 | (s.substring(i, i + 2).toLowerCase() != 'ui')) { // diérèse obligatoire si deux consonnes avant 72 | if (s.toLowerCase().charAt(i + 1) == 'y') { // diérèse possible du y pour des mots comme "ennuyer" ou "essuyer" 73 | max++; 74 | } 75 | coupure = 2; 76 | } else if ((voyelles.indexOf(s.charAt(i + 1)) > -1)) { 77 | if (((s.substring(i + 1, i + 4).toLowerCase() != 'ent') && (s.substring(i + 1, i + 4).toLowerCase() != 'es')) || // Si terminaisons en "-aient" et en "-aie(s)" : pas de diérèse possible 78 | (s.substring(i, i + 2).toLowerCase() != 'ui')) { // Si mot comme "fruit", "bruit", "impuissant", diérèse très rare mais tolérable 79 | max++; 80 | } 81 | } 82 | } 83 | if (coupure == 1) { // Couper ici 84 | voy = s.substring(j, i); 85 | syllabes.push(voy); 86 | j = i; 87 | } else if (coupure == 2) { // Couper au caractère suivant 88 | i++; 89 | voy = s.substring(j, i); 90 | syllabes.push(voy); 91 | j = i; 92 | } 93 | i++; 94 | } 95 | nb = syllabes.length; 96 | if ((j == n) && (nb > 0) && (consonnes.indexOf(s.charAt(n)) > -1)) { //Dernière lettre 97 | syllabes[nb - 1] = syllabes[nb - 1] + s.charAt(n); 98 | } else { 99 | voy = s.substring(j, n + 1); 100 | syllabes.push(voy); // Dernière syllabe 101 | nb++; 102 | } 103 | return {syllabes: syllabes, nb: nb, max: nb + max}; 104 | }; 105 | 106 | // Prend un tableau de mots en entrée. Pour chaque mot dans le tableau (vers), applique syllabify avec les règles d'élision du e 107 | self.elisioner = function (mots) { 108 | var voyelles = ['a', 'A', 'á', 'Á', 'à', 'À', 'â', 'Â', 'e', 'E', 'é', 'É', 'è', 'È', 'ê', 'Ê', 'í', 'Í', 'o', 'ó', 'O', 'Ó', 'ô', 'Ô', 'ú', 'Ú', 'i', 'I', 'u', 'U', 'ü', 'Ü', 'û', 'Û', 'ï', 'Ï', 'î', 'Î']; 109 | var elision = voyelles.concat(['h', 'H']); 110 | var syllabes, nb = 0, max = 0; 111 | 112 | for (var i = 0; i < mots.length; i++) { 113 | syllabes = self.syllabify(mots[i]); 114 | nb += syllabes.nb; 115 | max += syllabes.max; 116 | if ((i > 0) && 117 | (mots[i - 1].toLowerCase().slice(-1) == 'e') && 118 | (elision.indexOf(mots[i].charAt(0)) > -1) && 119 | (self.sansAccents(mots[i - 1].toLowerCase().slice(-2, -1)) != self.sansAccents(mots[i].charAt(0)))) { // élision du e de fin dans le mot précédent si liaison (MAIS élision interdite si même son, ex: "Thésée excusable") 120 | nb--; 121 | if (['h', 'H'].indexOf(mots[i].charAt(0)) < 0) { 122 | max--; 123 | } 124 | } 125 | if ((i == mots.length - 1) && 126 | (mots[i].toLowerCase().slice(-1) == 'e' || mots[i].toLowerCase().slice(-2) == 'es' || mots[i].toLowerCase().slice(-3) == 'ent')) { // élision du e en fin de vers 127 | nb--; 128 | if (!((voyelles.indexOf(mots[i].toLowerCase().slice(-2, -1)) > -1) && (mots[i].toLowerCase().slice(-1) == 'e')) && // Si finit par une voyelle + "e" : l'élision peut-être évitée en appuyant le e (ex: "patrie") 129 | !((voyelles.indexOf(mots[i].toLowerCase().slice(-3, -2)) > -1) && (mots[i].toLowerCase().slice(-2) == 'es')) && 130 | !((voyelles.indexOf(mots[i].toLowerCase().slice(-4, -3)) > -1) && (mots[i].toLowerCase().slice(-3) == 'ent')) && 131 | (mots[i].toLowerCase().slice(-4) != 'ment')) { // Si c'est un adverbe, la syllabe finale est obligatoire donc on ne diminue pas max pour prévenir ces cas 132 | max--; 133 | } 134 | } 135 | } 136 | return {nb: nb, max: max}; 137 | }; 138 | 139 | // Compte le nombre de syllabes des vers d'un poème en suivant les règles classiques d'élision 140 | self.metrify = function (s) { 141 | s = s.replace(/[\.,…\/#!$%\^&\*;\?:{}=\_`~()]/g, "").replace(/[0-9]/g, '').replace(/\s{2,}/g, " ").replace(/œ/g, "oe").replace(/æ/g, "ae").replace(/\r\n|\r|\n/g, "
"); 142 | var vers = s.split("
"); 143 | vers = vers.filter(function(v) { 144 | return v !== ''; 145 | }); 146 | var mots = []; 147 | var nbsyllabes = []; 148 | 149 | for (var i = 0; i < vers.length; i++) { 150 | var lesmots = vers[i].split(" "); 151 | lesmots = lesmots.filter(function(v) { 152 | return v !== ''; 153 | }); 154 | mots[i] = lesmots; // range les mots dans un tableau différent pour chaque vers 155 | } 156 | 157 | // Appliquer elisioner au tableau de mots de chaque vers 158 | for (var k = 0; k < mots.length; k++) { 159 | nbsyllabes[k] = self.elisioner(mots[k]); 160 | } 161 | 162 | return {vers: vers, mots: mots, nbsyllabes: nbsyllabes}; 163 | }; 164 | 165 | // Récupère les rimes d'un mot ayant le même nombre de syllabes et la même nature (Verbe, nom, adjectif...) 166 | self.rimify = function (s, addWord, success, error) { 167 | var syllabes = self.syllabify(s); 168 | self.getRimesQuery(s, function(data) { 169 | if(addWord) 170 | data.rimes.push(s); 171 | this.success = success || function(data) { 172 | console.log(data); 173 | return data; 174 | }; 175 | this.success(data); 176 | }, error); 177 | }; 178 | 179 | // Récupère les rimes d'un mot à l'aide de ses propriétés et exécute le callback avec le tableau de rimes obtenu si besoin 180 | self.getRimesQuery = function (word, success, error) { 181 | self.ajaxRequest('POST', 'getRimes.php', 'word=' + word, function(data) { 182 | data = JSON.parse(data); 183 | data.isFem = data.isFem == "1"; 184 | this.success = success || function(data) { 185 | console.log(data); 186 | }; 187 | this.success(data); 188 | }, function () { 189 | this.error = error || function() { 190 | console.log("An error happened in getRimesQuery"); 191 | }; 192 | this.error(); 193 | }); 194 | }; 195 | 196 | 197 | // Get Poem from Wikisource 198 | self.getPoem = function (poemUrl) { 199 | var poemDIV = document.getElementById("poem"), request; 200 | if (poemUrl.indexOf("wikisource.org/wiki/") < 0) { 201 | poemDIV.innerHTML = "
"; 202 | document.getElementById("meta").innerHTML = "Veuillez entrer une adresse Wikisource valide.
"; 203 | } else { 204 | document.body.style.cursor = "wait"; 205 | self.ajaxRequest('POST', 'getPoem.php', "poemUrl=" + poemUrl, function(data) { 206 | document.body.style.cursor = "default"; 207 | data = data.replace(/Warning([^;]*){/, '{'); 208 | if (data == "Erreur") { 209 | poemDIV.innerHTML = "
"; 210 | document.getElementById("meta").innerHTML = "Erreur lors de la récupération du poème. Réessayer.
"; 211 | } else { 212 | data = JSON.parse(data); 213 | data.poeme = data.poeme.replace(/###/g, '\n'); 214 | data.poeme = data.poeme.replace(/\[[^;]*]/g, ""); 215 | data.poeme = data.poeme.replace("'", "’"); 216 | data.titre = data.titre.replace(/\//g, " - "); 217 | self.parsePoemToHTML(data.poeme, poemDIV); 218 | document.getElementById("meta").innerHTML = '

' + data.titre + '

de ' + data.auteur + ''; 219 | } 220 | }, function () { 221 | poemDIV.innerHTML = "
"; 222 | document.getElementById("meta").innerHTML = "Erreur lors de la récupération du poème. Réessayer.
"; 223 | }); 224 | } 225 | }; 226 | 227 | // Parse la nature de la rime et compare à celle du mot 228 | self.natureEquals = function (natureRime, nature) { 229 | for (var i = 0; i < natureRime.length; i++) { 230 | if (nature.indexOf(natureRime[i]) > -1) { 231 | return true; 232 | } 233 | } 234 | return false; 235 | }; 236 | 237 | self.sansAccents = function (s) { 238 | var r = s.toLowerCase(); 239 | r = r.replace(/[àáâãäå]/g, "a"); 240 | r = r.replace(/[èéêë]/g, "e"); 241 | r = r.replace(/[ìíîï]/g, "i"); 242 | r = r.replace(/[òóôõö]/g, "o"); 243 | r = r.replace(/[ùúûü]/g, "u"); 244 | r = r.replace(/[ýÿ]/g, "y"); 245 | return r; 246 | }; 247 | 248 | self.ajaxRequest = function (method, file, sendContent, success, error){ 249 | var request = new XMLHttpRequest(); 250 | request.open(method, phpDirectory + file, true); 251 | request.onreadystatechange = function() { 252 | if (this.readyState === 4) { 253 | if (this.status >= 200 && this.status < 400) { 254 | try{ 255 | var data = this.responseText; 256 | if(data.length !== 0){ 257 | this.success = success || function(data) { 258 | console.log(data); 259 | }; 260 | this.success(data); 261 | }else{ 262 | console.log("No data returned"); 263 | } 264 | }catch(e){ 265 | console.log(e); 266 | console.log("Error in returned data handling"); 267 | } 268 | }else{ 269 | this.error = error || function() { 270 | console.log(this); 271 | }; 272 | this.error(this); 273 | } 274 | } 275 | }; 276 | request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 277 | request.send(sendContent); 278 | request = null; 279 | }; 280 | 281 | self.parsePoemToHTML = function (poeme, poemDIV) { 282 | var poem = ''; 283 | poeme.split(/\r\n|\r|\n/g).forEach(function(vers) { 284 | vers = vers.charAt(0).toUpperCase() + vers.slice(1); 285 | poem += vers + '\n'; 286 | }); 287 | poem = poem.slice(0, -1); 288 | poem = poem.replace(/[^\S\n]/g, ' '); 289 | poem = poem.replace(/\r\n|\r|\n/g, '
'); 290 | poem = '' + poem + ''; 291 | poemDIV.innerHTML = poem; 292 | poemDIV.innerHTML = poemDIV.innerHTML.replace(new RegExp(escapeRegExp(''), 'g'), ""); 293 | }; 294 | 295 | self.unparsePoemFromHTML = function(poeme) { 296 | poeme = replaceAll('', '', poeme); 297 | poeme = replaceAll('', '', poeme); 298 | poeme = replaceAll('
', '\n', poeme); 299 | poeme = replaceAll('', '', poeme); 300 | return poeme; 301 | }; 302 | 303 | return self; 304 | }; 305 | -------------------------------------------------------------------------------- /exemples/Parolyma/getRandomSong.php: -------------------------------------------------------------------------------- 1 | query('//b/a[starts-with(@href, "/wiki/'.$artistLink.':") and not(contains(@href, "?action=edit"))]'); 13 | 14 | if($songsNodes->length > 0){ 15 | // Create songs array to filter duplicate songs 16 | $songs = array(); 17 | foreach($songsNodes as $node) { 18 | $songs[] = $node->getAttribute("title") . '/href=' . $node->getAttribute("href"); 19 | } 20 | $songs = array_values(array_filter(array_unique($songs))); 21 | 22 | // Take a random song 23 | $idx = intval(rand(0, count($songs) - 1)); 24 | $song = $songs[$idx]; 25 | $songAttrTitle = substr($song, 0, strrpos($song, "/href=")); 26 | $songAttrHref = substr($song, strrpos($song, "/href=") + strlen("/href=")); 27 | $artistName = substr($songAttrTitle, 0 , strrpos($songAttrTitle, ":")); 28 | $songName = substr($songAttrTitle, strrpos($songAttrTitle, ":") + 1); 29 | $lyricsLink = "http://lyrics.wikia.com" . $songAttrHref; 30 | 31 | // Get the lyrics and credits 32 | $lyricsPage = getCURLOutput($lyricsLink); 33 | $lyricsPage = str_replace('
', '###', $lyricsPage); 34 | $lyricsXpath = getDOMXPath($lyricsPage); 35 | $lyricsQuery = $lyricsXpath->query('//div[@class="lyricbox"]'); 36 | $creditsQuery = $lyricsXpath->query('//div[@class="song-credit-box"]/text()'); 37 | $lyrics = $lyricsQuery->item($i)->nodeValue; 38 | $lyrics = delete_all_between("(", ")", $lyrics); 39 | $lyrics = str_replace("'", "’", $lyrics); 40 | 41 | if (isset($lyricsLink) && isset($songName) && isset($artistName) && isset($lyrics)) { 42 | $arr = array('url' => $lyricsLink, 'titre' => $songName, 'auteur' => $artistName, 'lyrics' => $lyrics); 43 | echo json_encode($arr); 44 | } else { 45 | echo "Erreur"; 46 | } 47 | } 48 | 49 | ?> 50 | -------------------------------------------------------------------------------- /exemples/Parolyma/getSong.php: -------------------------------------------------------------------------------- 1 | ', '###', $lyricsPage); 10 | $lyricsXpath = getDOMXPath($lyricsPage); 11 | $lyricsQuery = $lyricsXpath->query('//div[@class="lyricbox"]/text()'); 12 | $creditsQuery = $lyricsXpath->query('//div[@class="song-credit-box"]/text()'); 13 | $metaQuery = $lyricsXpath->query('//div[@class="header-column header-title"]/h1/text()'); 14 | $songAttrTitle = $metaQuery->item(0)->nodeValue; 15 | $songAttrTitle = str_replace(" Lyrics", "", $songAttrTitle); 16 | $artistName = substr($songAttrTitle, 0 , strrpos($songAttrTitle, ":")); 17 | $songName = substr($songAttrTitle, strrpos($songAttrTitle, ":") + 1); 18 | $lyrics = $lyricsQuery->item($i)->nodeValue; 19 | $lyrics = delete_all_between("(", ")", $lyrics); 20 | $lyrics = str_replace("'", "’", $lyrics); 21 | 22 | if (isset($lyricsLink) && isset($songName) && isset($artistName) && isset($lyrics)) { 23 | $arr = array('url' => $lyricsLink, 'titre' => $songName, 'auteur' => $artistName, 'lyrics' => $lyrics); 24 | echo json_encode($arr); 25 | } else { 26 | echo "Erreur"; 27 | } 28 | 29 | ?> 30 | -------------------------------------------------------------------------------- /exemples/Parolyma/helpers.php: -------------------------------------------------------------------------------- 1 | (.*?)#is', '', $output); 11 | return $output; 12 | } 13 | 14 | function getDOMXPath($page){ 15 | $dom = new DOMDocument; 16 | $page = mb_convert_encoding($page, 'HTML-ENTITIES', "UTF-8"); 17 | @$dom->loadHTML($page); 18 | $xpath = new DOMXPath($dom); 19 | return $xpath; 20 | } 21 | 22 | function delete_all_between($beginning, $end, $string) { 23 | $beginningPos = strpos($string, $beginning); 24 | $endPos = strpos($string, $end); 25 | if ($beginningPos === false || $endPos === false) { 26 | return $string; 27 | } 28 | $textToDelete = substr($string, $beginningPos, ($endPos + strlen($end)) - $beginningPos); 29 | return str_replace($textToDelete, '', $string); 30 | } 31 | 32 | ?> 33 | -------------------------------------------------------------------------------- /exemples/Parolyma/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | 16 | 17 | 18 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /exemples/Parolyma/parolyma.js: -------------------------------------------------------------------------------- 1 | var poet = new poetify("../../"); 2 | var artistsList = ["Booba", "Claude_François", "La_Fouine", "Lorie", "Noir_Désir", "Serge_Gainsbourg"]; 3 | var exampleDirectory = "./"; 4 | 5 | // Get Song from Lyrics Wikia 6 | poet.getSong = function (songUrl, songArtist) { 7 | var lyricsDIV = document.getElementById("lyrics"), request; 8 | if(songUrl !== null){ 9 | if (songUrl.indexOf("lyrics.wikia.com/") < 0 || songUrl.indexOf(":") < 0) { 10 | lyricsDIV.innerHTML = "
"; 11 | document.getElementById("meta").innerHTML = "Veuillez entrer une adresse Lyrics Wikia valide.
"; 12 | } else { 13 | document.body.style.cursor = "wait"; 14 | poet.ajaxRequest('POST', exampleDirectory + 'getSong.php', "songUrl=" + songUrl, function(data) { 15 | getSongCallback(data); 16 | }, function () { 17 | lyricsDIV.innerHTML = "
"; 18 | document.getElementById("meta").innerHTML = "Erreur lors de la récupération des paroles. Réessayer.
"; 19 | }); 20 | } 21 | }else{ 22 | if (artistsList.indexOf(songArtist) < 0) { 23 | lyricsDIV.innerHTML = "
"; 24 | document.getElementById("meta").innerHTML = "Artiste non valide.
"; 25 | } else { 26 | document.body.style.cursor = "wait"; 27 | poet.ajaxRequest('POST', exampleDirectory + 'getRandomSong.php', "songArtist=" + songArtist, function(data) { 28 | getSongCallback(data); 29 | }, function () { 30 | lyricsDIV.innerHTML = "
"; 31 | document.getElementById("meta").innerHTML = "Erreur lors de la récupération des paroles. Réessayer.
"; 32 | }); 33 | } 34 | } 35 | }; 36 | 37 | function getSongCallback(data){ 38 | var lyricsDIV = document.getElementById("lyrics"); 39 | document.body.style.cursor = "default"; 40 | data = data.replace(/Warning([^;]*){/, '{'); 41 | if (data == "Erreur") { 42 | lyricsDIV.innerHTML = "
"; 43 | document.getElementById("meta").innerHTML = "Erreur lors de la récupération des paroles. Réessayer.
"; 44 | } else { 45 | data = JSON.parse(data); 46 | data.lyrics = data.lyrics.replace(/###/g, '\n'); 47 | data.lyrics = data.lyrics.replace(/\[[^;]*]/g, ""); 48 | data.lyrics = data.lyrics.replace("'", "’"); 49 | data.titre = data.titre.replace(/\//g, " - "); 50 | poet.parsePoemToHTML(data.lyrics, lyricsDIV); 51 | document.getElementById("meta").innerHTML = '

' + data.titre + '

de ' + data.auteur + ''; 52 | } 53 | } 54 | 55 | window.onload = function() { 56 | var artist = artistsList[Math.floor(Math.random() * artistsList.length)]; 57 | poet.motsArray = []; // Variable globale des rimes chargées 58 | document.querySelector('[value="'+ artist +'"]').selected = true; 59 | getRandomSong(artist); 60 | }; 61 | 62 | function autoRandomizer(counter){ 63 | document.getElementById("autoRandomizer").value = "Transformation en cours..."; 64 | document.getElementById("autoRandomizer").disabled = true; 65 | var mots = document.getElementsByClassName("mot1"); 66 | mots = [].slice.call(mots); 67 | mots = mots.filter(function (a) {return a.innerText.length > 4;}); 68 | if(counter < mots.length && counter < 80){ 69 | mots[counter].click(); 70 | var currentMotsArray = poet.motsArray; 71 | waiter(currentMotsArray, counter, 0); 72 | }else{ 73 | document.getElementById("autoRandomizer").value = "Je suis paresseux, je préfère qu'un automate clique partout pour moi !"; 74 | document.getElementById("autoRandomizer").disabled = false; 75 | poet.charged = true; 76 | } 77 | } 78 | 79 | function waiter(currentMotsArray, counter, looping){ 80 | if(poet.charged !== true && poet.motsArray.equals(currentMotsArray) && looping < 10){ 81 | setTimeout(function (){waiter(currentMotsArray, counter, ++looping);}, 50); 82 | }else{ 83 | autoRandomizer(++counter); 84 | } 85 | } 86 | 87 | Array.prototype.equals = function (array) { 88 | // if the other array is a falsy value, return 89 | if (!array) 90 | return false; 91 | 92 | // compare lengths - can save a lot of time 93 | if (this.length != array.length) 94 | return false; 95 | 96 | for (var i = 0, l=this.length; i < l; i++) { 97 | // Check if we have nested arrays 98 | if (this[i] instanceof Array && array[i] instanceof Array) { 99 | // recurse into the nested arrays 100 | if (!this[i].equals(array[i])) 101 | return false; 102 | } 103 | else if (this[i] != array[i]) { 104 | // Warning - two different object instances will never be equal: {x:20} != {x:20} 105 | return false; 106 | } 107 | } 108 | return true; 109 | }; 110 | 111 | function getParolymaSong(songUrl){ 112 | poet.getSong(songUrl, null); 113 | if (document.body.addEventListener) { 114 | document.body.addEventListener('click', rimifyBinder, false); 115 | } 116 | else { 117 | document.body.attachEvent('onclick', rimifyBinder); //pour IE 118 | } 119 | } 120 | 121 | function getRandomSong(songArtist){ 122 | poet.getSong(null, songArtist); 123 | if (document.body.addEventListener) { 124 | document.body.addEventListener('click', rimifyBinder, false); 125 | } 126 | else { 127 | document.body.attachEvent('onclick', rimifyBinder); //pour IE 128 | } 129 | } 130 | 131 | // Parse les mots et vers, vérifie le chargement des rimes et appelle le traitement des rimes 132 | function rimifyBinder(e) 133 | { 134 | e = e || window.event; 135 | var target = e.target || e.srcElement; 136 | if (target.className == "mot1") 137 | { 138 | document.body.style.cursor = "progress"; 139 | var mot = e.target.innerHTML.replace('', '').replace('', ''); 140 | var vers = e.target.parentNode.innerHTML; 141 | vers = poet.unparsePoemFromHTML(vers); 142 | mot = mot.split(/[\.,…\/#!$%\^&\*;\?:{}=\_`~()]/g)[0];// Si il y a de la ponctuation on la coupe du mot 143 | var premot; 144 | if (mot.indexOf("’") > -1) { 145 | premot = mot.split("’")[0]; 146 | mot = mot.split("’")[1]; 147 | } 148 | var capitalize = mot.charAt(0) === mot.charAt(0).toUpperCase(); 149 | mot = mot.toLowerCase(); 150 | vers = vers.toLowerCase(); 151 | var rimes, k = 0, isFem; 152 | for (var i = 0; i < poet.motsArray.length; i++) { // Vérifier si les rimes du mot ne sont pas déjà chargées 153 | if (poet.motsArray[i].rimes.indexOf(mot) > -1) { 154 | rimes = poet.motsArray[i].rimes; 155 | k = poet.motsArray[i].rimes.indexOf(mot); 156 | isFem = poet.motsArray[i].isFem; 157 | k++; 158 | if (k == rimes.length) { 159 | k = 0; 160 | } 161 | i = poet.motsArray.length; 162 | } 163 | } 164 | if (rimes === undefined) { // Si les rimes n'ont pas été chargées, on les charge et on les traite 165 | poet.rimify(mot, true, function(rimesObj) { 166 | if (rimesObj.rimes.length !== 0) { 167 | traitementRimes(k, vers, mot, rimesObj.rimes, e.target, premot, rimesObj.isFem, true, capitalize); 168 | }else{ 169 | document.body.style.cursor = "default"; 170 | poet.motsArray = poet.motsArray.concat({rime: mot, rimes: [mot], index: 0, isFem: false}); 171 | return false; 172 | } 173 | }, function(){ 174 | document.body.style.cursor = "default"; 175 | }); 176 | } else { // Sinon on les traite 177 | traitementRimes(k, vers, mot, rimes, e.target, premot, isFem, false, capitalize); 178 | } 179 | } 180 | } 181 | 182 | // Pour le mot donné, cherche la première rime appropriée, puis remplace dans le poème et actualise le tableau des rimes chargées 183 | function traitementRimes(k, vers, mot, rimes, node, premot, isFem, isNew, isCapitalized) { 184 | var index = k, position; 185 | if (premot !== undefined) { 186 | position = vers.indexOf(premot + "’" + mot); 187 | } else { 188 | position = vers.indexOf(mot); 189 | } 190 | var metrique = poet.metrify(vers), metriqueRime, versRime, premotRime; 191 | do { 192 | if (premot !== undefined) { 193 | premotRime = genrifyPremot(premot, rimes[k % rimes.length], isFem); 194 | versRime = vers.replaceBetween(position, position + (premot + mot).length + 1, premotRime + rimes[k % rimes.length]); 195 | } else { 196 | versRime = vers.replaceBetween(position, position + mot.length, rimes[k % rimes.length]); 197 | } 198 | metriqueRime = poet.metrify(versRime); 199 | if (metriqueRime.nbsyllabes[0].nb == metrique.nbsyllabes[0].nb && metriqueRime.nbsyllabes[0].max == metrique.nbsyllabes[0].max && mot != rimes[k % rimes.length]) { 200 | if (isNew) { 201 | if (rimes.indexOf(mot) < 0) { 202 | rimes = rimes.concat(mot); 203 | } 204 | poet.motsArray = poet.motsArray.concat({rime: rimes[k % rimes.length], rimes: rimes, index: k % rimes.length, isFem: isFem}); 205 | } else { 206 | for (var i = 0; i < poet.motsArray.length; i++) { 207 | if (poet.motsArray[i].rimes.indexOf(mot) > -1) { 208 | poet.motsArray[i].rime = rimes[k % rimes.length]; 209 | poet.motsArray[i].index = k % rimes.length; 210 | } 211 | } 212 | } 213 | var rime = rimes[k % rimes.length]; 214 | if (premot !== undefined) { 215 | if (vers.charAt(position - 2) == '.' || vers.charAt(position - 2) == '!' || vers.charAt(position - 2) == '?' || vers.charAt(position - 2) == '…') { 216 | premot = premot.charAt(0).toUpperCase() + premot.slice(1); 217 | } 218 | node.innerHTML = node.innerHTML.toLowerCase().replace(premot + "'", premotRime); 219 | } else if (vers.charAt(position - 2) == '.' || vers.charAt(position - 2) == '!' || vers.charAt(position - 2) == '?' || vers.charAt(position - 2) == '…') { 220 | rime = rimes[k % rimes.length].charAt(0).toUpperCase() + rimes[k % rimes.length].slice(1); 221 | } 222 | node.innerHTML = node.innerHTML.toLowerCase().replace(mot, isCapitalized ? rime.capitalizeFirstLetter() : rime); 223 | var poeme = node.parentNode.parentNode.innerHTML; 224 | poeme = poet.unparsePoemFromHTML(poeme); 225 | poet.parsePoemToHTML(poeme, node.parentNode.parentNode); 226 | k = index + rimes.length; 227 | } else { 228 | k++; 229 | } 230 | } while (k % rimes.length != index); 231 | document.body.style.cursor = "default"; 232 | return poet.motsArray; 233 | } 234 | 235 | // Adapte le premot au genre du nouveau mot qui le suit (la nouvelle rime) 236 | function genrifyPremot(premot, rime, isFem) { 237 | var elision = ['a', 'A', 'á', 'Á', 'à', 'À', 'â', 'Â', 'e', 'E', 'é', 'É', 'è', 'È', 'ê', 'Ê', 'í', 'Í', 'o', 'ó', 'O', 'Ó', 'ô', 'Ô', 'ú', 'Ú', 'i', 'I', 'u', 'U', 'ü', 'Ü', 'û', 'Û', 'ï', 'Ï', 'î', 'Î', 'h', 'H']; 238 | if (elision.indexOf(rime.charAt(0)) > -1) { 239 | return premot + "'"; 240 | } 241 | if (premot.toLowerCase() == "d") { 242 | if (isFem) { 243 | return premot + "e la "; 244 | } else { 245 | return premot + "u "; 246 | } 247 | } 248 | if (premot.toLowerCase() == "l") { 249 | if (isFem) { 250 | return premot + "a "; 251 | } else { 252 | return premot + "e "; 253 | } 254 | } 255 | if (premot.toLowerCase() == "j" || premot.toLowerCase() == "n" || premot.toLowerCase() == "m" || premot.toLowerCase() == "s") { 256 | return premot + "e "; 257 | } 258 | if (premot.toLowerCase() == "t") { 259 | return premot + "u "; 260 | } 261 | if (premot.toLowerCase() == "c") { 262 | return premot + "ela "; 263 | } 264 | return premot + "'"; 265 | } 266 | 267 | // Parse correctement un string en RegExp 268 | function escapeRegExp(str) { 269 | return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 270 | } 271 | // Replace toutes les occurrences dans un string 272 | function replaceAll(find, replace, str) { 273 | return str.replace(new RegExp(escapeRegExp(find), 'g'), replace); 274 | } 275 | 276 | // Remplace une partie d'un string dont la position est définie par les indices 277 | String.prototype.replaceBetween = function(start, end, replace) { 278 | return this.substring(0, start) + replace + this.substring(end); 279 | }; 280 | 281 | String.prototype.capitalizeFirstLetter = function() { 282 | return this.charAt(0).toUpperCase() + this.slice(1); 283 | }; 284 | -------------------------------------------------------------------------------- /exemples/Parolyma/poetify.js: -------------------------------------------------------------------------------- 1 | var poetify = function (phpDirectory){ 2 | 3 | var self = this; 4 | 5 | // Comptage et découpage d'un mot en syllabes avec les possibilités de diérèses gérées par la variable max 6 | self.syllabify = function (s) { 7 | if (s.toLowerCase() == "pays") { // Exception pour ce mot ingérable autrement 8 | return ({syllabes: ["pa", "ys"], nb: 2, max: 2}); 9 | } 10 | if (!s.trim().match(/[a-zA-Z]/g)) { 11 | return {syllabes: [], nb: 0, max: 0}; 12 | } 13 | var consonnes = ['b', 'B', 'c', 'C', 'ç', 'Ç', 'd', 'D', 'f', 'F', 'g', 'G', 'h', 'H', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'ñ', 'Ñ', 'p', 'P', 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'v', 'V', 'w', 'W', 'x', 'X', 'y', 'Y', 'z', 'Z', '-']; 14 | var voyellesFortes = ['a', 'A', 'á', 'Á', 'à', 'À', 'â', 'Â', 'e', 'E', 'é', 'É', 'è', 'È', 'ê', 'Ê', 'í', 'Í', 'o', 'ó', 'O', 'Ó', 'ô', 'Ô', 'ú', 'Ú']; 15 | var voyellesFaibles = ['i', 'I', 'u', 'U', 'ü', 'Ü', 'ï', 'Ï', 'î', 'Î', 'û', 'Û']; 16 | var voyelles = voyellesFortes.concat(voyellesFaibles, ['y', 'Y']); 17 | var nb, coupure, voy; 18 | var j = 0, max = 0; 19 | var n = s.length - 1; 20 | var i = 0; 21 | var syllabes = []; 22 | while (i <= n) { 23 | coupure = 0; // Ne coupe pas 24 | if (consonnes.indexOf(s.charAt(i)) > -1) { 25 | if (voyelles.indexOf(s.charAt(i + 1)) > -1) { 26 | if (s.toLowerCase().charAt(i) == 'y') { // diérèse possible du y utilisé comme consonne 27 | max++; 28 | } 29 | if (voyelles.indexOf(s.charAt(i - 1)) > -1) { 30 | coupure = 1; 31 | } 32 | } else if ((['s', 'S'].indexOf(s.charAt(i)) > -1) && (['n', 'N'].indexOf(s.charAt(i - 1)) > -1) && (consonnes.indexOf(s.charAt(i + 1)) > -1)) { 33 | coupure = 2; 34 | } else if ((consonnes.indexOf(s.charAt(i + 1)) > -1) && (voyelles.indexOf(s.charAt(i - 1)) > -1)) { 35 | if (['r', 'R'].indexOf(s.charAt(i + 1)) > -1) { 36 | if (['b', 'B', 'c', 'C', 'd', 'D', 'f', 'F', 'g', 'G', 'k', 'K', 'p', 'P', 'r', 'R', 't', 'T', 'v', 'V'].indexOf(s.charAt(i)) > -1) { 37 | coupure = 1; 38 | } else { 39 | coupure = 2; 40 | } 41 | } else if (['l', 'L'].indexOf(s.charAt(i + 1)) > -1) { 42 | if (['b', 'B', 'c', 'C', 'd', 'D', 'f', 'F', 'g', 'G', 'k', 'K', 'l', 'L', 'p', 'P', 't', 'T', 'v', 'V'].indexOf(s.charAt(i)) > -1) { 43 | coupure = 1; 44 | } else { 45 | coupure = 2; 46 | } 47 | } else if (['h', 'H'].indexOf(s.charAt(i + 1)) > -1) { 48 | if (['c', 'C', 's', 'S', 'p', 'P'].indexOf(s.charAt(i)) > -1) { 49 | coupure = 1; 50 | } else { 51 | coupure = 2; 52 | } 53 | } else if ((['t', 'T', 'p', 'P'].indexOf(s.charAt(i + 1)) > -1) && (['s', 'S'].indexOf(s.charAt(i + 2)) > -1)) { // pour des mots comme "verts" ou "corps" 54 | coupure = 0; 55 | } else { 56 | coupure = 2; 57 | } 58 | } 59 | } else if (voyellesFortes.indexOf(s.charAt(i)) > -1) { 60 | if ((voyellesFortes.indexOf(s.charAt(i - 1)) > -1) && 61 | (s.substring(i - 2, i).toLowerCase() != 'ge') && 62 | (s.substring(i - 1, i + 2).toLowerCase() != 'eau') && 63 | (s.substring(i - 1, i + 1).toLowerCase() != 'oe') && 64 | ((s.substring(i - 1, i + 2).toLowerCase() != 'ée') && (s.substring(i + 1, i + 2).toLowerCase() != 'ées') && (s.substring(i + 1, i + 4).toLowerCase() != 'éent'))) { 65 | coupure = 1; 66 | } 67 | } else if (voyellesFaibles.indexOf(s.charAt(i)) > -1 && (s.substring(i - 1, i + 1).toLowerCase() != 'qu') && (s.substring(i - 1, i + 1).toLowerCase() != 'gu')) { // Gestion de la diérèse éventuelle, sauf pour les cas avec "qu" / "gu" 68 | if ((voyelles.indexOf(s.charAt(i + 1)) > -1) && 69 | (consonnes.indexOf(s.charAt(i - 1)) > -1) && 70 | (consonnes.indexOf(s.charAt(i - 2)) > -1) && 71 | (s.substring(i, i + 2).toLowerCase() != 'ui')) { // diérèse obligatoire si deux consonnes avant 72 | if (s.toLowerCase().charAt(i + 1) == 'y') { // diérèse possible du y pour des mots comme "ennuyer" ou "essuyer" 73 | max++; 74 | } 75 | coupure = 2; 76 | } else if ((voyelles.indexOf(s.charAt(i + 1)) > -1)) { 77 | if (((s.substring(i + 1, i + 4).toLowerCase() != 'ent') && (s.substring(i + 1, i + 4).toLowerCase() != 'es')) || // Si terminaisons en "-aient" et en "-aie(s)" : pas de diérèse possible 78 | (s.substring(i, i + 2).toLowerCase() != 'ui')) { // Si mot comme "fruit", "bruit", "impuissant", diérèse très rare mais tolérable 79 | max++; 80 | } 81 | } 82 | } 83 | if (coupure == 1) { // Couper ici 84 | voy = s.substring(j, i); 85 | syllabes.push(voy); 86 | j = i; 87 | } else if (coupure == 2) { // Couper au caractère suivant 88 | i++; 89 | voy = s.substring(j, i); 90 | syllabes.push(voy); 91 | j = i; 92 | } 93 | i++; 94 | } 95 | nb = syllabes.length; 96 | if ((j == n) && (nb > 0) && (consonnes.indexOf(s.charAt(n)) > -1)) { //Dernière lettre 97 | syllabes[nb - 1] = syllabes[nb - 1] + s.charAt(n); 98 | } else { 99 | voy = s.substring(j, n + 1); 100 | syllabes.push(voy); // Dernière syllabe 101 | nb++; 102 | } 103 | return {syllabes: syllabes, nb: nb, max: nb + max}; 104 | }; 105 | 106 | // Prend un tableau de mots en entrée. Pour chaque mot dans le tableau (vers), applique syllabify avec les règles d'élision du e 107 | self.elisioner = function (mots) { 108 | var voyelles = ['a', 'A', 'á', 'Á', 'à', 'À', 'â', 'Â', 'e', 'E', 'é', 'É', 'è', 'È', 'ê', 'Ê', 'í', 'Í', 'o', 'ó', 'O', 'Ó', 'ô', 'Ô', 'ú', 'Ú', 'i', 'I', 'u', 'U', 'ü', 'Ü', 'û', 'Û', 'ï', 'Ï', 'î', 'Î']; 109 | var elision = voyelles.concat(['h', 'H']); 110 | var syllabes, nb = 0, max = 0; 111 | 112 | for (var i = 0; i < mots.length; i++) { 113 | syllabes = self.syllabify(mots[i]); 114 | nb += syllabes.nb; 115 | max += syllabes.max; 116 | if ((i > 0) && 117 | (mots[i - 1].toLowerCase().slice(-1) == 'e') && 118 | (elision.indexOf(mots[i].charAt(0)) > -1) && 119 | (self.sansAccents(mots[i - 1].toLowerCase().slice(-2, -1)) != self.sansAccents(mots[i].charAt(0)))) { // élision du e de fin dans le mot précédent si liaison (MAIS élision interdite si même son, ex: "Thésée excusable") 120 | nb--; 121 | if (['h', 'H'].indexOf(mots[i].charAt(0)) < 0) { 122 | max--; 123 | } 124 | } 125 | if ((i == mots.length - 1) && 126 | (mots[i].toLowerCase().slice(-1) == 'e' || mots[i].toLowerCase().slice(-2) == 'es' || mots[i].toLowerCase().slice(-3) == 'ent')) { // élision du e en fin de vers 127 | nb--; 128 | if (!((voyelles.indexOf(mots[i].toLowerCase().slice(-2, -1)) > -1) && (mots[i].toLowerCase().slice(-1) == 'e')) && // Si finit par une voyelle + "e" : l'élision peut-être évitée en appuyant le e (ex: "patrie") 129 | !((voyelles.indexOf(mots[i].toLowerCase().slice(-3, -2)) > -1) && (mots[i].toLowerCase().slice(-2) == 'es')) && 130 | !((voyelles.indexOf(mots[i].toLowerCase().slice(-4, -3)) > -1) && (mots[i].toLowerCase().slice(-3) == 'ent')) && 131 | (mots[i].toLowerCase().slice(-4) != 'ment')) { // Si c'est un adverbe, la syllabe finale est obligatoire donc on ne diminue pas max pour prévenir ces cas 132 | max--; 133 | } 134 | } 135 | } 136 | return {nb: nb, max: max}; 137 | }; 138 | 139 | // Compte le nombre de syllabes des vers d'un poème en suivant les règles classiques d'élision 140 | self.metrify = function (s) { 141 | s = s.replace(/[\.,…\/#!$%\^&\*;\?:{}=\_`~()]/g, "").replace(/[0-9]/g, '').replace(/\s{2,}/g, " ").replace(/œ/g, "oe").replace(/æ/g, "ae").replace(/\r\n|\r|\n/g, "
"); 142 | var vers = s.split("
"); 143 | vers = vers.filter(function(v) { 144 | return v !== ''; 145 | }); 146 | var mots = []; 147 | var nbsyllabes = []; 148 | 149 | for (var i = 0; i < vers.length; i++) { 150 | var lesmots = vers[i].split(" "); 151 | lesmots = lesmots.filter(function(v) { 152 | return v !== ''; 153 | }); 154 | mots[i] = lesmots; // range les mots dans un tableau différent pour chaque vers 155 | } 156 | 157 | // Appliquer elisioner au tableau de mots de chaque vers 158 | for (var k = 0; k < mots.length; k++) { 159 | nbsyllabes[k] = self.elisioner(mots[k]); 160 | } 161 | 162 | return {vers: vers, mots: mots, nbsyllabes: nbsyllabes}; 163 | }; 164 | 165 | // Récupère les rimes d'un mot ayant le même nombre de syllabes et la même nature (Verbe, nom, adjectif...) 166 | self.rimify = function (s, addWord, success, error) { 167 | var syllabes = self.syllabify(s); 168 | self.getRimesQuery(s, function(data) { 169 | if(addWord) 170 | data.rimes.push(s); 171 | this.success = success || function(data) { 172 | console.log(data); 173 | return data; 174 | }; 175 | this.success(data); 176 | }, error); 177 | }; 178 | 179 | // Récupère les rimes d'un mot à l'aide de ses propriétés et exécute le callback avec le tableau de rimes obtenu si besoin 180 | self.getRimesQuery = function (word, success, error) { 181 | self.ajaxRequest('POST', 'getRimes.php', 'word=' + word, function(data) { 182 | data = JSON.parse(data); 183 | data.isFem = data.isFem == "1"; 184 | this.success = success || function(data) { 185 | console.log(data); 186 | }; 187 | this.success(data); 188 | }, function () { 189 | this.error = error || function() { 190 | console.log("An error happened in getRimesQuery"); 191 | }; 192 | this.error(); 193 | }); 194 | }; 195 | 196 | 197 | // Get Poem from Wikisource 198 | self.getPoem = function (poemUrl) { 199 | var poemDIV = document.getElementById("poem"), request; 200 | if (poemUrl.indexOf("wikisource.org/wiki/") < 0) { 201 | poemDIV.innerHTML = "
"; 202 | document.getElementById("meta").innerHTML = "Veuillez entrer une adresse Wikisource valide.
"; 203 | } else { 204 | document.body.style.cursor = "wait"; 205 | self.ajaxRequest('POST', 'getPoem.php', "poemUrl=" + poemUrl, function(data) { 206 | document.body.style.cursor = "default"; 207 | data = data.replace(/Warning([^;]*){/, '{'); 208 | if (data == "Erreur") { 209 | poemDIV.innerHTML = "
"; 210 | document.getElementById("meta").innerHTML = "Erreur lors de la récupération du poème. Réessayer.
"; 211 | } else { 212 | data = JSON.parse(data); 213 | data.poeme = data.poeme.replace(/###/g, '\n'); 214 | data.poeme = data.poeme.replace(/\[[^;]*]/g, ""); 215 | data.poeme = data.poeme.replace("'", "’"); 216 | data.titre = data.titre.replace(/\//g, " - "); 217 | self.parsePoemToHTML(data.poeme, poemDIV); 218 | document.getElementById("meta").innerHTML = '

' + data.titre + '

de ' + data.auteur + ''; 219 | } 220 | }, function () { 221 | poemDIV.innerHTML = "
"; 222 | document.getElementById("meta").innerHTML = "Erreur lors de la récupération du poème. Réessayer.
"; 223 | }); 224 | } 225 | }; 226 | 227 | // Parse la nature de la rime et compare à celle du mot 228 | self.natureEquals = function (natureRime, nature) { 229 | for (var i = 0; i < natureRime.length; i++) { 230 | if (nature.indexOf(natureRime[i]) > -1) { 231 | return true; 232 | } 233 | } 234 | return false; 235 | }; 236 | 237 | self.sansAccents = function (s) { 238 | var r = s.toLowerCase(); 239 | r = r.replace(/[àáâãäå]/g, "a"); 240 | r = r.replace(/[èéêë]/g, "e"); 241 | r = r.replace(/[ìíîï]/g, "i"); 242 | r = r.replace(/[òóôõö]/g, "o"); 243 | r = r.replace(/[ùúûü]/g, "u"); 244 | r = r.replace(/[ýÿ]/g, "y"); 245 | return r; 246 | }; 247 | 248 | self.ajaxRequest = function (method, file, sendContent, success, error){ 249 | var request = new XMLHttpRequest(); 250 | request.open(method, phpDirectory + file, true); 251 | request.onreadystatechange = function() { 252 | if (this.readyState === 4) { 253 | if (this.status >= 200 && this.status < 400) { 254 | try{ 255 | var data = this.responseText; 256 | if(data.length !== 0){ 257 | this.success = success || function(data) { 258 | console.log(data); 259 | }; 260 | this.success(data); 261 | }else{ 262 | console.log("No data returned"); 263 | } 264 | }catch(e){ 265 | console.log(e); 266 | console.log("Error in returned data handling"); 267 | } 268 | }else{ 269 | this.error = error || function() { 270 | console.log(this); 271 | }; 272 | this.error(this); 273 | } 274 | } 275 | }; 276 | request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 277 | request.send(sendContent); 278 | request = null; 279 | }; 280 | 281 | self.parsePoemToHTML = function (poeme, poemDIV) { 282 | var poem = ''; 283 | poeme.split(/\r\n|\r|\n/g).forEach(function(vers) { 284 | vers = vers.charAt(0).toUpperCase() + vers.slice(1); 285 | poem += vers + '\n'; 286 | }); 287 | poem = poem.slice(0, -1); 288 | poem = poem.replace(/[^\S\n]/g, '
'); 289 | poem = poem.replace(/\r\n|\r|\n/g, '

'); 290 | poem = '' + poem + ''; 291 | poemDIV.innerHTML = poem; 292 | poemDIV.innerHTML = poemDIV.innerHTML.replace(new RegExp(escapeRegExp(''), 'g'), ""); 293 | }; 294 | 295 | self.unparsePoemFromHTML = function(poeme) { 296 | poeme = replaceAll('', '', poeme); 297 | poeme = replaceAll('', '', poeme); 298 | poeme = replaceAll('
', '\n', poeme); 299 | poeme = replaceAll('', '', poeme); 300 | return poeme; 301 | }; 302 | 303 | return self; 304 | }; 305 | -------------------------------------------------------------------------------- /getPoem.php: -------------------------------------------------------------------------------- 1 | 7 |
', '###', $poemHTML); 8 | $classPoem = 'poem'; 9 | $classPoemVerse = 'poem verse'; 10 | $idTitle = 'firstHeading'; 11 | $idAuthor = 'ws-author'; 12 | $classAuthor = 'headertemplate-author'; 13 | $dom = new DOMDocument; 14 | $poemHTML = mb_convert_encoding($poemHTML, 'HTML-ENTITIES', "UTF-8"); 15 | @$dom->loadHTML($poemHTML); 16 | $xpath = new DOMXPath($dom); 17 | $poemdivs = $xpath->query("//*[@class='" . $classPoem . "']"); 18 | $poemversedivs = $xpath->query("//*[@class='" . $classPoemVerse . "']"); 19 | $title = $xpath->query("//*[@id='" . $idTitle . "']"); 20 | $authorWS = $xpath->query("//*[@id='" . $idAuthor . "']"); 21 | $author = $xpath->query("//*[@class='" . $classAuthor . "']"); 22 | if ($authorWS->length > 0) { 23 | $author = $authorWS->item(0)->nodeValue; 24 | } else if ($author->length > 0) { 25 | $author = $author->item(0)->nodeValue; 26 | } else { 27 | $author = "Auteur non récupéré"; 28 | } 29 | if ($poemdivs->length > 0) { 30 | for ($i = 0; $i < $poemdivs->length; $i++) { 31 | $poem = $poem . $poemdivs->item($i)->nodeValue; 32 | } 33 | } else if ($poemversedivs->length > 0) { 34 | for ($i = 0; $i < $poemversedivs->length; $i++) { 35 | $poem = $poem . $poemversedivs->item($i)->nodeValue; 36 | } 37 | } 38 | if (isset($poem) && $title->length > 0 && isset($author)) { 39 | $arr = array('url' => $poemUrl, 'titre' => $title->item(0)->nodeValue, 'auteur' => $author, 'poeme' => $poem); 40 | echo json_encode($arr); 41 | } else { 42 | echo "Erreur"; 43 | } 44 | } 45 | ?> -------------------------------------------------------------------------------- /getRimes.php: -------------------------------------------------------------------------------- 1 | PDO::ERRMODE_WARNING)); 13 | $bdd->exec("SET CHARACTER SET utf8"); 14 | } catch (PDOException $e) { 15 | echo 'Echec de la connexion : ' . $e->getMessage(); 16 | exit; 17 | } 18 | 19 | $response = $bdd->query("SELECT * FROM words WHERE word = '".$word."' ORDER BY freq DESC"); 20 | $words = $response->fetchAll(); 21 | $response->closeCursor(); 22 | 23 | if(count($words) == 0){ 24 | echo json_encode(array("rimes" => array())); 25 | exit; 26 | } 27 | 28 | $wordProp = $words[0]; 29 | 30 | function getWord($rime) 31 | { 32 | return($rime['word']); 33 | } 34 | 35 | $lastChar = substr($word, -1); 36 | 37 | $checkWordEnding = ''; 38 | $origines = explode(',', $wordProp['orig']); 39 | $origineQuery = ''; 40 | foreach ($origines as $key => $origine) { 41 | $parts = explode('|', $origine); 42 | if($key != 0) 43 | $origineQuery .= ' OR '; 44 | $origineQuery .= "(orig LIKE BINARY '%". $parts[0] ."%')"; 45 | if($parts[0] == "VER" || ($parts[0] == "NOM" && ($lastChar == "s" || $lastChar == "x"))) 46 | $checkWordEnding = " AND (word_end = '" . $wordProp['word_end'] . "')"; 47 | } 48 | 49 | // Uncomment end of query with RAND() and LIMIT to improve Panoryma example with more diverse rimes and better performance 50 | $response = $bdd->query("SELECT * FROM words WHERE (phon_end = '" . $wordProp['phon_end'] . "') ". $checkWordEnding ." AND (".$origineQuery.") AND ((max_nsyl >= '" . $wordProp['min_nsyl'] . "') AND (min_nsyl <= '" . $wordProp['max_nsyl'] . "' OR (elidable AND min_nsyl - 1 <= '" . $wordProp['max_nsyl'] . "' AND '" . $wordProp['elidable'] . "'))) /*ORDER BY RAND() LIMIT 1000*/"); 51 | $result = $response->fetchAll(); 52 | $response->closeCursor(); 53 | 54 | $result = array_map("getWord", $result); 55 | 56 | echo json_encode(array("rimes" => $result, "isFem" => $wordProp['feminine'])); 57 | ?> 58 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PoetifyJS - GetPoem 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 | 14 | 15 |
16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /poetify.js: -------------------------------------------------------------------------------- 1 | var poetify = function (phpDirectory){ 2 | 3 | var self = this; 4 | 5 | // Comptage et découpage d'un mot en syllabes avec les possibilités de diérèses gérées par la variable max 6 | self.syllabify = function (s) { 7 | if (s.toLowerCase() == "pays") { // Exception pour ce mot ingérable autrement 8 | return ({syllabes: ["pa", "ys"], nb: 2, max: 2}); 9 | } 10 | if (!s.trim().match(/[a-zA-Z]/g)) { 11 | return {syllabes: [], nb: 0, max: 0}; 12 | } 13 | var consonnes = ['b', 'B', 'c', 'C', 'ç', 'Ç', 'd', 'D', 'f', 'F', 'g', 'G', 'h', 'H', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'ñ', 'Ñ', 'p', 'P', 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'v', 'V', 'w', 'W', 'x', 'X', 'y', 'Y', 'z', 'Z', '-']; 14 | var voyellesFortes = ['a', 'A', 'á', 'Á', 'à', 'À', 'â', 'Â', 'e', 'E', 'é', 'É', 'è', 'È', 'ê', 'Ê', 'í', 'Í', 'o', 'ó', 'O', 'Ó', 'ô', 'Ô', 'ú', 'Ú']; 15 | var voyellesFaibles = ['i', 'I', 'u', 'U', 'ü', 'Ü', 'ï', 'Ï', 'î', 'Î', 'û', 'Û']; 16 | var voyelles = voyellesFortes.concat(voyellesFaibles, ['y', 'Y']); 17 | var nb, coupure, voy; 18 | var j = 0, max = 0; 19 | var n = s.length - 1; 20 | var i = 0; 21 | var syllabes = []; 22 | while (i <= n) { 23 | coupure = 0; // Ne coupe pas 24 | if (consonnes.indexOf(s.charAt(i)) > -1) { 25 | if (voyelles.indexOf(s.charAt(i + 1)) > -1) { 26 | if (s.toLowerCase().charAt(i) == 'y') { // diérèse possible du y utilisé comme consonne 27 | max++; 28 | } 29 | if (voyelles.indexOf(s.charAt(i - 1)) > -1) { 30 | coupure = 1; 31 | } 32 | } else if ((['s', 'S'].indexOf(s.charAt(i)) > -1) && (['n', 'N'].indexOf(s.charAt(i - 1)) > -1) && (consonnes.indexOf(s.charAt(i + 1)) > -1)) { 33 | coupure = 2; 34 | } else if ((consonnes.indexOf(s.charAt(i + 1)) > -1) && (voyelles.indexOf(s.charAt(i - 1)) > -1)) { 35 | if (['r', 'R'].indexOf(s.charAt(i + 1)) > -1) { 36 | if (['b', 'B', 'c', 'C', 'd', 'D', 'f', 'F', 'g', 'G', 'k', 'K', 'p', 'P', 'r', 'R', 't', 'T', 'v', 'V'].indexOf(s.charAt(i)) > -1) { 37 | coupure = 1; 38 | } else { 39 | coupure = 2; 40 | } 41 | } else if (['l', 'L'].indexOf(s.charAt(i + 1)) > -1) { 42 | if (['b', 'B', 'c', 'C', 'd', 'D', 'f', 'F', 'g', 'G', 'k', 'K', 'l', 'L', 'p', 'P', 't', 'T', 'v', 'V'].indexOf(s.charAt(i)) > -1) { 43 | coupure = 1; 44 | } else { 45 | coupure = 2; 46 | } 47 | } else if (['h', 'H'].indexOf(s.charAt(i + 1)) > -1) { 48 | if (['c', 'C', 's', 'S', 'p', 'P'].indexOf(s.charAt(i)) > -1) { 49 | coupure = 1; 50 | } else { 51 | coupure = 2; 52 | } 53 | } else if ((['t', 'T', 'p', 'P'].indexOf(s.charAt(i + 1)) > -1) && (['s', 'S'].indexOf(s.charAt(i + 2)) > -1)) { // pour des mots comme "verts" ou "corps" 54 | coupure = 0; 55 | } else { 56 | coupure = 2; 57 | } 58 | } 59 | } else if (voyellesFortes.indexOf(s.charAt(i)) > -1) { 60 | if ((voyellesFortes.indexOf(s.charAt(i - 1)) > -1) && 61 | (s.substring(i - 2, i).toLowerCase() != 'ge') && 62 | (s.substring(i - 1, i + 2).toLowerCase() != 'eau') && 63 | (s.substring(i - 1, i + 1).toLowerCase() != 'oe') && 64 | ((s.substring(i - 1, i + 2).toLowerCase() != 'ée') && (s.substring(i + 1, i + 2).toLowerCase() != 'ées') && (s.substring(i + 1, i + 4).toLowerCase() != 'éent'))) { 65 | coupure = 1; 66 | } 67 | } else if (voyellesFaibles.indexOf(s.charAt(i)) > -1 && (s.substring(i - 1, i + 1).toLowerCase() != 'qu') && (s.substring(i - 1, i + 1).toLowerCase() != 'gu')) { // Gestion de la diérèse éventuelle, sauf pour les cas avec "qu" / "gu" 68 | if ((voyelles.indexOf(s.charAt(i + 1)) > -1) && 69 | (consonnes.indexOf(s.charAt(i - 1)) > -1) && 70 | (consonnes.indexOf(s.charAt(i - 2)) > -1) && 71 | (s.substring(i, i + 2).toLowerCase() != 'ui')) { // diérèse obligatoire si deux consonnes avant 72 | if (s.toLowerCase().charAt(i + 1) == 'y') { // diérèse possible du y pour des mots comme "ennuyer" ou "essuyer" 73 | max++; 74 | } 75 | coupure = 2; 76 | } else if ((voyelles.indexOf(s.charAt(i + 1)) > -1)) { 77 | if (((s.substring(i + 1, i + 4).toLowerCase() != 'ent') && (s.substring(i + 1, i + 4).toLowerCase() != 'es')) || // Si terminaisons en "-aient" et en "-aie(s)" : pas de diérèse possible 78 | (s.substring(i, i + 2).toLowerCase() != 'ui')) { // Si mot comme "fruit", "bruit", "impuissant", diérèse très rare mais tolérable 79 | max++; 80 | } 81 | } 82 | } 83 | if (coupure == 1) { // Couper ici 84 | voy = s.substring(j, i); 85 | syllabes.push(voy); 86 | j = i; 87 | } else if (coupure == 2) { // Couper au caractère suivant 88 | i++; 89 | voy = s.substring(j, i); 90 | syllabes.push(voy); 91 | j = i; 92 | } 93 | i++; 94 | } 95 | nb = syllabes.length; 96 | if ((j == n) && (nb > 0) && (consonnes.indexOf(s.charAt(n)) > -1)) { //Dernière lettre 97 | syllabes[nb - 1] = syllabes[nb - 1] + s.charAt(n); 98 | } else { 99 | voy = s.substring(j, n + 1); 100 | syllabes.push(voy); // Dernière syllabe 101 | nb++; 102 | } 103 | return {syllabes: syllabes, nb: nb, max: nb + max}; 104 | }; 105 | 106 | // Prend un tableau de mots en entrée. Pour chaque mot dans le tableau (vers), applique syllabify avec les règles d'élision du e 107 | self.elisioner = function (mots) { 108 | var voyelles = ['a', 'A', 'á', 'Á', 'à', 'À', 'â', 'Â', 'e', 'E', 'é', 'É', 'è', 'È', 'ê', 'Ê', 'í', 'Í', 'o', 'ó', 'O', 'Ó', 'ô', 'Ô', 'ú', 'Ú', 'i', 'I', 'u', 'U', 'ü', 'Ü', 'û', 'Û', 'ï', 'Ï', 'î', 'Î']; 109 | var elision = voyelles.concat(['h', 'H']); 110 | var syllabes, nb = 0, max = 0; 111 | 112 | for (var i = 0; i < mots.length; i++) { 113 | syllabes = self.syllabify(mots[i]); 114 | nb += syllabes.nb; 115 | max += syllabes.max; 116 | if ((i > 0) && 117 | (mots[i - 1].toLowerCase().slice(-1) == 'e') && 118 | (elision.indexOf(mots[i].charAt(0)) > -1) && 119 | (self.sansAccents(mots[i - 1].toLowerCase().slice(-2, -1)) != self.sansAccents(mots[i].charAt(0)))) { // élision du e de fin dans le mot précédent si liaison (MAIS élision interdite si même son, ex: "Thésée excusable") 120 | nb--; 121 | if (['h', 'H'].indexOf(mots[i].charAt(0)) < 0) { 122 | max--; 123 | } 124 | } 125 | if ((i == mots.length - 1) && 126 | (mots[i].toLowerCase().slice(-1) == 'e' || mots[i].toLowerCase().slice(-2) == 'es' || mots[i].toLowerCase().slice(-3) == 'ent')) { // élision du e en fin de vers 127 | nb--; 128 | if (!((voyelles.indexOf(mots[i].toLowerCase().slice(-2, -1)) > -1) && (mots[i].toLowerCase().slice(-1) == 'e')) && // Si finit par une voyelle + "e" : l'élision peut-être évitée en appuyant le e (ex: "patrie") 129 | !((voyelles.indexOf(mots[i].toLowerCase().slice(-3, -2)) > -1) && (mots[i].toLowerCase().slice(-2) == 'es')) && 130 | !((voyelles.indexOf(mots[i].toLowerCase().slice(-4, -3)) > -1) && (mots[i].toLowerCase().slice(-3) == 'ent')) && 131 | (mots[i].toLowerCase().slice(-4) != 'ment')) { // Si c'est un adverbe, la syllabe finale est obligatoire donc on ne diminue pas max pour prévenir ces cas 132 | max--; 133 | } 134 | } 135 | } 136 | return {nb: nb, max: max}; 137 | }; 138 | 139 | // Compte le nombre de syllabes des vers d'un poème en suivant les règles classiques d'élision 140 | self.metrify = function (s) { 141 | s = s.replace(/[\.,…\/#!$%\^&\*;\?:{}=\_`~()]/g, "").replace(/[0-9]/g, '').replace(/\s{2,}/g, " ").replace(/œ/g, "oe").replace(/æ/g, "ae").replace(/\r\n|\r|\n/g, "
"); 142 | var vers = s.split("
"); 143 | vers = vers.filter(function(v) { 144 | return v !== ''; 145 | }); 146 | var mots = []; 147 | var nbsyllabes = []; 148 | 149 | for (var i = 0; i < vers.length; i++) { 150 | var lesmots = vers[i].split(" "); 151 | lesmots = lesmots.filter(function(v) { 152 | return v !== ''; 153 | }); 154 | mots[i] = lesmots; // range les mots dans un tableau différent pour chaque vers 155 | } 156 | 157 | // Appliquer elisioner au tableau de mots de chaque vers 158 | for (var k = 0; k < mots.length; k++) { 159 | nbsyllabes[k] = self.elisioner(mots[k]); 160 | } 161 | 162 | return {vers: vers, mots: mots, nbsyllabes: nbsyllabes}; 163 | }; 164 | 165 | // Récupère les rimes d'un mot ayant le même nombre de syllabes et la même nature (Verbe, nom, adjectif...) 166 | self.rimify = function (s, addWord, success, error) { 167 | var syllabes = self.syllabify(s); 168 | self.getRimesQuery(s, function(data) { 169 | if(addWord) 170 | data.rimes.push(s); 171 | this.success = success || function(data) { 172 | console.log(data); 173 | return data; 174 | }; 175 | this.success(data); 176 | }, error); 177 | }; 178 | 179 | // Récupère les rimes d'un mot à l'aide de ses propriétés et exécute le callback avec le tableau de rimes obtenu si besoin 180 | self.getRimesQuery = function (word, success, error) { 181 | self.ajaxRequest('POST', 'getRimes.php', 'word=' + word, function(data) { 182 | data = JSON.parse(data); 183 | data.isFem = data.isFem == "1"; 184 | this.success = success || function(data) { 185 | console.log(data); 186 | }; 187 | this.success(data); 188 | }, function () { 189 | this.error = error || function() { 190 | console.log("An error happened in getRimesQuery"); 191 | }; 192 | this.error(); 193 | }); 194 | }; 195 | 196 | 197 | // Get Poem from Wikisource 198 | self.getPoem = function (poemUrl) { 199 | var poemDIV = document.getElementById("poem"), request; 200 | if (poemUrl.indexOf("wikisource.org/wiki/") < 0) { 201 | poemDIV.innerHTML = "
"; 202 | document.getElementById("meta").innerHTML = "Veuillez entrer une adresse Wikisource valide.
"; 203 | } else { 204 | document.body.style.cursor = "wait"; 205 | self.ajaxRequest('POST', 'getPoem.php', "poemUrl=" + poemUrl, function(data) { 206 | document.body.style.cursor = "default"; 207 | data = data.replace(/Warning([^;]*){/, '{'); 208 | if (data == "Erreur") { 209 | poemDIV.innerHTML = "
"; 210 | document.getElementById("meta").innerHTML = "Erreur lors de la récupération du poème. Réessayer.
"; 211 | } else { 212 | data = JSON.parse(data); 213 | data.poeme = data.poeme.replace(/###/g, '\n'); 214 | data.poeme = data.poeme.replace(/\[[^;]*]/g, ""); 215 | data.poeme = data.poeme.replace("'", "’"); 216 | data.titre = data.titre.replace(/\//g, " - "); 217 | self.parsePoemToHTML(data.poeme, poemDIV); 218 | document.getElementById("meta").innerHTML = '

' + data.titre + '

de ' + data.auteur + ''; 219 | } 220 | }, function () { 221 | poemDIV.innerHTML = "
"; 222 | document.getElementById("meta").innerHTML = "Erreur lors de la récupération du poème. Réessayer.
"; 223 | }); 224 | } 225 | }; 226 | 227 | // Parse la nature de la rime et compare à celle du mot 228 | self.natureEquals = function (natureRime, nature) { 229 | for (var i = 0; i < natureRime.length; i++) { 230 | if (nature.indexOf(natureRime[i]) > -1) { 231 | return true; 232 | } 233 | } 234 | return false; 235 | }; 236 | 237 | self.sansAccents = function (s) { 238 | var r = s.toLowerCase(); 239 | r = r.replace(/[àáâãäå]/g, "a"); 240 | r = r.replace(/[èéêë]/g, "e"); 241 | r = r.replace(/[ìíîï]/g, "i"); 242 | r = r.replace(/[òóôõö]/g, "o"); 243 | r = r.replace(/[ùúûü]/g, "u"); 244 | r = r.replace(/[ýÿ]/g, "y"); 245 | return r; 246 | }; 247 | 248 | self.ajaxRequest = function (method, file, sendContent, success, error){ 249 | var request = new XMLHttpRequest(); 250 | request.open(method, phpDirectory + file, true); 251 | request.onreadystatechange = function() { 252 | if (this.readyState === 4) { 253 | if (this.status >= 200 && this.status < 400) { 254 | try{ 255 | var data = this.responseText; 256 | if(data.length !== 0){ 257 | this.success = success || function(data) { 258 | console.log(data); 259 | }; 260 | this.success(data); 261 | }else{ 262 | console.log("No data returned"); 263 | } 264 | }catch(e){ 265 | console.log(e); 266 | console.log("Error in returned data handling"); 267 | } 268 | }else{ 269 | this.error = error || function() { 270 | console.log(this); 271 | }; 272 | this.error(this); 273 | } 274 | } 275 | }; 276 | request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 277 | request.send(sendContent); 278 | request = null; 279 | }; 280 | 281 | self.parsePoemToHTML = function (poeme, poemDIV) { 282 | var poem = ''; 283 | poeme.split(/\r\n|\r|\n/g).forEach(function(vers) { 284 | vers = vers.charAt(0).toUpperCase() + vers.slice(1); 285 | poem += vers + '\n'; 286 | }); 287 | poem = poem.slice(0, -1); 288 | poem = poem.replace(/[^\S\n]/g, '
'); 289 | poem = poem.replace(/\r\n|\r|\n/g, '

'); 290 | poem = '' + poem + ''; 291 | poemDIV.innerHTML = poem; 292 | poemDIV.innerHTML = poemDIV.innerHTML.replace(new RegExp(escapeRegExp(''), 'g'), ""); 293 | }; 294 | 295 | self.unparsePoemFromHTML = function(poeme) { 296 | poeme = replaceAll('', '', poeme); 297 | poeme = replaceAll('', '', poeme); 298 | poeme = replaceAll('
', '\n', poeme); 299 | poeme = replaceAll('', '', poeme); 300 | return poeme; 301 | }; 302 | 303 | return self; 304 | }; 305 | --------------------------------------------------------------------------------