Trix 编辑器定义自定义附件样式

Trix editor define custom attachment styles

我在 Trix 编辑器中添加了一张图片,生成了以下代码:

<figure 
    data-trix-attachment="{lots of data}" 
    data-trix-content-type="image/jpeg"
    data-trix-attributes="{'presentation':'gallery'}" 
    class="attachment attachment--preview attachment--jpg">
    <img src="http://myhost/myimage.jpg" width="5731" height="3821">
    <figcaption class="attachment__caption">
        <span class="attachment__name">cool.jpg</span> <span class="attachment__size">4.1 MB</span>
    </figcaption>
</figure>

当我在基于 Bootstrap 的页面上显示编辑器生成的 HTML 时,图像明显扩展了屏幕(参见 widthheight)我想删除这些道具并将 img-fluid class 分配给它。

所以基本上我想使用配置:

Trix.config.css.attachment = 'img-fluid'

但这确实 a) 不会将 attachment class 更改为 img-fluid 并且它也不会将更改应用于图像但 figure.

我想避免在每次显示内容时使用 jQuery 并遍历所有内容 figures 然后在运行时操作图像的属性。

添加附件时没有定义这些样式的解决方案吗?

Trix does not have any kind of support to change the image element inside the attachment. One way to do it is by using MutationObserver 检查 Trix 编辑器中适用于 attributeschildListsubtree.

的突变

如果我们有 widthheight attributes 突变到具有 figure 父节点的 img 目标节点,那么我们删除这些属性我们可以将 class img-fluid 应用于第一个属性突变,例如 width.

运行 代码片段并尝试添加一些图像附件以查看或检查 HTML

请阅读内联评论

// Listen to trix-attachment-add event so we'll get rid of the progress bar just for this demo
// Here we should upload the attachment and handle progress properly
document.addEventListener("trix-attachment-add", event => {
  const { attachment } = event.attachment;
 
  // Get rid of the progress bar
  attachment.setUploadProgress(100)
});


// Get the Trix editor
const editor = document.querySelector('trix-editor');

// Instantiating an observer
const observer = new MutationObserver(function (mutations) {
  mutations.forEach(({ type, target, attributeName }) => {
    
    // If the parent is a figure with an img target
    if (target.parentNode.tagName === 'FIGURE' && 
        target.nodeName === 'IMG')
    {
      if (type === 'attributes') {
        switch(attributeName) {

          // If we have attribute width
          case 'width':
            // Remove attribute width
            target.removeAttribute('width');
            // Add img-fluid only once
            target.classList.add('img-fluid');
            break;

          // If we have attribute height
          case 'height':
            // Remove attribute height
            target.removeAttribute('height');
            break;
        }
      }

      // Render images HTML code
      renderHtmlOutput();
    }

  });
});

// Observing Trix Editor
observer.observe(editor, {
  attributes: true,
  childList: true,
  subtree: true
});

// Function to render every figure > img HTML code
function renderHtmlOutput() {
  const images = editor.querySelectorAll('figure > img');
  let output = '';

  for(const image of images) {
    output += image.outerHTML.replace(/ /g, "\n  ") + "\n";
  }

  document.getElementById('output-html').textContent = output;
}
body {
  height: 100vh;
  margin: 0;
  flex-direction: column;
  display: flex;
}
#main {
  display: flex;
  flex-direction: row;
  flex: 1;
  margin: 10px;
}

#editor-container {
  flex: 3;
}

#output-container {
  flex: 2;
  margin-left: 20px;
  border-left: 1px solid lightgray;
  overflow: auto;
}

#output-html {
  margin: 0;
  padding: 10px;
  font-size: small;
  color: blue;
}

/* Hide some Trix buttons to free horizontal space */
.trix-button--icon-increase-nesting-level,
.trix-button--icon-decrease-nesting-level,
.trix-button--icon-bullet-list,
.trix-button--icon-number-list { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/trix/1.2.1/trix.js" integrity="sha256-2D+ZJyeHHlEMmtuQTVtXt1gl0zRLKr51OCxyFfmFIBM=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/trix/1.2.1/trix.css" integrity="sha256-yebzx8LjuetQ3l4hhQ5eNaOxVLgqaY1y8JcrXuJrAOg=" crossorigin="anonymous"/>

<section id="main">
  <div id="editor-container">
    <form>
      <input id="editor" value="Editor content goes here" type="hidden" name="content">
      <trix-editor input="editor"></trix-editor>
    </form>
  </div>
  <div id="output-container">
    <pre id="output-html"></pre>
  </div>
</section>