← Back

Custom Code Container

I wasn't happy with how code was formatting in these posts. ChatGPT was able to help me extend Rouge highlighting built into Jekyll. I created a custom _include/after-content.html instead of modifying the default layout. The change gets applied to all {% highlight xxxx %} sections and gets implemented at build time. This likely will only work when building the site locally.

_plugins/highlight_override.rb

This puts the highlighted code block into code-block-container and adds a label for the code type and a copy code button.

ruby
module Jekyll
  module Tags
    class HighlightBlock < Liquid::Block
      alias_method :original_render, :render

      def render(context)
        # Call the original highlight render method
        highlighted_code = original_render(context).strip
        lang = @markup.strip.split.first || "plaintext"

        <<~HTML
        <div class="code-block-container">
          <div class="code-header">
            <strong>#{lang}</strong>
            <button class="copy-button">Copy Code</button>
          </div>
          <div class="code-block">
            #{highlighted_code}
          </div>
        </div>
        HTML
      end
    end
  end
end

_include/after-content.html

This styles the block and adds functionality to the button

html
<style>
.code-block-container {
  background-color: #1e1e1e; /* Black background */
  border-radius: 8px;
  padding: 10px;
  margin-bottom: 20px;
}

.code-header {
  background-color: #333;
  color: #fff;
  padding: 10px;
  text-align: left;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.code-header button {
  background-color: #828282;
  color: #fff;
  border: none;
  padding: 5px;
  font-size: 0.9rem;
  cursor: pointer;
  border-radius: 5px;
}

.code-header button:hover {
  background-color: #bcbabb;
}

.code-block::-webkit-scrollbar {
  height: 10px;
}

.code-block::-webkit-scrollbar-thumb {
  background: #888;
  border-radius: 5px;
}

.code-block::-webkit-scrollbar-thumb:hover {
  background: #555;
}
</style>


<script>
// Adding the Copy functionality for each code block
const copyButtonLabel = "Copy Code";

// Find all code blocks
let blocks = document.querySelectorAll(".code-block-container");

blocks.forEach((blocks) => {
  let button = block.querySelector(".copy-button");

  // Add copy button functionality if Clipboard API is supported
  if (navigator.clipboard) {
    button.addEventListener("click", async () => {
      let code = block.querySelector("code");
      let text = code.innerText;

      await navigator.clipboard.writeText(text);

      // Change button text to "Code Copied" after copying
      button.innerText = "Code Copied";

      setTimeout(() => {
        button.innerText = copyButtonLabel;
      }, 700);
    });
  }
});
</script>