아키텍처#
소스 구조#
플러그인의 모든 로직은 src/ 아래에 있습니다:
파일 |
역할 |
|---|---|
|
플러그인 진입점: 설정을 불러오고, 설정 탭·에디터 서제스트·라이브 프리뷰 익스텐션·포스트 프로세서를 연결하며, 주소록 새로고침 명령을 추가합니다. |
|
공용 타입: |
|
기본 설정값과 설정 UI입니다. |
|
Obsidian 공식 |
|
최소한의 읽기 전용 CardDAV 클라이언트입니다: Obsidian의 |
|
vCard 3/4를 파싱해 |
|
|
|
|
|
라이브 프리뷰에서 |
|
렌더링된 텍스트 노드를 순회하며 읽기 모드에서 동일한 치환을 수행하는 마크다운 포스트 프로세서입니다. |
|
칩 DOM 엘리먼트와, 클릭 시 열리는 상세 카드(직접 위치를 계산하는 플로팅 패널이며, 바깥 클릭이나 Esc로 닫힘)입니다. |
데이터 흐름#
settingsTab.ts --> CardDavProfile[] (server URL, credentials)
|
v
carddav/client.ts --> PROPFIND/REPORT over requestUrl
| (discovery + address book fetch)
v
carddav/vcard.ts --> parses each vCard into a Contact
|
v
carddav/store.ts --> merged, cached Contact[] across profiles
|
+--> editorSuggest.ts (HrcardEditorSuggest) --> autocomplete while typing
|
+--> render/livePreview.ts --> chip widgets (Live Preview)
|
+--> render/postProcessor.ts --> chip elements (Reading view)
|
v
render/chip.ts + render/card.ts --> click-to-open detail card
참조 문법#
확정된 참조는 {{hrcard:<profileId>:<uid>}} 형태로 저장됩니다. profileId와 uid는 연락처를 정확히 찾는 데 사용되므로, (같은 서버든 다른 서버든) 표시 이름이 우연히 같은 두 연락처가 서로 혼동되는 일이 없습니다 - 표시 이름 자체는 저장된 문법에 전혀 포함되지 않고, 렌더링 시점에 그 uid에 대해 스토어가 현재 가지고 있는 값에서 매번 가져올 뿐입니다. 프로필을 만들 때 한 번 생성되고 이후로 절대 바뀌지 않는 내부 id를 사용자가 지정한 name 대신 사용하므로, 이 변경 이후로 작성된 참조는 설정에서 프로필 이름을 바꿔도 더 이상 깨지지 않습니다 - editorSuggest.ts는 자동완성 1단계에서 여전히 프로필을 표시 이름으로 검색·목록화하지만, 삽입할 텍스트를 구성할 때는 그 자리를 id로 조용히 바꿔치기합니다. 이는 하위 호환되지 않습니다: 이 변경 전에 삽입된 참조는 프로필의 이름을 대신 저장하고 있었고, id와 이름을 함께 시도하는 대체 해석기가 없기 때문에, 그런 참조는 프로필 이름이 바뀌는 즉시(또는 애초에 그 자리 값이 현재 어떤 프로필의 id와도 일치하지 않는다면 즉시) 더 이상 해석되지 않으며, {{hrcard: 자동완성으로 삭제 후 다시 삽입해야 합니다. {{...}}는 Obsidian의 위키링크 문법이 아니므로, 가상의 [[...]] 형태와 달리 Obsidian 자체의 링크 파서에 가로채이는 일이 없습니다 - 읽기 모드와 라이브 프리뷰 모두 원문 텍스트를 직접 매칭합니다. 손으로 입력한 참조가 해석되려면 정확한 프로필 id와 CardDAV UID가 필요한데, 둘 다 UI 어디에도 표시되지 않으므로 기존 참조에서 복사해오는 경우가 아니라면 사실상 입력하기 어렵습니다 - 실제로는 항상 {{hrcard: 자동완성을 통해 참조를 삽입하세요.
런타임 의존성 없음#
Obsidian 자체가 제공하는 것(obsidian 패키지, CodeMirror 6) 외에는 런타임 의존성이 없습니다 — CardDAV 클라이언트와 vCard 파서 모두 npm에서 가져오지 않고 직접 작성해, 번들 크기를 작게 유지하고 서드파티 HTTP/XML 파싱 라이브러리 자체의 취약점에 노출될 일을 없앴습니다.