1 | fs = require 'fs'
|
2 | _ = require 'underscore'
|
3 | async = require 'async'
|
4 |
|
5 | Watcher = require './watcher'
|
6 | Finder = require './finder'
|
7 | Server = require './server'
|
8 |
|
9 | class Site
|
10 | constructor: ( @root=process.cwd() ) ->
|
11 | @config = Config
|
12 | @info = _.inject( Site.KINDS, (( h, k ) -> h[k] = {}; h ), {} )
|
13 | Logger.debug "SITE #{@}"
|
14 | determineIndex: () ->
|
15 | if @config.index?
|
16 | if (item = @info.pages[@config.index])?
|
17 | item.index = true
|
18 | Logger.debug "As index: #{item.kind}/#{item.permalink}"
|
19 | else
|
20 |
|
21 | newestThing = _.reject( @posts(), (p) -> p.draft )[0]
|
22 | newestThing.index = true
|
23 | Logger.debug "As index: #{newestThing.kind}/#{newestThing.permalink}"
|
24 | populateInfo: ( kind, items ) ->
|
25 | items.forEach ( item ) =>
|
26 | if !item.draft || @config.drafts
|
27 | @info[kind][item.permalink] = item
|
28 | else
|
29 | Logger.debug "Skipping #{item.kind}/#{item.permalink}"
|
30 | renderAll: ( kind, cb ) ->
|
31 | renderTasks = []
|
32 | for permalink, item of @info[kind]
|
33 | renderTasks.push( { item: item, fn: ( item ) -> ( cb ) -> item.render( cb ) } )
|
34 |
|
35 | renderFuncs = _.map( renderTasks, ( task ) -> task.fn(task.item) )
|
36 | async.parallel( renderFuncs, cb )
|
37 | watchContent: () ->
|
38 | again = @watchContent
|
39 | Site.WATCH_KINDS.forEach ( kind ) =>
|
40 | for permalink, item of @info[kind]
|
41 | toWatch = "_#{item.kind}s/#{item.srcPath}"
|
42 | Watcher.onChange toWatch, "#{@root}/#{toWatch}", (( itemToProcess ) ->
|
43 | () ->
|
44 | itemToProcess.process ( err, processed ) ->
|
45 | if err
|
46 | Logger.error "Could not re-process watched #{itemToProcess.kind}, #{err}"
|
47 | return
|
48 |
|
49 | itemToProcess.render ( err ) =>
|
50 | if err
|
51 | Logger.error "Clould not re-render watched #{itemToProcess.kind}, #{err}"
|
52 | return
|
53 | )(item)
|
54 | processContent: ( kind, cb ) ->
|
55 | cb ?= ( err ) -> Logger.error( "Could not reload content! #{err}" ) if err
|
56 | new Finder @, kind, ( err, items ) =>
|
57 | @populateInfo( kind, items )
|
58 | @determineIndex()
|
59 | cb( err )
|
60 | processStyles: ( cb ) ->
|
61 | new Finder @, 'styles', ( err, styles ) =>
|
62 | @populateInfo( 'styles', styles )
|
63 | @renderAll( 'styles', cb )
|
64 |
|
65 | compileScripts: ( cb ) ->
|
66 | new Finder @, 'scripts', ( err, scripts ) =>
|
67 | @populateInfo( 'scripts', scripts )
|
68 | @renderAll( 'scripts', cb )
|
69 | copyStatics: ( cb ) ->
|
70 | new Finder @, 'statics', ( err, statics ) =>
|
71 | @populateInfo( 'statics', statics )
|
72 | @renderAll( 'statics', cb )
|
73 | posts: () ->
|
74 | _(@info.posts).chain()
|
75 | .values()
|
76 | .sortBy( (v) -> return v.timestamp )
|
77 | .reverse()
|
78 | .value()
|
79 | pages: () ->
|
80 | _(@info.pages).values()
|
81 | build: ( cb ) ->
|
82 | cb ?= ( err ) ->
|
83 | if err
|
84 | Logger.error "Site build failed! #{e}"
|
85 | return
|
86 | else
|
87 | Logger.info "Build complete."
|
88 | s = @
|
89 | async.parallel(
|
90 | [
|
91 | ( cb ) ->
|
92 | s.processContent 'posts', ( err ) ->
|
93 | cb( err, 'posts' )
|
94 | ( cb ) ->
|
95 | s.processContent 'pages', ( err ) ->
|
96 | cb( err, 'pages' )
|
97 | ( cb ) ->
|
98 | s.processStyles ( err ) ->
|
99 | cb( err, 'styles' )
|
100 | ( cb ) ->
|
101 | s.compileScripts ( err ) ->
|
102 | cb( err, 'scripts' )
|
103 | ( cb ) ->
|
104 | s.copyStatics ( err ) ->
|
105 | cb( err, 'statics' )
|
106 | ],
|
107 | ( err, loaded ) ->
|
108 | async.parallel(
|
109 | [
|
110 | ( cb ) -> s.renderAll( 'posts', cb )
|
111 | ( cb ) -> s.renderAll( 'pages', cb )
|
112 | ],
|
113 | cb
|
114 | )
|
115 | )
|
116 | developmentMode: () ->
|
117 | @build ( err ) =>
|
118 | site = @
|
119 | if err
|
120 | Logger.error err
|
121 | return
|
122 | else
|
123 | Logger.info "Initial build complete!"
|
124 | @watchContent()
|
125 |
|
126 |
|
127 | fs.readdir @root, ( err, items ) ->
|
128 | items.forEach ( item ) ->
|
129 | return unless item.match( /^_/ )
|
130 | Watcher.onChange item, () ->
|
131 | site.build( () ->
|
132 | site.watchContent()
|
133 | )
|
134 |
|
135 | Watcher.onChange 'config.coffee', () ->
|
136 | site.config._reload()
|
137 | site.build()
|
138 | Watcher.onChange '_inc/layout.jade', () ->
|
139 | site.build()
|
140 |
|
141 | Site.WATCH_KINDS = [ 'pages', 'posts', 'styles', 'scripts' ]
|
142 | Site.KINDS = _.clone( Site.WATCH_KINDS ).concat( ['statics'] )
|
143 |
|
144 | module.exports = Site
|