Gérer un site ReadMe.io à partir d’un dépôt Git

illustrations illustrations illustrations illustrations illustrations illustrations illustrations
post-thumb

Publié le 19 mai 2022 par Andrew Owen (6 minutes)

ReadMe.io est un site populaire de documentation pour les utilisateurs. Il dispose d’un éditeur Markdown, d’un constructeur de thèmes et de l’importation de fichiers Swagger / OpenAPI. Il est rapide et réactif, et il est beau. Mais la dernière fois que j’ai vérifié, tout votre contenu va dans un seau auquel vous n’avez pas d’accès direct.

Il en résulte que si vous souhaitez apporter des modifications à des documents, par exemple changer le nom d’un produit, vous devez éditer les documents individuellement. Il serait bien plus agréable de pouvoir accéder directement au référentiel dans VS Code et d’effectuer des modifications à l’échelle du site.

Même si cela n’est pas pris en charge, il existe quelques fonctionnalités dans Readme.io qui peuvent vous permettre de prendre le contrôle de vos données. Tout d’abord, vous pouvez exporter votre contenu. Deuxièmement, Readme.io dispose d’une API. Vous devrez toujours effectuer certaines tâches dans l’interface web. Mais pour l’essentiel, vous pouvez conserver vos données dans un dépôt Git, apporter des modifications locales et utiliser l’API pour transférer vos modifications sur votre site.

API de ReadMe.io

Lorsque j’ai commencé, j’ai trouvé utile d’utiliser Postman pour interroger le site Readme.io. Vous pouvez sauvegarder cette collection en tant que readme.postman_collection.json:

{
"info": {
"_postman_id": "<!--insert your postman ID here-->",
"name": "readme.io",
"schema": "[https://schema.getpostman.com/json/collection/v2.1.0/collection.json](https://schema.getpostman.com/json/collection/v2.1.0/collection.json "https://schema.getpostman.com/json/collection/v2.1.0/collection.json")"
},
"item": \[
{
"name": "Get doc",
"request": {
"method": "GET",
"header": \[\],
"url": {
"raw": "[https://dash.readme.com/api/v1/docs/](https://dash.readme.com/api/v1/docs/ "https://dash.readme.com/api/v1/docs/"){{slug}}",
"protocol": "https",
"host": \[
"dash",
"readme",
"com"
\],
"path": \[
"api",
"v1",
"docs",
"{{slug}}"
\]
}
},
"response": \[\]
},
{
"name": "Get category ID",
"request": {
"method": "GET",
"header": \[\],
"url": {
"raw": "[https://dash.readme.com/api/v1/docs/get-category-id](https://dash.readme.com/api/v1/docs/get-category-id "https://dash.readme.com/api/v1/docs/get-category-id")",
"protocol": "https",
"host": \[
"dash",
"readme",
"com"
\],
"path": \[
"api",
"v1",
"docs",
"get-category-id"
\]
}
},
"response": \[\]
},
{
"name": "Update doc",
"request": {
"method": "PUT",
"header": \[\],
"body": {
"mode": "raw",
"raw": "{\\n \\"title\\": \\"{{title}}\\",\\n \\"excerpt\\": \\"{{excerpt}}\\",\\n \\"category\\": \\"{{category}}\\",\\n \\"hidden\\": {{hidden}},\\n \\"body\\": \\"{{body}}\\"\\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "[https://dash.readme.com/api/v1/docs/](https://dash.readme.com/api/v1/docs/ "https://dash.readme.com/api/v1/docs/"){{slug}}",
"protocol": "https",
"host": \[
"dash",
"readme",
"com"
\],
"path": \[
"api",
"v1",
"docs",
"{{slug}}"
\]
}
},
"response": \[\]
},
{
"name": "Delete doc",
"request": {
"method": "DELETE",
"header": \[\],
"url": {
"raw": "[https://dash.readme.com/api/v1/docs/](https://dash.readme.com/api/v1/docs/ "https://dash.readme.com/api/v1/docs/"){{slug}}",
"protocol": "https",
"host": \[
"dash",
"readme",
"com"
\],
"path": \[
"api",
"v1",
"docs",
"{{slug}}"
\]
}
},
"response": \[\]
},
{
"name": "Create doc",
"request": {
"method": "POST",
"header": \[\],
"body": {
"mode": "raw",
"raw": "{\\n \\"title\\": \\"{{title}}\\",\\n \\"excerpt\\": \\"{{excerpt}}\\",\\n \\"category\\": \\"{{category}}\\",\\n \\"hidden\\": true,\\n \\"body\\": \\"{{body}}\\"\\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "[https://dash.readme.com/api/v1/docs](https://dash.readme.com/api/v1/docs "https://dash.readme.com/api/v1/docs")",
"protocol": "https",
"host": \[
"dash",
"readme",
"com"
\],
"path": \[
"api",
"v1",
"docs"
\]
}
},
"response": \[\]
},
{
"name": "Search docs",
"request": {
"method": "POST",
"header": \[\],
"url": {
"raw": "[https://dash.readme.com/api/v1/docs/search?search=sphinx](https://dash.readme.com/api/v1/docs/search?search=sphinx "https://dash.readme.com/api/v1/docs/search?search=sphinx")",
"protocol": "https",
"host": \[
"dash",
"readme",
"com"
\],
"path": \[
"api",
"v1",
"docs",
"search"
\],
"query": \[
{
"key": "search",
"value": "sphinx"
}
\]
}
},
"response": \[\]
}
\],
"auth": {
"type": "basic",
"basic": \[
{
"key": "username",
"value": "{{apiKey}}",
"type": "string"
}
\]
},
"event": \[
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": \[
""
\]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": \[
""
\]
}
}
\],
"variable": \[
{
"key": "category\\n",
"value": "<!--get the category ID from the web interface-->"
},
{
"key": "slug",
"value": "sandbox"
},
{
"key": "title",
"value": "Sandbox"
},
{
"key": "hidden",
"value": "true"
},
{
"key": "body",
"value": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
\]
}

Importez la collection dans Postman et utilisez l’authentification de base avec la clé API comme nom d’utilisateur et un mot de passe vide.

Créer un document

Ce point d’accès nécessite ces attributs:

  • title – le nom tel que vous voulez qu’il soit affiché sur le site.
  • category – UUID
  • hidden – false
  • body – Chaîne JSON

L’attribut hidden (caché) est toujours positionné à true. L’étape finale de la publication, après avoir revu le contenu tel qu’il apparaîtra, consiste à mettre cet attribut à false.

À moins que j’aie oublié quelque chose, lorsque j’ai conçu cette solution, il n’était possible de créer des catégories que sur Readme.io. Mais il existe une API pour cela (https://docs.readme.com/reference/createcategory “create category API”). Je n’ai pas actuellement d’abonnement actif à Readme.io à tester, je vous laisse donc le soin d’ajouter ces points de terminaison à la collection Postman.

Les articles peuvent être publiés sous des articles existants. Dans ce cas, vous devez faire un GET sur l’article parent pour obtenir l’ID de la catégorie.

Convertir Markdown en chaîne JSON avec JQ

Readme.io stocke les articles au format Markdown (avec un en-tête YAML). Mais l’API requiert des données au format JSON. Heureusement, il existe un outil en ligne de commande appelé JQ qui peut encapsuler le Markdown dans une chaîne JSON. Cela formera l’attribut body. A partir de l’interface de commande, entrez: jq -R -s . <nomdufichier.md > nomdufichier.txt.

Pousser les changements de votre référentiel vers le site live

J’ai écrit un script Bash pour mettre à jour automatiquement tous les fichiers .md d’un référentiel en utilisant la méthode PUT. C’est un peu un hack. Il nécessite que le jeton $AUTH soit défini, et il ne fonctionnera que sur les fichiers dont l’en-tête fait exactement huit lignes.

\---
title: "article title"
category: "category UUID"
excerpt: "article description"
hidden: true
createdAt: "2022-05-19T00:00:00.000Z"
updatedAt: "2022-05-19T10:00:00.001Z"
\---

Par défaut, les articles téléchargés depuis Readme.io incluent les métadonnées slug mais pas les métadonnées category. Puisque la balise est dérivée du nom de fichier, vous devez remplacer les métadonnées slug par les métadonnées category et leur donner l’UUID approprié pour l’intitulé de la catégorie dans laquelle ils apparaissent.

Note: Si vous n’incluez pas de définition excerpt, vous devez vous assurer que le texte body commence à la ligne 9 du fichier.

Voici le script Bash. Sauvegardez-le sous le nom md2json.sh dans le dossier v1.0 de votre site exporté.

export AUTH="<!--your AUTH token-->"
for subdir in *; do
test -d "$subdir" || continue
echo $subdir
cd "$subdir"
for f in _.md; do
export SLUG=${f%%._}
sed '1,8d' $f > "$SLUG.tmp"
sed '6,$d' $f > "$SLUG.yml"
jq -R -s . < "$SLUG.tmp" > "$SLUG.bdy"
rm "$SLUG.tmp"
printf "body: " >> "$SLUG.yml"
cat "$SLUG.bdy" >> "$SLUG.yml"
yq < "$SLUG.yml" > "$SLUG.json"
rm "$SLUG.bdy"
rm "$SLUG.yml"
curl -X PUT -H 'Content-Type: application/json'   
\-H "Authorization: Basic $AUTH"   
\-d "$(<$SLUG.json)"   
https://dash.readme.com/api/v1/docs/$SLUG
rm "$SLUG.json"
done
cd ..
done

Gestion des images

La dernière partie du puzzle est la gestion des images. Au moment où j’écris ces lignes, je ne connais pas de moyen de télécharger des images à l’aide de l’API. Je vous suggère de conserver un article caché sur le site web et d’y ajouter des images à l’aide de l’interface web. Readme.io renommera le fichier et lui attribuera un identifiant. Vous pouvez ensuite extraire ces informations de l’article. J’ajouterais ensuite une copie de l’image avec ce nom de fichier modifié à votre dépôt (au cas où vous souhaiteriez migrer vers une autre solution de documentation). Cela vous permettra également de prévisualiser votre contenu localement avant de l’envoyer sur le site.