Saturday, June 7, 2025

ATV 0.2


While every cool kid across the planet is experimenting with vibe coding, I’ve been overhauling my pet project, ATV, from the ground up. It is now re-written—still in pure Vanilla JavaScript—but this time in nice modular ES6. This time around I’m a little proud of the code. 


ATV is a replacement for stimulus.js, same concept but done in a functional style. In my mind, the controller code reads much cleaner and DRYer. 


Actually I did “vibe code” one part, I must admit. As an experiment I wanted to know if GitHub CoPilot (the only AI I have access to) could write (from an English description and examples only) a recursive descent parser for me, in the style of Douglas Crockford. Surprisingly it came pretty close, although it was also very close to my own first draft.


Other than that, the new ATV is old-timey human coded JavaScript!  It does everything shown on the ATV By Examples page (https://www.sbrew.com/atv_by_example) and more with almost no changes from the 0.1 version.


Two changes to the API are improvements, plus one feature was removed until/if/when I hear someone wants it:

  1. Now actually pluralizes the groups of targets, so if you have five targets called puppy, you will get them via targets.puppies
  2. For actions with parameters, strings now must be quoted, like : data-atv-zoo-action: { "click->greet(‘puppy’)" }
  3. ATV no longer notifies if targets are removed or added to the page. I'd love to hear what the use case is for this and I can add it back!


Other features include:


  • Consists of 14 ES6 modules, the largest of which is 157 lines including comments
  • Gzips down to under 4KB.
  • Passes JSLint *and* ESLint, except for whitespace rules where I let ESLint win.
  • No “this”
  • No “classes”
  • Recursive descent parsing of actions

Sunday, January 26, 2025

What is the right tool for email validation?


One of my pet peeves is seeing something like this in a codebase, grabbed from a friendly StackOverflow article or maybe even regurgitated by some carbon-spewing AI:

EMAIL_REGEX = (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Don't get me wrong: I love regular expressions when they are the right tool for the job. I can even appreciate a clever one now and then. So what is wrong with this picture?
  1. It is almost certainly incorrect. Please prove me wrong if anyone has proof or exhaustive tests in a repo somewhere.
  2. It is ridiculously big and impossible to understand.
  3. Regular expressions tend to inadvertently introduce punitive algorithmic complexity explosion due to their power and expressiveness.
RFC 5322 Section 3.4 defines (as of this writing) the format of an email address. It consists of complex rules and formats going back to the beginning of time (well, not all the way back to UUCP email such as my first email address ..!ualberta!tim). It also defers validation of the parts to other RFCs and even to the implementations. Fortunately though, it does provide enough to build a simple procedural parser that any programmer can understand and adjust if business needs change.

For the parser, I suggest a divide and conquer strategy that breaks the address into its constituent parts using language string manipulation. These parts can then be further broken down and validated using regular expressions or other language features.

I have built this already four or fives times in various languages including Java, Ruby, JavaScript, and Elm for previous projects. This time I'll finally write a gem for it. Stay posted, I'll have a GitHub repo ready in a bit.

And if you know of a gem or other open source implementation that is still current for RFC style procedural validation please let me know!