card-mod-format 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/lib/card/format/css_format.rb +17 -0
  3. data/lib/card/format/csv_format.rb +19 -0
  4. data/lib/card/format/data_format.rb +6 -0
  5. data/lib/card/format/file_format.rb +8 -0
  6. data/lib/card/format/html_format.rb +45 -0
  7. data/lib/card/format/js_format.rb +17 -0
  8. data/lib/card/format/json_format.rb +24 -0
  9. data/lib/card/format/rss_format.rb +9 -0
  10. data/lib/card/format/text_format.rb +16 -0
  11. data/lib/card/format/xml_format.rb +13 -0
  12. data/lib/card/path.rb +127 -0
  13. data/set/all/active_card.rb +6 -0
  14. data/set/all/base.rb +137 -0
  15. data/set/all/css.rb +37 -0
  16. data/set/all/csv.rb +93 -0
  17. data/set/all/error.rb +79 -0
  18. data/set/all/export.rb +68 -0
  19. data/set/all/file.rb +9 -0
  20. data/set/all/frame.rb +53 -0
  21. data/set/all/haml.rb +75 -0
  22. data/set/all/head.rb +148 -0
  23. data/set/all/header.rb +62 -0
  24. data/set/all/header/header_wrap.haml +4 -0
  25. data/set/all/html_content.rb +168 -0
  26. data/set/all/html_content/labeled.haml +4 -0
  27. data/set/all/html_error.rb +193 -0
  28. data/set/all/html_error/debug_server_error.haml +1015 -0
  29. data/set/all/html_error/not_found.haml +7 -0
  30. data/set/all/html_error/server_error.haml +5 -0
  31. data/set/all/html_show.rb +53 -0
  32. data/set/all/html_title.rb +47 -0
  33. data/set/all/html_wrapper.rb +159 -0
  34. data/set/all/js.rb +10 -0
  35. data/set/all/json.rb +166 -0
  36. data/set/all/links.rb +149 -0
  37. data/set/all/menu.rb +129 -0
  38. data/set/all/meta_tags.haml +4 -0
  39. data/set/all/path.rb +78 -0
  40. data/set/all/rich_html.rb +4 -0
  41. data/set/all/rss.rb +76 -0
  42. data/set/all/text.rb +7 -0
  43. data/set/self/home.rb +9 -0
  44. data/set/type/html.rb +27 -0
  45. data/set/type/json.rb +41 -0
  46. data/set/type/number.rb +22 -0
  47. data/set/type/phrase.rb +5 -0
  48. data/set/type/plain_text.rb +9 -0
  49. data/set/type/toggle.rb +38 -0
  50. data/set/type/uri.rb +15 -0
  51. metadata +123 -0
@@ -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
@@ -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
@@ -0,0 +1,4 @@
1
+ %meta{ charset: "UTF-8" }
2
+ %meta{ content: "width=device-width, initial-scale=1.0", name: "viewport" }
3
+ - if card.unknown?
4
+ %meta{ content: "noindex", name: "robots"}
@@ -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
@@ -0,0 +1,4 @@
1
+ format :html do
2
+ delegate :class_up, :class_down, :with_class_up, :without_upped_class, :classy,
3
+ to: :voo
4
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+
2
+ format :text do
3
+ view :core do
4
+ HTMLEntities.new.decode strip_tags(super()).to_s
5
+ # need this string method to get out of html_safe mode
6
+ end
7
+ end