123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- using AngleSharp;
- using AngleSharp.Css.Dom;
- using AngleSharp.Dom;
- using AngleSharp.Html.Parser;
- using CefSharpWrap;
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Windows.Forms;
- namespace MarkdownRenderer
- {
- public partial class MarkdownRendererForm : Form
- {
- private readonly CefSharpWrapBrowser _rendererBrowser;
- private readonly HtmlParser _agHtmlParser;
- private string _html;
- private double _scrollPosition;
- private string _styleSheet;
- private string _bodyClassName;
- public MarkdownRendererForm()
- {
- InitializeComponent();
- _rendererBrowser = CefSharpWrapFactory.CreateSealedInstance($"{CefSharpWrapFactory.SchemeName}://{CefSharpWrapFactory.CustomResourceDomainName}/{MarkdownRendererMain.CustomResourcePath}/");
- _rendererBrowser.FillToControl(MainPanel);
- _rendererBrowser.RegisterJsObject("BridgeObject", new RenderJsObjectBridge(this));
- _rendererBrowser.ExternalRequested += delegate (object sender, string fileName)
- {
- try
- {
- Process.Start(fileName);
- }
- catch (Exception e)
- {
- MessageBox.Show(e.ToString(), "External execute fail", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- };
- var agContext = BrowsingContext.New(Configuration.Default.WithDefaultLoader().WithCss());
- _agHtmlParser = new HtmlParser(new HtmlParserOptions(), agContext);
- FillStyleSheetDropDownMenuItems(BuiltInStyleSheetsBulidinToolStripMenuItem, StyleSheetStore.BuiltInEntries);
- RefreshCustomStyleSheetMenuItems();
- //TODO: Active last used style sheet
- SetStyleSheet(StyleSheetStore.BuiltInEntries[0]);
- }
- private void SetStyleSheet(StyleSheetEntry styleSheet)
- {
- _styleSheet = styleSheet.Css;
- _bodyClassName = styleSheet.BodyClass;
- _rendererBrowser.ExecuteJsAsync("syncStyle()");
- }
- public void PutMarkdown(string mdText)
- {
- var action = new Action(() =>
- {
- _html = MarkdownHtmlConverter.ToHtml(mdText);
- _rendererBrowser.ExecuteJsAsync("syncHtml()");
- });
- if (InvokeRequired) Invoke(action);
- else action();
- }
- public void ScrollToPercent(double scrollPosition)
- {
- //TODO: Sync scroll position match to section. too hard to implement
- _scrollPosition = scrollPosition;
- _rendererBrowser.ExecuteJsAsync("syncScroll()");
- }
- private void RefreshCustomStyleSheetMenuItems()
- {
- for (var i = CustomStyleSheetNoneToolStripMenuItem.DropDownItems.Count - 1; i >= 0; i--)
- {
- var item = CustomStyleSheetNoneToolStripMenuItem.DropDownItems[i];
- if (item != CustomStyleSheetNoneToolStripMenuItem) CustomStyleSheetNoneToolStripMenuItem.DropDownItems.Remove(item);
- }
- var entries = StyleSheetStore.GetEntries();
- if (false == (CustomStyleSheetNoneToolStripMenuItem.Visible = entries.Length == 0))
- {
- FillStyleSheetDropDownMenuItems(BuiltInStyleSheetsBulidinToolStripMenuItem, entries);
- }
- }
- private static void FillStyleSheetDropDownMenuItems(ToolStripDropDownItem container, IEnumerable<StyleSheetEntry> entries)
- {
- foreach (var entry in entries)
- {
- var item = new ToolStripMenuItem
- {
- Text = entry.Name,
- Tag = entry
- };
- //TODO: restore check state
- container.DropDownItems.Add(item);
- }
- }
- private string GenerateHtmlForExport()
- {
- var htmlTemplate = Properties.Resources.TemplatePageForExport;
- var doc = _agHtmlParser.ParseDocument(htmlTemplate);
- doc.QuerySelector("style").InnerHtml = _styleSheet;
- var body = doc.QuerySelector("body");
- body.InnerHtml = _html;
- body.ClassName = _bodyClassName;
- using (var writer = new StringWriter())
- {
- doc.ToHtml(writer);
- return writer.ToString();
- }
- }
- private void CopyToolStripButton_Click(object sender, EventArgs e)
- {
- try
- {
- var html = GenerateHtmlForExport();
- Clipboard.SetText(html);
- }
- catch (Exception exception)
- {
- MessageBox.Show(exception.ToString(), "Copy HTML fail", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- }
- private void CopyInlineStyleHtml_Click(object sender, EventArgs e)
- {
- try
- {
- var html = GenerateHtmlForExport();
- var doc = _agHtmlParser.ParseDocument(html);
- //TODO: check why pre and quote missing background-image
- foreach (var element in doc.QuerySelectorAll("body,body *"))
- {
- var style = doc.DefaultView.GetComputedStyle(element);
- element.SetStyle(style.CssText.Replace('\"', '\''));
- element.RemoveAttribute("class");
- }
- foreach (var element in doc.QuerySelectorAll("style"))
- {
- element.Remove();
- }
- var writer = new StringWriter();
- doc.ToHtml(writer);
- var processedHtml = writer.ToString();
- Clipboard.SetText(processedHtml);
- }
- catch (Exception exception)
- {
- MessageBox.Show(exception.ToString(), "Copy HTML fail", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- }
- private void SaveToolStripButton_Click(object sender, EventArgs e)
- {
- var sfd = new SaveFileDialog
- {
- Title = "Save as HTML",
- Filter = "HTML files (*.html;*.htm)|*.htm;*.html"
- };
- if (DialogResult.OK != sfd.ShowDialog()) return;
- try
- {
- var html = GenerateHtmlForExport();
- File.WriteAllText(sfd.FileName, html);
- }
- catch (Exception exception)
- {
- MessageBox.Show(exception.ToString(), "Save as HTML fail", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- }
- private void PrintToolStripButton_Click(object sender, EventArgs e)
- {
- new PrintToPdfForm(_rendererBrowser).ShowDialog();
- }
- private void StyleSheetManageToolStripMenuItem_Click(object sender, EventArgs e)
- {
- new StyleSheetForm().ShowDialog();
- //TODO: if current active entry was delete (not found in custom and bulit-in), choose an other one or reset to first built-in
- RefreshCustomStyleSheetMenuItems();
- }
- private void HelpToolStripButton_Click(object sender, EventArgs e)
- {
- new AboutForm().ShowDialog();
- }
- private void F12ToolStripButton_Click(object sender, EventArgs e)
- {
- _rendererBrowser.ShowF12();
- }
- private void MarkdownRendererForm_FormClosed(object sender, FormClosedEventArgs e)
- {
- _rendererBrowser.Dispose();
- }
- private void StyleSheetsToolStripMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
- {
- foreach (ToolStripMenuItem item in CustomStyleSheetNoneToolStripMenuItem.DropDownItems) item.Checked = false;
- foreach (ToolStripMenuItem item in BuiltInStyleSheetsBulidinToolStripMenuItem.DropDownItems) item.Checked = false;
- var clickedItem = (ToolStripMenuItem)e.ClickedItem;
- clickedItem.Checked = true;
- SetStyleSheet((StyleSheetEntry)clickedItem.Tag);
- //TODO: Save currelt selected style sheet id to config store
- }
- private class RenderJsObjectBridge
- {
- private readonly MarkdownRendererForm _formInstance;
- public RenderJsObjectBridge(MarkdownRendererForm formInstance) => _formInstance = formInstance;
- // ReSharper disable UnusedMember.Local
- public string StyleSheet => _formInstance._styleSheet;
- public string BodyClassName => _formInstance._bodyClassName;
- public string Html => _formInstance._html;
- public double ScrollPosition => _formInstance._scrollPosition;
- // ReSharper restore UnusedMember.Local
- }
- }
- }
|