SenY commited on
Commit
4b4719a
·
verified ·
1 Parent(s): 70433fb

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +456 -19
index.html CHANGED
@@ -1,19 +1,456 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ja">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Gemini Prompt Generator</title>
8
+ <link href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
10
+ crossorigin="anonymous">
11
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/json5/2.2.3/index.min.js"
12
+ integrity="sha512-44jdhc+R2TFfzBflS3/dGNEABiNUxBkkrqwO7GWTvGsj3HkQNr3GESvI9PUvAxmqxSnTosR0Ij9y3+o+6J1hig=="
13
+ crossorigin="anonymous" referrerpolicy="no-referrer"></script>
14
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/i18next/23.14.0/i18next.min.js"
15
+ integrity="sha512-8ANNUVMWPf6aWGXZqDhS4OXJWBCRxfjlW7lKfupuiG1FZah0ST6LiI2qnEb1L5mp05v/+0hn3s2FO4EwIbIgfA=="
16
+ crossorigin="anonymous" referrerpolicy="no-referrer"></script>
17
+ <script
18
+ src="https://cdnjs.cloudflare.com/ajax/libs/i18next-browser-languagedetector/8.0.0/i18nextBrowserLanguageDetector.min.js"
19
+ integrity="sha512-8/RTkAM23B3lQzi6fmPs+Yf9qhIHzrzRpeSZsBsQ8OEmo95mbVp+68dB647VDCuyQIBbF+OIbS9b30aTWUkoog=="
20
+ crossorigin="anonymous" referrerpolicy="no-referrer"></script>
21
+ </head>
22
+
23
+ <body data-bs-theme="dark">
24
+ <div class="container">
25
+ <div class="row m-0 border-start border-end border-2">
26
+ <div class="row">
27
+ <div id="inputQuery" class="col-md-6 mb-4">
28
+ <div class="card h-100">
29
+ <div class="card-header bg-primary text-white">
30
+ <h5 class="mb-0" id="inputQueryTitle">入力クエリ</h5>
31
+ </div>
32
+ <div class="card-body">
33
+ <div class="form-group">
34
+ <textarea class="form-control" id="query" rows="16"
35
+ placeholder="ここにクエリを入力してください"></textarea>
36
+ </div>
37
+ </div>
38
+ <div class="card-footer d-flex align-items-center">
39
+ <button id="generatePromptButton" class="btn btn-primary flex-grow-1 me-2"
40
+ onclick="generatePrompt()">
41
+ <i class="fas fa-magic me-2"></i><span id="generateButtonText">プロンプト生成</span>
42
+ <i class="fas fa-spinner fa-spin me-2 d-none" id="loading"></i>
43
+ </button>
44
+ <div class="form-check form-switch" id="splitStringsSwitchWrapper">
45
+ <input class="form-check-input" type="checkbox" id="splitStringsSwitch">
46
+ <label class="form-check-label" for="splitStringsSwitch">
47
+ <i class="fas fa-shield-alt" id="splitStrings">分割送信</i>
48
+ </label>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <div id="outputPrompt" class="col-md-6 mb-4">
54
+ <div class="card h-100">
55
+ <div class="card-header bg-success text-white">
56
+ <h5 class="mb-0" id="outputPromptTitle">生成されたプロンプト</h5>
57
+ </div>
58
+ <div class="card-body">
59
+ <div class="form-group">
60
+ <textarea class="form-control" id="promptEn" rows="8"
61
+ placeholder="英語のプロンプトがここに表示されます"></textarea>
62
+ </div>
63
+ <div class="form-group mt-3">
64
+ <textarea class="form-control" id="promptMyLanguage" rows="8" disabled
65
+ placeholder="日本訳がここに表示されます"></textarea>
66
+ </div>
67
+ </div>
68
+ </div>
69
+ </div>
70
+ <div class="col-12 mb-4">
71
+ <div class="card">
72
+ <div class="card-header bg-primary text-white">
73
+ <h5 class="mb-0" id="settingsTitle">設定</h5>
74
+ </div>
75
+ <div class="card-body">
76
+ <div class="form-group mb-3">
77
+ <label for="apiKey" class="form-label" id="apiKeyLabel"><a
78
+ href="https://aistudio.google.com/app/apikey?hl=ja"
79
+ target="_blank">APIキー</a></label>
80
+ <input type="text" class="form-control" id="apiKey" placeholder="APIキーを入力してください">
81
+ </div>
82
+ <div class="form-group">
83
+ <label for="characterCount" class="form-label" id="characterCountLabel">文字数</label>
84
+ <input type="number" value="320" class="form-control" id="characterCount"
85
+ placeholder="生成するプロンプトの文字数を入力してください">
86
+ </div>
87
+ <div class="form-group">
88
+ <label for="languageSelect" class="form-label" id="languageSelectLabel">Language</label>
89
+ <select class="form-select" id="languageSelect">
90
+ <option value="ja">日本語</option>
91
+ <option value="en">English</option>
92
+ <option value="zh">中文</option>
93
+ <option value="ko">한국어</option>
94
+ <option value="fr">Français</option>
95
+ <option value="es">Español</option>
96
+ <option value="de">Deutsch</option>
97
+ <option value="it">Italiano</option>
98
+ </select>
99
+ </div>
100
+ </div>
101
+ </div>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ <script>
107
+ let language;
108
+ const translations = {
109
+ ja: {
110
+ inputQueryTitle: "入力クエリ",
111
+ generateButtonText: "プロンプト生成",
112
+ splitStrings: "分割送信",
113
+ outputPromptTitle: "生成されたプロンプト",
114
+ settingsTitle: "設定",
115
+ apiKeyLabel: "APIキー",
116
+ characterCountLabel: "文字数",
117
+ languageSelectLabel: "言語",
118
+ promptEnPlaceholder: "英語のプロンプトがここに表示されます",
119
+ promptMyLanguagePlaceholder: "日本訳がここに表示されます",
120
+ apiKeyPlaceholder: "APIキーを入力してください",
121
+ characterCountPlaceholder: "生成するプロンプトの文字数を入力してください"
122
+ },
123
+ en: {
124
+ inputQueryTitle: "Input Query",
125
+ generateButtonText: "Generate Prompt",
126
+ splitStrings: "Split Strings",
127
+ outputPromptTitle: "Generated Prompt",
128
+ settingsTitle: "Settings",
129
+ apiKeyLabel: "API Key",
130
+ characterCountLabel: "Character Count",
131
+ languageSelectLabel: "Language",
132
+ promptEnPlaceholder: "English prompt will be displayed here",
133
+ promptMyLanguagePlaceholder: "Translation will be displayed here",
134
+ apiKeyPlaceholder: "Enter your API key",
135
+ characterCountPlaceholder: "Enter the number of characters for the generated prompt"
136
+ },
137
+ zh: {
138
+ inputQueryTitle: "输入查询",
139
+ generateButtonText: "生成提示",
140
+ splitStrings: "分割字符串",
141
+ outputPromptTitle: "生成的提示",
142
+ settingsTitle: "设置",
143
+ apiKeyLabel: "API密钥",
144
+ characterCountLabel: "字符数",
145
+ languageSelectLabel: "语言",
146
+ promptEnPlaceholder: "英文提示将显示在这里",
147
+ promptMyLanguagePlaceholder: "翻译将显示在这里",
148
+ apiKeyPlaceholder: "请输入您的API密钥",
149
+ characterCountPlaceholder: "请输入生成提示的字符数"
150
+ },
151
+ ko: {
152
+ inputQueryTitle: "입력 쿼리",
153
+ generateButtonText: "프롬프트 생성",
154
+ splitStrings: "문자열 분할",
155
+ outputPromptTitle: "생성된 프롬프트",
156
+ settingsTitle: "설정",
157
+ apiKeyLabel: "API 키",
158
+ characterCountLabel: "문자 수",
159
+ languageSelectLabel: "언어",
160
+ promptEnPlaceholder: "영어 프롬프트가 여기에 표시됩니다",
161
+ promptMyLanguagePlaceholder: "번역이 여기에 표시됩니다",
162
+ apiKeyPlaceholder: "API 키를 입력하세요",
163
+ characterCountPlaceholder: "생성할 프롬프트의 문자 수를 입력하세요"
164
+ },
165
+ fr: {
166
+ inputQueryTitle: "Requête d'entrée",
167
+ generateButtonText: "Générer le prompt",
168
+ splitStrings: "Diviser les chaînes",
169
+ outputPromptTitle: "Prompt généré",
170
+ settingsTitle: "Paramètres",
171
+ apiKeyLabel: "Clé API",
172
+ characterCountLabel: "Nombre de caractères",
173
+ languageSelectLabel: "Langue",
174
+ promptEnPlaceholder: "Le prompt en anglais s'affichera ici",
175
+ promptMyLanguagePlaceholder: "La traduction s'affichera ici",
176
+ apiKeyPlaceholder: "Entrez votre clé API",
177
+ characterCountPlaceholder: "Entrez le nombre de caractères pour le prompt généré"
178
+ },
179
+ es: {
180
+ inputQueryTitle: "Consulta de entrada",
181
+ generateButtonText: "Generar prompt",
182
+ splitStrings: "Dividir cadenas",
183
+ outputPromptTitle: "Prompt generado",
184
+ settingsTitle: "Configuración",
185
+ apiKeyLabel: "Clave API",
186
+ characterCountLabel: "Recuento de caracteres",
187
+ languageSelectLabel: "Idioma",
188
+ promptEnPlaceholder: "El prompt en inglés se mostrará aquí",
189
+ promptMyLanguagePlaceholder: "La traducción se mostrará aquí",
190
+ apiKeyPlaceholder: "Ingrese su clave API",
191
+ characterCountPlaceholder: "Ingrese el número de caracteres para el prompt generado"
192
+ },
193
+ de: {
194
+ inputQueryTitle: "Eingabeabfrage",
195
+ generateButtonText: "Prompt generieren",
196
+ splitStrings: "Zeichenketten aufteilen",
197
+ outputPromptTitle: "Generierter Prompt",
198
+ settingsTitle: "Einstellungen",
199
+ apiKeyLabel: "API-Schlüssel",
200
+ characterCountLabel: "Zeichenanzahl",
201
+ languageSelectLabel: "Sprache",
202
+ promptEnPlaceholder: "Der englische Prompt wird hier angezeigt",
203
+ promptMyLanguagePlaceholder: "Die Übersetzung wird hier angezeigt",
204
+ apiKeyPlaceholder: "Geben Sie Ihren API-Schlüssel ein",
205
+ characterCountPlaceholder: "Geben Sie die Anzahl der Zeichen für den generierten Prompt ein"
206
+ },
207
+ it: {
208
+ inputQueryTitle: "Query di input",
209
+ generateButtonText: "Genera prompt",
210
+ splitStrings: "Dividi stringhe",
211
+ outputPromptTitle: "Prompt generato",
212
+ settingsTitle: "Impostazioni",
213
+ apiKeyLabel: "Chiave API",
214
+ characterCountLabel: "Conteggio caratteri",
215
+ languageSelectLabel: "Lingua",
216
+ promptEnPlaceholder: "Il prompt in inglese verrà visualizzato qui",
217
+ promptMyLanguagePlaceholder: "La traduzione verrà visualizzata qui",
218
+ apiKeyPlaceholder: "Inserisci la tua chiave API",
219
+ characterCountPlaceholder: "Inserisci il numero di caratteri per il prompt generato"
220
+ }
221
+ }
222
+ const resources = {
223
+ ja: {
224
+ translation: translations.ja
225
+ },
226
+ en: {
227
+ translation: translations.en
228
+ },
229
+ zh: {
230
+ translation: translations.zh
231
+ },
232
+ ko: {
233
+ translation: translations.ko
234
+ },
235
+ fr: {
236
+ translation: translations.fr
237
+ },
238
+ es: {
239
+ translation: translations.es
240
+ },
241
+ de: {
242
+ translation: translations.de
243
+ },
244
+ it: {
245
+ translation: translations.it
246
+ }
247
+ }
248
+
249
+ // 既存のスクリプトの前に追加
250
+ document.addEventListener('DOMContentLoaded', function () {
251
+ i18next
252
+ .use(i18nextBrowserLanguageDetector)
253
+ .init({
254
+ fallbackLng: 'ja', // デフォルト言語
255
+ resources: resources
256
+ })
257
+ .then(function (t) {
258
+ document.getElementById('languageSelect').value = i18next.language;
259
+ document.getElementById('languageSelect').dispatchEvent(new Event('change'));
260
+ });
261
+ });
262
+
263
+ function updateContent() {
264
+ // 各要素のテキストを更新
265
+ document.getElementById('inputQueryTitle').textContent = i18next.t('inputQueryTitle');
266
+ document.getElementById('generateButtonText').textContent = i18next.t('generateButtonText');
267
+ document.getElementById('splitStrings').textContent = i18next.t('splitStrings');
268
+ document.getElementById('outputPromptTitle').textContent = i18next.t('outputPromptTitle');
269
+ document.getElementById('settingsTitle').textContent = i18next.t('settingsTitle');
270
+ document.getElementById('apiKeyLabel').textContent = i18next.t('apiKeyLabel');
271
+ document.getElementById('characterCountLabel').textContent = i18next.t('characterCountLabel');
272
+ document.getElementById('languageSelectLabel').textContent = i18next.t('languageSelectLabel');
273
+
274
+ // プレースホルダーを更新
275
+ document.getElementById('promptEn').placeholder = i18next.t('promptEnPlaceholder');
276
+ document.getElementById('promptMyLanguage').placeholder = i18next.t('promptMyLanguagePlaceholder');
277
+ document.getElementById('apiKey').placeholder = i18next.t('apiKeyPlaceholder');
278
+ document.getElementById('characterCount').placeholder = i18next.t('characterCountPlaceholder');
279
+ }
280
+
281
+ // 言語切り替え関数
282
+ function changeLang(language) {
283
+ i18next.changeLanguage(language, (err, t) => {
284
+ if (err) return console.error('言語切り替えエラー', err);
285
+ updateContent();
286
+ });
287
+ }
288
+
289
+ document.getElementById('languageSelect').addEventListener('change', function () {
290
+ changeLang(this.value);
291
+ });
292
+ </script>
293
+
294
+ <script>
295
+ function generatePrompt() {
296
+ if (!document.getElementById('apiKey').value) {
297
+ alert("APIキーを入力してください");
298
+ return;
299
+ }
300
+ let query = document.getElementById('query').value;
301
+ let textFormat = 'str';
302
+
303
+ if (document.getElementById('splitStringsSwitch').checked) {
304
+ query = Array.from(document.getElementById('query').value).join(":::");
305
+ //textFormat = 'array, # テキストは1character(not word)ずつ格納した配列にして返すこと。 Example: ["I", "t", " ", "i", "s", " ", "a", " ", "p", "e", "n", "."], ["こ", "れ", "は", " ", "ペ", "ン", "で", "す", "。"], ';
306
+ }
307
+
308
+ let anotherLanguage = "";
309
+
310
+ if (!["en", "ja"].includes(i18next.language)) {
311
+ anotherLanguage = `,
312
+ {
313
+ "language": "${i18next.language}",
314
+ "text": ${textFormat}
315
+ }`;
316
+ }
317
+
318
+
319
+ const text = `「 ${query} 」をテーマに画像生成AIに送るプロンプトを考えてください。
320
+ 背景や小物のディテイール、構図、視覚効果など視覚的な情報のみに言及すること。
321
+ その上で長文を日本語と英語で返信してください。
322
+ 返答は以下のフォーマットのjson形式でのみ行う。json以外の内容をレスポンスに含めないこと。
323
+ \`\`\`json
324
+ {
325
+ "results": [
326
+ {
327
+ "language": "en",
328
+ "text": ${textFormat} # ${document.getElementById('characterCount').value}文字程度,
329
+ },
330
+ {
331
+ "language": "ja",
332
+ "text": ${textFormat}
333
+ }${anotherLanguage}
334
+ ]
335
+ }
336
+ \`\`\`
337
+ `;
338
+ const url = "https://generativelanguage.googleapis.com/v1/models/gemini-1.5-flash:generateContent?key=" + document.getElementById('apiKey').value;
339
+ const payload = {
340
+ contents: [
341
+ {
342
+ parts: [
343
+ { text: text }
344
+ ]
345
+ }
346
+ ],
347
+ generation_config: {
348
+ max_output_tokens: 4095,
349
+ temperature: 1,
350
+ top_p: 1,
351
+ top_k: 32
352
+ }
353
+ };
354
+
355
+ console.debug(text);
356
+
357
+ // fetchを使用してリクエストを送信
358
+ // ローディングアイコンを表示
359
+ document.getElementById('loading').classList.remove('d-none');
360
+ // generatePromptボタンを無効化
361
+ document.getElementById('generatePromptButton').disabled = true;
362
+ document.getElementById('generatePromptButton').classList.remove('btn-primary');
363
+ document.getElementById('generatePromptButton').classList.remove('btn-danger');
364
+ document.getElementById('generatePromptButton').classList.add('btn-secondary');
365
+ fetch(url, {
366
+ method: 'POST',
367
+ headers: {
368
+ 'Content-Type': 'application/json'
369
+ },
370
+ body: JSON.stringify(payload)
371
+ })
372
+ .then(response => response.json())
373
+ .then(data => {
374
+ console.debug(data.candidates[0].content);
375
+ // レスポンスからテキストを抽出
376
+ const responseText = data.candidates[0].content.parts[0].text
377
+ console.debug(responseText);
378
+
379
+ let jsonString = responseText.replace(/```json|```/g, '').trim();
380
+ console.debug(jsonString);
381
+ // JSONをパース
382
+ const parsedData = JSON5.parse(jsonString);
383
+
384
+ // 結果を表示
385
+ console.debug(parsedData);
386
+ let promptEn = parsedData.results.find(x => x.language === 'en').text;
387
+ let promptMyLanguage = parsedData.results.find(x => x.language === i18next.language).text;
388
+ [promptEn, promptMyLanguage] = [promptEn, promptMyLanguage].map(x => {
389
+ return Array.isArray(x) ? x.join("") : x;
390
+ });
391
+ document.getElementById('promptEn').value = promptEn.replace(/\. ?/g, '.\n\n');
392
+ document.getElementById('promptEn').value = document.getElementById('promptEn').value.replace(/^ */g, '');
393
+ document.getElementById('promptMyLanguage').value = promptMyLanguage.replace(/\。 ?/g, '。\n\n');
394
+
395
+
396
+ // ローディングアイコンを非表示
397
+ document.getElementById('loading').classList.add('d-none');
398
+ document.getElementById('generatePromptButton').disabled = false;
399
+ document.getElementById('generatePromptButton').classList.remove('btn-secondary');
400
+ document.getElementById('generatePromptButton').classList.add('btn-primary');
401
+ saveToUserStorage(true);
402
+ })
403
+ .catch(error => {
404
+ console.error(error);
405
+ // エラー時もローディングアイコンを非表示
406
+ document.getElementById('loading').classList.add('d-none');
407
+ document.getElementById('generatePromptButton').disabled = false;
408
+ document.getElementById('generatePromptButton').classList.remove('btn-secondary');
409
+ document.getElementById('generatePromptButton').classList.add('btn-danger');
410
+ });
411
+ };
412
+ let lastSaveTimestamp = new Date();
413
+ function saveToUserStorage(force = false) {
414
+ const currentTime = new Date();
415
+ if (!force && currentTime - lastSaveTimestamp < 5000) {
416
+ return;
417
+ }
418
+ const data = {};
419
+ document.querySelectorAll('input, textarea').forEach(input => {
420
+ data[input.id] = input.value;
421
+ });
422
+ localStorage.setItem('gemini_prompt', JSON.stringify(data));
423
+ lastSaveTimestamp = currentTime;
424
+ return true;
425
+ }
426
+ function loadFromUserStorage() {
427
+ const data = JSON.parse(localStorage.getItem('gemini_prompt')) || {};
428
+ document.querySelectorAll('input, textarea').forEach(input => {
429
+ let v = data[input.id] || "";
430
+ if (v) {
431
+ if (input.type === "number") {
432
+ v = parseInt(v);
433
+ }
434
+ input.value = v;
435
+ }
436
+ });
437
+ }
438
+ loadFromUserStorage();
439
+ // 60秒ごとに自動保存を実行
440
+ setInterval(() => {
441
+ saveToUserStorage();
442
+ }, 60000);
443
+ document.querySelectorAll('input, textarea').forEach(input => {
444
+ input.addEventListener('input', saveToUserStorage);
445
+ });
446
+ // Ctrl+Enterでプロンプト生成を実行する
447
+ document.addEventListener('keydown', function (event) {
448
+ if (event.ctrlKey && event.key === 'Enter') {
449
+ event.preventDefault(); // デフォルトの動作を防ぐ
450
+ generatePrompt(); // プロンプト生成関数を呼び出す
451
+ }
452
+ });
453
+ </script>
454
+ </body>
455
+
456
+ </html>