At the risk of reinventing a wheel;
String.parse = function parse() {
    if(typeof arguments[0] === 'string' && typeof arguments[1] === 'string' ) {
        var str = arguments[0];
        var val = arguments[1];
        var array = [], obj = {};
        var re = /(?:{)([a-z]*)(?:})/gi;
        var match, sre = str;
        while(match = re.exec(str)) {
            array.push(match[1]);
            sre = sre.replace(match[0], '(\\w*)');          
        }
        re = new RegExp(sre);
        var matches = val.match(re);
        if(matches) {
            for(var i = 1; i < matches.length; i++) {
                obj[array[i-1]] = matches[i];       
            }
        }
        return obj;
    }
}
No doubt there are a bunch of ways this will break but works with your example;
String.parse("{year}-{month}-{day}-{name}-{topic}.{extension}", "2014-12-22-thomas-javascript.md");
EDIT
And for performing the reverse;
String.format = function format() {
    if (typeof arguments[0] === 'string') {
        var s = arguments[0];
        var re = /(?:{)(\d*)(?:})/gi;
        var a, i, match, search = s;
        while (match = re.exec(search)) {
            for (i = 1; i < arguments.length; i++) {
                a = parseInt(match[1]) + 1;
                s = s.replace(match[0], typeof arguments[a] !== 'object' ? arguments[a] || '' : '');
            }
        }
        re = /(?:{)([a-z]*)(?:})/gi;
        match, search = s;
        while (match = re.exec(search)) {
            for (i = 1; i < arguments.length; i++) {
                if (arguments[i].hasOwnProperty(match[1])) {
                    s = s.replace(match[0], arguments[i][match[1]]);
                }
            }
        }
        return s;
    }
}
Which can accept named object members or positional for non-objects.
String.format("{0}-{name}{1}-{year}-{src}", 20, "abc", { name: "xyz", year: 2014 }, { src: 'StackOverflow' });
20-xyzabc-2014-StackOverflow