tenon 1.0.56 → 1.0.57

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d25f0289d0204d15f98fd5cdee6f4eb20c02d57
4
- data.tar.gz: addc833b08b5718662d201b4eef53661f291cba8
3
+ metadata.gz: 2fa377e208a93cb3c4055726e4426d6c19071b95
4
+ data.tar.gz: 4a579c1c5d84967166901b55a7f4b99f64e6c7a2
5
5
  SHA512:
6
- metadata.gz: e752b86e68bcb4f30a3b209f7fc48145f2eab331f0840db60b5ca6f137d850b4a06064a755bf123e01b2d209d2f92d6e707da23b2fb425250f730a50dc737e19
7
- data.tar.gz: 84ea75bbfd4a959d4f3075a889508f4e52ef7958813cc1ebc66aad6c1f4b1636d996cc0c2dedcd0a7181f0cb5b313bb732a9a3970247695da9c521ca20d8e029
6
+ metadata.gz: e40afd867429f2e8022e558b10817730a56371cbb28fa678a86e07bca8c47f7ae474cabdbbbad876bd7868fd8f38a7637ce4c03baa3bc35164b1860bb9cfa9d7
7
+ data.tar.gz: 18ad631a0e525d60ee8397df3eacf4b5e9c936d85de9d59879a0f69b75d97332b1a49c1d8ce18eac0c9e0215af079df1495f3f86bda7b00ba77ae0492512fc03
@@ -28,7 +28,7 @@ class Tenon.features.tenonContent.ColumnSizing
28
28
  @_setSizes(word, newClass, siblingClass, newSiblingClass)
29
29
 
30
30
  _decreaseFrom: (word, num) =>
31
- unless num <= 2
31
+ unless num <= 1
32
32
  siblingClass = @_numberToWord(@_words.length - num)
33
33
  newSiblingClass = @_numberToWord(@_words.length - num + 1)
34
34
  newClass = @_numberToWord(num - 1)
@@ -4,6 +4,10 @@ module Tenon
4
4
  h.asset_icon(object)
5
5
  end
6
6
 
7
+ def tile
8
+ h.asset_tile(object)
9
+ end
10
+
7
11
  def human_size
8
12
  h.number_to_human_size(object.attachment_file_size)
9
13
  end
@@ -2,11 +2,11 @@ module Tenon
2
2
  module AssetHelper
3
3
  def asset_icon(asset)
4
4
  if asset.attachment.exists?(:thumbnail)
5
- i = image_tag(asset.attachment.url(:thumbnail))
5
+ image = image_tag(asset.attachment.url(:thumbnail))
6
6
  else
7
- i = image_tag(default_asset_thumbnail(asset))
7
+ image = image_tag(default_asset_thumbnail(asset))
8
8
  end
9
- asset_icon_link(asset, i)
9
+ asset_icon_link(asset, image)
10
10
  end
11
11
 
12
12
  def asset_icon_link(asset, icon)
@@ -17,6 +17,23 @@ module Tenon
17
17
  end
18
18
  end
19
19
 
20
+ def asset_tile(asset)
21
+ if asset.attachment.exists?(:tile)
22
+ image = image_tag(asset.attachment.url(:tile))
23
+ else
24
+ image = image_tag(default_asset_thumbnail(asset))
25
+ end
26
+ asset_tile_link(asset, image)
27
+ end
28
+
29
+ def asset_tile_link(asset, icon)
30
+ if asset.is_image?
31
+ link_to(icon, [:crop, asset], crop_options(asset))
32
+ else
33
+ link_to(icon, asset.attachment.url, target: '_')
34
+ end
35
+ end
36
+
20
37
  def default_asset_thumbnail(asset)
21
38
  if asset && asset.attachment_content_type.match('video')
22
39
  'tenon/thumb-video.png'
@@ -26,22 +43,21 @@ module Tenon
26
43
  end
27
44
 
28
45
  private
29
-
30
- def crop_options(asset)
31
- {
32
- class: 'asset-crop',
33
- data: {
34
- 'asset-id' => asset.id,
35
- 'post-crop-handler' => 'Tenon.features.AssetListPostCropHandler'
46
+ def crop_options(asset)
47
+ {
48
+ class: 'asset-crop',
49
+ data: {
50
+ 'asset-id' => asset.id,
51
+ 'post-crop-handler' => 'Tenon.features.AssetListPostCropHandler'
52
+ }
36
53
  }
37
- }
38
- end
54
+ end
39
55
 
40
- def default_options
41
- {
42
- 'data-modal-remote' => true,
43
- 'data-modal-title' => 'Edit Asset'
44
- }
56
+ def default_options
57
+ {
58
+ 'data-modal-remote' => true,
59
+ 'data-modal-title' => 'Edit Asset'
60
+ }
61
+ end
45
62
  end
46
- end
47
63
  end
@@ -0,0 +1,77 @@
1
+ module Tenon
2
+ module PieceHelper
3
+ def piece_image_tag(piece, options = {})
4
+ responsive_image_tag(piece, options, Tenon.config.breakpoints.front_end)
5
+ end
6
+
7
+ def backend_piece_image_tag(piece, options = {})
8
+ responsive_image_tag(piece, options, Tenon.config.breakpoints.back_end)
9
+ end
10
+
11
+ private
12
+ # Returns the actual image_tag
13
+ def responsive_image_tag(piece, options = {}, breakpoints)
14
+ srcset = generate_srcset(piece)
15
+ sizes = generate_sizes(piece, breakpoints)
16
+ # Let's just use an plain image_tag if responsive styles haven't been
17
+ # generated. We'll test for :x2000 to determine if that's the case
18
+ if piece.image.attachment.exists?(computed_style(piece, 'x2000'))
19
+ image_tag(piece.image.url(default_style(piece, breakpoints)), options.merge(srcset: srcset, sizes: sizes))
20
+ else
21
+ image_tag(piece.image.url(:_medium), options)
22
+ end
23
+ end
24
+
25
+ # Figure out the default style based on the largest size at the largest
26
+ # breakpoint for browsers that don't support srcset. This is at least
27
+ # better than always serving the largest style (:x2000).
28
+ def default_style(piece, breakpoints)
29
+ sizes = breakpoints[:full]
30
+
31
+ # calculate the image size at :full breakpoint based on the piece width
32
+ image_size = (piece.sizes[piece_size(piece).to_sym] / 12 * content_size(sizes, piece)).to_i
33
+
34
+ # round up to nearest 200
35
+ image_size = image_size.round(-2)
36
+ image_size += 100 if (image_size / 100).odd?
37
+
38
+ default_style = computed_style(piece, "x#{image_size}").to_sym
39
+
40
+ piece.image.attachment.exists?(default_style) ? default_style : :_medium
41
+ end
42
+
43
+ # Iterate through the defined breakpoints and lookup the tenon_content
44
+ # sizes for the piece's row's item type. Use sizes[:default] width if
45
+ # item_type-specific tenon_content width not defined.
46
+ def generate_sizes(piece, breakpoints)
47
+ breakpoints.map do |name, sizes|
48
+ "(min-width: #{sizes[:browser]}px) #{(piece.sizes[piece_size(piece).to_sym] / 12 * 100 * content_size(sizes, piece) / sizes[:browser]).to_i}vw"
49
+ end.join(', ')
50
+ end
51
+
52
+ # Build the srcset values from the list of piece styles (2000px-200px)
53
+ def generate_srcset(piece)
54
+ piece.styles.map do |name, width|
55
+ if piece.image.attachment.exists?(computed_style(piece, name).to_sym)
56
+ "#{piece.image.attachment.url(computed_style(piece, name).to_sym)} #{width}w"
57
+ else
58
+ "#{piece.image.attachment.url(:original)} #{width}w"
59
+ end
60
+ end.join(', ')
61
+ end
62
+
63
+ # Handle 'twelve' pieces that have size set to '' in the db
64
+ def piece_size(piece)
65
+ piece_size = piece.size == '' ? 'twelve' : piece.size
66
+ end
67
+
68
+ def computed_style(piece, style)
69
+ computed_style = "#{piece.image.style_prefix}_#{style}"
70
+ end
71
+
72
+ # Return the width of tenon_content for this piece, or the :default size
73
+ def content_size(sizes, piece)
74
+ sizes[piece.row.item_type.demodulize.downcase.to_sym] || sizes[:default]
75
+ end
76
+ end
77
+ end
@@ -28,18 +28,18 @@ module Tenon
28
28
 
29
29
  def tenon_content_sizes
30
30
  links = []
31
- Tenon.config.front_end[:breakpoints].each do |name, size|
32
- links << link_to(name.to_s.titleize, '#', class: 'btn btn-white', data: { size: size_for_breakpoint(size) })
31
+ Tenon.config.breakpoints.front_end.each do |name, widths|
32
+ links << link_to(name.to_s.titleize, '#', class: 'btn btn-white', data: { size: size_for_breakpoint(widths[:default]) })
33
33
  end
34
- last = Tenon.config.front_end[:breakpoints].values.last
34
+ last = Tenon.config.breakpoints.front_end.values.last
35
35
  links << link_to('Mobile', '#', class: 'btn btn-white', data: { size: 320, mobile: true })
36
36
  links.join('').html_safe
37
37
  end
38
38
 
39
39
  def size_for_breakpoint(breakpoint)
40
- content_cols = Tenon.config.front_end[:content_columns][:default]
41
- gutter_width = Tenon.config.front_end[:gutter]
42
- columns = Tenon.config.front_end[:columns]
40
+ content_cols = Tenon.config.grid.content_columns[:default]
41
+ gutter_width = Tenon.config.grid.gutter
42
+ columns = Tenon.config.grid.columns
43
43
  (((breakpoint + gutter_width) / columns.to_f) * content_cols) - gutter_width
44
44
  end
45
45
  end
@@ -1,6 +1,7 @@
1
1
  module Tenon
2
2
  class Asset < ActiveRecord::Base
3
3
  attr_accessor :crop_x, :crop_y, :crop_w, :crop_h, :duplicate
4
+
4
5
  # Scopes
5
6
  default_scope -> { order('created_at DESC').includes(:item_assets) }
6
7
 
@@ -1,7 +1,10 @@
1
1
  module Tenon
2
2
  class Photo < ActiveRecord::Base
3
3
  belongs_to :gallery, class_name: 'Gallery', foreign_key: 'gallery_id', inverse_of: :photos
4
- has_asset :file, styles: { original: '800x800>', thumbnail: '300x300#' }
4
+ has_asset :file, styles: {
5
+ original: '800x800>',
6
+ thumbnail: '300x300#' # DEPRECATED
7
+ }
5
8
  default_scope { order(:list_order) }
6
9
  end
7
10
  end
@@ -2,9 +2,43 @@ module Tenon
2
2
  module TenonContent
3
3
  class Piece < ActiveRecord::Base
4
4
  self.table_name = 'tenon_tenon_content_pieces'
5
+ attr_reader :sizes, :styles
6
+
7
+ def sizes
8
+ # to translate between the stored piece size in words and a number for math
9
+ {
10
+ :one => 1.0,
11
+ :two => 2.0,
12
+ :three => 3.0,
13
+ :four => 4.0,
14
+ :five => 5.0,
15
+ :six => 6.0,
16
+ :seven => 7.0,
17
+ :eight => 8.0,
18
+ :nine => 9.0,
19
+ :ten => 10.0,
20
+ :eleven => 11.0,
21
+ :twelve => 12.0
22
+ }
23
+ end
24
+
25
+ def styles
26
+ Hash[(1..10).map{|n| ["x#{n*200}", (n*200).to_s]}]
27
+ end
5
28
 
6
29
  # Scopes, attachments, etc.
7
- has_asset :image, styles: { wrap: '400', half: '600', full: '1400' }
30
+ has_asset :image, styles: {
31
+ x2000: '2000>',
32
+ x1800: '1800>',
33
+ x1600: '1600>',
34
+ x1400: '1400>',
35
+ x1200: '1200>',
36
+ x1000: '1000>',
37
+ x800: '800>',
38
+ x600: '600>',
39
+ x400: '400>',
40
+ x200: '200>'
41
+ }
8
42
 
9
43
  # Relationships
10
44
  belongs_to :row, class_name: '::Tenon::TenonContent::Row'
@@ -1,5 +1,5 @@
1
1
  json.extract!(asset,
2
- :id, :display_name, :icon, :to_param, :human_size,
2
+ :id, :display_name, :icon, :tile, :to_param, :human_size,
3
3
  :attachment_content_type, :edit_link, :delete_link,
4
4
  :crop_link, :download_link
5
5
  )
@@ -1,9 +1,9 @@
1
1
  .tn-tc-image{class: piece.stretch_to_fill? ? 'stretch' : ''}
2
2
  - if piece.image.present?
3
3
  - if piece.link_url.blank?
4
- = image_tag(piece.image.url(:_medium))
4
+ = piece_image_tag(piece)
5
5
  - else
6
- = link_to image_tag(piece.image.url(:_medium)), piece.link_url, target: '_'
6
+ = link_to piece_image_tag(piece), piece.link_url, target: '_'
7
7
  - else
8
8
  = image_tag('tenon/thumb-doc.png')
9
9
  - if piece.show_caption
@@ -4,7 +4,7 @@
4
4
  = f.hidden_field :stretch_to_fill
5
5
  .image{class: f.object.stretch_to_fill? ? 'stretch' : ''}
6
6
  - if f.object.image
7
- = image_tag(f.object.image.url(:_medium))
7
+ = backend_piece_image_tag(f.object)
8
8
  - else
9
9
  = link_to(new_item_asset_path, class: 'add-image', data: {'modal-remote' => true, 'modal-title' => "Select Image", 'modal-handler' => 'Tenon.features.tenonContent.AssetAttachment'}) do
10
10
  %span Add Image
@@ -2,21 +2,43 @@
2
2
  # by the site developer. There is a Settings module built into Tenon
3
3
  # where you can expose other settings to your client.
4
4
  Tenon.configure do |config|
5
- # Set up grid config for the front end. This is done here so that we can
6
- # present accurate sizing
7
- config.front_end = {
8
- breakpoints: {
9
- desktop: 1400,
10
- laptop: 960,
11
- tablet: 768
12
- },
13
- columns: 24,
14
- gutter: 20,
5
+ # Define all your breakpoints and associated tenon_content widths.
6
+ # This is necessary because you may have multiple models with tenon_content
7
+ # with different maximum widths and therefore different widths at various
8
+ # breakpoints. By getting more precise with these widths we can serve the
9
+ # most efficient responsive images to the front end.
10
+ # config.breakpoints.front_end = {
11
+ # full: {
12
+ # browser: 1920, # the width of the browser for this breakpoint
13
+ # default: 1920, # default tenon_content width for piece's without specific widths
14
+ # page: 1920, # the width of tenon_content for Pages
15
+ # post: 1920 # the width of tenon_content for Posts
16
+ # },
17
+ # desktop: {
18
+ # browser: 1400,
19
+ # default: 1400,
20
+ # page: 1400,
21
+ # post: 1400
22
+ # },
23
+ # laptop: {
24
+ # browser: 960,
25
+ # default: 960,
26
+ # page: 960,
27
+ # post: 960
28
+ # },
29
+ # tablet: {
30
+ # browser: 768,
31
+ # default: 768,
32
+ # page: 768,
33
+ # post: 768
34
+ # }
35
+ # }
15
36
 
16
- content_columns: {
17
- default: 18
18
- }
19
- }
37
+ # config.grid.columns = 24
38
+ # config.grid.gutter = 20
39
+ # config.grid.content_columns = {
40
+ # default: 18
41
+ # }
20
42
 
21
43
  # Set platform hints color(s)
22
44
  config.client_color = '#9c0f17'
@@ -47,4 +69,19 @@ Tenon.configure do |config|
47
69
 
48
70
  # If you need to add further config options you can add them
49
71
  # in lib/tenon.rb as attr_accessors to Tenon::Configuration
72
+
73
+ # config.front_end is DEPRECATED as of 1.0.57
74
+ config.front_end = {
75
+ breakpoints: {
76
+ desktop: 1400,
77
+ laptop: 960,
78
+ tablet: 768
79
+ },
80
+ columns: 24,
81
+ gutter: 20,
82
+
83
+ content_columns: {
84
+ default: 18
85
+ }
86
+ }
50
87
  end
@@ -1,4 +1,43 @@
1
- # desc "Explaining what the task does"
2
- # task :tenon do
3
- # # Task goes here
4
- # end
1
+ namespace :tenon do
2
+ desc "Generate Asset responsive styles"
3
+ task :generate_responsive_styles => :environment do
4
+ styles = [
5
+ :tenon_tenon_content_piece_image_x2000,
6
+ :tenon_tenon_content_piece_image_x1800,
7
+ :tenon_tenon_content_piece_image_x1600,
8
+ :tenon_tenon_content_piece_image_x1400,
9
+ :tenon_tenon_content_piece_image_x1200,
10
+ :tenon_tenon_content_piece_image_x1000,
11
+ :tenon_tenon_content_piece_image_x800,
12
+ :tenon_tenon_content_piece_image_x600,
13
+ :tenon_tenon_content_piece_image_x400,
14
+ :tenon_tenon_content_piece_image_x200
15
+ ]
16
+
17
+ item_assets = Tenon::ItemAsset.where(item_type: 'Tenon::TenonContent::Piece').pluck(:asset_id).uniq
18
+
19
+ # only reprocess assets that are referenced by Pieces, and only do them once each even if they are referenced by multiple pieces
20
+ Tenon::Asset.find(item_assets).each_with_index do |asset, i|
21
+ print "(#{i+1}/#{item_assets.count}) #{asset.attachment_file_name} "
22
+ styles.each do |style|
23
+ asset.attachment.reprocess! style
24
+ print '.'
25
+ $stdout.flush
26
+ end
27
+ puts ''
28
+ end
29
+ puts 'Done!'
30
+ end
31
+
32
+ desc "Regenerate all Asset styles"
33
+ task :regenerate_asset_styles => :environment do
34
+ total_assets = Tenon::Asset.all.count
35
+
36
+ Tenon::Asset.all.each_with_index do |asset, i|
37
+ puts "(#{i+1}/#{total_assets}) #{asset.attachment_file_name} "
38
+ asset.attachment.reprocess!
39
+ end
40
+ puts 'Done!'
41
+ end
42
+
43
+ end
@@ -22,7 +22,8 @@ module Tenon
22
22
  {
23
23
  original: { processors: ['cropper'], geometry: '' },
24
24
  thumbnail: '200x200#',
25
- medium: '1400>'
25
+ medium: '1400>', # DEPRECATED
26
+ tile: '350x350#',
26
27
  }
27
28
  end
28
29
 
@@ -0,0 +1,77 @@
1
+ module Tenon
2
+ class Configuration
3
+ attr_accessor :breakpoints
4
+
5
+ def breakpoints
6
+ @breakpoints ||= BreakpointConfiguration.new
7
+ end
8
+
9
+ class BreakpointConfiguration
10
+ attr_accessor :front_end, :back_end, :grid
11
+
12
+ def initialize
13
+ # Define all your breakpoints and associated tenon_content widths.
14
+ # This is necessary because you may have multiple models with tenon_content
15
+ # with different maximum widths and therefore different widths at various
16
+ # breakpoints. By getting more precise with these widths we can serve the
17
+ # most efficient responsive images to the front end.
18
+ @front_end = {
19
+ full: {
20
+ browser: 1920, # the width of the browser for this breakpoint
21
+ default: 1920, # default tenon_content width for piece's without specific widths
22
+ page: 1920, # the width of tenon_content for Pages
23
+ post: 1920 # the width of tenon_content for Posts
24
+ },
25
+ desktop: {
26
+ browser: 1400,
27
+ default: 1400,
28
+ page: 1400,
29
+ post: 1400
30
+ },
31
+ laptop: {
32
+ browser: 960,
33
+ default: 960,
34
+ page: 960,
35
+ post: 960
36
+ },
37
+ tablet: {
38
+ browser: 768,
39
+ default: 768,
40
+ page: 768,
41
+ post: 768
42
+ }
43
+ }
44
+
45
+ # set up the back-end breakpoints and associated tenon_content widths since
46
+ # we know what they always are
47
+ @back_end = {
48
+ full: {
49
+ browser: 1920,
50
+ default: 1225
51
+ },
52
+ desktop: {
53
+ browser: 1400,
54
+ default: 740
55
+ },
56
+ laptop: {
57
+ browser: 960,
58
+ default: 680
59
+ },
60
+ tablet: {
61
+ browser: 768,
62
+ default: 750
63
+ }
64
+ }
65
+
66
+ @grid = {
67
+ columns: 24,
68
+ gutter: 20,
69
+
70
+ content_columns: {
71
+ default: 18
72
+ }
73
+ }
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,21 @@
1
+ module Tenon
2
+ class Configuration
3
+ attr_accessor :grid
4
+
5
+ def grid
6
+ @grid ||= GridConfiguration.new
7
+ end
8
+
9
+ class GridConfiguration
10
+ attr_accessor :columns, :gutter, :content_columns
11
+
12
+ def initialize
13
+ @columns = 24
14
+ @gutter = 20
15
+ @content_columns = {
16
+ default: 18
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,6 @@
1
1
  module Tenon
2
2
  class ProxyAttachment
3
- attr_reader :attachment, :asset
3
+ attr_reader :attachment, :asset, :style_prefix
4
4
 
5
5
  def initialize(attachment, klass, asset_name)
6
6
  @attachment = attachment.try(:attachment) || attachment
data/lib/tenon/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tenon
2
- VERSION = '1.0.56'
2
+ VERSION = '1.0.57'
3
3
  end
data/lib/tenon.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'tenon/engine'
2
+ require 'tenon/config/breakpoints.rb'
2
3
  require 'tenon/config/events.rb'
4
+ require 'tenon/config/grid.rb'
3
5
  require 'tenon/can_be_foreign.rb'
4
6
  require 'tenon/can_have_comments.rb'
5
7
  require 'tenon/has_asset.rb'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tenon
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.56
4
+ version: 1.0.57
5
5
  platform: ruby
6
6
  authors:
7
7
  - factor[e] design initiative
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-28 00:00:00.000000000 Z
11
+ date: 2015-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: better_errors
@@ -1110,6 +1110,7 @@ files:
1110
1110
  - app/helpers/tenon/i18n_helper.rb
1111
1111
  - app/helpers/tenon/item_version_helper.rb
1112
1112
  - app/helpers/tenon/nav_helper.rb
1113
+ - app/helpers/tenon/piece_helper.rb
1113
1114
  - app/helpers/tenon/platform_hints_helper.rb
1114
1115
  - app/helpers/tenon/tenon_content_helper.rb
1115
1116
  - app/helpers/tenon/tenon_helper.rb
@@ -1378,7 +1379,9 @@ files:
1378
1379
  - lib/tenon/asset_style_generator.rb
1379
1380
  - lib/tenon/can_be_foreign.rb
1380
1381
  - lib/tenon/can_have_comments.rb
1382
+ - lib/tenon/config/breakpoints.rb
1381
1383
  - lib/tenon/config/events.rb
1384
+ - lib/tenon/config/grid.rb
1382
1385
  - lib/tenon/engine.rb
1383
1386
  - lib/tenon/factories/assets.rb
1384
1387
  - lib/tenon/factories/comments.rb