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.
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/bin/moft +83 -0
- data/lib/moft.rb +89 -0
- data/lib/moft/command.rb +27 -0
- data/lib/moft/commands/build.rb +64 -0
- data/lib/moft/commands/new.rb +50 -0
- data/lib/moft/commands/serve.rb +33 -0
- data/lib/moft/configuration.rb +171 -0
- data/lib/moft/converter.rb +48 -0
- data/lib/moft/converters/identity.rb +21 -0
- data/lib/moft/converters/markdown.rb +43 -0
- data/lib/moft/converters/markdown/kramdown_parser.rb +44 -0
- data/lib/moft/converters/markdown/maruku_parser.rb +47 -0
- data/lib/moft/converters/markdown/rdiscount_parser.rb +26 -0
- data/lib/moft/converters/markdown/redcarpet_parser.rb +40 -0
- data/lib/moft/converters/textile.rb +50 -0
- data/lib/moft/convertible.rb +152 -0
- data/lib/moft/core_ext.rb +68 -0
- data/lib/moft/deprecator.rb +34 -0
- data/lib/moft/draft.rb +35 -0
- data/lib/moft/errors.rb +4 -0
- data/lib/moft/filters.rb +141 -0
- data/lib/moft/generator.rb +4 -0
- data/lib/moft/generators/pagination.rb +131 -0
- data/lib/moft/layout.rb +42 -0
- data/lib/moft/logger.rb +52 -0
- data/lib/moft/mime.types +85 -0
- data/lib/moft/page.rb +147 -0
- data/lib/moft/plugin.rb +75 -0
- data/lib/moft/post.rb +377 -0
- data/lib/moft/site.rb +422 -0
- data/lib/moft/static_file.rb +70 -0
- data/lib/moft/tags/gist.rb +30 -0
- data/lib/moft/tags/highlight.rb +83 -0
- data/lib/moft/tags/include.rb +37 -0
- data/lib/moft/tags/post_url.rb +46 -0
- data/lib/site_template/_config.yml +1 -0
- data/lib/site_template/_layouts/default.html +38 -0
- data/lib/site_template/_layouts/post.html +6 -0
- data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +24 -0
- data/lib/site_template/css/screen.css +189 -0
- data/lib/site_template/css/syntax.css +60 -0
- data/lib/site_template/images/.gitkeep +0 -0
- data/lib/site_template/images/rss.png +0 -0
- data/lib/site_template/index.html +13 -0
- data/moft.gemspec +100 -0
- 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 @@
|
|
1
|
+
|
@@ -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,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
|
+
}
|