Created
March 28, 2019 16:17
-
-
Save ajs139/f84ccbe5678ef1497a53965cc326b452 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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