basecamp/trix

heading1 override doesn't work when updating content in Chrome

Closed this issue · 9 comments

When using:

Trix.config.blockAttributes.heading1.tagName = "h3";

to override the heading tag to h3, it works when adding new content, but not when updating existing content inside the editor.

Steps to Reproduce
  1. Use Chrome to open https://codepen.io/anon/pen/ejoaBO
  2. Inspect the source the source and you'll see the h3 tag is converted to a div with br tags

<div><!--block--><strong><br>H3 Heading<br></strong><br></div>

Details
  • Trix version: latest
  • Browser name and version: Chrome 68.0.3440.106 (Official Build) (64-bit)
  • Operating system: Mac OS High Sierra
javan commented

I think the issue you're having is with CodePen, actually. Your JS code gets processed by Babel and added to the page asynchronously so your Trix.config change isn't applied until after the initial content has loaded.

Seems to work fine here: https://jsfiddle.net/javan/zs3wdfy6/

I appreciate your quick response, but it's not that because I updated the codepen with your jsfiddle code and removed the Babel pre-processing (I had forked a different example that had that and didn't remove it), and the issue is still there for me in Chrome https://codepen.io/anon/pen/ejoaBO

I can see your jsfiddle example works, but on my website even if I edit the trix.js file and add the override below the trix code so there are to timing issues, the issue is still there in Chrome.

Question: Is there an existing event where I would be able to add the override before the editor initializes that would allow to programmatically make always the configuration change on time.

javan commented

Let's rule out any timing issues caused by online code editors. Can you make a plain HTML file that reproduces the issue? Here's mine: https://gist.github.com/javan/82cb8c485155c76f52b0e052afec914e

Thanks javan for your time and the examples. I finally managed to get this working within my application by changing the way I was adding the config override. It would be nice if there were a way to add the changes before the editor initializes using an event so that timing issues would never be a problem.

I use a javascript loader so it doesn't look like it's possible to change the configuration this way because when the trix script loads, the trix element has already been loaded onto the page.

@javan Please check this example here using the javascript loader https://gist.github.com/jreviews/2f0e2a29c1ae0ab552b91b5f82ed0a1c

I understand that it doesn't work due to the timing issue because trix will process the existing trix-editor elements as soon as it loads. And that is why I think it would be useful to have an event/callback that is run before that happens that allows you to change the configuration settings before the tags are processed. For now, I have to modify the core code to replace the h1 tag directly, but this also doesn't allow to make this configurable. Another option would be to allow using data attributes in the trix-editor tag to allow specifying the values there, but this would also have to work when there are many editors on the page.

Hopefully, these suggestions can be taken into consideration.

Thanks!

javan commented

For now, I have to modify the core code to replace the h1 tag directly

If you're using a build tool like webpack, I suggest creating a custom bundle instead. Something like:

// trix-bundle.js
const Trix = require("trix")
Trix.config.blockAttributes.heading1.tagName = "h3"
<script>
  head.load("/js/trix-bundle.js", function() {
    console.log("My custom Trix bundle loaded…")
  })
</script>

I have this issue

#= require vendor/trix
Trix.config.blockAttributes.heading1.tagName = 'h2'

coffee sprockets, no webpack and babel

For now, I have to modify the core code to replace the h1 tag directly

If you're using a build tool like webpack, I suggest creating a custom bundle instead. Something like:

// trix-bundle.js
const Trix = require("trix")
Trix.config.blockAttributes.heading1.tagName = "h3"
<script>
  head.load("/js/trix-bundle.js", function() {
    console.log("My custom Trix bundle loaded…")
  })
</script>

I'm actually quite positive that this won't work as expected. The reason is that packaging it in a module is no different than executing the library and the config lines one after the other after the html is already loaded on the page. It's just that as the browser interprets the JS, the require("trix") will find any instances of trix-editor and will act on them. It is only the after that the Trix.config.blockAttributes .. will apply.

At least that's the behaviour I'm seeing by extracting trix and its config in a separate, async-loaded module.

So, I do believe that cases when html is first on the page, and js is loaded second is problematic for applying configs to Trix.

I had the same problem, with Rails and Vite-Rails. I have a custom trix-package, in which I basically did this:

document.addEventListener("trix-before-initialize", () => {
  Trix.config.blockAttributes.heading1.tagName = 'h3';
});

import 'trix';

However, my event handler trix-before-initialize was never reached, as the build tool probably changes the line order, or something like that 🤷

What did help was putting a <script> tag in my <head>-section, which is executed synchronously, and therefore before the trix package gets loaded, e.g. before trix is initialized:

// app/views/layouts/_head.html.erb
<script>
  document.addEventListener("trix-before-initialize", () => {
    Trix.config.blockAttributes.heading1.tagName = 'h3';
  });
</script>

I would really love to be able to change the configuration before trix gets initialized, e.g. something like

import Trix from `trix`;
Trix.config.blockAttributes.heading1.tagName = 'h3';
Trix.start();

This could be done by adding named exports to the trix package, which would not clash with the current default export, and would therefore be downward compatible!