来自正则表达式的模板字符串

时间:2017-07-26 22:02:15

标签: javascript regex templating

我们说我有以下网址路径:

/api/resource/:id

给定上下文对象{id: 1},路径将转换为/api/resource/1

现在我想构建一个更复杂的路径模板:

/api/resource/:id(/relationships/:name)?

此处relationships成员是可选的,因此两个上下文都可以匹配:

  • {id: 1, name: 'rel1'}将构建字符串/api/resource/1/relationships/rel1
  • {id: 1}仍应构建字符串/api/resource/1

我希望能够使用一组有限的正则表达式魔术来构建这样的字符串。

如何实现这样的模板引擎?

3 个答案:

答案 0 :(得分:1)

在node.js中,您只需定义两个不同的模板:

routes.route('/api/resource/:id')
  .get....

routes.route('/api/resource/:id/relationships/:name')
  .get...

但是,正如trincot所提到的,如果您说明了用于构建此功能的框架,将会很有帮助。

答案 1 :(得分:1)

您可以在replace中使用带有回调函数的正则表达式:



function applyTemplate(template, obj) {
    return template.replace(/\(([^()]*):(\w+)([^()]*)\)\?|:(\w+)/g, 
        function (match, before, name1, after, name2) {
            let name = name1 || name2;
            return name in obj ? (before||'') + obj[name] + (after||'') : '';
        });
}

var result,
    template = "/api/resource/:id(/relationships/:name)?";

result = applyTemplate(template, {id: 1, name: 'rel1'});
console.log(result);

result = applyTemplate(template, {id: 1});
console.log(result);




这不会处理( )?形式的嵌套括号。如果你需要,那么我建议有一个循环首先解析所有这些可选表达式,直到没有剩下:



function applyTemplate(template, obj) {
    var repeat = true;
    while (repeat) {
        repeat = false;
        template = template.replace(/\(([^()]*):(\w+)([^()]*)\)\?/g, function (match, before, name, after) {
            repeat = true;
            return name in obj ? before + obj[name] + after : '';
        });
    }
    // Now replace the non-optionals:
    return template.replace(/:(\w+)/g, function (match, name) {
        return obj[name] || '';
    });
}

var result,
    // Nested example
    template = "/api/resource/:id(/relationships(/option/:option)?/:name)?";

result = applyTemplate(template, {id: 1, option: 'special', name: 'rel1'});
console.log(result);
result = applyTemplate(template, {id: 1, name: 'rel1'});
console.log(result);
result = applyTemplate(template, {id: 1});
console.log(result);




答案 2 :(得分:0)

实际上,我发现path-to-regex完全符合我的要求。