<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>validator on
A Scripter's Notes</title><link>https://scripter.co/tags/validator/</link><description>Recent content in validator
on A Scripter's Notes</description><language>en-us</language><managingEditor>kaushal.modi@gmail.com (Kaushal Modi)</managingEditor><webMaster>kaushal.modi@gmail.com (Kaushal Modi)</webMaster><lastBuildDate>Wed, 22 Apr 2026 08:24:58 -0400</lastBuildDate><generator>Hugo -- gohugo.io</generator><docs>https://validator.w3.org/feed/docs/rss2.html</docs><atom:link href="https://scripter.co/tags/validator/index.xml" rel="self" type="application/rss+xml"/><item><title>Saving Python pip dependencies</title><link>https://scripter.co/saving-python-pip-dependencies/</link><description>&lt;blockquote>How I generated the Python dependencies file &lt;code>requirements.txt&lt;/code> so
that Netlify can install and run the HTML5 Validator before deploying
this site.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#create-a-virtual-environment">&lt;span class="section-num">1&lt;/span> Create a &lt;em>virtual environment&lt;/em>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#activate-the-virtual-environment">&lt;span class="section-num">2&lt;/span> Activate the &lt;em>virtual environment&lt;/em>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#install-the-packages-using-pip">&lt;span class="section-num">3&lt;/span> Install the packages using &lt;code>pip&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#generate-requirements-dot-txt">&lt;span class="section-num">4&lt;/span> Generate &lt;code>requirements.txt&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#netlify-deployment">Netlify deployment&lt;/a>&lt;/li>
&lt;li>&lt;a href="#summary">Summary&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>Recently I learned about the Python tool &lt;code>html5validator&lt;/code> tool and
used it to run HTML5 validation on local HTML files. You can read more
about that in the &lt;a href="https://scripter.co/offline-html5-validator/">Offline HTML5 Validator&lt;/a> post.&lt;/p>
&lt;p>But then I wondered .. &amp;ldquo;Wouldn&amp;rsquo;t it be awesome if I run this
validation step &lt;strong>each time&lt;/strong> after Hugo generates this site on &lt;a href="https://netlify.com">Netlify&lt;/a>,
but &lt;span class="underline">before&lt;/span> it gets deployed?&amp;rdquo;. That curiosity led me to &lt;a href="https://docs.netlify.com/configure-builds/manage-dependencies/#python-dependencies">Netlify&amp;rsquo;s
documentation on Python dependencies&lt;/a>, and I learned that Netlify will
run &lt;code>pip install&lt;/code> to install the dependencies in &lt;code>requirements.txt&lt;/code>
present in the repository&amp;rsquo;s base directory.&lt;/p>
&lt;p>&lt;span class="org-target" id="netlify-pip-freeze">&lt;/span> I followed the &lt;code>pip freeze &amp;gt; requirements.txt&lt;/code>
step in that documentation but that ended up listing &lt;strong>all&lt;/strong> my &lt;code>pip&lt;/code>
installed packages in that file! I needed the &lt;code>requirements.txt&lt;/code> to
include the dependencies only for &lt;code>html5validator&lt;/code>. This post was born
in my quest to achieve that.&lt;/p>
&lt;p>The solution to this problem was to first create a Python &lt;em>virtual
environment&lt;/em> in my site directory, and &lt;em>then&lt;/em> do all the &lt;code>pip&lt;/code>
operations in there. I learned about this &lt;em>virtual environment&lt;/em> step
from &lt;a href="https://medium.com/python-pandemonium/better-python-dependency-and-package-management-b5d8ea29dff1">this Python Pandemonium post&lt;/a>.&lt;/p>
&lt;p>The &lt;a href="https://docs.python.org/3/library/venv.html">&lt;strong>venv&lt;/strong> documentation&lt;/a> has a lot of details &amp;mdash; I&amp;rsquo;ll just list the
key steps in this post.&lt;/p>
&lt;h2 id="create-a-virtual-environment">&lt;span class="section-num">1&lt;/span> Create a &lt;em>virtual environment&lt;/em>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#create-a-virtual-environment">#&lt;/a>&lt;/h2>
&lt;p>&lt;em>cd&lt;/em> to your site directory and run the below command create a
virtualenv directory named &lt;code>pyenv&lt;/code> in there.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">python3 -m venv pyenv
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="note">
&lt;p>As we are creating this &lt;em>virtual environment&lt;/em> just for the sake of
creating a &lt;code>requirements.txt&lt;/code>, we don&amp;rsquo;t need to commit this
directory to &lt;em>git&lt;/em>.&lt;/p>
&lt;/div>
&lt;h2 id="activate-the-virtual-environment">&lt;span class="section-num">2&lt;/span> Activate the &lt;em>virtual environment&lt;/em>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#activate-the-virtual-environment">#&lt;/a>&lt;/h2>
&lt;p>The virtualenv directory &lt;code>pyenv/bin/&lt;/code> will have multiple flavors of
shell scripts to activate your virtualenv. I am using
&lt;code>activate.csh&lt;/code> here as my shell is &lt;em>tcsh&lt;/em> 🙄.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">source&lt;/span> pyenv/bin/activate.csh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Just to emphasize, it is important to use the &lt;strong>&lt;code>source&lt;/code>&lt;/strong> command here,
and not just call the shell script directly.&lt;/p>
&lt;p>Once you activate this virtualenv, you should see something like
&lt;em>[pyenv]&lt;/em> in the shell prompt.&lt;/p>
&lt;h2 id="install-the-packages-using-pip">&lt;span class="section-num">3&lt;/span> Install the packages using &lt;code>pip&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#install-the-packages-using-pip">#&lt;/a>&lt;/h2>
&lt;p>Install all the project-specific packages. In this case it was just
this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">pip install html5validator
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The package (and its dependencies) will be installed in
&lt;code>pyenv/lib/python3.7/site-packages/&lt;/code>. Here, the &lt;code>python3.7/&lt;/code>
sub-directory name will match the version of Python you have
installed.&lt;/p>
&lt;h2 id="generate-requirements-dot-txt">&lt;span class="section-num">4&lt;/span> Generate &lt;code>requirements.txt&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#generate-requirements-dot-txt">#&lt;/a>&lt;/h2>
&lt;p>Finally, we run the &lt;code>pip freeze&lt;/code> command &lt;a href="#netlify-pip-freeze">mentioned&lt;/a> in Netlify docs,
but with the &lt;strong>&lt;code>--local&lt;/code>&lt;/strong> switch:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">pip freeze --local &amp;gt; requirements.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="note">
&lt;p>The &lt;code>--local&lt;/code> option ensures that globally-installed packages are not
listed even if the virtualenv has global access.&lt;/p>
&lt;/div>
&lt;p>Here&amp;rsquo;s the &lt;code>requirements.txt&lt;/code> created by that command:&lt;/p>
&lt;p>&lt;a id="code-snippet--netlify-requirements.txt">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">html5validator==0.4.2
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PyYAML==6.0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--netlify-requirements.txt">Code Snippet 1&lt;/a>:&lt;/span>
The &lt;code>requirements.txt&lt;/code> for Netlify
&lt;/div>
&lt;p>Now, I could have just manually typed &lt;code>html5validator==0.4.2&lt;/code> in a
&lt;code>requirements.txt&lt;/code> and committed that, and that would work too. But
then, I wouldn&amp;rsquo;t have learned how to create a project-specific &lt;em>pip
dependency file&lt;/em> 😄.&lt;/p>
&lt;h2 id="netlify-deployment">Netlify deployment&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#netlify-deployment">#&lt;/a>&lt;/h2>
&lt;p>The &lt;code>html5validator&lt;/code> has a dependency on Java 8. Luckily the Netlify
environment already comes with that installed. So the only extra setup
needed to make this package work on Netlify was to set the
&lt;code>PYTHON_VERSION&lt;/code> environment variable to &lt;strong>3.8&lt;/strong>
&lt;span class="sidenote-number">&lt;small class="sidenote">
The version number should be one of the values listed in &lt;a href="https://github.com/netlify/build-image/blob/focal/included_software.md">Netlify&amp;rsquo;s
&lt;em>included software&lt;/em> list&lt;/a>.
&lt;/small>&lt;/span>
.&lt;/p>
&lt;h2 id="summary">Summary&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#summary">#&lt;/a>&lt;/h2>
&lt;p>The numbered headings in this post already summarize the steps needed
to create a project-specific &lt;code>requirements.txt&lt;/code>.&lt;/p>
&lt;p>With these in place:&lt;/p>
&lt;div class="verse">
&lt;p>✅ &lt;code>requirements.txt&lt;/code> committed in site directory root&lt;br />
✅ Netlify environment variable &lt;code>PYTHON_VERSION&lt;/code> set to 3.8&lt;br />&lt;/p>
&lt;/div>
&lt;p>my Netlify deployment script now does HTML5 Validation along with few
other checks before this site gets deployed 🎉.&lt;/p>
&lt;p>Here&amp;rsquo;s the &lt;a href="https://gitlab.com/kaushalmodi/kaushalmodi.gitlab.io/-/blob/master/build.sh">full &lt;code>build.sh&lt;/code> script&lt;/a>.&lt;/p></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/web">web</category><category domain="https://scripter.co/series/html5-validator">HTML5 Validator</category><category domain="https://scripter.co/tags/html">html</category><category domain="https://scripter.co/tags/validator">validator</category><category domain="https://scripter.co/tags/python">python</category><category domain="https://scripter.co/tags/pip">pip</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/netlify">netlify</category><guid>https://scripter.co/saving-python-pip-dependencies/</guid><pubDate>Tue, 14 Jun 2022 00:38:00 -0400</pubDate></item><item><title>Zero HTML Validation Errors!</title><link>https://scripter.co/zero-html-validation-errors/</link><description>&lt;blockquote>How I fixed my site content and went down from 46 HTML validations
errors down to 0!&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#avoid-duplicate-heading-id-attributes">&lt;span class="section-num">1&lt;/span> Avoid duplicate heading &lt;code>id&lt;/code> attributes&lt;/a>&lt;/li>
&lt;li>&lt;a href="#remove-inline-style-elements">&lt;span class="section-num">2&lt;/span> Remove inline &lt;code>&amp;lt;style&amp;gt;&lt;/code> elements&lt;/a>&lt;/li>
&lt;li>&lt;a href="#ensure-that-all-images-have-captions-or-alt-attributes">&lt;span class="section-num">3&lt;/span> Ensure that all images have captions or &lt;code>alt&lt;/code> attributes&lt;/a>&lt;/li>
&lt;li>&lt;a href="#do-not-have-hyperlinks-in-headings">&lt;span class="section-num">4&lt;/span> Do not have hyperlinks in headings&lt;/a>&lt;/li>
&lt;li>&lt;a href="#validation-ignores">Validation Ignores&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#ignore-errors-due-to-hyperlinks-in-inline-svg">&lt;span class="section-num">5&lt;/span> Ignore errors due to hyperlinks in inline SVG&lt;/a>&lt;/li>
&lt;li>&lt;a href="#ignore-files-not-expected-to-serve-html-content">&lt;span class="section-num">6&lt;/span> Ignore files not expected to serve HTML content&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#summary">Summary&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>In my &lt;a href="https://scripter.co/offline-html5-validator/">previous HTML5 Validator post&lt;/a>, I mentioned:&lt;/p>
&lt;blockquote>
&lt;p>I was a bit disappointed to see validation errors on my site, but then
it wasn&amp;rsquo;t too bad .. 46 errors.&lt;/p>
&lt;/blockquote>
&lt;p>But they truly say ..&lt;/p>
&lt;div class="org-center">
&lt;p>Ignorance is bliss.&lt;/p>
&lt;/div>
&lt;p>So .. once I realized that my site had 46 validation errors, I lost
that &lt;em>bliss&lt;/em> .. and I couldn&amp;rsquo;t rest easy &amp;mdash; I had to fix them all
😁.&lt;/p>
&lt;p>This post summarizes the categories of those errors and how I fixed
&lt;span class="sidenote-number">&lt;small class="sidenote">
The fixes mentioned in this post refer to changes in Org mode
content. But you should be able to derive equivalent fixes for
Markdown too.
&lt;/small>&lt;/span>
them all.&lt;/p>
&lt;h2 id="avoid-duplicate-heading-id-attributes">&lt;span class="section-num">1&lt;/span> Avoid duplicate heading &lt;code>id&lt;/code> attributes&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#avoid-duplicate-heading-id-attributes">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:636.34-636.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:300.34-300.52: error: Duplicate ID &amp;#34;older-issue&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:306.20-306.33: error: Duplicate ID &amp;#34;floats&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/page/6/index.html&amp;#34;:29.39-29.54: error: Duplicate ID &amp;#34;fnref:1&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Errors with above kind of signatures were fixed by,&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Converting headings to description lists&lt;/p>
&lt;p>I had a bunch of generic headings like &amp;ldquo;Notes&amp;rdquo; and &amp;ldquo;Older Issue&amp;rdquo; in
some of my posts. After taking a second look at those, it made more
sense to convert those to description lists. So in Org mode, I
converted headings like &lt;code class="code-inline language-org">&lt;span class="gh">*&lt;/span>&lt;span class="gs"> Notes&lt;/span>&lt;/code> to
description lists &lt;code class="code-inline language-org">&lt;span class="k">- &lt;/span>Notes ::&lt;/code>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Setting &lt;code>CUSTOM_ID&lt;/code> heading property&lt;/p>
&lt;p>For the cases, where the headings needed to be left as so, their
IDs were uniquified by setting their &lt;code>CUSTOM_ID&lt;/code> property. For
example, below fixed the &lt;em>Duplicate ID &amp;ldquo;floats&amp;rdquo;&lt;/em> errors.
&lt;a id="code-snippet--using-custom-id-to-uniquify-heading-id">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl"> ** Precision
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> *** Floats
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:PROPERTIES:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:CUSTOM_ID: precision-floats
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:END:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ** Type (only for numbers)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> *** Floats
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:PROPERTIES:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:CUSTOM_ID: type-floats
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+:END:
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--using-custom-id-to-uniquify-heading-id">Code Snippet 1&lt;/a>:&lt;/span>
Using &lt;code>CUSTOM_ID&lt;/code> property to uniquify heading ID's
&lt;/div>
&lt;/li>
&lt;li>
&lt;p>Prevent footnote links in post summaries&lt;/p>
&lt;p>This issue was due to me not being conscious about how the footnote
references work in a post &lt;em>versus&lt;/em> on a page outside that post&amp;rsquo;s
context. The issue was caused by footnote references getting into
the post summaries parsed by Hugo, which will then show up on the
list pages.&lt;/p>
&lt;p>The fix was simple &amp;mdash; Edit the post summaries so that they don&amp;rsquo;t
contain any footnote references.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="remove-inline-style-elements">&lt;span class="section-num">2&lt;/span> Remove inline &lt;code>&amp;lt;style&amp;gt;&lt;/code> elements&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#remove-inline-style-elements">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​grep-po/index.html&amp;#34;:51.139-51.145: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​how-do-i-write-org-mode/index.html&amp;#34;:23.194-23.200: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Errors with above kind of signatures were fixed by,&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Avoiding export of raw &lt;code>&amp;lt;style&amp;gt;&lt;/code> elements in the Markdown content&lt;/p>
&lt;p>I figured out which functions were responsible for injecting
&lt;code>&amp;lt;style&amp;gt;&lt;/code> elements in Markdown content and then advised them to
stop that. After applying these advises, I lost the in-content
rules for CSS classes &lt;code>.org-center&lt;/code> and &lt;code>.csl-entry&lt;/code>. So I put
those rules directly in this website&amp;rsquo;s CSS.
&lt;a id="code-snippet--advices-to-prevent-style-elem-in-exports">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/org-blackfriday-center-block&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">_center-block&lt;/span> &lt;span class="nv">contents&lt;/span> &lt;span class="nv">info&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let*&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">class&lt;/span> &lt;span class="s">&amp;#34;org-center&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;div class=\&amp;#34;%s\&amp;#34;&amp;gt;%s\n\n%s\n&amp;lt;/div&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">class&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">org-blackfriday--extra-div-hack&lt;/span> &lt;span class="nv">info&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nv">contents&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">advice-add&lt;/span> &lt;span class="ss">&amp;#39;org-blackfriday-center-block&lt;/span> &lt;span class="nb">:override&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">modi/org-blackfriday-center-block&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/org-cite-csl-render-bibliography&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">bib-str&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">replace-regexp-in-string&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;style&amp;gt;\\.csl-entry[^&amp;lt;]+&amp;lt;/style&amp;gt;&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="nv">bib-str&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">advice-add&lt;/span> &lt;span class="ss">&amp;#39;org-cite-csl-render-bibliography&lt;/span> &lt;span class="nb">:filter-return&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">modi/org-cite-csl-render-bibliography&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--advices-to-prevent-style-elem-in-exports">Code Snippet 2&lt;/a>:&lt;/span>
Emacs-Lisp advices to prevent &lt;code>&amp;lt;style&amp;gt;&lt;/code> elements in exports
&lt;/div>
&lt;/li>
&lt;li>
&lt;p>Removing unnecessary micro-styling&lt;/p>
&lt;p>I found a single case, where an inline CSS rule was defined in
content for CSS class &lt;code>.repr-type&lt;/code> for a table. I just removed that
without affecting the looks of that rendered table too much.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="ensure-that-all-images-have-captions-or-alt-attributes">&lt;span class="section-num">3&lt;/span> Ensure that all images have captions or &lt;code>alt&lt;/code> attributes&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#ensure-that-all-images-have-captions-or-alt-attributes">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​hugo-use-goat-code-blocks-for-ascii-diagrams/index.html&amp;#34;:24.130-24.255: error: An &amp;#34;img&amp;#34; element must have an &amp;#34;alt&amp;#34; attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Errors with above kind of signatures were easily fixed by ensuring
that all images had captions
&lt;span class="sidenote-number">&lt;small class="sidenote">
Thankfully, there were only two images that were missing captions.
&lt;/small>&lt;/span>
. The Hugo &lt;code>figure&lt;/code> shortcode adds the caption to the &lt;code>alt&lt;/code> attribute if
the &lt;code>alt&lt;/code> is not specified separately.&lt;/p>
&lt;p>As an example, here&amp;rsquo;s how I fixed the above error:&lt;/p>
&lt;p>&lt;a id="code-snippet--adding-a-caption-to-an-image">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ #+name: fig__disproportionate_box_drawing
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">+ #+caption: Disproportionate box drawing characters
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span>[[file:images/​hugo-use-goat-code-blocks-for-ascii-diagrams/ascii-diagram-rendered-in-plain-text-code-block.png]]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--adding-a-caption-to-an-image">Code Snippet 3&lt;/a>:&lt;/span>
A &lt;code>git diff&lt;/code> showing addition of caption to an image
&lt;/div>
&lt;h2 id="do-not-have-hyperlinks-in-headings">&lt;span class="section-num">4&lt;/span> Do not have hyperlinks in headings&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#do-not-have-hyperlinks-in-headings">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​using-emacs-advice-to-silence-messages-from-functions/index.html&amp;#34;:151.687-151.732: error: Start tag &amp;#34;a&amp;#34; seen but an element of the same type was already open.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​using-emacs-advice-to-silence-messages-from-functions/index.html&amp;#34;:151.748-151.751: error: Stray end tag &amp;#34;a&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.446-114.475: error: Start tag &amp;#34;a&amp;#34; seen but an element of the same type was already open.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.446-114.475: error: End tag &amp;#34;a&amp;#34; violates nesting rules.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.526-114.529: error: Stray end tag &amp;#34;a&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>While the hyperlinks in headings work well, they created invalid HTML
in the Hugo-generated TOC. So while these errors were created
technically because of a bug in Hugo
&lt;span class="sidenote-number">&lt;small class="sidenote">
It&amp;rsquo;s really cool when you end up finding a bug in an upstream project
while trying to fix the errors in your own thing 😎.
&lt;/small>&lt;/span>
, I wanted to fix these errors on my end as soon as I can.&lt;/p>
&lt;p>I reviewed the errors, and this is all it took to get rid of them all:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Remove manually inserting hyperlinks in headings
&lt;a id="code-snippet--removing-hyperlink-from-a-heading">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl"> show two methods of finding sources of any printed messages.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">-***** Using plain-old /grep/ or [[https://github.com/BurntSushi/ripgrep][/rg/]]
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+***** Using plain-old /grep/ or /ripgrep (rg)/
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> This method is pretty easy (but not robust) to use if the search
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ..
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Org source directory and search for the /&amp;#34;org-babel-exp process ..&amp;#34;/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">-string ..
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+string using [[https://github.com/BurntSushi/ripgrep][~rg~]] ..
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--removing-hyperlink-from-a-heading">Code Snippet 4&lt;/a>:&lt;/span>
Removing hyperlink from a heading
&lt;/div>
&lt;/li>
&lt;li>
&lt;p>Remove Org Radio links that created links in headings&lt;/p>
&lt;p>Here, a Org heading happened to contain the string &amp;ldquo;Day count&amp;rdquo;,
which was also an &lt;a href="https://orgmode.org/manual/Radio-Targets.html" title="Emacs Lisp: (info &amp;quot;(org) Radio Targets&amp;quot;)">an Org Radio link&lt;/a> in that post. While ideally
that shouldn&amp;rsquo;t have mattered, I removed that radio link to get
around this Hugo bug.
&lt;a id="code-snippet--removing-an-org-radio-link">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-diff" data-lang="diff">&lt;span class="line">&lt;span class="cl"> .. /Just may be/. But regardless, I am already enjoying writing once
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">-again, and it&amp;#39;s great to see the &amp;lt;&amp;lt;&amp;lt;Day count&amp;gt;&amp;gt;&amp;gt; (counting up to 100)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gd">&lt;/span>&lt;span class="gi">+again, and it&amp;#39;s great to see the Day count (counting up to 100)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="gi">&lt;/span> increase with each new post!
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--removing-an-org-radio-link">Code Snippet 5&lt;/a>:&lt;/span>
Removing an Org Radio link
&lt;/div>
&lt;/li>
&lt;/ol>
&lt;h2 id="validation-ignores">Validation Ignores&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#validation-ignores">#&lt;/a>&lt;/h2>
&lt;p>Above fixes fixed 43 out of 46 errors, but the remaining 3 were unfixable.&lt;/p>
&lt;h3 id="ignore-errors-due-to-hyperlinks-in-inline-svg">&lt;span class="section-num">5&lt;/span> Ignore errors due to hyperlinks in inline SVG&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#ignore-errors-due-to-hyperlinks-in-inline-svg">#&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​plantuml/index.html&amp;#34;:114.474-114.678: error: Attribute &amp;#34;title&amp;#34; not allowed on element &amp;#34;a&amp;#34; at this point.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This error was caused by hyperlinks in inline SVG elements. These SVG
elements are created by &lt;a href="https://plantuml.com/">PlantUML&lt;/a>. The &lt;em>hyperlinks in SVG&lt;/em> feature
works great, and as these are generated by PlantUML, I chose to just
ignore these errors.&lt;/p>
&lt;p>I ignored this error by adding the &lt;code>--ignore-re 'notes/plantuml.*Attribute.*title.*not allowed'&lt;/code> switch to the
&lt;code>html5validator&lt;/code> command.&lt;/p>
&lt;h3 id="ignore-files-not-expected-to-serve-html-content">&lt;span class="section-num">6&lt;/span> Ignore files not expected to serve HTML content&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#ignore-files-not-expected-to-serve-html-content">#&lt;/a>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/googleFOO.html&amp;#34;:1.1-1.52: error: Non-space characters found without seeing a doctype first. Expected &amp;#34;&amp;lt;!DOCTYPE html&amp;gt;&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>googleFOO.html&lt;/code> file here is not a valid HTML file. It&amp;rsquo;s a just a
&lt;em>cookie&lt;/em> file that was used by Google to verify that I own this
domain.&lt;/p>
&lt;p>This error was masked by adding the &lt;code>--ignore 'googleFOO'&lt;/code> switch to
the &lt;code>html5validator&lt;/code> command.&lt;/p>
&lt;h2 id="summary">Summary&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#summary">#&lt;/a>&lt;/h2>
&lt;p>Once I fixed the 43 errors by tweaking the Org mode content, and added
those two ignores, I had &lt;strong>zero validation errors&lt;/strong>! 🎉&lt;/p>
&lt;p>If you are interested in the fix details, &lt;a href="https://gitlab.com/kaushalmodi/kaushalmodi.gitlab.io/-/compare/a7cac5dd1293442a51fd5020a3bcef8da7f75fdc...42d6c72d533c337b5c67fa09207f68e45efe6e6c">here are the commits&lt;/a>.&lt;/p></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/web">web</category><category domain="https://scripter.co/categories/org">org</category><category domain="https://scripter.co/series/html5-validator">HTML5 Validator</category><category domain="https://scripter.co/tags/html">html</category><category domain="https://scripter.co/tags/validator">validator</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/zero-html-validation-errors/</guid><pubDate>Sun, 05 Jun 2022 17:58:00 -0400</pubDate></item><item><title>Offline HTML5 Validator</title><link>https://scripter.co/offline-html5-validator/</link><description>&lt;blockquote>Validate your website offline &amp;mdash; It&amp;rsquo;s just one &lt;code>curl&lt;/code> command away.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#using-the-dot-jar">Using the &lt;code>.jar&lt;/code>&lt;/a>
&lt;ul>
&lt;li>&lt;a href="#using-pip-install">Using &lt;code>pip install&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="#using-pre-compiled-binary">Using pre-compiled binary&lt;/a>&lt;/li>
&lt;li>&lt;a href="#results">Results&lt;/a>&lt;/li>
&lt;li>&lt;a href="#conclusion">Conclusion&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>I have been using the online HTML5 Validator
&lt;a href="https://html5.validator.nu/">https://html5.validator.nu/&lt;/a> for few years now. I have a link at the
bottom of each post to validate that page&amp;rsquo;s HTML. For an example, see
the &lt;em>html5 validator&lt;/em> link at the &lt;a href="#bottom">bottom&lt;/a> of this
post.&lt;/p>
&lt;p>But it didn&amp;rsquo;t occur to me until now to look for a way to do the same
validation offline! Offline validation would be useful so that I can
look at any HTML generation problem before I deploy the website. So I
looked for a solution online, and of course it&amp;rsquo;s &lt;a href="https://stackoverflow.com/a/26505206/1219634">answered on
StackOverflow&lt;/a> 😄.&lt;/p>
&lt;p>It turns out that same &lt;a href="https://github.com/validator/validator">Nu HTML5 Validator&lt;/a> project that provides the
online validation service, also provides a Java application as well as
pre-compiled binaries for Linux, Windows and MacOS for offline use!&lt;/p>
&lt;p>To use the Java &lt;em>.jar&lt;/em> file, you need to have at least Java 8
installed on your system. But you don&amp;rsquo;t need to have any version of
Java installed if you use the pre-compiled binary instead. See &lt;a href="https://validator.github.io/validator/">its
documentation&lt;/a> for more details.&lt;/p>
&lt;h2 id="using-the-dot-jar">Using the &lt;code>.jar&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#using-the-dot-jar">#&lt;/a>&lt;/h2>
&lt;div class="note">
&lt;p>Requires at least Java 8&lt;/p>
&lt;/div>
&lt;dl>
&lt;dt>Download&lt;/dt>
&lt;dd>Download the latest &lt;code>vnu.jar&lt;/code> from the project&amp;rsquo;s &lt;a href="https://github.com/validator/validator/releases">GitHub
Releases section&lt;/a>.
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">curl -ROLs https://github.com/validator/validator/releases/download/latest/vnu.jar
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;dt>Run&lt;/dt>
&lt;dd>Below command runs the validator only on the HTML files in
the &lt;code>public/&lt;/code>
&lt;span class="sidenote-number">&lt;small class="sidenote">
If you are using &lt;a href="https://gohugo.io">Hugo&lt;/a>, the &lt;code>hugo&lt;/code> command will publish the HTML
files in the &lt;code>public/&lt;/code> directory by default.
&lt;/small>&lt;/span>
directory. See its &lt;a href="https://validator.github.io/validator/#usage">Usage documentation&lt;/a> for more details.
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">java -jar vnu.jar --skip-non-html --errors-only public/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>For my usecase, if I don&amp;rsquo;t provide the &lt;code>--skip-non-html --errors-only&lt;/code> switches, the output is too noisy.&lt;/p>
&lt;/dd>
&lt;/dl>
&lt;h3 id="using-pip-install">Using &lt;code>pip install&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#using-pip-install">#&lt;/a>&lt;/h3>
&lt;p>If you do not want to manually download the &lt;code>.jar&lt;/code>, there&amp;rsquo;s a Python
wrapper available to do the same for you: &lt;a href="https://github.com/svenkreiss/html5validator">html5validator&lt;/a>.&lt;/p>
&lt;dl>
&lt;dt>Install&lt;/dt>
&lt;dd>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl"> pip install --user html5validator
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;dt>Run&lt;/dt>
&lt;dd>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl"> html5validator --root public/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>It seems like this Python wrapper implicitly passes &lt;code>--skip-non-html --errors-only&lt;/code> to the Java app. So those are not needed when running
&lt;code>html5validator&lt;/code>. But on the flip side, it needs the &lt;code>--root&lt;/code> switch
when specifying the directory to run the script on.&lt;/dd>
&lt;/dl>
&lt;p>Note that you still need to have at least Java 8 installed when
running this Python app too, because it downloads and run the same
&lt;code>.jar&lt;/code> behind the scenes.&lt;/p>
&lt;h2 id="using-pre-compiled-binary">Using pre-compiled binary&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#using-pre-compiled-binary">#&lt;/a>&lt;/h2>
&lt;p>If your system doesn&amp;rsquo;t have the required Java version, you can use the
pre-compiled binary instead.&lt;/p>
&lt;dl>
&lt;dt>Download &amp;amp; Extract&lt;/dt>
&lt;dd>Download and extract the &lt;code>vnu.&amp;lt;OS&amp;gt;.zip&lt;/code> for
your &lt;strong>OS&lt;/strong> from the same &lt;em>Releases&lt;/em> section. Here, I am showing how
to do that on Linux:
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">curl -ROLs https://github.com/validator/validator/releases/download/latest/vnu.linux.zip
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">unzip vnu.linux.zip
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The extracted binary path will be &lt;code>vnu-runtime-image/bin/vnu&lt;/code>.&lt;/p>
&lt;/dd>
&lt;dt>Run&lt;/dt>
&lt;dd>The run options will be the exact same; just that you will be
running the binary directly instead of running through &lt;code>java&lt;/code>.
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">vnu-runtime-image/bin/vnu --skip-non-html --errors-only public/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;/dl>
&lt;h2 id="results">Results&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#results">#&lt;/a>&lt;/h2>
&lt;div class="logbook-notes">
&lt;dl>
&lt;dt>
&lt;span class="timestamp-wrapper">
&lt;span class="timestamp">
&amp;lt;2022-06-05&amp;gt;
&lt;/span>
&lt;/span>
&lt;/dt>
&lt;dd>
This website now has zero validation errors! 🎉 All the errors
listed in the &lt;a href="#org-target--validation-log">collapsed log below&lt;/a> are now resolved. See my &lt;a href="https://scripter.co/zero-html-validation-errors/">Zero HTML Validation Errors!&lt;/a> post on how I did that.
&lt;/dd>
&lt;/dl>
&lt;/div>
&lt;p>I was a bit disappointed to see validation errors on my site, but then
it wasn&amp;rsquo;t too bad .. &lt;del>52&lt;/del> 46 errors:&lt;/p>
&lt;dl>
&lt;dt>Some I already fixed&lt;/dt>
&lt;dd>These 6 errors were fixed in &lt;a href="https://gitlab.com/kaushalmodi/kaushalmodi.gitlab.io/-/commit/4288a70fa473800b597d46c77bf4021d7c0cd060">this commit&lt;/a>.
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​getting-started-with-texlive/index.html&amp;#34;:6.2198-6.2206: error: Element &amp;#34;package&amp;#34; not allowed as child of element &amp;#34;li&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​getting-started-with-texlive/index.html&amp;#34;:6.2256-6.2259: error: End tag &amp;#34;li&amp;#34; implied, but there were open elements.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​getting-started-with-texlive/index.html&amp;#34;:6.2198-6.2206: error: Unclosed element &amp;#34;package&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​getting-started-with-texlive/index.html&amp;#34;:6.2307-6.2315: error: Element &amp;#34;package&amp;#34; not allowed as child of element &amp;#34;li&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​getting-started-with-texlive/index.html&amp;#34;:6.2316-6.2319: error: End tag &amp;#34;li&amp;#34; implied, but there were open elements.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​getting-started-with-texlive/index.html&amp;#34;:6.2307-6.2315: error: Unclosed element &amp;#34;package&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;dt>Some I can probably fix&lt;/dt>
&lt;dd>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> &amp;#34;file:/public/notes/​nim/index.html&amp;#34;:472.480-472.486: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;file:/public/notes/​nim/index.html&amp;#34;:1359.221-1359.231: error: Duplicate ID &amp;#34;log&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ..
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;dt>Some need to be ignored&lt;/dt>
&lt;dd>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> &amp;#34;file:/public/​google4a938eaf9bbacbcd.html&amp;#34;:1.1-1.52: error: Non-space characters found without seeing a doctype first. Expected &amp;#34;&amp;lt;!DOCTYPE html&amp;gt;&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;file:/public/​google4a938eaf9bbacbcd.html&amp;#34;:1.1-1.52: error: Element &amp;#34;head&amp;#34; is missing a required instance of child element &amp;#34;title&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ..
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;dt>And the rest would be out of my scope to fix&lt;/dt>
&lt;dd>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> &amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.446-114.475: error: Start tag &amp;#34;a&amp;#34; seen but an element of the same type was already open.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.446-114.475: error: End tag &amp;#34;a&amp;#34; violates nesting rules.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.526-114.529: error: Stray end tag &amp;#34;a&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ..
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/dd>
&lt;/dl>
&lt;p>Expand the below drawer if you&amp;rsquo;d like to see the full log with 46
errors: &lt;span class="org-target" id="org-target--validation-log">&lt;/span>&lt;/p>
&lt;details>
&lt;summary>Output of running &lt;code>html5validator --root public/&lt;/code>&lt;/summary>
&lt;div class="details">
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​google4a938eaf9bbacbcd.html&amp;#34;:1.1-1.52: error: Non-space characters found without seeing a doctype first. Expected &amp;#34;&amp;lt;!DOCTYPE html&amp;gt;&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​google4a938eaf9bbacbcd.html&amp;#34;:1.1-1.52: error: Element &amp;#34;head&amp;#34; is missing a required instance of child element &amp;#34;title&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​plantuml/index.html&amp;#34;:114.474-114.678: error: Attribute &amp;#34;title&amp;#34; not allowed on element &amp;#34;a&amp;#34; at this point.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:300.34-300.52: error: Duplicate ID &amp;#34;older-issue&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:306.20-306.33: error: Duplicate ID &amp;#34;floats&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:339.34-339.52: error: Duplicate ID &amp;#34;older-issue&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:341.320-341.335: error: Duplicate ID &amp;#34;integers&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:341.494-341.507: error: Duplicate ID &amp;#34;floats&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim-fmt/index.html&amp;#34;:385.34-385.48: error: Duplicate ID &amp;#34;strings&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:134.34-134.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:239.34-239.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:269.34-269.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:336.34-336.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:513.106-513.118: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:588.106-588.118: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:636.34-636.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:731.34-731.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:797.34-797.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:846.34-846.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:894.34-894.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:920.34-920.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:942.34-942.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:1012.34-1012.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​string-fns-nim-vs-python/index.html&amp;#34;:1074.34-1074.46: error: Duplicate ID &amp;#34;notes&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim/index.html&amp;#34;:472.480-472.486: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim/index.html&amp;#34;:1359.221-1359.231: error: Duplicate ID &amp;#34;log&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim/index.html&amp;#34;:2364.130-2364.149: error: Duplicate ID &amp;#34;named-tuples&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim/index.html&amp;#34;:2403.149-2403.172: error: Duplicate ID &amp;#34;anonymous-tuples&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim/index.html&amp;#34;:3370.284-3370.303: error: Duplicate ID &amp;#34;installation&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim/index.html&amp;#34;:3410.354-3410.373: error: Duplicate ID &amp;#34;installation&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim/index.html&amp;#34;:5033.34-5033.52: error: Duplicate ID &amp;#34;older-issue&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim/index.html&amp;#34;:5376.34-5376.45: error: Duplicate ID &amp;#34;json&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/notes/​nim/index.html&amp;#34;:6066.64-6066.81: error: Duplicate ID &amp;#34;references&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/bits/​plantuml-version/index.html&amp;#34;:7.37-7.94: error: An &amp;#34;img&amp;#34; element must have an &amp;#34;alt&amp;#34; attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.446-114.475: error: Start tag &amp;#34;a&amp;#34; seen but an element of the same type was already open.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.446-114.475: error: End tag &amp;#34;a&amp;#34; violates nesting rules.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​auto-count-100daystooffload-posts/index.html&amp;#34;:114.526-114.529: error: Stray end tag &amp;#34;a&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​generics-not-exactly-in-systemverilog/index.html&amp;#34;:118.232-118.238: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​grep-po/index.html&amp;#34;:51.139-51.145: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​how-do-i-write-org-mode/index.html&amp;#34;:23.194-23.200: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​hugo-use-goat-code-blocks-for-ascii-diagrams/index.html&amp;#34;:24.130-24.255: error: An &amp;#34;img&amp;#34; element must have an &amp;#34;alt&amp;#34; attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​hugo-modules-getting-started/index.html&amp;#34;:6.865-6.871: error: Element &amp;#34;style&amp;#34; not allowed as child of element &amp;#34;div&amp;#34; in this context. (Suppressing further errors from this subtree.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​using-emacs-advice-to-silence-messages-from-functions/index.html&amp;#34;:151.687-151.732: error: Start tag &amp;#34;a&amp;#34; seen but an element of the same type was already open.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/​using-emacs-advice-to-silence-messages-from-functions/index.html&amp;#34;:151.748-151.751: error: Stray end tag &amp;#34;a&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/page/6/index.html&amp;#34;:29.39-29.54: error: Duplicate ID &amp;#34;fnref:1&amp;#34;.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;file:/public/page/6/index.html&amp;#34;:49.169-49.184: error: Duplicate ID &amp;#34;fnref:1&amp;#34;.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>
&lt;/details>
&lt;h2 id="conclusion">Conclusion&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#conclusion">#&lt;/a>&lt;/h2>
&lt;p>It was really easy to download the run the &lt;code>vnu&lt;/code> application using
Java, the standalone Linux binary and also through the
&lt;code>html5validator&lt;/code> Python wrapper.&lt;/p>
&lt;p>After my quick trials, I think I will use the &lt;code>html5validator&lt;/code>
approach more because,&lt;/p>
&lt;ol>
&lt;li>It works as I expect will the least number of switches.&lt;/li>
&lt;li>I am able to redirect the output using &lt;code>html5validator --root public/ &amp;gt; validate.log&lt;/code>. &lt;em>I tried the same using the &lt;code>vnu.jar&lt;/code> and
Linux compiled &lt;code>vnu&lt;/code> binary, but the error log redirection didn&amp;rsquo;t
work with those.&lt;/em>&lt;/li>
&lt;/ol></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/web">web</category><category domain="https://scripter.co/series/html5-validator">HTML5 Validator</category><category domain="https://scripter.co/tags/html">html</category><category domain="https://scripter.co/tags/validator">validator</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/offline-html5-validator/</guid><pubDate>Wed, 01 Jun 2022 00:11:00 -0400</pubDate></item></channel></rss>