...
This commit is contained in:
		
							
								
								
									
										32
									
								
								examples/loadscripts/scripts/math_utils.rhai
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								examples/loadscripts/scripts/math_utils.rhai
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
// Math utility functions for Tera templates
 | 
			
		||||
 | 
			
		||||
// Format a number with commas as thousands separators
 | 
			
		||||
fn format_number(num) {
 | 
			
		||||
    let str = num.to_string();
 | 
			
		||||
    let result = "";
 | 
			
		||||
    let len = str.len;
 | 
			
		||||
    
 | 
			
		||||
    for i in 0..len {
 | 
			
		||||
        if i > 0 && (len - i) % 3 == 0 {
 | 
			
		||||
            result += ",";
 | 
			
		||||
        }
 | 
			
		||||
        result += str.substr(i, 1);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Calculate percentage
 | 
			
		||||
fn percentage(value, total) {
 | 
			
		||||
    if total == 0 {
 | 
			
		||||
        return "0%";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    let pct = (value / total) * 100.0;
 | 
			
		||||
    pct.round().to_string() + "%"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Format currency
 | 
			
		||||
fn currency(amount, symbol) {
 | 
			
		||||
    symbol + format_number(amount.round(2))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								examples/loadscripts/scripts/string_utils.rhai
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								examples/loadscripts/scripts/string_utils.rhai
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
// String manipulation functions that will be exposed to Tera templates
 | 
			
		||||
 | 
			
		||||
// Capitalize the first letter of each word
 | 
			
		||||
fn capitalize(text) {
 | 
			
		||||
    if text.len == 0 {
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    let words = text.split(" ");
 | 
			
		||||
    let result = [];
 | 
			
		||||
    
 | 
			
		||||
    for word in words {
 | 
			
		||||
        if word.len > 0 {
 | 
			
		||||
            let first_char = word.substr(0, 1).to_upper();
 | 
			
		||||
            let rest = word.substr(1, word.len - 1);
 | 
			
		||||
            result.push(first_char + rest);
 | 
			
		||||
        } else {
 | 
			
		||||
            result.push("");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    result.join(" ")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Truncate text with ellipsis
 | 
			
		||||
fn truncate(text, max_length) {
 | 
			
		||||
    if text.len <= max_length {
 | 
			
		||||
        return text;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    text.substr(0, max_length - 3) + "..."
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert text to slug format (lowercase, hyphens)
 | 
			
		||||
fn slugify(text) {
 | 
			
		||||
    let slug = text.to_lower();
 | 
			
		||||
    slug = slug.replace(" ", "-");
 | 
			
		||||
    slug = slug.replace(".", "");
 | 
			
		||||
    slug = slug.replace(",", "");
 | 
			
		||||
    slug = slug.replace("!", "");
 | 
			
		||||
    slug = slug.replace("?", "");
 | 
			
		||||
    slug
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								examples/loadscripts/scripts/test_utils.rhai
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								examples/loadscripts/scripts/test_utils.rhai
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
// Test utility functions to verify dynamic function discovery
 | 
			
		||||
// These functions were not in the original hardcoded lists
 | 
			
		||||
 | 
			
		||||
// Reverse a string
 | 
			
		||||
fn reverse_string(text) {
 | 
			
		||||
    let result = "";
 | 
			
		||||
    let i = text.len - 1;
 | 
			
		||||
    
 | 
			
		||||
    // Using a different approach to reverse the string
 | 
			
		||||
    // We'll iterate backwards with a while loop instead of using step
 | 
			
		||||
    while i >= 0 {
 | 
			
		||||
        result += text.substr(i, 1); 
 | 
			
		||||
        i -= 1;
 | 
			
		||||
    }
 | 
			
		||||
    result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Count words in a string - rewritten to avoid split issues
 | 
			
		||||
fn count_words(text) {
 | 
			
		||||
    if text.len == 0 {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Manual word counting implementation
 | 
			
		||||
    let count = 1; // Start with 1 for the first word
 | 
			
		||||
    let in_word = true;
 | 
			
		||||
    
 | 
			
		||||
    for i in 0..text.len {
 | 
			
		||||
        let char = text.substr(i, 1);
 | 
			
		||||
        
 | 
			
		||||
        if char == " " {
 | 
			
		||||
            in_word = false;
 | 
			
		||||
        } else if !in_word {
 | 
			
		||||
            // Found a non-space after a space = new word
 | 
			
		||||
            count += 1;
 | 
			
		||||
            in_word = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if text.substr(0, 1) == " " {
 | 
			
		||||
        // If text starts with space, reduce count
 | 
			
		||||
        count -= 1;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    count
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Calculate factorial
 | 
			
		||||
fn factorial(n) {
 | 
			
		||||
    // Ensure consistent integer type using to_int()
 | 
			
		||||
    let num = n.to_int();
 | 
			
		||||
    if num <= 1 {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    num * factorial(num-1)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										93
									
								
								examples/loadscripts/test_dynamic_loading.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								examples/loadscripts/test_dynamic_loading.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
use crate::tera_integration::RhaiTeraIntegration;
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
use rhai::Dynamic;
 | 
			
		||||
 | 
			
		||||
/// Test the dynamic loading of Rhai scripts and functions
 | 
			
		||||
pub fn test_dynamic_loading() -> Result<(), String> {
 | 
			
		||||
    println!("\n=== TESTING DYNAMIC FUNCTION LOADING ===\n");
 | 
			
		||||
    
 | 
			
		||||
    // Create a new RhaiTeraIntegration
 | 
			
		||||
    let mut integration = RhaiTeraIntegration::new();
 | 
			
		||||
    
 | 
			
		||||
    println!("Loading Rhai scripts...");
 | 
			
		||||
    
 | 
			
		||||
    // Load the original scripts
 | 
			
		||||
    integration.load_script("string_utils", "src/tera_integration/scripts/string_utils.rhai")?;
 | 
			
		||||
    integration.load_script("math_utils", "src/tera_integration/scripts/math_utils.rhai")?;
 | 
			
		||||
    
 | 
			
		||||
    // Load the new test script (which wasn't in the original hardcoded lists)
 | 
			
		||||
    integration.load_script("test_utils", "src/tera_integration/scripts/test_utils.rhai")?;
 | 
			
		||||
    
 | 
			
		||||
    // Get function names
 | 
			
		||||
    let function_names = integration.get_function_names();
 | 
			
		||||
    
 | 
			
		||||
    // Print all available functions
 | 
			
		||||
    println!("\nAll available functions:");
 | 
			
		||||
    for name in &function_names {
 | 
			
		||||
        println!("  - {}", name);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Group functions by their script prefix to display nicely
 | 
			
		||||
    let scripts = group_functions_by_script(&function_names);
 | 
			
		||||
    
 | 
			
		||||
    // Display functions by script
 | 
			
		||||
    display_functions_by_script(&scripts);
 | 
			
		||||
        
 | 
			
		||||
    // Test some functions from each script
 | 
			
		||||
    println!("\nDynamic function testing:");
 | 
			
		||||
    
 | 
			
		||||
    // Test original string utils functions
 | 
			
		||||
    test_function(&integration, "string_utils:capitalize", vec![Dynamic::from("hello world")])?;
 | 
			
		||||
    
 | 
			
		||||
    // Test original math utils functions
 | 
			
		||||
    test_function(&integration, "math_utils:format_number", vec![Dynamic::from(1234567)])?;
 | 
			
		||||
    
 | 
			
		||||
    // Test new functions from test_utils
 | 
			
		||||
    test_function(&integration, "test_utils:reverse_string", vec![Dynamic::from("hello world")])?;
 | 
			
		||||
    
 | 
			
		||||
    test_function(&integration, "test_utils:count_words", 
 | 
			
		||||
        vec![Dynamic::from("this is a test sentence")])?;
 | 
			
		||||
    
 | 
			
		||||
    test_function(&integration, "test_utils:factorial", 
 | 
			
		||||
        vec![Dynamic::from(5)])?;
 | 
			
		||||
    
 | 
			
		||||
    println!("\n=== DYNAMIC FUNCTION LOADING TEST COMPLETE ===\n");
 | 
			
		||||
    
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper function to group functions by script
 | 
			
		||||
fn group_functions_by_script(function_names: &[String]) -> HashMap<String, Vec<String>> {
 | 
			
		||||
    let mut scripts = HashMap::new();
 | 
			
		||||
    
 | 
			
		||||
    for name in function_names {
 | 
			
		||||
        let parts: Vec<&str> = name.split(':').collect();
 | 
			
		||||
        if parts.len() == 2 {
 | 
			
		||||
            let script = parts[0].to_string();
 | 
			
		||||
            let func = parts[1].to_string();
 | 
			
		||||
            
 | 
			
		||||
            scripts.entry(script).or_insert_with(Vec::new).push(func);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    scripts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper function to display functions grouped by script
 | 
			
		||||
fn display_functions_by_script(scripts: &HashMap<String, Vec<String>>) {
 | 
			
		||||
    println!("\nFunctions by script:");
 | 
			
		||||
    
 | 
			
		||||
    for (script, funcs) in scripts {
 | 
			
		||||
        println!("  {}:", script);
 | 
			
		||||
        for func in funcs {
 | 
			
		||||
            println!("    - {}", func);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper function to test a function and display its result
 | 
			
		||||
fn test_function(integration: &RhaiTeraIntegration, name: &str, args: Vec<Dynamic>) -> Result<(), String> {
 | 
			
		||||
    let result = integration.call_function(name, args)?;
 | 
			
		||||
    println!("  {}() => {}", name, result);
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										146
									
								
								examples/simple/scripts/data_objects.rhai
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								examples/simple/scripts/data_objects.rhai
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
			
		||||
// Data objects for Tera template integration
 | 
			
		||||
// This script defines complex objects that can be accessed from Tera templates
 | 
			
		||||
 | 
			
		||||
// Create a products catalog object
 | 
			
		||||
fn create_products() {
 | 
			
		||||
    let products = [
 | 
			
		||||
        #{
 | 
			
		||||
            id: 1,
 | 
			
		||||
            name: "Laptop",
 | 
			
		||||
            price: 1299.99,
 | 
			
		||||
            features: [
 | 
			
		||||
                "16GB RAM",
 | 
			
		||||
                "512GB SSD",
 | 
			
		||||
                "Intel i7 processor"
 | 
			
		||||
            ],
 | 
			
		||||
            available: true
 | 
			
		||||
        },
 | 
			
		||||
        #{
 | 
			
		||||
            id: 2,
 | 
			
		||||
            name: "Smartphone",
 | 
			
		||||
            price: 899.99,
 | 
			
		||||
            features: [
 | 
			
		||||
                "6.7 inch display",
 | 
			
		||||
                "128GB storage",
 | 
			
		||||
                "12MP camera"
 | 
			
		||||
            ],
 | 
			
		||||
            available: true
 | 
			
		||||
        },
 | 
			
		||||
        #{
 | 
			
		||||
            id: 3,
 | 
			
		||||
            name: "Tablet",
 | 
			
		||||
            price: 499.99,
 | 
			
		||||
            features: [
 | 
			
		||||
                "10.9 inch display",
 | 
			
		||||
                "64GB storage",
 | 
			
		||||
                "A14 chip"
 | 
			
		||||
            ],
 | 
			
		||||
            available: false
 | 
			
		||||
        },
 | 
			
		||||
        #{
 | 
			
		||||
            id: 4,
 | 
			
		||||
            name: "Headphones",
 | 
			
		||||
            price: 249.99,
 | 
			
		||||
            features: [
 | 
			
		||||
                "Noise cancellation",
 | 
			
		||||
                "Wireless",
 | 
			
		||||
                "20h battery life"
 | 
			
		||||
            ],
 | 
			
		||||
            available: true
 | 
			
		||||
        }
 | 
			
		||||
    ];
 | 
			
		||||
    
 | 
			
		||||
    products
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get all products
 | 
			
		||||
fn get_products() {
 | 
			
		||||
    create_products()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get available products only
 | 
			
		||||
fn get_available_products() {
 | 
			
		||||
    let all_products = create_products();
 | 
			
		||||
    let available = [];
 | 
			
		||||
    
 | 
			
		||||
    for product in all_products {
 | 
			
		||||
        if product.available {
 | 
			
		||||
            available.push(product);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    available
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get a specific product by ID
 | 
			
		||||
fn get_product_by_id(id) {
 | 
			
		||||
    let products = create_products();
 | 
			
		||||
    
 | 
			
		||||
    // Convert ID to integer to ensure type compatibility
 | 
			
		||||
    let search_id = id.to_int();
 | 
			
		||||
    
 | 
			
		||||
    for product in products {
 | 
			
		||||
        if product.id == search_id {
 | 
			
		||||
            return product;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #{}  // Return empty object if not found
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Calculate total price of all products
 | 
			
		||||
fn calculate_total_price() {
 | 
			
		||||
    let products = create_products();
 | 
			
		||||
    let total = 0.0;
 | 
			
		||||
    
 | 
			
		||||
    for product in products {
 | 
			
		||||
        total += product.price;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    total
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Format price with currency symbol
 | 
			
		||||
fn format_price(price) {
 | 
			
		||||
    "$" + price.to_string()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get all product features as a flattened array
 | 
			
		||||
fn get_all_features() {
 | 
			
		||||
    let products = create_products();
 | 
			
		||||
    let all_features = [];
 | 
			
		||||
    
 | 
			
		||||
    for product in products {
 | 
			
		||||
        for feature in product.features {
 | 
			
		||||
            all_features.push(feature);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    all_features
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get a user object
 | 
			
		||||
fn get_user() {
 | 
			
		||||
    #{
 | 
			
		||||
        name: "John Doe",
 | 
			
		||||
        email: "john@example.com",
 | 
			
		||||
        role: "admin",
 | 
			
		||||
        settings: #{
 | 
			
		||||
            theme: "dark",
 | 
			
		||||
            notifications: true,
 | 
			
		||||
            language: "en"
 | 
			
		||||
        },
 | 
			
		||||
        orders: [
 | 
			
		||||
            #{
 | 
			
		||||
                id: "ORD-001",
 | 
			
		||||
                date: "2025-03-25",
 | 
			
		||||
                total: 1299.99
 | 
			
		||||
            },
 | 
			
		||||
            #{
 | 
			
		||||
                id: "ORD-002",
 | 
			
		||||
                date: "2025-04-01",
 | 
			
		||||
                total: 249.99
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										114
									
								
								examples/simple/templates/product_catalog.tera
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								examples/simple/templates/product_catalog.tera
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <title>Product Catalog</title>
 | 
			
		||||
    <style>
 | 
			
		||||
        body {
 | 
			
		||||
            font-family: Arial, sans-serif;
 | 
			
		||||
            margin: 0;
 | 
			
		||||
            padding: 20px;
 | 
			
		||||
        }
 | 
			
		||||
        .product {
 | 
			
		||||
            border: 1px solid #ddd;
 | 
			
		||||
            padding: 10px;
 | 
			
		||||
            margin-bottom: 10px;
 | 
			
		||||
            border-radius: 5px;
 | 
			
		||||
        }
 | 
			
		||||
        .product-available {
 | 
			
		||||
            background-color: #f0fff0;
 | 
			
		||||
        }
 | 
			
		||||
        .product-unavailable {
 | 
			
		||||
            background-color: #fff0f0;
 | 
			
		||||
        }
 | 
			
		||||
        .features {
 | 
			
		||||
            margin-top: 5px;
 | 
			
		||||
        }
 | 
			
		||||
        .price {
 | 
			
		||||
            font-weight: bold;
 | 
			
		||||
            color: #2a5885;
 | 
			
		||||
        }
 | 
			
		||||
        .total {
 | 
			
		||||
            margin-top: 20px;
 | 
			
		||||
            text-align: right;
 | 
			
		||||
            font-size: 1.2em;
 | 
			
		||||
        }
 | 
			
		||||
        .user-info {
 | 
			
		||||
            background-color: #f5f5f5;
 | 
			
		||||
            padding: 10px;
 | 
			
		||||
            margin-top: 20px;
 | 
			
		||||
            border-radius: 5px;
 | 
			
		||||
        }
 | 
			
		||||
    </style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <h1>Product Catalog</h1>
 | 
			
		||||
    
 | 
			
		||||
    <!-- Call Rhai function to get products and iterate over them -->
 | 
			
		||||
    {% let products = data_objects:get_products() %}
 | 
			
		||||
    <h2>All Products</h2>
 | 
			
		||||
    {% for product in products %}
 | 
			
		||||
    <div class="product {% if product.available %}product-available{% else %}product-unavailable{% endif %}">
 | 
			
		||||
        <h3>{{ product.name }}</h3>
 | 
			
		||||
        <div class="price">{{ data_objects:format_price(product.price) }}</div>
 | 
			
		||||
        <div class="features">
 | 
			
		||||
            <strong>Features:</strong>
 | 
			
		||||
            <ul>
 | 
			
		||||
                {% for feature in product.features %}
 | 
			
		||||
                <li>{{ feature }}</li>
 | 
			
		||||
                {% endfor %}
 | 
			
		||||
            </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div>
 | 
			
		||||
            {% if product.available %}
 | 
			
		||||
            <span class="available">In Stock</span>
 | 
			
		||||
            {% else %}
 | 
			
		||||
            <span class="unavailable">Out of Stock</span>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
    
 | 
			
		||||
    <!-- Call Rhai function to get only available products -->
 | 
			
		||||
    {% let available_products = data_objects:get_available_products() %}
 | 
			
		||||
    <h2>Available Products ({{ available_products.len() }})</h2>
 | 
			
		||||
    {% for product in available_products %}
 | 
			
		||||
    <div class="product product-available">
 | 
			
		||||
        <h3>{{ product.name }}</h3>
 | 
			
		||||
        <div class="price">{{ data_objects:format_price(product.price) }}</div>
 | 
			
		||||
    </div>
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
    
 | 
			
		||||
    <!-- Display total price using Rhai function -->
 | 
			
		||||
    <div class="total">
 | 
			
		||||
        Total Catalog Value: {{ data_objects:format_price(data_objects:calculate_total_price()) }}
 | 
			
		||||
    </div>
 | 
			
		||||
    
 | 
			
		||||
    <!-- Display user information from Rhai function -->
 | 
			
		||||
    {% let user = data_objects:get_user() %}
 | 
			
		||||
    <div class="user-info">
 | 
			
		||||
        <h2>User Information</h2>
 | 
			
		||||
        <p><strong>Name:</strong> {{ user.name }}</p>
 | 
			
		||||
        <p><strong>Email:</strong> {{ user.email }}</p>
 | 
			
		||||
        <p><strong>Role:</strong> {{ user.role }}</p>
 | 
			
		||||
        <p><strong>Theme:</strong> {{ user.settings.theme }}</p>
 | 
			
		||||
        
 | 
			
		||||
        <h3>Order History</h3>
 | 
			
		||||
        <ul>
 | 
			
		||||
            {% for order in user.orders %}
 | 
			
		||||
            <li>
 | 
			
		||||
                <strong>{{ order.id }}</strong> ({{ order.date }}) - 
 | 
			
		||||
                {{ data_objects:format_price(order.total) }}
 | 
			
		||||
            </li>
 | 
			
		||||
            {% endfor %}
 | 
			
		||||
        </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
    
 | 
			
		||||
    <!-- List all unique features -->
 | 
			
		||||
    <h2>All Features</h2>
 | 
			
		||||
    <ul>
 | 
			
		||||
        {% let features = data_objects:get_all_features() %}
 | 
			
		||||
        {% for feature in features %}
 | 
			
		||||
        <li>{{ feature }}</li>
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
    </ul>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user