Include images and fonts in themes and components

Themes and theme components allow you to handle uploaded assets such as images and fonts. You can control what assets your theme accepts using the site setting: theme authorized extensions

There are two classifications of themes and components - local and remote.

Local:

  • The default Light and Dark themes that ship with every Discourse instance
  • Themes and components created using the + Create New installation method
  • Themes and components that were uploaded from your local computer using the From your device installation method.

Remote:

  • Themes and components installed from the Popular list of themes
  • Themes and components installed using the From a git repository method

Uploading assets to local themes and components

Navigate to your theme or component and select + Add in the Uploads section:

In the Add Upload modal, choose a file and enter a SCSS variable name to use with with your CSS, javascript, and/or handlbars customizations

Once uploaded, the asset will pop up in the Uploads list:

uploaded-font

:warning: Important Note: Do not add uploads to themes and components through the admin interface if the component was installed remotely from a git repository. Updates to the component will clear out any uploads that were not included in the git repository.

Including assets in remote themes and components

See Create and share a font theme component for a detailed example.

How to make use of the assets

SCSS

@font-face {
  font-family: Amazing;
  src: url($Comic-Sans) format('woff2')
}

body {
    font-family: Amazing;
    font-size: 15px;
} 

.d-header {
    background-image: url($texture);
}

Javascript

<script type="text/discourse-plugin" version="0.8">
   console.log(settings.theme_uploads.balloons)
</script>

Handlebars

<script type="text/x-handlebars" data-template-name="/connectors/topic-above-post-stream/foobar">
  <img src="{{theme-setting "theme_uploads.balloons"}}">
</script>
19 Likes

Can this be used to add additional javascript files as “assets”? Or is it just images/fonts?

If it would allow javascript files, that could effectively allow client-side plugins to be distributed without having to mess with app.yml, which would be awesome! Especially for people on managed hosting who can’t install plugins.

Up to @sam but that sounds like a lot of scope creep to me. Plus added danger…

1 Like

Oh wow, this is awesome! Themes keep getting better and better. :slight_smile: For those of us experimenting with building remote repo themes, what is (or will be) the equivalent way to include assets in our repository?

5 Likes

Yeah, this is not planned at the moment. My brain can think of a hack that could make this work, but it is horrid and I am not going to disclose how it could be done.

I think we can revisit this in a few more months when the system has fully stabilized and community themes and theme components have sprouted :sunflower:

9 Likes

Hi.

I tried to add google material design font-icons as posted above, but I couldn’t succeed. I just wanted to be sure if I’m doing anything wrong or this recipe is not for font-icons.

I did as followings:

  • uploaded the icon font via the +add button of the theme,
  • scss name is set to $Material
  • added these lines in the body:
@font-face {
  font-family: Material Icons;
  src: url($MIwoff2) format('woff2')
}
  • added these lines to css:
  .fa-gear::before{
  font-family: 'Material Icons';
  font-feature-settings: 'liga';
  font-weight: normal;
  font-style: normal;
  font-size: 24px;  /* Preferred icon size */
    content: "settings";
}

Screenshot of upload section? Any errors when you save the sass?

all the font formats seem to be uploaded, without errors:

and this is the screenshot of the settings icon:

If the CSS saves with no error when you add the var it means it should have taken correctly. Maybe try explicitly to preview the component, then dig into CSS using dev tools.

2 Likes

the error was with the font icons, it seems that the way to use material design icons is to add this line to the head section, and not to attach them!

<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet">

Currently (as of 2018-08-18) after uploading three weights of a single font family, each with unique variable names:

  1. If I use the full URL path to the uploaded font, things are fine, but
  2. If I use the variable, the font does not render.

:frowning:

Is it possible to upload images in PNG format - to preserve their transparent background?

I’m trying to upload the logo & small logo for our site but it’s being converted to JPG.

becomes

I’m trying to create a dark theme for the site at the moment (:wave: Mojave) & this giving the image a white background which doesn’t look that great.

Try the instructions laid out in this topic:

And also note:

https://meta.discourse.org/t/how-to-actually-upload-files-to-a-new-discourse/40877/7?u=tshenry

4 Likes

Simpler workaround here would be to run png through tinypng.com and upload that

2 Likes

If I upload a font, I get a CORS policy for the No ‘Access-Control-Allow-Origin’ because our uploads are via a different subdomain on our ‘s3 cdn url’ setting e.g. forums.mudspike.com vs uploads.mudspike.com (for the CDN).

Is there a way to get around that for font files in themes?

this makes me wonder…

i do love the Samsung Sans font. How would I go about changing my site’s font to Samsung Sans?

In the site settings there’s an cors origins option — if you add your uploads url there it should allow it.

All the instructions for adding a custom font are in the original post above. You need to upload the font file and then add the custom CSS.

7 Likes

Just a note here that I was playing around with images in themes, and found that I wanted to use a theme image url in a template. Perhaps there’s another way of doing this, but I found this nifty method using SASS functions and JSON: Making Sass talk to JavaScript with JSON | CSS-Tricks

about.json

"assets": {
  "balloons": "assets/balloons.png",
  "bike": "assets/bike.png"
}

common.scss

@function image-urls() {
  @return '{ "balloons" : "#{$balloons}", "bike" : "#{$bike}" }';
};

body::before {
  display: none;
  content: image-urls();
}

head.html

<script type='text/x-handlebars' data-template-name='components/categories-and-latest-topics'>
  ...
  <img src="{{imageUrls.balloons}}">
  ...
</script>

<script type="text/discourse-plugin" version="0.8">
const computed = require('ember-addons/ember-computed-decorators').default;

api.modifyClass('component:categories-and-latest-topics', {
  @computed()
  imageUrls(){
    let style = null;
    if (window.getComputedStyle && window.getComputedStyle(document.body, '::before')) {
      style = window.getComputedStyle(document.body, '::before');
      style = style.content;
    }
    return JSON.parse(JSON.parse(style));
  }
});
</script>
8 Likes

Nice workaround! I think it would be good for us to make asset URLs available to javascript/templates. Easiest thing would be to make it work like

handlebars: {{theme-setting "assets.balloons"}}

javascript: settings.assets.balloons

Or with slightly more effort we could have

handlebars: {{theme-asset "balloons"}}

javascript: themeAssets.balloons
11 Likes