Pull to refresh

JSTE — как я писал свою версию EJS

Началось все с того, что я решил выучить PHP, а что из этого вышло — смотрите ниже.


После прочтения уроков по php, я захотел написать свой шаблонизатор для Express с синтаксисом очень похожим на php.


Идея моей реализации простая — на место html подставлять функцию, при выполнение которой на экран будет добавлен этот htm, в качестве аргументов этой функции передавать тот код, который встраивается в специальных inline блоках (<?=, ?>) в html, которые в свою очередь встраивают javascript значения в html. А весь остальной код собирать в один файл и при рендеринге скармливать интерпретатору.Выдумывать синтаксис не стал, взял из php заменив лишь <?php на <?js. Код
этого шаблонизатора ужасен для прочтения — на всякий случай, имя встраиваемых функций начинаются тремя символами долларов, чередующихся с пробелом ($_$_$_code001_$_$_$).
Те, кому стало интересно могут заглянуть под спойлер.


Осторожно: страшный код
const fs = require('fs');

const jsAll = /<\?js\s+([\S\s]*?)\s+\?>/mg;
const jsInject = /<\?=\s*([\S\s]*?)\s*\?>/mg;

function read(path) {
    return fs.readFileSync(path,'utf-8');
}

function evalute(noncode) {
    let noncodes = noncode.replace(jsInject,'$%&').split('$%&').filter(function(i){return i});
    let evals = noncode.match(jsInject);
    let evs = [];
    let evrs = [];
    let fnoncode = '';
    for(c in noncodes){
        fnoncode+=noncodes[c];
        if(c < noncodes.length-1){
            fnoncode += "$_$_$_"+evals[c].replace('<?=','').replace('?>','')+"_$_$_$";
            evs.push("$_$_$_"+evals[c].replace('<?=','').replace('?>','')+"_$_$_$");
            evrs.push(""+evals[c].replace('<?=','').replace('?>','')+"");
        }
    }
    return [fnoncode,evrs,evs];
}

function parse(text,document) {
    documen = {
        write:function (txt, arn, args) {
            for (an in arn){
                txt = txt.replace(arn[an],args[an]);
            }
            document.write(txt);
    }};
    let codes = text.match(jsAll);
    let noncode = text.replace(jsAll,'$%&');
    let fcode = '';
    let $_$_$_fcs_$_$_$ = {};

    let prevdata = noncode.shift();
    let qrt = evalute(prevdata);
    fcode+="$_$_$_fcs_$_$_$['$_$_$_code"+"prev"+"_$_$_$'](["+qrt[1].join(',')+"]);\n";
    $_$_$_fcs_$_$_$["$_$_$_code"+"prev"+"_$_$_$"]=function(txt,arn){return function(args){documen.write(txt,arn,args)}};
    $_$_$_fcs_$_$_$["$_$_$_code"+"prev"+"_$_$_$"]=$_$_$_fcs_$_$_$["$_$_$_code"+"prev"+"_$_$_$"](qrt[0],qrt[2]);

    for(c in codes){
        fcode+=codes[c].replace('<?js','').replace('?>','');
        if(c < codes.length-1){
            let qrt = evalute(noncode.shift());
            fcode+="$_$_$_fcs_$_$_$['$_$_$_code"+c+"_$_$_$'](["+qrt[1].join(',')+"]);\n";
            $_$_$_fcs_$_$_$["$_$_$_code"+c+"_$_$_$"]=function(txt,arn){return function(args){documen.write(txt,arn,args)}};
            $_$_$_fcs_$_$_$["$_$_$_code"+c+"_$_$_$"]=$_$_$_fcs_$_$_$["$_$_$_code"+c+"_$_$_$"](qrt[0],qrt[2]);
        }
    }
    if(noncode.length>0){
        let postdata = noncode.join('\n');
        let qrt = evalute(postdata);
        fcode+="$_$_$_fcs_$_$_$['$_$_$_code"+"post"+"_$_$_$'](["+qrt[1].join(',')+"]);\n";
        $_$_$_fcs_$_$_$["$_$_$_code"+"post"+"_$_$_$"]=function(txt,arn){return function(args){documen.write(txt,arn,args)}};
        $_$_$_fcs_$_$_$["$_$_$_code"+"post"+"_$_$_$"]=$_$_$_fcs_$_$_$["$_$_$_code"+"post"+"_$_$_$"](qrt[0],qrt[2]);
    }
    return function () {
        eval(fcode);
    }
}

С написанием песочницы проблем не возникло. Быстро собрав браузерную версию кода, написал страничку, которую затем опубликовал на git pages. С подсветкой синтаксиса тоже не было проблем — благо синтаксис моего шаблонизатора мало чем отличается от php и html.


Напоследок оставлю ссылки на небольшую документацию, NPM и пару примеров. Работы еще много, в планах написать плагины для InteliJ и других редакторов, доработать документацию и сделать хотя бы пару сайтов для примера. Но надеюсь что сообщество оценит мой труд (желательно положительно). Об ошибках и предложениях пишите в комментариях, с радостью отвечу на все.

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.