|
| 1 | +# Contributing to Manga Editor Desu! |
| 2 | + |
| 3 | +Thank you for your interest in contributing! This guide will help you get started. |
| 4 | + |
| 5 | +## Table of Contents |
| 6 | + |
| 7 | +- [Getting Started](#getting-started) |
| 8 | +- [Development Setup](#development-setup) |
| 9 | +- [Code Style](#code-style) |
| 10 | +- [Project Structure](#project-structure) |
| 11 | +- [Making Changes](#making-changes) |
| 12 | +- [Submitting Changes](#submitting-changes) |
| 13 | +- [Translation Guide](#translation-guide) |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## Getting Started |
| 18 | + |
| 19 | +### Prerequisites |
| 20 | + |
| 21 | +- Git |
| 22 | +- Node.js (for linting tools) |
| 23 | +- A modern web browser (Chrome recommended) |
| 24 | +- Python 3 (optional, for local server) |
| 25 | + |
| 26 | +### Clone the Repository |
| 27 | + |
| 28 | +```bash |
| 29 | +git clone https://github.com/new-sankaku/manga-editor-desu.git |
| 30 | +cd manga-editor-desu |
| 31 | +npm install |
| 32 | +``` |
| 33 | + |
| 34 | +--- |
| 35 | + |
| 36 | +## Development Setup |
| 37 | + |
| 38 | +### Running Locally |
| 39 | + |
| 40 | +**Option 1: Direct file access** |
| 41 | +```bash |
| 42 | +start index.html |
| 43 | +``` |
| 44 | + |
| 45 | +**Option 2: Local server (recommended for full functionality)** |
| 46 | +```bash |
| 47 | +python 99_server.py |
| 48 | +``` |
| 49 | +Then open `http://localhost:8000` |
| 50 | + |
| 51 | +### Why use a local server? |
| 52 | +Some browser security features restrict `file://` protocol access. Using a local server ensures all features work correctly. |
| 53 | + |
| 54 | +--- |
| 55 | + |
| 56 | +## Code Style |
| 57 | + |
| 58 | +### Formatting Rules |
| 59 | + |
| 60 | +This project uses a specific formatting style: |
| 61 | + |
| 62 | +- **No indentation** - Code has no leading tabs or spaces |
| 63 | +- **Minimal whitespace** - Remove unnecessary spaces around operators, commas, etc. |
| 64 | +- **camelCase** - Use camelCase for variables and functions |
| 65 | +- **PascalCase** - Use PascalCase for classes |
| 66 | +- **UPPER_SNAKE_CASE** - Use for constants (or camelCase) |
| 67 | + |
| 68 | +### Auto-Format |
| 69 | + |
| 70 | +Run the formatter before committing: |
| 71 | + |
| 72 | +```bash |
| 73 | +npm run format |
| 74 | +``` |
| 75 | + |
| 76 | +This removes: |
| 77 | +- Leading indentation |
| 78 | +- Trailing whitespace |
| 79 | +- Spaces around operators |
| 80 | +- Spaces after commas/semicolons |
| 81 | +- Spaces inside parentheses |
| 82 | + |
| 83 | +It preserves: |
| 84 | +- Spaces inside string literals |
| 85 | +- Spaces inside comments |
| 86 | +- Line breaks |
| 87 | + |
| 88 | +### ESLint |
| 89 | + |
| 90 | +```bash |
| 91 | +# Check for issues |
| 92 | +npm run lint |
| 93 | + |
| 94 | +# Auto-fix issues |
| 95 | +npm run lint:fix |
| 96 | +``` |
| 97 | + |
| 98 | +### Logging |
| 99 | + |
| 100 | +**Do NOT use `console.log()`**. Use the Logger system instead: |
| 101 | + |
| 102 | +```javascript |
| 103 | +// Create a logger for your module |
| 104 | +var myLogger = new SimpleLogger('moduleName', LogLevel.DEBUG); |
| 105 | + |
| 106 | +// Use it |
| 107 | +myLogger.debug("Debug message"); |
| 108 | +myLogger.info("Info message"); |
| 109 | +myLogger.warn("Warning message"); |
| 110 | +myLogger.error("Error message"); |
| 111 | +``` |
| 112 | + |
| 113 | +Logger is defined in `js/core/logger.js`. |
| 114 | +Log levels: `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `SILENT` |
| 115 | + |
| 116 | +### API Response Properties |
| 117 | + |
| 118 | +When working with external APIs: |
| 119 | +- Keep API response property names as-is (e.g., `response.prompt_id`) |
| 120 | +- Use camelCase for local variables (e.g., `var promptId = response.prompt_id;`) |
| 121 | + |
| 122 | +--- |
| 123 | + |
| 124 | +## Project Structure |
| 125 | + |
| 126 | +``` |
| 127 | +manga-editor-desu/ |
| 128 | +├── index.html # Main entry point |
| 129 | +├── js/ # JavaScript source files |
| 130 | +│ ├── core/ # Core functionality |
| 131 | +│ ├── ui/ # UI components |
| 132 | +│ └── shortcut.js # Keyboard shortcuts |
| 133 | +├── css/ # Stylesheets |
| 134 | +├── 99_server.py # Local development server |
| 135 | +├── package.json # Node.js dependencies |
| 136 | +└── eslint.config.mjs # ESLint configuration |
| 137 | +``` |
| 138 | + |
| 139 | +### Excluded Directories |
| 140 | + |
| 141 | +The following directories should not be searched or modified: |
| 142 | +- `json_js/` |
| 143 | +- `test/` |
| 144 | +- `third/` |
| 145 | +- `01_build/` |
| 146 | +- `02_images_svg/` |
| 147 | +- `03_images/` |
| 148 | +- `99_doc/` |
| 149 | +- `font/` |
| 150 | + |
| 151 | +--- |
| 152 | + |
| 153 | +## Making Changes |
| 154 | + |
| 155 | +### History Management (Undo/Redo) |
| 156 | + |
| 157 | +When making changes that affect canvas history: |
| 158 | + |
| 159 | +**Single operation:** |
| 160 | +```javascript |
| 161 | +// Automatic history save |
| 162 | +canvas.add(object); |
| 163 | +saveStateByManual(); |
| 164 | +``` |
| 165 | + |
| 166 | +**Multiple operations (prevent intermediate states):** |
| 167 | +```javascript |
| 168 | +changeDoNotSaveHistory(); |
| 169 | +canvas.remove(oldObject); |
| 170 | +canvas.add(newObject); |
| 171 | +changeDoSaveHistory(); |
| 172 | +saveStateByManual(); // Only final state is saved |
| 173 | +``` |
| 174 | + |
| 175 | +**Per-object history control:** |
| 176 | +```javascript |
| 177 | +activeObject.saveHistory = false; // Disable for this object |
| 178 | +``` |
| 179 | + |
| 180 | +### Image Data Storage |
| 181 | + |
| 182 | +When saving image data to `imageMap`: |
| 183 | + |
| 184 | +- **Always use** `data:` URLs or JSON strings |
| 185 | +- **Never use** `blob:` URLs (they become invalid after session ends) |
| 186 | +- Use `convertImageMapBlobUrls()` to convert blob URLs before saving |
| 187 | +- Use `JSON.stringify()` for objects (like 2D arrays) |
| 188 | + |
| 189 | +### Browser Storage (localStorage) |
| 190 | + |
| 191 | +The app uses `localStorage` for persisting user preferences. Here are the keys used: |
| 192 | + |
| 193 | +| Key | Purpose | Location | |
| 194 | +|-----|---------|----------| |
| 195 | +| `localSettingsData` | API settings, generation parameters | `js/project-management.js` | |
| 196 | +| `mode` | Dark/light mode preference | `js/ui/util/mode-change.js` | |
| 197 | +| `language` | UI language setting | `js/ui/third/i18next.js` | |
| 198 | +| `uiSettings` | Prompt Helper UI settings | `js/ui/imagePromptHelper/prompt-helper.js` | |
| 199 | +| `CustomSet` | Custom prompt presets | `js/ui/imagePromptHelper/prompt-helper.js` | |
| 200 | +| `startupIntroShown` | First-time tutorial flag | `js/ui/third/intro.js` | |
| 201 | + |
| 202 | +**Guidelines:** |
| 203 | +- Keep localStorage keys descriptive and unique |
| 204 | +- Always use `JSON.stringify()` / `JSON.parse()` for objects |
| 205 | +- Document new keys in this table when adding storage features |
| 206 | + |
| 207 | +--- |
| 208 | + |
| 209 | +## Submitting Changes |
| 210 | + |
| 211 | +### Bug Reports |
| 212 | + |
| 213 | +1. Go to [Issues](https://github.com/new-sankaku/manga-editor-desu/issues) |
| 214 | +2. Create a new issue with **[Bug]** in the title |
| 215 | +3. Include: |
| 216 | + - Steps to reproduce |
| 217 | + - Expected behavior |
| 218 | + - Actual behavior |
| 219 | + - Browser and OS version |
| 220 | + - Screenshots if applicable |
| 221 | + |
| 222 | +### Feature Requests |
| 223 | + |
| 224 | +1. Go to [Issues](https://github.com/new-sankaku/manga-editor-desu/issues) |
| 225 | +2. Create a new issue with **[Feature Request]** in the title |
| 226 | +3. Describe the feature and its use case |
| 227 | + |
| 228 | +### Pull Requests |
| 229 | + |
| 230 | +1. Fork the repository |
| 231 | +2. Create a feature branch: `git checkout -b feature/your-feature` |
| 232 | +3. Make your changes |
| 233 | +4. Run `npm run format` and `npm run lint` |
| 234 | +5. Commit with a clear message |
| 235 | +6. Push to your fork |
| 236 | +7. Open a Pull Request |
| 237 | + |
| 238 | +--- |
| 239 | + |
| 240 | +## Translation Guide |
| 241 | + |
| 242 | +Translations are stored in `js/ui/third/i18next.js` in the `resources` constant. |
| 243 | + |
| 244 | +### Adding New Translations |
| 245 | + |
| 246 | +1. Create a new date-keyed entry (YYYYMMDD format) |
| 247 | +2. Place it above existing entries |
| 248 | +3. Add translations for all 10 languages: |
| 249 | + - `ja` - Japanese |
| 250 | + - `en` - English |
| 251 | + - `ko` - Korean |
| 252 | + - `fr` - French |
| 253 | + - `zh` - Chinese |
| 254 | + - `ru` - Russian |
| 255 | + - `es` - Spanish |
| 256 | + - `pt` - Portuguese |
| 257 | + - `th` - Thai |
| 258 | + - `de` - German |
| 259 | + |
| 260 | +### Translation Tips |
| 261 | + |
| 262 | +- Keep translations short (UI space is limited) |
| 263 | +- Maintain consistency with existing terminology |
| 264 | +- Test in the UI to ensure text fits |
| 265 | + |
| 266 | +### Example |
| 267 | + |
| 268 | +```javascript |
| 269 | +const resources = { |
| 270 | + // New entry - add at top |
| 271 | + "20250112": { |
| 272 | + ja: "新しいテキスト", |
| 273 | + en: "New text", |
| 274 | + ko: "새 텍스트", |
| 275 | + fr: "Nouveau texte", |
| 276 | + zh: "新文本", |
| 277 | + ru: "Новый текст", |
| 278 | + es: "Nuevo texto", |
| 279 | + pt: "Novo texto", |
| 280 | + th: "ข้อความใหม่", |
| 281 | + de: "Neuer Text" |
| 282 | + }, |
| 283 | + // Existing entries below... |
| 284 | +}; |
| 285 | +``` |
| 286 | + |
| 287 | +--- |
| 288 | + |
| 289 | +## Questions? |
| 290 | + |
| 291 | +- **GitHub Issues:** [https://github.com/new-sankaku/manga-editor-desu/issues](https://github.com/new-sankaku/manga-editor-desu/issues) |
| 292 | + |
| 293 | +Thank you for contributing! |
0 commit comments