supports the base64 section

This commit is contained in:
hetima
2026-01-29 10:45:19 +09:00
parent 3502a8bd83
commit f5b8233aca
3 changed files with 232 additions and 0 deletions
+29
View File
@@ -57,6 +57,21 @@ app.registerExtension({
`;
document.head.appendChild(style);
const base64prefix = ":::base64:::";
const decodeBase64Unicode = function (input) {
let rawBase64 = input;
if (input.startsWith(base64prefix)) {
rawBase64 = input.slice(base64prefix.length);
}else{
return "";
}
//bytes = Uint8Array.fromBase64(rawBase64);
const binString = atob(rawBase64);
const bytes = Uint8Array.from(binString, (m) => m.charCodeAt(0));
return new TextDecoder().decode(bytes);
}
const addListItem = function (container) {
const itm = document.createElement("div");
itm.className = "single-line-picker-list-item";
@@ -395,6 +410,7 @@ app.registerExtension({
const result = [];
let currentBody = [];
let currentTitle = null;
let includesBase64 = false;
lineArray.forEach((line) => {
const trimmedLine = line.trim();
@@ -411,6 +427,9 @@ app.registerExtension({
} else {
// accumulate the body
if (currentTitle !== null) {
if (currentBody.length == 0 && trimmedLine === base64prefix) {
includesBase64 = true;
}
currentBody.push(trimmedLine);
}
}
@@ -421,6 +440,16 @@ app.registerExtension({
result.push(currentTitle, currentBody.join('\n'));
}
if (includesBase64) {
for (let index = 0; index < result.length; index++) {
const itm = result[index];
if (itm.startsWith(base64prefix)) {
result[index] = decodeBase64Unicode(result[index]);
}
}
}
return result;
}
+98
View File
@@ -0,0 +1,98 @@
import argparse
import base64
from pathlib import Path
def output_to_file(output_content, target_dir):
target_dir = Path(target_dir)
if output_content:
# 既存ファイルは上書きされる
target_dir.write_text(output_content, encoding='utf-8')
print(f"Successfully saved to: {target_dir}")
else:
print("No content generated. Check if the directory contains .txt files.")
def get_folder_contents(target_dir):
"""
フォルダ直下のtxtファイルを読み込み、指定フォーマットの文字列を返します。
"""
target_dir = Path(target_dir)
if not target_dir.is_dir():
return ""
results = ["#section"]
# フォルダ直下の .txt ファイルを昇順で取得
for file_path in sorted(target_dir.glob("*.txt")):
try:
# 改行コードを \n に統一して読み込み
if file_path.name.endswith(".slp.txt"):
continue
content = file_path.read_text(encoding='utf-8').replace('\r\n', '\n').replace('\r', '\n')
results.append(f"[{file_path.stem}]")
results.append(content)
except Exception as e:
results.append(f"[{file_path.stem}]\nError reading file: {e}")
if len(results) <= 1:
return ""
return "\n".join(results)
def process_folder(target_dir):
"""-d: フォルダ内のテキストファイルを処理して保存"""
target_dir = Path(target_dir)
output_file = target_dir / "output.slp.txt"
output_to_file(get_folder_contents(target_dir), output_file)
def merge_subfolder_files(target_dir):
"""
-dd: サブフォルダ(1階層)ごとに get_folder_contents を実行し、
結果をbase64エンコードしてまとめます。
"""
target_dir = Path(target_dir)
if not target_dir.is_dir():
print(f"Error: {target_dir} is not a directory.")
return
final_results = ["#section"]
# 1階層下のディレクトリのみを抽出
subdirectories = sorted([d for d in target_dir.iterdir() if d.is_dir()])
for sub_dir in subdirectories:
# サブフォルダ内のテキスト情報を取得
folder_text = get_folder_contents(sub_dir)
# テキストが存在する場合のみ処理
if folder_text:
# 文字列をバイトに変換してBase64エンコード
b64_encoded = base64.b64encode(folder_text.encode('utf-8')).decode('utf-8')
final_results.append(f"[{sub_dir.name}]")
final_results.append(":::base64:::")
final_results.append(b64_encoded)
output_content = ""
if len(final_results) > 1:
output_content = "\n".join(final_results)
output_file = target_dir / "output.slp.txt"
output_to_file(output_content, output_file)
def main():
parser = argparse.ArgumentParser(description='Converts text files to SLP compatible text file.')
parser.add_argument('path', help='Path to the target file or directory')
group = parser.add_mutually_exclusive_group()
group.add_argument('-d', action='store_true', help='Process text files in the folder')
group.add_argument('-dd', action='store_true', help='Process text files in subfolders and merge them into a single file')
args = parser.parse_args()
target_path = Path(args.path)
if args.d:
process_folder(target_path)
elif args.dd:
merge_subfolder_files(target_path)
else:
# オプションなしの場合は-d
process_folder(target_path)
if __name__ == '__main__':
main()
+105
View File
@@ -0,0 +1,105 @@
import argparse
import base64
import csv
from pathlib import Path
def output_to_file(output_content, file_path):
"""指定されたファイル名で内容を保存"""
file_path = Path(file_path)
if not output_content:
print(f"No content to write for {file_path}")
return
file_path.write_text(output_content, encoding='utf-8')
print(f"Successfully saved to: {file_path}")
def process_csv_or_tsv(file_path):
"""
CSV/TSVを処理し、1行ずつリストに追加して最後に結合します。
"""
path = Path(file_path)
if not path.is_file():
return ""
delim = '\t' if path.suffix.lower() == '.tsv' else ','
results = ["#section"]
try:
with path.open(encoding='utf-8', newline='') as f:
reader = csv.reader(f, delimiter=delim)
for row in reader:
if len(row) >= 2 and row[0] and row[1]:
# [title]
results.append(f"[{row[0]}]")
# body (改行コード正規化)
results.append(row[1].replace('\r\n', '\n').replace('\r', '\n'))
# 3列目がある場合の追加処理
if len(row) >= 3:
results.append("---")
results.append(row[2].replace('\r\n', '\n').replace('\r', '\n'))
except Exception as e:
return f"Error processing {path.name}: {e}"
if len(results) <= 1:
return ""
return "\n".join(results)
def merge_folder_files(target_dir):
"""フォルダ内の全ファイルを処理し、結果をBase64化して連結"""
target_dir = Path(target_dir)
final_results = ["#section"]
files = sorted([f for f in target_dir.iterdir() if f.suffix.lower() in ['.csv', '.tsv']])
for file in files:
content = process_csv_or_tsv(file)
if content:
b64_encoded = base64.b64encode(content.encode('utf-8')).decode('utf-8')
final_results.append(f"[{file.stem}]")
final_results.append(":::base64:::")
final_results.append(b64_encoded)
if len(final_results) <= 1:
return ""
return "\n".join(final_results)
def process_csv(target_path):
# 単体ファイル処理
target_path = Path(target_path)
if target_path.suffix.lower() not in ['.csv', '.tsv']:
print("Error: Target path must be a .csv or .tsv file")
return
content = process_csv_or_tsv(target_path)
output_file_path = target_path.with_suffix('.slp.txt')
output_to_file(content, output_file_path)
def process_folder(target_path):
target_path = Path(target_path)
if not target_path.is_dir():
print("Error: Target path must be a directory.")
return
content = merge_folder_files(target_path)
output_file_path = target_path / "output.slp.txt"
output_to_file(content, output_file_path)
def main():
parser = argparse.ArgumentParser(description='Converts CSV/TSV to SLP compatible text file.')
parser.add_argument('path', help='Path to the target CSV/TSV file or directory')
args = parser.parse_args()
target_path = Path(args.path)
if target_path.is_dir():
# フォルダ一括処理
process_folder(target_path)
elif target_path.suffix.lower() in ['.csv', '.tsv']:
# 単体ファイル処理
process_csv(target_path)
else:
print("Error: Target path must be a .csv or .tsv file or directory.")
if __name__ == '__main__':
main()