Javascript: tester la validité des liens d'une page afin de les styler

Petit bout de code fait à la va-vite dans le but de vérifier la validité des liens d'une page. Mon objectif est de pouvoir à terme montrer automatiquement les liens ne répondant plus sur la page où je regroupe les liens de téléchargement illégal

Le bout de code actuel

Dans le code ci-dessous, j'utilise fetch et les promesses pour lancer des requêtes afin de styler les liens testés:

function checkLinks(nodelist){
    function checkUrl(link){
        return fetch(link).then(function(response){     
            return response.status;
        }).catch(function(error){
            return error.status;
        });
    }
    if (!nodelist){
        checkLinks(document.querySelectorAll('.checkLink'));
        return;
    }
    for (let obj of nodelist){
        if (obj.tagName=="A"){
            checkUrl(obj.href).then(function(response){obj.classList.add("status"+response);});
        }else if (obj.hasAttribute("src")){
            checkUrl(obj.src).then(function(response){obj.classList.add("status"+response);});
        }else{
            checkLinks(obj.querySelectorAll("*[href],*[src]"));
        }
    }
}
checkLinks();

Explication rapide

Étape 1

J'ai d'abord fait une fonction qui appelle une URL et renvoie une promesse qui, une fois résolue, renverra le statut de la requête. On y retrouve .then qui renvoie le statut d'une requête qui aboutit et .catch qui renvoie celui d'une requête se soldant par une erreur.

function checkUrl(link){
        return fetch(link).then(function(response){     
            return response.status;
        }).catch(function(error){
            return error.status;
        });
    }

Les plus coquinous d'entre-vous me feront remarquer à juste titre que, vu ce que je renvoie, je pouvais me contenter de

function checkUrl(link){
        return fetch(link).then(function(response){     
            return response.status;
        });
    }

Ceci dit, en prévoyant les deux cas, je m'autorise à gérer le retour différemment selon si ça aboutit ou pas (par exemple retourner «ok200» ou «error404»

Étape 2:

Ce block n'est là que pour simplifier la vie de l'utilisateur en lui évitant de procéder lui-même au querySelectorAll()

if (!nodelist){
        checkLinks(document.querySelectorAll('.checkLink'));
        return;
    }

Étape 3:

Je parcours la nodeList en vérifiant l'URL passée en href (pour les A) ou en src (pour les img par exemple).

Le dernier cas est celui où l'on souhaite vérifier les liens contenus dans un div portant la classe .checkLink : il suffit d'appeler la même fonction de façon récursive en lui fournissant le nodeList des liens contenus das le DIV en question. (ça permet de vérifier un grand nombre de liens sans avoir à leur ajouter individuellement la classe .checkLink, ce qui est particulièrement utile quand on publie des articles en utilisant markdown )

for (let obj of nodelist){
        if (obj.tagName=="A"){
            checkUrl(obj.href).then(function(response){obj.classList.add("status"+response);});
        }else if (obj.hasAttribute("src")){
            checkUrl(obj.src).then(function(response){obj.classList.add("status"+response);});
        }else{
            checkLinks(obj.querySelectorAll("a,img"));
        }
    }

Comment on l'utilise ?

Il suffit de mettre la classe .checkLink à tout objet dont on veut tester les liens et de coller la fonction dans la page puis de l'appeler via un checkLinks(); de bon aloi.

En l'état, la fonction ajoutera une classe .status200 pour les liens ok ou .status404 pour les URL qui ne répondent plus.

Il ne reste plus qu'à styler ces classes en changeant la couleur, le fond ou en ajoutant des emoji avec un petit content. On peut même éventuellement masquer un objet dont l'URL ne répond pas...

Limites

Le script étant en JS, il se heurte évidemment aux règles de la politique CORS: toute requête hors du domaine en cours va échouer à moins de redéfinir le CORS dans le Head de la page via

<meta http-equiv="Content-Security-Policy" content="Content-Security-Policy:..."/>

Licence

Comme d'habitude, il s'agit autant d'un proof of concept que d'une truc utile... en tout cas, n'hésitez pas à en faire rigoureusement ce que vous voulez: c'est cadeau...

API + BOT = RTE_color_bot (@RTE_color@piaille.fr)

Parfois, un post en entraîne un autre... Ainsi, tu t'es mis à coder un BOT presque par inadvertance - avec les difficultés qu'on connaît - et tu le partages parce qu'il n'y a pas de raison que l'auteur soit le seul à pleurer... pis t'as un copain qui te lit et qui prend le truc au sérieux... en tout cas suffisamment pour te proposer d'en faire un autre !

Non, c'est vrai ?!    T'AS TROUVÉ ÇA BIEN ?!

Donc, me v'la reparti pour un tour...

Objectif de la demande: récupérer les données de l'API RTE tempo ( https://data.rte-france.com/catalog/-/api/consumption/Tempo-Like-Supply-Contract/v1.1 ) pour dire la couleur du jour et celle du lendemain et les poster sur un bot mastodon (mais pouvoir appeler le script comme une API aussi)

Je suis donc parti pour tester ladite API: pour la faire courte, ça m'a permis - après les galères d'usage - de comprendre comment tout ça fonctionnait (en particulier la demande d'un token, l'appel d'une api en php etc)

J'en suis arrivé à un script qui produit un texte donnant la couleur du jour et celle du lendemain.

«Oui, mais ce serait cool...»

Le texte c'est bien, mais ce serait mieux si on pouvait récup les données en HTML et intégrer ça avec une Iframe, comme un code d'intégration.

Pis éventuellement en RSS aussi...

Bon, tant que j'y étais, j'ai aussi fait un mode json, au cas où on voudrait ça dans un frontend à soi...

Du coup, mon API s'appelle de plusieurs façons différentes:

  • URL seule ➜ retour en texte RAW (prêt à poster)
  • URL?html ➜ retourne le code HTML
  • URL?json ➜ renvoie les données en JSON
  • URL?rss ➜ le flux RSS de l'API
  • (cadeau bonux) URL?embed_code ➜ retourne le code pour mettre ça sur son site avec une iframe.

Pour faire bonne mesure

Le script produit un fichier pour chaque type de retour et ne le régénère qu'une fois par jour afin d'éviter de se faire «hammerer» comme dit @parigotmanchot

Jusque là, tout va à peu près dans un monde couci, couça

À ce stade, le script fonctionne même si le code est un peu sale et pas bien rangé... il fait ce qu'on lui demande. A part que parfois, il ne donne pas la couleur du lendemain... mais pas en local... juste en distant. Je n'ai pas encore vraiment cherché pourquoi, mais je pense que c'est dû au moment où l'on appelle l'API de RTE.

Pourquoi s'en tenir là ?

Tant que j'y étais, j'ai regardé l'API ECOWATT ( https://data.rte-france.com/catalog/-/api/consumption/Ecowatt/v4.0 ) qui donne une couleur et un message décrivant le niveau de stress du réseau.

Du coup, le script appelle les deux API et retourne les données cumulées des deux.

ce qui donne ça

Capture du 2022-12-11 10-47-34.png

Capture du 2022-12-11 10-49-23.png

J'en veux j'en veux...

Si ça vous intéresse, le zip est là : RTETempo.zip et il est distribué sous stricte licence faites-en ce que vous voulez. 😅

Les constantes au début permettent de configurer un peu:

  • TOKEN_BASE64 : pour mettre votre propre jeton si vous voulez vous inscrire sur RTE (qui accepte les emails jetables type yopmail, je dis ça je dis rien 😬)
  • TEMPO_BEFORE_TODAY, TEMPO_BEFORE_TOMORROW, ECOWATT_BEFORE_TODAY, ECOWATT_BEFORE_TOMORROW : pour définir le texte renvoyé avant la couleur.
  • HTML_STYLE : pour changer le style du HTML généré
  • TEMPO_HTML_TEMPLATE, ECOWATT_HTML_TEMPLATE : pour changer le code HTML à utiliser en cas de retour HTML
  • ECOWATT, TEMPO : deux booléens permettant de débrayer l'un ou l'autre des appels (si vous ne voulez que ECOWATT ou que TEMPO)

Et le BOT ?!

Ben j'ai fait un autre BOT pour poster les couleurs du réseau une fois par jour... https://piaille.fr/@RTE_color ( @RTE_color@piaille.fr )

Capture du 2022-12-11 11-01-14.png

YoutubeRSS

Hier, je me suis aperçu que le bookmarklet que j'avais fait pour trouver le flux RSS d'une chaîne youtube ne fonctionnait pas toujours 🤬: en effet, si l'URL de la chaîne n'est pas du type www.youtube.com/channel/xxxCHANNEL_IDxxx ça ne fonctionne pas... Or, les chaînes peuvent être aussi sous une forme dans laquelle le channel_id n'apparaît pas.

zut flûte et cacaboudin

Du coup, je m'y mets

Au lieu de laisser youtube me chier dans les bottes, je me suis dit que, si le channel_id n'est pas dans l'URL, il doit être planqué quelque part dans le html de la page.

En fouillant un peu, twingo bongo jannielongo bingo 🥳 J'ai trouvé ça en parsant avec (presque) la même regex que pour l'URL.

con.jpeg

J'ai donc codé vite fait une «api» qui renvoie l'URL du flux RSS d'une chaîne Youtube dont on fournit l'adresse.

On peut l'utiliser avec le frontend minimaliste prévu, en faisant une requête GET ou via le bookmarklet qui va bien.

Le tout est bien entendu utilisable, autohébergeable et modifiable, comme d'habitude

Allez !

Cadeau du lundi: pas un, pas deux mais TROIS plugins Pluxml... (et oui !)

Bon, il ne s'agit pas de trois   plugins que j'aurais fait en   une fois, mais de trois plugins   codés à des moments différents   et que j'avais oublié de partager   jusque-là...

ok

🥇 Plugin N°1 : uniquePagePreview

Si toi aussi t'en as marre que le bouton Aperçu de la page article t'ouvre à chaque fois un nouvel onglet aboutissant rapidement à une accumulation visuellement insupportable du nombre d'échecs qu'il te faut avant de parvenir à un billet un tant soit peu abouti ? Alors ce ... «plugin» est pour toi: il se contente de changer le «_blank» de l'attribut onclick du bouton en «article_preview»... et ça, tu vois, ça change tout...

Désormais, la visualisation de l'article se fera toujours dans le même onglet (ouvert lors de la première visualisation)

⚡ Téléchargement direct du ZIP: https://repo.warriordudimanche.net/ZIPFILES/uniquePagePreview.zip

🥈 plugin N°2 : resizeArticleTextarea

Un truc qui me chiffonnait dans la rédaction d'articles un peu longs, c'était:

  1. de ne jamais voir l'article en entier pendant la rédaction
  2. de passer mon temps à défiler DANS le textarea en plus de défiler DANS la page...
Ok, ça fait deux trucs...

Grâce à ce plugin, on ne passe plus son temps à défiler QUE dans la page

En effet, il redimensionne les textareas de la page article en fonction de leur contenu. La zone de texte grandit avec le volume de texte tapé dedans.

⚡ Téléchargement direct du ZIP: https://repo.warriordudimanche.net/ZIPFILES/resizeArticleTextarea.zip

🥉 plugin N°3 : adminPanel

Un plugin dérivé d'un de mes anciens qui s'avérait obsolète avec la nouvelle maquette. Il permet d'afficher un menu visible uniquement quand l'admin est connecté. Ce menu regroupe plusieurs icônes:

Capture du 2022-11-14 14-35-06.png

  • un lien vers l'espace admin
  • un lien vers un tag particulier: je m'en sers pour accéder aux articles publiés pour lecture ultérieure sous le tag «riditleteur»
  • un lien vers la page commentaires avec un décompte des commentaires non lus
  • un bouton de déconnexion

Il affiche de plus un lien sur chaque article pour éditer directement ce dernier (pratique pour corriger ou mettre à jour un article)

Ces deux fonctions sont accessibles via deux hooks, «editArticleIcon» et «adminPanel», dont il faut placer l'appel dans les pages header.php et articles.php du thème

Une page de config permet de redéfinir les icônes et texte des boutons ainsi que le tag du raccourci.

Capture du 2022-11-14 14-43-09.png

⚡ Téléchargement direct du ZIP: https://repo.warriordudimanche.net/ZIPFILES/AdminPanel.zip

Si ça peut vous servir, c'est cadeau !

L'appli de documents que j'ai codée pour le taf...

Ça fait un moment que je parle de certaines de mes applis au fil de billets ou de commentaires, en particulier de celle que j'utilise au boulot. Un très long billet totalement dispensable destiné à ceux que l'enseignement intéresse (ou les logiciels dans l'enseignement)

Je me suis dit que ça pouvait intéresser des gens de voir avec quoi je taffe.

Les autres, vous  pouvez y aller...

Les attentes (le pourquoi du comment j'ai décidé de faire mon propre truc)

Tout est venu de l'aspect pour le moins instable et aléatoire des logiciels et environnements proposés dans le cadre de mon boulot que ce soit au niveau du ministère, de l'académie, du département ou même du collège.

1- du problème des évolutions 👎

En gros, on change soit de logiciel soit d'environnement soit de machines à peu près tous les ans ou les deux ans, ce qui induit une certaine appréhension au niveau de la conservation de nos données: les exercices réalisés dans les exerciseurs disparaissent, les données et documents de l'ENT également... bref: c'est du taf inutile à se retaper tous les ans (ou deux ans) 💩

2- du problème des logiciels 👎

Mon autre souci, c'est que les logiciels proposés sont rarement utilisés par ceux qui les codent puisqu'il s'agit d'applis à caractère administratif (appel/cahier de texte etc) ou pédagogiques (exerciseurs / stockage de données / expos etc)

Résultat, l'UI est merdique et il est impossible de faire la moindre opération sans un nombre de clics qui à lui seul justifierait qu'on vire le bureau d'études. Quand tu dois swapper clavier souris trois fois pour juste une case à cocher, on a un problème. 😬

Ce problème vient du fait qu'à vouloir donner la possibilité de réaliser des choses complexes, on complexifie inutilement la réalisation des choses simples... or, on fait plus souvent des cases à cocher ou des cases de texte à remplir que des formulaires insérés dans des vidéos. 😭

3- de mes attentes persos quant aux applis

Pour ma part, j'attends d'une appli destinée aux élèves et aux professeurs que:

Pour les élèves:

  1. la consultation et les exercices se retrouvent sur la même plate-forme et dans des espaces clairs
  2. les élèves n'aient pas à se logger pour pouvoir consulter ou s'exercer ( limiter la friction de travail selon mon adage: «si c'est galère il va pas le faire» 😅)
  3. ça passe partout y compris et surtout SUR LEUR PITIN DE TELEPHONES ! Quand tu vois l'ENT sur mobile, ça te donne des envies de suicide collectif.
  4. que ce soit clair, lisible et simple.
  5. que tous les documents / pdf etc utilisés lors d'un cours soient dispo depuis un seul lien de partage

Pour moi:

  1. pas de perte de temps au moment de mettre en ligne: je copiecolle le lien de partage de mon document dans l'ENT et c'est tout.
  2. pas de perte d'énergie au moment de réaliser les documents et travaux (limiter la friction d'usage selon mon adage «la vie est trop courte pour se faire chier deux heures sur un document»)
  3. mise en ligne rapide et simple des documents (et possibilité de partager des documents sur une page sans la réaliser vraiment: génération auto de la page de partage)
  4. pas de perte de mon boulot: c'est sur mon serveur, pas sur une merde académique hébergée aux USA qui va se perdre ou être fliquée.
  5. pas de flicage ni de moi ni de mes élèves.
  6. rapidité et simplicité de la création d'exercices

Naissance de Documentos

Il s'agit d'une appli en ligne de consultation libre des documents utilisés en cours.

Côté élève, un lien de partage conduit à la page que j'utilise en classe pour faire cours: il a donc toutes les ressources pour revoir la leçon ou récupérer le cours en un seul lien.

Cette même page me permet de mettre une image en plein écran en un clic, de faire plusieurs diapos simplement etc.

Côté enseignant, elle fournit un explorateur de fichiers , un éditeur de pages etc. On peut ainsi créer un nouveau dossier de travail pour les 5ème, y déposer en une fois mp3, images etc, y créer une page dans laquelle on organise le tout et même créer des exercices numériques sans que ça prenne plus de temps de le faire là que de le faire sous libreoffice (souvent, la version papier me prend grave plus de temps que la version numérique en fait 😅)

Ok, mais ça a quelle tronche ton truc ?

La racine de la page d'accueil donne accès à tous les niveaux

documentos1 copie.jpg

et dans chaque niveau, une page unique liste tous les documents disponibles. Quand le prof cherche le document du jour, il peut filtrer en tapant une partie du nom du dossier contenant lesdits documents.

documentos2 copie.jpg

Une fois sur le document, l'élève (ou le prof en classe) a une page claire avec documentation, questions, liens vers les fiches de révision et pdf éventuellement distribué.

document copie.jpg

L'enseignant peut également ajouter des éléments de formulaire dynamiques permettant de sélectionner, cocher, ordonner, compléter

documentos3 copie.jpg

Vous noterez au passage qu'on peut ajouter un bouton permettant de se rendre directement à un temps T d'une vidéo ou d'un enregistrement, pour guider les élèves.

J'ai ajouté un bouton servant à changer la police de caractères pour l'opendyslexic:

documentos3dys copie.jpg

Et côté admin alors ?

Le prof a un filemanager pour créer des dossiers et des fichiers simplement, uploader en glisser-déposer, éditer des fichiers. L'accent a été mis sur la rapidité et la simplicité d'utilisation.

filemanager copie.jpg

Si on se contente d'uploader sans mettre de page, le lien générera une page complète avec les documents. Sinon, on ajoute une page html qu'on édite ensuite (deux clics)

editeur copie.jpg

Tous les fichiers constituant un «document de classe» se trouvent dans le même dossier par défaut: si on crée des sous-dossiers dans celui du document, chaque sous-dossier devient une diapo indépendante générée comme des pages individuelles. Lorsqu'on se rend sur la page de partage, on passera de l'une à l'autre avec les flèches du clavier ou celles apparaissant sur les côtés de l'écran... pas besoin de se faire chmir à créer les diapos, les lier que sais-je.

On a donc: ROOT> niveau> document> fichiers ou ROOT> niveau> document> diapo1>fichiers , ROOT> niveau> document> fichiers>diapo2>fichiers etc.

Et la réalisation d'exercices alors ?

Pour la mise en page, on utilise markdown, donc, du texte brut. Hors de question pour moi de devoir me prendre le chou avec des mises en page compliquées.

Sur ce principe, pas de boîtes de dialogue, de clics multiples pour créer des exos: tout se fait par deux types de «balises» sans lâcher son clavier:

les {{}}

Propres à mon framework perso, je les ai adaptées à Documentos:

  • pour insérer un fichier à un endroit: {{fichier.ext}} et c'est tout.
  • pour insérer tous les fichiers d'un type {{*.jpg}}, et si on ne se souvient pas bien du nom {{*moncul.jpg}} fonctionne très bien.
  • pas de boutons ou balises spéciales selon les documents: documentos se démerde seul... ainsi {{fichier.jpg}} crée une image qui passe en fullscreen au clic, {{fichier.mp3}} crée un lecteur audio, {{fichier.mp4}} crée un lecteur video etc...
  • on peut ajouter facilement des choses plus poussées en insérant des {{fichier.css}} ou {{fichier.js}}spécifiques.
  • L'appli offre certaines constantes accessibles de la même façon: {{BLEU}} change le fond en bleu, {{FULLSCREEN}} passe en fullscreen dès le chargement, {{FECHA}} ajoute la date du jour en espagnol...

les []

Les éléments de formulaire sont générés via des commandes gu genre {{app->flashcards("")}} qui ne sont pas super simple à mémoriser ou sexy à voir. Du coup, j'ai créé des aliases plus simples qui utilisent les crochets. Ainsi:

  • une case texte ? [texte à trouver]
  • Il faut accepter plusieurs réponses ? [réponse1+réponse2]
  • une liste déroulante ? [choix 1,choix 2, +bon choix,choix3]
  • Une case à cocher ? []texte d'une case à ne pas cocher], [+]texte d'une à case cocher]
  • un verbe à conjuguer ? [conjugaison:llamo,llamas,llama,llamamos,llamáis,llaman]
  • une phrase à ordonner ? [ordonne:La primera pelota está en la estantería.]
  • des flashcards ? [flashcards:texteface:textedos;texteface2:textedos2]
  • Une liste de mots à trouver ? [mots:textefr:texteesp;textefr2:texteesp2]
  • Un mot avec traduction ? [texte es=texte fr]
  • Un bouton pour aller au temps T d'un media ? [espana.mp3>0:07] ou [>0:07] si un seul media est présent sur la page.
  • Un bouton pour stocker les réponses de l'élève ? [envoyer]
  • Un enregistreur pour les élèves n'ayant pas d'appli d'enregistrement ? [enregistreur]

Le fait de ne jamais quitter le clavier supprime la plupart des clics et la perte de temps du passage entre clavier et souris. ça s'avère redoutable dès qu'on a un peu l'habitude: on ne s'occupe que du contenu sans jamais perdre de temps à chercher comment faire (friction d'utilisation minimale)

Par contre, c'est moche

Tu as parlé de stocker les réponses des élèves ! ET LE RGPD ? 😱

T'inquiète, mon con de chef m'a suffisamment fait chier avec ça pour que je ne coure aucun risque (faire une recherche sur ce site avec le mot clé «j'abandonne» 😡):

  1. rien n'est hébergé hors serveur,
  2. je n'utilise rien que je n'ai fait moi-même (aucune lib notamment)
  3. les données des formulaires remplis qui sont sauvegardées le sont dans un fichier anonymisé: à aucun moment l'élève ne renseigne son nom et à aucun moment une donnée perso n'est utilisée pour le nommage de fichiers. Quand l'élève a envoyé le formulaire, le site lui donne un code à fournir au prof afin qu'il ait accès à la copie.

J'utilise Documentos depuis 2018 et je le modifie régulièrement. L'utilisation au quotidien est top et lors du confinement, je n'ai pas eu à changer grand-chose pour que le distanciel soit possible... je pouvais fournir presque en temps réel et mes élèves ont pu bosser dès les premières minutes de confinement sans être déroutés et depuis n'importe quel appareil (là où l'ENT était à genoux dès 8:10)

Pas de lien ?!

Je ne fournis pas le code de Documentos pour plusieurs raisons:

  1. c'est codé pour moi, avec mes habitudes... ça peut ne pas convenir à d'autres
  2. c'est fait pour l'espagnol: on peut l'adapter, mais faut coder
  3. il y a toujours des bugs par ci par là: je m'en accommode parce que je n'ai pas le temps de coder plus que ça et que ça ne touche pas le côté élève... mais ce serait chiant pour un autre.
  4. j'ai beau essayer de maintenir la cohérence et la logique du code, le patch à la truelle nécessite de reprendre certains aspects.
  5. pas de lien de démo car les documents fournis aux élèves sont copyrightés et que je ne veux pas d'emmerdes avec les éditeurs de bouquins

Après, on peut discuter, hein 😉

L'outil inutile du jour : UNIBAR

Unicode, c'est bien joli, mais c'est chiant à coller quand t'en as besoin. Du coup, tu lâches l'affaire.

Bon, ben j'ai bricolé une page pour copier ces caractères qu'on utilise le plus.

J'vous préviens, j'ai fait ça   en mode vite fait
Qui a dit   «comme toujours» ?
Bon, c'est pas complètement  faux, en même temps...

Le but est de copier rapidement dans le presse-papier le (ou les) caractères unicode désirés.

Quand on clique sur un caractère il se passe deux choses:

  • 🥇 ledit caractère est copié dans le presse-papier
  • 🥈 il est également ajouté à la suite dans le bouton du haut qui donne la possibilité de cumuler plusieurs caractères de suite. (clic sur le bouton copie le contenu du bouton, double-clic l'efface)

captureunibar.jpg

Et pour configurer ?

Ben tu édites le code passque  j'avais pas envie de faire tout  un bouzin sécurisé en php  pour sauvegarder la config  alors qu'il suffit de modifier le  code et que du coup ça reste  du html avec JS tout bête
Il SUFFIT d'éditer les lignes  de variables unicode...

Capture du 2022-04-22 18-21-11.jpg

Vous noterez que les chaînes peuvent n'être qu'un seul caractère unicode ou toute une série, si vous en utilisez régulièrement.



unicode={
    "ONGLET1":"chaine1,chaine2,chaine3,etc",
    "ONGLET2":"chaine1,chaine2,chaine3,etc",
}

Comme c'est du html+js+css, pas besoin d'un serveur, on peut l'utiliser en local. 🎉

Ok, mais à quoi ça sert en vrai ?!

Ben je sais pas moi ! Vu que vous pouvez mettre les caractères/chaînes que vous voulez, ça peut servir pour les matheux (coucou les profs) qui ont besoin des symboles de math simplement ou ponctuellement , en musique, ou en électronique... explorez unicode !

Download

⭐ Pour l'utiliser, c'est par là (∩`-´)⊃━━☆゚.*・。゚ http://outils.warriordudimanche.net/outils/unibar

⭐ Pour le télécharger, c'est par ici (ノʘヮʘ)ノ*:・゚✧ http://outils.warriordudimanche.net/outils/unibar/unibar.zip

MAJ Plugin PluXML: Markdown_parser

📢 Petite mise à jour du plugin Markdown_parser qui permet d'ajouter la gestion du markdown dans PluXML.

☑ J'ai étendu le markdown aux commentaires

☑ j'ai ajouté la possibilité d'accéder à des caractères unicodes directement.

☑ Vous pouvez choisir lesquels en passant par la page de config et en collant les caractères à la suite. Le plugin générera un bouton par caractère.

config.png

unicode.png

📎 Pour télécharger : https://repo.warriordudimanche.net/ZIPFILES/Markdown_parser.zip

DBAD by philsturgeon

Ma future licence favorite ?

# DON'T BE A DICK PUBLIC LICENSE

> Version 1.1, December 2016

> Copyright (C) [year] [fullname]

Everyone is permitted to copy and distribute verbatim or modified
copies of this license document.

> DON'T BE A DICK PUBLIC LICENSE
> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

1. Do whatever you like with the original work, just don't be a dick.

   Being a dick includes - but is not limited to - the following instances:

 1a. Outright copyright infringement - Don't just copy this and change the name.
 1b. Selling the unmodified original with no work done what-so-ever, that's REALLY being a dick.
 1c. Modifying the original work to contain hidden harmful content. That would make you a PROPER dick.

2. If you become rich through modifications, related works/services, or supporting the original work,
share the love. Only a dick would make loads off this work and not buy the original work's
creator(s) a pint.

3. Code is provided with no warranty. Using somebody else's code and bitching when it goes wrong makes
you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.
Merci à https://nicolas-delsaux.hd.free.fr/Shaarli/?X31NQQ

<video> : c'est du <track> cas ! HELP [EDIT 2h après] [Merci Bill2]

Et allez, encore une matinée de perdue pour un truc que j'avais pas prévu et qui devrait fonctionner parfaitement: la balise <video> et la balise <track> pour ajouter les sous-titres.

Pour afficher une video pour les élèves avec les sous-titres que j'ai traduit de youtube, en gros, je fais un truc comme ça:


<video controls title="sdfgsdfg" preload="auto" >
    <source src="http://serveur/Marco Castelblanco.mp4"  type="video/mp4">
    <track kind="subtitle" srclang="fr" label="sous-titre" src="http://serveur/Marco Castelblanco.vtt" default="true"/>
    Sorry, your browser doesn't support embedded videos.
</video>

Pour ce fichier de sous-titres, J'ai :

  • récupéré vidéo+sous-titres avec JDownloader
  • j'ai traduit les sous-titres
  • j'ai converti le format .srt fourni par yt en .vtt, le format compatible avec track

MAIS ÇA MARCHE PAS

  • J'ai beau essayer en local, en distant,
  • en http et en https,
  • dans un fichier html ou php,
  • sur firefox/chromium/vivaldi,
  • tous les fichiers se chargent normalement (ils n'apparaissent pas comme 404 dans la console-réseau.)
  • l'encodage est bon
  • le format de fichier (vtt) est bon aussi...
  • [edit] l'attribut crossorigin sur video ne change rien

J'ai cherché partout, je me prends la tête depuis des heures...

J'ai même essayé de forcer le track.mode à "showing" au cas où. Mais non.

Si quelqu'un a une idée, je prends...

Solution !

Il suffit de mettre kind="captions" au lieu de kind="subtitle" pour que ça fonctionne...

Merci à Bill2 pour la solution !

EN FAIT C'EST MOI K'É COUILLON

Une matinée perdue pour un «s» manquant à subtitleS : kind="subtitles"

B64: outil + API

En passant, je vous mets le lien vers un petit outil pour convertie en et de Base64.

Bon, yen a plein, hein, en particulier celui de Timo ... J'en ai quand même refait un from scratch pour pouvoir l'utiliser comme une appli online (le front end ci-dessous) ou bien comme une «API» utilisable via un bookmarklet par exemple: ainsi, en sélectionnant du texte puis en lançant le bookmarklet qui va bien, on peut encoder/décoder en un clic...

Capture du 2022-03-10 13-50-08.png

Comme d'habitude, si ça intéresse quelqu'un, on sait jamais... https://api.warriordudimanche.net/b64/ et pour télécharger

Mardi 1 Mars 2022: Plinstagram, c'est toujours pas ça... [Edit à 14:23]

Précédemment sur le Warriordudimanche: https://warriordudimanche.net/index.php?article1636/ya-pas-que-les-voitures-qui-sont-allergiques-vanille-php-aussi-fait-trucs-passionnants-help

Bon, je bosse dessus parce que je suis entêté et que j'aime bien comprendre mais là... j'ai du mal.

Ce que j'ai fait

Côté frontend

  • J'ai épuré mon code JS au max
  • j'ai simplifié le formulaire en laissant tomber les noms de fichier: je n'envoie que le contenu de l'image en base64 et je génère un nom backend.
  • j'ai changé l'ajout des hidden servant à transmettre les images au format base64: au lieu de les ajouter au fur et à mesure de la génération des images redimensionnées, je les crée dans l'événement onSubmit du formulaire.
  • j'ai essayé de virer l'enctype du formulaire vu que, avec l'URL_rewriting à off j'obtenais une erreur 406 en distant... J'ai même essayé en text/plain pour voir... C'est pas ça.

    Capture du 2022-03-01 11-03-18.png

côté backend

  • j'ai simplifié au max
  • j'ai ajouté la création d'un nom de fichier local (l'extension est déduite des données base64 qui démarrent comme suit: base64:image/jpeg ...)
  • j'ai regardé, en local, la taille des données envoyées:
    'data' => 
      array (size=6)
        0 => string 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAOEBLADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1'... (length=286259)
        1 => string 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAOEBLADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1'... (length=782555)
        2 => string 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAOEBLADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1'... (length=900279)
        3 => string 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCASwA4QDAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1'... (length=903563)
        4 => string 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAOEBLADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1'... (length=636547)
        5 => string 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAOEBLADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1'... (length=1020399)

Je sais, on a l'impression que c'est toujours la même image mais en fait non... c'est sans doute dû au fait que base64 est très verbeux et que le début est toujours le même pour des images.

Le tout fait un post d'environ 4.5 Mo ce qui n'est pas choquant dans un formulaire multipart/form-data et reste très en dessous des limites de PHP_INI sur le serveur.

Aucun fichier .htaccess ne vient non plus foutre le bran...

HELP

Encore une fois, ça marche impeccable en local.

J'ai commenté au max mon code pour le cas où quelqu'un se sent de regarder, parce que pour ma part, je commence à voir flou et à avoir des hallucinations... je vous mets un zip: http://warriordudimanche.net/vrac/Plinstagram.zip

PISTE DE RECHERCHE

Omagad ! en cherchant, j'ai trouvé un truc: un problème éventuel avec ModSecurity disponible sur CPanel ( https://doc.ubuntu-fr.org/modsecurity & https://www.webfulcreations.com/how-to-fix-an-appropriate-representation-of-the-requested-resource-could-not-be-found-on-this-server-this-error-was-generated-by-mod_security-error/ ) En le mettant sur off depuis cpanel, mon script parvient à la page article.php !

Bon, ça fait une erreur de token, hein, mais on progresse !!!

Ya pas que les voitures qui sont allergiques à la vanille... PHP aussi fait des trucs passionnants. HELP

(wink @Sebsauvage : https://sebsauvage.net/links/?-WagqA )

Bon, accrochez-vous les lacets,   mettez du collyre, prenez un   Xanax, parce que là,   j'ai besoin de parler.

Je me suis aperçu que mon plugin Plinstagram faisait des trucs étranges et refusait parfois de poster. Pensant à une erreur d'identification, j'ai repris le code mais rien n'y faisait.

J'ai commencé à avoir des problèmes de redirection incompréhensibles: le header("location") ne fonctionnait pas (voir https://warriordudimanche.net/article1635/1635 )

Une fois la ruse très moche appliquée, ça semblait revenu à la normale. Puis j'ai décidé d'aller marcher un peu et j'ai pris des photos dans l'idée de tester à nouveau Plinstagram.

Et là, c'est le drame

J'ai beau tout essayer, pas moyen d'envoyer le post avec les photos... mais curieusement, j'aboutis à une erreur 404 et pas à une erreur d'exécution. Je me dis que ça doit être un problème de taille de formulaire et je me rappelle que, comme un con, j'ai omis de virer l'input files du formulaire avant envoi. J'explique rapidement comment fonctionne Plinstagram:

Côté JS

1 - l'utilisateur sélectionne des photos sur son ordinateur

2 - pour chaque image, le script js se charge de:

  • récupérer les images sélectionnées,
  • créer une miniature avec un canvas
  • stocker l'image réduite sous forme de donnée base64 dans un input hidden (avec le nom de fichier dans un autre input hidden) créés à la volée

Ainsi on obtient un $_POST[data] et un $_POST[filename] qui contiennent chacun un tableau avec les données de chaque image pour l'un et le nom de chaque image pour l'autre.

Quand on poste, le script vire l'input file pour éviter l'upload de grosses photos.

Côté PHP

Vient ensuite le hook AdminArticlePrepend de la page core/admin/article.php vers laquelle pointe le formulaire de plinstagram: celui-ci se charge de :

1 - parcourir l'array des images redimensionnées postées en base64,

2 - récupérer le nom de chaque image

3 - sauvegarder localement chaque image dans un sous-dossier dédié à l'article

4 - générer une galerie qu'il ajoute au corps du post

5 - finaliser la création des données de l'article.

À ce moment-là pluXML reprend la main et s'occupe du stockage de ces données.

Quand je teste en distant (sur WDD)

Avec une photo, tout se passe normalement. Si j'en mets ne serait-ce que deux, pluXML me renvoie à la page 404, comme si l'URL était fausse: or, il n'en est rien ! L'URL de la barre d'adresse est la bonne, celle du formulaire aussi... pourtant, avec plus d'une photo, la requête n'arrive jamais à core/admin/article.php

Pire, une fois sur la page 404, si je clique dans la barre d'adresse puis que j'appuie sur entrée, j'arrive sans encombre à la page voulue (mais sans les données de formulaire bien entendu): l'URL est donc bonne.

J'ai pensé à une redirection foireuse mais la seule redirection qui reste est celle qui se fait AVANT le formulaire et seulement dans le cas où l'utilisateur n'est pas connecté.

Et puis ça ne semble pas être la faute de mon script PHP vu qu'on n'arrive même pas jusqu'à lui (j'ai collé des exit('moncul'); partout pour voir et rien !)

Quand je teste en local... ô surprise!

TOUT FONCTIONNE SANS PROBLEME ! (le fameux «ça marche sur mon ordi»)

  • J'ai pensé à un problème de version de PHP: j'ai essayé de changer et c'est pas ça
  • j'ai songé à une limite de la taille de fichiers ou la limite de taille de post... c'est pas ça (puis ça générerait une erreur, pas un pseudo 404)

Pour résumer

index.jpeg

Conclusion

J'en suis à me dire qu'il doit y avoir un genre de restriction pour la taille des données contenues dans des inputs et que cette restriction ne doit pas être la même en local.

Une autre piste que je dois explorer est une éventuelle incompatibilité entre deux plugins... Mais je vois pas lesquels et pis là, faut que j'aille pleurer d'abord.

EDIT dix minutes plus tard:

Tiens, la différence entre le local et le distant, c'est la configuration du rewrite URL dans pluXML: activée en distant. Je mets sur OFF et là, j'obtiens une erreur 406:

Not Acceptable: An appropriate representation of the requested resource could not be found on this server.

ça progresse. Je retourne pleurer.

Cette conférence sur le thème de   la loose en programmation et la   remise en question de mes   passions, compétences et priorités   générales dans la vie est à présent   terminée... Vous pouvez disposer.

api: Flashcards

Dans la rubrique «je bosse une grosse fois pis c'est bon» j'ai eu besoin de pouvoir faire rapidement une page de révision de vocabulaire pour mes élèves; mais quand je dis rapidement, je veux que ce soit fissa avec une friction proche de zéro et sans avoir recours à une appli à la con: copier coller un lien dans l'ENT doit suffire.

J'ai donc opté pour les flashcards, qui sont très efficaces dans ce domaine et j'ai codé un truc vite fait qui ne représente pas une prise de tête quand on veut donner du boulot aux gamins.

Capture du 2022-02-21 16-23-22 copie.jpg

En gros, tu écris les mots à apprendre sous la forme
question1:réponse1, question2:réponse2,...
puis tu récupères la page avec le lien à utiliser.

Capture du 2022-02-21 16-23-39 copie.jpg

Sur la page, tu cliques sur la carte et elle se retourne.

L'exemple de la capture est là

C'est un peu en béta, hein, mais ça marche. Si ça peut servir, c'est cadeau...

Quand Java bien... - Warrior du Dimanche - Antichesse (o ^ω^ o)

Merci à tous pour vos témoignages anti-java qui font que je me sens moins seul et pour vos conseils en la matière !

@Antichesse (o ^ω^ o) Merci à toi en particulier pour ta proposition il se pourrait que je te prenne au mot o/ Je vais aller essayer la rubrique openclassroom dédiée à Kotlin DQP ( https://www.youtube.com/watch?v=QpNOl2BU7tE pour la référence ^u^ )

Fil RSS des articles