Créez des aides de guidon personnalisées dans Ghost !
Cet article s'adresse à de nombreux développeurs et créateurs de thèmes qui trouvent les aides standards proposées par Ghost (https://ghost.org/docs/themes/helpers/) insuffisantes. Il est tout à fait normal de chercher des moyens d'étendre les capacités de nos thèmes qui utilisent les guidons fournis par Ghost. Avant de publier cet article et de trouver une solution pour mon thème, j'ai parcouru tout Internet et effectué moi-même une analyse du code source de Ghost.
Méthode 1 (modification du code principal)
J'ai découvert qu'il est possible d'étendre le code source de Ghost avec des aides supplémentaires. J'y suis parvenu en ajoutant un nouveau répertoire dans current/core/frontend/apps. J'ai utilisé l'exemple d'une « application » existante appelée amp, dont le code est très simple, pour commencer à créer un nouvel assistant disponible dans le thème. Dans ces applications existantes, la structure est simple car les helpers sont enregistrés dans lib/helpers. À la fin du processus, vous devez ajouter le nom de votre répertoire dans apps à current/core/shared/config/overrides.json dans la section apps.internal JSON.
Un exemple de contenu du fichier index.js dans notre application serait :
const path = require('path'); module.exports = { activate: function activate(ghost) { ghost.helperService.registerDir(path.resolve(__dirname, './lib/helpers')); } };
Ensuite, dans le répertoire lib de cette application, nous créons un dossier nommé helpers. À l’intérieur, nous créons un nouveau fichier, qui sera le nom de l’assistant à appeler dans un modèle de guidon. Par exemple, nommons-le uppercase.js.
Vous trouverez ci-dessous un exemple d'un tel code d'assistance, qui convertit simplement les lettres du texte donné dans l'argument d'assistance en majuscules :
const {SafeString, escapeExpression} = require('../../../../services/handlebars'); module.exports = function uppercase(text) { return `${text.toUpperCase()}`; };
N'oubliez pas d'ajouter le nom du répertoire de l'application à current/core/shared/config/overrides.json. Après avoir redémarré Ghost, tout devrait être prêt.
Méthode 2 (sans modifier le code principal)
J'ai récemment développé cette méthode, et vous pouvez l'appliquer non seulement sur Ghost auto-hébergé mais également sur les instances Ghost proposées par les hébergeurs. Dans ce dernier cas, cela nécessite une planification architecturale appropriée et l'achat d'un petit serveur qui fera office de proxy pour votre instance Ghost finale.
L'architecture que nous utiliserons dans cette méthode :
Serveur Nginx ← Middleware Node.js ← Instance Ghost
Le navigateur de l'utilisateur envoie une requête au serveur Nginx, qui contient l'amont du middleware. Toutes les demandes, quel que soit leur emplacement, seront transmises par proxy au middleware.
Le middleware est un serveur Express fonctionnant dans Node.js avec la bibliothèque express-http-proxy (https://github.com/villadora/express-http-proxy) ajoutée, ce qui simplifie considérablement le travail. Nous configurons le proxy pour communiquer avec l'instance Ghost. La bibliothèque express-http-proxy possède une propriété userResDecorator que nous pouvons utiliser pour « décorer la réponse du serveur mandaté ». En termes simples, nous pouvons modifier la réponse de Ghost avant de l'envoyer au navigateur de l'utilisateur.
Notre userResDecorator sera asynchrone afin de ne pas bloquer le thread principal. Nous reviendrons sur le sujet du traitement asynchrone lors de la création des helpers. Pour l'instant, vous devez savoir que tout ce que demande le navigateur de l'utilisateur n'a pas besoin d'être décoré. Par conséquent, la première étape consistera à vérifier l’en-tête content-type de la réponse de Ghost. Vous pouvez procéder comme suit puis comparer s'il s'agit de texte/html pour décorer uniquement les documents HTML renvoyés à l'utilisateur :
const path = require('path'); module.exports = { activate: function activate(ghost) { ghost.helperService.registerDir(path.resolve(__dirname, './lib/helpers')); } };
Dans cette instruction conditionnelle, nous pouvons commencer à modifier htmlContent, mais pourquoi en avons-nous besoin ? Commençons par jeter les bases de notre assistant personnalisé dans le thème Ghost !
Dans cet article, je vais créer un assistant personnalisé dans le fichier index.hbs (page d'accueil) de mon thème. Dans un emplacement visible dans le modèle de guidon, j'ajoute un exemple d'assistant personnalisé, le nommant {{hello_world}}.
⚠️ Ensuite, je le place à un endroit visible sur la page d'accueil — mais remarquez ce qui se passe lorsque j'actualise la page Ghost !
const {SafeString, escapeExpression} = require('../../../../services/handlebars'); module.exports = function uppercase(text) { return `${text.toUpperCase()}`; };
Dans cette variable, nous avons la réponse de l'instance Ghost comme le code HTML complet de la page. Imaginez que cette réponse soit la page d'accueil de votre instance Ghost. Le contenu HTML inclura également notre texte brut {{hello_world}}, qui est affiché sous forme de texte brut. Si notre assistant personnalisé se présente sous cette forme, nous pouvons le compiler à l'aide de Handlebars.js (https://handlebarsjs.com/) dans notre middleware. N'oubliez pas d'installer d'abord la bibliothèque via un gestionnaire de packages, par exemple npm : npm install handlebars et ajoutez-la à votre code : const handlebars = require("handlebars");.
// Where 'proxyRes' is your proxy response inside 'userResDecorator' const contentType = proxyRes.headers['content-type'] || ''; if (!contentType.includes('text/html')) { // Return original content if response is not 'text/html' return proxyResData; } let htmlContent = proxyResData.toString('utf8'); // Do something with 'htmlContent' and return return htmlContent;
Wow ! Nous avons maintenant compilé et rendu du HTML à l'aide de guidons.js, mais nous n'avons pas encore terminé. Nous devons encore enregistrer notre assistant personnalisé {{hello_world}}. Ajoutez le code suivant, de préférence après avoir initialisé Handles.js :
{{!< default}} <div> <p>After refreshing, I get an error message from Ghost because the {{hello_world}} helper doesn’t exist in Ghost's default helpers. For our logic to work, we must escape this helper so that it’s not treated as a helper by Ghost’s built-in Handlebars.</p> <p>The correct way is to write this helper as \{{hello_world}}. This way, Ghost treats it as plain text. After refreshing the Ghost homepage, you should see the plain text {{hello_world}}. If this happens, you are on the right track. Let’s now return to the middleware server file, where we will use the response decorator.</p> <p>⚠️ Remember to escape custom helpers in your theme! Don’t forget to add the \ character.<br> </p> <pre class="brush:php;toolbar:false">let htmlContent = proxyResData.toString('utf8');
Après avoir redémarré le serveur middleware et enregistré l'assistant ci-dessus, vous devriez voir l'assistant rendu dans le navigateur avec le texte renvoyé par notre assistant ainsi que la date et l'heure actuelles.
À ce stade, vous pouvez étendre votre thème Ghost avec des assistants personnalisés supplémentaires, que vous ajouterez au code du serveur middleware.
Sécurité
À un moment donné, vous souhaiterez peut-être rendre diverses choses à vos aides. Par défaut, la bibliothèque protège contre les attaques XSS, mais lorsque vous utilisez la méthode SafeString, cette protection cesse de fonctionner. Évitez de l'utiliser autant que possible.
Encore une chose ! Imaginez qu'un utilisateur ajoute une telle aide dans la section commentaires sous une publication et ajoute du contenu malveillant dans le paramètre. Soyez attentif à la sécurité. Par exemple, si vous restituez entièrement chaque code HTML, vous pourriez être vulnérable aux attaques XSS. Il est recommandé de compiler et de restituer Handles.js dans des zones spécifiques et fermées. Vous pouvez utiliser la bibliothèque cheerio (https://cheerio.js.org/) pour analyser le HTML et restituer les guidons si nécessaire. Voici un exemple de la façon dont vous pouvez vous sécuriser en modifiant le code de rendu précédent :
const path = require('path'); module.exports = { activate: function activate(ghost) { ghost.helperService.registerDir(path.resolve(__dirname, './lib/helpers')); } };
N'oubliez pas d'ajouter l'initialisation de la bibliothèque au début de votre script : const asyncHelpers = require('handlebars-async-helpers');. Si vous rencontrez des problèmes d'installation en raison de conflits de versions entre handlebars-async-helpers et handlebars, rétrogradez simplement handlebars vers ^4.7.6. Malheureusement, la bibliothèque d'assistance asynchrone n'a pas été maintenue depuis un certain temps, mais elle fonctionne toujours dans la pratique.
Communication et objets de base de données
Si vous souhaitez effectuer des requêtes dans la base de données dans Ghost pour récupérer, par exemple, la publication en cours, c'est possible et pas difficile. Vous pouvez utiliser une bibliothèque comme knex (https://knexjs.org/), qui est un générateur de requêtes SQL clair et rapide. N'oubliez pas que vous aurez besoin de handlebars-async-helpers pour cela. Configurez correctement knex pour vous connecter à la base de données de Ghost.
Initialisez knex comme variable db et essayez le code suivant :
const {SafeString, escapeExpression} = require('../../../../services/handlebars'); module.exports = function uppercase(text) { return `${text.toUpperCase()}`; };
Ensuite, dans le modèle post.hbs du thème Ghost, ajoutez l'assistant suivant : {{post_title uuid="{{uuid}}"}}. Dans cet exemple, {{uuid}} sera récupéré et transmis en tant qu'assistant disponible dans Ghost, remplissant le champ uuid de notre assistant et provoquant l'affichage du titre du message par l'assistant personnalisé.
Vous pouvez également utiliser axios pour envoyer des requêtes HTTP à l'API Ghost Content, mais cela est nettement plus lent que la communication directe avec la base de données.
Performance
Je sais qu'une solution basée sur un middleware n'est peut-être pas la meilleure en termes de vitesse, mais j'utilise personnellement cette solution et je n'ai pas remarqué de baisse significative des temps de chargement des pages. Le temps de réponse moyen pour une seule requête était inférieur à 100 ms (selon express-status-monitor) et j'utilise un assistant personnalisé qui récupère certaines valeurs de la base de données sur chaque page.
Vous pouvez bien sûr ajouter des mécanismes de mise en cache pour améliorer les performances du middleware ou utiliser des solutions alternatives au lieu d'express-http-proxy.
Mise en œuvre de l'architecture
Utilisez Docker ou un autre mécanisme de conteneurisation. Je l'ai utilisé dans mon projet et cela fonctionne très bien. Ajoutez des images Ghost et de base de données pour Ghost, Nginx et une image Node.js. Connectez-les à un réseau partagé (driver : bridge), configurez Nginx et le serveur Node.js en conséquence — tout est très simple !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds











Différents moteurs JavaScript ont des effets différents lors de l'analyse et de l'exécution du code JavaScript, car les principes d'implémentation et les stratégies d'optimisation de chaque moteur diffèrent. 1. Analyse lexicale: convertir le code source en unité lexicale. 2. Analyse de la grammaire: générer un arbre de syntaxe abstrait. 3. Optimisation et compilation: générer du code machine via le compilateur JIT. 4. Exécuter: Exécutez le code machine. Le moteur V8 optimise grâce à une compilation instantanée et à une classe cachée, SpiderMonkey utilise un système d'inférence de type, résultant en différentes performances de performances sur le même code.

Python convient plus aux débutants, avec une courbe d'apprentissage en douceur et une syntaxe concise; JavaScript convient au développement frontal, avec une courbe d'apprentissage abrupte et une syntaxe flexible. 1. La syntaxe Python est intuitive et adaptée à la science des données et au développement back-end. 2. JavaScript est flexible et largement utilisé dans la programmation frontale et côté serveur.

Le passage de C / C à JavaScript nécessite de s'adapter à la frappe dynamique, à la collecte des ordures et à la programmation asynchrone. 1) C / C est un langage dactylographié statiquement qui nécessite une gestion manuelle de la mémoire, tandis que JavaScript est dynamiquement typé et que la collecte des déchets est automatiquement traitée. 2) C / C doit être compilé en code machine, tandis que JavaScript est une langue interprétée. 3) JavaScript introduit des concepts tels que les fermetures, les chaînes de prototypes et la promesse, ce qui améliore la flexibilité et les capacités de programmation asynchrones.

Les principales utilisations de JavaScript dans le développement Web incluent l'interaction client, la vérification du formulaire et la communication asynchrone. 1) Mise à jour du contenu dynamique et interaction utilisateur via les opérations DOM; 2) La vérification du client est effectuée avant que l'utilisateur ne soumette les données pour améliorer l'expérience utilisateur; 3) La communication de rafraîchissement avec le serveur est réalisée via la technologie AJAX.

L'application de JavaScript dans le monde réel comprend un développement frontal et back-end. 1) Afficher les applications frontales en créant une application de liste TODO, impliquant les opérations DOM et le traitement des événements. 2) Construisez RestulAPI via Node.js et Express pour démontrer les applications back-end.

Comprendre le fonctionnement du moteur JavaScript en interne est important pour les développeurs car il aide à écrire du code plus efficace et à comprendre les goulots d'étranglement des performances et les stratégies d'optimisation. 1) Le flux de travail du moteur comprend trois étapes: analyse, compilation et exécution; 2) Pendant le processus d'exécution, le moteur effectuera une optimisation dynamique, comme le cache en ligne et les classes cachées; 3) Les meilleures pratiques comprennent l'évitement des variables globales, l'optimisation des boucles, l'utilisation de const et de locations et d'éviter une utilisation excessive des fermetures.

Python et JavaScript ont leurs propres avantages et inconvénients en termes de communauté, de bibliothèques et de ressources. 1) La communauté Python est amicale et adaptée aux débutants, mais les ressources de développement frontal ne sont pas aussi riches que JavaScript. 2) Python est puissant dans les bibliothèques de science des données et d'apprentissage automatique, tandis que JavaScript est meilleur dans les bibliothèques et les cadres de développement frontaux. 3) Les deux ont des ressources d'apprentissage riches, mais Python convient pour commencer par des documents officiels, tandis que JavaScript est meilleur avec MDNWEBDOCS. Le choix doit être basé sur les besoins du projet et les intérêts personnels.

Les choix de Python et JavaScript dans les environnements de développement sont importants. 1) L'environnement de développement de Python comprend Pycharm, Jupyternotebook et Anaconda, qui conviennent à la science des données et au prototypage rapide. 2) L'environnement de développement de JavaScript comprend Node.js, VScode et WebPack, qui conviennent au développement frontal et back-end. Le choix des bons outils en fonction des besoins du projet peut améliorer l'efficacité du développement et le taux de réussite du projet.
