lumpiajs 1.0.12 → 1.0.13
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/lib/commands/build.js +54 -42
- package/package.json +1 -1
package/lib/commands/build.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
// ... (KAMUS
|
|
2
|
+
// ... (KAMUS same as before) ...
|
|
3
3
|
const KAMUS = [
|
|
4
4
|
{ from: /paten\s/g, to: 'const ' },
|
|
5
5
|
{ from: /ono\s/g, to: 'let ' },
|
|
@@ -24,8 +24,12 @@ import { loadConfig } from '../core/Config.js';
|
|
|
24
24
|
|
|
25
25
|
function transpileSemarangan(content) {
|
|
26
26
|
let code = content;
|
|
27
|
+
// 1. Keep .lmp import relative for now, or assume .js
|
|
27
28
|
code = code.replace(/from\s+['"](.+?)\.lmp['"]/g, "from '$1.js'");
|
|
28
|
-
|
|
29
|
+
|
|
30
|
+
// 2. DO NOT TOUCH 'lumpiajs' IMPORT.
|
|
31
|
+
// We will use Import Map in index.html to resolve 'lumpiajs' to './core/lumpia.js'
|
|
32
|
+
// This solves the relative path hell once and for all.
|
|
29
33
|
|
|
30
34
|
code = code.split('\n').map(line => {
|
|
31
35
|
let l = line;
|
|
@@ -46,18 +50,6 @@ function processDirectory(source, dest, rootDepth = 0) {
|
|
|
46
50
|
} else {
|
|
47
51
|
if (item.endsWith('.lmp') || item.endsWith('.js')) {
|
|
48
52
|
let content = fs.readFileSync(srcPath, 'utf8');
|
|
49
|
-
let backSteps = rootDepth > 0 ? '../'.repeat(rootDepth) : './';
|
|
50
|
-
if(rootDepth === 0) backSteps = './'; // core is in dist/core/.
|
|
51
|
-
|
|
52
|
-
// Fix path calculation to Core
|
|
53
|
-
// dist/routes/web.js (depth 1) -> ../core/lumpia.js
|
|
54
|
-
// dist/app/controllers/Home.js (depth 2) -> ../../core/lumpia.js
|
|
55
|
-
|
|
56
|
-
// Let's rely on simple replace logic based on file type location usually known
|
|
57
|
-
// But dynamic is better.
|
|
58
|
-
|
|
59
|
-
content = content.replace(/from\s+['"]lumpiajs['"]/g, `from '${backSteps}../core/lumpia.js'`);
|
|
60
|
-
|
|
61
53
|
content = transpileSemarangan(content);
|
|
62
54
|
const finalDest = destPath.replace('.lmp', '.js');
|
|
63
55
|
fs.writeFileSync(finalDest, content);
|
|
@@ -73,7 +65,21 @@ export class Controller {
|
|
|
73
65
|
constructor() { this.params={}; }
|
|
74
66
|
async tampil(viewName, data={}) {
|
|
75
67
|
try {
|
|
76
|
-
|
|
68
|
+
// Fetch view must be relative to root of dist.
|
|
69
|
+
// Since we use Import Map, we are modernized.
|
|
70
|
+
// Better to assume deployment at known base or use explicit relative if possible.
|
|
71
|
+
// But fetch('views/...') is relative to current page URL.
|
|
72
|
+
// If current page is /2025/lumpiajs/produk, fetch('views/home.lmp') -> /2025/lumpiajs/views/home.lmp (Works!)
|
|
73
|
+
// Wait, if /produk is virtual path, browser thinks we are in folder /lumpiajs/.
|
|
74
|
+
// If /produk/detail/1 -> browser thinks folder is /lumpiajs/produk/detail/.
|
|
75
|
+
// Fetch 'views/...' will fail (404).
|
|
76
|
+
|
|
77
|
+
// SOLUSI: Selalu fetch dari ROOT relative (pakai Window Base yang kita set di index.html)
|
|
78
|
+
const basePath = window.LUMPIA_BASE || '';
|
|
79
|
+
// Ensure slash
|
|
80
|
+
const url = basePath + '/views/' + viewName + '.lmp';
|
|
81
|
+
|
|
82
|
+
const res = await fetch(url.replace('//', '/')); // simple cleanup
|
|
77
83
|
if(!res.ok) throw new Error('View 404: ' + viewName);
|
|
78
84
|
let html = await res.text();
|
|
79
85
|
|
|
@@ -116,42 +122,42 @@ const indexHtml = `<!DOCTYPE html>
|
|
|
116
122
|
<meta charset="UTF-8">
|
|
117
123
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
118
124
|
<title>LumpiaJS</title>
|
|
125
|
+
<!-- IMPORT MAP: KUNCI SUKSES LOAD MODULE DI SUBFOLDER -->
|
|
126
|
+
<script type="importmap">
|
|
127
|
+
{
|
|
128
|
+
"imports": {
|
|
129
|
+
"lumpiajs": "./core/lumpia.js"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
</script>
|
|
119
133
|
<link rel="stylesheet" href="public/css/style.css">
|
|
134
|
+
<script>
|
|
135
|
+
// DETEKSI BASE PATH DENGAN LEBIH AMAN (Via current script location fallback)
|
|
136
|
+
// Kita ambil lokasi index.html ini sebagai 'Source of Truth' root aplikasi.
|
|
137
|
+
window.LUMPIA_BASE = window.location.pathname
|
|
138
|
+
.replace(new RegExp('/index\\\\.html$'), '')
|
|
139
|
+
.replace(new RegExp('/$'), '');
|
|
140
|
+
// console.log('Base:', window.LUMPIA_BASE);
|
|
141
|
+
</script>
|
|
120
142
|
</head>
|
|
121
143
|
<body>
|
|
122
144
|
<div id="app">Loading...</div>
|
|
123
145
|
|
|
124
146
|
<script type="module">
|
|
147
|
+
// Import Map makes this work:
|
|
125
148
|
import { Jalan } from './routes/web.js';
|
|
126
149
|
|
|
127
150
|
async function navigate() {
|
|
128
|
-
// FIX: Gunakan new RegExp string biar aman dari escaping hell
|
|
129
|
-
const cleanPath = (p) => p.replace(new RegExp('/index\\\\.html$'), '').replace(new RegExp('/$'), '');
|
|
130
|
-
|
|
131
|
-
const basePath = cleanPath(window.location.pathname);
|
|
132
|
-
// Tapi tunggu, basePath itu harusnya folder ROOT project.
|
|
133
|
-
// Misal: /2025/lumpiajs/
|
|
134
|
-
// URL saat ini: /2025/lumpiajs/index.html -> Base: /2025/lumpiajs
|
|
135
|
-
// Kalau kita navigate ke sub-route (via history pushState): /2025/lumpiajs/produk
|
|
136
|
-
// Maka window.location.pathname adalah /2025/lumpiajs/produk.
|
|
137
|
-
// Kita HARUS tau base path awalnya apa. Kita bisa tebak dari script tag src location?
|
|
138
|
-
// Atau kita asumsikan saat pertama load (yang biasanya index.html), itu lah base path.
|
|
139
|
-
|
|
140
|
-
// Trik: Simpan base path di window variable saat pertama load (index.html)
|
|
141
|
-
if (!window.LUMPIA_BASE) {
|
|
142
|
-
window.LUMPIA_BASE = window.location.pathname.replace(new RegExp('/index\\\\.html$'), '').replace(new RegExp('/$'), '');
|
|
143
|
-
}
|
|
144
|
-
|
|
145
151
|
let currentPath = window.location.pathname;
|
|
146
|
-
|
|
147
|
-
|
|
152
|
+
|
|
153
|
+
// Normalize: Strip Base Path
|
|
154
|
+
if (window.LUMPIA_BASE && currentPath.startsWith(window.LUMPIA_BASE)) {
|
|
148
155
|
currentPath = currentPath.substring(window.LUMPIA_BASE.length);
|
|
149
156
|
}
|
|
150
157
|
if (!currentPath || currentPath === '/index.html') currentPath = '/';
|
|
151
158
|
|
|
152
159
|
let m = null, args = {};
|
|
153
160
|
for(let r of Jalan.routes) {
|
|
154
|
-
// Regex: Replace {slug} -> ([^/]+)
|
|
155
161
|
let regexStr = '^' + r.p.replace(/{([a-zA-Z0-9_]+)}/g, '([^/]+)') + '$';
|
|
156
162
|
let reg = new RegExp(regexStr);
|
|
157
163
|
let res = currentPath.match(reg);
|
|
@@ -161,12 +167,13 @@ const indexHtml = `<!DOCTYPE html>
|
|
|
161
167
|
if(m) {
|
|
162
168
|
const [cName, fName] = m.a.split('@');
|
|
163
169
|
try {
|
|
170
|
+
// Import Relative to index.html (selalu root dist)
|
|
164
171
|
const mod = await import('./app/controllers/'+cName+'.js?'+Date.now());
|
|
165
172
|
const C = mod.default; const i = new C(); i.params=args;
|
|
166
173
|
await i[fName](...args);
|
|
167
174
|
} catch(e) {
|
|
168
175
|
console.error(e);
|
|
169
|
-
document.getElementById('app').innerHTML='<h1>Error
|
|
176
|
+
document.getElementById('app').innerHTML='<h1>Error</h1><pre>'+e.message+'</pre>';
|
|
170
177
|
}
|
|
171
178
|
} else {
|
|
172
179
|
document.getElementById('app').innerHTML='<h1>404 Not Found</h1><p>Route: '+currentPath+'</p>';
|
|
@@ -174,16 +181,21 @@ const indexHtml = `<!DOCTYPE html>
|
|
|
174
181
|
}
|
|
175
182
|
|
|
176
183
|
window.addEventListener('popstate', navigate);
|
|
184
|
+
|
|
185
|
+
// SPA LINK INTERCEPTOR (SAT SET MODE)
|
|
177
186
|
document.body.addEventListener('click', e => {
|
|
178
|
-
|
|
187
|
+
// Cari elemen <a> (bisa jadi klik di span dalam a)
|
|
188
|
+
const link = e.target.closest('a');
|
|
189
|
+
if (link && link.href.startsWith(window.location.origin)) {
|
|
190
|
+
// Ignore if target blank or control click
|
|
191
|
+
if (link.target === '_blank' || e.ctrlKey) return;
|
|
192
|
+
|
|
179
193
|
e.preventDefault();
|
|
180
|
-
history.pushState(null,'',
|
|
194
|
+
history.pushState(null, '', link.href);
|
|
181
195
|
navigate();
|
|
182
196
|
}
|
|
183
197
|
});
|
|
184
198
|
|
|
185
|
-
// Init Base Path immediately
|
|
186
|
-
window.LUMPIA_BASE = window.location.pathname.replace(new RegExp('/index\\\\.html$'), '').replace(new RegExp('/$'), '');
|
|
187
199
|
navigate();
|
|
188
200
|
</script>
|
|
189
201
|
</body>
|
|
@@ -194,7 +206,7 @@ export function buildProject() {
|
|
|
194
206
|
const dist = path.join(root, 'dist');
|
|
195
207
|
const config = loadConfig(root);
|
|
196
208
|
|
|
197
|
-
console.log('🍳 Goreng Project (Mode
|
|
209
|
+
console.log('🍳 Goreng Project (Mode Import Map + Sat Set SPA)...');
|
|
198
210
|
if (fs.existsSync(dist)) fs.rmSync(dist, { recursive: true, force: true });
|
|
199
211
|
fs.mkdirSync(dist);
|
|
200
212
|
|
|
@@ -215,5 +227,5 @@ export function buildProject() {
|
|
|
215
227
|
|
|
216
228
|
fs.writeFileSync(path.join(dist, '.htaccess'), `<IfModule mod_rewrite.c>\nRewriteEngine On\nRewriteRule ^index\\.html$ - [L]\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule . index.html [L]\n</IfModule>`);
|
|
217
229
|
|
|
218
|
-
console.log('✅ Mateng! Siap
|
|
230
|
+
console.log('✅ Mateng! Siap dihidangkan di folder manapun.');
|
|
219
231
|
}
|