Journal d'un Terrien

Web log de Serge Boisse

On line depuis 1992 !

Publicité
Si cette page vous a plu, Copiez son adresse et partagez-la !
http://sboisse.free.fr/programmation/Publier des notes Obsidian sur le web/Obsidian Share.php
Savez-vous quels sont les articles les plus vendus sur Amazon.fr ?
Obsidian Share

Obsidian share

C'est quoi Obsidian Share ?

C'est un convertisseur Markdown (tuto) vers HTML qui reproduit à l'identique ce que l'on voit dans la preview d'Obsidian (mais pour une note seulement) ; il faut refaire la manip pour chaque fichier. Obsidianshare transfère aussi le fichier HTML sur le serveur web, et éventuellement les CSS, fonts.. si ce n'est déjà fait.

Voir aussi: mettre ici des liens entre vers des sujets voisins
_Publier le contenu d'Obsidian sur un site
@ Markdown en HTML(lien privé)

ressources

Source sur GitHub : Obsidian share (page web)

fonctionnalités

🔹 Local and remote image support.

🔹 Supports anything that Obsidian Preview mode does, like rendered Dataview queries and any custom CSS you might have enabled.

🔹 Supports callouts with full styling:

🔹 Filenames are anonymised through hashing so people can't discover your other shared notes.

🔹 If your shared note links to another note which is also shared, that link will also function on the shared webpage.

🔹 Frontmatter is stripped on upload to avoid leaking unwanted data.

Premier test

On peut utiliser la note galerie formats markdown qui contient un échantillon de texte formatté...

J'ai créé un virtual host "TestObsidianShare" sur mon serveur Wampserver, j'y ai mis le "point d'accès" upload.php, Voir TestObsidianShare (Répertoire sur D)(lien privé)

j'ai paramétré le script obsidian_share.js (voir GitHub) pour y mettre l'adresse de ce serveur et de ce fichier :

  • YAML_FIELD - The frontmatter field prefix for storing share link and updated time. A value of share will create frontmatter fields of share_link and share_updated.
  • UPLOAD_LOCATION - The root path for uploaded files. Needs to end with a trailing slash.
  • UPLOAD_ENDPOINT - Path to the upload endpoint relative to upload location.
  • SECRET - Authentication secret for file uploading. See the simple upload script at the bottom for an example.
  • SHOW_FOOTER - Turn the "Published with Obsidian Share" footer on or off. You can also replace the footer text with anything you want by editing the footer variable in the code.

J'ai créé les modèles templater S_Obsidian Share Wamp(lien privé) et S_Obsidian Share Site(lien privé) avec le code js à l'intérieur.
Ensuite, aller dans la note ci-dessus, CTRL-P, templater, "insert modal" (ou bien simplement ALT-i) et choisir le modèle S_Obsidianshare_wamp... ça marche ! 😊 encore plus simple, j'ai crée le raccourci Templater ALT-P

résultat

cf le site local : Galerie markdown (page web)

il faut lancer le serveur web wamp64. Rendu pas visible hors de chez moi.

Tout le contenu de la note est rendu correctement dans Chrome, avec le style du thème (j'utilise Blue Topaz, light mode), et les snippets sauf le style **_ texte _** En dégradé mais bon... il n'est pas documenté.

Les transclusions ![[...]] fonctionnent ! (si la note source est sur le site...) Elles deviennent inline ce qui est normal pour un document publié.

Les checkboxes ont le bon style, elles sont actives, mais le style disparait lorsqu'on clique deux fois dessus.

Le résultat de DataviewJS est affiché, mais sans l'interaction avec les composants html actifs (boutons...). C'est normal, il n'y a pas de js dans les fichiers générés.

Les callouts "dépliants" ne marchent pas. (faute de javascript...)

obsidian-execute-code ? ne marche pas mais le bouton run est là

Plus embêtant les liens web fonctionnent, mais pas les liens internes ?
Essayons de publier une autre note, par exemple... celle-ci même. OK...
Le lien avec la première note ne semble pas marcher... Mais en re-publiant , YES !

Toutes les notes se retrouvent au même endroit à la racine du serveur (ou du répertoire paramétré dans le .js), avec des noms cryptés (pas terrible pour le référencement)

Test sur mon site free

Là ça ne marche pas... La raison est que Free pages perso utilise PHP 4.4.3, version antédiluvienne... Pas sûr que même en réécrivant le fichier "upload", ça fonctionne. Mais bon, mon idée n'est pas de publier directement le site.

Comment ça marche

Le script appelé par Templater crée un tas de fichiers dont le nom est crypté dans le répertoire du serveur :

  • les fichiers .jpg des images de la page,
  • des fichiers .woff2" (polices de caractères)
  • ainsi qu'un fichier html pour la page
    plus un énorme fichier "style.css" (3 Mo !)
ce fichier fait planter notepad++ !

En libérant de la mémoire, on peut l'afficher. Cela semble être le CSS complet d'obsidian !

Correction d'un bug : j'ai modifié une ligne dans obsidian_share.js

}).filter(Boolean).join('').replace(/\n/g, '')
remplacé par
}).filter(Boolean).join('\n')
Résultat : 1) fichier CSS ne fait plus planter notepad++, (cause ligne trop longue je pense)
2) Desmos fonctionne !

Warning

Par contre la partie du fichier CSS pour MathJax appelle des fontes sur le web, et donc erreur CORS. vu sur le débugger (pas trop grave)

le cryptage

Le nom de la note note est crypté (par le fichier js) afin que personne ne puisse tomber dessus par hasard en explorant le site, d'autant qu'elles sont toutes dans le même répertoire. Le nom crypté = sha256(path avec nom)

Il y a un autre cryptage pour le transfert : Le cryptage est simple : il y un code secret, qui est connu du seul script javascript off-line (dans le coffre), et du fichier "upload.php" sur le site.

Lors de l'upload, le script js utilise un "nonce" qui est un timestamp en milisecondes, il le concatène avec le code secret, et crypte le résultat en SHA256. Puis il crée un fichier JSON qui contient cinq champs : "auth" (le nonce crypté), "nonce" (le même non crypté), "filename", "encoding" et "content". Enfin il envoie ce fichier vers le upload.php sur le site.

Sur le site, le script php crypte à nouveau le nonce+code secret, et vérifie que le résultat est égal à auth.
Si c'est OK, il stocke le fichier sur le site après décodage éventuel selon l'encodage.

Le CSS

il est créé à la volée en par le script js qui demande à Obsidian tous les CSS requis par les éléments dans la note. j'ai pu le dé-minifier en utilisant le débugger Chrome, car en chargeant une note html générée par Chrome il y a une erreur 404 sur GET http://testobsidianshare/public/images/874d8b8e340f75575caa.svg avec un lien vers le CSS. est intéressant de noter que les premières lignes de ce CSS commencent par des choses comme

.ͼ1.cm-editor.cm-focused {
    outline: rgb(33, 33, 33) dotted 1px;
}

et que le caractère "ͼ" (sigma lunaire pointé) me semble faire référence à la fenêtre de l'application obsidian elle-même.
Le CSS utilise plein de définitions personnalisées cf trucs HTML remarqués > trucs CSS
Il contient des liens de chargements vers "public/images", c'est à dire les répertoires de Essai de clone de Obsidian Help...

Je recopie donc le dossier "public" vers ObsidianShare...

Petit test avec la note galerie formats markdown (page web locale sur wamp)(lien privé)
Le format est bon, mais le débugger montre plein d'erreurs dus à des chargement de fontes woff pour Mathjax qui ne marchent pas. Je récupère ces fontes, je les mets dans un nouveau dossier : D:\wamp64\www\TestObsidianShare\public\fonts\MathJax
Puis je modifie le script js (qui va générer le CSS) en remplaçant }).filter(Boolean).join('').replace(/\n/g, '') par }).filter(Boolean).join('').replaceAll('app://obsidian.md/lib/mathjax/output/chtml/fonts/woff-v2/','public/fonts/MathJax/')
Effacer le frontmatter share_updated: et share_link: dans Obsidian,
puis relancer le script par ALT-i) modèle S_Obsidianshare_wamp
--> plus aucune erreur 😊

petite expérience

pour ajouter de l'interactivité : J'ai pris un fichier html généré par Obsidian share, et j'ai ajouté la ligne <script defer src="app.js"></script> à la fin du head. J'ai copié le app.js (l'API obsidian) que j'avais récupéré (cf Essai de clone de Obsidian Help) dans le répertoire TestObsidianShare du serveur, ça ne change rien...

Mais apparemment c'est parce que app.js a besoin du purify.. je l'installe (npm) et je l'appelle depuis mon html avant app.js. --> plus d'erreur, mais ça change toujours rien.
Bon ces fichiers ne serveur à rien dans mon cas.

Mes ajouts

L'interaction sur la page

Cela consiste à gérer tout ce que le lecteur (humain) de la page pourrait faire (à part scroller, redimensionner la page et cliquer sur les liens)

Commençons par regarder...

Le format du html généré

on va créer une note presque vide : Coucou callouts(lien privé) avec un callout repliable. Surprise, le titre est éditable dans Chrome !
La structure de base est relativement simple :

<body class="mod-windows is-frameless is-hidden-frameless obsidian-app theme-light show-inline-title show-view-header is-focused" style="--zoom-factor:1; --accent-h:207; --accent-s:100%; --accent-l:29%; --font-text-size:21px;">
<div class="app-container">
<div class="horizontal-main-container">
<div class="workspace">
<div class="workspace-split mod-vertical mod-root">
<div class="workspace-leaf mod-active">
<div class="workspace-leaf-content">
<div class="view-content">
<div class="markdown-reading-view" style="max-width:900px;margin: 0 auto;">
<div class="markdown-preview-view markdown-rendered node-insert-event is-readable-line-width allow-fold-headings show-indentation-guide allow-fold-lists">
<div class="markdown-preview-sizer markdown-preview-section">

Je pense que l'on pourra supprimer les premieres divs...

La largeur du texte de la note décrite dans le script est appliquée à la div markdow-reading-view
La suite (le contenu de la note) est moins lisible car il n'y a pas de retour à la ligne. Je remplace une ligne dans le script,

//  content = leaf.view.modes.preview.renderer.sections.reduce((p, c) => p + c.el.innerHTML, '')
	content = leaf.view.modes.preview.renderer.sections.reduce((p, c) => p + c.el.innerHTML, '').replaceAll("</div>","</div>\n") //serge

C'est plus lisible. La suite, donc, c'est

<div class="inline-title" contenteditable="true" spellcheck="false" tabindex="-1" enterkeyhint="done">Coucou</div>

D'où vient ce contenteditable="true" ? Bon, encore un replace à faire dans le script... done. OK pour le titre !

Suite du code html : <p>bonjour !</p> d'accord....
Et enfin le callout :

<div data-callout-metadata="" data-callout-fold="-" data-callout="note" class="callout is-collapsible is-collapsed">
<div class="callout-title">...</div>
<div class="callout-content" style="display: none;">...</div>

gestion des callouts

Quel est le script qui déplie/replie le callout ? il semble que ce soit "enhance.js"; que je recopie donc dans "scripts serge", avec App.js Ceci dit ça ne change rien non plus.
Le problème c'est que nos divs dans le html n'ont pas d'ID donc difficile à récupérer...
Bon on va utiliser un handler global (ou sur tous les callouts-title) et récupérer l'élement par

document.addEventListener('click', function(e) {
    e = e || window.event;
    var target = e.target || e.srcElement,
        text = target.textContent || target.innerText;   
}, false);
if(target.hasClass('mydivclass')) ...
target.getAttribute("data-callout-fold"))

script pour l'interaction

Je vais donc créer un nouveau script "note-interaction.js" à ajouter sur le site et à inclure dans toutes les pages (re-modif du script templater, donc)
a la fin de la section qui fabrique le head :
<script defer src="scriptsSerge/note-interaction.js"></script>
(il faudra modifier le path plus tard pour la version prod)

Après quelques galères, OK pour les callouts !

Execute-code

alert("bonjour");

cf obsidian-execute-code (mon test de ce plugin)

Il faut supprimer les boutons run et clear. Quid du bouton "copy (to clipboard)" ? Il faut l'exécuter ?

la structure du code html généré est la suivante (en dessous de <div class="markdown-preview-sizer markdown-preview-section">)
pour le code suivant :

console.log("hello");
<pre class="language-js" tabindex="0">
	<code class="language-js is-loaded">
	... le code
	</code>
	<button class="run-code-button">Run</button>
	<button class="copy-code-button">Copier</button>
	<code class="language-output">
		<hr><span class="stdout">... résultat </span>
			<input class="interactive-stdin" style="display: none;">
	</code>
	<button class="clear-button">Clear</button>
</pre>

Pour python, idem sauf que "js" est remplacé par "python"

Donc il suffit de virer les deux classes de boutons run et clear. Mais comme
on ne peut pas modifier des peudo classes comme :hover, il faut créer une nouvelle feuille de style.
On peut faire ça par programme :

var css = 'pre:hover .run-code-button, pre:hover .clear-button {diplay:none;}'
var style = document.createElement('style');

if (style.styleSheet) {
    style.styleSheet.cssText = css;
} else {
    style.appendChild(document.createTextNode(css));
}

document.getElementsByTagName('head')[0].appendChild(style);

J'en ai profité pour gérer la copie par le bouton copier, et du coup j'ai aussi ajouté la fonction creeNotice(texte) qui affiche une notice pendant 2 secondes en haut à droite.

Les tags

dans le html généré par le script obsidian share, le tags sont rendus par

<a href="#notebook" class="tag" target="_blank" rel="noopener">#notebook</a>

target="_blank" sur des éléments <a> fournit implicitement le même comportement que si l'on avait utilisé rel="noopener", c'est donc redondant..
Le CSS pour a.tag est classique, mais il y a aussi un bloc pour a.tag:hover ce qui est plus embêtant.

  1. L'idéal of course c'est que le clic sur un tag renvoie à une liste des pages qui contiennent ce tag... Mais on verra ça plus tard.
  2. Une autre solution est de supprimer (ou rendre invisible) le texte du tag, (au besoin en retirant les <a> de la lasse "tag"), et peut-être aussi l'élément parent si c'est <li> ou <ul>
  3. Ou alors laisser le tag affiché comme il est mais supprimer l'interaction "hover" et le lien
  4. ou alors supprimer seulement le lien du <a>

Je choisis provisoirement la dernière solution. Ce qui veut dire soit remplacer le innerhtml par <a href='javascript:'>, soit ajouter une nouvelle feuille de style qui aura priorité sur la première, comme on avait fait pour les callouts., avec

a.tag, a.tag:hover, .editor .cl-hashtag, .editor .cl-hashtag:hover {
	/*display:none;*/
    pointer-events:none;
}

Et voila !

les checkBoxes

Je rajoute le CSS dynamiquement :

task-list-item-checkbox,task-list-item-checkbox:hover,
ul > li.task-list-item .task-list-item-checkbox
	{/*display:none;*/ pointer-events:none;}
  • ok

dataviewJS

Les résultats sont bien rendus, mais le problème c'est lorsque 'on utilise dv.el pour créer des éléments "input", boutons... et des EventListeners.
Dans le code html généré :

<div>
<div class="block-language-dataviewjs node-insert-event">
		<input type="range" style="width: 80%; height: 15px; background: rgb(255, 255, 136);">
		<i><span>50%</span></i>
		<progress value="0.5" style="width: 80%; height: 50px;">
		<span>-</span></progress>	
</div>
</div>

Il n'y a pas de code... Il va falloir éditer le js templater. Ca a l'air trés compliqué à moins d'utiliser l'API plugin obsidian.
#TBC

Mise à jour du contenu des notes sur le site

La doc# Running Obsidian Share on your own serverl (page web) dit que le CSS n'est pas rechargé lorsqu'on ajoute des notes.

The next time you share the same file, it will ignore the CSS. If you want to force the theme CSS to re-upload, just remove the share_link property from your frontmatter.

ça veut dire quoi ? je ne comprends pas..

En fait, ce que je n'avais pas vu, c'est que le script templater modifie le frontmatter de la note avant sa publication en y ajoutant share_link et share_updated

Ca permet de faciliter la mise à jour du site !

Lorsqu'on déplace une note :

The URL of the shared file is based on the note path + name. If you've changed the path or name and want to keep the same URL, you can add a share_hash YAML property with the original hash.
For example, if your URL was https://file.obsidianshare.com/572e1ae4a0aeadf5943862d1deaf8fe6.html, you would set share_hash to be 572e1ae4a0aeadf5943862d1deaf8fe6 and the URL will stay the same no matter if you rename or move the Obsidian note.

reste à faire pour fusionner mon site et Osbsidian...

Reste à faire pour re-créer mon site avec les notes Obsidian
Reste à faire pour re-créer mon site avec les notes Obsidian

Reste à faire pour re-créer mon site avec les notes Obsidian

Pour la partie "rendu de chaque note" :

cf Obsidian Share > Mes ajouts
finalement je ne vais pas utiliser Obsidian Share, mais je vais créer mon propre plugin : my Obsidian website (plugin)

texte markdown

liens

  • déterminer comment gérer les liens (notamment vers les fichiers externes, l'aide Obsidian, les notes non publiées, les liens avec changement de nom par "|")... cf Les liens dans Obsidian
    • liens vers les autres notes du coffre
      • cibler #start pour mettre le sticky en haut
      • et ajouter la balise ancre <a name="start" id="start"></a> au début du contenu de chaque note générée, juste après <div class="mod-header">
    • pour les liens internes dans la note ou vers une partie d'une autre bote
    • OK pour les liens vers images hors coffre sur disque local
    • OK pour liens web
    • pour les liens obsidian://open..., les docs des plugins, l'aide obsidian il faudrait celle en ligne, pas celle de l'app !)
    • liens tags par défaut ils renvoient vers #tag de la même page. rediriger vers la page spéciale tags
    • liens vers fichiers PDF externes pas gérés
    • liens vers notes inexistantes (il manque le .html en fin du lien)
    • vidéos youtube inline ?
  • backlinks

images

rendu des plugins externes

  • changements de thème ? OK commutateur sombre/clair
    • reste à l'intégrer dans le framework HTML
  • Excalidraw
  • callouts
    • Déplier/replier les callouts repliables
    • Animation
    • replier les "-", déplier les "+" au chargement de la page
    • Au contraire inhiber l'interaction sur les checkboxes. ? OK.
  • Faire marcher les scripts de DataviewJS cf DataviewJS dans une page web
  • synthèse sonore dans Music-abc
  • execute-code
    voir le script note-interaction.js (fait pour obsidian-share)
    • Gérer les boutons run et clear de Execute-code
    • gérer copy code to clipboard
    • notices ?
  • Canvas

code HTML généré

  • rajouter l'en-tête <!DOCTYPE html> et la balise <HTML lang="fr">
  • rajouter l'url canonique
    • transcoder les caractères spéciaux
  • footer de page
  • la largeur de la bande principale ? une taille courante est 1440 de large, avec le contenu principal à 1140. je choisis 1280 de large ??
  • créer un nouveau plugin ? Pour remplacer templater ALT-p (de share) Pas forcément nécessaire... si ! cf my Obsidian website (plugin)
  • problème avec le CSS généré par obsidian share pour mathjax : il semble différent pour chaque fichier. RESOLU avec wep page HTML export et le my Obsidian website (plugin)
  • ne pas inclure le code mathjax dans les pages qui n'ont pas de maths
  • relocaliser les liens http/https vers des sources que je ne maîtrise pas (jquery, font awesome...). (dans obsidian-styles.css et ?...)
  • les fonts svg inline dans le code (mywebsite.ts)
  • Hasard renvoie toujours la même page. corrigé

intégration sur un site (statique...)

  • Déterminer la structure du site
  • déconstruire Perlite cf Recréer Perlite en html Inutile.
  • Le graphe ? navigation hyperbolique ? Ce sera pour plus tard.
  • plan du site ? inutile vu qu'il y a le menu
  • fusion avec le site existant cf Fusionner mon site et mes notes Obsidian
  • Gérer le pb des retours à la ligne après transclusion des images (e.g. liste de mes livres)
  • Transformer en liens relatifs les liens vers le site dans la page ?
  • changements de thème global sur le site ?
    • sombre/clair
    • choix de thème (mais le plugin utilise le thème choisi dans Obsidian)
  • Le look : image de fond....
  • URL canoniques,
  • tags : faire pointer vers une liste des notes concernées ? cf Obsidian Share > Les tags
  • Bandeau en haut (sticky, c'est à dire toujours en haut même si on scrolle ?)
  • fil d'Ariane ?
  • liens de partage sur réseaux sociaux
  • gérer l'emplacement des pubs adsense et autre ?
  • rendu sur mobile ?
  • scripts à mettre dans le head (les étoiles...)
    • le script étoiles ne marche pas
  • notes privées
  • fireworks ? Confetti ?

Publicité
Commentaires

Commentaires (0) :

Page :



Ajouter un commentaire (pas besoin de s'enregistrer)

Pseudo :
Message :


image de protection
En cliquant sur le bouton "Envoyer" vous acceptez les conditions suivantes : Ne pas poster de message injurieux, obscène ou contraire à la loi, ni de liens vers de tels sites. Respecter la "netiquette", ne pas usurper le pseudo d'une autre personne, respecter les posts faits par les autres. L'auteur du site se réserve le droit de supprimer un ou plusieurs posts à tout moment. Merci !
Ah oui : le bbcode et le html genre <br>, <a href=...>, <b>b etc. ne fonctionnent pas dans les commentaires. C'est voulu.
< Retour en haut de la page