Alex's Slip-box

These are my org-mode notes in sort of Zettelkasten style

Customizing ActionText views

:ID: 0c0f903a-ade6-46ea-a5b4-d633df841981

# Styling the Trix editor

Action Text uses the Trix Editor. Out of the box it comes with a style sheet that actually does a rather good job of providing basic styling. Without any styles, the editor is usable, but very raw.

If using a CSS framework that has utility classes, with SCSS, the Trix and Action Text classes can be made to extend from the CSS framework classes. For example, have the attachment caption extend from several bootstrap utility classes.

// app/assets/stylesheets/actiontext.scss
@import 'trix/dist/trix'; // Optionally use Trix's provided stylesheet as a starter
action-text-attachment {
  .attachment__caption {
    @extend .fw-light, .text-center, .text-black-50;
  }
}

See also https://sass-lang.com/documentation/at-rules/extend/

# Customizing the Trix editor

# Customizing the blob

See also https://github.com/rails/rails/tree/v7.1.2/actiontext See also https://acuments.com/uploading-audio-video-pdf-with-action-text.html

Rails provides a basic view partial to render attachments: app/views/active_storage/blobs/_blob.html.haml. In order do anything meaningful with attachments other than images, this will need some customization. For example, play an audio file using the HTML5 audio player.

First, I like using view components, so I extracted the blob partial to a component which is rendered in _blob.html.haml

# app/views/active_storage/blobs/_blob.html.haml
= render BlobComponent.new(blob: blob, in_gallery: local_assigns[:in_gallery])
# app/views/components/blob_component.rb

class BlobComponent < ApplicationViewComponent
  DEFAULT_IMAGE_SIZE = [1024, 768].freeze
  GALLERY_IMAGE_SIZE = [800, 600].freeze

  attr_reader :blob, :in_gallery

  delegate :audio?, :byte_size, :content_type, :filename, :representable?, :representation, :url, to: :blob

  def initialize(blob:, in_gallery:)
    @blob = blob
    @in_gallery = in_gallery
  end

  def caption
    return @caption if defined? @caption

    @caption = blob.try(:caption)
  end

  def caption? = caption.present?

    def humanized_file_size
      number_to_human_size byte_size
    end

    def resize_to_limit
      in_gallery ? GALLERY_IMAGE_SIZE : DEFAULT_IMAGE_SIZE
    end

    def fig_caption
      tag.figcaption(class: 'attachment__caption') do
        if caption?
          caption
        else
          tag.span(filename, class: 'attachment__name') +
            tag.span(humanized_file_size, class: 'attachment__size')
        end
      end
    end
  end

When the blob’s content type is an audio file, make it playable in the HTML5 audio player. There is some stuff omitted here to keep it simple. There’s a StimulusJS controller for instance, but that’s not required for this example.

-# app/views/components/blob_component/blob_component.html.haml
.c-blob{data: { controller: :blob }}
  %figure{class:  "attachment attachment--#{representable? ? 'preview' : 'file'} attachment--#{filename.extension}"}
    - if audio?
      .audio-player.d-flex
        %div
          %audio{controls: true, preload: :metadata, width: "100%", data: { 'blob-target' => :audio }}
            %source{src: url, type: content_type}
          = fig_caption

    - elsif representable?
      = image_tag representation(resize_to_limit: resize_to_limit)
      = fig_caption

In order to do this customization, we have to whitelist the HTML attributes and tags with the sanitizer, otherwise they will not be rendered.

# config/application.rb

config.after_initialize do
  ActionText::ContentHelper.sanitizer.class.allowed_attributes += %w[
    style controls poster preload type data-controller data-blob-target data-bs-toggle aria-expanded
  ]
  ActionText::ContentHelper.sanitizer.class.allowed_tags += %w[
    audio embed iframe source video button
  ]
end

# Customizing plain text attachment

See also https://gorails.com/blog/how-to-render-actiontext-attachments-in-plain-text

On the attachable class (or ActiveStorage::Blob) override the following method:

def attachable_plain_text_representation(caption = nil)
  caption || sprintf(self.class::PLAIN_TEXT_ATTACHMENT_TEMPLATE,
                      json: attributes.slice('content_type', 'filename').to_json)
end

This is from tmp. In this case I’m serializing attributes to JSON to be retrieved by a view component and replaced with some custom HTML markup (eg, icons to represent the attachment type)

# Observing changes to attachments

See event trix-attachment-add See also https://stackoverflow.com/a/63675437 for observing when attachment is finished uploading

Search Results