├── .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 |
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 = '