Skip to content

Instantly share code, notes, and snippets.

@whiteball
Last active May 19, 2022 12:18
Show Gist options
  • Save whiteball/16a28cb57b1c97043ee89354f24e6b2f to your computer and use it in GitHub Desktop.
Save whiteball/16a28cb57b1c97043ee89354f24e6b2f to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name [テスト版]AIのべりすとユーティリティ
// @namespace https://ai-novelist-share.geo.jp/
// @version 0.13.0-beta
// @description 「Ctrl+/」で選択範囲の行の上下に「@/*」と「@*/」を追加/削除する機能と、リトライ・Undo・Redoする前に確認ダイアログを出す機能と、本文入力欄の分割を複数文コメントや最新の出力文(色の変わっている部分)の途中になるのを避ける機能と、@endpointの前に出力するときは@endpointの位置にスクロールする機能と、Redoを3回押した時にもUndo履歴を挿入する機能と、サーバーに送信するテキストを確認する機能と、最大20回分まで過去の出力テキストの履歴を確認する機能と、トークンとして読み取れない文字をハイライトする機能と、編集ページを開いてからの出力数カウント表示などを追加します。※Chrome/Firefoxで動作確認
// @author しらたま
// @match https://ai-novel.com/novel.php
// @icon https://www.google.com/s2/favicons?sz=64&domain=ai-novel.com
// @updateURL https://gist.github.com/whiteball/16a28cb57b1c97043ee89354f24e6b2f/raw/ai_novelist_utility_test.user.js
// @downloadURL https://gist.github.com/whiteball/16a28cb57b1c97043ee89354f24e6b2f/raw/ai_novelist_utility_test.user.js
// @supportURL https://gist.github.com/whiteball/16a28cb57b1c97043ee89354f24e6b2f
// @grant none
// ==/UserScript==
/*
更新履歴
2022/05/19 0.13.0b GUIv2:AI出力後、メモリ/脚注を置換するスクリプトのオプションを追加。
使い方:種別を「使用しない」に設置し置換対象がメモリなら「(?:M){0}」、脚注なら「(?:A){0}」をINの先頭に書く。それに続けてAIの出力にマッチする正規表現を書く。OUTには「メモリ/脚注にマッチする正規表現<|>置換後のテキスト」を書く。OUTでは特殊な変数として「#数字#」が使える。これはOUTを正規表現として解釈する前に、INに書いた正規表現のキャプチャでその部分を置換する。
例:IN:(?:M){0}(.+)にいる。/OUT:\[場所:.+\]<|>[場所:#1#]という設定で出力が「大きな広場にいる。」なら、メモリの「[場所:~~]」が「[場所:大きな広場]」に置換される。
2022/05/18 0.12.0 GUIv2/v3:情報表示に最後にローカル/リモートへ保存した日時を追加。
2022/05/17 0.11.4 GUIv2:文字数がシャーディング上限*n+シャーディング上限/2(PCの場合だと4000文字、12000文字……)ぐらいのとき、本文末での分割回避が誤動作するのを修正。
2022/05/16 0.11.3 GUIv2:シャーディングの分割が本文末近くでは起きないようにする変更が、最後の一行を消してしまう不具合を修正。
2022/05/16 0.11.2 GUIv2:トークンとして読み取れない文字から、単独の濁点記号を除外。シャーディングの分割が本文末近くでは起きないように変更。
2022/04/24 0.11.1 GUIv3向けのダイアログに幅と高さの調整ボタンを追加。ダイアログを表示したときに、そのダイアログが常に一番上に来ないのを修正。
2022/04/23 0.11.0 GUIv3向けに、送信テキスト、履歴の履歴、情報の各ダイアログを表示するボタンを追加。PCの場合、ダイアログはドラッグで移動可能(Firefoxはドラッグがもっさりしています)。
2022/04/20 0.10.12 シャーディング境界の手前にコメントがあるとき、本文が一行ごとに区切られてしまうのを修正。
2022/04/15 0.10.11 公式で@endpointの認識位置が最後に出現した場所から、最初に出現した場所に変わったのでそれに追随した。
2022/04/15 0.10.10 トークンとして読み取れない文字をハイライトしているときに、ハイライト部分の直後に改行があると見なされてしまうのを修正。
2022/04/03 0.10.9 @endpointがシャーディング境界に来たときに、Undo/Redoしたときに編集していないのに確認ダイアログが出るのを修正。
@endpointがシャーディング境界に来たときに、前の枠の最後に長い複数行コメントがあると、その中央にスクロールしてしまうのを修正。
コメント(@/ *~@* /)が連続するときに先に出てきた方のコメントに色分けが適用されないのを修正。@endpointがシャーディング境界に来たときに、出力文が@endpointがある側のシャーディング枠に入ってしまうのを修正。
2022/04/03 0.10.8 @endpointがシャーディング境界に来たときに、出力文が@endpointがある側のシャーディング枠に入ってしまうのを修正。
2022/04/01 0.10.7 @endpointがあるときに、シャーディングの区切りが常に@endpointの直前になってしまうのを修正。
2022/03/26 0.10.6 @endpointがシャーディング境界に来たときに、分割がおかしくなるのを修正。
2022/03/26 0.10.5 情報表示のデータをセッションに保存するようにした。これによりページを閉じない限り、再読込してもデータが維持されるようになった。
2022/03/24 0.10.4 情報表示におおよその本文の文字数を追加。
2022/03/23 0.10.3 リトライやUndo履歴を表示するときのスクロールが、@endpointのコメント領域の中心に繰るのを修正。
2022/03/21 0.10.2 入れ子になったコメント(@/ *~@* /)に正しくfontタグが設定されるように修正。
2022/03/21 0.10.1 @endpointがあっても出力文を一番下に挿入する設定を環境設定の一番下に追加。
2022/03/21 0.10.0 公式で@endpoint前への挿入が実装されたので、バッティングしないように関連機能を修正。
2022/03/19 0.9.3 接続エラーなどが出た後にリトライすると、編集していないのに確認ダイアログが出るのを修正。
2022/03/18 0.9.2 @endpointへのスクロールがずれるのを修正。
2022/03/17 0.9.1 オプションアイコンを横スクロール出来るようにする設定を環境設定の一番下に追加。
2022/03/17 0.9.0 編集ページを開いてからの出力数カウント表示を追加。
2022/03/17 0.8.2 履歴の履歴でまだ存在していない「○個前」を表示しないようにした。
2022/03/14 0.8.1 テスト用コードを消し忘れていたのを修正。
2022/03/14 0.8.0 トークンとして読み取れない文字をハイライトする機能を追加。
2022/03/11 0.7.1 「@/ *」と「@* /」の削除時が改行位置によっては正しく動かない不具合を修正。
2022/03/09 0.7.0 サーバー送信テキスト確認と履歴の履歴を、オプションアイコンのところに追加したアイコンから開閉出来るようにした。
2022/03/07 0.6.3 ロードタイミングがずれて履歴の履歴のボタンが表示出来ないときに、出力をするとエラーで止まるのを修正。
2022/03/03 0.6.2 インデントを調整。
2022/02/28 0.6.1 出力完了時に履歴の履歴の表示か切り替わらないのを修正。Firefoxでの読み込みタイミングがおかしいのをやや改善。
2022/02/28 0.6 最大20回分まで過去の出力テキストの履歴を確認する機能を追加。
2022/02/21 0.5 @endpointを囲っているfontタグに付けていたclassを削除。スクロール先の要素指定が固定になってしまっていたのを修正。このスクリプト自体の自動更新が動くようにした。(※ここからFirefoxでも動作確認)
2022/02/20 0.4 Redoを3回押した時にもUndo履歴を挿入する機能と、サーバーに送信したテキストを確認する機能を追加。インデントを調整。
2022/02/20 0.3 @endpointがあるときにその前に出力を挿入するを追加(※動作確認はChromeのみ)。
2022/02/14 0.2 本文入力欄の分割を複数文コメントや最新の出力文(色の変わっている部分)の途中になるのを避ける機能を追加。
2022/02/14 0.1 公開。「Ctrl+/」で選択範囲の行の上下に「@/ *」と「@* /」を追加/削除する機能と、リトライ・Undo・Redoする前に確認ダイアログを出す機能。
*/
(function () {
'use strict';
const formatDate = function (dateTime, no_delimiter = false) {
const date_del = no_delimiter ? '' : '/',
center_del = no_delimiter ? '' : ' ',
time_del = no_delimiter ? '' : ':'
return dateTime.getFullYear() + date_del + ('0' + (dateTime.getMonth()+1)).slice(-2) + date_del + ('0' + dateTime.getDate()).slice(-2) + center_del + ('0' + dateTime.getHours()).slice(-2) + time_del + ('0' + dateTime.getMinutes()).slice(-2) + time_del + ('0' + dateTime.getSeconds()).slice(-2)
}
if (document.getElementById('app')) {
v3_setting()
return
}
// 「Ctrl+/」で選択範囲の行の上下に「@/*」と「@*/」を追加/削除する機能
document.getElementById('data_container').addEventListener('keyup', function (event) {
if (event.isComposing || event.keyCode === 229) {
return;
}
if (!(event.ctrlKey && event.code === 'Slash')) {
return
}
const selection = document.getSelection()
const range = selection.getRangeAt(0)
let start = range.startContainer, end = range.endContainer;
if (start.nodeName !== '#text') {
start = start.childNodes[range.startOffset]
}
if (end.nodeName !== '#text') {
end = end.childNodes[range.endOffset - 1]
}
if (start.textContent === '@/*' && end.textContent === '@*/') {
if (start.nextSibling.tagName.toLowerCase() === 'br') {
start.parentNode.removeChild(start.nextSibling)
}
start.parentNode.removeChild(start)
if (end.previousSibling.nodeName === '#text' && end.previousSibling.textContent === '' && end.previousSibling.previousSibling.tagName && end.previousSibling.previousSibling.tagName.toLowerCase() === 'br') {
end.parentNode.removeChild(end.previousSibling.previousSibling)
end.parentNode.removeChild(end.previousSibling)
} else {
if (end.previousSibling.tagName && end.previousSibling.tagName.toLowerCase() === 'br') {
end.parentNode.removeChild(end.previousSibling)
}
}
end.parentNode.removeChild(end)
return
}
const before = document.createTextNode('@/*'), after = document.createTextNode('@*/')
const brBefore = document.createElement('br'), brAfter = document.createElement('br')
start.parentNode.insertBefore(before, start)
start.parentNode.insertBefore(brBefore, start)
end.parentNode.insertBefore(after, end.nextSibling)
end.parentNode.insertBefore(brAfter, end.nextSibling)
selection.removeAllRanges()
selection.setBaseAndExtent(before, 0, after, 3)
})
// リトライ・Undo・Redoする前に確認ダイアログを出す機能
document.getElementById('getcontinuation').addEventListener('click', function () {
for (const target of ['retry', 'undo', 'redo']) {
let origin = document.querySelector('#' + target)
if (origin.getAttribute('data-clone') === '1') {
continue
}
let clone = origin.cloneNode()
let parent = origin.parentNode
clone.setAttribute('data-clone', '1')
clone.removeAttribute('onclick')
clone.addEventListener('click', function () {
const data_undo = document.getElementById('data_undo').value.split('<|entry|>')
let all = document.getElementsByClassName('data_edit');
let currentText = '';
const isBr = function (text) {
return text.substring(text.length - 4) === '<br>'
}
for (let e of all) {
currentText += e.innerHTML;
if (!isBr(currentText)) {
currentText += '<br>';
}
}
if (isBr(currentText)) {
currentText = currentText.slice(0, -4);
}
let cache = data_undo[localStorage.undo_last]
if (isBr(cache)) {
cache = cache.slice(0, -4);
}
let cache_base = data_undo[1]
if (isBr(cache_base)) {
cache_base = cache_base.slice(0, -4);
}
// タグ削除
cache = cache.replace(/(<br>)*<span[^>]*>/g, '').replace(/<\/span>/g, '').replace(/<font color="#aaaaaa"[^>]*>/g, '').replace(/<\/font>/g, '')
cache_base = cache_base.replace(/(<br>)*<span[^>]*>/g, '').replace(/<\/span>/g, '').replace(/<font color="#aaaaaa"[^>]*>/g, '').replace(/<\/font>/g, '')
currentText = currentText.replace(/(<br>)*<span[^>]*>/g, '').replace(/<\/span>/g, '').replace(/<font color="#aaaaaa"[^>]*>/g, '').replace(/<\/font>/g, '')
const last = Number(localStorage.undo_last)
// 履歴が最初の時にUndoする場合と最後の時にRedoする場合はスルー
const undo_text = document.getElementById('undo').value, redo_text = document.getElementById('redo').value
if (!(target === 'undo' && last === 1 && undo_text !== 'History') && !(target === 'redo' && last + 1 === data_undo.length && redo_text !== 'History')) {
// 履歴と現在のテキストが異なっていたら確認を挟む
if (cache !== currentText && cache_base !== currentText && !window.confirm('テキストは編集されています。このまま続けると編集が失われます。\n続けますか?')) {
return
}
}
origin.dispatchEvent(new Event('click'))
})
origin.setAttribute('id', target + '-origin')
origin.style.display = 'none'
origin.style.visibility = 'hidden'
parent.insertBefore(clone, origin)
}
})
// デフォルトのスクロールを無効化
const originalScrollTop = window.jQuery.fn.init.prototype.scrollTop
const enableScrollTop = function () {
window.jQuery.fn.init.prototype.scrollTop = originalScrollTop
}
const disableScrollTop = function () {
window.jQuery.fn.init.prototype.scrollTop = (e) => { }
}
// endpointの検索
const endpointSearch = function () {
const all = document.getElementsByClassName('data_edit')
let endpoint = -1, target = -1, target_pos = -1
for (let i = all.length - 1; i >= 0; i--) {
endpoint = all[i].innerHTML.lastIndexOf('<font color="#aaaaaa">@endpoint')
if (endpoint === 0) {
// 枠の先頭にいる
if (i === 0) {
target = 0
target_pos = endpoint
} else {
target = i - 1
target_pos = all[target].innerHTML.length
}
} else if (endpoint > 0 && all[i].innerHTML.slice(endpoint - 4, endpoint) === '<br>') {
target = i
target_pos = endpoint - 4
}
}
return target < 0 ? false : [all, target_pos, target]
}
// endpointの直前にスクロール
const endpointScroll = function (target_element) {
let $ = window.jQuery
if (pref.force_insert_last) {
$("#data_container").scrollTop($("#data_edit").height() * 4096)
return
}
const result = endpointSearch()
if (result !== false) {
const [all, endpoint, target] = result
let ai_output
const top = window.scrollY, left = window.scrollX
if (target_element && (ai_output = document.getElementById(target_element))) {
ai_output.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'start' })
} else {
let endpoint_target = undefined
for (const font_tag of all[target].querySelectorAll('font[color="#aaaaaa"]')) {
if (font_tag.innerHTML.slice(0, '@endpoint'.length) === '@endpoint') {
endpoint_target = font_tag
break
}
}
if (endpoint_target) {
if (endpoint_target.previousSibling) {
endpoint_target.previousSibling.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'start' })
} else {
endpoint_target.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'start' })
}
} else {
const temp_element = document.createElement('span')
all[target].appendChild(temp_element)
temp_element.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'start' })
all[target].removeChild(temp_element)
}
}
window.scrollTo({ top: top, left: left, behavior: 'auto' })
} else {
$("#data_container").scrollTop($("#data_edit").height() * 4096);
}
}
const t = !0
const char_list = {' ':t,' ':t,'!':t,'"':t,'#':t,'$':t,'%':t,'&':t,'\'':t,'(':t,')':t,'*':t,'+':t,',':t,'-':t,'.':t,'/':t,'0':t,'1':t,'2':t,'3':t,'4':t,'5':t,'6':t,'7':t,'8':t,'9':t,':':t,';':t,'<':t,'=':t,'>':t,'?':t,'@':t,'A':t,'B':t,'C':t,'D':t,'E':t,'F':t,'G':t,'H':t,'I':t,'J':t,'K':t,'L':t,'M':t,'N':t,'O':t,'P':t,'Q':t,'R':t,'S':t,'T':t,'U':t,'V':t,'W':t,'X':t,'Y':t,'Z':t,'[':t,'\\':t,']':t,'^':t,'_':t,'a':t,'b':t,'c':t,'d':t,'e':t,'f':t,'g':t,'h':t,'i':t,'j':t,'k':t,'l':t,'m':t,'n':t,'o':t,'p':t,'q':t,'r':t,'s':t,'t':t,'u':t,'v':t,'w':t,'x':t,'y':t,'z':t,'{':t,'|':t,'}':t,'~':t,'«':t,'®':t,'°':t,'±':t,'·':t,'»':t,'Á':t,'Å':t,'É':t,'Ö':t,'×':t,'Ø':t,'ß':t,'à':t,'á':t,'â':t,'ã':t,'ä':t,'å':t,'æ':t,'ç':t,'è':t,'é':t,'ê':t,'ë':t,'ì':t,'í':t,'î':t,'ï':t,'ð':t,'ñ':t,'ò':t,'ó':t,'ô':t,'ö':t,'ø':t,'ù':t,'ú':t,'ü':t,'ý':t,'ā':t,'ă':t,'ć':t,'Č':t,'č':t,'ē':t,'ě':t,'ī':t,'ı':t,'ł':t,'ō':t,'ş':t,'Š':t,'š':t,'ū':t,'Ž':t,'ž':t,'ə':t,'ˈ':t,'ː':t,'́':t,'Γ':t,'Δ':t,'Ζ':t,'Λ':t,'Σ':t,'Ω':t,'α':t,'β':t,'γ':t,'δ':t,'ε':t,'ζ':t,'η':t,'θ':t,'ι':t,'κ':t,'λ':t,'μ':t,'ν':t,'ο':t,'π':t,'ρ':t,'ς':t,'σ':t,'τ':t,'φ':t,'χ':t,'ω':t,'А':t,'Б':t,'В':t,'Д':t,'К':t,'М':t,'О':t,'П':t,'Р':t,'С':t,'Т':t,'а':t,'б':t,'в':t,'г':t,'д':t,'е':t,'з':t,'и':t,'й':t,'к':t,'л':t,'м':t,'н':t,'о':t,'п':t,'р':t,'с':t,'т':t,'у':t,'х':t,'ч':t,'ы':t,'ь':t,'я':t,'ו':t,'י':t,'ا':t,'ب':t,'ة':t,'ت':t,'ج':t,'ح':t,'د':t,'ر':t,'س':t,'ع':t,'ق':t,'ل':t,'م':t,'ن':t,'ه':t,'و':t,'ي':t,'ی':t,'र':t,'ा':t,'्':t,'ก':t,'ง':t,'ด':t,'ต':t,'ท':t,'น':t,'พ':t,'ม':t,'ย':t,'ร':t,'ล':t,'ว':t,'ส':t,'ห':t,'อ':t,'ั':t,'า':t,'ิ':t,'ี':t,'ุ':t,'เ':t,'่':t,'་':t,'‐':t,'–':t,'—':t,'―':t,'‘':t,'’':t,'“':t,'”':t,'†':t,'•':t,'‰':t,'′':t,'※':t,'⁄':t,'←':t,'↑':t,'→':t,'⇒':t,'⇔':t,'∀':t,'∈':t,'−':t,'∞':t,'∶':t,'≒':t,'≤':t,'≪':t,'≫':t,'─':t,'┗':t,'■':t,'□':t,'▲':t,'△':t,'◆':t,'○':t,'◎':t,'●':t,'◯':t,'★':t,'☆':t,'♂':t,'♡':t,'♥':t,'♪':t,'♭':t,'、':t,'。':t,'々':t,'〇':t,'〈':t,'〉':t,'《':t,'》':t,'「':t,'」':t,'『':t,'』':t,'【':t,'】':t,'〒':t,'〔':t,'〕':t,'〜':t,'ぁ':t,'あ':t,'ぃ':t,'い':t,'ぅ':t,'う':t,'ぇ':t,'え':t,'ぉ':t,'お':t,'か':t,'が':t,'き':t,'ぎ':t,'く':t,'ぐ':t,'け':t,'げ':t,'こ':t,'ご':t,'さ':t,'ざ':t,'し':t,'じ':t,'す':t,'ず':t,'せ':t,'ぜ':t,'そ':t,'ぞ':t,'た':t,'だ':t,'ち':t,'ぢ':t,'っ':t,'つ':t,'づ':t,'て':t,'で':t,'と':t,'ど':t,'な':t,'に':t,'ぬ':t,'ね':t,'の':t,'は':t,'ば':t,'ぱ':t,'ひ':t,'び':t,'ぴ':t,'ふ':t,'ぶ':t,'ぷ':t,'へ':t,'べ':t,'ぺ':t,'ほ':t,'ぼ':t,'ぽ':t,'ま':t,'み':t,'む':t,'め':t,'も':t,'ゃ':t,'や':t,'ゅ':t,'ゆ':t,'ょ':t,'よ':t,'ら':t,'り':t,'る':t,'れ':t,'ろ':t,'わ':t,'ゐ':t,'ゑ':t,'を':t,'ん':t,'゚':t,'ゝ':t,'ゞ':t,'ァ':t,'ア':t,'ィ':t,'イ':t,'ゥ':t,'ウ':t,'ェ':t,'エ':t,'ォ':t,'オ':t,'カ':t,'ガ':t,'キ':t,'ギ':t,'ク':t,'グ':t,'ケ':t,'ゲ':t,'コ':t,'ゴ':t,'サ':t,'ザ':t,'シ':t,'ジ':t,'ス':t,'ズ':t,'セ':t,'ゼ':t,'ソ':t,'ゾ':t,'タ':t,'ダ':t,'チ':t,'ヂ':t,'ッ':t,'ツ':t,'ヅ':t,'テ':t,'デ':t,'ト':t,'ド':t,'ナ':t,'ニ':t,'ヌ':t,'ネ':t,'ノ':t,'ハ':t,'バ':t,'パ':t,'ヒ':t,'ビ':t,'ピ':t,'フ':t,'ブ':t,'プ':t,'ヘ':t,'ベ':t,'ペ':t,'ホ':t,'ボ':t,'ポ':t,'マ':t,'ミ':t,'ム':t,'メ':t,'モ':t,'ャ':t,'ヤ':t,'ュ':t,'ユ':t,'ョ':t,'ヨ':t,'ラ':t,'リ':t,'ル':t,'レ':t,'ロ':t,'ワ':t,'ヰ':t,'ヱ':t,'ヲ':t,'ン':t,'ヴ':t,'ヵ':t,'ヶ':t,'・':t,'ー':t,
'一':t,'丁':t,'七':t,'万':t,'丈':t,'三':t,'上':t,'下':t,'不':t,'与':t,'丑':t,'且':t,'丕':t,'世':t,'丘':t,'丙':t,'丞':t,'両':t,'並':t,'中':t,'串':t,'丸':t,'丹':t,'主':t,'丼':t,'乂':t,'乃':t,'久':t,'之':t,'乏':t,'乖':t,'乗':t,'乙':t,'九':t,'乞':t,'也':t,'乱':t,'乳':t,'乾':t,'亀':t,'了':t,'予':t,'争':t,'事':t,'二':t,'于':t,'云':t,'互':t,'五':t,'井':t,'亘':t,'些':t,'亜':t,'亞':t,'亡':t,'亢':t,'交':t,'亥':t,'亦':t,'亨':t,'享':t,'京':t,'亭':t,'亮':t,'人':t,'什':t,'仁':t,'仄':t,'仇':t,'今':t,'介':t,'仏':t,'仔':t,'仕':t,'他':t,'仗':t,'付':t,'仙':t,'代':t,'令':t,'以':t,'仮':t,'仰':t,'仲':t,'件':t,'任':t,'企':t,'伊':t,'伍':t,'伎':t,'伏':t,'伐':t,'休':t,'会':t,'伝':t,'伯':t,'伴':t,'伸':t,'伺':t,'似':t,'伽':t,'佃':t,'但':t,'佇':t,'位':t,'低':t,'住':t,'佐':t,'佑':t,'体':t,'何':t,'余':t,'佛':t,'作':t,'佩':t,'佳':t,'併':t,'使':t,'侃':t,'來':t,'例':t,'侍':t,'侑':t,'供':t,'依':t,'侠':t,'価':t,'侮':t,'侯':t,'侵':t,'侶':t,'便':t,'係':t,'促':t,'俄':t,'俊':t,'俗':t,'俘':t,'保':t,'俟':t,'信':t,'俣':t,'修':t,'俯':t,'俳':t,'俵':t,'俸':t,'俺':t,'倉':t,'個':t,'倍':t,'倒':t,'倖':t,'候':t,'借':t,'倣':t,'値':t,'倦':t,'倫':t,'倭':t,'倶':t,'倹':t,'偉':t,'偏':t,'偕':t,'做':t,'停':t,'健':t,'偲':t,'側':t,'偵':t,'偶':t,'偽':t,'傀':t,'傅':t,'傍':t,'傑':t,'傘':t,'備':t,'催':t,'傭':t,'傲':t,'傳':t,'債':t,'傷':t,'傾':t,'僅':t,'働':t,'像':t,'僑':t,'僕':t,'僚':t,'僧':t,'僭':t,'僻':t,'儀':t,'儁':t,'億':t,'儒':t,'償':t,'儡':t,'優':t,'儲':t,'允':t,'元':t,'兄':t,'充':t,'兆':t,'先':t,'光':t,'克':t,'兌':t,'免':t,'兎':t,'児':t,'兗':t,'党':t,'兜':t,'入':t,'全':t,'兪':t,'八':t,'公':t,'六':t,'共':t,'兵':t,'其':t,'具':t,'典':t,'兼':t,'冀':t,'内':t,'円':t,'冉':t,'冊':t,'再':t,'冏':t,'冑':t,'冒':t,'冗':t,'写':t,'冠':t,'冤':t,'冥':t,'冨':t,'冪':t,'冬':t,'冲':t,'冴':t,'冶':t,'冷':t,'凄':t,'准':t,'凋':t,'凌':t,'凍':t,'凛':t,'凝':t,'凡':t,'処':t,'凧':t,'凪':t,'凰':t,'凱':t,'凶':t,'凸':t,'凹':t,'出':t,'函':t,'刀':t,'刃':t,'分':t,'切':t,'刈':t,'刊':t,'刑':t,'列':t,'初':t,'判':t,'別':t,'利':t,'到':t,'制':t,'刷':t,'券':t,'刹':t,'刺':t,'刻':t,'剃':t,'則':t,'削':t,'剌':t,'前':t,'剖':t,'剛':t,'剣':t,'剤':t,'剥':t,'剪':t,'副':t,'剰':t,'割':t,'創':t,'劇':t,'劉':t,'力':t,'功':t,'加':t,'劣':t,'助':t,'努':t,'劫':t,'励':t,'労':t,'効':t,'劾':t,'勃':t,'勅':t,'勇':t,'勉':t,'勒':t,'動':t,'勘':t,'務':t,'勝':t,'募':t,'勢':t,'勤':t,'勧':t,'勲':t,'勾':t,'勿':t,'匁':t,'匂':t,'包':t,'匈':t,'匍':t,'匐':t,'化':t,'北':t,'匝':t,'匠':t,'匡':t,'匪':t,'匹':t,'区':t,'医':t,'匿':t,'十':t,'千':t,'升':t,'午':t,'半':t,'卍':t,'卑':t,'卒':t,'卓':t,'協':t,'南':t,'単':t,'博':t,'卜':t,'占':t,'卦':t,'卯':t,'印':t,'危':t,'即':t,'却':t,'卵':t,'卸':t,'卿':t,'厄':t,'厘':t,'厚':t,'原':t,'厥':t,'厨':t,'厩':t,'厭':t,'厳':t,'去':t,'参':t,'又':t,'叉':t,'及':t,'友':t,'双':t,'反':t,'収':t,'叔':t,'取':t,'受':t,'叙':t,'叛':t,'叟':t,'叡':t,'叢':t,'口':t,'古':t,'句':t,'叩':t,'只':t,'叫':t,'召':t,'可':t,'台':t,'叱':t,'史':t,'右':t,'叶':t,'号':t,'司':t,'吃':t,'各':t,'合':t,'吉':t,'吊':t,'同':t,'名':t,'后':t,'吏':t,'吐':t,'向':t,'君':t,'吟':t,'吠':t,'否':t,'含':t,'吸':t,'吹':t,'吻':t,'吾':t,'呂':t,'呆':t,'呈':t,'呉':t,'告':t,'呑':t,'呟':t,'周':t,'呪':t,'味':t,'呼':t,'命':t,'咀':t,'咄':t,'咋':t,'和':t,'咎':t,'咤':t,'咬':t,'咲':t,'咳':t,'咸':t,'咽':t,'哀':t,'品':t,'哈':t,'哉':t,'員':t,'哥':t,'哨':t,'哭':t,'哲':t,'哺':t,'唄':t,'唆':t,'唇':t,'唐':t,'唖':t,'唯':t,'唱':t,'唾':t,'啄':t,'商':t,'問':t,'啓':t,'喀':t,'善':t,'喉':t,'喋':t,'喘':t,'喚':t,'喜':t,'喝':t,'喧':t,'喩':t,'喪':t,'喫':t,'喬':t,'喰':t,'営':t,'嗅':t,'嗚':t,'嗜':t,'嗣':t,'嘆':t,'嘉':t,'嘔':t,
'嘗':t,'嘘':t,'嘩':t,'嘱':t,'嘲':t,'嘴':t,'噂':t,'噌':t,'噛':t,'器':t,'噴':t,'噺':t,'嚆':t,'嚇':t,'嚢':t,'嚥':t,'囁':t,'囃':t,'囚':t,'四':t,'回':t,'因':t,'団':t,'囮':t,'困':t,'囲':t,'図':t,'固':t,'国':t,'圀':t,'圃':t,'國':t,'圏':t,'園':t,'圓':t,'團':t,'土':t,'圧':t,'在':t,'圭':t,'地':t,'圳':t,'址':t,'坂':t,'均':t,'坊':t,'坐':t,'坑':t,'坡':t,'坤':t,'坦':t,'坪':t,'垂':t,'型':t,'垢':t,'垣':t,'埃':t,'埋':t,'城':t,'埔':t,'埜':t,'域':t,'埠':t,'埴':t,'執':t,'培':t,'基':t,'埼':t,'堀':t,'堂':t,'堅':t,'堆':t,'堕':t,'堡':t,'堤':t,'堪':t,'堯':t,'堰':t,'報':t,'場':t,'堵':t,'堺':t,'塀':t,'塁':t,'塊':t,'塑':t,'塔':t,'塗':t,'塘':t,'塙':t,'塚':t,'塞':t,'塩':t,'填':t,'塵':t,'塹':t,'塾':t,'境':t,'墓':t,'増':t,'墜':t,'墟':t,'墨':t,'墳':t,'墺':t,'墾':t,'壁':t,'壇':t,'壊':t,'壌':t,'壕':t,'士':t,'壬':t,'壮':t,'声':t,'壱':t,'売':t,'壷':t,'壺':t,'壽':t,'変':t,'夏':t,'夕':t,'外':t,'多':t,'夜':t,'夢':t,'大':t,'天':t,'太':t,'夫':t,'夭':t,'央':t,'失':t,'夷':t,'奄':t,'奇':t,'奈':t,'奉':t,'奎':t,'奏':t,'契':t,'奔':t,'奕':t,'套':t,'奘':t,'奚':t,'奠':t,'奢':t,'奥':t,'奨':t,'奪':t,'奮':t,'女':t,'奴':t,'奸':t,'好':t,'如':t,'妃':t,'妄':t,'妊':t,'妓':t,'妖':t,'妙':t,'妥':t,'妨':t,'妬':t,'妹':t,'妻':t,'妾':t,'姉':t,'始':t,'姑':t,'姓':t,'委':t,'姚':t,'姜':t,'姥':t,'姦':t,'姪':t,'姫':t,'姶':t,'姻':t,'姿':t,'威':t,'娘':t,'娠':t,'娥':t,'娩':t,'娯':t,'娶':t,'娼':t,'婁':t,'婆':t,'婉':t,'婚':t,'婢':t,'婦':t,'婿':t,'媒':t,'媚':t,'媛':t,'嫁':t,'嫉':t,'嫌':t,'嫡':t,'嬉':t,'嬢':t,'嬪':t,'嬰':t,'子':t,'孔':t,'孕':t,'字':t,'存':t,'孚':t,'孝':t,'孟':t,'季':t,'孤':t,'学':t,'孫':t,'孵':t,'學':t,'宅':t,'宇':t,'守':t,'安':t,'宋':t,'完':t,'宍':t,'宏':t,'宕':t,'宗':t,'官':t,'宙':t,'定':t,'宛':t,'宜':t,'宝':t,'実':t,'客':t,'宣':t,'室':t,'宥':t,'宦':t,'宮':t,'宰':t,'害':t,'宴':t,'宵':t,'家':t,'宸':t,'容':t,'宿':t,'寂':t,'寄':t,'寅':t,'密':t,'寇':t,'富':t,'寒':t,'寓':t,'寛':t,'寝':t,'察':t,'寡':t,'實':t,'寧':t,'寨':t,'審':t,'寮':t,'寵':t,'寶':t,'寸':t,'寺':t,'対':t,'寿':t,'封':t,'専':t,'射':t,'将':t,'尉':t,'尊':t,'尋':t,'導':t,'小':t,'少':t,'尖':t,'尚':t,'尤':t,'尭':t,'就':t,'尸':t,'尹':t,'尺':t,'尻':t,'尼':t,'尽':t,'尾':t,'尿':t,'局':t,'居':t,'屈':t,'届':t,'屋':t,'屍':t,'屏':t,'屑':t,'屓':t,'展':t,'属':t,'屠':t,'層':t,'履':t,'屯':t,'山':t,'岐':t,'岑':t,'岡':t,'岩':t,'岬':t,'岱':t,'岳':t,'岸':t,'峙':t,'峠':t,'峡':t,'峨':t,'峯':t,'峰':t,'島':t,'峻':t,'崇':t,'崋':t,'崎':t,'崑':t,'崔':t,'崖':t,'崗':t,'崙':t,'崩':t,'嵌':t,'嵐':t,'嵩':t,'嵯':t,'嶋':t,'嶺':t,'嶼':t,'嶽':t,'巌':t,'巖':t,'川':t,'州':t,'巡':t,'巣':t,'工':t,'左':t,'巧':t,'巨':t,'巫':t,'差':t,'己':t,'已':t,'巳':t,'巴':t,'巷':t,'巻':t,'巽':t,'巾':t,'市':t,'布':t,'帆':t,'希':t,'帖':t,'帛':t,'帝':t,'帥':t,'師':t,'席':t,'帯':t,'帰':t,'帳':t,'帷':t,'常':t,'帽':t,'幅':t,'幇':t,'幌':t,'幕':t,'幟':t,'幡':t,'幣':t,'干':t,'平':t,'年':t,'并':t,'幸':t,'幹':t,'幻':t,'幼':t,'幽':t,'幾':t,'庁':t,'広':t,'庄':t,'庇':t,'床':t,'序':t,'底':t,'店':t,'庚':t,'府':t,'度':t,'座':t,'庫':t,'庭':t,'庵':t,'庶':t,'康':t,'庸':t,'庾':t,'廃':t,'廈':t,'廉':t,'廊':t,'廓':t,'廖':t,'廟':t,'廠':t,'廣':t,'廬':t,'延':t,'廷':t,'建':t,'廻':t,'廿':t,'弁':t,'弄':t,'弊':t,'式':t,'弐':t,'弓':t,'弔':t,'引':t,'弘':t,'弛':t,'弟':t,'弥':t,'弦':t,'弧':t,'弩':t,'弱':t,'張':t,'強':t,'弼':t,'弾':t,'彅':t,'彌':t,'当':t,'彗':t,'彙':t,'形':t,'彦':t,'彩':t,'彪':t,'彫':t,'彬':t,'彭':t,'彰':t,'影':t,'彷':t,'役':t,'彼':t,'彿':t,'往':t,'征':t,'径':t,'待':t,'徊':t,'律':t,'後':t,'徐':t,'徒':t,'従':t,'得':t,'徘':t,'御':t,'徨':t,'復':t,'循':t,'微':t,'徳':t,'徴':t,'德':t,'徹':t,'徽':t,'心':t,'必':t,'忌':t,
'忍':t,'志':t,'忘':t,'忙':t,'応':t,'忠':t,'快':t,'念':t,'忽':t,'怒':t,'怖':t,'怜':t,'思':t,'怠':t,'怡':t,'急':t,'性':t,'怨':t,'怪':t,'怯':t,'恋':t,'恐':t,'恒':t,'恕':t,'恣':t,'恥':t,'恨':t,'恩':t,'恪':t,'恭':t,'息':t,'恰':t,'恵':t,'悉':t,'悌':t,'悔':t,'悟':t,'悠':t,'患':t,'悦':t,'悩':t,'悪':t,'悲':t,'悶':t,'悼':t,'情':t,'惇':t,'惑':t,'惚':t,'惜':t,'惟':t,'惠':t,'惣':t,'惧':t,'惨':t,'惰':t,'想':t,'惹':t,'愁':t,'愉':t,'愍':t,'意':t,'愕':t,'愚':t,'愛':t,'感':t,'慄':t,'慈':t,'態':t,'慌':t,'慎':t,'慕':t,'慢':t,'慣':t,'慧':t,'慨':t,'慮':t,'慰':t,'慶':t,'憂':t,'憎':t,'憐':t,'憑':t,'憚':t,'憤':t,'憧':t,'憩':t,'憲':t,'憶':t,'憾':t,'懇':t,'應':t,'懐':t,'懲':t,'懸':t,'懺':t,'懿':t,'戊':t,'戌':t,'戍':t,'戎':t,'成':t,'我':t,'戒':t,'或':t,'戚':t,'戟':t,'戦':t,'戮':t,'戯':t,'戴':t,'戸':t,'戻':t,'房':t,'所':t,'扁':t,'扇':t,'扈':t,'扉':t,'手':t,'才':t,'打':t,'払':t,'托':t,'扮':t,'扱':t,'扶':t,'批':t,'承':t,'技':t,'抄':t,'把':t,'抑':t,'抒':t,'投':t,'抗':t,'折':t,'抜':t,'択':t,'披':t,'抱':t,'抵':t,'抹':t,'押':t,'抽':t,'担':t,'拉':t,'拌':t,'拍':t,'拐':t,'拒':t,'拓':t,'拗':t,'拘':t,'拙':t,'招':t,'拝':t,'拠':t,'拡':t,'括':t,'拭':t,'拮':t,'拳':t,'拵':t,'拶':t,'拷':t,'拼':t,'拾':t,'拿':t,'持':t,'指':t,'按':t,'挑':t,'挙':t,'挟':t,'挨':t,'挫':t,'振':t,'挺':t,'挽':t,'挿':t,'捉':t,'捌':t,'捏':t,'捕':t,'捗':t,'捜':t,'捧':t,'捨':t,'捩':t,'据':t,'捲':t,'捷':t,'捺':t,'捻':t,'掃':t,'授':t,'掌':t,'排':t,'掘':t,'掛':t,'掟':t,'掠':t,'採':t,'探':t,'接':t,'控':t,'推':t,'掩':t,'措':t,'掬':t,'掲':t,'掴':t,'掻':t,'掾':t,'揃':t,'揄':t,'揆':t,'揉':t,'描':t,'提':t,'揖':t,'揚':t,'換':t,'握':t,'揮':t,'援':t,'揶':t,'揺':t,'損':t,'搬':t,'搭':t,'携':t,'搾':t,'摂':t,'摘':t,'摩':t,'摯':t,'摺':t,'撃':t,'撒':t,'撚':t,'撤':t,'撥':t,'撫':t,'播':t,'撮':t,'撰':t,'撲':t,'撹':t,'擁':t,'操':t,'擢':t,'擦':t,'擬':t,'擲':t,'擾':t,'攀':t,'攘':t,'攣':t,'攪':t,'攫':t,'支':t,'攸':t,'改':t,'攻':t,'放':t,'政':t,'故':t,'敏':t,'救':t,'敗':t,'教':t,'敢':t,'散':t,'敦':t,'敬':t,'数':t,'整':t,'敵':t,'敷':t,'斂':t,'文':t,'斉':t,'斌':t,'斎':t,'斐':t,'斑':t,'斗':t,'料':t,'斛':t,'斜':t,'斡':t,'斤':t,'斥':t,'斧':t,'斬':t,'断':t,'斯':t,'新':t,'方':t,'於':t,'施':t,'旅':t,'旋':t,'族':t,'旗':t,'旛':t,'既':t,'日':t,'旦':t,'旧':t,'旨':t,'早':t,'旬':t,'旭':t,'旱':t,'旺':t,'昂':t,'昆':t,'昇':t,'昌':t,'明':t,'昏':t,'易':t,'昔':t,'星':t,'映':t,'春':t,'昧':t,'昨':t,'昭':t,'是':t,'昴':t,'昶':t,'昼':t,'晁':t,'時':t,'晃':t,'晋':t,'晏':t,'晒':t,'晟':t,'晦':t,'晧':t,'晩':t,'普':t,'景':t,'晰':t,'晴':t,'晶':t,'智':t,'暁':t,'暇':t,'暉':t,'暑':t,'暖':t,'暗':t,'暢':t,'暦':t,'暫':t,'暮':t,'暴':t,'曇':t,'曖':t,'曙':t,'曜':t,'曝':t,'曰':t,'曲':t,'曳':t,'更':t,'書':t,'曹':t,'曼':t,'曽':t,'曾':t,'替':t,'最':t,'會':t,'月':t,'有':t,'朋':t,'服':t,'朔':t,'朕':t,'朗':t,'望':t,'朝':t,'期':t,'朧':t,'木':t,'未':t,'末':t,'本':t,'札':t,'朱':t,'朴':t,'机':t,'朽':t,'杉':t,'李':t,'杏':t,'材':t,'村':t,'杓':t,'杖':t,'杜':t,'束':t,'条':t,'杣':t,'来':t,'杭':t,'杯':t,'東':t,'杵':t,'杷':t,'松':t,'板':t,'枇':t,'析':t,'枕':t,'林':t,'枚':t,'果':t,'枝':t,'枠':t,'枡':t,'枢':t,'枯':t,'架':t,'柄':t,'柊':t,'柏':t,'某':t,'柑':t,'染':t,'柔':t,'柘':t,'柚':t,'柩':t,'柯':t,'柱':t,'柳':t,'柴':t,'柵':t,'査':t,'柿':t,'栃':t,'栄':t,'栓':t,'栖':t,'栗':t,'栞':t,'校':t,'株':t,'核':t,'根':t,'格':t,'栽':t,'桁':t,'桂':t,'桃':t,'案':t,'桐':t,'桑':t,'桓':t,'桔':t,'桜':t,'桝':t,'桟':t,'桧':t,'桶':t,'桿':t,'梁':t,'梅':t,'梓':t,'梗':t,'條':t,'梢':t,'梧':t,'梨':t,'梯':t,'械':t,'梱':t,'梵':t,'梶':t,'棄':t,'棋':t,'棍':t,'棒':t,'棗':t,'棘':t,'棚':t,'棟':t,'棠':t,'森':t,'棲':t,'棹':t,'棺':t,
'椀':t,'椅':t,'椋':t,'植':t,'椎':t,'椒':t,'検':t,'椿':t,'楊':t,'楓':t,'楔':t,'楕':t,'楚':t,'楠':t,'楡':t,'楢':t,'業':t,'楯':t,'極':t,'楷':t,'楼':t,'楽':t,'概':t,'榊':t,'榎':t,'榛':t,'榜':t,'榮':t,'榴':t,'槃':t,'槇':t,'構':t,'槌':t,'槍':t,'槐':t,'槓':t,'様':t,'槙':t,'槨':t,'槻':t,'槽':t,'槿':t,'樂':t,'樊':t,'樋':t,'標':t,'樟':t,'模':t,'権':t,'横':t,'樫':t,'樹':t,'樺':t,'樽':t,'橋':t,'橘':t,'橙':t,'機':t,'橿':t,'檀':t,'檄':t,'檎':t,'檗':t,'檜':t,'檣':t,'檻':t,'櫂':t,'櫃':t,'櫓':t,'櫛':t,'櫻':t,'欄':t,'欅':t,'欠':t,'次':t,'欣':t,'欧':t,'欲':t,'欺':t,'欽':t,'款':t,'歌':t,'歓':t,'止':t,'正':t,'此':t,'武':t,'歩':t,'歪':t,'歯':t,'歳':t,'歴':t,'死':t,'歿':t,'殆':t,'殉':t,'殊':t,'残':t,'殖':t,'殲':t,'殴':t,'段':t,'殷':t,'殺':t,'殻':t,'殿':t,'毀':t,'毅':t,'母':t,'毎':t,'毒':t,'比':t,'毘':t,'毛':t,'毫':t,'毬':t,'毯':t,'氏':t,'氐':t,'民':t,'気':t,'氣':t,'水':t,'氷':t,'永':t,'氾':t,'汀':t,'汁':t,'求':t,'汎':t,'汐':t,'汗':t,'汚':t,'汝':t,'江':t,'池':t,'汪':t,'汰':t,'汲':t,'決':t,'汽':t,'汾':t,'沂':t,'沃':t,'沈':t,'沌':t,'沓':t,'沖':t,'沙':t,'沛':t,'没':t,'沢':t,'沫':t,'河':t,'沸':t,'油':t,'治':t,'沼':t,'沿':t,'況':t,'泄':t,'泉':t,'泊':t,'泌':t,'法':t,'泗':t,'泡':t,'波':t,'泣':t,'泥':t,'注':t,'泰':t,'泳':t,'洋':t,'洒':t,'洗':t,'洙':t,'洛':t,'洞':t,'津':t,'洩':t,'洪':t,'洲':t,'活':t,'派':t,'流':t,'浄':t,'浅':t,'浙':t,'浚':t,'浜':t,'浦':t,'浩':t,'浪':t,'浬':t,'浮':t,'浴':t,'海':t,'浸':t,'涅':t,'消':t,'涌':t,'涙':t,'涛':t,'涜':t,'涯':t,'液':t,'涵':t,'涼':t,'淀':t,'淋':t,'淑':t,'淘':t,'淡':t,'淫':t,'淮':t,'深':t,'淳':t,'淵':t,'混':t,'添':t,'清':t,'渇':t,'済':t,'渉':t,'渋':t,'渓':t,'渕':t,'渚':t,'減':t,'渠':t,'渡':t,'渤':t,'渥':t,'渦':t,'温':t,'渫':t,'測':t,'渭':t,'港':t,'游':t,'渾':t,'湊':t,'湖':t,'湘':t,'湛':t,'湧':t,'湯':t,'湾':t,'湿':t,'満':t,'源':t,'準':t,'溜':t,'溝':t,'溢':t,'溥':t,'溪':t,'溶':t,'溺':t,'滄':t,'滅':t,'滋':t,'滑':t,'滓':t,'滝':t,'滞':t,'滬':t,'滲':t,'滴':t,'滸':t,'漁':t,'漂':t,'漆':t,'漉':t,'漏':t,'漑':t,'演':t,'漕':t,'漠':t,'漢':t,'漣':t,'漫':t,'漬':t,'漱':t,'漳':t,'漸':t,'漿':t,'潁':t,'潔':t,'潘':t,'潜':t,'潟':t,'潤':t,'潭':t,'潮':t,'潰':t,'潼':t,'澁':t,'澄':t,'澎':t,'澤':t,'澪':t,'澱':t,'澳':t,'激':t,'濁':t,'濃':t,'濠':t,'濡':t,'濤':t,'濫':t,'濯':t,'濱':t,'濾':t,'瀉':t,'瀋':t,'瀑':t,'瀕':t,'瀞':t,'瀧':t,'瀬':t,'瀾':t,'灌':t,'灘':t,'火':t,'灯':t,'灰':t,'灸':t,'灼':t,'災':t,'炉':t,'炊':t,'炎':t,'炒':t,'炙':t,'炭':t,'炳':t,'炸':t,'点':t,'為':t,'烈':t,'烏':t,'烙':t,'焉':t,'焔':t,'焙':t,'焚':t,'無':t,'焦':t,'然':t,'焼':t,'煉':t,'煌':t,'煎':t,'煕':t,'煙':t,'煤':t,'煥':t,'照':t,'煩':t,'煬':t,'煮':t,'煽':t,'熊':t,'熙':t,'熟':t,'熱':t,'熹':t,'熾':t,'燁':t,'燃':t,'燈':t,'燐':t,'燕':t,'燥':t,'燦':t,'燭':t,'燮':t,'燻':t,'爆':t,'爛':t,'爪':t,'爬':t,'爵':t,'父':t,'爺':t,'爽':t,'爾':t,'片':t,'版':t,'牌':t,'牒':t,'牙':t,'牛':t,'牝':t,'牟':t,'牡':t,'牢':t,'牧':t,'物':t,'牲':t,'特':t,'牽':t,'犀':t,'犠':t,'犬':t,'犯':t,'状':t,'狂':t,'狄':t,'狐':t,'狗':t,'狙':t,'狛':t,'狡':t,'狩':t,'独':t,'狭':t,'狸':t,'狼':t,'猛':t,'猟':t,'猥':t,'猪':t,'猫':t,'献':t,'猶':t,'猷':t,'猾':t,'猿':t,'獄':t,'獅':t,'獣':t,'獨':t,'獲':t,'玄':t,'率':t,'玉':t,'王':t,'玖':t,'玩':t,'玲':t,'珀':t,'珂':t,'珈':t,'珊':t,'珍':t,'珠':t,'珪':t,'班':t,'現':t,'球':t,'琅':t,'理':t,'琉':t,'琢':t,'琥':t,'琨':t,'琲':t,'琳':t,'琴':t,'琵':t,'琶':t,'瑕':t,'瑚':t,'瑛':t,'瑜':t,'瑞':t,'瑠':t,'瑤':t,'瑩':t,'瑪':t,'瑳':t,'璃':t,'璋':t,'璧':t,'環':t,'璽':t,'瓊':t,'瓜':t,'瓢':t,'瓦':t,'瓶':t,'甑':t,'甕':t,'甘':t,'甚':t,'生':t,'産':t,'甥':t,'甦':t,'用':t,'甫':t,'田':t,'由':t,'甲':t,'申':t,'男':t,'町':t,
'画':t,'界':t,'畏':t,'畑':t,'畔':t,'留':t,'畜':t,'畝':t,'畠':t,'畢':t,'略':t,'畦':t,'番':t,'異':t,'畳':t,'當':t,'畷':t,'畿':t,'疆':t,'疇':t,'疋':t,'疎':t,'疏':t,'疑':t,'疫':t,'疱':t,'疲':t,'疵':t,'疹':t,'疼':t,'疽':t,'疾':t,'病':t,'症':t,'痍':t,'痒':t,'痕':t,'痘':t,'痙':t,'痛':t,'痢':t,'痩':t,'痰':t,'痴':t,'痺':t,'瘍':t,'瘡':t,'瘤':t,'療':t,'癌':t,'癒':t,'癖':t,'癬':t,'発':t,'登':t,'白':t,'百':t,'的':t,'皆':t,'皇':t,'皐':t,'皓':t,'皝':t,'皮':t,'皿':t,'盃':t,'盆':t,'盈':t,'益':t,'盗':t,'盛':t,'盟':t,'監':t,'盤':t,'盧':t,'盪':t,'目':t,'盲':t,'直':t,'相':t,'盾':t,'省':t,'眉':t,'看':t,'県':t,'眞':t,'真':t,'眠':t,'眩':t,'眷':t,'眺':t,'眼':t,'着':t,'睡':t,'督':t,'睦':t,'睨':t,'睿':t,'瞑':t,'瞞':t,'瞬':t,'瞭':t,'瞰':t,'瞳':t,'瞼':t,'矛':t,'矢':t,'知':t,'矩':t,'短':t,'矮':t,'矯':t,'石':t,'砂':t,'研':t,'砕':t,'砥':t,'砦':t,'砧':t,'砲':t,'破':t,'砺':t,'硝':t,'硫':t,'硬':t,'硯':t,'碁':t,'碇':t,'碍':t,'碑':t,'碓':t,'碗':t,'碧':t,'碩':t,'確':t,'磁':t,'磐':t,'磔':t,'磨':t,'磯':t,'礁':t,'礎':t,'礦':t,'礫':t,'示':t,'礼':t,'社':t,'祀':t,'祁':t,'祇':t,'祈':t,'祉':t,'祐':t,'祓':t,'祖':t,'祗':t,'祚':t,'祝':t,'神':t,'祟':t,'祠':t,'祢':t,'祥':t,'票':t,'祭':t,'祷':t,'祺':t,'禁':t,'禄':t,'禅':t,'禍':t,'禎':t,'福':t,'禧':t,'禮':t,'禰':t,'禹':t,'禽':t,'禿':t,'秀':t,'私':t,'秉':t,'秋':t,'科':t,'秒':t,'秘':t,'租':t,'秤':t,'秦':t,'秩':t,'称':t,'移':t,'稀':t,'程':t,'税':t,'稔':t,'稗':t,'稙':t,'稚':t,'稜':t,'稠':t,'種':t,'稲':t,'稷':t,'稼':t,'稽':t,'稿':t,'穀':t,'穂':t,'穆':t,'積':t,'穎':t,'穏':t,'穢':t,'穣':t,'穫':t,'穴':t,'究':t,'空':t,'穿':t,'突':t,'窃':t,'窄':t,'窒':t,'窓':t,'窟':t,'窩':t,'窪':t,'窮':t,'窯':t,'窺':t,'竄':t,'竇':t,'竈':t,'立':t,'站':t,'竜':t,'章':t,'竣':t,'童':t,'竪':t,'端':t,'競':t,'竹':t,'竺':t,'竿':t,'笏':t,'笑':t,'笙':t,'笛':t,'笠':t,'笥':t,'符':t,'第':t,'笹':t,'筆':t,'筈':t,'等':t,'筋':t,'筏':t,'筐':t,'筑':t,'筒':t,'答':t,'策':t,'筵':t,'箇':t,'箋':t,'箏':t,'箒':t,'箔':t,'箕':t,'算':t,'箚':t,'管':t,'箪':t,'箭':t,'箱':t,'箸':t,'節':t,'範':t,'篆':t,'篇':t,'築':t,'篠':t,'篤':t,'篩':t,'篭':t,'簒':t,'簗':t,'簡':t,'簾':t,'簿':t,'籃':t,'籍':t,'籠':t,'籤':t,'米':t,'籾':t,'粉':t,'粋':t,'粍':t,'粒':t,'粕':t,'粗':t,'粘':t,'粛':t,'粟':t,'粥':t,'粧':t,'粲':t,'精':t,'糊':t,'糎':t,'糖':t,'糞':t,'糟':t,'糠':t,'糧':t,'糸':t,'系':t,'糾':t,'紀':t,'約':t,'紅':t,'紆':t,'紇':t,'紋':t,'納':t,'紐':t,'純':t,'紗':t,'紘':t,'紙':t,'級':t,'紛':t,'素':t,'紡':t,'索':t,'紫':t,'累':t,'細':t,'紳':t,'紹':t,'紺':t,'終':t,'絃':t,'組':t,'絆':t,'経':t,'結':t,'絞':t,'絡':t,'絢':t,'給':t,'絨':t,'統':t,'絵':t,'絶':t,'絹':t,'綏':t,'經':t,'継':t,'続':t,'綜':t,'綬':t,'維':t,'綱':t,'網':t,'綴':t,'綸':t,'綺':t,'綻':t,'綽':t,'綾':t,'綿':t,'緊':t,'緋':t,'総':t,'緑':t,'緒':t,'線':t,'締':t,'編':t,'緩':t,'緬':t,'緯':t,'練':t,'緻':t,'縁':t,'縄':t,'縛':t,'縞':t,'縣':t,'縦':t,'縫':t,'縮':t,'總':t,'績':t,'繁':t,'繊':t,'繋':t,'繍':t,'織':t,'繕':t,'繡':t,'繭':t,'繰':t,'繹':t,'纂':t,'纏':t,'缶':t,'罠':t,'罪':t,'置':t,'罰':t,'署':t,'罵':t,'罷':t,'罹':t,'羅':t,'羊':t,'羌':t,'美':t,'羞':t,'群':t,'羨':t,'義':t,'羲':t,'羹':t,'羽':t,'翁':t,'翅':t,'翊':t,'翌':t,'習':t,'翔':t,'翟':t,'翠':t,'翰':t,'翻':t,'翼':t,'耀':t,'老':t,'考':t,'者':t,'耆':t,'而':t,'耐':t,'耕':t,'耗':t,'耳':t,'耶':t,'耽':t,'耿':t,'聖':t,'聘':t,'聚':t,'聞':t,'聡':t,'聯':t,'聰':t,'聲':t,'聳':t,'聴':t,'職':t,'聾':t,'肆':t,'肇':t,'肉':t,'肋':t,'肌':t,'肖':t,'肘':t,'肛':t,'肝':t,'股':t,'肢':t,'肥':t,'肩':t,'肪':t,'肯':t,'育':t,'肴':t,'肺':t,'胃':t,'胆':t,'背':t,'胎':t,'胚':t,'胞':t,'胡':t,'胤':t,'胱':t,'胴':t,'胸':t,'能':t,'脂':t,'脅':t,'脆':t,
'脇':t,'脈':t,'脊':t,'脚':t,'脛':t,'脩':t,'脱':t,'脳':t,'脹':t,'脾':t,'腋':t,'腎':t,'腐':t,'腔':t,'腕':t,'腫':t,'腰':t,'腱':t,'腸':t,'腹':t,'腺':t,'腿':t,'膀':t,'膏':t,'膚':t,'膜':t,'膝':t,'膠':t,'膣':t,'膨':t,'膳':t,'膵':t,'膿':t,'臀':t,'臂':t,'臆':t,'臍':t,'臓':t,'臣':t,'臥':t,'臧':t,'臨':t,'自':t,'臭':t,'至':t,'致':t,'臺':t,'臼':t,'舅':t,'與':t,'興':t,'舌':t,'舎':t,'舐':t,'舒':t,'舗':t,'舘':t,'舛':t,'舜':t,'舞':t,'舟':t,'航':t,'般':t,'舵':t,'舶':t,'舷':t,'船':t,'艇':t,'艘':t,'艤':t,'艦':t,'良':t,'色':t,'艶':t,'艾':t,'芋':t,'芒':t,'芙':t,'芝':t,'芥':t,'芦':t,'芭':t,'芯':t,'花':t,'芳':t,'芸':t,'芹':t,'芽':t,'苅':t,'苑':t,'苔':t,'苗':t,'苛':t,'苞':t,'若':t,'苦':t,'苫':t,'英':t,'苺':t,'苻':t,'茂':t,'范':t,'茅':t,'茉':t,'茎':t,'茜':t,'茨':t,'茲':t,'茶':t,'茸':t,'茹':t,'荀':t,'草':t,'荊':t,'荏':t,'荒':t,'荘':t,'荷':t,'荻':t,'荼':t,'莉':t,'莞':t,'莢':t,'莫':t,'莱':t,'莽':t,'菅':t,'菊':t,'菌':t,'菓':t,'菖':t,'菜':t,'菟':t,'菩':t,'華':t,'菰':t,'菱':t,'萄':t,'萇':t,'萊':t,'萌':t,'萎':t,'萩':t,'萬':t,'萱':t,'萼':t,'落':t,'葉':t,'著':t,'葛':t,'葡':t,'董':t,'葦':t,'葬':t,'葯':t,'葱':t,'葵':t,'葺':t,'蒐':t,'蒔':t,'蒙':t,'蒜':t,'蒲':t,'蒸':t,'蒼':t,'蓄':t,'蓉':t,'蓋':t,'蓑':t,'蓬':t,'蓮':t,'蓼':t,'蔑':t,'蔓':t,'蔚':t,'蔡':t,'蔣':t,'蔦':t,'蔭':t,'蔵':t,'蔽':t,'蕃':t,'蕉':t,'蕊':t,'蕎':t,'蕨':t,'蕩':t,'蕪':t,'蕭':t,'蕾':t,'薄':t,'薇':t,'薊':t,'薔':t,'薗':t,'薙':t,'薛':t,'薦':t,'薨':t,'薩':t,'薪':t,'薫':t,'薬':t,'薮':t,'藁':t,'藍':t,'藏':t,'藝':t,'藤':t,'藩':t,'藪':t,'藺':t,'藻':t,'蘂':t,'蘆':t,'蘇':t,'蘭':t,'虎':t,'虐':t,'虔':t,'虚':t,'虜':t,'虞':t,'號':t,'虫':t,'虹':t,'虻':t,'蚊':t,'蚕':t,'蛇':t,'蛋':t,'蛍':t,'蛙':t,'蛛':t,'蛭':t,'蛮':t,'蛸':t,'蛹':t,'蛾':t,'蜀':t,'蜂':t,'蜘':t,'蜜':t,'蜷':t,'蝉':t,'蝋':t,'蝕':t,'蝦':t,'蝶':t,'融':t,'螺':t,'蟄':t,'蟲':t,'蟹':t,'蟻':t,'蠣':t,'血':t,'衆':t,'行':t,'衍':t,'術':t,'街':t,'衙':t,'衛':t,'衝':t,'衞':t,'衡':t,'衣':t,'表':t,'衰':t,'衷':t,'袁':t,'袂':t,'袈':t,'袋':t,'袖':t,'被':t,'袴':t,'裁':t,'裂':t,'装':t,'裏':t,'裔':t,'裕':t,'補':t,'裟':t,'裡':t,'裳':t,'裴':t,'裸':t,'製':t,'裾':t,'複':t,'褐':t,'褒':t,'褻':t,'襄':t,'襖':t,'襟':t,'襲':t,'襷':t,'西':t,'要':t,'覆':t,'覇':t,'見':t,'規':t,'視':t,'覗':t,'覚':t,'覧':t,'親':t,'観':t,'角':t,'解':t,'触':t,'言':t,'訂':t,'訃':t,'計':t,'訊':t,'討':t,'訓':t,'託':t,'記':t,'訛':t,'訟':t,'訣':t,'訥':t,'訪':t,'設':t,'許':t,'訳':t,'訴':t,'訶':t,'診':t,'註':t,'証':t,'詐':t,'詔':t,'評':t,'詞':t,'詠':t,'詣':t,'試':t,'詩':t,'詫':t,'詮':t,'詰':t,'話':t,'該':t,'詳':t,'誅':t,'誇':t,'誉':t,'誌':t,'認':t,'誓':t,'誕':t,'誘':t,'語':t,'誠':t,'誤':t,'誦':t,'説':t,'読':t,'誰':t,'課':t,'誹':t,'誼':t,'調':t,'談':t,'請':t,'諌':t,'諍':t,'諏':t,'諒':t,'論':t,'諜':t,'諡':t,'諦':t,'諧':t,'諫':t,'諭':t,'諮':t,'諱':t,'諷':t,'諸':t,'諺':t,'諾':t,'謀':t,'謁':t,'謂':t,'謄':t,'謎':t,'謐':t,'謗':t,'謙':t,'講':t,'謝':t,'謡':t,'謨':t,'謬':t,'謳':t,'謹':t,'證':t,'識':t,'譚':t,'譜':t,'警':t,'議':t,'譲':t,'護':t,'讀':t,'讃':t,'讐':t,'讒':t,'谷':t,'豆':t,'豊':t,'豚':t,'象':t,'豪':t,'豫':t,'豹':t,'貌':t,'貝':t,'貞':t,'負':t,'財':t,'貢':t,'貧':t,'貨':t,'販':t,'貪':t,'貫':t,'責':t,'貯':t,'貰':t,'貴':t,'貶':t,'買':t,'貸':t,'費':t,'貼':t,'貿':t,'賀':t,'賂':t,'賃':t,'賄':t,'資':t,'賈':t,'賊':t,'賑':t,'賓':t,'賛':t,'賜':t,'賞':t,'賠':t,'賢':t,'賣':t,'賤':t,'賦':t,'質':t,'賭':t,'購':t,'賽':t,'贄':t,'贅':t,'贈':t,'贋':t,'贔':t,'贖':t,'赤':t,'赦':t,'赫':t,'走':t,'赳':t,'赴':t,'起':t,'超':t,'越':t,'趙':t,'趣':t,'趨':t,'足':t,'趾':t,'跋':t,'距':t,'跡':t,'跨':t,'路':t,'跳':t,'践':t,'踊':t,'踏':t,'踪':t,'踵':t,'蹂':t,'蹄':t,
'蹊':t,'蹟':t,'蹴':t,'躁':t,'躇':t,'躊':t,'躍':t,'躙':t,'身':t,'躯':t,'車':t,'軋':t,'軌':t,'軍':t,'軒':t,'軟':t,'転':t,'軸':t,'軽':t,'較':t,'載':t,'輌':t,'輔':t,'輛':t,'輜':t,'輝':t,'輩':t,'輪':t,'輯':t,'輸':t,'輻':t,'輿':t,'轄':t,'轍':t,'轟':t,'轢':t,'辛':t,'辞':t,'辟':t,'辣':t,'辰':t,'辱':t,'農':t,'辺':t,'辻':t,'込':t,'辿':t,'迂':t,'迄':t,'迅':t,'迎':t,'近':t,'返':t,'迦':t,'迪':t,'迫':t,'迭':t,'述':t,'迷':t,'迹':t,'追':t,'退':t,'送':t,'逃':t,'逅':t,'逆':t,'逍':t,'透':t,'逐':t,'逓':t,'途':t,'逗':t,'這':t,'通':t,'逝':t,'速':t,'造':t,'逢':t,'連':t,'逮':t,'週':t,'進':t,'逵':t,'逸':t,'逼':t,'遁':t,'遂':t,'遅':t,'遇':t,'遊':t,'運':t,'遍':t,'過':t,'道':t,'達':t,'違':t,'遙':t,'遜':t,'遠':t,'遡':t,'遣':t,'遥':t,'適':t,'遭':t,'遮':t,'遵':t,'遷':t,'選':t,'遺':t,'遼':t,'遽':t,'避':t,'邁':t,'邂':t,'還':t,'邇':t,'邉':t,'邊':t,'邑':t,'邢':t,'那':t,'邦':t,'邨':t,'邪':t,'邯':t,'邱':t,'邵':t,'邸':t,'郁':t,'郊':t,'郎':t,'郡':t,'郢':t,'部':t,'郭':t,'郵':t,'郷':t,'都':t,'鄒':t,'鄧':t,'鄭':t,'鄲':t,'鄴':t,'酉':t,'酋':t,'酌':t,'配':t,'酎':t,'酒':t,'酔':t,'酢':t,'酪':t,'酬':t,'酵':t,'酷':t,'酸':t,'醍':t,'醐':t,'醒':t,'醜':t,'醤':t,'醸':t,'采':t,'釈':t,'釉':t,'里':t,'重':t,'野':t,'量':t,'金':t,'釘':t,'釜':t,'針':t,'釣':t,'釧':t,'鈍':t,'鈔':t,'鈞':t,'鈴':t,'鉄':t,'鉉':t,'鉛':t,'鉢':t,'鉤':t,'鉦':t,'鉱':t,'鉾':t,'銀':t,'銃':t,'銅':t,'銑':t,'銘':t,'銚':t,'銭':t,'鋏':t,'鋒':t,'鋤':t,'鋭':t,'鋲':t,'鋳':t,'鋸':t,'鋼':t,'錆':t,'錐':t,'錘':t,'錠':t,'錦':t,'錨':t,'錫':t,'錬':t,'錮':t,'錯':t,'録':t,'鍋':t,'鍔':t,'鍛':t,'鍬':t,'鍮':t,'鍵':t,'鍼':t,'鍾':t,'鎌':t,'鎖':t,'鎚':t,'鎧':t,'鎬':t,'鎮':t,'鏃':t,'鏑':t,'鏡':t,'鐘':t,'鐵':t,'鐸':t,'鑑':t,'鑽':t,'長':t,'門':t,'閃':t,'閉':t,'開':t,'閏':t,'閑':t,'間':t,'閔':t,'閘':t,'関':t,'閣':t,'閤':t,'閥':t,'閩':t,'閭':t,'閲':t,'閻':t,'閾':t,'闇':t,'闊':t,'闍':t,'闕':t,'闘':t,'阜':t,'阪':t,'阮':t,'防':t,'阻':t,'阿':t,'陀':t,'附':t,'降':t,'限':t,'陛':t,'陝':t,'院':t,'陣':t,'除':t,'陥':t,'陪':t,'陰':t,'陳':t,'陵':t,'陶':t,'陸':t,'険':t,'陽':t,'隅':t,'隆':t,'隈':t,'隊':t,'隋':t,'階':t,'随':t,'隔':t,'隕':t,'隘':t,'隙':t,'際':t,'障':t,'隠':t,'隣':t,'隧':t,'隴':t,'隷':t,'隻':t,'隼':t,'雀':t,'雁':t,'雄':t,'雅':t,'集':t,'雇':t,'雉':t,'雌':t,'雍':t,'雑':t,'雙':t,'雛':t,'離':t,'難':t,'雨':t,'雪':t,'雫':t,'雰':t,'雲':t,'零':t,'雷':t,'電':t,'需':t,'震':t,'霊':t,'霍':t,'霖':t,'霜':t,'霞':t,'霧':t,'露':t,'霸':t,'青':t,'靖':t,'静':t,'非':t,'靡':t,'面':t,'革':t,'靭':t,'靱':t,'靳':t,'靴':t,'靺':t,'鞄':t,'鞆':t,'鞍':t,'鞘':t,'鞠':t,'鞨':t,'鞭':t,'韋':t,'韓':t,'韮':t,'音':t,'韶':t,'韻':t,'響':t,'頁':t,'頂':t,'頃':t,'項':t,'順':t,'須':t,'頌':t,'預':t,'頑':t,'頒':t,'頓':t,'領':t,'頚':t,'頬':t,'頭':t,'頴':t,'頸':t,'頻':t,'頼':t,'顆':t,'題':t,'額':t,'顎':t,'顒':t,'顔':t,'顕':t,'願':t,'顛':t,'類':t,'顧':t,'風':t,'颯':t,'飛':t,'食':t,'飢':t,'飫':t,'飯':t,'飲':t,'飴':t,'飼':t,'飽':t,'飾':t,'餃':t,'餅':t,'養':t,'餌':t,'餐':t,'餓':t,'餡':t,'館':t,'饅':t,'饉':t,'饌':t,'饒':t,'饗':t,'首':t,'香':t,'馨':t,'馬':t,'馮':t,'馳':t,'馴':t,'駁':t,'駄':t,'駅':t,'駆':t,'駐':t,'駒':t,'駕':t,'駿':t,'騎':t,'騒':t,'験':t,'騙':t,'騨':t,'騰':t,'驃':t,'驚':t,'驤':t,'骨':t,'骸':t,'髄':t,'髏':t,'髑':t,'體':t,'高':t,'髙':t,'髪':t,'髭':t,'髷':t,'鬘':t,'鬚':t,'鬱':t,'鬼':t,'魁':t,'魂':t,'魃':t,'魅':t,'魏':t,'魔':t,'魚':t,'魯':t,'鮎':t,'鮑':t,'鮫':t,'鮭':t,'鮮':t,'鯉':t,'鯖':t,'鯛':t,'鯨':t,'鯱':t,'鰐':t,'鰓':t,'鰭':t,'鰹':t,'鰻':t,'鱒':t,'鱗':t,'鳥':t,'鳩':t,'鳳':t,'鳴':t,'鳶':t,'鴉':t,'鴎':t,'鴨':t,'鴻':t,'鵜':t,'鵠':t,'鵬':t,'鶏':t,'鶯':t,'鶴':t,'鷗':t,'鷲':t,'鷹':t,'鷺':t,'鸞':t,
'鹵':t,'鹸':t,'鹿':t,'麒':t,'麓':t,'麗':t,'麟':t,'麦':t,'麹':t,'麺':t,'麻':t,'麾':t,'麿':t,'黄':t,'黌':t,'黎':t,'黒':t,'黔':t,'黙':t,'黛':t,'鼎':t,'鼓':t,'鼠':t,'鼻':t,'齊':t,'齋':t,'齟':t,'齢':t,'齧':t,'齬':t,'龍':t,'龐':t,'龕':t,'이':t,'﨑':t,'~':t,
'A':t,'B':t,'C':t,'D':t,'E':t,'F':t,'G':t,'H':t,'I':t,'J':t,'K':t,'L':t,'M':t,'N':t,'O':t,'P':t,'Q':t,'R':t,'S':t,'T':t,'U':t,'V':t,'W':t,'X':t,'Y':t,'Z':t,'a':t,'b':t,'c':t,'d':t,'e':t,'f':t,'g':t,'h':t,'i':t,'j':t,'k':t,'l':t,'m':t,'n':t,'o':t,'p':t,'q':t,'r':t,'s':t,'t':t,'u':t,'v':t,'w':t,'x':t,'y':t,'z':t,'0':t,'1':t,'2':t,'3':t,'4':t,'5':t,'6':t,'7':t,'8':t,'9':t,
'/':t,'*':t,'.':t,'?':t,'!':t,'(':t,')':t,'【':t,'】':t,'{':t,'}':t,'<':t,'>':t,':':t,'…':t,'”':t,'$':t,'%':t,'&':t,'’':t,'@':t,'*':t,'^':t,'=':t,'|':t,';':t,'+':t,'_':t,'゛':t,
}
// 本文入力欄の分割を複数文コメントや最新の出力文(色の変わっている部分)の途中になるのを避ける機能
window.TextSharding = function (orig_text = null, nospan = true, noscroll = false) {
let $ = window.jQuery
if (!orig_text) {
orig_text = localStorage.textdata;
}
let sharding_max = 0
if ($.cookie("use_shards") == "optout") {
if (window.matchMedia && window.matchMedia('(max-device-width: 900px)').matches) {
sharding_max = 10000;
} else {
sharding_max = 500000;
}
} else if (window.matchMedia && window.matchMedia('(max-device-width: 900px)').matches) {
sharding_max = 3000;
} else {
sharding_max = 8000;
}
$('#data_container').empty();
if (orig_text.length >= 1280) { $('#data_container').css('min-height', $('#data_container').css('max-height')); }
else { $('#data_container').css('min-height', ''); }
let i = 0;
if (nospan == true) {
orig_text = orig_text.replace(/<span.*?>|<\/span>/gi, '');
}
orig_text = orig_text.replace(/(<font.*?>|<\/font>)/gi, '');
orig_text = orig_text.replace(/(<a.*?>)/gi, '');
orig_text = orig_text.replace(/(<\/a>)/gi, '');
orig_text = orig_text.replace(/(<pre.*?>|<\/pre>)/gi, '');
orig_text = orig_text.replace(/(\n)/gi, '<br>');
orig_text = orig_text.replace(/(<div><br>)/gi, '<br>');
orig_text = orig_text.replace(/(<br.*?>)/gi, '<br>');
orig_text = orig_text.replace(/(<div.*?>)/gi, '<br>');
orig_text = orig_text.replace(/(<\/div>)/gi, '');
orig_text = orig_text.replace(/(@\/\*|@/*)(.*?)(?!(?:@\/\*|@/*))(.*?)(@\*\/|@*/)/g, '<font color=\"#aaaaaa\">$1$2$3$4</font>');
//orig_text = orig_text.replace(/(@\/\*)/gi, '<font color=\"#aaaaaa\">@/*');
//orig_text = orig_text.replace(/(@\*\/)/gi, '@*</a>\/</font>');
//orig_text = orig_text.replace(/(@/*)/gi, '<font color=\"#aaaaaa\">@/*');
//orig_text = orig_text.replace(/(@*/)/gi, '@*</a>/</font>');
orig_text = orig_text.replace(/(@_)(.*?)(<br>)/gi, '<font color=\"#aaaaaa\">@_$2</font><br>');
//orig_text = orig_text.replace(/@endpoint(?!.*?@endpoint.*?)(.*?)(<br>)*$/i, '<font color=\"#aaaaaa\">@endpoint$1</font>');
orig_text = orig_text.replace(/@endpoint(.*?)(<br>)*$/i, '<font color=\"#aaaaaa\">@endpoint$1</font>');
for (let i = orig_text.length - 1; i >= 0; i--) {
if (orig_text[i] === '>') {
// タグ部分をスキップ
const pos = orig_text.lastIndexOf('<', i)
if (pos > 0) {
const tag_name = orig_text.substring(pos + 1, i)
if (tag_name[0] === '/') {
const pos2 = orig_text.lastIndexOf('<' + tag_name.substring(1), pos)
if (pos2 > 0) {
i = pos2
}
} else {
i = pos
}
}
} else {
// ハイライトを挿入
let j = i
for (; j >= 0; j--) {
if (char_list[orig_text[j]]) {
break
}
}
if (i !== j) {
orig_text = orig_text.substring(0, j + 1) + '<a style="border:1px solid;color:inherit">' + orig_text.substring(j + 1, i + 1) + '</a>' + orig_text.substring(i + 1)
i = j
}
}
}
const font_family = document.getElementById("vis_fontfamily").value.replace(/"/gi, '');
var shard_ends_with_br = false;
while (orig_text.length >= 1) {
const tmp_max_cur = orig_text.substring(0, sharding_max)
let divide_text_by1 = tmp_max_cur.lastIndexOf("<br>");
let divide_text_by2 = tmp_max_cur.lastIndexOf("</font>");
let divide_text_by = divide_text_by1 > divide_text_by2 ? divide_text_by1 : (divide_text_by2 + "</font>".length)
if (orig_text.length <= divide_text_by * 1.1) {
// 境界が本文末近くにあるときは、シャーディングの分割を手前の方において、本文末近くでは分割されないようにする
const tmp_half_cur = orig_text.substring(0, Math.floor(orig_text.length * 2 / 3))
divide_text_by1 = tmp_half_cur.lastIndexOf("<br>");
divide_text_by2 = tmp_half_cur.lastIndexOf("</font>");
divide_text_by = divide_text_by1 > divide_text_by2 ? divide_text_by1 : (divide_text_by2 + "</font>".length);
}
if (divide_text_by <= sharding_max / 2) { divide_text_by = sharding_max; }
let temp_cur = orig_text.substring(0, divide_text_by);
// fontタグが入れ子になっていないかのチェック
let font_start = temp_cur.lastIndexOf('<font'), font_end = temp_cur.lastIndexOf('</font>')
if (font_start > 0 && font_end > font_start ) {
let font_outside_start = temp_cur.lastIndexOf('<font', font_start - 1),
font_outside_end = temp_cur.lastIndexOf('</font>', font_start - 1),
font_inside = temp_cur.indexOf('</font>', font_start)
if (font_inside === font_end && font_outside_start >= 0 && font_outside_end < 0) {
font_start = font_outside_start
font_end = -1
}
}
let span_start = temp_cur.lastIndexOf('<span'), span_end = temp_cur.lastIndexOf('</span>')
if (font_start >= 0 && (font_end < 0 || (font_end >= 0 && font_start > font_end))) {
// fontタグが分断されている
font_end = orig_text.indexOf('</font>', divide_text_by) + '</font>'.length
const font_endpoint = temp_cur.lastIndexOf('<font color="#aaaaaa">@endpoint')
divide_text_by = -1
if (font_end >= sharding_max * 1.2 || font_endpoint === font_start) {
// 規定のサイズより大きめであればfontタグの前に分割点を置く
divide_text_by = temp_cur.lastIndexOf('<br>', font_start);
}
if (divide_text_by <= 0) {
// fontタグの後ろの分割点を決める。spanタグがあれば、その前に置く
divide_text_by = orig_text.indexOf('<br>', font_end);
const posSpan = orig_text.indexOf('<span', font_end);
if (posSpan >= 0 && posSpan < divide_text_by) {
divide_text_by = posSpan
} else if (divide_text_by < 0) {
// 分割点に改行がなければ改行を挿入する
if (orig_text.slice(-4) !== '<br>') {
orig_text = orig_text + '<br>'
}
divide_text_by = orig_text.length
}
}
temp_cur = orig_text.substring(0, divide_text_by);
} else if (span_start >= 0 && (span_end < 0 || (span_end >= 0 && span_start > span_end))) {
// spanタグが分断されている
span_end = orig_text.indexOf('</span>', divide_text_by) + '</span>'.length
divide_text_by = orig_text.indexOf('<br>', span_end);
if (divide_text_by < 0) {
divide_text_by = orig_text.length
}
temp_cur = orig_text.substring(0, divide_text_by);
}
if (temp_cur.substring(0, 4) == "<br>" && shard_ends_with_br == false) { temp_cur = temp_cur.substring(4); }
if (temp_cur.trim().length <= 0) { break; }
const id_temp = 'data_edit';
$("<div contenteditable spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\" id=\"" + id_temp + "\" class=\"data_edit\" style=\"font-family: " + font_family + "; font-size:" + document.getElementById("vis_fontsize").value / 40 + "rem; letter-spacing:" + document.getElementById("vis_fontkerning").value / 80 + "rem; line-height:" + document.getElementById("vis_fontleading").value / 10 + "rem; color:" + document.getElementById("vis_fontcolor").value + ";\" onclick=\"CopyContent(); savecurrentwork();\" onmouseout=\"CopyContent(); savecurrentwork();\" onpaste=\"handle_paste(this, event); return false;\">" + temp_cur + "</div>").appendTo('#data_container');
orig_text = orig_text.substring(divide_text_by);
if (temp_cur.substring(temp_cur.length - 4) == "<br>") { shard_ends_with_br = true; }
else { shard_ends_with_br = false; }
i++;
}
// 通常のスクロールをendpointがあればその前になるようにする
endpointScroll('ai_output')
if (!nospan) {
// 出力挿入時やUndo、Redoなどのスクロールを止める
disableScrollTop()
}
}
// 情報表示の機能
let totalOutputChar = 0, totalOutputCount = 0, totalRetryCount = 0, lastTextDateCount = 0
// セッション情報の読み書き
const saveSession = function () {
const history_hidden = document.getElementById('show-history-text-hidden')
const current_undo = createHistoryText()
const history = (current_undo ? '<|entry|>' + current_undo : '') + (history_hidden ? history_hidden.value : '')
sessionStorage['usermod_stat_' + localStorage.current_works_id] = JSON.stringify({totalOutputChar, totalOutputCount, totalRetryCount, history})
}
const loadSession = function () {
if (sessionStorage['usermod_stat_' + localStorage.current_works_id]) {
const stat_data = JSON.parse(sessionStorage['usermod_stat_' + localStorage.current_works_id])
totalOutputChar = stat_data.totalOutputChar
totalOutputCount = stat_data.totalOutputCount
totalRetryCount = stat_data.totalRetryCount
const history_hidden = document.getElementById('show-history-text-hidden')
if (history_hidden) {
history_hidden.value = stat_data.history
buildHistorySelect()
UpdateModInfo()
}
}
}
const UpdateModInfo = function () {
const area = document.getElementById('mod-information')
const avgOutputChar = totalOutputChar / totalOutputCount,
avgRetryCount = totalRetryCount / (totalOutputCount - totalRetryCount)
if (area && ! Number.isNaN(avgOutputChar) && ! Number.isNaN(avgRetryCount)) {
const text = `総出力回数: ${totalOutputCount}回
総出力文字数: ${totalOutputChar}文字
平均出力文字数: ${Math.round(avgOutputChar*100)/100}文字
総リトライ回数: ${totalRetryCount}回
平均リトライ回数: ${Math.round(avgRetryCount*100)/100}回`
area.value = text + (lastTextDateCount ? `\nおおよその本文の文字数:約${lastTextDateCount}文字` : '') + (lastLocalSave !== '' ? `\n最後にローカル保存した日時:${lastLocalSave}` : '') + (lastRemoteSave !== '' ? `\n最後にリモート保存した日時:${lastRemoteSave}` : '')
} else if (lastLocalSave !== '' || lastRemoteSave !== '') {
area.value = (lastLocalSave !== '' ? `最後にローカル保存した日時:${lastLocalSave}` : '') + (lastRemoteSave !== '' ? `\n最後にリモート保存した日時:${lastRemoteSave}` : '')
}
}
// @endpointの前に出力を挿入する機能
// @endpointの直前に改行がないと動きません
// PushHistoryが基本的に最新出力文挿入後にしか呼ばれないため、無理矢理割り込んでいます
const originalPushHistory = window.PushHistory
window.PushHistory = function (data) {
let start = data.lastIndexOf('<span id="ai_output"'), end = data.indexOf('</span>', start)
if (start >= 0 && end >= 0) {
// 出力した後
end += '</span>'.length
const output = data.slice(start, end)
const ai = document.getElementById('ai_output')
if (ai.parentNode.tagName.toLowerCase() === 'font') {
const next_br = ai.nextSibling
if (!!pref.force_insert_last) {
ai.parentNode.removeChild(next_br)
document.querySelector('#data_container > div:last-child').insertAdjacentElement('beforeend', ai)
} else {
const target = ai.parentNode
// @endpointがシャーディング境界にある、かつ、先頭のシャーディングではない場合は、一つ前のシャーディングの最後に追加する
if (target.previousElementSibling === null && target.parentNode.previousElementSibling !== null) {
target.parentNode.previousElementSibling.insertAdjacentElement('beforeend', ai)
} else {
target.insertAdjacentElement('beforebegin', ai)
}
ai.insertAdjacentElement('afterend', next_br)
if (ai.previousSibling && ai.previousSibling.tagName && ai.previousSibling.tagName.toLowerCase() === 'br') {
ai.parentNode.removeChild(ai.previousSibling)
}
}
window.CopyContent()
data = localStorage.textdata
}
if (output !== '') {
endpointScroll()
// 情報表示のためのカウント
totalOutputCount++
if (window.retry) {
totalRetryCount++
}
totalOutputChar += output.replace(/<span[^>]*>/g, '').replace(/<\/span>/g, '').length
UpdateModInfo()
// 特殊なスクリプト(置換)
const memory = document.getElementById('memory'),
authorsnote = document.getElementById('authorsnote')
let needCopyContent = false
for (let i = 0 ;i < 100; i++) {
const script_selector = document.getElementById('script_selector' + i)
if (script_selector && script_selector.value === 'script_none') {
const script_in = document.getElementById('script_in' + i)
let target
if (script_in && script_in.value.indexOf('(?:M){0}') === 0) {
target = memory
} else if (script_in && script_in.value.indexOf('(?:A){0}') === 0) {
target = authorsnote
} else {
continue
}
const script_out = document.getElementById('script_out' + i)
let script_out_text = script_out.value
const regexp_in = new RegExp(script_in.value)
const result_in = regexp_in.exec(output.replace(/<br>/gi, "\n").replace(/<\/?[^>]+>/gi, ''))
if (result_in !== null) {
for (let j = 1; j < result_in.length; j++) {
script_out_text = script_out_text.replace('#' + j + '#', result_in[j])
}
const [script_out_before, script_out_after] = script_out_text.split('<|>')
const regexp_out = new RegExp(script_out_before)
target.value = target.value.replace(regexp_out, script_out_after)
needCopyContent = true
}
}
}
if (needCopyContent) {
window.CopyContent()
}
}
}
originalPushHistory(data)
enableScrollTop()
}
// 続きを書くやリトライ後にスクロールを復活させる
const originalCopyContent = window.CopyContent
window.CopyContent = function () {
enableScrollTop()
const all = document.getElementsByClassName('data_edit')
let comment = -1, target = -1, target_pos = -1
for (let i = all.length - 1; i >= 0; i--) {
comment = all[i].innerHTML.indexOf('<font color="#aaaaaa"')
if (comment === 0 && i !== 0) {
const tag_name = all[i - 1].childNodes[all[i - 1].childNodes.length - 1].nodeName.toLowerCase()
if (tag_name !== 'br' && tag_name !== 'span') {
// 枠の先頭にコメントがいる&一つ前に枠がある&一つ前の枠の最後に改行がないと出力に失敗するので改行(空っぽのspan)を挿入する
const span = document.createElement('span')
span.classList.add('__temporary')
all[i - 1].appendChild(span)
}
}
}
originalCopyContent()
for (let i = all.length - 1; i >= 0; i--) {
for (const span of all[i].querySelectorAll('span.__temporary')) {
all[i].removeChild(span)
}
}
}
// Redoを押した数をカウントする
let freeze_history_redo_tap_count = 0
// Undo、Redo後にスクロールを復活させる
const originalUndoRedoLabel = window.UndoRedoLabel
window.UndoRedoLabel = function () {
enableScrollTop()
originalUndoRedoLabel()
// Redoボタンのラベル張りかえ
const data_undo = document.getElementById('data_undo')
if (!!localStorage.undo_last && data_undo && document.getElementById("data_undo").value) {
const history_list = data_undo.value.split("<|entry|>")
if (Number(localStorage.undo_last) >= (history_list.length - 1)) {
document.getElementById("redo").value = "Redo >>";
} else {
document.getElementById("redo").value = "Redo ("+(history_list.length - Number(localStorage.undo_last) - 1)+")";
}
}
freeze_history_redo_tap_count = 0
}
// Undo履歴の挿入をendpoint前にする
window.FreezeUndoHistory = function (isRedo = false) {
if (document.getElementById('submitarea').style.display == "none") { return false; }
if (!document.getElementById("data_undo").value) { return false; }
if (document.getElementById("data_undo").value.indexOf("<|entry|>") == -1) { return false; }
// 挿入テキストの作成
var temp = "";
for (var i = 2; i < 100; i++) {
var history = window.GetHistory(i);
if (history) {
const posOutput = history.indexOf('<span id="ai_output"'),
substring = history.substring(posOutput, history.indexOf('</span>', posOutput) + '</span>'.length)
temp += '(' + (i - 1) + ')<br>' + substring + '<br>';
} else {
break;
}
}
// 挿入位置の確定
const base_history = window.GetHistory(1)
let pos = base_history.indexOf('@endpoint')
if (!pref.force_insert_last && pos >= 0) {
const font_tag = '<font color="#aaaaaa">'
if (base_history.lastIndexOf(font_tag, pos) === pos - font_tag.length) {
pos = pos - font_tag.length
}
const head = base_history.slice(0, pos).replace(/(\n)/gi, '<br>')
temp = head + (head.slice(-4) === '<br>' ? '' : '<br>') + '@/*<br>' + temp.replace(/<span.*?>/g, '').replace(/<\/span>/g, '') + '@*/<br>' + base_history.slice(pos).replace(/(\n)/gi, '<br>');
} else {
temp = base_history.replace(/(\n)/gi, '<br>') + '@/*<br>' + temp.replace(/<span.*?>/g, '').replace(/<\/span>/g, '') + '@*/<br><br>';
}
window.TextSharding(temp, false);
enableScrollTop()
VisualChange();
if (isRedo) {
document.getElementById('redo').value = 'History';
freeze_history_redo_tap_count = 0;
} else {
document.getElementById('undo').value = 'History';
freeze_history_tap_count = 0;
}
}
// Redoを3回押した時にUndo履歴を挿入する
const originalRedoContent = window.RedoContent
window.RedoContent = function () {
if (document.getElementById('submitarea').style.display == "none") { return false; }
if (!document.getElementById("data_undo").value) { return false; }
if (document.getElementById("data_undo").value.indexOf("<|entry|>") == -1) { return false; }
if (document.getElementById('redo').value === 'History') {
freeze_history_redo_tap_count = 0
const undo_last = Number(localStorage.undo_last) - 1
if (window.GetHistory(undo_last)) {
localStorage.undo_last = String(undo_last);
}
} else if (!window.GetHistory(Number(localStorage.undo_last) + 1)) {
freeze_history_redo_tap_count++
if (freeze_history_redo_tap_count >= 3) { window.FreezeUndoHistory(true) }
return false
} else {
freeze_history_redo_tap_count = 0
}
return originalRedoContent()
}
// 送信テキストをテキストエリアに流す/出力履歴をため込む - ここから
const createHistoryText = () => {
// 挿入テキストの作成
let temp = ''
for (var i = 2; i < 100; i++) {
var history = window.GetHistory(i);
if (history) {
const posOutput = history.indexOf('<span id="ai_output"'),
substring = history.substring(posOutput, history.indexOf('</span>', posOutput) + '</span>'.length)
temp += '(' + (i - 1) + ')\n' + substring.replace(/<br>/g, '\n').replace(/<\/?span[^>]*>/g, '') + '\n'
} else {
break
}
}
return temp
}
const originalAjax = window.jQuery.ajax
window.jQuery.ajax = function (param) {
if (param.type === 'POST' && param.data) {
if (param.url === 'getrequest_v5.php') {
const data = param.data.find(function (value) {
return value.name === 'data'
})
lastTextDateCount = data.value.length
} else if (param.url === '_remotestories.php') {
// リモート保存時の日時を記録する
const now = new Date()
lastRemoteSave = formatDate(now)
UpdateModInfo()
} else if (param.headers && param.headers['Content-Type'] === 'application/json') {
const json_data = JSON.parse(param.data)
const textarea = document.getElementById('send-text-confirm')
if (json_data.text && textarea) {
textarea.value = json_data.text
const counter = document.getElementById('options_usermod_text_count')
if (counter) {
counter.textContent = json_data.text.length + '文字'
}
}
}
}
return originalAjax(param)
}
const buildHistorySelect = function (historyText = '') {
const textarea_history_hidden = document.getElementById('show-history-text-hidden')
if (textarea_history_hidden) {
const history_history = textarea_history_hidden.value.split('<|entry|>')
if (history_history.length > 20) {
history_history.pop()
}
if (historyText) {
textarea_history_hidden.value = '<|entry|>' + historyText + history_history.join('<|entry|>')
}
const select_history = document.getElementById('show-history-select')
for (let i = select_history.children.length; i <= history_history.length - (historyText ? 0 : 1); i++) {
const option = document.createElement('option')
option.innerText = i + '個前'
option.value = i
select_history.appendChild(option)
}
select_history.dispatchEvent(new Event('change'))
}
}
const originalCleanUpUndo = window.CleanUpUndo
window.CleanUpUndo = function () {
if (document.getElementById("data_undo").value !== '') {
// 挿入テキストの作成
buildHistorySelect(createHistoryText())
}
originalCleanUpUndo()
}
const originalShowPost = window.showpost
window.showpost = function () {
originalShowPost()
const select_history = document.getElementById('show-history-select')
if (select_history) {
select_history.dispatchEvent(new Event('change'))
saveSession()
}
}
;(function () {
const balloon_options_option = document.getElementById('balloon_options_option'),
options_goodies = document.getElementById('options_goodies')
if (!balloon_options_option || !options_goodies) {
// 起点となる要素がないのでスルーする
return
}
// アイコンの準備
const color_black = 'rgb(68,68,68)', color_white = 'rgb(255,255,255)'
const text_svg = `<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 512 512" style="width: 64px; height: 64px; opacity: 1;" xml:space="preserve"><style type="text/css">.st0{fill:#4B4B4B;}</style><g><path class="st0" d="M449.891,87.953c-3.766-8.906-10.031-16.438-17.922-21.781c-7.891-5.328-17.5-8.469-27.719-8.469h-42.656v-7.359h-61.828c0.281-2,0.438-4.063,0.438-6.141C300.203,19.828,280.375,0,256,0s-44.203,19.828-44.203,44.203c0,2.078,0.156,4.141,0.438,6.141h-61.828v7.359H107.75c-6.813,0-13.359,1.391-19.281,3.906c-8.906,3.766-16.453,10.031-21.797,17.922c-5.328,7.906-8.469,17.5-8.469,27.719v355.219c0,6.781,1.391,13.344,3.906,19.281c3.766,8.906,10.031,16.438,17.922,21.781c7.906,5.344,17.5,8.469,27.719,8.469h296.5c6.797,0,13.359-1.375,19.281-3.906c8.922-3.75,16.453-10.031,21.797-17.922c5.328-7.891,8.469-17.5,8.469-27.703V107.25C453.797,100.438,452.422,93.891,449.891,87.953z M256,27.797c9.047,0,16.406,7.359,16.406,16.406c0,2.172-0.438,4.234-1.203,6.141h-30.391c-0.781-1.906-1.219-3.969-1.219-6.141C239.594,35.156,246.969,27.797,256,27.797z M424.328,462.469c0,2.813-0.563,5.406-1.578,7.797c-1.5,3.578-4.063,6.672-7.281,8.859c-3.219,2.156-7,3.406-11.219,3.406h-296.5c-2.813,0-5.422-0.563-7.813-1.563c-3.594-1.516-6.672-4.094-8.844-7.297c-2.156-3.219-3.406-7-3.422-11.203V107.25c0-2.813,0.563-5.422,1.578-7.813c1.516-3.594,4.078-6.688,7.281-8.844c3.219-2.156,7-3.406,11.219-3.422h42.656v6.141c0,11.531,9.344,20.875,20.891,20.875h169.422c11.531,0,20.875-9.344,20.875-20.875v-6.141h42.656c2.813,0,5.422,0.563,7.813,1.578c3.578,1.5,6.672,4.063,8.844,7.281s3.422,7,3.422,11.219V462.469z" style="fill: color_setting;"></path><rect x="156.141" y="170.672" class="st0" width="31.625" height="31.625" style="fill: color_setting;"></rect><rect x="225.516" y="170.672" class="st0" width="130.359" height="31.625" style="fill: color_setting;"></rect><rect x="156.141" y="264.125" class="st0" width="31.625" height="31.625" style="fill: color_setting;"></rect><rect x="225.516" y="264.125" class="st0" width="130.359" height="31.625" style="fill: color_setting;"></rect><rect x="156.141" y="357.594" class="st0" width="31.625" height="31.625" style="fill: color_setting;"></rect><rect x="225.516" y="357.594" class="st0" width="130.359" height="31.625" style="fill: color_setting;"></rect></g></svg>`,
history_svg = `<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 512 512" style="width: 64px; height: 64px; opacity: 1;" xml:space="preserve"><style type="text/css">.st0{fill:#4B4B4B;}</style><g> <path class="st0" d="M141.18,56.938l30.484,33.531v157.594c0,2.563,1.422,4.938,3.688,6.141c2.281,1.203,5.031,1.063,7.156-0.391l36.406-24.656l36.391,24.656c2.141,1.453,4.891,1.594,7.172,0.391c2.25-1.203,3.688-3.578,3.688-6.141V90.469l-30.5-33.531H141.18z" style="fill: color_setting;"></path> <path class="st0" d="M436.008,93.344l-25.875-62.563c9.188-0.563,14.719-8.156,14.719-14.078C424.852,7.469,417.383,0,408.164,0H109.477C92.086,0,76.195,7.094,64.836,18.5C53.43,29.859,46.32,45.75,46.336,63.125V470.75c0,22.781,18.469,41.25,41.25,41.25h343.359c19.188,0,34.719-15.547,34.719-34.734V127.578C465.664,110.125,452.789,95.844,436.008,93.344z M290.664,92.844v155.219c0,11.672-6.406,22.328-16.719,27.797c-4.531,2.391-9.625,3.672-14.75,3.672c-6.313,0-12.422-1.875-17.641-5.438l-22.641-15.344l-22.656,15.344c-5.219,3.563-11.313,5.438-17.641,5.438c-5.109,0-10.219-1.281-14.75-3.688c-10.297-5.453-16.703-16.109-16.703-27.781V99.938l-6.469-7.094h-31.219c-8.266,0-15.594-3.313-21.016-8.703c-5.406-5.453-8.719-12.766-8.719-21.016s3.313-15.578,8.719-21c5.422-5.406,12.75-8.719,21.016-8.719H383.57l26.688,59.438H290.664z" style="fill: color_setting;"></path></g></svg>`,
info_svg = `<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="width: 64px; height: 64px; opacity: 1;" xml:space="preserve"><style type="text/css">.st0{fill:#4B4B4B;}</style><g><path class="st0" d="M437.015,74.978C390.768,28.686,326.619-0.014,256,0C185.381-0.014,121.231,28.686,74.978,74.978C28.694,121.224-0.015,185.381,0,256c-0.015,70.612,28.694,134.762,74.978,181.015C121.231,483.314,185.381,512.008,256,512c70.619,0.008,134.768-28.686,181.015-74.985c46.299-46.253,75-110.403,74.985-181.015C512.014,185.381,483.314,121.224,437.015,74.978z M403.56,403.552c-37.851,37.798-89.866,61.112-147.56,61.12c-57.694-0.008-109.709-23.321-147.56-61.12C70.649,365.716,47.336,313.702,47.321,256c0.014-57.702,23.328-109.716,61.119-147.552C146.291,70.649,198.306,47.343,256,47.329c57.694,0.014,109.709,23.32,147.56,61.119c37.791,37.836,61.104,89.851,61.119,147.552C464.664,313.702,441.351,365.716,403.56,403.552z" style="fill: color_setting;"></path><path class="st0" d="M251.694,194.328c21.381,0,38.732-17.343,38.732-38.724c0-21.396-17.351-38.724-38.732-38.724c-21.38,0-38.724,17.328-38.724,38.724C212.97,176.986,230.314,194.328,251.694,194.328z" style="fill: color_setting;"></path><path class="st0" d="M299.164,362.806h-5.262c-5.387,0-9.761-4.358-9.761-9.746V216.731c0-1.79-0.94-3.462-2.47-4.38c-1.53-0.933-3.44-0.977-5.023-0.142l-66.544,36.986c-19.358,9.679-10.068,21.239-2.858,20.94c7.202-0.284,28.679-2.41,28.679-2.41v85.336c0,5.388-4.373,9.746-9.761,9.746h-10.336c-2.686,0-4.88,2.194-4.88,4.88v21.284c0,2.687,2.194,4.881,4.88,4.881h83.336c2.694,0,4.881-2.194,4.881-4.881v-21.284C304.045,365,301.858,362.806,299.164,362.806z" style="fill: color_setting;"></path></g></svg>`
const blob_text_icon = new Blob([text_svg.replace(/color_setting/g, color_black)], {type:'image/svg+xml'}),
blob_history_icon = new Blob([history_svg.replace(/color_setting/g, color_black)], {type:'image/svg+xml'}),
blob_info_icon = new Blob([info_svg.replace(/color_setting/g, color_black)], {type:'image/svg+xml'}),
blob_text_icon_white = new Blob([text_svg.replace(/color_setting/g, color_white)], {type:'image/svg+xml'}),
blob_history_icon_white = new Blob([history_svg.replace(/color_setting/g, color_white)], {type:'image/svg+xml'}),
blob_info_icon_white = new Blob([info_svg.replace(/color_setting/g, color_white)], {type:'image/svg+xml'})
const text_icon_url = URL.createObjectURL(blob_text_icon),
history_icon_url = URL.createObjectURL(blob_history_icon),
info_icon_url = URL.createObjectURL(blob_info_icon),
text_icon_white_url = URL.createObjectURL(blob_text_icon_white),
history_icon_white_url = URL.createObjectURL(blob_history_icon_white),
info_icon_white_url = URL.createObjectURL(blob_info_icon_white)
let style = 'margin-left: 40px;', style_baloon = 'margin: 10px;'
if (navigator.userAgent.match(/iPhone|Android.+Mobile/)) {
style = 'margin-left: 15px;'
style_baloon = 'margin: 5px;'
}
// オプション枠の追加
document.getElementById('balloon_options_option').parentNode.insertAdjacentHTML('beforeend', `<p class="balloon" id="balloon_options_usermod_text" style="background-color:#ffffff;` + style_baloon + `" title="送信テキスト確認(ユーザースクリプト)" onClick="ToggleOptions('101');">
<img src="` + text_icon_url + `" class="options_icons" id="img_options_usermod_text" width="32" height="32" style="margin-top:16px;"></p>
<p class="balloon" id="balloon_options_usermod_history" style="background-color:#ffffff;` + style_baloon + `" title="出力履歴確認(ユーザースクリプト)" onClick="ToggleOptions('102');">
<img src="` + history_icon_url + `" class="options_icons" id="img_options_usermod_history" width="32" height="32" style="margin-top:16px;"></p>
<p class="balloon" id="balloon_options_usermod_info" style="background-color:#ffffff;` + style_baloon + `" title="情報表示(ユーザースクリプト)" onClick="ToggleOptions('103');">
<img src="` + info_icon_url + `" class="options_icons" id="img_options_usermod_info" width="32" height="32" style="margin-top:16px;"></p>`)
const select_history = document.createElement('select')
select_history.style = 'margin-bottom: 10px;height: 2rem;width: 100px;'
select_history.id = 'show-history-select'
const option = document.createElement('option')
option.innerText = '現在'
option.value = 0
select_history.appendChild(option)
select_history.readOnly = true
document.getElementById('options_goodies').insertAdjacentHTML('afterend',`<div id="options_usermod_text" style="display: none;"><dl id="acMenu">
<dt><div class="header2" style="padding:0px;"><h3 style="padding-left:15px;">▼ 送信テキスト確認(ユーザースクリプト)</h3></div></dt>
<dd class="dd-margin" style="margin-top: 15px;` + style+ `display: block;">
<div style="max-width:90%; color:#777777;width:85vw" class="explanations"><div style="float:left;text-align:left">最後にAIに送信した入力テキスト内容を確認できます。</div><div style="float:none;text-align:right" id="options_usermod_text_count"></div></div>
<textarea id="send-text-confirm" rows="30" readOnly></textarea></dd></dl></div>
<div id="options_usermod_history" style="display: none;"><dl id="acMenu">
<dt><div class="header2" style="padding:0px;"><h3 style="padding-left:15px;">▼ 出力履歴確認(ユーザースクリプト)</h3></div></dt>
<dd class="dd-margin" style="margin-top: 15px;` + style+ `display: block;">
<div style="max-width:90%; color:#777777;" class="explanations">過去20回分までAIが出力したテキストの履歴を確認できます。<br>確認可能なすべての履歴をファイルに保存することもできます。<br>ページを閉じると履歴は消えます。</div>
` + select_history.outerHTML + `<button id="show-history-download" style="margin-left: 20px;margin-bottom: 10px;height: 2rem;width: 120px;">ファイルに保存</button><br><textarea id="show-history-text" rows="30" readOnly></textarea>
</dd></dl><textarea id="show-history-text-hidden" style="display:none;" rows="30" readOnly></textarea></div>
<div id="options_usermod_info" style="display: none;"><dl id="acMenu">
<dt><div class="header2" style="padding:0px;"><h3 style="padding-left:15px;">▼ 情報表示(ユーザースクリプト)</h3></div></dt>
<dd class="dd-margin" style="margin-top: 15px;` + style+ `display: block;">
<div style="max-width:90%; color:#777777;" class="explanations">編集ページを開いてから集計した情報を表示します。<br>ページを閉じない限り継続して集計します。</div>
<textarea id="mod-information" rows="8" readOnly></textarea></dd></dl></div>`)
document.getElementById('show-history-select').addEventListener('change', function () {
const textarea_history_hidden = document.getElementById('show-history-text-hidden'),
textarea_history = document.getElementById('show-history-text')
if (this.value === '0') {
textarea_history.value = createHistoryText()
return
}
if (textarea_history_hidden.value === '') {
textarea_history.value = ''
return
}
const history_history = textarea_history_hidden.value.split('<|entry|>')
if (history_history[this.value]) {
textarea_history.value = history_history[this.value]
} else {
textarea_history.value = ''
}
})
document.getElementById('show-history-download').addEventListener('click', function () {
const textarea_history_hidden = document.getElementById('show-history-text-hidden')
if (!textarea_history_hidden) {
return
}
const title = localStorage.textdata_title, separator = '\n---*---*---*---*---*---\n'
const temp = title + separator + createHistoryText() + textarea_history_hidden.value.replace(/<\|entry\|>/g, separator)
const blob = new Blob([temp], {type: 'text/plain'}),
a = document.createElement("a")
const now = new Date()
a.href = URL.createObjectURL(blob);
document.body.appendChild(a);
a.download = title.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g, '')+'_' + now.getFullYear() + (now.getMonth()+1) + now.getDate() + now.getHours() + now.getMinutes() + now.getSeconds() + '.txt';
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(a.href);
})
// 表示の調整
const VisualChange2 = function () {
const $ = window.jQuery
$('#show-history-text,#send-text-confirm').css('font-family', document.getElementById("vis_fontfamily").value);
$('#show-history-text,#send-text-confirm').css('font-size', document.getElementById("vis_fontsize").value / 40+'rem');
$('#show-history-text,#send-text-confirm').css('letter-spacing', document.getElementById("vis_fontkerning").value / 80+'rem');
$('#show-history-text,#send-text-confirm').css('line-height', document.getElementById("vis_fontleading").value / 10+'rem');
const array_iconsize_actuals = new Array('32','20','24','28','32','36','40','48');
$('#balloon_options_usermod_text').each( function() {
$(this).css('width', array_iconsize_actuals[document.getElementById("gui_iconsize").value] * 2);
$(this).css('height', array_iconsize_actuals[document.getElementById("gui_iconsize").value] * 2);
$(this).css('margin-right', array_iconsize_actuals[document.getElementById("gui_iconsize").value] / 7);
});
$('#balloon_options_usermod_history').each( function() {
$(this).css('width', array_iconsize_actuals[document.getElementById("gui_iconsize").value] * 2);
$(this).css('height', array_iconsize_actuals[document.getElementById("gui_iconsize").value] * 2);
$(this).css('margin-right', array_iconsize_actuals[document.getElementById("gui_iconsize").value] / 7);
});
$('#balloon_options_usermod_info').each( function() {
$(this).css('width', array_iconsize_actuals[document.getElementById("gui_iconsize").value] * 2);
$(this).css('height', array_iconsize_actuals[document.getElementById("gui_iconsize").value] * 2);
$(this).css('margin-right', array_iconsize_actuals[document.getElementById("gui_iconsize").value] / 7);
});
}
document.getElementById('vis_fontsize').addEventListener('input', VisualChange2);
document.getElementById('vis_fontkerning').addEventListener('input', VisualChange2);
document.getElementById('vis_fontleading').addEventListener('input', VisualChange2);
document.getElementById('gui_iconsize').addEventListener('input', VisualChange2);
const originalFontFamily = window.FontFamily
window.FontFamily = function (elem) {
originalFontFamily(elem)
VisualChange2()
}
const originalToggleOptions = window.ToggleOptions
window.ToggleOptions = function (id, dontclose = false) {
document.getElementById('options_usermod_text').style.display = "none";
document.getElementById('options_usermod_history').style.display = "none";
document.getElementById('options_usermod_info').style.display = "none";
document.getElementById('balloon_options_usermod_text').style.backgroundColor = "white";
document.getElementById('balloon_options_usermod_history').style.backgroundColor = "white";
document.getElementById('balloon_options_usermod_info').style.backgroundColor = "white";
document.getElementById('img_options_usermod_text').src = text_icon_url;
document.getElementById('img_options_usermod_history').src = history_icon_url;
document.getElementById('img_options_usermod_info').src = info_icon_url;
originalToggleOptions(id, dontclose)
if (document.getElementById('modelinfo').style.display !== '') {
if ( Number(id) === 101 ) {
document.getElementById('options_usermod_text').style.display = "";
document.getElementById('balloon_options_usermod_text').style.backgroundColor = "#444444";
document.getElementById('img_options_usermod_text').src = text_icon_white_url;
} else if ( Number(id) === 102 ) {
document.getElementById('options_usermod_history').style.display = "";
document.getElementById('balloon_options_usermod_history').style.backgroundColor = "#444444";
document.getElementById('img_options_usermod_history').src = history_icon_white_url;
} else if ( Number(id) === 103 ) {
document.getElementById('options_usermod_info').style.display = "";
document.getElementById('balloon_options_usermod_info').style.backgroundColor = "#444444";
document.getElementById('img_options_usermod_info').src = info_icon_white_url;
}
}
}
const originalLoadVisConfigFromStorage = window.LoadVisConfigFromStorage
window.LoadVisConfigFromStorage = function (id, dontclose = false) {
originalLoadVisConfigFromStorage()
VisualChange2()
}
VisualChange2()
})()
// 送信テキストをテキストエリアに流す/出力履歴をため込む - ここまで
const pref = JSON.parse(localStorage.user_script_pref ? localStorage.user_script_pref : '{}')
const savePref = function () {
if (pref) {
localStorage.user_script_pref = JSON.stringify(pref)
}
}
document.querySelector('#options_goodies > .prefencesMenu > dd')
.insertAdjacentHTML('beforeend', `<h3>ユーザースクリプト</h3>
<input type="checkbox" style="font-size: 18px; transform:scale(1.5);" id="mod_icon_scroll" name="mod_icon_scroll" onclick="CopyContent();" ` + (pref.icon_scroll ? 'checked' : '') + `><span class="explanations"> アイコンのスクロールを有効化</span><br>
<input type="checkbox" style="font-size: 18px; transform:scale(1.5);margin-top:1rem" id="mod_force_insert_last" name="mod_force_insert_last" onclick="CopyContent();" ` + (pref.force_insert_last ? 'checked' : '') + `><span class="explanations"> endpoint存在時でも一番下に出力</span>`)
const mod_icon_scroll = document.getElementById('mod_icon_scroll')
if (mod_icon_scroll) {
mod_icon_scroll.addEventListener('change', function () {
if (this.checked) {
const elem = document.querySelector('#operation_btn_container+div')
elem.style['overflow-x'] = 'scroll'
elem.style['white-space'] = 'nowrap'
pref.icon_scroll = true
} else {
const elem = document.querySelector('#operation_btn_container+div')
elem.style['overflow-x'] = ''
elem.style['white-space'] = ''
pref.icon_scroll = false
}
savePref()
})
mod_icon_scroll.dispatchEvent(new Event('change'))
}
const mod_force_insert_last = document.getElementById('mod_force_insert_last')
if (mod_force_insert_last) {
mod_force_insert_last.addEventListener('change', function () {
if (this.checked) {
pref.force_insert_last = true
} else {
pref.force_insert_last = false
}
savePref()
})
}
// 最終保存日時の記録
let lastLocalSave = '', lastRemoteSave = ''
const originalLocalStorageSetItem = localStorage.setItem.bind(localStorage)
localStorage.setItem = function (key, value) {
const work_id = localStorage.getItem('current_works_id')
if (key === 'works' + work_id) {
const now = new Date()
lastLocalSave = formatDate(now)
UpdateModInfo()
}
return originalLocalStorageSetItem(key, value)
}
loadSession()
function v3_setting() {
// GUI定義
const select_history = document.createElement('select')
select_history.style = 'margin-bottom: 10px;height: 2rem;width: 100px;position:relative;top:5px'
select_history.id = 'mod-history-dialog-select'
const option = document.createElement('option')
option.innerText = '現在'
option.value = 0
select_history.appendChild(option)
select_history.readOnly = true
document.getElementsByTagName('head')[0].insertAdjacentHTML('beforeend', `<style type="text/css">
#editor {max-height:calc(100% - 40px)}
#mod-area {height:40px;position:absolute; bottom:0px;}
.mod-button {margin:5px;background-color: var(--primary-color);border:none;border-radius:5px;color: #fff;font-size: 1rem;cursor: pointer;}
.mod-button:hover {background-color: var(--primary-color-hover)}
#mod-send-text-dialog{top:100px;padding:0;border: black 2px solid;border-radius:5px;}
#mod-send-text-dialog *{left:5%}
#mod-send-text-dialog p{font-size: 75%;width:90%;position:relative;margin:0;}
#mod-history-dialog{top:100px;padding:0;border: black 2px solid;border-radius:5px;}
#mod-history-dialog *{left:5%}
#mod-history-dialog p{font-size: 75%;width:90%;position:relative;margin:0;}
#mod-info-dialog{top:100px;padding:0;border: black 2px solid;border-radius:5px;}
#mod-info-dialog *{left:5%}
#mod-info-dialog p{font-size: 75%;width:90%;position:relative;margin:0;}
.dialog-footer{
margin-bottom:5px;
height: 30px;
}
.dialog-footer .height-scale{
text-align:left;
float:left;
width: 30%;
}
.dialog-footer .width-scale{
text-align:right;
float:right;
width: 30%;
}
.dialog-footer .height-scale button, .dialog-footer .width-scale button{
margin: 0 5px;
width:25px;
height:25px;
}
.dialog-footer .close-area{
text-align:center;
width: 40%;
float: left;
margin: 0 auto;
}
</style>`)
document.getElementById('app').insertAdjacentHTML('afterend', `<div id="mod-area">
<button class="mod-button" id="mod-send-text-button">送信テキスト</button>
<button class="mod-button" id="mod-history-button">履歴の履歴</button>
<button class="mod-button" id="mod-info-button">情報</button>
</div>
<dialog id="mod-send-text-dialog" style="z-index:100;width:50%;" draggable="true">
<p style="margin-top:5px;">最後にAIに送信した入力テキスト内容を確認できます。(文字数:<span id="mod-send-text-dialog-count"></span>)</p>
<textarea id="mod-send-text-dialog-text" style="width:90%;height:60vh;position:relative;left:5%;font-family: arial sans-serif;" readOnly></textarea>
<div class="dialog-footer">
<div class="height-scale"><button>+</button><button>-</button></div>
<div class="close-area"><button onclick="document.getElementById('mod-send-text-dialog').close()">閉じる</button></div>
<div class="width-scale"><button>+</button><button>-</button></div>
</div></dialog>
<dialog id="mod-history-dialog" style="z-index:200;width:50%;" draggable="true">
<p style="margin-top:5px;">過去20回分までAIが出力したテキストの履歴を確認できます。確認可能なすべての履歴をファイルに保存することもできます。ページを閉じると履歴は消えます。</p>` +
select_history.outerHTML + `<button id="mod-history-dialog-download" class="mod-button" style="margin-left: 20px;margin-bottom: 10px;height: 2rem;width: 140px;position:relative;top: 5px;">ファイルに保存</button><br>
<textarea id="mod-history-dialog-text" style="width:90%;height:60vh;position:relative;left:5%;font-family: arial sans-serif;" readOnly></textarea>
<div class="dialog-footer">
<div class="height-scale"><button>+</button><button>-</button></div>
<div class="close-area"><button onclick="document.getElementById('mod-history-dialog').close()">閉じる</button></div>
<div class="width-scale"><button>+</button><button>-</button></div>
</div></dialog>
<dialog id="mod-info-dialog" style="z-index:300;width:50%;" draggable="true">
<p style="margin-top:5px;">編集ページを開いてから集計した情報を表示します。ページを閉じない限り継続して集計します。</p>
<textarea id="mod-info-dialog-text" style="width:90%;height:30vh;position:relative;left:5%;font-family: arial sans-serif;" rows="6" readOnly></textarea>
<div class="dialog-footer">
<div class="height-scale"><button>+</button><button>-</button></div>
<div class="close-area"><button onclick="document.getElementById('mod-info-dialog').close()">閉じる</button></div>
<div class="width-scale"><button>+</button><button>-</button></div>
</div></dialog>`)
const sendTextDialog = document.getElementById('mod-send-text-dialog')
const sendTextDialogText = document.getElementById('mod-send-text-dialog-text')
const sendTextDialogCount = document.getElementById('mod-send-text-dialog-count')
const historyDialog = document.getElementById('mod-history-dialog')
const historyDialogText = document.getElementById('mod-history-dialog-text')
const infoDialog = document.getElementById('mod-info-dialog')
const infoDialogText = document.getElementById('mod-info-dialog-text')
if (window.innerWidth < 768) {
sendTextDialog.style.width = '90%'
historyDialog.style.width = '90%'
infoDialog.style.width = '90%'
}
const scaleDialog = function (self, target, type) {
let param = Number(target.style[type].replace('%','').replace('vh',''))
const isLarger = self.textContent === '+'
if (isLarger) {
param += 5
} else {
param -= 5
}
if (param > 0 && param < 100) {
target.style[type] = String(param) + ((type === 'width') ? '%' : 'vh')
}
}
for (let targetElements of [
{width: sendTextDialog, height: sendTextDialogText},
{width: historyDialog, height: historyDialogText},
{width: infoDialog, height: infoDialogText},
]) {
for (let direction of ['height', 'width']) {
for (let scaleBtn of targetElements.width.querySelectorAll('.' + direction + '-scale button')){
scaleBtn.addEventListener('click', function (event) { scaleDialog(this, targetElements[direction], direction) })
}
}
}
// ダイアログの表示順調整
const setDialogOrder = function (dialog) {
let list = [sendTextDialog, historyDialog, infoDialog]
list.sort(function (a, b) {
if (a.style.zIndex < b.style.zIndex) {
return -1
}
if (a.style.zIndex > b.style.zIndex) {
return 1
}
return 0
})
for (let i = 0; i < list.length - 1; i++) {
if (list[i] === dialog) {
const z = dialog.style.zIndex
dialog.style.zIndex = list[i + 1].style.zIndex
list[i + 1].style.zIndex = z
list[i] = list[i + 1]
list[i + 1] = dialog
}
}
}
// 送信テキストダイアログの設定
document.getElementById('mod-send-text-button').addEventListener('click', function () {
if (sendTextDialog.open) {
sendTextDialog.close()
} else {
setDialogOrder(sendTextDialog)
sendTextDialog.show()
}
})
let sendTextDialogMousePos = {
x: 0,
y: 0
}
sendTextDialog.addEventListener('dragstart', function (event) {
setDialogOrder(sendTextDialog)
sendTextDialogMousePos.y = event.pageY - sendTextDialog.offsetTop
sendTextDialogMousePos.x = event.pageX - sendTextDialog.offsetLeft
event.dataTransfer.setDragImage(document.createElement('div'), 0, 0)
})
sendTextDialog.addEventListener('drag', function (event) {
if (event.x === 0 && event.y === 0) {
return
}
const top = event.pageY - sendTextDialogMousePos.y
const left = event.pageX - sendTextDialogMousePos.x
const right = window.outerWidth - event.pageX
sendTextDialog.style.top = top + 'px'
sendTextDialog.style.left = left + 'px'
sendTextDialog.style.right = right + 'px'
})
sendTextDialog.addEventListener('dragend', function (event) {
sendTextDialogMousePos = {
x: 0,
y: 0
}
});
sendTextDialog.addEventListener('click', function () {
setDialogOrder(sendTextDialog)
})
// 履歴の履歴ダイアログの設定
document.getElementById('mod-history-button').addEventListener('click', function () {
if (historyDialog.open) {
historyDialog.close()
} else {
setDialogOrder(historyDialog)
historyDialog.show()
}
})
let historyDialogMousePos = {
x: 0,
y: 0
}
historyDialog.addEventListener('dragstart', function (event) {
setDialogOrder(historyDialog)
historyDialogMousePos.y = event.pageY - historyDialog.offsetTop
historyDialogMousePos.x = event.pageX - historyDialog.offsetLeft
event.dataTransfer.setDragImage(document.createElement('div'), 0, 0)
})
historyDialog.addEventListener('drag', function (event) {
if (event.x === 0 && event.y === 0) {
return
}
const top = event.pageY - historyDialogMousePos.y
const left = event.pageX - historyDialogMousePos.x
const right = window.outerWidth - event.pageX
historyDialog.style.top = top + 'px'
historyDialog.style.left = left + 'px'
historyDialog.style.right = right + 'px'
})
historyDialog.addEventListener('dragend', function (event) {
historyDialogMousePos = {
x: 0,
y: 0
}
});
historyDialog.addEventListener('click', function () {
setDialogOrder(historyDialog)
})
// 情報ダイアログの設定
document.getElementById('mod-info-button').addEventListener('click', function () {
if (infoDialog.open) {
infoDialog.close()
} else {
setDialogOrder(infoDialog)
infoDialog.show()
}
})
let infoDialogMousePos = {
x: 0,
y: 0
}
infoDialog.addEventListener('dragstart', function (event) {
setDialogOrder(infoDialog)
infoDialogMousePos.y = event.pageY - infoDialog.offsetTop
infoDialogMousePos.x = event.pageX - infoDialog.offsetLeft
event.dataTransfer.setDragImage(document.createElement('div'), 0, 0)
})
infoDialog.addEventListener('drag', function (event) {
if (event.x === 0 && event.y === 0) {
return
}
const top = event.pageY - infoDialogMousePos.y
const left = event.pageX - infoDialogMousePos.x
const right = window.outerWidth - event.pageX
infoDialog.style.top = top + 'px'
infoDialog.style.left = left + 'px'
infoDialog.style.right = right + 'px'
})
infoDialog.addEventListener('dragend', function (event) {
infoDialogMousePos = {
x: 0,
y: 0
}
});
infoDialog.addEventListener('click', function () {
setDialogOrder(infoDialog)
})
document.addEventListener('dragover', function (event) {
// Firefoxのdragイベントに座標が入っていないので代替処理
if (event.x === 0 && event.y === 0) {
return
}
if (event.originalTarget === sendTextDialog && sendTextDialogMousePos.y !== 0 && sendTextDialogMousePos.x !== 0) {
const top = event.pageY - sendTextDialogMousePos.y
const left = event.pageX - sendTextDialogMousePos.x
const right = window.outerWidth - event.pageX
sendTextDialog.style.top = top + 'px'
sendTextDialog.style.left = left + 'px'
sendTextDialog.style.right = right + 'px'
} else if (event.originalTarget === historyDialog && historyDialogMousePos.y !== 0 && historyDialogMousePos.x !== 0) {
const top = event.pageY - historyDialogMousePos.y
const left = event.pageX - historyDialogMousePos.x
const right = window.outerWidth - event.pageX
historyDialog.style.top = top + 'px'
historyDialog.style.left = left + 'px'
historyDialog.style.right = right + 'px'
} else if (event.originalTarget !== infoDialog && infoDialogMousePos.y !== 0 && infoDialogMousePos.x !== 0) {
const top = event.pageY - infoDialogMousePos.y
const left = event.pageX - infoDialogMousePos.x
const right = window.outerWidth - event.pageX
infoDialog.style.top = top + 'px'
infoDialog.style.left = left + 'px'
infoDialog.style.right = right + 'px'
}
})
// 情報表示の変数
let totalOutputChar = 0, totalOutputCount = 0, totalRetryCount = 0, lastTextDateCount = 0
// セッション情報の読み書き
const saveSession = function () {
sessionStorage['usermod_for_v3_stat_' + localStorage.current_works_id] = JSON.stringify({totalOutputChar, totalOutputCount, totalRetryCount, historyStack})
}
const loadSession = function () {
if (sessionStorage['usermod_for_v3_stat_' + localStorage.current_works_id]) {
const stat_data = JSON.parse(sessionStorage['usermod_for_v3_stat_' + localStorage.current_works_id])
totalOutputChar = stat_data.totalOutputChar
totalOutputCount = stat_data.totalOutputCount
totalRetryCount = stat_data.totalRetryCount
historyStack = stat_data.historyStack
buildHistory()
UpdateModInfo()
}
}
// 情報表示
const UpdateModInfo = function () {
const avgOutputChar = totalOutputChar / totalOutputCount,
avgRetryCount = totalRetryCount / (totalOutputCount - totalRetryCount)
if (infoDialogText && ! Number.isNaN(avgOutputChar) && ! Number.isNaN(avgRetryCount)) {
const text = `総出力回数: ${totalOutputCount}回
総出力文字数: ${totalOutputChar}文字
平均出力文字数: ${Math.round(avgOutputChar*100)/100}文字
総リトライ回数: ${totalRetryCount}回
平均リトライ回数: ${Math.round(avgRetryCount*100)/100}回`
infoDialogText.value = text + (lastTextDateCount ? `\nおおよその本文の文字数:約${lastTextDateCount}文字` : '') + (lastLocalSave !== '' ? `\n最後にローカル保存した日時:${lastLocalSave}` : '') + (lastRemoteSave !== '' ? `\n最後にリモート保存した日時:${lastRemoteSave}` : '')
} else if (lastLocalSave !== '' || lastRemoteSave !== '') {
infoDialogText.value = (lastLocalSave !== '' ? `最後にローカル保存した日時:${lastLocalSave}` : '') + (lastRemoteSave !== '' ? `\n最後にリモート保存した日時:${lastRemoteSave}` : '')
}
}
// 履歴の履歴選択
const historySelect = document.getElementById('mod-history-dialog-select')
let previoutText = undefined
let historyStack = []
const updateHisotry = function () {
let text = ''
let count = 1
for (let item of historyStack[historySelect.value]) {
text += `(${count})\n${item}\n\n`
count++
}
historyDialogText.value = text
}
const buildHistory = function () {
if (historyStack.length > 20) {
historyStack.pop()
}
for (let i = historySelect.children.length; i < historyStack.length; i++) {
const option = document.createElement('option')
option.innerText = i + '個前'
option.value = i
historySelect.appendChild(option)
}
historySelect.dispatchEvent(new Event('change'))
}
historySelect.addEventListener('change',function () {
updateHisotry()
})
// 続きを書くボタンが再出現したときに出力を拾う
const buttonChecker = function () {
const button = document.getElementById('get-continuation')
if (button) {
let list = []
/*
for (let span of document.querySelectorAll('.ai-output')) {
list.push([span.textContent, Number(span.parentElement.attributes['data-id'])])
}
list.sort(function (a, b) {
if (a[1] < b[1]) {
return -1
} else if (a[1] > b[1]) {
return 1
}
return 0
})
let text = list.map(function (item) { return item[0] }).join("\n")
*/
for (let span of document.querySelectorAll('.ai-output')) {
list.push(span.textContent)
}
let text = list.join("\n")
if (text === '') {
return
}
historyStack[0].push(text)
updateHisotry()
totalOutputCount += 1
if (historyStack[0].length > 1) {
totalRetryCount += 1
}
totalOutputChar += text.length
UpdateModInfo()
saveSession()
} else {
setTimeout(buttonChecker, 100)
}
}
// 外部接続に割り込み
const originalFetch = window.fetch
window.fetch = function (resource, init = {}) {
if (resource.indexOf('.coreweave.cloud/') >= 0) {
// バックエンド接続時のリクエストを読んで送信テキストに設定
const json_data = JSON.parse(init.body)
sendTextDialogText.value = json_data.text
sendTextDialogCount.innerText = json_data.text.length + '文字'
} else if (resource.indexOf('getrequest_v5.php') >= 0) {
// フロントエンド接続時のリクエストを読んで、前回と本文が変わっていたら履歴の履歴を順送りする
const data = init.body.get('data')
if (previoutText === undefined || previoutText !== data) {
historyStack.unshift([])
previoutText = data
buildHistory()
}
lastTextDateCount = data.length
} else if (resource.indexOf('_remotestories.php') >= 0) {
// リモート保存時の日時を記録する
const now = new Date()
lastRemoteSave = formatDate(now)
UpdateModInfo()
}
return originalFetch(resource, init).then(res => {
if (res.url.indexOf('.coreweave.cloud/') >= 0) {
// バックエンド接続時のレスポンスをトリガーに、出力を履歴の履歴に追加する
/*res.clone().json().then(json_data => {
historyStack[0].push(json_data.data.text)
console.log(historyStack)
updateHisotry()
})*/
setTimeout(buttonChecker, 100)
}
return res
})
}
document.getElementById('mod-history-dialog-download').addEventListener('click', function () {
if (historyStack.length === 0) {
return
}
const title = localStorage.textdata_title, separator = '\n---*---*---*---*---*---\n'
let textList = []
for (let history of historyStack) {
let text = ''
let count = 1
for (let item of history) {
text += `(${count})\n${item}\n\n`
count++
}
textList.push(text)
}
const text = textList.join(separator)
if (text === '') {
return
}
const temp = title + separator + text
const blob = new Blob([temp], {type: 'text/plain'}),
a = document.createElement("a")
const now = new Date()
a.href = URL.createObjectURL(blob);
document.body.appendChild(a);
a.download = title.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g, '')+'_' + now.getFullYear() + ('0' + (now.getMonth()+1)).slice(-2) + ('0' + now.getDate()).slice(-2) + ('0' + now.getHours()).slice(-2) + ('0' + now.getMinutes()).slice(-2) + ('0' + now.getSeconds()).slice(-2) + '.txt';
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(a.href);
})
let lastLocalSave = '', lastRemoteSave = ''
const originalLocalStorageSetItem = localStorage.setItem.bind(localStorage)
localStorage.setItem = function (key, value) {
const work_id = localStorage.getItem('current_works_id')
if (key === 'works' + work_id) {
const now = new Date()
lastLocalSave = formatDate(now)
UpdateModInfo()
}
return originalLocalStorageSetItem(key, value)
}
loadSession()
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment