moft 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. data/Gemfile +2 -0
  2. data/LICENSE +21 -0
  3. data/bin/moft +83 -0
  4. data/lib/moft.rb +89 -0
  5. data/lib/moft/command.rb +27 -0
  6. data/lib/moft/commands/build.rb +64 -0
  7. data/lib/moft/commands/new.rb +50 -0
  8. data/lib/moft/commands/serve.rb +33 -0
  9. data/lib/moft/configuration.rb +171 -0
  10. data/lib/moft/converter.rb +48 -0
  11. data/lib/moft/converters/identity.rb +21 -0
  12. data/lib/moft/converters/markdown.rb +43 -0
  13. data/lib/moft/converters/markdown/kramdown_parser.rb +44 -0
  14. data/lib/moft/converters/markdown/maruku_parser.rb +47 -0
  15. data/lib/moft/converters/markdown/rdiscount_parser.rb +26 -0
  16. data/lib/moft/converters/markdown/redcarpet_parser.rb +40 -0
  17. data/lib/moft/converters/textile.rb +50 -0
  18. data/lib/moft/convertible.rb +152 -0
  19. data/lib/moft/core_ext.rb +68 -0
  20. data/lib/moft/deprecator.rb +34 -0
  21. data/lib/moft/draft.rb +35 -0
  22. data/lib/moft/errors.rb +4 -0
  23. data/lib/moft/filters.rb +141 -0
  24. data/lib/moft/generator.rb +4 -0
  25. data/lib/moft/generators/pagination.rb +131 -0
  26. data/lib/moft/layout.rb +42 -0
  27. data/lib/moft/logger.rb +52 -0
  28. data/lib/moft/mime.types +85 -0
  29. data/lib/moft/page.rb +147 -0
  30. data/lib/moft/plugin.rb +75 -0
  31. data/lib/moft/post.rb +377 -0
  32. data/lib/moft/site.rb +422 -0
  33. data/lib/moft/static_file.rb +70 -0
  34. data/lib/moft/tags/gist.rb +30 -0
  35. data/lib/moft/tags/highlight.rb +83 -0
  36. data/lib/moft/tags/include.rb +37 -0
  37. data/lib/moft/tags/post_url.rb +46 -0
  38. data/lib/site_template/_config.yml +1 -0
  39. data/lib/site_template/_layouts/default.html +38 -0
  40. data/lib/site_template/_layouts/post.html +6 -0
  41. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +24 -0
  42. data/lib/site_template/css/screen.css +189 -0
  43. data/lib/site_template/css/syntax.css +60 -0
  44. data/lib/site_template/images/.gitkeep +0 -0
  45. data/lib/site_template/images/rss.png +0 -0
  46. data/lib/site_template/index.html +13 -0
  47. data/moft.gemspec +100 -0
  48. metadata +412 -0
@@ -0,0 +1,30 @@
1
+ # Gist Liquid Tag
2
+ #
3
+ # Example:
4
+ # {% gist 1234567 %}
5
+ # {% gist 1234567 file.rb %}
6
+
7
+ module Moft
8
+ class GistTag < Liquid::Tag
9
+ def render(context)
10
+ if tag_contents = @markup.strip.match(/\A(\d+) ?(\S*)\Z/)
11
+ gist_id, filename = tag_contents[1].strip, tag_contents[2].strip
12
+ gist_script_tag(gist_id, filename)
13
+ else
14
+ "Error parsing gist id"
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def gist_script_tag(gist_id, filename=nil)
21
+ if filename.empty?
22
+ "<script src=\"https://gist.github.com/#{gist_id}.js\"> </script>"
23
+ else
24
+ "<script src=\"https://gist.github.com/#{gist_id}.js?file=#{filename}\"> </script>"
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ Liquid::Template.register_tag('gist', Moft::GistTag)
@@ -0,0 +1,83 @@
1
+ module Moft
2
+ module Tags
3
+ class HighlightBlock < Liquid::Block
4
+ include Liquid::StandardFilters
5
+
6
+ # The regular expression syntax checker. Start with the language specifier.
7
+ # Follow that by zero or more space separated options that take one of two
8
+ # forms:
9
+ #
10
+ # 1. name
11
+ # 2. name=value
12
+ SYNTAX = /^([a-zA-Z0-9.+#-]+)((\s+\w+(=\w+)?)*)$/
13
+
14
+ def initialize(tag_name, markup, tokens)
15
+ super
16
+ if markup.strip =~ SYNTAX
17
+ @lang = $1
18
+ @options = {}
19
+ if defined?($2) && $2 != ''
20
+ $2.split.each do |opt|
21
+ key, value = opt.split('=')
22
+ if value.nil?
23
+ if key == 'linenos'
24
+ value = 'inline'
25
+ else
26
+ value = true
27
+ end
28
+ end
29
+ @options[key] = value
30
+ end
31
+ end
32
+ else
33
+ raise SyntaxError.new <<-eos
34
+ Syntax Error in tag 'highlight' while parsing the following markup:
35
+
36
+ #{markup}
37
+
38
+ Valid syntax: highlight <lang> [linenos]
39
+ eos
40
+ end
41
+ end
42
+
43
+ def render(context)
44
+ if context.registers[:site].pygments
45
+ render_pygments(context, super)
46
+ else
47
+ render_codehighlighter(context, super)
48
+ end
49
+ end
50
+
51
+ def render_pygments(context, code)
52
+ @options[:encoding] = 'utf-8'
53
+
54
+ output = add_code_tags(
55
+ Pygments.highlight(code, :lexer => @lang, :options => @options),
56
+ @lang
57
+ )
58
+
59
+ output = context["pygments_prefix"] + output if context["pygments_prefix"]
60
+ output = output + context["pygments_suffix"] if context["pygments_suffix"]
61
+ output
62
+ end
63
+
64
+ def render_codehighlighter(context, code)
65
+ #The div is required because RDiscount blows ass
66
+ <<-HTML
67
+ <div>
68
+ <pre><code class='#{@lang}'>#{h(code).strip}</code></pre>
69
+ </div>
70
+ HTML
71
+ end
72
+
73
+ def add_code_tags(code, lang)
74
+ # Add nested <code> tags to code blocks
75
+ code = code.sub(/<pre>/,'<pre><code class="' + lang + '">')
76
+ code = code.sub(/<\/pre>/,"</code></pre>")
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+
83
+ Liquid::Template.register_tag('highlight', Moft::Tags::HighlightBlock)
@@ -0,0 +1,37 @@
1
+ module Moft
2
+ module Tags
3
+ class IncludeTag < Liquid::Tag
4
+ def initialize(tag_name, file, tokens)
5
+ super
6
+ @file = file.strip
7
+ end
8
+
9
+ def render(context)
10
+ includes_dir = File.join(context.registers[:site].source, '_includes')
11
+
12
+ if File.symlink?(includes_dir)
13
+ return "Includes directory '#{includes_dir}' cannot be a symlink"
14
+ end
15
+
16
+ if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
17
+ return "Include file '#{@file}' contains invalid characters or sequences"
18
+ end
19
+
20
+ Dir.chdir(includes_dir) do
21
+ choices = Dir['**/*'].reject { |x| File.symlink?(x) }
22
+ if choices.include?(@file)
23
+ source = File.read(@file)
24
+ partial = Liquid::Template.parse(source)
25
+ context.stack do
26
+ partial.render(context)
27
+ end
28
+ else
29
+ "Included file '#{@file}' not found in _includes directory"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ Liquid::Template.register_tag('include', Moft::Tags::IncludeTag)
@@ -0,0 +1,46 @@
1
+ module Moft
2
+ module Tags
3
+ class PostComparer
4
+ MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)$/
5
+
6
+ attr_accessor :date, :slug
7
+
8
+ def initialize(name)
9
+ who, cares, date, slug = *name.match(MATCHER)
10
+ @slug = slug
11
+ @date = Time.parse(date)
12
+ end
13
+
14
+ def ==(other)
15
+ slug == other.slug &&
16
+ date.year == other.date.year &&
17
+ date.month == other.date.month &&
18
+ date.day == other.date.day
19
+ end
20
+ end
21
+
22
+ class PostUrl < Liquid::Tag
23
+ def initialize(tag_name, post, tokens)
24
+ super
25
+ @orig_post = post.strip
26
+ @post = PostComparer.new(@orig_post)
27
+ end
28
+
29
+ def render(context)
30
+ site = context.registers[:site]
31
+
32
+ site.posts.each do |p|
33
+ if @post == p
34
+ return p.url
35
+ end
36
+ end
37
+
38
+ puts "ERROR: post_url: \"#{@orig_post}\" could not be found"
39
+
40
+ return "#"
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ Liquid::Template.register_tag('post_url', Moft::Tags::PostUrl)
@@ -0,0 +1,38 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
5
+ <title>{{ page.title }}</title>
6
+ <!-- syntax highlighting CSS -->
7
+ <link rel="stylesheet" href="/css/syntax.css" type="text/css" />
8
+ <!-- Homepage CSS -->
9
+ <link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen, projection" />
10
+ </head>
11
+ <body>
12
+ <div class="site">
13
+ <div class="title">
14
+ <a href="/">Your Name</a>
15
+ <a class="extra" href="/">home</a>
16
+ </div>
17
+
18
+ {{ content }}
19
+
20
+ <div class="footer">
21
+ <div class="contact">
22
+ <p>
23
+ Your Name<br />
24
+ What You Are<br />
25
+ your@email.com
26
+ </p>
27
+ </div>
28
+ <div class="contact">
29
+ <p>
30
+ <a href="http://github.com/yourusername/">github.com/yourusername</a><br />
31
+ <a href="http://twitter.com/yourusername/">twitter.com/yourusername</a><br />
32
+ </p>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ <a href="http://github.com/yourusername"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub" /></a>
37
+ </body>
38
+ </html>
@@ -0,0 +1,6 @@
1
+ ---
2
+ layout: default
3
+ ---
4
+ <div id="post">
5
+ {{ content }}
6
+ </div>
@@ -0,0 +1,24 @@
1
+ ---
2
+ layout: post
3
+ title: "Welcome to Moft!"
4
+ date: <%= Time.now.strftime('%Y-%m-%d %H:%M:%S') %>
5
+ categories: moft update
6
+ ---
7
+
8
+ You'll find this post in your `_posts` directory - edit this post and re-build (or run with the `-w` switch) to see your changes!
9
+ To add new posts, simply add a file in the `_posts` directory that follows the convention: YYYY-MM-DD-name-of-post.ext.
10
+
11
+ Moft also offers powerful support for code snippets:
12
+
13
+ {% highlight ruby %}
14
+ def print_hi(name)
15
+ puts "Hi, #{name}"
16
+ end
17
+ print_hi('Tom')
18
+ #=> prints 'Hi, Tom' to STDOUT.
19
+ {% endhighlight %}
20
+
21
+ Check out the [Moft docs][moft] for more info on how to get the most out of Moft. File all bugs/feature requests at [Moft's GitHub repo][moft-gh].
22
+
23
+ [moft-gh]: https://github.com/mojombo/moft
24
+ [moft]: http://moftrb.com
@@ -0,0 +1,189 @@
1
+ /*****************************************************************************/
2
+ /*
3
+ /* Common
4
+ /*
5
+ /*****************************************************************************/
6
+
7
+ /* Global Reset */
8
+
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ }
13
+
14
+ html, body {
15
+ height: 100%;
16
+ }
17
+
18
+ body {
19
+ background-color: white;
20
+ font: 13.34px helvetica, arial, clean, sans-serif;
21
+ *font-size: small;
22
+ text-align: center;
23
+ }
24
+
25
+ h1, h2, h3, h4, h5, h6 {
26
+ font-size: 100%;
27
+ }
28
+
29
+ h1 {
30
+ margin-bottom: 1em;
31
+ }
32
+
33
+ p {
34
+ margin: 1em 0;
35
+ }
36
+
37
+ a {
38
+ color: #00a;
39
+ }
40
+
41
+ a:hover {
42
+ color: black;
43
+ }
44
+
45
+ a:visited {
46
+ color: #a0a;
47
+ }
48
+
49
+ table {
50
+ font-size: inherit;
51
+ font: 100%;
52
+ }
53
+
54
+ /*****************************************************************************/
55
+ /*
56
+ /* Home
57
+ /*
58
+ /*****************************************************************************/
59
+
60
+ ul.posts {
61
+ list-style-type: none;
62
+ margin-bottom: 2em;
63
+ }
64
+
65
+ ul.posts li {
66
+ line-height: 1.75em;
67
+ }
68
+
69
+ ul.posts span {
70
+ color: #aaa;
71
+ font-family: Monaco, "Courier New", monospace;
72
+ font-size: 80%;
73
+ }
74
+
75
+ /*****************************************************************************/
76
+ /*
77
+ /* Site
78
+ /*
79
+ /*****************************************************************************/
80
+
81
+ .site {
82
+ font-size: 110%;
83
+ text-align: justify;
84
+ width: 42em;
85
+ margin: 3em auto 2em auto;
86
+ line-height: 1.5em;
87
+ }
88
+
89
+ .title {
90
+ color: #a00;
91
+ font-weight: bold;
92
+ margin-bottom: 2em;
93
+ }
94
+
95
+ .site .title a {
96
+ color: #a00;
97
+ text-decoration: none;
98
+ }
99
+
100
+ .site .title a:hover {
101
+ color: black;
102
+ }
103
+
104
+ .site .title a.extra {
105
+ color: #aaa;
106
+ text-decoration: none;
107
+ margin-left: 1em;
108
+ }
109
+
110
+ .site .title a.extra:hover {
111
+ color: black;
112
+ }
113
+
114
+ .site .meta {
115
+ color: #aaa;
116
+ }
117
+
118
+ .site .footer {
119
+ font-size: 80%;
120
+ color: #666;
121
+ border-top: 4px solid #eee;
122
+ margin-top: 2em;
123
+ overflow: hidden;
124
+ }
125
+
126
+ .site .footer .contact {
127
+ float: left;
128
+ margin-right: 3em;
129
+ }
130
+
131
+ .site .footer .contact a {
132
+ color: #8085C1;
133
+ }
134
+
135
+ .site .footer .rss {
136
+ margin-top: 1.1em;
137
+ margin-right: -.2em;
138
+ float: right;
139
+ }
140
+
141
+ .site .footer .rss img {
142
+ border: 0;
143
+ }
144
+
145
+ /*****************************************************************************/
146
+ /*
147
+ /* Posts
148
+ /*
149
+ /*****************************************************************************/
150
+
151
+ #post {
152
+
153
+ }
154
+
155
+ /* standard */
156
+
157
+ #post pre {
158
+ border: 1px solid #ddd;
159
+ background-color: #eef;
160
+ padding: 0 .4em;
161
+ }
162
+
163
+ #post ul,
164
+ #post ol {
165
+ margin-left: 1.35em;
166
+ }
167
+
168
+ #post code {
169
+ border: 1px solid #ddd;
170
+ background-color: #eef;
171
+ font-size: 85%;
172
+ padding: 0 .2em;
173
+ }
174
+
175
+ #post pre code {
176
+ border: none;
177
+ }
178
+
179
+ /* terminal */
180
+
181
+ #post pre.terminal {
182
+ border: 1px solid black;
183
+ background-color: #333;
184
+ color: white;
185
+ }
186
+
187
+ #post pre.terminal code {
188
+ background-color: #333;
189
+ }