comfy_middle_seat 4.3.0 → 4.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9433cede5d17f15d7c30a4a6bb30e9951ddb944129c317dc8b9a008f8e8d69f0
4
- data.tar.gz: 6f30614dae87dfc9735ee436c640f5431ef66e58a084483549fb105ab43bffa2
3
+ metadata.gz: 5f6717192c25596be740e0176e1ae1f6e4b0bd5dd07a71a5f7a8271ad047fc10
4
+ data.tar.gz: 7c18f5c772a0ee0a8bab66870066d515b6977a5a962484479eccf5a7c2d9525b
5
5
  SHA512:
6
- metadata.gz: fba6ed160d2930727df376eb665f184df898ad3bf732b45a734abbee4f4edbe0f063f056db66c8f95adcba9111b9fd43a0640f8f5aebb1860c36b451ddcc09d5
7
- data.tar.gz: f0801cb516d4d98bd8adc25c8e51bf73c2fc13b25f8930a6597c854abd216dd7a98ba5b08dd214cd45f85f73139844a7e5a6a3bb7771e8bd6c66954dd026c187
6
+ metadata.gz: b940efa50666b34b7963839d60fa6265ce5f84566c959388e981cf9e29c02757d9e37a330c59150cebe1c09a27e8c6d2bd72f040922664e7ef39cc37aadd7195
7
+ data.tar.gz: '088311053691f043a38462dd1f9b84d57c6a8fff0ae88afe97803d339dc1feceacefff99c99d6b3c52ab0627fe50d324634680e22e8878d0565df78e13be0142'
@@ -39,6 +39,9 @@ jobs:
39
39
  ruby-version: ${{ matrix.ruby-version }}
40
40
  bundler-cache: true
41
41
 
42
+ - name: Install image processors
43
+ run: sudo apt-get update && sudo apt-get install -y imagemagick libvips-dev
44
+
42
45
  - name: Update CMS gem
43
46
  run: bundle update comfy_middle_seat
44
47
 
@@ -40,6 +40,9 @@ jobs:
40
40
  ruby-version: ${{ matrix.ruby-version }}
41
41
  bundler-cache: true
42
42
 
43
+ - name: Install image processors
44
+ run: sudo apt-get update && sudo apt-get install -y imagemagick libvips-dev
45
+
43
46
  - name: Update CMS gem
44
47
  run: bundle update comfy_middle_seat
45
48
 
data/CHANGELOG.md CHANGED
@@ -14,9 +14,33 @@ This changelog follows the project's lineage: **Comfortable Mexican Sofa → Com
14
14
 
15
15
  ### Added
16
16
 
17
- - Add CMS comment blocks and short notes to hide content without processing enclosed tags.
18
- - Expand CMS tags with editor shortcuts and searchable completion.
19
- - Open the shortcut selector with `;;` + Tab and filter with fuzzy search.
17
+ - Add `layout_asset`, `render_partial`, and `render_template` aliases; existing tags remain supported.
18
+
19
+ ### Changed
20
+
21
+ - Generate layout asset links through Rails routes and HTML helpers.
22
+
23
+ ## [v4.4.0] - 2026-10-25
24
+
25
+ ### Added
26
+
27
+ - Resize, crop, and pad images with ImageMagick or Vips.
28
+ - Validate image dimensions with a configurable size limit.
29
+
30
+ ### Fixed
31
+
32
+ - Restore supported legacy image resizing and modernize admin thumbnails.
33
+ - Keep original file links for images that cannot be resized.
34
+
35
+ **Upgrading:** Clear rendered page and translation caches. Review legacy sizing options and the new 4096-pixel limit; see [image resizing](README.md#image-resizing). No database migration is required.
36
+
37
+ ## [v4.3.0] - 2026-10-17
38
+
39
+ ### Added
40
+
41
+ - Hide content with CMS comment blocks and add short inline notes.
42
+ - Insert CMS tags with editor shortcuts and selected parameter placeholders.
43
+ - Find shortcuts with `;;` + Tab or Ctrl+Space and fuzzy search.
20
44
 
21
45
  ## [v4.2.0] - 2026-10-13
22
46
 
@@ -262,7 +286,9 @@ First release of `comfortable_media_surfer`. This new gem is a revival of [Comfo
262
286
 
263
287
  - Rebranded **ComfortableMexicanSofa** as **ComfortableMediaSurfer** in order to publish new gem (database table names and schema have not changed).
264
288
 
265
- [Unreleased]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.2.0...master
289
+ [Unreleased]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.4.0...master
290
+ [v4.4.0]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.3.0...v4.4.0
291
+ [v4.3.0]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.2.0...v4.3.0
266
292
  [v4.2.0]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.1.0...v4.2.0
267
293
  [v4.1.0]: https://github.com/avonderluft/comfy-middle-seat/compare/v4.0.4...v4.1.0
268
294
  [v4.0.4]: https://github.com/avonderluft/comfy-middle-seat/compare/ea2bb99c0398e1f4d6e850a25e0c13afc577c3ad...v4.0.4
data/README.md CHANGED
@@ -114,6 +114,24 @@ A Site defines a hostname, path, and language. Layouts define page structure and
114
114
 
115
115
  When an editor creates a Page using this Layout, the admin automatically presents fields for `title` and `content`. Content tags can also provide Markdown, files, images, dates, numbers, checkboxes, snippets, partials, helpers, navigation, and other reusable content.
116
116
 
117
+ ### Descriptive tag aliases
118
+
119
+ These names are interchangeable; existing tags remain supported:
120
+
121
+ | Existing tag | Alias |
122
+ | --- | --- |
123
+ | `asset` | `layout_asset` |
124
+ | `partial` | `render_partial` |
125
+ | `template` | `render_template` |
126
+
127
+ ```liquid
128
+ {{ cms:layout_asset main, type: css, as: tag }}
129
+ {{ cms:render_partial "layouts/embed_video", id: MYpbvXgpIzc }}
130
+ {{ cms:render_template "marketing/landing" }}
131
+ ```
132
+
133
+ Aliases preserve all parameters, defaults, and existing allowlist behavior. No new allowlist requirement or content migration is introduced. Asset tags still require `type: css` or `type: js`; omitting the type does not default to CSS. Their URLs follow the configured Rails routes, not an independent manual override of `public_cms_path`. HTML attributes are preserved, though formatting may differ. Check for conflicts if your application already registers custom tags with these alias names.
134
+
117
135
  ### Editor shortcuts
118
136
 
119
137
  In HTML and Markdown code editors, type a shortcut and press **Tab** to insert a CMS tag. The parameter placeholder is selected so you can replace it immediately. For example, `;md` inserts `{{ cms:markdown content }}` with `content` selected.
@@ -152,7 +170,7 @@ Use the arrow keys and **Enter** or **Tab** to choose. The tag replaces the enti
152
170
  | `;ec` | `endcomment` | — |
153
171
  | `;end` | `end` | — |
154
172
 
155
- Placeholders are examples: replace them with your field names, identifiers, paths, or IDs. `;asset` inserts the CSS version; `;comment` inserts a full comment block.
173
+ Placeholders are examples: replace them with your field names, identifiers, paths, or IDs. `;asset` inserts the CSS version; `;comment` inserts a full comment block. The descriptive aliases (`;layout_asset`, `;render_partial`, `;render_template`) also work for expansion and search, inserting the existing tag spellings.
156
174
 
157
175
  Shortcuts work at the start of a line, after whitespace, or after `>`, outside an existing CMS tag. Unrecognized shortcuts retain normal Tab behavior. CSS, JavaScript, ordinary text fields, and visual editors are unchanged. Saved content uses the standard `{{ cms:... }}` syntax.
158
176
 
@@ -178,6 +196,62 @@ Comments produce no rendered output and do not create editor fields. Unlike HTML
178
196
 
179
197
  Blocks may be nested and must end with `{{cms:endcomment}}`, not `{{cms:end}}`. Short notes accept single or double quotes, with backslash-escaped quotes. Unclosed blocks and malformed comment tags raise a clear syntax error. Comments work in layouts, snippets, and rendered fragment content, including Markdown. They are not a place for secrets: original source remains available to editors and may be exposed by APIs that include raw content.
180
198
 
199
+ ### Image resizing
200
+
201
+ Resize images from the media library or page attachments without changing the originals:
202
+
203
+ ```liquid
204
+ {{ cms:image "Homepage banner", resize_to_limit: "1600x600" }}
205
+ {{ cms:file card_photo, as: image, resize_to_fill: "600x400" }}
206
+ {{ cms:image "Product photo", resize_and_pad: "500x500" }}
207
+ ```
208
+
209
+ The same options work with `file`, `files`, `image`, `file_link`, and `page_file_link`:
210
+
211
+ | Option | Result |
212
+ | --- | --- |
213
+ | `resize_to_limit` | Fit within the dimensions; never enlarge. |
214
+ | `resize_to_fit` | Fit within the dimensions; allow enlargement. |
215
+ | `resize_to_fill` | Fill the exact dimensions with a centered crop. |
216
+ | `resize_and_pad` | Fit the whole image into the exact dimensions with padding. |
217
+
218
+ Specify one operation and positive dimensions as `"WIDTHxHEIGHT"`. Invalid values, conflicting operations, and dimensions above the configured limit raise an error. Padding uses the processor's defaults; its color/transparency can differ between processors and image formats. Sizing options are ignored for missing attachments and files that Active Storage cannot transform, such as PDFs and SVGs under its default configuration. Missing attachments render nothing; non-transformable files retain their original URLs.
219
+
220
+ The default maximum requested width or height is 4096 pixels. Change it in `config/initializers/comfy_middle_seat.rb`:
221
+
222
+ ```ruby
223
+ ComfyMiddleSeat.configure do |config|
224
+ config.max_image_dimension = 6000
225
+ end
226
+ ```
227
+
228
+ This limits requested tag dimensions, not upload sizes or all intermediate processing memory. Admin thumbnails use fixed sizes.
229
+
230
+ The CMS respects your application's Active Storage processor. Use ImageMagick with `:mini_magick`, or install libvips and add `ruby-vips` to your application's Gemfile, then configure:
231
+
232
+ ```ruby
233
+ # config/application.rb, inside your application class
234
+ config.active_storage.variant_processor = :vips
235
+ ```
236
+
237
+ Restart after changing processors. No processor switch is required to use the new options; the gem retains its existing MiniMagick dependency for compatibility.
238
+
239
+ #### Existing image tags
240
+
241
+ - `resize: "400x300"` translates to `resize_to_fit`; `resize: "400x300>"` translates to `resize_to_limit`. Both work with either processor.
242
+ - Supported legacy combinations of `resize`, `gravity`, and `crop` retain their operation order under MiniMagick. Resize accepts `WxH` with an optional `>`, `<`, `!`, or `^` suffix; crop requires `WxH+X+Y` (signed offsets). Offset-free crops are rejected because ImageMagick treats them as tiling, not a single crop. Gravity accepts the standard compass positions and `center`.
243
+ - Other legacy geometry, including percentages and one-dimensional sizes, raises an actionable error. Replace it with an explicit two-dimensional operation. The size limit applies to legacy dimensions too.
244
+ - Complex legacy expressions are not silently approximated on Vips. Convert them before switching processors; do not mix legacy and modern options in a tag.
245
+
246
+ After upgrading, clear rendered page and translation caches once so image links use the new transformations:
247
+
248
+ ```ruby
249
+ Comfy::Cms::Page.update_all(content_cache: nil)
250
+ Comfy::Cms::Translation.update_all(content_cache: nil)
251
+ ```
252
+
253
+ No database migration or re-upload is needed. New variants are generated on demand and may increase storage use temporarily; originals and old variants are not deleted. Purge any external page/CDN HTML caches separately. Clear rendered caches again after changing the sizing policy. Active Storage's variant keys do not include the processor: switching processors reuses existing variants with the same options, even after clearing page caches. To regenerate those images with the new processor, invalidate the affected derived variants separately, preserving the original uploads, and clear any cached derivative files on your CDN.
254
+
181
255
  ### Publishing pages
182
256
 
183
257
  A page is publicly visible only when it and all its ancestors are published. Unpublishing a parent hides its branch without changing descendants’ individual publication settings. Republishing the parent restores only descendants whose full ancestor chain is published; drafts stay unpublished. Translations must also satisfy their own publication settings.
@@ -194,7 +268,7 @@ Development mode continues to show unpublished pages for preview. Check public v
194
268
  | Rails | CI tests 7.2, 8.0, and 8.1 |
195
269
  | Node.js | 18 or newer for asset compilation |
196
270
  | File storage | Active Storage |
197
- | Image processing | ImageMagick |
271
+ | Image processing | ImageMagick or libvips (via Active Storage) |
198
272
 
199
273
  Pagination is provided by [Kaminari](https://github.com/amatsuda/kaminari). The admin uses Bootstrap, CodeMirror, and Redactor.
200
274
 
@@ -25,12 +25,12 @@ const completions = [
25
25
  tag("fl", "file_link", "file_id, as: link", "file_id"),
26
26
  tag("pfl", "page_file_link", "attachment, as: link", "attachment"),
27
27
  tag("sn", "snippet", "identifier", "identifier"),
28
- tag("as", "asset", "layout_identifier, type: css, as: tag", "layout_identifier"),
28
+ tag("as", "asset", "layout_identifier, type: css, as: tag", "layout_identifier", ["layout_asset"]),
29
29
  tag("css", "asset", "layout_identifier, type: css, as: tag", "layout_identifier"),
30
30
  tag("js", "asset", "layout_identifier, type: js, as: tag", "layout_identifier"),
31
31
  tag("hlp", "helper", "method_name", "method_name"),
32
- tag("par", "partial", '"path/to/partial"', "path/to/partial"),
33
- tag("tpl", "template", '"path/to/template"', "path/to/template"),
32
+ tag("par", "partial", '"path/to/partial"', "path/to/partial", ["render_partial"]),
33
+ tag("tpl", "template", '"path/to/template"', "path/to/template", ["render_template"]),
34
34
  tag("cr", "breadcrumbs"),
35
35
  tag("ch", "children"),
36
36
  tag("si", "siblings"),
@@ -23,7 +23,13 @@ class Comfy::Admin::Cms::FilesController < Comfy::Admin::Cms::BaseController
23
23
  case params[:type]
24
24
  when 'image'
25
25
  file_scope.with_images.collect do |file|
26
- { thumb: url_for(file.attachment.variant(combine_options: Comfy::Cms::File::VARIANT_SIZE[:redactor])),
26
+ attachment = file.attachment
27
+ thumbnail = if attachment.variable?
28
+ attachment.variant(Comfy::Cms::File::VARIANT_SIZE[:redactor])
29
+ else
30
+ attachment
31
+ end
32
+ { thumb: url_for(thumbnail),
27
33
  image: url_for(file.attachment),
28
34
  title: file.label }
29
35
  end
@@ -6,9 +6,9 @@ class Comfy::Cms::File < ActiveRecord::Base
6
6
  include Comfy::Cms::WithCategories
7
7
 
8
8
  VARIANT_SIZE = {
9
- redactor: { resize: '100x75^', gravity: 'center', crop: '100x75+0+0' },
10
- thumb: { resize: '200x150^', gravity: 'center', crop: '200x150+0+0' },
11
- icon: { resize: '28x28^', gravity: 'center', crop: '28x28+0+0' }
9
+ redactor: { resize_to_fill: [100, 75] },
10
+ thumb: { resize_to_fill: [200, 150] },
11
+ icon: { resize_to_fill: [28, 28] }
12
12
  }.freeze
13
13
 
14
14
  # temporary place to store attachment
@@ -2,7 +2,7 @@
2
2
  - attachments.each do |attachment|
3
3
  :ruby
4
4
  thumb_url = if attachment.variable?
5
- url_for(attachment.variant(combine_options: Comfy::Cms::File::VARIANT_SIZE[:thumb]))
5
+ url_for(attachment.variant(Comfy::Cms::File::VARIANT_SIZE[:thumb]))
6
6
  end
7
7
  filename = attachment.filename.to_s
8
8
  truncated_filename = truncate(filename, length: 40, omission: "...#{filename.last(10)}")
@@ -46,6 +46,10 @@ ComfyMiddleSeat.configure do |config|
46
46
  # object you want to keep. Set it to 0 if you wish to turn this feature off.
47
47
  # config.revisions_limit = 25
48
48
 
49
+ # Maximum requested width or height for image resizing in CMS tags.
50
+ # Values above this limit raise an error rather than being silently reduced.
51
+ # config.max_image_dimension = 4096
52
+
49
53
  # Locale definitions. If you want to define your own locale merge
50
54
  # {:locale => 'Locale Title'} with this.
51
55
  # config.locales = {:en => 'English', :es => 'Español'}
@@ -84,6 +84,9 @@ class ComfyMiddleSeat::Configuration
84
84
  # For example: include fragments into json data with `config.page_to_json_options = { include: [:fragments] }`
85
85
  attr_accessor :page_to_json_options
86
86
 
87
+ # Maximum requested width or height for image transformations in CMS tags.
88
+ attr_accessor :max_image_dimension
89
+
87
90
  # Configuration defaults
88
91
  def initialize
89
92
  @cms_title = 'ComfyMiddleSeat CMS Engine'
@@ -99,6 +102,7 @@ class ComfyMiddleSeat::Configuration
99
102
  @enable_seeds = false
100
103
  @seeds_path = File.expand_path('db/cms_seeds', Rails.root)
101
104
  @revisions_limit = 25
105
+ @max_image_dimension = 4096
102
106
  @locales = {
103
107
  'ar' => 'عربي',
104
108
  'ca' => 'Català',
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Restrict CMS-authored transformations to bounded image operations. Never pass
4
+ # arbitrary tag options through to an image processor.
5
+ class ComfyMiddleSeat::Content::ImageTransformations
6
+ OPERATIONS = %w[resize_to_limit resize_to_fit resize_to_fill resize_and_pad].freeze
7
+ LEGACY_OPTIONS = %w[resize gravity crop].freeze
8
+ OPTIONS = (OPERATIONS + LEGACY_OPTIONS).freeze
9
+ GRAVITIES = %w[northwest north northeast west center east southwest south southeast].freeze
10
+
11
+ def self.normalize(options, processor: ActiveStorage.variant_processor)
12
+ new(options, processor).normalize
13
+ end
14
+
15
+ def initialize(options, processor)
16
+ @options = options.stringify_keys
17
+ @processor = processor
18
+ end
19
+
20
+ def normalize
21
+ return {} if @options.empty?
22
+
23
+ unknown = @options.keys - OPTIONS
24
+ error!("Unknown image options: #{unknown.join(', ')}") if unknown.any?
25
+ modern = @options.keys & OPERATIONS
26
+ if modern.size > 1 || (modern.any? && @options.keys.intersect?(LEGACY_OPTIONS))
27
+ error!('Use one resize operation; do not mix modern and legacy image options')
28
+ end
29
+
30
+ if modern.any?
31
+ operation = modern.first
32
+ { operation.to_sym => dimensions(@options[operation], operation) }
33
+ else
34
+ legacy_transformations
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def dimensions(value, operation)
41
+ match = value.is_a?(String) && %r{\A\s*(\d+)\s*x\s*(\d+)\s*\z}.match(value)
42
+ error!("#{operation} must be dimensions such as \"400x300\"") unless match
43
+ validate_dimensions(match[1].to_i, match[2].to_i)
44
+ end
45
+
46
+ def validate_dimensions(width, height)
47
+ limit = ComfyMiddleSeat.config.max_image_dimension
48
+ unless limit.is_a?(Integer) && limit.positive?
49
+ error!('max_image_dimension must be a positive integer')
50
+ end
51
+ unless width.positive? && height.positive? && width <= limit && height <= limit
52
+ error!("Image dimensions must be between 1 and #{limit} pixels; adjust max_image_dimension if needed")
53
+ end
54
+ [width, height]
55
+ end
56
+
57
+ def legacy_transformations
58
+ if @options.key?('resize')
59
+ size, modifier = legacy_resize
60
+ if @options.keys == ['resize'] && ['', '>'].include?(modifier)
61
+ operation = modifier == '>' ? :resize_to_limit : :resize_to_fit
62
+ return { operation => size }
63
+ end
64
+ end
65
+
66
+ validate_legacy_crop if @options.key?('crop')
67
+
68
+ if @options.key?('gravity') && !GRAVITIES.include?(@options['gravity'])
69
+ error!("Unsupported gravity; choose #{GRAVITIES.join(', ')}")
70
+ end
71
+ unless @options.key?('resize') || @options.key?('crop')
72
+ error!('Legacy gravity requires resize or crop')
73
+ end
74
+ unless @processor == :mini_magick
75
+ error!('Legacy crop, gravity, and resize modifiers require MiniMagick; use a modern resize option with Vips')
76
+ end
77
+
78
+ # image_processing combines these operations itself. The order matters for
79
+ # existing resize/gravity/crop expressions; combine_options is unsupported.
80
+ @options.slice(*LEGACY_OPTIONS).symbolize_keys
81
+ end
82
+
83
+ def legacy_resize
84
+ value = @options['resize']
85
+ match = value.is_a?(String) && %r{\A(\d+)x(\d+)([!<>^]?)\z}.match(value)
86
+ error!('Legacy resize must be WxH with an optional >, <, !, or ^ suffix; use a modern resize option') unless match
87
+ [validate_dimensions(match[1].to_i, match[2].to_i), match[3]]
88
+ end
89
+
90
+ def validate_legacy_crop
91
+ value = @options['crop']
92
+ match = value.is_a?(String) && %r{\A(\d+)x(\d+)[+-]\d+[+-]\d+\z}.match(value)
93
+ error!('Legacy crop requires explicit offsets: WxH+X+Y; use resize_to_fill for a centered crop') unless match
94
+ validate_dimensions(match[1].to_i, match[2].to_i)
95
+ end
96
+
97
+ def error!(message)
98
+ raise ComfyMiddleSeat::Content::Tag::Error, message
99
+ end
100
+ end
@@ -30,28 +30,23 @@ class ComfyMiddleSeat::Content::Tags::Asset < ComfyMiddleSeat::Content::Tag
30
30
  def content
31
31
  return '' unless layout
32
32
 
33
- base = ComfyMiddleSeat.config.public_cms_path || ''
34
- unless base.ends_with?('/')
35
- base += '/'
36
- end
33
+ url_helpers = Rails.application.routes.url_helpers
34
+ options = { site_id: context.site.id, identifier: layout.identifier, cache_buster: layout.cache_buster, format: @type }
35
+ helpers = ActionController::Base.helpers
37
36
 
37
+ # These are CMS endpoints, not pipeline assets. Use HTML builders to avoid
38
+ # adding asset-host prefixes or applying asset-pipeline settings to the URL.
38
39
  case @type
39
40
  when 'css'
40
- out = "#{base}cms-css/#{context.site.id}/#{@identifier}/#{layout.cache_buster}.css"
41
- if @as == 'tag'
42
- out = "<link href='#{out}' media='screen' rel='stylesheet' type='text/css' />"
43
- end
44
- out
41
+ path = url_helpers.comfy_cms_render_css_path(**options)
42
+ @as == 'tag' ? helpers.tag.link(href: path, media: 'screen', rel: 'stylesheet', type: 'text/css') : path
45
43
  when 'js'
46
- out = "#{base}cms-js/#{context.site.id}/#{@identifier}/#{layout.cache_buster}.js"
47
- if @as == 'tag'
48
- out = "<script src='#{out}' type='text/javascript'></script>"
49
- end
50
- out
44
+ path = url_helpers.comfy_cms_render_js_path(**options)
45
+ @as == 'tag' ? helpers.content_tag(:script, '', src: path, type: 'text/javascript') : path
51
46
  end
52
47
  end
53
48
  end
54
49
 
55
- ComfyMiddleSeat::Content::Renderer.register_tag(
56
- :asset, ComfyMiddleSeat::Content::Tags::Asset
57
- )
50
+ %i[asset layout_asset].each do |name|
51
+ ComfyMiddleSeat::Content::Renderer.register_tag(name, ComfyMiddleSeat::Content::Tags::Asset)
52
+ end
@@ -8,9 +8,8 @@ require_relative 'mixins/file_content'
8
8
  #
9
9
  # `as` - url (default) | link | image - render out link or image tag
10
10
  # `label` - attach label attribute to link or image tag
11
- # `resize` - imagemagic option. For example: "100x50>"
12
- # `gravity` - imagemagic option. For example: "center"
13
- # `crop` - imagemagic option. For example: "100x50+0+0"
11
+ # Image sizing: resize_to_limit, resize_to_fit, resize_to_fill, resize_and_pad ("100x50").
12
+ # Legacy resize/gravity/crop expressions remain supported for MiniMagick.
14
13
  # `class` - any html classes that you want on the result link or image tag. For example "class1 class2"
15
14
  #
16
15
  class ComfyMiddleSeat::Content::Tags::File < ComfyMiddleSeat::Content::Tags::Fragment
@@ -28,7 +27,7 @@ class ComfyMiddleSeat::Content::Tags::File < ComfyMiddleSeat::Content::Tags::Fra
28
27
  @as = options['as'] || 'url'
29
28
  @label = options['label']
30
29
  @class = options['class']
31
- @variant_attrs = options.slice('resize', 'gravity', 'crop')
30
+ @variant_attrs = options.slice(*ComfyMiddleSeat::Content::ImageTransformations::OPTIONS)
32
31
  end
33
32
 
34
33
  def form_field(object_name, view, index)
@@ -9,12 +9,8 @@ require_relative 'mixins/file_content'
9
9
  # `as` - url (default) | link | image - how file gets rendered out
10
10
  # `class` - any html classes that you want on the result link or image tag. For example "class1 class2"
11
11
  #
12
- # - variant_attrs are not functional, perhaps due to some change in ImageMagick
13
- # - Simply use a class in your CSS / SASS to style your image display
14
- # `label` - attach label attribute to link or image tag
15
- # `resize` - imagemagick option. For example: "100x50>"
16
- # `gravity` - imagemagick option. For example: "center"
17
- # `crop` - imagemagick option. For example: "100x50+0+0"
12
+ # Image sizing: resize_to_limit, resize_to_fit, resize_to_fill, resize_and_pad ("100x50").
13
+ # Legacy resize/gravity/crop expressions remain supported for MiniMagick.
18
14
  #
19
15
  class ComfyMiddleSeat::Content::Tags::FileLink < ComfyMiddleSeat::Content::Tag
20
16
  include ComfyMiddleSeat::Content::Tags::Mixins::FileContent
@@ -28,7 +24,7 @@ class ComfyMiddleSeat::Content::Tags::FileLink < ComfyMiddleSeat::Content::Tag
28
24
  @identifier = params[0]
29
25
  @as = options['as'] || 'url'
30
26
  @class = options['class']
31
- @variant_attrs = options.slice('resize', 'gravity', 'crop') # broken for ImageMagick
27
+ @variant_attrs = options.slice(*ComfyMiddleSeat::Content::ImageTransformations::OPTIONS)
32
28
 
33
29
  return if @identifier.present?
34
30
 
@@ -7,12 +7,8 @@ require_relative 'mixins/file_content'
7
7
  #
8
8
  # `class` - any html classes that you want on the image tag. For example "class1 class2"
9
9
  #
10
- # - variant_attrs are not functional, perhaps due to some change in ImageMagick
11
- # - Simply use a class in your CSS / SASS to style your image display
12
- # `label` - attach label attribute to link or image tag
13
- # `resize` - imagemagick option. For example: "100x50>"
14
- # `gravity` - imagemagick option. For example: "center"
15
- # `crop` - imagemagick option. For example: "100x50+0+0"
10
+ # Image sizing: resize_to_limit, resize_to_fit, resize_to_fill, resize_and_pad ("100x50").
11
+ # Legacy resize/gravity/crop expressions remain supported for MiniMagick.
16
12
 
17
13
  class ComfyMiddleSeat::Content::Tags::Image < ComfyMiddleSeat::Content::Tag
18
14
  include ComfyMiddleSeat::Content::Tags::Mixins::FileContent
@@ -26,7 +22,7 @@ class ComfyMiddleSeat::Content::Tags::Image < ComfyMiddleSeat::Content::Tag
26
22
  @identifier = params[0]
27
23
  @as = 'image'
28
24
  @class = options['class']
29
- @variant_attrs = options.slice('resize', 'gravity', 'crop') # broken for ImageMagick
25
+ @variant_attrs = options.slice(*ComfyMiddleSeat::Content::ImageTransformations::OPTIONS)
30
26
 
31
27
  return if @identifier.present?
32
28
 
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../image_transformations'
4
+
3
5
  # A mixin for tags that returns the file as their content.
4
6
  module ComfyMiddleSeat::Content::Tags::Mixins
5
7
  module FileContent
6
8
  # @param [ActiveStorage::Blob] file
7
9
  # @param ["link", "image", "url"] as
8
- # @param [{String => String}] variant_attrs ImageMagick variant attributes
10
+ # @param [{String => String}] variant_attrs Modern or legacy image options
9
11
  # @param [String] label alt text for `as: "image"`, link text for `as: "link"`
10
12
  # @return [String]
11
13
  def content(file: self.file, as: self.as, variant_attrs: self.variant_attrs, label: self.label)
@@ -14,8 +16,9 @@ module ComfyMiddleSeat::Content::Tags::Mixins
14
16
  url_helpers = Rails.application.routes.url_helpers
15
17
 
16
18
  attachment_url =
17
- if variant_attrs.present? && file.image?
18
- variant = file.variant(combine_options: variant_attrs)
19
+ if variant_attrs.present? && file.variable?
20
+ transformations = ComfyMiddleSeat::Content::ImageTransformations.normalize(variant_attrs)
21
+ variant = file.variant(transformations)
19
22
  url_helpers.rails_representation_path(variant, only_path: true)
20
23
  else
21
24
  url_helpers.rails_blob_path(file, only_path: true)
@@ -18,12 +18,8 @@ require_relative 'mixins/file_content'
18
18
  # `as` - url (default) | link | image - how file gets rendered out
19
19
  # `class` - any html classes that you want on the result link or image tag. For example "class1 class2"
20
20
  #
21
- # - the following params are deprecated / not functional, perhaps due to some change in ImageMagick
22
- # - Simply use a class in your CSS / SASS to style your image display
23
- # `label` - attach label attribute to link or image tag
24
- # `resize` - imagemagick option. For example: "100x50>"
25
- # `gravity` - imagemagick option. For example: "center"
26
- # `crop` - imagemagick option. For example: "100x50+0+0"
21
+ # Image sizing: resize_to_limit, resize_to_fit, resize_to_fill, resize_and_pad ("100x50").
22
+ # Legacy resize/gravity/crop expressions remain supported for MiniMagick.
27
23
  #
28
24
  class ComfyMiddleSeat::Content::Tags::PageFileLink < ComfyMiddleSeat::Content::Tag
29
25
  include ComfyMiddleSeat::Content::Tags::Mixins::FileContent
@@ -48,7 +44,7 @@ class ComfyMiddleSeat::Content::Tags::PageFileLink < ComfyMiddleSeat::Content::T
48
44
  @identifier = params[0]
49
45
  @as = options['as'] || 'url'
50
46
  @class = options['class']
51
- @variant_attrs = options.slice('resize', 'gravity', 'crop')
47
+ @variant_attrs = options.slice(*ComfyMiddleSeat::Content::ImageTransformations::OPTIONS)
52
48
  @filename = options['filename']
53
49
 
54
50
  return if @identifier.present?
@@ -42,6 +42,6 @@ class ComfyMiddleSeat::Content::Tags::Partial < ComfyMiddleSeat::Content::Tag
42
42
  end
43
43
  end
44
44
 
45
- ComfyMiddleSeat::Content::Renderer.register_tag(
46
- :partial, ComfyMiddleSeat::Content::Tags::Partial
47
- )
45
+ %i[partial render_partial].each do |name|
46
+ ComfyMiddleSeat::Content::Renderer.register_tag(name, ComfyMiddleSeat::Content::Tags::Partial)
47
+ end
@@ -37,6 +37,6 @@ class ComfyMiddleSeat::Content::Tags::Template < ComfyMiddleSeat::Content::Tag
37
37
  end
38
38
  end
39
39
 
40
- ComfyMiddleSeat::Content::Renderer.register_tag(
41
- :template, ComfyMiddleSeat::Content::Tags::Template
42
- )
40
+ %i[template render_template].each do |name|
41
+ ComfyMiddleSeat::Content::Renderer.register_tag(name, ComfyMiddleSeat::Content::Tags::Template)
42
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ComfyMiddleSeat
4
- VERSION = '4.3.0'
4
+ VERSION = '4.5.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: comfy_middle_seat
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.0
4
+ version: 4.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleg Khabarov
@@ -574,6 +574,7 @@ files:
574
574
  - lib/comfy_middle_seat/configuration.rb
575
575
  - lib/comfy_middle_seat/content.rb
576
576
  - lib/comfy_middle_seat/content/block.rb
577
+ - lib/comfy_middle_seat/content/image_transformations.rb
577
578
  - lib/comfy_middle_seat/content/params_parser.rb
578
579
  - lib/comfy_middle_seat/content/renderer.rb
579
580
  - lib/comfy_middle_seat/content/tag.rb