UNPKG

4.41 kBtext/coffeescriptView Raw
1fs = require 'fs'
2_ = require 'underscore'
3async = require 'async'
4
5Watcher = require './watcher'
6Finder = require './finder'
7Server = require './server'
8
9class 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 # determine newest/index post
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 ) => @info[kind][item.permalink] = item
26 renderAll: ( kind, cb ) ->
27 renderTasks = []
28 for permalink, item of @info[kind]
29 renderTasks.push( { item: item, fn: ( item ) -> ( cb ) -> item.render( cb ) } )
30
31 renderFuncs = _.map( renderTasks, ( task ) -> task.fn(task.item) )
32 async.parallel( renderFuncs, cb )
33 watchContent: () ->
34 again = @watchContent
35 Site.WATCH_KINDS.forEach ( kind ) =>
36 for permalink, item of @info[kind]
37 toWatch = "_#{item.kind}s/#{item.srcPath}"
38 Watcher.onChange toWatch, "#{@root}/#{toWatch}", (( itemToProcess ) ->
39 () ->
40 itemToProcess.process ( err, processed ) ->
41 if err
42 Logger.error "Could not re-process watched #{itemToProcess.kind}, #{err}"
43 return
44
45 itemToProcess.render ( err ) =>
46 if err
47 Logger.error "Clould not re-render watched #{itemToProcess.kind}, #{err}"
48 return
49 )(item)
50 processContent: ( kind, cb ) ->
51 cb ?= ( err ) -> Logger.error( "Could not reload content! #{err}" ) if err
52 new Finder @, kind, ( err, items ) =>
53 @populateInfo( kind, items )
54 @determineIndex()
55 cb( err )
56 processStyles: ( cb ) ->
57 new Finder @, 'styles', ( err, styles ) =>
58 @populateInfo( 'styles', styles )
59 @renderAll( 'styles', cb )
60
61 compileScripts: ( cb ) ->
62 new Finder @, 'scripts', ( err, scripts ) =>
63 @populateInfo( 'scripts', scripts )
64 @renderAll( 'scripts', cb )
65 copyStatics: ( cb ) ->
66 new Finder @, 'statics', ( err, statics ) =>
67 @populateInfo( 'statics', statics )
68 @renderAll( 'statics', cb )
69 posts: () ->
70 _(@info.posts).chain()
71 .values()
72 .sortBy( (v) -> return v.timestamp )
73 .reverse()
74 .value()
75 pages: () ->
76 _(@info.pages).values()
77 build: ( cb ) ->
78 cb ?= ( err ) ->
79 if err
80 Logger.error "Site build failed! #{e}"
81 return
82 else
83 Logger.info "Build complete."
84 s = @
85 async.parallel(
86 [
87 ( cb ) ->
88 s.processContent 'posts', ( err ) ->
89 cb( err, 'posts' )
90 ( cb ) ->
91 s.processContent 'pages', ( err ) ->
92 cb( err, 'pages' )
93 ( cb ) ->
94 s.processStyles ( err ) ->
95 cb( err, 'styles' )
96 ( cb ) ->
97 s.compileScripts ( err ) ->
98 cb( err, 'scripts' )
99 ( cb ) ->
100 s.copyStatics ( err ) ->
101 cb( err, 'statics' )
102 ],
103 ( err, loaded ) ->
104 async.parallel(
105 [
106 ( cb ) -> s.renderAll( 'posts', cb )
107 ( cb ) -> s.renderAll( 'pages', cb )
108 ],
109 cb
110 )
111 )
112 developmentMode: () ->
113 @build ( err ) =>
114 site = @
115 if err
116 Logger.error err
117 return
118 else
119 Logger.info "Initial build complete!"
120 @watchContent()
121 # watch for new files in top level ^_.* directories
122 # and re-do the whole site if they change
123 fs.readdir @root, ( err, items ) ->
124 items.forEach ( item ) ->
125 return unless item.match( /^_/ )
126 Watcher.onChange item, () ->
127 site.build( () ->
128 site.watchContent()
129 )
130 # watch config file
131 Watcher.onChange 'config.coffee', () ->
132 site.config._reload()
133 site.build()
134 Watcher.onChange '_inc/layout.jade', () ->
135 site.build()
136
137Site.WATCH_KINDS = [ 'pages', 'posts', 'styles', 'scripts' ]
138Site.KINDS = _.clone( Site.WATCH_KINDS ).concat( ['statics'] )
139
140module.exports = Site