Module: Writecast

Defined in:
lib/writecast/config.rb,
lib/writecast/models.rb,
lib/writecast/version.rb,
lib/writecast/views/base.rb,
lib/writecast/views/page.rb,
lib/writecast/views/post.rb,
lib/writecast/views/index.rb,
lib/writecast/views/tag_index.rb,
lib/writecast/views/year_index.rb,
lib/writecast/views/month_index.rb,
lib/writecast/views/all_tags_index.rb

Defined Under Namespace

Classes: All_tags_index, All_tags_index_view, Base_view, Document, Index, Index_view, Month_index, Month_index_view, Page, Page_view, Post, Post_view, Tag_index, Tag_index_view, Year_index, Year_index_view

Constant Summary collapse

PRETTY_HTML =
true
KRAMDOWN_OPTS =
{:coderay_line_numbers => :table, :coderay_css => :class}
VERSION =
"0.0.1"

Class Method Summary collapse

Class Method Details

.helpObject



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/writecast/commands/help.rb', line 4

def Writecast::help

    def em string
        "\033[1m#{string}\033[m"
    end

    puts <<-DOC.strip_heredoc

    #{em'NAME'}
        writecast - a slightly opinionated static website generator.

    #{em'SYNOPSIS'}
        #{em'writecast help'}
        #{em'writecast init'} [target_directory]
        #{em'writecast process'} [target_directory]
        #{em'writecast serve'} [target_directory]
        #{em'writecast override'} target_view

    #{em'DESCRIPTION'}
        #{em'writecast'} is a static website generator. It is slightly
        'opinionated' in that it uses a few conventions in order to make
        publishing a simple website easy.

    #{em'EXAMPLES'}
        #{em'writecast help'}
            Display this help documentation.

        #{em'writecast init'} ~/my_new_blog
            Initialise the directory structure below '~/my_new_blog'.

        #{em'writecast process'} ~/my_new_blog
            ...
        #{em'writecast serve'} ~/my_new_blog
            ...
        #{em'writecast override'} views/index
            ...

    #{em'OVERVIEW'}

    #{em'DEFAULTS'}

    #{em'ERROR REPORTING'}

    #{em'EXIT STATUS'}

    #{em'HISTORY'}

    DOC
end

.init(destination) ⇒ Object



1
2
3
4
5
6
7
8
9
10
11
12
13
14
# File 'lib/writecast/commands/init.rb', line 1

def Writecast::init destination
    Kernel.abort "Destination must be a directory" unless File.ftype(destination) == "directory"
    puts "Initialising site in '#{destination}'"
    p Dir.pwd
    puts "creating 'content/pages'"
    FileUtils.mkdir_p(File.join(destination, 'content', 'pages'))
    puts "creating 'content/posts'"
    FileUtils.mkdir_p(File.join(destination, 'content', 'posts'))
    puts "creating 'content/static'"
    FileUtils.mkdir_p(File.join(destination, 'content', 'static'))
    puts "creating 'public_html/'"
    FileUtils.mkdir_p(File.join(destination, 'public_html'))
    puts "done."
end

.loadviewsObject

try to load from the override dir first



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/writecast/views/base.rb', line 78

def Writecast::loadviews
    def loadview view
        view_dir = File.join(Dir.pwd, 'views')
        begin
            require File.join(view_dir, view)
        rescue LoadError
            require_relative view
        end
    end
    views = 'index','post','page','month_index','year_index','tag_index','all_tags_index'
    views.each {|view| loadview view}
end

.override(view_path) ⇒ Object



1
2
3
4
5
6
7
8
9
10
11
12
13
14
# File 'lib/writecast/commands/override.rb', line 1

def Writecast::override view_path
    file_path = File.join(File.dirname(__FILE__), '..', "#{view_path}.rb")
    if File.exist? file_path
        local_file_path = File.join(Dir.pwd, "#{view_path}.rb")
        if File.exist? local_file_path
            Kernel.abort 'view already overridden'
        else
            FileUtils.mkdir_p File.join(Dir.pwd, 'views')
            FileUtils.cp(file_path, local_file_path)
        end
    else
        Kernel.abort 'no such view'
    end
end

.process(dir) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/writecast/commands/process.rb', line 4

def Writecast::process dir

    Dir::chdir dir

    FileUtils.rm_r(Dir["public_html/*"]) # clean old public_html
    FileUtils.mkdir("public_html") unless Dir.exist?("public_html")
    FileUtils.cp_r('content/static', 'public_html/static') # set up new public_html's static content

    # store posts in a nested hash by date, and in a hash by tag
    posts_hash = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)}
    tags_hash = {}
    num_posts = 0
    Dir["content/posts/**/*"].each do |post_raw|
        if File.ftype(post_raw) == 'file' && Writecast::DOC_EXTS.include?(File.extname(post_raw).downcase)
            post = Writecast::Post.new(post_raw)

            if posts_hash[post.time.year][post.time.month].empty?
                posts_hash[post.time.year][post.time.month] = [post]
            else
                posts_hash[post.time.year][post.time.month] << post
            end

            post.tags and post.tags.each do |tag|
                escaped_tag = CGI.escape(tag)
                if tags_hash[[tag,escaped_tag]]
                    tags_hash[[tag,escaped_tag]] << post
                else
                    tags_hash[[tag,escaped_tag]] = [post]
                end
            end

            # create public_html folder structure
            post_path = File.dirname(post.file_path)
            FileUtils.mkdir_p("public_html#{post_path}")

            # copy static files associated with post, if any
            if Dir.exist?("#{post_raw}_static")
                FileUtils.cp_r(
                    "#{post_raw}_static",
                    "public_html#{post_path}/#{File.basename(post_raw)}_static"
                )
            end
            num_posts += 1
        end
    end

    # posts_hash is passed to the index so that recent posts and yearly archives can be built.
    index = Writecast::Index.new(posts_hash, tags_hash, num_posts)
    # generate index atom feed
    File.open("public_html/feed.atom", "w") {|file| file.write(index.to_atom)}

    pages = [index]
    Dir["content/pages/**/*"].each do |page_raw|
        if File.ftype(page_raw) == 'file' && Writecast::DOC_EXTS.include?(File.extname(page_raw).downcase)
            page = Writecast::Page.new(page_raw)
            pages << page

            page_path = File.dirname(page.file_path)
            if Dir.exist?("#{page_raw}_static")
                FileUtils.cp_r(
                    "#{page_raw}_static",
                    "public_html#{page_path}/#{File.basename(page_raw)}_static"
                )
            end
        end
    end
    pages.each do |page|
        File.open("public_html/#{page.file_path}", "w") {|file| file.write(page.to_html(pages))}
    end

    posts_hash.each do |year,month_hash|

        # write year indices
        File.open("public_html/#{year}/index.html", "w") do |file|
            file.write(Writecast::Year_index.new(year, month_hash).to_html(pages))
        end

        month_hash.each do |month,month_posts|
            # write month indices
            File.open("public_html/#{year}/#{"%02d" % month}/index.html", "w") do |file|
                file.write(Writecast::Month_index.new(year, month, month_posts).to_html(pages))
            end

            # write posts
            month_posts.each do |post|
                File.open("public_html/#{post.file_path}", "w") {|file| file.write(post.to_html(pages))}
            end
        end
    end

    FileUtils.mkdir_p("public_html/tags")
    tags_hash.each do |tag_set, posts|
        tag,escaped_tag = tag_set
        FileUtils.mkdir_p("public_html/tags/#{tag}")
        tag_index = Writecast::Tag_index.new(tag_set, posts)
        File.open("public_html/tags/#{tag}/index.html", "w") {|file| file.write(tag_index.to_html(pages))}
        # generate tag atom feed
        File.open("public_html/tags/#{tag}/feed.atom", "w") {|file| file.write(tag_index.to_atom)}
    end
    File.open("public_html/tags/index.html", "w") do |file|
        file.write(Writecast::All_tags_index.new(tags_hash).to_html(pages))
    end
end

.serve(dir) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/writecast/commands/serve.rb', line 3

def Writecast::serve dir

    rack_app = Proc.new { |env|

        root = File.join(dir, 'public_html')
        default_charset = "; charset=utf-8"

        # Extract the requested path from the request
        path = Rack::Utils.unescape(env['PATH_INFO'])
        index_file = root + "#{path}/index.html"

        if File.exists?(index_file)
            # Return the index
            [200, {'Content-Type' => 'text/html' + default_charset}, [File.read(index_file)]]
        else
            # Pass the request to the directory app
            response = Rack::Directory.new(root).call(env)
            if response[1]['Content-Type']
                response[1]['Content-Type'] += default_charset
            end
            response
        end
    }

    Rack::Server.new(:app => rack_app,
                     :Port => 3000,
                     :server => 'webrick'
                    ).start
end