lumpiajs 1.0.2 → 1.0.4

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 ADDED
@@ -0,0 +1,130 @@
1
+ # 🥟 LumpiaJS
2
+
3
+ **Framework Web MVC dengan Kearifan Lokal Semarangan.**
4
+ _Framework ini dibuat untuk seru-seruan (have fun), tapi diam-diam powerful seperti PHP Framework modern!_
5
+
6
+ ## 🚀 Cara Mulai (Quick Start)
7
+
8
+ ### 1. Buat Project Baru
9
+
10
+ Langsung gas pakai perintah ini:
11
+
12
+ ```bash
13
+ npx lumpiajs create-project warung-ku
14
+ ```
15
+
16
+ _(Atau pakai istilah lokal: `npx lumpiajs buka-cabang warung-ku`)_
17
+
18
+ ### 2. Masuk & Install Bumbu
19
+
20
+ Masuk ke foldernya dan install dependencies (wajib, biar kodingannya gurih):
21
+
22
+ ```bash
23
+ cd warung-ku
24
+ npm install
25
+ ```
26
+
27
+ ### 3. Dodolan (Jalankan Server)
28
+
29
+ Nyalakan server development:
30
+
31
+ ```bash
32
+ npm start
33
+ ```
34
+
35
+ Atau pakai perintah manual: `npx lumpia dodolan`.
36
+ Websitemu bakal jalan di `http://localhost:3000`.
37
+
38
+ ---
39
+
40
+ ## 🏗️ Struktur Project (MVL - Model View Logika)
41
+
42
+ LumpiaJS nggunake istilah sing luwih "Njawani" tapi tetep MVC:
43
+
44
+ ```
45
+ warung-ku/
46
+ ├── app/
47
+ │ ├── logika/ # Logika Program (Controller)
48
+ │ └── belakang/ # Data & Dapur (Model)
49
+ ├── jalur/
50
+ │ └── web.js # Rute URL (Routes)
51
+ ├── depan/ # Tampilan (View)
52
+ ├── package.json
53
+ └── ...
54
+ ```
55
+
56
+ ### 1. Jalur (Routes)
57
+
58
+ Atur URL di `jalur/web.js`:
59
+
60
+ ```javascript
61
+ import { Jalan } from "lumpiajs";
62
+
63
+ // Nulis rute: Jalan.gawe(url, 'NamaLogika@method')
64
+ Jalan.gawe("/", "BerandaLogika@index");
65
+ Jalan.gawe("/api/produk", "ProdukLogika@index");
66
+ ```
67
+
68
+ ### 2. Logika (Controller)
69
+
70
+ Bikin logika di `app/logika/BerandaLogika.js`.
71
+ Class harus extend `Logika`.
72
+
73
+ ```javascript
74
+ import { Logika } from "lumpiajs";
75
+
76
+ export default class BerandaLogika extends Logika {
77
+ index() {
78
+ // Tampilke file ning folder 'depan/beranda.lmp'
79
+ return this.tampil("beranda", {
80
+ pesan: "Sugeng Rawuh, Lur!",
81
+ tanggal: new Date().toLocaleDateString(),
82
+ });
83
+ }
84
+ }
85
+ ```
86
+
87
+ ### 3. Depan (View)
88
+
89
+ Bikin tampilan di `depan/beranda.lmp`.
90
+ Gunakan `{{ variabel }}` buat nampilin data.
91
+
92
+ ```html
93
+ <lump>
94
+ <klambi> h1 { color: red; } </klambi>
95
+
96
+ <kulit>
97
+ <h1>{{ pesan }}</h1>
98
+ <p>Saiki tanggal: {{ tanggal }}</p>
99
+ </kulit>
100
+ </lump>
101
+ ```
102
+
103
+ ### 4. Belakang (Model)
104
+
105
+ Simpen data utawa logika database ning `app/belakang/Produk.js`.
106
+ Bisa nggunake `Model` ala Eloquent.
107
+
108
+ ```javascript
109
+ import { Model } from "lumpiajs";
110
+ // ... logika model ...
111
+ ```
112
+
113
+ ---
114
+
115
+ ## 🤝 Cara Lapor Masalah
116
+
117
+ Nembe nemu bug? Atau punya ide jenius?
118
+
119
+ 1. Buka link ini: [https://github.com/fastroware/lumpiajs/issues](https://github.com/fastroware/lumpiajs/issues)
120
+ 2. Klik **"New Issue"**.
121
+ 3. Ceritakan keluh kesahmu.
122
+
123
+ ---
124
+
125
+ ## ⚠️ DISCLAIMER
126
+
127
+ **LumpiaJS ini 100% project _Have Fun_.**
128
+ Gunakan dengan bijak. Kalau ada error di production, jangan nyalahin kami ya! 🙏
129
+
130
+ _Dibuat dengan ❤️ dan 🥟 dari Semarang._
package/bin/lumpia.js ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import { createProject } from '../lib/commands/create.js';
3
+ import { serveProject } from '../lib/commands/serve.js';
4
+
5
+ async function main() {
6
+ const args = process.argv.slice(2);
7
+ const perintah = args[0];
8
+ const parameter = args[1];
9
+
10
+ if (perintah === 'create-project' || perintah === 'buka-cabang') {
11
+ createProject(parameter);
12
+ }
13
+ else if (perintah === 'dodolan' || perintah === 'serve') {
14
+ serveProject();
15
+ }
16
+ else if (perintah === 'goreng') {
17
+ console.log("🚧 Fitur 'goreng' saiki wis otomatis digabung karo 'dodolan' via JIT Compiler MVC.");
18
+ console.log(" Silakan gunake: lumpia dodolan");
19
+ }
20
+ else {
21
+ console.log('Perintah ora dikenal.');
22
+ console.log('------------------------------------------------');
23
+ console.log('1. lumpia create-project <nama> (Bikin project)');
24
+ console.log('2. lumpia dodolan (Jalanin server)');
25
+ console.log('------------------------------------------------');
26
+ }
27
+ }
28
+
29
+ main();
package/index.js CHANGED
@@ -1,142 +1,4 @@
1
- #!/usr/bin/env node
2
- import fs from 'fs';
3
- import path from 'path';
4
1
 
5
- // --- KAMUS BAHASA SEMARANG ---
6
- const dictionary = [
7
- { asal: /<lump>/g, jadi: '' },
8
- { asal: /<\/lump>/g, jadi: '' },
9
- { asal: /ono\s/g, jadi: 'let ' },
10
- { asal: /paten\s/g, jadi: 'const ' },
11
- { asal: /gawe\s/g, jadi: 'function ' },
12
- { asal: /yen\s/g, jadi: 'if ' },
13
- { asal: /liyane/g, jadi: 'else' },
14
- { asal: /mandek;/g, jadi: 'return;' },
15
- { asal: /ora\s/g, jadi: '!' },
16
- { asal: /panjang\(/g, jadi: 'len(' },
17
- ];
18
-
19
- const runtimeScript = `
20
- <script>
21
- function ambil(sel) { return document.querySelector(sel).value; }
22
- function tampil(txt) {
23
- let el = document.getElementById('output-lumpia');
24
- if(el) el.innerText = txt;
25
- else alert(txt);
26
- }
27
- function len(x) { return x.length; }
28
- </script>
29
- `;
30
-
31
- // --- TEMPLATE PROJECT BARU ---
32
- const boilerplateCode = `<lump>
33
- <klambi>
34
- h1 { color: #d35400; font-family: sans-serif; }
35
- button { padding: 10px 20px; background: #2ecc71; border: none; color: white; cursor: pointer; }
36
- button:hover { background: #27ae60; }
37
- </klambi>
38
-
39
- <kulit>
40
- <h1>Sugeng Rawuh di LumpiaJS</h1>
41
- <p>Project anyar siap dimasak!</p>
42
- <button onclick="sapa()">Pencet Aku</button>
43
- </kulit>
44
-
45
- <isi>
46
- gawe sapa() {
47
- tampil("Halo! Iki project pertamamu, Bro!");
48
- }
49
- </isi>
50
- </lump>`;
51
-
52
- async function main() {
53
- const args = process.argv.slice(2);
54
- const perintah = args[0]; // misal: 'create-project' atau 'goreng'
55
- const parameter = args[1]; // misal: 'tokoku'
56
-
57
- // --- FITUR 1: Bikin Project Baru ---
58
- if (perintah === 'create-project' || perintah === 'buka-cabang') {
59
- const namaProject = parameter;
60
-
61
- if (!namaProject) {
62
- console.log('❌ Eh, jeneng project-e opo?');
63
- console.log('Contoh: lumpia create-project warung-baru');
64
- return;
65
- }
66
-
67
- const projectPath = path.join(process.cwd(), namaProject);
68
- const srcPath = path.join(projectPath, 'src');
69
-
70
- if (fs.existsSync(projectPath)) {
71
- console.log(`⚠️ Waduh, folder "${namaProject}" wis ono, Bro. Ganti jeneng liyo.`);
72
- return;
73
- }
74
-
75
- console.log(`🔨 Lagi nyiapke lahan kanggo "${namaProject}"...`);
76
-
77
- // 1. Bikin Folder Utama
78
- fs.mkdirSync(projectPath);
79
-
80
- // 2. Bikin Folder src
81
- fs.mkdirSync(srcPath);
82
-
83
- // 3. Tulis file contoh (Boilerplate)
84
- fs.writeFileSync(path.join(srcPath, 'app.lmp'), boilerplateCode);
85
-
86
- console.log('✅ Siap, Juragan! Project wis dadi.');
87
- console.log('-------------------------------------------');
88
- console.log(`cd ${namaProject}`);
89
- console.log('lumpia goreng');
90
- console.log('-------------------------------------------');
91
- }
92
-
93
- // --- FITUR 2: Compile (Goreng) ---
94
- else if (perintah === 'goreng') {
95
- console.log('🍳 Sik, lagi nggoreng kodingan...');
96
- const srcDir = './src';
97
- const distDir = './dist';
98
-
99
- if (!fs.existsSync(srcDir)) return console.log('❌ Folder src ora ono! (Coba: lumpia create-project namaproject)');
100
- if (!fs.existsSync(distDir)) fs.mkdirSync(distDir);
101
-
102
- const files = fs.readdirSync(srcDir).filter(file => file.endsWith('.lmp'));
103
-
104
- files.forEach(file => {
105
- let content = fs.readFileSync(path.join(srcDir, file), 'utf-8');
106
-
107
- const matchKulit = content.match(/<kulit>([\s\S]*?)<\/kulit>/);
108
- const matchIsi = content.match(/<isi>([\s\S]*?)<\/isi>/);
109
- const matchKlambi = content.match(/<klambi>([\s\S]*?)<\/klambi>/);
110
-
111
- let htmlnya = matchKulit ? matchKulit[1] : '';
112
- let logicnya = matchIsi ? matchIsi[1] : '';
113
- let cssnya = matchKlambi ? matchKlambi[1] : '';
114
-
115
- dictionary.forEach(kata => logicnya = logicnya.replace(kata.asal, kata.jadi));
116
-
117
- const hasil = `<!DOCTYPE html>
118
- <html>
119
- <head>
120
- <title>Lumpia App</title>
121
- <style>body{font-family:sans-serif;padding:20px;} ${cssnya}</style>
122
- </head>
123
- <body>
124
- ${htmlnya}
125
- <div id="output-lumpia" style="margin-top:20px; font-weight:bold;"></div>
126
- ${runtimeScript}
127
- <script>${logicnya}</script>
128
- </body>
129
- </html>`;
130
-
131
- const namaFileBaru = file.replace('.lmp', '.html');
132
- fs.writeFileSync(path.join(distDir, namaFileBaru), hasil);
133
- console.log(`✅ Mateng: dist/${namaFileBaru}`);
134
- });
135
- } else {
136
- console.log('Perintah ora dikenal.');
137
- console.log('1. lumpia create-project <nama>');
138
- console.log('2. lumpia goreng');
139
- }
140
- }
141
-
142
- main();
2
+ export { Jalan, routes } from './lib/core/Router.js';
3
+ export { LumpiaModel as Model } from './lib/core/Model.js';
4
+ export { Logika } from './lib/core/Controller.js'; // Export Logika instead of Kontroler
@@ -0,0 +1,148 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ // --- TEMPLATES ---
5
+ const routesTemplate = `import { Jalan } from 'lumpiajs';
6
+
7
+ // Definisi Jalur (Routes)
8
+ Jalan.gawe('/', 'BerandaLogika@index');
9
+ Jalan.gawe('/profil', 'BerandaLogika@profil');
10
+ Jalan.gawe('/api/produk', 'ProdukLogika@index');
11
+ `;
12
+
13
+ const controllerTemplate = `import { Logika, Model } from 'lumpiajs';
14
+
15
+ export default class BerandaLogika extends Logika {
16
+ index() {
17
+ // Kirim data ke tampilan (view) ning folder 'depan'
18
+ return this.tampil('beranda', {
19
+ pesan: 'Sugeng Rawuh di LumpiaJS!',
20
+ penulis: 'Pakdhe Koding'
21
+ });
22
+ }
23
+
24
+ profil() {
25
+ return this.tampil('profil', { nama: 'User Setia' });
26
+ }
27
+ }
28
+ `;
29
+
30
+ const modelTemplate = `// Contoh dummy data
31
+ const dataProduk = [
32
+ { id: 1, jeneng: 'Lumpia Basah', rego: 5000 },
33
+ { id: 2, jeneng: 'Lumpia Goreng', rego: 6000 },
34
+ { id: 3, jeneng: 'Tahu Gimbal', rego: 12000 }
35
+ ];
36
+
37
+ export default dataProduk;
38
+ `;
39
+
40
+ const produkControllerTemplate = `import { Logika, Model } from 'lumpiajs';
41
+ import DataProduk from '../../belakang/Produk.js';
42
+
43
+ export default class ProdukLogika extends Logika {
44
+ index() {
45
+ // Eloquent-style: Model.use(data).dimana(...).jupuk()
46
+ const asil = Model.use(DataProduk)
47
+ .dimana('rego', '>', 5500)
48
+ .jupuk();
49
+
50
+ return this.json({
51
+ status: 'sukses',
52
+ data: asil
53
+ });
54
+ }
55
+ }
56
+ `;
57
+
58
+ const viewBerandaTemplate = `<lump>
59
+ <klambi>
60
+ h1 { color: #d35400; text-align: center; }
61
+ .box { border: 1px solid #ddd; padding: 20px; text-align: center; margin-top: 20px; }
62
+ </klambi>
63
+
64
+ <kulit>
65
+ <h1>{{ pesan }}</h1>
66
+ <div class="box">
67
+ <p>Digawe karo tresno dening: <strong>{{ penulis }}</strong></p>
68
+ <button onclick="cekrego()">Cek Harga API</button>
69
+ <br><br>
70
+ <a href="/profil">Menyang Profil</a>
71
+ </div>
72
+ </kulit>
73
+
74
+ <isi>
75
+ gawe cekrego() {
76
+ fetch('/api/produk')
77
+ .then(res => res.json())
78
+ .then(data => {
79
+ alert('Data seko API: ' + JSON.stringify(data));
80
+ });
81
+ }
82
+ </isi>
83
+ </lump>`;
84
+
85
+ const viewProfilTemplate = `<lump>
86
+ <kulit>
87
+ <h1>Profil Pengguna</h1>
88
+ <p>Halo, <strong>{{ nama }}</strong>!</p>
89
+ <a href="/">Bali Mulih</a>
90
+ </kulit>
91
+ </lump>`;
92
+
93
+ const packageJsonTemplate = (name) => `{
94
+ "name": "${name}",
95
+ "version": "1.0.0",
96
+ "main": "jalur/web.js",
97
+ "type": "module",
98
+ "scripts": {
99
+ "start": "lumpia dodolan",
100
+ "serve": "lumpia dodolan",
101
+ "goreng": "lumpia goreng"
102
+ },
103
+ "dependencies": {
104
+ "lumpiajs": "latest"
105
+ }
106
+ }
107
+ `;
108
+
109
+ export function createProject(parameter) {
110
+ const namaProject = parameter;
111
+ if (!namaProject) {
112
+ console.log('❌ Eh, jeneng project-e opo?');
113
+ console.log('Contoh: lumpia create-project warung-baru');
114
+ return;
115
+ }
116
+
117
+ const root = path.join(process.cwd(), namaProject);
118
+ if (fs.existsSync(root)) return console.log(`❌ Folder ${namaProject} wis ono. Ganti jeneng liyo.`);
119
+
120
+ console.log(`🔨 Mbangun pondasi warung MVC (Model-View-Logika) ing ${namaProject}...`);
121
+
122
+ fs.mkdirSync(root);
123
+ // STRUCTURE UPDATE:
124
+ // app/logika (Controller)
125
+ // app/belakang (Model)
126
+ // depan (View)
127
+
128
+ fs.mkdirSync(path.join(root, 'app', 'logika'), { recursive: true });
129
+ fs.mkdirSync(path.join(root, 'app', 'belakang'), { recursive: true });
130
+ fs.mkdirSync(path.join(root, 'jalur'));
131
+ fs.mkdirSync(path.join(root, 'depan'));
132
+
133
+ // Write files
134
+ fs.writeFileSync(path.join(root, 'package.json'), packageJsonTemplate(namaProject));
135
+ fs.writeFileSync(path.join(root, 'jalur', 'web.js'), routesTemplate);
136
+ fs.writeFileSync(path.join(root, 'app', 'logika', 'BerandaLogika.js'), controllerTemplate);
137
+ fs.writeFileSync(path.join(root, 'app', 'logika', 'ProdukLogika.js'), produkControllerTemplate);
138
+ fs.writeFileSync(path.join(root, 'app', 'belakang', 'Produk.js'), modelTemplate);
139
+ fs.writeFileSync(path.join(root, 'depan', 'beranda.lmp'), viewBerandaTemplate);
140
+ fs.writeFileSync(path.join(root, 'depan', 'profil.lmp'), viewProfilTemplate);
141
+
142
+ console.log('✅ Warung siap! Struktur M-V-L wis ketata rapi.');
143
+ console.log('----------------------------------------------------');
144
+ console.log(`cd ${namaProject}`);
145
+ console.log('npm install <-- (Wajib ben lumpiajs ke-install)');
146
+ console.log('npm run serve <-- (Kanggo dodolan/start server)');
147
+ console.log('----------------------------------------------------');
148
+ }
@@ -0,0 +1,82 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import http from 'http';
4
+ import { routes } from '../core/Router.js';
5
+ import { renderLumpia } from '../core/View.js';
6
+
7
+ export async function serveProject() {
8
+ const root = process.cwd();
9
+ const routesFile = path.join(root, 'jalur', 'web.js');
10
+
11
+ if (!fs.existsSync(routesFile)) return console.log("❌ Iki dudu warung LumpiaJS MVC! (Ora nemu jalur/web.js)");
12
+
13
+ console.log('🔄 Loading core framework...');
14
+
15
+ try {
16
+ // Load User Routes
17
+ const userRouteUrl = path.join(root, 'jalur', 'web.js');
18
+ await import('file://' + userRouteUrl);
19
+
20
+ console.log(`🛣️ Total jalur ditemu: ${routes.length}`);
21
+
22
+ // Start Server
23
+ const server = http.createServer(async (req, res) => {
24
+ const method = req.method;
25
+ const url = new URL(req.url, `http://${req.headers.host}`);
26
+ const pathname = url.pathname;
27
+
28
+ console.log(`📥 ${method} ${pathname}`);
29
+
30
+ const match = routes.find(r => r.path === pathname && r.method === method);
31
+
32
+ if (match) {
33
+ try {
34
+ // Action format: 'NamaLogika@method'
35
+ const [controllerName, methodName] = match.action.split('@');
36
+
37
+ // Path ke folder 'app/logika'
38
+ const controllerPath = path.join(root, 'app', 'logika', controllerName + '.js');
39
+
40
+ if (!fs.existsSync(controllerPath)) throw new Error(`Logika (Controller) ${controllerName} ora ketemu ning app/logika!`);
41
+
42
+ const module = await import('file://' + controllerPath + '?update=' + Date.now());
43
+ const ControllerClass = module.default;
44
+ const instance = new ControllerClass();
45
+
46
+ if (typeof instance[methodName] !== 'function') {
47
+ throw new Error(`Method ${methodName} ora ono nang ${controllerName}`);
48
+ }
49
+
50
+ const result = await instance[methodName]();
51
+
52
+ if (result.type === 'html') {
53
+ res.writeHead(200, {'Content-Type': 'text/html'});
54
+ res.end(result.content);
55
+ } else if (result.type === 'json') {
56
+ res.writeHead(200, {'Content-Type': 'application/json'});
57
+ res.end(result.content);
58
+ } else {
59
+ res.writeHead(200, {'Content-Type': 'text/plain'});
60
+ res.end(String(result));
61
+ }
62
+ } catch (e) {
63
+ console.error(e);
64
+ res.writeHead(500, {'Content-Type': 'text/html'});
65
+ res.end(`<h1>500: Kompor Meleduk</h1><pre>${e.message}\n${e.stack}</pre>`);
66
+ }
67
+ } else {
68
+ res.writeHead(404, {'Content-Type': 'text/html'});
69
+ res.end('<h1>404: Dalane buntu, Mas.</h1>');
70
+ }
71
+ });
72
+
73
+ const port = 3000;
74
+ server.listen(port, () => {
75
+ console.log(`🚀 Warung buka ning http://localhost:${port}`);
76
+ console.log(`(Tekan Ctrl+C kanggo tutup warung)`);
77
+ });
78
+
79
+ } catch (err) {
80
+ console.error('Fatal Error saat loading routes:', err);
81
+ }
82
+ }
@@ -0,0 +1,20 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { renderLumpia } from './View.js';
4
+
5
+ // 3. BASE LOGIKA (Controller)
6
+ export class Logika {
7
+ tampil(viewName, data = {}) {
8
+ // Cek lokasi view relative dari CWD user (folder 'depan')
9
+ const viewPath = path.join(process.cwd(), 'depan', `${viewName}.lmp`);
10
+ if (fs.existsSync(viewPath)) {
11
+ return { type: 'html', content: renderLumpia(viewPath, data) };
12
+ } else {
13
+ return { type: 'html', content: `<h1>404: Tampilan '${viewName}' ora ketemu ning folder 'depan', Lur.</h1>` };
14
+ }
15
+ }
16
+
17
+ json(data) {
18
+ return { type: 'json', content: JSON.stringify(data) };
19
+ }
20
+ }
@@ -0,0 +1,41 @@
1
+ // 1. MODEL (Eloquent-like)
2
+ export class LumpiaModel {
3
+ constructor(data = []) {
4
+ this.data = data;
5
+ }
6
+
7
+ static use(jsonData) {
8
+ return new LumpiaModel(jsonData);
9
+ }
10
+
11
+ // Ambil kabeh data
12
+ kabeh() {
13
+ return this.data;
14
+ }
15
+
16
+ // Filter cari (where)
17
+ dimana(key, operator, value) {
18
+ if (value === undefined) { value = operator; operator = '=='; }
19
+
20
+ const filtered = this.data.filter(item => {
21
+ if (operator === '==') return item[key] == value;
22
+ if (operator === '>') return item[key] > value;
23
+ if (operator === '<') return item[key] < value;
24
+ if (operator === '>=') return item[key] >= value;
25
+ if (operator === '<=') return item[key] <= value;
26
+ if (operator === '!=') return item[key] != value;
27
+ return false;
28
+ });
29
+ return new LumpiaModel(filtered);
30
+ }
31
+
32
+ // Ambil satu (first)
33
+ siji() {
34
+ return this.data[0] || null;
35
+ }
36
+
37
+ // Return raw array
38
+ jupuk() {
39
+ return this.data;
40
+ }
41
+ }
@@ -0,0 +1,14 @@
1
+
2
+ // 2. ROUTER : Simpan Jalur
3
+ export const routes = [];
4
+
5
+ export const Jalan = {
6
+ gawe: (path, action) => routes.push({ path, action, method: 'GET' }), // GET
7
+ jupuk: (path, action) => routes.push({ path, action, method: 'GET' }), // Alias GET
8
+ kirim: (path, action) => routes.push({ path, action, method: 'POST' }),
9
+ anyar: (path, action) => routes.push({ path, action, method: 'PUT' }),
10
+ bucak: (path, action) => routes.push({ path, action, method: 'DELETE' }),
11
+ };
12
+
13
+ // Global Router Container (for easy access in runtime)
14
+ global.LumpiaRouter = routes;
@@ -0,0 +1,58 @@
1
+ import fs from 'fs';
2
+
3
+ // --- KAMUS BAHASA SEMARANG (Blade-like Template Engine) ---
4
+ // Mengubah sintaks .lmp ke HTML siap render dengan interpolasi data
5
+ export function renderLumpia(viewPath, data = {}) {
6
+ let content = fs.readFileSync(viewPath, 'utf-8');
7
+
8
+ // 1. Ekstrak bagian <klambi>, <kulit>, <isi>
9
+ const matchKulit = content.match(/<kulit>([\s\S]*?)<\/kulit>/);
10
+ const matchIsi = content.match(/<isi>([\s\S]*?)<\/isi>/); // Client-side JS
11
+ const matchKlambi = content.match(/<klambi>([\s\S]*?)<\/klambi>/);
12
+
13
+ let htmlBody = matchKulit ? matchKulit[1] : '';
14
+ let clientScript = matchIsi ? matchIsi[1] : '';
15
+ let cssStyle = matchKlambi ? matchKlambi[1] : '';
16
+
17
+ // 2. Transpile Client-side JS (Semarangan -> JS Standard)
18
+ const dictionary = [
19
+ { asal: /ono\s/g, jadi: 'let ' },
20
+ { asal: /paten\s/g, jadi: 'const ' },
21
+ { asal: /gawe\s/g, jadi: 'function ' },
22
+ { asal: /yen\s/g, jadi: 'if ' },
23
+ { asal: /liyane/g, jadi: 'else' },
24
+ { asal: /mandek;/g, jadi: 'return;' },
25
+ { asal: /ora\s/g, jadi: '!' },
26
+ { asal: /panjang\(/g, jadi: 'len(' },
27
+ ];
28
+ dictionary.forEach(kata => clientScript = clientScript.replace(kata.asal, kata.jadi));
29
+
30
+ // 3. Templating Engine (Mirip Blade {{ variable }})
31
+ // Mengganti {{ variable }} dengan value dari `data`
32
+ for (const [key, value] of Object.entries(data)) {
33
+ const regex = new RegExp(`{{\\s*${key}\\s*}}`, 'g');
34
+ // Simple XSS protection could be added here
35
+ htmlBody = htmlBody.replace(regex, value);
36
+ }
37
+
38
+ // 4. Rakit Akhir
39
+ return `<!DOCTYPE html>
40
+ <html>
41
+ <head>
42
+ <title>Lumpia App</title>
43
+ <style>body{font-family:sans-serif;padding:20px;} ${cssStyle}</style>
44
+ </head>
45
+ <body>
46
+ ${htmlBody}
47
+ <div id="output-lumpia"></div>
48
+ <script>
49
+ // Runtime Helper
50
+ function tampil(txt) {
51
+ let el = document.getElementById('output-lumpia');
52
+ if(el) el.innerText = txt;
53
+ }
54
+ ${clientScript}
55
+ </script>
56
+ </body>
57
+ </html>`;
58
+ }
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "lumpiajs",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Bahasa Pemrograman Semarangan",
5
5
  "type": "module",
6
+ "main": "index.js",
6
7
  "bin": {
7
- "lumpia": "./index.js"
8
+ "lumpia": "./bin/lumpia.js"
8
9
  },
9
10
  "dependencies": {
10
11
  "fs-extra": "^11.1.1"