Integrating a customized highlight.js into my forum


(Mark Alldritt) #1

I have a need to incorporate a customized version of highlight.js in my Discourse forum. What is the best way to go about this without interfering with the Discourse update processes?


(Mark Alldritt) #2

As I read further, I see the following articles:

This is all pretty heavy weight for what I want to do. I need to apply a patch to highlight.js to introduce 3 extra lines. Can this be done safely from the container/app.yml file (or some other configuration point)? There is a build process for highlight.js and its not clear to me when that takes place in Discourse.


(Jeff Atwood) #3

Why do you need it customized? Can you explain with an example?


(Mark Alldritt) #4

Sure.

My Discourse forum is focused on my product which is an AppleScript editor and debugger. Mac OS X defines a AppleScript URL scheme for loading source code in a new window within an AppleScript script editor application. This URL takes the form: applescript://com.apple.scripteditor/action=new&script=<url-encoded-source-code>. My modifications to highlight.js add a HTML link for this URL so that my users can load code samples directly into my product.

I’m trying to add this code to the highlight function (just before the return statement) within highlight.js:

  if (name == "applescript") {
    result = "<p><strong><a class=\"hljs-title\" href=\"applescript://com.apple.scripteditor?action=new&script=" + encodeURIComponent(value) + "\">Open in Script Debugger</a></strong></p>" + result;
  }

(Jeff Atwood) #5

If you look at #releases you will find that arbitrary URI components are on the release list for the current beta 1.7.


(Mark Alldritt) #6

Support for other URL schemes will be really helpful when it lands. However, the change I’m trying to make will generate these URLs automatically for all AppleScript sample code my users post. This matches the behaviour of other AppleScript-centric sites and is a much requested feature for our forum.


(cpradio) #7

I think you can achieve this if you override this module and point it to your custom highlight.js (through a plugin)


(Mark Alldritt) #8

Thank you for this suggestion. I’ve managed to create a plugin that replaces the HighlightJs.bundle method and introduces my Open in Script Debugger link. However, I’ve stumbled again because Discourse’s click-tracking mechanism is not allowing clicks on my sdapplescript:// link to be forwarded by the Web browser to my application.

My Plugin looks like this:

# name: 	LNSHighlightJS
# about: 	Patch HighlightJs module to provide applescript:// links
# version: 	0.1
# authors: 	Mark Alldritt
# url:		https://github.com/alldritt/discourse-LNSHighlightJS


after_initialize do

  #puts("LNSHighlightJS.a")
  
  module ::HighlightJs
#    def self.languages
#	  Dir.glob(File.dirname(__FILE__) << "/../../lib/assets/lang/*.js").map do |path|
#	    File.basename(path)[0..-4]
#	  end
#   end

    def self.bundle(langs)
      warn("LNSHighlightJS.HighlightJs.bundle");

	  path = File.dirname(__FILE__) << "/../../lib/highlight_js/assets/"

 	  result = File.read(path + "highlight.js")
	
	  # Patch the contents of highlight.js (now in result) to include our code...
	  matchCode = "return{"
	  newCode = "if(e==\"applescript\"){L=\"<p><strong><a class=\\\"hljs-title\\\" href=\\\"sdapplescript://com.apple.scriptdebugger?action=new&script=\"+encodeURIComponent(t)+\"\\\">Open in Script Debugger</a></strong></p>\"+L;}"
	  result = result.sub(matchCode, newCode + matchCode)

	  langs.each do |lang|
	    begin
		  result << "\n" << File.read(path + "lang/#{lang}.js")
	    rescue Errno::ENOENT
		  # no file, don't care
	    end
	  end

	  result
    end

#    def self.version(lang_string)
#	  (@lang_string_cache ||= {})[lang_string] ||=
#	    Digest::SHA1.hexdigest(bundle lang_string.split("|"))
#    end

#    def self.path
#	  "/highlight-js/#{Discourse.current_hostname}/#{version SiteSetting.highlighted_languages}.js"
#    end
  end
end

Do you have an suggestions for addressing this issue before I begin the process of trying to understand Discourse’s click-tracking code?


(cpradio) #9

Not sure what the error is, but I can tell you it will be in this file

And any changes you would need to make to that to support the different protocol, or tell it to skip click-tracking all together would likely be accepted in Core.

I think if you right-click and choose open in New Tab/Window, the link should work and skip click-track (again, I think). I know that isn’t the most feasible, but just something to keep in mind.

Actually thinking through this, if you change your generated link to also have the class of hljs-title no-track-link, it should solve your problem.


(Mark Alldritt) #10

Thank you again for the suggestion.

I tried adding the no-track-link class, but that resulted in this error from deep in ember_jquery:

[Error] SecurityError: DOM Exception 18: An attempt was made to break through the security policy of the user agent.
	pushState (application-72aac18a96c4f73cf687f7540a368cfdf6dec40bca63e533dbb5a93a06d3f98f.js:8:1335)
	pushState (application-72aac18a96c4f73cf687f7540a368cfdf6dec40bca63e533dbb5a93a06d3f98f.js:8:1335)
	setURL (application-72aac18a96c4f73cf687f7540a368cfdf6dec40bca63e533dbb5a93a06d3f98f.js:8:1089)
	i (ember_jquery-c9524b48466ee05bcf3f9ddaf05405387eb17017e61e90e76628f989db37eb4e.js:9:31196)
	invoke (ember_jquery-c9524b48466ee05bcf3f9ddaf05405387eb17017e61e90e76628f989db37eb4e.js:3:30779)
	flush (ember_jquery-c9524b48466ee05bcf3f9ddaf05405387eb17017e61e90e76628f989db37eb4e.js:3:31299)
	flush (ember_jquery-c9524b48466ee05bcf3f9ddaf05405387eb17017e61e90e76628f989db37eb4e.js:3:29456)
	end (ember_jquery-c9524b48466ee05bcf3f9ddaf05405387eb17017e61e90e76628f989db37eb4e.js:3:24655)
	(anonymous function) (ember_jquery-c9524b48466ee05bcf3f9ddaf05405387eb17017e61e90e76628f989db37eb4e.js:3:23479)

It appears to have something to do with pushing my URL onto the history stack, but my understanding of what is going on is poor so I could have it all wrong.

In the end, I switched from an <a href="..."> to <a onclick="window.open(...)"> and that is working.

For those that care:

Plugin: GitHub - alldritt/discourse-LNSHighlightJS: A discourse plugin that introduces a hacked version of highlight.js to provide 'Open in Script Debugger' links for AppleScript code blocks.

Example page: Google URL shortener - AppleScript - Late Night Software Ltd.