faqmarkdown 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/.rvmrc +1 -0
  5. data/Appraisals +13 -0
  6. data/Gemfile +10 -0
  7. data/Rakefile +11 -0
  8. data/app/controllers/application_controller.rb +2 -0
  9. data/app/controllers/faqs_controller.rb +66 -0
  10. data/app/helpers/faq_helper.rb +23 -0
  11. data/app/models/faq.rb +170 -0
  12. data/app/views/faqs/_faq.html.haml +16 -0
  13. data/app/views/faqs/_feed_link.html.haml +2 -0
  14. data/app/views/faqs/feed.xml.builder +29 -0
  15. data/app/views/faqs/index.html.haml +8 -0
  16. data/app/views/faqs/show.html.haml +3 -0
  17. data/app/views/layouts/faqmarkdown.html.haml +16 -0
  18. data/config.ru +8 -0
  19. data/faqmarkdown.gemspec +37 -0
  20. data/gemfiles/rails3_0.gemfile +13 -0
  21. data/gemfiles/rails3_1.gemfile +14 -0
  22. data/gemfiles/rails3_2.gemfile +14 -0
  23. data/lib/faqmarkdown/config.rb +24 -0
  24. data/lib/faqmarkdown/engine.rb +12 -0
  25. data/lib/faqmarkdown/railtie.rb +20 -0
  26. data/lib/faqmarkdown/routes.rb +30 -0
  27. data/lib/faqmarkdown/util.rb +12 -0
  28. data/lib/faqmarkdown/version.rb +3 -0
  29. data/lib/faqmarkdown.rb +5 -0
  30. data/lib/generators/faqmarkdown/faq_generator.rb +42 -0
  31. data/lib/generators/faqmarkdown/install_generator.rb +19 -0
  32. data/lib/generators/faqmarkdown/override_generator.rb +48 -0
  33. data/lib/generators/faqmarkdown/templates/example-faq.markdown +67 -0
  34. data/lib/generators/faqmarkdown/usage/faq.txt +14 -0
  35. data/lib/generators/faqmarkdown/usage/install.txt +10 -0
  36. data/lib/generators/faqmarkdown/usage/override.txt +9 -0
  37. data/readme.md +191 -0
  38. data/spec/helpers/faq_helper_spec.rb +49 -0
  39. data/spec/integrations/faqs_spec.rb +209 -0
  40. data/spec/internal/.gitignore +2 -0
  41. data/spec/internal/app/faqs/2011-04-01-first-faq.markdown +5 -0
  42. data/spec/internal/app/faqs/2011-04-28-image.markdown +5 -0
  43. data/spec/internal/app/faqs/2011-04-28-summary.markdown +10 -0
  44. data/spec/internal/app/faqs/2011-05-01-full-metadata.markdown +20 -0
  45. data/spec/internal/app/faqs/2015-02-13-custom-title.markdown +5 -0
  46. data/spec/internal/app/views/layouts/application.html.erb +12 -0
  47. data/spec/internal/app/views/layouts/custom_layout.html.erb +14 -0
  48. data/spec/internal/config/database.yml +3 -0
  49. data/spec/internal/config/environments/test.rb +9 -0
  50. data/spec/internal/config/routes.rb +3 -0
  51. data/spec/internal/db/combustion_test.sqlite +0 -0
  52. data/spec/internal/db/schema.rb +3 -0
  53. data/spec/internal/log/.gitignore +1 -0
  54. data/spec/internal/public/favicon.ico +0 -0
  55. data/spec/lib/generators/faqmarkdown/faq_generator_spec.rb +99 -0
  56. data/spec/models/faqs_spec.rb +103 -0
  57. data/spec/requests/assets_spec.rb +16 -0
  58. data/spec/requests/views_spec.rb +34 -0
  59. data/spec/routing/faqs_routing_spec.rb +80 -0
  60. data/spec/spec_helper.rb +38 -0
  61. data/spec/support/data/faqs/2011-04-01-first-faq.markdown +3 -0
  62. data/spec/support/data/faqs/2011-04-28-image.markdown +9 -0
  63. data/spec/support/data/faqs/2011-04-28-summary.markdown +10 -0
  64. data/spec/support/data/faqs/2011-05-01-full-metadata.markdown +13 -0
  65. data/spec/support/data/faqs/2011-05-02-md-file-extension.md +1 -0
  66. data/spec/support/data/faqs/2011-05-02-mdown-file-extension.mdown +1 -0
  67. data/spec/support/data/faqs/2011-05-02-mkd-file-extension.mkd +1 -0
  68. data/spec/support/data/faqs/2012-02-13-102030-custom-title-and-timestamp.markdown +5 -0
  69. data/spec/support/data/faqs/2015-02-13-custom-title.markdown +5 -0
  70. data/spec/support/data/faqs/missing-date-from-filename.markdown +1 -0
  71. data/spec/support/rails_app/.gitignore +4 -0
  72. data/spec/support/rails_app/app/controllers/application_controller.rb +3 -0
  73. data/spec/support/rails_app/app/faqs/2011-04-01-first-faq.markdown +5 -0
  74. data/spec/support/rails_app/app/faqs/2011-04-28-image.markdown +5 -0
  75. data/spec/support/rails_app/app/faqs/2011-04-28-summary.markdown +10 -0
  76. data/spec/support/rails_app/app/faqs/2011-05-01-full-metadata.markdown +20 -0
  77. data/spec/support/rails_app/app/faqs/2015-02-13-custom-title.markdown +5 -0
  78. data/spec/support/rails_app/app/views/layouts/application.html.erb +12 -0
  79. data/spec/support/rails_app/app/views/layouts/custom_layout.html.erb +14 -0
  80. data/spec/support/rails_app/config/application.rb +42 -0
  81. data/spec/support/rails_app/config/boot.rb +10 -0
  82. data/spec/support/rails_app/config/database.yml +22 -0
  83. data/spec/support/rails_app/config/environment.rb +5 -0
  84. data/spec/support/rails_app/config/environments/test.rb +9 -0
  85. data/spec/support/rails_app/config/initializers/secret_token.rb +7 -0
  86. data/spec/support/rails_app/config/routes.rb +3 -0
  87. data/spec/support/rails_app/config.ru +4 -0
  88. data/spec/support/rails_app/db/seeds.rb +7 -0
  89. data/spec/support/rails_app/doc/README_FOR_APP +2 -0
  90. data/vendor/assets/stylesheets/faqmarkdown/faqmarkdown.css +69 -0
  91. 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
@@ -0,0 +1,7 @@
1
+ .bundle
2
+ Gemfile.lock
3
+ gemfiles/*.gemfile.lock
4
+ db/*.sqlite3
5
+ log/*.log
6
+ tmp/
7
+ pkg/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format Fuubar
2
+ --colour
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create 2.0.0@faqmarkdown
data/Appraisals ADDED
@@ -0,0 +1,13 @@
1
+ appraise 'rails3_0' do
2
+ gem 'rails', '~> 3.0.0'
3
+ end
4
+
5
+ appraise 'rails3_1' do
6
+ gem 'rails', '~> 3.1.0'
7
+ gem 'combustion', '~> 0.3.1'
8
+ end
9
+
10
+ appraise 'rails3_2' do
11
+ gem 'rails', '~> 3.2.0'
12
+ gem 'combustion', '~> 0.3.1'
13
+ end
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
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'
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'appraisal'
3
+ require 'bundler/setup'
4
+ require 'bundler/gem_tasks'
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :default do
10
+ exec 'rake appraisal spec'
11
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -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&hellip;'.html_safe, faq
15
+ - else
16
+ ~ faq_content_html faq
@@ -0,0 +1,2 @@
1
+ - content_for :head do
2
+ %link{:href => faqs_feed_path, :type => 'application/atom+xml', :rel => :alternate, :title => Faqmarkdown::Config.options[:feed_title]}
@@ -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,8 @@
1
+ = render 'feed_link'
2
+
3
+ %section#faqs
4
+ - if @collection.present?
5
+ = render @collection, :summary => true
6
+ = paginate @collection
7
+ - else
8
+ No faqs found.
@@ -0,0 +1,3 @@
1
+ = render 'feed_link'
2
+
3
+ = render @resource, :summary => false
@@ -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 &copy; #{Date.today.year}".html_safe
data/config.ru ADDED
@@ -0,0 +1,8 @@
1
+ ENV['BUNDLE_GEMFILE'] = 'gemfiles/rails3_1.gemfile'
2
+ # require 'rubygems'
3
+ require 'bundler'
4
+
5
+ Bundler.require :default, :development
6
+
7
+ Combustion.initialize!
8
+ run Combustion::Application
@@ -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,12 @@
1
+ module Faqmarkdown
2
+ require 'faqmarkdown'
3
+ require 'rails'
4
+ require 'gravtastic'
5
+ require 'rdiscount'
6
+ require 'nokogiri'
7
+ require 'haml'
8
+ require 'kaminari'
9
+
10
+ class Engine < Rails::Engine
11
+ end
12
+ end
@@ -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
@@ -0,0 +1,12 @@
1
+ module Faqmarkdown
2
+ module Util
3
+ def self.app_name
4
+ Rails.application.class.name.split('::')[0..-2].join.titleize
5
+ end
6
+
7
+ def self.git_config(name)
8
+ value = `git config --get #{name}`.chomp
9
+ value if $?.success?
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Faqmarkdown
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'faqmarkdown/engine'
2
+ require 'faqmarkdown/config'
3
+ require 'faqmarkdown/routes'
4
+ require 'faqmarkdown/railtie'
5
+ require 'faqmarkdown/util'
@@ -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