markdownview — u_pbt_markdownview #
← Référence des composants · Sommaire du guide
markdownview affiche un document Markdown en lecture seule, aux couleurs du thème : titres, listes, tableaux, listes de tâches, code coloré, images. Vous posez le texte dans
is_markdown, ou le chemin d'un fichier dansis_source; un lien ne navigue jamais, il lèveue_link_clickedet c'est l'application qui décide. Le HTML brut d'un document n'est jamais exécuté.
▶ Le voir en vrai — Application de démonstration, tuile Markdown viewer, avec le code et cette page côte à côte.
En bref #
| Userobject | u_pbt_markdownview |
| Entrée | Un texte Markdown (is_markdown), ou un fichier du poste ou une URL https:// (is_source) |
| Syntaxe | CommonMark, plus les tableaux, les listes de tâches, le barré, les liens et adresses e-mail nus, les alertes (> [!NOTE]) et les émojis (:+1:) de GitHub |
| Retour | ue_link_clicked pour un lien, avec sa nature (l'application décide), ue_loaded / ue_load_failed pour un document, ue_search_result pour la recherche, ue_task_toggled pour une case cochée |
| Sécurité | Le HTML brut est montré comme du texte ; un lien javascript:, vbscript: ou data: n'est pas cliquable ; une image http:// est refusée, une image d'un partage réseau aussi ; un document du Web n'affiche aucun fichier du poste |
Démarrage rapide #
// Show a Markdown file : its pictures and relative links are read against its folder
uo_md.is_source = "C:\Acme\Help\guide.md"
// ... or any text the application has
uo_md.is_markdown = "# Release notes~n~n- [x] Orders~n- [ ] Invoices"
// ue_link_clicked : the viewer never navigates, the application decides where to open as_url
Propriétés #
| Propriété | Type | Défaut | Description |
|---|---|---|---|
is_markdown | string | "" | Le texte Markdown à montrer. Le poser remplace le document (is_source se relit alors vide) ; vide efface la vue. Un nouveau texte du MÊME document — la recette d'édition — garde la position de lecture. Le HTML brut qu'il contient est affiché comme du texte, jamais exécuté (voir ib_allow_html). Se relit tel qu'il a été posé |
is_source | string | "" | Un fichier Markdown à montrer : un chemin du poste (.md, .markdown, .txt…), une adresse file:/// ou une URL https:// — lue par le client HTTPS natif de la bibliothèque (le proxy et l'identité Windows du poste, aucun mur CORS). Ses images et liens relatifs se lisent contre son dossier. http:// est refusé (REASON_INSECURE), comme tout fichier qui n'est pas du texte (REASON_UNSUPPORTED) ; au-delà de 16 Mo, fichier ou URL, REASON_TOO_LARGE. Le fichier se lit en arrière-plan : lisez la table des matières ou déplacez-vous dedans une fois ue_loaded reçu (pendant la lecture, of_toc rend 0 et of_scroll_to attend le fichier). Le poser remplace le document (is_markdown se relit alors vide) |
is_base_path | string | "" | Le dossier (ou l'adresse https://) contre lequel se lisent les images et liens relatifs d'un TEXTE posé par is_markdown — une aide gardée en base de données à côté de ses images. Vide : le dossier courant de l'application. Un fichier montré par is_source prend toujours son propre dossier. Lue en direct |
ib_allow_html | boolean | false | true dessine une liste COURTE et fermée de balises HTML inertes du document — b, i, u, s, kbd, sub, sup, mark, small, br, img (src, alt, width, height : les règles d'une image Markdown), a (href : les règles d'un lien Markdown) et details / summary. Toute autre balise, un script, un style, un gestionnaire d'événement restent du texte. false : tout le HTML est montré tel qu'écrit |
ib_network_pictures | boolean | false | false : une image du document posée sur le RÉSEAU (un partage d'un serveur) n'est pas chargée — ouvrir un partage livre l'identité Windows de l'utilisateur à ce serveur —, sauf si elle est sur le partage d'où le document lui-même a été lu. true : pour l'application qui montre SES documents depuis un partage. Un document lu sur le Web n'affiche jamais un fichier du poste |
ib_remote_pictures | boolean | true | true charge les images https:// d'un document ; false n'en charge aucune — rien ne quitte le poste du seul fait qu'un document est affiché (un pixel de suivi reste une vignette) |
ib_tasks_editable | boolean | false | true laisse l'utilisateur cocher les cases d'une liste de tâches (un clic, ou Espace sur une case) : ue_task_toggled donne la LIGNE du source et le nouvel état ; le TEXTE reste à l'application, qui le réécrit. false : les cases sont en lecture seule |
ib_track_heading | boolean | false | true lève ue_heading_visible chaque fois qu'un autre titre atteint le haut de la vue pendant que le lecteur fait défiler — une table des matières qui suit la lecture |
ii_zoom | integer | 100 | La taille de lecture, de 50 à 300 % (100 : la taille du thème). Ctrl+molette dans le document la change par pas de 10 ; lue en direct |
is_position | string | "" | La position de lecture, un texte comme 12:35 (le premier bloc visible et de combien il commence au-dessus du haut). Lisez-la avant de fermer un long document, reposez-la pour le rouvrir là où le lecteur l'avait laissé. Lue en direct ; vide quand rien n'est affiché. Un fichier en cours de lecture la prend une fois à l'écran |
ib_search_enabled | boolean | true | Ctrl+F dans le document ouvre une zone de recherche — la même recherche que of_search : taper surligne, Entrée ou F3 suivant, Maj+Entrée ou Maj+F3 précédent, Échap ferme. false laisse le raccourci à une application qui cherche depuis sa propre zone |
ib_find_match_case | boolean | false | Option de recherche : ne trouve que le texte de même casse. La bascule Aa de la zone de recherche est le même interrupteur. Lue en direct ; of_reset la remet à false |
ib_find_whole_word | boolean | false | Option de recherche : ne trouve le texte que comme mot entier (pen n'est pas trouvé dans pencil). La bascule ab de la zone de recherche est le même interrupteur. Lue en direct ; of_reset la remet à false |
is_theme_style | string | "" | Style visuel du composant (constantes THEME_STYLE_*) ; vide = celui de l'application, suivi à chaque changement |
is_theme_mode | string | "" | Variante claire ou sombre (constantes THEME_MODE_*) ; vide = celle de l'application, suivie à chaque changement |
il_theme_accent | long | -1 | Couleur d'accent de ce composant (-1 = l'accent de l'application, ou celui du thème) |
is_tooltip | string | "" | Info-bulle simple affichée au survol du composant |
is_super_tooltip_title | string | "" | Titre de l'info-bulle enrichie (prend le pas sur is_tooltip) |
is_super_tooltip_text | string | "" | Texte de l'info-bulle enrichie (balisage riche accepté) |
is_super_tooltip_image | string | "" | Image de l'info-bulle enrichie |
Méthodes #
| Méthode | Description |
|---|---|
of_clear ( ) → long | Vide la vue : is_markdown et is_source se relisent vides ; ib_search_enabled et les options de recherche gardent leur valeur (c'est of_reset qui remet chaque propriété). Une recherche ouverte le dit : ue_search_result(0, 0). Rend 0, -2 si le composant n'est pas créé |
of_clear_search ( ) → long | Efface la recherche : plus de surlignage ni d'occurrence courante (of_match_count rend 0), la zone de recherche se ferme. Rend 0, -2 si le composant n'est pas créé |
of_copy ( ) → long | Copie dans le presse-papiers le texte que l'utilisateur a sélectionné — ce que font Ctrl+C et Ctrl+Inser dans le document. Rend 0, -5 si rien n'est sélectionné, -2 si le composant n'est pas créé |
of_match_count ( ) → long | Rend le nombre d'occurrences de la recherche courante, lu EN DIRECT — le 12 d'une barre d'état 3 / 12 ; 50 000 au plus sont comptées. 0 sans recherche |
of_match_index ( ) → long | Rend la position (1-basée) de l'occurrence courante, lue EN DIRECT — le 3 d'une barre d'état 3 / 12. 0 sans occurrence |
of_refresh ( ) → long | Relit is_source (sur le disque ou le réseau) : de quoi montrer un fichier réécrit au même chemin ; la position de lecture est gardée ; ue_loaded ou ue_load_failed suit. Rend 0, -5 si aucun document n'est montré, -2 si le composant n'est pas créé |
of_scroll_to ( string as_anchor ) → long | Amène le titre as_anchor en haut de la vue : son ancre telle que of_toc la donne, avec ou sans #, ou son texte ; un titre dans un details fermé l'ouvre. Pendant la lecture d'un fichier posé par is_source, l'ancre attend le fichier et l'appel rend 0. Rend 0, -5 si aucun titre ne correspond, -2 si le composant n'est pas créé |
of_search ( string as_query ) → long | Surligne chaque occurrence (sans casse par défaut — voir ib_find_match_case —, en mot entier avec ib_find_whole_word) et saute à la première ; une occurrence peut traverser un gras, un lien ou un retour à la ligne du source, jamais un saut de ligne forcé. ue_search_result dit combien (50 000 au plus). Une requête vide est of_clear_search. Pendant la lecture d'un fichier, la recherche porte sur lui quand il arrive. La zone de recherche s'ouvre avec la requête dedans ; avec ib_search_enabled à false, le document surligne seulement. Rend 0, -2 si le composant n'est pas créé |
of_search_next ( ) → long | Passe à l'occurrence SUIVANTE (revient à la première après la dernière) ; ue_search_result donne la nouvelle position. Rend 0, -2 si le composant n'est pas créé |
of_search_prev ( ) → long | Passe à l'occurrence PRÉCÉDENTE (revient à la dernière avant la première) ; ue_search_result donne la nouvelle position. Rend 0, -2 si le composant n'est pas créé |
of_selected_text ( ) → string | Rend le texte que l'utilisateur a sélectionné dans le document, lu EN DIRECT — vide quand rien n'est sélectionné |
of_toc ( ref string as_titles[], ref long al_levels[], ref string as_anchors[] ) → long | La table des matières, lue EN DIRECT : une entrée par titre, dans l'ordre — son texte, son niveau (1 à 6) et son ancre (ce que prennent of_scroll_to et un lien #ancre, à la manière de GitHub : « Release checklist » donne release-checklist). Les tableaux sont vidés d'abord. Rend le nombre de titres, 0 pour un document sans titre — et pendant la lecture d'un fichier posé par is_source : demandez-la dans ue_loaded |
Événements #
| Événement | Quand |
|---|---|
ue_heading_visible (string as_anchor) | Avec ib_track_heading : un autre titre a atteint le haut de la vue. as_anchor est son ancre telle que of_toc la donne, vide au-dessus du premier titre |
ue_link_clicked (string as_url, string as_kind) | L'utilisateur a suivi un lien (un clic, ou Entrée sur un lien qui a le focus). Le composant ne navigue PAS : ouvrez as_url où vous voulez. as_kind dit ce que c'est — LINK_WEB, LINK_MAIL, LINK_DOCUMENT (un fichier Markdown ou texte que ce composant sait montrer), LINK_FILE (tout autre fichier : ne le lancez jamais sans demander), LINK_OTHER. Un lien relatif d'un fichier montré par is_source arrive résolu contre son dossier ; un lien #titre défile tout seul et n'est pas levé ; un lien javascript: ou data: n'est même pas cliquable |
ue_loaded (string as_source) | Le document est à l'écran : as_source est is_source tel que vous l'avez écrit, ou une chaîne vide pour un texte posé par is_markdown |
ue_load_failed (string as_source, string as_reason) | Le document n'a pas pu être montré : as_reason est l'une des constantes REASON_* — REASON_NOT_FOUND (pas de fichier), REASON_TOO_LARGE (plus de 16 Mo), REASON_INSECURE (http://), REASON_UNSUPPORTED (pas un fichier texte, ou un autre protocole), REASON_FAILED (une erreur de lecture ou de réseau, ou un texte illisible). as_source est vide pour un texte posé par is_markdown ; le document précédent reste affiché. ue_loaded n'est pas levé |
ue_search_result (long al_count, long al_index) | Une recherche a démarré ou avancé : al_count occurrences en tout (50 000 au plus), la courante est al_index (1-basé, 0 si aucune) — de quoi afficher « 3 / 12 » |
ue_task_toggled (long al_line, boolean ab_checked) | Avec ib_tasks_editable : l'utilisateur a coché (ab_checked à true) ou décoché une case d'une liste de tâches. al_line est la ligne du source Markdown (1-basée). Le composant ne réécrit pas le texte : l'application change [ ] / [x] sur cette ligne et repose le texte (voir l'exemple) |
Exemple #
Une aide en ligne qui ouvre ses liens #
Un document vient souvent d'ailleurs : le tri se fait sur la nature du lien, jamais sur son texte. Une page Web ou un courriel s'ouvrent dans leur programme, un autre document s'affiche dans le même composant, et un fichier — un .exe, un .bat — n'est jamais lancé sans demander.
// ue_link_clicked of uo_md : the viewer never navigates, the application decides by the kind
choose case as_kind
case u_pbt_markdownview.LINK_WEB, u_pbt_markdownview.LINK_MAIL
// A web page, a mail : their program
ShellExecuteW(0, "open", as_url, "", "", 1)
case u_pbt_markdownview.LINK_DOCUMENT
// Another page of the help : in this viewer
uo_md.is_source = as_url
case else
// A file of the disk or of the network : never run without asking
MessageBox("Link", "This link leads to a file : " + as_url)
end choose
Éditer du Markdown : un codeeditor et un markdownview #
Le visualiseur garde sa position de lecture quand le texte change : on édite la fin d'un long document sans que l'aperçu remonte en haut.
// Local variables
string ls_notes
// The notes of the customer, in Markdown
ls_notes = "# Notes~n~n- [ ] Call back on Monday"
// The editor colours Markdown ; the viewer shows the page
uo_editor.is_syntax = u_pbt_codeeditor.SYNTAX_MARKDOWN
uo_editor.is_text = ls_notes
uo_md.is_markdown = ls_notes
// ue_changed of uo_editor : the whole recipe
uo_md.is_markdown = uo_editor.is_text
Une table des matières dans une liste #
Pour un fichier posé par is_source, remplissez la liste dans ue_loaded : avant, le fichier est encore en lecture.
// Local variables
string ls_titles[], ls_anchors[]
long ll_levels[], ll_i
// ue_loaded of uo_md : one line per heading, indented by its level
lb_toc.Reset()
for ll_i = 1 to uo_md.of_toc(/*titles*/ ls_titles, /*levels*/ ll_levels, /*anchors*/ ls_anchors)
lb_toc.AddItem(Fill(" ", (ll_levels[ll_i] - 1) * 3) + ls_titles[ll_i])
next
// Local variables
string ls_titles[], ls_anchors[]
long ll_levels[]
// SelectionChanged of lb_toc : bring that heading to the top
uo_md.of_toc(/*titles*/ ls_titles, /*levels*/ ll_levels, /*anchors*/ ls_anchors)
uo_md.of_scroll_to(/*anchor*/ ls_anchors[index])
Une liste de contrôle que l'utilisateur coche #
// Local variables
string ls_text
long ll_at, ll_n
// The user may tick the boxes of the text
uo_md.ib_tasks_editable = true
// ue_task_toggled of uo_md : the start of line al_line of the text
ls_text = uo_md.is_markdown
ll_at = 1
for ll_n = 2 to al_line
ll_at = Pos(ls_text, "~n", ll_at) + 1
next
// Its box, the first "[" of the line, becomes [x] or [ ]
ll_at = Pos(ls_text, "[", ll_at)
if ab_checked then
ls_text = Replace(ls_text, ll_at, 3, "[x]")
else
ls_text = Replace(ls_text, ll_at, 3, "[ ]")
end if
// The text set back : the view keeps its place
uo_md.is_markdown = ls_text
Le composant ne réécrit jamais le texte lui-même : l'application garde la main sur ce qu'elle enregistre.
Rouvrir un document là où le lecteur l'a laissé #
// Before closing the window : remember the place in the guide
SetProfileString("acme.ini", "help", "position", uo_md.is_position)
// When the guide is shown again : the place is taken once the file is on screen
uo_md.is_source = "C:\Acme\Help\guide.md"
uo_md.is_position = ProfileString("acme.ini", "help", "position", "")
Bonnes pratiques #
- C'est un lecteur, pas un éditeur : pour écrire du Markdown, un
codeeditorenSYNTAX_MARKDOWNà côté, relié par une ligne dans son ue_changed (voir l'exemple) ; le visualiseur garde sa place quand le texte change. - Les liens sont à vous : rien ne s'ouvre tout seul ;
ue_link_clickeddonne l'adresse, déjà résolue contre le dossier du fichier, et sa nature (as_kind) — triez sur elle, jamais sur le texte de l'adresse, et ne lancez jamais unLINK_FILEsans demander. - Un document n'exécute rien : le HTML brut s'affiche tel qu'écrit (ou, avec
ib_allow_html, seulement une courte liste de balises inertes), un lienjavascript:reste du texte, une imagehttp://est refusée, une image d'un partage réseau aussi (ib_network_pictures) — un document venu d'ailleurs se montre sans risque. - Les images : un chemin relatif se lit contre le dossier du fichier (ou
is_base_pathpour un texte) ; pour une image du Web, préférezhttps://, ou téléchargez-la d'abord (restclient.of_download) et donnez son chemin.ib_remote_picturesàfalsen'en charge aucune. - Un fichier se lit en arrière-plan : après
is_source, attendezue_loadedpour lire la table des matières ; une ancre et une recherche demandées entre-temps attendent le fichier. - Un gros document reste fluide : les premiers blocs s'affichent tout de suite, le reste dans les instants qui suivent ; la recherche (50 000 occurrences au plus),
of_scroll_toet l'impression attendent qu'il soit entier. - De droite à gauche : le document suit le sens de l'application (listes, citations et tableaux se retournent), un bloc de code reste de gauche à droite, et une colonne que l'auteur a alignée (
:--,--:) garde son côté.
Hérité du socle commun #
Ces membres existent sur tous les composants visuels — ils ne sont pas propres à celui-ci. Ils sont détaillés une seule fois, dans les chapitres transverses ; cette table dit seulement où les lire.
| Membres | Rôle | Détaillé dans |
|---|---|---|
of_reset | Remettre le composant à zéro | 3.6 Remettre un composant à zéro : of_reset() |
of_register_shortcut · of_clear_shortcuts | Raccourcis clavier du composant | 3.5 Les raccourcis clavier |
of_is_created · of_is_ready · of_get_last_error | S'il est né, s'il est prêt, ce qui a échoué | 3.7 Diagnostic |
of_save_as_png · of_save_as_jpg | Exporter le rendu en image | 3.8 Exporter le rendu en image |
of_set_redraw | Grouper les modifications en un seul repaint | 3.10 Bonnes pratiques |
of_preload_icons | Icônes affichées sans délai | Affichage instantané : of_icon |
of_set_translation | Traduire un libellé du composant | 5.2 Adapter un libellé : of_set_translation |
of_focus_webview | Donner le focus au composant | 6.4 Clavier et focus |
of_print · of_print_to_pdf | Imprimer, ou écrire un PDF | 6.9 Imprimer |
of_set_property · of_get_property · of_component_name | Piloter une propriété par son nom | 3.1 Le moteur de propriétés |
is_accessible_name · is_accessible_description | Le nom et la description que dit un lecteur d'écran | 3.4 Propriétés et events optionnels |