尝试更优雅的写作

2016/05/10 其他

虽然用markdown写作确实感到前所未有的简洁和优雅,但是我表示对markdown的分栏显示非常的不舒适。某天朋友推荐了Typora,一个真正的所见即所得的markdown编辑器。

Typora编辑器界面

QQ截图20160510095108

真正的所见即所得,所以当我第一次使用Typora的时候,就不再使用typecho自带的编辑器了。虽然装了个小插件可以分栏显示,但是分栏显示并不是真正意义上的markdown所见即所得。

Typora区别于其他markdown编辑器的优势

  • 单栏即时显示,真正的所见即所得
  • 非常友好的表格及公式编辑
  • 类似Office的快捷键
  • 本地图片直接拖拽到编辑器即可插入

不方便的地方

用Typora写完文章再复制到博客上,会有很多麻烦的地方。比如

  • 每次写完都要登陆博客去发表。略麻烦。
  • 图片上传问题。由于写文章的时候偶尔需要用到的图片都是本地的,所以拖拽到Typora后的图片地址是本地的地址,复制到博客后还得重新上传一下图片。很麻烦且本身typecho后台传图片就不友好。

所以要解决以上问题,得自己写个程序,即能很方便的把文章发出去,也能很友好的传图片。用C#写了个简单的程序来解决自己的问题。

QQ截图20160510101027

  1. 用Typora编辑好的文章拖拽到这里后,直接提交到博客上
  2. 把本地的图片找出来传到服务器并把文章中的图片地址给替换掉。

实现更优雅的操作

本地读取文件,提取图片或者附件,上传到服务器,返回url替换到本地的文章,上传文章到博客。

1.友好的拖拽读取文件

实现这个在C#窗体程序并不难。只需要给对应的panel添加DragDro()和DragEnter()事件。如:

private void panel1_DragEnter(object sender, DragEventArgs e)  
		{  
    
            if (e.Data.GetDataPresent(DataFormats.FileDrop))  
                e.Effect = DragDropEffects.Link;  
            else  
            {  
                e.Effect = DragDropEffects.None;  
            }  
        }        
private void panel1_DragDrop(object sender, DragEventArgs e)  
        {  
            //文件路径  
            String pathStr = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();  
            
            fileManage.setTextFilePath(pathStr);  
        }  

2.找文本中的图片

Markdown的图片格式如

QQ截图20160510113240

"叹号"[名称](地址)

表达式:!\[(?<name>.*?)\]\((?<path>.*?)\)可匹配到对应的字符串。

”!”符号不能省,用于区别于超链接[名称](地址)的写法

参考:正则表达式30分钟入门教程

在线正则表达式测试

在C#中,可以用regex.Matches() 匹配多个,如

Regex regex = new Regex(@"!\[(?<name>.*?)\]\((?<path>.*?)\)");  
            MatchCollection matches = regex.Matches(fileManage.getTextFileText());  
            foreach (Match match in matches)  
            {  
            }  

在foreach中遍历处理匹配的name 和path即可。

3.上传图片并替换url

由于typecho使用的是php,所以能想到的方法便是在服务器端挂个php脚本,接收图片。

  1. 服务端

在服务器端新建一个脚本放在 usr/upload_QoiuernRsjk2345Iffj.php

<?php  
if ($_FILES["file"]["error"] > 0)  
	{  
		echo "error";  
	}  
else  
{  
	$url = "http://539go.com/usr/";  
	$path = "uploads/".date("Y/m-d/");  
	creatdir($path);  
	if (file_exists($path . $_FILES["file"]["name"]))  
	{  
		echo "exists";  
	}  
	else  
	{  
		move_uploaded_file($_FILES["file"]["tmp_name"],  
		$path . $_FILES["file"]["name"]);  
		echo $url . $path . $_FILES["file"]["name"];  
	}  
}  
function creatdir($path)  
{  
	if(!is_dir($path))  
	{  
		if(creatdir(dirname($path)))  
		{  
			mkdir($path,0777);  
			return true;  
		}  
	}  
	else  
	{  
		return true;  
	}  
}  
?>  

其中$url = "http://539go.com/usr/";是php文本所放置的地址。

$path = "uploads/".date("Y/m-d/");是保存图片的格式,比如这里我要保存到 uploads/年份/月-日/ 这样的格式下。

  1. 客户端

C#

        public string SendFile(string fileName, Uri uri, string encodingType = "UTF-8")  
        {  
            WebClient myWebClient = new WebClient();  
            byte[] responseArray = myWebClient.UploadFile(uri, "POST", fileName);  
  
            return Encoding.GetEncoding(encodingType).GetString(responseArray);  
        }  
String str = SendFile(imgItem.path, new Uri("http://http://539go.com/usr/upload_QoiuernRsjk2345Iffj.php"));  

这里只是提供一个示例,调用senFile()后,str会接收php返回的内容,比如没有文件时返回error,文件存在时返回返回 exists,否则返回对应的url。都需要做对应的处理。

没有学过php,所以加密码什么的暂时不做了。

4.提交到博客

这个相对来说简单,分析一下typecho数据库的字段然后编写sql语句就行了。

QQ截图20160510105845

contents表就是typecho保存文章内容的表了。

QQ截图20160510110040

cid是自增的,其他的都好理解,其中created和modified字段是创建日期和修改日期的,是int类型的时间戳格式。所以需要在添加日期的时候转换一下。

        /// <summary>  
        /// 时间戳转为C#格式时间  
        /// </summary>  
        /// <param name="timeStamp"></param>  
        /// <returns></returns>  
        private DateTime StampToDateTime(string timeStamp)  
        {  
            DateTime dateTimeStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));  
            long lTime = long.Parse(timeStamp + "0000000");  
            TimeSpan toNow = new TimeSpan(lTime);  
  
            return dateTimeStart.Add(toNow);  
        }  
  
        /// <summary>  
        /// DateTime时间格式转换为Unix时间戳格式  
        /// </summary>  
        /// <param name="time"></param>  
        /// <returns></returns>  
        private int DateTimeToStamp(System.DateTime time)  
        {  
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));  
            return (int)(time - startTime).TotalSeconds;  
        }  
		/// <summary>  
        /// 获取时间戳(现在)  
        /// </summary>  
        /// <returns></returns>  
        static public int getDateStampNow()  
        {  
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));  
            return (int)(System.DateTime.Now - startTime).TotalSeconds;  
        }  

另外,在C#上使用mysql需要引用MySql.Data.dll,不然是没办法使用MySqlConnection的。

插入文章的Sql:

insert into typecho_contents (title,slug,created,modified,text,authorId,allowComment,allowPing,allowFeed)  
values(@title,@slug,@created,@modified,@text,@authorId,@allowComment,@allowPing,@allowFeed)  

有的字段不用添加,因为有默认值。

另外,由于没有插入cid,slug字段在typecho上是默认和cid相同的,所以,当执行完sql后,需要根据得到的cid修改slug字段

update typecho_contents set slug=@slug where cid=@cid;

4.完成后

QQ20160510110916

提交后的界面只能待会儿上传了后再上传了。因为暂时没有做修改的功能。

时间匆忙,还有很多不足的地方需要有空慢慢实现,仅仅完整了暂时的需求。

需要完善的地方

  • php加个密码
  • 上传后最好可以修改文章
  • 中文问题
  • 界面太丑

提交后的界面
1111111111.jpg