faqmarkdown 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Appraisals +13 -0
- data/Gemfile +10 -0
- data/Rakefile +11 -0
- data/app/controllers/application_controller.rb +2 -0
- data/app/controllers/faqs_controller.rb +66 -0
- data/app/helpers/faq_helper.rb +23 -0
- data/app/models/faq.rb +170 -0
- data/app/views/faqs/_faq.html.haml +16 -0
- data/app/views/faqs/_feed_link.html.haml +2 -0
- data/app/views/faqs/feed.xml.builder +29 -0
- data/app/views/faqs/index.html.haml +8 -0
- data/app/views/faqs/show.html.haml +3 -0
- data/app/views/layouts/faqmarkdown.html.haml +16 -0
- data/config.ru +8 -0
- data/faqmarkdown.gemspec +37 -0
- data/gemfiles/rails3_0.gemfile +13 -0
- data/gemfiles/rails3_1.gemfile +14 -0
- data/gemfiles/rails3_2.gemfile +14 -0
- data/lib/faqmarkdown/config.rb +24 -0
- data/lib/faqmarkdown/engine.rb +12 -0
- data/lib/faqmarkdown/railtie.rb +20 -0
- data/lib/faqmarkdown/routes.rb +30 -0
- data/lib/faqmarkdown/util.rb +12 -0
- data/lib/faqmarkdown/version.rb +3 -0
- data/lib/faqmarkdown.rb +5 -0
- data/lib/generators/faqmarkdown/faq_generator.rb +42 -0
- data/lib/generators/faqmarkdown/install_generator.rb +19 -0
- data/lib/generators/faqmarkdown/override_generator.rb +48 -0
- data/lib/generators/faqmarkdown/templates/example-faq.markdown +67 -0
- data/lib/generators/faqmarkdown/usage/faq.txt +14 -0
- data/lib/generators/faqmarkdown/usage/install.txt +10 -0
- data/lib/generators/faqmarkdown/usage/override.txt +9 -0
- data/readme.md +191 -0
- data/spec/helpers/faq_helper_spec.rb +49 -0
- data/spec/integrations/faqs_spec.rb +209 -0
- data/spec/internal/.gitignore +2 -0
- data/spec/internal/app/faqs/2011-04-01-first-faq.markdown +5 -0
- data/spec/internal/app/faqs/2011-04-28-image.markdown +5 -0
- data/spec/internal/app/faqs/2011-04-28-summary.markdown +10 -0
- data/spec/internal/app/faqs/2011-05-01-full-metadata.markdown +20 -0
- data/spec/internal/app/faqs/2015-02-13-custom-title.markdown +5 -0
- data/spec/internal/app/views/layouts/application.html.erb +12 -0
- data/spec/internal/app/views/layouts/custom_layout.html.erb +14 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/config/environments/test.rb +9 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/combustion_test.sqlite +0 -0
- data/spec/internal/db/schema.rb +3 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/lib/generators/faqmarkdown/faq_generator_spec.rb +99 -0
- data/spec/models/faqs_spec.rb +103 -0
- data/spec/requests/assets_spec.rb +16 -0
- data/spec/requests/views_spec.rb +34 -0
- data/spec/routing/faqs_routing_spec.rb +80 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/data/faqs/2011-04-01-first-faq.markdown +3 -0
- data/spec/support/data/faqs/2011-04-28-image.markdown +9 -0
- data/spec/support/data/faqs/2011-04-28-summary.markdown +10 -0
- data/spec/support/data/faqs/2011-05-01-full-metadata.markdown +13 -0
- data/spec/support/data/faqs/2011-05-02-md-file-extension.md +1 -0
- data/spec/support/data/faqs/2011-05-02-mdown-file-extension.mdown +1 -0
- data/spec/support/data/faqs/2011-05-02-mkd-file-extension.mkd +1 -0
- data/spec/support/data/faqs/2012-02-13-102030-custom-title-and-timestamp.markdown +5 -0
- data/spec/support/data/faqs/2015-02-13-custom-title.markdown +5 -0
- data/spec/support/data/faqs/missing-date-from-filename.markdown +1 -0
- data/spec/support/rails_app/.gitignore +4 -0
- data/spec/support/rails_app/app/controllers/application_controller.rb +3 -0
- data/spec/support/rails_app/app/faqs/2011-04-01-first-faq.markdown +5 -0
- data/spec/support/rails_app/app/faqs/2011-04-28-image.markdown +5 -0
- data/spec/support/rails_app/app/faqs/2011-04-28-summary.markdown +10 -0
- data/spec/support/rails_app/app/faqs/2011-05-01-full-metadata.markdown +20 -0
- data/spec/support/rails_app/app/faqs/2015-02-13-custom-title.markdown +5 -0
- data/spec/support/rails_app/app/views/layouts/application.html.erb +12 -0
- data/spec/support/rails_app/app/views/layouts/custom_layout.html.erb +14 -0
- data/spec/support/rails_app/config/application.rb +42 -0
- data/spec/support/rails_app/config/boot.rb +10 -0
- data/spec/support/rails_app/config/database.yml +22 -0
- data/spec/support/rails_app/config/environment.rb +5 -0
- data/spec/support/rails_app/config/environments/test.rb +9 -0
- data/spec/support/rails_app/config/initializers/secret_token.rb +7 -0
- data/spec/support/rails_app/config/routes.rb +3 -0
- data/spec/support/rails_app/config.ru +4 -0
- data/spec/support/rails_app/db/seeds.rb +7 -0
- data/spec/support/rails_app/doc/README_FOR_APP +2 -0
- data/vendor/assets/stylesheets/faqmarkdown/faqmarkdown.css +69 -0
- metadata +354 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e97e7d37b6ca257059b481870e27fbaff846542f
|
4
|
+
data.tar.gz: b18e95c7f427c492b80d6e3722321c2a20c92dc3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 715e48611684b253eb7f7a2373a3581e8d7f566532ce33a9b6e8f792044b3b8ba791997167ffa79b3c7e0b9b67800d3419db01dbf2878f6b770bf4bbc84e317e
|
7
|
+
data.tar.gz: d368e527772a7fac12bd77fd065754db16b21468259cc5fe9d2db3277178a785b39fed624b488faefe4eb9cde77818a99f69feedc5cac3b1b88506b7dc1ecc84
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm --create 2.0.0@faqmarkdown
|
data/Appraisals
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
class FaqsController < ApplicationController
|
3
|
+
layout :choose_layout
|
4
|
+
|
5
|
+
def index
|
6
|
+
collection
|
7
|
+
respond_to { |format| format.html }
|
8
|
+
end
|
9
|
+
|
10
|
+
def show
|
11
|
+
resource
|
12
|
+
respond_to { |format| format.html }
|
13
|
+
end
|
14
|
+
|
15
|
+
def faq_per_category
|
16
|
+
collection
|
17
|
+
respond_to do |format|
|
18
|
+
format.html { render :index }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def feed
|
23
|
+
max_age = 4.hours
|
24
|
+
response.headers['Cache-Control'] = 'public, max-age=' + max_age.to_i.to_s
|
25
|
+
response.headers['Expires'] = max_age.from_now.httpdate
|
26
|
+
response.content_type = 'application/atom+xml'
|
27
|
+
fresh_when :last_modified => Faq.feed_last_modified
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def resource
|
33
|
+
@action = 'show'
|
34
|
+
@resource ||= Faq.find(params[:id])
|
35
|
+
end
|
36
|
+
# helper_method :resource
|
37
|
+
|
38
|
+
def collection
|
39
|
+
@action = 'index'
|
40
|
+
@collection ||= begin
|
41
|
+
faqs = if params.include?(:category)
|
42
|
+
Faq.find_by_category(params[:category])
|
43
|
+
else
|
44
|
+
Faq.where(params.slice(:year, :month, :day))
|
45
|
+
end
|
46
|
+
faqs = Kaminari.paginate_array(faqs).page(params[:page]).per(faqs_per_page)
|
47
|
+
faqs
|
48
|
+
end
|
49
|
+
end
|
50
|
+
# helper_method :collection
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def faqs_per_page
|
55
|
+
params[:count] || Faqmarkdown::Config.options[:faqs_per_page]
|
56
|
+
end
|
57
|
+
|
58
|
+
def choose_layout
|
59
|
+
if Faqmarkdown::Config.options[:use_theme]
|
60
|
+
ActiveSupport::Deprecation.warn "`Faqmarkdown::Config.options[:use_theme]` is deprecated. Use `Faqmarkdown::Config.options[:layout] = 'faqmarkdown'` instead."
|
61
|
+
'faqmarkdown'
|
62
|
+
else
|
63
|
+
Faqmarkdown::Config.options[:layout]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module FaqHelper
|
2
|
+
class Sanitizer < HTML::WhiteListSanitizer
|
3
|
+
self.allowed_tags.merge(%w(img a))
|
4
|
+
end
|
5
|
+
|
6
|
+
def faq_summary_html(faq)
|
7
|
+
if faq.summary.present?
|
8
|
+
content_tag :p, faq.summary
|
9
|
+
else
|
10
|
+
reg = /<!--more-->/
|
11
|
+
html_text = faq_content_html(faq)
|
12
|
+
|
13
|
+
html = !((html_text =~ reg).nil?) ? html_text[0..(html_text =~ reg)-1] : html_text
|
14
|
+
doc = Nokogiri::HTML.fragment(html)
|
15
|
+
doc = doc.search('p').detect { |p| p.text.present? } if (html_text =~ reg).nil?
|
16
|
+
doc.try(:to_html).try(:html_safe)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def faq_content_html(faq)
|
21
|
+
RDiscount.new(render(:inline => faq.content)).to_html.html_safe
|
22
|
+
end
|
23
|
+
end
|
data/app/models/faq.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'active_record/errors'
|
2
|
+
require 'stringex'
|
3
|
+
|
4
|
+
class Faq
|
5
|
+
extend ActiveModel::Naming
|
6
|
+
include ActiveModel::Conversion
|
7
|
+
|
8
|
+
include Gravtastic
|
9
|
+
is_gravtastic
|
10
|
+
|
11
|
+
attr_reader :slug
|
12
|
+
|
13
|
+
TIME_FORMAT = /-\d{6}/
|
14
|
+
DATE_FORMAT = /\d{4}-\d{2}-\d{2}(#{TIME_FORMAT})?/
|
15
|
+
SLUG_FORMAT = /[A-Za-z0-9_\-]+/
|
16
|
+
EXTENSION_FORMAT = /\.[^.]+/
|
17
|
+
|
18
|
+
FILENAME_FORMAT = /^(#{DATE_FORMAT})-(#{SLUG_FORMAT})(#{EXTENSION_FORMAT})$/
|
19
|
+
|
20
|
+
def initialize(path)
|
21
|
+
@path = path
|
22
|
+
@date_str, _, @slug = File.basename(path).match(FILENAME_FORMAT).captures
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_param
|
26
|
+
case permalink_format
|
27
|
+
when :day then "%04d/%02d/%02d/%s" % [year, month, day, slug]
|
28
|
+
when :month then "%04d/%02d/%s" % [year, month, slug]
|
29
|
+
when :year then "%04d/%s" % [year, slug]
|
30
|
+
when :slug then slug
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def permalink_format
|
35
|
+
Faqmarkdown::Config.options[:permalink_format]
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_key
|
39
|
+
[slug]
|
40
|
+
end
|
41
|
+
|
42
|
+
def metadata
|
43
|
+
load_content
|
44
|
+
@metadata
|
45
|
+
end
|
46
|
+
|
47
|
+
def content
|
48
|
+
load_content
|
49
|
+
@content
|
50
|
+
end
|
51
|
+
|
52
|
+
def title
|
53
|
+
metadata[:title] || slug.titleize
|
54
|
+
end
|
55
|
+
|
56
|
+
def summary
|
57
|
+
metadata[:summary]
|
58
|
+
end
|
59
|
+
|
60
|
+
def author
|
61
|
+
metadata[:author]
|
62
|
+
end
|
63
|
+
|
64
|
+
def email
|
65
|
+
metadata[:email]
|
66
|
+
end
|
67
|
+
|
68
|
+
def categories
|
69
|
+
metadata[:categories]
|
70
|
+
end
|
71
|
+
|
72
|
+
def categories_to_url
|
73
|
+
categories = []
|
74
|
+
self.categories.each {|x| categories << x.to_url}
|
75
|
+
categories
|
76
|
+
end
|
77
|
+
|
78
|
+
def date
|
79
|
+
@date ||= Time.zone.parse(metadata[:date] || @date_str).to_date
|
80
|
+
end
|
81
|
+
|
82
|
+
delegate :year, :month, :day, :to => :date
|
83
|
+
|
84
|
+
def timestamp
|
85
|
+
date.to_time_in_current_zone
|
86
|
+
end
|
87
|
+
alias_method :last_modified, :timestamp
|
88
|
+
|
89
|
+
def visible?
|
90
|
+
timestamp <= Time.zone.now
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_s
|
94
|
+
"#{title.inspect} (#{slug})"
|
95
|
+
end
|
96
|
+
|
97
|
+
class << self
|
98
|
+
def all
|
99
|
+
file_extensions = Faqmarkdown::Config.options[:markdown_file_extensions].join(',')
|
100
|
+
@@faqs ||= Dir.glob("#{directory}/*.{#{file_extensions}}").map do |filename|
|
101
|
+
Faq.new filename
|
102
|
+
end.select(&:visible?).sort_by(&:date).reverse
|
103
|
+
end
|
104
|
+
|
105
|
+
def find_by_category(category=nil)
|
106
|
+
faqs = []
|
107
|
+
all.select do |faq|
|
108
|
+
faqs << faq if !faq.categories.nil? and faq.categories_to_url.include?(category)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def categories_all
|
113
|
+
categories = []
|
114
|
+
all.select do |faq|
|
115
|
+
faq.categories.each {|x| categories << x} unless faq.categories.nil?
|
116
|
+
end
|
117
|
+
categories.uniq
|
118
|
+
end
|
119
|
+
|
120
|
+
def directory
|
121
|
+
Rails.root.join('app', 'faqs')
|
122
|
+
end
|
123
|
+
|
124
|
+
def where(conditions = {})
|
125
|
+
conditions = conditions.symbolize_keys
|
126
|
+
conditions.assert_valid_keys :year, :month, :day, :slug, :to_param
|
127
|
+
[:year, :month, :day].each do |key|
|
128
|
+
conditions[key] = conditions[key].to_i if conditions[key].present?
|
129
|
+
end
|
130
|
+
all.select do |faq|
|
131
|
+
conditions.all? { |key, value| faq.send(key) == value }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def find(id)
|
136
|
+
where(:to_param => id).first or raise ActiveRecord::RecordNotFound, "Could not find faq with ID #{id.inspect}"
|
137
|
+
end
|
138
|
+
|
139
|
+
def first
|
140
|
+
all.first
|
141
|
+
end
|
142
|
+
|
143
|
+
def last
|
144
|
+
all.last
|
145
|
+
end
|
146
|
+
|
147
|
+
def feed
|
148
|
+
all.first(10)
|
149
|
+
end
|
150
|
+
|
151
|
+
def feed_last_modified
|
152
|
+
feed.first.try(:last_modified) || Time.now.utc
|
153
|
+
end
|
154
|
+
|
155
|
+
def reset!
|
156
|
+
@@faqs = nil
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
protected
|
161
|
+
|
162
|
+
def load_content
|
163
|
+
@content = File.read(@path)
|
164
|
+
if @content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
165
|
+
@content = @content[($1.size + $2.size)..-1]
|
166
|
+
@metadata = YAML.load($1)
|
167
|
+
end
|
168
|
+
@metadata = (@metadata || {}).with_indifferent_access
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
= content_tag_for :article, faq do
|
2
|
+
%header
|
3
|
+
%h1= link_to faq.title, faq
|
4
|
+
= image_tag faq.gravatar_url(:size => 32, :default => 'identicon'), :height => 32, :width => 32
|
5
|
+
.meta
|
6
|
+
Posted on
|
7
|
+
%time{:pubdate => 'true', :datetime => faq.timestamp.iso8601}
|
8
|
+
= faq.date.strftime '%e %B %Y'
|
9
|
+
%span
|
10
|
+
by
|
11
|
+
= faq.author
|
12
|
+
- if summary
|
13
|
+
= faq_summary_html faq
|
14
|
+
%p.more= link_to 'Read more…'.html_safe, faq
|
15
|
+
- else
|
16
|
+
~ faq_content_html faq
|
@@ -0,0 +1,29 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.feed :xmlns => 'http://www.w3.org/2005/Atom' do
|
3
|
+
xml.title Faqmarkdown::Config.options[:feed_title]
|
4
|
+
xml.link :href => faqs_feed_url, :rel => :self, :type => 'application/atom+xml'
|
5
|
+
xml.link :href => faqs_url, :rel => :alternate, :type => 'text/html'
|
6
|
+
xml.id faqs_url
|
7
|
+
xml.updated Faq.feed_last_modified.xmlschema
|
8
|
+
|
9
|
+
Faq.feed.each do |faq|
|
10
|
+
xml.entry do
|
11
|
+
xml.title faq.title, :type => :text
|
12
|
+
xml.link :href => faq_url(faq), :rel => :alternate, :type => 'text/html'
|
13
|
+
xml.published faq.timestamp.xmlschema
|
14
|
+
xml.updated faq.last_modified.xmlschema
|
15
|
+
|
16
|
+
if faq.author.present?
|
17
|
+
xml.author do
|
18
|
+
xml.name faq.author
|
19
|
+
xml.email faq.email if faq.email.present?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
xml.id faq_url(faq)
|
24
|
+
xml.content :type => :html, 'xml:base' => faq_url(faq) do
|
25
|
+
xml.cdata! faq_content_html(faq)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title= Faqmarkdown::Util.app_name
|
5
|
+
= stylesheet_link_tag 'faqmarkdown/faqmarkdown'
|
6
|
+
= yield :head
|
7
|
+
%body
|
8
|
+
%header#header
|
9
|
+
%h1= link_to Faqmarkdown::Util.app_name, '/'
|
10
|
+
%p
|
11
|
+
A #{link_to 'faqmarkdown', 'https://github.com/rrmartins/faqmarkdown'} faq
|
12
|
+
- if Faq.last.try(:author)
|
13
|
+
= "by #{Faq.last.author}"
|
14
|
+
%section#content= yield
|
15
|
+
%footer
|
16
|
+
%small= "Copyright © #{Date.today.year}".html_safe
|
data/config.ru
ADDED
data/faqmarkdown.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'faqmarkdown/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'faqmarkdown'
|
7
|
+
s.version = Faqmarkdown::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ['Rodrigo Martins']
|
10
|
+
s.email = ['rodrigo@rrmartins.com']
|
11
|
+
s.licenses = ['MIT']
|
12
|
+
|
13
|
+
s.homepage = ''
|
14
|
+
s.summary = %q{A simple Rails FAQ engine powered by markdown.}
|
15
|
+
s.description = s.summary
|
16
|
+
|
17
|
+
s.rubyforge_project = 'faqmarkdown'
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
+
s.require_paths = ['lib', 'public']
|
23
|
+
|
24
|
+
s.add_dependency 'rails', '~> 3.0'
|
25
|
+
s.add_dependency 'haml', '~> 3.1'
|
26
|
+
s.add_dependency 'gravtastic'
|
27
|
+
s.add_dependency 'nokogiri'
|
28
|
+
s.add_dependency 'rdiscount'
|
29
|
+
s.add_dependency 'kaminari'
|
30
|
+
|
31
|
+
s.add_development_dependency 'appraisal'
|
32
|
+
s.add_development_dependency 'rspec-rails', '~> 2.8'
|
33
|
+
s.add_development_dependency 'capybara', '~> 1.0.0.beta'
|
34
|
+
s.add_development_dependency 'sqlite3'
|
35
|
+
s.add_development_dependency 'delorean', '>= 0.2'
|
36
|
+
s.add_development_dependency 'combustion', '~> 0.3.1'
|
37
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "stringex"
|
6
|
+
gem "pry", :require=>false
|
7
|
+
gem "fuubar", "~> 1.1", :require=>false
|
8
|
+
gem "timecop", :require=>false
|
9
|
+
gem "generator_spec", :require=>false
|
10
|
+
gem "debugger"
|
11
|
+
gem "rails", "~> 3.0.0"
|
12
|
+
|
13
|
+
gemspec :path=>"../"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "stringex"
|
6
|
+
gem "pry", :require=>false
|
7
|
+
gem "fuubar", "~> 1.1", :require=>false
|
8
|
+
gem "timecop", :require=>false
|
9
|
+
gem "generator_spec", :require=>false
|
10
|
+
gem "debugger"
|
11
|
+
gem "rails", "~> 3.1.0"
|
12
|
+
gem "combustion", "~> 0.3.1"
|
13
|
+
|
14
|
+
gemspec :path=>"../"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "stringex"
|
6
|
+
gem "pry", :require=>false
|
7
|
+
gem "fuubar", "~> 1.1", :require=>false
|
8
|
+
gem "timecop", :require=>false
|
9
|
+
gem "generator_spec", :require=>false
|
10
|
+
gem "debugger"
|
11
|
+
gem "rails", "~> 3.2.0"
|
12
|
+
gem "combustion", "~> 0.3.1"
|
13
|
+
|
14
|
+
gemspec :path=>"../"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Faqmarkdown
|
2
|
+
module Config
|
3
|
+
extend self
|
4
|
+
|
5
|
+
@options = {}
|
6
|
+
attr_accessor :options
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
Faqmarkdown::Config.options[:feed_title] = nil
|
11
|
+
|
12
|
+
Faqmarkdown::Config.options[:permalink_format] = :day
|
13
|
+
|
14
|
+
Faqmarkdown::Config.options[:faqs_per_page] = 5
|
15
|
+
|
16
|
+
Faqmarkdown::Config.options[:layout] = 'application'
|
17
|
+
|
18
|
+
Faqmarkdown::Config.options[:permalink_regex] = {}
|
19
|
+
Faqmarkdown::Config.options[:permalink_regex][:day] = %r[\d{4}/\d{2}/\d{2}/[^/]+]
|
20
|
+
Faqmarkdown::Config.options[:permalink_regex][:month] = %r[\d{4}/\d{2}/[^/]+]
|
21
|
+
Faqmarkdown::Config.options[:permalink_regex][:year] = %r[\d{4}/[^/]+]
|
22
|
+
Faqmarkdown::Config.options[:permalink_regex][:slug] = %r[[^/]+]
|
23
|
+
|
24
|
+
Faqmarkdown::Config.options[:markdown_file_extensions] = %w(md mkd mdown markdown)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Faqmarkdown
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer :before_initialize do
|
4
|
+
unless Rails.application.config.respond_to?(:assets) && Rails.application.config.assets.enabled
|
5
|
+
require 'rack'
|
6
|
+
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Rack::Static',
|
7
|
+
:urls => ['/stylesheets/faqmarkdown'],
|
8
|
+
:root => "#{faqmarkdown_root}/vendor/assets"
|
9
|
+
)
|
10
|
+
end
|
11
|
+
ActionController::Base.append_view_path("#{faqmarkdown_root}/app/views")
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def faqmarkdown_root
|
17
|
+
File.expand_path(File.dirname(__FILE__) + '/../..')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class ActionDispatch::Routing::Mapper
|
2
|
+
require 'faqmarkdown/util'
|
3
|
+
|
4
|
+
def faqmarkdown(options = {})
|
5
|
+
options.reverse_merge!({ :as => :faqs, :permalink_format => :day })
|
6
|
+
|
7
|
+
get "/#{options[:as]}(/:year(/:month(/:day)))" => 'faqs#index', as: :faqs, :constraints => { :year => /\d{4}/, :month => /\d{2}/, :day => /\d{2}/}
|
8
|
+
get "/#{options[:as]}/feed" => 'faqs#feed', as: :faqs_feed, :format => :xml
|
9
|
+
get "/#{options[:as]}/*id" => 'faqs#show', as: :faq, :constraints => { :id => faqmarkdown_permalink_regex(options) }
|
10
|
+
get "/#{options[:as]}/categoria/:category" => 'faqs#faq_per_category', as: :faqs_category
|
11
|
+
|
12
|
+
faqmarkdown_feed_title(options[:as])
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def faqmarkdown_permalink_regex(options)
|
18
|
+
Faqmarkdown::Config.options[:permalink_format] = options[:permalink_format]
|
19
|
+
Faqmarkdown::Config.options[:permalink_regex].try(:[], options[:permalink_format]) or raise_faqmarkdown_permalink_error
|
20
|
+
end
|
21
|
+
|
22
|
+
def faqmarkdown_feed_title(path)
|
23
|
+
Faqmarkdown::Config.options[:feed_title] ||= "#{Faqmarkdown::Util.app_name} #{path.to_s.tr('/', '_').humanize.titleize}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def raise_faqmarkdown_permalink_error
|
27
|
+
possible_options = Faqmarkdown::Config.options[:permalink_regex].map { |k,v| k.inspect }.join(', ')
|
28
|
+
raise "Faqmarkdown Routing Error: Invalid :permalink_format option #{Faqmarkdown::Config.options[:permalink_format].inspect} - must be one of the following: #{possible_options}"
|
29
|
+
end
|
30
|
+
end
|
data/lib/faqmarkdown.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Faqmarkdown
|
2
|
+
class FaqGenerator < Rails::Generators::Base
|
3
|
+
desc File.read(File.expand_path('../usage/faq.txt', __FILE__)).gsub('{{CURRENT_DATE}}', Time.zone.now.strftime('%Y-%m-%d'))
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
argument :slug, :type => :string, :required => true
|
6
|
+
class_option :date, :type => :string, :group => :runtime, :desc => 'Publish date for the faq'
|
7
|
+
|
8
|
+
def check_slug
|
9
|
+
unless slug =~ /^#{Faq::SLUG_FORMAT}$/
|
10
|
+
puts 'Invalid slug - valid characters include letters, digits and dashes.'
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def check_date
|
16
|
+
if options.date && options.date !~ /^#{Faq::DATE_FORMAT}$/
|
17
|
+
puts 'Invalid date - please use the following format: YYYY-MM-DD, eg. 2011-01-01.'
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate_faq
|
23
|
+
template 'example-faq.markdown', "app/faqs/#{publish_date}-#{slug.downcase}.markdown"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def publish_date
|
29
|
+
format = '%Y-%m-%d-%H%M%S'
|
30
|
+
|
31
|
+
if options.date.present?
|
32
|
+
date_string = options.date
|
33
|
+
date_string += '-000000' unless options.date.match(/(#{Faq::TIME_FORMAT}$)/)
|
34
|
+
date = Time.strptime(date_string, format)
|
35
|
+
else
|
36
|
+
date = Time.zone.now
|
37
|
+
end
|
38
|
+
|
39
|
+
date.strftime(format)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|