/*jshint node:true */
|
/*
|
|
The MIT License (MIT)
|
|
Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
|
|
Permission is hereby granted, free of charge, to any person
|
obtaining a copy of this software and associated documentation files
|
(the "Software"), to deal in the Software without restriction,
|
including without limitation the rights to use, copy, modify, merge,
|
publish, distribute, sublicense, and/or sell copies of the Software,
|
and to permit persons to whom the Software is furnished to do so,
|
subject to the following conditions:
|
|
The above copyright notice and this permission notice shall be
|
included in all copies or substantial portions of the Software.
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
SOFTWARE.
|
*/
|
|
'use strict';
|
|
var Pattern = require('./pattern').Pattern;
|
|
|
var template_names = {
|
django: false,
|
erb: false,
|
handlebars: false,
|
php: false,
|
smarty: false
|
};
|
|
// This lets templates appear anywhere we would do a readUntil
|
// The cost is higher but it is pay to play.
|
function TemplatablePattern(input_scanner, parent) {
|
Pattern.call(this, input_scanner, parent);
|
this.__template_pattern = null;
|
this._disabled = Object.assign({}, template_names);
|
this._excluded = Object.assign({}, template_names);
|
|
if (parent) {
|
this.__template_pattern = this._input.get_regexp(parent.__template_pattern);
|
this._excluded = Object.assign(this._excluded, parent._excluded);
|
this._disabled = Object.assign(this._disabled, parent._disabled);
|
}
|
var pattern = new Pattern(input_scanner);
|
this.__patterns = {
|
handlebars_comment: pattern.starting_with(/{{!--/).until_after(/--}}/),
|
handlebars_unescaped: pattern.starting_with(/{{{/).until_after(/}}}/),
|
handlebars: pattern.starting_with(/{{/).until_after(/}}/),
|
php: pattern.starting_with(/<\?(?:[= ]|php)/).until_after(/\?>/),
|
erb: pattern.starting_with(/<%[^%]/).until_after(/[^%]%>/),
|
// django coflicts with handlebars a bit.
|
django: pattern.starting_with(/{%/).until_after(/%}/),
|
django_value: pattern.starting_with(/{{/).until_after(/}}/),
|
django_comment: pattern.starting_with(/{#/).until_after(/#}/),
|
smarty: pattern.starting_with(/{(?=[^}{\s\n])/).until_after(/[^\s\n]}/),
|
smarty_comment: pattern.starting_with(/{\*/).until_after(/\*}/),
|
smarty_literal: pattern.starting_with(/{literal}/).until_after(/{\/literal}/)
|
};
|
}
|
TemplatablePattern.prototype = new Pattern();
|
|
TemplatablePattern.prototype._create = function() {
|
return new TemplatablePattern(this._input, this);
|
};
|
|
TemplatablePattern.prototype._update = function() {
|
this.__set_templated_pattern();
|
};
|
|
TemplatablePattern.prototype.disable = function(language) {
|
var result = this._create();
|
result._disabled[language] = true;
|
result._update();
|
return result;
|
};
|
|
TemplatablePattern.prototype.read_options = function(options) {
|
var result = this._create();
|
for (var language in template_names) {
|
result._disabled[language] = options.templating.indexOf(language) === -1;
|
}
|
result._update();
|
return result;
|
};
|
|
TemplatablePattern.prototype.exclude = function(language) {
|
var result = this._create();
|
result._excluded[language] = true;
|
result._update();
|
return result;
|
};
|
|
TemplatablePattern.prototype.read = function() {
|
var result = '';
|
if (this._match_pattern) {
|
result = this._input.read(this._starting_pattern);
|
} else {
|
result = this._input.read(this._starting_pattern, this.__template_pattern);
|
}
|
var next = this._read_template();
|
while (next) {
|
if (this._match_pattern) {
|
next += this._input.read(this._match_pattern);
|
} else {
|
next += this._input.readUntil(this.__template_pattern);
|
}
|
result += next;
|
next = this._read_template();
|
}
|
|
if (this._until_after) {
|
result += this._input.readUntilAfter(this._until_pattern);
|
}
|
return result;
|
};
|
|
TemplatablePattern.prototype.__set_templated_pattern = function() {
|
var items = [];
|
|
if (!this._disabled.php) {
|
items.push(this.__patterns.php._starting_pattern.source);
|
}
|
if (!this._disabled.handlebars) {
|
items.push(this.__patterns.handlebars._starting_pattern.source);
|
}
|
if (!this._disabled.erb) {
|
items.push(this.__patterns.erb._starting_pattern.source);
|
}
|
if (!this._disabled.django) {
|
items.push(this.__patterns.django._starting_pattern.source);
|
// The starting pattern for django is more complex because it has different
|
// patterns for value, comment, and other sections
|
items.push(this.__patterns.django_value._starting_pattern.source);
|
items.push(this.__patterns.django_comment._starting_pattern.source);
|
}
|
if (!this._disabled.smarty) {
|
items.push(this.__patterns.smarty._starting_pattern.source);
|
}
|
|
if (this._until_pattern) {
|
items.push(this._until_pattern.source);
|
}
|
this.__template_pattern = this._input.get_regexp('(?:' + items.join('|') + ')');
|
};
|
|
TemplatablePattern.prototype._read_template = function() {
|
var resulting_string = '';
|
var c = this._input.peek();
|
if (c === '<') {
|
var peek1 = this._input.peek(1);
|
//if we're in a comment, do something special
|
// We treat all comments as literals, even more than preformatted tags
|
// we just look for the appropriate close tag
|
if (!this._disabled.php && !this._excluded.php && peek1 === '?') {
|
resulting_string = resulting_string ||
|
this.__patterns.php.read();
|
}
|
if (!this._disabled.erb && !this._excluded.erb && peek1 === '%') {
|
resulting_string = resulting_string ||
|
this.__patterns.erb.read();
|
}
|
} else if (c === '{') {
|
if (!this._disabled.handlebars && !this._excluded.handlebars) {
|
resulting_string = resulting_string ||
|
this.__patterns.handlebars_comment.read();
|
resulting_string = resulting_string ||
|
this.__patterns.handlebars_unescaped.read();
|
resulting_string = resulting_string ||
|
this.__patterns.handlebars.read();
|
}
|
if (!this._disabled.django) {
|
// django coflicts with handlebars a bit.
|
if (!this._excluded.django && !this._excluded.handlebars) {
|
resulting_string = resulting_string ||
|
this.__patterns.django_value.read();
|
}
|
if (!this._excluded.django) {
|
resulting_string = resulting_string ||
|
this.__patterns.django_comment.read();
|
resulting_string = resulting_string ||
|
this.__patterns.django.read();
|
}
|
}
|
if (!this._disabled.smarty) {
|
// smarty cannot be enabled with django or handlebars enabled
|
if (this._disabled.django && this._disabled.handlebars) {
|
resulting_string = resulting_string ||
|
this.__patterns.smarty_comment.read();
|
resulting_string = resulting_string ||
|
this.__patterns.smarty_literal.read();
|
resulting_string = resulting_string ||
|
this.__patterns.smarty.read();
|
}
|
}
|
}
|
return resulting_string;
|
};
|
|
|
module.exports.TemplatablePattern = TemplatablePattern;
|