JavaScript Template String Parser
This challenge involves creating a JavaScript function that can parse and evaluate template strings. Template strings are a powerful feature that allows embedding expressions within strings, making string formatting more dynamic and readable. This skill is fundamental for building many web applications, from generating dynamic HTML to constructing complex API requests.
Problem Description
Your task is to implement a JavaScript function named parseTemplateString that takes two arguments:
templateString: A string containing placeholders.data: An object containing key-value pairs, where keys correspond to the names within the placeholders.
The function should replace all placeholders in the templateString with their corresponding values from the data object and return the resulting string.
Key Requirements:
- Placeholder Syntax: Placeholders will be enclosed in double curly braces, e.g.,
{{variableName}}. - Data Lookup: The parser should look up
variableNamein thedataobject. - Value Replacement: If a key exists in the
dataobject, its value should replace the placeholder. - Handling Missing Data: If a placeholder's key is not found in the
dataobject, the placeholder itself (e.g.,{{missingKey}}) should remain in the output string. - Nested Data (Optional but Recommended): For a more advanced challenge, consider supporting nested object properties using dot notation within placeholders, e.g.,
{{user.address.city}}. If any part of the nested path is missing, the entire placeholder should remain.
Expected Behavior:
The function should iterate through the templateString, identify all placeholders, and attempt to resolve them using the provided data object. The function should return the fully processed string.
Edge Cases to Consider:
- Empty
templateString. - Empty
dataobject. - Placeholders that are substrings of other words (e.g.,
{{user}}within{{username}}). The parser should correctly identify and replace only the intended placeholders. - Placeholders with special characters in their names (if supported by object keys, though typically variable names are alphanumeric and underscores).
- Values in the
dataobject that are not strings (e.g., numbers, booleans, null, undefined). These should be converted to their string representations.
Examples
Example 1:
Input:
templateString = "Hello, {{name}}! You are {{age}} years old."
data = { name: "Alice", age: 30 }
Output:
"Hello, Alice! You are 30 years old."
Explanation:
The placeholder "{{name}}" is replaced with "Alice" from the data object.
The placeholder "{{age}}" is replaced with "30" (converted from a number) from the data object.
Example 2:
Input:
templateString = "The product is {{productName}}. Price: {{price}}. Available: {{available}}"
data = { productName: "Laptop", price: 1200 }
Output:
"The product is Laptop. Price: 1200. Available: {{available}}"
Explanation:
"{{productName}}" is replaced with "Laptop".
"{{price}}" is replaced with "1200".
"{{available}}" is not found in the data object, so it remains in the output.
Example 3 (Nested Data - if implemented):
Input:
templateString = "User email: {{user.email}}. City: {{user.address.city}}."
data = { user: { email: "test@example.com", address: { street: "123 Main St" } } }
Output:
"User email: test@example.com. City: {{user.address.city}}."
Explanation:
"{{user.email}}" is resolved successfully.
"{{user.address.city}}" is not fully resolved because "city" is missing from "user.address", so the placeholder remains.
Example 4 (Edge Case - Empty String):
Input:
templateString = ""
data = { name: "Bob" }
Output:
""
Explanation:
An empty template string results in an empty output string.
Constraints
- The
templateStringwill be a JavaScript string. - The
dataobject will be a JavaScript object. Keys will be strings. Values can be of any primitive type (string, number, boolean, null, undefined) or nested objects. - The parser should be reasonably efficient for strings of moderate length (e.g., up to a few thousand characters). A naive iterative approach is acceptable.
- The placeholder names will consist of alphanumeric characters and dots (for nested properties, if supported).
Notes
- Consider using regular expressions to find the placeholders.
- Be mindful of how different data types should be converted to strings.
- For nested properties, a helper function to safely access nested values from an object can be very useful.
- The challenge focuses on the core logic of parsing and replacement. Libraries like Handlebars or Mustache offer more robust templating features, but this exercise is about understanding the underlying mechanics.