card-mod-format 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/card/format/css_format.rb +17 -0
- data/lib/card/format/csv_format.rb +19 -0
- data/lib/card/format/data_format.rb +6 -0
- data/lib/card/format/file_format.rb +8 -0
- data/lib/card/format/html_format.rb +45 -0
- data/lib/card/format/js_format.rb +17 -0
- data/lib/card/format/json_format.rb +24 -0
- data/lib/card/format/rss_format.rb +9 -0
- data/lib/card/format/text_format.rb +16 -0
- data/lib/card/format/xml_format.rb +13 -0
- data/lib/card/path.rb +127 -0
- data/set/all/active_card.rb +6 -0
- data/set/all/base.rb +137 -0
- data/set/all/css.rb +37 -0
- data/set/all/csv.rb +93 -0
- data/set/all/error.rb +79 -0
- data/set/all/export.rb +68 -0
- data/set/all/file.rb +9 -0
- data/set/all/frame.rb +53 -0
- data/set/all/haml.rb +75 -0
- data/set/all/head.rb +148 -0
- data/set/all/header.rb +62 -0
- data/set/all/header/header_wrap.haml +4 -0
- data/set/all/html_content.rb +168 -0
- data/set/all/html_content/labeled.haml +4 -0
- data/set/all/html_error.rb +193 -0
- data/set/all/html_error/debug_server_error.haml +1015 -0
- data/set/all/html_error/not_found.haml +7 -0
- data/set/all/html_error/server_error.haml +5 -0
- data/set/all/html_show.rb +53 -0
- data/set/all/html_title.rb +47 -0
- data/set/all/html_wrapper.rb +159 -0
- data/set/all/js.rb +10 -0
- data/set/all/json.rb +166 -0
- data/set/all/links.rb +149 -0
- data/set/all/menu.rb +129 -0
- data/set/all/meta_tags.haml +4 -0
- data/set/all/path.rb +78 -0
- data/set/all/rich_html.rb +4 -0
- data/set/all/rss.rb +76 -0
- data/set/all/text.rb +7 -0
- data/set/self/home.rb +9 -0
- data/set/type/html.rb +27 -0
- data/set/type/json.rb +41 -0
- data/set/type/number.rb +22 -0
- data/set/type/phrase.rb +5 -0
- data/set/type/plain_text.rb +9 -0
- data/set/type/toggle.rb +38 -0
- data/set/type/uri.rb +15 -0
- metadata +123 -0
data/set/all/css.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
format :css do
|
3
|
+
def default_nest_view
|
4
|
+
:raw
|
5
|
+
end
|
6
|
+
|
7
|
+
def show view, args
|
8
|
+
view ||= :content
|
9
|
+
render! view, args
|
10
|
+
end
|
11
|
+
|
12
|
+
view :titled do
|
13
|
+
major_comment(%( Style Card: \\"#{card.name}\\" )) + _render_core
|
14
|
+
end
|
15
|
+
|
16
|
+
view :content do
|
17
|
+
_render_core
|
18
|
+
end
|
19
|
+
|
20
|
+
view :unknown do
|
21
|
+
major_comment "MISSING Style Card: #{card.name}"
|
22
|
+
end
|
23
|
+
|
24
|
+
view :import do
|
25
|
+
_render_core
|
26
|
+
end
|
27
|
+
|
28
|
+
view :url, perms: :none do
|
29
|
+
path mark: card.name, format: :css
|
30
|
+
end
|
31
|
+
|
32
|
+
def major_comment comment, char="-"
|
33
|
+
edge = %(/* #{char * (comment.length + 4)} */)
|
34
|
+
main = %(/* #{char} #{comment} #{char} */)
|
35
|
+
"#{edge}\n#{main}\n#{edge}\n\n"
|
36
|
+
end
|
37
|
+
end
|
data/set/all/csv.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require "csv"
|
2
|
+
|
3
|
+
format :csv do
|
4
|
+
def default_nest_view
|
5
|
+
:core
|
6
|
+
end
|
7
|
+
|
8
|
+
def default_item_view
|
9
|
+
depth.zero? ? :csv_row : :name
|
10
|
+
end
|
11
|
+
|
12
|
+
view :core do
|
13
|
+
if (item_view_options[:view] == :name_with_fields) && focal?
|
14
|
+
title_row("item name") + name_with_field_rows
|
15
|
+
else
|
16
|
+
super()
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
view :csv_row do
|
21
|
+
array = _render_raw.scan(/\{\{[^\}]*\}\}/).map do |inc|
|
22
|
+
process_content(inc).strip
|
23
|
+
end
|
24
|
+
|
25
|
+
CSV.generate_line(array).strip
|
26
|
+
# strip is because search already joins with newlines
|
27
|
+
end
|
28
|
+
|
29
|
+
view :unknown do
|
30
|
+
""
|
31
|
+
end
|
32
|
+
|
33
|
+
view :name_with_fields do
|
34
|
+
CSV.generate_line name_with_fields_row
|
35
|
+
end
|
36
|
+
|
37
|
+
def name_with_fields_row
|
38
|
+
nested_field_names.each_with_object([card.name]) do |field_name, row|
|
39
|
+
row << nest(field_name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def name_with_field_rows
|
44
|
+
return [] unless row_card_names.present?
|
45
|
+
|
46
|
+
row_card_names.map do |item_name|
|
47
|
+
CSV.generate_line row_from_field_names(item_name, columns)
|
48
|
+
end.join
|
49
|
+
end
|
50
|
+
|
51
|
+
def row_card_names
|
52
|
+
@row_cards ||= card.item_names
|
53
|
+
end
|
54
|
+
|
55
|
+
def columns
|
56
|
+
csv_structure_card.format.nested_field_names.map(&:tag)
|
57
|
+
end
|
58
|
+
|
59
|
+
def csv_structure_card
|
60
|
+
card.rule_card(:csv_structure) || Card.fetch(row_card_names.first)
|
61
|
+
end
|
62
|
+
|
63
|
+
def row_from_field_names parent_name, field_names, view=:core
|
64
|
+
field_names.each_with_object([parent_name]) do |field, row|
|
65
|
+
row << nest([parent_name, field], view: view)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def title_row extra_titles=nil
|
70
|
+
titles = column_titles extra_titles
|
71
|
+
return "" unless titles.present?
|
72
|
+
CSV.generate_line titles.map(&:upcase)
|
73
|
+
end
|
74
|
+
|
75
|
+
def column_titles extra_titles=nil
|
76
|
+
res = Array extra_titles
|
77
|
+
card1 = Card.fetch card.item_names(limit: 1).first
|
78
|
+
card1.nest_chunks.each do |chunk|
|
79
|
+
res << column_title(chunk.options)
|
80
|
+
end
|
81
|
+
res.compact
|
82
|
+
end
|
83
|
+
|
84
|
+
def column_title opts
|
85
|
+
if opts[:title]
|
86
|
+
opts[:title]
|
87
|
+
elsif %w[name link].member? opts[:view]
|
88
|
+
opts[:view]
|
89
|
+
else
|
90
|
+
opts[:nest_name].to_name.tag
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/set/all/error.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
format do
|
2
|
+
view :compact_missing, perms: :none, compact: true do
|
3
|
+
""
|
4
|
+
end
|
5
|
+
|
6
|
+
view :unknown, perms: :none, cache: :never do
|
7
|
+
""
|
8
|
+
end
|
9
|
+
|
10
|
+
view :server_error, perms: :none do
|
11
|
+
tr(:server_error)
|
12
|
+
end
|
13
|
+
|
14
|
+
view :denial, perms: :none do
|
15
|
+
focal? ? tr(:denial) : ""
|
16
|
+
end
|
17
|
+
|
18
|
+
view :not_found, perms: :none do
|
19
|
+
error_name = card.name.present? ? safe_name : tr(:not_found_no_name)
|
20
|
+
tr(:not_found_named, cardname: error_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
view :bad_address, perms: :none do
|
24
|
+
root.error_status = 404
|
25
|
+
tr(:bad_address)
|
26
|
+
end
|
27
|
+
|
28
|
+
view :errors do
|
29
|
+
["Problem:", "", error_messages].flatten.join "\n"
|
30
|
+
end
|
31
|
+
|
32
|
+
def error_messages
|
33
|
+
card.errors.map do |error|
|
34
|
+
if error.attribute == :abort
|
35
|
+
simple_error_message error.message
|
36
|
+
else
|
37
|
+
standard_error_message error
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# for override
|
43
|
+
def simple_error_message message
|
44
|
+
message
|
45
|
+
end
|
46
|
+
|
47
|
+
# for override
|
48
|
+
def standard_error_message error
|
49
|
+
"#{error.attribute.to_s.upcase}: #{error.message}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def unsupported_view_error_message view
|
53
|
+
tr(:unsupported_view, view: view, cardname: card.name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
format :json do
|
58
|
+
view :errors do
|
59
|
+
format_error error_list
|
60
|
+
end
|
61
|
+
|
62
|
+
view :server_error, :errors
|
63
|
+
view :denial, :errors
|
64
|
+
view :not_found, :errors
|
65
|
+
|
66
|
+
view :bad_address do
|
67
|
+
format_error super()
|
68
|
+
end
|
69
|
+
|
70
|
+
def format_error error
|
71
|
+
{ error_status: error_status, errors: error }
|
72
|
+
end
|
73
|
+
|
74
|
+
def error_list
|
75
|
+
card.errors.each_with_object([]) do |(field, message), list|
|
76
|
+
list << { field: field, message: message }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/set/all/export.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
format :json do
|
2
|
+
# returns an array of Hashes (each in export_item view)
|
3
|
+
view :export, cache: :never do
|
4
|
+
exporting_uniques do
|
5
|
+
Array.wrap(render_export_item).concat(export_items_in_view(:export)).flatten
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def max_export_depth
|
10
|
+
Env.params[:max_export_depth].present? ? Env.params[:max_export_depth].to_i : 2
|
11
|
+
end
|
12
|
+
|
13
|
+
# returns an array of Hashes (each in export_item view)
|
14
|
+
view :export_items, cache: :never do
|
15
|
+
exporting_uniques do
|
16
|
+
export_items_in_view(:export).flatten
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# returns Hash with the essentials needed to import a card into a new database
|
21
|
+
view :export_item do
|
22
|
+
item = { name: card.name, type: card.type_name, content: card.content }
|
23
|
+
item[:codename] = card.codename if card.codename
|
24
|
+
track_exporting card
|
25
|
+
item
|
26
|
+
end
|
27
|
+
|
28
|
+
def export_items_in_view view
|
29
|
+
within_max_depth do
|
30
|
+
valid_items_for_export.map do |item|
|
31
|
+
nest item, view: view
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def track_exporting card
|
37
|
+
return unless @exported_keys
|
38
|
+
@exported_keys << card.key
|
39
|
+
end
|
40
|
+
|
41
|
+
def exporting_uniques
|
42
|
+
@exported_keys ||= inherit(:exported_keys) || ::Set.new
|
43
|
+
yield
|
44
|
+
end
|
45
|
+
|
46
|
+
# prevent recursion
|
47
|
+
def within_max_depth
|
48
|
+
@export_depth ||= inherit(:export_depth).to_i + 1
|
49
|
+
@export_depth > max_export_depth ? [] : yield
|
50
|
+
end
|
51
|
+
|
52
|
+
def items_for_export
|
53
|
+
nest_chunks.map do |chunk|
|
54
|
+
next if chunk.try :main?
|
55
|
+
chunk.referee_card
|
56
|
+
end.compact
|
57
|
+
end
|
58
|
+
|
59
|
+
def valid_items_for_export
|
60
|
+
items_for_export.flatten.reject(&:blank?).uniq.find_all do |card|
|
61
|
+
valid_export_card? card
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def valid_export_card? ecard
|
66
|
+
ecard.real? && !@exported_keys.include?(ecard.key)
|
67
|
+
end
|
68
|
+
end
|
data/set/all/file.rb
ADDED
data/set/all/frame.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
format :html do
|
2
|
+
view :flash, cache: :never, unknown: true, perms: :none do
|
3
|
+
flash_notice = params[:flash] || Env.success.flash
|
4
|
+
return "" unless flash_notice.present? && focal?
|
5
|
+
|
6
|
+
Array(flash_notice).join "\n"
|
7
|
+
end
|
8
|
+
|
9
|
+
def frame &block
|
10
|
+
standard_frame(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def standard_frame slot=true
|
14
|
+
with_frame slot do
|
15
|
+
wrap_body { yield } if block_given?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def with_frame slot=true, header=frame_header, slot_opts={}
|
20
|
+
voo.hide :help
|
21
|
+
add_name_context
|
22
|
+
wrap slot, slot_opts do
|
23
|
+
panel do
|
24
|
+
[header, frame_help, render_flash, (yield if block_given?)]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def frame_header
|
30
|
+
_render_header
|
31
|
+
end
|
32
|
+
|
33
|
+
def frame_help
|
34
|
+
with_class_up "help-text", "alert alert-info" do
|
35
|
+
_render :help
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def frame_and_form action, form_opts={}
|
40
|
+
form_opts ||= {}
|
41
|
+
frame do
|
42
|
+
card_form action, form_opts do
|
43
|
+
yield
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def panel
|
49
|
+
wrap_with :div, class: classy("d0-card-frame") do
|
50
|
+
yield
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/set/all/haml.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
format do
|
2
|
+
include Card::Set::Format::HamlPaths
|
3
|
+
|
4
|
+
define_method :the_scope do
|
5
|
+
set_scope
|
6
|
+
end
|
7
|
+
|
8
|
+
define_method :haml_scope do
|
9
|
+
set_scope
|
10
|
+
end
|
11
|
+
|
12
|
+
# Renders haml templates. The haml template can be passed as string or
|
13
|
+
# block or a symbol that refers to a view template.
|
14
|
+
# @param args [Hash, String, Symbol]
|
15
|
+
# If a symbol is given then a template is expected in the corresponding view
|
16
|
+
# directory.
|
17
|
+
# @return [String] rendered haml as HTML
|
18
|
+
# @example render a view template
|
19
|
+
# # view/type/basic/my_template.haml:
|
20
|
+
# %p
|
21
|
+
# Hi
|
22
|
+
# = name
|
23
|
+
#
|
24
|
+
# # set/type/basic.rb:
|
25
|
+
# view :my_view do
|
26
|
+
# haml :my_template, name: "Joe: # => "<p>Hi Joe<p/>"
|
27
|
+
# end
|
28
|
+
# @example use a block to pass haml
|
29
|
+
# haml name: "Joe" do
|
30
|
+
# <<-HAML.strip_heredoc
|
31
|
+
# %p
|
32
|
+
# Hi
|
33
|
+
# = name
|
34
|
+
# HAML
|
35
|
+
# # => <p>Hi Joe</p>
|
36
|
+
# @example create a slot in haml code
|
37
|
+
# - haml_wrap do
|
38
|
+
# %p
|
39
|
+
# some haml
|
40
|
+
|
41
|
+
def haml *args, &block
|
42
|
+
if args.first.is_a? Symbol
|
43
|
+
process_haml_template(*args)
|
44
|
+
else
|
45
|
+
process_haml(*args, &block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def haml_partial partial, locals={}
|
50
|
+
locals[:template_path] ||= @template_path
|
51
|
+
process_haml_template "_#{partial}".to_sym, locals
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def process_haml *args
|
57
|
+
args.unshift yield if block_given?
|
58
|
+
haml_to_html(*args)
|
59
|
+
end
|
60
|
+
|
61
|
+
def process_haml_template template_name, *args
|
62
|
+
locals = args.first || {}
|
63
|
+
path = identify_template_path template_name, locals
|
64
|
+
with_template_path path do
|
65
|
+
haml_to_html ::File.read(path), *args
|
66
|
+
end
|
67
|
+
# rescue => e
|
68
|
+
# raise Card::Error, "HAML error #{template_name}: #{e.message}\n#{e.backtrace}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def identify_template_path view, locals={}
|
72
|
+
base_path = locals.delete(:template_path) || caller_locations[2].path
|
73
|
+
haml_template_path view, base_path
|
74
|
+
end
|
75
|
+
end
|
data/set/all/head.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
format do
|
2
|
+
view :page_title, unknown: true, perms: :none do
|
3
|
+
title_parts = [Card::Rule.global_setting(:title)]
|
4
|
+
title_parts.unshift safe_name if card.name.present?
|
5
|
+
title_parts.join " - "
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
format :html do
|
10
|
+
# add tuples containing a
|
11
|
+
# - the codename of a card with javascript config (usually in json format)
|
12
|
+
# - the name of a javascript method that handles the config
|
13
|
+
basket :mod_js_config
|
14
|
+
|
15
|
+
view :head, unknown: true, perms: :none do
|
16
|
+
views_in_head.map { |viewname| render viewname }.flatten.compact.join "\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
def views_in_head
|
20
|
+
%i[meta_tags page_title_tag favicon_tag head_stylesheet
|
21
|
+
decko_script_variables head_javascript html5shiv_tag
|
22
|
+
script_config_and_initiation
|
23
|
+
universal_edit_button rss_links]
|
24
|
+
end
|
25
|
+
|
26
|
+
# FIXME: tags not working with `template: :haml`
|
27
|
+
view :meta_tags, unknown: true, perms: :none do
|
28
|
+
haml :meta_tags
|
29
|
+
end
|
30
|
+
|
31
|
+
view :html5shiv_tag, unknown: true, perms: :none do
|
32
|
+
nest :script_html5shiv_printshiv, view: :script_tag
|
33
|
+
end
|
34
|
+
|
35
|
+
view :page_title_tag, unknown: true, perms: :none do
|
36
|
+
content_tag(:title) { render :page_title }
|
37
|
+
end
|
38
|
+
|
39
|
+
view :favicon_tag, unknown: true, perms: :none do
|
40
|
+
nest :favicon, view: :link_tag
|
41
|
+
end
|
42
|
+
|
43
|
+
view :universal_edit_button, unknown: true, denial: :blank, perms: :update do
|
44
|
+
return if card.new?
|
45
|
+
tag "link", rel: "alternate", type: "application/x-wiki",
|
46
|
+
title: "Edit this page!", href: path(view: :edit)
|
47
|
+
end
|
48
|
+
|
49
|
+
# these should render a view of the rule card
|
50
|
+
# it would then be safe to cache if combined with param handling
|
51
|
+
# (but note that machine clearing would need to reset card cache...)
|
52
|
+
view :head_stylesheet, unknown: true, cache: :never, perms: :none do
|
53
|
+
return unless (href = head_stylesheet_path)
|
54
|
+
tag "link", href: href, media: "all", rel: "stylesheet", type: "text/css"
|
55
|
+
end
|
56
|
+
|
57
|
+
view :head_javascript, unknown: true, cache: :never, perms: :none do
|
58
|
+
Array.wrap(head_javascript_paths).map do |path|
|
59
|
+
javascript_include_tag path
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
view :decko_script_variables, unknown: true, cache: :never, perms: :none do
|
64
|
+
string = ""
|
65
|
+
decko_script_variables.each do |k, v|
|
66
|
+
string += "#{k}=#{script_variable_to_js v};\n"
|
67
|
+
end
|
68
|
+
javascript_tag { string }
|
69
|
+
end
|
70
|
+
|
71
|
+
def decko_script_variables
|
72
|
+
{
|
73
|
+
"window.decko": { rootUrl: card_url("") },
|
74
|
+
"decko.doubleClick": Card.config.double_click,
|
75
|
+
"decko.cssPath": head_stylesheet_path,
|
76
|
+
"decko.currentUserId": (Auth.current_id if Auth.signed_in?)
|
77
|
+
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def script_variable_to_js value
|
82
|
+
if value.is_a? Hash
|
83
|
+
string = "{"
|
84
|
+
value.each { |k, v| string += "#{k}:#{script_variable_to_js v}" }
|
85
|
+
string + "}"
|
86
|
+
else
|
87
|
+
"'#{value}'"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def param_or_rule_card setting
|
92
|
+
if params[setting]
|
93
|
+
Card[params[setting]]
|
94
|
+
else
|
95
|
+
root.card.rule_card setting
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def debug_or_machine_path setting, &block
|
100
|
+
return unless (asset_card = param_or_rule_card setting)
|
101
|
+
debug_path(setting, asset_card, &block) || asset_card.machine_output_url
|
102
|
+
end
|
103
|
+
|
104
|
+
def debug_path setting, asset_card
|
105
|
+
return unless params[:debug] == setting.to_s
|
106
|
+
yield asset_card
|
107
|
+
end
|
108
|
+
|
109
|
+
def head_stylesheet_path
|
110
|
+
debug_or_machine_path :style do |style_card|
|
111
|
+
path mark: style_card.name, item: :import, format: :css
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def head_javascript_paths
|
116
|
+
debug_or_machine_path :script do |script_card|
|
117
|
+
script_card.item_cards.map do |script|
|
118
|
+
script.format(:js).render :source
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
view :script_config_and_initiation, unknown: true, perms: :none do
|
124
|
+
javascript_tag do
|
125
|
+
(mod_js_configs << trigger_slot_ready).join "\n\n"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def mod_js_configs
|
130
|
+
mod_js_config.map do |codename, js_decko_function|
|
131
|
+
config_json = escape_javascript Card::Rule.global_setting(codename)
|
132
|
+
"decko.#{js_decko_function}('#{config_json}')"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def trigger_slot_ready
|
137
|
+
"$('document').ready(function() { $('.card-slot').trigger('slotReady'); })"
|
138
|
+
end
|
139
|
+
|
140
|
+
# TODO: move to rss mod
|
141
|
+
view :rss_links, unknown: true, perms: :none do
|
142
|
+
render :rss_link_tag if rss_link?
|
143
|
+
end
|
144
|
+
|
145
|
+
def rss_link?
|
146
|
+
Card.config.rss_enabled && respond_to?(:rss_link_tag)
|
147
|
+
end
|
148
|
+
end
|