Emitting relative URLs from the editor
Tom builds the authoring tool for a documentation platform. Technical writers use his WinForms app to draft articles -- screenshots, inline diagrams, hyperlinks to other articles -- and when they hit "Publish", the article HTML gets uploaded to a CDN where images are served from a completely different base URL than the local authoring folder.
When Tom first wired up WinFormHtmlEditor, every published article was broken. Writers were inserting images via the editor's image dialog, picking files from C:\Articles\screenshots\step-1.png, and the published HTML went out with that exact absolute Windows path baked into <img src=>. Once the article was live on the CDN, every image was a broken link.
The fix is a chain of four properties. Tom worked through them one at a time.
BaseUrl: tell the editor where the document lives
Without BaseUrl, the editor has no anchor against which to measure "relative". Tom set it to the article's working folder on the writer's machine in his form's Load handler:
private void Form1_Load(object sender, EventArgs e){ // Each article has its own working folder; screenshots live alongside the .htm file. htmlEditor1.BaseUrl = Path.Combine(currentArticle.WorkingDir, "images");}This made images render correctly inside the editor itself, but the saved HTML was still absolute. BaseUrl alone is just the anchor -- it doesn't rewrite anything.
[IMAGE: relative-url-baseurl-anchor.png -- folder layout showing BaseUrl pointing at the article's images folder]
ConvertAbsoluteUrlsToRelativeUrls: emit relative paths
Next switch:
htmlEditor1.Options.ConvertAbsoluteUrlsToRelativeUrls = true;With this on, every img src, a href, and similar URL attribute that points inside the BaseUrl tree gets rewritten relative to it when Tom reads DocumentHtml. The writer's screenshot at C:\Articles\my-article\images\step-1.png serialized as src="step-1.png" -- exactly what the CDN deploy script wants. URLs pointing outside the tree (a remote https link, a different drive) were left absolute, which is the right call: a relative path that climbs out with ../../../ is never what you want.
ConvertFileUrlsToLocalPaths: strip file:// scheme
Tom noticed some pasted images came in as file:///C:/Articles/.../foo.png. The browser engine that backs the editor sometimes hands back that form even when the user picked a plain Windows path. The relative-URL rewriter wouldn't recognize them as living inside BaseUrl until the scheme was stripped. One more line:
htmlEditor1.Options.ConvertFileUrlsToLocalPaths = true;These two options work as a pair: turn one on, turn the other on.
[IMAGE: file-url-conversion.png -- before/after: file:///C:/Articles/screenshots/step-1.png becomes step-1.png]
UrlEncodeHyperlinkHRefs: portable hyperlinks
Writers paste a lot of reference URLs -- Wikipedia, RFCs, internal SharePoint pages. Those URLs are full of spaces, parentheses, and the occasional accented character. Raw, they break in feed readers and email clients. Tom flipped the final switch:
htmlEditor1.Options.UrlEncodeHyperlinkHRefs = true;Now href="https://example.com/My Page (v2).html" serializes as href="https://example.com/My%20Page%20%28v2%29.html". The visible link text is untouched; only the href attribute gets encoded so the markup survives whatever environment it lands in.
The full setup
Tom's final block, done once at form load:
htmlEditor1.BaseUrl = Path.Combine(currentArticle.WorkingDir, "images");htmlEditor1.Options.ConvertAbsoluteUrlsToRelativeUrls = true;htmlEditor1.Options.ConvertFileUrlsToLocalPaths = true;htmlEditor1.Options.UrlEncodeHyperlinkHRefs = true;The deploy script now uploads the article HTML and the images/ folder side by side to the CDN. The CDN serves both from https://cdn.example.com/articles/<slug>/, and the relative src attributes resolve correctly with no rewriting on the server. Tom's next sprint had no broken-image tickets at all.
[IMAGE: relative-url-options-matrix.png -- table mapping each option to the resulting markup before/after]