Technology Tales

Notes drawn from experiences in consumer and enterprise technology

Altering table and hyperlink tags for single Grav articles using HTML post-processing

Published on 1st April 2026 Estimated Reading Time: 3 minutes

This year, there have been a few entries on here regarding Grav because of my moving parts of my website estate to that content management system, first from Textpattern and latterly from WordPress. Once the second activity was completed, I then added an article on German public holidays elsewhere. That brought me to the topic of this piece: ensuring that some Markdown was rendered as required.

There were two parts to this: the styling of tables and the actions of hyperlinks. Each needs to be performed in a page template when all HTML has been initially rendered. Further processing then makes the required changes. Since this is a page template and not a partial template and not a partial template, you need to import a master template like this:

{% extends 'partials/base.html.twig' %}

Then, you go to the next stage, defining the content block within {% block content %}...{% endblock %} Twig tags:

{% set content = page.content
|replace({'<table>': '<table class="table mt-5 mb-5">'})
|replace({'<a href="http': '<a target="_blank" rel="noopener noreferrer" href="http'})
%}

The above reads in the page content (page.content) and does some text replacement operations. The first of these changes <table> to <table class="table mt-5 mb-5">, while the second replaces <a href="http with <a target="_blank" rel="noopener noreferrer" href="http. While my content was a mix of Markdown and HTML, depending on the article, the latter operation appeared to standardise every link.

Once the text replacement has been completed, the next step is to output the processed HTML like this:

{{ content|raw }}

This last line sits outside the {% block content %}...{% endblock %} block; coming after it, in fact. To send the processed output to the generated web page, you need to ensure that you are referring to the right variable, the local one called content and not page.content. The raw filter also is essential here to ensure that nothing is rendered into HTML when the raw HTML itself is what is needed.

All of this effort ensures that straightforward Markdown can be used in content, while Grav does some extra work in the background to ensure that all is rendered without extra intervention. While there may need to be a certain level of standardisation to make this all work well, I find that it does what is needed, albeit in a different manner from shortcode approach that you find in Hugo.

Add a Comment

Your email address will not be published. Required fields are marked *

Please be aware that comment moderation is enabled and may delay the appearance of your contribution.

  • The content, images, and materials on this website are protected by copyright law and may not be reproduced, distributed, transmitted, displayed, or published in any form without the prior written permission of the copyright holder. All trademarks, logos, and brand names mentioned on this website are the property of their respective owners. Unauthorised use or duplication of these materials may violate copyright, trademark and other applicable laws, and could result in criminal or civil penalties.

  • All comments on this website are moderated and should contribute meaningfully to the discussion. We welcome diverse viewpoints expressed respectfully, but reserve the right to remove any comments containing hate speech, profanity, personal attacks, spam, promotional content or other inappropriate material without notice. Please note that comment moderation may take up to 24 hours, and that repeatedly violating these guidelines may result in being banned from future participation.

  • By submitting a comment, you grant us the right to publish and edit it as needed, whilst retaining your ownership of the content. Your email address will never be published or shared, though it is required for moderation purposes.