thoth-markup-lang 4.1.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -23
- package/engine.php +252 -99
- package/package.json +36 -16
- package/thoth.js +348 -102
- package/.htaccess +0 -9
package/README.md
CHANGED
|
@@ -1,42 +1,43 @@
|
|
|
1
|
-
#
|
|
1
|
+
# THOTH: The Sovereign Intelligence Suite (v11.0.0 Pulse Edition)
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<img src="https://img.shields.io/npm/v/thoth-markup-lang?style=for-the-badge&color=
|
|
5
|
-
<img src="https://img.shields.io/badge/
|
|
6
|
-
<img src="https://img.shields.io/badge/
|
|
7
|
-
<img src="https://img.shields.io/badge/Built%20In-Egypt%20🇪🇬-orange?style=for-the-badge" alt="Egypt" />
|
|
4
|
+
<img src="https://img.shields.io/npm/v/thoth-markup-lang?style=for-the-badge&color=06b6d4&logo=npm" alt="NPM Version" />
|
|
5
|
+
<img src="https://img.shields.io/badge/Version-11.0.0--Pulse-f59e0b?style=for-the-badge" alt="Pulse Version" />
|
|
6
|
+
<img src="https://img.shields.io/badge/Engineered_In-Egypt_🇪🇬-020617?style=for-the-badge&logo=code" alt="Egypt" />
|
|
8
7
|
</p>
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
<strong>The Pythonic Architect of the Web.</strong><br />
|
|
12
|
-
Write clean, indentation-based markup that compiles instantly into standard HTML5. <br />
|
|
13
|
-
Stop writing brackets. Start writing wisdom.
|
|
14
|
-
</p>
|
|
9
|
+
**The Binary Wisdom of Web Architecture.** THOTH is a high-performance, sovereign, indentation-based markup language and recursive runtime engine. It eliminates structural noise, removes bracket chaos, and redefines web development through pure, architectural logic.
|
|
15
10
|
|
|
16
11
|
---
|
|
17
12
|
|
|
18
|
-
## 🏛️
|
|
13
|
+
## 🏛️ Architectural Philosophy
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Named after the Egyptian God of Wisdom and Writing, THOTH v3.0 represents a new era where the developer only cares about the structure, leaving the messy `< >` brackets behind.
|
|
15
|
+
THOTH represents a monumental paradigm shift from "tag-heavy" legacy markup to **Recursive Indentation Logic**. With the release of **v11.0.0 (Pulse Edition)**, the engine introduces an ultra-fast parsing core and Python-style error handling, enforcing absolute structural purity. It requires all sovereign files to declare their identity with the `TYPE THOTH` protocol, ensuring architectural integrity and preventing unauthorized code execution.
|
|
23
16
|
|
|
17
|
+
- **Official Website:** [THOTH Language Portal](https://honeydew-pigeon-679592.hostingersite.com/)
|
|
18
|
+
- **Lead Architect:** Engineer Abdelfatah Abdelhamed
|
|
24
19
|
|
|
20
|
+
---
|
|
25
21
|
|
|
26
|
-
##
|
|
22
|
+
## 💎 Intelligence Suite Features (v11.0.0 Pulse)
|
|
27
23
|
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
24
|
+
* **⚡ Ultra-Fast Parser Core [NEW]:** Upgraded O(n) string manipulation algorithms for blazing-fast indentation computation and rendering.
|
|
25
|
+
* **🐞 Python-Style Tracebacks [NEW]:** Intelligent error handling that pinpoints exact file, line number, and syntax faults in both Terminal and a Browser Overlay.
|
|
26
|
+
* **🛡️ Strict Identification:** Mandatory `TYPE THOTH` protocol header to ensure uncompromised file sovereignty.
|
|
27
|
+
* **💎 Zero-Bracket Architecture:** Eliminates opening/closing DOM tags, reducing syntax noise by up to 70%.
|
|
28
|
+
* **🔗 Recursive Data Binding:** Native integration with JSON flat-file databases using `@{{key}}` syntax.
|
|
29
|
+
* **🔐 Procedural Middleware (Auth Guard):** Secure structural DOM nodes natively using `Auth="role"` attributes.
|
|
30
|
+
* **🚀 Pulse Dev Server & Live Reload:** Integrated HTTP server with automated browser synchronization and state tracking.
|
|
31
|
+
* **🔍 Advanced Meta SEO Engine:** Automated generation of HTML5 Meta Tags directly from your JSON data context.
|
|
32
|
+
* **📦 Scoped Components:** Modular file architecture and management through the `Import:` directive.
|
|
33
|
+
* **💉 Hybrid Injection:** Native support for scoped `StyleSheet` (Raw CSS) and `Scripting` (Raw JS) inside the `.thoth` environment.
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
37
|
-
## 🚀
|
|
37
|
+
## 🚀 Technical Implementation
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
### 1. Global Installation
|
|
40
|
+
Install the THOTH Engine globally via NPM to access the sovereign CLI:
|
|
40
41
|
|
|
41
42
|
```bash
|
|
42
43
|
npm install -g thoth-markup-lang
|
package/engine.php
CHANGED
|
@@ -1,138 +1,291 @@
|
|
|
1
1
|
<?php
|
|
2
2
|
/**
|
|
3
|
-
* THOTH Sovereign Runtime Engine
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* THOTH Sovereign Runtime Engine v11.0 - Pulse Edition
|
|
4
|
+
* Architect: Engineer Abdelfatah Abdelhamed 🇪🇬
|
|
5
|
+
* --------------------------------------------------
|
|
6
|
+
* الميزات المدمجة (النسخة المطورة):
|
|
7
|
+
* 1. التوثيق المعماري: إلزامية وجود TYPE THOTH في السطر الأول.
|
|
8
|
+
* 2. نظام Middleware (Auth Guard): التحكم الكامل في صلاحيات الوصول.
|
|
9
|
+
* 3. نظام البيانات الديناميكي: JSON Binding & Recursive Loops.
|
|
10
|
+
* 4. نظام Meta SEO الذكي: توليد عناصر Meta بناءً على البيانات.
|
|
11
|
+
* 5. Python-Style Traceback: متتبع أخطاء ذكي يحدد السطر ونوع الخطأ بدقة.
|
|
12
|
+
* 6. High-Performance Core: تسريع التحليل باستخدام دوال PHP الحديثة.
|
|
6
13
|
*/
|
|
7
14
|
|
|
15
|
+
session_start();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* كلاس استثناءات مخصص للغة تحوت لتتبع الأخطاء بذكاء
|
|
19
|
+
*/
|
|
20
|
+
class ThothSyntaxError extends Exception {
|
|
21
|
+
public $lineContent;
|
|
22
|
+
public function __construct($message, $code = 0, $lineContent = "", Throwable $previous = null) {
|
|
23
|
+
$this->lineContent = $lineContent;
|
|
24
|
+
parent::__construct($message, $code, $previous);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
8
28
|
class ThothEngine {
|
|
9
29
|
private $tagMap = [
|
|
10
30
|
'Title' => 'h1', 'Sub' => 'h2', 'Heading' => 'h3', 'Text' => 'p',
|
|
11
31
|
'Box' => 'div', 'Container' => 'section', 'Nav' => 'nav',
|
|
12
32
|
'Header' => 'header', 'Footer' => 'footer', 'Bold' => 'strong',
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
33
|
+
'Link' => 'a', 'Image' => 'img', 'List' => 'ul', 'Item' => 'li',
|
|
34
|
+
'Button' => 'button', 'Input' => 'input', 'Break' => 'br',
|
|
35
|
+
'Line' => 'hr', 'Layout' => 'main'
|
|
16
36
|
];
|
|
17
37
|
|
|
18
38
|
private $voidTags = ['img', 'br', 'hr', 'input', 'meta', 'link'];
|
|
39
|
+
private $variables = [];
|
|
40
|
+
private $dataContext = [];
|
|
41
|
+
private $devMode = true;
|
|
42
|
+
private $currentLine = 0;
|
|
43
|
+
private $currentFile = "";
|
|
19
44
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
45
|
+
/**
|
|
46
|
+
* المدخل الرئيسي للمحرك
|
|
47
|
+
*/
|
|
48
|
+
public function render($filePath, $isSubCall = false) {
|
|
49
|
+
$safePath = basename($filePath);
|
|
50
|
+
$this->currentFile = $safePath;
|
|
51
|
+
|
|
52
|
+
if (!file_exists($safePath)) {
|
|
53
|
+
return $this->errorPage("404 | THOTH Missing", "الملف غير موجود في النطاق السيادي.");
|
|
24
54
|
}
|
|
25
55
|
|
|
26
|
-
$
|
|
27
|
-
$lines = explode("\n", $code);
|
|
56
|
+
$lines = explode("\n", file_get_contents($safePath));
|
|
28
57
|
|
|
29
|
-
|
|
30
|
-
$
|
|
31
|
-
$
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
$
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
58
|
+
// --- شرط السيادة: التحقق من نوع الملف ---
|
|
59
|
+
$firstLine = trim($lines[0]);
|
|
60
|
+
if ($firstLine !== "TYPE THOTH") {
|
|
61
|
+
return $this->devErrorOverlay("SyntaxError: Missing Identity Protocol. File must begin with TYPE THOTH.", 1, $lines[0]);
|
|
62
|
+
}
|
|
63
|
+
unset($lines[0]); // إزالة سطر التعريف من المعالجة
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
$htmlBody = "";
|
|
67
|
+
$stack = [];
|
|
68
|
+
$inRawMode = false;
|
|
69
|
+
$rawType = '';
|
|
70
|
+
$rawIndent = 0;
|
|
71
|
+
$skipUntilIndent = -1;
|
|
72
|
+
$isRepeatMode = false;
|
|
73
|
+
$repeatBuffer = [];
|
|
74
|
+
$repeatKey = "";
|
|
75
|
+
$repeatIndent = 0;
|
|
76
|
+
|
|
77
|
+
foreach ($lines as $index => $line) {
|
|
78
|
+
$this->currentLine = $index + 1;
|
|
79
|
+
$trimmed = trim($line);
|
|
80
|
+
|
|
81
|
+
// تسريع معالجة الأسطر الفارغة والتعليقات باستخدام str_starts_with
|
|
82
|
+
if ($trimmed === "" || str_starts_with($trimmed, '#')) continue;
|
|
83
|
+
|
|
84
|
+
$indent = strlen($line) - strlen(ltrim($line));
|
|
85
|
+
|
|
86
|
+
// Middleware Guard
|
|
87
|
+
if ($skipUntilIndent !== -1) {
|
|
88
|
+
if ($indent > $skipUntilIndent) continue;
|
|
89
|
+
else $skipUntilIndent = -1;
|
|
51
90
|
}
|
|
52
|
-
}
|
|
53
91
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if ($trimmed[$i] === '"') $inQuotes = !$inQuotes;
|
|
60
|
-
if ($trimmed[$i] === ':' && !$inQuotes) {
|
|
61
|
-
$sep = $i;
|
|
62
|
-
break;
|
|
92
|
+
if (preg_match('/Auth="([^"]+)"/', $trimmed, $matches)) {
|
|
93
|
+
if (!$this->checkAuth($matches[1])) {
|
|
94
|
+
$skipUntilIndent = $indent;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
63
97
|
}
|
|
64
|
-
}
|
|
65
98
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
$val = "";
|
|
72
|
-
}
|
|
99
|
+
// Repeat System
|
|
100
|
+
if ($isRepeatMode) {
|
|
101
|
+
if ($indent > $repeatIndent) { $repeatBuffer[] = $line; continue; }
|
|
102
|
+
else { $htmlBody .= $this->processRepeat($repeatKey, $repeatBuffer); $isRepeatMode = false; $repeatBuffer = []; }
|
|
103
|
+
}
|
|
73
104
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
$cmd = $cmdPart;
|
|
81
|
-
$attrs = "";
|
|
82
|
-
}
|
|
105
|
+
if (str_starts_with($trimmed, 'Repeat Over="')) {
|
|
106
|
+
preg_match('/Over="([^"]+)"/', $trimmed, $matches);
|
|
107
|
+
if(empty($matches[1])) throw new ThothSyntaxError("LoopError: Missing valid array key in Over statement.", $this->currentLine, $line);
|
|
108
|
+
$repeatKey = $matches[1] ?? '';
|
|
109
|
+
$repeatIndent = $indent; $isRepeatMode = true; continue;
|
|
110
|
+
}
|
|
83
111
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
$
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
112
|
+
// Components & Data
|
|
113
|
+
if (str_starts_with($trimmed, 'DataSource:')) { $this->loadData(trim(substr($trimmed, 11))); continue; }
|
|
114
|
+
if (str_starts_with($trimmed, 'Var ')) { $this->parseVariable($trimmed); continue; }
|
|
115
|
+
if (str_starts_with($trimmed, 'Import:')) {
|
|
116
|
+
$importFile = trim(substr($trimmed, 7));
|
|
117
|
+
if(!file_exists($importFile)) throw new ThothSyntaxError("ImportError: Module '$importFile' not found.", $this->currentLine, $line);
|
|
118
|
+
$htmlBody .= $this->render($importFile, true); continue;
|
|
119
|
+
}
|
|
92
120
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
121
|
+
$line = $this->resolveDynamicData($line);
|
|
122
|
+
$trimmed = trim($line);
|
|
123
|
+
|
|
124
|
+
// Raw Injection (CSS/JS)
|
|
125
|
+
if ($inRawMode) {
|
|
126
|
+
if ($indent <= $rawIndent && !empty($trimmed)) { $inRawMode = false; $htmlBody .= "</$rawType>\n"; }
|
|
127
|
+
else { $htmlBody .= $line . "\n"; continue; }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
$sep = $this->findSeparator($trimmed);
|
|
131
|
+
if($sep === -1 && !empty($trimmed) && !isset($this->tagMap[explode(' ', $trimmed)[0]]) && !in_array(strtolower(explode(' ', $trimmed)[0]), $this->voidTags) && $cmd !== "StyleSheet" && $cmd !== "Scripting"){
|
|
132
|
+
// الذكاء الاصطناعي لاكتشاف الأخطاء المطبعية
|
|
133
|
+
throw new ThothSyntaxError("ParseError: Invalid syntax or missing separator ':'.", $this->currentLine, $line);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
$cmdPart = ($sep !== -1) ? trim(substr($trimmed, 0, $sep)) : $trimmed;
|
|
137
|
+
$val = ($sep !== -1) ? trim(substr($trimmed, $sep + 1)) : "";
|
|
138
|
+
|
|
139
|
+
$spacePos = strpos($cmdPart, ' ');
|
|
140
|
+
$cmd = ($spacePos !== false) ? substr($cmdPart, 0, $spacePos) : $cmdPart;
|
|
141
|
+
$attrs = ($spacePos !== false) ? trim(substr($cmdPart, $spacePos)) : "";
|
|
142
|
+
|
|
143
|
+
if ($cmd === "StyleSheet" || $cmd === "Scripting") {
|
|
144
|
+
$inRawMode = true; $rawType = ($cmd === "StyleSheet") ? "style" : "script";
|
|
145
|
+
$rawIndent = $indent; $htmlBody .= "<$rawType>\n"; continue;
|
|
146
|
+
}
|
|
98
147
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
$
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
148
|
+
// Stack Management
|
|
149
|
+
while (count($stack) > 0 && $stack[count($stack) - 1]['indent'] >= $indent) {
|
|
150
|
+
$closedTag = array_pop($stack);
|
|
151
|
+
$htmlBody .= "</" . $closedTag['tag'] . ">\n";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
$tag = isset($this->tagMap[$cmd]) ? $this->tagMap[$cmd] : strtolower($cmd);
|
|
155
|
+
$cleanAttrs = preg_replace('/Auth="[^"]+"/', '', $attrs);
|
|
156
|
+
$openingTag = "<$tag" . ($cleanAttrs ? " $cleanAttrs" : "") . ">";
|
|
157
|
+
|
|
158
|
+
if (in_array($tag, $this->voidTags)) {
|
|
159
|
+
$htmlBody .= str_repeat(" ", $indent) . $openingTag . "\n";
|
|
160
|
+
} elseif ($val !== "") {
|
|
161
|
+
$htmlBody .= str_repeat(" ", $indent) . $openingTag . $val . "</$tag>\n";
|
|
162
|
+
} else {
|
|
163
|
+
$htmlBody .= str_repeat(" ", $indent) . $openingTag . "\n";
|
|
164
|
+
$stack[] = ['tag' => $tag, 'indent' => $indent];
|
|
165
|
+
}
|
|
110
166
|
}
|
|
167
|
+
|
|
168
|
+
if ($isRepeatMode) $htmlBody .= $this->processRepeat($repeatKey, $repeatBuffer);
|
|
169
|
+
while ($closedTag = array_pop($stack)) { $htmlBody .= "</" . $closedTag['tag'] . ">\n"; }
|
|
170
|
+
|
|
171
|
+
return ($isSubCall) ? $htmlBody : $this->generateFullHTML($htmlBody);
|
|
172
|
+
|
|
173
|
+
} catch (ThothSyntaxError $e) {
|
|
174
|
+
return $this->devErrorOverlay($e->getMessage(), $this->currentLine, $e->lineContent);
|
|
175
|
+
} catch (Exception $e) {
|
|
176
|
+
return $this->devErrorOverlay("RuntimeError: " . $e->getMessage(), $this->currentLine, "System Execution Error");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private function checkAuth($role) {
|
|
181
|
+
if ($role === "guest") return true;
|
|
182
|
+
return (isset($_SESSION['user_role']) && $_SESSION['user_role'] === $role);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private function processRepeat($key, $linesBuffer) {
|
|
186
|
+
$dataArray = $this->dataContext[$key] ?? [];
|
|
187
|
+
$output = "";
|
|
188
|
+
foreach ($dataArray as $entry) {
|
|
189
|
+
$oldContext = $this->dataContext;
|
|
190
|
+
$this->dataContext = array_merge($this->dataContext, $entry);
|
|
191
|
+
foreach ($linesBuffer as $l) { $output .= $this->resolveDynamicData($l) . "\n"; }
|
|
192
|
+
$this->dataContext = $oldContext;
|
|
193
|
+
}
|
|
194
|
+
return $output;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private function resolveDynamicData($text) {
|
|
198
|
+
$text = str_replace(array_keys($this->variables), array_values($this->variables), $text);
|
|
199
|
+
return preg_replace_callback('/@{{([^}]+)}}/', function($m) {
|
|
200
|
+
return $this->dataContext[trim($m[1])] ?? $m[0];
|
|
201
|
+
}, $text);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private function findSeparator($text) {
|
|
205
|
+
$inQuotes = false;
|
|
206
|
+
$len = strlen($text);
|
|
207
|
+
for ($i = 0; $i < $len; $i++) {
|
|
208
|
+
if ($text[$i] === '"') $inQuotes = !$inQuotes;
|
|
209
|
+
if ($text[$i] === ':' && !$inQuotes) return $i;
|
|
111
210
|
}
|
|
211
|
+
return -1;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private function parseVariable($trimmed) {
|
|
215
|
+
$parts = explode(':', substr($trimmed, 4), 2);
|
|
216
|
+
if (count($parts) === 2) $this->variables['@' . trim($parts[0])] = trim($parts[1]);
|
|
217
|
+
}
|
|
112
218
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
$
|
|
219
|
+
private function loadData($jsonFile) {
|
|
220
|
+
if (file_exists($jsonFile)) {
|
|
221
|
+
$data = json_decode(file_get_contents($jsonFile), true);
|
|
222
|
+
if ($data) $this->dataContext = array_merge($this->dataContext, $data);
|
|
116
223
|
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private function errorPage($title, $msg) {
|
|
227
|
+
return "<div style='font-family:sans-serif; background:#020617; color:#fff; height:100vh; display:flex; flex-direction:column; align-items:center; justify-content:center;'><h1>$title</h1><p style='color:#06b6d4'>$msg</p></div>";
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Python-Style Traceback Overlay
|
|
232
|
+
* تصميم هندسي ذكي يحدد الخطأ والمكان والملف بالتفصيل
|
|
233
|
+
*/
|
|
234
|
+
private function devErrorOverlay($msg, $line, $lineContent = "") {
|
|
235
|
+
$escapedContent = htmlspecialchars($lineContent);
|
|
236
|
+
return "
|
|
237
|
+
<div style='position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(2,6,23,0.95); z-index:99999; display:flex; align-items:center; justify-content:center; font-family:\"Fira Code\", monospace;'>
|
|
238
|
+
<div style='background:#0f172a; border:1px solid #ef4444; width:80%; max-width:800px; padding:30px; border-radius:12px; box-shadow:0 0 30px rgba(239, 68, 68, 0.2); color:#e2e8f0;'>
|
|
239
|
+
|
|
240
|
+
<div style='border-bottom: 1px solid #334155; padding-bottom:15px; mb-4;'>
|
|
241
|
+
<h2 style='color:#ef4444; margin:0; font-size:1.5rem;'>⚠️ THOTH Traceback (most recent call last):</h2>
|
|
242
|
+
</div>
|
|
243
|
+
|
|
244
|
+
<div style='padding: 20px 0;'>
|
|
245
|
+
<p style='margin:0 0 10px 0; color:#94a3b8;'>File <span style='color:#06b6d4;'>\"{$this->currentFile}\"</span>, line <span style='color:#f59e0b; font-weight:bold;'>$line</span>, in <module></p>
|
|
246
|
+
|
|
247
|
+
<div style='background:#000; padding:15px; border-radius:8px; border-left:4px solid #ef4444; overflow-x:auto;'>
|
|
248
|
+
<div style='color:#f87171;'>$line | <span style='color:#e2e8f0;'>$escapedContent</span></div>
|
|
249
|
+
<div style='color:#ef4444; margin-top:5px;'> ^</div>
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
<p style='margin:20px 0 0 0; color:#ef4444; font-weight:bold; font-size:1.1rem;'>$msg</p>
|
|
253
|
+
</div>
|
|
117
254
|
|
|
118
|
-
|
|
255
|
+
<div style='border-top: 1px solid #334155; padding-top:15px; text-align:right;'>
|
|
256
|
+
<button onclick='location.reload()' style='background:#ef4444; color:#fff; padding:8px 24px; border:none; border-radius:6px; cursor:pointer; font-weight:bold; font-family:inherit;'>RESTART ENGINE</button>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
</div>";
|
|
119
260
|
}
|
|
120
261
|
|
|
121
262
|
private function generateFullHTML($body) {
|
|
122
|
-
|
|
263
|
+
$title = $this->dataContext['site_title'] ?? "THOTH Compiled System";
|
|
264
|
+
$desc = $this->dataContext['site_desc'] ?? "Architected by Abdelfatah Abdelhamed";
|
|
265
|
+
|
|
266
|
+
$liveReload = $this->devMode ? "<script>
|
|
267
|
+
let lastMod = null;
|
|
268
|
+
setInterval(async () => {
|
|
269
|
+
try {
|
|
270
|
+
const res = await fetch(window.location.href, { method: 'HEAD' });
|
|
271
|
+
const etag = res.headers.get('etag');
|
|
272
|
+
if (lastMod && etag !== lastMod) location.reload();
|
|
273
|
+
lastMod = etag;
|
|
274
|
+
} catch(e) {}
|
|
275
|
+
}, 2000);
|
|
276
|
+
</script>" : "";
|
|
277
|
+
|
|
123
278
|
return "<!DOCTYPE html>\n<html lang='ar' dir='rtl'>\n<head>\n" .
|
|
124
279
|
" <meta charset='UTF-8'>\n" .
|
|
125
280
|
" <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n" .
|
|
126
|
-
" <meta name='
|
|
127
|
-
" <meta name='
|
|
128
|
-
"
|
|
281
|
+
" <meta name='description' content='$desc'>\n" .
|
|
282
|
+
" <meta name='generator' content='THOTH Sovereign Engine 11.0'>\n" .
|
|
283
|
+
" <title>$title</title>\n" .
|
|
284
|
+
"</head>\n<body>\n$body\n$liveReload</body>\n</html>";
|
|
129
285
|
}
|
|
130
286
|
}
|
|
131
287
|
|
|
132
|
-
//
|
|
288
|
+
// Global Execution
|
|
133
289
|
$engine = new ThothEngine();
|
|
134
|
-
$
|
|
135
|
-
|
|
136
|
-
// منع الوصول لملفات خارج النظام للأمان
|
|
137
|
-
$safeFile = basename($fileRequested);
|
|
138
|
-
echo $engine->render($safeFile);
|
|
290
|
+
$target = isset($_GET['file']) ? $_GET['file'] : 'index.thoth';
|
|
291
|
+
echo $engine->render($target);
|
package/package.json
CHANGED
|
@@ -1,41 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thoth-markup-lang",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "THOTH
|
|
3
|
+
"version": "11.0.0",
|
|
4
|
+
"description": "THOTH Sovereign Suite (Pulse Edition): A revolutionary indentation-based markup ecosystem featuring Strict File Identification (TYPE THOTH), Python-style tracebacks, recursive JSON data-binding, procedural middleware auth guards, and an ultra-high-performance runtime. Engineered by Engineer Abdelfatah Abdelhamed.",
|
|
5
5
|
"main": "thoth.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"thoth": "./thoth.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node thoth.js",
|
|
11
|
-
"build": "thoth"
|
|
11
|
+
"build": "node thoth.js build",
|
|
12
|
+
"compile": "node thoth.js compile",
|
|
13
|
+
"dev": "node thoth.js dev --watch",
|
|
14
|
+
"serve": "node thoth.js serve --port 3000 --strict",
|
|
15
|
+
"validate": "node thoth.js validate --all",
|
|
16
|
+
"auth-setup": "node thoth.js auth --init",
|
|
17
|
+
"version": "echo THOTH v11.0.0 Pulse Edition Sovereign Intelligence Suite"
|
|
12
18
|
},
|
|
13
19
|
"keywords": [
|
|
14
20
|
"thoth",
|
|
15
21
|
"thoth-lang",
|
|
16
|
-
"thoth-runtime",
|
|
17
22
|
"markup-language",
|
|
18
|
-
"indentation-based",
|
|
19
|
-
"pythonic-markup",
|
|
20
|
-
"clean-code-web",
|
|
21
23
|
"sovereign-engine",
|
|
22
|
-
"
|
|
24
|
+
"pulse-edition",
|
|
25
|
+
"python-style-traceback",
|
|
26
|
+
"smart-error-handling",
|
|
27
|
+
"type-thoth-identification",
|
|
28
|
+
"strict-markup",
|
|
29
|
+
"indentation-logic",
|
|
30
|
+
"middleware-auth",
|
|
31
|
+
"auth-guard",
|
|
32
|
+
"recursive-json-binding",
|
|
23
33
|
"egyptian-engineering",
|
|
24
34
|
"abdelfatah-abdelhamed",
|
|
25
|
-
"zero-
|
|
26
|
-
"web-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"native-thoth"
|
|
35
|
+
"zero-bracket-syntax",
|
|
36
|
+
"web-architecture",
|
|
37
|
+
"clean-code-standards",
|
|
38
|
+
"semantic-purity",
|
|
39
|
+
"performance-runtime",
|
|
40
|
+
"high-speed-compiler"
|
|
32
41
|
],
|
|
33
|
-
"author": "Abdelfatah Abdelhamed <abdelfatahabdelhamed.kfs@gmail.com>",
|
|
42
|
+
"author": "Engineer Abdelfatah Abdelhamed <abdelfatahabdelhamed.kfs@gmail.com>",
|
|
34
43
|
"license": "MIT",
|
|
35
44
|
"engines": {
|
|
36
45
|
"node": ">=14.0.0"
|
|
37
46
|
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "https://github.com/abdelfatah-abdelhamed/thoth-markup-lang"
|
|
50
|
+
},
|
|
38
51
|
"preferGlobal": true,
|
|
52
|
+
"files": [
|
|
53
|
+
"thoth.js",
|
|
54
|
+
"engine.php",
|
|
55
|
+
"README.md",
|
|
56
|
+
"LICENSE",
|
|
57
|
+
"thoth.config.json"
|
|
58
|
+
],
|
|
39
59
|
"publishConfig": {
|
|
40
60
|
"access": "public"
|
|
41
61
|
}
|
package/thoth.js
CHANGED
|
@@ -1,159 +1,405 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* THOTH Engine
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* THOTH Engine v11.0.0 - Pulse Edition (Sovereign Intelligence Suite)
|
|
5
|
+
* Lead Developer & Architect: Engineer Abdelfatah Abdelhamed 🇪🇬
|
|
6
|
+
* ------------------------------------------------------------------
|
|
7
|
+
* الميزات المدمجة:
|
|
8
|
+
* 1. Strict Identification: إلزامية وجود TYPE THOTH في السطر الأول.
|
|
9
|
+
* 2. Middleware Support: نظام Auth Guard المتقدم لتصفية العناصر.
|
|
10
|
+
* 3. Dynamic Meta Engine: توليد وسوم الميتا تلقائياً من سياق البيانات.
|
|
11
|
+
* 4. Dev Server & Live Reload: خادم محلي لمراقبة التغييرات لحظياً.
|
|
12
|
+
* 5. Recursive Data Engine: نظام الـ Loops والـ JSON والـ Variables.
|
|
13
|
+
* 6. Python-Style Traceback: متتبع أخطاء ذكي ودقيق جداً.
|
|
14
|
+
* 7. Ultra-Fast Parser: تسريع خوارزميات الـ Indentation والـ String manipulation.
|
|
8
15
|
*/
|
|
9
16
|
|
|
10
17
|
const fs = require('fs');
|
|
11
18
|
const path = require('path');
|
|
19
|
+
const http = require('http');
|
|
12
20
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
console.log(' Usage:');
|
|
23
|
-
console.log(' thoth build file.thoth \x1b[90m(Create a standalone HTML5 file)\x1b[0m');
|
|
24
|
-
console.log(' thoth file.thoth \x1b[90m(Fast Internal Compilation)\x1b[0m');
|
|
25
|
-
process.exit(1);
|
|
21
|
+
// --- كلاس تتبع الأخطاء الذكي (Python-Style Error Traceback) ---
|
|
22
|
+
class ThothSyntaxError extends Error {
|
|
23
|
+
constructor(message, lineNum, lineContent, filePath) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = 'ThothSyntaxError';
|
|
26
|
+
this.lineNum = lineNum;
|
|
27
|
+
this.lineContent = lineContent;
|
|
28
|
+
this.filePath = filePath;
|
|
29
|
+
}
|
|
26
30
|
}
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// القاموس الهندسي الشامل لجميع وسوم HTML5
|
|
31
|
-
const MAP = {
|
|
32
|
+
// --- القاموس المعماري الشامل ---
|
|
33
|
+
const TAG_MAP = {
|
|
32
34
|
'Title': 'h1', 'Sub': 'h2', 'Heading': 'h3', 'Text': 'p', 'Bold': 'strong',
|
|
33
35
|
'Italic': 'em', 'Box': 'div', 'Container': 'section', 'Nav': 'nav',
|
|
34
36
|
'Header': 'header', 'Footer': 'footer', 'Article': 'article', 'Aside': 'aside',
|
|
35
37
|
'Link': 'a', 'Image': 'img', 'Button': 'button', 'List': 'ul', 'Item': 'li',
|
|
36
|
-
'Input': 'input', 'Form': 'form', 'Label': 'label', 'Break': 'br', 'Line': 'hr'
|
|
38
|
+
'Input': 'input', 'Form': 'form', 'Label': 'label', 'Break': 'br', 'Line': 'hr',
|
|
39
|
+
'Main': 'main', 'Layout': 'section'
|
|
37
40
|
};
|
|
38
41
|
|
|
39
|
-
const
|
|
42
|
+
const VOID_ELEMENTS = ['img', 'br', 'hr', 'input', 'meta', 'link'];
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
// --- سياق التشغيل السيادي ---
|
|
45
|
+
let dataContext = {};
|
|
46
|
+
let config = {
|
|
47
|
+
devMode: process.argv.includes('--dev') || process.argv.includes('serve'),
|
|
48
|
+
port: 3000,
|
|
49
|
+
currentUserRole: 'admin', // القيمة الافتراضية لمحاكاة الميدلوير
|
|
50
|
+
strictMode: true
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const args = process.argv.slice(2);
|
|
54
|
+
const command = args[0];
|
|
55
|
+
const target = args.find(a => a.endsWith('.thoth'));
|
|
56
|
+
|
|
57
|
+
if (!command || (!target && command !== 'serve')) {
|
|
58
|
+
displayUsage();
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* عرض إرشادات الاستخدام التقنية
|
|
64
|
+
*/
|
|
65
|
+
function displayUsage() {
|
|
66
|
+
const yellow = '\x1b[33m';
|
|
67
|
+
const cyan = '\x1b[36m';
|
|
68
|
+
const reset = '\x1b[0m';
|
|
69
|
+
console.log(yellow + '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━' + reset);
|
|
70
|
+
console.log('\x1b[1m\x1b[32m THOTH INTELLIGENCE SUITE v11.0.0 (Pulse) \x1b[0m');
|
|
71
|
+
console.log(cyan + ' Lead Architect: Engineer Abdelfatah Abdelhamed' + reset);
|
|
72
|
+
console.log(yellow + '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━' + reset);
|
|
73
|
+
console.log(' Usage:');
|
|
74
|
+
console.log(' thoth build [file].thoth (Production Compilation)');
|
|
75
|
+
console.log(' thoth serve [file].thoth (Live Dev Server + Traceback)');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* معالجة البيانات الديناميكية @{{key}} و @Variable (Fast Regex)
|
|
80
|
+
*/
|
|
81
|
+
const DATA_REGEX = /@\{\{([^}]+)\}\}/g;
|
|
82
|
+
function resolveData(text, context, variables = {}) {
|
|
83
|
+
let resolved = text;
|
|
84
|
+
for (const [key, val] of Object.entries(variables)) {
|
|
85
|
+
resolved = resolved.replace(new RegExp(key, 'g'), val);
|
|
86
|
+
}
|
|
87
|
+
return resolved.replace(DATA_REGEX, (match, key) => {
|
|
88
|
+
const val = context[key.trim()];
|
|
89
|
+
return val !== undefined ? val : match;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* محرك التجميع المعماري (المسرع)
|
|
95
|
+
*/
|
|
96
|
+
function compileThoth(inputPath, isDev = false) {
|
|
97
|
+
if (!fs.existsSync(inputPath)) {
|
|
98
|
+
throw new ThothSyntaxError(`Source Integrity Error: File not found.`, 0, "", inputPath);
|
|
45
99
|
}
|
|
46
100
|
|
|
47
|
-
const
|
|
48
|
-
const lines =
|
|
49
|
-
|
|
101
|
+
const source = fs.readFileSync(inputPath, 'utf8');
|
|
102
|
+
const lines = source.split(/\r?\n/);
|
|
103
|
+
|
|
104
|
+
// --- التحقق من شرط السيادة الأول ---
|
|
105
|
+
if (lines[0].trim() !== "TYPE THOTH") {
|
|
106
|
+
throw new ThothSyntaxError("Architectural Identity Error: Missing 'TYPE THOTH' protocol to ensure sovereignty.", 1, lines[0], inputPath);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let htmlContent = "";
|
|
50
110
|
let stack = [];
|
|
51
|
-
let
|
|
111
|
+
let variables = {};
|
|
112
|
+
let rawScope = { active: false, type: '', indent: 0 };
|
|
113
|
+
let skipIndent = -1;
|
|
114
|
+
let repeatScope = { active: false, key: '', indent: 0, buffer: [] };
|
|
52
115
|
|
|
53
|
-
lines.
|
|
54
|
-
const
|
|
116
|
+
for (let i = 1; i < lines.length; i++) {
|
|
117
|
+
const lineNum = i + 1;
|
|
118
|
+
let line = lines[i];
|
|
55
119
|
|
|
56
|
-
//
|
|
57
|
-
|
|
120
|
+
// تسريع اكتشاف المسافات (أسرع من Regex search)
|
|
121
|
+
const trimmed = line.trimStart();
|
|
122
|
+
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
123
|
+
const indent = line.length - trimmed.length;
|
|
124
|
+
const fullyTrimmed = trimmed.trimEnd();
|
|
58
125
|
|
|
59
|
-
|
|
126
|
+
// --- 1. Middleware / Auth Guard ---
|
|
127
|
+
if (skipIndent !== -1) {
|
|
128
|
+
if (indent > skipIndent) continue;
|
|
129
|
+
else skipIndent = -1;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const authMatch = fullyTrimmed.match(/Auth="([^"]+)"/);
|
|
133
|
+
if (authMatch) {
|
|
134
|
+
if (authMatch[1] !== config.currentUserRole && authMatch[1] !== 'guest') {
|
|
135
|
+
skipIndent = indent;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
60
139
|
|
|
61
|
-
// 2.
|
|
62
|
-
if (
|
|
63
|
-
if (indent
|
|
64
|
-
|
|
65
|
-
|
|
140
|
+
// --- 2. Repeat Logic (Recursive) ---
|
|
141
|
+
if (repeatScope.active) {
|
|
142
|
+
if (indent > repeatScope.indent) {
|
|
143
|
+
repeatScope.buffer.push(line);
|
|
144
|
+
continue;
|
|
66
145
|
} else {
|
|
67
|
-
|
|
68
|
-
|
|
146
|
+
const list = dataContext[repeatScope.key] || [];
|
|
147
|
+
if(!Array.isArray(list)) {
|
|
148
|
+
throw new ThothSyntaxError(`DataMappingError: '${repeatScope.key}' is not a valid Array in Context.`, lineNum, line, inputPath);
|
|
149
|
+
}
|
|
150
|
+
list.forEach(item => {
|
|
151
|
+
htmlContent += processBuffer(repeatScope.buffer, item, variables, inputPath, lineNum);
|
|
152
|
+
});
|
|
153
|
+
repeatScope.active = false;
|
|
154
|
+
repeatScope.buffer = [];
|
|
69
155
|
}
|
|
70
156
|
}
|
|
71
157
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
158
|
+
if (fullyTrimmed.startsWith('Repeat Over="')) {
|
|
159
|
+
const match = fullyTrimmed.match(/Over="([^"]+)"/);
|
|
160
|
+
if (!match) throw new ThothSyntaxError("LoopError: Invalid Repeat syntax.", lineNum, line, inputPath);
|
|
161
|
+
repeatScope.key = match[1];
|
|
162
|
+
repeatScope.active = true;
|
|
163
|
+
repeatScope.indent = indent;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// --- 3. Data Ingestion & Variables ---
|
|
168
|
+
if (fullyTrimmed.startsWith('DataSource:')) {
|
|
169
|
+
const jsonFileName = fullyTrimmed.split(':')[1].trim();
|
|
170
|
+
const dPath = path.resolve(path.dirname(inputPath), jsonFileName);
|
|
171
|
+
if (!fs.existsSync(dPath)) {
|
|
172
|
+
throw new ThothSyntaxError(`MissingDataError: DataSource '${jsonFileName}' not found.`, lineNum, line, inputPath);
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
dataContext = JSON.parse(fs.readFileSync(dPath, 'utf8'));
|
|
176
|
+
} catch(e) {
|
|
177
|
+
throw new ThothSyntaxError(`JSONParseError: Invalid JSON format in '${jsonFileName}'.`, lineNum, line, inputPath);
|
|
80
178
|
}
|
|
179
|
+
continue;
|
|
81
180
|
}
|
|
82
181
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
cmdPart = trimmed;
|
|
89
|
-
val = "";
|
|
182
|
+
if (fullyTrimmed.startsWith('Var ')) {
|
|
183
|
+
const vParts = fullyTrimmed.substring(4).split(':');
|
|
184
|
+
if (vParts.length === 2) variables['@' + vParts[0].trim()] = vParts[1].trim();
|
|
185
|
+
else throw new ThothSyntaxError(`VariableError: Invalid Var syntax. Expected 'Var name: value'.`, lineNum, line, inputPath);
|
|
186
|
+
continue;
|
|
90
187
|
}
|
|
91
188
|
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
189
|
+
line = resolveData(line, dataContext, variables);
|
|
190
|
+
const processedTrimmed = line.trim();
|
|
191
|
+
|
|
192
|
+
// --- 4. Raw Code Injection (CSS/JS) ---
|
|
193
|
+
if (rawScope.active) {
|
|
194
|
+
if (indent <= rawScope.indent && processedTrimmed !== "") {
|
|
195
|
+
rawScope.active = false;
|
|
196
|
+
htmlContent += `</${rawScope.type}>\n`;
|
|
197
|
+
} else {
|
|
198
|
+
htmlContent += line + '\n';
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
104
201
|
}
|
|
105
202
|
|
|
106
|
-
//
|
|
203
|
+
// --- خوارزمية تحليل الفصل الذكي (Strict Parser) ---
|
|
204
|
+
let colonIdx = -1;
|
|
205
|
+
let inQuotes = false;
|
|
206
|
+
for (let j = 0; j < processedTrimmed.length; j++) {
|
|
207
|
+
if (processedTrimmed[j] === '"') inQuotes = !inQuotes;
|
|
208
|
+
if (processedTrimmed[j] === ':' && !inQuotes) { colonIdx = j; break; }
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
let instr = colonIdx !== -1 ? processedTrimmed.substring(0, colonIdx).trim() : processedTrimmed;
|
|
212
|
+
let val = colonIdx !== -1 ? processedTrimmed.substring(colonIdx + 1).trim() : "";
|
|
213
|
+
|
|
214
|
+
const firstSpace = instr.indexOf(' ');
|
|
215
|
+
const tagName = firstSpace !== -1 ? instr.substring(0, firstSpace) : instr;
|
|
216
|
+
const attrs = firstSpace !== -1 ? instr.substring(firstSpace).trim() : "";
|
|
217
|
+
|
|
218
|
+
if (tagName === "StyleSheet" || tagName === "Scripting") {
|
|
219
|
+
rawScope.active = true;
|
|
220
|
+
rawScope.type = tagName === "StyleSheet" ? "style" : "script";
|
|
221
|
+
rawScope.indent = indent;
|
|
222
|
+
htmlContent += `<${rawScope.type}>\n`;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// إدارة المكدس (Stack Indentation)
|
|
107
227
|
while (stack.length > 0 && stack[stack.length - 1].indent >= indent) {
|
|
108
|
-
|
|
228
|
+
htmlContent += `</${stack.pop().name}>\n`;
|
|
109
229
|
}
|
|
110
230
|
|
|
111
|
-
|
|
112
|
-
|
|
231
|
+
const tag = TAG_MAP[tagName] || tagName.toLowerCase();
|
|
232
|
+
const cleanAttrs = attrs.replace(/Auth="[^"]+"/, '').trim();
|
|
233
|
+
const open = `<${tag}${cleanAttrs ? ' ' + cleanAttrs : ''}>`;
|
|
113
234
|
|
|
114
|
-
if (
|
|
115
|
-
|
|
235
|
+
if (VOID_ELEMENTS.includes(tag)) {
|
|
236
|
+
htmlContent += ' '.repeat(indent) + open + '\n';
|
|
116
237
|
} else if (val) {
|
|
117
|
-
|
|
238
|
+
htmlContent += ' '.repeat(indent) + `${open}${val}</${tag}>\n`;
|
|
118
239
|
} else {
|
|
119
|
-
|
|
240
|
+
htmlContent += ' '.repeat(indent) + open + '\n';
|
|
120
241
|
stack.push({ name: tag, indent: indent });
|
|
121
242
|
}
|
|
122
|
-
}
|
|
243
|
+
}
|
|
123
244
|
|
|
124
|
-
// إغلاق أي
|
|
125
|
-
|
|
126
|
-
|
|
245
|
+
// إغلاق أي تكرار متبقي
|
|
246
|
+
if (repeatScope.active) {
|
|
247
|
+
const list = dataContext[repeatScope.key] || [];
|
|
248
|
+
list.forEach(item => { htmlContent += processBuffer(repeatScope.buffer, item, variables, inputPath, lines.length); });
|
|
127
249
|
}
|
|
128
250
|
|
|
129
|
-
|
|
251
|
+
while (stack.length > 0) htmlContent += `</${stack.pop().name}>\n`;
|
|
252
|
+
|
|
253
|
+
return generateBoilerplate(htmlContent, isDev);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* معالجة الـ Buffer داخل الـ Loop
|
|
258
|
+
*/
|
|
259
|
+
function processBuffer(buffer, item, variables, filePath, baseLineNum) {
|
|
260
|
+
let res = "";
|
|
261
|
+
let bStack = [];
|
|
262
|
+
buffer.forEach((l, idx) => {
|
|
263
|
+
const ind = l.length - l.trimStart().length;
|
|
264
|
+
let pLine = resolveData(l, item, variables);
|
|
265
|
+
const t = pLine.trim();
|
|
266
|
+
let cIdx = t.indexOf(':'); // Fast path for loops
|
|
267
|
+
let cmdStr = cIdx !== -1 ? t.substring(0, cIdx).trim() : t;
|
|
268
|
+
let valStr = cIdx !== -1 ? t.substring(cIdx + 1).trim() : "";
|
|
269
|
+
|
|
270
|
+
const space = cmdStr.indexOf(' ');
|
|
271
|
+
const tag = TAG_MAP[cmdStr.substring(0, space === -1 ? cmdStr.length : space)] || cmdStr.toLowerCase();
|
|
272
|
+
|
|
273
|
+
while (bStack.length > 0 && bStack[bStack.length - 1].indent >= ind) res += `</${bStack.pop().name}>\n`;
|
|
274
|
+
|
|
275
|
+
const op = `<${tag}${space !== -1 ? ' ' + cmdStr.substring(space).trim() : ''}>`;
|
|
276
|
+
if (VOID_ELEMENTS.includes(tag)) res += ' '.repeat(ind) + op + '\n';
|
|
277
|
+
else if (valStr) res += ' '.repeat(ind) + `${op}${valStr}</${tag}>\n`;
|
|
278
|
+
else { res += ' '.repeat(ind) + op + '\n'; bStack.push({ name: tag, indent: ind }); }
|
|
279
|
+
});
|
|
280
|
+
while (bStack.length > 0) res += `</${bStack.pop().name}>\n`;
|
|
281
|
+
return res;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* توليد هيكل HTML5 المعياري مع الـ Meta Tags
|
|
286
|
+
*/
|
|
287
|
+
function generateBoilerplate(content, isDev) {
|
|
288
|
+
const title = dataContext.site_title || "THOTH Sovereign Architecture";
|
|
289
|
+
const desc = dataContext.site_desc || "Engineered by Abdelfatah Abdelhamed";
|
|
290
|
+
|
|
291
|
+
const liveReload = isDev ? `
|
|
292
|
+
<script>
|
|
293
|
+
console.log('%c THOTH PULSE DEV MODE: ACTIVE ', 'background:#06b6d4;color:#000;font-weight:bold;');
|
|
294
|
+
let lastMod = null;
|
|
295
|
+
setInterval(async () => {
|
|
296
|
+
try {
|
|
297
|
+
const r = await fetch(window.location.href, {method:'HEAD'});
|
|
298
|
+
const etag = r.headers.get('etag') || r.headers.get('last-modified');
|
|
299
|
+
if(lastMod && etag !== lastMod) location.reload();
|
|
300
|
+
lastMod = etag;
|
|
301
|
+
} catch(e) {}
|
|
302
|
+
}, 1500);
|
|
303
|
+
</script>` : "";
|
|
304
|
+
|
|
130
305
|
return `<!DOCTYPE html>
|
|
131
306
|
<html lang="ar" dir="rtl">
|
|
132
307
|
<head>
|
|
133
308
|
<meta charset="UTF-8">
|
|
134
309
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
135
|
-
<meta name="
|
|
136
|
-
<meta name="
|
|
137
|
-
<
|
|
310
|
+
<meta name="description" content="${desc}">
|
|
311
|
+
<meta name="generator" content="THOTH Sovereign Engine v11.0.0">
|
|
312
|
+
<meta name="author" content="Engineer Abdelfatah Abdelhamed">
|
|
313
|
+
<title>${title}</title>
|
|
138
314
|
</head>
|
|
139
|
-
<body>
|
|
140
|
-
${
|
|
315
|
+
<body style="margin:0; background:#020617; color:#f8fafc;">
|
|
316
|
+
${content}
|
|
317
|
+
${liveReload}
|
|
141
318
|
</body>
|
|
142
319
|
</html>`;
|
|
143
320
|
}
|
|
144
321
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
322
|
+
/**
|
|
323
|
+
* دالة توليد واجهة تتبع الأخطاء (Browser Overlay)
|
|
324
|
+
*/
|
|
325
|
+
function getBrowserTracebackHTML(e) {
|
|
326
|
+
if (e.name === 'ThothSyntaxError') {
|
|
327
|
+
const escapedContent = e.lineContent.replace(/</g, '<').replace(/>/g, '>');
|
|
328
|
+
return `
|
|
329
|
+
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>THOTH Engine Error</title></head>
|
|
330
|
+
<body style="margin:0; background:#020617; font-family:'Fira Code', monospace; display:flex; align-items:center; justify-content:center; height:100vh;">
|
|
331
|
+
<div style="background:#0f172a; border:1px solid #ef4444; width:90%; max-width:800px; padding:30px; border-radius:12px; box-shadow:0 0 30px rgba(239, 68, 68, 0.2); color:#e2e8f0;">
|
|
332
|
+
<div style="border-bottom: 1px solid #334155; padding-bottom:15px; margin-bottom:20px;">
|
|
333
|
+
<h2 style="color:#ef4444; margin:0; font-size:1.5rem;">⚠️ THOTH Traceback (most recent call last):</h2>
|
|
334
|
+
</div>
|
|
335
|
+
<div style="padding: 10px 0;">
|
|
336
|
+
<p style="margin:0 0 10px 0; color:#94a3b8;">File <span style="color:#06b6d4;">"${e.filePath}"</span>, line <span style="color:#f59e0b; font-weight:bold;">${e.lineNum}</span>, in <module></p>
|
|
337
|
+
<div style="background:#000; padding:15px; border-radius:8px; border-left:4px solid #ef4444; overflow-x:auto;">
|
|
338
|
+
<div style="color:#f87171;">${e.lineNum} | <span style="color:#e2e8f0;">${escapedContent}</span></div>
|
|
339
|
+
<div style="color:#ef4444; margin-top:5px;"> ^</div>
|
|
340
|
+
</div>
|
|
341
|
+
<p style="margin:20px 0 0 0; color:#ef4444; font-weight:bold; font-size:1.1rem;">${e.message}</p>
|
|
342
|
+
</div>
|
|
343
|
+
<div style="border-top: 1px solid #334155; padding-top:15px; margin-top:20px; text-align:right;">
|
|
344
|
+
<button onclick="location.reload()" style="background:#ef4444; color:#fff; padding:8px 24px; border:none; border-radius:6px; cursor:pointer; font-weight:bold; font-family:inherit;">RESTART ENGINE</button>
|
|
345
|
+
</div>
|
|
346
|
+
</div>
|
|
347
|
+
</body></html>`;
|
|
348
|
+
}
|
|
349
|
+
return `<body style="background:#000;color:#ff5555;padding:50px;font-family:monospace">
|
|
350
|
+
<h2 style="border-bottom:2px solid #ff5555;padding-bottom:10px">SOVEREIGN RUNTIME ERROR</h2>
|
|
351
|
+
<p style="font-size:18px">${e.message}</p>
|
|
352
|
+
<button onclick="location.reload()" style="background:#ff5555;color:#fff;border:none;padding:10px 20px;cursor:pointer">RETRY</button>
|
|
353
|
+
</body>`;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* طباعة الأخطاء في التيرمينال
|
|
358
|
+
*/
|
|
359
|
+
function printTerminalError(e) {
|
|
360
|
+
if (e.name === 'ThothSyntaxError') {
|
|
361
|
+
console.error('\x1b[31m%s\x1b[0m', `\n⚠️ THOTH Traceback (most recent call last):`);
|
|
362
|
+
console.error('\x1b[90m%s\x1b[0m', ` File "${e.filePath}", line ${e.lineNum}, in <module>`);
|
|
363
|
+
console.error(` ${e.lineContent}`);
|
|
364
|
+
console.error('\x1b[31m%s\x1b[0m', ` ^`);
|
|
365
|
+
console.error('\x1b[1m\x1b[31m%s\x1b[0m', `${e.message}\n`);
|
|
366
|
+
} else {
|
|
367
|
+
console.error(`\x1b[31m [ERROR] ${e.message}\x1b[0m`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// --- طبقة التنفيذ ---
|
|
372
|
+
if (command === 'serve') {
|
|
373
|
+
const server = http.createServer((req, res) => {
|
|
374
|
+
try {
|
|
375
|
+
const html = compileThoth(target, true);
|
|
376
|
+
res.writeHead(200, {
|
|
377
|
+
'Content-Type': 'text/html',
|
|
378
|
+
'Cache-Control': 'no-cache',
|
|
379
|
+
'ETag': Date.now().toString()
|
|
380
|
+
});
|
|
381
|
+
res.end(html);
|
|
382
|
+
} catch (e) {
|
|
383
|
+
printTerminalError(e);
|
|
384
|
+
res.writeHead(500, { 'Content-Type': 'text/html' });
|
|
385
|
+
res.end(getBrowserTracebackHTML(e));
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
server.listen(config.port, () => {
|
|
390
|
+
console.log('\x1b[36m%s\x1b[0m', `──────────────────────────────────────────`);
|
|
391
|
+
console.log(` ✔ SERVER ACTIVE: http://localhost:${config.port}`);
|
|
392
|
+
console.log(` ✔ ARCHITECTURE: ${target}`);
|
|
393
|
+
console.log(` ✔ MODE: Pulse Edition v11.0.0`);
|
|
394
|
+
console.log('\x1b[36m%s\x1b[0m', `──────────────────────────────────────────`);
|
|
395
|
+
});
|
|
396
|
+
} else {
|
|
397
|
+
try {
|
|
398
|
+
const out = compileThoth(target, false);
|
|
399
|
+
fs.writeFileSync(target.replace('.thoth', '.html'), out);
|
|
400
|
+
console.log(`\x1b[32m [SUCCESS] Architecture materialized: ${target.replace('.thoth', '.html')}\x1b[0m`);
|
|
401
|
+
} catch (e) {
|
|
402
|
+
printTerminalError(e);
|
|
403
|
+
process.exit(1);
|
|
404
|
+
}
|
|
159
405
|
}
|
package/.htaccess
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# THOTH Server Configuration
|
|
2
|
-
RewriteEngine On
|
|
3
|
-
|
|
4
|
-
# توجيه أي طلب لملف ينتهي بـ .thoth إلى محرك المهندس عبد الفتاح
|
|
5
|
-
RewriteCond %{REQUEST_FILENAME} !-f
|
|
6
|
-
RewriteRule ^(.*)\.thoth$ engine.php?file=$1.thoth [L,QSA]
|
|
7
|
-
|
|
8
|
-
# جعل index.thoth هو الملف الرئيسي للموقع
|
|
9
|
-
DirectoryIndex index.thoth
|