mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
JS: Extract placeholders in HTML
This commit is contained in:
@@ -81,8 +81,7 @@ public class HTMLExtractor implements IExtractor {
|
||||
source,
|
||||
content.getBegin(),
|
||||
isTypeScript,
|
||||
elt,
|
||||
context);
|
||||
context.getNodeLabel(elt));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -93,6 +92,14 @@ public class HTMLExtractor implements IExtractor {
|
||||
// ignore empty attributes
|
||||
if (attr.getValue() == null || attr.getValue().isEmpty()) continue;
|
||||
|
||||
extractTemplateTags(
|
||||
textualExtractor,
|
||||
scopeManager,
|
||||
attr.getSource(),
|
||||
attr.getBegin(),
|
||||
attr.getEnd(),
|
||||
() -> context.getNodeLabel(attr));
|
||||
|
||||
String source = attr.getValue();
|
||||
int valueStart = attr.getValueSegment().getBegin();
|
||||
if (JS_ATTRIBUTE.matcher(attr.getName()).matches()) {
|
||||
@@ -104,8 +111,7 @@ public class HTMLExtractor implements IExtractor {
|
||||
source,
|
||||
valueStart,
|
||||
false /* isTypeScript */,
|
||||
attr,
|
||||
context);
|
||||
context.getNodeLabel(attr));
|
||||
} else if (isAngularTemplateAttributeName(attr.getName())) {
|
||||
// For an attribute *ngFor="let var of EXPR", start parsing at EXPR
|
||||
int offset = 0;
|
||||
@@ -125,8 +131,7 @@ public class HTMLExtractor implements IExtractor {
|
||||
source,
|
||||
valueStart + offset,
|
||||
false /* isTypeScript */,
|
||||
attr,
|
||||
context);
|
||||
context.getNodeLabel(attr));
|
||||
} else if (source.startsWith("javascript:")) {
|
||||
source = source.substring(11);
|
||||
extractSnippet(
|
||||
@@ -137,13 +142,19 @@ public class HTMLExtractor implements IExtractor {
|
||||
source,
|
||||
valueStart + 11,
|
||||
false /* isTypeScript */,
|
||||
attr,
|
||||
context);
|
||||
context.getNodeLabel(attr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleText(
|
||||
Source src, int textBegin, int textEnd, Label parentLabel, boolean isCData) {
|
||||
extractTemplateTags(
|
||||
textualExtractor, scopeManager, src, textBegin, textEnd, () -> parentLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldExtractAttributes(Element element) {
|
||||
Attributes attributes = element.getAttributes();
|
||||
@@ -294,8 +305,7 @@ public class HTMLExtractor implements IExtractor {
|
||||
String source,
|
||||
int offset,
|
||||
boolean isTypeScript,
|
||||
Segment parentHtmlNode,
|
||||
HtmlPopulator.Context context) {
|
||||
Label parentLabel) {
|
||||
TrapWriter trapWriter = textualExtractor.getTrapwriter();
|
||||
LocationManager locationManager = textualExtractor.getLocationManager();
|
||||
// JavaScript AST extraction does not currently support source maps, so just set
|
||||
@@ -330,7 +340,7 @@ public class HTMLExtractor implements IExtractor {
|
||||
scriptLocationManager.getFileLabel(),
|
||||
scriptLocationManager.getStartLine(),
|
||||
scriptLocationManager.getStartColumn());
|
||||
emitTopLevelXmlNodeBinding(parentHtmlNode, topLevelLabel, context, trapWriter);
|
||||
emitTopLevelXmlNodeBinding(parentLabel, topLevelLabel, trapWriter);
|
||||
// Note: LoC info is accounted for later, so not added here.
|
||||
return;
|
||||
}
|
||||
@@ -347,7 +357,7 @@ public class HTMLExtractor implements IExtractor {
|
||||
Pair<Label, LoCInfo> result = extractor.extract(tx, source, toplevelKind, scopeManager);
|
||||
Label toplevelLabel = result.fst();
|
||||
if (toplevelLabel != null) { // can be null when script ends up being parsed as JSON
|
||||
emitTopLevelXmlNodeBinding(parentHtmlNode, toplevelLabel, context, trapWriter);
|
||||
emitTopLevelXmlNodeBinding(parentLabel, toplevelLabel, trapWriter);
|
||||
}
|
||||
locInfo.add(result.snd());
|
||||
} catch (ParseError e) {
|
||||
@@ -356,8 +366,88 @@ public class HTMLExtractor implements IExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
private void emitTopLevelXmlNodeBinding(Segment parentHtmlNode, Label topLevelLabel, HtmlPopulator.Context context, TrapWriter writer) {
|
||||
Label htmlNodeLabel = context.getNodeLabel(parentHtmlNode);
|
||||
private void emitTopLevelXmlNodeBinding(
|
||||
Label htmlNodeLabel, Label topLevelLabel, TrapWriter writer) {
|
||||
writer.addTuple("toplevel_parent_xml_node", topLevelLabel, htmlNodeLabel);
|
||||
}
|
||||
|
||||
private static final String MUSTACHE_TAG_DOUBLE = "\\{\\{(?!\\{)(.*?)\\}\\}"; // {{ x }}
|
||||
private static final String MUSTACHE_TAG_TRIPLE = "\\{\\{\\{(.*?)\\}\\}\\}"; // {{{ x }}}
|
||||
private static final String MUSTACHE_TAG_PERCENT = "\\{%(?!>)(.*?)%\\}"; // {% x %}
|
||||
private static final String EJS_TAG = "<%(?![%<>}])[-=]?(.*?)[_-]?%>"; // <% x %>
|
||||
|
||||
/** Pattern for a template tag whose contents should be parsed as an expression */
|
||||
private static final Pattern TEMPLATE_EXPR_OPENING_TAG = Pattern.compile("^(?:\\{\\{\\{?|<%[-=])"); // {{, {{{, <%=, <%-
|
||||
|
||||
private static final Pattern TEMPLATE_TAGS =
|
||||
Pattern.compile(
|
||||
StringUtil.glue(
|
||||
"|", MUSTACHE_TAG_DOUBLE, MUSTACHE_TAG_TRIPLE, MUSTACHE_TAG_PERCENT, EJS_TAG),
|
||||
Pattern.DOTALL);
|
||||
|
||||
private void extractTemplateTags(
|
||||
TextualExtractor textualExtractor,
|
||||
ScopeManager scopeManager,
|
||||
Source root,
|
||||
int start,
|
||||
int end,
|
||||
Supplier<Label> parentLabel) {
|
||||
if (isEmbedded) return; // Do not extract template tags for HTML snippets embedded in a JS file
|
||||
|
||||
LocationManager locationManager = textualExtractor.getLocationManager();
|
||||
TrapWriter trapwriter = textualExtractor.getTrapwriter();
|
||||
Matcher m = TEMPLATE_TAGS.matcher(textualExtractor.getSource()).region(start, end);
|
||||
while (m.find()) {
|
||||
int startOffset = m.start();
|
||||
int endOffset = m.end();
|
||||
if (endOffset - startOffset > 10_000) {
|
||||
// Do not extract long template strings as they're likely to be FP matches and
|
||||
// unlikely to be parsed correctly.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Emit an entity for the template tag
|
||||
Label lbl = trapwriter.freshLabel();
|
||||
String rawText = m.group();
|
||||
trapwriter.addTuple("template_placeholder_tag_info", lbl, parentLabel.get(), rawText);
|
||||
|
||||
// Emit location
|
||||
Position startPos = textualExtractor.getSourceMap().getStart(startOffset);
|
||||
Position endPos = textualExtractor.getSourceMap().getEnd(endOffset - 1);
|
||||
int endColumn = endPos.getColumn() - 1; // Convert to inclusive end position (still 1-based)
|
||||
locationManager.emitFileLocation(
|
||||
lbl, startPos.getLine(), startPos.getColumn(), endPos.getLine(), endColumn);
|
||||
|
||||
// Parse the contents as a template expression, if the delimiter expects an expression.
|
||||
Matcher delimMatcher = TEMPLATE_EXPR_OPENING_TAG.matcher(rawText);
|
||||
if (delimMatcher.find()) {
|
||||
// The body of the template tag is stored in the first capture group of each pattern
|
||||
int bodyGroup = getNonNullCaptureGroup(m);
|
||||
if (bodyGroup != -1) {
|
||||
extractSnippet(
|
||||
TopLevelKind.ANGULAR_TEMPLATE,
|
||||
config.withSourceType(SourceType.ANGULAR_TEMPLATE),
|
||||
scopeManager,
|
||||
textualExtractor,
|
||||
m.group(bodyGroup),
|
||||
m.start(bodyGroup),
|
||||
false /* isTypeScript */,
|
||||
lbl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the first capture group that captured something
|
||||
* (apart from group zero which is the whole match).
|
||||
*/
|
||||
private static int getNonNullCaptureGroup(Matcher m) {
|
||||
for (int i = 1; i <= m.groupCount(); ++i) {
|
||||
if (m.group(i) != null) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
14
javascript/extractor/tests/generatedcode/input/test.html
Normal file
14
javascript/extractor/tests/generatedcode/input/test.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>{{title}}</h1>
|
||||
{{{subtitle_html}}}
|
||||
<p><%- body_html %></p>
|
||||
<p><%= footer %></p>
|
||||
<script>
|
||||
var data1 = {{{ user_data1 }}};
|
||||
var data2 = {{ user_data2 | json | safe }};
|
||||
var data3 = <%- user_data3 %>;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,775 @@
|
||||
#10000=@"/test.html;sourcefile"
|
||||
files(#10000,"/test.html","test","html",0)
|
||||
#10001=@"/;folder"
|
||||
folders(#10001,"/","")
|
||||
containerparent(#10001,#10000)
|
||||
#10002=@"loc,{#10000},0,0,0,0"
|
||||
locations_default(#10002,#10000,0,0,0,0)
|
||||
hasLocation(#10000,#10002)
|
||||
#20000=@"global_scope"
|
||||
scopes(#20000,0)
|
||||
#20001=*
|
||||
#20002=@"script;{#10000},8,13"
|
||||
#20003=*
|
||||
lines(#20003,#20002,"","
|
||||
")
|
||||
#20004=@"loc,{#10000},8,13,8,12"
|
||||
locations_default(#20004,#10000,8,13,8,12)
|
||||
hasLocation(#20003,#20004)
|
||||
#20005=*
|
||||
lines(#20005,#20002," var data1 = {{{ user_data1 }}};","
|
||||
")
|
||||
#20006=@"loc,{#10000},9,1,9,37"
|
||||
locations_default(#20006,#10000,9,1,9,37)
|
||||
hasLocation(#20005,#20006)
|
||||
indentation(#10000,9," ",6)
|
||||
#20007=*
|
||||
lines(#20007,#20002," var data2 = {{ user_data2 | json | safe }};","
|
||||
")
|
||||
#20008=@"loc,{#10000},10,1,10,49"
|
||||
locations_default(#20008,#10000,10,1,10,49)
|
||||
hasLocation(#20007,#20008)
|
||||
indentation(#10000,10," ",6)
|
||||
#20009=*
|
||||
lines(#20009,#20002," var data3 = <%- user_data3 %>;","
|
||||
")
|
||||
#20010=@"loc,{#10000},11,1,11,36"
|
||||
locations_default(#20010,#10000,11,1,11,36)
|
||||
hasLocation(#20009,#20010)
|
||||
indentation(#10000,11," ",6)
|
||||
#20011=*
|
||||
lines(#20011,#20002," ","")
|
||||
#20012=@"loc,{#10000},12,1,12,4"
|
||||
locations_default(#20012,#10000,12,1,12,4)
|
||||
hasLocation(#20011,#20012)
|
||||
numlines(#20002,5,3,0)
|
||||
#20013=*
|
||||
tokeninfo(#20013,7,#20002,0,"var")
|
||||
#20014=@"loc,{#10000},9,7,9,9"
|
||||
locations_default(#20014,#10000,9,7,9,9)
|
||||
hasLocation(#20013,#20014)
|
||||
#20015=*
|
||||
tokeninfo(#20015,6,#20002,1,"data1")
|
||||
#20016=@"loc,{#10000},9,11,9,15"
|
||||
locations_default(#20016,#10000,9,11,9,15)
|
||||
hasLocation(#20015,#20016)
|
||||
#20017=*
|
||||
tokeninfo(#20017,8,#20002,2,"=")
|
||||
#20018=@"loc,{#10000},9,17,9,17"
|
||||
locations_default(#20018,#10000,9,17,9,17)
|
||||
hasLocation(#20017,#20018)
|
||||
#20019=*
|
||||
tokeninfo(#20019,8,#20002,3,"}}}")
|
||||
#20020=@"loc,{#10000},9,34,9,36"
|
||||
locations_default(#20020,#10000,9,34,9,36)
|
||||
hasLocation(#20019,#20020)
|
||||
#20021=*
|
||||
tokeninfo(#20021,8,#20002,4,";")
|
||||
#20022=@"loc,{#10000},9,37,9,37"
|
||||
locations_default(#20022,#10000,9,37,9,37)
|
||||
hasLocation(#20021,#20022)
|
||||
#20023=*
|
||||
tokeninfo(#20023,7,#20002,5,"var")
|
||||
#20024=@"loc,{#10000},10,7,10,9"
|
||||
locations_default(#20024,#10000,10,7,10,9)
|
||||
hasLocation(#20023,#20024)
|
||||
#20025=*
|
||||
tokeninfo(#20025,6,#20002,6,"data2")
|
||||
#20026=@"loc,{#10000},10,11,10,15"
|
||||
locations_default(#20026,#10000,10,11,10,15)
|
||||
hasLocation(#20025,#20026)
|
||||
#20027=*
|
||||
tokeninfo(#20027,8,#20002,7,"=")
|
||||
#20028=@"loc,{#10000},10,17,10,17"
|
||||
locations_default(#20028,#10000,10,17,10,17)
|
||||
hasLocation(#20027,#20028)
|
||||
#20029=*
|
||||
tokeninfo(#20029,8,#20002,8,"}}")
|
||||
#20030=@"loc,{#10000},10,47,10,48"
|
||||
locations_default(#20030,#10000,10,47,10,48)
|
||||
hasLocation(#20029,#20030)
|
||||
#20031=*
|
||||
tokeninfo(#20031,8,#20002,9,";")
|
||||
#20032=@"loc,{#10000},10,49,10,49"
|
||||
locations_default(#20032,#10000,10,49,10,49)
|
||||
hasLocation(#20031,#20032)
|
||||
#20033=*
|
||||
tokeninfo(#20033,7,#20002,10,"var")
|
||||
#20034=@"loc,{#10000},11,7,11,9"
|
||||
locations_default(#20034,#10000,11,7,11,9)
|
||||
hasLocation(#20033,#20034)
|
||||
#20035=*
|
||||
tokeninfo(#20035,6,#20002,11,"data3")
|
||||
#20036=@"loc,{#10000},11,11,11,15"
|
||||
locations_default(#20036,#10000,11,11,11,15)
|
||||
hasLocation(#20035,#20036)
|
||||
#20037=*
|
||||
tokeninfo(#20037,8,#20002,12,"=")
|
||||
#20038=@"loc,{#10000},11,17,11,17"
|
||||
locations_default(#20038,#10000,11,17,11,17)
|
||||
hasLocation(#20037,#20038)
|
||||
#20039=*
|
||||
tokeninfo(#20039,8,#20002,13,"%>")
|
||||
#20040=@"loc,{#10000},11,34,11,35"
|
||||
locations_default(#20040,#10000,11,34,11,35)
|
||||
hasLocation(#20039,#20040)
|
||||
#20041=*
|
||||
tokeninfo(#20041,8,#20002,14,";")
|
||||
#20042=@"loc,{#10000},11,36,11,36"
|
||||
locations_default(#20042,#10000,11,36,11,36)
|
||||
hasLocation(#20041,#20042)
|
||||
#20043=*
|
||||
tokeninfo(#20043,0,#20002,15,"")
|
||||
#20044=@"loc,{#10000},12,5,12,4"
|
||||
locations_default(#20044,#10000,12,5,12,4)
|
||||
hasLocation(#20043,#20044)
|
||||
toplevels(#20002,1)
|
||||
#20045=@"loc,{#10000},8,13,12,4"
|
||||
locations_default(#20045,#10000,8,13,12,4)
|
||||
hasLocation(#20002,#20045)
|
||||
#20046=@"var;{data1};{#20000}"
|
||||
variables(#20046,"data1",#20000)
|
||||
#20047=@"var;{data2};{#20000}"
|
||||
variables(#20047,"data2",#20000)
|
||||
#20048=@"var;{data3};{#20000}"
|
||||
variables(#20048,"data3",#20000)
|
||||
#20049=*
|
||||
stmts(#20049,18,#20002,0,"var dat ... a1 }}};")
|
||||
#20050=@"loc,{#10000},9,7,9,37"
|
||||
locations_default(#20050,#10000,9,7,9,37)
|
||||
hasLocation(#20049,#20050)
|
||||
stmt_containers(#20049,#20002)
|
||||
#20051=*
|
||||
exprs(#20051,64,#20049,0,"data1 = ... ta1 }}}")
|
||||
#20052=@"loc,{#10000},9,11,9,36"
|
||||
locations_default(#20052,#10000,9,11,9,36)
|
||||
hasLocation(#20051,#20052)
|
||||
enclosing_stmt(#20051,#20049)
|
||||
expr_containers(#20051,#20002)
|
||||
#20053=*
|
||||
exprs(#20053,78,#20051,0,"data1")
|
||||
hasLocation(#20053,#20016)
|
||||
enclosing_stmt(#20053,#20049)
|
||||
expr_containers(#20053,#20002)
|
||||
literals("data1","data1",#20053)
|
||||
decl(#20053,#20046)
|
||||
#20054=*
|
||||
exprs(#20054,120,#20051,1,"{{{ user_data1 }}}")
|
||||
#20055=@"loc,{#10000},9,19,9,36"
|
||||
locations_default(#20055,#10000,9,19,9,36)
|
||||
hasLocation(#20054,#20055)
|
||||
enclosing_stmt(#20054,#20049)
|
||||
expr_containers(#20054,#20002)
|
||||
generated_code_expr_info(#20054,"{{{","}}}"," user_data1 ")
|
||||
#20056=*
|
||||
stmts(#20056,18,#20002,1,"var dat ... afe }};")
|
||||
#20057=@"loc,{#10000},10,7,10,49"
|
||||
locations_default(#20057,#10000,10,7,10,49)
|
||||
hasLocation(#20056,#20057)
|
||||
stmt_containers(#20056,#20002)
|
||||
#20058=*
|
||||
exprs(#20058,64,#20056,0,"data2 = ... safe }}")
|
||||
#20059=@"loc,{#10000},10,11,10,48"
|
||||
locations_default(#20059,#10000,10,11,10,48)
|
||||
hasLocation(#20058,#20059)
|
||||
enclosing_stmt(#20058,#20056)
|
||||
expr_containers(#20058,#20002)
|
||||
#20060=*
|
||||
exprs(#20060,78,#20058,0,"data2")
|
||||
hasLocation(#20060,#20026)
|
||||
enclosing_stmt(#20060,#20056)
|
||||
expr_containers(#20060,#20002)
|
||||
literals("data2","data2",#20060)
|
||||
decl(#20060,#20047)
|
||||
#20061=*
|
||||
exprs(#20061,120,#20058,1,"{{ user ... safe }}")
|
||||
#20062=@"loc,{#10000},10,19,10,48"
|
||||
locations_default(#20062,#10000,10,19,10,48)
|
||||
hasLocation(#20061,#20062)
|
||||
enclosing_stmt(#20061,#20056)
|
||||
expr_containers(#20061,#20002)
|
||||
generated_code_expr_info(#20061,"{{","}}"," user_data2 | json | safe ")
|
||||
#20063=*
|
||||
stmts(#20063,18,#20002,2,"var dat ... ta3 %>;")
|
||||
#20064=@"loc,{#10000},11,7,11,36"
|
||||
locations_default(#20064,#10000,11,7,11,36)
|
||||
hasLocation(#20063,#20064)
|
||||
stmt_containers(#20063,#20002)
|
||||
#20065=*
|
||||
exprs(#20065,64,#20063,0,"data3 = ... ata3 %>")
|
||||
#20066=@"loc,{#10000},11,11,11,35"
|
||||
locations_default(#20066,#10000,11,11,11,35)
|
||||
hasLocation(#20065,#20066)
|
||||
enclosing_stmt(#20065,#20063)
|
||||
expr_containers(#20065,#20002)
|
||||
#20067=*
|
||||
exprs(#20067,78,#20065,0,"data3")
|
||||
hasLocation(#20067,#20036)
|
||||
enclosing_stmt(#20067,#20063)
|
||||
expr_containers(#20067,#20002)
|
||||
literals("data3","data3",#20067)
|
||||
decl(#20067,#20048)
|
||||
#20068=*
|
||||
exprs(#20068,120,#20065,1,"<%- user_data3 %>")
|
||||
#20069=@"loc,{#10000},11,19,11,35"
|
||||
locations_default(#20069,#10000,11,19,11,35)
|
||||
hasLocation(#20068,#20069)
|
||||
enclosing_stmt(#20068,#20063)
|
||||
expr_containers(#20068,#20002)
|
||||
generated_code_expr_info(#20068,"<%-","%>"," user_data3 ")
|
||||
#20070=*
|
||||
entry_cfg_node(#20070,#20002)
|
||||
hasLocation(#20070,#20004)
|
||||
#20071=*
|
||||
exit_cfg_node(#20071,#20002)
|
||||
hasLocation(#20071,#20044)
|
||||
successor(#20063,#20067)
|
||||
successor(#20068,#20065)
|
||||
successor(#20067,#20068)
|
||||
successor(#20065,#20071)
|
||||
successor(#20056,#20060)
|
||||
successor(#20061,#20058)
|
||||
successor(#20060,#20061)
|
||||
successor(#20058,#20063)
|
||||
successor(#20049,#20053)
|
||||
successor(#20054,#20051)
|
||||
successor(#20053,#20054)
|
||||
successor(#20051,#20056)
|
||||
successor(#20070,#20049)
|
||||
toplevel_parent_xml_node(#20002,#20001)
|
||||
#20072=*
|
||||
xmlChars(#20072,"
|
||||
",#10000,0,0,#10000)
|
||||
#20073=@"loc,{#10000},1,16,1,16"
|
||||
locations_default(#20073,#10000,1,16,1,16)
|
||||
xmllocations(#20072,#20073)
|
||||
#20074=*
|
||||
xmlElements(#20074,"html",#10000,1,#10000)
|
||||
#20075=@"loc,{#10000},2,1,14,7"
|
||||
locations_default(#20075,#10000,2,1,14,7)
|
||||
xmllocations(#20074,#20075)
|
||||
#20076=*
|
||||
xmlChars(#20076,"
|
||||
",#20074,0,0,#10000)
|
||||
#20077=@"loc,{#10000},2,7,3,2"
|
||||
locations_default(#20077,#10000,2,7,3,2)
|
||||
xmllocations(#20076,#20077)
|
||||
#20078=*
|
||||
xmlChars(#20078,"
|
||||
",#20074,2,0,#10000)
|
||||
#20079=@"loc,{#10000},13,10,13,10"
|
||||
locations_default(#20079,#10000,13,10,13,10)
|
||||
xmllocations(#20078,#20079)
|
||||
#20080=*
|
||||
xmlElements(#20080,"body",#20074,1,#10000)
|
||||
#20081=@"loc,{#10000},3,3,13,9"
|
||||
locations_default(#20081,#10000,3,3,13,9)
|
||||
xmllocations(#20080,#20081)
|
||||
#20082=*
|
||||
xmlChars(#20082,"
|
||||
",#20080,0,0,#10000)
|
||||
#20083=@"loc,{#10000},3,9,4,4"
|
||||
locations_default(#20083,#10000,3,9,4,4)
|
||||
xmllocations(#20082,#20083)
|
||||
#20084=*
|
||||
template_placeholder_tag_info(#20084,#20080,"{{{subtitle_html}}}")
|
||||
#20085=@"loc,{#10000},5,5,5,23"
|
||||
locations_default(#20085,#10000,5,5,5,23)
|
||||
hasLocation(#20084,#20085)
|
||||
#20086=@"script;{#10000},5,8"
|
||||
#20087=*
|
||||
lines(#20087,#20086,"subtitle_html","")
|
||||
#20088=@"loc,{#10000},5,8,5,20"
|
||||
locations_default(#20088,#10000,5,8,5,20)
|
||||
hasLocation(#20087,#20088)
|
||||
numlines(#20086,1,1,0)
|
||||
#20089=*
|
||||
tokeninfo(#20089,6,#20086,0,"subtitle_html")
|
||||
hasLocation(#20089,#20088)
|
||||
#20090=*
|
||||
tokeninfo(#20090,0,#20086,1,"")
|
||||
#20091=@"loc,{#10000},5,21,5,20"
|
||||
locations_default(#20091,#10000,5,21,5,20)
|
||||
hasLocation(#20090,#20091)
|
||||
toplevels(#20086,4)
|
||||
hasLocation(#20086,#20088)
|
||||
#20092=@"module;{#10000},5,8"
|
||||
scopes(#20092,3)
|
||||
scopenodes(#20086,#20092)
|
||||
scopenesting(#20092,#20000)
|
||||
is_module(#20086)
|
||||
#20093=*
|
||||
stmts(#20093,2,#20086,0,"subtitle_html")
|
||||
hasLocation(#20093,#20088)
|
||||
stmt_containers(#20093,#20086)
|
||||
#20094=*
|
||||
exprs(#20094,79,#20093,0,"subtitle_html")
|
||||
hasLocation(#20094,#20088)
|
||||
enclosing_stmt(#20094,#20093)
|
||||
expr_containers(#20094,#20086)
|
||||
literals("subtitle_html","subtitle_html",#20094)
|
||||
#20095=@"var;{subtitle_html};{#20092}"
|
||||
variables(#20095,"subtitle_html",#20092)
|
||||
bind(#20094,#20095)
|
||||
#20096=*
|
||||
entry_cfg_node(#20096,#20086)
|
||||
#20097=@"loc,{#10000},5,8,5,7"
|
||||
locations_default(#20097,#10000,5,8,5,7)
|
||||
hasLocation(#20096,#20097)
|
||||
#20098=*
|
||||
exit_cfg_node(#20098,#20086)
|
||||
hasLocation(#20098,#20091)
|
||||
successor(#20093,#20094)
|
||||
successor(#20094,#20098)
|
||||
successor(#20096,#20093)
|
||||
toplevel_parent_xml_node(#20086,#20084)
|
||||
#20099=*
|
||||
xmlChars(#20099,"
|
||||
{{{subtitle_html}}}
|
||||
",#20080,2,0,#10000)
|
||||
#20100=@"loc,{#10000},4,23,6,4"
|
||||
locations_default(#20100,#10000,4,23,6,4)
|
||||
xmllocations(#20099,#20100)
|
||||
#20101=*
|
||||
xmlChars(#20101,"
|
||||
",#20080,4,0,#10000)
|
||||
#20102=@"loc,{#10000},6,28,7,4"
|
||||
locations_default(#20102,#10000,6,28,7,4)
|
||||
xmllocations(#20101,#20102)
|
||||
#20103=*
|
||||
xmlChars(#20103,"
|
||||
",#20080,6,0,#10000)
|
||||
#20104=@"loc,{#10000},7,25,8,4"
|
||||
locations_default(#20104,#10000,7,25,8,4)
|
||||
xmllocations(#20103,#20104)
|
||||
#20105=*
|
||||
xmlChars(#20105,"
|
||||
",#20080,8,0,#10000)
|
||||
#20106=@"loc,{#10000},12,14,13,2"
|
||||
locations_default(#20106,#10000,12,14,13,2)
|
||||
xmllocations(#20105,#20106)
|
||||
xmlElements(#20001,"script",#20080,7,#10000)
|
||||
#20107=@"loc,{#10000},8,5,12,13"
|
||||
locations_default(#20107,#10000,8,5,12,13)
|
||||
xmllocations(#20001,#20107)
|
||||
#20108=*
|
||||
template_placeholder_tag_info(#20108,#20001,"{{{ user_data1 }}}")
|
||||
locations_default(#20055,#10000,9,19,9,36)
|
||||
hasLocation(#20108,#20055)
|
||||
#20109=@"script;{#10000},9,22"
|
||||
#20110=*
|
||||
lines(#20110,#20109," user_data1 ","")
|
||||
#20111=@"loc,{#10000},9,22,9,33"
|
||||
locations_default(#20111,#10000,9,22,9,33)
|
||||
hasLocation(#20110,#20111)
|
||||
indentation(#10000,9," ",1)
|
||||
numlines(#20109,1,1,0)
|
||||
#20112=*
|
||||
tokeninfo(#20112,6,#20109,0,"user_data1")
|
||||
#20113=@"loc,{#10000},9,23,9,32"
|
||||
locations_default(#20113,#10000,9,23,9,32)
|
||||
hasLocation(#20112,#20113)
|
||||
#20114=*
|
||||
tokeninfo(#20114,0,#20109,1,"")
|
||||
#20115=@"loc,{#10000},9,34,9,33"
|
||||
locations_default(#20115,#10000,9,34,9,33)
|
||||
hasLocation(#20114,#20115)
|
||||
toplevels(#20109,4)
|
||||
hasLocation(#20109,#20111)
|
||||
#20116=@"module;{#10000},9,22"
|
||||
scopes(#20116,3)
|
||||
scopenodes(#20109,#20116)
|
||||
scopenesting(#20116,#20000)
|
||||
is_module(#20109)
|
||||
#20117=*
|
||||
stmts(#20117,2,#20109,0,"user_data1")
|
||||
hasLocation(#20117,#20113)
|
||||
stmt_containers(#20117,#20109)
|
||||
#20118=*
|
||||
exprs(#20118,79,#20117,0,"user_data1")
|
||||
hasLocation(#20118,#20113)
|
||||
enclosing_stmt(#20118,#20117)
|
||||
expr_containers(#20118,#20109)
|
||||
literals("user_data1","user_data1",#20118)
|
||||
#20119=@"var;{user_data1};{#20116}"
|
||||
variables(#20119,"user_data1",#20116)
|
||||
bind(#20118,#20119)
|
||||
#20120=*
|
||||
entry_cfg_node(#20120,#20109)
|
||||
#20121=@"loc,{#10000},9,22,9,21"
|
||||
locations_default(#20121,#10000,9,22,9,21)
|
||||
hasLocation(#20120,#20121)
|
||||
#20122=*
|
||||
exit_cfg_node(#20122,#20109)
|
||||
hasLocation(#20122,#20115)
|
||||
successor(#20117,#20118)
|
||||
successor(#20118,#20122)
|
||||
successor(#20120,#20117)
|
||||
toplevel_parent_xml_node(#20109,#20108)
|
||||
#20123=*
|
||||
template_placeholder_tag_info(#20123,#20001,"{{ user_data2 | json | safe }}")
|
||||
locations_default(#20062,#10000,10,19,10,48)
|
||||
hasLocation(#20123,#20062)
|
||||
#20124=@"script;{#10000},10,21"
|
||||
#20125=*
|
||||
lines(#20125,#20124," user_data2 | json | safe ","")
|
||||
#20126=@"loc,{#10000},10,21,10,46"
|
||||
locations_default(#20126,#10000,10,21,10,46)
|
||||
hasLocation(#20125,#20126)
|
||||
indentation(#10000,10," ",1)
|
||||
numlines(#20124,1,1,0)
|
||||
#20127=*
|
||||
tokeninfo(#20127,6,#20124,0,"user_data2")
|
||||
#20128=@"loc,{#10000},10,22,10,31"
|
||||
locations_default(#20128,#10000,10,22,10,31)
|
||||
hasLocation(#20127,#20128)
|
||||
#20129=*
|
||||
tokeninfo(#20129,8,#20124,1,"|")
|
||||
#20130=@"loc,{#10000},10,33,10,33"
|
||||
locations_default(#20130,#10000,10,33,10,33)
|
||||
hasLocation(#20129,#20130)
|
||||
#20131=*
|
||||
tokeninfo(#20131,6,#20124,2,"json")
|
||||
#20132=@"loc,{#10000},10,35,10,38"
|
||||
locations_default(#20132,#10000,10,35,10,38)
|
||||
hasLocation(#20131,#20132)
|
||||
#20133=*
|
||||
tokeninfo(#20133,8,#20124,3,"|")
|
||||
#20134=@"loc,{#10000},10,40,10,40"
|
||||
locations_default(#20134,#10000,10,40,10,40)
|
||||
hasLocation(#20133,#20134)
|
||||
#20135=*
|
||||
tokeninfo(#20135,6,#20124,4,"safe")
|
||||
#20136=@"loc,{#10000},10,42,10,45"
|
||||
locations_default(#20136,#10000,10,42,10,45)
|
||||
hasLocation(#20135,#20136)
|
||||
#20137=*
|
||||
tokeninfo(#20137,0,#20124,5,"")
|
||||
#20138=@"loc,{#10000},10,47,10,46"
|
||||
locations_default(#20138,#10000,10,47,10,46)
|
||||
hasLocation(#20137,#20138)
|
||||
toplevels(#20124,4)
|
||||
hasLocation(#20124,#20126)
|
||||
#20139=@"module;{#10000},10,21"
|
||||
scopes(#20139,3)
|
||||
scopenodes(#20124,#20139)
|
||||
scopenesting(#20139,#20000)
|
||||
is_module(#20124)
|
||||
#20140=*
|
||||
stmts(#20140,2,#20124,0,"user_da ... | safe")
|
||||
#20141=@"loc,{#10000},10,22,10,45"
|
||||
locations_default(#20141,#10000,10,22,10,45)
|
||||
hasLocation(#20140,#20141)
|
||||
stmt_containers(#20140,#20124)
|
||||
#20142=*
|
||||
exprs(#20142,13,#20140,0,"user_da ... | safe")
|
||||
hasLocation(#20142,#20141)
|
||||
enclosing_stmt(#20142,#20140)
|
||||
expr_containers(#20142,#20124)
|
||||
#20143=*
|
||||
exprs(#20143,119,#20142,-1,"safe")
|
||||
hasLocation(#20143,#20136)
|
||||
enclosing_stmt(#20143,#20140)
|
||||
expr_containers(#20143,#20124)
|
||||
#20144=*
|
||||
exprs(#20144,0,#20143,0,"safe")
|
||||
hasLocation(#20144,#20136)
|
||||
enclosing_stmt(#20144,#20140)
|
||||
expr_containers(#20144,#20124)
|
||||
literals("safe","safe",#20144)
|
||||
#20145=*
|
||||
exprs(#20145,13,#20142,0,"user_data2 | json")
|
||||
#20146=@"loc,{#10000},10,22,10,38"
|
||||
locations_default(#20146,#10000,10,22,10,38)
|
||||
hasLocation(#20145,#20146)
|
||||
enclosing_stmt(#20145,#20140)
|
||||
expr_containers(#20145,#20124)
|
||||
#20147=*
|
||||
exprs(#20147,119,#20145,-1,"json")
|
||||
hasLocation(#20147,#20132)
|
||||
enclosing_stmt(#20147,#20140)
|
||||
expr_containers(#20147,#20124)
|
||||
#20148=*
|
||||
exprs(#20148,0,#20147,0,"json")
|
||||
hasLocation(#20148,#20132)
|
||||
enclosing_stmt(#20148,#20140)
|
||||
expr_containers(#20148,#20124)
|
||||
literals("json","json",#20148)
|
||||
#20149=*
|
||||
exprs(#20149,79,#20145,0,"user_data2")
|
||||
hasLocation(#20149,#20128)
|
||||
enclosing_stmt(#20149,#20140)
|
||||
expr_containers(#20149,#20124)
|
||||
literals("user_data2","user_data2",#20149)
|
||||
#20150=@"var;{user_data2};{#20139}"
|
||||
variables(#20150,"user_data2",#20139)
|
||||
bind(#20149,#20150)
|
||||
#20151=*
|
||||
entry_cfg_node(#20151,#20124)
|
||||
#20152=@"loc,{#10000},10,21,10,20"
|
||||
locations_default(#20152,#10000,10,21,10,20)
|
||||
hasLocation(#20151,#20152)
|
||||
#20153=*
|
||||
exit_cfg_node(#20153,#20124)
|
||||
hasLocation(#20153,#20138)
|
||||
successor(#20140,#20143)
|
||||
successor(#20149,#20145)
|
||||
successor(#20147,#20149)
|
||||
successor(#20145,#20142)
|
||||
successor(#20143,#20147)
|
||||
successor(#20142,#20153)
|
||||
successor(#20151,#20140)
|
||||
toplevel_parent_xml_node(#20124,#20123)
|
||||
#20154=*
|
||||
template_placeholder_tag_info(#20154,#20001,"<%- user_data3 %>")
|
||||
locations_default(#20069,#10000,11,19,11,35)
|
||||
hasLocation(#20154,#20069)
|
||||
#20155=@"script;{#10000},11,22"
|
||||
#20156=*
|
||||
lines(#20156,#20155," user_data3 ","")
|
||||
#20157=@"loc,{#10000},11,22,11,33"
|
||||
locations_default(#20157,#10000,11,22,11,33)
|
||||
hasLocation(#20156,#20157)
|
||||
indentation(#10000,11," ",1)
|
||||
numlines(#20155,1,1,0)
|
||||
#20158=*
|
||||
tokeninfo(#20158,6,#20155,0,"user_data3")
|
||||
#20159=@"loc,{#10000},11,23,11,32"
|
||||
locations_default(#20159,#10000,11,23,11,32)
|
||||
hasLocation(#20158,#20159)
|
||||
#20160=*
|
||||
tokeninfo(#20160,0,#20155,1,"")
|
||||
#20161=@"loc,{#10000},11,34,11,33"
|
||||
locations_default(#20161,#10000,11,34,11,33)
|
||||
hasLocation(#20160,#20161)
|
||||
toplevels(#20155,4)
|
||||
hasLocation(#20155,#20157)
|
||||
#20162=@"module;{#10000},11,22"
|
||||
scopes(#20162,3)
|
||||
scopenodes(#20155,#20162)
|
||||
scopenesting(#20162,#20000)
|
||||
is_module(#20155)
|
||||
#20163=*
|
||||
stmts(#20163,2,#20155,0,"user_data3")
|
||||
hasLocation(#20163,#20159)
|
||||
stmt_containers(#20163,#20155)
|
||||
#20164=*
|
||||
exprs(#20164,79,#20163,0,"user_data3")
|
||||
hasLocation(#20164,#20159)
|
||||
enclosing_stmt(#20164,#20163)
|
||||
expr_containers(#20164,#20155)
|
||||
literals("user_data3","user_data3",#20164)
|
||||
#20165=@"var;{user_data3};{#20162}"
|
||||
variables(#20165,"user_data3",#20162)
|
||||
bind(#20164,#20165)
|
||||
#20166=*
|
||||
entry_cfg_node(#20166,#20155)
|
||||
#20167=@"loc,{#10000},11,22,11,21"
|
||||
locations_default(#20167,#10000,11,22,11,21)
|
||||
hasLocation(#20166,#20167)
|
||||
#20168=*
|
||||
exit_cfg_node(#20168,#20155)
|
||||
hasLocation(#20168,#20161)
|
||||
successor(#20163,#20164)
|
||||
successor(#20164,#20168)
|
||||
successor(#20166,#20163)
|
||||
toplevel_parent_xml_node(#20155,#20154)
|
||||
#20169=*
|
||||
xmlChars(#20169,"
|
||||
var data1 = {{{ user_data1 }}};
|
||||
var data2 = {{ user_data2 | json | safe }};
|
||||
var data3 = <%- user_data3 %>;
|
||||
",#20001,0,0,#10000)
|
||||
locations_default(#20045,#10000,8,13,12,4)
|
||||
xmllocations(#20169,#20045)
|
||||
#20170=*
|
||||
xmlElements(#20170,"p",#20080,5,#10000)
|
||||
#20171=@"loc,{#10000},7,5,7,24"
|
||||
locations_default(#20171,#10000,7,5,7,24)
|
||||
xmllocations(#20170,#20171)
|
||||
#20172=*
|
||||
template_placeholder_tag_info(#20172,#20170,"<%= footer %>")
|
||||
#20173=@"loc,{#10000},7,8,7,20"
|
||||
locations_default(#20173,#10000,7,8,7,20)
|
||||
hasLocation(#20172,#20173)
|
||||
#20174=@"script;{#10000},7,11"
|
||||
#20175=*
|
||||
lines(#20175,#20174," footer ","")
|
||||
#20176=@"loc,{#10000},7,11,7,18"
|
||||
locations_default(#20176,#10000,7,11,7,18)
|
||||
hasLocation(#20175,#20176)
|
||||
indentation(#10000,7," ",1)
|
||||
numlines(#20174,1,1,0)
|
||||
#20177=*
|
||||
tokeninfo(#20177,6,#20174,0,"footer")
|
||||
#20178=@"loc,{#10000},7,12,7,17"
|
||||
locations_default(#20178,#10000,7,12,7,17)
|
||||
hasLocation(#20177,#20178)
|
||||
#20179=*
|
||||
tokeninfo(#20179,0,#20174,1,"")
|
||||
#20180=@"loc,{#10000},7,19,7,18"
|
||||
locations_default(#20180,#10000,7,19,7,18)
|
||||
hasLocation(#20179,#20180)
|
||||
toplevels(#20174,4)
|
||||
hasLocation(#20174,#20176)
|
||||
#20181=@"module;{#10000},7,11"
|
||||
scopes(#20181,3)
|
||||
scopenodes(#20174,#20181)
|
||||
scopenesting(#20181,#20000)
|
||||
is_module(#20174)
|
||||
#20182=*
|
||||
stmts(#20182,2,#20174,0,"footer")
|
||||
hasLocation(#20182,#20178)
|
||||
stmt_containers(#20182,#20174)
|
||||
#20183=*
|
||||
exprs(#20183,79,#20182,0,"footer")
|
||||
hasLocation(#20183,#20178)
|
||||
enclosing_stmt(#20183,#20182)
|
||||
expr_containers(#20183,#20174)
|
||||
literals("footer","footer",#20183)
|
||||
#20184=@"var;{footer};{#20181}"
|
||||
variables(#20184,"footer",#20181)
|
||||
bind(#20183,#20184)
|
||||
#20185=*
|
||||
entry_cfg_node(#20185,#20174)
|
||||
#20186=@"loc,{#10000},7,11,7,10"
|
||||
locations_default(#20186,#10000,7,11,7,10)
|
||||
hasLocation(#20185,#20186)
|
||||
#20187=*
|
||||
exit_cfg_node(#20187,#20174)
|
||||
hasLocation(#20187,#20180)
|
||||
successor(#20182,#20183)
|
||||
successor(#20183,#20187)
|
||||
successor(#20185,#20182)
|
||||
toplevel_parent_xml_node(#20174,#20172)
|
||||
#20188=*
|
||||
xmlChars(#20188,"<%= footer %>",#20170,0,0,#10000)
|
||||
locations_default(#20173,#10000,7,8,7,20)
|
||||
xmllocations(#20188,#20173)
|
||||
#20189=*
|
||||
xmlElements(#20189,"p",#20080,3,#10000)
|
||||
#20190=@"loc,{#10000},6,5,6,27"
|
||||
locations_default(#20190,#10000,6,5,6,27)
|
||||
xmllocations(#20189,#20190)
|
||||
#20191=*
|
||||
template_placeholder_tag_info(#20191,#20189,"<%- body_html %>")
|
||||
#20192=@"loc,{#10000},6,8,6,23"
|
||||
locations_default(#20192,#10000,6,8,6,23)
|
||||
hasLocation(#20191,#20192)
|
||||
#20193=@"script;{#10000},6,11"
|
||||
#20194=*
|
||||
lines(#20194,#20193," body_html ","")
|
||||
#20195=@"loc,{#10000},6,11,6,21"
|
||||
locations_default(#20195,#10000,6,11,6,21)
|
||||
hasLocation(#20194,#20195)
|
||||
indentation(#10000,6," ",1)
|
||||
numlines(#20193,1,1,0)
|
||||
#20196=*
|
||||
tokeninfo(#20196,6,#20193,0,"body_html")
|
||||
#20197=@"loc,{#10000},6,12,6,20"
|
||||
locations_default(#20197,#10000,6,12,6,20)
|
||||
hasLocation(#20196,#20197)
|
||||
#20198=*
|
||||
tokeninfo(#20198,0,#20193,1,"")
|
||||
#20199=@"loc,{#10000},6,22,6,21"
|
||||
locations_default(#20199,#10000,6,22,6,21)
|
||||
hasLocation(#20198,#20199)
|
||||
toplevels(#20193,4)
|
||||
hasLocation(#20193,#20195)
|
||||
#20200=@"module;{#10000},6,11"
|
||||
scopes(#20200,3)
|
||||
scopenodes(#20193,#20200)
|
||||
scopenesting(#20200,#20000)
|
||||
is_module(#20193)
|
||||
#20201=*
|
||||
stmts(#20201,2,#20193,0,"body_html")
|
||||
hasLocation(#20201,#20197)
|
||||
stmt_containers(#20201,#20193)
|
||||
#20202=*
|
||||
exprs(#20202,79,#20201,0,"body_html")
|
||||
hasLocation(#20202,#20197)
|
||||
enclosing_stmt(#20202,#20201)
|
||||
expr_containers(#20202,#20193)
|
||||
literals("body_html","body_html",#20202)
|
||||
#20203=@"var;{body_html};{#20200}"
|
||||
variables(#20203,"body_html",#20200)
|
||||
bind(#20202,#20203)
|
||||
#20204=*
|
||||
entry_cfg_node(#20204,#20193)
|
||||
#20205=@"loc,{#10000},6,11,6,10"
|
||||
locations_default(#20205,#10000,6,11,6,10)
|
||||
hasLocation(#20204,#20205)
|
||||
#20206=*
|
||||
exit_cfg_node(#20206,#20193)
|
||||
hasLocation(#20206,#20199)
|
||||
successor(#20201,#20202)
|
||||
successor(#20202,#20206)
|
||||
successor(#20204,#20201)
|
||||
toplevel_parent_xml_node(#20193,#20191)
|
||||
#20207=*
|
||||
xmlChars(#20207,"<%- body_html %>",#20189,0,0,#10000)
|
||||
locations_default(#20192,#10000,6,8,6,23)
|
||||
xmllocations(#20207,#20192)
|
||||
#20208=*
|
||||
xmlElements(#20208,"h1",#20080,1,#10000)
|
||||
#20209=@"loc,{#10000},4,5,4,22"
|
||||
locations_default(#20209,#10000,4,5,4,22)
|
||||
xmllocations(#20208,#20209)
|
||||
#20210=*
|
||||
template_placeholder_tag_info(#20210,#20208,"{{title}}")
|
||||
#20211=@"loc,{#10000},4,9,4,17"
|
||||
locations_default(#20211,#10000,4,9,4,17)
|
||||
hasLocation(#20210,#20211)
|
||||
#20212=@"script;{#10000},4,11"
|
||||
#20213=*
|
||||
lines(#20213,#20212,"title","")
|
||||
#20214=@"loc,{#10000},4,11,4,15"
|
||||
locations_default(#20214,#10000,4,11,4,15)
|
||||
hasLocation(#20213,#20214)
|
||||
numlines(#20212,1,1,0)
|
||||
#20215=*
|
||||
tokeninfo(#20215,6,#20212,0,"title")
|
||||
hasLocation(#20215,#20214)
|
||||
#20216=*
|
||||
tokeninfo(#20216,0,#20212,1,"")
|
||||
#20217=@"loc,{#10000},4,16,4,15"
|
||||
locations_default(#20217,#10000,4,16,4,15)
|
||||
hasLocation(#20216,#20217)
|
||||
toplevels(#20212,4)
|
||||
hasLocation(#20212,#20214)
|
||||
#20218=@"module;{#10000},4,11"
|
||||
scopes(#20218,3)
|
||||
scopenodes(#20212,#20218)
|
||||
scopenesting(#20218,#20000)
|
||||
is_module(#20212)
|
||||
#20219=*
|
||||
stmts(#20219,2,#20212,0,"title")
|
||||
hasLocation(#20219,#20214)
|
||||
stmt_containers(#20219,#20212)
|
||||
#20220=*
|
||||
exprs(#20220,79,#20219,0,"title")
|
||||
hasLocation(#20220,#20214)
|
||||
enclosing_stmt(#20220,#20219)
|
||||
expr_containers(#20220,#20212)
|
||||
literals("title","title",#20220)
|
||||
#20221=@"var;{title};{#20218}"
|
||||
variables(#20221,"title",#20218)
|
||||
bind(#20220,#20221)
|
||||
#20222=*
|
||||
entry_cfg_node(#20222,#20212)
|
||||
#20223=@"loc,{#10000},4,11,4,10"
|
||||
locations_default(#20223,#10000,4,11,4,10)
|
||||
hasLocation(#20222,#20223)
|
||||
#20224=*
|
||||
exit_cfg_node(#20224,#20212)
|
||||
hasLocation(#20224,#20217)
|
||||
successor(#20219,#20220)
|
||||
successor(#20220,#20224)
|
||||
successor(#20222,#20219)
|
||||
toplevel_parent_xml_node(#20212,#20210)
|
||||
#20225=*
|
||||
xmlChars(#20225,"{{title}}",#20208,0,0,#10000)
|
||||
locations_default(#20211,#10000,4,9,4,17)
|
||||
xmllocations(#20225,#20211)
|
||||
numlines(#10000,14,10,0)
|
||||
filetype(#10000,"html")
|
||||
@@ -2894,18 +2894,17 @@ class ImportMetaExpr extends @import_meta_expr, Expr {
|
||||
*/
|
||||
class GeneratedCodeExpr extends @generated_code_expr, Expr {
|
||||
/** Gets the opening delimiter, such as `{{` or `{{{`. */
|
||||
string getOpeningDelimiter() {
|
||||
generated_code_expr_info(this, result, _, _)
|
||||
}
|
||||
string getOpeningDelimiter() { generated_code_expr_info(this, result, _, _) }
|
||||
|
||||
/** Gets the closing delimiter, such as `}}` or `}}}`. */
|
||||
string getClosingDelimiter() {
|
||||
generated_code_expr_info(this, _, result, _)
|
||||
}
|
||||
string getClosingDelimiter() { generated_code_expr_info(this, _, result, _) }
|
||||
|
||||
/** Gets the text between the delimiters, including any surrounding whitespace, such as the `x` in `{{x}}`. */
|
||||
string getBody() {
|
||||
generated_code_expr_info(this, _, _, result)
|
||||
string getBody() { generated_code_expr_info(this, _, _, result) }
|
||||
|
||||
/** Gets the placeholder tag that was parsed as an expression. */
|
||||
Templating::TemplatePlaceholderTag getPlaceholderTag() {
|
||||
result.getLocation() = this.getLocation()
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GeneratedCodeExpr" }
|
||||
|
||||
@@ -1268,6 +1268,22 @@ module DataFlow {
|
||||
override string toString() { result = variable.getName() }
|
||||
}
|
||||
|
||||
/** A data flow node representing the value plugged into a template tag. */
|
||||
class TemplatePlaceholderTagNode extends Node, TTemplatePlaceholderTag {
|
||||
/** Gets the template tag represented by this data flow node. */
|
||||
Templating::TemplatePlaceholderTag getTag() { this = TTemplatePlaceholderTag(result) }
|
||||
|
||||
override BasicBlock getBasicBlock() { none() }
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
getTag().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
override string toString() { result = getTag().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL. DO NOT USE.
|
||||
*
|
||||
|
||||
@@ -30,4 +30,5 @@ newtype TNode =
|
||||
TFunctionReturnNode(Function f) or
|
||||
TExceptionalFunctionReturnNode(Function f) or
|
||||
TExceptionalInvocationReturnNode(InvokeExpr e) or
|
||||
TGlobalAccessPathRoot()
|
||||
TGlobalAccessPathRoot() or
|
||||
TTemplatePlaceholderTag(Templating::TemplatePlaceholderTag tag)
|
||||
|
||||
@@ -48,4 +48,23 @@ module Templating {
|
||||
string getDelimiterMatchingRegexpWithPrefix(string prefix) {
|
||||
result = "(?s)" + prefix + "(" + concat("\\Q" + getADelimiter() + "\\E", "|") + ").*"
|
||||
}
|
||||
|
||||
/** A placeholder tag for a templating engine. */
|
||||
class TemplatePlaceholderTag extends @template_placeholder_tag, Locatable {
|
||||
override Location getLocation() { hasLocation(this, result) }
|
||||
|
||||
override string toString() { template_placeholder_tag_info(this, _, result) }
|
||||
|
||||
/** Gets the full text of the template tag, including delimiters. */
|
||||
string getRawText() { template_placeholder_tag_info(this, _, result) }
|
||||
|
||||
/** Gets the enclosing HTML element, attribute, or file. */
|
||||
Locatable getParent() { template_placeholder_tag_info(this, result, _) }
|
||||
|
||||
/** Gets a data flow node representing the value plugged into this placeholder. */
|
||||
DataFlow::TemplatePlaceholderTagNode asDataFlowNode() { result.getTag() = this }
|
||||
|
||||
/** Gets the top-level containing the template expression to be inserted at this placeholder. */
|
||||
Angular2::TemplateTopLevel getInnerTopLevel() { toplevel_parent_xml_node(result, this) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ is_nodejs (int tl: @toplevel ref);
|
||||
is_es2015_module (int tl: @toplevel ref);
|
||||
is_closure_module (int tl: @toplevel ref);
|
||||
|
||||
@xml_node_with_code = @xmlelement | @xmlattribute;
|
||||
@xml_node_with_code = @xmlelement | @xmlattribute | @template_placeholder_tag;
|
||||
toplevel_parent_xml_node(
|
||||
unique int toplevel: @toplevel ref,
|
||||
int xmlnode: @xml_node_with_code ref);
|
||||
@@ -424,6 +424,14 @@ generated_code_expr_info(
|
||||
varchar(900) body: string ref
|
||||
);
|
||||
|
||||
@template_placeholder_tag_parent = @xmlelement | @xmlattribute | @file;
|
||||
|
||||
template_placeholder_tag_info(
|
||||
unique int node: @template_placeholder_tag,
|
||||
int parentNode: @template_placeholder_tag_parent ref,
|
||||
varchar(900) raw: string ref
|
||||
);
|
||||
|
||||
// scopes
|
||||
scopes (unique int id: @scope,
|
||||
int kind: int ref);
|
||||
@@ -987,7 +995,8 @@ case @json_value.kind of
|
||||
| @jsdoc | @jsdoc_type_expr | @jsdoc_tag
|
||||
| @yaml_locatable
|
||||
| @xmllocatable
|
||||
| @configLocatable;
|
||||
| @configLocatable
|
||||
| @template_placeholder_tag;
|
||||
|
||||
hasLocation (unique int locatable: @locatable ref,
|
||||
int location: @location ref);
|
||||
|
||||
Reference in New Issue
Block a user