diff --git a/app/init.go b/app/init.go index a0cb922..604bf4d 100644 --- a/app/init.go +++ b/app/init.go @@ -1,66 +1,67 @@ package app import ( - "github.com/revel/revel" - . "github.com/leanote/leanote/app/lea" - "github.com/leanote/leanote/app/service" - "github.com/leanote/leanote/app/db" + "encoding/json" + "fmt" "github.com/leanote/leanote/app/controllers" "github.com/leanote/leanote/app/controllers/admin" "github.com/leanote/leanote/app/controllers/member" + "github.com/leanote/leanote/app/db" + . "github.com/leanote/leanote/app/lea" _ "github.com/leanote/leanote/app/lea/binder" - "github.com/leanote/leanote/app/lea/session" "github.com/leanote/leanote/app/lea/memcache" "github.com/leanote/leanote/app/lea/route" - "reflect" - "fmt" + "github.com/leanote/leanote/app/lea/session" + "github.com/leanote/leanote/app/service" + "github.com/revel/revel" "html/template" "math" - "strings" - "strconv" - "time" - "encoding/json" "net/url" + "reflect" + "strconv" + "strings" + "time" ) func init() { // Filters is the default set of global filters. revel.Filters = []revel.Filter{ - revel.PanicFilter, // Recover from panics and display an error page instead. + revel.PanicFilter, // Recover from panics and display an error page instead. route.RouterFilter, // revel.RouterFilter, // Use the routing table to select the right Action // AuthFilter, // Invoke the action. revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters. revel.ParamsFilter, // Parse parameters into Controller.Params. // revel.SessionFilter, // Restore and write the session cookie. - + // 使用SessionFilter标准版从cookie中得到sessionID, 然后通过MssessionFilter从Memcache中得到 // session, 之后MSessionFilter将session只存sessionID然后返回给SessionFilter返回到web - session.SessionFilter, // leanote session - // session.MSessionFilter, // leanote memcache session - - revel.FlashFilter, // Restore and write the flash cookie. - revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie. - revel.I18nFilter, // Resolve the requested language - revel.InterceptorFilter, // Run interceptors around the action. - revel.CompressFilter, // Compress the result. - revel.ActionInvoker, // Invoke the action. + session.SessionFilter, // leanote session + // session.MSessionFilter, // leanote memcache session + + revel.FlashFilter, // Restore and write the flash cookie. + revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie. + revel.I18nFilter, // Resolve the requested language + revel.InterceptorFilter, // Run interceptors around the action. + revel.CompressFilter, // Compress the result. + revel.ActionInvoker, // Invoke the action. } - + + //自定义模版函数 revel.TemplateFuncs["raw"] = func(str string) template.HTML { return template.HTML(str) } revel.TemplateFuncs["add"] = func(i int) string { - i = i + 1; + i = i + 1 return fmt.Sprintf("%v", i) } revel.TemplateFuncs["sub"] = func(i int) int { - i = i - 1; + i = i - 1 return i } // 增加或减少 revel.TemplateFuncs["incr"] = func(n, i int) int { - n = n + i; + n = n + i return n } revel.TemplateFuncs["join"] = func(arr []string) template.HTML { @@ -84,11 +85,11 @@ func init() { return v.Get("a") } revel.TemplateFuncs["json"] = func(i interface{}) string { - b, _ := json.Marshal(i) + b, _ := json.Marshal(i) return string(b) } revel.TemplateFuncs["jsonJs"] = func(i interface{}) template.JS { - b, _ := json.Marshal(i) + b, _ := json.Marshal(i) return template.JS(string(b)) } revel.TemplateFuncs["datetime"] = func(t time.Time) template.HTML { @@ -102,10 +103,10 @@ func init() { t := time.Unix(int64(sec), 0) return template.HTML(t.Format("2006-01-02 15:04:05")) } - + // interface是否有该字段 revel.TemplateFuncs["has"] = func(i interface{}, key string) bool { - t := reflect.TypeOf(i) + t := reflect.TypeOf(i) _, ok := t.FieldByName(key) return ok } @@ -124,64 +125,64 @@ func init() { str = tag } tagStr += str - if i != lenTags - 1 { + if i != lenTags-1 { tagStr += "," } } return template.HTML(tagStr) } /* - revel.TemplateFuncs["blogTags"] = func(tags []string) template.HTML { - if tags == nil || len(tags) == 0 { - return "" - } - // TODO 这里判断语言, 从语言包中拿 - tagMap := map[string]string{"red": "红色", "yellow": "黄色", "blue": "蓝色", "green": "绿色"} - tagStr := "" - lenTags := len(tags) - for i, tag := range tags { - if text, ok := tagMap[tag]; ok { - tagStr += text - } else { - tagStr += tag + revel.TemplateFuncs["blogTags"] = func(tags []string) template.HTML { + if tags == nil || len(tags) == 0 { + return "" } - if i != lenTags - 1 { - tagStr += "," + // TODO 这里判断语言, 从语言包中拿 + tagMap := map[string]string{"red": "红色", "yellow": "黄色", "blue": "蓝色", "green": "绿色"} + tagStr := "" + lenTags := len(tags) + for i, tag := range tags { + if text, ok := tagMap[tag]; ok { + tagStr += text + } else { + tagStr += tag + } + if i != lenTags - 1 { + tagStr += "," + } } + return template.HTML(tagStr) } - return template.HTML(tagStr) - } */ revel.TemplateFuncs["li"] = func(a string) string { return "" } // str连接 - revel.TemplateFuncs["urlConcat"] = func(url string, v... interface{}) string { + revel.TemplateFuncs["urlConcat"] = func(url string, v ...interface{}) string { html := "" for i := 0; i < len(v); i = i + 2 { item := v[i] if i+1 == len(v) { - break; + break } value := v[i+1] if item != nil && value != nil { - keyStr, _ := item.(string) - valueStr, err := value.(string) - if !err { - valueInt, _ := value.(int) - valueStr = strconv.Itoa(valueInt) - } - if keyStr != "" && valueStr != "" { - s := keyStr + "=" + valueStr - if html != "" { - html += "&" + s - } else { - html += s - } - } - } + keyStr, _ := item.(string) + valueStr, err := value.(string) + if !err { + valueInt, _ := value.(int) + valueStr = strconv.Itoa(valueInt) + } + if keyStr != "" && valueStr != "" { + s := keyStr + "=" + valueStr + if html != "" { + html += "&" + s + } else { + html += s + } + } + } } - + if html != "" { if strings.Index(url, "?") >= 0 { return url + "&" + html @@ -191,11 +192,11 @@ func init() { } return url } - + revel.TemplateFuncs["urlCond"] = func(url string, sorterI, keyords interface{}) template.HTML { return "" } - + // http://stackoverflow.com/questions/14226416/go-lang-templates-always-quotes-a-string-and-removes-comments revel.TemplateFuncs["rawMsg"] = func(renderArgs map[string]interface{}, message string, args ...interface{}) template.JS { str, ok := renderArgs[revel.CurrentLocaleRenderArg].(string) @@ -204,38 +205,38 @@ func init() { } return template.JS(revel.Message(str, message, args...)) } - + // 为后台管理sorter th使用 // 必须要返回HTMLAttr, 返回html, golang 会执行安全检查返回ZgotmplZ // sorterI 可能是nil, 所以用interfalce{}来接收 /* - data-url="/adminUser/index" - data-sorter="email" - class="th-sortable {{if eq .sorter "email-up"}}th-sort-up{{else}}{{if eq .sorter "email-down"}}th-sort-down{{end}}{{end}}" + data-url="/adminUser/index" + data-sorter="email" + class="th-sortable {{if eq .sorter "email-up"}}th-sort-up{{else}}{{if eq .sorter "email-down"}}th-sort-down{{end}}{{end}}" */ revel.TemplateFuncs["sorterTh"] = func(url, sorterField string, sorterI interface{}) template.HTMLAttr { sorter := "" if sorterI != nil { sorter, _ = sorterI.(string) } - html := "data-url=\"" + url + "\" data-sorter=\"" + sorterField + "\""; - html += " class=\"th-sortable "; - if sorter == sorterField + "-up" { - html += "th-sort-up\""; - } else if(sorter == sorterField + "-down") { - html += "th-sort-down"; + html := "data-url=\"" + url + "\" data-sorter=\"" + sorterField + "\"" + html += " class=\"th-sortable " + if sorter == sorterField+"-up" { + html += "th-sort-up\"" + } else if sorter == sorterField+"-down" { + html += "th-sort-down" } - html += "\""; + html += "\"" return template.HTMLAttr(html) } - + // pagination revel.TemplateFuncs["page"] = func(urlBase string, page, pageSize, count int) template.HTML { if count == 0 { - return ""; + return "" } - totalPage := int(math.Ceil(float64(count)/float64(pageSize))) - + totalPage := int(math.Ceil(float64(count) / float64(pageSize))) + preClass := "" prePage := page - 1 if prePage == 0 { @@ -244,10 +245,10 @@ func init() { nextClass := "" nextPage := page + 1 var preUrl, nextUrl string - - preUrl = urlBase + "?page=" + strconv.Itoa(prePage) + + preUrl = urlBase + "?page=" + strconv.Itoa(prePage) nextUrl = urlBase + "?page=" + strconv.Itoa(nextPage) - + // 没有上一页了 if page == 1 { preClass = "disabled" @@ -265,49 +266,49 @@ func init() { // http://play.golang.org/p/snygrVpQva // http://grokbase.com/t/gg/golang-nuts/142a6dhfh3/go-nuts-text-template-using-comparison-operators-eq-gt-etc-on-non-existent-variable-causes-the-template-to-stop-outputting-but-with-no-error-correct-behaviour /* - revel.TemplateFuncs["gt"] = func(a1, a2 interface{}) bool { - switch a1.(type) { - case string: - switch a2.(type) { + revel.TemplateFuncs["gt"] = func(a1, a2 interface{}) bool { + switch a1.(type) { case string: - return reflect.ValueOf(a1).String() > reflect.ValueOf(a2).String() - } - case int, int8, int16, int32, int64: - switch a2.(type) { + switch a2.(type) { + case string: + return reflect.ValueOf(a1).String() > reflect.ValueOf(a2).String() + } case int, int8, int16, int32, int64: - return reflect.ValueOf(a1).Int() > reflect.ValueOf(a2).Int() - } - case uint, uint8, uint16, uint32, uint64: - switch a2.(type) { + switch a2.(type) { + case int, int8, int16, int32, int64: + return reflect.ValueOf(a1).Int() > reflect.ValueOf(a2).Int() + } case uint, uint8, uint16, uint32, uint64: - return reflect.ValueOf(a1).Uint() > reflect.ValueOf(a2).Uint() - } - case float32, float64: - switch a2.(type) { + switch a2.(type) { + case uint, uint8, uint16, uint32, uint64: + return reflect.ValueOf(a1).Uint() > reflect.ValueOf(a2).Uint() + } case float32, float64: - return reflect.ValueOf(a1).Float() > reflect.ValueOf(a2).Float() + switch a2.(type) { + case float32, float64: + return reflect.ValueOf(a1).Float() > reflect.ValueOf(a2).Float() + } } + return false } - return false - } */ - + /* - {{range $i := N 1 10}} -
{{$i}}
- {{end}} - */ + {{range $i := N 1 10}} +
{{$i}}
+ {{end}} + */ revel.TemplateFuncs["N"] = func(start, end int) (stream chan int) { - stream = make(chan int) - go func() { - for i := start; i <= end; i++ { - stream <- i - } - close(stream) - }() - return + stream = make(chan int) + go func() { + for i := start; i <= end; i++ { + stream <- i + } + close(stream) + }() + return } - + // init Email revel.OnAppStart(func() { // 数据库 diff --git a/public/blog/themes/medium/404.html b/public/blog/themes/medium/404.html new file mode 100644 index 0000000..4a698af --- /dev/null +++ b/public/blog/themes/medium/404.html @@ -0,0 +1,19 @@ +{{template "header.html" .}} + +
+ +
+
+
+ 404 NOT FOUND +
+
+ Sorry, We can't find this page. +
+
+
+
+{{template "footer.html" $}} + + + \ No newline at end of file diff --git a/public/blog/themes/medium/archive.html b/public/blog/themes/medium/archive.html new file mode 100644 index 0000000..abe6c85 --- /dev/null +++ b/public/blog/themes/medium/archive.html @@ -0,0 +1,38 @@ +{{template "header.html" .}} + +
+
+

归档 {{if $.curCateTitle}} - {{$.curCateTitle}}{{end}}

+
+
+ +
+
    + {{range $.archives}} +
  • {{.Year}} +
      + {{range .MonthAchives}} +
    • + {{.Month}} +
        + {{range .Posts}} +
      • + {{dateFormat .PublicTime "2006-01-02"}} {{.Title}} +
      • + {{end}} +
      + +
    • + {{end}} +
    +
  • + {{end}} +
+
+
+
+ +{{template "footer.html" .}} + + + \ No newline at end of file diff --git a/public/blog/themes/medium/cate.html b/public/blog/themes/medium/cate.html new file mode 100644 index 0000000..57dd247 --- /dev/null +++ b/public/blog/themes/medium/cate.html @@ -0,0 +1,42 @@ +{{template "header.html" .}} + +
+
+

分类 - {{$.curCateTitle}}

+
+
+ {{range $.posts}} +
+ +
+ + {{if .Tags}} + {{blogTags $ .Tags}} + {{else}} + 无 + {{end}} + | + 更新 {{.UpdatedTime | datetime}} + | + 创建 {{.CreatedTime | datetime}} +
+
+ {{.Abstract | raw}} +
+ 查看 +
+ {{end}} + + {{template "paging.html" $}} +
+
+ +{{template "footer.html" $}} +{{template "highlight.html" $}} + + + \ No newline at end of file diff --git a/public/blog/themes/medium/footer.html b/public/blog/themes/medium/footer.html new file mode 100644 index 0000000..a2ea9e7 --- /dev/null +++ b/public/blog/themes/medium/footer.html @@ -0,0 +1,65 @@ +
+ {{$userId := $.blogInfo.UserId}} + +
+ + + + diff --git a/public/blog/themes/medium/header.html b/public/blog/themes/medium/header.html new file mode 100644 index 0000000..68548ca --- /dev/null +++ b/public/blog/themes/medium/header.html @@ -0,0 +1,122 @@ + + + + + + + + + + + +{{if $.curIsIndex}} + {{$.blogInfo.Title}} +{{else if $.curIsCate}} + 分类-{{$.curCateTitle}} +{{else if $.curIsSearch}} + 搜索-{{$.keywords}} +{{else if $.curIsTags}} + 我的标签 +{{else if $.curIsTagPosts}} + 标签-{{$.curTag}} +{{else if $.curIsPost}} + {{$.post.Title}} +{{else if $.curIsSingle}} + {{$.single.Title}} +{{else if $.curIsArchive}} + 归档 +{{end}} + + + + + + + + + + + + +
+
+ + +
+ + + +
\ No newline at end of file diff --git a/public/blog/themes/medium/highlight.html b/public/blog/themes/medium/highlight.html new file mode 100644 index 0000000..e92783b --- /dev/null +++ b/public/blog/themes/medium/highlight.html @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/public/blog/themes/medium/images/leanote-icon.jpg b/public/blog/themes/medium/images/leanote-icon.jpg new file mode 100644 index 0000000..ada2a2c Binary files /dev/null and b/public/blog/themes/medium/images/leanote-icon.jpg differ diff --git a/public/blog/themes/medium/images/loading-32.gif b/public/blog/themes/medium/images/loading-32.gif new file mode 100644 index 0000000..9297c2d Binary files /dev/null and b/public/blog/themes/medium/images/loading-32.gif differ diff --git a/public/blog/themes/medium/images/noise.png b/public/blog/themes/medium/images/noise.png new file mode 100644 index 0000000..65ebef2 Binary files /dev/null and b/public/blog/themes/medium/images/noise.png differ diff --git a/public/blog/themes/medium/images/screenshot.png b/public/blog/themes/medium/images/screenshot.png new file mode 100644 index 0000000..eea306e Binary files /dev/null and b/public/blog/themes/medium/images/screenshot.png differ diff --git a/public/blog/themes/medium/images/triangle_2x.png b/public/blog/themes/medium/images/triangle_2x.png new file mode 100644 index 0000000..e687c12 Binary files /dev/null and b/public/blog/themes/medium/images/triangle_2x.png differ diff --git a/public/blog/themes/medium/index.html b/public/blog/themes/medium/index.html new file mode 100644 index 0000000..b61a1e5 --- /dev/null +++ b/public/blog/themes/medium/index.html @@ -0,0 +1,39 @@ +{{template "header.html" .}} + +
+ +
+ {{range $.posts}} +
+ +
+ + {{if .Tags}} + {{blogTags $ .Tags}} + {{else}} + 无 + {{end}} + | + 更新 {{.UpdatedTime | datetime}} + | + 创建 {{.CreatedTime | datetime}} +
+
+ {{.Abstract | raw}} +
+ 查看 +
+ {{end}} + + {{template "paging.html" $}} +
+
+{{template "footer.html" $}} +{{template "highlight.html" $}} + + + \ No newline at end of file diff --git a/public/blog/themes/medium/page.html b/public/blog/themes/medium/page.html new file mode 100644 index 0000000..a92dda2 --- /dev/null +++ b/public/blog/themes/medium/page.html @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaa \ No newline at end of file diff --git a/public/blog/themes/medium/paging.html b/public/blog/themes/medium/paging.html new file mode 100644 index 0000000..329943f --- /dev/null +++ b/public/blog/themes/medium/paging.html @@ -0,0 +1,27 @@ +{{if gt $.paging.TotalPage 1}} + + +{{if gt $.paging.CurPage 1}} + {{set . "prePageClass" ""}} + {{set . "prePageUrl" (urlConcat $.pagingBaseUrl "page" (incr $.paging.CurPage -1)) }} +{{else}} + {{set . "prePageClass" "disabled"}} + {{set . "prePageUrl" "#"}} +{{end}} + + +{{if lt $.paging.CurPage $.paging.TotalPage }} + {{set . "nextPageClass" ""}} + {{set . "nextPageUrl" (urlConcat $.pagingBaseUrl "page" (incr $.paging.CurPage 1)) }} +{{else}} + {{set . "nextPageClass" "disabled"}} + {{set . "nextPageUrl" "#"}} +{{end}} + +{{$.paging.CurPage}}/{{$.paging.TotalPage}} + + +{{end}} \ No newline at end of file diff --git a/public/blog/themes/medium/post.html b/public/blog/themes/medium/post.html new file mode 100644 index 0000000..f59ad3e --- /dev/null +++ b/public/blog/themes/medium/post.html @@ -0,0 +1,143 @@ +{{template "header.html" .}} + +
+
+
+
+ {{.post.Title}} +
+
+ + {{if .post.Tags}} + {{blogTags $ .post.Tags}} + {{else}} + 无 + {{end}} + | + 更新 {{$.post.UpdatedTime | datetime}} + | + 创建 {{$.post.CreatedTime | datetime}} +
+ + +
+ {{ if $.blogInfo.UserLogo}} + + {{else}} + + {{end}} + {{$.blogInfo.Username}} + + {{if .post.Tags}} +   + + {{blogTags $ $.post.Tags}} + {{end}} +
+ +
+ {{if $.post.IsMarkdown }} + +
+ +
+ {{else}} + {{$.post.Content | raw}} + {{end}} +
+ +
+

+ 上一篇: {{if $.prePost}}{{$.prePost.Title}}{{else}}无{{end}} +

+

+ 下一篇: {{if $.nextPost}}{{$.nextPost.Title}}{{else}}无{{end}} +

+
+ + + {{template "share_comment.html" $}} +
+
+
+ +{{template "footer.html" $}} +{{template "highlight.html" $}} + +
+
+ + 文档导航 +
+
+
+
+ + + + + + + + + + + + + + + + + +{{if $.post.IsMarkdown }} + + + + + + + + + + + + + +{{else}} + +{{end}} + + + \ No newline at end of file diff --git a/public/blog/themes/medium/search.html b/public/blog/themes/medium/search.html new file mode 100644 index 0000000..d0f8660 --- /dev/null +++ b/public/blog/themes/medium/search.html @@ -0,0 +1,49 @@ +{{template "header.html" .}} + +
+
+

搜索 - {{.keywords}}

+
+ +
+ {{range .posts}} +
+ +
+ + {{if .Tags}} + {{blogTags $ .Tags}} + {{else}} + 无 + {{end}} + | + 更新 {{.UpdatedTime | datetime}} | + 创建 {{.CreatedTime | datetime}} +
+
+ {{.Abstract | raw}} +
+ 查看 +
+ + + {{else}} +
+ 无 +
+ {{end}} + + + {{template "paging.html" $}} + +
+
+ +{{template "footer.html" $}} +{{template "highlight.html" $}} + + \ No newline at end of file diff --git a/public/blog/themes/medium/share_comment.html b/public/blog/themes/medium/share_comment.html new file mode 100644 index 0000000..0a6db7f --- /dev/null +++ b/public/blog/themes/medium/share_comment.html @@ -0,0 +1,172 @@ + +
+
+ + {{if $.post.ReadNum}}{{$.post.ReadNum}}{{else}}1{{end}} 人读过 +
+
+
+ + + +
+
+
+
+ + +{{if and $.blogInfo.OpenComment (not (eq $.blogInfo.CommentType "disqus"))}} + + + + +
+
+
+
+ +
+
+ +
+
+
+ +
+
+
+ 立即登录, 发表评论. +
+ 没有帐号? 立即注册 +
+
+ + {{$.post.CommentNum}} 条评论 + +
+ + +
+ + +
+
+ More... +
+
+ +
+
+{{end}} + +{{if and $.blogInfo.OpenComment (eq $.blogInfo.CommentType "disqus")}} + +
+ + + +comments powered by Disqus +{{end}} \ No newline at end of file diff --git a/public/blog/themes/medium/single.html b/public/blog/themes/medium/single.html new file mode 100644 index 0000000..5b5468d --- /dev/null +++ b/public/blog/themes/medium/single.html @@ -0,0 +1,53 @@ +{{template "header.html" .}} + +
+
+
+
+ {{.single.Title}} +
+
+ 更新 {{$.single.UpdatedTime | datetime}} + | + 创建 {{$.single.CreatedTime | datetime}} +
+ + +
+ {{ if $.blogInfo.UserLogo}} + + {{else}} + + {{end}} + {{$.blogInfo.Username}} +
+ +
+ {{$.single.Content | raw}} +
+
+
+
+{{template "footer.html" $}} + +{{template "highlight.html" $}} + +
+
+ + 文档导航 +
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/public/blog/themes/medium/style.css b/public/blog/themes/medium/style.css new file mode 100644 index 0000000..ea80c61 --- /dev/null +++ b/public/blog/themes/medium/style.css @@ -0,0 +1,530 @@ +#posts img { + max-width: 100%; +} +#content * { + font-size: 16px; +} +#content h1 { + font-size: 30px; +} +#content h2 { + font-size: 24px; +} +#content h3 { + font-size: 18px; +} +#content h4 { + font-size: 14px; +} +@-webkit-keyframes dropdown { + 0% { + margin-top: -25px; + opacity: 0; + } + 90% { + margin-top: 2px; + } + 100% { + margin-top: 0; + opacity: 1; + } +} +@-moz-keyframes dropdown { + 0% { + margin-top: -25px; + opacity: 0; + } + 90% { + margin-top: 2px; + } + 100% { + margin-top: 0; + opacity: 1; + } +} +@-ms-keyframes dropdown { + 0% { + margin-top: -25px; + opacity: 0; + } + 90% { + margin-top: 2px; + } + 100% { + margin-top: 0; + opacity: 1; + } +} +@keyframes dropdown { + 0% { + margin-top: -25px; + opacity: 0; + } + 90% { + margin-top: 2px; + } + 100% { + margin-top: 0; + opacity: 1; + } +} +@-webkit-keyframes pulldown { + 0% { + top: 0; + opacity: 0; + } + 90% { + top: 90%; + } + 100% { + top: 100%; + opacity: 1; + } +} +@-moz-keyframes pulldown { + 0% { + top: 0; + opacity: 0; + } + 90% { + top: 90%; + } + 100% { + top: 100%; + opacity: 1; + } +} +@-ms-keyframes pulldown { + 0% { + top: 0; + opacity: 0; + } + 90% { + top: 90%; + } + 100% { + top: 100%; + opacity: 1; + } +} +@keyframes pulldown { + 0% { + top: 0; + opacity: 0; + } + 90% { + top: 90%; + } + 100% { + top: 100%; + opacity: 1; + } +} +a, +.btn { + -webkit-transition: all 0.2s ease; + -moz-transition: all 0.2s ease; + transition: all 0.2s ease; +} +.btn:focus { + outline: none; +} +ul.dropdown-menu { + box-shadow: rgba(0, 0, 0, 0.172549) 0px 6px 12px 0px; +} +ul.dropdown-menu:before { + content: ""; + width: 20px; + height: 12px; + position: absolute; + top: -12px; + right: 20px; + background-image: url("images/triangle_2x.png"); + background-size: 20px 12px; +} +ul.dropdown-menu { + display: block; + visibility: hidden; + opacity: 0; +} +.open ul.dropdown-menu { + -webkit-animation: pulldown .2s; + animation: pulldown .2s; + visibility: visible; + opacity: 1; +} +.created-time .fa { + color: #666; +} +#blogNav { + display: none; + background-color: #fff; + opacity: 0.7; + position: fixed; + z-index: 10; + padding: 3px; + border-radius: 3px; +} +#blogNavContent { + overflow-y: auto; + max-height: 250px; + display: none; + -webkit-overflow-scrolling: touch !important; +} +#blogNavNav { + cursor: pointer; +} +#blogNav a { + color: #666; +} +#blogNav:hover { + opacity: 0.9; +} +#blogNav a:hover { + color: #0fb264; +} +#blogNav ul { + padding-left: 20px; +} +#blogNav ul .nav-h2 { + margin-left: 20px; +} +#blogNav ul .nav-h3 { + margin-left: 30px; +} +#blogNav ul .nav-h4 { + margin-left: 40px; +} +#blogNav ul .nav-h5 { + margin-left: 50px; +} +.mobile-created-time { + display: none; +} +#footer { + padding-bottom: 10px; +} +.navbar-brand { + display: none; +} +#themeList label { + text-align: center; + margin-bottom: 5px; +} +#themeList .preview { + display: block; + width: 400px; + background: #fff; + border: 1px solid #ccc; + padding: 5px; + border-radius: 5px; +} + +/*"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue", Helvetica, "Microsoft Yahei", Verdana, Simsun, "Segoe UI", "Segoe UI Web Regular", "Segoe UI Symbol", "BBAlpha Sans", "S60 Sans", Arial, sans-serif;*/ +::selection { + background: #000000; + color: #ffffff; +} +::-moz-selection { + background: #000000; + color: #ffffff; +} +::-webkit-selection { + background: #000000; + color: #ffffff; +} +*, +body { + font-family: 'Open Sans', 'Helvetica Neue', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; + font-weight: 300; + font-size: 14px; +} +h1, +h2, +h3 { + font-family: 'Open Sans', 'Helvetica Neue', Arial, 'Hiragino Sans GB', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif; + font-weight: 300 !important; +} +a { + cursor: pointer; +} +a:hover { + text-decoration: none !important; +} +#headerContainer { + height: 100px; + background-color: #fff; +} +#posts { + width: 845px; + margin: auto; +} +#postsContainer { + background: #f5f5f5 url("images/noise.png"); + padding-bottom: 5px; +} +/* header */ +#header { + color: #000000; + position: relative; + padding: 0 0 20px 0; + margin-top: 15px; +} +#header h1 { + margin: 0; + font-size: 32px; +} +#header h1 a { + color: #000000; + font-size: 32px; +} +#header h1 a img { + height: 40px; +} +#header #blogDesc { + margin-top: 10px; +} +.navbar { + margin-bottom: 0; + border-radius: 0; + border: none; +} +.navbar-collapse { + padding-left: 0; + padding-right: 0; +} +.navbar-form { + padding: 0; +} +/* posts */ +#posts { + padding-top: 10px; +} +#posts .each-post { + border-bottom: 1px solid #ebeff2; + margin-bottom: 10px; + padding: 30px; + background-color: #fff; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + border-radius: 3px; +} +#posts .each-post .title { + font-size: 32px; + color: #0fb264; + padding: 0 0 15px 0; +} +#posts .each-post .title a { + font-size: 32px; + color: #0fb264; + padding: 0 0 15px 0; +} +#posts .each-post .created-time { + border-bottom: 1px solid #eee; + padding-bottom: 3px; + margin-bottom: 5px; +} +#posts .each-post .more { + background: #0fb264; + padding: 9px 10px; + border-radius: 2px; + line-height: 1; + font-size: 13px; + display: inline-block; + text-transform: uppercase; + margin-top: 15px; + margin-bottom: 15px; + color: #fff; +} +#disqus_thread { + border-top: 1px solid #eee; + padding: 5px 0 0 0; +} +#search { + width: 200px; +} +#footerContainer { + background-color: #ffffff; + color: #666666; +} +#footerContainer #footer a { + color: #666666; +} +#footerContainer #footer ul { + list-style: none; + margin: 0; + padding-left: 20px; +} +@media screen and (max-width: 600px) { + html, + body { + overflow-x: hidden; + background-color: #fbfcf7; + } + * { + font-size: 16px; + } + #headerContainer, + #footerContainer { + background-color: #fbfcf7; + margin: 10px 0; + } + #posts .each-post, + #postsContainer { + background-color: #fbfcf7 !important; + } + img { + max-width: 100%; + } + #posts .each-post { + padding: 10px; + } + #posts .each-post .title { + font-size: 24px; + border-left: 5px solid #65bd77; + font-weight: bold; + padding: 5px 0; + padding-left: 10px; + margin-bottom: 10px; + } + .container { + padding-right: 10px; + padding-left: 10px; + } + .created-time { + display: none; + } + .mobile-created-time { + display: block; + } + .mobile-created-time #userLogo { + display: inline-block; + max-height: 40px; + width: 40px; + border-radius: 50%; + } + #content { + margin-top: 10px; + } + .right-section .dropdown, + .right-section .btn { + display: none !important; + } + #blogNav { + left: initial !important; + right: 10px !important; + } + #postsContainer .container, + #footerContainer .container { + max-width: 100%; + } + #postsContainer { + margin: 0 !important; + max-width: 100%; + padding-top: 10px; + background: #f5f5f5 url("../../images/noise.png"); + } + #posts { + max-width: 100% !important; + } + #footerContainer #footer a { + padding: 3px; + } + #footerContainer #footer a:hover, + #footerContainer #footer a:focus { + color: #65bd77; + } + #headerAndNav { + position: initial; + text-align: left; + width: 100%; + border-bottom: 2px dashed #ebeff2; + } + #headerAndNav #headerContainer { + width: 100%; + height: auto; + padding-top: 30px; + } + #headerAndNav #header { + margin: 0; + padding: 0; + } + #headerAndNav #header h1 { + display: none; + } + #headerAndNav .navbar-collapse { + overflow-x: hidden; + } + #headerAndNav #blogDesc { + border: none; + margin-top: 20px; + font-size: 24px; + } + #headerAndNav .navbar-brand { + display: inline-block; + line-height: 50px; + padding: 0; + padding-left: 10px; + } + #headerAndNav .navbar-brand img { + height: 40px; + } + #headerAndNav .navbar .container { + width: auto; + padding: 0 15px; + } + #headerAndNav .navbar { + position: fixed; + top: 0; + right: 0; + left: 0; + background: #fbfcf7; + z-index: 1000; + border-bottom: 1px solid #DEDDDF; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), inset 0 1px 0 #ffffff; + background-color: #FDFFF5; + } + #headerAndNav .navbar-nav { + margin: 0 10px; + } + #headerAndNav .navbar-nav a { + padding-left: 10px; + border-radius: 5px; + } + #headerAndNav #search { + width: 100%; + margin: 10px; + } + #headerAndNav .navbar-form { + border: none; + } + #myTab, + .tab-content { + padding: 0 10px; + } +} + + +table { + margin-bottom: 16px; +} +table th, table td { + padding: 6px 13px; + border: 1px solid #ddd; +} +table th { + font-weight: bold; +} + +table tr { + background-color: #fff; + border-top: 1px solid #ccc; +} +table tr:nth-child(2n) { + background-color: #f8f8f8; +} +.mce-item-table, .mce-item-table td, .mce-item-table th, .mce-item-table caption { + border: 1px solid #ddd; + border-collapse: collapse; + padding: 6px 13px; +} diff --git a/public/blog/themes/medium/tag_posts.html b/public/blog/themes/medium/tag_posts.html new file mode 100644 index 0000000..2325551 --- /dev/null +++ b/public/blog/themes/medium/tag_posts.html @@ -0,0 +1,47 @@ +{{template "header.html" .}} + +
+
+

标签 - {{.curTag}}

+
+ +
+ {{range .posts}} +
+ +
+ + {{if .Tags}} + {{blogTags $ .Tags}} + {{else}} + 无 + {{end}} + | + 更新 {{.UpdatedTime | datetime}} | + 创建 {{.CreatedTime | datetime}} +
+
+ {{.Abstract | raw}} +
+ 查看 +
+ {{else}} +
+ 无 +
+ {{end}} + + + {{template "paging.html" $}} + +
+
+ +{{template "footer.html" $}} +{{template "highlight.html" $}} + + \ No newline at end of file diff --git a/public/blog/themes/medium/tags.html b/public/blog/themes/medium/tags.html new file mode 100644 index 0000000..0befb5c --- /dev/null +++ b/public/blog/themes/medium/tags.html @@ -0,0 +1,26 @@ +{{template "header.html" .}} + +
+
+

标签

+
+
+ +
+ +
+
+
+ +{{template "footer.html" .}} + + + \ No newline at end of file diff --git a/public/blog/themes/medium/theme.json b/public/blog/themes/medium/theme.json new file mode 100644 index 0000000..c8ff579 --- /dev/null +++ b/public/blog/themes/medium/theme.json @@ -0,0 +1,31 @@ +/* +以下是本主题的配置, 采用JSON格式 +其中Name, Version, Author, AuthorUrl是必填项(注意首字大写) +你也可以定义其它的配置, 如FriendLinks, 在模板文件使用 $.themeInfo.FriendLinks来获取值 + +注意: +1) JSON语法严格, 键必须用双引号, 最后不得有空','来结尾 +2) 以下配置不能包含任何注释, 不然解析会出错! + +请在此解析所有配置 +* Name 主题名 +* Version 主题版本 +* Author 主题的作者 +* AuthorUrl 作者的博客链接或相关链接 + +* FriendLinks 友情链接 + +*/ +{ + "Name": "leanote default theme", + "Version": "1.0", + "Author": "leanote.com", + "AuthorUrl": "http://leanote.com", + "FriendLinks": [ + {"Title": "我的笔记", "Url": "http://leanote.com/note"}, + {"Title": "leanote home", "Url": "http://leanote.com"}, + {"Title": "leanote 社区", "Url": "http://bbs.leanote.com"}, + {"Title": "lea++", "Url": "http://lea.leanote.com"}, + {"Title": "leanote github", "Url": "https://github.com/leanote/leanote"} + ] +} \ No newline at end of file