From c514d0bc1c54dfe1d4f34e1b58e81eba6c353a00 Mon Sep 17 00:00:00 2001
From: life <lifephp@gmail.com>
Date: Thu, 8 Jan 2015 21:15:56 +0800
Subject: [PATCH] =?UTF-8?q?Ace=20&=20Markdown=E5=85=A8=E6=96=B0=E7=BC=96?=
 =?UTF-8?q?=E8=BE=91=E5=99=A8=20&=20others?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

邀请注册
共享后图片可见问题 fileService::getFile()
笔记历史记录问题
共享后得到被共享者列表问题 shareService
themeService 博客主题新建问题, 模板循环引用问题
markdown编辑器双屏大小不能保存问题
---
 app/controllers/AttachController.go           |  14 +-
 app/controllers/AuthController.go             |   7 +-
 app/controllers/BaseController.go             |   7 +-
 app/controllers/BlogController.go             |   5 +-
 app/controllers/FileController.go             |  92 ++-------
 app/controllers/PreviewController.go          |   2 +
 .../member/MemberBlogController.go            | 187 +++++++++---------
 app/controllers/member/init.go                |   3 +-
 app/db/Mgo.go                                 |  15 +-
 app/lea/Debug.go                              |  13 +-
 app/release/release.go                        |  34 +++-
 app/service/AuthService.go                    |  11 +-
 app/service/FileService.go                    |  10 +
 app/service/NoteContentHistoryService.go      |   5 +-
 app/service/ShareService.go                   |   3 +-
 app/service/ThemeService.go                   | 135 ++++++++++++-
 app/service/UserService.go                    |   2 +-
 app/views/errors/500-blog.html                |  63 ++++++
 app/views/home/register.html                  |   4 +-
 app/views/member/blog/add_single.html         |   4 +-
 app/views/member/blog/base.html               |   2 +-
 app/views/member/blog/single.html             |   4 +-
 app/views/member/blog/theme.html              |  30 ++-
 app/views/member/blog/update_theme.html       |   2 +-
 app/views/note/note-dev.html                  | 158 +++++++++++++--
 app/views/note/note.html                      | 161 +++++++++++++--
 26 files changed, 719 insertions(+), 254 deletions(-)
 create mode 100644 app/views/errors/500-blog.html

diff --git a/app/controllers/AttachController.go b/app/controllers/AttachController.go
index 90246d7..d7f2134 100644
--- a/app/controllers/AttachController.go
+++ b/app/controllers/AttachController.go
@@ -62,7 +62,7 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
 		maxFileSize = 1000
 	}
 	if(float64(len(data)) > maxFileSize * float64(1024*1024)) {
-		resultMsg = fmt.Sprintf("附件大于%vM", maxFileSize)
+		resultMsg = fmt.Sprintf("The file's size is bigger than %vM", maxFileSize)
 		return re
 	}
 	
@@ -100,11 +100,15 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
 	id := bson.NewObjectId();
 	fileInfo.AttachId = id
 	fileId = id.Hex()
-	Ok = attachService.AddAttach(fileInfo)
+	Ok, resultMsg = attachService.AddAttach(fileInfo)
+	if resultMsg != "" {
+		resultMsg = c.Message(resultMsg)
+	}
 	
 	fileInfo.Path = ""; // 不要返回
-	resultMsg = "success"
-	
+	if Ok {
+		resultMsg = "success"
+	}
 	return re
 }
 
@@ -212,4 +216,4 @@ func (c Attach) DownloadAll(noteId string) revel.Result {
 //    file, _ := os.Open(dir + "/" + filename)
 	// fw.Seek(0, 0)
     return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachment
-}
\ No newline at end of file
+}
diff --git a/app/controllers/AuthController.go b/app/controllers/AuthController.go
index 3814668..8cd0d5b 100644
--- a/app/controllers/AuthController.go
+++ b/app/controllers/AuthController.go
@@ -91,18 +91,19 @@ func (c Auth) Demo() revel.Result {
 
 //--------
 // 注册
-func (c Auth) Register(from string) revel.Result {
+func (c Auth) Register(from, iu string) revel.Result {
 	if !configService.IsOpenRegister() {
 		return c.Redirect("/index")
 	}
 	c.SetLocale()
 	c.RenderArgs["from"] = from
+	c.RenderArgs["iu"] = iu
 	
 	c.RenderArgs["title"] = c.Message("register")
 	c.RenderArgs["subTitle"] = c.Message("register")
 	return c.RenderTemplate("home/register.html")
 }
-func (c Auth) DoRegister(email, pwd string) revel.Result {
+func (c Auth) DoRegister(email, pwd, iu string) revel.Result {
 	if !configService.IsOpenRegister() {
 		return c.Redirect("/index")
 	}
@@ -117,7 +118,7 @@ func (c Auth) DoRegister(email, pwd string) revel.Result {
 	}
 	
 	// 注册
-	re.Ok, re.Msg = authService.Register(email, pwd)
+	re.Ok, re.Msg = authService.Register(email, pwd, iu)
 	
 	// 注册成功, 则立即登录之
 	if re.Ok {
diff --git a/app/controllers/BaseController.go b/app/controllers/BaseController.go
index fcef661..e82be4a 100644
--- a/app/controllers/BaseController.go
+++ b/app/controllers/BaseController.go
@@ -193,12 +193,13 @@ func (c BaseController) SetLocale() string {
 }
 
 // 设置userInfo
-func (c BaseController) SetUserInfo() {
+func (c BaseController) SetUserInfo() info.User {
 	userInfo := c.GetUserInfo()
 	c.RenderArgs["userInfo"] = userInfo
 	if(userInfo.Username == configService.GetAdminUsername()) {
 		c.RenderArgs["isAdmin"] = true
 	}
+	return userInfo
 }
 
 // life
@@ -224,6 +225,7 @@ func (c BaseController) RenderTemplateStr(templatePath string) string {
 // 为了msg
 // msg-v1-v2-v3
 func (c BaseController) RenderRe(re info.Re) revel.Result {
+	oldMsg := re.Msg
 	if re.Msg != "" {
 		if(strings.Contains(re.Msg, "-")) {
 			msgAndValues := strings.Split(re.Msg, "-")
@@ -241,5 +243,8 @@ func (c BaseController) RenderRe(re info.Re) revel.Result {
 			re.Msg = c.Message(re.Msg)
 		}
 	}
+	if strings.HasPrefix(re.Msg, "???") {
+		re.Msg = oldMsg
+	}
 	return c.RenderJson(re)
 }
diff --git a/app/controllers/BlogController.go b/app/controllers/BlogController.go
index 088ddf8..98c6c36 100644
--- a/app/controllers/BlogController.go
+++ b/app/controllers/BlogController.go
@@ -57,6 +57,9 @@ func (c Blog) render(templateName string, themePath string) revel.Result {
 		isPreview = true
 		themePath = themePath2.(string)
 		c.setPreviewUrl()
+		
+		// 因为common的themeInfo是从UserBlog.ThemeId来取的, 所以这里要fugai下
+		c.RenderArgs["themeInfo"] = c.RenderArgs["themeInfoPreview"];
 	}
 	return blog.RenderTemplate(templateName, c.RenderArgs, revel.BasePath+"/"+themePath, isPreview)
 }
@@ -846,4 +849,4 @@ func (c Blog) ListCateLatest(notebookId, callback string) revel.Result {
 	re.Ok = true
 	re.List = blogs
 	return c.RenderJsonP(callback, re)
-}
\ No newline at end of file
+}
diff --git a/app/controllers/FileController.go b/app/controllers/FileController.go
index 7e4a4b7..49f4d1e 100644
--- a/app/controllers/FileController.go
+++ b/app/controllers/FileController.go
@@ -10,7 +10,7 @@ import (
 	"io/ioutil"
 	"os"
 	"fmt"
-	"strconv"
+//	"strconv"
 	"strings"
 )
 
@@ -85,7 +85,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
 	var fileUrlPath = ""
 	var fileId = ""
 	var resultCode = 0 // 1表示正常
-	var resultMsg = "内部错误" // 错误信息
+	var resultMsg = "error" // 错误信息
 	var Ok = false
 	
 	defer func() {
@@ -120,7 +120,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
 	} else {
 		_, ext = SplitFilename(filename)
 		if(ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg") {
-			resultMsg = "不是图片"
+			resultMsg = "Please upload image"
 			return re
 		}
 	}
@@ -147,7 +147,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
 	// > 2M?
 	if(float64(len(data)) > maxFileSize * float64(1024*1024)) {
 		resultCode = 0
-		resultMsg = fmt.Sprintf("图片大于%vM", maxFileSize)
+		resultMsg = fmt.Sprintf("The file Size is bigger than %vM", maxFileSize)
 		return re
 	}
 	
@@ -163,7 +163,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
 	filesize := GetFilesize(toPathGif)
 	fileUrlPath += "/" + filename
 	resultCode = 1
-	resultMsg = "上传成功!"
+	resultMsg = "Upload Success!"
 	
 	// File
 	fileInfo := info.File{Name: filename,
@@ -178,7 +178,8 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
 		fileId = "public/upload/" + c.GetUserId() + "/images/logo/" + filename
 	}
 	
-	Ok = fileService.AddImage(fileInfo, albumId, c.GetUserId())
+	Ok, resultMsg = fileService.AddImage(fileInfo, albumId, c.GetUserId(), from == "" || from == "pasteImage")
+	resultMsg = c.Message(resultMsg)
 	
 	fileInfo.Path = ""; // 不要返回
 	re.Item = fileInfo
@@ -203,55 +204,6 @@ func (c File) DeleteImage(fileId string) revel.Result {
 	re.Ok, re.Msg = fileService.DeleteImage(c.GetUserId(), fileId)
 	return c.RenderJson(re)
 }
-
-// update image uploader to leaui image, 
-// scan all user's images and insert into db
-func (c File) UpgradeLeauiImage() revel.Result {
-	re := info.NewRe()
-	
-	if ok, _ := revel.Config.Bool("upgradeLeauiImage"); !ok {
-		re.Msg = "Not allowed"
-		return c.RenderJson(re)
-	}
-	
-	uploadPath := revel.BasePath + "/public/upload";
-	userIds := ListDir(uploadPath)
-	if userIds == nil {
-		re.Msg = "no user"
-		return c.RenderJson(re)
-	}
-	
-	msg := "";
-	
-	for _, userId := range userIds {
-		dirPath := uploadPath + "/" + userId +  "/images"
-		images := ListDir(dirPath)
-		if images == nil {
-			msg += userId + " no images "
-			continue;
-		}
-		
-		hadImages := fileService.GetAllImageNamesMap(userId)
-		
-		i := 0
-		for _, filename := range images {
-			if _, ok := hadImages[filename]; !ok {
-				fileUrlPath := "/upload/" + userId + "/images/" + filename
-				fileInfo := info.File{Name: filename,
-					Title: filename,
-					Path: fileUrlPath,
-					Size: GetFilesize(dirPath + "/" + filename)}
-				fileService.AddImage(fileInfo, "", userId)
-				i++
-			}
-		}
-		msg += userId + ": " + strconv.Itoa(len(images)) + " -- " + strconv.Itoa(i) + " images "
-	}
-	
-	re.Msg = msg
-	return c.RenderJson(re)
-}
-
 //-----------
 
 // 输出image
@@ -267,15 +219,15 @@ func (c File) OutputImage(noteId, fileId string) revel.Result {
 }
 
 // 协作时复制图片到owner
+// 需要计算对方大小
 func (c File) CopyImage(userId, fileId, toUserId string) revel.Result {
 	re := info.NewRe()
-	
 	re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId)
-	
 	return c.RenderJson(re)
 }
 
 // 复制外网的图片, 成公共图片 放在/upload下
+// 都要好好的计算大小
 func (c File) CopyHttpImage(src string) revel.Result {
 	re := info.NewRe()
 	fileUrlPath := "upload/" + c.GetUserId() + "/images"
@@ -302,29 +254,7 @@ func (c File) CopyHttpImage(src string) revel.Result {
 	
 	re.Id = id.Hex()
 	re.Item = fileInfo.Path
-	re.Ok = fileService.AddImage(fileInfo, "", c.GetUserId())
+	re.Ok, re.Msg = fileService.AddImage(fileInfo, "", c.GetUserId(), true)
 	
 	return c.RenderJson(re)
-}
-
-//------------
-// 过时 已弃用!
-func (c File) UploadImage(renderHtml string) revel.Result {
-	if renderHtml == "" {
-		renderHtml = "file/image.html"
-	}
-	
-	re := c.uploadImage("", "");
-	
-	c.RenderArgs["fileUrlPath"] = configService.GetSiteUrl() + re.Id
-	c.RenderArgs["resultCode"] = re.Code
-	c.RenderArgs["resultMsg"] = re.Msg
-
-	return c.RenderTemplate(renderHtml)
-}
-
-// 已弃用
-func (c File) UploadImageJson(from, noteId string) revel.Result {
-	re := c.uploadImage(from, "");
-	return c.RenderJson(re)
-}
+}
\ No newline at end of file
diff --git a/app/controllers/PreviewController.go b/app/controllers/PreviewController.go
index 03cfca9..f24afa8 100644
--- a/app/controllers/PreviewController.go
+++ b/app/controllers/PreviewController.go
@@ -33,6 +33,8 @@ func (c Preview) getPreviewThemeAbsolutePath(themeId string) bool {
 	theme := themeService.GetTheme(c.GetUserId(), themeId)
 	
 	c.RenderArgs["isPreview"] = true
+	c.RenderArgs["themeId"] = themeId
+	c.RenderArgs["themeInfoPreview"] = theme.Info
 	c.RenderArgs["themePath"] = theme.Path
 	if theme.Path == "" {
 		return false
diff --git a/app/controllers/member/MemberBlogController.go b/app/controllers/member/MemberBlogController.go
index 97359b1..2ae4c3e 100644
--- a/app/controllers/member/MemberBlogController.go
+++ b/app/controllers/member/MemberBlogController.go
@@ -1,15 +1,15 @@
 package member
 
 import (
-	"github.com/revel/revel"
-	. "github.com/leanote/leanote/app/lea"
-	"github.com/leanote/leanote/app/info"
-	"os"
-	"io/ioutil"
-	"time"
 	"fmt"
+	"github.com/leanote/leanote/app/info"
+	. "github.com/leanote/leanote/app/lea"
+	"github.com/revel/revel"
+	"io/ioutil"
+	"os"
 	"strings"
-//	"github.com/leanote/leanote/app/lea/blog"
+	"time"
+	//	"github.com/leanote/leanote/app/lea/blog"
 )
 
 // 博客管理
@@ -28,35 +28,34 @@ func (c MemberBlog) common() info.UserBlog {
 
 	userBlog := blogService.GetUserBlog(userId)
 	c.RenderArgs["userBlog"] = userBlog
-	
+
 	c.SetUserInfo()
 	c.SetLocale()
 	return userBlog
 }
 
-
 // 得到sorterField 和 isAsc
 // okSorter = ['email', 'username']
-func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool){
+func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool) {
 	sorter := ""
 	c.Params.Bind(&sorter, "sorter")
 	if sorter == "" {
-		return sorterField, isAsc;
+		return sorterField, isAsc
 	}
-	
+
 	// sorter形式 email-up, email-down
 	s2 := strings.Split(sorter, "-")
 	if len(s2) != 2 {
-		return sorterField, isAsc;
+		return sorterField, isAsc
 	}
-	
+
 	// 必须是可用的sorter
 	if okSorter != nil && len(okSorter) > 0 {
 		if !InArray(okSorter, s2[0]) {
-			return sorterField, isAsc;
+			return sorterField, isAsc
 		}
 	}
-	
+
 	sorterField = strings.Title(s2[0])
 	if s2[1] == "up" {
 		isAsc = true
@@ -64,28 +63,29 @@ func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string)
 		isAsc = false
 	}
 	c.RenderArgs["sorter"] = sorter
-	return sorterField, isAsc;
+	return sorterField, isAsc
 }
 
 // 博客列表
 var userPageSize = 15
+
 func (c MemberBlog) Index(sorter, keywords string) revel.Result {
 	userId := c.GetUserId()
 	userInfo := userService.GetUserInfo(userId)
 	c.RenderArgs["userInfo"] = userInfo
-	
+
 	c.RenderArgs["title"] = "Posts"
 	pageNumber := c.GetPage()
-	sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"});
-	pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc);
+	sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"})
+	pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc)
 	c.RenderArgs["pageInfo"] = pageInfo
 	c.RenderArgs["blogs"] = blogs
 	c.RenderArgs["keywords"] = keywords
-	
+
 	userAndBlog := userService.GetUserAndBlog(c.GetUserId())
 	c.RenderArgs["userAndBlog"] = userAndBlog
-	
-	return c.RenderTemplate("member/blog/list.html");
+
+	return c.RenderTemplate("member/blog/list.html")
 }
 
 // 修改笔记的urlTitle
@@ -95,17 +95,16 @@ func (c MemberBlog) UpdateBlogUrlTitle(noteId, urlTitle string) revel.Result {
 	return c.RenderJson(re)
 }
 
-
 // 修改笔记的urlTitle
 func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result {
 	c.RenderArgs["title"] = "Update Post Abstract"
-	note := noteService.GetNoteAndContent(noteId, c.GetUserId());
+	note := noteService.GetNoteAndContent(noteId, c.GetUserId())
 	if !note.Note.IsBlog {
-		return c.E404();
+		return c.E404()
 	}
 	c.RenderArgs["note"] = note
 	c.RenderArgs["noteId"] = noteId
-	return c.RenderTemplate("member/blog/update_abstract.html");
+	return c.RenderTemplate("member/blog/update_abstract.html")
 }
 func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string) revel.Result {
 
@@ -118,38 +117,33 @@ func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string)
 func (c MemberBlog) Base() revel.Result {
 	c.common()
 	c.RenderArgs["title"] = "Blog Base Info"
-	return c.RenderTemplate("member/blog/base.html");
+	return c.RenderTemplate("member/blog/base.html")
 }
 func (c MemberBlog) Comment() revel.Result {
 	c.common()
 	c.RenderArgs["title"] = "Comment"
-	return c.RenderTemplate("member/blog/comment.html");
-}
-func (c MemberBlog) Domain() revel.Result {
-	c.common()
-	c.RenderArgs["title"] = "Domain"
-	return c.RenderTemplate("member/blog/domain.html");
+	return c.RenderTemplate("member/blog/comment.html")
 }
 
 func (c MemberBlog) Paging() revel.Result {
 	c.common()
 	c.RenderArgs["title"] = "Paging"
-	return c.RenderTemplate("member/blog/paging.html");
+	return c.RenderTemplate("member/blog/paging.html")
 }
 
 func (c MemberBlog) Cate() revel.Result {
 	userBlog := c.common()
 	c.RenderArgs["title"] = "Cate"
-	
+
 	notebooks := blogService.ListBlogNotebooks(c.GetUserId())
 	notebooksMap := map[string]info.Notebook{}
 	for _, each := range notebooks {
 		notebooksMap[each.NotebookId.Hex()] = each
 	}
-	
-	var i = 0;
+
+	var i = 0
 	notebooks2 := make([]info.Notebook, len(notebooks))
-	
+
 	// 先要保证已有的是正确的排序
 	cateIds := userBlog.CateIds
 	has := map[string]bool{} // cateIds中有的
@@ -171,8 +165,8 @@ func (c MemberBlog) Cate() revel.Result {
 		}
 	}
 	c.RenderArgs["notebooks"] = notebooks2
-	
-	return c.RenderTemplate("member/blog/cate.html");
+
+	return c.RenderTemplate("member/blog/cate.html")
 }
 
 // 修改分类排序
@@ -199,9 +193,10 @@ func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result {
 	c.RenderArgs["title"] = "Add Single"
 	c.RenderArgs["singleId"] = singleId
 	if singleId != "" {
+		c.RenderArgs["title"] = "Update Single"
 		c.RenderArgs["single"] = blogService.GetSingle(singleId)
 	}
-	return c.RenderTemplate("member/blog/add_single.html");
+	return c.RenderTemplate("member/blog/add_single.html")
 }
 func (c MemberBlog) SortSingles(singleIds []string) revel.Result {
 	re := info.NewRe()
@@ -226,8 +221,8 @@ func (c MemberBlog) Single() revel.Result {
 	c.common()
 	c.RenderArgs["title"] = "Cate"
 	c.RenderArgs["singles"] = blogService.GetSingles(c.GetUserId())
-	
-	return c.RenderTemplate("member/blog/single.html");
+
+	return c.RenderTemplate("member/blog/single.html")
 }
 
 // 主题
@@ -236,15 +231,16 @@ func (c MemberBlog) Theme() revel.Result {
 	activeTheme, otherThemes := themeService.GetUserThemes(c.GetUserId())
 	c.RenderArgs["activeTheme"] = activeTheme
 	c.RenderArgs["otherThemes"] = otherThemes
-	
+
 	c.RenderArgs["optionThemes"] = themeService.GetDefaultThemes()
-	
+
 	c.RenderArgs["title"] = "Theme"
-	return c.RenderTemplate("member/blog/theme.html");
+	return c.RenderTemplate("member/blog/theme.html")
 }
 
 // 编辑主题
 var baseTpls = []string{"header.html", "footer.html", "index.html", "cate.html", "search.html", "post.html", "single.html", "tags.html", "tag_posts.html", "archive.html", "share_comment.html", "404.html", "theme.json", "style.css", "blog.js"}
+
 func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
 	// 查看用户是否有该theme, 若没有则复制default之
 	// 得到主题的文件列表
@@ -253,22 +249,25 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
 		_, themeId = themeService.NewThemeForFirst(userBlog)
 		return c.Redirect("/member/blog/updateTheme?themeId=" + themeId)
 	}
-	
+
 	c.common()
 	c.RenderArgs["title"] = "Upate Theme"
 	c.RenderArgs["isNew"] = isNew
-	
+
 	// 先复制之
 	c.RenderArgs["themeId"] = themeId
-	
+
 	// 得到脚本目录
 	userId := c.GetUserId()
-	
-	theme := themeService.GetTheme(userId, themeId) 
+
+	theme := themeService.GetTheme(userId, themeId)
+	if theme.ThemeId == "" {
+		return c.E404()
+	}
 	c.RenderArgs["theme"] = theme
-	
+
 	path := revel.BasePath + "/" + theme.Path
-	
+
 	tpls := ListDir(path)
 	myTpls := make([]string, len(baseTpls))
 	tplMap := map[string]bool{}
@@ -279,16 +278,16 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
 	// 得到没有的tpls
 	for _, t := range tpls {
 		if t == "images" {
-			continue;
+			continue
 		}
 		if !tplMap[t] {
 			myTpls = append(myTpls, t)
 		}
 	}
-	
+
 	c.RenderArgs["myTpls"] = myTpls
-	
-	return c.RenderTemplate("member/blog/update_theme.html");
+
+	return c.RenderTemplate("member/blog/update_theme.html")
 }
 
 // 得到文件内容
@@ -296,13 +295,13 @@ func (c MemberBlog) GetTplContent(themeId string, filename string) revel.Result
 	re := info.NewRe()
 	re.Ok = true
 	re.Item = themeService.GetTplContent(c.GetUserId(), themeId, filename)
-	
+
 	return c.RenderJson(re)
 }
 func (c MemberBlog) UpdateTplContent(themeId, filename, content string) revel.Result {
 	re := info.NewRe()
 	re.Ok, re.Msg = themeService.UpdateTplContent(c.GetUserId(), themeId, filename, content)
-	return c.RenderJson(re)
+	return c.RenderRe(re)
 }
 
 func (c MemberBlog) DeleteTpl(themeId, filename string) revel.Result {
@@ -331,7 +330,7 @@ func (c MemberBlog) DeleteThemeImage(themeId, filename string) revel.Result {
 
 // 上传主题图片
 func (c MemberBlog) UploadThemeImage(themeId string) revel.Result {
-	re := c.uploadImage(themeId);
+	re := c.uploadImage(themeId)
 	c.RenderArgs["fileUrlPath"] = re.Id
 	c.RenderArgs["resultCode"] = re.Code
 	c.RenderArgs["resultMsg"] = re.Msg
@@ -339,17 +338,17 @@ func (c MemberBlog) UploadThemeImage(themeId string) revel.Result {
 }
 func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
 	var fileId = ""
-	var resultCode = 0 // 1表示正常
+	var resultCode = 0     // 1表示正常
 	var resultMsg = "内部错误" // 错误信息
 	var Ok = false
-	
+
 	defer func() {
 		re.Id = fileId // 只是id, 没有其它信息
 		re.Code = resultCode
 		re.Msg = resultMsg
 		re.Ok = Ok
 	}()
-	
+
 	file, handel, err := c.Request.FormFile("file")
 	if err != nil {
 		return re
@@ -363,11 +362,11 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
 	}
 	// 生成新的文件名
 	filename := handel.Filename
-	
-	var ext string;
-	
+
+	var ext string
+
 	_, ext = SplitFilename(filename)
-	if(ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg") {
+	if ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg" {
 		resultMsg = "不是图片"
 		return re
 	}
@@ -378,15 +377,15 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
 		LogJ(err)
 		return re
 	}
-	
+
 	// > 2M?
-	if(len(data) > 5 * 1024 * 1024) {
+	if len(data) > 5*1024*1024 {
 		resultCode = 0
 		resultMsg = "图片大于2M"
 		return re
 	}
-	
-	toPath := dir + "/" + filename;
+
+	toPath := dir + "/" + filename
 	err = ioutil.WriteFile(toPath, data, 0777)
 	if err != nil {
 		LogJ(err)
@@ -395,7 +394,7 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
 	TransToGif(toPath, 0, true)
 	resultCode = 1
 	resultMsg = "上传成功!"
-	
+
 	return re
 }
 
@@ -406,18 +405,21 @@ func (c MemberBlog) ActiveTheme(themeId string) revel.Result {
 	re.Ok = themeService.ActiveTheme(c.GetUserId(), themeId)
 	return c.RenderJson(re)
 }
+
 // 删除主题
 func (c MemberBlog) DeleteTheme(themeId string) revel.Result {
 	re := info.NewRe()
 	re.Ok = themeService.DeleteTheme(c.GetUserId(), themeId)
 	return c.RenderJson(re)
 }
+
 // 管理员公开主题
 func (c MemberBlog) PublicTheme(themeId string) revel.Result {
 	re := info.NewRe()
 	re.Ok = themeService.PublicTheme(c.GetUserId(), themeId)
 	return c.RenderJson(re)
 }
+
 // 导出
 func (c MemberBlog) ExportTheme(themeId string) revel.Result {
 	re := info.NewRe()
@@ -427,21 +429,21 @@ func (c MemberBlog) ExportTheme(themeId string) revel.Result {
 		return c.RenderText("error...")
 	}
 	fw, err := os.Open(path)
-    if err != nil {
+	if err != nil {
 		return c.RenderText("error")
-    }
-    return c.RenderBinary(fw, GetFilename(path), revel.Attachment, time.Now()) // revel.Attachment
+	}
+	return c.RenderBinary(fw, GetFilename(path), revel.Attachment, time.Now()) // revel.Attachment
 }
 
 // 导入主题
 func (c MemberBlog) ImportTheme() revel.Result {
 	re := info.NewRe()
-	
+
 	file, handel, err := c.Request.FormFile("file")
 	if err != nil {
 		re.Msg = fmt.Sprintf("%v", err)
 		return c.RenderJson(re)
-		
+
 	}
 	defer file.Close()
 	// 生成上传路径
@@ -454,10 +456,10 @@ func (c MemberBlog) ImportTheme() revel.Result {
 	}
 	// 生成新的文件名
 	filename := handel.Filename
-	
-	var ext string;
+
+	var ext string
 	_, ext = SplitFilename(filename)
-	if(ext != ".zip") {
+	if ext != ".zip" {
 		re.Msg = "请上传zip文件"
 		return c.RenderJson(re)
 	}
@@ -467,40 +469,40 @@ func (c MemberBlog) ImportTheme() revel.Result {
 	if err != nil {
 		return c.RenderJson(re)
 	}
-	
+
 	// > 10M?
-	if(len(data) > 10 * 1024 * 1024) {
+	if len(data) > 10*1024*1024 {
 		re.Msg = "文件大于10M"
 		return c.RenderJson(re)
 	}
-	
-	toPath := dir + "/" + filename;
+
+	toPath := dir + "/" + filename
 	err = ioutil.WriteFile(toPath, data, 0777)
 	if err != nil {
 		re.Msg = fmt.Sprintf("%v", err)
 		return c.RenderJson(re)
 	}
-	
+
 	// 上传好后, 增加之
-	themeService.ImportTheme(c.GetUserId(), toPath)
-	
-	re.Ok = true
-	return c.RenderJson(re)
+	re.Ok, re.Msg = themeService.ImportTheme(c.GetUserId(), toPath)
+	return c.RenderRe(re)
 }
-	
+
 // 安装
 func (c MemberBlog) InstallTheme(themeId string) revel.Result {
 	re := info.NewRe()
 	re.Ok = themeService.InstallTheme(c.GetUserId(), themeId)
 	return c.RenderJson(re)
 }
+
 // 新建主题
 func (c MemberBlog) NewTheme() revel.Result {
 	_, themeId := themeService.NewTheme(c.GetUserId())
 	return c.Redirect("/member/blog/updateTheme?isNew=1&themeId=" + themeId)
 }
+
 //-----------
-// 
+//
 func (c MemberBlog) SetUserBlogBase(userBlog info.UserBlogBase) revel.Result {
 	re := info.NewRe()
 	re.Ok = blogService.UpdateUserBlogBase(c.GetUserId(), userBlog)
@@ -516,6 +518,7 @@ func (c MemberBlog) SetUserBlogStyle(userBlog info.UserBlogStyle) revel.Result {
 	re.Ok = blogService.UpdateUserBlogStyle(c.GetUserId(), userBlog)
 	return c.RenderJson(re)
 }
+
 func (c MemberBlog) SetUserBlogPaging(perPageSize int, sortField string, isAsc bool) revel.Result {
 	re := info.NewRe()
 	re.Ok, re.Msg = blogService.UpdateUserBlogPaging(c.GetUserId(), perPageSize, sortField, isAsc)
diff --git a/app/controllers/member/init.go b/app/controllers/member/init.go
index d891db2..b52edb0 100644
--- a/app/controllers/member/init.go
+++ b/app/controllers/member/init.go
@@ -128,6 +128,7 @@ func init() {
 	revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberIndex{})
 	revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberUser{})
 	revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberBlog{})
+	revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberGroup{})
 	revel.OnAppStart(func() {
 	})
-}
+}
\ No newline at end of file
diff --git a/app/db/Mgo.go b/app/db/Mgo.go
index 37b0bdb..684ae10 100644
--- a/app/db/Mgo.go
+++ b/app/db/Mgo.go
@@ -3,6 +3,7 @@ package db
 import (
 	"fmt"
 	"github.com/revel/revel"
+	. "github.com/leanote/leanote/app/lea"
 	"gopkg.in/mgo.v2"
 	"gopkg.in/mgo.v2/bson"
 )
@@ -56,12 +57,15 @@ var Themes *mgo.Collection
 var Sessions *mgo.Collection
 
 // 初始化时连接数据库
-func Init() {
-	var url string
-	var ok bool
+func Init(url, dbname string) {
+	ok := true
 	config := revel.Config
-	url, ok = config.String("db.url")
-	dbname, _ := config.String("db.dbname")
+	if url == "" { 
+		url, ok = config.String("db.url")
+	}
+	if dbname == "" {
+		dbname, _ = config.String("db.dbname")
+	}
 	if !ok {
 		host, _ := revel.Config.String("db.host")
 		port, _ := revel.Config.String("db.port")
@@ -73,6 +77,7 @@ func Init() {
 		}
 		url = "mongodb://" + usernameAndPassword + host + ":" + port + "/" + dbname
 	}
+	Log(url)
 
 	// [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]
 	// mongodb://myuser:mypass@localhost:40001,otherhost:40001/mydb
diff --git a/app/lea/Debug.go b/app/lea/Debug.go
index ce8bb02..7684521 100644
--- a/app/lea/Debug.go
+++ b/app/lea/Debug.go
@@ -3,6 +3,7 @@ package lea
 import (
 	"encoding/json"
 	"github.com/revel/revel"
+	"fmt"
 )
 
 func Log(i interface{}) {
@@ -12,4 +13,14 @@ func Log(i interface{}) {
 func LogJ(i interface{}) {
 	b, _ := json.MarshalIndent(i, "", "	") 
 	revel.INFO.Println(string(b))
-}
\ No newline at end of file
+}
+
+// 为test用
+func L(i interface{}) {
+	fmt.Println(i)
+}
+
+func LJ(i interface{}) {
+	b, _ := json.MarshalIndent(i, "", "	") 
+	fmt.Println(string(b))
+}
diff --git a/app/release/release.go b/app/release/release.go
index 05c0d2b..dfe4019 100644
--- a/app/release/release.go
+++ b/app/release/release.go
@@ -7,6 +7,7 @@ import (
 	"io/ioutil"
 	"strings"
 )
+
 /*
 用golang exec 总是说找不到uglifyjs命令, 需要全部路径
 而且node, npm要在/usr/bin下, 已建ln
@@ -33,8 +34,8 @@ var jss = []string{"js/jquery-cookie", "js/bootstrap",
 	"js/common", "js/app/note", "js/app/tag", "js/app/notebook", "js/app/share", 
 	"js/object_id", "js/ZeroClipboard/ZeroClipboard"}
 	
-var base1 = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/"
-var base = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/public/"
+var base1 = "/Users/life/Documents/Go/package1/src/github.com/leanote/leanote/"
+var base = "/Users/life/Documents/Go/package1/src/github.com/leanote/leanote/public/"
 var cmdPath = "/usr/local/bin/uglifyjs"
 
 func cmdError(err error) {
@@ -52,7 +53,7 @@ func compressJs(filename string) {
 	to := base + filename + "-min.js"
 	cmd := exec.Command(cmdPath, source, "-o", to)
 	_, err := cmd.CombinedOutput()
-
+	fmt.Println(source);
 	cmdError(err)
 }
 	
@@ -80,7 +81,10 @@ func combineJs() {
 // 改note-dev->note
 func dev() {
 	// 即替换note.js->note-min.js
-	m := map[string]string{"note.js": "note-min.js", 
+	m := map[string]string{"tinymce.dev.js": "tinymce.min.js", 
+		"tinymce.js": "tinymce.min.js", 
+		"jquery.ztree.all-3.5.js": "jquery.ztree.all-3.5-min.js",
+		"note.js": "note-min.js", 
 		"app.js": "app-min.js", 
 		"page.js": "page-min.js", 
 		"common.js": "common-min.js",
@@ -88,6 +92,7 @@ func dev() {
 		"share.js": "share-min.js",
 		"tag.js": "tag-min.js",
 		"main.js": "main-min.js",
+		"jquery.slimscroll.js": "jquery.slimscroll-min.js",
 		"jquery.contextmenu.js": "jquery.contextmenu-min.js",
 		"editor/editor.js": "editor/editor-min.js",
 		"/public/mdeditor/editor/scrollLink.js": "/public/mdeditor/editor/scrollLink-min.js",
@@ -111,12 +116,21 @@ func tinymce() {
 //	cmd := exec.Command("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify", "bundle[themes:modern,plugins:table,paste,advlist,autolink,link,image,lists,charmap,hr,searchreplace,visualblocks,visualchars,code,nav,tabfocus,contextmenu,directionality,codemirror,codesyntax,textcolor,fullpage]")
 	cmd := exec.Command("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify")
 	cmd.Dir = "/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master"
-	c, err := cmd.CombinedOutput()
+	
+	// 必须要先删除
+	cmd2 := exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.dev.js")
+	cmd2.CombinedOutput()
+	cmd2 = exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.jquery.dev.js")
+	c, _ := cmd2.CombinedOutput()
+	fmt.Println(string(c))
+	c, _ = cmd.CombinedOutput()
 	fmt.Println(string(c))
-	cmdError(err)
 }
 
 func main() {
+	// 压缩tinymce
+	tinymce()
+	
 	dev();
 	
 	// 其它零散的需要压缩的js
@@ -133,6 +147,10 @@ func main() {
 		"mdeditor/editor/underscore",
 		"mdeditor/editor/mathJax",
 		"js/jQuery-slimScroll-1.3.0/jquery.slimscroll",
+		"js/app/editor_drop_paste",
+		"js/app/attachment_upload",
+		"js/jquery.ztree.all-3.5",
+		"js/jQuery-slimScroll-1.3.0/jquery.slimscroll",
 		}
 		
 	for _, js := range otherJss {
@@ -141,7 +159,5 @@ func main() {
 	
 	// 先压缩后合并
 	combineJs()
-	
-	// 压缩tinymce
-	tinymce()
+
 }
diff --git a/app/service/AuthService.go b/app/service/AuthService.go
index 6e4fd24..3937741 100644
--- a/app/service/AuthService.go
+++ b/app/service/AuthService.go
@@ -5,6 +5,7 @@ import (
 //	"github.com/leanote/leanote/app/db"
 	"github.com/leanote/leanote/app/info"
 //	"github.com/revel/revel"
+	"strings"
 	. "github.com/leanote/leanote/app/lea"
 	"fmt"
 	"strconv"
@@ -17,6 +18,8 @@ type AuthService struct {
 
 // pwd已md5了
 func (this *AuthService) Login(emailOrUsername, pwd string) info.User {
+	emailOrUsername = strings.Trim(emailOrUsername, " ")
+//	pwd = strings.Trim(pwd, " ")
 	userInfo := userService.LoginGetUserInfo(emailOrUsername, Md5(pwd))
 	return userInfo
 }
@@ -32,12 +35,16 @@ func (this *AuthService) Login(emailOrUsername, pwd string) info.User {
 // 1. 添加用户
 // 2. 将leanote共享给我
 // [ok]
-func (this *AuthService) Register(email, pwd string) (bool, string) {
+func (this *AuthService) Register(email, pwd, fromUserId string) (bool, string) {
 	// 用户是否已存在
 	if userService.IsExistsUser(email) {
 		return false, "userHasBeenRegistered-" + email
 	}
 	user := info.User{UserId: bson.NewObjectId(), Email: email, Username: email, Pwd: Md5(pwd)}
+	if fromUserId != "" && IsObjectId(fromUserId) {
+		user.FromUserId = bson.ObjectIdHex(fromUserId)
+	}
+	LogJ(user)
 	return this.register(user)
 }
 
@@ -129,4 +136,4 @@ func (this *AuthService) ThirdRegister(thirdType, thirdUserId, thirdUsername str
 		}
 	_, _ = this.register(userInfo)
 	return
-}
\ No newline at end of file
+}
diff --git a/app/service/FileService.go b/app/service/FileService.go
index 21a2e5e..6a403ae 100644
--- a/app/service/FileService.go
+++ b/app/service/FileService.go
@@ -147,7 +147,16 @@ func (this *FileService) GetFile(userId, fileId string) string {
 			return path
 		}
 		
+		// 2014/12/28 修复, 如果是分享给用户组, 那就不行, 这里可以实现
+		for _, noteId := range noteIds {
+			note := noteService.GetNoteById(noteId.Hex())
+			if shareService.HasReadPerm(note.UserId.Hex(), userId, noteId.Hex()) {
+				return path;
+			}
+		}
+		/*
 		// 若有共享给我的笔记?
+		// 对该笔记可读?
 		if db.Has(db.ShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NoteId": bson.M{"$in": noteIds}}) {
 			return path
 		}
@@ -166,6 +175,7 @@ func (this *FileService) GetFile(userId, fileId string) string {
 				return path
 			}
 		}
+		*/
 	}
 	
 	// 可能是刚复制到owner上, 但内容又没有保存, 所以没有note->imageId的映射, 此时看是否有fromFileId
diff --git a/app/service/NoteContentHistoryService.go b/app/service/NoteContentHistoryService.go
index 4b67c31..803feb6 100644
--- a/app/service/NoteContentHistoryService.go
+++ b/app/service/NoteContentHistoryService.go
@@ -33,7 +33,8 @@ func (this *NoteContentHistoryService) AddHistory(noteId, userId string, eachHis
 		// TODO
 		l := len(history.Histories)
 		if l >= maxSize {
-			history.Histories = history.Histories[l-maxSize:]
+			// history.Histories = history.Histories[l-maxSize:] // BUG, 致使都是以前的
+			history.Histories = history.Histories[:maxSize]
 		}
 		newHistory := []info.EachHistory{eachHistory}
 		newHistory = append(newHistory, history.Histories...) // 在开头加了, 最近的在最前
@@ -61,4 +62,4 @@ func (this *NoteContentHistoryService) ListHistories(noteId, userId string) []in
 	histories := info.NoteContentHistory{}
 	db.GetByIdAndUserId(db.NoteContentHistories, noteId, userId, &histories)
 	return histories.Histories
-}
\ No newline at end of file
+}
diff --git a/app/service/ShareService.go b/app/service/ShareService.go
index 40219b3..d1c05bb 100644
--- a/app/service/ShareService.go
+++ b/app/service/ShareService.go
@@ -49,6 +49,7 @@ func (this *ShareService) getOrQ(userId string) bson.M {
 	return q
 }
 
+// 得到共享给我的笔记本和用户(谁共享给了我)
 func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksByUser, []info.User) {
 	// 得到共享给我的用户s信息
 	// 得到我参与的组织
@@ -60,7 +61,7 @@ func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksB
 	db.Distinct(db.ShareNotes, q, "UserId", &userIds1)
 	
 	userIds2 := []bson.ObjectId{}
-	db.Distinct(db.ShareNotebooks, q, "UserId", &userIds1)
+	db.Distinct(db.ShareNotebooks, q, "UserId", &userIds2) // BUG之前是userId1, 2014/12/29
 	
 	userIds := append(userIds1, userIds2...)
 	userInfos := userService.GetUserInfosOrderBySeq(userIds);
diff --git a/app/service/ThemeService.go b/app/service/ThemeService.go
index 95577a7..0867299 100644
--- a/app/service/ThemeService.go
+++ b/app/service/ThemeService.go
@@ -13,6 +13,7 @@ import (
 	"fmt"
 	"html/template"
 	"regexp"
+	"io/ioutil"
 	"encoding/json"
 )
 
@@ -127,7 +128,8 @@ func (this *ThemeService) CopyDefaultTheme(userBlog info.UserBlog) (ok bool, the
 // 设为active true
 func (this *ThemeService) NewThemeForFirst(userBlog info.UserBlog) (ok bool, themeId string) {
 	ok, themeId = this.CopyDefaultTheme(userBlog)
-	db.UpdateByQField(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId)}, "IsActive", true)
+	this.ActiveTheme(userBlog.UserId.Hex(), themeId)
+	// db.UpdateByQField(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId)}, "IsActive", true)
 	return
 }
 
@@ -285,11 +287,15 @@ func (this *ThemeService) GetThemePath(userId, themeId string) string {
 }
 // 更新模板内容
 func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content string) (ok bool, msg string) {
-	path := this.GetThemeAbsolutePath(userId, themeId) + "/" + filename
+	basePath := this.GetThemeAbsolutePath(userId, themeId)
+	path := basePath + "/" + filename
 	if strings.Contains(filename, ".html") {
-		// 模板
-		if ok, msg = this.mustTpl(filename, content); ok {
-			ok = PutFileStrContent(path, content)
+		Log(">>")
+		if ok, msg = this.ValidateTheme(basePath, filename, content); ok {
+			// 模板
+			if ok, msg = this.mustTpl(filename, content); ok {
+				ok = PutFileStrContent(path, content)
+			}
 		}
 		return
 	} else if filename == "theme.json" {
@@ -410,6 +416,11 @@ func (this *ThemeService) ImportTheme(userId, path string) (ok bool, msg string)
 		DeleteFile(targetPath)
 		return
 	}
+	// 主题验证
+	if ok, msg = this.ValidateTheme(targetPath, "", ""); !ok {
+		DeleteFile(targetPath)
+		return
+	}
 	// 解压成功, 那么新建之
 	// 保存到数据库中
 	theme, _ := this.getThemeConfig(targetPath)
@@ -505,5 +516,119 @@ func (this *ThemeService) InstallTheme(userId, themeId string) (ok bool) {
 	
 	ok = db.Insert(db.Themes, theme)
 	
+	// 激活之
+	this.ActiveTheme(userId, themeId);
+
 	return ok
 }
+
+// 验证主题是否全法, 存在循环引用?
+// filename, newContent 表示在修改模板时要判断模板修改时是否有错误
+func (this *ThemeService) ValidateTheme(path string, filename, newContent string) (ok bool, msg string) {
+	Log("theme Path")
+	Log(path)
+	// 建立一个有向图	
+	// 将该path下的所有文件提出, 得到文件的引用情况
+	files := ListDir(path)
+	LogJ(files);
+	size := len(files)
+	if(size > 100) {
+		ok = false;
+		msg = "tooManyFiles"
+		return
+	}
+	/*
+	111111111
+	111000000
+	*/
+	vector := make([][]int, size)
+	for i := 0; i < size; i++ {
+		vector[i] = make([]int, size)
+	}
+	fileIndexMap := map[string]int{} // fileName => index
+	fileContent := map[string]string{} // fileName => content
+	index := 0
+	// 得到文件内容, 和建立索引, 每个文件都有一个index, 对应数组位置
+	for _, t := range files {
+		if !strings.Contains(t, ".html") {
+			continue;
+		}
+		if t != filename {
+			fileBytes, err := ioutil.ReadFile(path + "/" + t)
+			if err != nil {
+				continue
+			}
+			
+			fileIndexMap[t] = index;
+			// html内容
+			fileStr := string(fileBytes)
+			fileContent[t] = fileStr
+		} else {
+			fileIndexMap[t] = index
+			fileContent[t] = newContent
+		}
+		index++
+	}
+	// 分析文件内容, 建立有向图
+	reg, _ := regexp.Compile("{{ *template \"(.+?\\.html)\".*}}")
+	for filename, content := range fileContent {
+		thisIndex := fileIndexMap[filename]
+		finds := reg.FindAllStringSubmatch(content, -1) // 子匹配
+		LogJ(finds)
+//		Log(content)
+		if finds != nil && len(finds) > 0 {
+			for _, includes := range finds {
+				include := includes[1]
+				includeIndex, has := fileIndexMap[include]
+				Log(includeIndex)
+				Log("??")
+				Log(has)
+				if has {
+					vector[thisIndex][includeIndex] = 1
+				}
+			}
+		}
+	}
+	
+	LogJ(vector)
+	LogJ(fileIndexMap)
+	// 建立图后, 判断是否有环
+	if this.hasRound(vector, index) {
+		ok = false
+		msg = "themeValidHasRoundInclude"
+	} else {
+		ok = true
+	}
+	return;
+}
+
+// 检测有向图是否有环, DFS
+func (this *ThemeService) hasRound(vector [][]int, size int) (ok bool) {
+	for i := 0; i < size; i++ {
+		visited := make([]int, size)
+		if this.hasRoundEach(vector, i, size, visited) {
+			Log(">>")
+			Log(i);
+			return true;
+		}
+	}
+	return false
+}
+
+// 从每个节点出发, 判断是否有环
+func (this *ThemeService) hasRoundEach(vector [][]int, index int, size int, visited []int) (ok bool) {
+	if visited[index] > 0 {
+		Log("<")
+		Log(index)
+		return true
+	}
+	visited[index] = 1;
+	// 遍历它的孩子
+	for i := 0; i < size; i++ {
+		if vector[index][i] > 0 {
+			return this.hasRoundEach(vector, i, size, visited);
+		}
+	}
+	visited[index] = 0;
+	return false;
+}
diff --git a/app/service/UserService.go b/app/service/UserService.go
index cea7c79..9577a6b 100644
--- a/app/service/UserService.go
+++ b/app/service/UserService.go
@@ -369,7 +369,7 @@ func (this *UserService) ThirdAddUser(userId, email, pwd string) (ok bool, msg s
 // 宽度
 func (this *UserService)UpdateColumnWidth(userId string, notebookWidth, noteListWidth, mdEditorWidth int) bool {
 	return db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)}, 
-	bson.M{"NotebookWidth": notebookWidth, "NoteListWidth": noteListWidth, "mdEditorWidth": mdEditorWidth})
+	bson.M{"NotebookWidth": notebookWidth, "NoteListWidth": noteListWidth, "MdEditorWidth": mdEditorWidth})
 }
 // 左侧是否隐藏
 func  (this *UserService)UpdateLeftIsMin(userId string, leftIsMin bool) bool {
diff --git a/app/views/errors/500-blog.html b/app/views/errors/500-blog.html
new file mode 100644
index 0000000..b15d4d4
--- /dev/null
+++ b/app/views/errors/500-blog.html
@@ -0,0 +1,63 @@
+{{template "home/header_box.html" .}}
+
+<section id="box">
+	<div>
+		<div>
+			<h1 class="h text-white animated fadeInDownBig">ERROR!</h1>
+		</div>
+		<div id="errorBox">
+			<p class="error-info">
+				Sorry, you(not we) got an error. This error is just showing in blog preview for test.
+			</p>
+			
+		    <div class="list-group m-b-sm bg-white m-b-lg"> 
+		    
+		{{with .Error}}
+		<div id="header" class="block">
+			<h1>
+				{{.Title}}
+			</h1>
+			<p>
+				{{if .SourceType}}
+					The {{.SourceType}} <strong>{{.Path}}</strong> does not compile: <strong>{{.Description}}</strong>
+				{{else}}
+					{{.Description}}
+				{{end}}
+			</p>
+		</div>
+		{{if .Path}}
+		<div id="source" class="block">
+			<h2>In {{.Path}}
+				{{if .Line}}
+					(around {{if .Line}}line {{.Line}}{{end}}{{if .Column}} column {{.Column}}{{end}})
+				{{end}}
+			</h2>
+			{{range .ContextSource}}
+				<div class="line {{if .IsError}}error{{end}}">
+					<span class="lineNumber">{{.Line}}:</span>
+					<pre>{{.Source}}</pre>
+				</div>
+			{{end}}
+		</div>
+		{{end}}
+		{{if .MetaError}}
+			<div id="source" class="block">
+				<h2>Additionally, an error occurred while handling this error.</h2>
+				<div class="line error">
+					{{.MetaError}}
+				</div>
+			</div>
+		{{end}}
+		{{end}}
+ 
+		    </div>
+		</div>		
+    </div>
+</section>
+<div id="boxFooter">
+	<p>
+		<a href="/index">leanote</a> © 2014
+	</p>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/app/views/home/register.html b/app/views/home/register.html
index c8f9038..520eea0 100644
--- a/app/views/home/register.html
+++ b/app/views/home/register.html
@@ -100,7 +100,9 @@ $(function() {
 		$("#registerBtn").html("{{msg . "ing"}}...").addClass("disabled");
 		// hideMsg();
 		
-		$.post("/doRegister", {email: email, pwd: pwd}, function(e) {
+		var iu = "{{.iu}}";
+		
+		$.post("/doRegister", {email: email, pwd: pwd, iu: iu}, function(e) {
 			$("#registerBtn").html("{{msg . "register"}}").removeClass("disabled");
 			if(e.Ok) {
 				$("#registerBtn").html("{{msg . "registerSuccessAndRdirectToNote"}}");
diff --git a/app/views/member/blog/add_single.html b/app/views/member/blog/add_single.html
index 6446d71..a60c742 100644
--- a/app/views/member/blog/add_single.html
+++ b/app/views/member/blog/add_single.html
@@ -1,6 +1,6 @@
 {{template "member/top.html" .}}
 <div class="m-b-md"> <h3 class="m-b-none">
-{{if .page}}
+{{if .single}}
 {{msg . "updateSingle"}}
 {{else}}
 {{msg . "addSingle"}}
@@ -41,7 +41,7 @@
 
 </div>
 {{template "member/footer.html" .}}
-<script type="text/javascript" src="/tinymce/tinymce.min.js"></script>
+<script type="text/javascript" src="/tinymce/tinymce.js"></script>
 <script>
 var urlPrefix = "{{.siteUrl}}";
 $(function() {
diff --git a/app/views/member/blog/base.html b/app/views/member/blog/base.html
index 999c86e..97798dd 100644
--- a/app/views/member/blog/base.html
+++ b/app/views/member/blog/base.html
@@ -20,7 +20,7 @@
 						<label for="logo">{{msg . "blogLogo"}}</label>
 							<input type="hidden" name="Logo" id="Logo"
 								value="{{.userBlog.Logo}}" />
-							<form id="formLogo" action="{{$.siteUrl}}/file/uploadBlogLogo" method="post"
+							<form id="formLogo" action="/file/uploadBlogLogo" method="post"
 								enctype="multipart/form-data" target="logoTarget">
 								<input type="file" class="form-control" id="logo2" name="file"
 									onChange='$("#formLogo").submit();' /> 
diff --git a/app/views/member/blog/single.html b/app/views/member/blog/single.html
index 869e3b3..23aa5bf 100644
--- a/app/views/member/blog/single.html
+++ b/app/views/member/blog/single.html
@@ -37,7 +37,7 @@
 
 </div>
 {{template "member/footer.html" .}}
-<script type="text/javascript" src="{{.siteUrl}}/public/member/js/jquery.sortable.js"></script>
+<script type="text/javascript" src="/public/member/js/jquery.sortable.js"></script>
 <script>
 $(function() {
 	$("#baseBtn").click(function(){
@@ -79,7 +79,7 @@ $(function() {
 				art.alert(re.Msg || "error");
 			}
 		});
-	});
+	});
 });
 </script>
 
diff --git a/app/views/member/blog/theme.html b/app/views/member/blog/theme.html
index e05f384..7c62b29 100644
--- a/app/views/member/blog/theme.html
+++ b/app/views/member/blog/theme.html
@@ -8,6 +8,7 @@
 		</small>
 	</h3>
 </div>
+
 <div class="row">
 <div class="col-sm-12 theme-container">
 	<section class="panel panel-default">
@@ -27,8 +28,8 @@
 			<p>
 			{{msg . "currentTheme"}}:
 			</p>
-			<ul class="themes">
-				<li class="theme">	
+			<div class="themes clearfix">
+				<div class="theme pull-left">	
 				    <a class="choose-theme" data-method="put" href="#" rel="nofollow">
 				      <div class="theme-thumb thumb active-theme">
 					      <img src="/{{.activeTheme.Path}}/images/screenshot.png" alt="preview">
@@ -41,12 +42,21 @@
 				    <div class="theme-btns">
 				    	<div class="btn-group" data-id="{{.activeTheme.ThemeId.Hex}}">
 					    	<a class="btn btn-default btn-sm btn-export"><span class="fa fa-download"></span> {{msg $ "export"}}</a>
-					    	<a class="btn btn-default btn-sm" href="{{$.siteUrl}}/preview?themeId={{.activeTheme.ThemeId.Hex}}" target="_blank"><span class="fa fa-eye"></span> {{msg $ "preview"}}</a>
+					    	<!-- 必须是自己的主题 -->
+					    	{{if .activeTheme.ThemeId}}
+						    	<a class="btn btn-default btn-sm" href="{{$.siteUrl}}/preview?themeId={{.activeTheme.ThemeId.Hex}}" target="_blank"><span class="fa fa-eye"></span> {{msg $ "preview"}}</a>
+					    	{{end}}
 					    	<a class="btn btn-primary btn-sm" target="_blank" href="/member/blog/updateTheme?themeId={{if .activeTheme.ThemeId}}{{.activeTheme.ThemeId.Hex}}{{end}}"><span class="fa fa-pencil"></span> {{msg $ "edit"}}</a>
 				    	</div>
 				    </div>
-			    </li>
-			</ul>
+			    </div>
+			    {{if .activeTheme.Info.Desc}}
+			    <!-- 描述 -->
+			    <div class="pull-left theme-desc">
+			    	{{.activeTheme.Info.Desc|raw}}
+			    </div>
+			    {{end}}
+			</div>
 			
 			<hr />
 			<p>
@@ -59,6 +69,11 @@
 				    <a class="choose-theme" data-method="put" href="#" rel="nofollow">
 				      <div class="theme-thumb thumb">
 					      <img src="/{{.Path}}/images/screenshot.png" alt="preview">
+					      {{if .Info.Desc}}
+					      <div class="theme-desc-mask">
+					      	{{.Info.Desc|raw}}
+					      </div>
+					      {{end}}
 				      </div>
 				      <span class="theme-title">{{.Name}}</span>
 					</a>
@@ -100,6 +115,11 @@
 				    <a class="choose-theme" data-method="put" href="#" rel="nofollow">
 				      <div class="theme-thumb thumb">
 					      <img src="/{{.Path}}/images/screenshot.png" alt="preview">
+					      {{if .Info.Desc}}
+					      <div class="theme-desc-mask">
+					      	{{.Info.Desc|raw}}
+					      </div>
+					      {{end}}
 				      </div>
 				      <span class="theme-title">{{.Name}}</span>
 					</a>
diff --git a/app/views/member/blog/update_theme.html b/app/views/member/blog/update_theme.html
index fa0cbca..fd69d0d 100644
--- a/app/views/member/blog/update_theme.html
+++ b/app/views/member/blog/update_theme.html
@@ -107,7 +107,7 @@
 </div>
 
 {{template "member/footer.html" .}}
-<script src="/public/member/js/ace/ace.js" type="text/javascript"></script>
+<script src="/public/libs/ace/ace.js" type="text/javascript"></script>
 <script>
 var editor = ace.edit("tplContent");
 editor.setTheme("ace/theme/tomorrow");
diff --git a/app/views/note/note-dev.html b/app/views/note/note-dev.html
index 9aeb1ea..8fce04d 100644
--- a/app/views/note/note-dev.html
+++ b/app/views/note/note-dev.html
@@ -13,10 +13,12 @@
 <link href="/css/bootstrap.css" rel="stylesheet" />
 <!-- 先加载, 没有样式, 宽度不定 -->
 <link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" rel="stylesheet"/>
-
 <!-- leanote css -->
 <link href="/css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" />
 <link href="/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
+<!-- mdeditor -->
+<link href="/public/dist/themes/default.css" rel="stylesheet" />
+
 <script>
 var hash = location.hash;
 if(hash.indexOf("writing") >= 0) {
@@ -169,7 +171,7 @@ function log(o) {
 							{{if .isAdmin}}
 							<li role="presentation" class="divider"></li>
 							<li role="presentation">
-								<a target="_blank" title="{{msg . "amdin"}}" href="/admin/index">
+								<a target="_blank" title="{{msg . "admin"}}" href="/admin/index">
 									<i class="fa fa-dashboard"></i> 
 									<span>{{msg . "admin"}}</span>
 								</a>
@@ -184,13 +186,11 @@ function log(o) {
 					</div>
 				</div>
 
-				<!--
 				<div class="pull-right top-nav writting-hide lea-blog">
 					<a target="_blank" href="http://lea.leanote.com"> 
 						lea++
 					</a>
 				</div>
-				-->
 				
 				<div class="pull-right top-nav writting-hide" id="myBlog">
 					<a target="_blank" href="{{$.blogUrl}}/{{.userInfo.Username}}"> 
@@ -557,12 +557,12 @@ function log(o) {
 							</a>
 						</div>
 						<div class="editorBg"></div>
-						<div id="leanoteNav">
+						<div id="leanoteNav" class="leanoteNav">
 							<h1>
-								<i class="fa fa-align-justify" title="文档导航"></i>
+								<i class="fa fa-align-justify" title="{{msg . "nav"}}"></i>
 								<span>{{msg . "nav"}}</span>
 							</h1>
-							<div id="leanoteNavContent">
+							<div id="leanoteNavContent" class="leanoteNavContent">
 							</div>
 						</div>
 						
@@ -583,9 +583,85 @@ function log(o) {
 					</div>
 					
 					<div id="mdEditor">
+					
+											
+						<div class="layout-wrapper-l1">
+						    <div class="layout-wrapper-l2">
+						        <div class="navbar navbar-default">
+						            <div class="navbar-inner" id="wmd-button-bar">
+						                <ul class="nav left-buttons">
+						                    <li class="wmd-button-group1 btn-group"></li>
+						                </ul>
+						                <ul class="nav left-buttons">
+						                    <li class="wmd-button-group2 btn-group"></li>
+						                </ul>
+						                <ul class="nav left-buttons">
+						                    <li class="wmd-button-group3 btn-group"></li>
+						                </ul>
+						                <ul class="nav left-buttons">
+						                    <li class="wmd-button-group5 btn-group"></li>
+						                </ul>
+						                <!-- 帮助 -->
+						                 <ul class="nav left-buttons">
+						                    <li class="wmd-button-group6 btn-group">
+						                    	<li class="wmd-button btn btn-success" id="wmd-help-button" title="Markdown syntax" style="left: 0px; display: none;"><span style="display: none; background-position: 0px 0px;"></span><i class="fa fa-question-circle"></i></li>
+						                    </li>
+						                </ul>
+						               
+						               <!--
+						                <ul class="nav pull-right right-buttons">
+						                    <li class="offline-status hide">
+						                        <div class="text-danger">
+						                            <i class="icon-attention-circled"></i>offline
+						                        </div>
+						                    </li>
+						                    <li class="extension-buttons"></li>
+						                </ul>
+						                <ul class="nav pull-right title-container">
+						                    <li><div class="working-indicator"></div></li>
+						                    <li><a class="btn btn-success file-title-navbar" href="#"
+						                        title="Rename document"> </a></li>
+						                    <li><div class="input-file-title-container"><input type="text"
+						                        class="col-sm-4 form-control hide input-file-title"
+						                        placeholder="Document title" /></div></li>
+						                </ul>
+						                -->
+						            </div>
+						            <div class="editorBg"></div>
+						        </div>
+						        <div class="layout-wrapper-l3">
+						        	<div id="left-column">
+							            <pre id="wmd-input" class="form-control"><div class="editor-content mousetrap" contenteditable=true></div><div class="editor-margin"></div></pre>
+						            </div>
+						            <div id="right-column">
+						            <div class="preview-panel panel-open" id="preview-panel">
+							            <div id="mdSplitter2" class="layout-resizer layout-resizer-preview open" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); touch-action: none;"></div>
+						                <div class="layout-toggler layout-toggler-preview btn btn-info open" title="Toggle preview" data-open="1"><i class="fa fa-angle-right"></i></div>
+						                <div class="preview-container">
+						                    <div id="preview-contents">
+						                        <div id="wmd-preview" class="preview-content"></div>
+						                    </div>
+						                </div>
+						            </div>
+						            </div>
+						        </div>
+						        <div class="extension-preview-buttons">
+									<div id="leanoteNavMd" class="leanoteNav">
+										<h1>
+											<i class="fa fa-align-justify" title="{{msg . "nav"}}"></i>
+											<span>{{msg . "nav"}}</span>
+										</h1>
+										<div id="leanoteNavContentMd" class="leanoteNavContent table-of-contents">
+										</div>
+									</div>
+						        </div>
+						    </div>
+						    <div id="wmd-button-bar" class="hide"></div>
+						</div>	
+					
+						<!--
 						<div id="wmd-button-bar" id="mdBar"></div>
 						<div class="editorBg"></div>
-						<!-- 为了scroll -->
 	                    
 						<div class="clearfix" id="mdEditorPreview">
 							<div id="left-column">
@@ -601,11 +677,59 @@ function log(o) {
 				            </div>
 						</div>
 	                    <textarea id="md-section-helper"></textarea>
+	                    -->
 					</div>
 				</div>	
 			</div>
 			
 			<!-- mdEditor -->
+			<!-- v2 -->
+			<div class="modal fade modal-insert-link">
+			    <div class="modal-dialog">
+			        <div class="modal-content">
+			            <div class="modal-header">
+			                <button type="button" class="close" data-dismiss="modal"
+			                    aria-hidden="true">&times;</button>
+			                <h4 class="modal-title">Hyperlink</h4>
+			            </div>
+			            <div class="modal-body">
+			                <p>Please provide the link URL and an optional title:</p>
+			                <div class="input-group">
+			                    <span class="input-group-addon"><i class="icon-globe"></i></span><input
+			                        id="input-insert-link" type="text" class="col-sm-5 form-control"
+			                        placeholder='http://example.com/ "optional title"' />
+			                </div>
+			            </div>
+			            <div class="modal-footer">
+			                <a href="#" class="btn btn-default" data-dismiss="modal">Cancel</a>
+			                <a href="#" class="btn btn-primary action-insert-link"
+			                    data-dismiss="modal">OK</a>
+			            </div>
+			        </div>
+			    </div>
+			</div>
+			
+			<!-- 插入图片 -->
+			<div class="modal fade modal-insert-image">
+			    <div class="modal-dialog"  style="width: 840px">
+			        <div class="modal-content">
+			            <div class="modal-header">
+			                <button type="button" class="close" data-dismiss="modal"
+			                    aria-hidden="true">&times;</button>
+			                <h4 class="modal-title">Image</h4>
+			            </div>
+			            <div class="modal-body" style="padding-top: 0; padding-bottom: 0">
+			            	<iframe name="mdImageManager" style="width: 100%; height: 350px" scrolling="no" id="leauiIfrForMD" src="" frameborder="0"></iframe>
+			            </div>
+			            <div class="modal-footer">
+			                 <a href="#" class="btn btn-default"
+			                    data-dismiss="modal">Cancel</a> <a href="#"
+			                    class="btn btn-primary action-insert-image" data-dismiss="modal">Insert Image</a>
+			            </div>
+			        </div>
+			    </div>
+			</div>
+			<!-- v1 -->
 			<!-- Hidden Popup Modal -->
 			<div class="modal fade bs-modal-sm" id="editorDialog" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
 				<div class="modal-dialog modal-sm">
@@ -774,28 +898,32 @@ var GlobalConfigs = {{.globalConfigs|jsonJs}}; // 2014/11/9 beta2
 
 <!-- 渲染view -->
 <script src="/tinymce/tinymce.js"></script>
+<script src="/public/libs/ace/ace.js"></script>
 <script src="/js/app/page.js"></script>
 <script src="/js/jQuery-slimScroll-1.3.0/jquery.slimscroll.js"></script>
 <script src="/js/contextmenu/jquery.contextmenu.js"></script>
-<script src="/js/jquery-cookie.js"></script>
 <script src="/js/bootstrap-min.js"></script>
 <script src="/js/app/note.js"></script>
 <script src="/js/app/tag.js"></script>
 <script src="/js/app/notebook.js"></script>
 <script src="/js/app/share.js"></script>
 <script src="/js/object_id-min.js"></script>
-<script src="/js/ZeroClipboard/ZeroClipboard-min.js"></script>
 <script>
 initPage();
 </script>
- 
+
 <!-- context-menu -->
 <link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" />
-<!-- code -->
-<link href="/public/mdeditor/editor/google-code-prettify/prettify.css" rel="stylesheet" />
-<!-- js version 2.0 use require.js -->
+
+<!-- v2 use require.js, mdeditor -->
+<script>
+window.baseDir = '/public/dist';
+window.require = {
+    baseUrl: window.baseDir,
+    deps: ['main']
+};
+</script>
 <script src="/js/require.js"></script>
-<script src="/js/main.js"></script>
 </script>
 </body>
 </html>
\ No newline at end of file
diff --git a/app/views/note/note.html b/app/views/note/note.html
index 2dfc97c..43492db 100644
--- a/app/views/note/note.html
+++ b/app/views/note/note.html
@@ -17,6 +17,9 @@
 <!-- leanote css -->
 <link href="/css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" />
 <link href="/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
+
+<link href="/public/res-min/themes/default.css" rel="stylesheet" />
+
 <script>
 var hash = location.hash;
 if(hash.indexOf("writing") >= 0) {
@@ -169,7 +172,7 @@ function log(o) {
 							{{if .isAdmin}}
 							<li role="presentation" class="divider"></li>
 							<li role="presentation">
-								<a target="_blank" title="{{msg . "amdin"}}" href="/admin/index">
+								<a target="_blank" title="{{msg . "admin"}}" href="/admin/index">
 									<i class="fa fa-dashboard"></i> 
 									<span>{{msg . "admin"}}</span>
 								</a>
@@ -184,13 +187,11 @@ function log(o) {
 					</div>
 				</div>
 
-				<!--
 				<div class="pull-right top-nav writting-hide lea-blog">
 					<a target="_blank" href="http://lea.leanote.com"> 
 						lea++
 					</a>
 				</div>
-				-->
 				
 				<div class="pull-right top-nav writting-hide" id="myBlog">
 					<a target="_blank" href="{{$.blogUrl}}/{{.userInfo.Username}}"> 
@@ -557,12 +558,12 @@ function log(o) {
 							</a>
 						</div>
 						<div class="editorBg"></div>
-						<div id="leanoteNav">
+						<div id="leanoteNav" class="leanoteNav">
 							<h1>
-								<i class="fa fa-align-justify" title="文档导航"></i>
+								<i class="fa fa-align-justify" title="{{msg . "nav"}}"></i>
 								<span>{{msg . "nav"}}</span>
 							</h1>
-							<div id="leanoteNavContent">
+							<div id="leanoteNavContent" class="leanoteNavContent">
 							</div>
 						</div>
 						
@@ -583,9 +584,85 @@ function log(o) {
 					</div>
 					
 					<div id="mdEditor">
+					
+											
+						<div class="layout-wrapper-l1">
+						    <div class="layout-wrapper-l2">
+						        <div class="navbar navbar-default">
+						            <div class="navbar-inner" id="wmd-button-bar">
+						                <ul class="nav left-buttons">
+						                    <li class="wmd-button-group1 btn-group"></li>
+						                </ul>
+						                <ul class="nav left-buttons">
+						                    <li class="wmd-button-group2 btn-group"></li>
+						                </ul>
+						                <ul class="nav left-buttons">
+						                    <li class="wmd-button-group3 btn-group"></li>
+						                </ul>
+						                <ul class="nav left-buttons">
+						                    <li class="wmd-button-group5 btn-group"></li>
+						                </ul>
+						                <!-- 帮助 -->
+						                 <ul class="nav left-buttons">
+						                    <li class="wmd-button-group6 btn-group">
+						                    	<li class="wmd-button btn btn-success" id="wmd-help-button" title="Markdown syntax" style="left: 0px; display: none;"><span style="display: none; background-position: 0px 0px;"></span><i class="fa fa-question-circle"></i></li>
+						                    </li>
+						                </ul>
+						               
+						               <!--
+						                <ul class="nav pull-right right-buttons">
+						                    <li class="offline-status hide">
+						                        <div class="text-danger">
+						                            <i class="icon-attention-circled"></i>offline
+						                        </div>
+						                    </li>
+						                    <li class="extension-buttons"></li>
+						                </ul>
+						                <ul class="nav pull-right title-container">
+						                    <li><div class="working-indicator"></div></li>
+						                    <li><a class="btn btn-success file-title-navbar" href="#"
+						                        title="Rename document"> </a></li>
+						                    <li><div class="input-file-title-container"><input type="text"
+						                        class="col-sm-4 form-control hide input-file-title"
+						                        placeholder="Document title" /></div></li>
+						                </ul>
+						                -->
+						            </div>
+						            <div class="editorBg"></div>
+						        </div>
+						        <div class="layout-wrapper-l3">
+						        	<div id="left-column">
+							            <pre id="wmd-input" class="form-control"><div class="editor-content mousetrap" contenteditable=true></div><div class="editor-margin"></div></pre>
+						            </div>
+						            <div id="right-column">
+						            <div class="preview-panel panel-open" id="preview-panel">
+							            <div id="mdSplitter2" class="layout-resizer layout-resizer-preview open" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); touch-action: none;"></div>
+						                <div class="layout-toggler layout-toggler-preview btn btn-info open" title="Toggle preview" data-open="1"><i class="fa fa-angle-right"></i></div>
+						                <div class="preview-container">
+						                    <div id="preview-contents">
+						                        <div id="wmd-preview" class="preview-content"></div>
+						                    </div>
+						                </div>
+						            </div>
+						            </div>
+						        </div>
+						        <div class="extension-preview-buttons">
+									<div id="leanoteNavMd" class="leanoteNav">
+										<h1>
+											<i class="fa fa-align-justify" title="{{msg . "nav"}}"></i>
+											<span>{{msg . "nav"}}</span>
+										</h1>
+										<div id="leanoteNavContentMd" class="leanoteNavContent table-of-contents">
+										</div>
+									</div>
+						        </div>
+						    </div>
+						    <div id="wmd-button-bar" class="hide"></div>
+						</div>	
+					
+						<!--
 						<div id="wmd-button-bar" id="mdBar"></div>
 						<div class="editorBg"></div>
-						<!-- 为了scroll -->
 	                    
 						<div class="clearfix" id="mdEditorPreview">
 							<div id="left-column">
@@ -601,11 +678,59 @@ function log(o) {
 				            </div>
 						</div>
 	                    <textarea id="md-section-helper"></textarea>
+	                    -->
 					</div>
 				</div>	
 			</div>
 			
 			<!-- mdEditor -->
+			<!-- v2 -->
+			<div class="modal fade modal-insert-link">
+			    <div class="modal-dialog">
+			        <div class="modal-content">
+			            <div class="modal-header">
+			                <button type="button" class="close" data-dismiss="modal"
+			                    aria-hidden="true">&times;</button>
+			                <h4 class="modal-title">Hyperlink</h4>
+			            </div>
+			            <div class="modal-body">
+			                <p>Please provide the link URL and an optional title:</p>
+			                <div class="input-group">
+			                    <span class="input-group-addon"><i class="icon-globe"></i></span><input
+			                        id="input-insert-link" type="text" class="col-sm-5 form-control"
+			                        placeholder='http://example.com/ "optional title"' />
+			                </div>
+			            </div>
+			            <div class="modal-footer">
+			                <a href="#" class="btn btn-default" data-dismiss="modal">Cancel</a>
+			                <a href="#" class="btn btn-primary action-insert-link"
+			                    data-dismiss="modal">OK</a>
+			            </div>
+			        </div>
+			    </div>
+			</div>
+			
+			<!-- 插入图片 -->
+			<div class="modal fade modal-insert-image">
+			    <div class="modal-dialog"  style="width: 840px">
+			        <div class="modal-content">
+			            <div class="modal-header">
+			                <button type="button" class="close" data-dismiss="modal"
+			                    aria-hidden="true">&times;</button>
+			                <h4 class="modal-title">Image</h4>
+			            </div>
+			            <div class="modal-body" style="padding-top: 0; padding-bottom: 0">
+			            	<iframe name="mdImageManager" style="width: 100%; height: 350px" scrolling="no" id="leauiIfrForMD" src="" frameborder="0"></iframe>
+			            </div>
+			            <div class="modal-footer">
+			                 <a href="#" class="btn btn-default"
+			                    data-dismiss="modal">Cancel</a> <a href="#"
+			                    class="btn btn-primary action-insert-image" data-dismiss="modal">Insert Image</a>
+			            </div>
+			        </div>
+			    </div>
+			</div>
+			<!-- v1 -->
 			<!-- Hidden Popup Modal -->
 			<div class="modal fade bs-modal-sm" id="editorDialog" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
 				<div class="modal-dialog modal-sm">
@@ -751,7 +876,7 @@ function log(o) {
 	</div>
 </div>
 <script src="/js/jquery-1.9.0.min.js"></script>
-<script src="/js/jquery.ztree.all-3.5.js"></script>
+<script src="/js/jquery.ztree.all-3.5-min.js"></script>
 <script src="/js/i18n/msg.{{.locale}}.js"></script>
 <script src="/js/common-min.js"></script>
 <script>
@@ -773,29 +898,31 @@ var GlobalConfigs = {{.globalConfigs|jsonJs}}; // 2014/11/9 beta2
 </script>
 
 <!-- 渲染view -->
-<script src="/tinymce/tinymce.js"></script>
+<script src="/tinymce/tinymce.min.js"></script>
+<script src="/js/ace/ace.js"></script>
 <script src="/js/app/page-min.js"></script>
-<script src="/js/jQuery-slimScroll-1.3.0/jquery.slimscroll.js"></script>
+<script src="/js/jQuery-slimScroll-1.3.0/jquery.slimscroll-min.js"></script>
 <script src="/js/contextmenu/jquery.contextmenu-min.js"></script>
-<script src="/js/jquery-cookie.js"></script>
 <script src="/js/bootstrap-min.js"></script>
 <script src="/js/app/note-min.js"></script>
 <script src="/js/app/tag-min.js"></script>
 <script src="/js/app/notebook-min.js"></script>
 <script src="/js/app/share-min.js"></script>
 <script src="/js/object_id-min.js"></script>
-<script src="/js/ZeroClipboard/ZeroClipboard-min.js"></script>
 <script>
 initPage();
 </script>
- 
+
 <!-- context-menu -->
 <link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" />
-<!-- code -->
-<link href="/public/mdeditor/editor/google-code-prettify/prettify.css" rel="stylesheet" />
-<!-- js version 2.0 use require.js -->
+<script>
+window.baseDir = '/public/res-min';
+window.require = {
+    baseUrl: window.baseDir,
+    deps: ['main']
+};
+</script>
 <script src="/js/require.js"></script>
-<script src="/js/main-min.js"></script>
 </script>
 </body>
 </html>
\ No newline at end of file