Skip to content

Instantly share code, notes, and snippets.

@ialex32x
Created June 15, 2021 05:30
Show Gist options
  • Select an option

  • Save ialex32x/c16055d1619e1418b98155de25d33c07 to your computer and use it in GitHub Desktop.

Select an option

Save ialex32x/c16055d1619e1418b98155de25d33c07 to your computer and use it in GitHub Desktop.

Revisions

  1. ialex32x created this gist Jun 15, 2021.
    174 changes: 174 additions & 0 deletions vue_parsetext.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,174 @@

    var validDivisionCharRE = /[\w).+\-_$\]]/;

    function parseFilters(exp) {
    var inSingle = false;
    var inDouble = false;
    var inTemplateString = false;
    var inRegex = false;
    var curly = 0;
    var square = 0;
    var paren = 0;
    var lastFilterIndex = 0;
    var c, prev, i, expression, filters;

    for (i = 0; i < exp.length; i++) {
    prev = c;
    c = exp.charCodeAt(i);
    if (inSingle) {
    if (c === 0x27 && prev !== 0x5C) { inSingle = false; }
    } else if (inDouble) {
    if (c === 0x22 && prev !== 0x5C) { inDouble = false; }
    } else if (inTemplateString) {
    if (c === 0x60 && prev !== 0x5C) { inTemplateString = false; }
    } else if (inRegex) {
    if (c === 0x2f && prev !== 0x5C) { inRegex = false; }
    } else if (
    c === 0x7C && // pipe
    exp.charCodeAt(i + 1) !== 0x7C &&
    exp.charCodeAt(i - 1) !== 0x7C &&
    !curly && !square && !paren
    ) {
    if (expression === undefined) {
    // first filter, end of expression
    lastFilterIndex = i + 1;
    expression = exp.slice(0, i).trim();
    } else {
    pushFilter();
    }
    } else {
    switch (c) {
    case 0x22: inDouble = true; break // "
    case 0x27: inSingle = true; break // '
    case 0x60: inTemplateString = true; break // `
    case 0x28: paren++; break // (
    case 0x29: paren--; break // )
    case 0x5B: square++; break // [
    case 0x5D: square--; break // ]
    case 0x7B: curly++; break // {
    case 0x7D: curly--; break // }
    }
    if (c === 0x2f) { // /
    var j = i - 1;
    var p = (void 0);
    // find first non-whitespace prev char
    for (; j >= 0; j--) {
    p = exp.charAt(j);
    if (p !== ' ') { break }
    }
    if (!p || !validDivisionCharRE.test(p)) {
    inRegex = true;
    }
    }
    }
    }

    if (expression === undefined) {
    expression = exp.slice(0, i).trim();
    } else if (lastFilterIndex !== 0) {
    pushFilter();
    }

    function pushFilter() {
    (filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim());
    lastFilterIndex = i + 1;
    }

    if (filters) {
    for (i = 0; i < filters.length; i++) {
    expression = wrapFilter(expression, filters[i]);
    }
    }

    return expression
    }

    function wrapFilter(exp, filter) {
    var i = filter.indexOf('(');
    if (i < 0) {
    // _f: resolveFilter
    return ("_f(\"" + filter + "\")(" + exp + ")")
    } else {
    var name = filter.slice(0, i);
    var args = filter.slice(i + 1);
    return ("_f(\"" + name + "\")(" + exp + (args !== ')' ? ',' + args : args))
    }
    }

    var defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g;
    var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g;

    /**
    * Create a cached version of a pure function.
    */
    function cached(fn) {
    var cache = Object.create(null);
    return (function cachedFn(str) {
    var hit = cache[str];
    return hit || (cache[str] = fn(str))
    })
    }

    var buildRegex = cached(function (delimiters) {
    var open = delimiters[0].replace(regexEscapeRE, '\\$&');
    var close = delimiters[1].replace(regexEscapeRE, '\\$&');
    return new RegExp(open + '((?:.|\\n)+?)' + close, 'g')
    });



    function parseText(
    text,
    delimiters
    ) {
    var tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE;
    if (!tagRE.test(text)) {
    console.error(tagRE, text);
    return
    }
    var tokens = [];
    var rawTokens = [];
    var lastIndex = tagRE.lastIndex = 0;
    var match, index, tokenValue;
    while ((match = tagRE.exec(text))) {
    index = match.index;
    // push text token
    if (index > lastIndex) {
    rawTokens.push(tokenValue = text.slice(lastIndex, index));
    tokens.push(JSON.stringify(tokenValue));
    }
    // tag token
    var exp = parseFilters(match[1].trim());
    tokens.push(("_s(" + exp + ")"));
    rawTokens.push({ '@binding': exp });
    lastIndex = index + match[0].length;
    }
    if (lastIndex < text.length) {
    rawTokens.push(tokenValue = text.slice(lastIndex));
    tokens.push(JSON.stringify(tokenValue));
    }
    return {
    expression: tokens.join('+'),
    tokens: rawTokens
    }
    }

    function fn() {
    return 1;
    }

    function test() {
    return "hello";
    }

    let name = "Emma";

    let res = parseText("TEST {{1 + 1/2 * fn()}} WITH {{test()}} AND {{name}} Self {{self.name}}", null);
    console.log(res.expression);

    (function () {
    let name = "Jill";
    let self = { name: "(self test)" };
    let e = eval("(function (_s) { return " + res.expression + "; })");
    console.log(e((v) => new String(v)));
    })();