11package main
22
33import (
4- "fmt"
5- "html/template"
6- "os"
7- "path/filepath"
8- "strings "
9- "sync "
10- "time "
11- "sort "
4+ "fmt"
5+ "html/template"
6+ "os"
7+ "path/filepath"
8+ "sort "
9+ "strings "
10+ "sync "
11+ "time "
1212)
1313
1414// Parse config
@@ -19,176 +19,202 @@ var themePath, publicPath, sourcePath string
1919var wg sync.WaitGroup
2020
2121type ArticleInfo struct {
22- Date string
23- Title string
24- Link string
22+ Date string
23+ Title string
24+ Link string
2525}
2626
2727type Archive struct {
28- Year string
29- Articles [] ArticleInfo
28+ Year string
29+ Articles Collections
3030}
3131
3232type Tag struct {
33- Name string
34- Count int
35- Articles []ArticleInfo
33+ Name string
34+ Count int
35+ Articles Collections
36+ }
37+
38+ type Collections []interface {}
39+
40+ func (v Collections ) Len () int { return len (v ) }
41+ func (v Collections ) Swap (i , j int ) { v [i ], v [j ] = v [j ], v [i ] }
42+ func (v Collections ) Less (i , j int ) bool {
43+ switch v [i ].(type ) {
44+ case ArticleInfo :
45+ return v [i ].(ArticleInfo ).Date > v [j ].(ArticleInfo ).Date
46+ case Article :
47+ return v [i ].(Article ).Date > v [j ].(Article ).Date
48+ case Archive :
49+ return v [i ].(Archive ).Year > v [j ].(Archive ).Year
50+ case Tag :
51+ return v [i ].(Tag ).Count > v [j ].(Tag ).Count
52+ }
53+ return false
3654}
3755
3856func Build () {
39- startTime := time .Now ()
40- var articles = make (Articles , 0 )
41- var tagMap = make (map [string ]Articles )
42- var archiveMap = make (map [string ][]ArticleInfo )
43- // Parse config
44- themePath = filepath .Join (rootPath , globalConfig .Site .Theme )
45- publicPath = filepath .Join (rootPath , "public" )
46- sourcePath = filepath .Join (rootPath , "source" )
47- // Compile template
48- articleTpl = CompileTpl (filepath .Join (themePath , "article.html" ), "article" )
49- pageTpl = CompileTpl (filepath .Join (themePath , "page.html" ), "page" )
50- archiveTpl = CompileTpl (filepath .Join (themePath , "archive.html" ), "archive" )
51- tagTpl = CompileTpl (filepath .Join (themePath , "tag.html" ), "tag" )
52- // Clean public folder
53- cleanPatterns := []string {"post" , "tag" , "images" , "js" , "css" , "*.html" }
54- for _ , pattern := range cleanPatterns {
55- files , _ := filepath .Glob (filepath .Join (publicPath , pattern ))
56- for _ , path := range files {
57- os .RemoveAll (path )
58- }
59- }
60- // Find all .md to generate article
61- filepath .Walk (sourcePath , func (path string , info os.FileInfo , err error ) error {
62- fileExt := strings .ToLower (filepath .Ext (path ))
63- if fileExt == ".md" {
64- // Parse markdown data
65- article := ParseMarkdown (path )
66- if article .Draft {
67- return nil
68- }
69- // Generate page name
70- fileName := strings .TrimSuffix (strings .ToLower (filepath .Base (path )), ".md" )
71- Log ("Building " + fileName )
72- // Generate directory
73- unixTime := time .Unix (article .Date , 0 )
74- directory := unixTime .Format ("post/2006/01/02/" )
75- err := os .MkdirAll (filepath .Join (publicPath , directory ), 0777 )
76- if err != nil {
77- Fatal (err .Error ())
78- }
79- outPath := directory + fileName + ".html"
80- // Generate file path
81- article .Link = outPath
82- article .GlobalConfig = * globalConfig
83- articles = append (articles , * article )
84- // Get tags info
85- for _ , tag := range article .Tags {
86- if _ , ok := tagMap [tag ]; ! ok {
87- tagMap [tag ] = make (Articles , 0 )
88- }
89- tagMap [tag ] = append (tagMap [tag ], * article )
90- }
91- // Get archive info
92- dateYear := unixTime .Format ("2006" )
93- if _ , ok := archiveMap [dateYear ]; ! ok {
94- archiveMap [dateYear ] = make ([]ArticleInfo , 0 )
95- }
96- articleInfo := ArticleInfo {
97- Date : unixTime .Format ("2006-01-02" ),
98- Title : article .Title ,
99- Link : article .Link ,
100- }
101- archiveMap [dateYear ] = append (archiveMap [dateYear ], articleInfo )
102- // Render article
103- wg .Add (1 )
104- go RenderPage (articleTpl , article , filepath .Join (publicPath , outPath ))
105- }
106- return nil
107- })
108- // Sort by time
109- sort .Sort (Articles (articles ))
110- // Generate article pages
111- wg .Add (1 )
112- go RenderArticles ("" , articles , "" )
113- // Generate tags pages
114- for tagName , articles := range tagMap {
115- wg .Add (1 )
116- go RenderArticles (filepath .Join ("tag" , tagName ), articles , tagName )
117- }
118- // Generate archive page
119- archives := make ([]Archive , 0 )
120- for year , articleInfos := range archiveMap {
121- archives = append (archives , Archive {
122- Year : year ,
123- Articles : articleInfos ,
124- })
125- }
126- wg .Add (1 )
127- go RenderPage (archiveTpl , map [string ]interface {}{
128- "Total" : len (articles ),
129- "Archive" : archives ,
130- "Site" : globalConfig .Site ,
131- }, filepath .Join (publicPath , "archive.html" ))
132- // Generate tag page
133- tags := make ([]Tag , 0 )
134- for tagName , tagArticles := range tagMap {
135- articleInfos := make ([]ArticleInfo , 0 )
136- for _ , article := range tagArticles {
137- articleInfos = append (articleInfos , ArticleInfo {
138- Date : time .Unix (article .Date , 0 ).Format ("2006-01-02" ),
139- Title : article .Title ,
140- Link : article .Link ,
141- })
142- }
143- tags = append (tags , Tag {
144- Name : tagName ,
145- Count : len (tagArticles ),
146- Articles : articleInfos ,
147- })
148- }
149- wg .Add (1 )
150- go RenderPage (tagTpl , map [string ]interface {}{
151- "Total" : len (articles ),
152- "Tag" : tags ,
153- "Site" : globalConfig .Site ,
154- }, filepath .Join (publicPath , "tag.html" ))
155- // Generate other pages
156- files , _ := filepath .Glob (filepath .Join (sourcePath , "*.html" ))
157- for _ , path := range files {
158- fileExt := strings .ToLower (filepath .Ext (path ))
159- baseName := filepath .Base (path )
160- if fileExt == ".html" {
161- htmlTpl := CompileTpl (path , baseName )
162- relPath , _ := filepath .Rel (sourcePath , path )
163- wg .Add (1 )
164- go RenderPage (htmlTpl , globalConfig , filepath .Join (publicPath , relPath ))
165- }
166- }
167- // Copy static files
168- Log ("Copying files" )
169- Copy ()
170- wg .Wait ()
171- endTime := time .Now ()
172- usedTime := endTime .Sub (startTime )
173- fmt .Printf ("\n Build finish in public folder (%v)\n " , usedTime )
57+ startTime := time .Now ()
58+ var articles = make (Collections , 0 )
59+ var tagMap = make (map [string ]Collections )
60+ var archiveMap = make (map [string ]Collections )
61+ // Parse config
62+ themePath = filepath .Join (rootPath , globalConfig .Site .Theme )
63+ publicPath = filepath .Join (rootPath , "public" )
64+ sourcePath = filepath .Join (rootPath , "source" )
65+ // Compile template
66+ articleTpl = CompileTpl (filepath .Join (themePath , "article.html" ), "article" )
67+ pageTpl = CompileTpl (filepath .Join (themePath , "page.html" ), "page" )
68+ archiveTpl = CompileTpl (filepath .Join (themePath , "archive.html" ), "archive" )
69+ tagTpl = CompileTpl (filepath .Join (themePath , "tag.html" ), "tag" )
70+ // Clean public folder
71+ cleanPatterns := []string {"post" , "tag" , "images" , "js" , "css" , "*.html" , "favicon.ico" , "robots.txt" }
72+ for _ , pattern := range cleanPatterns {
73+ files , _ := filepath .Glob (filepath .Join (publicPath , pattern ))
74+ for _ , path := range files {
75+ os .RemoveAll (path )
76+ }
77+ }
78+ // Find all .md to generate article
79+ filepath .Walk (sourcePath , func (path string , info os.FileInfo , err error ) error {
80+ fileExt := strings .ToLower (filepath .Ext (path ))
81+ if fileExt == ".md" {
82+ // Parse markdown data
83+ article := ParseMarkdown (path )
84+ if article .Draft {
85+ return nil
86+ }
87+ // Generate page name
88+ fileName := strings .TrimSuffix (strings .ToLower (filepath .Base (path )), ".md" )
89+ Log ("Building " + fileName )
90+ // Generate directory
91+ unixTime := time .Unix (article .Date , 0 )
92+ directory := unixTime .Format ("post/2006/01/02/" )
93+ err := os .MkdirAll (filepath .Join (publicPath , directory ), 0777 )
94+ if err != nil {
95+ Fatal (err .Error ())
96+ }
97+ outPath := directory + fileName + ".html"
98+ // Generate file path
99+ article .Link = outPath
100+ article .GlobalConfig = * globalConfig
101+ articles = append (articles , * article )
102+ // Get tags info
103+ for _ , tag := range article .Tags {
104+ if _ , ok := tagMap [tag ]; ! ok {
105+ tagMap [tag ] = make (Collections , 0 )
106+ }
107+ tagMap [tag ] = append (tagMap [tag ], * article )
108+ }
109+ // Get archive info
110+ dateYear := unixTime .Format ("2006" )
111+ if _ , ok := archiveMap [dateYear ]; ! ok {
112+ archiveMap [dateYear ] = make (Collections , 0 )
113+ }
114+ articleInfo := ArticleInfo {
115+ Date : unixTime .Format ("2006-01-02" ),
116+ Title : article .Title ,
117+ Link : article .Link ,
118+ }
119+ archiveMap [dateYear ] = append (archiveMap [dateYear ], articleInfo )
120+ // Render article
121+ wg .Add (1 )
122+ go RenderPage (articleTpl , article , filepath .Join (publicPath , outPath ))
123+ }
124+ return nil
125+ })
126+ // Sort by date
127+ sort .Sort (articles )
128+ // Generate article pages
129+ wg .Add (1 )
130+ go RenderArticles ("" , articles , "" )
131+ // Generate tags pages
132+ for tagName , articles := range tagMap {
133+ wg .Add (1 )
134+ go RenderArticles (filepath .Join ("tag" , tagName ), articles , tagName )
135+ }
136+ // Generate archive page
137+ archives := make (Collections , 0 )
138+ for year , articleInfos := range archiveMap {
139+ // Sort by date
140+ sort .Sort (articleInfos )
141+ archives = append (archives , Archive {
142+ Year : year ,
143+ Articles : articleInfos ,
144+ })
145+ }
146+ // Sort by year
147+ sort .Sort (archives )
148+ wg .Add (1 )
149+ go RenderPage (archiveTpl , map [string ]interface {}{
150+ "Total" : len (articles ),
151+ "Archive" : archives ,
152+ "Site" : globalConfig .Site ,
153+ }, filepath .Join (publicPath , "archive.html" ))
154+ // Generate tag page
155+ tags := make (Collections , 0 )
156+ for tagName , tagArticles := range tagMap {
157+ articleInfos := make (Collections , 0 )
158+ for _ , article := range tagArticles {
159+ articleInfos = append (articleInfos , ArticleInfo {
160+ Date : time .Unix (article .(Article ).Date , 0 ).Format ("2006-01-02" ),
161+ Title : article .(Article ).Title ,
162+ Link : article .(Article ).Link ,
163+ })
164+ }
165+ // Sort by date
166+ sort .Sort (articleInfos )
167+ tags = append (tags , Tag {
168+ Name : tagName ,
169+ Count : len (tagArticles ),
170+ Articles : articleInfos ,
171+ })
172+ // Sort by count
173+ sort .Sort (Collections (tags ))
174+ }
175+ wg .Add (1 )
176+ go RenderPage (tagTpl , map [string ]interface {}{
177+ "Total" : len (articles ),
178+ "Tag" : tags ,
179+ "Site" : globalConfig .Site ,
180+ }, filepath .Join (publicPath , "tag.html" ))
181+ // Generate other pages
182+ files , _ := filepath .Glob (filepath .Join (sourcePath , "*.html" ))
183+ for _ , path := range files {
184+ fileExt := strings .ToLower (filepath .Ext (path ))
185+ baseName := filepath .Base (path )
186+ if fileExt == ".html" {
187+ htmlTpl := CompileTpl (path , baseName )
188+ relPath , _ := filepath .Rel (sourcePath , path )
189+ wg .Add (1 )
190+ go RenderPage (htmlTpl , globalConfig , filepath .Join (publicPath , relPath ))
191+ }
192+ }
193+ // Copy static files
194+ Log ("Copying files" )
195+ Copy ()
196+ wg .Wait ()
197+ endTime := time .Now ()
198+ usedTime := endTime .Sub (startTime )
199+ fmt .Printf ("\n Build finish in public folder (%v)\n " , usedTime )
174200}
175201
176202// Copy static files
177203func Copy () {
178- srcList := globalConfig .Build .Copy
179- for _ , source := range srcList {
180- srcPath := filepath .Join (rootPath , source )
181- file , err := os .Stat (srcPath )
182- if err != nil {
183- Fatal ("Not exist: " + srcPath )
184- }
185- fileName := file .Name ()
186- desPath := filepath .Join (publicPath , fileName )
187- wg .Add (1 )
188- if file .IsDir () {
189- go CopyDir (srcPath , desPath )
190- } else {
191- go CopyFile (srcPath , desPath )
192- }
193- }
204+ srcList := globalConfig .Build .Copy
205+ for _ , source := range srcList {
206+ srcPath := filepath .Join (rootPath , source )
207+ file , err := os .Stat (srcPath )
208+ if err != nil {
209+ Fatal ("Not exist: " + srcPath )
210+ }
211+ fileName := file .Name ()
212+ desPath := filepath .Join (publicPath , fileName )
213+ wg .Add (1 )
214+ if file .IsDir () {
215+ go CopyDir (srcPath , desPath )
216+ } else {
217+ go CopyFile (srcPath , desPath )
218+ }
219+ }
194220}
0 commit comments