<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gids123</title>
    <description>The latest articles on DEV Community by Gids123 (@gids123).</description>
    <link>https://dev.to/gids123</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2467755%2F529270aa-2611-43e3-ba22-44824dcd12a5.jpeg</url>
      <title>DEV Community: Gids123</title>
      <link>https://dev.to/gids123</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gids123"/>
    <language>en</language>
    <item>
      <title>Delint: a folder of single-file HTML tools for the data cleanup I kept doing by hand</title>
      <dc:creator>Gids123</dc:creator>
      <pubDate>Tue, 28 Jul 2026 05:28:05 +0000</pubDate>
      <link>https://dev.to/gids123/delint-a-folder-of-single-file-html-tools-for-the-data-cleanup-i-kept-doing-by-hand-1gfd</link>
      <guid>https://dev.to/gids123/delint-a-folder-of-single-file-html-tools-for-the-data-cleanup-i-kept-doing-by-hand-1gfd</guid>
      <description>&lt;p&gt;I keep ending up with the same problem: someone hands me an export — a CSV, an Excel sheet, a block of text copied out of Word — and before I can do anything useful with it, I have to clean it up. Ragged rows, mismatched delimiters, MSO junk riding along in pasted HTML, mojibake from a re-encoded file, JSON with a trailing comma some upstream tool left behind.&lt;/p&gt;

&lt;p&gt;For a while I was doing this in throwaway Python scripts. Then I got tired of rewriting the same script for the fifth time and started building small, single-purpose HTML pages instead — each one doing exactly one cleanup job, running entirely in the browser, with nothing to install and nothing uploaded anywhere.&lt;/p&gt;

&lt;p&gt;That collection is now &lt;a href="https://delint.vercel.app/" rel="noopener noreferrer"&gt;Delint&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually is
&lt;/h2&gt;

&lt;p&gt;Delint is a flat site of standalone tools, each one a single HTML file. No build step, no backend, no account. You open a page, paste or drop a file in, and get clean output back — all processing happens client-side in JavaScript. The libraries doing the heavy lifting are CDN-hosted: PapaParse for CSV parsing, SheetJS for reading and writing Excel files.&lt;/p&gt;

&lt;p&gt;Right now there are two groups of tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text &amp;amp; data cleanup:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://delint.vercel.app/index.html" rel="noopener noreferrer"&gt;Text cleaner&lt;/a&gt; — strips MSO conditional comments, inline font/color spans, and tracking markup out of text pasted from Word, Google Docs, or a webpage. Outputs plain text or Markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://delint.vercel.app/clean-csv.html" rel="noopener noreferrer"&gt;CSV cleaner&lt;/a&gt; — auto-detects the delimiter, repairs ragged rows, trims stray whitespace.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://delint.vercel.app/encoding-fixer.html" rel="noopener noreferrer"&gt;Encoding fixer&lt;/a&gt; — fixes mojibake and double-encoded UTF-8 (the &lt;code&gt;â€™&lt;/code&gt; and &lt;code&gt;Ã©&lt;/code&gt; kind of mess) and normalizes Unicode.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://delint.vercel.app/json-fixer.html" rel="noopener noreferrer"&gt;JSON fixer&lt;/a&gt; — repairs the common syntax errors that break JSON.parse: trailing commas, single quotes, unquoted keys, comments.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://delint.vercel.app/mail-check.html" rel="noopener noreferrer"&gt;Mail checker&lt;/a&gt; — scans pasted email text or HTML for phishing red flags: urgency language, mismatched links, lookalike domains.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Spreadsheet tools:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://delint.vercel.app/sheet-cleaner.html" rel="noopener noreferrer"&gt;Sheet cleaner&lt;/a&gt; — strips hidden characters and unusual whitespace out of text cells in an Excel workbook.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://delint.vercel.app/column-splitter.html" rel="noopener noreferrer"&gt;Column splitter&lt;/a&gt; — splits one column into several, by delimiter or fixed width.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://delint.vercel.app/split-into-tabs.html" rel="noopener noreferrer"&gt;Split into tabs&lt;/a&gt; — groups rows by a column's value and fans them out into separate sheet tabs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full list is on the &lt;a href="https://delint.vercel.app/sitemap.html" rel="noopener noreferrer"&gt;sitemap&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why single-file, no-backend
&lt;/h2&gt;

&lt;p&gt;The constraint wasn't arbitrary — it's what makes the tools trustworthy to use on real data. Membership exports, employer summaries, anything with personal information in it: I didn't want to be in the position of asking anyone to upload that to a server I run, even one I trust. If a tool is a static HTML file that does everything in the browser, there's nothing to upload and nothing to explain. You can even open the file locally with no internet connection and it still works.&lt;/p&gt;

&lt;p&gt;It also keeps the maintenance cost near zero. There's no server to patch, no dependency graph to keep current beyond a handful of CDN script tags, no deploy pipeline beyond pushing to Vercel.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I got wrong the first time
&lt;/h2&gt;

&lt;p&gt;I built the first several tools as fully standalone pages — each one its own little island, no shared header, nav, or styling. That was fine until there were more than three or four of them and it became obvious a visitor had no way to discover the others. I ended up writing a retrofit script to go back through every tool and bolt on a shared shell (&lt;code&gt;nav.js&lt;/code&gt; for the tool registry, a common stylesheet, consistent header/footer).&lt;/p&gt;

&lt;p&gt;It worked, but it was a chore that didn't need to happen. The lesson that stuck: build the shared chrome first, even for tool #1, even when it feels premature. Retrofitting a dozen files is much more annoying than starting the pattern once.&lt;/p&gt;

&lt;p&gt;The other decision I'd make again: &lt;code&gt;nav.js&lt;/code&gt; is the single source of truth for the tool list. Early on I was tempted to keep a curated "featured tools" subset somewhere else — a sidebar, a homepage list — separate from the full registry. That's a dual-maintenance trap waiting to happen the moment you add a tool and forget to update the second list. Grouping the existing registry into sections turned out to be all the curation I actually needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Nine tools is where it stands today, not where it stops. More are coming — the registry in &lt;code&gt;nav.js&lt;/code&gt; is built to make adding another single-file tool a small change, not a redesign, so new cleanup jobs get added as I run into them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you're regularly stuck cleaning up exports, pasted text, or spreadsheets by hand, &lt;a href="https://delint.vercel.app/" rel="noopener noreferrer"&gt;Delint&lt;/a&gt; is free, has no account or tracking, and nothing you paste in ever leaves your browser. If there's a cleanup job you keep doing manually that isn't covered yet, get in touch — I'm always looking for the next tool to build, and I'm open to building one for your specific problem if it's a good fit.&lt;/p&gt;

&lt;p&gt;Everything stays free either way, but if a tool saves you time and you want to &lt;a href="https://delint.vercel.app/donate.html" rel="noopener noreferrer"&gt;chip in&lt;/a&gt;, that's appreciated too — it's optional, no paywall, no nagging.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
