I once had the task of prepping an HTML newsletter every week. We had a general template, and the weekly content was prepped by a designer in Fireworks, with links and everything already sorted. My task was to insert the generated HTML table into the template and update all the links to append Google tracking code. This used to take me "half of forever" every week, especially since lots of times there would be errors in the newsletter that necessitated starting my whole process from scratch every time. I think it was Fridays.
Anyway, I got good at this after a while - it would only take me about an hour to receive an image and have the newsletter updated, uploaded, and ready to fire off to our 10,000 subscribers. But this was still way too much time, and ruined any other projects I had at the end of the week, which happens to coincide with how deadlines naturally appear. So I tried to research another way of tackling this problem. My thoughts turned to regular expressions, and, as they say, I now had two problems.
Here is how the links always appeared in the newsletter:
<a href="http://sharkis.org?foo=bar"><img src="images/image1.png"/></a>
<a href="http://sharkis.org?foo=baz"><img src="images/image2.png"/></a>
<a href="http://sharkis.org?foo=bad"><img src="images/image3.png"/></a>
<a href="http://sharkis.org?foo=bat"><img src="images/image4.png"/></a>
<a href="http://sharkis.org?foo=bag"><img src="images/image5.png"/></a>
So there were two issues with this, really: the missing tracking code, and the image path was relative when it should be absolute (this is an email newsletter, so we need to link to the images).
function! Newsreplace(issue,start,end)
let previssue = (a:issue - 1)
"replace previous issue links with current issue
execute '%s/-'.previssue.'/-'.a:issue.'/g'
"prepend img src in block with protocol and domain for absolute link
execute a:start.','.a:end.'s/src="\zs\ze/http:\/\/www.sharkis.org\/newsletter\//g'
"append block style to images in block for gmail, etc.
execute a:start.','.a:end.'s/img \zs\ze/style="display:block;"/g'
"append google campaign stuff to each link in block
execute 'let @a=0 | '.a:start.','.a:end.'s/\zs\ze" target/\="?utm-source=newsletter='.a:issue.'&utm-medium=link-".(@a+setreg("a",@a+1))."&utm-campaign=newsletter-'.a:issue.'"/g'
"change first link to shipping-top
execute '%s/link-0/shipping-top/g'
"change last link to shipping-bottom
execute '%s/link-'.(@a-1).'/shipping-bottom/g'
endfunction
The function takes as arguments the issue number, the starting line for the link/image table, and the last line as well. Ok, so I have some vestigial code that I DO remember at the top on line 3. This finds any reference to the newsletter in the template and increments the number to match the current issue number. After that, it's a simple loop to match the regex and replace it appropriately.
\(href=".*\)"
This regular expression matches the href, equals sign, opening quote, and any characters before the closing quote, as well as the closing quote. The parenthesis group everything but the last quotation mark together for backreference purposes.
\1\&utm-campaign=newsletter-'.a:issue.'\&utm-medium=link-'.a.'"
\1 indicates the backreference I just mentioned, so it spits out the href, equals, first quote, and the entire original link. The ampersand ( & ) is escaped because in vimscript land, the ampersand will expand to the entire matched pattern we searched for. The ampersand also extends the GET parameters of the link, allowing me to add utm-campaign (equal to the newsletter number) and utm-medium (equal to the ordinal position of the link within the document) before I finally close the href with the final quotation mark.
At the bottom of the document, I change link-0 and the last link to banner-top and banner-bottom because those were common elements we had that we wished to independently track. This closes the function.
So, you would start with something like this:
And end with this instantly after executing the command:
This was just the beginning of my adventures with vim, but even this early on, I recognized the power that lay within this program. Macros used in this way can provide a value not just in easing workload, but actual time and money saved, as I now well know.
Kommentare