MarkWord - 可发布博客的 Markdown编辑器 代码开源
因为前一段时间看到 NetAnalyzer 在Windows10系统下UI表现惨不忍睹,所以利用一段时间为了学习一下WPF相关的内容,于是停停写写,用了WPF相关的技术,两个星期做了一个Markdown编辑器,并且集成了:编辑时与网页同步,博客发布,PDF导出等功能。也主要是不忿某款外国软件收费,故有此作。
代码下载地址
https://github.com/Twzy/MarkWord
展示与说明
代码同步编辑

博客发布

代码说明
博客发布
MarkWord支持博客园和CSDN博客发布,并且可以进行图片同步(无论是本地图片还是网上的图片,都可以同步到博客服务器)。 该功能使用了MetaWeblog技术。使用方法如下,其中图片上传为newMediaObject 接口
/// <summary>
/// 文档上传,包括新增与更新
/// </summary>
public static string UploadBlogs(string apiUrl, string BlogId, string userId, string password, string
BlogsModel, string postId, string title, string Markdown, bool publish)
{ int procIndex = ; SendMsg(, procIndex, "准备数据中……");
//转换为html
string Blogs = string.Format("<!-- edit by MarkWord 墨云软件 -->\r\n{0}",
CommonMark.CommonMarkConverter.Convert(Markdown));
metaTools.Url = apiUrl; Post blogsPost = new Post(); //分类
List<string> tmpCategories = new List<string>();
tmpCategories.Add("");//添加空分类,是因为部分博客(如csdn)字段这部分为必填字段不添加会产生异常
blogsPost.categories = tmpCategories.ToArray(); //添加时间
blogsPost.dateCreated = DateTime.Now.ToLocalTime(); //添加标题
blogsPost.title = title; //指定文章编号
blogsPost.postid = postId; //内容
blogsPost.description = BlogsModel.Contains("{0}") ?//必须使用{0}占位符
string.Format(BlogsModel, Blogs) : //根据模板生成数据 主要是为了制定Markdown模板
BlogsModel + Blogs; //通过前缀方式添加 //开始查找图片并更新到服务器
HtmlDocument htmlDoc = new HtmlDocument();
WebClient webClient = new WebClient();
htmlDoc.LoadHtml(blogsPost.description);
var ImgList = htmlDoc.DocumentNode.Descendants("img"); int procCount = + ImgList.Count(); SendMsg(procCount, procIndex++, string.Format("数据分析完成,总共需要上传{0}张图片", ImgList.Count()));
int imgErr = ;//图片上传错误数量
foreach (var i in ImgList)
{
SendMsg(procCount, procIndex++, "正在上传图片数据……");
//获取图片文件字符串
string ImgUrl = i.GetAttributeValue("src", "");
if (string.IsNullOrEmpty(ImgUrl))
{
imgErr++;
continue;
}
try
{
var imgeData = webClient.DownloadData(ImgUrl);//下载文件 FileData fd = default(FileData);
fd.bits = imgeData;//图片数据
fd.name = Path.GetExtension(ImgUrl);//文件名
fd.type = string.Format("image/{0}", fd.name.Substring()); UrlData obj = metaTools.newMediaObject(BlogId, userId, password, fd);
blogsPost.description = blogsPost.description.Replace(ImgUrl, obj.url);
}
catch
{
imgErr++;
continue;
}
}
try
{
if (string.IsNullOrWhiteSpace(postId))
{
SendMsg(procCount, procIndex++, "开始发布文章……");
postId = metaTools.newPost(BlogId, userId, password, blogsPost, publish);
}
else
{
SendMsg(procCount, procIndex++, "正在更新文章……");
metaTools.editPost(postId, userId, password, blogsPost, publish);
}
}
catch (Exception ex)
{
Common.ShowMessage("博客发送失败");
return postId;
} if (imgErr == )
{
Common.ShowMessage("博客发送成功");
}
else
{
Common.ShowMessage(string.Format("博客发送成功了,但是有{0}张图片发送失败", imgErr));
}
SendMsg(procCount, procCount, "完成");
return postId; }
具体API实现方法见代码中的BlogsAPI项目
PDF导出
PDF导出功能,使用了HTML转PDF方法 相关DLL已经包含在项目当中了
//html to Pdf
public static void HtmlToPdf(string filePath, string html, bool isOrientation = false)
{
if (string.IsNullOrEmpty(html))
html = "Null";
// 创建全局信息
GlobalConfig gc = new GlobalConfig();
gc.SetMargins(new Margins(, , , ))
.SetDocumentTitle("MarkWord")
.SetPaperSize(PaperKind.A4)
.SetPaperOrientation(isOrientation)
.SetOutlineGeneration(true); //页面信息
ObjectConfig oc = new ObjectConfig();
oc.SetCreateExternalLinks(false)
.SetFallbackEncoding(Encoding.UTF8)
.SetLoadImages(true)
.SetScreenMediaType(true)
.SetPrintBackground(true);
//.SetZoomFactor(1.5); var pechkin = new SimplePechkin(gc);
pechkin.Finished += Pechkin_Finished;
pechkin.Error += Pechkin_Error;
pechkin.ProgressChanged += Pechkin_ProgressChanged;
var buf = pechkin.Convert(oc, html); if (buf == null)
{
Common.ShowMessage("导出异常");
return;
} try
{
string fn = filePath; //Path.GetTempFileName() + ".pdf";
FileStream fs = new FileStream(fn, FileMode.Create);
fs.Write(buf, , buf.Length);
fs.Close(); //Process myProcess = new Process();
//myProcess.StartInfo.FileName = fn;
//myProcess.Start();
}
catch { }
}
CommonMark使用
最后就Markdown的转换,在这里我使用了CommonMark,使用方法比较简单
CommonMark.CommonMarkConverter.Convert("### test")
编辑与html页面同步原理
在改工具中比较有意思的就是编辑器与Webbrower的页面同步功能,包括页面"无刷新"同步呈现,已经页面同步滚动,在这里使用的是编辑器触发 textEditor_TextChanged 事件和 ScrollViewer 触发的scrViewer_ScrollChanged 分别通过webbrowser 的 InvokeScript 动态调用Js实现的,我们先来看看两个js的内容
同步呈现
function updatePageContent(msg){
document.body.innerHTML= msg;
}
非常简单,只是将转换出来的html直接通过document.body.innerHTML 赋给当前页面既可以了。
同步滚动
function scrollToPageContent(value){
window.scrollTo(0, value * (document.body.scrollHeight - document.body.clientHeight));
}
这部分,是需要通过WPF页面转过来一个对应的页面位移高度与窗口显示高度的一个页面比例,然后在webbrowser中根据该比例计算页面需要偏移量来实现同步移动
而对应的WPF端的代码为
/// <summary>
/// 同步呈现
/// </summary>
/// <param name="value"></param>
public void LoadBody(string MarkValue)
{ if (winWebDoc.Document == null)
return;
winWebDoc.Document.InvokeScript("updatePageContent", new object[] { CommonMark.CommonMarkConverter.Convert(MarkValue) });
} /// <summary>
/// 文本更变
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void textEditor_TextChanged(object sender, EventArgs e)
{
if (!isLoadFlag)
{
if (this.textEditor.Text != "" && scrViewer != null)
if (scrViewer.ScrollableHeight == scrViewer.VerticalOffset)
scrViewer.ScrollToBottom(); BLL.FileManager.isChangeFlag = true;
}
//加载文档
if (MarkDoc == null)
return;
if (Config.Common.WorkType == WorkType.Both)
{
MarkDoc.LoadBody(this.textEditor.Text);
}
}
//////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// 同步滚动
/// </summary>
/// <param name="value"></param>
public void ScrollAuto(double value)
{
if (winWebDoc.Document == null)
return;
winWebDoc.Document.InvokeScript("scrollToPageContent", new object[] { value.ToString(System.Globalization.CultureInfo.InvariantCulture) }); }
//计算比例
public double ScrollViewerPositionPercentage
{
get
{
double num = this.scrViewer.ExtentHeight - this.scrViewer.ViewportHeight;
double result;
if (num != 0.0)
{
result = this.scrViewer.VerticalOffset / num;
}
else
{
result = 0.0;
}
return result;
}
} //触发同步
private void scrViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (MarkDoc == null) return;
if (Config.Common.WorkType == WorkType.Both)
{
MarkDoc.ScrollAuto(this.ScrollViewerPositionPercentage);
}
}
至此,Markword 中设计到的内容点已经基本覆盖到了,如有疑问欢迎交流!!!
最后来一发小广告
NetAnalyzer2016网络协议分析软件源码开放购买,可以分析80多种协议,支持http数据还原(包含chunked和gzip数据) ,欢迎大家可以支持一下!!
墨云NetAnalyzer官网
代码购买链接
如有疑问欢迎QQ联系:470200051
祝大家周末愉快
MarkWord - 可发布博客的 Markdown编辑器 代码开源的更多相关文章
- 博客用Markdown编辑器插入视频
要展示一些App的效果用或者更方便地展示工具的操作,可以使用视频. 以下有两种方式可以在博客中插入视频 第一种 此方法适用于插入来源优酷的视频或者你自己录制了视频上传到优酷,这种方法的好处是可以插入时 ...
- Orchard运用 - 为博客启用Markdown编辑器
有时决定你是否使用某一个博客系统,最看重就是如何更简便的写博客,不能让其成为一个负担或别扭费力不讨好的工作. 对此一个好的编辑器就是一个最靓丽的卖点.比如最新的博客系统ghost.org就只定位一个最 ...
- 201771010117—马兴德—实验一 软件工程准备—掌握博客中MarkDown的使用以及通读《现代软件工程—构建之法》的总结
实验一 软件工程的前期准备工作 在前期的准备工作以及老师上课的讲解中,我懂得了"软件=程序+软件工程"这句话的基本含义,以前只是对软件工程有一个很浅显的概念,现在在读了<现代 ...
- 从零开始,搭建博客系统MVC5+EF6搭建框架(4)下,前后台布局实现、发布博客以及展示。
一.博客系统进度回顾 目前已经完成了,前台展示,以及后台发布的功能,最近都在做这个,其实我在国庆的时候就可以弄完的,但是每天自己弄,突然最后国庆2天,连电脑都不想碰,所以就一直拖着,上一篇写了前端实现 ...
- Flask博客开发——Tinymce编辑器
之前Flask博客的文本编辑器比较简陋,这里为博客添加个优雅易用的Tinymce文本编辑器. 1.项目中添加Tinymce 下载好Tinymce包以及语言包,并添加到项目中.添加到项目的方法,参考了这 ...
- 【干货】利用MVC5+EF6搭建博客系统(四)(下)前后台布局实现、发布博客以及展示
二.博客系统后台布局实现 2.1.这里所用的是MVC的布局页来实现的,后台主要分为三部分:导航.菜单.主要内容 代码实现: 这里把后台单独放在一个区域里面,所以我这里建立一个admin的区域 在布局页 ...
- 测试用Word2007发布博客文章
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- 用WORD2007发布博客文章
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- Word2007发布博客
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
随机推荐
- C#判断网站运行状态是否正常
我使用的是控制台应用程序来监控网站的运行状态,通过判断网站请求头(HEAD)来判断是否运行正常 下面列出几种常见的网站状态码 StatusCode 数字表示 OK 200. OK 指示请求成功,且请求 ...
- Mysql group_concat
select p.id,p.parent_id,group_concat(distinct(CONCAT("分类名称:",c.name)) order by c.id desc s ...
- ASP.NET 页面间数据传递的方法
在做WEB开发时,很多地方会涉及到页面间的数据传递.这几天在完善教务基础系统,遇到了这个问题,上网查了一些资料,现总结如下: 说到页面间数据传递,很多人都会想到通过像Session这样的全局变量,但是 ...
- 多线程11-Semaphore信号灯
1.概念 Semaphore可以维护当前访问自身的线程个数,并提供了同步机制.使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数 2.案例 package org ...
- 32位和64位adb下载及安装
一.已安装android sdk时 1.拷贝 从%ANDROID_HOME/platform-tools 下拷贝如下文件到/System32和/SysWOW64下即可. adb.exe AdbWinA ...
- How To Learn English Very Fast
How do you learn English very fast? Every week, I get emails about this topic. Typically, someone ...
- Android Framework------之ActivityManagerService与Activity之间的通信
研究Android系统的童鞋,想必都已经了解一个Activity的启动过程了.而且在网上,关于Activity的启动的文章非常多,很容易就能找到的.这篇文章的重点放在ActivityManagerSe ...
- oracle 数据库连接的四种方式
Oracle Thin JDBC Driver驱动程序包名:ojdbc14.jar.ojdbc6.jar驱动程序类名: oracle.jdbc.driver.OracleDriverJDBC URL: ...
- d3可视化实战01:理解SVG元素特性
一. SVG简介 ————————————————————————————————————————————————————————————————— SVG是一种和图像分辨率无关的矢量图形格式,它使用 ...
- BZOJ 4407 于神之怒加强版
http://www.lydsy.com/JudgeOnline/problem.php?id=4407 题意: 给下N,M,K.求 思路: 来自:http://blog.csdn.net/ws_y ...