From de9567a36a6fdc265272d1a6fb89f8c7a2621750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdussamed=20ULUTA=C5=9E?= Date: Tue, 25 Oct 2022 01:00:01 +0300 Subject: [PATCH] First commit --- .gitignore | 2 + Processor/File.js | 44 +++++ Processor/Parse.js | 347 +++++++++++++++++++++++++++++++++++++ init.js | 14 ++ package.json | 14 ++ source/abc.blade.php | 14 ++ source/abc.blade.php.cache | Bin 0 -> 872 bytes source/abc.blade.php.js | 5 + target/abc.html | 14 ++ test.js | 15 ++ 10 files changed, 469 insertions(+) create mode 100644 .gitignore create mode 100644 Processor/File.js create mode 100644 Processor/Parse.js create mode 100644 init.js create mode 100644 package.json create mode 100644 source/abc.blade.php create mode 100644 source/abc.blade.php.cache create mode 100644 source/abc.blade.php.js create mode 100644 target/abc.html create mode 100644 test.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..25c8fdb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +package-lock.json \ No newline at end of file diff --git a/Processor/File.js b/Processor/File.js new file mode 100644 index 0000000..371c523 --- /dev/null +++ b/Processor/File.js @@ -0,0 +1,44 @@ +let parser = require("./Parse"); +let crypto = require("node:crypto"); +let vm = require("node:vm"); + +module.exports = File; +/** + * @class File + */ +function File() +{ + this.content = ""; + this.contentmd5 = ""; + this.parsedContent = ""; + this.cachedData = undefined; +}; + + +function sha256(content) +{ + return crypto.createHash("sha256").update(content,'utf-8').digest('hex'); +} + +File.prototype.build = function(){ + this.contentmd5 = sha256(this.content); + this.parsedContent = parser(this); +}; + +File.prototype.isRequiredRebuild = function(content){ + return this.contentmd5 == sha256(content); +}; +File.prototype.execute = function(memoriable){ + let output = []; + let t = new vm.Script(this.parsedContent,{ + cachedData: this.cachedData, + }); + let content = vm.createContext({ + ...memoriable, + output, + echo:(...args) => output.push(...args) + }); + t.runInContext(content); + this.cachedData = t.createCachedData(); + return output.join(''); +}; \ No newline at end of file diff --git a/Processor/Parse.js b/Processor/Parse.js new file mode 100644 index 0000000..dddf075 --- /dev/null +++ b/Processor/Parse.js @@ -0,0 +1,347 @@ +let Hemex = require("@saqut/hemex"); +const File = require("./File"); +/** + * @param {File} file + */ +function ParseEngine(file) +{ + let content = []; + let buffer = []; + let hmx = new Hemex(); + hmx.setText(file.content); + function flushBuffer() + { + if(buffer.length) + { + content.push({ + type:'text', + value: buffer.join('') + }); + } + buffer=[]; + } + hmx.addLexer({ + name: "scope" + },()=>{ + hmx.while(()=>{ + if(hmx.include('{{')) + { + let doubleBrackContent = hmx.gather('double-brack'); + flushBuffer(); + content.push({ + type:'js-value', + value: doubleBrackContent + }); + return true; + }; + if(hmx.include('@{')) + { + let jsBlockContent = hmx.gather('js-block'); + flushBuffer(); + content.push({ + type:'js-block', + value: jsBlockContent + }); + return true; + }; + if(hmx.include('@if(')) + { + let jsStatement = hmx.gather('js-if-block'); + flushBuffer(); + content.push({ + type:'js-if-block', + value: jsStatement + }); + return true; + }; + if(hmx.include('@endif', true)) + { + flushBuffer(); + content.push({ + type:'js-end-block' + }); + return true; + }; + if(hmx.include('@for(')) + { + let jsStatement = hmx.gather('js-for-block'); + flushBuffer(); + content.push({ + type:'js-for-block', + value: jsStatement + }); + return true; + }; + if(hmx.include('@import(', true)) + { + let importedThing = hmx.gather('import'); + flushBuffer(); + content.push({ + type:'import', + value: importedThing + }); + return true; + }; + if(hmx.include('@endfor', true)) + { + flushBuffer(); + content.push({ + type:'js-end-block' + }); + return true; + }; + buffer.push(hmx.getChar()); + hmx.nextChar(); + return true; + }); + flushBuffer(); + }); + hmx.addLexer({ + name: "js-block" + },() => { + hmx.beginPosition(); + if(hmx.include('@{')) + { + hmx.toChar(+2); + }; + let script = hmx.gather('readjscontent','}'); + if(hmx.include('}')) + { + hmx.toChar(+1); + }; + hmx.acceptPosition(); + return script; + }) + + hmx.addLexer({ + name: "double-brack" + },()=>{ + hmx.beginPosition(); + if(hmx.include('{{')) + { + hmx.toChar(+2); + }; + let jsContent = hmx.gather('readjscontent', '}}'); + if(hmx.include('}}')) + { + hmx.toChar(+2); + }; + hmx.acceptPosition(); + return jsContent; + }); + + hmx.addLexer({ + name: "import" + },()=>{ + hmx.beginPosition(); + if(hmx.include('@import(')) + { + hmx.toChar(+8); + }; + let jsContent = hmx.gather('readjscontent',')'); + if(hmx.include(')')) + { + hmx.toChar(+1); + }; + hmx.acceptPosition(); + return jsContent; + }); + + hmx.addLexer({ + name: "js-if-block" + },()=>{ + hmx.beginPosition(); + if(hmx.include('@if(')) + { + hmx.toChar(+4); + }; + let jsContent = hmx.gather('readjscontent', ')'); + if(hmx.include(')')) + { + hmx.toChar(+2); + }; + hmx.acceptPosition(); + return jsContent; + }); + hmx.addLexer({ + name: "js-for-block" + },()=>{ + hmx.beginPosition(); + if(hmx.include('@for(')) + { + hmx.toChar(+5); + }; + let jsContent = hmx.gather('readjscontent', ')'); + if(hmx.include(')')) + { + hmx.toChar(+1); + }; + hmx.acceptPosition(); + return jsContent; + }); + hmx.addLexer({ + name: "readjscontent" + },(hmx, content)=>{ + hmx.beginPosition(); + let scopeLevel = 0; + hmx.while(()=>{ + if(scopeLevel == 0) + { + if(content == null) + { + if(hmx.isWhiteSpace()) + { + return false; + } + }else if(hmx.include(content)) + { + return false; + } + } + switch(hmx.getChar()) + { + case '{':{ + scopeLevel++; + hmx.nextChar(); + return true; + } + case '(':{ + scopeLevel++; + hmx.nextChar(); + return true; + } + case '}':{ + scopeLevel = Math.max(scopeLevel - 1, 0); + hmx.nextChar(); + return true; + } + case ')':{ + scopeLevel = Math.max(scopeLevel - 1, 0); + hmx.nextChar(); + return true; + } + case '/':{ + if(hmx.include('//')) + throw new Error("Çift parantezlerde yorum satırı kullanılamaz") + else hmx.gather('skip-regex-content'); + return true; + } + case '\'': + case '"': + case '`':{ + hmx.gather('skip-string-content',hmx.getChar()); + return true; + } + default:{ + hmx.nextChar(); + return true; + } + }; + }); + let jscontent = hmx.getPositionRange(); + hmx.acceptPosition(); + return jscontent; + }); + hmx.addLexer({ + name: "skip-string-content" + },(hmx, char)=>{ + hmx.beginPosition(); + if(hmx.isChar(char)) + { + hmx.nextChar(); + } + hmx.while(()=>{ + switch(hmx.getChar()) + { + case '\\':{ + hmx.nextChar(); + hmx.nextChar(); + return true; + } + case char:{ + hmx.nextChar(); + return; + } + default:{ + hmx.nextChar(); + return true; + } + }; + }); + hmx.acceptPosition(); + }); + hmx.addLexer({ + name: "skip-regex-content" + },()=>{ + hmx.beginPosition(); + if(hmx.isChar('/')) + { + hmx.nextChar(); + }; + hmx.while(()=>{ + switch(hmx.getChar()) + { + case '\\':{ + hmx.nextChar(); + hmx.nextChar(); + return true; + } + case '/':{ + hmx.nextChar(); + return false; + } + default:{ + return true; + } + }; + }); + hmx.acceptPosition(); + }); + hmx.gather('scope'); + function useAST(content) + { + let jsContent = []; + for (const { + type, + value + } of content) switch(type) + { + case "js-value":{ + jsContent.push(`output.push(${value});\n`); + break; + } + case "js-block":{ + jsContent.push(`\n${value}\n`); + break; + } + case "text":{ + jsContent.push(`output.push(${JSON.stringify(value)});\n`); + break; + } + case "import":{ + jsContent.push(`output.push(${JSON.stringify(``)});\n`); + break; + } + case "js-if-block":{ + jsContent.push(`if(${value}){\n`); + break; + } + case "js-for-block":{ + jsContent.push(`for(${value}){\n`); + break; + } + case "js-endif-block":{ + jsContent.push(`if(${value}){\n`); + break; + } + case "js-end-block":{ + jsContent.push(`\n};\n`); + break; + } + } + return jsContent.join(''); + } + return useAST(content); +}; + +module.exports = ParseEngine; \ No newline at end of file diff --git a/init.js b/init.js new file mode 100644 index 0000000..b3e59b9 --- /dev/null +++ b/init.js @@ -0,0 +1,14 @@ +const { readFile } = require("node:fs/promises"); +let {resolve} = require("node:path"); + +let File = require("./Processor/File"); + +exports.processFile = async path => { + let absolute = resolve(path); + let content = await readFile(absolute,"utf8"); + let file = new File(); + file.content = content; + file.build(); + return file; +}; + diff --git a/package.json b/package.json new file mode 100644 index 0000000..cdb823d --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "razorblade", + "version": "1.0.0", + "description": "", + "main": "test.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@saqut/hemex": "^0.7.2" + } +} diff --git a/source/abc.blade.php b/source/abc.blade.php new file mode 100644 index 0000000..863c821 --- /dev/null +++ b/source/abc.blade.php @@ -0,0 +1,14 @@ + + + + + + + + {{ "Merhaba" }} + + + + @import("merhaba") + + \ No newline at end of file diff --git a/source/abc.blade.php.cache b/source/abc.blade.php.cache new file mode 100644 index 0000000000000000000000000000000000000000..d191d40e3d41276942db76c96babab691407a936 GIT binary patch literal 872 zcmY+CJ#5oJ6vyvU6NiwZ01+P|gJaQ7TvH?j40hD238E07p{;7Wtu@(j-$^yJQn|p*b)$(OZoQbvh=Nfdg;L$YbsK?tq9<%%B&OcCqwR>F` z62f;I_nvgD=2y^0sd{~G>GncRb9vxb#c2j^=hb6RZg(U1nr)cYP= zZATqGQoZUq+%+B6_iRSw; zWgVAV6yain?R@+2X98IAg!2ExM%j&DZCH`BmbeL@;|=H9_po&mv{52N^8#^M=4g5l z+vlC4}CPU7UJ*B(=5jd-sr zOMIg`E#|#3FL(YzjB@eE;=KCEI+)OOVFoFA7|9yXs4p@Z*`4gudhHls)~9|zZPyFg zltIHNTnnOJw}R-XvC!3~m{SAwYM=ziIduXzrGn|Gf~3xZUazhsUT`)ackVzI;vY7v B$sqs$ literal 0 HcmV?d00001 diff --git a/source/abc.blade.php.js b/source/abc.blade.php.js new file mode 100644 index 0000000..2480b78 --- /dev/null +++ b/source/abc.blade.php.js @@ -0,0 +1,5 @@ +output.push("\r\n\r\n\r\n \r\n \r\n \r\n \r\n "); +output.push( "Merhaba" ); +output.push("\r\n \r\n\r\n\r\n "); +output.push(""); +output.push("\r\n\r\n"); diff --git a/target/abc.html b/target/abc.html new file mode 100644 index 0000000..71d6fc6 --- /dev/null +++ b/target/abc.html @@ -0,0 +1,14 @@ + + + + + + + + Merhaba + + + + + + \ No newline at end of file diff --git a/test.js b/test.js new file mode 100644 index 0000000..695f5a3 --- /dev/null +++ b/test.js @@ -0,0 +1,15 @@ +let parser = require("./init"); +let {writeFile} = require("node:fs/promises"); + +async function main() +{ + let node = await parser.processFile("./source/abc.blade.php"); + await writeFile("./source/abc.blade.php.js", node.parsedContent, "utf8"); + let result = node.execute({ + ebilet: 25 + }); + await writeFile("./source/abc.blade.php.cache", node.cachedData, "utf8"); + await writeFile("./target/abc.html", result, "utf8"); +}; + +process.nextTick(main); \ No newline at end of file