|
@@ -19,6 +19,7 @@ namespace Spry {
|
|
|
|
|
|
|
|
private static Dictionary<Type, ComponentTemplate> templates;
|
|
private static Dictionary<Type, ComponentTemplate> templates;
|
|
|
private static Mutex templates_lock = Mutex();
|
|
private static Mutex templates_lock = Mutex();
|
|
|
|
|
+ private string instance_id = Uuid.string_random();
|
|
|
|
|
|
|
|
public abstract string markup { get; }
|
|
public abstract string markup { get; }
|
|
|
public virtual StatusCode get_status() {
|
|
public virtual StatusCode get_status() {
|
|
@@ -149,18 +150,18 @@ namespace Spry {
|
|
|
return final_instance;
|
|
return final_instance;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- internal async MarkupDocument get_fragment_document(string fragment) throws Error {
|
|
|
|
|
|
|
+ internal async MarkupDocument get_dynamic_section(string name) throws Error {
|
|
|
if(!_prepare_once_called) {
|
|
if(!_prepare_once_called) {
|
|
|
yield prepare_once();
|
|
yield prepare_once();
|
|
|
_prepare_once_called = true;
|
|
_prepare_once_called = true;
|
|
|
}
|
|
}
|
|
|
yield prepare();
|
|
yield prepare();
|
|
|
|
|
|
|
|
- // Extract the fragment
|
|
|
|
|
|
|
+ // Extract the dynamic fragment
|
|
|
var final_instance = instance.copy();
|
|
var final_instance = instance.copy();
|
|
|
- var template_fragment = final_instance.select_one(@"//*[@spry-fragment='$fragment']")?.outer_html;
|
|
|
|
|
|
|
+ var template_fragment = final_instance.select_one(@"//*[@spry-dynamic='$name']")?.outer_html;
|
|
|
if(template_fragment == null) {
|
|
if(template_fragment == null) {
|
|
|
- throw new ComponentError.ELEMENT_NOT_FOUND(@"Could not find fragment names '$fragment'.");
|
|
|
|
|
|
|
+ throw new ComponentError.ELEMENT_NOT_FOUND(@"Could not find spry-dynamic section '$name'.");
|
|
|
}
|
|
}
|
|
|
final_instance.body.inner_html = template_fragment;
|
|
final_instance.body.inner_html = template_fragment;
|
|
|
|
|
|
|
@@ -218,6 +219,7 @@ namespace Spry {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private async void transform_document(MarkupDocument doc) throws Error {
|
|
private async void transform_document(MarkupDocument doc) throws Error {
|
|
|
|
|
+ transform_unique_attributes(doc); // Done first so as to ensure the tracking numbers don't change
|
|
|
transform_if_attributes(doc); // Outputs spry-hidden attributes
|
|
transform_if_attributes(doc); // Outputs spry-hidden attributes
|
|
|
remove_hidden_blocks(doc); // Removes tags with spry-hidden attributes
|
|
remove_hidden_blocks(doc); // Removes tags with spry-hidden attributes
|
|
|
yield transform_per_attributes(doc); // Executes spry-per-* loops, which handles nested expression attributes
|
|
yield transform_per_attributes(doc); // Executes spry-per-* loops, which handles nested expression attributes
|
|
@@ -228,7 +230,7 @@ namespace Spry {
|
|
|
transform_target_nodes(doc);
|
|
transform_target_nodes(doc);
|
|
|
transform_global_nodes(doc);
|
|
transform_global_nodes(doc);
|
|
|
transform_script_nodes(doc);
|
|
transform_script_nodes(doc);
|
|
|
- transform_fragment_attributes(doc);
|
|
|
|
|
|
|
+ transform_dynamic_attributes(doc);
|
|
|
transform_continuation_nodes(doc);
|
|
transform_continuation_nodes(doc);
|
|
|
remove_internal_sids(doc);
|
|
remove_internal_sids(doc);
|
|
|
yield append_globals(doc);
|
|
yield append_globals(doc);
|
|
@@ -271,7 +273,7 @@ namespace Spry {
|
|
|
foreach(var node in target_nodes) {
|
|
foreach(var node in target_nodes) {
|
|
|
var target_node = doc.select_one(@"//*[@sid='$(node.get_attribute("spry-target"))']");
|
|
var target_node = doc.select_one(@"//*[@sid='$(node.get_attribute("spry-target"))']");
|
|
|
if(target_node.id == null) {
|
|
if(target_node.id == null) {
|
|
|
- target_node.id = "_spry-" + Uuid.string_random();
|
|
|
|
|
|
|
+ target_node.id = "_spry-target-" + Uuid.string_random();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
node.set_attribute("hx-target", @"#$(target_node.id)");
|
|
node.set_attribute("hx-target", @"#$(target_node.id)");
|
|
@@ -330,10 +332,10 @@ namespace Spry {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private void transform_fragment_attributes(MarkupDocument doc) throws Error {
|
|
|
|
|
- var nodes = doc.select("//*[@spry-fragment]");
|
|
|
|
|
|
|
+ private void transform_dynamic_attributes(MarkupDocument doc) throws Error {
|
|
|
|
|
+ var nodes = doc.select("//*[@spry-dynamic]");
|
|
|
foreach (var node in nodes) {
|
|
foreach (var node in nodes) {
|
|
|
- var name = node.get_attribute("spry-fragment");
|
|
|
|
|
|
|
+ var name = node.get_attribute("spry-dynamic");
|
|
|
|
|
|
|
|
MarkupNode parent = node;
|
|
MarkupNode parent = node;
|
|
|
while((parent = parent.parent) != null) {
|
|
while((parent = parent.parent) != null) {
|
|
@@ -341,12 +343,30 @@ namespace Spry {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
if(parent == null) {
|
|
if(parent == null) {
|
|
|
- throw new ComponentError.INVALID_TEMPLATE("A tag with a spry-fragment attribute must be the child of a tag with a spry-continuation attribute");
|
|
|
|
|
|
|
+ throw new ComponentError.INVALID_TEMPLATE("A tag with a spry-dynamic attribute must be the child of a tag with a spry-continuation attribute");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- node.set_attribute("sse-swap", @"_spry-fragment-$name");
|
|
|
|
|
|
|
+ node.set_attribute("sse-swap", @"_spry-dynamic-$name");
|
|
|
node.set_attribute("hx-swap", "outerHTML");
|
|
node.set_attribute("hx-swap", "outerHTML");
|
|
|
- node.remove_attribute("spry-fragment");
|
|
|
|
|
|
|
+ if(!node.has_attribute("id")) {
|
|
|
|
|
+ node.set_attribute("id", @"_spry-dynamic-$name-$instance_id");
|
|
|
|
|
+ }
|
|
|
|
|
+ node.remove_attribute("spry-dynamic");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void transform_unique_attributes(MarkupDocument doc) throws Error {
|
|
|
|
|
+ var nodes = doc.select("//*[@spry-unique]");
|
|
|
|
|
+ var counter = 1000;
|
|
|
|
|
+ foreach (var node in nodes) {
|
|
|
|
|
+ if(node.has_attribute("id")) {
|
|
|
|
|
+ throw new ComponentError.INVALID_TEMPLATE("Cannot specify id attribute for an element with a spry-unique attribute");
|
|
|
|
|
+ }
|
|
|
|
|
+ if(node.get_attributes().keys.any(a => a.has_prefix("spry-per-")) || has_any_parent_where(node, n => n.get_attributes().keys.any(a => a.has_prefix("spry-per-")))) {
|
|
|
|
|
+ throw new ComponentError.INVALID_TEMPLATE("The spry-unique attribute is not valid on any element or child of any element with a spry-per attribute");
|
|
|
|
|
+ }
|
|
|
|
|
+ node.set_attribute("id", @"_spry-unique-$counter-$instance_id");
|
|
|
|
|
+ counter++;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -506,6 +526,16 @@ namespace Spry {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private bool has_any_parent_where(MarkupNode node, PredicateDelegate<MarkupNode> predicate) {
|
|
|
|
|
+ var current = node;
|
|
|
|
|
+ while((current = current.parent) != null) {
|
|
|
|
|
+ if(predicate(current)) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|