
Mac에서 작성한 Obsidian 문서를 윈도나 웹에서 열어보면 간혹 깨진 문자가 섞여있다.
Mac 화면에선 보이지 않고 나머지 시스템에선 보인다.
<- Mac이 아닌 시스템에서만 보임
이 문자의 정체가 뭘까. JS inspector에 붙여넣어보니
Uncaught SyntaxError: illegal character U+0008
U+0008은 BACKSPACE였다.
해결을 위한 시도들
어쩌면 내가 macOS에서 한영전환을 특이하게 해서 그럴 수도 있다. 기본적으로 CAPS Lock 키도 한영전환용으로 쓰면서, 거기에 더해 Karabiner Elements를 이용해서, 우측 Opt 키를 다른 조합 없이 눌렀다 뗄 때 한영전환이 되도록 설정했는데 어쩌면 그게 원인일 수도 있다.
아무튼, 투명 깨진 문자가 생겼을 때 Mac에서는 화면에 보이지 않기 때문에 수습이 필요하다.
옵시디언 플러그인을 사용하면 깨진 문자가 보이는가?
- Obsidian에 Control Character라는 플러그인을 찾아 설치해봤다. 여전히 문제의
0x08문자는 화면 출력이 안된다. 이 플러그인 설치 후 한 가지 문제가 발생했는데, 스페이스 다음의 첫 한글은 작은 점 안에 표시된다. 삭제. - Show Whitespace 플러그인 역시
0x08은 표시해주지 못한다. 삭제. - 이 플러그인들은 공백, 탭, 개행 문자에 특화되어있는 듯 하다. 둘 다 삭제했다.
커밋 시점에 수정?
Quartz sync시 이상한 현상에서와 마찬가지로 git hook을 이용해 커밋 이벤트에 특수문자를 삭제해는 접근이다.
- tr, awk, sed는 UTF-8 대응이 완전하지 않아서 제외. perl을 사용함.
iconv -c사용해봤으나0x08문자 사라지지 않음.
ChatGPT 시켜서 만든 스크립트:
#!/bin/bash
remove_control_chars() {
local file="$1"
local lockfile="$file.lock"
local dry_run=$2
# 동시 처리를 방지하기 위해 잠금 파일을 생성 시도
if ! mkdir "$lockfile" 2>/dev/null; then
echo "File is already being processed: $file"
return
fi
# 스크립트가 실패하더라도 잠금 파일과 임시 파일을 제거하도록 보장
trap 'rm -rf "$lockfile"; rm -f "$file.tmp" "$file.tmp.cleaned"' EXIT
# 임시 파일을 생성하고 iconv를 사용하여 잘못된 UTF-8 문자를 제거
iconv -f UTF-8 -t UTF-8 -c "$file" > "$file.tmp" 2>/dev/null || { echo "Error processing $file"; exit 1; }
# Perl을 사용하여 특정 제어 문자(예: 백스페이스 0x08)를 안전하게 제거
perl -CSD -pe 's/\x08//g' "$file.tmp" > "$file.tmp.cleaned" || { echo "Error removing control characters from $file"; exit 1; }
# 파일이 수정된 경우 업데이트하고 수정된 파일 이름을 출력
if ! cmp -s "$file" "$file.tmp.cleaned"; then
if [ "$dry_run" = true ]; then
echo "[Dry-Run] Updated Markdown file: $file"
else
echo "Updated Markdown file: $file"
cp "$file.tmp.cleaned" "$file"
fi
fi
# 초기 임시 파일 제거
rm -f "$file.tmp.cleaned" "$file.tmp"
# 잠금 해제
rm -rf "$lockfile"
}
# dry-run 플래그에 대한 인수 파싱
dry_run=false
while [[ "$1" == --* ]]; do
case "$1" in
--dry-run)
dry_run=true
;;
esac
shift
done
# find 명령을 사용하여 모든 .md 파일을 재귀적으로 읽고 각 파일에 대해 remove_control_chars 호출
find ./content -type f -name "*.md" -print0 | while IFS= read -r -d '' file; do
remove_control_chars "$file" $dry_run
done위 스크립트를 pre-commit 스크립트에 넣어볼 예정.