public void PreviewMarkdown(MarkdownDocumentEditor editor = null, bool keepScrollPosition = false, bool showInBrowser = false, string renderedHtml = null, int editorLineNumber = -1) { try { // only render if the preview is actually visible and rendering in Preview Browser if (!Model.IsPreviewBrowserVisible && !showInBrowser) { return; } if (editor == null) { editor = Window.GetActiveMarkdownEditor(); } if (editor == null) { return; } var doc = editor.MarkdownDocument; var ext = Path.GetExtension(doc.Filename).ToLower().Replace(".", ""); string mappedTo = "markdown"; if (!string.IsNullOrEmpty(renderedHtml)) { mappedTo = "html"; ext = null; } else { // only show preview for Markdown and HTML documents Model.Configuration.EditorExtensionMappings.TryGetValue(ext, out mappedTo); mappedTo = mappedTo ?? string.Empty; } if (string.IsNullOrEmpty(ext) || mappedTo == "markdown" || mappedTo == "html") { dynamic dom = null; if (!showInBrowser) { if (keepScrollPosition) { dom = WebBrowser.Document; doc.LastEditorLineNumber = dom.documentElement.scrollTop; } else { Window.ShowPreviewBrowser(false, false); doc.LastEditorLineNumber = 0; } } if (mappedTo == "html") { if (string.IsNullOrEmpty(renderedHtml)) { renderedHtml = doc.CurrentText; } if (!doc.WriteFile(doc.HtmlRenderFilename, renderedHtml)) { // need a way to clear browser window return; } } else { // Fix up `\` or `~\` Web RootPaths via `webRootPath: <path>` in YAML header // Specify a physical or relative path that `\` or `~\` maps to doc.GetPreviewWebRootPathFromDocument(); bool usePragma = !showInBrowser && mmApp.Configuration.PreviewSyncMode != PreviewSyncMode.None; if (string.IsNullOrEmpty(renderedHtml)) { renderedHtml = doc.RenderHtmlToFile(usePragmaLines: usePragma, renderLinksExternal: mmApp.Configuration.MarkdownOptions.RenderLinksAsExternal); } if (renderedHtml == null) { Window.ShowStatusError($"Access denied: {Path.GetFileName(doc.Filename)}"); // need a way to clear browser window return; } // Handle raw URLs to render if (renderedHtml.StartsWith("http") && StringUtils.CountLines(renderedHtml) == 1) { WebBrowser.Navigate(new Uri(renderedHtml)); Window.ShowPreviewBrowser(); return; } renderedHtml = StringUtils.ExtractString(renderedHtml, "<!-- Markdown Monster Content -->", "<!-- End Markdown Monster Content -->"); } if (showInBrowser) { var url = doc.HtmlRenderFilename; mmFileUtils.ShowExternalBrowser(url); return; } WebBrowser.Cursor = Cursors.None; WebBrowser.ForceCursor = true; // if content contains <script> tags we must do a full page refresh bool forceRefresh = renderedHtml != null && renderedHtml.Contains("<script "); if (keepScrollPosition && !mmApp.Configuration.AlwaysUsePreviewRefresh && !forceRefresh) { string browserUrl = WebBrowser.Source.ToString().ToLower(); string documentFile = "file:///" + doc.HtmlRenderFilename.Replace('\\', '/') .ToLower(); if (browserUrl == documentFile) { dom = WebBrowser.Document; //var content = dom.getElementById("MainContent"); if (string.IsNullOrEmpty(renderedHtml)) { PreviewMarkdown(editor, false, false); // fully reload document } else { try { // explicitly update the document with JavaScript code // much more efficient and non-jumpy and no wait cursor var window = dom.parentWindow; try { // scroll preview to selected line if (mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorAndPreview || mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorToPreview) { int highlightLineNo = editorLineNumber; if (editorLineNumber < 0) { highlightLineNo = editor.GetLineNumber(); editorLineNumber = highlightLineNo; } if (renderedHtml.Length < 80000) { highlightLineNo = 0; // no special handling render all code snippets } window.updateDocumentContent(renderedHtml, highlightLineNo); window.scrollToPragmaLine(editorLineNumber); } else { window.updateDocumentContent(renderedHtml); } } catch { /* ignore scroll error */ } } catch { // Refresh doesn't fire Navigate event again so // the page is not getting initiallized properly //PreviewBrowser.Refresh(true); WebBrowser.Tag = "EDITORSCROLL"; WebBrowser.Navigate(new Uri(doc.HtmlRenderFilename)); } } return; } } WebBrowser.Tag = "EDITORSCROLL"; WebBrowser.Navigate(new Uri(doc.HtmlRenderFilename)); return; } // not a markdown or HTML document to preview Window.ShowPreviewBrowser(true, keepScrollPosition); } catch (Exception ex) { //mmApp.Log("PreviewMarkdown failed (Exception captured - continuing)", ex); Debug.WriteLine("PreviewMarkdown failed (Exception captured - continuing)", ex); } }
public void PreviewMarkdown(MarkdownDocumentEditor editor = null, bool keepScrollPosition = false, bool showInBrowser = false, string renderedHtml = null, int editorLineNumber = -1) { if (DotnetInterop == null) { return; } try { // only render if the preview is actually visible and rendering in Preview Browser if (!Model.IsPreviewBrowserVisible && !showInBrowser) { return; } if (editor == null) { editor = Window.GetActiveMarkdownEditor(); } if (editor == null) { return; } var doc = editor.MarkdownDocument; var ext = Path.GetExtension(doc.Filename).ToLower().Replace(".", ""); string mappedTo = "markdown"; if (!string.IsNullOrEmpty(renderedHtml)) { mappedTo = "html"; ext = null; } else { // only show preview for Markdown and HTML documents Model.Configuration.EditorExtensionMappings.TryGetValue(ext, out mappedTo); mappedTo = mappedTo ?? string.Empty; } if (string.IsNullOrEmpty(ext) || mappedTo == "markdown" || mappedTo == "html") { // TODO: Get DOM and //dynamic dom = null; //if (!showInBrowser) //{ // if (keepScrollPosition) // { // dom = WebBrowser..Document; // editor.MarkdownDocument.LastEditorLineNumber = dom.documentElement.scrollTop; // } // else // { // Window.ShowPreviewBrowser(false, false); // editor.MarkdownDocument.LastEditorLineNumber = 0; // } //} if (mappedTo == "html") { if (string.IsNullOrEmpty(renderedHtml)) { renderedHtml = editor.MarkdownDocument.CurrentText; } if (!editor.MarkdownDocument.WriteFile(editor.MarkdownDocument.HtmlRenderFilename, renderedHtml)) { // need a way to clear browser window return; } } else { bool usePragma = !showInBrowser && mmApp.Configuration.PreviewSyncMode != PreviewSyncMode.None; if (string.IsNullOrEmpty(renderedHtml)) { renderedHtml = editor.MarkdownDocument.RenderHtmlToFile(usePragmaLines: usePragma); } if (renderedHtml == null) { Window.SetStatusIcon(FontAwesomeIcon.Warning, Colors.Red, false); Window.ShowStatus($"Access denied: {Path.GetFileName(editor.MarkdownDocument.Filename)}", 5000); // need a way to clear browser window return; } renderedHtml = StringUtils.ExtractString(renderedHtml, "<!-- Markdown Monster Content -->", "<!-- End Markdown Monster Content -->"); } if (showInBrowser) { var url = editor.MarkdownDocument.HtmlRenderFilename; mmFileUtils.ShowExternalBrowser(url); return; } WebBrowser.Cursor = System.Windows.Input.Cursors.None; WebBrowser.ForceCursor = true; // if content contains <script> tags we must do a full page refresh bool forceRefresh = renderedHtml != null && renderedHtml.Contains("<script "); if (keepScrollPosition && !mmApp.Configuration.AlwaysUsePreviewRefresh && !forceRefresh) { string browserUrl = WebBrowser.Source?.ToString().ToLower(); string documentFile = "file:///" + editor.MarkdownDocument.HtmlRenderFilename.Replace('\\', '/') .ToLower(); if (browserUrl == documentFile) { if (string.IsNullOrEmpty(renderedHtml)) { PreviewMarkdown(editor, false, false); // fully reload document } else { try { JsInterop = DotnetInterop.JsInterop; int lineno = editor.GetLineNumber(); _ = JsInterop.UpdateDocumentContent(renderedHtml, lineno); try { // scroll preview to selected line if (mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorAndPreview || mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorToPreview) { if (lineno > -1) { _ = JsInterop.ScrollToPragmaLine(lineno); } } } catch { /* ignore scroll error */ } } catch { // Refresh doesn't fire Navigate event again so // the page is not getting initiallized properly //PreviewBrowser.Refresh(true); WebBrowser.Tag = "EDITORSCROLL"; WebBrowser.Source = new Uri(editor.MarkdownDocument.HtmlRenderFilename); mmApp.Log("Document Update Crash", null, false, LogLevels.Information); } } return; } } WebBrowser.Tag = "EDITORSCROLL"; var uri = new Uri(editor.MarkdownDocument.HtmlRenderFilename); if (WebBrowser.Source != null && WebBrowser.Source.Equals(uri)) { WebBrowser.CoreWebView2.Reload(); } else { WebBrowser.Source = new Uri(editor.MarkdownDocument.HtmlRenderFilename); } return; } // not a markdown or HTML document to preview Window.ShowPreviewBrowser(true, keepScrollPosition); } catch (Exception ex) { //mmApp.Log("PreviewMarkdown failed (Exception captured - continuing)", ex); Debug.WriteLine("PreviewMarkdown failed (Exception captured - continuing)", ex); } }
private void PreviewBrowserOnLoadCompleted(object sender, NavigationEventArgs e) { if (e.Uri == null) { return; } string url = e.Uri.ToString(); if (!url.Contains("_MarkdownMonster_Preview") && !url.Contains("__untitled.htm")) { return; } bool shouldScrollToEditor = WebBrowser.Tag != null && WebBrowser.Tag.ToString() == "EDITORSCROLL"; WebBrowser.Tag = null; dynamic window = null; MarkdownDocumentEditor editor = null; try { editor = Window.GetActiveMarkdownEditor(); dynamic dom = WebBrowser.Document; window = dom.parentWindow; dom.documentElement.scrollTop = editor.MarkdownDocument.LastEditorLineNumber; window.initializeinterop(editor); if (shouldScrollToEditor) { try { // scroll preview to selected line if (mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorAndPreview || mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorToPreview) { int lineno = editor.GetLineNumber(); if (lineno > -1) { window.scrollToPragmaLine(lineno); } } } catch { /* ignore scroll error */ } } } catch { // try again Task.Delay(500).ContinueWith(t => { try { window.initializeinterop(editor); } catch { //mmApp.Log("Preview InitializeInterop failed: " + url, ex); } }); } }
/// <summary> /// Saves a bitmap image to file using a standard mechanism that /// prompts for a filename (unless you pass one in), optionally /// compresses the file and by default embeds a link at cursor position. /// /// Overrides let you remove some of these tasks. /// /// The method returns the embedded image path - a relative path if possible. /// </summary> /// <param name="bitmap">The bitmap to save</param> /// <param name="editor">An instance of the editor to paste into. If not passed the open document is used.</param> /// <param name="imageFilename">Optional image filename. If not passed you are prompted using MM's default locations (last document location, project/folder root/current directory)</param> /// <param name="noImageCompression">Images are compressed by default, set to true to avoid compression. Uses Pingo compressor for max size reduction.</param> /// <returns>relative image URL used for embedding</returns> /// <remarks>Make sure you `.Dispose()` the bitmap to avoid big memory leaks</remarks> public static string SaveBitmapAndLinkInEditor(Bitmap bitmap, MarkdownDocumentEditor editor = null, string imageFilename = null, bool noImageCompression = false, bool noEditorEmbedding = false) { if (editor == null) { editor = mmApp.Model.ActiveEditor; } if (editor == null) { return(null); } var document = editor.MarkdownDocument; string initialFolder = document?.LastImageFolder; string documentPath = null; if (!string.IsNullOrEmpty(document?.Filename) && document.Filename != "untitled") { documentPath = Path.GetDirectoryName(document.Filename); if (string.IsNullOrEmpty(initialFolder)) { initialFolder = documentPath; } } if (string.IsNullOrEmpty(initialFolder) && !string.IsNullOrEmpty(document.Filename) && document.Filename != "untitled" && File.Exists(document.Filename)) { initialFolder = document.GetWebRootPathFromMarkerFiles(Path.GetDirectoryName(document.Filename)); } if (string.IsNullOrEmpty(initialFolder)) { initialFolder = mmApp.Model.Window.FolderBrowser?.FolderPath; } //WindowUtilities.DoEvents(); var sd = new SaveFileDialog { Filter = "Image files (*.png;*.jpg;*.gif;)|*.png;*.jpg;*.jpeg;*.gif|All Files (*.*)|*.*", FilterIndex = 1, Title = "Save Image from Clipboard as", InitialDirectory = initialFolder, CheckFileExists = false, OverwritePrompt = true, CheckPathExists = true, RestoreDirectory = true, ValidateNames = true }; var result2 = sd.ShowDialog(); if (result2 == null || !result2.Value) { return(null); } imageFilename = sd.FileName; var ext = Path.GetExtension(imageFilename)?.ToLower(); try { File.Delete(imageFilename); if (ext == ".jpg" || ext == ".jpeg") { using (var bmp = new Bitmap(bitmap)) { mmImageUtils.SaveJpeg(bmp, imageFilename, mmApp.Configuration.Images.JpegImageCompressionLevel); } } else { var format = mmImageUtils.GetImageFormatFromFilename(imageFilename); bitmap.Save(imageFilename, format); } if (!noImageCompression && ext == ".png" || ext == ".jpeg" || ext == ".jpg") { mmFileUtils.OptimizeImage(sd.FileName); // async } } catch (Exception ex) { MessageBox.Show($"Couldn't save {imageFilename}: \r\n" + ex.Message, "SnagIt Capture"); mmApp.Log($"Failed to save clipboard image.\r\nFile: {imageFilename}", ex); return(null); } document.LastImageFolder = Path.GetDirectoryName(imageFilename); string relPath = Path.GetDirectoryName(document.LastImageFolder); if (documentPath != null) { try { relPath = FileUtils.GetRelativePath(imageFilename, documentPath); } catch (Exception ex) { mmApp.Log($"Failed to get relative path.\r\nFile: {imageFilename}", ex); } imageFilename = relPath; } if (imageFilename.Contains(":\\")) { imageFilename = "file:///" + imageFilename; } else { imageFilename = imageFilename.Replace("\\", "/"); } if (!noEditorEmbedding) { editor.SetSelectionAndFocus($"![]({imageFilename.Replace(" ", "%20")})"); // Force the browser to refresh completely so image changes show up mmApp.Model?.Window?.PreviewBrowser?.Refresh(true); } return(imageFilename); }
void ExecuteCore() { if (!mmApp.Configuration.MarkdownOptions.AutoLinks) { var result = MessageBox.Show("AutoLinks must be enabled in Markdown Monster " + "for table of contents links to function. " + "Is it okay to enable AutoLinks?", "Enable AutoLinks?", MessageBoxButton.YesNoCancel, MessageBoxImage.Question); if (result == MessageBoxResult.Cancel) { return; } if (result == MessageBoxResult.Yes) { mmApp.Configuration.MarkdownOptions.AutoLinks = true; } } MarkdownDocumentEditor editor = GetMarkdownEditor(); int caretLineNumber = editor.GetLineNumber(); var markdown = GetMarkdown(); string[] lines = markdown.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); int maxDepth = TocAddinConfiguration.Current.MaxDepth; if (maxDepth < 0) { maxDepth = 3; } string[] prefixes = new string[maxDepth]; string hashString = string.Empty; for (int i = 0; i < maxDepth; i++) { hashString = hashString + "#"; prefixes[i] = hashString + " "; } var headings = new List <Heading>(); int beginTocLineIndex = caretLineNumber; int endTocLineIndex = caretLineNumber; bool hasBeginIndicator = false; bool hasEndIndicator = false; int lineIndex = 0; foreach (var line in lines) { if (line.Contains(tocBeginIndicator)) { hasBeginIndicator = true; beginTocLineIndex = lineIndex; } else if (line.Contains(tocEndIndicator)) { hasEndIndicator = true; endTocLineIndex = lineIndex; } lineIndex++; } bool replaceToc = hasBeginIndicator && hasEndIndicator && beginTocLineIndex <= endTocLineIndex; int firstDepth = -1; lineIndex = -1; /* Locate headings */ foreach (var line in lines) { lineIndex++; if (replaceToc && lineIndex < endTocLineIndex) { continue; } if (!replaceToc && lineIndex < caretLineNumber) { continue; } var trimmed = line.TrimStart(); for (int i = prefixes.Length - 1; i >= 0; i--) { var prefix = prefixes[i]; if (trimmed.StartsWith(prefix)) { string text = trimmed.Substring(i + 2); string anchorId = "#" + text.Replace(" ", "-").ToLower(); if (firstDepth == -1) { firstDepth = i; } /* The depth is calculated relative the the first depth encountered. */ int depth = i - firstDepth; if (depth < 0) { MessageBox.Show($"Invalid heading hierarchy detected at \"{text}\". " + "Headings must have equal or greater depth " + "than the first heading that comes after the TOC.", AddinTitle, MessageBoxButton.OK, MessageBoxImage.Warning); return; } headings.Add(new Heading(depth, text, anchorId)); } } } /* Create an array of tabs that is used to prepend generated toc links. */ string[] tabArray = new string[maxDepth]; string tabString = string.Empty; for (int i = 0; i < maxDepth; i++) { tabArray[i] = tabString; tabString = tabString + "\t"; } /* Create the TOC */ StringBuilder sb = new StringBuilder(); sb.AppendLine(tocBeginIndicator); foreach (Heading heading in headings) { string tabs = tabArray[heading.Depth]; sb.AppendLine($"{tabs}* [{heading.Text}]({heading.Href})"); } sb.AppendLine(); sb.AppendLine(tocEndIndicator); string tocText = sb.ToString(); /* If there isn't an existing TOC, set the current selection to the TOC. */ if (!replaceToc) { SetSelection(tocText); } else { int indexOfStart = markdown.IndexOf(tocBeginIndicator, StringComparison.Ordinal); int indexOfEnd = markdown.IndexOf(tocEndIndicator, StringComparison.Ordinal); if (indexOfStart < 0 || indexOfEnd < 0 || indexOfStart > indexOfEnd) { /* The TOC indicators are out of whack. */ SetSelection(tocText); } else { /* There's an existing TOC, so replace it with the new TOC. * There's probably a better way to replace a portion of the document. * The AceEditor looks able to do that. But, I'm concerned that interacting with it directly * may polute the state of the MarkdownDocumentEditor. * Rick, please let me know if there's an API for this. */ string beforeToc = markdown.Substring(0, indexOfStart); string afterToc = markdown.Substring(indexOfEnd + tocEndIndicator.Length); string newMarkdown = beforeToc + tocText + afterToc; SetMarkdown(newMarkdown); } } }
public void PreviewMarkdownAsync(MarkdownDocumentEditor editor = null, bool keepScrollPosition = false, string renderedHtml = null, int editorLineNumber = -1) { PreviewBrowserHandler.PreviewMarkdownAsync(editor, keepScrollPosition, renderedHtml, editorLineNumber); }
public void PreviewMarkdown(MarkdownDocumentEditor editor = null, bool keepScrollPosition = false, bool showInBrowser = false, string renderedHtml = null, int editorLineNumber = -1) { PreviewBrowser.PreviewMarkdown(editor, keepScrollPosition, showInBrowser, renderedHtml); }
public void PreviewMarkdown(MarkdownDocumentEditor editor = null, bool keepScrollPosition = false, bool showInBrowser = false, string renderedHtml = null, int editorLineNumber = -1) { try { // only render if the preview is actually visible and rendering in Preview Browser if (!Model.IsPreviewBrowserVisible && !showInBrowser) { return; } if (editor == null) { editor = Window.GetActiveMarkdownEditor(); } if (editor == null) { return; } var doc = editor.MarkdownDocument; var ext = Path.GetExtension(doc.Filename).ToLower().Replace(".", ""); string mappedTo = "markdown"; if (!string.IsNullOrEmpty(renderedHtml)) { mappedTo = "html"; ext = null; } else { mappedTo = editor.MarkdownDocument.EditorSyntax; } PreviewBrowserInterop interop = null; if (string.IsNullOrEmpty(ext) || mappedTo == "markdown" || mappedTo == "html") { if (!showInBrowser) { if (keepScrollPosition) { interop = new PreviewBrowserInterop(PreviewBrowserInterop.GetWindow(WebBrowser)); } else { Window.ShowPreviewBrowser(false, false); } } if (mappedTo == "html") { if (string.IsNullOrEmpty(renderedHtml)) { renderedHtml = doc.CurrentText; } if (!doc.WriteFile(doc.HtmlRenderFilename, renderedHtml)) { // need a way to clear browser window return; } renderedHtml = StringUtils.ExtractString(renderedHtml, "<!-- Markdown Monster Content -->", "<!-- End Markdown Monster Content -->"); } else { // Fix up `/` or `~/` Web RootPaths via `webRootPath: <path>` in YAML header // Specify a physical or relative path that `\` or `~\` maps to doc.GetPreviewWebRootPath(); bool usePragma = !showInBrowser && mmApp.Configuration.PreviewSyncMode != PreviewSyncMode.None; if (string.IsNullOrEmpty(renderedHtml)) { renderedHtml = doc.RenderHtmlToFile(usePragmaLines: usePragma); } if (renderedHtml == null) { Window.ShowStatusError($"Access denied: {Path.GetFileName(doc.Filename)}"); // need a way to clear browser window return; } // Handle raw URLs to render if (renderedHtml.StartsWith("http") && StringUtils.CountLines(renderedHtml) == 1) { WebBrowser.Navigate(new Uri(renderedHtml)); Window.ShowPreviewBrowser(); return; } renderedHtml = StringUtils.ExtractString(renderedHtml, "<!-- Markdown Monster Content -->", "<!-- End Markdown Monster Content -->"); } if (showInBrowser) { var url = doc.HtmlRenderFilename; mmFileUtils.ShowExternalBrowser(url); return; } WebBrowser.Cursor = Cursors.None; WebBrowser.ForceCursor = true; // if content contains <script> tags we must do a full page refresh bool forceRefresh = renderedHtml != null && renderedHtml.Contains("<script "); if (keepScrollPosition && !mmApp.Configuration.AlwaysUsePreviewRefresh && !forceRefresh) { string browserUrl = WebBrowser.Source.ToString().ToLower(); string documentFile = "file:///" + doc.HtmlRenderFilename.Replace('\\', '/') .ToLower(); if (browserUrl == documentFile) { if (string.IsNullOrEmpty(renderedHtml)) { PreviewMarkdown(editor, false, false); // fully reload document } else { try { try { // scroll preview to selected line if (mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorAndPreview || mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorToPreview || mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.NavigationOnly) { int highlightLineNo = editorLineNumber; if (editorLineNumber < 0) { highlightLineNo = editor.GetLineNumber(); editorLineNumber = highlightLineNo; } if (renderedHtml.Length < 100000) { highlightLineNo = 0; // no special handling render all code snippets } var lineText = editor.GetLine(editorLineNumber).Trim(); if (mmApp.Configuration.PreviewSyncMode != PreviewSyncMode.NavigationOnly) { interop.UpdateDocumentContent(renderedHtml, highlightLineNo); } // TODO: We need to get Header Ids var headerId = string.Empty; // headers may not have pragma lines if (editorLineNumber > -1) { if (lineText.StartsWith("#") && lineText.Contains("# ")) // it's header { lineText = lineText.TrimStart(new[] { ' ', '#', '\t' }); headerId = LinkHelper.UrilizeAsGfm(lineText); } } if (editor.MarkdownDocument.EditorSyntax == "markdown") { interop.ScrollToPragmaLine(editorLineNumber, headerId); } else if (editor.MarkdownDocument.EditorSyntax == "html") { interop.ScrollToHtmlBlock(lineText); } } else { interop.UpdateDocumentContent(renderedHtml, 0); } } catch { /* ignore scroll error */ } } catch { // Refresh doesn't fire Navigate event again so // the page is not getting initiallized properly //PreviewBrowser.Refresh(true); WebBrowser.Tag = "EDITORSCROLL"; WebBrowser.Navigate(new Uri(doc.HtmlRenderFilename)); } } return; } } WebBrowser.Tag = "EDITORSCROLL"; WebBrowser.Navigate(new Uri(doc.HtmlRenderFilename)); return; } // not a markdown or HTML document to preview Window.ShowPreviewBrowser(true, keepScrollPosition); } catch (Exception ex) { //mmApp.Log("PreviewMarkdown failed (Exception captured - continuing)", ex); Debug.WriteLine("PreviewMarkdown failed (Exception captured - continuing): " + ex.Message, ex); } }
private void PreviewBrowserOnLoadCompleted(object sender, NavigationEventArgs e) { if (e.Uri == null) { return; } string url = e.Uri.ToString(); if (!url.Contains("_MarkdownMonster_Preview") && !url.Contains("__untitled.htm")) { return; } bool shouldScrollToEditor = WebBrowser.Tag != null && WebBrowser.Tag.ToString() == "EDITORSCROLL"; WebBrowser.Tag = null; PreviewBrowserInterop interop = null; MarkdownDocumentEditor editor = null; try { editor = Window.GetActiveMarkdownEditor(); interop = new PreviewBrowserInterop(PreviewBrowserInterop.GetWindow(WebBrowser)); interop.InitializeInterop(editor); interop.SetHighlightTimeout(Model.Configuration.Editor.PreviewHighlightTimeout); //window.previewer.highlightTimeout = Model.Configuration.Editor.PreviewHighlightTimeout; if (shouldScrollToEditor) { try { // scroll preview to selected line if (mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorAndPreview || mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorToPreview) { int lineno = editor.GetLineNumber(); if (lineno > -1) { string headerId = string.Empty; var lineText = editor.GetCurrentLine().Trim(); if (lineText.StartsWith("#") && lineText.Contains("# ")) // it's header { lineText = lineText.TrimStart(new[] { ' ', '#', '\t' }); headerId = LinkHelper.UrilizeAsGfm(lineText); } if (editor.MarkdownDocument.EditorSyntax == "markdown") { interop.ScrollToPragmaLine(lineno, headerId); } else if (editor.MarkdownDocument.EditorSyntax == "html") { interop.ScrollToHtmlBlock(lineText); } } } } catch { /* ignore scroll error */ } } } catch { // try again after a short wait Model.Window.Dispatcher.Delay(500, (i) => { var introp = i as PreviewBrowserInterop; try { introp.InitializeInterop(editor); introp.SetHighlightTimeout(Model.Configuration.Editor.PreviewHighlightTimeout); } catch { //mmApp.Log("Preview InitializeInterop failed: " + url, ex); } }, interop); } }
/// <summary> /// Opens read /// </summary> /// <returns></returns> public TabItem OpenTopicInEditor(bool setFocus = false) { Debug.WriteLine("OpenTopicInEditor"); DocTopic topic = TreeTopicBrowser.SelectedItem as DocTopic; if (topic == null) { return(null); } var window = Model.KavaDocsModel.Window; TabItem tab; if (topic != null && topic.Body != null && (topic.IsLink || topic.Body.StartsWith("http"))) { tab = Model.MarkdownMonsterModel.Window.OpenBrowserTab(topic.Link ?? topic.Body); return(tab); } var file = topic.GetTopicFileName(force: true); MarkdownDocumentEditor editor = null; // is tab open already as a file? If so use that tab = window.GetTabFromFilename(file); if (tab != null) { editor = tab?.Tag as MarkdownDocumentEditor; if (editor == null) { return(null); } } else { // Will also open the tab if not open yet // EXPLICITLY NOT SELECTING THE TAB SO THAT IT'S NOT RENDERED YET // Assign topic first then explicitly select //tab = Model.KavaDocsModel.Window.RefreshTabFromFile(file, noFocus: !setFocus, isPreview: true, noSelectTab:true); tab = Model.KavaDocsModel.Window.ActivateTab(file, noFocus: !setFocus, isPreview: true, noSelectTab: true); //RefreshTabFromFile(file, noFocus: !setFocus, isPreview: true, noSelectTab: true); editor = tab?.Tag as MarkdownDocumentEditor; if (editor == null) { return(null); } } if (tab == null) { return(null); } // make sure topic is associated with editor SetEditorWithTopic(editor, topic, isUnEdited: true); // kavaUi.AddinModel.ActiveTopic); // Explicitly read in the current text from an open tab and save to body var body = editor.GetMarkdown(); if (!string.IsNullOrEmpty(body)) { topic.Body = topic.StripYaml(body); } if (string.IsNullOrEmpty(topic.Link)) { var relative = FileUtils.GetRelativePath(topic.GetTopicFileName(), topic.Project.ProjectDirectory); if (!string.IsNullOrEmpty(relative)) { topic.Link = FileUtils.NormalizePath(relative); if (string.IsNullOrEmpty(topic.Link)) { topic.Link = topic.Link.Replace("\\", "/"); } } } if (body != topic.Body) { editor.SetMarkdown(topic.Body); } window.TabControl.SelectedItem = tab; return(tab); }
public void PreviewMarkdown(MarkdownDocumentEditor editor, bool keepScrollPosition, bool showInBrowser, string renderedHtml = null) { PreviewBrowser.PreviewMarkdown(editor, keepScrollPosition, showInBrowser, renderedHtml); }
public void PreviewMarkdownAsync(MarkdownDocumentEditor editor = null, bool keepScrollPosition = false, string renderedHtml = null) { PreviewBrowser.PreviewMarkdownAsync(editor, keepScrollPosition, renderedHtml); }
private void PreviewBrowserOnLoadCompleted(object sender, NavigationEventArgs e) { if (e.Uri == null) { return; } string url = e.Uri.ToString(); if (!url.Contains("_MarkdownMonster_Preview") && !url.Contains("__untitled.htm")) { return; } bool shouldScrollToEditor = WebBrowser.Tag != null && WebBrowser.Tag.ToString() == "EDITORSCROLL"; WebBrowser.Tag = null; PreviewBrowserInterop interop = null; MarkdownDocumentEditor editor = null; try { editor = Window.GetActiveMarkdownEditor(); interop = new PreviewBrowserInterop(PreviewBrowserInterop.GetWindow(WebBrowser)); //ReflectionUtils. //dom.documentElement.scrollTop = editor.MarkdownDocument.LastEditorLineNumber; interop.InitializeInterop(editor); interop.SetHighlightTimeout(Model.Configuration.Editor.PreviewHighlightTimeout); //window.previewer.highlightTimeout = Model.Configuration.Editor.PreviewHighlightTimeout; if (shouldScrollToEditor) { try { // scroll preview to selected line if (mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorAndPreview || mmApp.Configuration.PreviewSyncMode == PreviewSyncMode.EditorToPreview) { int lineno = editor.GetLineNumber(); if (lineno > -1) { interop.ScrollToPragmaLine(lineno); } } } catch { /* ignore scroll error */ } } } catch { // try again after a short wait Model.Window.Dispatcher.Delay(500, (i) => { var introp = i as PreviewBrowserInterop; try { introp.InitializeInterop(editor); introp.SetHighlightTimeout(Model.Configuration.Editor.PreviewHighlightTimeout); } catch { //mmApp.Log("Preview InitializeInterop failed: " + url, ex); } }, interop); } }
public void PreviewMarkdown(MarkdownDocumentEditor editor, bool keepScrollPosition, bool showInBrowser) { PreviewBrowser.PreviewMarkdown(editor, keepScrollPosition); }
public void PreviewMarkdownAsync(MarkdownDocumentEditor editor, bool keepScrollPosition) { PreviewBrowser.PreviewMarkdownAsync(editor, keepScrollPosition); }
public override void OnExecute(object sender) { MarkdownDocumentEditor editor = GetMarkdownEditor(); var markdown = GetMarkdown(); string[] lines = markdown.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); var config = AutoNumberAddinConfiguration.Current; string ignoreMarker = config.IgnoreMarker; List <LineReplacement> replacements = new List <LineReplacement>(); var captionRegexes = GetCaptionRegexes(); var seeRegexes = GetSeeRegexes(); int[] captionIndexes = new int[captionRegexes.Count]; int lineIndex = -1; int ignoreCount = 0; foreach (var line in lines) { lineIndex++; bool hasCaption = false; if (line.Contains(ignoreMarker)) { ignoreCount++; continue; } for (var i = 0; i < captionRegexes.Count; i++) { Regex regex = captionRegexes[i]; var match = regex.Match(line); if (match.Success) { hasCaption = true; if (ignoreCount > 0) { ignoreCount--; } else { captionIndexes[i]++; var text = ReplaceNamedGroup(match, "Number", captionIndexes[i].ToString()); replacements.Add(new LineReplacement(lineIndex, text, line.Length)); } break; } } if (hasCaption) { continue; } for (var i = 0; i < seeRegexes.Count; i++) { Regex regex = seeRegexes[i]; Match match = regex.Match(line); if (match.Success) { if (ignoreCount > 0) { ignoreCount--; } else { var text = ReplaceNamedGroup(match, "Number", (captionIndexes[i] + 1).ToString()); replacements.Add(new LineReplacement(lineIndex, text, line.Length)); } break; } } } // foreach (LineReplacement replacement in replacements) // { // MarkdownDocumentEditor editor = GetMarkdownEditor(); // var range = new { start = new { row = replacement.LineIndex, column = 0}, // end = new { row = replacement.LineIndex, column = replacement.LineLength } }; // editor.AceEditor.editor.session.replace(range, replacement.Text); // var range = editor.AceEditor.editor.getSelectionRange(); //getLineRange(replacement.LineIndex); // // } foreach (LineReplacement replacement in replacements) { lines[replacement.LineIndex] = replacement.Text; } StringBuilder sb = new StringBuilder(); foreach (var line in lines) { sb.AppendLine(line); } string newContent = sb.ToString(); SetMarkdown(newContent); bool dirty = replacements.Any(); if (dirty) { editor.SetDirty(true); } }