Replace without start & stop


(NomNuggetNom ) #1

I’m trying to make a simple plugin that allows users to use fontawesome icons. For example, they would type: [fa:envelope] and it would be replaced with the icon.

I’ve seen lots of plugins use Discourse.Dialect.inLineBetween, which seems to be the standard. However, I don’t have a start and stop. Is there a standard hook I should be using to process the text correctly?

I know that Discourse.Dialect.postProcessText is a global receiver of text, but I don’t know if this is the way I should be doing it. Any help is appreciated :).

EDIT: Another concern I have is code blocks. Will this be handled automatically? In my experience Disource.Dialect.postProcessText was passed text in raw sections.


(Jens Maier) #2

Try something like this:

Discourse.Dialect.inlineRegexp({
  start: '[fa:',
  matcher: /^\[fa:([a-z]+)\]/
  emitter: function(match) {
    var icon = match[1];
    return ['i', {class: ['fa', 'fa-' + icon]} ];
  }
});

You’ll probably want to return bare text if the extracted word isn’t a valid icon, you need to whitelist the CSS classes that are being used and I’m not sure that I’ve built the class array right. :grin:


(NomNuggetNom ) #3

Awesome, thank you! I’ve gotten it working:

And here is my code:

https://github.com/NomNuggetNom/discourse-fontawesome/blob/master/assets/javascripts/fontawesome.js


(NomNuggetNom ) #4

Actually, it’s not working. I can post:

This is a test post.

But when I try to post:

[fa:circle] This is a test post

I get this:

And when I try and edit an old post to contain [fa:circle]

Even though it looks correct in the preview pane! What am I doing wrong?


(Jens Maier) #5

Anything in the server log?


(NomNuggetNom ) #6

Forgot about that, here’s the log:

at escapeHTML (/var/www/discourse/vendor/assets/javascripts/better_markdown.js:441:19)
at render_tree (/var/www/discourse/vendor/assets/javascripts/better_markdown.js:477:21)
at render_tree (/var/www/discourse/vendor/assets/javascripts/better_markdown.js:468:21)
at Markdown.renderJsonML (/var/www/discourse/vendor/assets/javascripts/better_markdown.js:387:23)
at Discourse.Dialect.cook (/var/www/discourse/app/assets/javascripts/discourse/dialects/dialect.js:269:25)
at makeHtml (/var/www/discourse/app/assets/javascripts/discourse/lib/markdown.js:287:34)
at <eval>:1:44
/var/www/discourse/lib/pretty_text.rb:185:in `block in markdown'

Link for convenience:

https://github.com/discourse/discourse/blob/master/vendor/assets/javascripts/better_markdown.js#L441

Here’s the HTML from the post in the preview pane:


(Jens Maier) #7

Huh. Isn’t there an actual error message besides the stack trace?


(NomNuggetNom ) #8

PrettyText::JavaScriptError (PrettyText::JavaScriptError)

Nothing too helpful.


(Kane York) #9

That sounds like a JS syntax error… anything in your browser console?


(Jens Maier) #10

Ok, I see what’s going on. Ember, which is only present on the client, defines replace for Arrays, which is why it works in preview but not on the server…

Just eliminate the array: {class: "fa fa-"+icon}
That was a mistake on my part to begin with.


(NomNuggetNom ) #11

Perfect! Thank you! Here’s the finished plugin:

(function() {
  Discourse.Dialect.inlineRegexp({
    start: '[fa:',
    matcher: /^\[fa:([a-z-]+)\]/,
    emitter: function(contents) {
      var icon = contents[1];
      return ['i', {class: 'fa fa-' + icon}];
    }
  });
  Discourse.Markdown.whiteListTag('i', 'class', /fa fa-[a-z-]+/);
})();

Obviously nothing special, but I had to start somewhere :blush:.