Skip to content

Instantly share code, notes, and snippets.

@ajs139
Created March 28, 2019 16:17
Show Gist options
  • Save ajs139/f84ccbe5678ef1497a53965cc326b452 to your computer and use it in GitHub Desktop.
Save ajs139/f84ccbe5678ef1497a53965cc326b452 to your computer and use it in GitHub Desktop.
export const extract = (text: string): Object => {
const re = /\{+\s*(.*?)\s*\}+/g;
const tags: any[] = [];
let matches;
while (Boolean((matches = re.exec(text)))) {
if (matches) {
tags.push(matches[1]);
}
}
const root: any = {};
let context: any = root;
const stack: any[] = [];
const setVar = (variable: string, val: any) => {
const numLevelsUp = (variable.match(/\\.\\./g) || []).length;
if (numLevelsUp) {
const v = variable.split('/').pop();
const c = stack[stack.length - numLevelsUp];
if (c && v) {
c[v] = val;
}
} else {
context[variable] = val;
}
};
for (var tag of tags) {
if (tag.startsWith('! ')) {
continue;
}
if (tag == 'else') {
continue;
}
if ('#^'.includes(tag[0]) && !tag.includes(' ')) {
setVar(tag.substr(1), true);
stack.push(context);
continue;
}
if (tag.startsWith('#if')) {
const vars = tag.split(' ').slice(1);
for (const v of vars) {
setVar(v, true);
}
stack.push(context);
continue;
}
if (tag.startsWith('/if')) {
context = stack.pop();
continue;
}
if (tag.startsWith('#with ')) {
const v = tag.split(' ')[1];
var newContext = {};
context[v] = newContext;
stack.push(context);
context = newContext;
continue;
}
if (tag.startsWith('/with')) {
context = stack.pop();
continue;
}
if (tag.startsWith('#unless ')) {
const v = tag.split(' ')[1];
setVar(v, true);
stack.push(context);
continue;
}
if (tag.startsWith('/unless')) {
context = stack.pop();
continue;
}
if (tag.startsWith('#each ')) {
const v = tag.split(' ')[1];
const newContext = {};
context[v] = [newContext];
stack.push(context);
context = newContext;
continue;
}
if (tag.startsWith('/each')) {
context = stack.pop();
continue;
}
if (tag.startsWith('/')) {
context = stack.pop();
continue;
}
setVar(tag, '');
}
var cleanThis = (obj: any): any => {
if (Array.isArray(obj)) {
const acc = [];
for (var item of obj) {
acc.push(cleanThis(item));
}
return acc;
}
if (typeof obj == 'object' && obj.constructor == Object) {
if (Object.keys(obj).length == 1 && obj.hasOwnProperty('this')) {
return cleanThis(obj['this']);
}
const acc: any = {};
for (var [k, v] of Object.entries(obj)) {
acc[k] = cleanThis(v);
}
return acc;
}
return obj;
};
return cleanThis(root);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment