Example #1
0
        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);
            }
        }
Example #2
0
        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);
            }
        }
Example #3
0
        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);
                    }
                });
            }
        }
Example #4
0
        /// <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);
        }
Example #5
0
        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);
            }
        }
Example #10
0
        /// <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);
        }
Example #11
0
 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);
            }
        }