faqmarkdown 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.
- 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
|