Skip to content

Instantly share code, notes, and snippets.

@debrouwere
Last active December 12, 2015 09:19
Show Gist options
  • Save debrouwere/4750850 to your computer and use it in GitHub Desktop.
Save debrouwere/4750850 to your computer and use it in GitHub Desktop.
Shortlinks for static site generators... for heroes. (No databases, no web apps, just NGINX rewrites.)
fs = require 'fs'
routing = require './utils'
postDir = 'posts'
shortlinksFile = 'shortlinks.conf'
stream = fs.createWriteStream shortlinksFile, {flags: 'a'}
shortlinks = (fs.readFileSync shortlinksFile, 'utf8').replace(/\s+$/).split '\n'
tail = shortlinks.slice(-1)[0]
counter = parseInt (tail.match /(\d+)\s/)?[1] or 0
formats =
filename: new routing.Format '{year}-{month}-{day}-{title}'
permalink: new routing.Format '/{year}/{month}/{day}/{title}/'
for post in fs.readdirSync postDir
context = isPost = formats.filename.match post
permalink = formats.permalink.fill context
shortlinkMatches = shortlinks.filter (redirect) -> (redirect.indexOf permalink) isnt -1
hasShortlink = shortlinkMatches.length
if isPost and not hasShortlink
counter++
rewrite = "rewrite ^/#{counter} #{permalink} permanent;\n"
stream.write rewrite
class exports.Format
constructor: (@raw, @defaults = {}) ->
# is this a fully-specified path or a template with placeholders?
if (@raw.indexOf '{') > -1
@isTemplate = yes
else
@isTemplate = no
# analog to matching a regular expression against a string
match: (str) ->
keys = @raw.match /\{([^\}]+)\}/g
keys = keys.map (match) ->
match.slice 1, -1
keys.push 'extension'
regex = @raw.replace /\{([^\}]+)\}/g, '(.+?)'
regex = new RegExp "#{regex}\.([^.]+)$"
matchObj = regex.exec(str)
return null unless matchObj
matches = matchObj[1..]
context = @defaults
for key in keys
context[key] = matches.shift()
context
toTemplate: ->
(context) =>
str = @raw
for key, value of context
str = str.replace "{#{key}}", value, 'g'
str
# fill the placeholders in our formatted string with
# the context variables
fill: (context) ->
@toTemplate()(context)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment