First commit

This commit is contained in:
Abdussamed ULUTAŞ 2022-10-25 01:00:01 +03:00
commit de9567a36a
10 changed files with 469 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
package-lock.json

44
Processor/File.js Normal file
View File

@ -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('');
};

347
Processor/Parse.js Normal file
View File

@ -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(`<!-- imported ${value}--->`)});\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;

14
init.js Normal file
View File

@ -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;
};

14
package.json Normal file
View File

@ -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"
}
}

14
source/abc.blade.php Normal file
View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
{{ "Merhaba" }}
</title>
</head>
<body>
@import("merhaba")
</body>
</html>

BIN
source/abc.blade.php.cache Normal file

Binary file not shown.

5
source/abc.blade.php.js Normal file
View File

@ -0,0 +1,5 @@
output.push("<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>\r\n ");
output.push( "Merhaba" );
output.push("\r\n </title>\r\n</head>\r\n<body>\r\n ");
output.push("<!-- imported \"merhaba\"--->");
output.push("\r\n</body>\r\n</html>");

14
target/abc.html Normal file
View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
Merhaba
</title>
</head>
<body>
<!-- imported "merhaba"--->
</body>
</html>

15
test.js Normal file
View File

@ -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);