First commit
This commit is contained in:
commit
de9567a36a
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
package-lock.json
|
|
@ -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('');
|
||||||
|
};
|
|
@ -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;
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
Binary file not shown.
|
@ -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>");
|
|
@ -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>
|
|
@ -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);
|
Reference in New Issue