JS: Extract placeholders in HTML

This commit is contained in:
Asger Feldthaus
2021-07-20 10:33:54 +02:00
parent b1ce3d1c5a
commit 8666bc1894
8 changed files with 948 additions and 25 deletions

View File

@@ -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" }

View File

@@ -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.
*

View File

@@ -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)

View File

@@ -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) }
}
}

View File

@@ -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);