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/links.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
RESOURCE_TYPE_REGEXP = /^([a-zA-Z][\-+\.a-zA-Z\d]*):/
|
2
|
+
|
3
|
+
# The #link_to methods support smart formatting of links in multiple formats.
|
4
|
+
format do
|
5
|
+
# Creates a "link", the meaning of which depends upon the format. In this base
|
6
|
+
# format, the link looks like [text][absolute path]
|
7
|
+
#
|
8
|
+
# @param text [String] optional string associated with link
|
9
|
+
# @param opts [Hash] optional Hash. In simple formats, :path is usually the only key
|
10
|
+
def link_to text=nil, opts={}
|
11
|
+
path = path((opts.delete(:path) || {}))
|
12
|
+
if text && path != text
|
13
|
+
"#{text}[#{path}]"
|
14
|
+
else
|
15
|
+
path
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# link to a different view of the current card
|
20
|
+
# @param view [Symbol,String]
|
21
|
+
# @param text [String]
|
22
|
+
# @param opts [Hash]
|
23
|
+
def link_to_view view, text=nil, opts={}
|
24
|
+
add_to_path opts, view: view unless view == :home
|
25
|
+
link_to text, opts
|
26
|
+
end
|
27
|
+
|
28
|
+
# link to a card other than the current card.
|
29
|
+
# @param cardish [Integer, Symbol, String, Card] a card identifier
|
30
|
+
# @param text [String]
|
31
|
+
# @param opts [Hash]
|
32
|
+
def link_to_card cardish, text=nil, opts={}
|
33
|
+
add_to_path opts, mark: Card::Name[cardish]
|
34
|
+
link_to text, opts
|
35
|
+
end
|
36
|
+
|
37
|
+
# a "resource" is essentially a reference to something that
|
38
|
+
# decko doesn't recognize to be a card. Can be a remote url,
|
39
|
+
# a local url (that decko hasn't parsed) or a local path.
|
40
|
+
# @param resource [String]
|
41
|
+
# @param text [String]
|
42
|
+
# @param opts [Hash]
|
43
|
+
def link_to_resource resource, text=nil, opts={}
|
44
|
+
resource = clean_resource resource, resource_type(resource)
|
45
|
+
link_to text, opts.merge(path: resource)
|
46
|
+
end
|
47
|
+
|
48
|
+
# smart_link_to is wrapper method for #link_to, #link_to_card, #link_to_view, and
|
49
|
+
# #link_to_resource. If the opts argument contains :view, :related, :card, or
|
50
|
+
# :resource, it will use the respective method to render a link.
|
51
|
+
#
|
52
|
+
# This is usually most useful when writing views that generate many different
|
53
|
+
# kinds of links.
|
54
|
+
def smart_link_to text, opts={}
|
55
|
+
if (linktype = %i[view card resource].find { |key| opts[key] })
|
56
|
+
send "link_to_#{linktype}", opts.delete(linktype), text, opts
|
57
|
+
else
|
58
|
+
send :link_to, text, opts
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def resource_type resource
|
65
|
+
case resource
|
66
|
+
when /^https?\:/ then "external-link"
|
67
|
+
when %r{^/} then "internal-link"
|
68
|
+
when /^mailto\:/ then "email-link"
|
69
|
+
when RESOURCE_TYPE_REGEXP then Regexp.last_match(1) + "-link"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def clean_resource resource, resource_type
|
74
|
+
if resource_type == "internal-link"
|
75
|
+
contextualize_path resource[1..-1]
|
76
|
+
else
|
77
|
+
resource
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_to_path opts, new_hash
|
82
|
+
opts[:path] = (opts[:path] || {}).merge new_hash
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
public
|
87
|
+
|
88
|
+
format :html do
|
89
|
+
# in HTML, #link_to renders an anchor tag <a>
|
90
|
+
# it treats opts other than "path" as html opts for that tag,
|
91
|
+
# and it adds special handling of "remote" and "method" opts
|
92
|
+
# (changes them into data attributes)
|
93
|
+
def link_to text=nil, opts={}
|
94
|
+
opts[:href] ||= path opts.delete(:path)
|
95
|
+
text = raw(text || opts[:href])
|
96
|
+
interpret_data_opts_to_link_to opts
|
97
|
+
wrap_with :a, text, opts
|
98
|
+
end
|
99
|
+
|
100
|
+
# in HTML, #link_to_card adds special css classes indicated whether a
|
101
|
+
# card is "known" (real or virtual) or "wanted" (unknown)
|
102
|
+
# TODO: upgrade from (known/wanted)-card to (real/virtual/unknown)-card
|
103
|
+
def link_to_card cardish, text=nil, opts={}
|
104
|
+
name = Card::Name[cardish]
|
105
|
+
slotterify opts if opts[:slotter]
|
106
|
+
add_known_or_wanted_class opts, name
|
107
|
+
super name, (text || name), opts
|
108
|
+
end
|
109
|
+
|
110
|
+
# in HTML, #link_to_view defaults to a remote link with rel="nofollow".
|
111
|
+
def link_to_view view, text=nil, opts={}
|
112
|
+
slotterify opts
|
113
|
+
super view, (text || view), opts
|
114
|
+
end
|
115
|
+
|
116
|
+
# in HTML, #link_to_resource automatically adds a target to external resources
|
117
|
+
# so they will open in another tab. It also adds css classes indicating whether
|
118
|
+
# the resource is internal or external
|
119
|
+
def link_to_resource resource, text=nil, opts={}
|
120
|
+
add_resource_opts opts, resource_type(resource)
|
121
|
+
super
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def slotterify opts
|
127
|
+
opts.delete(:slotter)
|
128
|
+
opts.reverse_merge! remote: true, rel: "nofollow"
|
129
|
+
add_class opts, "slotter"
|
130
|
+
end
|
131
|
+
|
132
|
+
def add_known_or_wanted_class opts, name
|
133
|
+
known = opts.delete :known
|
134
|
+
known = Card.known?(name) if known.nil?
|
135
|
+
add_class opts, (known ? "known-card" : "wanted-card")
|
136
|
+
end
|
137
|
+
|
138
|
+
def interpret_data_opts_to_link_to opts
|
139
|
+
%i[remote method].each do |key|
|
140
|
+
next unless (val = opts.delete key)
|
141
|
+
opts["data-#{key}"] = val
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def add_resource_opts opts, resource_type
|
146
|
+
opts[:target] ||= "_blank" if resource_type == "external-link"
|
147
|
+
add_class opts, resource_type
|
148
|
+
end
|
149
|
+
end
|
data/set/all/menu.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
format :html do
|
2
|
+
view :menu, denial: :blank, unknown: true do
|
3
|
+
return "" if card.unknown?
|
4
|
+
|
5
|
+
wrap_with :div, class: "card-menu #{menu_link_classes}" do
|
6
|
+
[render_help_link,
|
7
|
+
menu_link,
|
8
|
+
(voo.show?(:bridge_link) ? bridge_link(false) : nil)]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def menu_link
|
13
|
+
case voo.edit
|
14
|
+
when :inline
|
15
|
+
edit_inline_link
|
16
|
+
when :full
|
17
|
+
edit_in_bridge_link
|
18
|
+
else # :standard
|
19
|
+
edit_link
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def edit_view
|
24
|
+
case voo.edit
|
25
|
+
when :inline
|
26
|
+
:edit_inline
|
27
|
+
when :full
|
28
|
+
:edit
|
29
|
+
else # :standard
|
30
|
+
edit_link
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
view :edit_link, unknown: true, denial: :blank do
|
35
|
+
edit_link edit_link_view
|
36
|
+
end
|
37
|
+
|
38
|
+
def edit_link_view
|
39
|
+
:edit
|
40
|
+
end
|
41
|
+
|
42
|
+
view :full_page_link do
|
43
|
+
full_page_link
|
44
|
+
end
|
45
|
+
|
46
|
+
view :bridge_link, unknown: true do
|
47
|
+
bridge_link
|
48
|
+
end
|
49
|
+
|
50
|
+
def bridge_link in_modal=true
|
51
|
+
opts = { class: "bridge-link" }
|
52
|
+
if in_modal
|
53
|
+
# add_class opts, "close"
|
54
|
+
opts["data-slotter-mode"] = "modal-replace"
|
55
|
+
end
|
56
|
+
link_to_view :bridge, material_icon(:more_horiz), opts
|
57
|
+
end
|
58
|
+
|
59
|
+
# no caching because help_text view doesn't cache, and we can't have a
|
60
|
+
# stub in the data-content attribute or it will get html escaped.
|
61
|
+
view :help_link, cache: :never, unknown: true do
|
62
|
+
help_link render_help_text, help_title
|
63
|
+
end
|
64
|
+
|
65
|
+
def help_link text=nil, title=nil
|
66
|
+
opts = help_popover_opts text, title
|
67
|
+
add_class opts, "_card-menu-popover"
|
68
|
+
link_to help_icon, opts
|
69
|
+
end
|
70
|
+
|
71
|
+
def help_popover_opts text=nil, title=nil
|
72
|
+
text ||= render_help_text
|
73
|
+
opts = { "data-placement": :left, class: "help-link" }
|
74
|
+
popover_opts text, title, opts
|
75
|
+
end
|
76
|
+
|
77
|
+
def help_icon
|
78
|
+
material_icon("help")
|
79
|
+
end
|
80
|
+
|
81
|
+
def help_title
|
82
|
+
"#{name_parts_links} (#{render_type}) #{full_page_link unless card.simple?}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def name_parts_links
|
86
|
+
card.name.parts.map do |part|
|
87
|
+
link_to_card part
|
88
|
+
end.join Card::Name.joint
|
89
|
+
end
|
90
|
+
|
91
|
+
def full_page_link
|
92
|
+
link_to_card full_page_card, full_page_icon, class: classy("full-page-link")
|
93
|
+
end
|
94
|
+
|
95
|
+
def full_page_card
|
96
|
+
card
|
97
|
+
end
|
98
|
+
|
99
|
+
def edit_in_bridge_link opts={}
|
100
|
+
edit_link :bridge, opts
|
101
|
+
end
|
102
|
+
|
103
|
+
def edit_link view=:edit, opts={}
|
104
|
+
link_to_view view, opts.delete(:link_text) || menu_icon,
|
105
|
+
edit_link_opts(opts.reverse_merge(modal: :lg))
|
106
|
+
end
|
107
|
+
|
108
|
+
# @param modal [Symbol] modal size
|
109
|
+
def edit_link_opts modal: nil
|
110
|
+
opts = { class: classy("edit-link") }
|
111
|
+
if modal
|
112
|
+
opts[:"data-slotter-mode"] = "modal"
|
113
|
+
opts[:"data-modal-class"] = "modal-#{modal}"
|
114
|
+
end
|
115
|
+
opts
|
116
|
+
end
|
117
|
+
|
118
|
+
def menu_link_classes
|
119
|
+
"nodblclick" + (show_view?(:hover_link) ? " _show-on-hover" : "")
|
120
|
+
end
|
121
|
+
|
122
|
+
def menu_icon
|
123
|
+
material_icon "edit"
|
124
|
+
end
|
125
|
+
|
126
|
+
def full_page_icon
|
127
|
+
icon_tag :open_in_new
|
128
|
+
end
|
129
|
+
end
|
data/set/all/path.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
format do
|
2
|
+
# Decko uses the term "path" a bit unusually.
|
3
|
+
#
|
4
|
+
# In most formats, #path returns a full url. In HTML, it provides everything after
|
5
|
+
# the domain/port.
|
6
|
+
#
|
7
|
+
# If you're feeling saucy, you might point out that typically "paths" don't
|
8
|
+
# include queries and fragment identifiers, much less protocols, domains, and ports.
|
9
|
+
# 10 pedantry points to you! But "path" is easy to type and the method is smart about
|
10
|
+
# format needs, so using it will lead you down the right ... something or other.
|
11
|
+
|
12
|
+
# Format#path is for generating standard card routes, eg, assuming the card
|
13
|
+
# associated with the current format is named "current", it will generate paths like
|
14
|
+
# these:
|
15
|
+
|
16
|
+
# path view: :bar -> "current?view=bar"
|
17
|
+
# path mark: [mycardid] -> "mycardname"
|
18
|
+
# path format: :csv) -> "current.csv"
|
19
|
+
# path action: :update -> "update/current"
|
20
|
+
|
21
|
+
# #path produces paths that follow one of three main patterns:
|
22
|
+
|
23
|
+
# 1. mark[.format][?query] # standard GET request
|
24
|
+
# 2. action/mark[?query] # GET variant of standard actions
|
25
|
+
# 3. new/mark # shortcut for "new" view of cardtype
|
26
|
+
|
27
|
+
# @param opts [Hash, String] a String is treated as a complete path and
|
28
|
+
# bypasses all processing
|
29
|
+
# @option opts [String, Card::Name, Integer, Symbol, Card] :mark
|
30
|
+
# @option opts [Symbol] :action card action (:create, :update, :delete)
|
31
|
+
# @option opts [Symbol] :format
|
32
|
+
# @option opts [Hash] :card
|
33
|
+
# @option opts [TrueClass] :no_mark
|
34
|
+
|
35
|
+
def path opts={}
|
36
|
+
return opts unless opts.is_a? Hash
|
37
|
+
path = Card::Path.new(card, opts)&.render
|
38
|
+
contextualize_path path
|
39
|
+
end
|
40
|
+
|
41
|
+
# in base format (and therefore most other formats), even internal paths
|
42
|
+
# are rendered as absolute urls.
|
43
|
+
def contextualize_path relative_path
|
44
|
+
card_url relative_path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
format :json do
|
49
|
+
def add_unknown_name_to_opts name, opts
|
50
|
+
# noop
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
format :css do
|
55
|
+
def contextualize_path relative_path
|
56
|
+
if Card.config.file_storage == :local
|
57
|
+
# absolute paths lead to invalid assets path in css for cukes
|
58
|
+
card_path relative_path
|
59
|
+
else
|
60
|
+
# ...but relative paths are problematic when machine output and
|
61
|
+
# hard-coded assets (like fonts) are on different servers
|
62
|
+
card_url relative_path
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
format :html do
|
68
|
+
# in HTML, decko paths rendered as relative to the site's root.
|
69
|
+
def contextualize_path relative_path
|
70
|
+
card_path relative_path
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
format :email_html do
|
75
|
+
def contextualize_path relative_path
|
76
|
+
card_url relative_path
|
77
|
+
end
|
78
|
+
end
|
data/set/all/rss.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
format :rss do
|
2
|
+
attr_accessor :xml
|
3
|
+
|
4
|
+
def initialize card, args
|
5
|
+
super
|
6
|
+
@xml = @parent ? @parent.xml : ::Builder::XmlMarkup.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def show view, args
|
10
|
+
view ||= :feed
|
11
|
+
render! view, args
|
12
|
+
end
|
13
|
+
|
14
|
+
# FIXME: integrate this with common XML features when it is added
|
15
|
+
view :feed, cache: :never do
|
16
|
+
return "RSS feeds disabled" unless Cardio.config.rss_enabled
|
17
|
+
begin
|
18
|
+
@xml.instruct! :xml, version: "1.0", standalone: "yes"
|
19
|
+
@xml.rss version: "2.0",
|
20
|
+
"xmlns:content" => "http://purl.org/rss/1.0/modules/content/" do
|
21
|
+
@xml.channel do
|
22
|
+
@xml.title render_feed_title
|
23
|
+
@xml.description render_feed_description
|
24
|
+
@xml.link render_url
|
25
|
+
render_feed_body
|
26
|
+
end
|
27
|
+
end
|
28
|
+
rescue => e
|
29
|
+
@xml.error "\n\nERROR rendering RSS: #{e.inspect}\n\n #{e.backtrace}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def raw_feed_items
|
34
|
+
[card]
|
35
|
+
end
|
36
|
+
|
37
|
+
view :feed_body, cache: :never do
|
38
|
+
raw_feed_items.each do |item|
|
39
|
+
@xml.item do
|
40
|
+
subformat(item).render! :feed_item
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
view :feed_title do
|
46
|
+
Card::Rule.global_setting(:title) + " : " + card.name.gsub(/^\*/, "")
|
47
|
+
end
|
48
|
+
|
49
|
+
view :feed_item do
|
50
|
+
@xml.title card.name
|
51
|
+
add_name_context
|
52
|
+
@xml.description render_feed_item_description
|
53
|
+
@xml.pubDate pub_date
|
54
|
+
@xml.link render_url
|
55
|
+
@xml.guid render_url
|
56
|
+
end
|
57
|
+
|
58
|
+
def pub_date
|
59
|
+
(card.updated_at || Time.zone.now).to_s(:rfc822)
|
60
|
+
# updated_at fails on virtual
|
61
|
+
# cards, because not all to_s's take args (just actual dates)
|
62
|
+
end
|
63
|
+
|
64
|
+
view :feed_item_description do
|
65
|
+
render_open_content
|
66
|
+
end
|
67
|
+
|
68
|
+
view(:feed_description) { "" }
|
69
|
+
view(:comment_box) { "" }
|
70
|
+
view(:menu) { "" }
|
71
|
+
|
72
|
+
view :open, :titled, mod: All::Base::Format
|
73
|
+
view :content, :core, mod: All::Base::Format
|
74
|
+
view :open_content, :core, mod: All::Base::Format
|
75
|
+
view :closed, :link, mod: All::Base::Format
|
76
|
+
end
|