Templating of my "component" broke. How do I fix it?

In a Discourse instance I maintain, I have a component (inherited from the previous maintainer of the instance) to display the logos of the sponsors of that instance in the footer. The component used to work fine until recently, but now is rendered wrongly, displaying the template control directives literally (and putting the template value placeholders literally into the HTML, so that the paths to the images aren’t resolved):

The component isn’t maintained in a git repo, it’s configured directly under “Admin” → “Appearance” → “Themes & components” → tab “Components”:

Custom Code

Custom sections:

  • Common: CSS, Footer, JS

Uploads

Extra files

Export theme to view these files.
  • javascripts/discourse/api-initializers/theme-initializer.gjs

content of those “sections”

as seen when clicking “Edit Code”; path to corresponding files in the export given in parentheses

CSS (common/common.scss)
.sponsors {
    .inner {
        display: flex;
        align-items: center;
        justify-content: space-around;
        margin-bottom: 10px;
    }

    .heading {
        font-size: 1.75em;
    }

    .sponsor-image {
        max-height: 55px;
    }

    .geoaargau {
        max-height: 45px;
    }
}
Footer (common/footer.html)
  {{#if displaySponsors}}
    <div class="sponsors-wrapper wrap">
      <div class="inner">
        <h3 class="heading">Sponsoren</h3>
        <a href="http://www.asseco-berit.ch/"><img src="{{theme-setting "theme_uploads.asseco_berit"}}" alt="Asseco Berit" class="sponsor-image asseco-berit"></a>
        <a href="http://www.geoaargau.ch/"><img src="{{theme-setting "theme_uploads.geoaargau"}}" alt="GEOAargau" class="sponsor-image geoaargau"></a>
      </div>
    </div>
  {{/if}}
JS (javascripts/discourse/api-initializers/theme-initializer.gjs)
import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  // This is the plugin outlet, followed by a custom name for the component
  api.registerConnectorClass("above-footer", "sponsors", {

    setupComponent(args, component) {
        
     var topMenuRoutes = 
        component.siteSettings.top_menu.split('|')
        .map(function(route) {return '/' + route});
      
     var homeRoute = topMenuRoutes[0];
     
     api.onPageChange((url) => {

        if (url === "/" || url === homeRoute ){ 
          document.querySelector("html").classList.add("sponsors"); 
          component.set("displaySponsors", true); 
        } else {
          document.querySelector("html").classList.remove("sponsors"); 
          component.set("displaySponsors", false); 
        }
      });
    }
    
  });
});

The export additionally contains:
about.json (466 Bytes)
which I guess is generated on-the-fly when exporting, so I don’t assume it’s relavant.

The relevant part of the effective DOM with this breakage is:

<div class="custom-footer-content">
    {{#if displaySponsors}}
    <div class="sponsors-wrapper wrap">
      <div class="inner">
        <h3 class="heading">Sponsoren</h3>
        <a href="http://www.asseco-berit.ch/"><img src="{{theme-setting " theme_uploads.asseco_berit"}}"="" alt="Asseco Berit" class="sponsor-image asseco-berit"></a>
        <a href="http://www.geoaargau.ch/"><img src="{{theme-setting " theme_uploads.geoaargau"}}"="" alt="GEOAargau" class="sponsor-image geoaargau"></a>
      </div>
    </div>
  {{/if}}
</div>

so we can see that the control directive {{#if ...}}...{{/if}} and the placeholders {{theme-setting "..."}} were used as literal HTML rather than executed / evaluated / interpolated.

How and why did that change and how should I fix it?

Is it maybe related to Upcoming Header Changes - Preparing Themes and Plugins? (Though I don’t see changes to the templating syntax mentioned there.)

לייק 1

(By “how and why” I mean: What was the underlying change, and did I miss any notifications about it? I’m sufficiently sure that whatever caused this change in behavior landed in that instance by the activated automatic Discourse updates, but I’d like to know what the root cause is.)

Is there any error or warning in the console to provide further info?

לייק 1

In the browser console? Maybe — I’m not sure what’s “normal” there and what could be hinting at the issue. Can I just paste its contents here or could that leak sensitive information?

Yes, the browser console – it’s fine to paste it :slight_smile: Often, if something is deprecated, the console will throw some useful info out

לייק 1
Full browser console content from loading https://www.geowebforum.ch/c/feedback/2
ℹ️ Discourse v2026.3.0-latest — https://github.com/discourse/discourse/commits/38ad2acd2c — Ember v6.6.0 chunk.f47b6dc1cc59c827db42.d41d8cd9.js:275:35231
[PLUGIN discourse-weekly-newsletter] To prevent errors in tests, add a `pluginId` key to your `modifyClass` call. This will ensure the modification is only applied once. chunk.f47b6dc1cc59c827db42.d41d8cd9.js:209:136918
DEPRECATION NOTICE: Defining connector classes via registerConnectorClass is deprecated. See https://meta.discourse.org/t/32727 for more modern patterns. [deprecation id: discourse.register-connector-class-legacy] chunk.f47b6dc1cc59c827db42.d41d8cd9.js:134:74065
Error in parsing value for ‘-webkit-text-size-adjust’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:1:800
Error in parsing value for ‘-moz-text-size-adjust’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:1:827
Unknown property ‘text-size-adjust’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:1:849
Unknown pseudo-class or pseudo-element ‘-moz-focus-inner’.  Ruleset ignored due to bad selector. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:1:1615
Expected ‘none’, URL, or filter function but found ‘alpha(’.  Error in parsing value for ‘filter’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:622
Ruleset ignored due to bad selector. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:36117
Error in parsing value for ‘justify-content’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:181379
Error in parsing value for ‘text-wrap’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:205516
Error in parsing value for ‘image-rendering’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:264428
Error in parsing value for ‘-webkit-text-size-adjust’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:268491
Error in parsing value for ‘-moz-text-size-adjust’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:268518
Unknown property ‘text-size-adjust’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:268540
Error in parsing value for ‘font-size’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:298136
Expected ‘none’, URL, or filter function but found ‘alpha(’.  Error in parsing value for ‘filter’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:447258
Expected ‘none’, URL, or filter function but found ‘alpha(’.  Error in parsing value for ‘filter’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:447681
Expected ‘none’, URL, or filter function but found ‘alpha(’.  Error in parsing value for ‘filter’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:6:33799
Error in parsing value for ‘text-wrap’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:6:105390
Error in parsing value for ‘text-wrap’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:6:105471
Error in parsing value for ‘padding’.  Declaration dropped. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:6:257744

I guess I have to look at Using Plugin Outlet Connectors from a Theme or Plugin

So, I think registerConnectorClass with setupComponent is deprecated, see your error log:

DEPRECATION NOTICE: Defining connector classes via registerConnectorClass is deprecated. See https://meta.discourse.org/t/32727 for more modern patterns. [deprecation id: discourse.register-connector-class-legacy] chunk.f47b6dc1cc59c827db42.d41d8cd9.js:134:74065

and I’m also not sure we still tolerate the raw html, like in your footer component.

So this component will have to be refactored to modern patterns, and I’d advise moving it to a proper component as well, as opposed as where it currently lives under Admin.

To answer your other question

It’s due to the ongoing work of modernising Discourse and moving to new modern standards with Glimmer components.

3 לייקים

If not raw HTML(-template), what is the expected content of https://www.geowebforum.ch/admin/customize/themes/3/common/footer/edit? Markdown, like in user-provided content?

Can you point to some guidance on how to do this? I’m feeling a bit lost with Discourse documentations seemingly spread all over the meta forum.

For that, can I just unpack the “export” and check it into a Git repo?

Isn’t my component already a Glimmer component if it has a *.gjs file in the export? Or is that actually part of the problem – current Discourse mistaking my component for a Glimmer component (and thus exporting it with that file name) although code-wise it isn’t one yet?

(Please excuse my ignorance. I’m not a web dev and know near nothing about Ember and Glimmer.)

לייק 1

I meant: The raw HTML isn’t properly parsed anymore with the latest version, hence you are just seeing the HTML dumped instead of rendered.

Yes, .gjs file indeed indicated a glimmer component, but the used method of registerConnectorClass in it won’t work (anymore)/

This is fully understandable. What Using Plugin Outlet Connectors from a Theme or Plugin essentially is saying is that, to render information somewhere on the page via that registerConnectorClass method , the way your footer.html file did, we now use a specific element, called a plugin outlet. For a footer, the above-footer outlet would work well.

It’s probably a good idea to read through Beginner's guide to using Discourse Themes and Developing Discourse Themes & Theme Components

It can also help to have a look at a simple theme component, to understand the structure. For example: GitHub - discourse/discourse-minimal-footer · GitHub

And finally, the Discourse bot might be able to help you a whole end of the way: it knows Discourse patterns well so you can give it your current code, explain the issue, and ask it to help you refactor it.

If you absolutely don’t feel like tinkering with it, the last option is to make a topic in Marketplace for some paid help.

But it’s really a very small component so I personally would advise to start with setting up a new component via our template, and figuring it out with the help of the bot.

2 לייקים

Do you refer to @discobot?