create-arkajs 1.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 ADDED
@@ -0,0 +1,69 @@
1
+ # create-arkajs
2
+
3
+ Scaffold tool untuk membuat project **ARKAJS** — mini framework client-side routing menggunakan HTML, CSS, dan JavaScript murni (tanpa dependency lain).
4
+
5
+ ## Cara pakai
6
+
7
+ ```bash
8
+ npx create-arkajs nama-project
9
+ ```
10
+
11
+ atau
12
+
13
+ ```bash
14
+ npm create arkajs nama-project
15
+ ```
16
+
17
+ Ini akan membuat folder `nama-project` berisi struktur lengkap ARKAJS, siap dijalankan.
18
+
19
+ Kalau tidak diberi nama folder, project akan dibuat di folder aktif:
20
+
21
+ ```bash
22
+ npx create-arkajs
23
+ ```
24
+
25
+ ## Setelah itu
26
+
27
+ Masuk ke folder project lalu jalankan lewat live server (karena pakai `fetch`, butuh HTTP server, tidak bisa dibuka langsung dari `file://`):
28
+
29
+ ```bash
30
+ npx serve
31
+ ```
32
+
33
+ Lalu buka `index.html` lewat browser.
34
+
35
+ ## Struktur project
36
+
37
+ ```
38
+ nama-project/
39
+ ├── gaya/ → file CSS
40
+ ├── halaman/ → konten halaman (beranda.html, tentang.html, dst)
41
+ ├── rancangan/ → komponen layout (header, footer, navbar, sidebar)
42
+ ├── logika/ → script tambahan
43
+ ├── sistem/ → engine routing (app.js, navigasi.js, kelola.js, rakit.js, rute.json)
44
+ └── index.html
45
+ ```
46
+
47
+ ## Menambah rute baru
48
+
49
+ 1. Tambah file HTML baru di folder `halaman/`
50
+ 2. Daftarkan di `sistem/rute.json`, contoh:
51
+
52
+ ```json
53
+ "/kontak": {
54
+ "judul": "Kontak",
55
+ "header": "header.html",
56
+ "main": "kontak.html",
57
+ "css": "gaya.css"
58
+ }
59
+ ```
60
+
61
+ 3. Tambahkan link `<a href="/kontak">Kontak</a>` di halaman manapun — routing akan otomatis tertangani.
62
+
63
+ ## Catatan penting
64
+
65
+ Project ini menggunakan `history.pushState` untuk routing, sehingga saat di-deploy ke hosting statis (misalnya Cloudflare Pages, Netlify, Vercel), pastikan hosting tersebut mendukung **SPA fallback** (semua path tanpa file fisik tetap mengarah ke `index.html`). Beberapa hosting seperti Cloudflare Pages sudah mendukung ini secara otomatis.
66
+
67
+ ## Lisensi
68
+
69
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ const templateDir = path.join(__dirname, "..", "template");
10
+ const targetArg = process.argv[2];
11
+ const targetDir = targetArg ? path.join(process.cwd(), targetArg) : process.cwd();
12
+
13
+ function copyFolderSync(src, dest) {
14
+ if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
15
+ for (const item of fs.readdirSync(src)) {
16
+ const srcPath = path.join(src, item);
17
+ const destPath = path.join(dest, item);
18
+ if (fs.statSync(srcPath).isDirectory()) {
19
+ copyFolderSync(srcPath, destPath);
20
+ } else {
21
+ fs.copyFileSync(srcPath, destPath);
22
+ }
23
+ }
24
+ }
25
+
26
+ console.log(`Membuat project ARKAJS di: ${targetDir}`);
27
+ copyFolderSync(templateDir, targetDir);
28
+ console.log("Selesai! Project ARKAJS sudah siap dipakai.");
29
+ console.log("Jalankan dengan live server (misal: npx serve) lalu buka index.html");
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "create-arkajs",
3
+ "version": "1.0.0",
4
+ "description": "Scaffold tool untuk membuat project ARKAJS — mini framework client-side routing berbasis HTML/CSS/JS murni",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-arkajs": "./bin/cli.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "template"
12
+ ],
13
+ "keywords": [
14
+ "arkajs",
15
+ "router",
16
+ "spa",
17
+ "framework",
18
+ "scaffold",
19
+ "starter",
20
+ "vanilla-js"
21
+ ],
22
+ "author": "",
23
+ "license": "MIT",
24
+ "engines": {
25
+ "node": ">=14"
26
+ }
27
+ }
@@ -0,0 +1,145 @@
1
+ :root {
2
+ --bg: #0a8120;
3
+ --fc: #0b53ae;
4
+ --dark: #0f172a;
5
+ --light: #f8fafc;
6
+ --muted: #64748b;
7
+ --border: #e2e8f0;
8
+ }
9
+
10
+ * {
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ margin: 0;
16
+ font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
17
+ color: var(--dark);
18
+ background: var(--light);
19
+ line-height: 1.6;
20
+ }
21
+
22
+ /* Header & Navbar */
23
+ .header {
24
+ background: var(--dark);
25
+ color: #fff;
26
+ }
27
+
28
+ .header__inner {
29
+ max-width: 960px;
30
+ margin: 0 auto;
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: space-between;
34
+ padding: 16px 20px;
35
+ }
36
+
37
+ .logo {
38
+ color: #fff;
39
+ font-weight: 700;
40
+ font-size: 1.3rem;
41
+ text-decoration: none;
42
+ }
43
+
44
+ .logo span {
45
+ color: var(--bg);
46
+ }
47
+
48
+ .navbar__list {
49
+ display: flex;
50
+ gap: 24px;
51
+ list-style: none;
52
+ margin: 0;
53
+ padding: 0;
54
+ }
55
+
56
+ .navbar__list a {
57
+ color: #cbd5e1;
58
+ text-decoration: none;
59
+ font-weight: 500;
60
+ transition: color 0.2s;
61
+ }
62
+
63
+ .navbar__list a:hover {
64
+ color: #fff;
65
+ }
66
+
67
+ /* Main content */
68
+ main {
69
+ display: block;
70
+ max-width: 960px;
71
+ margin: 0 auto;
72
+ padding: 40px 20px;
73
+ min-height: 60vh;
74
+ }
75
+
76
+ .hero {
77
+ text-align: center;
78
+ padding: 40px 0;
79
+ }
80
+
81
+ .hero h1 {
82
+ font-size: 2.2rem;
83
+ margin-bottom: 12px;
84
+ }
85
+
86
+ .hero p {
87
+ color: var(--muted);
88
+ font-size: 1.1rem;
89
+ max-width: 600px;
90
+ margin: 0 auto;
91
+ }
92
+
93
+ .fitur {
94
+ display: grid;
95
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
96
+ gap: 20px;
97
+ margin-top: 40px;
98
+ }
99
+
100
+ .fitur__item {
101
+ border: 1px solid var(--border);
102
+ border-radius: 10px;
103
+ padding: 20px;
104
+ background: #fff;
105
+ }
106
+
107
+ .fitur__item h3 {
108
+ margin-top: 0;
109
+ color: var(--fc);
110
+ }
111
+
112
+ .konten h1 {
113
+ font-size: 1.8rem;
114
+ }
115
+
116
+ .konten h2 {
117
+ font-size: 1.3rem;
118
+ margin-top: 32px;
119
+ color: var(--fc);
120
+ }
121
+
122
+ .konten code {
123
+ background: #eef2f7;
124
+ padding: 2px 6px;
125
+ border-radius: 4px;
126
+ font-size: 0.9em;
127
+ }
128
+
129
+ .konten pre {
130
+ background: var(--dark);
131
+ color: #f8fafc;
132
+ padding: 16px;
133
+ border-radius: 8px;
134
+ overflow-x: auto;
135
+ }
136
+
137
+ .konten pre code {
138
+ background: none;
139
+ color: inherit;
140
+ padding: 0;
141
+ }
142
+
143
+ .dok-list {
144
+ padding-left: 20px;
145
+ }
@@ -0,0 +1,19 @@
1
+ <section class="hero">
2
+ <h1>Selamat Datang di ARKAJS</h1>
3
+ <p>Mini framework client-side routing yang ringan, tanpa dependency, dan dibangun murni dengan HTML, CSS, dan JavaScript.</p>
4
+ </section>
5
+
6
+ <section class="fitur">
7
+ <div class="fitur__item">
8
+ <h3>Ringan</h3>
9
+ <p>Tanpa build tool, tanpa dependency tambahan. Tinggal jalan langsung di browser.</p>
10
+ </div>
11
+ <div class="fitur__item">
12
+ <h3>Routing Sederhana</h3>
13
+ <p>Atur semua rute aplikasi cukup lewat satu file <code>rute.json</code>.</p>
14
+ </div>
15
+ <div class="fitur__item">
16
+ <h3>Modular</h3>
17
+ <p>Header, footer, navbar, dan halaman dipisah rapi di folder masing-masing.</p>
18
+ </div>
19
+ </section>
@@ -0,0 +1,26 @@
1
+ <section class="konten">
2
+ <h1>Dokumentasi</h1>
3
+
4
+ <h2>Struktur Folder</h2>
5
+ <ul class="dok-list">
6
+ <li><strong>gaya/</strong> — file CSS</li>
7
+ <li><strong>halaman/</strong> — konten setiap halaman</li>
8
+ <li><strong>rancangan/</strong> — komponen layout (header, footer, navbar, sidebar)</li>
9
+ <li><strong>sistem/</strong> — engine routing (app.js, navigasi.js, kelola.js, rakit.js, rute.json)</li>
10
+ </ul>
11
+
12
+ <h2>Menambah Halaman Baru</h2>
13
+ <p>1. Buat file HTML baru di folder <code>halaman/</code>, misalnya <code>kontak.html</code>.</p>
14
+ <p>2. Daftarkan rutenya di <code>sistem/rute.json</code>:</p>
15
+ <pre><code>"/kontak": {
16
+ "judul": "Kontak",
17
+ "header": "header.html",
18
+ "main": "kontak.html",
19
+ "css": "gaya.css"
20
+ }</code></pre>
21
+ <p>3. Tambahkan link navigasi di header atau halaman manapun:</p>
22
+ <pre><code>&lt;a href="/kontak"&gt;Kontak&lt;/a&gt;</code></pre>
23
+
24
+ <h2>Catatan Deploy</h2>
25
+ <p>Karena ARKAJS menggunakan <code>history.pushState</code>, pastikan hosting yang digunakan mendukung fallback ke <code>index.html</code> untuk semua path (misalnya Cloudflare Pages, Netlify, atau Vercel).</p>
26
+ </section>
@@ -0,0 +1,7 @@
1
+ <section class="konten">
2
+ <h1>Tentang ARKAJS</h1>
3
+ <p>ARKAJS dibuat untuk siapa saja yang ingin membangun website dengan routing client-side tanpa perlu belajar framework besar seperti React atau Vue terlebih dahulu.</p>
4
+ <p>Cukup pahami HTML, CSS, dan JavaScript dasar, dan kamu sudah bisa membangun aplikasi web dengan navigasi antar halaman tanpa reload.</p>
5
+ <h2>Bagaimana cara kerjanya?</h2>
6
+ <p>Setiap klik pada link akan dicegat oleh JavaScript, lalu konten halaman akan diganti secara dinamis berdasarkan rute yang terdaftar di <code>rute.json</code> — tanpa perlu memuat ulang halaman dari server.</p>
7
+ </section>
@@ -0,0 +1,22 @@
1
+ <!doctype html>
2
+ <html lang="id">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta http-equiv="X-UA-Compatible" content="ie=edge" />
7
+ <meta name="description" content="" />
8
+ <meta name="keywords" content="" />
9
+ <meta name="robots" content="index,follow" />
10
+ <meta name="author" content="azqilana" />
11
+ <meta property="og:title" content="" />
12
+ <meta property="og:description" content="" />
13
+ <meta property="og:image" content="" />
14
+ <title></title>
15
+ <style id="gaya"></style>
16
+ </head>
17
+ <body>
18
+ <header id="header"></header>
19
+ <main id="main"></main>
20
+ <script type="module" src="sistem/app.js"></script>
21
+ </body>
22
+ </html>
@@ -0,0 +1,5 @@
1
+ const h1=document.querySelector('h1')
2
+ h1.addEventListener('click',(e)=>{
3
+ e.stopPropagation();
4
+ h1.textContent='Header Nya kan ini'
5
+ })
@@ -0,0 +1,12 @@
1
+ <header class="header">
2
+ <div class="header__inner">
3
+ <a href="/" class="logo">ARKA<span>JS</span></a>
4
+ <nav class="navbar">
5
+ <ul class="navbar__list">
6
+ <li><a href="/">Beranda</a></li>
7
+ <li><a href="/tentang">Tentang</a></li>
8
+ <li><a href="/dokumentasi">Dokumentasi</a></li>
9
+ </ul>
10
+ </nav>
11
+ </div>
12
+ </header>
@@ -0,0 +1,8 @@
1
+ import kelolaNavigasi from "./navigasi.js"
2
+
3
+ const kelNav=new kelolaNavigasi();
4
+
5
+ window.addEventListener('DOMContentLoaded',async ()=> kelNav.kelolaW())
6
+ document.addEventListener('click', async (e)=> await kelNav.kelolaKlik(e))
7
+ window.addEventListener('popstate',async ()=>kelNav.kelolaW())
8
+ console.log(window.location.pathname)
File without changes
@@ -0,0 +1,32 @@
1
+ export default class kelolaRute {
2
+ async cekIsiDataRute() {
3
+ try {
4
+ const response = await fetch("sistem/rute.json");
5
+ const dataRute = await response.json();
6
+ return dataRute;
7
+ } catch (error) {
8
+ console.log("Error:", error);
9
+ }
10
+ }
11
+ async cekRute(rute) {
12
+ if (rute) {
13
+ const dataIsiRute = await this.cekIsiDataRute();
14
+ if (dataIsiRute[rute]) {
15
+ const dIR=dataIsiRute[rute];
16
+ const resMain = await fetch(`./halaman/${dIR.main}`);
17
+ const resHeader = await fetch(`./rancangan/${dIR.header}`);
18
+ const resCss = await fetch(`./gaya/${dIR.css}`);
19
+ const isiHeader = await resHeader.text();
20
+ const isiMain=await resMain.text()
21
+ const isiCss= await resCss.text()
22
+ const isiRute={
23
+ judul:dIR.judul,
24
+ css: isiCss,
25
+ header: isiHeader,
26
+ main: isiMain
27
+ }
28
+ return isiRute;
29
+ }
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,29 @@
1
+ import kelolaRute from "./kelola.js";
2
+ import {Rakit} from "./rakit.js"
3
+
4
+ const kR = new kelolaRute();
5
+ const R= new Rakit();
6
+
7
+ export default class kelolaNavigasi {
8
+ async kelolaKlik(e){
9
+ const el = e.target.closest("a");
10
+ const w_origin = window.location.origin;
11
+ if ( el &&el.hasAttribute("href") &&
12
+ el.getAttribute("href") &&
13
+ el.origin === w_origin) {
14
+ const hrefnya = el.getAttribute("href");
15
+ e.preventDefault();
16
+ history.pushState(null, "", hrefnya);
17
+ const hasil=await this.hasilCekRute(hrefnya)
18
+ }
19
+ }
20
+ async kelolaW(){
21
+ const hrefnya = window.location.pathname
22
+ const hasil=await this.hasilCekRute(hrefnya)
23
+ }
24
+ async hasilCekRute(rute){
25
+ const hasilRute = await kR.cekRute(rute)
26
+ R.ambilHasil(hasilRute)
27
+ }
28
+
29
+ }
@@ -0,0 +1,27 @@
1
+
2
+ export class Rakit {
3
+ ambilHasil(hasil){
4
+ this.pasangJudul(hasil.judul)
5
+ this.pasangHeader(hasil.header)
6
+ this.pasangCss(hasil.css)
7
+ this.pasangMain(hasil.main)
8
+ }
9
+ pasangJudul(judul){
10
+ document.title=judul
11
+ }
12
+ pasangHeader(header){
13
+ const Header=this.selectEl("#header")
14
+ Header.innerHTML=header
15
+ }
16
+ pasangMain(main){
17
+ const Main =this.selectEl("#main")
18
+ Main.innerHTML=main
19
+ }
20
+ pasangCss(css){
21
+ const Css=this.selectEl("#gaya")
22
+ Css.innerHTML=css
23
+ }
24
+ selectEl(selector){
25
+ return document.querySelector(selector)
26
+ }
27
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "/index.html": {
3
+ "judul": "Dashboard",
4
+ "header": "header.html",
5
+ "main": "beranda.html",
6
+ "css": "gaya.css"
7
+ },
8
+ "/": {
9
+ "judul": "Dashboard",
10
+ "header": "header.html",
11
+ "main": "beranda.html",
12
+ "css": "gaya.css"
13
+ },
14
+ "/tentang": {
15
+ "judul": "Tentang",
16
+ "header": "header.html",
17
+ "main": "tentang.html",
18
+ "css": "gaya.css"
19
+ },
20
+ "/dokumentasi": {
21
+ "judul": "Dokumentasi",
22
+ "header": "header.html",
23
+ "main": "dokumentasi.html",
24
+ "css": "gaya.css"
25
+ }
26
+ }