b4um_generators 0.2.8 → 0.2.9

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: 4ac1397c02b6a4475966dd32cae4aa31b251ac3b6e29cbc0fda6994a3e325a3f
4
- data.tar.gz: fd7a685c7cbd61c96c9fd2e54ffd622b0b4593f83c0e27257d1afec24d0375ff
3
+ metadata.gz: 4554ba68c9377451369455eee637d0ebf9b05926d17f1cca4e7846ed9a3e7ffe
4
+ data.tar.gz: 52c056de9b177de1f0e790ede1d7c13fcd5888c18eb95e02d5e93895c2827040
5
5
  SHA512:
6
- metadata.gz: 43445dcd341aa92ebca76c14eafd500bfa993110e58e203f7f8ea2b0af22127e24c97374e95c33c336cb90f10220175dbf277168edd4e31f55de2fdd1392f87b
7
- data.tar.gz: '00147389d26a82e439a634c6712f4b42c7561f99593451c80ddf5d6b23205feb377d6f569ceb2adf2dbd82fec8335d29436451c7dad21515a22619464421c0ae'
6
+ metadata.gz: c2758a16ff6d6fdfc220c7c49c8c698d09628ba53ecf45054f446bf062d291dfed85c5ca2a31d50e69e3d6a77521500d01805eaa21ff07cc8bf1adabe6ec0566
7
+ data.tar.gz: 22027e9c4911cbc9b16f8ad15132ff9681c32eaa4b53760c4e7c5838f7ff86e609879d94450bf19e975a105a48c196864d7c5bdcbea351266901c109563399e8
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module B4umGenerators
4
- VERSION = "0.2.8"
4
+ VERSION = "0.2.9"
5
5
  end
@@ -1,7 +1,9 @@
1
1
  /* -------------------------------------------------------
2
2
  Image lightbox
3
3
  ------------------------------------------------------- */
4
-
4
+ .lupe {
5
+ cursor: zoom-in;
6
+ }
5
7
  .resource-image__button,
6
8
  .resource-images__button {
7
9
  display: block;
@@ -38,7 +40,11 @@
38
40
  padding: 70px 90px 110px;
39
41
  box-sizing: border-box;
40
42
 
41
- background-color: rgba(0, 0, 0, 0.92);
43
+ background: var(--b4um-hero-teaser-background);
44
+ color: var(--b4um-hero-teaser-text);
45
+
46
+ backdrop-filter: blur(16px);
47
+ -webkit-backdrop-filter: blur(16px);
42
48
  }
43
49
 
44
50
  .image-lightbox[hidden] {
@@ -121,7 +127,7 @@ body.image-lightbox-open {
121
127
  top: 28px;
122
128
  left: 28px;
123
129
 
124
- color: #ffffff;
130
+ color: var(--b4um-hero-teaser-text);
125
131
 
126
132
  font-size: 0.9rem;
127
133
  font-weight: 500;
@@ -146,7 +152,7 @@ body.image-lightbox-open {
146
152
  border: 0;
147
153
 
148
154
  background: transparent;
149
- color: #ffffff;
155
+ color: var(--b4um-hero-teaser-text);
150
156
 
151
157
  font: inherit;
152
158
  font-size: 2.5rem;
@@ -165,11 +171,11 @@ body.image-lightbox-open {
165
171
  justify-content: center;
166
172
 
167
173
  width: 56px;
168
- height: 72px;
169
- padding: 0;
174
+ height: 56px;
175
+ padding-bottom: 12px;
170
176
 
171
177
  border: 0;
172
- border-radius: 8px;
178
+ border-radius: 50%;
173
179
 
174
180
  background-color: rgba(0, 0, 0, 0.35);
175
181
  color: #ffffff;
@@ -181,7 +187,7 @@ body.image-lightbox-open {
181
187
 
182
188
  cursor: pointer;
183
189
 
184
- transform: translateY(-50%);
190
+ transform: translateY(-100%);
185
191
 
186
192
  transition:
187
193
  background-color 0.18s ease,
@@ -189,7 +195,7 @@ body.image-lightbox-open {
189
195
  }
190
196
 
191
197
  .image-lightbox__navigation:hover {
192
- background-color: rgba(255, 255, 255, 0.16);
198
+ background-color: rgba(0, 0, 0, 0.16);
193
199
  }
194
200
 
195
201
  .image-lightbox__navigation--previous {
@@ -212,7 +218,7 @@ body.image-lightbox-open {
212
218
  bottom: 24px;
213
219
  left: 20px;
214
220
 
215
- color: #ffffff;
221
+ color: var(--b4um-hero-teaser-text);
216
222
 
217
223
  font-size: 0.85rem;
218
224
  text-align: center;
@@ -220,6 +226,82 @@ body.image-lightbox-open {
220
226
  overflow-wrap: anywhere;
221
227
  }
222
228
 
229
+ /* -------------------------------------------------------
230
+ Thumbnails
231
+ ------------------------------------------------------- */
232
+
233
+ .image-lightbox__thumbnails {
234
+ position: absolute;
235
+ right: 6rem;
236
+ bottom: 2rem;
237
+ left: 6rem;
238
+ z-index: 3;
239
+
240
+ display: flex;
241
+ align-items: center;
242
+ justify-content: center;
243
+
244
+ gap: 0.75rem;
245
+
246
+ overflow-x: auto;
247
+ overflow-y: hidden;
248
+
249
+ padding: 0.5rem;
250
+
251
+ scrollbar-width: none;
252
+ }
253
+
254
+ .image-lightbox__thumbnails::-webkit-scrollbar {
255
+ display: none;
256
+ }
257
+
258
+ .image-lightbox__thumbnail {
259
+ flex: 0 0 auto;
260
+
261
+ width: 72px;
262
+ height: 52px;
263
+
264
+ padding: 3px;
265
+
266
+ overflow: hidden;
267
+
268
+ border: 2px solid transparent;
269
+ border-radius: 10px;
270
+
271
+ background: rgba(255, 255, 255, 0.12);
272
+
273
+ opacity: 0.55;
274
+ cursor: pointer;
275
+
276
+ transition:
277
+ opacity 0.2s ease,
278
+ border-color 0.2s ease,
279
+ transform 0.2s ease;
280
+ }
281
+
282
+ .image-lightbox__thumbnail:hover {
283
+ opacity: 0.85;
284
+ }
285
+
286
+ .image-lightbox__thumbnail.is-active {
287
+ border-color: var(--b4um-hero-teaser-text);
288
+
289
+ opacity: 1;
290
+
291
+ transform: scale(1.06);
292
+ }
293
+
294
+ .image-lightbox__thumbnail img {
295
+ display: block;
296
+
297
+ width: 100%;
298
+ height: 100%;
299
+
300
+ border-radius: 6px;
301
+
302
+ object-fit: cover;
303
+ }
304
+
223
305
  @media (prefers-reduced-motion: reduce) {
224
306
  .image-lightbox__image--sliding {
225
307
  transition: none;
@@ -62,6 +62,10 @@
62
62
  --b4um-primary-shadow: rgba(46, 71, 210, 0.22);
63
63
  --b4um-primary-shadow-soft: rgba(46, 71, 210, 0.12);
64
64
  --b4um-danger-shadow: rgba(204, 0, 0, 0.18);
65
+
66
+ --b4um-hero-teaser-background: rgba(255, 255, 255, 0.55);
67
+ --b4um-hero-teaser-text: rgba(20, 20, 20, 0.9);
68
+ --b4um-hero-teaser-border: rgba(255, 255, 255, 0.3);
65
69
  }
66
70
 
67
71
  /* -------------------------------------------------------
@@ -128,5 +132,9 @@
128
132
  --b4um-primary-shadow-soft: rgba(142, 162, 255, 0.14);
129
133
  --b4um-danger-shadow: rgba(255, 133, 133, 0.18);
130
134
 
135
+ --b4um-hero-teaser-background: rgba(20, 20, 20, 0.55);
136
+ --b4um-hero-teaser-text: rgba(255, 255, 255, 0.85);
137
+ --b4um-hero-teaser-border: rgba(255, 255, 255, 0.18);
138
+
131
139
  color-scheme: dark;
132
140
  }
@@ -1,7 +1,17 @@
1
1
  import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  export default class extends Controller {
4
- static targets = ['item', 'overlay', 'stage', 'image', 'caption', 'counter', 'previousButton', 'nextButton']
4
+ static targets = [
5
+ 'item',
6
+ 'overlay',
7
+ 'stage',
8
+ 'image',
9
+ 'caption',
10
+ 'counter',
11
+ 'previousButton',
12
+ 'nextButton',
13
+ 'thumbnails'
14
+ ]
5
15
 
6
16
  connect() {
7
17
  this.currentIndex = 0
@@ -22,6 +32,7 @@ export default class extends Controller {
22
32
  if (index === -1) return
23
33
 
24
34
  this.currentIndex = index
35
+ this.buildThumbnails()
25
36
  this.showCurrentImage()
26
37
 
27
38
  this.overlayTarget.hidden = false
@@ -30,6 +41,64 @@ export default class extends Controller {
30
41
  this.overlayTarget.focus()
31
42
  }
32
43
 
44
+ buildThumbnails() {
45
+ if (!this.hasThumbnailsTarget) return
46
+
47
+ this.thumbnailsTarget.innerHTML = ''
48
+
49
+ this.itemTargets.forEach((item, index) => {
50
+ const button = document.createElement('button')
51
+ button.type = 'button'
52
+ button.className = 'image-lightbox__thumbnail'
53
+ button.setAttribute('aria-label', `Bild ${index + 1} anzeigen`)
54
+
55
+ const image = document.createElement('img')
56
+ image.src = item.dataset.imageLightboxUrl
57
+ image.alt = item.dataset.imageLightboxAlt || ''
58
+
59
+ button.appendChild(image)
60
+
61
+ button.addEventListener('click', (event) => {
62
+ event.stopPropagation()
63
+
64
+ if (index === this.currentIndex) return
65
+ if (this.isSliding) return
66
+
67
+ const direction = index > this.currentIndex ? 'next' : 'previous'
68
+
69
+ this.updateThumbnails(index)
70
+ this.slideTo(index, direction)
71
+ })
72
+
73
+ this.thumbnailsTarget.appendChild(button)
74
+ })
75
+
76
+ this.updateThumbnails()
77
+ }
78
+
79
+ updateThumbnails(activeIndex = this.currentIndex) {
80
+ if (!this.hasThumbnailsTarget) return
81
+
82
+ const thumbnails = Array.from(this.thumbnailsTarget.querySelectorAll('.image-lightbox__thumbnail'))
83
+
84
+ thumbnails.forEach((thumbnail, index) => {
85
+ const active = index === activeIndex
86
+
87
+ thumbnail.classList.toggle('is-active', active)
88
+ thumbnail.setAttribute('aria-current', active ? 'true' : 'false')
89
+ })
90
+
91
+ const activeThumbnail = thumbnails[activeIndex]
92
+
93
+ if (activeThumbnail) {
94
+ activeThumbnail.scrollIntoView({
95
+ behavior: this.prefersReducedMotion() ? 'auto' : 'smooth',
96
+ block: 'nearest',
97
+ inline: 'center'
98
+ })
99
+ }
100
+ }
101
+
33
102
  close() {
34
103
  if (this.isSliding) return
35
104
 
@@ -37,13 +106,6 @@ export default class extends Controller {
37
106
  document.body.classList.remove('image-lightbox-open')
38
107
  }
39
108
 
40
- /*
41
- closeOnBackground(event) {
42
- if (event.target !== this.overlayTarget) return
43
-
44
- this.close()
45
- }*/
46
-
47
109
  closeOnBackground(event) {
48
110
  if (this.isDragging || this.isSliding) return
49
111
 
@@ -207,6 +269,7 @@ export default class extends Controller {
207
269
 
208
270
  this.currentIndex = newIndex
209
271
  this.updateInformation()
272
+ this.updateThumbnails()
210
273
 
211
274
  this.dragPreviousImage = null
212
275
  this.dragNextImage = null
@@ -361,6 +424,7 @@ export default class extends Controller {
361
424
 
362
425
  this.currentIndex = index
363
426
  this.updateInformation()
427
+ this.updateThumbnails()
364
428
 
365
429
  this.isSliding = false
366
430
  }
@@ -1,20 +1,22 @@
1
1
  <div id="<%= plural_table_name %>" class="b4um-grid">
2
2
  <%% <%= plural_table_name %>.each_with_index do |<%= singular_table_name %>, index| %>
3
- <%% card_class =
4
- case index % 5
5
- when 0
6
- "b4um-card b4um-card--wide"
7
- when 1
8
- "b4um-card b4um-card--soft"
9
- when 3
10
- "b4um-card b4um-card--large"
11
- else
12
- "b4um-card"
13
- end
14
- %>
3
+ <%% card_class, preview_length =
4
+ case index % 5
5
+ when 0
6
+ ["b4um-card b4um-card--wide", 240]
7
+ when 1
8
+ ["b4um-card b4um-card--soft", 58]
9
+ when 3
10
+ ["b4um-card b4um-card--large", 1600]
11
+ else
12
+ ["b4um-card", 58]
13
+ end
14
+ %>
15
15
 
16
16
  <article class="<%%= card_class %>">
17
- <%%= render <%= singular_table_name %>, compact: true %>
17
+ <%%= render <%= singular_table_name %>,
18
+ compact: true,
19
+ preview_length: preview_length %>
18
20
 
19
21
  <div class="b4um-card__actions">
20
22
  <%%= link_to "Show",
@@ -76,11 +76,21 @@
76
76
  <%%= form.label :<%= attribute.name %>, class: "form-label" %>
77
77
  </div>
78
78
 
79
- <% elsif [:integer, :float, :decimal].include?(attribute.type) -%>
79
+ <% elsif attribute.type == :integer -%>
80
80
  <div class="form-field">
81
81
  <%%= form.number_field :<%= attribute.name %>,
82
82
  class: "form-input",
83
- placeholder: " " %>
83
+ placeholder: " ",
84
+ step: 1 %>
85
+ <%%= form.label :<%= attribute.name %>, class: "form-label" %>
86
+ </div>
87
+
88
+ <% elsif [:float, :decimal].include?(attribute.type) -%>
89
+ <div class="form-field">
90
+ <%%= form.number_field :<%= attribute.name %>,
91
+ class: "form-input",
92
+ placeholder: " ",
93
+ step: "any" %>
84
94
  <%%= form.label :<%= attribute.name %>, class: "form-label" %>
85
95
  </div>
86
96
 
@@ -49,6 +49,8 @@
49
49
  alt="">
50
50
  </div>
51
51
 
52
+ <div class="image-lightbox__thumbnails" data-image-lightbox-target="thumbnails"></div>
53
+
52
54
  <div class="image-lightbox__caption"
53
55
  data-image-lightbox-target="caption"></div>
54
56
  </div>
@@ -119,6 +121,8 @@
119
121
  &#8250;
120
122
  </button>
121
123
 
124
+ <div class="image-lightbox__thumbnails" data-image-lightbox-target="thumbnails"></div>
125
+
122
126
  <div class="image-lightbox__caption"
123
127
  data-image-lightbox-target="caption"></div>
124
128
  </div>
@@ -131,11 +135,23 @@
131
135
  <% elsif attribute.type == :text -%>
132
136
  <span class="resource-value">
133
137
  <%% if local_assigns[:compact] %>
134
- <%%= truncate(<%= singular_table_name %>.<%= attribute.name %>, length: 160) %>
138
+ <%%= truncate(
139
+ <%= singular_table_name %>.<%= attribute.name %>,
140
+ length: local_assigns.fetch(:preview_length, 160)
141
+ ) %>
135
142
  <%% else %>
136
143
  <%%= <%= singular_table_name %>.<%= attribute.name %> %>
137
144
  <%% end %>
138
145
  </span>
146
+ <% elsif attribute.type == :decimal -%>
147
+ <span class="resource-value">
148
+ <%%= number_with_precision(
149
+ <%= singular_table_name %>.<%= attribute.name %>,
150
+ precision: 2,
151
+ delimiter: ".",
152
+ separator: ","
153
+ ) %>
154
+ </span>
139
155
  <% else -%>
140
156
  <span class="resource-value"><%%= <%= singular_table_name %>.<%= attribute.name %> %></span>
141
157
  <% end -%>
@@ -20,6 +20,13 @@
20
20
  </span>
21
21
  <% elsif attribute.type == :text -%>
22
22
  <%%= truncate(<%= singular_table_name %>.<%= attribute.name %>, length: 100) %>
23
+ <% elsif attribute.type == :decimal -%>
24
+ <%%= number_with_precision(
25
+ <%= singular_table_name %>.<%= attribute.name %>,
26
+ precision: 2,
27
+ delimiter: ".",
28
+ separator: ","
29
+ ) %>
23
30
  <% else -%>
24
31
  <%%= <%= singular_table_name %>.<%= attribute.name %> %>
25
32
  <% end -%>
@@ -10,7 +10,8 @@ module B4umRichTextHelper
10
10
  first_element = document.element_children.first
11
11
  heading = b4um_preview_heading(first_element)
12
12
 
13
- plain_text = rich_text.to_plain_text.strip
13
+ document.css("action-text-attachment").remove
14
+ plain_text = document.text.strip
14
15
 
15
16
  if heading
16
17
  heading_text = heading.text.strip
@@ -43,6 +43,7 @@ configureHeadingAttributes()
43
43
  configureAlignmentAttributes()
44
44
  configureContainerAttributes()
45
45
  configureColorAttributes()
46
+ preserveNestedContainerHtmlAttributes()
46
47
  registerAlignmentElements()
47
48
 
48
49
  document.addEventListener('trix-initialize', (event) => {
@@ -77,6 +78,8 @@ function insertContainer(editor, tagName) {
77
78
  return
78
79
  }
79
80
 
81
+ const selectedText = editor.getDocument().toString().slice(selectedRange[0], selectedRange[1]).trim()
82
+
80
83
  const id = window.prompt('Bitte geben Sie die ID ein:')
81
84
 
82
85
  if (id === null) return
@@ -91,14 +94,23 @@ function insertContainer(editor, tagName) {
91
94
  editor.recordUndoEntry(`Insert ${tagName.toUpperCase()} Container`)
92
95
 
93
96
  editor.setSelectedRange(selectedRange)
97
+ editor.activateAttribute(tagName)
94
98
 
95
- const attributeName = tagName === 'div' ? 'b4umDiv' : tagName
99
+ const documentModel = editor.getDocument()
96
100
 
97
- editor.activateAttribute(attributeName)
101
+ const block = documentModel.getBlocks().find((block) => {
102
+ return block.getAttributes().includes(tagName) && block.toString().includes(selectedText)
103
+ })
98
104
 
99
- editor.composition.setHTMLAtributeAtPosition(selectedRange[0], 'id', trimmedId)
105
+ if (!block) {
106
+ console.error('b4um Trix: Container-Block wurde nicht gefunden.')
107
+ return
108
+ }
100
109
 
101
- editor.setSelectedRange(selectedRange)
110
+ const newBlock = block.addHTMLAttribute('id', trimmedId)
111
+ const newDocument = documentModel.replaceBlock(block, newBlock)
112
+
113
+ editor.loadDocument(newDocument)
102
114
  }
103
115
 
104
116
  /* -------------------------------------------------------------------------- */
@@ -106,8 +118,6 @@ function insertContainer(editor, tagName) {
106
118
  /* -------------------------------------------------------------------------- */
107
119
 
108
120
  function allowB4umHtmlAttributes() {
109
- const originalSetHTML = Trix.HTMLSanitizer.setHTML
110
-
111
121
  Trix.HTMLSanitizer.setHTML = function (element, html, options = {}) {
112
122
  const allowedAttributes = [
113
123
  'style',
@@ -121,10 +131,14 @@ function allowB4umHtmlAttributes() {
121
131
  ...(options.allowedAttributes || [])
122
132
  ]
123
133
 
124
- return originalSetHTML.call(this, element, html, {
134
+ const sanitizedElement = this.sanitize(html, {
125
135
  ...options,
126
136
  allowedAttributes: [...new Set(allowedAttributes)]
127
137
  })
138
+
139
+ const sanitizedHtml = sanitizedElement.getHTML ? sanitizedElement.getHTML() : sanitizedElement.outerHTML
140
+
141
+ element.innerHTML = sanitizedHtml
128
142
  }
129
143
  }
130
144
 
@@ -152,22 +166,17 @@ function configureAlignmentAttributes() {
152
166
  }
153
167
 
154
168
  function configureContainerAttributes() {
155
- Trix.config.blockAttributes.default.htmlAttributes = ['id']
156
-
157
- Trix.config.blockAttributes.b4umDiv = {
158
- tagName: 'div',
169
+ Trix.config.blockAttributes.section = {
170
+ tagName: 'section',
159
171
  parse: true,
160
172
  nestable: false,
161
173
  exclusive: true,
162
174
  group: false,
163
- htmlAttributes: ['id'],
164
- test(element) {
165
- return element.hasAttribute('id')
166
- }
175
+ htmlAttributes: ['id']
167
176
  }
168
177
 
169
- Trix.config.blockAttributes.section = {
170
- tagName: 'section',
178
+ Trix.config.blockAttributes.article = {
179
+ tagName: 'article',
171
180
  parse: true,
172
181
  nestable: false,
173
182
  exclusive: true,
@@ -175,8 +184,8 @@ function configureContainerAttributes() {
175
184
  htmlAttributes: ['id']
176
185
  }
177
186
 
178
- Trix.config.blockAttributes.article = {
179
- tagName: 'article',
187
+ Trix.config.blockAttributes.div = {
188
+ tagName: 'div',
180
189
  parse: true,
181
190
  nestable: false,
182
191
  exclusive: true,
@@ -185,6 +194,40 @@ function configureContainerAttributes() {
185
194
  }
186
195
  }
187
196
 
197
+ function preserveNestedContainerHtmlAttributes() {
198
+ const prototype = Trix.HTMLParser.prototype
199
+
200
+ if (prototype.b4umPreservesNestedContainerHtmlAttributes) return
201
+
202
+ const originalAppendBlockForAttributesWithElement = prototype.appendBlockForAttributesWithElement
203
+
204
+ prototype.appendBlockForAttributesWithElement = function (attributes, element, htmlAttributes = {}) {
205
+ let mergedHtmlAttributes = { ...htmlAttributes }
206
+ let parentElement = element.parentElement
207
+
208
+ while (parentElement && parentElement !== this.containerElement) {
209
+ const tagName = parentElement.tagName.toLowerCase()
210
+
211
+ const isB4umContainer = ['section', 'article', 'div'].includes(tagName)
212
+
213
+ if (isB4umContainer && parentElement.hasAttribute('id')) {
214
+ mergedHtmlAttributes = {
215
+ id: parentElement.getAttribute('id'),
216
+ ...mergedHtmlAttributes
217
+ }
218
+
219
+ break
220
+ }
221
+
222
+ parentElement = parentElement.parentElement
223
+ }
224
+
225
+ return originalAppendBlockForAttributesWithElement.call(this, attributes, element, mergedHtmlAttributes)
226
+ }
227
+
228
+ prototype.b4umPreservesNestedContainerHtmlAttributes = true
229
+ }
230
+
188
231
  function configureColorAttributes() {
189
232
  FOREGROUND_COLORS.forEach((color, index) => {
190
233
  Trix.config.textAttributes[`fgColor${index + 1}`] = {
@@ -312,9 +355,7 @@ function installContainerButtonHandlers(editorElement, toolbar) {
312
355
  if (!editor) return
313
356
 
314
357
  toolbar
315
- .querySelectorAll(
316
- '[data-trix-attribute="b4umDiv"], [data-trix-attribute="section"], [data-trix-attribute="article"]'
317
- )
358
+ .querySelectorAll('[data-trix-attribute="section"], [data-trix-attribute="article"], [data-trix-attribute="div"]')
318
359
  .forEach((button) => {
319
360
  if (button.dataset.b4umContainerHandler === 'true') return
320
361
 
@@ -334,9 +375,7 @@ function installContainerButtonHandlers(editorElement, toolbar) {
334
375
  event.preventDefault()
335
376
  event.stopImmediatePropagation()
336
377
 
337
- const tagName = attributeName === 'b4umDiv' ? 'div' : attributeName
338
-
339
- insertContainer(editor, tagName)
378
+ insertContainer(editor, attributeName)
340
379
  },
341
380
  true
342
381
  )
@@ -447,15 +486,6 @@ function containerButtonsTemplate() {
447
486
  <span
448
487
  class="trix-button-group trix-button-group--container-tools"
449
488
  data-trix-button-group="container-tools">
450
- <button
451
- type="button"
452
- class="trix-button"
453
- data-trix-attribute="b4umDiv"
454
- title="DIV"
455
- aria-label="DIV"
456
- tabindex="-1">
457
- div
458
- </button>
459
489
  <button
460
490
  type="button"
461
491
  class="trix-button"
@@ -474,6 +504,15 @@ function containerButtonsTemplate() {
474
504
  tabindex="-1">
475
505
  article
476
506
  </button>
507
+ <button
508
+ type="button"
509
+ class="trix-button"
510
+ data-trix-attribute="div"
511
+ title="DIV"
512
+ aria-label="DIV"
513
+ tabindex="-1">
514
+ div
515
+ </button>
477
516
  </span>
478
517
  `
479
518
  }
@@ -151,16 +151,49 @@ module B4um
151
151
 
152
152
  resource_name = name.underscore
153
153
 
154
+ preview_length =
155
+ 'local_assigns\.fetch\(:preview_length,\s*160\)'
156
+
157
+ resource_attribute =
158
+ "#{Regexp.escape(resource_name)}\\.#{Regexp.escape(attribute)}"
159
+
160
+ rich_text_pattern =
161
+ /truncate\(\s*#{resource_attribute},\s*length:\s*#{preview_length}\s*\)/m
162
+
163
+ plain_text_pattern =
164
+ /truncate\(\s*#{resource_attribute}\.to_plain_text,\s*length:\s*#{preview_length}\s*\)/m
165
+
166
+ replacement =
167
+ "b4um_rich_text_preview(" \
168
+ "#{resource_name}.#{attribute}, " \
169
+ "length: local_assigns.fetch(:preview_length, 160))"
170
+
171
+ legacy_replacement =
172
+ "b4um_rich_text_preview(" \
173
+ "#{resource_name}.#{attribute}, length: 160)"
174
+
175
+ gsub_file(
176
+ resource_partial_path,
177
+ rich_text_pattern,
178
+ replacement
179
+ )
180
+
181
+ gsub_file(
182
+ resource_partial_path,
183
+ plain_text_pattern,
184
+ replacement
185
+ )
186
+
154
187
  gsub_file(
155
188
  resource_partial_path,
156
189
  "truncate(#{resource_name}.#{attribute}, length: 160)",
157
- "b4um_rich_text_preview(#{resource_name}.#{attribute}, length: 160)"
190
+ legacy_replacement
158
191
  )
159
192
 
160
193
  gsub_file(
161
194
  resource_partial_path,
162
195
  "truncate(#{resource_name}.#{attribute}.to_plain_text, length: 160)",
163
- "b4um_rich_text_preview(#{resource_name}.#{attribute}, length: 160)"
196
+ legacy_replacement
164
197
  )
165
198
 
166
199
  partial = File.read(resource_partial_path)
@@ -243,7 +276,7 @@ module B4um
243
276
  unless partial.include?("blob.video?")
244
277
  gsub_file(
245
278
  action_text_blob_partial_path,
246
- /<% if blob\.representable\? %>\s*(<%= image_tag .+? %>)\s*<% end %>/m,
279
+ /<% if blob\.representable\? %>\s*<%= image_tag .+? %>\s*<% end %>/m,
247
280
  <<~ERB.chomp
248
281
  <% if blob.video? %>
249
282
  <%= video_tag rails_blob_path(blob, disposition: "inline"),
@@ -251,8 +284,8 @@ module B4um
251
284
  playsinline: true,
252
285
  preload: "metadata",
253
286
  class: "b4um-rich-text-video" %>
254
- <% elsif blob.representable? %>
255
- \\1
287
+ <% elsif blob.image? %>
288
+ <%= image_tag rails_blob_path(blob, disposition: "inline") %>
256
289
  <% end %>
257
290
  ERB
258
291
  )
@@ -266,13 +299,14 @@ module B4um
266
299
  action_text_blob_partial_path,
267
300
  /<%= image_tag (.+?) %>/,
268
301
  <<~ERB.chomp
269
- <%= image_tag \\1,
302
+ <%= image_tag rails_blob_path(blob, disposition: "inline"),
270
303
  data: {
271
304
  image_lightbox_target: "item",
272
305
  image_lightbox_url: rails_blob_path(blob, only_path: true),
273
306
  image_lightbox_alt: blob.filename.to_s,
274
307
  action: "click->image-lightbox#open"
275
- } %>
308
+ },
309
+ class: "lupe" %>
276
310
  ERB
277
311
  )
278
312
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: b4um_generators
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Baum
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-09-28 00:00:00.000000000 Z
10
+ date: 2026-10-04 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: railties