Un plugin de recherche en texte intégral pur javascript, léger et intégré au navigateur pour Ghost (blog)
SearchinGhost est un moteur de recherche léger et extensible dédié à la plateforme de blogs Ghost. À la base, il utilise l'API Ghost Content pour charger le contenu de votre blog et la puissante bibliothèque FlexSearch pour indexer et exécuter des requêtes de recherche.
Tout se passe dans le navigateur client, il nous aide à fournir des résultats de recherche ultra-rapides et à les afficher en temps réel à vos utilisateurs (alias « recherche au fur et à mesure que vous tapez »). Nous veillons également à minimiser les charges du réseau en nous appuyant sur le navigateur localStorage
qui n'envoie des requêtes que lorsque cela est nécessaire.
Votre blog est en cyrillique, chinois, coréen, grec, indien ou toute autre langue non latine ? Pas de soucis, il est supporté, voir la rubrique dédiée.
BONUS : si le concept vous plaît mais que vous aimeriez l'installer rapidement et facilement (en moins de 3 minutes, vraiment !), rendez-vous sur le projet SearchinGhostEasy.
Avant de vous lancer dans l'installation et la configuration, essayez-le vous-même avec cette démo en direct .
Sur cette démo, le contenu consultable provient de l'API de démonstration officielle de Ghost (c'est-à-dire https://demo.ghost.io). Les options sont définies par défaut afin que chaque mot saisi soit recherché dans le titre, les balises, l'extrait et le contenu principal des articles.
Par exemple, recherchez le mot « marmelade ». Il n'existe dans aucun titre d'article, extrait ou tag mais il est utilisé une fois dans l'article "Down The Rabbit Hole", c'est pourquoi vous l'obtiendrez en conséquence.
Tout d’abord, mettez à jour le fichier default.hbs
de votre thème pour inclure un champ de saisie et un élément de sortie pour afficher les résultats de la recherche. Ensuite, ajoutez un lien vers le script SearchinGhost et initialisez-le avec votre propre CONTENT_API_KEY
. Pour obtenir la clé API de contenu, veuillez vous référer à la documentation officielle de Ghost.
< input id =" search-bar " >
< ul id =" search-results " > </ ul >
< script src =" https://cdn.jsdelivr.net/npm/[email protected]/dist/searchinghost.min.js " > </ script >
< script >
var searchinGhost = new SearchinGhost ( {
key : 'CONTENT_API_KEY'
} ) ;
</ script >
Ça y est, tout est fait ! Si vous avez besoin d'une configuration plus fine, veuillez lire les sections suivantes.
Vous pouvez installer SearchinGhost en utilisant différentes méthodes, voici les possibilités :
Il s’agit de la méthode la plus simple et préférée pour installer SearchinGhost. Ajoutez l'un de ces scripts dans votre thème default.hbs
. Nous recommandons également l'utilisation de jsdelivr plutôt que de unpkg pour sa fiabilité et ses performances.
< script src =" https://cdn.jsdelivr.net/npm/[email protected]/dist/searchinghost.min.js " > </ script >
<!-- OR -->
< script src =" https://unpkg.com/[email protected]/dist/searchinghost.min.js " > </ script >
Si vous souhaitez servir SearchinGhost à partir de votre propre serveur ou l'inclure dans votre processus de construction, vous pouvez l'obtenir à partir des ressources de la page de version ou télécharger le fichier dist/searchinghost.min.js
.
Installez SearchinGhost en tant que dépendance du projet.
$ npm install searchinghost
# OR
$ yarn add searchinghost
Ensuite, chargez-le à partir de n’importe quel fichier Javascript.
import SearchinGhost from 'searchinghost' ;
// OR
var SearchinGhost = require ( 'searchinghost' ) ;
Le seul champ de configuration obligatoire est key
. Tout autre champ a une valeur par défaut et est devenu facultatif.
SearchinGhost a été conçu pour fonctionner immédiatement, cette configuration minimale est pourtant puissante ! À chaque frappe, il recherchera le titre, les balises, l’extrait et le contenu des articles. Il s'agit du comportement par défaut car il semble être le plus courant.
// SearchinGhost minimal configuration
var searchinGhost = new SearchinGhost ( {
key : '<CONTENT_API_KEY>'
} ) ;
Néanmoins, une petite configuration supplémentaire pourrait valoir la peine pour répondre à vos besoins. Disons que vous souhaitez uniquement rechercher dans le title
et afficher les champs title
et published_at
pour chaque article trouvé. Vous pouvez utiliser cette configuration :
var searchinGhost = new SearchinGhost ( {
key : '<CONTENT_API_KEY>' ,
postsFields : [ 'title' , 'url' , 'published_at' ] ,
postsExtraFields : [ ] ,
postsFormats : [ ] ,
indexedFields : [ 'title' ] ,
template : function ( post ) {
return `<a href=" ${ post . url } "> ${ post . published_at } - ${ post . title } </a>`
}
} ) ;
SearchinGhost est facilement personnalisable et extensible grâce à sa configuration, prenez votre temps pour examiner chaque option de la section suivante.
{
key : '' ,
url : window . location . origin ,
version : 'v3' ,
loadOn : 'focus' ,
searchOn : 'keyup' ,
limit : 10 ,
inputId : [ 'search-bar' ] ,
outputId : [ 'search-results' ] ,
outputChildsType : 'li' ,
postsFields : [ 'title' , 'url' , 'excerpt' , 'custom_excerpt' , 'published_at' , 'feature_image' ] ,
postsExtraFields : [ 'tags' ] ,
postsFormats : [ 'plaintext' ] ,
indexedFields : [ 'title' , 'string_tags' , 'excerpt' , 'plaintext' ] ,
template : function ( post ) {
var o = `<a href=" ${ post . url } ">`
if ( post . feature_image ) o += `<img src=" ${ post . feature_image } ">`
o += '<section>'
if ( post . tags . length > 0 ) {
o += `<header>
<span class="head-tags"> ${ post . tags [ 0 ] . name } </span>
<span class="head-date"> ${ post . published_at } </span>
</header>`
} else {
o += `<header>
<span class="head-tags">UNKNOWN</span>
<span class="head-date"> ${ post . published_at } </span>
</header>`
}
o += `<h2> ${ post . title } </h2>`
o += `</section></a>`
return o ;
} ,
emptyTemplate : function ( ) { } ,
customProcessing : function ( post ) {
if ( post . tags ) post . string_tags = post . tags . map ( o => o . name ) . join ( ' ' ) . toLowerCase ( ) ;
return post ;
} ,
date : {
locale : document . documentElement . lang || "en-US" ,
options : { year : 'numeric' , month : 'short' , day : 'numeric' }
} ,
cacheMaxAge : 1800 ,
onFetchStart : function ( ) { } ,
onFetchEnd : function ( posts ) { } ,
onIndexBuildStart : function ( ) { } ,
onIndexBuildEnd : function ( index ) { } ,
onSearchStart : function ( ) { } ,
onSearchEnd : function ( posts ) { } ,
indexOptions : { } ,
searchOptions : { } ,
debug : false
} ) ;
La clé API de contenu public pour accéder aux données du blog.
exemple :
'22444f78447824223cefc48062'
Le nom de domaine complet de l'API Ghost.
exemple :
'https://demo.ghost.io'
par défaut :
window.location.origin
Définissez la version de l'API Ghost. Travaillez avec
'v2'
et'v3'
.par défaut :
'v3'
Définissez la stratégie de chargement de la bibliothèque. Il peut être déclenché lorsque la page HTML a été chargée, à la demande lorsque l'utilisateur clique sur la barre de recherche ou jamais.
Pour déclencher vous-même l'initialisation de la barre de recherche, définissez cette valeur sur
false
(booléen). De cette façon, vous pouvez appelersearchinGhost.loadData()
lorsque le reste de votre code est prêt.valeurs attendues :
'page'
,'focus'
oufalse
par défaut :
'focus'
Choisissez quand la requête de recherche doit être exécutée. Pour effectuer une recherche sur chaque frappe de touche utilisateur et soumission de formulaire, utilisez
'keyup'
. Pour rechercher uniquement lorsque l'utilisateur soumet le formulaire via un bouton ou en saisissant la touche « Entrée », utilisez'submit'
. Si vous souhaitez en avoir un contrôle complet à partir de votre propre code javascript, utilisezfalse
(booléen) et exécutez la recherche par vous-même en utilisantsearchinGhost.search("...")
.valeurs attendues :
'keyup'
,'submit'
oufalse
par défaut :
'keyup'
Définissez le nombre maximum de publications renvoyées par une requête de recherche. Toute valeur comprise entre
1
et50
sera ultra-rapide et une valeur inférieure à1000
ne devrait pas trop dégrader les performances. Mais n’oubliez pas que lorsque le moteur de recherche atteint cette limite, il arrête de creuser et renvoie les résultats : plus le niveau est bas, mieux c’est.Même si cela est fortement déconseillé, fixez cette valeur à
0
pour afficher tous les résultats disponibles.par défaut :
10
[Obsolète] Avant
v1.6.0
, ce champ était unestring
, ce comportement est obsolète.Votre site Web peut avoir une ou plusieurs barres de recherche, chacune d'elles doit avoir un attribut
id
HTML unique. Mettez chaqueid
de barre de recherche dans ce tableau. N'incluez pas « # » dans le nom.Si vous n'avez besoin d'aucun champ de saisie, définissez la valeur sur
[]
(tableau vide) et définissez égalementsearchOn
surfalse
(booléen). Ensuite, lancez une recherche en utilisantsearchinGhost.search("<your query>")
.par défaut :
['search-bar']
[Obsolète] Avant
v1.6.0
, ce champ était unestring
, ce comportement est obsolète.Votre site Web peut utiliser un ou plusieurs éléments HTML pour afficher les résultats de la recherche. Ce tableau fait référence à tous les attributs
id
de ces éléments de sortie. Si l'un de ces éléments possède déjà un contenu, celui-ci sera écrasé par les résultats de la recherche.Si vous utilisez un framework JS pour afficher les résultats de la recherche, définissez cette valeur sur
[]
(tableau vide). Vous obtiendrez les publications trouvées comme valeur renvoyée par la fonctionsearchinGhost.search("<your query>")
.par défaut :
['search-results']
[Obsolète] Avant la
v1.6.0
, ce champ était unestring
. cela est obsolète.Chaque résultat de recherche est enveloppé dans un élément enfant avant d'être ajouté à l'élément parent
outputId
. Le type par défaut estli
mais vous pouvez le définir sur n'importe quel élément HTML valide (voir la documentation MDN).Si vous ne souhaitez pas utiliser un élément d'habillage pour ajouter directement les résultats de
template
etemptyTemplate
à l'élément de sortie, définissez la valeur surfalse
(booléen).par défaut :
'li'
Un tableau de tous les champs de publications souhaités. Tous ces champs deviendront disponibles dans la fonction
template
pour afficher des informations utiles sur les publications.Référez-vous à la documentation officielle "champs".
Remarque : si vous utilisez
'custom_excerpt'
, son contenu sera automatiquement placé dans'excerpt'
pour faciliter la création de modèles.par défaut :
['title', 'url', 'excerpt', 'custom_excerpt', 'published_at', 'feature_image']
Ce tableau vous permet d'utiliser des champs supplémentaires comme
tags
ouauthors
. Personnellement, je ne sais pas pourquoi ils ne le sont pas avec les autres "champs" mais l'API Ghost est conçue de cette façon...Définissez sa valeur sur
[]
(tableau vide) pour le désactiver complètement.Reportez-vous à la documentation officielle "inclure".
par défaut :
['tags']
Cela correspond à l'API Ghost "formats" qui permet de récupérer le contenu des articles en HTML ou en texte brut.
Définissez sa valeur sur
[]
(tableau vide) pour le désactiver complètement.Veuillez vous référer à la documentation officielle "formats".
par défaut :
['plaintext']
Liste des champs indexés. Le contenu de tous ces champs sera consultable.
Toutes les valeurs de cette liste doivent être définies dans les messages. Sinon, le résultat de la recherche ne sera pas précis mais l'application ne plantera pas ! Vérifiez les valeurs
postsFields
,postsExtraFields
etpostsFormats
.NOTE : le champ bizarre
'string_tags'
est ajouté dans l'optioncustomProcessing
. Si vous souhaitez utiliser des balises, cette chose laide est nécessaire (pour l'instant) car FlexSearch ne peut pas gérer correctement les tableaux. Si vous ne le souhaitez pas, remplacez lecustomProcessing
pour renvoyer uniquementposts
sans modification supplémentaire. Si vous décidez d'utiliser des balises, veuillez également utiliser'string_tags'
ici.par défaut :
['title', 'string_tags', 'excerpt', 'plaintext']
Définissez votre propre modèle de résultat. Ce modèle sera utilisé pour chaque publication trouvée pour générer le résultat et ajouté en tant qu'élément enfant à l'élément de sortie. Il n'y a pas de moteur de création de modèles, juste une fonction javascript native utilisant un objet
post
comme argument.Cette option de modèle est beaucoup plus puissante que ce à quoi vous pourriez vous attendre. On peut aussi y penser comme une fonction de traitement personnalisé appelée sur les résultats de recherche. Par exemple, si vous souhaitez effectuer un filtrage, ne renvoyez rien (par exemple
return;
) ou une chaîne vide (par exemplereturn "";
) pour supprimer un élément.Veuillez noter l'utilisation de guillemets (par exemple « ») au lieu de guillemets simples/doubles. Ceci est nécessaire pour activer l'interpolation de variables javascript très utile.
Les variables disponibles sont celles définies dans l'option
postsFields
.exemple:
template: function ( post ) { return `<a href=" ${ post . url } "># ${ post . tags } - ${ post . published_at } - ${ post . title } </a>` }
Définissez votre propre modèle de résultat lorsqu'aucun résultat n'est trouvé.
exemple:
emptyTemplate: function ( ) { return '<p>Sorry, nothing found...</p>' }
Vous devez apporter des modifications supplémentaires aux données de publication récupérées depuis Ghost ? Utilisez cette fonction pour faire tout ce dont vous avez besoin. Cette fonction est appelée à chaque publication, exécutée après
onFetchEnd()
et avantonIndexBuildStart()
.Si vous souhaitez supprimer une publication, renvoyez toute valeur fausse JS (par exemple
null
,undefined
,false
,""
, ...).Pour déboguer facilement vos entrées/sorties, utilisez
onFetchEnd()
etonIndexBuildEnd()
pour afficher le résultat avec unconsole.log()
. Si vous êtes un utilisateur plus avancé, la meilleure option reste d’utiliser le débogueur. N'oubliez pas non plus de nettoyer votre cache local lors des tests !note : par défaut, cette option est déjà remplie d'une fonction d'assistance pour faciliter l'utilisation du champ "tags" dans les posts. Voir les options
indexedFields
.exemple:
customProcessing: function ( post ) { post . extra_field = "hello" ; return post ; }
Définissez le format de date extrait des publications.
Consultez la référence MDN pour obtenir plus d’informations.
exemple:
date: { locale : "fr-FR" , options : { weekday : 'long' , year : 'numeric' , month : 'long' , day : 'numeric' } }
Définissez l’âge maximum du cache en secondes. Pendant ce laps de temps, si un index déjà existant est trouvé dans le stockage local, il sera chargé sans aucune requête HTTP supplémentaire pour confirmer sa validité. Lorsque le cache est purgé, la valeur est réinitialisée.
Ceci est particulièrement utile pour économiser les charges haut débit et réseau de votre serveur. La valeur par défaut est définie sur une demi-heure. Cette valeur provient de la durée de session utilisateur par défaut utilisée par Google Analytics.
par défaut :
1800
Définissez une fonction de rappel avant de récupérer les données de l'API Ghost.
Cette fonction ne prend aucun argument.
exemple:
onFetchStart: function ( ) { console . log ( "before data fetch" ) ; }
Définissez une fonction de rappel lorsque la récupération est terminée. Même si les modifications apportées aux
posts
sont conservées, nous recommandons d'utiliser la fonctioncustomProcessing()
pour ce faire.La fonction prend un argument : le tableau de toutes les publications renvoyées par Ghost lui-même.
exemple:
onFetchEnd: function ( posts ) { console . log ( "Total posts found on Ghost:" , posts . length ) ; }
Définissez une fonction de rappel avant de commencer à créer l'index de recherche.
La fonction ne prend aucun argument.
exemple:
onIndexBuildStart: function ( ) { console . log ( "before building the index" ) ; }
Définissez une fonction de rappel lorsque la création de l'index de recherche est terminée.
La fonction prend un argument : l'objet d'index de construction FlexSearch.
exemple:
onIndexBuildEnd: function ( index ) { console . log ( "index built:" , index ) ; }
Définissez une fonction de rappel avant de commencer à exécuter la requête de recherche. Par exemple, il pourrait être utilisé pour masquer l'élément HTML des résultats en attendant la fin
onSearchEnd
ou pour ajouter des effets de transition sophistiqués. Mais dans la plupart des cas, cela n’est pas nécessaire car la fonction de recherche est suffisamment rapide pour être agréable à regarder.La fonction ne prend aucun argument.
exemple:
onSearchStart: function ( ) { console . log ( "before executing the search query" ) ; }
Définissez une fonction de rappel lorsque les résultats de la recherche sont prêts.
La fonction prend 1 argument : le tableau des publications correspondantes.
exemple:
onSearchEnd: function ( posts ) { console . log ( "search complete, posts found:" , posts ) ; }
Ajoutez une configuration d’index de recherche supplémentaire ou remplacez celles par défaut. Ces options seront fusionnées avec celle déjà fournie :
{ doc : { id : "id" , field : this . config . indexedFields } , encode : "simple" , tokenize : "forward" , threshold : 0 , resolution : 4 , depth : 0 }Utilisez également ce paramètre pour activer la prise en charge des langues non latines, voir cette section.
défaut:
{}
Conçu pour les utilisateurs avancés, vous permet d'affiner les requêtes de recherche. Reportez-vous à cette documentation FlexSearch.
Nous utilisons cette construction de requête spécifique :
index.search("your query", searchOptions)
donc tout ce qui est ajouté àsearchOptions
sera transmis à FlexSearch de cette façon.Ce paramètre peut être très utile lors du filtrage des publications en fonction d'une balise. A titre d'exemple :
searchOptions: { where : { string_tags : "getting started" } }Notez également que l'option
limit
Searchinghost est automatiquement fusionnée danssearchOptions
. Dans notre cas, cela deviendrait finalement :searchOptions: { where : { string_tags : "getting started" } , limit : 10 }défaut:
{}
Lorsque quelque chose ne fonctionne pas comme prévu, définissez-le sur
true
pour afficher les journaux d'application.par défaut :
false
Si votre blog utilise une langue à alphabet latin (par exemple anglais, français, espagnol) ou une langue d'Europe du Nord/de l'Est (par exemple allemand, suédois, hongrois, slovène, estonien), la configuration par défaut fonctionnera très bien. Dans les autres cas, recherchez la valeur indexOptions
appropriée et ajoutez-la à votre configuration SearchinGhost principale.
Pour créer vos propres paramètres spécifiques, reportez-vous au README FlexSearch et à ces trois problèmes.
Si rien ne fonctionne pour vous ou si le comportement qui en résulte n'est pas correct, n'hésitez pas à créer un problème.
indexOptions: {
encode : false ,
rtl : true ,
split : / s+ /
}
indexOptions: {
encode : false ,
tokenize : function ( str ) {
return str . replace ( / [x00-x7F] / g , "" ) . split ( "" ) ;
}
}
Cette option peut être utilisée par toutes les langues de mots séparés par des espaces qui utilisent des caractères complexes.
indexOptions: {
encode : false ,
split : / s+ /
}
Si vous devez utiliser plusieurs types de langues (par exemple cyrillique/anglais ou indien/espagnol), utilisez la configuration dédiée ci-dessous. Je sais, cela peut paraître effrayant à première vue, mais copiez/collez-le et faites-moi confiance.
indexOptions: {
split : / s+ / ,
encode : function ( str ) {
var regexp_replacements = {
"a" : / [àáâãäå] / g ,
"e" : / [èéêë] / g ,
"i" : / [ìíîï] / g ,
"o" : / [òóôõöő] / g ,
"u" : / [ùúûüű] / g ,
"y" : / [ýŷÿ] / g ,
"n" : / ñ / g ,
"c" : / [ç] / g ,
"s" : / ß / g ,
" " : / [-/] / g ,
"" : / ['!"#$%&\()*+,-./:;<=>?@[]^_`{|}~] / g ,
" " : / s+ / g ,
}
str = str . toLowerCase ( ) ;
for ( var key of Object . keys ( regexp_replacements ) ) {
str = str . replace ( regexp_replacements [ key ] , key ) ;
}
return str === " " ? "" : str ;
}
}
Dans un premier temps, nous avons également essayé ces autres solutions : Lunr.js, minisearch et fuse.js. Au final, FlexSearch offrait les meilleurs résultats globaux avec des résultats rapides et précis , une taille de bundle suffisamment petite et il était également facile à installer/configurer. Il y a tout à choisir !
Pas de soucis, c'est normal. SearchinGhost utilise un système de cache pour stocker les données de votre blog dans le navigateur et limiter les interactions réseau. Par défaut, les données mises en cache stockées il y a moins de 30 minutes sont toujours considérées comme valides. Passé ce délai, le nouvel article sera à votre disposition.
Gardez à l’esprit que les autres utilisateurs n’auront peut-être pas besoin d’attendre 30 minutes selon la dernière fois qu’ils ont effectué une recherche. Si vous l'étiez il y a 1h, leur cache sera purgé et renouvelé afin que l'article apparaisse.
Si vous souhaitez que vos utilisateurs soient toujours parfaitement à jour, définissez le cacheMaxAge
sur 0
. Ce faisant, vous devez également définir loadOn
sur 'focus'
pour limiter le nombre de requêtes HTTP.
Par défaut, lorsque vous utilisez la variable URL feature_image
pour afficher des images dans vos résultats de recherche, vous obtiendrez toujours celle d'origine/pleine taille et elles sont généralement trop grandes (en taille et en poids) pour nos besoins, une miniature serait préférable. ajuster.
Depuis Ghost V3, un moteur de traitement multimédia est intégré pour créer des images réactives. Par défaut, Ghost recrée 6 images différentes de celle donnée. Les tailles disponibles sont : w30
, w100
, w300
, w600
, w1000
, w2000
.
Dans notre cas, le moyen le plus simple de charger des images plus rapidement consiste simplement à utiliser des images plus petites. En gros, nous voulons que cette URL https://www.example.fr/content/images/2020/05/picture.jpg
(celle par défaut récupérée depuis l'API Ghost) devienne https://www.example.fr/content/images/size/w600/2020/05/picture.jpg
(celui de largeur 600px).
Pour ce faire, mettez à jour la configuration en ajoutant un champ "customProcessing"
avec l'exemple de code suivant. Bien sûr, vous pouvez utiliser n'importe quelle taille disponible mentionnée ci-dessus au lieu de w600
.
customProcessing: function ( post ) {
if ( post . tags ) post . string_tags = post . tags . map ( o => o . name ) . join ( ' ' ) . toLowerCase ( ) ;
if ( post . feature_image ) post . feature_image = post . feature_image . replace ( '/images/' , '/images/size/w600/' ) ; // reduce image size to w600
return post ;
}
Cette modification n'est pas immédiate, il faut un rafraîchissement du cache pour réellement voir la différence.
Créez un élément HTML avec l'ID "search-counter"
et utilisez la fonction onSearchEnd()
pour le remplir avec le résultat. Voici un exemple :
< p id =" search-counter " > </ p >
onSearchEnd: function ( posts ) {
var counterEl = document . getElementById ( 'search-counter' ) ;
counterEl . textContent = ` ${ posts . length } posts found` ;
}
Oui, en utilisant les méthodes internes de SearchinGhost mais c'est possible. Cela peut ressembler à de la magie noire, mais ajoutez le code ci-dessous à votre configuration actuelle. Ici, searchinGhost
fait référence à votre propre instance créée avec new SearchinGhost(...)
.
emptyTemplate: function ( ) {
var allPostsArray = Object . values ( searchinGhost . index . l ) ;
var latestPosts = allPostsArray . slice ( 0 , 6 ) ;
searchinGhost . display ( latestPosts ) ;
}
Si vous utilisez un framework comme React, Vue ou Angular, vous ne souhaitez probablement pas laisser SearchinGhost manipuler le DOM par lui-même. Parce que vous devez absolument conserver toute mise à jour de contenu dans votre cadre, voici la configuration que vous devez utiliser :
var searchinGhost = new SearchinGhost ( {
key : '<CONTENT_API_KEY>' ,
inputId : false ,
outputId : false ,
[ ... ]
} ) ;
Maintenant, pour exécuter une requête de recherche, appelez cette méthode SearchinGhost :
var postsFound = searchinGhost . search ( "my query" ) ;
// Where 'postsFound' content looks like:
[
{
"title" : "A Full and Comprehensive Style Test" ,
"published_at" : "Sep 1, 2012" ,
[ ... ]
} ,
{
"title" : "Publishing options" ,
"published_at" : "Aug 20, 2018" ,
[ ... ]
}
]
De cette façon, rien ne sera rendu dans votre dos et tout restera sous contrôle dans le shadowDom.
debug: true
onFetchStart()
, onSearchStart()
, ... Désormais, toute modification est tracée dans ce fichier CHANGELOG.md dédié.
Toute contribution est plus que bienvenue ! Si vous avez trouvé un bug ou souhaitez améliorer le code, n'hésitez pas à créer un problème ou un PR.
Toutes les mises à jour du code doivent être effectuées sous le répertoire src
.
Pour construire le projet par vous-même, exécutez :
$ npm install
$ npm run build
Lors du développement, utilisez plutôt la commande watch, elle se reconstruira plus rapidement à chaque modification de fichier et inclura un lien vers la carte source ce qui facilitera le débogage.
$ npm run watch
Remarque : lors de la création de ce projet, j'utilise Node v12.16.2 avec NPM v6.14.4, mais il devrait également fonctionner avec des versions plus anciennes/plus récentes.
SearchinGhost n'est pas seul dans le domaine des plugins de recherche Ghost. Voici une courte liste d’autres projets connexes. Vous devriez absolument les essayer pour voir s’ils répondent mieux à vos besoins :
GhostHunter (v0.6.0 - 101 Ko, 26 Ko gzip)
Avantages :
- Le plus connu, de nombreux articles et tutoriels à ce sujet
- Un système de cache puissant basé sur localStorage
- Indexation du texte intégral (pas seulement le titre des articles)
Inconvénients :
- S'appuie sur jQuery
- Fonctionne uniquement avec l'API Ghost v2 (pour l'instant)
- Le code source est devenu compliqué avec le temps
recherche fantôme (v1.1.0 - 12 Ko, 4,2 Ko gzip)
Avantages :
- Base de code bien écrite et facile à lire
- Tirer parti des capacités « floues »
Inconvénients :
- Le navigateur est en retard lors de la recherche de mots longs
- Peut envoyer trop de requêtes API
- N'utilise pas de système de notation pour afficher les meilleurs résultats en premier
Ghost Finder (v3.1.2 - 459 Ko, 116 Ko gzip)
Avantages :
- Bibliothèque Javascript pure
Inconvénients :
- La taille massive du paquet final
- Envoyez une requête HTTP pour chaque touche enfoncée !
- N'utilise pas de moteur de recherche, recherche uniquement les sous-chaînes dans les titres des articles
- N'indexe pas correctement les caractères accentués (par exemple, 'é' doit être trouvé avec 'e')