Blogging with Style
October 18th, 2005Since I’m a little obsessed with AppleScript, I end up pasting AppleScript code into my blog. I recently decided it was a real shame that I couldn’t easily replicate the way AppleScript code looks in Script Editor, in my blog. I thought about this situation for a while, and then did some experimenting.
If I copy the contents of a Script Editor window, and paste it into TextEdit, it looks great! Just like Script Editor! Why can’t I get that in HTML? I decided to try saving as HTML from TextEdit. Sure enough, that yields an HTML look-alike, but it depends on a rather elaborate set of CSS definitions in the <head> block of the document. I’m not ambitious enough to figure out whether I can include non-inlined CSS styles in random locations like the content of my blog post. Besides, I’d like to be able to “grab some styled text” and run with it.
It occurred to me that maybe AppleScript itself could help me get the formatting I needed. After a little tinkering, Sure enough, with TextEdit and the Text Suite, I can parse a chunk of styled text and spit out reasonably similar-looking HTML!
In this blog entry, I submit to you a script that will turn the text from the front-most document in TextEdit into a self-contained, inline styled chunk of HTML. It’s not pretty, but it works! As a proof-of-concept, the following code was copied from Script Editor, pasted into TextEdit, and then run from Script Editor. Because of some WordPress funkiness I had to change a few minor details in the source for this page, but I think you’ll find that the script works as expected in most contexts.:
tell application "Script Editor"
-- Since we are probably capturing newlines, tabs, etc.,
-- Let’s tag the content as "pre-formatted".
set myHTML to "<pre>"
--
Prefetch lists from the runs for performance during loopset {myFonts} to {font} of attribute runs of document 1
set {myColors} to {color} of attribute runs of document 1
set {mySizes} to {size} of attribute runs of document 1
set {myTexts} to {characters} of attribute runs of document 1
--
Build an independent HTML span for every attribute runrepeat with attrIndex from 1 to count of attribute runs of document 1
-- Figure the color
set thisColor to (item attrIndex of myColors)
set redComp to (my RGBColorNumToHex(item 1 of thisColor) as string)
set blueComp to (my RGBColorNumToHex(item 2 of thisColor) as string)
set greenComp to (my RGBColorNumToHex(item 3 of thisColor) as string)
set thisHexString to "#" & redComp & blueComp & greenComp
--
Font name and sizeset thisFont to (item attrIndex of myFonts as string)
set thisFontSize to (item attrIndex of mySizes as string)
--
Get the textset thisTextRun to (item attrIndex of myTexts as string)
--
Put it all togetherset thisHTMLRun to "<span style=\"color:" & thisHexString & "; font-family:’" & thisFont & "’; font-size:" & thisFontSize & "pt;\">" & thisTextRun & "</span>"
set myHTML to myHTML & thisHTMLRun end repeat
set myHTML to myHTML & "</pre>"
set the clipboard to myHTML
end tell
--
Based on Num32ToHex by Walter Ian Kaye-- http://www.natural-innovations.com/as/snippets.html
on RGBColorNumToHex(num)
-- We want smaller numbers
set num to num / 256
set out to ""
repeat with idx from 1 to 0 by -1
set bas to (16 ^ idx) as integer
if num ≥ bas then
set mult to ((num – (num mod bas)) / bas) as integer
set out to out & character mult of "123456789ABCDEF"
set num to (num – bas * mult)
else
set out to out & "0"
end if
end repeat
return out
end RGBColorNumToHex
Wow, that looks quite a bit more Script-Editor-like than your average web posting! It’s shamefully inefficent (take a look at the HTML it generates), but it gets the job done! I am happy to have this new tool at my disposal, but aside from producing rotten HTML code, the script is also dog slow. Also, when I copy the script above and paste it into Script Editor, it comes out double-spaced. Anybody out there have any tips for achieving this goal in a slightly more gallant manner?
Update: The script above has been updated since the original post. I discovered a few prefetching tricks that dramatically improve performance of the script. How dramatically? Thanks to Shark I can tell you! The test case for both scripts is converting the styled script text above from TextEdit to inline HTML. The old script? 58 seconds! 40% of which was spent in TextEdit itself. The optimized version above, which prefetches the pertinent styled text data from TextEdit? 4.5 seconds, with only 5.4% of the processor taken up by TextEdit. More than 10-times faster! Just imagine how fast it will be when a good scripter rewrites it!
October 19th, 2005 at 4:04 am
I wrote a pretty similar script the other day.
I’ve also discovered you can use this idea with any program – almost anything will allow for runs of text & attributes. Thus, if your Syntax Styling editor didn’t output HTML, you could easily cobble together a script that does.
I also wrote into my script the use of CSS, and put the CSS code on my site, so I can have smaller/more compact code created.
I like yours though, it’s a bit more general than mine.
October 19th, 2005 at 7:25 am
Thanks for the note, Matt. I didn’t realize the “text runs” would work in so many apps! In fact, I changed my script posted above to simply target Script Editor directly, and it does the trick.
I discovered that I need to update the script to at least look out for an convert entities like “<“, though. I’m not sure if I should try to do that with AppleScript, or switch to something more performance appropriate. It’s probably not a bad idea to grab the text runs with AppleScript and then pass them to perl or something for sanitizing and constructing the HTML.
October 19th, 2005 at 5:47 pm
Here’s my post describing the script I wrote.
http://schinckel.blogsome.com/2005/10/05/script-to-xhtml/
I think my output looks nicer than yours on IE Win (your lines seem to be overlapping each other a little). However, it’s Script Editor/AppleScript specific, and yours is a bit more General (potentially).
And, I note that Script Editor doesn’t report properly attributes at the start of comment blocks or lines. It may be worth coding this in, but would again make it AppleScript specific.
Oh, and the other thing I’ve done is copy it all to the clipboard at the end.
It’s probably possible to replace all of my replace() function calls with a single ‘sed’ command, but I haven’t gotten around to this. Mainly because I’ve been doing more JavaScript than AppleScript lately. And SubEthaEdit already has a “Copy to XHTML”. It doesn’t do as good a job with AppleScript, though, as it doesn’t recognise application commands properly.
I wonder if one of the alternative AppleScript development environments already does an Export to XHTML…
Oh, and there is already a program available that does this – converts scripts to HTML. I downloaded it, and got the source from the author, but haven’t really looked at it. It had some issues, and I was going to fix it, but ended up writing my own from scratch instead.
October 19th, 2005 at 5:52 pm
Hmm, your code looks better now. Not sure if you did anything, or if it was just a random IE issue. It must be the latter, as soon as I start editing the comment, it screws up again.
I did notice you don’t add the bold sections in. I think it’s because Verdana-Bold isn’t a real font: CSS needs it to be font-weight:bold.
October 19th, 2005 at 6:16 pm
Interesting, thanks for the feedback. Some good ideas to look into when I have more time!
I haven’t tried from IE yet (Windows or Mac), but I wouldn’t be surprised if some of the funkiness is due to my WordPress installation. I have noticed some funkiness which I think is because of inherited CSS attributes that I haven’t tracked down entirely.