Reliability
This commit is contained in:
259
README.md
Normal file
259
README.md
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
# Inkject
|
||||||
|
|
||||||
|
A lightweight, powerful JavaScript template engine with support for conditionals, variables, and nested data structures.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Zero dependencies** - Pure JavaScript implementation
|
||||||
|
- **Variable interpolation** with nested object support
|
||||||
|
- **Conditional rendering** with if/elseif/else logic
|
||||||
|
- **Inline conditionals** for compact templates
|
||||||
|
- **Nested conditionals** for complex logic
|
||||||
|
- **Customizable delimiters** - Use any delimiter you want
|
||||||
|
- **Clean syntax** - Easy to read and write templates
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Include the inkject class in your project
|
||||||
|
const inkject = require('inkject');
|
||||||
|
const renderer = new inkject();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const template = "Hello &name&! You have &messages& new messages.";
|
||||||
|
const data = {
|
||||||
|
name: "Alice",
|
||||||
|
messages: 5
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = renderer.render(template, data);
|
||||||
|
console.log(result); // "Hello Alice! You have 5 new messages."
|
||||||
|
```
|
||||||
|
|
||||||
|
## Syntax Reference
|
||||||
|
|
||||||
|
### Variable Interpolation
|
||||||
|
|
||||||
|
Access data using dot notation for nested objects:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const template = `
|
||||||
|
Welcome &user.name&!
|
||||||
|
Email: &user.profile.email&
|
||||||
|
Score: &stats.points&
|
||||||
|
`;
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
user: {
|
||||||
|
name: "John",
|
||||||
|
profile: { email: "john@example.com" }
|
||||||
|
},
|
||||||
|
stats: { points: 1250 }
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Delimiters
|
||||||
|
|
||||||
|
Change delimiters by passing a third parameter:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Using $$ as delimiters
|
||||||
|
renderer.render("Hello $$name$$", { name: "World" }, "$$$$");
|
||||||
|
// NOTE: It splits the delimiter string in two, so $$$$ means $$ for start and $$ for end
|
||||||
|
|
||||||
|
// Using different open/close delimiters
|
||||||
|
renderer.render("Hello {{name}}", { name: "World" }, "{{}}");
|
||||||
|
|
||||||
|
// Using triple delimiters
|
||||||
|
renderer.render("Hello $$$name$$$", { name: "World" }, "$$$$$$");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conditionals
|
||||||
|
|
||||||
|
#### Basic If/Else
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const template = `
|
||||||
|
&#if user.isActive&
|
||||||
|
Welcome back, &user.name&!
|
||||||
|
&#else&
|
||||||
|
Please activate your account.
|
||||||
|
&/if&
|
||||||
|
`;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### If/Elseif/Else Chains
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const template = `
|
||||||
|
&#if user.role === "admin"&
|
||||||
|
🔑 Administrator Access
|
||||||
|
&#elseif user.role === "manager"&
|
||||||
|
👔 Manager Access
|
||||||
|
&#else&
|
||||||
|
👤 Standard User
|
||||||
|
&/if&
|
||||||
|
`;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Inline Conditionals
|
||||||
|
|
||||||
|
Perfect for conditional text within sentences:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const template = `
|
||||||
|
You have &#if notifications > 0&¬ifications& new&#else&no&/if& notifications.
|
||||||
|
Status: &#if user.isActive&✅ Active&#else&❌ Inactive&/if&`;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Comparison Operators
|
||||||
|
|
||||||
|
Support for all common comparison operators:
|
||||||
|
|
||||||
|
- `===` - Strict equality
|
||||||
|
- `!==` - Strict inequality
|
||||||
|
- `==` - Loose equality
|
||||||
|
- `!=` - Loose inequality
|
||||||
|
- `>` - Greater than
|
||||||
|
- `<` - Less than
|
||||||
|
- `>=` - Greater than or equal
|
||||||
|
- `<=` - Less than or equal
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const template = `
|
||||||
|
&#if age >= 18&
|
||||||
|
You are an adult.
|
||||||
|
&#elseif age >= 13&
|
||||||
|
You are a teenager.
|
||||||
|
&#else&
|
||||||
|
You are a child.
|
||||||
|
&/if&`;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Negation
|
||||||
|
|
||||||
|
Use `!` to negate conditions:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const template = `
|
||||||
|
&#if !user.isSubscribed&
|
||||||
|
Subscribe now for premium features!
|
||||||
|
&/if&
|
||||||
|
`;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nested Conditionals
|
||||||
|
|
||||||
|
Create complex logic with nested conditions:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const template = `
|
||||||
|
&#if user.isActive&
|
||||||
|
Welcome, &user.name&!
|
||||||
|
&#if user.role === "admin"&
|
||||||
|
&#if company.employees > 100&
|
||||||
|
Managing large organization (&company.employees& employees)
|
||||||
|
&#else&
|
||||||
|
Managing small team (&company.employees& employees)
|
||||||
|
&/if&
|
||||||
|
&/if&
|
||||||
|
&/if&
|
||||||
|
`;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### User Dashboard
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const dashboardTemplate = `
|
||||||
|
=== USER DASHBOARD ===
|
||||||
|
|
||||||
|
Welcome, &user.name&!
|
||||||
|
|
||||||
|
&#if user.role === "admin"&
|
||||||
|
🔑 ADMIN ACCESS GRANTED
|
||||||
|
You have full system privileges.
|
||||||
|
|
||||||
|
&#if company.employees > 100&
|
||||||
|
📊 Large Company Management:
|
||||||
|
- Company: &&company.name&&
|
||||||
|
- Total Employees: &&company.employees&
|
||||||
|
&#else&
|
||||||
|
📊 Small Company Management:
|
||||||
|
- Company: &&company.name&&
|
||||||
|
- Team Size: &company.employees&
|
||||||
|
&/if&
|
||||||
|
|
||||||
|
&#elseif user.role === "manager"&
|
||||||
|
👔 MANAGER ACCESS
|
||||||
|
You can view team data and reports.
|
||||||
|
&#else&
|
||||||
|
👤 USER ACCESS
|
||||||
|
Limited access to personal data only.
|
||||||
|
&/if&
|
||||||
|
|
||||||
|
Account Status: &#if user.isActive&✅ Active&#else&❌ Inactive&/if&
|
||||||
|
`;
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
user: {
|
||||||
|
name: "Alice Johnson",
|
||||||
|
role: "admin",
|
||||||
|
isActive: true
|
||||||
|
},
|
||||||
|
company: {
|
||||||
|
name: "TechCorp",
|
||||||
|
employees: 150
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(renderer.render(dashboardTemplate, data));
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### `render(template, data, delimiter)`
|
||||||
|
|
||||||
|
Renders a template with the provided data.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `template` (string): The template string to render
|
||||||
|
- `data` (object): The data object containing variables
|
||||||
|
- `delimiter` (string, optional): Custom delimiter (default: '&&')
|
||||||
|
|
||||||
|
**Returns:** Rendered string
|
||||||
|
|
||||||
|
### Delimiter Rules
|
||||||
|
|
||||||
|
- **Even length**: Split in half for open/close (e.g., `{{}}` -> `{{` and `}}`)
|
||||||
|
- **Odd length**: Same delimiter for open/close (e.g., `$$$` -> `$$$` and `$$$`)
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
Inkject handles errors gracefully:
|
||||||
|
|
||||||
|
- **Missing variables**: Returns empty string
|
||||||
|
- **Undefined nested properties**: Returns empty string
|
||||||
|
- **Invalid conditions**: Evaluates to false
|
||||||
|
- **Malformed templates**: Processes what it can, leaves invalid syntax unchanged
|
||||||
|
|
||||||
|
## Performance Tips
|
||||||
|
|
||||||
|
1. **Reuse renderer instances** - Create one `inkject` instance and reuse it
|
||||||
|
2. **Simple conditions** - Complex JavaScript expressions aren't supported
|
||||||
|
3. **Avoid deep nesting** - Keep conditional nesting reasonable for readability
|
||||||
|
4. **Cache templates** - Store frequently used templates in variables
|
||||||
|
|
||||||
|
## Browser Compatibility
|
||||||
|
|
||||||
|
Works in all modern browsers and Node.js environments. No transpilation required.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License - feel free to use in your projects!
|
||||||
|
|
||||||
|
---
|
||||||
216
inkject.js
216
inkject.js
@@ -1,14 +1,9 @@
|
|||||||
class inkject {
|
class inkject {
|
||||||
render(template, data = {}, delimiter = '&&') {
|
render(template, data = {}, delimiter = '&&') {
|
||||||
const [openDelim, closeDelim] = this.parseDelimiter(delimiter);
|
const [openDelim, closeDelim] = this.parseDelimiter(delimiter);
|
||||||
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
||||||
const openPattern = escapeRegex(openDelim);
|
|
||||||
const closePattern = escapeRegex(closeDelim);
|
|
||||||
|
|
||||||
let result = template;
|
let result = template;
|
||||||
result = this.processConditionals(result, data, openPattern, closePattern);
|
result = this.processConditionals(result, data, openDelim, closeDelim);
|
||||||
result = this.processVariables(result, data, openPattern, closePattern);
|
result = this.processVariables(result, data, openDelim, closeDelim);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,65 +17,194 @@ class inkject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processConditionals(template, data, openPattern, closePattern) {
|
processConditionals(template, data, openDelim, closeDelim) {
|
||||||
const conditionalRegex = new RegExp(
|
let result = template;
|
||||||
`${openPattern}#if\\s+([^${closePattern.charAt(0)}]+?)${closePattern}([\\s\\S]*?)(?:${openPattern}#elseif\\s+([^${closePattern.charAt(0)}]+?)${closePattern}([\\s\\S]*?))*(?:${openPattern}#else${closePattern}([\\s\\S]*?))?${openPattern}/if${closePattern}`,
|
let changed = true;
|
||||||
'g'
|
|
||||||
);
|
|
||||||
|
|
||||||
return template.replace(conditionalRegex, (fullMatch) => {
|
while (changed) {
|
||||||
return this.processComplexConditional(fullMatch, data, openPattern, closePattern);
|
changed = false;
|
||||||
});
|
const match = this.findInnermostConditional(result, openDelim, closeDelim);
|
||||||
|
if (match) {
|
||||||
|
const replacement = this.evaluateConditionalBlock(match.content, data, openDelim, closeDelim);
|
||||||
|
const beforeMatch = result.slice(0, match.start);
|
||||||
|
const afterMatch = result.slice(match.end);
|
||||||
|
|
||||||
|
const isInline = this.isInlineConditional(beforeMatch, afterMatch, match.content);
|
||||||
|
|
||||||
|
if (isInline) {
|
||||||
|
result = beforeMatch + replacement + afterMatch;
|
||||||
|
} else {
|
||||||
|
let cleanedReplacement = replacement.trim();
|
||||||
|
let cleanedBefore = beforeMatch;
|
||||||
|
let cleanedAfter = afterMatch;
|
||||||
|
|
||||||
|
if (cleanedReplacement === '') {
|
||||||
|
if (cleanedBefore.endsWith('\n')) {
|
||||||
|
cleanedBefore = cleanedBefore.slice(0, -1);
|
||||||
|
}
|
||||||
|
if (cleanedAfter.startsWith('\n')) {
|
||||||
|
cleanedAfter = cleanedAfter.slice(1);
|
||||||
|
}
|
||||||
|
result = cleanedBefore + cleanedAfter;
|
||||||
|
} else {
|
||||||
|
const needsNewlineBefore = cleanedBefore.length > 0 && !cleanedBefore.endsWith('\n') && cleanedReplacement.length > 0;
|
||||||
|
const needsNewlineAfter = cleanedAfter.length > 0 && !cleanedAfter.startsWith('\n') && cleanedReplacement.length > 0;
|
||||||
|
|
||||||
|
result = cleanedBefore +
|
||||||
|
(needsNewlineBefore ? '\n' : '') +
|
||||||
|
cleanedReplacement +
|
||||||
|
(needsNewlineAfter ? '\n' : '') +
|
||||||
|
cleanedAfter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processComplexConditional(match, data, openPattern, closePattern) {
|
return result;
|
||||||
const blocks = [];
|
|
||||||
const ifMatch = new RegExp(`${openPattern}#if\\s+([^${closePattern.charAt(0)}]+?)${closePattern}`).exec(match);
|
|
||||||
if (ifMatch) {
|
|
||||||
blocks.push({ type: 'if', condition: ifMatch[1].trim() });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const elseifRegex = new RegExp(`${openPattern}#elseif\\s+([^${closePattern.charAt(0)}]+?)${closePattern}`, 'g');
|
isInlineConditional(beforeMatch, afterMatch, conditionalContent) {
|
||||||
let elseifMatch;
|
const beforeLastNewline = beforeMatch.lastIndexOf('\n');
|
||||||
while ((elseifMatch = elseifRegex.exec(match)) !== null) {
|
const afterFirstNewline = afterMatch.indexOf('\n');
|
||||||
blocks.push({ type: 'elseif', condition: elseifMatch[1].trim() });
|
|
||||||
|
const beforeText = beforeLastNewline === -1 ? beforeMatch : beforeMatch.slice(beforeLastNewline + 1);
|
||||||
|
const afterText = afterFirstNewline === -1 ? afterMatch : afterMatch.slice(0, afterFirstNewline);
|
||||||
|
|
||||||
|
const hasContentBefore = beforeText.trim().length > 0;
|
||||||
|
const hasContentAfter = afterText.trim().length > 0;
|
||||||
|
|
||||||
|
const conditionalHasNewlines = conditionalContent.includes('\n');
|
||||||
|
|
||||||
|
return (hasContentBefore || hasContentAfter) && !conditionalHasNewlines;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match.includes(`${this.unescapeRegex(openPattern)}#else${this.unescapeRegex(closePattern)}`)) {
|
findInnermostConditional(template, openDelim, closeDelim) {
|
||||||
blocks.push({ type: 'else' });
|
const ifPattern = openDelim + '#if ';
|
||||||
|
const endifPattern = openDelim + '/if' + closeDelim;
|
||||||
|
|
||||||
|
let deepestIf = null;
|
||||||
|
let maxDepth = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < template.length; i++) {
|
||||||
|
if (template.substr(i, ifPattern.length) === ifPattern) {
|
||||||
|
let depth = 0;
|
||||||
|
let currentPos = i;
|
||||||
|
let foundMatching = false;
|
||||||
|
|
||||||
|
while (currentPos < template.length) {
|
||||||
|
if (template.substr(currentPos, ifPattern.length) === ifPattern) {
|
||||||
|
depth++;
|
||||||
|
currentPos += ifPattern.length;
|
||||||
|
} else if (template.substr(currentPos, endifPattern.length) === endifPattern) {
|
||||||
|
depth--;
|
||||||
|
if (depth === 0) {
|
||||||
|
if (!foundMatching || depth >= maxDepth) {
|
||||||
|
let hasNestedIf = false;
|
||||||
|
const blockContent = template.slice(i + ifPattern.length, currentPos);
|
||||||
|
if (blockContent.indexOf(ifPattern) !== -1) {
|
||||||
|
hasNestedIf = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = this.extractConditionalContent(match, openPattern, closePattern, blocks);
|
if (!hasNestedIf) {
|
||||||
|
deepestIf = {
|
||||||
|
start: i,
|
||||||
|
end: currentPos + endifPattern.length,
|
||||||
|
content: template.slice(i, currentPos + endifPattern.length)
|
||||||
|
};
|
||||||
|
maxDepth = depth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foundMatching = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentPos += endifPattern.length;
|
||||||
|
} else {
|
||||||
|
currentPos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < blocks.length; i++) {
|
return deepestIf;
|
||||||
const block = blocks[i];
|
}
|
||||||
if (block.type === 'else' || this.evaluateCondition(block.condition, data)) {
|
|
||||||
return content[i] || '';
|
evaluateConditionalBlock(block, data, openDelim, closeDelim) {
|
||||||
|
const sections = this.parseConditionalSections(block, openDelim, closeDelim);
|
||||||
|
|
||||||
|
for (const section of sections) {
|
||||||
|
if (section.type === 'else' || this.evaluateCondition(section.condition, data)) {
|
||||||
|
return section.content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
extractConditionalContent(match, openPattern, closePattern, blocks) {
|
parseConditionalSections(block, openDelim, closeDelim) {
|
||||||
const unescapedOpen = this.unescapeRegex(openPattern);
|
const sections = [];
|
||||||
const unescapedClose = this.unescapeRegex(closePattern);
|
|
||||||
|
|
||||||
const parts = match.split(new RegExp(`${openPattern}(?:#(?:if|elseif|else)|/if)(?:\\s+[^${closePattern.charAt(0)}]*?)?${closePattern}`));
|
const ifRegex = new RegExp(`^${this.escapeRegex(openDelim)}#if\\s+([^${this.escapeRegex(closeDelim)}]+)${this.escapeRegex(closeDelim)}`);
|
||||||
return parts.slice(1, -1);
|
const elseifRegex = new RegExp(`${this.escapeRegex(openDelim)}#elseif\\s+([^${this.escapeRegex(closeDelim)}]+)${this.escapeRegex(closeDelim)}`, 'g');
|
||||||
|
const elseRegex = new RegExp(`${this.escapeRegex(openDelim)}#else${this.escapeRegex(closeDelim)}`);
|
||||||
|
const endifRegex = new RegExp(`${this.escapeRegex(openDelim)}/if${this.escapeRegex(closeDelim)}$`);
|
||||||
|
|
||||||
|
const ifMatch = block.match(ifRegex);
|
||||||
|
if (!ifMatch) return sections;
|
||||||
|
|
||||||
|
let content = block.replace(ifRegex, '').replace(endifRegex, '');
|
||||||
|
let pos = 0;
|
||||||
|
let currentCondition = ifMatch[1].trim();
|
||||||
|
let currentType = 'if';
|
||||||
|
|
||||||
|
const elseifMatches = [];
|
||||||
|
let elseifMatch;
|
||||||
|
while ((elseifMatch = elseifRegex.exec(content)) !== null) {
|
||||||
|
elseifMatches.push({
|
||||||
|
index: elseifMatch.index,
|
||||||
|
condition: elseifMatch[1].trim(),
|
||||||
|
fullMatch: elseifMatch[0]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
unescapeRegex(str) {
|
const elseMatch = content.match(elseRegex);
|
||||||
return str.replace(/\\(.)/g, '$1');
|
const elsePos = elseMatch ? content.search(elseRegex) : -1;
|
||||||
|
|
||||||
|
const allBreakpoints = [
|
||||||
|
...elseifMatches.map(m => ({ pos: m.index, type: 'elseif', condition: m.condition, length: m.fullMatch.length })),
|
||||||
|
...(elsePos !== -1 ? [{ pos: elsePos, type: 'else', condition: null, length: elseMatch[0].length }] : [])
|
||||||
|
].sort((a, b) => a.pos - b.pos);
|
||||||
|
|
||||||
|
for (let i = 0; i <= allBreakpoints.length; i++) {
|
||||||
|
const start = i === 0 ? 0 : allBreakpoints[i - 1].pos + allBreakpoints[i - 1].length;
|
||||||
|
const end = i === allBreakpoints.length ? content.length : allBreakpoints[i].pos;
|
||||||
|
|
||||||
|
const sectionContent = content.slice(start, end);
|
||||||
|
|
||||||
|
sections.push({
|
||||||
|
type: currentType,
|
||||||
|
condition: currentCondition,
|
||||||
|
content: sectionContent
|
||||||
|
});
|
||||||
|
|
||||||
|
if (i < allBreakpoints.length) {
|
||||||
|
currentType = allBreakpoints[i].type;
|
||||||
|
currentCondition = allBreakpoints[i].condition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processVariables(template, data, openPattern, closePattern) {
|
return sections;
|
||||||
const varRegex = new RegExp(`${openPattern}([^#/][^${closePattern.charAt(0)}]*?)${closePattern}`, 'g');
|
}
|
||||||
|
|
||||||
|
processVariables(template, data, openDelim, closeDelim) {
|
||||||
|
const openPattern = this.escapeRegex(openDelim);
|
||||||
|
const closePattern = this.escapeRegex(closeDelim);
|
||||||
|
const varRegex = new RegExp(`${openPattern}([^#/][^${closePattern.slice(-1)}]*)${closePattern}`, 'g');
|
||||||
|
|
||||||
return template.replace(varRegex, (match, variable) => {
|
return template.replace(varRegex, (match, variable) => {
|
||||||
const value = this.getValue(variable.trim(), data);
|
const value = this.getValue(variable.trim(), data);
|
||||||
return value !== undefined ? String(value) : '';
|
return value !== undefined ? String(value) : '';
|
||||||
});
|
}).replace(/\n\s*\n\s*\n/g, '\n\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluateCondition(condition, data) {
|
evaluateCondition(condition, data) {
|
||||||
@@ -94,8 +218,10 @@ class inkject {
|
|||||||
|
|
||||||
const operators = ['===', '!==', '==', '!=', '>=', '<=', '>', '<'];
|
const operators = ['===', '!==', '==', '!=', '>=', '<=', '>', '<'];
|
||||||
for (const op of operators) {
|
for (const op of operators) {
|
||||||
if (condition.includes(op)) {
|
const opIndex = condition.indexOf(op);
|
||||||
const [left, right] = condition.split(op).map(s => s.trim());
|
if (opIndex !== -1) {
|
||||||
|
const left = condition.slice(0, opIndex).trim();
|
||||||
|
const right = condition.slice(opIndex + op.length).trim();
|
||||||
const leftValue = this.getValue(left, data);
|
const leftValue = this.getValue(left, data);
|
||||||
const rightValue = this.parseValue(right);
|
const rightValue = this.parseValue(right);
|
||||||
|
|
||||||
@@ -149,6 +275,10 @@ class inkject {
|
|||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
escapeRegex(str) {
|
||||||
|
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = inkject;
|
module.exports = inkject;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "inkject",
|
"name": "inkject",
|
||||||
"version": "1.0.0",
|
"version": "1.1.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "inkject.js",
|
"main": "inkject.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user