markdownview shows a Markdown document, read-only, at the colours of the theme: headings, lists, tables, task lists, coloured code, pictures. You set the text in is_markdown, or the path of a file in is_source; a link never navigates, it raises ue_link_clicked and the application decides. The raw HTML of a document is never run.
▶ See it live — Demo application, Markdown viewer tile, with the code and this page side by side.
// 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
The Markdown text to show. Setting it replaces the document (is_source then reads back empty); empty clears the view. The raw HTML it holds is displayed as text, never run. Reads back exactly as it was set
is_source
string
""
A Markdown file to show: a path of the workstation (.md, .markdown, .txt…), a file:/// address or an https:// URL. Its relative pictures and links are read against its folder. http:// is refused (REASON_INSECURE), as is any file that is not text (REASON_UNSUPPORTED); over 16 MB, REASON_TOO_LARGE. Setting it replaces the document (is_markdown then reads back empty); ue_loaded or ue_load_failed follows
ib_search_enabled
boolean
true
Ctrl+F in the document opens a search box — the same search as of_search: typing highlights, Enter or F3 next, Shift+Enter or Shift+F3 previous, Escape closes. false leaves the shortcut to an application that searches from its own box
ib_find_match_case
boolean
false
Search option: finds only the text with the same case. The Aa toggle of the search box is the same switch. Read back live; of_reset puts it back to false
ib_find_whole_word
boolean
false
Search option: finds the text only as a whole word (pen is not found inside pencil). The ab toggle of the search box is the same switch. Read back live; of_reset puts it back to false
is_theme_style
string
""
Visual style of the component (THEME_STYLE_* constants); empty = the application's, followed at every change
is_theme_mode
string
""
Light or dark variant (THEME_MODE_* constants); empty = the application's, followed at every change
il_theme_accent
long
-1
Accent colour of this component (-1 = the application accent, or the theme's)
is_tooltip
string
""
Simple tooltip shown when hovering the component
is_super_tooltip_title
string
""
Title of the rich tooltip (takes precedence over is_tooltip)
Empties the view: is_markdown and is_source read back empty; ib_search_enabled and the search options keep their values (of_reset is the one that puts every property back). Returns 0, -2 when the component is not created
of_refresh ( ) → long
Reads is_source again (from the disk or the network): the way to show a file rewritten at the same path; ue_loaded or ue_load_failed follows. Returns 0, -5 when no document is shown, -2 when the component is not created
of_search ( string as_query ) → long
Highlights every occurrence (whatever the case by default — see ib_find_match_case —, as a whole word with ib_find_whole_word) and jumps to the first; an occurrence may cross a bold or a link. ue_search_result says how many. An empty query is of_clear_search. The search box opens with the query in it; with ib_search_enabled false, the document only highlights. Returns 0, -2 when the component is not created
of_search_next ( ) → long
Moves to the NEXT occurrence (back to the first after the last); ue_search_result gives the new position. Returns 0, -2 when the component is not created
of_search_prev ( ) → long
Moves to the PREVIOUS occurrence (back to the last before the first); ue_search_result gives the new position. Returns 0, -2 when the component is not created
of_clear_search ( ) → long
Drops the search: no more highlight nor current occurrence (of_match_count returns 0), the search box closes. Returns 0, -2 when the component is not created
of_match_count ( ) → long
Returns how many occurrences the current search found, read LIVE — the 12 of a 3 / 12 status line. 0 without a search
of_match_index ( ) → long
Returns the 1-based position of the current occurrence, read LIVE — the 3 of a 3 / 12 status line. 0 without an occurrence
of_toc ( ref string as_titles[], ref long al_levels[], ref string as_anchors[] ) → long
The table of contents, read LIVE: one entry per heading, in order — its text, its level (1 to 6) and its anchor (what of_scroll_to and a #anchor link take, GitHub style: “Release checklist” gives release-checklist). The arrays are emptied first. Returns the number of headings, 0 for a document without any
of_scroll_to ( string as_anchor ) → long
Brings the heading as_anchor to the top of the view: its anchor as of_toc gives it, with or without #, or its text. Returns 0, -5 when no heading matches, -2 when the component is not created
The user followed a link (a click, or Enter on a focused link). The component does NOT navigate: open as_url where you want. A relative link of a file shown by is_source arrives resolved against its folder; a #heading link scrolls by itself and is not raised; a javascript: or data: link is not even clickable
ue_loaded (string as_source)
The document is on screen: as_source is is_source as you wrote it, or an empty string for a text set by is_markdown
is_source could not be shown: as_reason is one of the REASON_* constants — REASON_NOT_FOUND (no such file), REASON_TOO_LARGE (over 16 MB), REASON_INSECURE (http://), REASON_UNSUPPORTED (not a text file, or another scheme), REASON_FAILED (a read or network error). ue_loaded is not raised
ue_search_result (long al_count, long al_index)
A search ran or moved: al_count occurrences in all, the current one is al_index (1-based, 0 when none) — the makings of “3 / 12”
// ue_link_clicked of uo_md : the viewer never navigates, the application decides
if Lower(Right(as_url, 3)) = ".md" and FileExists(as_url) then
uo_md.is_source = as_url // another page of the help
else
ShellExecuteW(0, "open", as_url, "", "", 1) // a web page, a mail
end if
Editing Markdown: a codeeditor and a markdownview #
// 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
// Local variables
string ls_titles[], ls_anchors[]
long ll_levels[], ll_i
// One line per heading, indented by its level
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
// SelectionChanged of lb_toc : bring that heading to the top
uo_md.of_scroll_to(/*anchor*/ ls_anchors[index])
It is a reader, not an editor: to write Markdown, put a codeeditor in SYNTAX_MARKDOWN beside it, linked by one line in its ue_changed (see the example).
Links are yours: nothing opens by itself; ue_link_clicked gives the address, already resolved against the folder of the file, and you choose — the browser, another document in the same component, a screen of the application.
A document runs nothing: raw HTML is displayed as written, a javascript: link stays text, an http:// picture is refused — a document from elsewhere is shown safely.
Pictures: a relative path is read against the folder of the file; for a picture from the Web, prefer https://, or download it first (restclient.of_download) and give its path.
A large document stays smooth: the first blocks appear at once, the rest in the following moments; the search, of_scroll_to and printing wait until it is whole.
Right to left: the document follows the direction of the application (lists, quotes and tables turn round), a code block stays left to right.
These members exist on every visual component — they are not specific to this one. They are detailed once, in the transverse chapters; this table only says where to read them.