Problem/Motivation

Many sites need code formatting/syntax highlighting enabled for at least one of their text formats. However, it's surprisingly difficult to get it right on a Drupal site. For Drupal 8, several solutions exist such as:

Proposed resolution

We've settled on using CKEditor in Drupal 8 so the most sensible thing to do is to continue extending it for our needs. There's a great addon/library called Code Snippet that does just what we need and uses the popular highlight.js library.

There's also an excellent contrib module that acts as a wrapper for the Code Snippet library called CKEditor CodeSnippet. It very easily allows to add the Code Snippet button to the CKEditor toolbar and customize the languages that are supported as well as the template to use to render code blocks. Its requirements are that you add the library under the libraries directory at the root of your Drupal install and that you ensure <code> and <pre> are accepted HTML elements in your text formats.

This feature wouldn't be enabled by default so it wouldn't be intrusive.

Remaining tasks

  • Discuss relevancy (how code formatting needs compare to, e.g. sub/super script that ship but aren't enabled by default)
  • Evaluate if the CodeSnippet popup is compatible with our accessibility standards
  • Discuss whether we want to support another CKEditor plugin in core.

User interface changes

  • In case we'd be incorporating the CKEditor CodeSnippet Drupal module 'as is' in core, then users would have to enable the module from the Extend page.
  • If not, then nothing would change as the feature would be available as part of the CKEditor module integration
  • Users are now exposed with a new CKEditor button for code formatting when they are editing a CKEditor-powered text format.

API changes

None expected.

Data model changes

None expected.

Comments

anavarre created an issue. See original summary.

cilefen’s picture

Issue summary: View changes

"Discuss relevancy" is important. Developers know that code formatting is something a good site must have of course, but the rest of the world who don't code cannot be convinced. And, developers will find it easy to install a contrib module.

anavarre’s picture

Issue summary: View changes
thpoul’s picture

Issue tags: -ckeditor, -UX

I second #2. I personally can't imagine anyone else than a developer making use of it. There is already https://www.drupal.org/project/codesnippet which works great.

anavarre’s picture

It'd also be helpful for people writing technical documentation, e.g. a knowledge base

#4 - The proposal is about just that: adding https://www.drupal.org/project/codesnippet in a way that suits core.

wim leers’s picture

We've done #1993928: Language of parts: Introduce a language toolbar button for the Drupal 8.1 release. That also isn't relevant for everybody (many sites are monolingual). But it's a great option to have that preconfigured/well-integrated out of the box, because it addresses a common need.

I think the same can be said for this module. I'd love to first better understand how mature the Drupal contrib module is (i.e. the maintainer's POV), because there obviously is much more to configure than there is for #1993928: Language of parts: Introduce a language toolbar button. More to configure means more things that can go wrong or can be complex, and it's that that we must fully understand before actually considering to add this to Drupal core.

wim leers’s picture

kevinquillen’s picture

Two things that are hard at the moment with the nature of the plugin itself:

  • Adding custom stylesheet
  • Adding more languages

There are plenty, plenty of styles that come with the plugin out of the box that should be sufficient. But you always have a few who want to use their own. The module only looks at the styles directory of the plugin right now. This is minor to me.

Adding more languages to highlight is a little higher. At the moment, to support more languages you need to form alter and add your options, and you run into a few tricky parts:

  • The option key must match what HighlightJS designates as the language code
  • No easy-ish way to get that from the HighlightJS page without inspecting
  • You must pack your own HighlightJS, download and replace it to get support for your new language option(s)

Again, this may suit 99% of folks out there, but if someone wants to highlight some Erlang or Elixir for example, they will be out of luck. I am probably overthinking it and it could be not really an issue. The HighlightJS that would go into core could be customized with a more curated list, not sure how that would be handled.

Beyond that, it seems to work pretty well and feedback otherwise has been good.

edit: actually I just noticed that the default language list has changed with the last few releases, and I will need to update.

kevinquillen’s picture

It looks like the version of HighlightJS that ships with the codesnippet plugin is version 8, while the current release is version 10. How could that be resolved? Anyone who replaces HighlightJS with their own custom build will be on the new version.

kevinquillen’s picture

You could supply your own highlighting engine to this API.

In the interest of core, which one would satisfy most use cases? I still see similar issues persisting no matter the engine (adding new languages).

wim leers’s picture

Thanks, that's very helpful!

Let's first address the language selection. This is a hardcoded list, that can evolve over time. We don't want to expose the entire list, at least not by default. Funny coincidence: this is exactly the same problem that we faced at #1993928: Language of parts: Introduce a language toolbar button :) There, the language system came to our help in providing a predefined shorter list of languages (United Nations official languages). So then the site builder can choose either that shorter list, or the full list. We could do something similar here.

Second: code syntax highlighting theme selection. This is something that we can indeed easily auto-detect and then expose those choices.

Finally: CKEditor also offers codesnippet_geshi, which does server-side syntax highlighting (and hence doesn't require JS). This was the most popular option in the past. But not anymore. And more importantly, Geshi itself seems to have died: https://github.com/GeSHi/. So that's not even something we should remotely consider.

I'm going to do a review of your code and possibly post some patches.

kevinquillen’s picture

Some would say to throw all options in, but that isn't practical because it would be about 300kb+ in size for that javascript file, which loads for everyone. ~30-50kb would be optimal to me. Is there a way to customize the build instead of the download from ckeditor.com in a way that is easy to manage?

Was aware of GeSHi but was not aware of its inactivity. HighlightJS just released version 9.6.0 (my bad, I referenced it as 10 before) and is 10 years old. Looks like it still gets regular updates every couple of months.

There are others, like PrismJS, as well.

I would think that at a minimum, it should support:

  • HTML
  • CSS
  • PHP
  • Yaml
  • Sass
  • Less
  • Javascript
  • JSON
  • Gherkin
  • XML
  • Bash
  • SQL
wim leers’s picture

I didn't realize there were different packaged versions of highlight.js. That makes things annoyingly subjective :( I'd personally definitely omit Gherkin, for example. I'd also certainly include Diff and INI.

An easy-to-manage way for customizing that for a particular site… that's just not really feasible, unfortunately.

I think that even just for that reason, this being added to core may need to be postponed, until you've figured out a workable solution for that in contrib. Unless we can reach broad agreement on which languages to support.

Although… can't we rely on generic syntax highlighting for everything but the most common languages? Maybe we can even pick an objective metric, such as "top 20 languages"?

anavarre’s picture

I've been wondering about Prism as well since there's an already existing CKEditor add-on. As the add-on page says:

Essentially, it's the Code Snippet plugin with PrismJS under the hood.

Which is something that makes me wonder if that could be an alternative to highlight.js in case it wouldn't be suitable to core?

#11

Let's first address the language selection. This is a hardcoded list, that can evolve over time. We don't want to expose the entire list, at least not by default.

Could config.codeSnippet_languages help?

#12

Some would say to throw all options in, but that isn't practical because it would be about 300kb+ in size for that javascript file, which loads for everyone. ~30-50kb would be optimal to me.

The prism.js homepage says:

The core is 2KB minified & gzipped. Languages add 0.3-0.5KB each, themes are around 1KB.

But https://raw.githubusercontent.com/ranelpadon/ckeditor-prism/master/lib/prism/prism_patched.min.js is 98k large and 37k large when gzipped on my local computer.

Perhaps this is because the CKEditor add-on extends other libraries?

#13

Although… can't we rely on generic syntax highlighting for everything but the most common languages? Maybe we can even pick an objective metric, such as "top 20 languages"?

We can still follow the top 20 from http://www.tiobe.com/tiobe-index and add a few that we believe to still be relevant for a vast majority of developers/technical writers (e.g. diff)

Popularity

  • prism.js: 3.4k stars on Github, 145 contributors (last commit 13 hours ago)
  • highlight.js: 8.2k stars on Github. 289 contributors (last commit 6 days ago)
kevinquillen’s picture

Prism faces that same problem - if you wanted to support highlighting of many languages OOTB, the kitchen sink version (without any extra plugins for it) weighs in at:

Total filesize: 217.17KB (99% JavaScript + 1% CSS)

And thats minified.

Prism has the added benefit to have additional plugins (I use it on a non Drupal site) enhancing the highlighter, but it doesn't look like the ckeditor plugin makes much use of those. Again, adding those in is another 1-2 kb each. Not a big deal on desktop + wired connection, but bad for mobile and will ding you on performance benchmark frontend tests (if you're into that sort of thing).

The config.codeSnippet_languages is just a list - to actually support highlighting, the language needs to be packed into the javascript file. For example, if you added a new language in the form and the config, it will appear, but not highlight. That is why you have to go and select what languages you want these highlighters to support, and generate the new js file.

Both of the ckeditor plugins come with them bundled in, which is confusing because they could be versions behind (HighlightJS is) and configured differently than the default downloads on their site.

kevinquillen’s picture

This is interesting, I skipped right over this part before.

The CDN-hosted package doesn't have all the languages. Otherwise it'd be too big. If you don't see the language you need in the "Common" section, it can be added manually:

<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/go.min.js"></script>

This is the Common list:

  • Apache
  • Bash
  • C#
  • C++
  • CSS
  • CoffeeScript
  • Diff
  • HTML
  • XML
  • HTTP
  • Ini
  • JSON
  • Java
  • JavaScript
  • Makefile
  • Markdown
  • Nginx
  • Objective-C
  • PHP
  • Perl
  • Python
  • Ruby
  • SQL

That should be good enough for most, I would think.

Is there a way we can request updating the version of HighlightJS in the ckeditor.com plugin to the latest version? As for the extra languages, could there be an extended UI like Wim was mentioning, and add this into the page when language boxes are checked off:

<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/go.min.js">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/rust.min.js">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/erlang.min.js">

etc? That might be a good middle ground.

kevinquillen’s picture

Upon looking at the codesnippet plugin.js, I have refactored the CodeSnippet class to remove the config object that held codesnippet settings, as it was superfluous and really wasn't useful, #2800233: Refactor to remove dependency on config object.

It looks like it was there to do two things:

  • Set all languages as set by default when installing
  • Provide human friendly names

It looks like I did that to get around some quirks with the checkboxes form element. For example, the cpp array item value is C++. If you were to wrap that with an array_map, values like that will never be set as checked. Is there a cleaner way to do this?

I also posted a patch to introduce a hook_uninstall procedure, where the module cleans up after itself. See: #2800239: Cleanup on uninstall. I noticed that when uninstalling, plugin information isn't removed from editor configurations. Seems like it should be.

Grayside’s picture

Looking beyond content creation, a solution to add syntax highlighting might encompass serialized data highlighting, which goes beyond the WYSIWYG.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

wim leers’s picture

Status: Active » Closed (works as designed)

So, let's be realistic: this is not going to happen in Drupal core in the foreseeable future.