diff --git a/reference/MarkdownViewer/MarkdownViewer.upp b/reference/MarkdownViewer/MarkdownViewer.upp new file mode 100644 index 000000000..30fd6ead2 --- /dev/null +++ b/reference/MarkdownViewer/MarkdownViewer.upp @@ -0,0 +1,16 @@ +description "A simple markdown viewer with image displaying capability.\377"; + +uses + CtrlLib, + Painter, + plugin/jpg, + plugin/md; + +file + main.cpp, + Resources readonly separator, + example.md; + +mainconfig + "" = "GUI"; + diff --git a/reference/MarkdownViewer/example.md b/reference/MarkdownViewer/example.md new file mode 100644 index 000000000..0793405bc --- /dev/null +++ b/reference/MarkdownViewer/example.md @@ -0,0 +1,44 @@ + +# Markdown Test Document + +Markdown is a lightweight markup language with plain text formatting syntax. Its design allows it to be converted to many formats, but it's primarily used for formatting readme files, writing messages in online discussion forums, and creating rich text using a plain text editor. + +## Links + +Here are some examples of links: + +- [U++](https://www.ultimatepp.org) +- [Markdown Guide](https://www.markdownguide.org) + +## Images + +You can embed images: + +![Sample Image](tux.png) + +## Lists + +### Unordered List +- Item 1 +- Item 2 + - Subitem 2.1 + - Subitem 2.2 +- Item 3 + +### Ordered List +1. First item +2. Second item +3. Third item + +## Code Blocks + +You can include code blocks: + +```C++ +int main() +{ + printf("Hello, world!"); +} +``` + + diff --git a/reference/MarkdownViewer/main.cpp b/reference/MarkdownViewer/main.cpp new file mode 100644 index 000000000..9e6d052ab --- /dev/null +++ b/reference/MarkdownViewer/main.cpp @@ -0,0 +1,73 @@ +#include + +#include +#include +#include + +using namespace Upp; + +struct MarkdownViewer : TopWindow { + RichTextView view; + MenuBar menubar; + Array images; + + MarkdownViewer() + { + Title(t_("A simple markdown viewer")); + Sizeable().Zoomable().SetRect(0, 0, 800, 600); + Add(view.SizePos()); + AddFrame(menubar); + menubar.Set([this](Bar& menu) + { + menu.Sub(t_("File"), [this](Bar& menu) + { + menu.Add(t_("Open"), [this] { OpenFile(); }) + .Key(K_CTRL_O); + menu.Add(t_("Copy to clipboard (as qtf)"),[this] { CopyAsQtf(); }) + .Key(K_CTRL_C) + .Enable(!IsNull(~view)); + menu.Separator(); + menu.Add(t_("Exit"), THISFN(Close)) + .Key(K_CTRL_Q); + }); + }); + ParseFile(GetDataFile("example.md")); + } + + void OpenFile() + { + if(String f = SelectFileOpen("*.md"); !f.IsEmpty()) + ParseFile(f); + } + + void ParseFile(const String& fname) + { + images.Clear(); + MarkdownConverter mdc; + mdc.WhenImages = [&](VectorMap& imglist) + { + String dir = GetFileDirectory(fname); + Progress pi(t_("Loading images..."), imglist.GetCount()); + pi.pi.Percent(); + for(int i = 0; i < imglist.GetCount(); i++) { + if(String path = NormalizePath(imglist.GetKey(i), dir); FileExists(path)) { // Image resource paths are expected to be relative to the main markdown file's. + if(Image img = StreamRaster::LoadFileAny(path); !IsNull(img)) + imglist[i] << images.Add(CreatePNGObject(img)); + if(pi.StepCanceled()) + break; + } + } + }; + view.SetQTF(mdc.Tables().NoHtml().ToQtf(LoadFile(fname))); + } + + void CopyAsQtf() + { + AppendClipboardUnicodeText(~view); + } +}; + +GUI_APP_MAIN +{ + MarkdownViewer().Run(); +} diff --git a/reference/MarkdownViewer/tux.png b/reference/MarkdownViewer/tux.png new file mode 100644 index 000000000..a5d01d50c Binary files /dev/null and b/reference/MarkdownViewer/tux.png differ