Skip to content

Project: Markdown editor with WebView

This project upgrades the Module 4 markdown editor from Wx::HTML::HtmlWindow to Wx::WEB::WebView. The model and editor panel are completely unchanged. Only PreviewPanel is different — and the improvement is immediately visible.

1
2
bundle install
ruby main.rb

Requires internet access for highlight.js CDN.

Download markdown_editor_v2.zip

What changed — and what didn’t

The key architectural point of this project is what stayed the same. Open editor_frame.rb and compare it to the Module 4 version. They are identical except for the require_relative paths.

The frame calls:

1
2
@preview.update(@document.to_html)
@preview.clear

It does not know or care whether PreviewPanel uses HtmlWindow or WebView. The public interface is the same. Swapping the implementation required touching exactly one file.

The new PreviewPanel

lib/panels/preview_panel.rb is the only file that changed. It now uses JsBridge to call a JS method on the page:

1
2
3
4
def update(html)
  return unless @ready
  @bridge.call('updateContent', { html: html })
end

The JS side receives the rendered HTML and applies syntax highlighting:

1
2
3
4
5
6
7
RubyBridge.register('updateContent', function(payload) {
  document.getElementById('content').innerHTML = payload.html;
  document.querySelectorAll('pre code').forEach(function(block) {
    hljs.highlightElement(block);
  });
  return { ok: true };
});

The ready pattern from lesson 5.2 is applied — Ruby triggers ready after registering the handler:

1
2
3
4
5
@webview.evt_webview_loaded(@webview.id) do
  next if @webview.current_url == 'about:blank'
  @webview.add_script_message_handler('bridge')
  @bridge.run_script("RubyBridge.emit('ready', {})")
end

The preview page

lib/html/preview_page.rb contains the complete WebView page as a Ruby module. It loads two external resources from CDN:

1
2
3
4
<!-- Syntax highlighting -->
<link rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>

And uses full CSS for typography, code blocks, tables, and blockquotes — none of which was possible with HtmlWindow.

What improved over HtmlWindow

Feature HtmlWindow WebView
CSS stylesheets Limited ✓ Full
Syntax highlighting ✓ via highlight.js
Table styling Basic ✓ Custom
Blockquote styling Basic ✓ Custom
Typography control Limited ✓ Full
Code font and colours System default ✓ Controlled
JavaScript

The visual difference is striking. Open both editors side by side — the same markdown source renders very differently. The WebView version looks like a real documentation tool.

The debounce timer and ready

One subtlety worth noting: load_sample_content sets up the initial content and starts the debounce timer. But when the timer fires, the WebView may not be ready yet — the page is still loading. The return unless @ready guard in PreviewPanel#update handles this correctly — the first update is silently dropped, and the user can trigger another by typing.

For a production app you might store the pending HTML and send it immediately when ready fires. For this tutorial app the behaviour is acceptable.

What this project demonstrates

  • The value of interface-based panel design — swap PreviewPanel, touch nothing else
  • Full JsBridge pattern in a real editing workflow
  • CDN resources in WebView pages
  • Syntax highlighting with highlight.js — two lines of JS, zero Ruby changes
  • The ready pattern correctly applied

Previous: Leaflet maps | Next: Module 6 — Real-world applications