prosicht 1.3.0 → 1.4.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # prosicht
2
2
 
3
- Pro Sicht AI standartlarını ve sunum altyapısını projeye indiren CLI. Şablonlar [prosicht/ai-standards](https://github.com/prosicht/ai-standards) deposundan canlı olarak çekilir.
3
+ Pro Sicht AI standartlarını, sunum ve blog altyapısını projeye indiren CLI. Şablonlar [prosicht/ai-standards](https://github.com/prosicht/ai-standards) deposundan canlı olarak çekilir.
4
4
 
5
5
  ## Kullanım
6
6
 
@@ -10,18 +10,20 @@ npx prosicht init
10
10
  Önce ne yapmak istediğinizi sorar:
11
11
  - **Uygulama:** Proje şablonunu seçersiniz (web, landing, mobile, backend); kurallar `AGENTS.md` olarak iner.
12
12
  - **Sunum:** Etkileşimli, animasyonlu sunum altyapısı (çekirdek dosyalar, `AGENTS.md` ve çalışan bir örnek deste) bulunduğunuz klasöre iner.
13
+ - **Blog:** Etkileşimli, animasyonlu blog yazısı altyapısı (çekirdek dosyalar, `AGENTS.md` ve çalışan bir örnek yazı) bulunduğunuz klasöre iner.
13
14
 
14
15
  Şablonu doğrudan vermek için:
15
16
  ```bash
16
17
  npx prosicht init -t web
17
18
  npx prosicht init -t presentation
19
+ npx prosicht init -t blog
18
20
  ```
19
21
 
20
22
  Güncelleme (şablon, `AGENTS.md` başındaki etiketten otomatik tespit edilir):
21
23
  ```bash
22
24
  npx prosicht update
23
25
  ```
24
- Sunum klasörlerinde `update` yalnızca çekirdek dosyaları (`index.html`, `css/core/`, `js/core/`, `AGENTS.md`) yeniler; `js/scenes.js`, `js/sims/`, `css/theme.css`, `css/sims/`, `assets/` ve `sources.md` dokunulmadan kalır. Eski (1.x) klasör yapısındaki sunumlar onayla yeni yapıya taşınır (`--yes` sormadan taşır).
26
+ Sunum klasörlerinde `update` yalnızca çekirdek dosyaları (`index.html`, `css/core/`, `js/core/`, `AGENTS.md`) yeniler; `js/scenes.js`, `js/sims/`, `css/theme.css`, `css/sims/`, `assets/` ve `sources.md` dokunulmadan kalır. Blog klasörlerinde de yalnızca çekirdek yenilenir (`js/post.js`, `js/sims/`, `css/theme.css`, `css/sims/`, `assets/`, `sources.md` dokunulmaz). Eski (1.x) klasör yapısındaki sunumlar onayla yeni yapıya taşınır (`--yes` sormadan taşır). Sunum ve blog aynı çekirdek yollarını kullanır: bir kitin klasörüne diğeri yazılmadan önce onay istenir, `--yes` ile bu durumda işlem yapılmaz.
25
27
 
26
28
  ## Yayınlama
27
29
 
@@ -29,12 +31,12 @@ Sunum klasörlerinde `update` yalnızca çekirdek dosyaları (`index.html`, `css
29
31
  npx prosicht publish
30
32
  ```
31
33
  1. deck.prosicht.com'da hesap açın ve **Yeni sunum ekle** ile 32 karakterlik bir key alın.
32
- 2. Sunum klasöründe `npx prosicht publish` çalıştırın: **Sunum** → adres (varsayılan `deck.prosicht.com`) → key.
34
+ 2. Sunum veya blog klasöründe `npx prosicht publish` çalıştırın: **Sunum** / **Blog** (klasörden tespit edilip önceden seçilir) → adres (varsayılan `deck.prosicht.com`) → key.
33
35
  3. Link terminalde verilir. Key ve adres isterseniz `.prosicht/publish.json` içine kaydedilir (git dışı); sonraki yayınlar sormaz.
34
36
 
35
37
  Yalnızca `index.html`, `css/`, `js/` ve `assets/` yüklenir (en fazla 50 MB, dosya başına 25 MB, 500 dosya). `/` ile başlayan yollar için uyarı verilir. Kayıtlı key panelde yenilendiyse CLI yenisini sorar.
36
38
 
37
- Seçenekler: `--key <key>`, `--host <url>`, `-y` (soruları atla).
39
+ Seçenekler: `--key <key>`, `--host <url>`, `-y` (soruları atla; tür klasörden tespit edilir).
38
40
 
39
41
  ## Sunum hazırlama
40
42
 
@@ -45,12 +47,22 @@ python3 -m http.server 8000 # http://localhost:8000
45
47
  ```
46
48
  Ardından AI aracına konuyu söyleyin: *"KOBİ'ler için yapay zekâ konusunda 10 dakikalık sunum hazırla."*
47
49
 
50
+ ## Blog yazısı hazırlama
51
+
52
+ ```bash
53
+ mkdir yeni-yazi && cd yeni-yazi
54
+ npx prosicht init -t blog
55
+ python3 -m http.server 8000 # http://localhost:8000
56
+ ```
57
+ Görselleri `assets/images/` içine koyun ya da yolunu verin, sonra AI aracına konuyu söyleyin: *"Ev kahvesi demleme yöntemleri hakkında, gorseller/ klasöründeki fotoğrafları kullanarak etkileşimli bir blog yazısı hazırla."*
58
+
48
59
  ## Geliştirme
49
60
 
50
61
  Şablonları push etmeden yerel bir sunucudan denemek için (`PROSICHT_PUBLISH_URL` aynı şekilde yayın adresini değiştirir):
51
62
  ```bash
52
63
  cd ai-standards/templates && python3 -m http.server 8765
53
64
  PROSICHT_TEMPLATES_URL=http://127.0.0.1:8765 node /path/to/prosicht-cli/index.js init -t presentation
65
+ PROSICHT_TEMPLATES_URL=http://127.0.0.1:8765 node /path/to/prosicht-cli/index.js init -t blog
54
66
  ```
55
67
 
56
68
  Node.js 18 veya üstü gerekir.
package/index.js CHANGED
@@ -14,7 +14,8 @@ const BASE_URL = (process.env.PROSICHT_TEMPLATES_URL || 'https://raw.githubuserc
14
14
 
15
15
  const KINDS = {
16
16
  app: { title: 'Uygulama', description: 'Proje turune gore AGENTS.md (web, landing, mobile, backend)' },
17
- presentation: { title: 'Sunum', description: 'Etkilesimli, animasyonlu sunum altyapisi + AGENTS.md' }
17
+ presentation: { title: 'Sunum', description: 'Etkilesimli, animasyonlu sunum altyapisi + AGENTS.md' },
18
+ blog: { title: 'Blog', description: 'Etkilesimli, animasyonlu blog yazisi altyapisi + AGENTS.md' }
18
19
  };
19
20
 
20
21
  const APP_TEMPLATES = {
@@ -24,10 +25,35 @@ const APP_TEMPLATES = {
24
25
  backend: { name: 'Backend API Service', file: 'backend.md' }
25
26
  };
26
27
 
27
- // Sunum tek dosya degil, klasor: dosya listesi templates/presentation/manifest.json icinde
28
- const PRESENTATION = { key: 'presentation', name: 'Sunum Altyapisi', dir: 'presentation' };
28
+ // Sunum ve blog tek dosya degil, klasor: dosya listesi templates/<dir>/manifest.json icinde.
29
+ // owned: update'in dokunmadigi icerik dosyalari; migrate: kit 1.x klasorleri tasinabilir
30
+ const KITS = {
31
+ presentation: {
32
+ name: 'Sunum altyapisi',
33
+ dir: 'presentation',
34
+ migrate: true,
35
+ owned: 'Sunuma ait dosyalar (js/scenes.js, js/sims/, css/theme.css, css/sims/, assets/, sources.md) degistirilmedi.',
36
+ nextSteps: [
37
+ '1. python3 -m http.server 8000 -> http://localhost:8000 (ornek sunum)',
38
+ '2. AI aracina konuyu soyleyin: "<konu> hakkinda 10 dakikalik sunum hazirla"',
39
+ '3. npx prosicht publish -> deck.prosicht.com uzerinde yayinlayin'
40
+ ]
41
+ },
42
+ blog: {
43
+ name: 'Blog altyapisi',
44
+ dir: 'blog',
45
+ migrate: false,
46
+ owned: 'Yaziya ait dosyalar (js/post.js, js/sims/, css/theme.css, css/sims/, assets/, sources.md) degistirilmedi.',
47
+ nextSteps: [
48
+ '1. python3 -m http.server 8000 -> http://localhost:8000 (ornek yazi)',
49
+ '2. Gorselleri assets/images/ icine koyun ya da AI aracina yolunu verin',
50
+ '3. AI aracina konuyu soyleyin: "<konu> hakkinda, gorselleri kullanarak etkilesimli bir blog yazisi hazirla"',
51
+ '4. npx prosicht publish -> deck.prosicht.com uzerinde yayinlayin'
52
+ ]
53
+ }
54
+ };
29
55
 
30
- const TEMPLATE_KEYS = [...Object.keys(APP_TEMPLATES), PRESENTATION.key];
56
+ const TEMPLATE_KEYS = [...Object.keys(APP_TEMPLATES), ...Object.keys(KITS)];
31
57
  const TAG_PATTERN = /<!--\s*template:\s*(\w+)\s*-->\n?/;
32
58
 
33
59
  // Projedeki mevcut AGENTS.md dosyasından şablon türünü okur
@@ -80,11 +106,11 @@ async function askAppTemplate(message) {
80
106
  return response.template;
81
107
  }
82
108
 
83
- // Önce tür (Uygulama / Sunum), uygulamaysa ardından şablon sorulur
109
+ // Önce tür (Uygulama / Sunum / Blog), uygulamaysa ardından şablon sorulur
84
110
  async function askTemplate(message) {
85
111
  const kind = await askKind();
86
112
  if (!kind) return null;
87
- if (kind === 'presentation') return PRESENTATION.key;
113
+ if (KITS[kind]) return kind;
88
114
  return askAppTemplate(message);
89
115
  }
90
116
 
@@ -116,21 +142,34 @@ function resolveInsideCwd(relPath) {
116
142
  return target;
117
143
  }
118
144
 
119
- // init: çekirdek + başlangıç dosyaları (mevcut başlangıç dosyaları korunur)
120
- // update: yalnızca çekirdek dosyalar; sunum içeriğine dokunulmaz
121
- async function confirmMigration() {
122
- const response = await prompts({
123
- type: 'confirm',
124
- name: 'ok',
125
- initial: true,
126
- message: 'Bu sunum eski klasor yapisinda (kit 1.x). Yeni yapiya (index.html + css/ js/ assets/) tasinsin mi?'
127
- });
145
+ async function confirm(message, initial = true) {
146
+ const response = await prompts({ type: 'confirm', name: 'ok', initial, message });
128
147
  return Boolean(response.ok);
129
148
  }
130
149
 
131
- async function installPresentation(mode, options = {}) {
132
- const base = `${BASE_URL}/${PRESENTATION.dir}`;
133
- console.log(`\n[Pro Sicht] Sunum altyapisi ${mode === 'update' ? 'guncelleniyor' : 'indiriliyor'}...`);
150
+ // init: çekirdek + başlangıç dosyaları (mevcut başlangıç dosyaları korunur)
151
+ // update: yalnızca çekirdek dosyalar; sunum / yazı içeriğine dokunulmaz
152
+ async function installKit(key, mode, options = {}) {
153
+ const kit = KITS[key];
154
+ const base = `${BASE_URL}/${kit.dir}`;
155
+
156
+ // Sunum ve blog aynı çekirdek yollarını kullanır (index.html, js/core/app.js):
157
+ // başka bir kitin klasörüne yazmak onu bozar
158
+ const existing = detectExistingTemplate();
159
+ if (existing && existing !== key && (KITS[existing] || detectLayout(process.cwd()))) {
160
+ const label = KITS[existing] ? KITS[existing].name : `"${existing}" sablonu`;
161
+ if (options.yes) {
162
+ console.error(`Hata: Bu klasorde ${label} var; ${kit.name} cekirdek dosyalari ustune yazilmadi.`);
163
+ process.exitCode = 1;
164
+ return;
165
+ }
166
+ if (!(await confirm(`Bu klasorde ${label} var. ${kit.name} cekirdek dosyalari (index.html, js/core/ ...) ustune yazilsin mi?`, false))) {
167
+ console.log('Iptal edildi; hicbir dosya degistirilmedi.\n');
168
+ return;
169
+ }
170
+ }
171
+
172
+ console.log(`\n[Pro Sicht] ${kit.name} ${mode === 'update' ? 'guncelleniyor' : 'indiriliyor'}...`);
134
173
 
135
174
  try {
136
175
  const manifest = JSON.parse((await download(`${base}/manifest.json`)).toString('utf8'));
@@ -149,15 +188,15 @@ async function installPresentation(mode, options = {}) {
149
188
  const url = `${base}/${job.file.split('/').map(encodeURIComponent).join('/')}`;
150
189
  let data = await download(url);
151
190
  if (job.file === 'AGENTS.md') {
152
- data = Buffer.from(withTemplateTag(data.toString('utf8'), PRESENTATION.key), 'utf8');
191
+ data = Buffer.from(withTemplateTag(data.toString('utf8'), key), 'utf8');
153
192
  }
154
193
  return { ...job, data };
155
194
  }));
156
195
 
157
196
  // update: kit 1.x klasörünü önce yeni yapıya taşı (dosyalar indikten sonra, onayla).
158
197
  // Yalnızca uzaktaki kit de yeni yapıdaysa: eski manifest eski yollara yazar.
159
- if (mode === 'update' && detectLayout(process.cwd()) === 1 && Number(manifest.layout) >= 2) {
160
- if (!options.yes && !(await confirmMigration())) {
198
+ if (kit.migrate && mode === 'update' && detectLayout(process.cwd()) === 1 && Number(manifest.layout) >= 2) {
199
+ if (!options.yes && !(await confirm('Bu sunum eski klasor yapisinda (kit 1.x). Yeni yapiya (index.html + css/ js/ assets/) tasinsin mi?'))) {
161
200
  console.log('Iptal edildi; hicbir dosya degistirilmedi.\n');
162
201
  return;
163
202
  }
@@ -171,14 +210,13 @@ async function installPresentation(mode, options = {}) {
171
210
  }
172
211
  for (const job of kept) console.log(` = ${job.file} (mevcut, korundu)`);
173
212
 
174
- console.log(`Basarili: ${files.length} dosya yazildi (Sunum altyapisi v${manifest.version || '?'}).`);
213
+ console.log(`Basarili: ${files.length} dosya yazildi (${kit.name} v${manifest.version || '?'}).`);
175
214
  if (mode === 'init') {
176
215
  console.log('\nSonraki adimlar:');
177
- console.log(' 1. python3 -m http.server 8000 -> http://localhost:8000 (ornek sunum)');
178
- console.log(' 2. AI aracina konuyu soyleyin: "<konu> hakkinda 10 dakikalik sunum hazirla"');
179
- console.log(' 3. npx prosicht publish -> deck.prosicht.com uzerinde yayinlayin\n');
216
+ for (const step of kit.nextSteps) console.log(` ${step}`);
217
+ console.log('');
180
218
  } else {
181
- console.log('Sunuma ait dosyalar (js/scenes.js, js/sims/, css/theme.css, css/sims/, assets/, sources.md) degistirilmedi.\n');
219
+ console.log(`${kit.owned}\n`);
182
220
  }
183
221
  } catch (error) {
184
222
  console.error('Indirme hatasi:', error.message);
@@ -191,7 +229,7 @@ async function install(templateKey, mode, options = {}) {
191
229
  console.error(`Hata: Gecersiz sablon "${templateKey}". Gecerli: ${TEMPLATE_KEYS.join(', ')}`);
192
230
  process.exit(1);
193
231
  }
194
- if (templateKey === PRESENTATION.key) return installPresentation(mode, options);
232
+ if (KITS[templateKey]) return installKit(templateKey, mode, options);
195
233
  return fetchAndSaveTemplate(templateKey);
196
234
  }
197
235
 
@@ -202,7 +240,7 @@ program
202
240
 
203
241
  program
204
242
  .command('init')
205
- .description('Projeye AI standartlarini (AGENTS.md) veya sunum altyapisini indirir')
243
+ .description('Projeye AI standartlarini (AGENTS.md), sunum veya blog altyapisini indirir')
206
244
  .option('-t, --template <type>', `Sablon turu (${TEMPLATE_KEYS.join(', ')})`)
207
245
  .action(async (options) => {
208
246
  let templateKey = options.template;
@@ -217,9 +255,9 @@ program
217
255
 
218
256
  program
219
257
  .command('update')
220
- .description('Projedeki AGENTS.md (ve sunum altyapisinin cekirdek dosyalarini) tespit edip gunceller')
258
+ .description('Projedeki AGENTS.md (ve sunum / blog altyapisinin cekirdek dosyalarini) tespit edip gunceller')
221
259
  .option('-t, --template <type>', 'Sablon turunu zorla belirle')
222
- .option('-y, --yes', 'Eski sunum yapisini sormadan yeni yapiya tasi')
260
+ .option('-y, --yes', 'Sormadan devam et: eski sunum yapisini yeni yapiya tasir')
223
261
  .action(async (options) => {
224
262
  let templateKey = options.template;
225
263
 
@@ -240,10 +278,10 @@ program
240
278
 
241
279
  program
242
280
  .command('publish')
243
- .description('Sunumu deck.prosicht.com uzerinde yayinlar ve linki verir')
281
+ .description('Sunumu veya blog yazisini deck.prosicht.com uzerinde yayinlar ve linki verir')
244
282
  .option('-k, --key <key>', 'Panelden alinan 32 karakterlik yayin keyi')
245
283
  .option('--host <url>', 'Yayin adresi (varsayilan: https://deck.prosicht.com)')
246
- .option('-y, --yes', 'Sorulari atla: Sunum secilir, key kaydedilir')
284
+ .option('-y, --yes', 'Sorulari atla: tur klasorden tespit edilir, key kaydedilir')
247
285
  .action((options) => publish(options));
248
286
 
249
287
  program.parse(process.argv);
package/lib/files.js CHANGED
@@ -59,14 +59,23 @@ function findAbsolutePaths(files) {
59
59
  return hits;
60
60
  }
61
61
 
62
- // js/scenes.js içindeki deck.title (panelde ve paylaşım önizlemesinde görünür)
63
- function readDeckTitle(root) {
64
- const file = path.join(root, 'js', 'scenes.js');
62
+ // Başlık panelde ve paylaşım önizlemesinde görünür: sunumda js/scenes.js
63
+ // içindeki deck.title, blogda js/post.js içindeki post.title (ilk title alanı)
64
+ const CONTENT = { presentation: ['scenes.js', 'deck'], blog: ['post.js', 'post'] };
65
+
66
+ function readTitle(root, kind = 'presentation') {
67
+ const [fileName, name] = CONTENT[kind] || CONTENT.presentation;
68
+ const file = path.join(root, 'js', fileName);
65
69
  if (!fs.existsSync(file)) return null;
66
70
  const source = fs.readFileSync(file, 'utf8');
67
- const deck = source.match(/export\s+const\s+deck\s*=\s*\{([\s\S]*?)\};/);
68
- const title = deck && deck[1].match(/\btitle\s*:\s*(['"`])((?:(?!\1).)*)\1/);
69
- return title ? title[2].trim().slice(0, 120) : null;
71
+ // önce satır başındaki kapanış (iç içe nesneler), sonra tek satırlık yazım
72
+ const head = `export\\s+const\\s+${name}\\s*=\\s*\\{([\\s\\S]*?)`;
73
+ const block = source.match(new RegExp(`${head}\\n\\};`)) || source.match(new RegExp(`${head}\\};`));
74
+ const title = block && block[1].match(/\btitle\s*:\s*(['"`])((?:(?!\1).)*)\1/);
75
+ if (!title) return null;
76
+ // <br> ve *vurgu* işaretleri başlıkta görünmesin
77
+ const plain = title[2].replace(/<br\s*\/?>/gi, ' ').replace(/\*/g, '').replace(/\s+/g, ' ').trim();
78
+ return plain.slice(0, 120) || null;
70
79
  }
71
80
 
72
81
  function formatBytes(n) {
@@ -75,4 +84,4 @@ function formatBytes(n) {
75
84
  return `${(n / 1024 / 1024).toFixed(1)} MB`;
76
85
  }
77
86
 
78
- module.exports = { collectFiles, findAbsolutePaths, readDeckTitle, formatBytes, MIME_TYPES };
87
+ module.exports = { collectFiles, findAbsolutePaths, readTitle, formatBytes, MIME_TYPES };
package/lib/layout.js CHANGED
@@ -1,8 +1,8 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
- // Sunum klasör yapıları: 1 = kök dizinde app.js/sims/styles (kit 1.x),
5
- // 2 = index.html + css/ js/ assets/ (kit 2.x). 0 = sunum değil.
4
+ // Kit klasör yapıları: 1 = kök dizinde app.js/sims/styles (sunum kit 1.x),
5
+ // 2 = index.html + css/ js/ assets/ (sunum kit 2.x ve blog). 0 = kit değil.
6
6
  function detectLayout(root) {
7
7
  const has = (rel) => fs.existsSync(path.join(root, rel));
8
8
  if (has('js/core/app.js')) return 2;
@@ -10,6 +10,14 @@ function detectLayout(root) {
10
10
  return 0;
11
11
  }
12
12
 
13
+ // 2.x klasörünün türü: içerik dosyasından (blog: js/post.js, sunum: js/scenes.js)
14
+ function detectKit(root) {
15
+ const has = (rel) => fs.existsSync(path.join(root, rel));
16
+ if (has('js/post.js')) return 'blog';
17
+ if (has('js/scenes.js')) return 'presentation';
18
+ return null;
19
+ }
20
+
13
21
  // Proje klasöründeki .gitignore'a satır ekler (yoksa oluşturur)
14
22
  function ensureGitignore(root, line) {
15
23
  const file = path.join(root, '.gitignore');
@@ -20,4 +28,4 @@ function ensureGitignore(root, line) {
20
28
  return true;
21
29
  }
22
30
 
23
- module.exports = { detectLayout, ensureGitignore };
31
+ module.exports = { detectLayout, detectKit, ensureGitignore };
package/lib/publish.js CHANGED
@@ -1,8 +1,8 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
  const prompts = require('prompts');
4
- const { detectLayout, ensureGitignore } = require('./layout');
5
- const { collectFiles, findAbsolutePaths, readDeckTitle, formatBytes, MIME_TYPES } = require('./files');
4
+ const { detectLayout, detectKit, ensureGitignore } = require('./layout');
5
+ const { collectFiles, findAbsolutePaths, readTitle, formatBytes, MIME_TYPES } = require('./files');
6
6
 
7
7
  const DEFAULT_HOST = (process.env.PROSICHT_PUBLISH_URL || 'https://deck.prosicht.com').replace(/\/+$/, '');
8
8
  const KEY_PATTERN = /^[A-Za-z0-9]{32}$/;
@@ -95,7 +95,7 @@ async function upload(host, key, files, title) {
95
95
 
96
96
  function explain(status, body) {
97
97
  if (status === 401) fail('Key gecersiz veya yenilenmis. Panelden guncel keyi alin.');
98
- if (status === 413) fail('Sunum boyut sinirini asiyor (en fazla 50 MB).');
98
+ if (status === 413) fail('Dosyalar boyut sinirini asiyor (en fazla 50 MB).');
99
99
  if (status === 400 || status === 422) fail(body.error || 'Dosyalar reddedildi.', body.details || []);
100
100
  fail(`Sunucu hatasi (HTTP ${status})${body.error ? `: ${body.error}` : ''}`);
101
101
  }
@@ -103,18 +103,26 @@ function explain(status, body) {
103
103
  async function publish(options = {}) {
104
104
  const root = process.cwd();
105
105
 
106
- const kind = options.yes ? 'presentation' : await ask({
106
+ const detected = detectKit(root);
107
+ const choices = [
108
+ { title: 'Sunum', value: 'presentation' },
109
+ { title: 'Blog', value: 'blog' },
110
+ { title: 'Uygulama', value: 'app', disabled: true, description: 'yakinda' }
111
+ ];
112
+ const kind = options.yes ? (detected || 'presentation') : await ask({
107
113
  type: 'select', name: 'kind', message: 'Ne yayinlamak istiyorsunuz?',
108
- choices: [
109
- { title: 'Sunum', value: 'presentation' },
110
- { title: 'Uygulama', value: 'app', disabled: true, description: 'yakinda' }
111
- ]
114
+ choices,
115
+ initial: Math.max(0, choices.findIndex((c) => c.value === detected))
112
116
  });
113
- if (kind !== 'presentation') process.exit(0);
117
+ if (kind !== 'presentation' && kind !== 'blog') process.exit(0);
118
+ const label = kind === 'blog' ? 'blog yazisi' : 'sunum';
114
119
 
115
120
  const layout = detectLayout(root);
116
121
  if (layout === 1) fail('Bu sunum eski klasor yapisinda. Once `npx prosicht update` ile yeni yapiya tasiyin.');
117
- if (layout === 0) fail('Bu klasorde bir sunum bulunamadi (index.html ve js/core/app.js gerekli). Sunum klasorunde calistirin.');
122
+ if (layout === 0) fail(`Bu klasorde bir ${label} bulunamadi (index.html ve js/core/app.js gerekli). ${kind === 'blog' ? 'Blog' : 'Sunum'} klasorunde calistirin.`);
123
+ if (detected && detected !== kind) {
124
+ fail(`Bu klasordeki icerik bir ${detected === 'blog' ? 'blog yazisi' : 'sunum'}; "${kind === 'blog' ? 'Blog' : 'Sunum'}" secildi.`);
125
+ }
118
126
 
119
127
  const { files, total, errors } = collectFiles(root);
120
128
  if (errors.length) fail('Yayin oncesi kontrol basarisiz:', errors);
@@ -129,7 +137,7 @@ async function publish(options = {}) {
129
137
  let key = await chooseKey(options.key ? null : config.key, options.key);
130
138
  if (!key) process.exit(0);
131
139
 
132
- const title = readDeckTitle(root);
140
+ const title = readTitle(root, kind);
133
141
  const send = async () => {
134
142
  console.log(`\n[Pro Sicht] ${files.length} dosya (${formatBytes(total)}) yukleniyor...`);
135
143
  try {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "prosicht",
3
- "version": "1.3.0",
4
- "description": "Pro Sicht AI Standards CLI: AGENTS.md sablonlari ve sunum altyapisi",
3
+ "version": "1.4.0",
4
+ "description": "Pro Sicht AI Standards CLI: AGENTS.md sablonlari, sunum ve blog altyapisi",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "prosicht": "./index.js"
@@ -21,7 +21,8 @@
21
21
  "agents",
22
22
  "cli",
23
23
  "prosicht",
24
- "presentation"
24
+ "presentation",
25
+ "blog"
25
26
  ],
26
27
  "author": "Pro Sicht",
27
28
  "license": "MIT",