Spaces:
Running
Running
字下げボタン追加
Browse files- index.html +199 -0
index.html
CHANGED
|
@@ -116,6 +116,15 @@
|
|
| 116 |
<button class="btn btn-outline-danger btn-sm" onclick="clearTextarea('topText')" title="クリア">
|
| 117 |
<i class="fas fa-trash"></i>
|
| 118 |
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
</div>
|
| 120 |
<textarea id="topText" class="form-control" style="width:100%; min-height:50vh;"
|
| 121 |
rows="10" placeholder="ここにテキストを入力してください"></textarea>
|
|
@@ -144,6 +153,15 @@
|
|
| 144 |
<button class="btn btn-outline-danger btn-sm" onclick="clearTextarea('bottomText')" title="クリア">
|
| 145 |
<i class="fas fa-trash"></i>
|
| 146 |
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
</div>
|
| 148 |
<textarea id="bottomText" class="form-control" style="width:100%; min-height:50vh;"
|
| 149 |
rows="10" placeholder="ここにテキストを入力してください"></textarea>
|
|
@@ -173,6 +191,15 @@
|
|
| 173 |
<button class="btn btn-outline-danger btn-sm" onclick="clearTextarea('memoArea')" title="クリア">
|
| 174 |
<i class="fas fa-trash"></i>
|
| 175 |
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
</div>
|
| 177 |
<textarea id="memoArea" class="form-control" style="width:100%; min-height:50vh;"
|
| 178 |
rows="10" placeholder="ここにテキストを入力してください"></textarea>
|
|
@@ -415,6 +442,178 @@
|
|
| 415 |
saveToUserStorage(true); // クリアしたら自動保存
|
| 416 |
}
|
| 417 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 418 |
|
| 419 |
</script>
|
| 420 |
</body>
|
|
|
|
| 116 |
<button class="btn btn-outline-danger btn-sm" onclick="clearTextarea('topText')" title="クリア">
|
| 117 |
<i class="fas fa-trash"></i>
|
| 118 |
</button>
|
| 119 |
+
<button class="btn btn-outline-info btn-sm" onclick="applyIndent('topText')" title="字下げ">
|
| 120 |
+
<i class="fas fa-indent"></i>
|
| 121 |
+
</button>
|
| 122 |
+
<button class="btn btn-outline-warning btn-sm" onclick="applySpaces('topText')" title="スペース処理">
|
| 123 |
+
<i class="fas fa-space-shuttle"></i>
|
| 124 |
+
</button>
|
| 125 |
+
<button class="btn btn-outline-secondary btn-sm" onclick="applyNovelFormat('topText')" title="小説フォーマット統一">
|
| 126 |
+
<i class="fas fa-book"></i>
|
| 127 |
+
</button>
|
| 128 |
</div>
|
| 129 |
<textarea id="topText" class="form-control" style="width:100%; min-height:50vh;"
|
| 130 |
rows="10" placeholder="ここにテキストを入力してください"></textarea>
|
|
|
|
| 153 |
<button class="btn btn-outline-danger btn-sm" onclick="clearTextarea('bottomText')" title="クリア">
|
| 154 |
<i class="fas fa-trash"></i>
|
| 155 |
</button>
|
| 156 |
+
<button class="btn btn-outline-info btn-sm" onclick="applyIndent('bottomText')" title="字下げ">
|
| 157 |
+
<i class="fas fa-indent"></i>
|
| 158 |
+
</button>
|
| 159 |
+
<button class="btn btn-outline-warning btn-sm" onclick="applySpaces('bottomText')" title="スペース処理">
|
| 160 |
+
<i class="fas fa-space-shuttle"></i>
|
| 161 |
+
</button>
|
| 162 |
+
<button class="btn btn-outline-secondary btn-sm" onclick="applyNovelFormat('bottomText')" title="小説フォーマット統一">
|
| 163 |
+
<i class="fas fa-book"></i>
|
| 164 |
+
</button>
|
| 165 |
</div>
|
| 166 |
<textarea id="bottomText" class="form-control" style="width:100%; min-height:50vh;"
|
| 167 |
rows="10" placeholder="ここにテキストを入力してください"></textarea>
|
|
|
|
| 191 |
<button class="btn btn-outline-danger btn-sm" onclick="clearTextarea('memoArea')" title="クリア">
|
| 192 |
<i class="fas fa-trash"></i>
|
| 193 |
</button>
|
| 194 |
+
<button class="btn btn-outline-info btn-sm" onclick="applyIndent('memoArea')" title="字下げ">
|
| 195 |
+
<i class="fas fa-indent"></i>
|
| 196 |
+
</button>
|
| 197 |
+
<button class="btn btn-outline-warning btn-sm" onclick="applySpaces('memoArea')" title="スペース処理">
|
| 198 |
+
<i class="fas fa-space-shuttle"></i>
|
| 199 |
+
</button>
|
| 200 |
+
<button class="btn btn-outline-secondary btn-sm" onclick="applyNovelFormat('memoArea')" title="小説フォーマット統一">
|
| 201 |
+
<i class="fas fa-book"></i>
|
| 202 |
+
</button>
|
| 203 |
</div>
|
| 204 |
<textarea id="memoArea" class="form-control" style="width:100%; min-height:50vh;"
|
| 205 |
rows="10" placeholder="ここにテキストを入力してください"></textarea>
|
|
|
|
| 442 |
saveToUserStorage(true); // クリアしたら自動保存
|
| 443 |
}
|
| 444 |
|
| 445 |
+
// 日本語小説フォーマットに合わせた字下げを適用する関数
|
| 446 |
+
function applyJapaneseIndent(text) {
|
| 447 |
+
if (!text) return '';
|
| 448 |
+
|
| 449 |
+
// テキストを行に分割
|
| 450 |
+
const lines = text.split('\n');
|
| 451 |
+
const processedLines = [];
|
| 452 |
+
|
| 453 |
+
for (let i = 0; i < lines.length; i++) {
|
| 454 |
+
const line = lines[i].trim();
|
| 455 |
+
|
| 456 |
+
// 空行はそのまま保持
|
| 457 |
+
if (line === '') {
|
| 458 |
+
processedLines.push('');
|
| 459 |
+
continue;
|
| 460 |
+
}
|
| 461 |
+
|
| 462 |
+
// 括弧類で始まる行は字下げしない
|
| 463 |
+
const startsWithBracket = /^[「『(\((【〔[{]/.test(line);
|
| 464 |
+
|
| 465 |
+
// 段落の開始を判定
|
| 466 |
+
// 前の行が空行、または行末が句点(。)、疑問符(?)、感嘆符(!)、ハートマーク(♡♥❤)で終わっている場合
|
| 467 |
+
// 感嘆符の組み合わせ(!?、!!、?!など)も考慮
|
| 468 |
+
const isNewParagraph = (i === 0) ||
|
| 469 |
+
(processedLines[i - 1] === '') ||
|
| 470 |
+
/[。?!♡♥❤]([!?!?♡♥❤])*$/.test(processedLines[i - 1]);
|
| 471 |
+
|
| 472 |
+
if (isNewParagraph && !startsWithBracket) {
|
| 473 |
+
// 段落の最初の行には全角スペース1文字分の字下げを追加
|
| 474 |
+
processedLines.push(' ' + line);
|
| 475 |
+
} else {
|
| 476 |
+
// 段落の続きの行や括弧類で始まる行はそのまま
|
| 477 |
+
processedLines.push(line);
|
| 478 |
+
}
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
return processedLines.join('\n');
|
| 482 |
+
}
|
| 483 |
+
|
| 484 |
+
// 字下げボタンのクリックイベントハンドラー
|
| 485 |
+
function applyIndent(textareaId) {
|
| 486 |
+
const textarea = document.getElementById(textareaId);
|
| 487 |
+
const originalText = textarea.value;
|
| 488 |
+
const indentedText = applyJapaneseIndent(originalText);
|
| 489 |
+
textarea.value = indentedText;
|
| 490 |
+
saveToUserStorage(true); // 字下げ後に自動保存
|
| 491 |
+
}
|
| 492 |
+
|
| 493 |
+
// 感嘆符・ハートマーク後のスペース処理関数
|
| 494 |
+
function addSpacesAfterMarks(text) {
|
| 495 |
+
if (!text) return '';
|
| 496 |
+
|
| 497 |
+
// 感嘆符・ハートマークの後に全角スペースを追加
|
| 498 |
+
// 既にスペースがある場合は重複しないよう処理
|
| 499 |
+
let processedText = text;
|
| 500 |
+
|
| 501 |
+
// 感嘆符・ハートマークのパターン
|
| 502 |
+
const markPattern = /([!?!?♡♥❤]+)(\s*)/g;
|
| 503 |
+
|
| 504 |
+
processedText = processedText.replace(markPattern, function(match, marks, existingSpaces) {
|
| 505 |
+
// 既存のスペースを全角スペースに統一
|
| 506 |
+
const normalizedSpaces = existingSpaces.replace(/[ \u00A0]/g, ' ');
|
| 507 |
+
|
| 508 |
+
// 全角スペースが既に1つ以上ある場合はそのまま、ない場合は1つ追加
|
| 509 |
+
if (normalizedSpaces.length >= 1) {
|
| 510 |
+
return marks + normalizedSpaces;
|
| 511 |
+
} else {
|
| 512 |
+
return marks + ' ';
|
| 513 |
+
}
|
| 514 |
+
});
|
| 515 |
+
|
| 516 |
+
return processedText;
|
| 517 |
+
}
|
| 518 |
+
|
| 519 |
+
// スペース処理ボタンのクリックイベントハンドラー
|
| 520 |
+
function applySpaces(textareaId) {
|
| 521 |
+
const textarea = document.getElementById(textareaId);
|
| 522 |
+
const originalText = textarea.value;
|
| 523 |
+
const spacedText = addSpacesAfterMarks(originalText);
|
| 524 |
+
textarea.value = spacedText;
|
| 525 |
+
saveToUserStorage(true); // スペース処理後に自動保存
|
| 526 |
+
}
|
| 527 |
+
|
| 528 |
+
// 三点リーダーとダッシュの統一関数
|
| 529 |
+
function unifyEllipsisAndDash(text) {
|
| 530 |
+
if (!text) return '';
|
| 531 |
+
|
| 532 |
+
let processedText = text;
|
| 533 |
+
|
| 534 |
+
// 三点リーダーを2つ連続に統一(1つや3つ以上の場合も2つに)
|
| 535 |
+
processedText = processedText.replace(/…+/g, '……');
|
| 536 |
+
processedText = processedText.replace(/\.{3,}/g, '……');
|
| 537 |
+
|
| 538 |
+
// ダッシュを2つ連続に統一(1つや3つ以上の場合も2つに)
|
| 539 |
+
processedText = processedText.replace(/―+/g, '――');
|
| 540 |
+
processedText = processedText.replace(/-{2,}/g, '――');
|
| 541 |
+
|
| 542 |
+
return processedText;
|
| 543 |
+
}
|
| 544 |
+
|
| 545 |
+
// かぎ括弧内の句点削除関数
|
| 546 |
+
function removePeriodInQuotes(text) {
|
| 547 |
+
if (!text) return '';
|
| 548 |
+
|
| 549 |
+
let processedText = text;
|
| 550 |
+
|
| 551 |
+
// かぎ括弧内の文末句点を削除
|
| 552 |
+
processedText = processedText.replace(/「([^」]*)。」/g, '「$1」');
|
| 553 |
+
processedText = processedText.replace(/『([^』]*)。』/g, '『$1』');
|
| 554 |
+
|
| 555 |
+
return processedText;
|
| 556 |
+
}
|
| 557 |
+
|
| 558 |
+
// 数字表記統一関数(漢数字に統一)
|
| 559 |
+
function unifyNumbersToKanji(text) {
|
| 560 |
+
if (!text) return '';
|
| 561 |
+
|
| 562 |
+
let processedText = text;
|
| 563 |
+
|
| 564 |
+
// 基本的な数字の変換
|
| 565 |
+
const numberMap = {
|
| 566 |
+
'0': '〇', '1': '一', '2': '二', '3': '三', '4': '四',
|
| 567 |
+
'5': '五', '6': '六', '7': '七', '8': '八', '9': '九'
|
| 568 |
+
};
|
| 569 |
+
|
| 570 |
+
// 単独の数字を漢数字に変換(ただし、日付や時間、電話番号などは除外)
|
| 571 |
+
processedText = processedText.replace(/(?<![0-9])([0-9])(?![0-9])/g, function(match, digit) {
|
| 572 |
+
// 前後に数字がない単独の数字のみ変換
|
| 573 |
+
return numberMap[digit] || digit;
|
| 574 |
+
});
|
| 575 |
+
|
| 576 |
+
return processedText;
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
// 数字表記統一関数(算用数字に統一)
|
| 580 |
+
function unifyNumbersToArabic(text) {
|
| 581 |
+
if (!text) return '';
|
| 582 |
+
|
| 583 |
+
let processedText = text;
|
| 584 |
+
|
| 585 |
+
// 漢数字を算用数字に変換
|
| 586 |
+
const kanjiMap = {
|
| 587 |
+
'〇': '0', '一': '1', '二': '2', '三': '3', '四': '4',
|
| 588 |
+
'五': '5', '六': '6', '七': '7', '八': '8', '九': '9'
|
| 589 |
+
};
|
| 590 |
+
|
| 591 |
+
// 単独の漢数字を算用数字に変換
|
| 592 |
+
processedText = processedText.replace(/[〇一二三四五六七八九]/g, function(match) {
|
| 593 |
+
return kanjiMap[match] || match;
|
| 594 |
+
});
|
| 595 |
+
|
| 596 |
+
return processedText;
|
| 597 |
+
}
|
| 598 |
+
|
| 599 |
+
// 小説フォーマット統一ボタンのクリックイベントハンドラー
|
| 600 |
+
function applyNovelFormat(textareaId) {
|
| 601 |
+
const textarea = document.getElementById(textareaId);
|
| 602 |
+
let processedText = textarea.value;
|
| 603 |
+
|
| 604 |
+
// 1. 三点リーダーとダッシュの統一
|
| 605 |
+
processedText = unifyEllipsisAndDash(processedText);
|
| 606 |
+
|
| 607 |
+
// 2. かぎ括弧内の句点削除
|
| 608 |
+
processedText = removePeriodInQuotes(processedText);
|
| 609 |
+
|
| 610 |
+
// 3. 感嘆符・ハートマーク後のスペース処理
|
| 611 |
+
processedText = addSpacesAfterMarks(processedText);
|
| 612 |
+
|
| 613 |
+
textarea.value = processedText;
|
| 614 |
+
saveToUserStorage(true); // フォーマット統一後に自動保存
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
|
| 618 |
</script>
|
| 619 |
</body>
|