chili_pdf 0.3.0 → 0.4.0

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.
data.tar.gz.sig CHANGED
Binary file
data/Gemfile CHANGED
@@ -1,6 +1,7 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'wicked_pdf'
3
+ gem 'wicked_pdf', '~> 0.7'
4
+ gem 'nokogiri', '~> 1.4'
4
5
 
5
6
  group :development do
6
7
  gem 'autotest-rails', '~> 4.1'
data/Gemfile.lock CHANGED
@@ -21,6 +21,7 @@ GEM
21
21
  hoe (>= 2.2.0)
22
22
  i18n (0.4.2)
23
23
  json (1.4.6)
24
+ nokogiri (1.4.4)
24
25
  rack (1.0.1)
25
26
  rake (0.8.7)
26
27
  redmine_plugin_support (0.0.4)
@@ -42,7 +43,8 @@ DEPENDENCIES
42
43
  hoe (~> 2.8)
43
44
  hoe-git
44
45
  i18n (= 0.4.2)
46
+ nokogiri (~> 1.4)
45
47
  redmine_plugin_support
46
48
  rspec (= 1.3.1)
47
49
  rspec-rails (= 1.3.2)
48
- wicked_pdf
50
+ wicked_pdf (~> 0.7)
data/History.txt CHANGED
@@ -1,3 +1,20 @@
1
+ === 0.4.0 / 2011-06-18
2
+
3
+ * New features:
4
+ * Simplified customizating styles of of exported PDFs. Added ability to
5
+ insert custom CSS and JavaScript into the DOM before the PDF is
6
+ rendered [closes #12]
7
+ * Added support for images in wiki pages to be exported in PDFs [closes #10]
8
+ (Thanks to @roykolak for the code review!)
9
+ * Added support for rending the HTML used to create the PDF by passing
10
+ "as_html=true" in as a URL param (eg: /Page.pdf?as_html=true) [closes #9]
11
+ * Added nokogiri as a dependency to get around requests for protected
12
+ assets (images, etc) (see issue #10 for details)
13
+
14
+ * Minor enhancements:
15
+ * Fixed image-sizing issue when resolution of image is wider than
16
+ the exported PDF [closes #11]
17
+
1
18
  === 0.3.0 / 2011-06-13
2
19
 
3
20
  * New features
data/Manifest.txt CHANGED
@@ -10,7 +10,11 @@ app/controllers/extended_wiki_controller.rb
10
10
  app/helpers/chili_pdf_helper.rb
11
11
  app/views/extended_wiki/show.pdf.html.erb
12
12
  app/views/layouts/pdf.pdf.erb
13
+ app/views/settings/_chili_pdf_advanced_settings.html.erb
13
14
  app/views/settings/_chili_pdf_settings.html.erb
15
+ app/views/settings/_chili_pdf_typical_settings.html.erb
16
+ assets/javascripts/chili_pdf.js
17
+ assets/stylesheets/chili_pdf_settings_tweaks.css
14
18
  assets/stylesheets/pdf.css
15
19
  autotest/discover.rb
16
20
  config/locales/en.yml
@@ -21,6 +25,7 @@ lib/chili_pdf.rb
21
25
  lib/chili_pdf/config.rb
22
26
  lib/chili_pdf/formatter.rb
23
27
  lib/chili_pdf/string_token.rb
28
+ lib/chili_pdf/tag_mangler.rb
24
29
  lib/chili_pdf/token_manager.rb
25
30
  lib/tasks/chili_pdf_tasks.rb
26
31
  lib/tasks/contributor_tasks.rb
@@ -30,5 +35,7 @@ rails/init.rb
30
35
  test/chili_pdf/config_test.rb
31
36
  test/chili_pdf/formatter_test.rb
32
37
  test/chili_pdf/string_token_test.rb
38
+ test/chili_pdf/tag_mangler_test.rb
33
39
  test/chili_pdf/token_manager_test.rb
34
40
  test/test_helper.rb
41
+ test/unit/helpers/chili_pdf_helper_test.rb
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ChiliPDF Plugin - Flexible PDF exporting for ChiliProject/Redmine
2
2
 
3
- * http://github.com/tomkersten/chili_pdf
3
+ * http://github.com/tomkersten/chili\_pdf
4
4
 
5
5
  ## DESCRIPTION:
6
6
 
@@ -24,13 +24,16 @@ ChiliProject (/Redmine) plugin which implements/enhances PDF-export functionalit
24
24
 
25
25
  ## FEATURES:
26
26
 
27
- 1. Provides PDF export of any project wiki page to PDF with a baseline
28
- stylesheet. The styling can be customized by modifying the "pdf.css'
29
- asset file that ships with the library.
27
+ 1. Provides PDF export of any project wiki page to PDF with a decent
28
+ baseline style out of the box.
29
+ 1. Support for dynamic content in headers and footers administered via the
30
+ plugin configuration page.
31
+ 1. Flexible/easy PDF styling. The styling can be customized by adding your
32
+ own CSS and/or JavaScript on the plugin configuration page.
30
33
 
31
34
  ## SCREENSHOTS:
32
35
 
33
- You can find a few screenshots [here](http://www.flickr.com/photos/tomkersten/sets/72157626827940413/).
36
+ You can find a few screenshots [here](http://www.flickr.com/photos/tomkersten/sets/72157626992576450).
34
37
 
35
38
  ## PROBLEMS:
36
39
 
@@ -55,6 +58,7 @@ You can find a few screenshots [here](http://www.flickr.com/photos/tomkersten/se
55
58
  ## REQUIREMENTS:
56
59
 
57
60
  * wicked\_pdf
61
+ * nokogiri
58
62
 
59
63
  ## INSTALL:
60
64
 
@@ -136,3 +140,7 @@ You can also drop me a message on Twitter [@tomkersten](http://twitter.com/tomke
136
140
  ## LICENSE:
137
141
 
138
142
  Refer to the [LICENSE](https://github.com/tomkersten/chili_pdf/blob/master/LICENSE) file
143
+
144
+ ## Contributors (sorted alphabetically)
145
+
146
+ * Roy Kolak
data/Rakefile CHANGED
@@ -24,7 +24,7 @@ begin
24
24
  self.version = ChiliPDF::VERSION
25
25
  self.extra_rdoc_files = FileList['README.md', 'LICENSE', 'History.txt']
26
26
  self.summary = "ChiliProject (/Redmine) plugin which implements/enhances PDF-export functionality using the Webkit rendering engine."
27
- self.extra_deps = [['wicked_pdf', '0.7.0']]
27
+ self.extra_deps = [['wicked_pdf', '~> 0.7'], ['nokogiri', '~> 1.4']]
28
28
  self.extra_dev_deps = []
29
29
  developer('Tom Kersten', 'tom@whitespur.com')
30
30
  end
@@ -14,7 +14,7 @@ class ExtendedWikiController < WikiController
14
14
 
15
15
  private
16
16
  def formatter
17
- ChiliPDF::Formatter.new(filename, page_title)
17
+ ChiliPDF::Formatter.new(filename, page_title, wants_html_version?)
18
18
  end
19
19
 
20
20
  def filename
@@ -24,4 +24,8 @@ class ExtendedWikiController < WikiController
24
24
  def page_title
25
25
  "#{@project.name}, #{@page.title}"
26
26
  end
27
+
28
+ def wants_html_version?
29
+ @requesting_html_version = params[:as_html] == 'true' || request.format.html?
30
+ end
27
31
  end
@@ -1,10 +1,167 @@
1
1
  module ChiliPdfHelper
2
- # Taken almost verbatim from wicked_pdf gem
3
- def chili_pdf_stylesheets
4
- css_dir = Rails.root.join('public','plugin_assets', 'chili_pdf', 'stylesheets')
5
- css_file_list = Dir.glob("#{css_dir}/*css")
6
- css_file_list.collect { |css_file|
7
- "<style type='text/css'>#{File.read(css_file)}</style>"
2
+ # Public directory of ChiliPDF plugin JavaScript files
3
+ PLUGIN_JS_DIR = Rails.root.join('public','plugin_assets', 'chili_pdf', 'javascripts')
4
+
5
+ # Public directory of ChiliPDF plugin stylesheets
6
+ PLUGIN_CSS_DIR = Rails.root.join('public','plugin_assets', 'chili_pdf', 'stylesheets')
7
+
8
+ # Standard <script>-tag for Prototype JavaScript file
9
+ PROTOTYPE_SCRIPT_TAG = "#{Rails.root}/public/javascripts/prototype.js"
10
+
11
+
12
+ # Public: Generates <link> tags for all CSS files in the
13
+ # plugin_assets/chili_pdf/stylesheets directory, formatting
14
+ # the 'href' attribute value appropriately for HTML or PDF
15
+ # request types.
16
+ #
17
+ # wants_html - specifies whether the 'src' attribute should be formatted
18
+ # for HTML or PDF requests (local vs. relative paths). Added to
19
+ # keep excessive boolean logic out of views.
20
+ #
21
+ # Returns: String of link tags separated by a newline character.
22
+ def chili_pdf_stylesheets(wants_html)
23
+ file_type_list(:css, PLUGIN_CSS_DIR, wants_html) {|asset_path|
24
+ "<link href='#{asset_path}' rel='stylesheet' type='text/css' />\n"
8
25
  }.join("\n")
9
26
  end
27
+
28
+
29
+ # Public: Generate JS <script> tags for all JavaScript files in the
30
+ # plugin_assets/chili_pdf/stylesheets directory, formatting
31
+ # the 'src' attribute value appropriately for HTML or PDF request
32
+ # types
33
+ #
34
+ # wants_html - specifies whether the 'src' attribute should be formatted
35
+ # for HTML or PDF requests (local vs. relative paths). Added to
36
+ # keep excessive boolean logic out of views.
37
+ #
38
+ # Returns: string of <script> tags separated by a newline character
39
+ def chili_pdf_javascripts(wants_html)
40
+ file_type_list(:js, PLUGIN_JS_DIR, wants_html) {|asset_path|
41
+ "<script src='#{asset_path}' type='text/javascript'></script>"
42
+ }.join("\n")
43
+ end
44
+
45
+
46
+ # Public: Converts 'href' attributes of any <link> tags
47
+ # tags to be compatible with the `wkhtmltopdf` executable
48
+ # requirements, using "file://"-format for all local assets.
49
+ #
50
+ # content - the String of HTML content to normalize/update
51
+ # wants_html - specifies whether the 'src' attribute should be formatted
52
+ # for HTML or PDF requests (local vs. relative paths). Added to
53
+ # keep excessive boolean logic out of views.
54
+ #
55
+ # Returns content un-modified if wants_html is true. Otherwise returns
56
+ # the content string with the modified 'href' attribute on all
57
+ # locally-hosted <link>-tags in content.
58
+ def normalize_custom_link_href_tags_in(content, wants_html = false)
59
+ update_tag_attribute(:link, :href, content, wants_html)
60
+ end
61
+
62
+
63
+ # Public: Converts 'src' attributes of any <script> tags (with a 'src'
64
+ # attribute) to be compatible with the `wkhtmltopdf` executable
65
+ # requirements, using "file://"-format for all local assets.
66
+ #
67
+ # content - the String of HTML content to normalize/update
68
+ # wants_html - specifies whether the 'src' attribute should be formatted
69
+ # for HTML or PDF requests (local vs. relative paths). Added to
70
+ # keep excessive boolean logic out of views.
71
+ #
72
+ # Returns content un-modified if wants_html is true. Otherwise returns
73
+ # the content string with the modified 'src' attribute on all
74
+ # locally-hosted <script>-tags in content.
75
+ def normalize_custom_js_src_tags_in(content, wants_html = false)
76
+ update_tag_attribute(:script, :src, content, wants_html)
77
+ end
78
+
79
+
80
+ # Public: Converts 'src' attributes of any <img> tags to be compatible with
81
+ # the `wkhtmltopdf` executable requirements, using "file://"-format
82
+ # for all local assets.
83
+ #
84
+ # content - the String of HTML content to normalize/update
85
+ # wants_html - specifies whether the 'src' attribute should be formatted
86
+ # for HTML or PDF requests (local vs. relative paths). Added to
87
+ # keep excessive boolean logic out of views.
88
+ #
89
+ # Returns content un-modified if wants_html is true. Otherwise returns
90
+ # the content string with the modified 'src' attribute on all
91
+ # locally-hosted <img>-tags in content.
92
+ def update_img_src_tags_of(content, wants_html = false)
93
+ update_tag_attribute(:img, :src, content, wants_html)
94
+ end
95
+
96
+
97
+ private
98
+ # Updates the value of the specified attribute of any `tag_type` tags
99
+ # contained in `content` to be compatible with the `wkhtmltopdf`
100
+ # executable. If `wants_html` is falsey, no modifications are made
101
+ # to content.
102
+ #
103
+ # tag_type - String-link object which returns the tag to look for in
104
+ # 'content' when #to_s is called on it.
105
+ # content - String of the HTML content to search for `tag_type' in
106
+ # wants_html - specifies whether the attribute should be formatted
107
+ # for HTML or PDF requests (local vs. relative paths). Added to
108
+ # keep excessive boolean logic out of views.
109
+ def update_tag_attribute(tag_type, attribute, content, wants_html)
110
+ return content if wants_html
111
+
112
+ doc = ::Nokogiri::HTML(content)
113
+ doc.xpath("//#{tag_type.to_s}[@#{attribute.to_s}]").each do |a_tag|
114
+ a_tag["#{attribute.to_s}"] = mangle(a_tag["#{attribute.to_s}"])
115
+ end
116
+ doc.to_s
117
+ end
118
+
119
+
120
+ # Generate list of content based on files with the specified file extension
121
+ # in the specified source directory. The object passed into the block will
122
+ # be the path to an individual file path in either HTML- or PDF-request
123
+ # compatible form (file://-based or relative-url based). Useful for
124
+ # generating a series of tags for all files matching a particular file type
125
+ # in a specified directory.
126
+ #
127
+ # file_ext - the file extension to search for in the src_dir
128
+ # src_dir - the directory to search for file with the specified
129
+ # file extension (file_ext)
130
+ # wants_html - specifies whether the 'src' attribute should be formatted
131
+ # for HTML or PDF requests (local vs. relative paths). Added to
132
+ # keep excessive boolean logic out of views.
133
+ # &block - code to execute on each matching filename (filename is
134
+ # passed in as a parameter to &block)
135
+ # Returns an Array of the results of the &block executions.
136
+ def file_type_list(file_ext, src_dir, wants_html, &block)
137
+ # We want/need to prepend the Prototype script-tag before all other script-tags
138
+ file_list = file_ext.to_s == "js" ? [PROTOTYPE_SCRIPT_TAG] : []
139
+
140
+ file_list.push(*Dir.glob("#{src_dir}/*#{file_ext.to_s}")).collect do |file_path|
141
+ asset_path = file_path.to_s.sub(/^#{Rails.root}\/public/, '')
142
+ asset_path = mangle(asset_path) unless wants_html
143
+ yield asset_path
144
+ end
145
+ end
146
+
147
+ # Converts the specified String to PDF-format-friendly version of itself.
148
+ # Supports the '/attachments/:id/:filename' and '/attachments/download/:id' routes
149
+ # of ChiliProject as well as standard static assets (nested under RAILS_ROOT/public).
150
+ #
151
+ # content - String to convert
152
+ #
153
+ # Examples
154
+ #
155
+ # mangle('/stylesheets/application.css')
156
+ # => "file:///path/to/rails_root/public/stylesheets/application.css"
157
+ #
158
+ # mangle('/attachments/1/image.png')
159
+ # => "file:///path/to/rails_root/files/38278327_image.png"
160
+ #
161
+ # Returns modified String, unless requested asset either doesn't exist
162
+ # or is an invalid request (to, say, an asset located above
163
+ # the 'RAILS_ROOT/public' sub-directory.
164
+ def mangle(content)
165
+ TagMangler.new(content).to_local_src
166
+ end
10
167
  end
@@ -1,5 +1,9 @@
1
1
  <% content_for :header_tags do %>
2
- <%= chili_pdf_stylesheets %>
2
+ <%= chili_pdf_stylesheets(@requesting_html_version) %>
3
+ <%= chili_pdf_javascripts(@requesting_html_version) %>
4
+ <%= normalize_custom_link_href_tags_in(ChiliPDF::Config.custom_css, @requesting_html_version) %>
5
+ <%= normalize_custom_js_src_tags_in(ChiliPDF::Config.custom_js, @requesting_html_version) %>
3
6
  <% end %>
4
7
 
5
- <%= render(:partial => "wiki/content", :locals => {:content => @content}) %>
8
+ <%- html_content = textilizable(@content.text, :attachments => @content.page.attachments) %>
9
+ <%= update_img_src_tags_of(html_content, @requesting_html_version) %>
@@ -16,7 +16,7 @@
16
16
  <%= yield(:header_tags) %>
17
17
  </head>
18
18
 
19
- <body>
19
+ <body id="custom-pdf-styles">
20
20
  <%= yield(:layout) %>
21
21
  </body>
22
22
  </html>
@@ -0,0 +1,13 @@
1
+ <p class="chili-pdf-instructions">
2
+ You can add custom CSS & JavaScript which will be applied to your PDF before saving.
3
+ </p>
4
+
5
+ <p>
6
+ <label><%= l(:label_custom_css) %></label>
7
+ <%= text_area_tag "settings[#{ChiliPDF::Config::CUSTOM_CSS_KEYNAME}]", ChiliPDF::Config.custom_css %>
8
+ </p>
9
+
10
+ <p>
11
+ <label><%= l(:label_custom_js) %></label>
12
+ <%= text_area_tag "settings[#{ChiliPDF::Config::CUSTOM_JS_KEYNAME}]", ChiliPDF::Config.custom_js %>
13
+ </p>
@@ -1,82 +1,9 @@
1
1
  <% content_for :header_tags do %>
2
- <%= stylesheet_link_tag '/plugin_assets/chili_pdf/stylesheets/pdf' %>
2
+ <%= stylesheet_link_tag '/plugin_assets/chili_pdf/stylesheets/chili_pdf_settings_tweaks' %>
3
3
  <% end %>
4
4
 
5
- <p>
6
- <label for='settings_<%= ChiliPDF::Config::HEADER_ENABLED_KEYNAME %>'><%= l(:header_enabled_label) %></label>
7
- <%= check_box_tag "settings[#{ChiliPDF::Config::HEADER_ENABLED_KEYNAME}]", ChiliPDF::Config::ENABLED_VALUE, ChiliPDF::Config.header_enabled? %>
8
- </p>
5
+ <%= render_tabs([
6
+ {:name => 'typical_settings', :partial => 'settings/chili_pdf_typical_settings', :label => :typical_plugin_settings},
7
+ {:name => 'advanced_settings', :partial => 'settings/chili_pdf_advanced_settings', :label => :advanced_plugin_settings},
8
+ ]) %>
9
9
 
10
- <p>
11
- <label for='settings_<%= ChiliPDF::Config::FOOTER_ENABLED_KEYNAME %>'><%= l(:footer_enabled_label) %></label>
12
- <%= check_box_tag "settings[#{ChiliPDF::Config::FOOTER_ENABLED_KEYNAME}]", ChiliPDF::Config::ENABLED_VALUE, ChiliPDF::Config.footer_enabled? %>
13
- </p>
14
-
15
- <h3>Custom Header/Footer Content</h3>
16
-
17
- <h4>Rules</h4>
18
- <ol>
19
- <li>Any "plain text" will render, as is...</li>
20
- <li>
21
- There are a few 'variables' you can use to dynamically replace content. For example,
22
- you can add the current date to any page.
23
- </li>
24
- <li>All input will be escaped HTML, so injecting dynamic content via JavaScript will not work.</li>
25
- </ol>
26
-
27
- <table>
28
- <thead>
29
- <tr>
30
- <td></td>
31
- <td>Left</td>
32
- <td>Center</td>
33
- <td>Right</td>
34
- </tr>
35
- </thead>
36
- <tbody>
37
- <tr>
38
- <td>Header</td>
39
- <td>
40
- <%= text_field_tag "settings[#{ChiliPDF::Config::HEADER_LEFT_KEYNAME}]", ChiliPDF::Config.header_values[:left] %>
41
- </td>
42
- <td>
43
- <%= text_field_tag "settings[#{ChiliPDF::Config::HEADER_CENTER_KEYNAME}]", ChiliPDF::Config.header_values[:center] %>
44
- </td>
45
- <td>
46
- <%= text_field_tag "settings[#{ChiliPDF::Config::HEADER_RIGHT_KEYNAME}]", ChiliPDF::Config.header_values[:right] %>
47
- </td>
48
- </tr>
49
- <tr>
50
- <td>Footer</td>
51
- <td>
52
- <%= text_field_tag "settings[#{ChiliPDF::Config::FOOTER_LEFT_KEYNAME}]", ChiliPDF::Config.footer_values[:left] %>
53
- </td>
54
- <td>
55
- <%= text_field_tag "settings[#{ChiliPDF::Config::FOOTER_CENTER_KEYNAME}]", ChiliPDF::Config.footer_values[:center] %>
56
- </td>
57
- <td>
58
- <%= text_field_tag "settings[#{ChiliPDF::Config::FOOTER_RIGHT_KEYNAME}]", ChiliPDF::Config.footer_values[:right] %>
59
- </td>
60
- </tr>
61
- </tbody>
62
- </table>
63
-
64
- <div id="pdf-token-help">
65
- <h4>Dynamic text legend</h4>
66
- <table>
67
- <thead>
68
- <tr>
69
- <td>Enter this</td>
70
- <td>...to show this</td>
71
- </tr>
72
- </thead>
73
- <tbody>
74
- <%- ChiliPDF::TokenManager.tokens.each do |token| %>
75
- <tr>
76
- <td class="token"><%= token.matcher_with_delimiters %></td>
77
- <td class="description"><%= token.description %></td>
78
- </tr>
79
- <%- end %>
80
- </tbody>
81
- </table>
82
- </div>
@@ -0,0 +1,76 @@
1
+ <p class="chili-pdf-instructions">
2
+ <span class="tip-label">Pro Tip:</span>
3
+ You can see what impact your settings have on exported items by appending a
4
+ "<em>.pdf?as_html=true</em>" to the URL of any wiki page. This will give you an
5
+ idea of what your style/behavior changes will look like (without headers, margins,
6
+ et cetera).
7
+ </p>
8
+
9
+ <p>
10
+ <label for='settings_<%= ChiliPDF::Config::HEADER_ENABLED_KEYNAME %>'><%= l(:header_enabled_label) %></label>
11
+ <%= check_box_tag "settings[#{ChiliPDF::Config::HEADER_ENABLED_KEYNAME}]", ChiliPDF::Config::ENABLED_VALUE, ChiliPDF::Config.header_enabled? %>
12
+ </p>
13
+
14
+ <p>
15
+ <label for='settings_<%= ChiliPDF::Config::FOOTER_ENABLED_KEYNAME %>'><%= l(:footer_enabled_label) %></label>
16
+ <%= check_box_tag "settings[#{ChiliPDF::Config::FOOTER_ENABLED_KEYNAME}]", ChiliPDF::Config::ENABLED_VALUE, ChiliPDF::Config.footer_enabled? %>
17
+ </p>
18
+
19
+ <h3>Custom Header/Footer Content</h3>
20
+
21
+ <table>
22
+ <thead>
23
+ <tr>
24
+ <td></td>
25
+ <td>Left</td>
26
+ <td>Center</td>
27
+ <td>Right</td>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <tr>
32
+ <td>Header</td>
33
+ <td>
34
+ <%= text_field_tag "settings[#{ChiliPDF::Config::HEADER_LEFT_KEYNAME}]", ChiliPDF::Config.header_values[:left] %>
35
+ </td>
36
+ <td>
37
+ <%= text_field_tag "settings[#{ChiliPDF::Config::HEADER_CENTER_KEYNAME}]", ChiliPDF::Config.header_values[:center] %>
38
+ </td>
39
+ <td>
40
+ <%= text_field_tag "settings[#{ChiliPDF::Config::HEADER_RIGHT_KEYNAME}]", ChiliPDF::Config.header_values[:right] %>
41
+ </td>
42
+ </tr>
43
+ <tr>
44
+ <td>Footer</td>
45
+ <td>
46
+ <%= text_field_tag "settings[#{ChiliPDF::Config::FOOTER_LEFT_KEYNAME}]", ChiliPDF::Config.footer_values[:left] %>
47
+ </td>
48
+ <td>
49
+ <%= text_field_tag "settings[#{ChiliPDF::Config::FOOTER_CENTER_KEYNAME}]", ChiliPDF::Config.footer_values[:center] %>
50
+ </td>
51
+ <td>
52
+ <%= text_field_tag "settings[#{ChiliPDF::Config::FOOTER_RIGHT_KEYNAME}]", ChiliPDF::Config.footer_values[:right] %>
53
+ </td>
54
+ </tr>
55
+ </tbody>
56
+ </table>
57
+
58
+ <div id="pdf-token-help">
59
+ <h4>Dynamic text legend</h4>
60
+ <table>
61
+ <thead>
62
+ <tr>
63
+ <td>Enter this</td>
64
+ <td>...to show this</td>
65
+ </tr>
66
+ </thead>
67
+ <tbody>
68
+ <%- ChiliPDF::TokenManager.tokens.each do |token| %>
69
+ <tr>
70
+ <td class="token"><%= token.matcher_with_delimiters %></td>
71
+ <td class="description"><%= token.description %></td>
72
+ </tr>
73
+ <%- end %>
74
+ </tbody>
75
+ </table>
76
+ </div>
File without changes
@@ -0,0 +1,10 @@
1
+ em {font-style: italic;}
2
+ textarea {width: 600px; height: 200px;}
3
+
4
+ p.chili-pdf-instructions {padding-left: 0;}
5
+ .tip-label {font-weight: bold; text-decoration: underline;}
6
+
7
+ #pdf-token-help {margin-top: 20px;}
8
+ #pdf-token-help table {width: 100%; border: 1px #AAA solid;}
9
+ #pdf-token-help td {border-bottom: 1px dotted #CCC;}
10
+ #pdf-token-help thead td {font-weight: bold; border-bottom: 2px solid #CCC;}
@@ -33,12 +33,4 @@ li { padding: 0.1em; }
33
33
  ol li {list-style-type: decimal;}
34
34
  ul li {list-style-type: disc;}
35
35
  h1, h2 {font-weight: bold;}
36
-
37
- #pdf-token-help {
38
- margin-top: 20px;
39
- }
40
-
41
- #pdf-token-help table {width: 100%; border: 1px #AAA solid;}
42
- #pdf-token-help td {border-bottom: 1px dotted #CCC;}
43
-
44
- #pdf-token-help thead td {font-weight: bold; border-bottom: 2px solid #CCC;}
36
+ img {max-width: 100%;}
@@ -3,3 +3,7 @@ en:
3
3
  chili_pdf_instructions: 'You can customize the behavior of the ChiliPDf plugin with the settings below'
4
4
  header_enabled_label: Display page header?
5
5
  footer_enabled_label: Display page footer?
6
+ typical_plugin_settings: Typical Settings
7
+ advanced_plugin_settings: Technical Settings
8
+ label_custom_css: Custom CSS
9
+ label_custom_js: Custom JavaScript
data/config/routes.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  ActionController::Routing::Routes.draw do |map|
2
+ map.connect 'projects/:project_id/wiki.pdf', :controller => 'extended_wiki', :action => 'show', :format => 'pdf'
2
3
  map.connect 'projects/:project_id/wiki/:id.pdf', :controller => 'extended_wiki', :action => 'show', :format => 'pdf'
3
4
  end
data/init.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'redmine'
2
2
  require 'chili_pdf'
3
- require 'wicked_pdf'
3
+ require 'wicked_pdf' unless defined?(WickedPdf)
4
+ require 'nokogiri' unless defined?(Nokogiri)
4
5
  require 'dispatcher'
5
6
 
6
7
  Redmine::Plugin.register :chili_pdf do
data/lib/chili_pdf.rb CHANGED
@@ -2,7 +2,8 @@ require 'chili_pdf/config'
2
2
  require 'chili_pdf/token_manager'
3
3
  require 'chili_pdf/formatter'
4
4
  require 'chili_pdf/string_token'
5
+ require 'chili_pdf/tag_mangler'
5
6
 
6
7
  module ChiliPDF
7
- VERSION = '0.3.0'
8
+ VERSION = '0.4.0'
8
9
  end
@@ -7,6 +7,8 @@ module ChiliPDF
7
7
  DISABLED_VALUE = '0'
8
8
  FOOTER_ENABLED_KEYNAME = 'footer_enabled'
9
9
  HEADER_ENABLED_KEYNAME = 'header_enabled'
10
+ CUSTOM_CSS_KEYNAME = 'custom_css'
11
+ CUSTOM_JS_KEYNAME = 'custom_javascript'
10
12
 
11
13
  HEADER_LEFT_KEYNAME = :header_content_left
12
14
  HEADER_CENTER_KEYNAME = :header_content_center
@@ -21,6 +23,25 @@ module ChiliPDF
21
23
  FOOTER_LEFT_DEFAULT_VALUE = '{{datestamp}}'
22
24
  FOOTER_CENTER_DEFAULT_VALUE = ''
23
25
  FOOTER_RIGHT_DEFAULT_VALUE = '{{current_page}}/{{total_pages}}'
26
+ CUSTOM_CSS_DEFAULT_VALUE = <<END_OF_CSS_DEF
27
+ <!-- stylesheet link example, uncomment & modify if you like -->
28
+ <!-- <link href='/stylesheets/your_custom.css' rel='stylesheet' type='text/css' />
29
+
30
+ <!-- inline example -->
31
+ <style type="text/css">
32
+ //#custom-pdf-styles h2 {color: red;}
33
+ </style>
34
+ END_OF_CSS_DEF
35
+
36
+ CUSTOM_JS_DEFAULT_VALUE = <<END_OF_JS_DEF
37
+ <!-- Script tag link example. Uncomment & modify if you like. -->
38
+ <!-- <script src='/javascripts/your_custom.js' type='text/javascript' />
39
+
40
+ <!-- Inline JavaScript example -->
41
+ <script type="text/javascript">
42
+ // Your custom-inline JS here
43
+ </script>
44
+ END_OF_JS_DEF
24
45
 
25
46
  def defaults
26
47
  {
@@ -31,7 +52,9 @@ module ChiliPDF
31
52
  HEADER_RIGHT_KEYNAME => HEADER_RIGHT_DEFAULT_VALUE,
32
53
  FOOTER_LEFT_KEYNAME => FOOTER_LEFT_DEFAULT_VALUE,
33
54
  FOOTER_CENTER_KEYNAME => FOOTER_CENTER_DEFAULT_VALUE,
34
- FOOTER_RIGHT_KEYNAME => FOOTER_RIGHT_DEFAULT_VALUE
55
+ FOOTER_RIGHT_KEYNAME => FOOTER_RIGHT_DEFAULT_VALUE,
56
+ CUSTOM_CSS_KEYNAME => CUSTOM_CSS_DEFAULT_VALUE,
57
+ CUSTOM_JS_KEYNAME => CUSTOM_JS_DEFAULT_VALUE
35
58
  }
36
59
  end
37
60
 
@@ -72,6 +95,22 @@ module ChiliPDF
72
95
  default_footer_values.merge(stored_footer_settings)
73
96
  end
74
97
 
98
+ def custom_css
99
+ if plugin_settings[CUSTOM_CSS_KEYNAME].blank?
100
+ CUSTOM_CSS_DEFAULT_VALUE
101
+ else
102
+ plugin_settings[CUSTOM_CSS_KEYNAME]
103
+ end
104
+ end
105
+
106
+ def custom_js
107
+ if plugin_settings[CUSTOM_JS_KEYNAME].blank?
108
+ CUSTOM_JS_DEFAULT_VALUE
109
+ else
110
+ plugin_settings[CUSTOM_JS_KEYNAME]
111
+ end
112
+ end
113
+
75
114
  private
76
115
  def default_header_values
77
116
  {:left => HEADER_LEFT_DEFAULT_VALUE,
@@ -15,9 +15,10 @@ module ChiliPDF
15
15
  :description => "The project & wiki page name (eg: 'My Project, Wiki Page Title')"}}
16
16
  end
17
17
 
18
- def initialize(filename, title = nil)
18
+ def initialize(filename, title = nil, render_html_version = nil)
19
19
  @page_title = title
20
20
  @filename = filename
21
+ @allow_debugging = render_html_version
21
22
 
22
23
  # TODO: Hack...need to come up with better approach for this...
23
24
  TokenManager.add_token_definition do
@@ -31,6 +32,7 @@ module ChiliPDF
31
32
  :pdf => @filename,
32
33
  :template => view_template,
33
34
  :page_size => DEFAULT_PAGE_SIZE,
35
+ :show_as_html => render_as_html?,
34
36
  :margin => {
35
37
  :top => DEFAULT_MARGIN,
36
38
  :bottom => DEFAULT_MARGIN,
@@ -76,5 +78,9 @@ module ChiliPDF
76
78
  def view_template
77
79
  DEFAULT_VIEW_TEMPLATE
78
80
  end
81
+
82
+ def render_as_html?
83
+ !@allow_debugging.blank?
84
+ end
79
85
  end
80
86
  end
@@ -0,0 +1,65 @@
1
+ class TagMangler
2
+ def initialize(src)
3
+ @src_attribute = src
4
+ end
5
+
6
+ def to_local_src
7
+ full_file_path.blank? ? @src_attribute : "file://#{full_file_path}"
8
+ end
9
+
10
+ private
11
+ def full_file_path
12
+ if requesting_valid_static_asset?
13
+ requested_path
14
+ elsif requesting_attachment? && !attachment.blank?
15
+ attachment.diskfile
16
+ end
17
+ end
18
+
19
+ def attachment
20
+ Attachment.find_by_id(attachment_id)
21
+ end
22
+
23
+ def requesting_attachment?
24
+ !attachment_id.blank?
25
+ end
26
+
27
+ def requesting_valid_static_asset?
28
+ requested_asset_under_public_dir? && static_asset_exists?
29
+ end
30
+
31
+ def static_asset_exists?
32
+ File.exists?(requested_path)
33
+ end
34
+
35
+ def requested_path
36
+ File.expand_path(File.join(public_path, @src_attribute))
37
+ end
38
+
39
+ def public_path
40
+ File.expand_path(File.join(Rails.root, 'public'))
41
+ end
42
+
43
+ def requested_asset_under_public_dir?
44
+ requested_path.match(/^#{public_path}/)
45
+ end
46
+
47
+ # Pull the specified attachment ID out of the @src_attribute
48
+ # if it is in one of the 'standad' URL formats
49
+ # (ie: the :id field from the examples below)
50
+ #
51
+ # Example URLs:
52
+ # /attachments/:id/:filename
53
+ # /attachments/download/:id
54
+ #
55
+ # Returns the specified id as a string if a valid one is present
56
+ # Returns nil otherwise
57
+ def attachment_id
58
+ regexp = Regexp.new(/\/?attachments(?:\/download)?\/(\d+)\/?.*/)
59
+ @src_attribute.match(regexp) && $1
60
+ end
61
+
62
+
63
+ end
64
+
65
+
@@ -30,6 +30,23 @@ class FormatterTest < Test::Unit::TestCase
30
30
  assert_equal default_margins, @formatter.render_options[:margin]
31
31
  end
32
32
 
33
+ context "enabling/disabling viewing the underlying HTML of the PDF" do
34
+ should "set :show_as_html key to true when true is specified" do
35
+ formatter = Formatter.new('filename.pdf', 'title', true)
36
+ assert formatter.render_options[:show_as_html]
37
+ end
38
+
39
+ should "set :show_as_html key to false when false is specified" do
40
+ formatter = Formatter.new('filename.pdf', 'title', false)
41
+ assert !formatter.render_options[:show_as_html]
42
+ end
43
+
44
+ should "set :show_as_html key to false as the default" do
45
+ formatter = Formatter.new('filename.pdf', 'title')
46
+ assert !formatter.render_options[:show_as_html]
47
+ end
48
+ end
49
+
33
50
  context 'when footers are enabled' do
34
51
  setup do
35
52
  enable_footers
@@ -0,0 +1,115 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ def make_mangler_with(asset_path)
4
+ TagMangler.new(asset_path)
5
+ end
6
+
7
+ # Stolen from the Rails.root test_helper...
8
+ # not sure why they are not being included in here yet
9
+ def mock_file
10
+ file = 'a_file.png'
11
+ file.stubs(:size).returns(32)
12
+ file.stubs(:original_filename).returns('a_file.png')
13
+ file.stubs(:content_type).returns('image/png')
14
+ file.stubs(:read).returns(false)
15
+ file
16
+ end
17
+
18
+ class TokenManagerTest < Test::Unit::TestCase
19
+ context "#to_local_src" do
20
+ context "when requesting a static asset" do
21
+ setup do
22
+ @requested_asset = "../Rakefile"
23
+ @mangler = make_mangler_with(@requested_asset)
24
+ end
25
+
26
+ context "which is not nested under the 'public' directory of the application" do
27
+ should "return the original value without any modifications" do
28
+ assert_equal @requested_asset, @mangler.to_local_src
29
+ end
30
+ end
31
+
32
+ context "which does not exist on the filesystem" do
33
+ setup do
34
+ @requested_asset = 'stylesheets/faux_css_file_fildjakfldsa.css'
35
+ @mangler = make_mangler_with(@requested_asset)
36
+ end
37
+
38
+ should "return the original value without any modifications" do
39
+ assert_equal @requested_asset, @mangler.to_local_src
40
+ end
41
+ end
42
+
43
+ context "which does exist on the filesystem" do
44
+ setup do
45
+ # slightly brittle, but assuming application.css
46
+ # will always ship w/ app...
47
+ @requested_asset = 'stylesheets/application.css'
48
+ @mangler = make_mangler_with(@requested_asset)
49
+ end
50
+
51
+ should "return the full (local) path to the file prepended with 'file://'" do
52
+ css_path = File.join(Rails.root, 'public', 'stylesheets', 'application.css')
53
+ assert_equal "file://#{css_path}", @mangler.to_local_src
54
+ end
55
+ end
56
+ end
57
+
58
+ context "when requesting an Attachment" do
59
+ context "using a URI in the form of 'attachments/download/200'"do
60
+ setup do
61
+ @requested_asset = '/attachments/download/200'
62
+ @mangler = make_mangler_with(@requested_asset)
63
+ end
64
+
65
+ should "search for an attachment with an id of '200'" do
66
+ Attachment.expects(:find).with(:first, {:conditions => {:id => '200'}})
67
+ @mangler.to_local_src
68
+ end
69
+ end
70
+
71
+ context "using a URI in the form of 'attachments/2/after.png'"do
72
+ setup do
73
+ @requested_asset = 'attachments/2/after.png'
74
+ @mangler = make_mangler_with(@requested_asset)
75
+ end
76
+
77
+ should "search for an attachment with an id of '2'" do
78
+ Attachment.expects(:find).with(:first, :conditions => {:id => '2'})
79
+ @mangler.to_local_src
80
+ end
81
+ end
82
+
83
+ context "which does not exist" do
84
+ setup do
85
+ @requested_asset = '/attachments/download/1'
86
+ @mangler = make_mangler_with(@requested_asset)
87
+ Attachment.expects(:find).returns(nil)
88
+ end
89
+
90
+ should "return the original value without any modifications" do
91
+ assert_equal @requested_asset, @mangler.to_local_src
92
+ end
93
+ end
94
+
95
+ context "which exists" do
96
+ setup do
97
+ # Set up faux local file location & Attachment instance
98
+ @local_path = '/a/local/path/to/file.png'
99
+ @req_attachment = mock_file
100
+ @req_attachment.stubs(:diskfile).returns(@local_path)
101
+
102
+ # Stub finding the instance
103
+ Attachment.stubs(:find).returns(@req_attachment)
104
+
105
+ @requested_asset = '/attachments/download/200'
106
+ @mangler = make_mangler_with(@requested_asset)
107
+ end
108
+
109
+ should "render the full (local) path to the file" do
110
+ assert_equal "file://#{@local_path}", @mangler.to_local_src
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,101 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper'
2
+
3
+ class ChiliPdfHelperTest < HelperTestCase
4
+ include ChiliPdfHelper
5
+
6
+ context "#chili_pdf_stylesheets" do
7
+ should "include the pdf.css stylesheet" do
8
+ assert_match %r(<link.*href=['"].*pdf\.css['"].*>), chili_pdf_stylesheets(false)
9
+ end
10
+
11
+ context "when making an HTML request" do
12
+ should "set the vale of the 'href' attribute to a relative URL" do
13
+ assert_match %r(<link.*href=['"]/.*\.css['"].*>), chili_pdf_stylesheets(true)
14
+ end
15
+ end
16
+
17
+ context "when making a PDF request" do
18
+ should "set the vale of the 'href' attribute to a file://-based location" do
19
+ assert_match %r(<link.*href=['"]file://.*\.css['"].*>), chili_pdf_stylesheets(false)
20
+ end
21
+ end
22
+ end
23
+
24
+ context "#chili_pdf_javascripts" do
25
+ should "include the prototype JavaScript library" do
26
+ assert_match %r(<script.*src=['"].*prototype\.js['"].*></script>), chili_pdf_javascripts(false)
27
+ end
28
+
29
+ context "when making an HTML request" do
30
+ should "set the vale of the 'src' attribute to a relative URL" do
31
+ assert_match %r(<script.*src=['"]/.*\.js['"].*></script>), chili_pdf_javascripts(true)
32
+ end
33
+ end
34
+
35
+ context "when making a PDF request" do
36
+ should "set the vale of the 'src' attribute to a file://-based location" do
37
+ assert_match %r(<script.*src=['"]file://.*\.js['"].*></script>), chili_pdf_javascripts(false)
38
+ end
39
+ end
40
+ end
41
+
42
+ context "#normalize_custom_link_href_tags_in" do
43
+ setup do
44
+ @html = "<link href='/stylesheets/application.css' />"
45
+ end
46
+
47
+ context "when making an HTML request" do
48
+ should "set the vale of the 'href' attribute to a relative URL" do
49
+ results = normalize_custom_link_href_tags_in(@html, true)
50
+ assert_match %r(<link.*href=['"]/stylesheets/application\.css['"].*>), results
51
+ end
52
+ end
53
+
54
+ context "when making a PDF request" do
55
+ should "set the vale of the 'href' attribute to a file://-based location" do
56
+ results = normalize_custom_link_href_tags_in(@html, false)
57
+ assert_match %r(<link.*href=['"]file://.*/stylesheets/application\.css['"].*>), results
58
+ end
59
+ end
60
+ end
61
+
62
+ context "#normalize_custom_js_src_tags_in" do
63
+ setup do
64
+ @html = "<script src='/plugin_assets/chili_pdf/javascripts/chili_pdf.js'></script>"
65
+ end
66
+
67
+ context "when making an HTML request" do
68
+ should "set the vale of the 'src' attribute to a relative URL" do
69
+ results = normalize_custom_js_src_tags_in(@html, true)
70
+ assert_match %r(<script.*src=['"]/plugin_assets/chili_pdf/javascripts/chili_pdf\.js['"].*></script>), results
71
+ end
72
+ end
73
+
74
+ context "when making a PDF request" do
75
+ should "set the vale of the 'src' attribute to a file://-based location" do
76
+ results = normalize_custom_js_src_tags_in(@html, false)
77
+ assert_match %r(<script.*src=['"]file://.*/plugin_assets/chili_pdf/javascripts/chili_pdf\.js['"].*></script>), results
78
+ end
79
+ end
80
+ end
81
+
82
+ context "#update_img_src_tags_of" do
83
+ setup do
84
+ @html = "<img src='/images/cancel.png'>"
85
+ end
86
+
87
+ context "when making an HTML request" do
88
+ should "set the vale of the 'src' attribute to a relative URL" do
89
+ results = update_img_src_tags_of(@html, true)
90
+ assert_match %r(<img.*src=['"]/images/cancel\.png['"].*>), results
91
+ end
92
+ end
93
+
94
+ context "when making a PDF request" do
95
+ should "set the vale of the 'src' attribute to a file://-based location" do
96
+ results = update_img_src_tags_of(@html, false)
97
+ assert_match %r(<img.*src=['"]file://.*/images/cancel\.png['"].*>), results
98
+ end
99
+ end
100
+ end
101
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chili_pdf
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tom Kersten
@@ -36,7 +36,7 @@ cert_chain:
36
36
  NVADJA==
37
37
  -----END CERTIFICATE-----
38
38
 
39
- date: 2011-06-13 00:00:00 -05:00
39
+ date: 2011-06-18 00:00:00 -05:00
40
40
  default_executable:
41
41
  dependencies:
42
42
  - !ruby/object:Gem::Dependency
@@ -45,20 +45,34 @@ dependencies:
45
45
  requirement: &id001 !ruby/object:Gem::Requirement
46
46
  none: false
47
47
  requirements:
48
- - - "="
48
+ - - ~>
49
49
  - !ruby/object:Gem::Version
50
- hash: 3
50
+ hash: 5
51
51
  segments:
52
52
  - 0
53
53
  - 7
54
- - 0
55
- version: 0.7.0
54
+ version: "0.7"
56
55
  type: :runtime
57
56
  version_requirements: *id001
58
57
  - !ruby/object:Gem::Dependency
59
- name: hoe
58
+ name: nokogiri
60
59
  prerelease: false
61
60
  requirement: &id002 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ hash: 7
66
+ segments:
67
+ - 1
68
+ - 4
69
+ version: "1.4"
70
+ type: :runtime
71
+ version_requirements: *id002
72
+ - !ruby/object:Gem::Dependency
73
+ name: hoe
74
+ prerelease: false
75
+ requirement: &id003 !ruby/object:Gem::Requirement
62
76
  none: false
63
77
  requirements:
64
78
  - - ">="
@@ -70,7 +84,7 @@ dependencies:
70
84
  - 0
71
85
  version: 2.8.0
72
86
  type: :development
73
- version_requirements: *id002
87
+ version_requirements: *id003
74
88
  description: ChiliProject (/Redmine) plugin which implements/enhances PDF-export functionality using the Webkit rendering engine (via the 'wkhtmltopdf' executable).
75
89
  email:
76
90
  - tom@whitespur.com
@@ -96,7 +110,11 @@ files:
96
110
  - app/helpers/chili_pdf_helper.rb
97
111
  - app/views/extended_wiki/show.pdf.html.erb
98
112
  - app/views/layouts/pdf.pdf.erb
113
+ - app/views/settings/_chili_pdf_advanced_settings.html.erb
99
114
  - app/views/settings/_chili_pdf_settings.html.erb
115
+ - app/views/settings/_chili_pdf_typical_settings.html.erb
116
+ - assets/javascripts/chili_pdf.js
117
+ - assets/stylesheets/chili_pdf_settings_tweaks.css
100
118
  - assets/stylesheets/pdf.css
101
119
  - autotest/discover.rb
102
120
  - config/locales/en.yml
@@ -107,6 +125,7 @@ files:
107
125
  - lib/chili_pdf/config.rb
108
126
  - lib/chili_pdf/formatter.rb
109
127
  - lib/chili_pdf/string_token.rb
128
+ - lib/chili_pdf/tag_mangler.rb
110
129
  - lib/chili_pdf/token_manager.rb
111
130
  - lib/tasks/chili_pdf_tasks.rb
112
131
  - lib/tasks/contributor_tasks.rb
@@ -116,10 +135,12 @@ files:
116
135
  - test/chili_pdf/config_test.rb
117
136
  - test/chili_pdf/formatter_test.rb
118
137
  - test/chili_pdf/string_token_test.rb
138
+ - test/chili_pdf/tag_mangler_test.rb
119
139
  - test/chili_pdf/token_manager_test.rb
120
140
  - test/test_helper.rb
141
+ - test/unit/helpers/chili_pdf_helper_test.rb
121
142
  has_rdoc: true
122
- homepage: http://github.com/tomkersten/chili_pdf
143
+ homepage: http://github.com/tomkersten/chili\_pdf
123
144
  licenses: []
124
145
 
125
146
  post_install_message:
metadata.gz.sig CHANGED
Binary file