Spaces:
Running
Running
| <html lang="ja"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Gemini Prompt Generator</title> | |
| <!-- | |
| ファイル構成と役割: | |
| 1. index.html | |
| - メインのUIレイアウト | |
| - スタイル定義 | |
| - 外部リソースの読み込み | |
| 2. prompt.js | |
| - Gemini APIとの通信 | |
| - プロンプト生成のロジック | |
| - モデル管理 | |
| ※ API関連の機能追加はこのファイルに | |
| 3. storage.js | |
| - ローカルストレージの管理 | |
| - フォームデータの永続化 | |
| ※ データ保存関連の機能はこのファイルに | |
| 4. translation.js | |
| - 多言語対応 | |
| - i18next設定 | |
| - 言語リソース | |
| ※ 新しい言語や翻訳文字列の追加はこのファイルに | |
| 5. control.js | |
| - UIイベント管理 | |
| - レイアウト制御 | |
| - グローバルショートカット | |
| ※ UI操作に関する機能追加はこのファイルに | |
| 6. history.js | |
| - 履歴管理 | |
| - 履歴検索 | |
| - 履歴UI | |
| ※ 履歴関連の機能追加はこのファイルに | |
| 開発規約: | |
| 1. 各ファイルの責務を明確に分離し、機能追加は適切なファイルに行う | |
| 2. UIコンポーネントの追加は index.html に | |
| 3. スタイルの追加は index.html の <style> タグ内に | |
| 4. 新しい機能は既存のファイル構成に従い、適切なファイルに実装 | |
| 5. 共通で使用する定数や設定は storage.js で管理 | |
| 6. 多言語対応が必要な文字列は必ず translation.js に追加 | |
| --> | |
| <link href="https://unpkg.com/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" | |
| crossorigin="anonymous"> | |
| <style> | |
| textarea.form-control { | |
| min-height: 25vh; | |
| } | |
| #sidebar-container { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 0; /* 初期幅を0に設定 */ | |
| height: 100%; | |
| display: flex; | |
| z-index: 1000; | |
| transition: width 0.3s ease; | |
| } | |
| #sidebar { | |
| flex-grow: 1; | |
| overflow-y: auto; | |
| background-color: #343a40; | |
| } | |
| #sidebar-resizer { | |
| width: 10px; | |
| cursor: ew-resize; | |
| background-color: #2c3136; | |
| } | |
| #content { | |
| margin-left: 0; /* 初期マージンを0に設定 */ | |
| transition: margin-left 0.3s ease; | |
| } | |
| #historyContainer { | |
| max-height: none; | |
| /* 最大高さの制限を解除 */ | |
| overflow-y: visible; | |
| /* スクロールバーを削除 */ | |
| } | |
| #historyContainer::-webkit-scrollbar { | |
| width: 0; | |
| /* スクロールバーを非表示に */ | |
| } | |
| .comic-animation { | |
| width: 100%; | |
| height: auto; | |
| max-width: 680px; | |
| max-height: 680px; | |
| margin: 0 auto; | |
| background-size: contain; | |
| background-repeat: no-repeat; | |
| background-position: center; | |
| aspect-ratio: 1 / 1; | |
| animation: comic-frame-switch 6s step-end infinite; | |
| } | |
| @media (min-width: 768px) { | |
| .modal-dialog.modal-large { | |
| max-width: 700px; | |
| } | |
| } | |
| @media (max-width: 767px) { | |
| .comic-animation { | |
| width: 100%; | |
| height: auto; | |
| } | |
| .form-group { | |
| padding-left: 1rem; | |
| padding-right: 1rem; | |
| } | |
| } | |
| @keyframes comic-frame-switch { | |
| 0%, | |
| 50% { | |
| background-image: url("https://i.imgur.com/4A7K3TC.png"); | |
| } | |
| 50.01%, | |
| 100% { | |
| background-image: url("https://i.imgur.com/LqLqwJi.png"); | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body data-bs-theme="dark"> | |
| <div id="sidebar-container"> | |
| <div id="sidebar"> | |
| <div class="p-3"> | |
| <h3 id="settingsTitle" class="text-white">設定</h3> | |
| <div class="form-group mb-3"> | |
| <label for="apiKey" class="form-label" id="apiKeyLabel"> | |
| <a href="https://aistudio.google.com/app/apikey?hl=ja" target="_blank">APIキー</a> | |
| </label> | |
| <input type="text" class="form-control" id="apiKey" placeholder="APIキーを入力してください"> | |
| </div> | |
| <div class="form-group"> | |
| <label for="characterCount" class="form-label" id="characterCountLabel">文字数</label> | |
| <input type="number" value="576" class="form-control" id="characterCount" | |
| placeholder="生成するプロンプトの文字数を入力してください"> | |
| </div> | |
| <div class="form-group"> | |
| <label for="languageSelect" class="form-label" id="languageSelectLabel">Language</label> | |
| <select class="form-select" id="languageSelect"> | |
| <option value="ja">日本語</option> | |
| <option value="en">English</option> | |
| <option value="zh">中文</option> | |
| <option value="ko">한국어</option> | |
| <option value="fr">Français</option> | |
| <option value="es">Español</option> | |
| <option value="de">Deutsch</option> | |
| <option value="it">Italiano</option> | |
| </select> | |
| </div> | |
| <div class="form-group mb-3"> | |
| <label for="endpointSelect" class="form-label" id="endpointSelectLabel">エンドポイント</label> | |
| <select class="form-select" id="endpointSelect"> | |
| <option value="models/gemini-2.0-pro-exp">gemini-2.0-pro-exp</option> | |
| <option value="models/gemini-2.0-flash-exp">gemini-2.0-flash-exp</option> | |
| <option value="models/gemini-2.0-flash-thinking-exp">gemini-2.0-flash-thinking-exp</option> | |
| </select> | |
| </div> | |
| <h3 id="replacementTitle" class="text-white mt-4">置換設定</h3> | |
| <div id="replacementContainer"> | |
| <div id="replacementList"> | |
| <!-- 置換セットがここに動的に追加されます --> | |
| </div> | |
| <button id="addReplacementButton" class="btn btn-secondary mt-2"> | |
| <i class="fas fa-plus"></i> <span id="addReplacementButtonText">置換セット追加</span> | |
| </button> | |
| </div> | |
| <h3 id="historyTitle" class="text-white mt-4">履歴</h3> | |
| <div id="historyContainer"> | |
| <ul id="historyList" class="list-group small"> | |
| <!-- 履歴項目がここに動的に追加されます --> | |
| </ul> | |
| <p id="noHistoryMessage" class="text-white mt-2 d-none">履歴がありません。</p> | |
| </div> | |
| <!-- デバッグ用のモーダル表示ボタンを追加 --> | |
| <div class="mt-4"> | |
| <button id="showLoadingModalButton" class="btn btn-secondary w-100"> | |
| Show Modal | |
| </button> | |
| </div> | |
| <!-- 新しいボタンを追加 --> | |
| <div class="mt-4"> | |
| <button id="clearStorageButton" class="btn btn-danger w-100"> | |
| Clear All Settings | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="sidebar-resizer"></div> | |
| </div> | |
| <div id="content"> | |
| <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> | |
| <div class="container"> | |
| <button id="sidebarToggle" class="btn btn-outline-light me-2"> | |
| <i class="fas fa-bars"></i> | |
| </button> | |
| <a class="navbar-brand" href="#">Gemini Prompt Generator</a> | |
| </div> | |
| </nav> | |
| <div class="container"> | |
| <main class="row"> | |
| <div id="inputQuery" class="col-lg-4 col-md-12 mb-4 h-100"> | |
| <div class="card h-100"> | |
| <div class="card-header bg-primary text-white"> | |
| <h5 class="mb-0" id="inputQueryTitle">入力クエリ</h5> | |
| </div> | |
| <div class="card-body"> | |
| <div class="form-group"> | |
| <textarea class="form-control" id="query" placeholder="ここにクエリを入力してください"></textarea> | |
| </div> | |
| </div> | |
| <div class="card-footer d-flex align-items-center"> | |
| <button id="generatePromptButton" class="btn btn-primary flex-grow-1 me-2" | |
| onclick="generatePrompt()"> | |
| <i class="fas fa-magic me-2"></i><span id="generateButtonText">プロンプト生成</span> | |
| <i class="fas fa-spinner fa-spin me-2 d-none" id="loading"></i> | |
| </button> | |
| <div class="form-check form-switch" id="splitStringsSwitchWrapper"> | |
| <input class="form-check-input" type="checkbox" id="splitStringsSwitch"> | |
| <label class="form-check-label" for="splitStringsSwitch"> | |
| <i class="fas fa-shield-alt" id="splitStrings">分割送信</i> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="outputPrompt" class="col-lg-8 col-md-12 mb-4 h-100"> | |
| <div class="card h-100"> | |
| <div class="card-header bg-success text-white"> | |
| <h5 class="mb-0" id="outputPromptTitle">生成されたプロンプト</h5> | |
| </div> | |
| <div class="card-body"> | |
| <div class="form-group"> | |
| <label for="promptEn" class="form-label" id="promptEnLabel">English Prompt</label> | |
| <textarea class="form-control" id="promptEn" placeholder="English Prompt"></textarea> | |
| </div> | |
| <div class="form-group"> | |
| <label for="promptMyLanguage" class="form-label mt-3" id="promptMyLanguageLabel">Your | |
| Language Translation</label> | |
| <textarea class="form-control" id="promptMyLanguage" disabled></textarea> | |
| </div> | |
| <div class="form-group"> | |
| <label for="danbooruTags" class="form-label mt-3" id="danbooruTagsLabel"> | |
| danbooru tags | |
| </label> | |
| <input type="text" class="form-control" id="danbooruTags" placeholder="danbooru tags" | |
| readonly> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| </div> | |
| <div class="modal fade" id="loadingModal" tabindex="-1" aria-labelledby="loadingModalLabel" aria-hidden="true"> | |
| <div class="modal-dialog modal-dialog-centered modal-large"> | |
| <div class="modal-content bg-dark text-white"> | |
| <div class="modal-body text-center"> | |
| <h5 id="loadingModalLabel">プロンプト生成中...</h5> | |
| <div class="comic-animation"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/json5/2.2.3/index.min.js" | |
| integrity="sha512-44jdhc+R2TFfzBflS3/dGNEABiNUxBkkrqwO7GWTvGsj3HkQNr3GESvI9PUvAxmqxSnTosR0Ij9y3+o+6J1hig==" | |
| crossorigin="anonymous" referrerpolicy="no-referrer"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/i18next/23.15.1/i18next.min.js" | |
| integrity="sha512-8ANNUVMWPf6aWGXZqDhS4OXJWBCRxfjlW7lKfupuiG1FZah0ST6LiI2qnEb1L5mp05v/+0hn3s2FO4EwIbIgfA==" | |
| crossorigin="anonymous" referrerpolicy="no-referrer"></script> | |
| <script | |
| src="https://cdnjs.cloudflare.com/ajax/libs/i18next-browser-languagedetector/8.0.0/i18nextBrowserLanguageDetector.min.js" | |
| integrity="sha512-8/RTkAM23B3lQzi6fmPs+Yf9qhIHzrzRpeSZsBsQ8OEmo95mbVp+68dB647VDCuyQIBbF+OIbS9b30aTWUkoog==" | |
| crossorigin="anonymous" referrerpolicy="no-referrer"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" | |
| integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" | |
| crossorigin="anonymous"></script> | |
| <script src="translation.js"></script> | |
| <script src="prompt.js"></script> | |
| <script src="storage.js"></script> | |
| <script src="history.js"></script> | |
| <script src="control.js"></script> | |
| <script> | |
| document.getElementById('showLoadingModalButton').addEventListener('click', function () { | |
| var loadingModal = new bootstrap.Modal(document.getElementById('loadingModal')); | |
| loadingModal.show(); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |