Archive for the ‘web’ Category
This Wednesday, 11 February 2015, I will be giving a talk at the Amsterdam Clojure Meetup about our experiences at Studyflow implementing Event Sourcing with Clojure / ClojureScript. Daniel Marjenburgh will also be presenting “VisualReview: Web application layout testing with clj-webdriver”. This looks like it’s going to be an interesting evening.
If you want to attend, note that we are not at the regular old location @ Backbase any more. See the event web page for details.
This week, I re-implemented my main website. The text on the old one needed to be revised heavily (in fact I removed almost all of it except a short bio and some longer articles) and I wanted to experiment with a more colorful look. I need to revise the stylesheet a bit more to give a better experience on small screens (mobile), but so far I’m pleased with the result.
The new site html is generated completely by emacs’ org-mode project publishing functionality (the old one used a custom bunch of perl scripts generating from HTML snippets and perl POD documents). This hopefully means it’ll be easier to add and revise content, and it also provides nice syntax highlighting for any code snippets I put in my articles.
The whole switchover was pretty smooth, especially once I wrote a bit of elisp to roughly prepare conversion from POD formatting to org:
"Rougly convert region from pod syntax to org-mode"
(replace-regexp "C<\\([^>]+\\)>" "=\\1=" nil point mark)
(replace-regexp "I<\\([^>]+\\)>" "/\\1/" nil point mark)
(replace-regexp "B<\\([^>]+\\)>" "*\\1*" nil point mark)
(replace-regexp "^=head1 \\(.*\\)" "* \\1" nil point mark)
(replace-regexp "^=head2 \\(.*\\)" "** \\1" nil point mark)
(replace-regexp "^=head3 \\(.*\\)" "*** \\1" nil point mark)
(replace-regexp "^=head4 \\(.*\\)" "**** \\1" nil point mark)
(replace-regexp "^=head5 \\(.*\\)" "***** \\1" nil point mark))
Very basic, but pretty useful.
Now, I’m considering replacing WordPress for this blog with org-mode too. That probably requires a bit more investigation. I want to keep at least the tags/categories feature and related rss feeds, and I’m not sure if that’s available for org at the moment.
AuthSub is the authorization API Google uses for many of its products, meaning you can use it to ask a user to provide access to their private youtube listings, calendar entries etc without forcing them to hand over their password. The protocol is actually pretty simple and implementing it using clj-http was straight forward, except for one thing: clj-http always puts the connection port number in the Host header (which by the way is completely valid according to the HTTP/1.1 spec), but some google applications (notably, youtube) do not like that, giving a crypic HTTP status 401 “AuthSub token has the wrong scope” error. Figuring out the problem took a couple of hours given that that idiosyncrasy is not documented anywhere and I had to figure it out from some comments in the Python client for AuthSub.
With that issue out of the way, I’ve released clj-authsub version 0.1.0. It’s minimal and currently doesn’t support signed/secure tokens, but it works.
Some people when confronted with a problem, think “I know,
I’ll use ImageMagick.” Now they have two problems.*
For one of the sites I’m maintaining a lot of content is generated directly from (more or less print-ready) PDFs. The only free tool I’ve been able to find that can convert PDFs to decent quality JPGs or PNGs is ImageMagick.
But even when you’ve got ImageMagick’s
mogrify commands installed, conversion of PDFs still requires some careful tuning, that is: careful selection of arguments to
convert. Also; a sacrificial chicken and lots of patience. Anyway, here’s what I ended up with. Most of this is also available in my clj-imajine clojure library.
Many web browsers do not support any color space other than RGB/sRGB. If your PDFs are in the CMYK color space (usual for print) or any other color space, the resulting JPGs will look “weird” in many applications and web browsers; some viewers just show a blank image and others completely mess up the colors. To make sure the end result is in sRGB, use the option “
For much the same reasons, you want to enforce that the output color depth is 8 bits for JPGs. To do that, use the option “
PDFs are pretty complex documents and one potential pitfall is that there are at least 3 different indicators of the “boundaries” of the PDF. I’ve run into a few where the “right” boundaries were provided by the “cropbox” instead of the “media box”. This post by Joseph Scott provided the solution: use “
The final line becomes:
convert -define pdf:use-cropbox=true -colorspace sRGB -depth 8 pages.pdf pages.jpg
Note that if your PDF contains more than one page, this will generate a JPG for each one, named pages1.jpg, pages2.jpg etc… To select a single page you can use
convert -define pdf:use-cropbox=true -colorspace sRGB -depth 8 pages.pdf[X] pages.jpg where X is the page number minus 1. You can find the page numbers in a PDF using ImageMagick’s identify command like this:
identify -density 2 -format "%p," pages.pdf
*) paraphrased from Jamie Zawinski’s remark on regular expressions.
I’m working on pretzel right now. It’s a basic library that can be used to combine predicates and also holds a bunch of tests on string content.
Some people indicated they wanted some example code for my clj-decline
(validation) and flutter (form generation) libraries. So today I wrote
a simple demo application that uses both.
I pushed a new validation library for clojure to github yesterday. Check out clj-decline.
Why another validation library?
Well, why does validation suck so much?
Of course, dealing with user input is annoying anyway. But validation libraries always seem to want to do things in just the wrong way for the project you’re working on.
Let me count the ways:
- Also, validation does not mean “force this input into another type”. That’s not validation. Stick it somewhere else.
- They assume too much. If you can only validate a single value in a map, you’re useless. I need to check if a frobniz has either two wheebles or an odd number of crinks, and don’t try to stop me.
- I might need to validate something that isn’t a map. Maybe I want to check two maps. Maybe I need to check a single string or a file upload.
- They still assume too much. This may come as a shock, but not everyone speaks English on this planet. I have to support multiple languages in the same web app. Give me more options than pre-defined strings for errors, you lousy piece of American imperialist software! People of the earth, throw off your shackles and your “reality” TV shows!
- Macros, macros, macros all over the place. Yes, macros are cool, but no, I don’t want to stick every validation in a named var. If I wanted that, I could (def some-name (make-validation …)) so I don’t need your macro anyway. I want to use closures that validate for this specific user and now you’ve stopped me.
- Don’t be passive agressive. Validation is a user-centric feature. If I wanted to tell the user only their first error, I’d use exceptions. Don’t force the user to submit their form twenty times until they’ve fixed all their mistakes. Give them as much information as possible so they know what’s going on.
So, how does clj-decline fix all that?
It doesn’t. It just stays away from most of the above. clj-decline is simple. It validates arguments and returns errors. Everything else is up to the user or some other library. It’s completely functional, has no macros, no built-in predicates, nothing binds it to a web framework or anything else, and errors / messages can be anything you like. The only decision I made is that errors are grouped by key (which can also be anything you like).