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