monad 0.0.1
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/CONTRIBUTING.md +68 -0
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/README.md +88 -0
- data/Rakefile +136 -0
- data/bin/monad +102 -0
- data/cucumber.yml +3 -0
- data/features/create_sites.feature +112 -0
- data/features/data_sources.feature +76 -0
- data/features/drafts.feature +25 -0
- data/features/embed_filters.feature +60 -0
- data/features/markdown.feature +30 -0
- data/features/pagination.feature +54 -0
- data/features/permalinks.feature +65 -0
- data/features/post_data.feature +214 -0
- data/features/site_configuration.feature +206 -0
- data/features/site_data.feature +101 -0
- data/features/step_definitions/monad_steps.rb +175 -0
- data/features/support/env.rb +25 -0
- data/lib/monad.rb +90 -0
- data/lib/monad/command.rb +27 -0
- data/lib/monad/commands/build.rb +64 -0
- data/lib/monad/commands/doctor.rb +29 -0
- data/lib/monad/commands/new.rb +50 -0
- data/lib/monad/commands/serve.rb +33 -0
- data/lib/monad/configuration.rb +183 -0
- data/lib/monad/converter.rb +48 -0
- data/lib/monad/converters/identity.rb +21 -0
- data/lib/monad/converters/markdown.rb +43 -0
- data/lib/monad/converters/markdown/kramdown_parser.rb +44 -0
- data/lib/monad/converters/markdown/maruku_parser.rb +47 -0
- data/lib/monad/converters/markdown/rdiscount_parser.rb +35 -0
- data/lib/monad/converters/markdown/redcarpet_parser.rb +70 -0
- data/lib/monad/converters/textile.rb +50 -0
- data/lib/monad/convertible.rb +152 -0
- data/lib/monad/core_ext.rb +68 -0
- data/lib/monad/deprecator.rb +32 -0
- data/lib/monad/draft.rb +35 -0
- data/lib/monad/drivers/json_driver.rb +39 -0
- data/lib/monad/drivers/yaml_driver.rb +23 -0
- data/lib/monad/errors.rb +4 -0
- data/lib/monad/filters.rb +154 -0
- data/lib/monad/generator.rb +4 -0
- data/lib/monad/generators/pagination.rb +143 -0
- data/lib/monad/layout.rb +42 -0
- data/lib/monad/logger.rb +54 -0
- data/lib/monad/mime.types +85 -0
- data/lib/monad/page.rb +163 -0
- data/lib/monad/plugin.rb +75 -0
- data/lib/monad/post.rb +377 -0
- data/lib/monad/site.rb +455 -0
- data/lib/monad/static_file.rb +70 -0
- data/lib/monad/tags/gist.rb +30 -0
- data/lib/monad/tags/highlight.rb +85 -0
- data/lib/monad/tags/include.rb +37 -0
- data/lib/monad/tags/post_url.rb +61 -0
- data/lib/site_template/.gitignore +1 -0
- data/lib/site_template/_config.yml +2 -0
- data/lib/site_template/_layouts/default.html +46 -0
- data/lib/site_template/_layouts/post.html +9 -0
- data/lib/site_template/_posts/0000-00-00-welcome-to-monad.markdown.erb +24 -0
- data/lib/site_template/css/main.css +165 -0
- data/lib/site_template/css/syntax.css +60 -0
- data/lib/site_template/index.html +13 -0
- data/monad.gemspec +197 -0
- data/script/bootstrap +2 -0
- data/test/fixtures/broken_front_matter1.erb +5 -0
- data/test/fixtures/broken_front_matter2.erb +4 -0
- data/test/fixtures/broken_front_matter3.erb +7 -0
- data/test/fixtures/exploit_front_matter.erb +4 -0
- data/test/fixtures/front_matter.erb +4 -0
- data/test/fixtures/members.yaml +7 -0
- data/test/helper.rb +62 -0
- data/test/source/.htaccess +8 -0
- data/test/source/_includes/sig.markdown +3 -0
- data/test/source/_layouts/default.html +27 -0
- data/test/source/_layouts/simple.html +1 -0
- data/test/source/_plugins/dummy.rb +8 -0
- data/test/source/_posts/2008-02-02-not-published.textile +8 -0
- data/test/source/_posts/2008-02-02-published.textile +8 -0
- data/test/source/_posts/2008-10-18-foo-bar.textile +8 -0
- data/test/source/_posts/2008-11-21-complex.textile +8 -0
- data/test/source/_posts/2008-12-03-permalinked-post.textile +9 -0
- data/test/source/_posts/2008-12-13-include.markdown +8 -0
- data/test/source/_posts/2009-01-27-array-categories.textile +10 -0
- data/test/source/_posts/2009-01-27-categories.textile +7 -0
- data/test/source/_posts/2009-01-27-category.textile +7 -0
- data/test/source/_posts/2009-01-27-empty-categories.textile +7 -0
- data/test/source/_posts/2009-01-27-empty-category.textile +7 -0
- data/test/source/_posts/2009-03-12-hash-#1.markdown +6 -0
- data/test/source/_posts/2009-05-18-empty-tag.textile +6 -0
- data/test/source/_posts/2009-05-18-empty-tags.textile +6 -0
- data/test/source/_posts/2009-05-18-tag.textile +6 -0
- data/test/source/_posts/2009-05-18-tags.textile +9 -0
- data/test/source/_posts/2009-06-22-empty-yaml.textile +3 -0
- data/test/source/_posts/2009-06-22-no-yaml.textile +1 -0
- data/test/source/_posts/2010-01-08-triple-dash.markdown +5 -0
- data/test/source/_posts/2010-01-09-date-override.textile +7 -0
- data/test/source/_posts/2010-01-09-time-override.textile +7 -0
- data/test/source/_posts/2010-01-09-timezone-override.textile +7 -0
- data/test/source/_posts/2010-01-16-override-data.textile +4 -0
- data/test/source/_posts/2011-04-12-md-extension.md +7 -0
- data/test/source/_posts/2011-04-12-text-extension.text +0 -0
- data/test/source/_posts/2013-01-02-post-excerpt.markdown +14 -0
- data/test/source/_posts/2013-01-12-nil-layout.textile +6 -0
- data/test/source/_posts/2013-01-12-no-layout.textile +5 -0
- data/test/source/_posts/2013-03-19-not-a-post.markdown/.gitkeep +0 -0
- data/test/source/_posts/2013-04-11-custom-excerpt.markdown +10 -0
- data/test/source/_posts/2013-05-10-number-category.textile +7 -0
- data/test/source/_posts/es/2008-11-21-nested.textile +8 -0
- data/test/source/about.html +6 -0
- data/test/source/category/_posts/2008-9-23-categories.textile +6 -0
- data/test/source/contacts.html +5 -0
- data/test/source/contacts/bar.html +5 -0
- data/test/source/contacts/index.html +5 -0
- data/test/source/css/screen.css +76 -0
- data/test/source/deal.with.dots.html +7 -0
- data/test/source/foo/_posts/bar/2008-12-12-topical-post.textile +8 -0
- data/test/source/index.html +22 -0
- data/test/source/sitemap.xml +32 -0
- data/test/source/symlink-test/symlinked-file +22 -0
- data/test/source/win/_posts/2009-05-24-yaml-linebreak.markdown +7 -0
- data/test/source/z_category/_posts/2008-9-23-categories.textile +6 -0
- data/test/suite.rb +11 -0
- data/test/test_command.rb +39 -0
- data/test/test_configuration.rb +137 -0
- data/test/test_convertible.rb +51 -0
- data/test/test_core_ext.rb +88 -0
- data/test/test_filters.rb +102 -0
- data/test/test_generated_site.rb +83 -0
- data/test/test_json_driver.rb +63 -0
- data/test/test_kramdown.rb +35 -0
- data/test/test_new_command.rb +104 -0
- data/test/test_page.rb +193 -0
- data/test/test_pager.rb +115 -0
- data/test/test_post.rb +573 -0
- data/test/test_rdiscount.rb +22 -0
- data/test/test_redcarpet.rb +61 -0
- data/test/test_redcloth.rb +86 -0
- data/test/test_site.rb +374 -0
- data/test/test_tags.rb +310 -0
- data/test/test_yaml_driver.rb +35 -0
- metadata +554 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module Monad
|
|
2
|
+
class StaticFile
|
|
3
|
+
# The cache of last modification times [path] -> mtime.
|
|
4
|
+
@@mtimes = Hash.new
|
|
5
|
+
|
|
6
|
+
# Initialize a new StaticFile.
|
|
7
|
+
#
|
|
8
|
+
# site - The Site.
|
|
9
|
+
# base - The String path to the <source>.
|
|
10
|
+
# dir - The String path between <source> and the file.
|
|
11
|
+
# name - The String filename of the file.
|
|
12
|
+
def initialize(site, base, dir, name)
|
|
13
|
+
@site = site
|
|
14
|
+
@base = base
|
|
15
|
+
@dir = dir
|
|
16
|
+
@name = name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns source file path.
|
|
20
|
+
def path
|
|
21
|
+
File.join(@base, @dir, @name)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Obtain destination path.
|
|
25
|
+
#
|
|
26
|
+
# dest - The String path to the destination dir.
|
|
27
|
+
#
|
|
28
|
+
# Returns destination file path.
|
|
29
|
+
def destination(dest)
|
|
30
|
+
File.join(dest, @dir, @name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns last modification time for this file.
|
|
34
|
+
def mtime
|
|
35
|
+
File.stat(path).mtime.to_i
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Is source path modified?
|
|
39
|
+
#
|
|
40
|
+
# Returns true if modified since last write.
|
|
41
|
+
def modified?
|
|
42
|
+
@@mtimes[path] != mtime
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Write the static file to the destination directory (if modified).
|
|
46
|
+
#
|
|
47
|
+
# dest - The String path to the destination dir.
|
|
48
|
+
#
|
|
49
|
+
# Returns false if the file was not modified since last time (no-op).
|
|
50
|
+
def write(dest)
|
|
51
|
+
dest_path = destination(dest)
|
|
52
|
+
|
|
53
|
+
return false if File.exist?(dest_path) and !modified?
|
|
54
|
+
@@mtimes[path] = mtime
|
|
55
|
+
|
|
56
|
+
FileUtils.mkdir_p(File.dirname(dest_path))
|
|
57
|
+
FileUtils.cp(path, dest_path)
|
|
58
|
+
|
|
59
|
+
true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Reset the mtimes cache (for testing purposes).
|
|
63
|
+
#
|
|
64
|
+
# Returns nothing.
|
|
65
|
+
def self.reset_cache
|
|
66
|
+
@@mtimes = Hash.new
|
|
67
|
+
nil
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Gist Liquid Tag
|
|
2
|
+
#
|
|
3
|
+
# Example:
|
|
4
|
+
# {% gist 1234567 %}
|
|
5
|
+
# {% gist 1234567 file.rb %}
|
|
6
|
+
|
|
7
|
+
module Monad
|
|
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', Monad::GistTag)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Monad
|
|
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
|
+
require 'pygments'
|
|
53
|
+
|
|
54
|
+
@options[:encoding] = 'utf-8'
|
|
55
|
+
|
|
56
|
+
output = add_code_tags(
|
|
57
|
+
Pygments.highlight(code, :lexer => @lang, :options => @options),
|
|
58
|
+
@lang
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
output = context["pygments_prefix"] + output if context["pygments_prefix"]
|
|
62
|
+
output = output + context["pygments_suffix"] if context["pygments_suffix"]
|
|
63
|
+
output
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def render_codehighlighter(context, code)
|
|
67
|
+
#The div is required because RDiscount blows ass
|
|
68
|
+
<<-HTML
|
|
69
|
+
<div>
|
|
70
|
+
<pre><code class='#{@lang}'>#{h(code).strip}</code></pre>
|
|
71
|
+
</div>
|
|
72
|
+
HTML
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def add_code_tags(code, lang)
|
|
76
|
+
# Add nested <code> tags to code blocks
|
|
77
|
+
code = code.sub(/<pre>/,'<pre><code class="' + lang + '">')
|
|
78
|
+
code = code.sub(/<\/pre>/,"</code></pre>")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
Liquid::Template.register_tag('highlight', Monad::Tags::HighlightBlock)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Monad
|
|
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', Monad::Tags::IncludeTag)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Monad
|
|
2
|
+
module Tags
|
|
3
|
+
class PostComparer
|
|
4
|
+
MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)$/
|
|
5
|
+
|
|
6
|
+
attr_accessor :date, :slug
|
|
7
|
+
|
|
8
|
+
def initialize(name)
|
|
9
|
+
all, path, date, slug = *name.sub(/^\//, "").match(MATCHER)
|
|
10
|
+
@slug = path ? path + slug : slug
|
|
11
|
+
@date = Time.parse(date)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def ==(other)
|
|
15
|
+
slug == post_slug(other) &&
|
|
16
|
+
date.year == other.date.year &&
|
|
17
|
+
date.month == other.date.month &&
|
|
18
|
+
date.day == other.date.day
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
# Construct the directory-aware post slug for a Monad::Post
|
|
23
|
+
#
|
|
24
|
+
# other - the Monad::Post
|
|
25
|
+
#
|
|
26
|
+
# Returns the post slug with the subdirectory (relative to _posts)
|
|
27
|
+
def post_slug(other)
|
|
28
|
+
path = other.name.split("/")[0...-1].join("/")
|
|
29
|
+
if path.nil? || path == ""
|
|
30
|
+
other.slug
|
|
31
|
+
else
|
|
32
|
+
path + '/' + other.slug
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class PostUrl < Liquid::Tag
|
|
38
|
+
def initialize(tag_name, post, tokens)
|
|
39
|
+
super
|
|
40
|
+
@orig_post = post.strip
|
|
41
|
+
@post = PostComparer.new(@orig_post)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def render(context)
|
|
45
|
+
site = context.registers[:site]
|
|
46
|
+
|
|
47
|
+
site.posts.each do |p|
|
|
48
|
+
if @post == p
|
|
49
|
+
return p.url
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
puts "ERROR: post_url: \"#{@orig_post}\" could not be found"
|
|
54
|
+
|
|
55
|
+
return "#"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
Liquid::Template.register_tag('post_url', Monad::Tags::PostUrl)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
_site
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
|
6
|
+
<title>{{ page.title }}</title>
|
|
7
|
+
<meta name="viewport" content="width=device-width">
|
|
8
|
+
|
|
9
|
+
<!-- syntax highlighting CSS -->
|
|
10
|
+
<link rel="stylesheet" href="/css/syntax.css">
|
|
11
|
+
|
|
12
|
+
<!-- Custom CSS -->
|
|
13
|
+
<link rel="stylesheet" href="/css/main.css">
|
|
14
|
+
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
|
|
18
|
+
<div class="container">
|
|
19
|
+
<div class="site">
|
|
20
|
+
<div class="header">
|
|
21
|
+
<h1 class="title"><a href="/">{{ site.name }}</a></h1>
|
|
22
|
+
<a class="extra" href="/">home</a>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
{{ content }}
|
|
26
|
+
|
|
27
|
+
<div class="footer">
|
|
28
|
+
<div class="contact">
|
|
29
|
+
<p>
|
|
30
|
+
Your Name<br />
|
|
31
|
+
What You Are<br />
|
|
32
|
+
your@email.com
|
|
33
|
+
</p>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="contact">
|
|
36
|
+
<p>
|
|
37
|
+
<a href="http://github.com/yourusername/">github.com/yourusername</a><br />
|
|
38
|
+
<a href="http://twitter.com/yourusername/">twitter.com/yourusername</a><br />
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div> <!-- /container -->
|
|
44
|
+
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: post
|
|
3
|
+
title: "Welcome to Monad!"
|
|
4
|
+
date: <%= Time.now.strftime('%Y-%m-%d %H:%M:%S') %>
|
|
5
|
+
categories: monad 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
|
+
Monad 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 [Monad docs][monad] for more info on how to get the most out of Monad. File all bugs/feature requests at [Monad's GitHub repo][monad-gh].
|
|
22
|
+
|
|
23
|
+
[monad-gh]: https://github.com/mojombo/monad
|
|
24
|
+
[monad]: http://monadrb.com
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/*****************************************************************************/
|
|
2
|
+
/*
|
|
3
|
+
/* Common
|
|
4
|
+
/*
|
|
5
|
+
/*****************************************************************************/
|
|
6
|
+
|
|
7
|
+
/* Global Reset */
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
html, body { height: 100%; }
|
|
14
|
+
|
|
15
|
+
body {
|
|
16
|
+
background-color: #FFF;
|
|
17
|
+
font: 13.34px Helvetica, Arial, sans-serif;
|
|
18
|
+
font-size: small;
|
|
19
|
+
text-align: center;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
h1, h2, h3, h4, h5, h6 {
|
|
23
|
+
font-size: 100%; }
|
|
24
|
+
|
|
25
|
+
h1 { margin-bottom: 1em; }
|
|
26
|
+
p { margin: 1em 0; }
|
|
27
|
+
|
|
28
|
+
a { color: #00a; }
|
|
29
|
+
a:hover { color: #000; }
|
|
30
|
+
a:visited { color: #a0a; }
|
|
31
|
+
|
|
32
|
+
table {
|
|
33
|
+
font-size: inherit;
|
|
34
|
+
font: 100%;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*****************************************************************************/
|
|
38
|
+
/*
|
|
39
|
+
/* Home
|
|
40
|
+
/*
|
|
41
|
+
/*****************************************************************************/
|
|
42
|
+
ul.posts {
|
|
43
|
+
list-style-type: none;
|
|
44
|
+
margin-bottom: 2em;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
ul.posts li {
|
|
48
|
+
line-height: 1.75em;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
ul.posts span {
|
|
52
|
+
color: #aaa;
|
|
53
|
+
font-family: Monaco, "Courier New", monospace;
|
|
54
|
+
font-size: 80%;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/*****************************************************************************/
|
|
58
|
+
/*
|
|
59
|
+
/* Site
|
|
60
|
+
/*
|
|
61
|
+
/*****************************************************************************/
|
|
62
|
+
|
|
63
|
+
.site {
|
|
64
|
+
font-size: 115%;
|
|
65
|
+
text-align: justify;
|
|
66
|
+
width: 42em;
|
|
67
|
+
margin: 3em auto 2em;
|
|
68
|
+
line-height: 1.5em;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.site .header a {
|
|
72
|
+
font-weight: bold;
|
|
73
|
+
text-decoration: none;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.site .header h1.title {
|
|
77
|
+
display: inline-block;
|
|
78
|
+
margin-bottom: 2em;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.site .header h1.title a {
|
|
82
|
+
color: #a00;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.site .header h1.title a:hover {
|
|
86
|
+
color: #000;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.site .header a.extra {
|
|
90
|
+
color: #aaa;
|
|
91
|
+
margin-left: 1em;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.site .header a.extra:hover {
|
|
95
|
+
color: #000;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.site .meta {
|
|
99
|
+
color: #aaa;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.site .footer {
|
|
103
|
+
font-size: 80%;
|
|
104
|
+
color: #666;
|
|
105
|
+
border-top: 4px solid #eee;
|
|
106
|
+
margin-top: 2em;
|
|
107
|
+
overflow: hidden;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.site .footer .contact {
|
|
111
|
+
float: left;
|
|
112
|
+
margin-right: 3em;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.site .footer .contact a {
|
|
116
|
+
color: #8085C1;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.site .footer .rss {
|
|
120
|
+
margin-top: 1.1em;
|
|
121
|
+
margin-right: -.2em;
|
|
122
|
+
float: right;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.site .footer .rss img {
|
|
126
|
+
border: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/*****************************************************************************/
|
|
130
|
+
/*
|
|
131
|
+
/* Posts
|
|
132
|
+
/*
|
|
133
|
+
/*****************************************************************************/
|
|
134
|
+
|
|
135
|
+
/* standard */
|
|
136
|
+
#post pre {
|
|
137
|
+
border: 1px solid #ddd;
|
|
138
|
+
background-color: #eef;
|
|
139
|
+
padding: 0 .4em;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
#post ul, #post ol {
|
|
143
|
+
margin-left: 1.35em;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
#post code {
|
|
147
|
+
border: 1px solid #ddd;
|
|
148
|
+
background-color: #eef;
|
|
149
|
+
padding: 0 .2em;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#post pre code {
|
|
153
|
+
border: none;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* terminal */
|
|
157
|
+
#post pre.terminal {
|
|
158
|
+
border: 1px solid #000;
|
|
159
|
+
background-color: #333;
|
|
160
|
+
color: #FFF;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
#post pre.terminal code {
|
|
164
|
+
background-color: #333;
|
|
165
|
+
}
|