Jekyll, Liquid & Visual Studio Code

I’m switching from Atom to VS Code and I’m a bit overwhelmed by the options and the number of errors marked in the editor and explorer. Has someone managed to set up VS Code well for Jekyll?

Specifically:

  • Syntax highlighting for a mix of HTML + Liquid, JS + Liquid
  • Linting errors marked in the explorer for files with JS + Liquid

I’ve already installed the extensions ‘Liquid’, ‘Jekyll Run’, and ‘Jekyll Syntax Support’, but they don’t solve the issues above.

1 Like

I use VS Code for my Jekyll dev. I use “Liquid” extension also. Have you changed your format to “Liquid” in the bottom right?

image

I like using the Jekyll Syntax Support one (but I see it departed in favor of a Liquid one).

In Jekyll projects I set .md and .html files to “jekyll” in project settings file. Same as choosing “Jekyll (HTML)” in the bottom right.

I highlights HTML and Liquid and JS in a script tag. (I think I stopped using a Liquid extension and Liquid format before because it didn’t highlight HTML).
It doesn’t validate if, for etc.

It doesn’t format.

I use HTML format to prettify my file if there is a lot of HTML in it then I change back to Jekyll format for Jekyll support.

If you use jekyll build --trace, the errors in the console informative. Not as good as linting in place but it works.

Thank you Michael, that was very helpful. I wasn’t aware of how useful language and project-specific settings files are yet!

For those searching for this: you can change your VS Code preferences directly in its settings.json. Here are some of my preferences:

    "[jekyll]": {
        "editor.quickSuggestions": true,
        "editor.formatOnSave": true,
        "editor.wordWrap": "on",
        "editor.renderWhitespace": "all",
        "editor.acceptSuggestionOnEnter": "off"
    },
    "files.associations": {
        "*.md": "jekyll",
        "*.markdown": "jekyll",
        "*.html": "jekyll",
        "*.liquid": "jekyll",
    },

The only issue I still have is I have some JavaScript files with front matter and Liquid and those cause error warnings. Now I tried setting setting the language of all .js files to jekyll too, but that disables JavaScript syntax highlighting. My workaround:

  1. For each of the .js files that have front matter, set the language to ‘Jekyll (HTML)’ (bottom right)
  2. Move everything with JavaScript syntax to .js files in the _includes folder. Those files contain pure JS only.

The only thing I’d like to change is having the "editor.wordWrap": "on", setting only applied to markdown files, while maintaining the jekyll file association. I guess that’s not possible?

1 Like

I use the Liquid Language Support plugin by Neil Ding:
https://marketplace.visualstudio.com/items?itemName=neilding.language-liquid

I also use Shopify Liquid Template Snippets by Franky Lau. This does have a dependency on the Liquid Language Support plugin that I mentioned above:
https://marketplace.visualstudio.com/items?itemName=killalau.vscode-liquid-snippets

To make it all work, follow the detailed instructions by each extension. Here are the custom settings I had have in place (sorry if I am repeating anything from their setup instructions).

  1. Go to User Settings
  2. Go to Extensions->Emmet, and select ant of the Edit in settings.json options (they all go to the same place).
  3. Manually add the following code to the existing JSON settings, being careful not to overwrite existing code and paying attention to adding commas where necessary:
... other json code ...
    "emmet.includeLanguages": {
         "liquid": "html" },
    "emmet.excludeLanguages": [
        "markdown"
    ],
    "emmet.extensionsPath": "",
    "files.associations": {
        "*.html": "liquid",
        "*.markdown": "liquid"
    }
... other json code ...

Completely quit/exit Visual Studio Code before you open VSC and try it out.

In the files.assocations area, you can also add .htm and .md.

I did all this a while ago and believed this to be correct, so my apologies if there is anything in error. Using these extensions and the JSON file extensions, you should be able to add Shopify/Liquid commands to any html or markdown file without first having to inform VSC you want to use the language.

You mention that you see errors with JS+Liquid. I am not using any of that in my code (it is a purely static site). What I would try is adding another extension to the files.extensions area. I have not tested this, but I recommend you set it up like the following example and give it a try:

    "files.associations": {
        "*.html": "liquid",
        "*.markdown": "liquid",
       "*.js": "liquid"
    }

For the linting errors, again, I have not tried it, but give this a shot:

    "emmet.includeLanguages": {
         "liquid": "HTML",
         "liquid": javascript"
 },

Again, after you make any settings changes, quit/exit VSC and then come back in to make sure your changes are in place.

I hope this helps!

1 Like

@Koos good to hear and thanks for sharing.

If you have trouble with Liquid for a JS, consider rethinking your approach.

My recommended approach is to have JS which gets loaded using a script tag from a JS file. If the file is pure JS ie no Liquid, which means

  • it is easy to test alone in the browser or using Node and even unit tests or linting, without breaking on Liquid syntax.
  • No reliance of Jekyll Liquid is more robust and reusable as it doesn’t need Liquid and
  • doesn’t need compilation step and
  • isn’t dynamic so easier to reason about
  • you can use plain JS plugin to format, lint and validate plain JS code. No liquid + JS support needed
  • Also liquid syntax {{ is also valid in some JS templating, so you’d have to escape those in a liquid file. but not in a pure JS asset.

You can of course make a JS file which has a function that takes parameters so it becomes dynamic.

And then you can have a small JS snippet on your HTML page which mixes Liquid in.

For example, say you have JS which adds a popup or gallery or something to an element on the page. And the ID is different on each page.

e.g.

assets/main.js

function setupModal(elementId) {
  const el document.getElementById(elementId)
  el.addEvent("click", function() {
    console.log("Hello")
  }
}

Not 100% sure of event syntax but you get the idea.

Then load that in head of default.html layout.

e.g.

_layouts/default.html

<head>
<script src="assets/main.js"></script>

<script>
window.onload = function() {
  const elementId = '{{ page.modal_id }}'
  setupModal(elementId)
}
<script>
</head>
<body>
{{ content }}
</body>

The asset is pure JS. The second script tag uses Liquid to get a value from the page’s frontmatter.

Good point, thanks. There are two other reasons why I use Liquid for JS:

  1. Compiling several JS files (with common functions) into several other files (loaded on a page by page basis). Single file = single request, so faster?
  2. Applying the compress layout, which admittedly is horrible for this, but it reduces file size with about a quarter :slight_smile:

With the small file sizes I’m dealing with I’m reconsidering this now. Loading JS from JS as you suggest may be a more robust way to go about it. When I do this carefully I may be able to avoid rendering delays.

1 Like

@koos the most popular choice for both bundling a single JS file and minifying as bundle.min.js is using Webpack

I made a small example here:

There are an overwhelming number of alternatives too