create-medan-app 0.1.0 → 0.1.2

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/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
3
3
  import { resolve } from "node:path";
4
- import { GITIGNORE, MAIN_MEDAN, packageJson, readme } from "./templates.js";
4
+ import { DEV_MJS, GITIGNORE, mainMedan, packageJson, readme } from "./templates.js";
5
5
  function isValidPackageName(name) {
6
6
  return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name);
7
7
  }
@@ -22,13 +22,16 @@ function main() {
22
22
  }
23
23
  mkdirSync(targetDir, { recursive: true });
24
24
  writeFileSync(resolve(targetDir, "package.json"), packageJson(rawName));
25
- writeFileSync(resolve(targetDir, "main.medan"), MAIN_MEDAN);
25
+ writeFileSync(resolve(targetDir, "main.medan"), mainMedan(rawName));
26
+ writeFileSync(resolve(targetDir, "dev.mjs"), DEV_MJS);
26
27
  writeFileSync(resolve(targetDir, "README.md"), readme(rawName));
27
28
  writeFileSync(resolve(targetDir, ".gitignore"), GITIGNORE);
28
29
  console.log(`mantap kali! project '${rawName}' udah jadi.\n`);
29
30
  console.log("langkah selanjutnya:\n");
30
31
  console.log(` cd ${rawName}`);
31
32
  console.log(" npm install");
32
- console.log(" npm start");
33
+ console.log(" npm run dev # auto-regenerate tiap main.medan disave");
34
+ console.log(" # atau: npm start # generate sekali doang");
35
+ console.log(" # terus buka landing.html di browser");
33
36
  }
34
37
  main();
package/dist/templates.js CHANGED
@@ -4,54 +4,170 @@ export function packageJson(name) {
4
4
  "version": "0.1.0",
5
5
  "private": true,
6
6
  "scripts": {
7
- "start": "medan main.medan"
7
+ "start": "medan main.medan",
8
+ "dev": "node dev.mjs"
8
9
  },
9
10
  "dependencies": {
10
- "medan-language": "^0.1.2"
11
+ "medan-language": "^0.1.3"
11
12
  }
12
13
  }
13
14
  `;
14
15
  }
15
- export const MAIN_MEDAN = `// selamat datang di Medan-lang!
16
- // jalanin dengan: npm start
17
-
18
- // variabel
19
- modal nama = "Medan"
20
- bilang "Horas, " + nama + "!"
21
-
22
- // percabangan
23
- modal umur = 21
24
- kalo umur > 17
25
- bilang "Udah gede kali umur lu"
26
- kalo gak
27
- bilang "Masih bocil"
16
+ export const DEV_MJS = `// dev.mjs
17
+ // "npm run dev" jalanin file ini: generate landing.html sekali, terus
18
+ // nungguin main.medan berubah dan regenerate otomatis tiap disave.
19
+
20
+ import { spawnSync } from "node:child_process";
21
+ import { watch } from "node:fs";
22
+
23
+ function build() {
24
+ console.log("\\n[medan] generate landing.html ...");
25
+ const result = spawnSync("medan", ["main.medan"], { stdio: "inherit" });
26
+ if (result.status !== 0) {
27
+ console.error("[medan] ada error di atas, benerin dulu terus save lagi.");
28
+ }
29
+ }
30
+
31
+ build();
32
+ console.log("[medan] mantau main.medan, ctrl+c buat berhenti...");
33
+
34
+ let timer;
35
+ watch("main.medan", () => {
36
+ clearTimeout(timer);
37
+ timer = setTimeout(build, 100);
38
+ });
39
+ `;
40
+ export function mainMedan(name) {
41
+ return `// main.medan
42
+ // Ini titik masuk project "${name}" kamu.
43
+ // "npm start" jalanin file ini, yang nge-generate landing.html.
44
+ // Edit di bawah, jalanin lagi "npm start", terus refresh landing.html di browser.
45
+
46
+ bikin css()
47
+ balikin "
48
+ <style>
49
+ :root {
50
+ --bg: #1B120D;
51
+ --bg-2: #241A13;
52
+ --bg-3: #2E2117;
53
+ --ink: #F5EDE2;
54
+ --ink-dim: #C9B8A6;
55
+ --chili: #E4402A;
56
+ --chili-ink: #FFEDE9;
57
+ --turmeric: #F2B705;
58
+ --daun: #7FAE84;
59
+ --line: rgba(245,237,226,0.14);
60
+ --shadow: rgba(10,6,3,0.5);
61
+ }
62
+ @media (prefers-color-scheme: light) {
63
+ :root:not([data-theme='dark']) {
64
+ --bg: #F7EEDD; --bg-2: #FFFAF0; --bg-3: #FDF1DA;
65
+ --ink: #2A1B12; --ink-dim: #6B5645;
66
+ --chili: #C7301C; --chili-ink: #FFF6F4; --turmeric: #93690A; --daun: #3E6B45;
67
+ --line: rgba(42,27,18,0.14); --shadow: rgba(42,27,18,0.16);
68
+ }
69
+ }
70
+ :root[data-theme='light'] {
71
+ --bg: #F7EEDD; --bg-2: #FFFAF0; --bg-3: #FDF1DA;
72
+ --ink: #2A1B12; --ink-dim: #6B5645;
73
+ --chili: #C7301C; --chili-ink: #FFF6F4; --turmeric: #93690A; --daun: #3E6B45;
74
+ --line: rgba(42,27,18,0.14); --shadow: rgba(42,27,18,0.16);
75
+ }
76
+ * { box-sizing: border-box; }
77
+ body { margin: 0; background: var(--bg); color: var(--ink); font-family: 'Plus Jakarta Sans', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
78
+ .page { max-width: 880px; margin: 0 auto; padding: 0 24px 80px; }
79
+ code, .mono { font-family: 'JetBrains Mono', ui-monospace, monospace; }
80
+ h1, h2 { font-family: 'Alfa Slab One', Georgia, serif; font-weight: 400; text-wrap: balance; margin: 0; }
81
+ .eyebrow { font-family: 'JetBrains Mono', monospace; text-transform: uppercase; letter-spacing: 0.16em; font-size: 12px; color: var(--turmeric); margin: 0 0 12px; }
82
+ .hero { padding: 72px 0 40px; }
83
+ h1.headline { font-size: clamp(34px, 6vw, 58px); line-height: 1.02; text-shadow: 3px 3px 0 var(--shadow); }
84
+ h1.headline span { color: var(--chili); }
85
+ .lede { max-width: 60ch; font-size: 17px; line-height: 1.6; color: var(--ink-dim); margin: 18px 0 0; }
86
+ section { padding: 44px 0; border-top: 1px solid var(--line); }
87
+ section h2 { font-size: clamp(22px, 3.4vw, 30px); margin-bottom: 20px; }
88
+ .step-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
89
+ .step-list li { display: flex; gap: 16px; align-items: flex-start; background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px; padding: 16px 18px; }
90
+ .step-no { flex: none; width: 30px; height: 30px; border-radius: 50%; background: var(--turmeric); color: var(--bg); font-family: 'JetBrains Mono', monospace; font-weight: 700; display: flex; align-items: center; justify-content: center; font-size: 14px; }
91
+ .step-list strong { display: block; margin-bottom: 4px; font-size: 14.5px; }
92
+ .step-list code { display: inline-block; background: var(--bg-3); padding: 3px 7px; border-radius: 5px; font-size: 12.5px; }
93
+ .kw-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; }
94
+ .kw-card { background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px; padding: 16px; }
95
+ .kw-card h3 { font-family: 'JetBrains Mono', monospace; color: var(--chili); font-size: 15px; margin: 0 0 6px; }
96
+ .kw-card p { margin: 0; color: var(--ink-dim); font-size: 13px; }
97
+ .footer { color: var(--ink-dim); font-size: 13.5px; font-family: 'JetBrains Mono', monospace; }
98
+ .footer a { color: var(--turmeric); }
99
+ </style>
100
+ "
28
101
  siap
29
102
 
30
- // fungsi
31
- bikin tambah(a, b)
32
- balikin a + b
103
+ modal fontLink = "<link rel='preconnect' href='https://fonts.googleapis.com'><link rel='stylesheet' href='https://fonts.googleapis.com/css2?family=Alfa+Slab+One&family=Plus+Jakarta+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap'>"
104
+
105
+ bikin hero()
106
+ balikin "
107
+ <header class='hero'>
108
+ <p class='eyebrow'>project baru, rasa Medan</p>
109
+ <h1 class='headline'>SELAMAT DATANG DI<br><span>${name}</span></h1>
110
+ <p class='lede'>Halaman ini di-generate langsung oleh main.medan pake Medan-lang. Edit file itu, jalanin \\"npm start\\" lagi, terus refresh halaman ini.</p>
111
+ </header>
112
+ "
33
113
  siap
34
114
 
35
- bilang "5 + 7 = " + tambah(5, 7)
115
+ bikin stepItem(nomor, judul, kode)
116
+ balikin "<li><span class='step-no'>" + nomor + "</span><div><strong>" + judul + "</strong><code>" + kode + "</code></div></li>"
117
+ siap
118
+
119
+ bikin stepsSection()
120
+ modal items = []
121
+ tambahin(items, stepItem(1, "Edit kode kamu", "main.medan"))
122
+ tambahin(items, stepItem(2, "Generate ulang", "npm start"))
123
+ tambahin(items, stepItem(3, "Liat hasilnya", "buka landing.html di browser"))
124
+
125
+ balikin "
126
+ <section>
127
+ <h2>Mulai Dari Sini</h2>
128
+ <ol class='step-list'>" + gabung(items, "") + "</ol>
129
+ </section>
130
+ "
131
+ siap
36
132
 
37
- // while (gas)
38
- modal i = 0
39
- gas i < 3
40
- bilang "gas ke " + i
41
- i = i + 1
133
+ bikin kwCard(nama, arti)
134
+ balikin "<div class='kw-card'><h3>" + nama + "</h3><p>" + arti + "</p></div>"
42
135
  siap
43
136
 
44
- // ulang N kali
45
- ulang 3 kali
46
- bilang "mantap kali!"
137
+ bikin cheatsheetSection()
138
+ modal cards = []
139
+ tambahin(cards, kwCard("modal", "deklarasi variabel"))
140
+ tambahin(cards, kwCard("bilang", "cetak / print"))
141
+ tambahin(cards, kwCard("kalo / kalo gak", "if / else"))
142
+ tambahin(cards, kwCard("gas", "while"))
143
+ tambahin(cards, kwCard("ulang ... kali", "repeat N kali"))
144
+ tambahin(cards, kwCard("bikin / balikin", "fungsi / return"))
145
+ tambahin(cards, kwCard("mantap / lembek", "true / false"))
146
+ tambahin(cards, kwCard("kosong", "null"))
147
+ tambahin(cards, kwCard("[ ... ]", "array / list"))
148
+
149
+ balikin "
150
+ <section>
151
+ <h2>Contekan Keyword</h2>
152
+ <div class='kw-grid'>" + gabung(cards, "") + "</div>
153
+ </section>
154
+ "
47
155
  siap
48
156
 
49
- // array/list
50
- modal buah = ["mangga", "jeruk", "apel"]
51
- tambahin(buah, "duren")
52
- bilang buah
53
- bilang "panjang buah: " + panjang(buah)
157
+ bikin footerSection()
158
+ balikin "
159
+ <footer class='footer'>
160
+ <p>Dibuat pake <a href='https://www.npmjs.com/package/create-medan-app'>create-medan-app</a> &middot; powered by <a href='https://www.npmjs.com/package/medan-language'>medan-language</a></p>
161
+ </footer>
162
+ "
163
+ siap
164
+
165
+ modal halaman = "<title>${name}</title>" + fontLink + css() + "<div class='page'>" + hero() + stepsSection() + cheatsheetSection() + footerSection() + "</div>"
166
+
167
+ tulis("landing.html", halaman)
168
+ bilang "landing.html kelar digenerate. buka file itu di browser lu."
54
169
  `;
170
+ }
55
171
  export function readme(name) {
56
172
  return `# ${name}
57
173
 
@@ -61,9 +177,15 @@ Project Medan-lang, di-scaffold pakai \`create-medan-app\`.
61
177
 
62
178
  \`\`\`bash
63
179
  npm install
64
- npm start
180
+ npm run dev
65
181
  \`\`\`
66
182
 
183
+ \`npm run dev\` generate \`landing.html\` terus mantau \`main.medan\` — tiap kamu
184
+ save, otomatis di-generate ulang. Buka \`landing.html\` di browser, refresh
185
+ manual tiap abis edit & save.
186
+
187
+ Mau generate sekali doang tanpa watch mode, pakai \`npm start\`.
188
+
67
189
  ## Belajar lebih lanjut
68
190
 
69
191
  Referensi lengkap bahasa Medan-lang (semua keyword, tipe data, contoh) ada
@@ -71,4 +193,5 @@ di: https://www.npmjs.com/package/medan-language
71
193
  `;
72
194
  }
73
195
  export const GITIGNORE = `node_modules/
196
+ landing.html
74
197
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-medan-app",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Scaffold project Medan-lang baru, kayak 'npx create-next-app'.",
5
5
  "author": "Wilbert Law",
6
6
  "license": "MIT",