{"id":1461,"date":"2026-04-07T17:59:52","date_gmt":"2026-04-07T20:59:52","guid":{"rendered":"https:\/\/acsiv.com.br\/blog\/?p=1461"},"modified":"2026-04-07T18:07:46","modified_gmt":"2026-04-07T21:07:46","slug":"como-personalizei-o-trix","status":"publish","type":"post","link":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/","title":{"rendered":"Como personalizei o Trix Editor"},"content":{"rendered":"\n<p>Trix \u00e9 um editor de texto WYSIWYG (<em>what you see is what you get<\/em>, ou \u201co que voc\u00ea v\u00ea \u00e9 o que voc\u00ea recebe\u201d) desenvolvido pela 37signals para o ecossistema do <a href=\"https:\/\/acsiv.com.br\/blog\/2025\/09\/23\/camadas-declarativas-um-padrao-flexivel-para-ruby\/\" target=\"_blank\" rel=\"noreferrer noopener\">Ruby<\/a> on Rails. Seu objetivo \u00e9 oferecer uma solu\u00e7\u00e3o simples e eficiente para os casos de uso mais comuns de edi\u00e7\u00e3o de texto, sem deixar de lado a possibilidade de customiza\u00e7\u00f5es avan\u00e7adas.<br><\/p>\n\n\n\n<p>Criado originalmente para o Basecamp \u2014 o conhecido sistema de gerenciamento de projetos da 37signals \u2014 o Trix se destaca por sua leveza, integra\u00e7\u00e3o direta com Rails e uma arquitetura que permite extens\u00f5es e personaliza\u00e7\u00f5es. Essa caracter\u00edstica se deve em parte \u00e0 filosofia dos desenvolvedores da empresa, que evitam adicionar funcionalidades consideradas desnecess\u00e1rias ao seu pr\u00f3prio produto. Felizmente, essa mesma simplicidade abre espa\u00e7o para que cada projeto adapte o editor \u00e0s suas pr\u00f3prias necessidades.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Integra\u00e7\u00e3o com Stimulus, HTML e Simple Form<\/h3>\n\n\n\n<p>Na <strong>Acsiv<\/strong>, utilizamos extensivamente o <strong>Stimulus<\/strong>, e por isso toda a customiza\u00e7\u00e3o do Trix tamb\u00e9m passa por ele. A inicializa\u00e7\u00e3o mais simples do editor fica assim:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  &lt;div data-controller=\"trix\"&gt;\n    &lt;trix-editor&gt;&lt;\/trix-editor&gt;\n  &lt;\/div&gt;<\/code><\/pre>\n\n\n\n<p>Como tamb\u00e9m utilizamos a <em>gem<\/em> <strong>Simple Form<\/strong>, e o Trix aparece em praticamente todos os campos de <em>rich text<\/em>, criei um <em>input<\/em> customizado para simplificar o uso e evitar repeti\u00e7\u00e3o de configura\u00e7\u00e3o em cada formul\u00e1rio:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;%= f.input :draft, as: :rich_text_area %&gt;<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Criando um input personalizado no Simple Form<\/h5>\n\n\n\n<p>Se voc\u00ea n\u00e3o usa <strong>Simple Form<\/strong> ou j\u00e1 est\u00e1 familiarizado com a cria\u00e7\u00e3o de inputs customizados, pode pular esta parte.<\/p>\n\n\n\n<p>No <strong>Simple Form<\/strong>, um <em>input<\/em> personalizado nada mais \u00e9 do que uma classe que define como aquele tipo de campo deve ser renderizado. Para que possamos escrever <code>as: :rich_text_area<\/code> nos formul\u00e1rios, precisamos criar um <code>RichTextAreaInput<\/code> seguindo a conven\u00e7\u00e3o da <em>gem<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class RichTextAreaInput &lt; SimpleForm::Inputs::Base\n  def input(wrapper_options = nil)\n    merged_options = merge_wrapper_options(input_html_options, wrapper_options)\n\n    @builder.template.content_tag(:div, data: { controller: \"trix\" }) do\n      @builder.rich_text_area(attribute_name, merged_options)\n    end\n  end\nend<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Customizando a barra de ferramentas<\/h3>\n\n\n\n<p>Para a maioria dos usu\u00e1rios que desejam modificar o Trix, come\u00e7ar pela barra de ferramentas \u00e9 o passo mais natural. Uma abordagem bastante comum \u00e9 manipular diretamente o DOM ap\u00f3s o editor ser carregado \u2014 buscando elementos, removendo bot\u00f5es ou adicionando outros. Embora funcione, esse caminho tende a gerar c\u00f3digo mais fr\u00e1gil e dif\u00edcil de manter.<\/p>\n\n\n\n<p>A forma que considero mais interessante \u00e9 sobrescrever a fun\u00e7\u00e3o respons\u00e1vel por gerar o HTML da barra de ferramentas: <strong><code>Trix.config.toolbar.getDefaultHTML()<\/code><\/strong>. Essa fun\u00e7\u00e3o retorna exatamente a estrutura HTML utilizada pelo Trix, e substitu\u00ed-la d\u00e1 total liberdade para definir sua pr\u00f3pria toolbar.<\/p>\n\n\n\n<p>No nosso caso, mantive o HTML da barra separado do <em>controller<\/em> Stimulus para melhor organiza\u00e7\u00e3o do c\u00f3digo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_controller.js\n\nimport { Controller } from \"@hotwired\/stimulus\"\nimport { trixToolbarHTML } from \"..\/services\/trix_toolbar\"\n\nexport default class extends Controller {\n  connect() {\n    Trix.config.toolbar.getDefaultHTML = this.toolbarDefaultHTML\n  }\n\n  toolbarDefaultHTML() {\n    return trixToolbarHTML\n  }\n}<\/code><\/pre>\n\n\n\n<p>E aqui est\u00e1 o arquivo de toolbar customizada:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_toolbar.js\n\nexport const trixToolbarHTML = `\n&lt;div class=\"trix-button-row\"&gt;\n  &lt;span class=\"trix-button-group trix-button-group--text-tools\" data-trix-button-group=\"text-tools\"&gt;\n    &lt;button type=\"button\" class=\"trix-button trix-button--icon trix-button--icon-bold\" data-trix-attribute=\"bold\" data-trix-key=\"b\" tabindex=\"-1\"&gt;Bold&lt;\/button&gt;\n  &lt;\/span&gt;\n&lt;\/div&gt;\n`<\/code><\/pre>\n\n\n\n<p>O c\u00f3digo acima deixa apenas o bot\u00e3o de <strong>negrito<\/strong> na barra de ferramentas, mas j\u00e1 demonstra como a customiza\u00e7\u00e3o \u00e9 simples. A partir daqui, voc\u00ea pode alterar completamente a apar\u00eancia (no meu caso, utilizei <strong>Bootstrap<\/strong>) e estruturar a barra de ferramentas da forma que fizer mais sentido para o seu projeto.<\/p>\n\n\n\n<p>Se quiser entender melhor tudo o que o Trix oferece por padr\u00e3o, recomendo conferir a <a href=\"https:\/\/github.com\/basecamp\/trix\/blob\/1aa6c54a6a27bf447358a80eefba6414754da1aa\/src\/trix\/config\/toolbar.js\" target=\"_blank\" rel=\"noreferrer noopener\">barra de ferramentas original<\/a>. Ela serve como um \u00f3timo ponto de refer\u00eancia para conhecer todos os grupos e bot\u00f5es dispon\u00edveis.<\/p>\n\n\n\n<p>E \u00e9 justamente ao analisar o c\u00f3digo padr\u00e3o que surge a pergunta: <strong>como criar novos recursos?<\/strong><br>Afinal, o Trix entrega apenas <strong>negrito<\/strong>, <strong>it\u00e1lico<\/strong> e <strong>tachado<\/strong>.<br>Mas e se eu quiser ir al\u00e9m e adicionar <strong>sublinhado<\/strong>, <strong>sobrescrito<\/strong>, <strong>subscrito<\/strong>, <strong>marcador de texto<\/strong> e outros comandos totalmente customizados?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Adicionando novos recursos ao Trix<\/h3>\n\n\n\n<p>Vamos come\u00e7ar adicionando bot\u00f5es na barra de ferramentas (vou omitir as classes CSS para focar no essencial):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_toolbar.js\n\nexport const trixToolbarHTML = `\n&lt;div class=\"trix-button-row\"&gt;\n  &lt;span class=\"trix-button-group trix-button-group--text-tools\" data-trix-button-group=\"text-tools\"&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"bold\" data-trix-key=\"b\" tabindex=\"-1\"&gt;Bold&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"italic\" data-trix-key=\"i\" tabindex=\"-1\"&gt;Italic&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"underline\" data-trix-key=\"u\" tabindex=\"-1\"&gt;Underline&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"strike\" tabindex=\"-1\"&gt;Strike&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"superscript\" data-trix-key=\".\" tabindex=\"-1\"&gt;Superscript&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"subscript\" data-trix-key=\",\"   tabindex=\"-1\"&gt;Subscript&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"highlight\" data-trix-key=\"m\" tabindex=\"-1\"&gt;Highlighter&lt;\/button&gt;\n  &lt;\/span&gt;\n&lt;\/div&gt;\n`<\/code><\/pre>\n\n\n\n<p>Note que todos os bot\u00f5es possuem um atributo <code>data-trix-attribute<\/code>. Ao ser clicado, o Trix procura nas configura\u00e7\u00f5es internas (<code>Trix.config.textAttributes<\/code>) um atributo com o mesmo nome e aplica seu efeito ao texto selecionado.<\/p>\n\n\n\n<p>Al\u00e9m disso, tamb\u00e9m podemos definir um atributo <code>data-trix-key<\/code> que configura a tecla de atalho que aplica esse recurso ao ser usada em conjunto com a tecla <code>meta<\/code>.<\/p>\n\n\n\n<p>Para manter a estrutura organizada, podemos definir esses atributos em um arquivo dedicado, carregado globalmente pela aplica\u00e7\u00e3o (por exemplo em <code>application.js<\/code>, se voc\u00ea estiver usando <em>esbuild<\/em>):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_custom_attributes.js\n\nTrix.config.textAttributes.underline = {\n  tagName: \"u\",\n  inheritable: true\n}\n\nTrix.config.textAttributes.subscript = {\n  tagName: \"sub\",\n  inheritable: true,\n}\n\nTrix.config.textAttributes.superscript = {\n  tagName: \"sup\",\n  inheritable: true,\n}\n\nTrix.config.textAttributes.highlight = {\n  tagName: \"mark\",\n  inheritable: true,\n}<\/code><\/pre>\n\n\n\n<p>Sempre que o Trix encontrar um atributo correspondente ao bot\u00e3o clicado, ele envolver\u00e1 o texto selecionado no elemento especificado em <code>tagName<\/code>. Como todos os exemplos acima usam <strong>tags HTML5 nativas<\/strong>, o comportamento \u00e9 imediato e intuitivo.<\/p>\n\n\n\n<p>O objeto de configura\u00e7\u00e3o de um atributo de texto permite diversas op\u00e7\u00f5es:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Atributo<\/th><th>Tipo<\/th><th>Descri\u00e7\u00e3o<\/th><\/tr><\/thead><tbody><tr><td><code>tagName<\/code><\/td><td>String<\/td><td>Define qual <em>tag HTML<\/em> envolver\u00e1 o texto (<code>\"strong\"<\/code>, <code>\"em\"<\/code>, <code>\"u\"<\/code>, <code>\"mark\"<\/code>\u2026).<\/td><\/tr><tr><td><code>className<\/code><\/td><td>String<\/td><td>(Opcional) Classe CSS aplicada \u00e0 tag gerada.<\/td><\/tr><tr><td><code>style<\/code><\/td><td>Object<\/td><td>(Opcional) Estilos inline aplicados \u00e0 tag. Ex: <code>{ color: \"red\" }<\/code>.<\/td><\/tr><tr><td><code>inheritable<\/code><\/td><td>Boolean<\/td><td>Se <code>true<\/code>, novos caracteres digitados herdam automaticamente esse atributo enquanto ativo.<\/td><\/tr><tr><td><code>parser<\/code><\/td><td>Function<\/td><td>(Opcional) Fun\u00e7\u00e3o que diz ao Trix como detectar automaticamente esse atributo ao colar HTML.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Trix tamb\u00e9m possui <strong>atributos de bloco<\/strong>, que, em vez de serem aplicados a caracteres individuais, sempre afetam o <strong>bloco inteiro de conte\u00fado<\/strong>. Esse \u00e9 o caso de componentes como <strong>cita\u00e7\u00f5es<\/strong>, <strong>t\u00edtulos<\/strong> e <strong>listas<\/strong>, por exemplo. A sintaxe para definir um atributo de bloco \u00e9 simples:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  Trix.config.blockAttributes.quote = {\n    tagName: \"blockquote\",\n    nestable: true,\n  },<\/code><\/pre>\n\n\n\n<p>O objeto de configura\u00e7\u00e3o dos atributos de bloco tamb\u00e9m permitem diversas op\u00e7\u00f5es:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Atributo<\/th><th>Tipo<\/th><th>Descri\u00e7\u00e3o<\/th><\/tr><\/thead><tbody><tr><td><code>tagName<\/code><\/td><td>String<\/td><td>Define qual <em>tag HTML<\/em> envolver\u00e1 o texto (<code>\"blockquote\"<\/code>, <code>\"h1\"<\/code>, <code>\"ul\"<\/code>\u2026).<\/td><\/tr><tr><td><code>exclusive<\/code><\/td><td>Boolean<\/td><td>Indica que esse atributo \u00e9 exclusivo: ao ser aplicado, remove qualquer outro atributo de bloco ativo no mesmo bloco.<\/td><\/tr><tr><td><code>nestable<\/code><\/td><td>Boolean<\/td><td>Permite que esse bloco seja aninhado dentro de outro bloco (ex.: <code>blockquote<\/code> dentro de <code>blockquote<\/code>).<\/td><\/tr><tr><td><code>terminal<\/code><\/td><td>Boolean<\/td><td>Indica que o bloco \u00e9 terminal. Blocos terminais n\u00e3o podem conter outros blocos dentro deles.<\/td><\/tr><tr><td><code>parse<\/code><\/td><td>Boolean<\/td><td>Controla se o Trix deve reconhecer automaticamente esse bloco ao importar ou colar HTML correspondente.<\/td><\/tr><tr><td><code>group<\/code><\/td><td>Boolean<\/td><td>Agrupa atributos de bloco relacionados, permitindo que o Trix trate esses atributos como mutuamente exclusivos dentro do mesmo grupo.<\/td><\/tr><tr><td><code>breakOnReturn<\/code><\/td><td>Boolean<\/td><td>Quando <code>true<\/code>, pressionar Enter encerra o bloco atual e cria um novo bloco padr\u00e3o (ex: sair de um t\u00edtulo ao pressionar Enter).<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h5 class=\"wp-block-heading\">Adicionando recursos personalizados<\/h5>\n\n\n\n<p>Como voc\u00ea j\u00e1 deve ter percebido, at\u00e9 aqui utilizamos <strong>tags HTML5 nativas<\/strong> nos atributos criados. No entanto, o Trix permite ir al\u00e9m: ele cria um elemento com o valor definido em <code>tagName<\/code> <strong>independentemente de a tag existir oficialmente no HTML<\/strong>.<\/p>\n\n\n\n<p>Aproveitando essa flexibilidade, vamos criar quatro bot\u00f5es para controlar o alinhamento do bloco: <strong>alinhado \u00e0 esquerda<\/strong>, <strong>centralizado<\/strong>, <strong>alinhado \u00e0 direita<\/strong> e <strong>justificado<\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_toolbar.js\n\nexport const trixToolbarHTML = `\n&lt;div class=\"trix-button-row\"&gt;\n  &lt;span class=\"trix-button-group trix-button-group--alignment-tools\" data-trix-button-group=\"alignment-tools\"&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"alignLeft\" tabindex=\"-1\"&gt;left&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"alignCenter\" tabindex=\"-1\"&gt;center&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"alignRight\" tabindex=\"-1\"&gt;right&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"justify\" tabindex=\"-1\"&gt;justify&lt;\/button&gt;\n  &lt;\/span&gt;\n&lt;\/div&gt;\n`<\/code><\/pre>\n\n\n\n<p>Agora definimos os atributos de bloco correspondentes. Note que estamos utilizando <strong>tags customizadas<\/strong>, que n\u00e3o possuem significado sem\u00e2ntico por padr\u00e3o:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_custom_attributes.js\n\nTrix.config.blockAttributes.alignLeft = {\n  tagName: \"align-left\",\n}\n\nTrix.config.blockAttributes.alignCenter = {\n  tagName: \"align-center\",\n}\n\nTrix.config.blockAttributes.alignRight = {\n  tagName: \"align-right\",\n}\n\nTrix.config.blockAttributes.justify = {\n  tagName: \"justify\",\n}<\/code><\/pre>\n\n\n\n<p>Ao clicar em qualquer um desses bot\u00f5es, o Trix aplicar\u00e1 a <strong>tag customizada<\/strong> ao bloco selecionado. No entanto, visualmente nada acontecer\u00e1 \u2014 afinal, essas tags n\u00e3o possuem comportamento nativo.<\/p>\n\n\n\n<p>Para dar significado a esses elementos, precisamos definir seu estilo. Embora seja poss\u00edvel criar componentes JavaScript dedicados para cada caso, uma solu\u00e7\u00e3o simples e eficaz \u00e9 aplicar regras CSS diretamente:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* trix.css *\/\n\nalign-left &amp;nbsp; { text-align: left; &amp;nbsp; width: 100%; display: block; }\nalign-center { text-align: center; width: 100%; display: block; }\nalign-right &amp;nbsp;{ text-align: right; &amp;nbsp;width: 100%; display: block; }\njustify &amp;nbsp; &amp;nbsp; &amp;nbsp;{ text-align: justify; width: 100%; display: block; }<\/code><\/pre>\n\n\n\n<p>Com isso, ao clicar em qualquer um dos novos bot\u00f5es, o bloco ser\u00e1 alinhado conforme o comando escolhido.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Adicionando recursos com l\u00f3gica JavaScript<\/h5>\n\n\n\n<p>At\u00e9 aqui, todos os recursos adicionados s\u00e3o relativamente simples e n\u00e3o exigem l\u00f3gica adicional: a pr\u00f3pria API do Trix j\u00e1 se encarrega de selecionar atributos e envolver trechos de texto com elementos previamente definidos.<\/p>\n\n\n\n<p>A seguir, vamos implementar <strong>um seletor de tamanho de fonte<\/strong> (e, na sequ\u00eancia, um seletor de cores). Em ambos os casos, precisamos garantir que <strong>apenas uma op\u00e7\u00e3o esteja ativa por vez<\/strong>, sem exce\u00e7\u00f5es. Esse comportamento n\u00e3o \u00e9 oferecido diretamente pelas op\u00e7\u00f5es de configura\u00e7\u00e3o dos atributos (ao menos, n\u00e3o encontrei suporte nativo para isso), o que nos obriga a introduzir um pouco de l\u00f3gica JavaScript.<\/p>\n\n\n\n<p>Felizmente, o Trix facilita bastante esse processo ao permitir a defini\u00e7\u00e3o de <strong>a\u00e7\u00f5es customizadas<\/strong>, disparadas sempre que um bot\u00e3o da toolbar \u00e9 clicado. Vamos come\u00e7ar implementando o seletor de tamanhos seguindo a mesma abordagem utilizada nos exemplos anteriores.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_toolbar.js\n\nexport const trixToolbarHTML = `\n&lt;div class=\"trix-button-row\"&gt;\n  &lt;span class=\"trix-button-group trix-button-group--font-size-tools\" data-trix-button-group=\"font-size-tools\"&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"textSize1\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        textSize1\n    &lt;\/button&gt;\n\n    &lt;button type=\"button\" data-trix-attribute=\"textSize2\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        textSize2\n    &lt;\/button&gt;\n\n    &lt;button type=\"button\" data-trix-attribute=\"textSize3\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        textSize3\n    &lt;\/button&gt;\n\n    &lt;button type=\"button\" data-trix-attribute=\"textSize4\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        textSize4\n    &lt;\/button&gt;\n\n    &lt;button type=\"button\" data-trix-attribute=\"textSize5\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        textSize5\n    &lt;\/button&gt;\n  &lt;\/span&gt;\n&lt;\/div&gt;\n`<\/code><\/pre>\n\n\n\n<p>O ponto mais importante no trecho acima \u00e9 o atributo <code>data-trix-action<\/code>. \u00c9 nele que definimos o identificador do evento que ser\u00e1 disparado ao clicar no bot\u00e3o. O Trix exige que essas a\u00e7\u00f5es customizadas comecem com o prefixo <strong><code>x-<\/code><\/strong>, garantindo que n\u00e3o entrem em conflito com a\u00e7\u00f5es internas do editor.<\/p>\n\n\n\n<p>Agora, definimos os atributos de texto correspondentes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_custom_attributes.js\n\nfor (let i = 1; i &lt;= 5; i++) {\n  Trix.config.textAttributes&#91;`textSize${i}`] = {\n    tagName: `text-size-${i}`,\n    inheritable: true,\n  }\n}<\/code><\/pre>\n\n\n\n<p>E, por fim, o CSS respons\u00e1vel por aplicar o efeito visual:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* trix.css *\/\n\ntext-size-1 { font-size: 20px; }\ntext-size-2 { font-size: 24px; }\ntext-size-3 { font-size: 28px; }\ntext-size-4 { font-size: 32px; }\ntext-size-5 { font-size: 40px; }<\/code><\/pre>\n\n\n\n<p>Com isso, ao clicar em qualquer um dos bot\u00f5es, o tamanho da fonte do trecho selecionado ser\u00e1 alterado conforme o valor desejado. No entanto, ainda existe um problema: \u00e9 poss\u00edvel ativar <strong>todos os bot\u00f5es ao mesmo tempo<\/strong>, fazendo com que o texto seja envolvido por m\u00faltiplos elementos \u2014 e apenas o \u00faltimo aplicado ter\u00e1 efeito visual.<\/p>\n\n\n\n<p>Para evitar esse comportamento, precisamos garantir que, ao selecionar um tamanho, <strong>todos os outros sejam automaticamente desativados<\/strong>. \u00c9 aqui que entra a l\u00f3gica JavaScript:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_controller.js\n\nimport { Controller } from \"@hotwired\/stimulus\"\nimport { trixToolbarHTML } from \"..\/services\/trix_toolbar\"\n\nexport default class extends Controller {\n  connect() {\n    Trix.config.toolbar.getDefaultHTML = this.toolbarDefaultHTML\n  }\n\n  toolbarDefaultHTML() {\n    return trixToolbarHTML\n  }\n\n  installEventListeners() {\n    addEventListener(\"trix-action-invoke\", this.applyExclusiveTextSize)\n  }\n\n  applyExclusiveTextSize = ({ target, invokingElement, actionName }) =&gt; {\n    if (actionName === \"x-exclusive-text-size\") {\n      const attribute = invokingElement.dataset&#91;\"trixAttribute\"]\n\n      for (let i = 1; i &lt;= 5; i++) {\n        let runningAttribute = `textSize${i}`\n\n        if (attribute === runningAttribute) continue\n\n        target.editor.deactivateAttribute(runningAttribute)\n      }\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>Com essa abordagem, sempre que um tamanho de fonte for selecionado, todos os outros atributos de tamanho ser\u00e3o desativados automaticamente, garantindo que <strong>apenas um esteja ativo por vez<\/strong> \u2014 exatamente o comportamento esperado para esse tipo de controle.<\/p>\n\n\n\n<p>Para o seletor de cores, o processo \u00e9 essencialmente o mesmo. A \u00fanica diferen\u00e7a significativa est\u00e1 nos <strong>efeitos visuais<\/strong> aplicados ao texto:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_toolbar.js\n\nexport const trixToolbarHTML = `\n&lt;div class=\"trix-button-row\"&gt;\n  &lt;span class=\"trix-button-group trix-button-group--font-color-tools\" data-trix-button-group=\"font-color-tools\"&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"redText\" data-trix-action=\"x-exclusive-color\" tabindex=\"-1\"&gt;Red&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"greenText\" data-trix-action=\"x-exclusive-color\" tabindex=\"-1\"&gt;Green&lt;\/button&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"blueText\" data-trix-action=\"x-exclusive-color\" tabindex=\"-1\"&gt;Blue&lt;\/button&gt;\n  &lt;\/span&gt;\n&lt;\/div&gt;\n`<\/code><\/pre>\n\n\n\n<p>Definimos ent\u00e3o os atributos de texto correspondentes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_custom_attributes.js\n\n&#91;\"red\", \"green\", \"blue\"].forEach((color) =&gt; {\n  Trix.config.textAttributes&#91;`${color}Text`] = {\n    tagName: `${color}-text`,\n    inheritable: true\n  }\n})<\/code><\/pre>\n\n\n\n<p>E os estilos respons\u00e1veis pelo efeito visual:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* trix.css *\/\n\nred-text { color: #dc3545; }\ngreen-text { color: #198754; }\nblue-text { color: #0d6efd; }<\/code><\/pre>\n\n\n\n<p>Por fim, adicionamos a l\u00f3gica respons\u00e1vel por garantir que <strong>apenas uma cor esteja ativa por vez<\/strong>, reaproveitando o mesmo mecanismo de eventos customizados:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_controller.js\n\nimport { Controller } from \"@hotwired\/stimulus\"\nimport { trixToolbarHTML } from \"..\/services\/trix_toolbar\"\n\nexport default class extends Controller {\n  connect() {\n    Trix.config.toolbar.getDefaultHTML = this.toolbarDefaultHTML\n  }\n\n  toolbarDefaultHTML() {\n    return trixToolbarHTML\n  }\n\n  installEventListeners() {\n    addEventListener(\"trix-action-invoke\", this.applyExclusiveTextSize)\n    addEventListener(\"trix-action-invoke\", this.applyExclusiveColor)\n  }\n\n  applyExclusiveTextSize = ({ target, invokingElement, actionName }) =&gt; {\n    if (actionName === \"x-exclusive-text-size\") {\n      const attribute = invokingElement.dataset&#91;\"trixAttribute\"]\n\n      for (let i = 1; i &lt;= 5; i++) {\n        let runningAttribute = `textSize${i}`\n\n        if (attribute === runningAttribute) continue\n\n        target.editor.deactivateAttribute(runningAttribute)\n      }\n    }\n  }\n\n  applyExclusiveColor = ({ target, invokingElement, actionName }) =&gt; {\n    if (actionName === \"x-exclusive-color\") {\n      const attribute = invokingElement.dataset&#91;\"trixAttribute\"]\n      const colors = &#91;\"red\", \"green\", \"blue\"]\n\n      colors.forEach((color) =&gt; {\n        let runningAttribute = `${color}Text`\n\n        if (attribute === runningAttribute) return\n\n        target.editor.deactivateAttribute(runningAttribute)\n      })\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>Na <strong>Acsiv<\/strong>, como j\u00e1 mencionado, utilizamos <strong>Bootstrap<\/strong> para estilizar o produto \u2014 e com o <strong>Trix<\/strong> n\u00e3o foi diferente. Nossa paleta de cores faz sentido para o nosso contexto, mas pode n\u00e3o se adequar ao seu caso de uso. Por isso, os exemplos acima foram mantidos propositalmente simples. Ainda assim, nada impede que voc\u00ea implemente elementos visuais mais sofisticados, como <em>dropdowns<\/em>, e selecione as cores a partir deles.<\/p>\n<\/blockquote>\n\n\n\n<p>voc\u00ea tem total liberdade para criar <strong>componentes com l\u00f3gica extra<\/strong>, adaptados exatamente ao seu caso de uso. A API do Trix n\u00e3o imp\u00f5e grandes limita\u00e7\u00f5es nesse sentido \u2014 pelo contr\u00e1rio, ela incentiva esse tipo de extens\u00e3o.<\/p>\n\n\n\n<p>Um bom exemplo disso \u00e9 um bot\u00e3o respons\u00e1vel por <strong>remover todos os atributos atualmente aplicados a um trecho de texto<\/strong> \u2014 para voc\u00ea n\u00e3o precisar desativar eles um por um &#x1f60a;:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>resetFormattingAttributes = ({ target, invokingElement, actionName }) =&gt; {\n  if (actionName === \"x-reset-formatting-attributes\") {\n    Object.keys(Trix.config.textAttributes).forEach(attribute =&gt; {\n      if (target.editor.attributeIsActive(attribute)) target.editor.deactivateAttribute(attribute)\n    })\n\n    Object.keys(Trix.config.blockAttributes).forEach(attribute =&gt; {\n      if (target.editor.attributeIsActive(attribute)) target.editor.deactivateAttribute(attribute)\n    })\n  }\n}<\/code><\/pre>\n\n\n\n<p>Nesse caso, percorremos todos os <strong>atributos de texto<\/strong> e <strong>atributos de bloco<\/strong> registrados no Trix e desativamos apenas aqueles que est\u00e3o ativos no editor no momento da a\u00e7\u00e3o. O resultado \u00e9 um comportamento semelhante ao bot\u00e3o \u201climpar formata\u00e7\u00e3o\u201d encontrado em editores mais completos \u2014 mas totalmente customiz\u00e1vel.<\/p>\n\n\n\n<p>Esse padr\u00e3o refor\u00e7a um dos pontos mais interessantes do Trix: embora ele ofere\u00e7a uma API simples, ela \u00e9 poderosa o suficiente para permitir a constru\u00e7\u00e3o de comportamentos avan\u00e7ados sem a necessidade de <em>hacks<\/em> ou depend\u00eancias externas.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Finalizando<\/h3>\n\n\n\n<p>Com tudo o que vimos at\u00e9 aqui, voc\u00ea j\u00e1 deve ser capaz de implementar a maioria das customiza\u00e7\u00f5es que provavelmente ir\u00e1 precisar no <strong>Trix<\/strong>. Ainda assim, vale destacar dois pontos importantes que costumam passar despercebidos em um primeiro momento, mas que s\u00e3o essenciais em projetos reais: <strong>sanitiza\u00e7\u00e3o de conte\u00fado<\/strong> e <strong>tradu\u00e7\u00f5es<\/strong>.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Sanitiza\u00e7\u00f5es<\/h5>\n\n\n\n<p>Ao utilizar <strong>tags HTML customizadas<\/strong>, \u00e9 fundamental garantir que elas n\u00e3o sejam removidas durante o processo de sanitiza\u00e7\u00e3o do conte\u00fado. Isso vale tanto para o <strong>Trix<\/strong>, no lado do cliente, quanto para o <strong>ActiveRecord<\/strong>, no backend \u2014 especialmente se voc\u00ea utiliza <code>has_rich_text<\/code>.<\/p>\n\n\n\n<p>No caso do <strong>Trix<\/strong>, o processo \u00e9 simples. O editor j\u00e1 utiliza a biblioteca <strong>DOMPurify<\/strong>, ent\u00e3o basta informar explicitamente quais <strong>tags adicionais<\/strong> devem ser permitidas:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Trix.config.dompurify.ADD_TAGS = &#91;\"text-size-1\", \"text-size-2\", \"text-size-3\", \"text-size-4\", \"text-size-5\", \"red-text\", \"green-text\", \"blue-text\" \"align-left\", \"align-center\", \"align-right\", \"justify\"]<\/code><\/pre>\n\n\n\n<p>No backend, o processo \u00e9 igualmente direto. Caso voc\u00ea utilize <strong>Action Text<\/strong>, \u00e9 necess\u00e1rio estender a <em>whitelist<\/em> de tags permitidas pelo sanitizador do Rails. Um <em>initializer<\/em> simples j\u00e1 resolve o problema:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Rails.application.config.after_initialize do\n&amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"text-size-1\"\n&amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"text-size-2\"\n&amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"text-size-3\"\n&amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"text-size-4\"\n&amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"text-size-5\"\n\n&amp;nbsp; %w&#91;red green blue].each do |color|\n&amp;nbsp; &amp;nbsp; &amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"#{color}-#text\"\n&amp;nbsp; end\n\n&amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"align-left\"\n&amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"align-center\"\n&amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"align-right\"\n&amp;nbsp; Rails::Html::Sanitizer.white_list_sanitizer.allowed_tags &lt;&lt; \"justify\"\nend<\/code><\/pre>\n\n\n\n<p>Com isso, suas <strong>tags customizadas<\/strong> passam a ser preservadas tanto no editor quanto na persist\u00eancia dos dados.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Tradu\u00e7\u00f5es<\/h5>\n\n\n\n<p>As tradu\u00e7\u00f5es seguem a mesma filosofia do restante da API do Trix: s\u00e3o simples, diretas e f\u00e1ceis de estender.<\/p>\n\n\n\n<p>Primeiro, defina os textos desejados no objeto de configura\u00e7\u00e3o de idioma:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Trix.config.lang.textSize1 = \"Tamanho 1\"\nTrix.config.lang.textSize2 = \"Tamanho 2\"\nTrix.config.lang.textSize3 = \"Tamanho 3\"\nTrix.config.lang.textSize4 = \"Tamanho 4\"\nTrix.config.lang.textSize5 = \"Tamanho 5\"<\/code><\/pre>\n\n\n\n<p>Em seguida, utilize essas chaves diretamente no HTML da toolbar:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ trix_toolbar.js\n\nconst { lang } = Trix.config\n\nexport const trixToolbarHTML = `\n&lt;div class=\"trix-button-row\"&gt;\n  &lt;span class=\"trix-button-group trix-button-group--font-size-tools\" data-trix-button-group=\"font-size-tools\"&gt;\n    &lt;button type=\"button\" data-trix-attribute=\"textSize1\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        ${lang.textSize1}\n    &lt;\/button&gt;\n\n    &lt;button type=\"button\" data-trix-attribute=\"textSize2\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        ${lang.textSize2}\n    &lt;\/button&gt;\n\n    &lt;button type=\"button\" data-trix-attribute=\"textSize3\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        ${lang.textSize3}\n    &lt;\/button&gt;\n\n    &lt;button type=\"button\" data-trix-attribute=\"textSize4\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        ${lang.textSize4}\n    &lt;\/button&gt;\n\n    &lt;button type=\"button\" data-trix-attribute=\"textSize5\" data-trix-action=\"x-exclusive-text-size\" tabindex=\"-1\"&gt;\n        ${lang.textSize5}\n    &lt;\/button&gt;\n  &lt;\/span&gt;\n&lt;\/div&gt;\n`<\/code><\/pre>\n\n\n\n<p>Esse padr\u00e3o facilita n\u00e3o s\u00f3 a tradu\u00e7\u00e3o do editor, mas tamb\u00e9m sua futura manuten\u00e7\u00e3o e expans\u00e3o para m\u00faltiplos idiomas.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Encerrando de vez<\/h3>\n\n\n\n<p>Com esses ajustes, \u00e9 bem prov\u00e1vel que voc\u00ea consiga adaptar o <strong>Trix<\/strong> completamente ao seu contexto de uso \u2014 desde pequenas customiza\u00e7\u00f5es visuais at\u00e9 comportamentos mais complexos controlados por JavaScript.<\/p>\n\n\n\n<p>Existe, no entanto, uma funcionalidade bastante requisitada que o Trix n\u00e3o oferece nativamente: <strong>suporte a tabelas HTML<\/strong>. Essa foi uma decis\u00e3o consciente dos desenvolvedores originais, mas que nem sempre atende \u00e0s necessidades de produtos mais complexos.<\/p>\n\n\n\n<p>Na <strong>Acsiv<\/strong>, por exemplo, o uso de tabelas era indispens\u00e1vel. Por isso, implementamos esse suporte por conta pr\u00f3pria. No pr\u00f3ximo artigo, vou mostrar em detalhes como constru\u00edmos <strong>suporte a tabelas no Trix<\/strong>, respeitando sua arquitetura e mantendo uma boa experi\u00eancia de edi\u00e7\u00e3o.<\/p>\n\n\n\n<p>Se voc\u00ea chegou at\u00e9 aqui, j\u00e1 tem base mais do que suficiente para ir al\u00e9m do b\u00e1sico \u2014 e, com um pouco de paci\u00eancia, transformar o <strong>Trix<\/strong> em um editor muito mais poderoso do que ele aparenta \u00e0 primeira vista.<\/p>\n\n\n\n<p class=\"has-text-align-right\">Escrito por: Fillipe Palhares <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Trix \u00e9 um editor de texto WYSIWYG (what you see is what you get, ou \u201co que voc\u00ea v\u00ea \u00e9 o que voc\u00ea recebe\u201d) desenvolvido&hellip;<\/p>\n","protected":false},"author":2,"featured_media":1465,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1,8],"tags":[1177,1176,1179,1175,1178],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v19.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\r\n<title>Trix editor - Blog da Acsiv<\/title>\r\n<meta name=\"description\" content=\"Guia completo de customiza\u00e7\u00e3o do editor Trix no Ruby on Rails: integre com Stimulus, Simple Form e Action Text.\" \/>\r\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\r\n<link rel=\"canonical\" href=\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/\" \/>\r\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\r\n<meta property=\"og:type\" content=\"article\" \/>\r\n<meta property=\"og:title\" content=\"Trix editor - Blog da Acsiv\" \/>\r\n<meta property=\"og:description\" content=\"Guia completo de customiza\u00e7\u00e3o do editor Trix no Ruby on Rails: integre com Stimulus, Simple Form e Action Text.\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/\" \/>\r\n<meta property=\"og:site_name\" content=\"Blog da Acsiv\" \/>\r\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/acsiv\" \/>\r\n<meta property=\"article:published_time\" content=\"2026-04-07T20:59:52+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2026-04-07T21:07:46+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/acsiv.com.br\/blog\/wp-content\/uploads\/2026\/04\/ChatGPT_Image_7_de_abr._de_2026_18_02_26.png\" \/>\r\n\t<meta property=\"og:image:width\" content=\"1536\" \/>\r\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\r\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\r\n<meta name=\"author\" content=\"Eduardo Rodrigues\" \/>\r\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\r\n<meta name=\"twitter:creator\" content=\"@acsiv\" \/>\r\n<meta name=\"twitter:site\" content=\"@acsiv\" \/>\r\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Eduardo Rodrigues\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. tempo de leitura\" \/>\n\t<meta name=\"twitter:data2\" content=\"17 minutos\" \/>\r\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/acsiv.com.br\/blog\/#organization\",\"name\":\"Acsiv Sistema\",\"url\":\"https:\/\/acsiv.com.br\/blog\/\",\"sameAs\":[\"https:\/\/instagram.com\/acsivsistemas\",\"https:\/\/pt.linkedin.com\/company\/acsiv\",\"https:\/\/www.facebook.com\/acsiv\",\"https:\/\/twitter.com\/acsiv\"],\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/acsiv.com.br\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/acsiv.com.br\/blog\/wp-content\/uploads\/2020\/10\/Acsiv_logotipo.png\",\"contentUrl\":\"https:\/\/acsiv.com.br\/blog\/wp-content\/uploads\/2020\/10\/Acsiv_logotipo.png\",\"width\":1564,\"height\":668,\"caption\":\"Acsiv Sistema\"},\"image\":{\"@id\":\"https:\/\/acsiv.com.br\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/acsiv.com.br\/blog\/#website\",\"url\":\"https:\/\/acsiv.com.br\/blog\/\",\"name\":\"Blog da Acsiv\",\"description\":\"Conte\u00fado digital para cart\u00f3rios\",\"publisher\":{\"@id\":\"https:\/\/acsiv.com.br\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/acsiv.com.br\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/\",\"url\":\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/\",\"name\":\"Trix editor - Blog da Acsiv\",\"isPartOf\":{\"@id\":\"https:\/\/acsiv.com.br\/blog\/#website\"},\"datePublished\":\"2026-04-07T20:59:52+00:00\",\"dateModified\":\"2026-04-07T21:07:46+00:00\",\"description\":\"Guia completo de customiza\u00e7\u00e3o do editor Trix no Ruby on Rails: integre com Stimulus, Simple Form e Action Text.\",\"breadcrumb\":{\"@id\":\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"In\u00edcio\",\"item\":\"https:\/\/acsiv.com.br\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Como personalizei o Trix Editor\"}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/\"},\"author\":{\"name\":\"Eduardo Rodrigues\",\"@id\":\"https:\/\/acsiv.com.br\/blog\/#\/schema\/person\/54fd566d0efeb6dc731df7e4e38ce156\"},\"headline\":\"Como personalizei o Trix Editor\",\"datePublished\":\"2026-04-07T20:59:52+00:00\",\"dateModified\":\"2026-04-07T21:07:46+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/\"},\"wordCount\":2231,\"publisher\":{\"@id\":\"https:\/\/acsiv.com.br\/blog\/#organization\"},\"keywords\":[\"dev\",\"passo-a-passo\",\"ruby-on-rails\",\"stimulus\",\"trix-editor\"],\"articleSection\":[\"Sem Categoria\",\"Tecnologia\"],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/acsiv.com.br\/blog\/#\/schema\/person\/54fd566d0efeb6dc731df7e4e38ce156\",\"name\":\"Eduardo Rodrigues\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/acsiv.com.br\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/fee13940cf1da650036b52bc338d5881?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/fee13940cf1da650036b52bc338d5881?s=96&d=mm&r=g\",\"caption\":\"Eduardo Rodrigues\"}}]}<\/script>\r\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Trix editor - Blog da Acsiv","description":"Guia completo de customiza\u00e7\u00e3o do editor Trix no Ruby on Rails: integre com Stimulus, Simple Form e Action Text.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/","og_locale":"pt_BR","og_type":"article","og_title":"Trix editor - Blog da Acsiv","og_description":"Guia completo de customiza\u00e7\u00e3o do editor Trix no Ruby on Rails: integre com Stimulus, Simple Form e Action Text.","og_url":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/","og_site_name":"Blog da Acsiv","article_publisher":"https:\/\/www.facebook.com\/acsiv","article_published_time":"2026-04-07T20:59:52+00:00","article_modified_time":"2026-04-07T21:07:46+00:00","og_image":[{"width":1536,"height":1024,"url":"https:\/\/acsiv.com.br\/blog\/wp-content\/uploads\/2026\/04\/ChatGPT_Image_7_de_abr._de_2026_18_02_26.png","type":"image\/png"}],"author":"Eduardo Rodrigues","twitter_card":"summary_large_image","twitter_creator":"@acsiv","twitter_site":"@acsiv","twitter_misc":{"Escrito por":"Eduardo Rodrigues","Est. tempo de leitura":"17 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Organization","@id":"https:\/\/acsiv.com.br\/blog\/#organization","name":"Acsiv Sistema","url":"https:\/\/acsiv.com.br\/blog\/","sameAs":["https:\/\/instagram.com\/acsivsistemas","https:\/\/pt.linkedin.com\/company\/acsiv","https:\/\/www.facebook.com\/acsiv","https:\/\/twitter.com\/acsiv"],"logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/acsiv.com.br\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/acsiv.com.br\/blog\/wp-content\/uploads\/2020\/10\/Acsiv_logotipo.png","contentUrl":"https:\/\/acsiv.com.br\/blog\/wp-content\/uploads\/2020\/10\/Acsiv_logotipo.png","width":1564,"height":668,"caption":"Acsiv Sistema"},"image":{"@id":"https:\/\/acsiv.com.br\/blog\/#\/schema\/logo\/image\/"}},{"@type":"WebSite","@id":"https:\/\/acsiv.com.br\/blog\/#website","url":"https:\/\/acsiv.com.br\/blog\/","name":"Blog da Acsiv","description":"Conte\u00fado digital para cart\u00f3rios","publisher":{"@id":"https:\/\/acsiv.com.br\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/acsiv.com.br\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"pt-BR"},{"@type":"WebPage","@id":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/","url":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/","name":"Trix editor - Blog da Acsiv","isPartOf":{"@id":"https:\/\/acsiv.com.br\/blog\/#website"},"datePublished":"2026-04-07T20:59:52+00:00","dateModified":"2026-04-07T21:07:46+00:00","description":"Guia completo de customiza\u00e7\u00e3o do editor Trix no Ruby on Rails: integre com Stimulus, Simple Form e Action Text.","breadcrumb":{"@id":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"In\u00edcio","item":"https:\/\/acsiv.com.br\/blog\/"},{"@type":"ListItem","position":2,"name":"Como personalizei o Trix Editor"}]},{"@type":"Article","@id":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/#article","isPartOf":{"@id":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/"},"author":{"name":"Eduardo Rodrigues","@id":"https:\/\/acsiv.com.br\/blog\/#\/schema\/person\/54fd566d0efeb6dc731df7e4e38ce156"},"headline":"Como personalizei o Trix Editor","datePublished":"2026-04-07T20:59:52+00:00","dateModified":"2026-04-07T21:07:46+00:00","mainEntityOfPage":{"@id":"https:\/\/acsiv.com.br\/blog\/2026\/04\/07\/como-personalizei-o-trix\/"},"wordCount":2231,"publisher":{"@id":"https:\/\/acsiv.com.br\/blog\/#organization"},"keywords":["dev","passo-a-passo","ruby-on-rails","stimulus","trix-editor"],"articleSection":["Sem Categoria","Tecnologia"],"inLanguage":"pt-BR"},{"@type":"Person","@id":"https:\/\/acsiv.com.br\/blog\/#\/schema\/person\/54fd566d0efeb6dc731df7e4e38ce156","name":"Eduardo Rodrigues","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/acsiv.com.br\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/fee13940cf1da650036b52bc338d5881?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/fee13940cf1da650036b52bc338d5881?s=96&d=mm&r=g","caption":"Eduardo Rodrigues"}}]}},"_links":{"self":[{"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/posts\/1461"}],"collection":[{"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/comments?post=1461"}],"version-history":[{"count":2,"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/posts\/1461\/revisions"}],"predecessor-version":[{"id":1464,"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/posts\/1461\/revisions\/1464"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/media\/1465"}],"wp:attachment":[{"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/media?parent=1461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/categories?post=1461"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/acsiv.com.br\/blog\/wp-json\/wp\/v2\/tags?post=1461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}