diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5ca9ac3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +** +!Dockerfile +!release/ +!release/app/ +!release/app/** +!release/manifest.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ddecec1 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +TRILIUM_KO_PORT=8082 +TRILIUM_KO_BIND=127.0.0.1 +TRILIUM_KO_DATA_DIR=./data diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ad8ce6c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +*.sh text eol=lf +Dockerfile text eol=lf +*.yml text eol=lf +release/** -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f71202 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +data/ +backups/ +.env +*.bundle diff --git a/CHANGELOG.ko.md b/CHANGELOG.ko.md new file mode 100644 index 0000000..639331c --- /dev/null +++ b/CHANGELOG.ko.md @@ -0,0 +1,17 @@ +# 변경 기록 + +## 2.0.0 — 2026-09-13 + +- 기록용 폴더에 있던 최신 번역을 실제 Docker 이미지에 통합했습니다. +- 운영에서 확인한 Trilium 0.95.0 이미지의 다이제스트를 고정했습니다. +- 신규 설치용 기본 예제 ZIP을 한국어로 생성했습니다. 노트 ID가 바뀌어도 새로 가져올 수 있도록 원본 예제와 대응시켰습니다. +- 한국어 PDF와 도움말 및 API 문서와 Swagger 정적 파일을 포함했습니다. +- 서버 전용 경로를 쓰던 일회성 DB 마이그레이션 코드를 일반 배포 번들에서 제거했습니다. +- 설치 프로그램의 현재 폴더 사용과 포트·데이터 경로 설정을 정리했습니다. +- 이미지 빌드 시 파일 무결성과 JavaScript 구문을 검사합니다. +- 업데이트 전 데이터 백업과 이전 이미지 보존 및 기동 실패 시 이미지 복귀를 추가했습니다. +- `.dockerignore`로 빌드 입력을 배포 파일로 제한했습니다. +- 구형 루트 패치 파일은 `legacy/v1`로 옮겼습니다. 기존 v1.0.0 첨부 배포판은 최신 파일을 포함하지 않습니다. +- 신규 설치와 초기 예제 생성 및 공식 0.95.0에서의 전환과 재설치 및 고의 실패 복귀와 백업 복원을 검증했습니다. + +상세 결과는 [배포 검증 기록](docs/DEPLOYMENT-TESTS.ko.md)을 참고하세요. 과거 운영 서버 번역 과정은 [번역 변경 기록](updates/2026-09-05/CHANGELOG.ko.md)에 보관했습니다. diff --git a/Dockerfile b/Dockerfile index 3e988a1..2ead653 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,15 @@ -FROM triliumnext/notes:latest - -COPY main.cjs /usr/src/app/main.cjs -COPY translation.json /usr/src/app/public/translations/ko/translation.json -COPY server.json /usr/src/app/assets/translations/ko/server.json +FROM triliumnext/notes@sha256:611a430016585d35b170eb9a0fa300ce76318f04a8ec0067549c4c52561b0c36 +LABEL org.opencontainers.image.title="Trilium 이스톰 한국어판" \ + org.opencontainers.image.version="2.0.0" \ + org.opencontainers.image.source="https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch" +USER root +COPY release/app/ /usr/src/app/ +COPY release/manifest.json /usr/src/app/korean-release.json +RUN node -e "const fs=require('fs'),c=require('crypto'),m=require('./korean-release.json');for(const [p,v] of Object.entries(m.files)){const b=fs.readFileSync(p);if(b.length!==v.bytes||c.createHash('sha256').update(b).digest('hex')!==v.sha256)throw Error(p)}" \ + && node --check /usr/src/app/main.cjs +RUN find /usr/src/app/assets/doc_notes/en /usr/src/app/public/translations/ko /usr/src/app/assets/translations/ko -type d -exec chmod 755 {} \; \ + && find /usr/src/app/assets/doc_notes/en /usr/src/app/public/translations/ko /usr/src/app/assets/translations/ko -type f -exec chmod 644 {} \; \ + && chmod 644 /usr/src/app/main.cjs /usr/src/app/assets/db/demo.zip /usr/src/app/public/src/*.js /usr/src/app/public/src/emoji-ko.json +ENV TZ=Asia/Seoul +HEALTHCHECK --interval=10s --timeout=3s --start-period=60s --retries=6 \ + CMD node -e "require('http').get('http://127.0.0.1:8080/api/health-check',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))" diff --git a/README.md b/README.md index 14b2b23..f1ffba9 100644 --- a/README.md +++ b/README.md @@ -1,197 +1,87 @@ -# TriliumNext Notes 한국어 패치 (번역 + main.cjs 패치) +# Trilium 이스톰 한국어판 2.0.0 -최신 진행 상황: [2026-09-13 작업 기록](updates/2026-09-05/PROGRESS.md). 도움말 본문 173개와 제목 181개를 운영 서버에 반영했습니다. 전체 한글화는 추가 점검 중입니다. +Trilium 0.95.0용 한국어 배포판입니다. UI와 편집기 및 도움말과 API 참고 문서를 포함합니다. 새 문서에는 한국어 기본 예제와 한국어 PDF가 들어갑니다. 이미지 원본은 유지하고 한국어 설명을 제공합니다. -## 2026-09-05 후속 작업 +Dockerfile과 설치 스크립트가 최신 배포 파일을 사용하도록 통합했습니다. `latest` 대신 검증한 이미지 다이제스트를 고정합니다. 다른 Trilium 버전에 이 서버 번들을 덮어쓰지 마세요. -[최신 작업 상태와 파일](updates/2026-09-05/README.md) 및 [상세 변경 기록](updates/2026-09-05/CHANGELOG.ko.md)을 추가했습니다. 운영 서버에는 예제 노트 148개 수정과 편집기 한국어 사전 719개 문구 등을 반영했습니다. 2026-09-13에 기본 도움말 전체와 목록 제목을 서버에 반영했습니다. 전체 한글화는 진행 중입니다. +## 설치 -아래의 기존 설치 안내와 v1.0.0 다운로드는 이전 배포판에 대한 설명입니다. 이번 작업 폴더의 파일은 기존 설치 프로그램에 자동으로 포함되지 않습니다. - -[TriliumNext Notes](https://github.com/TriliumNext/Notes)의 비공식 커뮤니티 한국어 번역입니다. -이 글을 쓰는 시점 기준으로 TriliumNext는 한국어 언어팩이 없고, 심지어 UI 언어 선택기에 -뜨는 지원 언어 목록 자체가 `translations/` 폴더를 스캔해서 만들어지는 게 아니라 **컴파일된 -서버 번들(`main.cjs`) 안에 하드코딩된 배열**이라서, 번역 파일만 올바른 경로에 넣는다고 -"한국어"가 언어 선택기에 나타나지 않습니다. 그래서 번역 파일 외에 서버 번들을 패치하는 -스크립트도 함께 제공합니다. - -## 압축 파일로 받기 - -Git 없이 필요한 파일만 바로 받고 싶다면 압축된 배포판을 받으세요. 두 종류가 있습니다 -([릴리스 페이지](https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/releases/tag/v1.0.0)): - -- **[triliumnext-korean-patch.zip 다운로드](https://gitea.itosm.co.kr/attachments/11f09ff6-4d85-4234-8360-a4ae968dd437)** - (2.5MB) — **처음 새로 설치하는 경우.** `Dockerfile`, `install.sh`, `docker-compose.yml`까지 - 전부 포함되어 있어서, 압축을 풀고 `./install.sh`를 실행하거나 `docker compose up -d --build`를 - 실행하면 한국어가 내장된 새 컨테이너가 만들어집니다. -- **[triliumnext-korean-patch-only.zip 다운로드](https://gitea.itosm.co.kr/attachments/679762e6-8b68-48e4-9954-82a2163750a8)** - (2.4MB) — **이미 Trilium을 운영 중인 경우.** 이미지를 새로 빌드하거나 컨테이너를 새로 - 만들지 않고, 기존 데이터/설정을 그대로 둔 채 파일 3개만 bind-mount로 추가합니다. - 압축 안의 `README.md`에 기존 `docker-compose.yml`에 반영하는 방법이 자세히 적혀 있습니다. - -## 포함된 파일 - -- `install.sh` — **원클릭 설치 스크립트**. 명령어 한 줄로 저장소를 내려받고, 한국어가 - 내장된 이미지를 빌드해서 바로 실행시킵니다. -- `Dockerfile` — `triliumnext/notes:latest` 위에 번역 파일과 패치된 `main.cjs`를 - 구워 넣어서, 별도 bind-mount 없이 한국어가 기본 내장된 이미지를 만듭니다. -- `docker-compose.yml` — 위 `Dockerfile`로 빌드해서 바로 띄우는 compose 파일 - (`install.sh`가 내부적으로 이걸 사용합니다). -- `translation.json` — 클라이언트(브라우저) UI 문자열, 1,712개 키, 100% 번역 완료. -- `server.json` — 서버 문자열, 283개 키, 100% 번역 완료. -- `main.cjs` — **이미 패치가 적용된, 바로 쓸 수 있는 서버 번들** (`triliumnext/notes:latest`, - 빌드일 2025-06-07, appVersion 0.95.0 기준). -- `patch_main_cjs.js` — 위 `main.cjs`를 만들어낸 패치 스크립트. 다른 버전의 이미지를 쓰거나 - 이미지가 업데이트된 경우, 이 스크립트를 새 원본 `main.cjs`에 다시 돌려서 직접 패치된 - 파일을 만들어야 합니다 (왜 이게 필요한지는 스크립트 상단 주석 참고). -- `docker-compose.bind-mount.yml.example` — 이미 떠 있는 공식 이미지 컨테이너에 파일만 - bind-mount로 추가하고 싶을 때 쓰는 예시 (이미지를 새로 빌드하지 않는 방식). - -`triliumnext/notes:latest` (빌드일 2025-06-07, appVersion 0.95.0) 기준으로 테스트했습니다. -`main.cjs` 안의 변수명은 전부 난독화(minify)되어 있고 **빌드마다 이름이 바뀔 수 있습니다** — -`patch_main_cjs.js`를 새 이미지에 돌렸을 때 `[skip]`이 출력되면, 스크립트가 찾는 문자열 -패턴이 그 빌드에서 바뀐 것이니 새 빌드에서 같은 패턴을 다시 찾아 스크립트를 갱신해야 합니다. - -## 설치 방법 — 명령어 한 줄 (추천) - -Docker와 Docker Compose 플러그인만 설치되어 있으면 됩니다: +Linux 서버의 Docker Engine과 Docker Compose 플러그인이 필요합니다. Compose는 `up --wait`를 지원해야 합니다. 저장소를 내려받을 때는 Git도 필요합니다. Docker 명령을 실행할 권한이 있는 계정으로 진행하세요. ```bash -curl -fsSL https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/raw/branch/main/install.sh | bash +git clone https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch.git +cd triliumnext-korean-patch +cp .env.example .env +bash install.sh ``` -기본적으로 `./trilium-korean` 폴더에 저장소를 내려받고, 한국어가 내장된 이미지를 빌드해서 -`http://localhost:8082`로 띄웁니다. 포트를 바꾸고 싶으면: +기본 주소는 `http://127.0.0.1:8082`입니다. 서버에 리버스 프록시가 있다면 이 주소로 연결하세요. 직접 외부 접속을 허용하려면 `.env`의 `TRILIUM_KO_BIND`를 서버의 수신 주소로 변경하세요. 모든 인터페이스를 사용할 값은 `0.0.0.0`입니다. 포트는 `TRILIUM_KO_PORT`에서 바꿉니다. + +브라우저에서 새 문서를 만들고 비밀번호를 설정하세요. 언어 및 지역 설정에서 한국어를 선택하고 새로 고칩니다. 기존 계정의 언어 설정은 업데이트 때 유지합니다. + +Docker 이미지는 설치 중 로컬에서 빌드합니다. 이 저장소는 공개 컨테이너 레지스트리에 이미지를 올렸다고 가정하지 않습니다. 최초 빌드에는 고정된 기반 이미지 다운로드가 필요할 수 있습니다. + +## 업데이트 + +현재 설치 폴더에서 실행합니다. ```bash -TRILIUM_KO_PORT=9000 curl -fsSL https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/raw/branch/main/install.sh | bash +git pull --ff-only +bash install.sh ``` -설치가 끝나면 브라우저로 접속해서 초기 비밀번호를 설정한 뒤, **옵션 → 언어 및 지역**에서 -"한국어"를 선택하고 페이지를 새로고침하면 됩니다 (본문 텍스트까지 전부 한국어로 바뀌려면 -새로고침이 한 번 필요합니다 — 앱 자체의 동작이며 이 패치의 문제는 아닙니다). +스크립트는 새 이미지를 먼저 빌드합니다. 이후 이 Compose 프로젝트의 Trilium을 중지하고 데이터 전체를 `backups/날짜-번호/data.tar.gz`로 백업합니다. 새 컨테이너의 상태 검사를 통과해야 배포 성공으로 표시합니다. 기동 실패 시 이전 이미지로 복귀를 시도하며 백업은 보존합니다. 데이터베이스는 실패 시 자동으로 덮어쓰지 않습니다. -업데이트하려면 같은 명령어를 같은 폴더에서 다시 실행하면 됩니다. +새 설치용 예제 압축 파일을 바꿔도 기존 노트는 다시 가져오거나 덮어쓰지 않습니다. 기존 영어 예제나 사용자가 수정한 노트의 본문을 이 설치 스크립트가 임의로 번역하지 않습니다. 이스톰 운영 서버의 기존 노트 번역 기록은 `updates/2026-09-05`에 별도로 남아 있습니다. -## 설치 방법 — 이미 떠 있는 컨테이너에 추가하고 싶은 경우 +## 기존 다른 컨테이너에서 이전 -이미지를 새로 빌드하지 않고, 이미 쓰고 있는 공식 `triliumnext/notes` 컨테이너에 파일만 -얹고 싶다면: +이 배포판은 Trilium 0.95.0과 같은 데이터 형식으로 검사했습니다. 더 최신 버전에서 쓰던 DB를 이전 버전으로 되돌리는 용도로 사용하지 마세요. -1. **번역 파일 + `main.cjs`를 `docker-compose.yml`에 bind-mount로 등록** - (`docker cp`로만 넣지 말 것 — 아래 "문제 4" 참고): - - `main.cjs` → `/usr/src/app/main.cjs` - - `translation.json` → `/usr/src/app/public/translations/ko/translation.json` - - `server.json` → `/usr/src/app/assets/translations/ko/server.json` -2. `docker-compose.bind-mount.yml.example`을 참고해서 그대로 적용, 컨테이너 재시작. -3. 앱 안에서 **옵션 → 언어 및 지역**에서 "한국어" 선택 후 새로고침. +1. 기존 Trilium을 중지하고 데이터 폴더 전체를 백업합니다. +2. 기존 데이터를 별도 복사한 경로를 `.env`의 `TRILIUM_KO_DATA_DIR`로 지정합니다. +3. 다른 포트로 이 배포판을 설치해 노트와 첨부 파일을 확인합니다. +4. 확인 후 리버스 프록시의 연결 대상을 변경합니다. -## 설치 방법 — 다른 이미지 버전을 쓰는 경우 (직접 패치) +하나의 데이터 폴더를 두 컨테이너에서 동시에 열지 마세요. 설치 스크립트는 같은 데이터 경로를 사용 중인 다른 컨테이너가 있으면 중단합니다. 기존 컨테이너의 bind mount 패치 설정은 새 컨테이너에 추가하지 않습니다. 모든 패치는 이미지 안에 포함돼 있습니다. -이미지 버전이 다르면 `main.cjs`의 난독화된 변수명/위치가 달라 이 저장소의 `main.cjs`가 -그대로 안 맞을 수 있습니다. 이 경우 직접 패치해야 합니다: +## 백업 복원 -1. 번역 파일은 위와 동일하게 bind-mount. -2. **컨테이너의 원본(패치 안 된) `main.cjs`를 추출**하고 패치 스크립트 실행: - ```bash - docker create --name trilium-tmp triliumnext/notes:latest - docker cp trilium-tmp:/usr/src/app/main.cjs ./main.cjs - docker rm trilium-tmp - node patch_main_cjs.js ./main.cjs - node --check ./main.cjs # 반드시 배포 전에 문법 검사 - ``` - `[skip]`이 출력되면 스크립트가 찾는 문자열 패턴이 그 빌드에서 바뀐 것이니, 새 빌드에서 - 같은 패턴을 다시 찾아 스크립트를 갱신해야 합니다 (아래 "빌드마다 달라짐" 참고). -3. **패치된 `main.cjs`를 `docker-compose.yml`에서 원본 위치에 bind-mount** — - `docker-compose.bind-mount.yml.example` 참고: - ```yaml - services: - trilium: - image: triliumnext/notes:latest - restart: unless-stopped - ports: - - '127.0.0.1:18082:8080' - environment: - - TZ=Asia/Seoul - volumes: - - ./data:/home/node/trilium-data - - ./main.cjs:/usr/src/app/main.cjs:ro - - ./translation.json:/usr/src/app/public/translations/ko/translation.json:ro - - ./server.json:/usr/src/app/assets/translations/ko/server.json:ro - ``` -4. 컨테이너 시작 후 앱 안에서 **옵션 → 언어 및 지역**에서 "한국어" 선택. +복원 전 현재 컨테이너를 중지하세요. 백업을 새 빈 데이터 폴더에 풀고 `.env`의 데이터 경로를 그 폴더로 바꾸는 방식을 권장합니다. 원래 폴더는 확인이 끝날 때까지 보존하세요. 백업 파일은 컨테이너의 root 권한으로 생성돼 `sudo`가 필요할 수 있습니다. -## 겪었던 문제와 해결 (설치 전에 꼭 읽어보세요) +```bash +docker compose stop trilium +sudo mkdir /srv/trilium-restored +sudo tar -xzpf backups/복원할-백업/data.tar.gz -C /srv/trilium-restored +# .env의 TRILIUM_KO_DATA_DIR을 /srv/trilium-restored로 수정한 뒤 실행 +bash install.sh +``` -### 문제 1 — DB에서 `locale`을 직접 `'ko'`로 바꾸면 크래시 +이전 이미지의 복구용 태그는 `previous-image.txt`에 있으며 원래 ID는 `previous-image-id.txt`에 있습니다. 이미지 복귀만으로 DB 형식이 되돌아가지는 않으므로 다른 버전 사이의 복원에서는 해당 버전의 데이터 백업을 함께 사용하세요. -지원 언어 목록에 없는 값을 옵션 DB에 직접 넣으면 앱이 시작하다가 죽습니다. 이 방법으로는 -안 되고, 반드시 아래처럼 서버 번들 자체를 패치해야 합니다. +## 포함 범위 -### 문제 2 — `main.cjs` 패치 위치를 잘못 잡으면 문법 자체가 깨짐 +| 항목 | 내용 | +|---|---| +| 기반 앱 | Trilium 0.95.0 | +| 기반 이미지 | `triliumnext/notes@sha256:611a430016585d35b170eb9a0fa300ce76318f04a8ec0067549c4c52561b0c36` | +| UI | 한국어 사전과 편집기 및 지도·달력·마인드맵 수정 | +| 도움말 | 본문 173개와 제목 181개 | +| 이미지 설명 | 영문이 감지된 이미지 206개에 한국어 설명 | +| API 참고 화면 | 5개와 Swagger 정적 파일 | +| 신규 기본 예제 | 노트 170개 대응 및 번역 수정 148개와 한국어 PDF | +| 배포 파일 | `release/manifest.json`의 492개 파일 | -지원 언어 배열(테스트한 빌드에서 변수명 `K5i`)에 새 항목을 삽입할 때, 배열의 여는 대괄호 -`[` **바로 뒤**가 아니라 그 앞(변수 선언문 쪽)에 잘못 삽입하면 JS 문법 자체가 깨져서 앱이 -아예 뜨지 못하고 크래시를 반복합니다. `patch_main_cjs.js`는 이 위치를 정확히 계산해서 -삽입하지만, **패치 후에는 항상 `node --check`로 문법을 먼저 확인**하고 나서 컨테이너를 -재시작하세요. +함수 이름과 코드 문법 및 URL과 제품 이름은 원문을 유지합니다. 연결된 외부 사이트 전체를 번역한 것은 아닙니다. 외부 스크립트 API 사본은 운영 버전과 지원 범위가 다를 수 있음을 문서에 표시했습니다. -### 문제 3 — 완전 재생성(`docker compose down && up`) 시에만 나타나는 크래시 +## 검증과 재생성 -지원 언어 배열만 고치면 `docker restart`로는 잘 동작하는 것처럼 보이지만, 컨테이너를 완전히 -내렸다 올리면(`down && up`) 다시 크래시합니다. 원인은 Trilium 자체 번역과는 별개로, -**CKEditor 내장 다국어 리소스를 지연 로드하는 두 번째 하드코딩 맵**(테스트한 빌드에서 -변수명 `IMi`)에도 `ko` 항목이 없어서 발생하는 `TypeError`입니다. 이 리소스는 애초에 -한국어용 청크가 빌드에 포함되어 있지 않아 새로 만들 수 없으므로, `patch_main_cjs.js`는 -이 항목을 영어 로더로 대체(alias)해서 우회합니다. **`restart`뿐 아니라 완전 재생성까지 -반드시 테스트**하세요 — 재시작만으로는 이 문제가 드러나지 않습니다. +검증 결과는 [배포 검증 기록](docs/DEPLOYMENT-TESTS.ko.md)에 있습니다. 배포 파일은 Docker 빌드 중 SHA-256 검사와 JavaScript 구문 검사를 통과해야 합니다. 개발 환경에 Node.js가 있다면 다음 명령으로도 확인할 수 있습니다. -### 문제 4 — 번역이 배포 후 시간이 지나서 "모바일에서만" 다시 영어로 보임 +```bash +node tools/verify-release.mjs +``` -가장 까다로웠던 문제입니다. 번역을 배포하고 정상 동작까지 확인했는데, 이후 **모바일 -기기에서만** 옵션 페이지 등의 본문 텍스트가 다시 영어로 나오는 현상이 발생했습니다 -(페이지 제목이나 "한국어"라는 언어 이름 자체는 정상). 데스크톱에서는 동일 페이지가 -100% 정상이었습니다. +기록된 번역 단계와 `release/demo-ko.zip`에서 배포 트리를 다시 모으려면 `node tools/build-release.mjs`를 실행합니다. 예제 압축 파일 생성 원본과 ID 대응 자료는 `tools/demo-source`에 보관했습니다. 과거 일회성 운영 DB 마이그레이션 코드는 일반 배포 번들에서 제거했습니다. -처음엔 모바일 브라우저 캐시 문제로 의심했지만, 캐시를 초기화하고 서로 다른 브라우저 -엔진(Chrome, 삼성인터넷, 네이버) 세 개로 테스트해도 완전히 동일한 증상이 재현되어 -캐시 이론은 기각했습니다. - -**진짜 원인**: 번역 파일(`translation.json`, `server.json`)을 `docker cp`로 컨테이너 -내부에 직접 복사만 하고 `docker-compose.yml`에는 bind-mount로 등록하지 않았던 것이 -원인이었습니다. `docker cp`로 넣은 파일은 컨테이너의 쓰기 가능 레이어에만 존재하기 때문에, -이후 `main.cjs` 패치가 완전 재생성에도 살아남는지 테스트하려고 `docker compose down && up`을 -실행했을 때 번역 파일 두 개가 컨테이너와 함께 통째로 사라졌습니다 (bind-mount 되어 있던 -`main.cjs`만 살아남음). 서버가 `translations/ko/*.json` 요청에 404를 반환하기 시작했고, -i18next의 `fallbackLng:"en"` 설정 때문에 본문 텍스트가 조용히 영어로 대체됐습니다. -"한국어"라는 언어 이름만 정상이었던 이유는, 그 값이 이 JSON 파일이 아니라 별도의 DB 기반 -API(`options/locales`)에서 오기 때문에 영향을 받지 않았던 것입니다. - -데스크톱이 여전히 정상으로 보였던 이유는 단순히 파일이 사라지기 전에 브라우저가 이미 -받아둔 번역 응답을 캐시하고 있었기 때문입니다 — 즉 데스크톱 쪽이 오히려 "낡은 캐시를 -보여주던 쪽"이었고, 매번 새로 서버에 요청하는 모바일 쪽이 서버의 실제(망가진) 상태를 -정확히 반영하고 있었던 것입니다. 세 개의 다른 모바일 브라우저에서 전부 동일한 증상이 -나온 것도 이걸로 설명됩니다 — 캐시 종류와 무관하게 서버에 파일 자체가 없었으니까요. - -**교훈**: `docker cp`로 컨테이너 안에 넣은 파일은 컨테이너가 사라지면 함께 사라집니다. -번역 파일도 `main.cjs`와 마찬가지로 **반드시 `docker-compose.yml`의 `volumes:`에 -bind-mount로 선언**하세요 (위 설치 방법 3번, `docker-compose.yml.example` 참고). 그리고 -증상이 "특정 기기에서만 재현됨", "캐시를 지워도 재현됨"처럼 보이더라도, 실제 원인은 -클라이언트가 아니라 서버 쪽 데이터 유실일 수 있으므로 클라이언트 가설을 세우기 전에 -서버가 실제로 무엇을 응답하는지(`curl`로 정확한 URL 직접 확인)부터 검증하는 게 우선입니다. - -## 이전 배포판의 미해결 항목 — CKEditor 자체 툴바 - -2026-09-05 후속 패치에서는 한국어 사전 719개를 적용하고 운영 화면을 확인했습니다. 다음 문단은 이전 배포판의 기록입니다. - -CKEditor5 자체의 UI 문자열(툴바 버튼 이름 — "Paragraph", "Heading 2", "Bold" 등)은 -이 프로젝트가 건드리는 번역 시스템과 완전히 별개인 `window.CKEDITOR_TRANSLATIONS`라는 -자체 시스템에서 옵니다. 테스트한 빌드 기준으로, 독일어·프랑스어·스페인어·중국어를 -포함해 이미 "지원"되는 언어 **어느 것도** 실제 CKEditor 사전을 갖고 있지 않아서 전부 -영어 툴바로 나옵니다 — 한국어만의 문제가 아니라 업스트림 빌드 자체에 이미 있던 공백입니다. - -## 라이선스 - -TriliumNext Notes 본체와 동일한 라이선스를 따릅니다. 무보증 — 이 프로젝트는 컴파일된 -바이너리를 난독화된 변수명 문자열 매칭 방식으로 패치하는 것이라, 버전이 올라가면 -깨지기 쉬운 구조입니다. +`legacy/v1`과 `patch-only` 및 기존 v1.0.0 첨부 파일은 과거 배포판입니다. 신규 설치에는 이 문서와 루트의 Dockerfile·설치 스크립트를 사용하세요. 상세 번역 내역은 [변경 기록](updates/2026-09-05/CHANGELOG.ko.md)을 참고하세요. diff --git a/docker-compose.yml b/docker-compose.yml index 3c2050b..b33f4f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,11 +1,11 @@ services: trilium: build: . - container_name: trilium-ko + image: ${TRILIUM_KO_IMAGE:-trilium-korean:2.0.0} restart: unless-stopped ports: - - '8082:8080' + - '${TRILIUM_KO_BIND:-127.0.0.1}:${TRILIUM_KO_PORT:-8082}:8080' environment: - TZ=Asia/Seoul volumes: - - ./data:/home/node/trilium-data + - ${TRILIUM_KO_DATA_DIR:-./data}:/home/node/trilium-data diff --git a/docs/DEPLOYMENT-TESTS.ko.md b/docs/DEPLOYMENT-TESTS.ko.md new file mode 100644 index 0000000..5826e8f --- /dev/null +++ b/docs/DEPLOYMENT-TESTS.ko.md @@ -0,0 +1,42 @@ +# 한국어 배포판 2.0.0 검증 기록 + +검사일: 2026-09-13. Linux x86_64 서버의 Docker Engine 29.7.2와 Compose 5.5.0에서 검사했습니다. ARM과 다른 Trilium 버전으로의 업그레이드는 검사 범위에 포함하지 않습니다. + +운영 컨테이너와 분리된 Compose 프로젝트를 사용했습니다. 포트는 서버의 루프백 주소 19092와 19093만 사용했으며 테스트 전용 새 데이터 폴더에서 검사했습니다. + +| 검사 | 결과 | +|---|---| +| 고정된 공식 이미지에서 Docker 빌드 | 통과 | +| 이미지 내부 492개 파일 SHA-256 검사 | 통과 | +| 서버 번들 JavaScript 구문 검사 | 통과 | +| 설치 스크립트로 새 컨테이너 생성 | 통과 | +| 새 문서 생성과 기본 예제 가져오기 | HTTP 204 | +| 한국어 PDF 내용 검사 | 지정한 SHA-256과 일치 | +| 도움말 노트 생성 | 181개 | +| 내부 노트 링크 검사 | 끊어진 링크 0개 | +| 동일 설치의 재실행과 자동 백업 | 통과 | +| 공식 0.95.0 이미지에서 한국어 이미지로 전환 | 통과 | +| 업데이트 전후 노트 상태 비교 | 동일 | +| 종료 코드 42로 실패하는 이미지 배포 시험 | 실패를 감지하고 이전 이미지로 복귀 | +| 백업을 새 폴더에 복원 | 노트 상태 동일 | +| 복원한 데이터로 별도 컨테이너 기동 | 통과 | +| 실제 HTTP의 편집기 및 문서 파일 8개 | 배포 파일과 해시 일치 | +| Swagger 문서 경로 2개 | 정상 표시 파일 제공 | + +업데이트와 복구 과정에서 비교한 활성 노트는 417개입니다. 노트 ID와 제목 및 본문 blobId 목록의 SHA-256은 `3441f91b417ce62fff0b7a9c04d5b5e3262c284ff53edf3bffe92dc690c815ff`입니다. + +한국어 PDF의 SHA-256은 `1141ea4fb9d619fd55d75d0bdcd6bbd5678b161633586764d0eadfc4b9235400`입니다. 신규 예제 압축 파일은 원본 노트 170개를 제목 경로로 대응시켜 만들었습니다. 148개 노트의 번역 수정과 통계 표시 및 속성 이름과 할 일 접두사 및 PDF를 포함합니다. 원본의 폴더 항목과 가져오기 순서도 보존했습니다. + +일반 배포용 main.cjs의 SHA-256은 `d0dd274cc5ad926e8f9297bb0bd2ae806227dae686983bf76550dc2b3fed642f`입니다. 운영 서버에 사용했던 일회성 노트 마이그레이션 함수와 호출을 제거했으므로 운영 서버의 main.cjs와 해시가 다른 것이 정상입니다. + +## 시험 중 발견하고 수정한 사항 + +첫 예제 압축본은 폴더 항목이 빠져 일부 상위 노트를 생성하지 못했습니다. 원본 ZIP의 디렉토리 항목과 순서를 보존하도록 고친 뒤 완전히 새로운 데이터 폴더에서 새 문서 생성과 링크 검사를 다시 통과했습니다. + +첫 실패 복귀 시험에서는 Docker가 재빌드 후 이전 이미지 다이제스트를 찾지 못했습니다. 새 빌드 전에 이전 이미지에 고유한 복구 태그를 붙이도록 변경했습니다. 수정 후 고의 실패를 다시 일으켜 이전 이미지와 기동 상태가 복구되는 것을 확인했습니다. + +## 적용 범위 + +이 기록은 위 고정 버전과 환경에서 실제 수행한 검사 결과입니다. 새 설치와 공식 0.95.0에서의 전환 및 재설치 경로를 확인했습니다. 최신 Trilium 버전의 DB를 0.95.0으로 내리는 작업을 보장하지 않습니다. 기존 노트 본문을 자동으로 다시 번역하는 기능은 설치 프로그램에 넣지 않았습니다. + +원시 검사 결과는 `test-results`에 있으며 검사에 사용한 스크립트는 `tools/test-database.py`와 `tools/test-release-recovery.py`에 있습니다. 이 스크립트들은 운영 DB 오작동을 막기 위해 당시 테스트 경로만 허용합니다. 일반 설치에는 이 검사 스크립트가 필요하지 않습니다. diff --git a/docs/test-results/before-update.json b/docs/test-results/before-update.json new file mode 100644 index 0000000..d95e33e --- /dev/null +++ b/docs/test-results/before-update.json @@ -0,0 +1 @@ +{"activeNotes": 417, "koreanTitles": 319, "helpNotes": 181, "koreanPdf": true, "danglingInternalLinks": 0, "noteSnapshotSha256": "3441f91b417ce62fff0b7a9c04d5b5e3262c284ff53edf3bffe92dc690c815ff"} \ No newline at end of file diff --git a/docs/test-results/deployment-result.json b/docs/test-results/deployment-result.json new file mode 100644 index 0000000..5eb0a61 --- /dev/null +++ b/docs/test-results/deployment-result.json @@ -0,0 +1,15 @@ +{ + "status": "passed", + "newInstall": true, + "initialDocumentCreationStatus": 204, + "official095Upgrade": true, + "repeatInstall": true, + "httpAssetChecks": 8, + "swaggerChecks": 2, + "dataSnapshotUnchanged": true, + "release": "2.0.0", + "appVersion": "0.95.0", + "engine": "29.7.2", + "compose": "5.5.0", + "platform": "linux/amd64" +} \ No newline at end of file diff --git a/docs/test-results/recovery-result.json b/docs/test-results/recovery-result.json new file mode 100644 index 0000000..ad35e23 --- /dev/null +++ b/docs/test-results/recovery-result.json @@ -0,0 +1,8 @@ +{ + "forcedFailureRejected": true, + "previousImageRestored": true, + "backupDataMatched": true, + "restoredContainerStarted": true, + "backup": "/tmp/trilium-release-test-20260913-r1/backups/20260913T094924Z-414939/data.tar.gz", + "restoredNoteSnapshotSha256": "3441f91b417ce62fff0b7a9c04d5b5e3262c284ff53edf3bffe92dc690c815ff" +} \ No newline at end of file diff --git a/install.sh b/install.sh index 779d2ae..cb6260c 100755 --- a/install.sh +++ b/install.sh @@ -1,46 +1,20 @@ #!/usr/bin/env bash -# TriliumNext Notes 한국어 패치 — 원클릭 설치 스크립트 -# -# 사용법: -# curl -fsSL https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/raw/branch/main/install.sh | bash -# 또는 저장소를 직접 clone 한 뒤: -# ./install.sh [설치 폴더 이름, 기본값: trilium-korean] set -euo pipefail - -REPO_URL="https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch.git" -INSTALL_DIR="${1:-trilium-korean}" -PORT="${TRILIUM_KO_PORT:-8082}" - -if ! command -v docker >/dev/null 2>&1; then - echo "Docker가 설치되어 있지 않습니다. https://docs.docker.com/get-docker/ 를 먼저 설치하세요." >&2 - exit 1 -fi - -if ! docker compose version >/dev/null 2>&1; then - echo "Docker Compose 플러그인이 필요합니다 (docker compose, 하이픈 없는 버전)." >&2 - exit 1 -fi - -if [ -d "$INSTALL_DIR/.git" ]; then - echo "이미 설치되어 있습니다. 최신 패치로 업데이트합니다: $INSTALL_DIR" - git -C "$INSTALL_DIR" pull --ff-only +REPO_URL='https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch.git' +source_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]:-.}")" 2>/dev/null && pwd || pwd)" +if [[ $# -eq 0 && -f "$source_dir/release/manifest.json" ]]; then + install_dir="$source_dir" else - echo "저장소를 내려받습니다: $INSTALL_DIR" - git clone --depth 1 "$REPO_URL" "$INSTALL_DIR" + install_dir="${1:-trilium-korean}" + command -v git >/dev/null || { echo 'Git을 먼저 설치하세요.' >&2; exit 1; } + if [[ -d "$install_dir/.git" ]]; then + [[ -z "$(git -C "$install_dir" status --porcelain)" ]] || { echo '설치 폴더에 수정한 파일이 있습니다. 먼저 보관하거나 커밋하세요.' >&2; exit 1; } + git -C "$install_dir" pull --ff-only + elif [[ -e "$install_dir" ]]; then + echo '설치 대상 폴더가 이미 있습니다. 저장소 폴더에서 인수 없이 실행하거나 빈 경로를 지정하세요.' >&2; exit 1 + else + git clone "$REPO_URL" "$install_dir" + fi fi - -cd "$INSTALL_DIR" - -if [ "$PORT" != "8082" ]; then - sed -i.bak "s/'8082:8080'/'${PORT}:8080'/" docker-compose.yml -fi - -echo "이미지를 빌드하고 컨테이너를 시작합니다 (최초 실행 시 몇 분 걸릴 수 있습니다)..." -docker compose up -d --build - -echo -echo "설치 완료! http://localhost:${PORT} 로 접속하세요." -echo "처음 접속하면 초기 설정(마스터 비밀번호) 화면이 뜹니다." -echo "설정이 끝나면 옵션 → 언어 및 지역에서 '한국어'를 선택하세요." -echo -echo "업데이트하려면 이 스크립트를 같은 폴더 이름으로 다시 실행하면 됩니다: $INSTALL_DIR" +cd -- "$install_dir" +exec bash tools/deploy.sh diff --git a/legacy/v1/README.md b/legacy/v1/README.md new file mode 100644 index 0000000..14b2b23 --- /dev/null +++ b/legacy/v1/README.md @@ -0,0 +1,197 @@ +# TriliumNext Notes 한국어 패치 (번역 + main.cjs 패치) + +최신 진행 상황: [2026-09-13 작업 기록](updates/2026-09-05/PROGRESS.md). 도움말 본문 173개와 제목 181개를 운영 서버에 반영했습니다. 전체 한글화는 추가 점검 중입니다. + +## 2026-09-05 후속 작업 + +[최신 작업 상태와 파일](updates/2026-09-05/README.md) 및 [상세 변경 기록](updates/2026-09-05/CHANGELOG.ko.md)을 추가했습니다. 운영 서버에는 예제 노트 148개 수정과 편집기 한국어 사전 719개 문구 등을 반영했습니다. 2026-09-13에 기본 도움말 전체와 목록 제목을 서버에 반영했습니다. 전체 한글화는 진행 중입니다. + +아래의 기존 설치 안내와 v1.0.0 다운로드는 이전 배포판에 대한 설명입니다. 이번 작업 폴더의 파일은 기존 설치 프로그램에 자동으로 포함되지 않습니다. + +[TriliumNext Notes](https://github.com/TriliumNext/Notes)의 비공식 커뮤니티 한국어 번역입니다. +이 글을 쓰는 시점 기준으로 TriliumNext는 한국어 언어팩이 없고, 심지어 UI 언어 선택기에 +뜨는 지원 언어 목록 자체가 `translations/` 폴더를 스캔해서 만들어지는 게 아니라 **컴파일된 +서버 번들(`main.cjs`) 안에 하드코딩된 배열**이라서, 번역 파일만 올바른 경로에 넣는다고 +"한국어"가 언어 선택기에 나타나지 않습니다. 그래서 번역 파일 외에 서버 번들을 패치하는 +스크립트도 함께 제공합니다. + +## 압축 파일로 받기 + +Git 없이 필요한 파일만 바로 받고 싶다면 압축된 배포판을 받으세요. 두 종류가 있습니다 +([릴리스 페이지](https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/releases/tag/v1.0.0)): + +- **[triliumnext-korean-patch.zip 다운로드](https://gitea.itosm.co.kr/attachments/11f09ff6-4d85-4234-8360-a4ae968dd437)** + (2.5MB) — **처음 새로 설치하는 경우.** `Dockerfile`, `install.sh`, `docker-compose.yml`까지 + 전부 포함되어 있어서, 압축을 풀고 `./install.sh`를 실행하거나 `docker compose up -d --build`를 + 실행하면 한국어가 내장된 새 컨테이너가 만들어집니다. +- **[triliumnext-korean-patch-only.zip 다운로드](https://gitea.itosm.co.kr/attachments/679762e6-8b68-48e4-9954-82a2163750a8)** + (2.4MB) — **이미 Trilium을 운영 중인 경우.** 이미지를 새로 빌드하거나 컨테이너를 새로 + 만들지 않고, 기존 데이터/설정을 그대로 둔 채 파일 3개만 bind-mount로 추가합니다. + 압축 안의 `README.md`에 기존 `docker-compose.yml`에 반영하는 방법이 자세히 적혀 있습니다. + +## 포함된 파일 + +- `install.sh` — **원클릭 설치 스크립트**. 명령어 한 줄로 저장소를 내려받고, 한국어가 + 내장된 이미지를 빌드해서 바로 실행시킵니다. +- `Dockerfile` — `triliumnext/notes:latest` 위에 번역 파일과 패치된 `main.cjs`를 + 구워 넣어서, 별도 bind-mount 없이 한국어가 기본 내장된 이미지를 만듭니다. +- `docker-compose.yml` — 위 `Dockerfile`로 빌드해서 바로 띄우는 compose 파일 + (`install.sh`가 내부적으로 이걸 사용합니다). +- `translation.json` — 클라이언트(브라우저) UI 문자열, 1,712개 키, 100% 번역 완료. +- `server.json` — 서버 문자열, 283개 키, 100% 번역 완료. +- `main.cjs` — **이미 패치가 적용된, 바로 쓸 수 있는 서버 번들** (`triliumnext/notes:latest`, + 빌드일 2025-06-07, appVersion 0.95.0 기준). +- `patch_main_cjs.js` — 위 `main.cjs`를 만들어낸 패치 스크립트. 다른 버전의 이미지를 쓰거나 + 이미지가 업데이트된 경우, 이 스크립트를 새 원본 `main.cjs`에 다시 돌려서 직접 패치된 + 파일을 만들어야 합니다 (왜 이게 필요한지는 스크립트 상단 주석 참고). +- `docker-compose.bind-mount.yml.example` — 이미 떠 있는 공식 이미지 컨테이너에 파일만 + bind-mount로 추가하고 싶을 때 쓰는 예시 (이미지를 새로 빌드하지 않는 방식). + +`triliumnext/notes:latest` (빌드일 2025-06-07, appVersion 0.95.0) 기준으로 테스트했습니다. +`main.cjs` 안의 변수명은 전부 난독화(minify)되어 있고 **빌드마다 이름이 바뀔 수 있습니다** — +`patch_main_cjs.js`를 새 이미지에 돌렸을 때 `[skip]`이 출력되면, 스크립트가 찾는 문자열 +패턴이 그 빌드에서 바뀐 것이니 새 빌드에서 같은 패턴을 다시 찾아 스크립트를 갱신해야 합니다. + +## 설치 방법 — 명령어 한 줄 (추천) + +Docker와 Docker Compose 플러그인만 설치되어 있으면 됩니다: + +```bash +curl -fsSL https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/raw/branch/main/install.sh | bash +``` + +기본적으로 `./trilium-korean` 폴더에 저장소를 내려받고, 한국어가 내장된 이미지를 빌드해서 +`http://localhost:8082`로 띄웁니다. 포트를 바꾸고 싶으면: + +```bash +TRILIUM_KO_PORT=9000 curl -fsSL https://gitea.itosm.co.kr/syskiller/triliumnext-korean-patch/raw/branch/main/install.sh | bash +``` + +설치가 끝나면 브라우저로 접속해서 초기 비밀번호를 설정한 뒤, **옵션 → 언어 및 지역**에서 +"한국어"를 선택하고 페이지를 새로고침하면 됩니다 (본문 텍스트까지 전부 한국어로 바뀌려면 +새로고침이 한 번 필요합니다 — 앱 자체의 동작이며 이 패치의 문제는 아닙니다). + +업데이트하려면 같은 명령어를 같은 폴더에서 다시 실행하면 됩니다. + +## 설치 방법 — 이미 떠 있는 컨테이너에 추가하고 싶은 경우 + +이미지를 새로 빌드하지 않고, 이미 쓰고 있는 공식 `triliumnext/notes` 컨테이너에 파일만 +얹고 싶다면: + +1. **번역 파일 + `main.cjs`를 `docker-compose.yml`에 bind-mount로 등록** + (`docker cp`로만 넣지 말 것 — 아래 "문제 4" 참고): + - `main.cjs` → `/usr/src/app/main.cjs` + - `translation.json` → `/usr/src/app/public/translations/ko/translation.json` + - `server.json` → `/usr/src/app/assets/translations/ko/server.json` +2. `docker-compose.bind-mount.yml.example`을 참고해서 그대로 적용, 컨테이너 재시작. +3. 앱 안에서 **옵션 → 언어 및 지역**에서 "한국어" 선택 후 새로고침. + +## 설치 방법 — 다른 이미지 버전을 쓰는 경우 (직접 패치) + +이미지 버전이 다르면 `main.cjs`의 난독화된 변수명/위치가 달라 이 저장소의 `main.cjs`가 +그대로 안 맞을 수 있습니다. 이 경우 직접 패치해야 합니다: + +1. 번역 파일은 위와 동일하게 bind-mount. +2. **컨테이너의 원본(패치 안 된) `main.cjs`를 추출**하고 패치 스크립트 실행: + ```bash + docker create --name trilium-tmp triliumnext/notes:latest + docker cp trilium-tmp:/usr/src/app/main.cjs ./main.cjs + docker rm trilium-tmp + node patch_main_cjs.js ./main.cjs + node --check ./main.cjs # 반드시 배포 전에 문법 검사 + ``` + `[skip]`이 출력되면 스크립트가 찾는 문자열 패턴이 그 빌드에서 바뀐 것이니, 새 빌드에서 + 같은 패턴을 다시 찾아 스크립트를 갱신해야 합니다 (아래 "빌드마다 달라짐" 참고). +3. **패치된 `main.cjs`를 `docker-compose.yml`에서 원본 위치에 bind-mount** — + `docker-compose.bind-mount.yml.example` 참고: + ```yaml + services: + trilium: + image: triliumnext/notes:latest + restart: unless-stopped + ports: + - '127.0.0.1:18082:8080' + environment: + - TZ=Asia/Seoul + volumes: + - ./data:/home/node/trilium-data + - ./main.cjs:/usr/src/app/main.cjs:ro + - ./translation.json:/usr/src/app/public/translations/ko/translation.json:ro + - ./server.json:/usr/src/app/assets/translations/ko/server.json:ro + ``` +4. 컨테이너 시작 후 앱 안에서 **옵션 → 언어 및 지역**에서 "한국어" 선택. + +## 겪었던 문제와 해결 (설치 전에 꼭 읽어보세요) + +### 문제 1 — DB에서 `locale`을 직접 `'ko'`로 바꾸면 크래시 + +지원 언어 목록에 없는 값을 옵션 DB에 직접 넣으면 앱이 시작하다가 죽습니다. 이 방법으로는 +안 되고, 반드시 아래처럼 서버 번들 자체를 패치해야 합니다. + +### 문제 2 — `main.cjs` 패치 위치를 잘못 잡으면 문법 자체가 깨짐 + +지원 언어 배열(테스트한 빌드에서 변수명 `K5i`)에 새 항목을 삽입할 때, 배열의 여는 대괄호 +`[` **바로 뒤**가 아니라 그 앞(변수 선언문 쪽)에 잘못 삽입하면 JS 문법 자체가 깨져서 앱이 +아예 뜨지 못하고 크래시를 반복합니다. `patch_main_cjs.js`는 이 위치를 정확히 계산해서 +삽입하지만, **패치 후에는 항상 `node --check`로 문법을 먼저 확인**하고 나서 컨테이너를 +재시작하세요. + +### 문제 3 — 완전 재생성(`docker compose down && up`) 시에만 나타나는 크래시 + +지원 언어 배열만 고치면 `docker restart`로는 잘 동작하는 것처럼 보이지만, 컨테이너를 완전히 +내렸다 올리면(`down && up`) 다시 크래시합니다. 원인은 Trilium 자체 번역과는 별개로, +**CKEditor 내장 다국어 리소스를 지연 로드하는 두 번째 하드코딩 맵**(테스트한 빌드에서 +변수명 `IMi`)에도 `ko` 항목이 없어서 발생하는 `TypeError`입니다. 이 리소스는 애초에 +한국어용 청크가 빌드에 포함되어 있지 않아 새로 만들 수 없으므로, `patch_main_cjs.js`는 +이 항목을 영어 로더로 대체(alias)해서 우회합니다. **`restart`뿐 아니라 완전 재생성까지 +반드시 테스트**하세요 — 재시작만으로는 이 문제가 드러나지 않습니다. + +### 문제 4 — 번역이 배포 후 시간이 지나서 "모바일에서만" 다시 영어로 보임 + +가장 까다로웠던 문제입니다. 번역을 배포하고 정상 동작까지 확인했는데, 이후 **모바일 +기기에서만** 옵션 페이지 등의 본문 텍스트가 다시 영어로 나오는 현상이 발생했습니다 +(페이지 제목이나 "한국어"라는 언어 이름 자체는 정상). 데스크톱에서는 동일 페이지가 +100% 정상이었습니다. + +처음엔 모바일 브라우저 캐시 문제로 의심했지만, 캐시를 초기화하고 서로 다른 브라우저 +엔진(Chrome, 삼성인터넷, 네이버) 세 개로 테스트해도 완전히 동일한 증상이 재현되어 +캐시 이론은 기각했습니다. + +**진짜 원인**: 번역 파일(`translation.json`, `server.json`)을 `docker cp`로 컨테이너 +내부에 직접 복사만 하고 `docker-compose.yml`에는 bind-mount로 등록하지 않았던 것이 +원인이었습니다. `docker cp`로 넣은 파일은 컨테이너의 쓰기 가능 레이어에만 존재하기 때문에, +이후 `main.cjs` 패치가 완전 재생성에도 살아남는지 테스트하려고 `docker compose down && up`을 +실행했을 때 번역 파일 두 개가 컨테이너와 함께 통째로 사라졌습니다 (bind-mount 되어 있던 +`main.cjs`만 살아남음). 서버가 `translations/ko/*.json` 요청에 404를 반환하기 시작했고, +i18next의 `fallbackLng:"en"` 설정 때문에 본문 텍스트가 조용히 영어로 대체됐습니다. +"한국어"라는 언어 이름만 정상이었던 이유는, 그 값이 이 JSON 파일이 아니라 별도의 DB 기반 +API(`options/locales`)에서 오기 때문에 영향을 받지 않았던 것입니다. + +데스크톱이 여전히 정상으로 보였던 이유는 단순히 파일이 사라지기 전에 브라우저가 이미 +받아둔 번역 응답을 캐시하고 있었기 때문입니다 — 즉 데스크톱 쪽이 오히려 "낡은 캐시를 +보여주던 쪽"이었고, 매번 새로 서버에 요청하는 모바일 쪽이 서버의 실제(망가진) 상태를 +정확히 반영하고 있었던 것입니다. 세 개의 다른 모바일 브라우저에서 전부 동일한 증상이 +나온 것도 이걸로 설명됩니다 — 캐시 종류와 무관하게 서버에 파일 자체가 없었으니까요. + +**교훈**: `docker cp`로 컨테이너 안에 넣은 파일은 컨테이너가 사라지면 함께 사라집니다. +번역 파일도 `main.cjs`와 마찬가지로 **반드시 `docker-compose.yml`의 `volumes:`에 +bind-mount로 선언**하세요 (위 설치 방법 3번, `docker-compose.yml.example` 참고). 그리고 +증상이 "특정 기기에서만 재현됨", "캐시를 지워도 재현됨"처럼 보이더라도, 실제 원인은 +클라이언트가 아니라 서버 쪽 데이터 유실일 수 있으므로 클라이언트 가설을 세우기 전에 +서버가 실제로 무엇을 응답하는지(`curl`로 정확한 URL 직접 확인)부터 검증하는 게 우선입니다. + +## 이전 배포판의 미해결 항목 — CKEditor 자체 툴바 + +2026-09-05 후속 패치에서는 한국어 사전 719개를 적용하고 운영 화면을 확인했습니다. 다음 문단은 이전 배포판의 기록입니다. + +CKEditor5 자체의 UI 문자열(툴바 버튼 이름 — "Paragraph", "Heading 2", "Bold" 등)은 +이 프로젝트가 건드리는 번역 시스템과 완전히 별개인 `window.CKEDITOR_TRANSLATIONS`라는 +자체 시스템에서 옵니다. 테스트한 빌드 기준으로, 독일어·프랑스어·스페인어·중국어를 +포함해 이미 "지원"되는 언어 **어느 것도** 실제 CKEditor 사전을 갖고 있지 않아서 전부 +영어 툴바로 나옵니다 — 한국어만의 문제가 아니라 업스트림 빌드 자체에 이미 있던 공백입니다. + +## 라이선스 + +TriliumNext Notes 본체와 동일한 라이선스를 따릅니다. 무보증 — 이 프로젝트는 컴파일된 +바이너리를 난독화된 변수명 문자열 매칭 방식으로 패치하는 것이라, 버전이 올라가면 +깨지기 쉬운 구조입니다. diff --git a/docker-compose.bind-mount.yml.example b/legacy/v1/docker-compose.bind-mount.yml.example similarity index 100% rename from docker-compose.bind-mount.yml.example rename to legacy/v1/docker-compose.bind-mount.yml.example diff --git a/main.cjs b/legacy/v1/main.cjs similarity index 100% rename from main.cjs rename to legacy/v1/main.cjs diff --git a/patch_main_cjs.js b/legacy/v1/patch_main_cjs.js similarity index 100% rename from patch_main_cjs.js rename to legacy/v1/patch_main_cjs.js diff --git a/server.json b/legacy/v1/server.json similarity index 100% rename from server.json rename to legacy/v1/server.json diff --git a/translation.json b/legacy/v1/translation.json similarity index 100% rename from translation.json rename to legacy/v1/translation.json diff --git a/release/app/assets/db/demo.zip b/release/app/assets/db/demo.zip new file mode 100644 index 0000000..decc2ad Binary files /dev/null and b/release/app/assets/db/demo.zip differ diff --git a/release/app/assets/doc_notes/en/User Guide/!!!meta.json b/release/app/assets/doc_notes/en/User Guide/!!!meta.json new file mode 100644 index 0000000..21ec97a --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/!!!meta.json @@ -0,0 +1,3087 @@ +[ + { + "id": "_help_Otzi9La2YAUX", + "title": "설치와 설정", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-cog", + "type": "label" + } + ], + "children": [ + { + "id": "_help_poXkQfguuA0U", + "title": "데스크톱 설치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Desktop Installation" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_WOcw2SLH6tbX", + "title": "서버 설치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ], + "children": [ + { + "id": "_help_Dgg7bR3b6K9j", + "title": "1. 서버 설치", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-folder", + "type": "label" + } + ], + "children": [ + { + "id": "_help_3tW6mORuTHnB", + "title": "Linux 패키지 설치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux" + }, + { + "name": "iconClass", + "value": "bx bxl-tux", + "type": "label" + } + ] + }, + { + "id": "_help_rWX5eY045zbE", + "title": "Docker로 설치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker" + }, + { + "name": "iconClass", + "value": "bx bxl-docker", + "type": "label" + } + ] + }, + { + "id": "_help_moVgBcoxE3EK", + "title": "NixOS에 설치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS" + }, + { + "name": "iconClass", + "value": "bx bxl-tux", + "type": "label" + } + ] + }, + { + "id": "_help_J1Bb6lVlwU5T", + "title": "직접 설치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually" + }, + { + "name": "iconClass", + "value": "bx bx-code-alt", + "type": "label" + } + ] + }, + { + "id": "_help_DCmT6e7clMoP", + "title": "Kubernetes로 설치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes" + }, + { + "name": "iconClass", + "value": "bx bxl-kubernetes", + "type": "label" + } + ] + }, + { + "id": "_help_klCWNks3ReaQ", + "title": "여러 서버 인스턴스", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances" + }, + { + "name": "iconClass", + "value": "bx bxs-user-account", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_vcjrb3VVYPZI", + "title": "2. 리버스 프록시", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-folder", + "type": "label" + } + ], + "children": [ + { + "id": "_help_ud6MShXL4WpO", + "title": "Nginx 설정", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_fDLvzOx29Pfg", + "title": "Apache 설정", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_l2VkvOwUNfZj", + "title": "TLS 설정", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/TLS Configuration" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_0hzsNCP31IAB", + "title": "인증", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/Authentication" + }, + { + "name": "iconClass", + "value": "bx bx-lock-alt", + "type": "label" + } + ] + }, + { + "id": "_help_7DAiwaf8Z7Rz", + "title": "다중 인증", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication" + }, + { + "name": "iconClass", + "value": "bx bx-stopwatch", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_cbkrhQjrkKrh", + "title": "동기화", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Synchronization" + }, + { + "name": "iconClass", + "value": "bx bx-sync", + "type": "label" + } + ] + }, + { + "id": "_help_RDslemsQ6gCp", + "title": "모바일 화면", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Mobile Frontend" + }, + { + "name": "iconClass", + "value": "bx bx-mobile-alt", + "type": "label" + } + ] + }, + { + "id": "_help_MtPxeAWVAzMg", + "title": "웹 클리퍼", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Web Clipper" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_n1lujUxCwipy", + "title": "TriliumNext 업데이트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Upgrading TriliumNext" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_ODY7qQn5m2FT", + "title": "백업", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Backup" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_tAassRL4RSQL", + "title": "데이터 폴더", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Installation & Setup/Data directory" + }, + { + "name": "iconClass", + "value": "bx bx-folder-open", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_gh7bpGYxajRS", + "title": "기본 개념과 기능", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-help-circle", + "type": "label" + } + ], + "children": [ + { + "id": "_help_Vc8PjrjAGuOp", + "title": "화면 구성 요소", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-window-alt", + "type": "label" + } + ], + "children": [ + { + "id": "_help_x0JgW8UqGXvq", + "title": "세로 배치와 가로 배치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout" + }, + { + "name": "iconClass", + "value": "bx bxs-layout", + "type": "label" + } + ] + }, + { + "id": "_help_x3i7MxGccDuM", + "title": "전체 메뉴", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu" + }, + { + "name": "iconClass", + "value": "bx bx-menu", + "type": "label" + } + ] + }, + { + "id": "_help_oPVyFC7WL2Lp", + "title": "노트 트리", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree" + }, + { + "name": "iconClass", + "value": "bx bxs-tree-alt", + "type": "label" + } + ], + "children": [ + { + "id": "_help_YtSN43OrfzaA", + "title": "노트 트리 메뉴", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu" + }, + { + "name": "iconClass", + "value": "bx bx-menu", + "type": "label" + } + ] + }, + { + "id": "_help_yTjUdsOi4CIE", + "title": "여러 노트 선택", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection" + }, + { + "name": "iconClass", + "value": "bx bx-list-plus", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_BlN9DFI679QC", + "title": "상단 리본", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon" + }, + { + "name": "iconClass", + "value": "bx bx-dots-horizontal", + "type": "label" + } + ] + }, + { + "id": "_help_3seOhtN8uLIY", + "title": "탭", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs" + }, + { + "name": "iconClass", + "value": "bx bx-dock-top", + "type": "label" + } + ] + }, + { + "id": "_help_xYmIYSP6wE3F", + "title": "실행 도구 모음", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar" + }, + { + "name": "iconClass", + "value": "bx bx-sidebar", + "type": "label" + } + ] + }, + { + "id": "_help_8YBEPzcpUgxw", + "title": "노트 버튼", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons" + }, + { + "name": "iconClass", + "value": "bx bx-dots-vertical-rounded", + "type": "label" + } + ] + }, + { + "id": "_help_4TIF1oA4VQRO", + "title": "설정", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Options" + }, + { + "name": "iconClass", + "value": "bx bx-cog", + "type": "label" + } + ] + }, + { + "id": "_help_luNhaphA37EO", + "title": "분할 보기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View" + }, + { + "name": "iconClass", + "value": "bx bx-dock-right", + "type": "label" + } + ] + }, + { + "id": "_help_XpOYSgsLkTJy", + "title": "떠 있는 버튼", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons" + }, + { + "name": "iconClass", + "value": "bx bx-rectangle", + "type": "label" + } + ] + }, + { + "id": "_help_RnaPdbciOfeq", + "title": "오른쪽 사이드바", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar" + }, + { + "name": "iconClass", + "value": "bx bxs-dock-right", + "type": "label" + } + ] + }, + { + "id": "_help_r5JGHN99bVKn", + "title": "최근 변경 사항", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes" + }, + { + "name": "iconClass", + "value": "bx bx-history", + "type": "label" + } + ] + }, + { + "id": "_help_ny318J39E5Z0", + "title": "화면 확대와 축소", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom" + }, + { + "name": "iconClass", + "value": "bx bx-zoom-in", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_BFs8mudNFgCS", + "title": "노트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes" + }, + { + "name": "iconClass", + "value": "bx bx-notepad", + "type": "label" + } + ], + "children": [ + { + "id": "_help_p9kXRFAkwN4o", + "title": "노트 아이콘", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons" + }, + { + "name": "iconClass", + "value": "bx bxs-grid", + "type": "label" + } + ] + }, + { + "id": "_help_0vhv7lsOLy82", + "title": "첨부 파일", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Attachments" + }, + { + "name": "iconClass", + "value": "bx bx-paperclip", + "type": "label" + } + ] + }, + { + "id": "_help_IakOLONlIfGI", + "title": "노트 복제", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes" + }, + { + "name": "iconClass", + "value": "bx bx-duplicate", + "type": "label" + } + ], + "children": [ + { + "id": "_help_TBwsyfadTA18", + "title": "가지 접두사", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix" + }, + { + "name": "iconClass", + "value": "bx bx-rename", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_bwg0e8ewQMak", + "title": "보호된 노트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes" + }, + { + "name": "iconClass", + "value": "bx bx-lock-alt", + "type": "label" + } + ] + }, + { + "id": "_help_MKmLg5x6xkor", + "title": "보관된 노트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes" + }, + { + "name": "iconClass", + "value": "bx bx-box", + "type": "label" + } + ] + }, + { + "id": "_help_vZWERwf8U3nx", + "title": "노트 수정 이력", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions" + }, + { + "name": "iconClass", + "value": "bx bx-history", + "type": "label" + } + ] + }, + { + "id": "_help_aGlEvb9hyDhS", + "title": "노트 정렬", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes" + }, + { + "name": "iconClass", + "value": "bx bx-sort-up", + "type": "label" + } + ] + }, + { + "id": "_help_NRnIZmSMc5sj", + "title": "PDF로 내보내기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF" + }, + { + "name": "iconClass", + "value": "bx bxs-file-pdf", + "type": "label" + } + ] + }, + { + "id": "_help_CoFPLs3dRlXc", + "title": "읽기 전용 노트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes" + }, + { + "name": "iconClass", + "value": "bx bx-edit-alt", + "type": "label" + } + ] + }, + { + "id": "_help_0ESUbbAxVnoK", + "title": "노트 목록", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Note List" + }, + { + "name": "iconClass", + "value": "bx bxs-grid", + "type": "label" + } + ], + "children": [ + { + "id": "_help_xWbu3jpNWapp", + "title": "달력 보기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Notes/Note List/Calendar View" + }, + { + "name": "iconClass", + "value": "bx bx-calendar", + "type": "label" + } + ] + } + ] + } + ] + }, + { + "id": "_help_wArbEsdSae6g", + "title": "노트 탐색", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-navigation", + "type": "label" + } + ], + "children": [ + { + "id": "_help_kBrnXNG3Hplm", + "title": "트리의 개념", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts" + }, + { + "name": "iconClass", + "value": "bx bx-pyramid", + "type": "label" + } + ] + }, + { + "id": "_help_MMiBEQljMQh2", + "title": "노트 이동", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation" + }, + { + "name": "iconClass", + "value": "bx bxs-navigation", + "type": "label" + } + ] + }, + { + "id": "_help_Ms1nauBra7gq", + "title": "빠른 검색", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search" + }, + { + "name": "iconClass", + "value": "bx bx-search-alt-2", + "type": "label" + } + ] + }, + { + "id": "_help_F1r9QtzQLZqm", + "title": "노트로 이동", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note" + }, + { + "name": "iconClass", + "value": "bx bx-send", + "type": "label" + } + ] + }, + { + "id": "_help_eIg8jdvaoNNd", + "title": "검색", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Search" + }, + { + "name": "iconClass", + "value": "bx bx-search-alt-2", + "type": "label" + } + ] + }, + { + "id": "_help_u3YFHC9tQlpm", + "title": "북마크", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks" + }, + { + "name": "iconClass", + "value": "bx bx-bookmarks", + "type": "label" + } + ] + }, + { + "id": "_help_OR8WJ7Iz9K4U", + "title": "노트 확대 보기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting" + }, + { + "name": "iconClass", + "value": "bx bxs-chevrons-up", + "type": "label" + } + ] + }, + { + "id": "_help_9sRHySam5fXb", + "title": "작업 공간", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces" + }, + { + "name": "iconClass", + "value": "bx bx-door-open", + "type": "label" + } + ] + }, + { + "id": "_help_xWtq5NUHOwql", + "title": "비슷한 노트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes" + }, + { + "name": "iconClass", + "value": "bx bx-bar-chart", + "type": "label" + } + ] + }, + { + "id": "_help_McngOG2jbUWX", + "title": "노트 안에서 찾기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note" + }, + { + "name": "iconClass", + "value": "bx bx-search-alt-2", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_A9Oc6YKKc65v", + "title": "키보드 단축키", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts" + }, + { + "name": "iconClass", + "value": "bx bxs-keyboard", + "type": "label" + } + ] + }, + { + "id": "_help_Wy267RK4M69c", + "title": "테마", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Themes" + }, + { + "name": "iconClass", + "value": "bx bx-palette", + "type": "label" + } + ], + "children": [ + { + "id": "_help_VbjZvtUek0Ln", + "title": "테마 모음", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery" + }, + { + "name": "iconClass", + "value": "bx bx-book-reader", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_mHbBMPDPkVV5", + "title": "가져오기와 내보내기", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-import", + "type": "label" + } + ], + "children": [ + { + "id": "_help_Oau6X9rCuegd", + "title": "Markdown", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown" + }, + { + "name": "iconClass", + "value": "bx bxl-markdown", + "type": "label" + } + ] + }, + { + "id": "_help_syuSEKf2rUGr", + "title": "Evernote", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_GnhlmrATVqcH", + "title": "OneNote", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_rC3pL2aptaRE", + "title": "집중 모드", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Basic Concepts and Features/Zen mode" + }, + { + "name": "iconClass", + "value": "bx bxs-yin-yang", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_s3YCWHBfmYuM", + "title": "빠른 시작", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Quick Start" + }, + { + "name": "iconClass", + "value": "bx bx-run", + "type": "label" + } + ] + }, + { + "id": "_help_i6dbnitykE5D", + "title": "자주 묻는 질문", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/FAQ" + }, + { + "name": "iconClass", + "value": "bx bx-question-mark", + "type": "label" + } + ] + }, + { + "id": "_help_KSZ04uQ2D1St", + "title": "노트 유형", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types" + }, + { + "name": "iconClass", + "value": "bx bx-edit", + "type": "label" + } + ], + "children": [ + { + "id": "_help_iPIMuisry3hd", + "title": "텍스트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text" + }, + { + "name": "iconClass", + "value": "bx bx-note", + "type": "label" + } + ], + "children": [ + { + "id": "_help_NwBbFdNZ9h7O", + "title": "인용문과 안내 상자", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Block quotes & admonitions" + }, + { + "name": "iconClass", + "value": "bx bx-info-circle", + "type": "label" + } + ] + }, + { + "id": "_help_oSuaNgyyKnhu", + "title": "북마크", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Bookmarks" + }, + { + "name": "iconClass", + "value": "bx bx-bookmark", + "type": "label" + } + ] + }, + { + "id": "_help_veGu4faJErEM", + "title": "본문 언어와 오른쪽에서 왼쪽으로 쓰기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Content language & Right-to-le" + }, + { + "name": "iconClass", + "value": "bx bx-align-right", + "type": "label" + } + ] + }, + { + "id": "_help_2x0ZAX9ePtzV", + "title": "하위 노트로 잘라내기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Cut to subnote" + }, + { + "name": "iconClass", + "value": "bx bx-cut", + "type": "label" + } + ] + }, + { + "id": "_help_UYuUB1ZekNQU", + "title": "개발자용 서식", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Developer-specific formatting" + }, + { + "name": "iconClass", + "value": "bx bx-code-alt", + "type": "label" + } + ], + "children": [ + { + "id": "_help_QxEyIjRBizuC", + "title": "코드 블록", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks" + }, + { + "name": "iconClass", + "value": "bx bx-code", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_AgjCISero73a", + "title": "각주", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Footnotes" + }, + { + "name": "iconClass", + "value": "bx bx-bracket", + "type": "label" + } + ] + }, + { + "id": "_help_nRhnJkTT8cPs", + "title": "서식 도구 모음", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Formatting toolbar" + }, + { + "name": "iconClass", + "value": "bx bx-text", + "type": "label" + } + ] + }, + { + "id": "_help_Gr6xFaF6ioJ5", + "title": "일반 서식", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/General formatting" + }, + { + "name": "iconClass", + "value": "bx bx-bold", + "type": "label" + } + ] + }, + { + "id": "_help_AxshuNRegLAv", + "title": "강조 표시 목록", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Highlights list" + }, + { + "name": "iconClass", + "value": "bx bx-highlight", + "type": "label" + } + ] + }, + { + "id": "_help_mT0HEkOsz6i1", + "title": "이미지", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Images" + }, + { + "name": "iconClass", + "value": "bx bx-image-alt", + "type": "label" + } + ], + "children": [ + { + "id": "_help_0Ofbk1aSuVRu", + "title": "이미지 참조", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Images/Image references" + }, + { + "name": "iconClass", + "value": "bx bxs-file-image", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_nBAXQFj20hS1", + "title": "노트 포함", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Include Note" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_CohkqWQC1iBv", + "title": "삽입 메뉴", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Insert buttons" + }, + { + "name": "iconClass", + "value": "bx bx-plus", + "type": "label" + } + ] + }, + { + "id": "_help_oiVPnW8QfnvS", + "title": "편집 단축키", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Keyboard shortcuts" + }, + { + "name": "iconClass", + "value": "bx bxs-keyboard", + "type": "label" + } + ] + }, + { + "id": "_help_QEAPj01N5f7w", + "title": "링크", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Links" + }, + { + "name": "iconClass", + "value": "bx bx-link-alt", + "type": "label" + } + ] + }, + { + "id": "_help_S6Xx8QIWTV66", + "title": "목록", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Lists" + }, + { + "name": "iconClass", + "value": "bx bx-list-ul", + "type": "label" + } + ] + }, + { + "id": "_help_QrtTYPmdd1qq", + "title": "Markdown식 자동 서식", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Markdown-like formatting" + }, + { + "name": "iconClass", + "value": "bx bxl-markdown", + "type": "label" + } + ] + }, + { + "id": "_help_YfYAtQBcfo5V", + "title": "수식", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Math Equations" + }, + { + "name": "iconClass", + "value": "bx bx-math", + "type": "label" + } + ] + }, + { + "id": "_help_dEHYtoWWi8ct", + "title": "기타 기능", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Other features" + }, + { + "name": "iconClass", + "value": "bx bxs-grid", + "type": "label" + } + ] + }, + { + "id": "_help_BFvAtE74rbP6", + "title": "목차", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Table of contents" + }, + { + "name": "iconClass", + "value": "bx bx-heading", + "type": "label" + } + ] + }, + { + "id": "_help_NdowYOC1GFKS", + "title": "표", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Text/Tables" + }, + { + "name": "iconClass", + "value": "bx bx-table", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_6f9hih2hXXZk", + "title": "코드", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Code" + }, + { + "name": "iconClass", + "value": "bx bx-code", + "type": "label" + } + ] + }, + { + "id": "_help_m523cpzocqaD", + "title": "저장된 검색", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Saved Search" + }, + { + "name": "iconClass", + "value": "bx bx-file-find", + "type": "label" + } + ] + }, + { + "id": "_help_iRwzGnHPzonm", + "title": "관계도", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Relation Map" + }, + { + "name": "iconClass", + "value": "bx bxs-network-chart", + "type": "label" + } + ] + }, + { + "id": "_help_bdUJEHsAPYQR", + "title": "노트 지도", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Note Map" + }, + { + "name": "iconClass", + "value": "bx bxs-network-chart", + "type": "label" + } + ] + }, + { + "id": "_help_HcABDtFCkbFN", + "title": "렌더링 노트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Render Note" + }, + { + "name": "iconClass", + "value": "bx bx-extension", + "type": "label" + } + ] + }, + { + "id": "_help_GTwFsgaA0lCt", + "title": "책", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Book" + }, + { + "name": "iconClass", + "value": "bx bx-book", + "type": "label" + } + ] + }, + { + "id": "_help_s1aBHPd79XYj", + "title": "Mermaid 도표", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Mermaid Diagrams" + }, + { + "name": "iconClass", + "value": "bx bx-selection", + "type": "label" + } + ], + "children": [ + { + "id": "_help_RH6yLjjWJHof", + "title": "ELK 배치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout" + }, + { + "name": "iconClass", + "value": "bx bxs-network-chart", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_grjYqerjn243", + "title": "캔버스", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Canvas" + }, + { + "name": "iconClass", + "value": "bx bx-pen", + "type": "label" + } + ] + }, + { + "id": "_help_1vHRoWCEjj0L", + "title": "웹 보기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Web View" + }, + { + "name": "iconClass", + "value": "bx bx-globe-alt", + "type": "label" + } + ] + }, + { + "id": "_help_gBbsAeiuUxI5", + "title": "마인드맵", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Mind Map" + }, + { + "name": "iconClass", + "value": "bx bx-sitemap", + "type": "label" + } + ] + }, + { + "id": "_help_81SGnPGMk7Xc", + "title": "지리 지도", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/Geo Map" + }, + { + "name": "iconClass", + "value": "bx bx-map-alt", + "type": "label" + } + ] + }, + { + "id": "_help_W8vYD3Q1zjCR", + "title": "파일", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Note Types/File" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_BgmBlOIl72jZ", + "title": "문제 해결", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Troubleshooting" + }, + { + "name": "iconClass", + "value": "bx bx-bug", + "type": "label" + } + ], + "children": [ + { + "id": "_help_wy8So3yZZlH9", + "title": "문제 제보", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Troubleshooting/Reporting issues" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_x59R8J8KV5Bp", + "title": "익명화한 데이터베이스", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Troubleshooting/Anonymized Database" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_qzNzp9LYQyPT", + "title": "오류 로그", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Troubleshooting/Error logs" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_vdlYGAcpXAgc", + "title": "504 오류로 동기화가 실패할 때", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Troubleshooting/Synchronization fails with 504" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_s8alTXmpFR61", + "title": "앱 새로고침", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Troubleshooting/Refreshing the application" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_pKK96zzmvBGf", + "title": "테마 개발", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-palette", + "type": "label" + } + ], + "children": [ + { + "id": "_help_7NfNr5pZpVKV", + "title": "사용자 테마 만들기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Theme development/Creating a custom theme" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_WFGzWeUK6arS", + "title": "Next 테마 수정", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Theme development/Customize the Next theme" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_WN5z4M8ASACJ", + "title": "테마 개발 참고 자료", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Theme development/Reference" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_AlhDUqhENtH7", + "title": "앱 전체 사용자 CSS", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Theme development/Custom app-wide CSS" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_tC7s2alapj8V", + "title": "고급 사용법", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-rocket", + "type": "label" + } + ], + "children": [ + { + "id": "_help_zEY4DaJG4YT5", + "title": "속성", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Attributes" + }, + { + "name": "iconClass", + "value": "bx bx-list-check", + "type": "label" + } + ], + "children": [ + { + "id": "_help_HI6GBBIduIgv", + "title": "라벨", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Attributes/Labels" + }, + { + "name": "iconClass", + "value": "bx bx-hash", + "type": "label" + } + ] + }, + { + "id": "_help_Cq5X6iKQop6R", + "title": "관계", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Attributes/Relations" + }, + { + "name": "iconClass", + "value": "bx bx-transfer", + "type": "label" + } + ] + }, + { + "id": "_help_bwZpz2ajCEwO", + "title": "속성 상속", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance" + }, + { + "name": "iconClass", + "value": "bx bx-list-plus", + "type": "label" + } + ] + }, + { + "id": "_help_OFXdgB2nNk1F", + "title": "주요 속성", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes" + }, + { + "name": "iconClass", + "value": "bx bx-table", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_KC1HB96bqqHX", + "title": "템플릿", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Templates" + }, + { + "name": "iconClass", + "value": "bx bx-copy", + "type": "label" + } + ] + }, + { + "id": "_help_BCkXAVs63Ttv", + "title": "노트 지도와 연결 지도 및 트리 지도", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map)" + }, + { + "name": "iconClass", + "value": "bx bxs-network-chart", + "type": "label" + } + ] + }, + { + "id": "_help_R9pX4DGra2Vt", + "title": "공개 공유", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Sharing" + }, + { + "name": "iconClass", + "value": "bx bx-share-alt", + "type": "label" + } + ], + "children": [ + { + "id": "_help_Qjt68inQ2bRj", + "title": "노트 원문 제공", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_5668rwcirq1t", + "title": "고급 활용 예제", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Advanced Showcases" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ], + "children": [ + { + "id": "_help_l0tKav7yLHGF", + "title": "일일 노트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes" + }, + { + "name": "iconClass", + "value": "bx bx-calendar", + "type": "label" + } + ] + }, + { + "id": "_help_R7abl2fc6Mxi", + "title": "체중 기록", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_xYjQUYhpbUEW", + "title": "할 일 관리자", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager" + }, + { + "name": "iconClass", + "value": "bx bx-calendar-check", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_J5Ex1ZrMbyJ6", + "title": "사용자 요청 처리기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Custom Request Handler" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_d3fAXQ2diepH", + "title": "사용자 리소스 제공자", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Custom Resource Providers" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_pgxEVkzLl1OP", + "title": "ETAPI와 REST API", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/ETAPI (REST API)" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ], + "children": [ + { + "id": "_help_9qPsTWBorUhQ", + "title": "API 참고 자료", + "type": "webView", + "attributes": [ + { + "type": "label", + "name": "webViewSrc", + "value": "/etapi/docs" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_47ZrP6FNuoG8", + "title": "기본 노트 제목", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Default Note Title" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_wX4HbRucYSDD", + "title": "데이터베이스", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Database" + }, + { + "name": "iconClass", + "value": "bx bx-data", + "type": "label" + } + ], + "children": [ + { + "id": "_help_oyIAJ9PvvwHX", + "title": "데이터베이스 직접 수정", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Database/Manually altering the database" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ], + "children": [ + { + "id": "_help_YKWqdJhzi2VY", + "title": "SQL 콘솔", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console" + }, + { + "name": "iconClass", + "value": "bx bx-data", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_6tZeKvSHEUiB", + "title": "기본 예제 노트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Database/Demo Notes" + }, + { + "name": "iconClass", + "value": "bx bx-package", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_Gzjqa934BdH4", + "title": "설정 파일과 환경 변수", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Configuration (config.ini or e" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ], + "children": [ + { + "id": "_help_c5xB8m4g2IY6", + "title": "Trilium 인스턴스", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_LWtBjFej3wX3", + "title": "교차 출처 리소스 공유와 CORS", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing " + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_ivYnonVFBxbQ", + "title": "일괄 작업", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Bulk Actions" + }, + { + "name": "iconClass", + "value": "bx bx-list-plus", + "type": "label" + } + ] + }, + { + "id": "_help_4FahAwuGTAwC", + "title": "노트 소스", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Note source" + }, + { + "name": "iconClass", + "value": "bx bx-code", + "type": "label" + } + ] + }, + { + "id": "_help_1YeN2MzFUluU", + "title": "사용 기술", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Technologies used" + }, + { + "name": "iconClass", + "value": "bx bxs-component", + "type": "label" + } + ], + "children": [ + { + "id": "_help_MI26XDLSAlCD", + "title": "CKEditor", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Technologies used/CKEditor" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_N4IDkixaDG9C", + "title": "MindElixir", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Technologies used/MindElixir" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_H0mM1lTxF9JI", + "title": "Excalidraw", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_MQHyy2dIFgxS", + "title": "Leaflet", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Technologies used/Leaflet" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_m1lbrzyKDaRB", + "title": "노트 ID", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Note ID" + }, + { + "name": "iconClass", + "value": "bx bx-hash", + "type": "label" + } + ] + }, + { + "id": "_help_0vTSyvhPTAOz", + "title": "내부 API", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-folder", + "type": "label" + } + ], + "children": [ + { + "id": "_help_z8O2VG4ZZJD7", + "title": "API 참고 자료", + "type": "webView", + "attributes": [ + { + "type": "label", + "name": "webViewSrc", + "value": "/api/docs" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_2mUhVmZK8RF3", + "title": "숨겨진 노트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Hidden Notes" + }, + { + "name": "iconClass", + "value": "bx bx-hide", + "type": "label" + } + ] + }, + { + "id": "_help_uYF7pmepw27K", + "title": "운영 지표", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Advanced Usage/Metrics" + }, + { + "name": "iconClass", + "value": "bx bxs-data", + "type": "label" + } + ], + "children": [ + { + "id": "_help_bOP3TB56fL1V", + "title": "Grafana 대시보드 예제 (grafana-dashboard.json)", + "type": "doc", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + } + ] + }, + { + "id": "_help_LMAv4Uy3Wk6J", + "title": "AI", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-bot", + "type": "label" + } + ], + "children": [ + { + "id": "_help_GBBMSlVSOIGP", + "title": "AI 기능 소개", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/AI/Introduction" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_WkM7gsEUyCXs", + "title": "AI 제공자 안내", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/AI/AI Provider Information" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ], + "children": [ + { + "id": "_help_7EdTxPADv95W", + "title": "Ollama", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-folder", + "type": "label" + } + ], + "children": [ + { + "id": "_help_vvUCN7FDkq7G", + "title": "Ollama 설치", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/AI/AI Provider Information/Ollama/Installing Ollama" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_ZavFigBX9AwP", + "title": "OpenAI", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/AI/AI Provider Information/OpenAI" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_e0lkirXEiSNc", + "title": "Anthropic", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/AI/AI Provider Information/Anthropic" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + } + ] + }, + { + "id": "_help_CdNpE2pqjmI6", + "title": "스크립트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting" + }, + { + "name": "iconClass", + "value": "bx bxs-file-js", + "type": "label" + } + ], + "children": [ + { + "id": "_help_yIhgI5H7A2Sm", + "title": "프런트엔드 기초", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting/Frontend Basics" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_es8OU2GuguFU", + "title": "예제", + "type": "book", + "attributes": [ + { + "name": "iconClass", + "value": "bx bx-folder", + "type": "label" + } + ], + "children": [ + { + "id": "_help_TjLYAo3JMO8X", + "title": "새 할 일 실행 버튼", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting/Examples/New Task launcher button" + }, + { + "name": "iconClass", + "value": "bx bx-task", + "type": "label" + } + ] + }, + { + "id": "_help_7kZPMD0uFwkH", + "title": "Google 설문지 응답 내려받기", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting/Examples/Downloading responses from Goo" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_DL92EjAaXT26", + "title": "주요 속성으로 스크립트 설정", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting/Examples/Using promoted attributes to c" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_GPERMystNGTB", + "title": "이벤트", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting/Events" + }, + { + "name": "iconClass", + "value": "bx bx-rss", + "type": "label" + } + ] + }, + { + "id": "_help_MgibgPcfeuGz", + "title": "사용자 위젯", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting/Custom Widgets" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ], + "children": [ + { + "id": "_help_YNxAqkI5Kg1M", + "title": "단어 수 위젯", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting/Custom Widgets/Word count widget" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + }, + { + "id": "_help_SynTBQiBsdYJ", + "title": "위젯 기초", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting/Custom Widgets/Widget Basics" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_GLks18SNjxmC", + "title": "스크립트 API", + "type": "doc", + "attributes": [ + { + "type": "label", + "name": "docName", + "value": "User Guide/User Guide/Scripting/Script API" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ], + "children": [ + { + "id": "_help_Q2z6av6JZVWm", + "title": "프런트엔드 API", + "type": "webView", + "attributes": [ + { + "type": "label", + "name": "webViewSrc", + "value": "/assets/v0.95.0-ko-20260913-r8/doc_notes/en/api-ko/frontend.html" + }, + { + "name": "iconClass", + "value": "bx bx-folder", + "type": "label" + } + ], + "children": [ + { + "id": "_help_habiZ3HU8Kw8", + "title": "프런트엔드 노트 객체 (FNote)", + "type": "webView", + "attributes": [ + { + "type": "label", + "name": "webViewSrc", + "value": "/assets/v0.95.0-ko-20260913-r8/doc_notes/en/api-ko/fnote.html" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + }, + { + "id": "_help_MEtfsqa5VwNi", + "title": "백엔드 API", + "type": "webView", + "attributes": [ + { + "type": "label", + "name": "webViewSrc", + "value": "/assets/v0.95.0-ko-20260913-r8/doc_notes/en/api-ko/backend.html" + }, + { + "name": "iconClass", + "value": "bx bx-file", + "type": "label" + } + ] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/1_AI Provider Information_im.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/1_AI Provider Information_im.png new file mode 100644 index 0000000..80627e0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/1_AI Provider Information_im.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/1_Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/1_Introduction_image.png new file mode 100644 index 0000000..c0955f2 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/1_Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/2_Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/2_Introduction_image.png new file mode 100644 index 0000000..3908a5f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/2_Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/3_Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/3_Introduction_image.png new file mode 100644 index 0000000..0fe0c81 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/3_Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/4_Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/4_Introduction_image.png new file mode 100644 index 0000000..ef2ad8a Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/4_Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/5_Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/5_Introduction_image.png new file mode 100644 index 0000000..ede9d6a Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/5_Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/6_Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/6_Introduction_image.png new file mode 100644 index 0000000..e784df7 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/6_Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/7_Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/7_Introduction_image.png new file mode 100644 index 0000000..96d56b3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/7_Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/8_Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/8_Introduction_image.png new file mode 100644 index 0000000..afb6653 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/8_Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/9_Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/9_Introduction_image.png new file mode 100644 index 0000000..f50f695 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/9_Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information.html b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information.html new file mode 100644 index 0000000..3f514b3 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information.html @@ -0,0 +1,5 @@ +

이 버전에서 지원하는 제공자는 다음과 같습니다.

사용할 대화 모델의 제공자 이름을 다음 위치에 입력하세요.

대화 모델 제공자 설정

임베딩 제공자는 다음 위치에서 지정합니다.

임베딩 제공자 설정

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 대화 모델 제공자 설정

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 임베딩 제공자 설정

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Anthropic.html b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Anthropic.html new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Anthropic.html @@ -0,0 +1 @@ + diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/1_Installing Ollama_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/1_Installing Ollama_image.png new file mode 100644 index 0000000..821966b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/1_Installing Ollama_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/2_Installing Ollama_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/2_Installing Ollama_image.png new file mode 100644 index 0000000..7e585a7 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/2_Installing Ollama_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/3_Installing Ollama_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/3_Installing Ollama_image.png new file mode 100644 index 0000000..0a239f3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/3_Installing Ollama_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/4_Installing Ollama_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/4_Installing Ollama_image.png new file mode 100644 index 0000000..b5c4c29 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/4_Installing Ollama_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/5_Installing Ollama_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/5_Installing Ollama_image.png new file mode 100644 index 0000000..0c02db5 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/5_Installing Ollama_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/Installing Ollama.html b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/Installing Ollama.html new file mode 100644 index 0000000..8148256 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/Installing Ollama.html @@ -0,0 +1,10 @@ +

Ollama는 여러 방식으로 설치할 수 있으며 Docker 컨테이너에서도 실행할 수 있습니다. 지원되는 GPU를 사용하면 일반적으로 더 빠릅니다. CPU와 메모리만으로도 실행할 수 있습니다. 직접 설치하려면 공식 설치 프로그램을 이용하세요.

Ollama 내려받기 화면

설치 파일

설치 진행 화면

Windows에서는 설치 후 시작 메뉴에서 실행할 수 있습니다.

시작 메뉴의 Ollama

PowerShell이나 명령 프롬프트에서 ollama 명령도 사용할 수 있습니다.

Ollama 명령줄 실행

설치 후 pull 명령으로 사용할 모델을 내려받습니다. 다음은 원문 작성 시점인 2025년 4월에 소개한 도구 호출용 모델과 임베딩 모델의 예시입니다.

ollama pull llama3.1:8b
+ollama pull mxbai-embed-large

기본 포트는 11434입니다. 로컬 Ollama 상태 페이지를 열면 실행 여부를 확인할 수 있습니다.

Ollama 정상 실행 응답

서비스를 실행하고 모델을 내려받았다면 Trilium에서 채팅 제공자와 임베딩 제공자로 설정할 준비가 된 것입니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · Ollama 내려받기 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 설치 파일

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 설치 진행 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · 시작 메뉴의 Ollama

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 5 · Ollama 명령줄 실행

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 6 · Ollama 정상 실행 응답

Ollama 서버가 실행 중임을 알리는 응답입니다. 이 응답이 보이면 본문에 안내된 주소를 연결 설정에 사용합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/Installing Ollama_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/Installing Ollama_image.png new file mode 100644 index 0000000..cf5ee38 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/Ollama/Installing Ollama_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/OpenAI.html b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/OpenAI.html new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information/OpenAI.html @@ -0,0 +1 @@ + diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information_im.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information_im.png new file mode 100644 index 0000000..aa19e94 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/AI Provider Information_im.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/Introduction.html b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/Introduction.html new file mode 100644 index 0000000..aa615be --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/Introduction.html @@ -0,0 +1,15 @@ +

노트에 관해 AI와 대화하는 예제

Trilium의 AI 기능은 노트를 바탕으로 대화하고 정보를 찾도록 도와줍니다. 이 버전은 OpenAI와 Anthropic 및 Ollama 같은 제공자와의 대화뿐 아니라 도구 호출과 임베딩을 지원합니다.

설정의 AI/LLM 항목을 열고 기능을 켭니다.

AI 설정 위치

AI 기능 켜기

임베딩

임베딩은 노트의 의미를 수치로 표현한 자료입니다. 사람이 읽는 요약문과는 다릅니다. 코사인 유사도 같은 계산으로 대화에 관련된 노트를 찾아 AI에 전달하는 데 활용합니다. 이 버전에서는 OpenAI와 Voyage AI 및 Ollama로 임베딩을 만들 수 있습니다.

다음 예제는 직접 운영하는 Ollama를 사용합니다. 설치 방법은 Ollama 설치를 참고하세요. Ollama 임베딩 모델 목록에서 모델을 찾아 pull 명령으로 가져옵니다. 원문의 2025년 4월 예제는 mxbai-embed-large를 사용합니다.

제공자 탭에서 Ollama를 선택하고 기본 URL을 입력합니다. 같은 컴퓨터에서 실행하는 예제 주소는 http://localhost:11434입니다. 새로고침 버튼으로 모델 목록을 불러옵니다.

Ollama 주소와 모델 목록 설정

임베딩 모델 목록에서는 임베딩용 모델이 위쪽에 표시되고 일반 대화 모델과 구분선으로 나뉩니다.

임베딩 모델 선택

모델을 선택하면 임베딩 생성이 시작됩니다. 설정 위쪽의 통계에서 진행 상황을 확인합니다.

임베딩 생성 통계

생성이 시작되지 않으면 설정 아래쪽에서 모든 임베딩 다시 만들기를 누릅니다.

모든 임베딩 다시 만들기

생성에는 시간이 걸립니다. 노트를 만들거나 수정하거나 삭제하면 관련 임베딩도 갱신됩니다. 제공자나 모델을 바꾸면 전체 임베딩을 다시 만들어야 합니다.

도구

AI가 사용할 수 있도록 제공하는 함수입니다. 모델이 도구 이름과 인수를 요청하면 Trilium이 실행하고 결과를 대화에 전달합니다. 이 버전에는 다음 도구가 포함되어 있습니다.

대화 중 도구가 실행되면 다음처럼 결과가 표시됩니다. 특정 도구를 직접 지시하지 않아도 모델이 필요에 따라 선택할 수 있습니다.

대화 중 도구 실행 결과

대화 시작

노트와 대화 버튼으로 시작합니다.

노트와 대화 버튼

버튼이 보이지 않으면 실행 도구 모음 설정에서 사용 가능한 실행 도구를 표시할 실행 도구 영역으로 옮기세요.

대화 실행 도구 표시

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트에 관해 AI와 대화하는 예제

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · AI 설정 위치

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · AI 기능 켜기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · Ollama 주소와 모델 목록 설정

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 5 · 임베딩 모델 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 6 · 임베딩 생성 통계

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 7 · 모든 임베딩 다시 만들기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 8 · 대화 중 도구 실행 결과

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 9 · 노트와 대화 버튼

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 10 · 대화 실행 도구 표시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/AI/Introduction_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/Introduction_image.png new file mode 100644 index 0000000..5a8657f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/AI/Introduction_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/1_Metrics_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/1_Metrics_image.png new file mode 100644 index 0000000..6837895 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/1_Metrics_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/1_Note Map (Link map, Tree m.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/1_Note Map (Link map, Tree m.png new file mode 100644 index 0000000..a16316f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/1_Note Map (Link map, Tree m.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/2_Metrics_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/2_Metrics_image.png new file mode 100644 index 0000000..08181d9 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/2_Metrics_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases.html new file mode 100644 index 0000000..769ac4f --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases.html @@ -0,0 +1,2 @@ +

Trilium에서는 스크립트와 주요 속성을 활용해 고급 기능을 만들 수 있습니다. 사용 방법을 보여 주기 위해 기본 예제 노트에 다음 사례를 준비했습니다.

이 예제들은 Trilium에서 구성할 수 있는 기능을 보여 주기 위한 것입니다. 모든 기능이 완성된 기본 기능으로 제공되는 것은 아닙니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/1_Day Notes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/1_Day Notes_image.png new file mode 100644 index 0000000..9e03a23 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/1_Day Notes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes.html new file mode 100644 index 0000000..6ce601f --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes.html @@ -0,0 +1,3 @@ +

할 일과 회의록 및 그날의 생각처럼 날짜를 중심으로 모이는 기록이 많습니다. 일일 노트는 특정 날짜의 자료를 한곳에 모으는 공간입니다. Trilium이 날짜별 노트를 만들면 그 아래에 관련 노트를 보관할 수 있습니다. 기존 일일 노트에서 메뉴의 달력을 열고 날짜를 선택하면 해당 날짜의 노트를 만듭니다.

달력에서 날짜 선택

노트 복제를 이용하면 같은 노트를 일일 노트 아래와 다른 분류 아래에 함께 배치할 수 있습니다.

예제

일지의 날짜별 노트 구조

일지 아래에 연도와 월 및 날짜 순으로 노트가 구성됩니다. 일일 노트에는 본문과 하위 노트를 넣을 수 있습니다. 할 일 관리자의 노트도 함께 배치할 수 있습니다. 체중을 기록하는 weight 주요 속성은 체중 기록에서 활용합니다.

주별 노트와 분기별 노트

기본으로 꺼져 있습니다. #calendarRoot 라벨이 있는 달력 루트에 #enableWeekNote와 #enableQuarterNote를 추가하면 켜집니다. 주별 노트는 연도의 첫 주 설정에 영향을 받습니다. 설정을 바꿔도 기존 노트가 자동으로 변경되지 않으므로 중복에 주의하세요.

템플릿

템플릿을 일일 노트와 함께 사용할 수 있습니다. 달력 루트에 yearTemplate과 quarterTemplate 및 monthTemplate와 weekTemplate 및 dateTemplate 관계를 지정합니다. 분기와 주 템플릿은 해당 기능이 켜져 있어야 적용됩니다. 새 날짜 노트를 만들 때 알맞은 ~template 관계를 붙입니다. 매일 반복할 체크리스트 등에 활용할 수 있습니다.

이전 방식에서 옮기기

0.93.0 이전에는 ~child:template= 방식을 사용했을 수 있습니다. 먼저 달력 루트에 새 템플릿 관계를 지정합니다. 일괄 작업으로 일지 아래의 child:template과 child:child:template 관계를 제거하고 이전 설정이 남아 충돌하지 않는지 확인합니다.

자동 제목 형식

달력 루트에 #datePattern과 #weekPattern 및 #monthPattern와 #quarterPattern 및 #yearPattern을 지정합니다. 각 단계는 자기 단계와 상위 단계의 치환값을 사용할 수 있습니다. 월 형식에는 월·분기·연도 값을 사용할 수 있지만 주 값은 사용할 수 없습니다.

날짜

기본 형식은 {dateNumberPadded} - {weekDay}입니다.

주

원본 기본 형식은 Week {weekNumber}입니다. 한국어 형식은 {weekNumber}주처럼 지정할 수 있습니다.

월

기본 형식은 {monthNumberPadded} - {month}입니다.

분기

{quarterNumber}는 분기 숫자이며 {shortQuarter}는 Q1 같은 짧은 표시입니다. 원본 기본 형식은 Quarter {quarterNumber}입니다. 한국어 형식은 {quarterNumber}분기처럼 지정할 수 있습니다.

연도

{year}는 2025 같은 연도입니다. 기본 형식도 {year}입니다.

스크립트에서 사용

백엔드 스크립트 API의 getDayNote() 등을 사용합니다. 날짜 노트에는 #dateNote="2025-03-09" 같은 라벨이 붙으므로 스크립트에서 찾아 하위 노트를 추가할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 달력에서 날짜 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 일지의 날짜별 노트 구조

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes_image.png new file mode 100644 index 0000000..fd89503 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Day Notes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager.html new file mode 100644 index 0000000..c4591b0 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager.html @@ -0,0 +1,28 @@ +

할 일 관리는 주요 속성과 스크립트를 활용하는 기본 예제입니다.

동작 예시

할 일 관리 예제

할 일과 완료된 일을 구분합니다. doneDate에 값이 있으면 완료된 일로 처리합니다. 아직 하지 않은 일은 장소와 태그로 분류하며 속성을 바꾸면 알맞은 위치로 자동 이동합니다.

날짜별 노트와도 연동합니다. 예정일인 todoDate와 완료일인 doneDate에 해당하는 날짜 노트 아래에 같은 작업을 복제하고 원본 예제에서는 TODO와 DONE 접두사로 구분합니다.

구현

새 작업을 넣는 노트의 ~child:template 관계가 작업 템플릿을 가리킵니다. 속성 상속을 참고하세요.

속성

템플릿에서 예정일과 완료일 및 태그와 장소를 주요 속성으로 표시합니다. ~runOnAttributeChange는 속성이 바뀔 때 실행할 이벤트 처리기를 연결합니다. 이 스크립트는 완료일을 입력하면 완료 목록으로 옮기고 할 일과 장소 및 태그 목록에서 제거합니다.

새 할 일 버튼

api.addButtonToToolbar({
+    title: '새 할 일',
+    icon: 'check',
+    shortcut: 'alt+n',
+    action: async () => {
+        // 노트 생성은 백엔드에서 처리합니다.
+        const taskNoteId = await api.runOnBackend(async () => {
+            const todoRootNote = await api.getNoteWithLabel('taskTodoRoot');
+            const {note} = await api.createNote(todoRootNote.noteId, '새 할 일', '');
+
+            return note.noteId;
+        });
+
+        // 생성한 노트를 바로 엽니다.
+        await api.activateNewNote(taskNoteId);
+    }
+});

색상

다음 CSS 코드 노트는 할 일을 빨간색으로 표시하고 완료한 일을 초록색으로 표시합니다.

span.fancytree-node.todo .fancytree-title {
+    color: red !important;
+}
+
+span.fancytree-node.done .fancytree-title {
+    color: green !important;
+}

이 코드 노트에 #appCss 라벨을 지정하면 시작할 때 적용됩니다. 이벤트 처리기는 상태에 따라 #cssClass 값으로 todo나 done을 지정합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 할 일 관리 예제

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager_task-manager.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager_task-manager.png new file mode 100644 index 0000000..f2c5c9f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Task Manager_task-manager.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker.html new file mode 100644 index 0000000..a06f600 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker.html @@ -0,0 +1,48 @@ +

체중 기록 예제

체중 기록은 스크립트 API를 활용하는 기본 예제입니다. weight를 주요 속성으로 지정한 템플릿에서 날짜별 노트를 만들면 체중을 입력하고 시간에 따른 변화를 차트로 볼 수 있습니다.

구현 방식

체중 기록 화면은 HTML 표시 노트입니다. 자체 본문 대신 스크립트의 결과를 표시하는 영역을 제공합니다. ~renderNote 관계로 구현용 노트와 연결합니다.

구현에는 HTML과 JavaScript 코드 노트가 사용됩니다. weight 속성이 있는 노트를 모아 차트로 표시합니다. 차트 라이브러리 Chart.js는 Trilium에 내장되어 있지 않으므로 첨부 파일로 가져옵니다.

코드

다음 코드를 프런트엔드 JavaScript 코드 노트에 작성합니다.

async function getChartData() {
+    const days = await api.runOnBackend(async () => {
+        const notes = api.getNotesWithLabel('weight');
+        const days = [];
+
+        for (const note of notes) {
+            const date = note.getLabelValue('dateNote');
+            const weight = parseFloat(note.getLabelValue('weight'));
+
+            if (date && weight) {
+                days.push({ date, weight });
+            }
+        }
+
+        days.sort((a, b) => a.date > b.date ? 1 : -1);
+
+        return days;
+    });
+
+    const datasets = [
+        {
+            label: "체중 (kg)",
+            backgroundColor: 'red',
+            borderColor: 'red',
+            data: days.map(day => day.weight),
+            fill: false,
+            spanGaps: true,
+            datalabels: {
+                display: false
+            }
+        }
+    ];
+
+    return {
+        datasets: datasets,
+        labels: days.map(day => day.date)
+    };
+}
+
+const ctx = $("#canvas")[0].getContext("2d");
+
+new chartjs.Chart(ctx, {
+    type: 'line',
+    data: await getChartData()
+});

상단 버튼 숨기기

체중 기록의 연결된 노트 중 버튼 구현 노트를 찾아 본문을 지우거나 주석으로 처리하세요. Trilium을 다시 시작하면 체중 기록 버튼이 표시되지 않습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 체중 기록 예제

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker_image.png new file mode 100644 index 0000000..0167e75 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Advanced Showcases/Weight Tracker_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes.html new file mode 100644 index 0000000..20b2108 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes.html @@ -0,0 +1,8 @@ +

노트 속성

속성은 노트에 지정하는 이름과 값의 쌍입니다. 추가 정보를 저장하거나 기능을 설정하며 크게 두 종류로 나뉩니다.

속성 목록 확인하기

현재 노트에 직접 지정한 라벨과 관계는 상단 리본의 소유한 속성에서 확인하고 수정할 수 있습니다. 상위 노트에서 물려받은 항목은 상속된 속성에서 확인할 수 있으며 그곳에서는 수정할 수 없습니다.

목록에서 라벨 앞에는 #이 붙고 관계 앞에는 ~가 붙습니다.

같은 이름의 여러 값

같은 이름의 속성을 여러 개 지정할 수 있습니다. 이를 통해 한 항목에 여러 값을 저장할 수 있습니다.

속성 정의와 주요 속성

특별한 라벨로 속성의 형식과 표시 방법을 정의할 수 있습니다. 주요 속성을 참고하세요.

속성 상속

하위 노트가 상위 노트의 속성을 물려받을 수 있습니다. 자세한 내용은 속성 상속을 참고하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 속성

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance.html new file mode 100644 index 0000000..a46557e --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Attribute Inheritance.html @@ -0,0 +1,2 @@ +

상속은 라벨이나 관계를 여러 노트에 공통으로 적용하는 기능입니다. 주로 상위·하위 노트 사이에 적용하며 템플릿으로도 사용할 수 있습니다.

일반 상속

isInheritable을 true로 지정하면 해당 속성을 현재 노트와 모든 하위 노트에 적용합니다. 라벨과 관계 편집 화면에서 설정하거나 #myLabel(inheritable)=value처럼 작성할 수 있습니다.

예를 들어 archived 라벨의 상속을 켜면 하위 트리 전체를 검색 등의 목록에서 숨길 수 있습니다. 일반 상속은 모든 하위 노트에 적용됩니다. 일부 노트에서 개별적으로 바꿔야 한다면 복사 상속이나 템플릿 방식을 사용하세요.

복사 상속

속성 이름 앞에 child:를 붙이면 새 하위 노트에 해당 속성을 복사합니다. 복사된 속성은 독립적이며 노트를 다른 위치로 옮겨도 유지됩니다.

#child:exampleAttribute를 상위 노트에 지정하면 새로 만드는 바로 아래 노트에 #exampleAttribute가 생깁니다. 관계는 ~child:myRelation처럼 지정합니다. 기존 노트에는 소급 적용되지 않습니다. 무한한 하위 단계에 적용하려면 일반 상속이나 템플릿을 사용하세요.

여러 단계로 복사하기

#child:child:child:foo를 지정하면 첫 단계에는 #child:child:foo가 생기고 다음 단계에는 #child:foo가 생기며 세 번째 단계에는 #foo가 생깁니다. 관계도 ~child:child:child:foo로 같은 방식을 사용할 수 있습니다. 새로 만드는 노트에만 적용됩니다.

템플릿 상속

템플릿의 속성도 물려받을 수 있습니다. 비슷한 구조와 역할을 가진 노트에 공통 설정을 유지할 때 유용합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Labels.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Labels.html new file mode 100644 index 0000000..e8db283 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Labels.html @@ -0,0 +1,12 @@ +

라벨은 이름과 선택적인 값을 가진 노트의 속성입니다.

활용 방법

#year=1999와 #genre="공상 과학" 및 #author="닐 스티븐슨"처럼 분류 정보를 붙입니다. 주요 속성으로 표시하면 편리합니다. 앱의 고급 기능을 설정하거나 체중 기록의 weight처럼 스크립트에 필요한 정보를 담기도 합니다.

편집 화면에서 추가

상단 리본의 소유한 속성에서 더하기 → 새 라벨 추가를 선택합니다. 노트나 소유한 속성에 초점이 있을 때 Alt+L로도 엽니다. 이름을 입력하고 필요하면 값을 지정합니다. 하위 노트에도 적용하려면 상속 가능을 선택하세요. 속성 상속을 참고하세요.

직접 입력

상단 리본의 소유한 속성에 입력합니다.

미리 정의된 라벨

다음 라벨은 Trilium에서 특별한 기능을 수행합니다. 별표는 같은 접두사로 시작하는 여러 라벨을 뜻합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes.html new file mode 100644 index 0000000..3c890a5 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes.html @@ -0,0 +1,3 @@ +

주요 속성은 자주 사용하는 속성을 노트의 주 화면에 입력란으로 표시하는 기능입니다.

주요 속성 입력란

각 입력란은 일반 속성과 같은 값을 저장합니다. 검색이나 스크립트에서 사용할 속성을 매번 메뉴에서 찾지 않고 바로 확인하고 수정할 수 있습니다.

속성 정의

속성의 이름과 값은 문자열입니다. 속성 정의는 값을 글자나 날짜 등 어떤 형식으로 해석할지와 여러 값을 허용할지 및 주요 속성으로 표시할지를 지정합니다.

속성 정의 예시

실제 값을 저장하는 속성과 그 형식을 지정하는 속성은 별개입니다. 형식 정의에 상속을 설정하면 하위 트리 전체에 공통으로 적용하고 값은 각 노트에 따로 지정할 수 있습니다.

역방향 관계

배우자 관계처럼 양쪽에 같은 이름의 관계가 필요한 경우가 있습니다. 한 노트에서 다른 노트로 isPartnerOf를 연결했다면 반대 방향에도 같은 관계가 있어야 합니다.

부모와 자녀는 방향에 따라 이름이 다릅니다. 부모에서 자녀로는 isParentOf를 사용하고 반대쪽에는 isChildOf를 사용할 수 있습니다.

관계 정의에서 서로의 역방향 관계 이름을 지정하면 자동으로 관리할 수 있습니다. 부모·자녀 예제에서는 각 관계의 정의에 상대 관계 이름을 지정해야 합니다. 관계를 저장하면 대상 노트의 역방향 관계도 확인하고 생성합니다. 관계를 삭제하면 대응하는 역방향 관계도 삭제합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 주요 속성 입력란

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 속성 정의 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes_image.png new file mode 100644 index 0000000..ecb5f2d Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes_promot.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes_promot.png new file mode 100644 index 0000000..cca8683 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Promoted Attributes_promot.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Relations.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Relations.html new file mode 100644 index 0000000..1bbd5ad --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes/Relations.html @@ -0,0 +1,5 @@ +

관계는 라벨과 비슷하지만 텍스트 값 대신 다른 노트를 가리킵니다.

활용 방법

편집 화면에서 만들기

상단 리본의 소유한 속성에서 더하기 버튼을 누르고 새 관계 추가를 선택합니다. 노트나 소유한 속성에 초점이 있을 때 Alt+L을 눌러도 편집 화면이 열립니다.

관계 이름과 대상 노트를 지정합니다. 관계에는 대상 노트가 반드시 있어야 합니다. 하위 노트에도 적용하려면 상속 가능을 선택하세요. 속성 상속을 참고하세요.

직접 입력하기

상단 리본의 소유한 속성에서 ~myRelation=@를 입력합니다. 자동 완성 목록에 대상 제목을 입력한 다음 Enter를 누르거나 원하는 노트를 선택합니다. 노트 트리에서 노트를 복사했다면 @ 없이 = 뒤에 붙여 넣을 수도 있습니다.

상속 가능한 관계는 ~myRelation 대신 ~myRelation(inheritable)로 입력합니다.

미리 정의된 관계

다음 관계는 Trilium에서 특별한 기능을 수행합니다. 이름 끝의 별표는 같은 접두사로 시작하는 여러 관계를 뜻합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes_image.png new file mode 100644 index 0000000..f0d2a63 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Attributes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Bulk Actions.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Bulk Actions.html new file mode 100644 index 0000000..210a377 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Bulk Actions.html @@ -0,0 +1,6 @@ +

일괄 작업 설정

일괄 작업으로 여러 노트에 라벨을 추가하거나 지우고 스크립트를 실행할 수 있습니다.

사용 방법

노트 트리에서 노트 하나를 선택하거나 여러 노트 선택 방법으로 대상을 지정합니다. 노트 트리의 마우스 오른쪽 메뉴에서 고급 → 일괄 작업 적용을 선택합니다.

기본 대상은 선택한 노트뿐입니다. 하위 노트도 처리하려면 선택한 노트의 하위 항목 포함을 선택하세요. 위쪽의 대상 노트 수가 갱신됩니다. 사용 가능한 작업에서 항목을 선택하고 선택한 작업 영역에서 세부 값을 지정합니다. 같은 유형의 작업을 여러 번 추가할 수 있으며 오른쪽 X로 제거합니다. 설정을 마친 뒤 일괄 작업 실행을 누릅니다. 마지막 설정은 다음에 창을 열 때 복원됩니다.

라벨 작업

라벨을 다음과 같이 관리합니다.

관계 작업

관계의 추가와 대상 변경 및 이름 변경과 삭제를 지원합니다. 추가는 지정한 노트를 가리키는 관계를 만듭니다. 나머지 작업은 해당 관계가 있는 노트만 처리합니다. 이름을 바꿔도 대상 노트는 유지됩니다.

노트 작업

노트 이름 변경은 모든 대상의 제목을 지정한 값으로 바꿉니다. FNote 정보에 접근하는 템플릿 문자열도 사용할 수 있습니다. 새 항목: ${note.title}은 제목 앞에 문구를 붙입니다. ${note.dateCreatedObj.format('MM-DD')}: ${note.title}은 만든 날짜를 월·일 형식으로 붙입니다.

노트 이동은 지정한 상위 노트 아래로 옮깁니다. 간단한 이동은 노트 트리에서 잘라내기와 붙여넣기 또는 메뉴로 처리해도 됩니다. 노트 삭제는 대상을 삭제합니다. 노트 트리에서 선택하고 Delete를 누르는 방법도 있습니다. 노트 수정 이력 삭제는 대상의 모든 수정 이력을 지웁니다.

스크립트 실행

복잡한 작업은 JavaScript로 작성할 수 있습니다. 다음 예제는 제목 뒤에 문구를 붙입니다.

note.title = note.title + " - 추가 문구";

다음 예제는 #shareAlias 라벨을 노트 제목으로 설정합니다.

note.setLabel("shareAlias", note.title)
+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 일괄 작업 설정

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Bulk Actions_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Bulk Actions_image.png new file mode 100644 index 0000000..da70055 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Bulk Actions_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Configuration (config.ini or e.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Configuration (config.ini or e.html new file mode 100644 index 0000000..7e01ac5 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Configuration (config.ini or e.html @@ -0,0 +1,4 @@ +

Trilium은 config.ini 파일과 환경 변수로 설정할 수 있습니다. 지원하는 항목은 config-sample.ini 예제와 Notes 저장소를 참고하세요.

환경 변수는 다음 규칙을 따릅니다.

예를 들어 설정 파일에 다음 내용이 있다고 가정합니다.

[Network]
+host=localhost
+port=8080

다음 환경 변수로 값을 바꿀 수 있습니다.

TRILIUM_NETWORK_HOST=0.0.0.0
+TRILIUM_NETWORK_PORT=9000

설정은 다음 순서로 읽습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing .html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing .html new file mode 100644 index 0000000..5084da8 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Cross-Origin Resource Sharing .html @@ -0,0 +1 @@ +

기본 설정에서는 다른 도메인이나 출처의 웹페이지가 브라우저를 통해 Trilium에 요청하는 것을 허용하지 않습니다.

Trilium 0.93.0부터 환경 변수나 config.ini를 사용해 교차 출처 리소스 공유(CORS)를 설정할 수 있습니다.

CORS 헤더환경 변수config.ini의 Network 구역 설정
Access-Control-Allow-OriginTRILIUM_NETWORK_CORS_ALLOW_ORIGINcorsAllowOrigin
Access-Control-Allow-MethodsTRILIUM_NETWORK_CORS_ALLOW_METHODScorsAllowMethods
Access-Control-Allow-HeadersTRILIUM_NETWORK_CORS_ALLOW_HEADERScorsAllowHeaders
diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance.html new file mode 100644 index 0000000..35edaf3 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Configuration (config.ini or environment variables)/Trilium instance.html @@ -0,0 +1,3 @@ +

Trilium 인스턴스는 실행 중인 서버 하나를 뜻합니다. 동기화를 구성하면 데스크톱 앱 내부의 서버와 동기화 대상 서버 등 여러 인스턴스를 사용하게 됩니다. 이때 현재 어느 인스턴스에서 실행 중인지 구분하면 편리합니다.

인스턴스 이름 지정

config.ini에 다음과 같이 이름을 설정하세요.

[General]
+instanceName=내서버

서버에서 인스턴스 구분

api.getInstanceName()을 호출하면 설정 파일이나 환경 변수에 지정한 현재 서버의 인스턴스 이름을 얻을 수 있습니다.

특정 인스턴스에서만 스크립트 실행

정기적으로 실행하거나 특정 이벤트에 반응하는 스크립트를 일부 인스턴스에서만 실행할 수 있습니다. 코드를 바꿀 필요 없이 runOnInstance 라벨의 값에 실행할 인스턴스 이름을 넣으세요. 여러 인스턴스에서 실행하려면 라벨을 여러 개 추가하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Custom Request Handler.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Custom Request Handler.html new file mode 100644 index 0000000..eb7bcef --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Custom Request Handler.html @@ -0,0 +1,26 @@ +

스크립트로 공개 REST 요청을 처리할 수 있습니다. 외부 서비스에서 제목과 본문을 보내 노트를 만드는 등의 연동에 사용합니다.

외부 요청으로 노트 만들기

다음은 백엔드 JavaScript 코드 노트예제입니다. 예시 비밀값을 그대로 공개 서비스에 사용하면 안 됩니다.

const {req, res} = api;
+const {secret, title, content} = req.body;
+
+if (req.method == 'POST' && secret === 'secret-password') {
+    // 노트를 저장할 상위 노트를 지정합니다. 
+    // 이 코드 노트의 관계로 대상 상위 노트를 연결합니다.
+    // 간단한 예제에서는 노트 정보에서 확인한 고정 ID를 사용할 수도 있습니다.
+    const targetParentNoteId = api.currentNote.getRelationValue('targetNote');
+    
+    const {note} = api.createTextNote(targetParentNoteId, title, content);
+    const notePojo = note.getPojo();
+
+    res.status(201).json(notePojo);
+}
+else {
+    res.send(400);
+}

#customRequestHandler=create-note 라벨과 저장할 위치를 가리키는 ~targetNote 관계를 지정합니다.

요청 예시

POST http://my.trilium.org/custom/create-note
+Content-Type: application/json
+
+{
+  "secret": "secret-password",
+  "title": "인사",
+  "content": "안녕하세요."
+}

/custom 아래 요청은 customRequestHandler 라벨이 있는 노트에서 처리기를 찾습니다. 라벨 값은 경로에 대응하는 정규식입니다. 찾은 스크립트에는 Express의 요청 객체와 응답 객체가 api.req와 api.res로 제공됩니다.

이 경로는 기본 인증을 자동으로 요구하지 않습니다. 처리기에서 인증을 구현해야 합니다. 예제는 POST 방식과 비밀값을 확인한 뒤 스크립트 API로 노트를 만듭니다.

파일 제공

파일만 제공하려면 customResourceProvider 라벨에 경로 정규식을 지정할 수 있습니다. 사용자 지정 리소스 제공을 참고하세요.

고급 사용

요청과 응답 객체의 기능은 Express 공식 문서에서 확인할 수 있습니다.

경로 매개변수

http://my.trilium.org/custom/notes/123

마지막 숫자처럼 바뀌는 부분을 정규식으로 받을 수 있습니다.

notes/([0-9]+)

괄호로 묶은 일치 결과는 api.pathParams에 들어갑니다.

const noteId = api.pathParams[0];

?noteId=123 같은 쿼리 매개변수는 req.query.noteId로 읽습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Custom Resource Providers.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Custom Resource Providers.html new file mode 100644 index 0000000..531a311 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Custom Resource Providers.html @@ -0,0 +1,8 @@ +

사용자 지정 리소스 제공 기능은 Trilium에 가져온 이미지와 글꼴 및 스타일시트 등의 파일을 공개 주소로 제공합니다. 테마와 함께 사용자 글꼴을 제공할 때 활용할 수 있습니다.

설정 순서

hello 대신 다음과 같은 이름도 사용할 수 있습니다.

테마에서 사용하기

글꼴 파일을 가져온 뒤 #customResourceProvider=fonts/myfont.ttf 속성을 지정하세요. 테마 CSS에서는 다음처럼 불러올 수 있습니다.

@font-face {
+	font-family: customFont;
+	src: url("/custom/fonts/myfont.ttf");
+}
+
+div {
+	font-family: customFont;
+}
diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database.html new file mode 100644 index 0000000..9f71633 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database.html @@ -0,0 +1 @@ +

Trilium은 노트와 트리 구조 및 메타데이터와 대부분의 설정을 SQLite 데이터베이스에 저장합니다. 파일 이름은 document.db이며 기본 데이터 폴더에 있습니다.

사용 예제

처음 실행하면 주요 기능을 소개하는 예제 노트를 제공합니다. 사용 예제를 참고하세요.

데이터베이스 직접 수정하기

고급 사용자는 DB Browser for SQLite 같은 도구로 데이터베이스를 살펴보거나 수정할 수 있습니다. 자세한 내용은 데이터베이스 직접 수정하기를 참고하세요.

데이터베이스 초기화하기

시험 중인 환경을 초기 상태로 되돌리려면 기존 데이터베이스를 제거할 수 있습니다. 다음 실행 시 원본 예제 노트가 포함된 새 데이터베이스를 만듭니다. 기존 노트가 사라지므로 필요한 데이터를 먼저 백업하고 애플리케이션을 종료하세요.

데이터 폴더에서 document.db와 이름이 document.db로 시작하는 관련 파일을 제거합니다.

config.ini의 설정도 보존할 필요가 없다면 데이터 폴더의 내용을 모두 제거해 초기화할 수 있습니다. 파일 대신 환경 변수로 설정하는 방법은 설정 안내를 참고하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Demo Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Demo Notes.html new file mode 100644 index 0000000..4461900 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Demo Notes.html @@ -0,0 +1 @@ +

Trilium을 처음 실행하면 사용 예제가 포함된 데이터베이스를 만듭니다. 예제에서는 다음 기능을 살펴볼 수 있습니다.

사용 예제 복원하기

고급 기능을 시험한 뒤 원래 예제를 다시 확인하고 싶거나 새 기능이 추가된 최신 예제를 살펴보고 싶을 때 원본 예제를 가져올 수 있습니다.

Trilium의 가져오기 기능을 사용하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the data.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the data.png new file mode 100644 index 0000000..469899e Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the data.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database.html new file mode 100644 index 0000000..19e7cbe --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database.html @@ -0,0 +1,3 @@ +

고급 개발이나 문제 해결 과정에서 Trilium의 SQLite 데이터베이스를 직접 수정해야 할 때가 있습니다. 수정하기 전에 document.db를 백업하세요.

내장 SQL 콘솔 사용하기

Trilium에는 데이터베이스 편집기가 내장되어 있습니다. SQL 콘솔을 참고하세요.

외부 도구로 수정하기

애플리케이션이 실행되지 않는 경우처럼 SQL 콘솔을 사용할 수 없을 때는 외부 도구를 이용할 수 있습니다. 데스크톱 앱을 종료하거나 서버 서비스와 Docker 컨테이너를 중지한 뒤 작업하세요.

DB Browser for SQLite 사용하기

여러 운영체제에서 사용할 수 있는 그래픽 데이터베이스 편집기입니다.

외부 데이터베이스 편집기 사용 예시

SQLite 명령줄 도구 사용하기

데이터베이스 경로를 지정해 실행하세요.

sqlite3 ~/.local/share/trilium-data/document.db
+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 외부 데이터베이스 편집기 사용 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/1_SQL Console_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/1_SQL Console_image.png new file mode 100644 index 0000000..6f32f76 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/1_SQL Console_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/2_SQL Console_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/2_SQL Console_image.png new file mode 100644 index 0000000..1b1834b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/2_SQL Console_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/3_SQL Console_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/3_SQL Console_image.png new file mode 100644 index 0000000..ccef8f7 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/3_SQL Console_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console.html new file mode 100644 index 0000000..22e698c --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console.html @@ -0,0 +1,3 @@ +

SQL 콘솔은 Trilium에 내장된 데이터베이스 편집기입니다.

전체 메뉴 → 고급 → SQL 콘솔 열기에서 실행할 수 있습니다.

SQL 콘솔 화면

사용 방법

SQL 콘솔 저장하기

SQL 조회문이나 명령을 전용 노트로 저장할 수 있습니다. SQL 문을 작성한 뒤 저장 버튼을 누르세요. 저장한 노트는 날짜별 노트에 나타납니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · SQL 콘솔 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · SQL 조회 결과

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console_image.png new file mode 100644 index 0000000..32a91fc Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Database/Manually altering the database/SQL Console_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Default Note Title.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Default Note Title.html new file mode 100644 index 0000000..11b60e0 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Default Note Title.html @@ -0,0 +1,2 @@ +

새 노트의 기본 제목은 새 노트입니다. 다른 제목이나 생성 시점에 따라 달라지는 제목을 사용하려면 #titleTemplate 라벨을 지정하세요. 이 기능은 0.52부터 지원합니다.

상위 노트에 라벨과 값을 지정하면 하위 노트를 만들 때 그 값을 제목으로 사용합니다. 상속을 켜면 더 아래 단계에도 적용됩니다. 최상위 노트에 지정하면 전체 노트에 적용할 수 있습니다.

예를 들어 2022년에 읽은 책 아래에 닐 스티븐슨의 아나뎀과 프란츠 카프카의 변신을 기록한다고 가정해 보겠습니다. 상위 노트에 #titleTemplate="[저자]의 [책 제목] ([출간 연도])"를 지정하면 새 하위 노트의 제목이 이 형식으로 만들어집니다.

정보를 자동으로 추론하는 기능은 아닙니다. 대괄호 부분은 사용자가 직접 채워 넣는 자리입니다.

동적으로 제목 만들기

제목 템플릿은 노트를 만드는 순간 JavaScript 문자열로 평가됩니다. 문자열 보간을 사용하면 날짜나 상위 노트의 값을 넣을 수 있습니다. parentNote 변수는 상위 노트의 FNote 객체를 제공합니다.

본문까지 기본 내용을 지정하려면 템플릿도 참고하세요.

예제

서버 장애 기록을 날짜별로 남긴다면 상위 노트에 #titleTemplate="${now.format('YYYY-MM-DD')}: "를 지정하세요. 새 노트를 만들 때 now 날짜 객체를 사용해 날짜가 입력됩니다. 이후 시스템 중단이나 백업 지연처럼 사건 이름을 덧붙이면 됩니다.

상위 노트의 저자 속성을 사용하려면 #titleTemplate="${parentNote.getLabelValue('authorName')}의 작품"을 사용하세요. 상위 노트의 제목을 그대로 사용하려면 ${parentNote.title}을 지정합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/ETAPI (REST API).html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/ETAPI (REST API).html new file mode 100644 index 0000000..761d7ed --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/ETAPI (REST API).html @@ -0,0 +1,11 @@ +

ETAPI는 외부 프로그램에서 Trilium을 사용하는 REST API입니다. 0.50부터 제공됩니다. 명세는 OpenAPI 문서에서 확인할 수 있습니다.

클라이언트 라이브러리

trilium-py를 사용하면 Python에서 Trilium에 접근하는 코드를 더 쉽게 작성할 수 있습니다.

토큰 발급

모든 API 작업은 토큰으로 인증해야 합니다. 설정 → ETAPI에서 발급하거나 /auth/login 요청으로 받을 수 있습니다. 자세한 요청 형식은 API 명세를 참고하세요.

인증

Authorization 헤더

GET https://myserver.com/etapi/app-info
+Authorization: ETAPITOKEN

ETAPITOKEN을 발급받은 토큰으로 바꾸세요. 0.93.0부터는 다른 도구와의 호환성을 위해 Bearer ETAPITOKEN 형식도 지원합니다.

기본 인증

0.56부터 다음 형식도 지원합니다.

GET https://myserver.com/etapi/app-info
+Authorization: Basic BATOKEN

기본 인증만 지원하는 도구에서 사용할 수 있는 방식입니다.

Bash 스크립트 예제

다음 예제는 노트의 HTML 본문을 내려받습니다.

#!/usr/bin/env bash
+
+# 연결 설정
+TOKEN=YOUR_ETAPI_TOKEN
+SERVER=http://localhost:8080
+
+# 노트 ID로 본문 내려받기
+NOTE_ID="i6ra4ZshJhgN"
+curl "$SERVER/etapi/notes/$NOTE_ID/content" -H "Authorization: $TOKEN" 

실행 전에 다음 값을 바꾸세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/ETAPI (REST API)/API Reference.dat b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/ETAPI (REST API)/API Reference.dat new file mode 100644 index 0000000..e69de29 diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Hidden Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Hidden Notes.html new file mode 100644 index 0000000..145c8b6 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Hidden Notes.html @@ -0,0 +1,15 @@ +

숨겨진 노트 트리

Trilium은 여러 기능의 정보를 실제 노트로 저장합니다. 덕분에 속성과 관계 및 검색과 링크를 활용할 수 있습니다. 트리가 복잡해지거나 실수로 지우는 일을 줄이기 위해 기본적으로 숨겨 둡니다. 일반 노트처럼 데이터베이스에 저장되지만 특별한 노트 ID로 구분합니다.

숨겨진 트리 열기

전체 메뉴에서 고급 → 숨겨진 하위 트리 표시를 선택합니다.

구성

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 숨겨진 노트 트리

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Hidden Notes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Hidden Notes_image.png new file mode 100644 index 0000000..eb59b57 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Hidden Notes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Internal API/API Reference.dat b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Internal API/API Reference.dat new file mode 100644 index 0000000..e69de29 diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics.html new file mode 100644 index 0000000..d4586f2 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics.html @@ -0,0 +1,28 @@ +

측정 지표 API는 Prometheus 같은 외부 모니터링 시스템에 Trilium 상태를 제공합니다.

접속

GET /etapi/metrics로 요청합니다. ETAPI 토큰이 필요하며 기본 응답은 Prometheus 텍스트 형식입니다.

# ETAPI 토큰 발급 예시
+curl -X POST http://localhost:8080/etapi/auth/login \
+  -H "Content-Type: application/json" \
+  -d '{"password": "your_password"}'
+

사용 예시

curl -H "Authorization: YOUR_ETAPI_TOKEN" \
+  http://localhost:8080/etapi/metrics
+

다음과 같은 형식으로 응답합니다. 지표 이름과 형식은 연동을 위해 유지합니다.

# HELP trilium_info Trilium 인스턴스 정보
+# TYPE trilium_info gauge
+trilium_info{version="0.91.6",db_version="231",node_version="v18.17.0"} 1 1701432000
+
+# HELP trilium_notes_total 삭제된 노트를 포함한 전체 노트 수
+# TYPE trilium_notes_total gauge
+trilium_notes_total 1234 1701432000
+

JSON으로 받으려면 다음처럼 요청합니다.

curl -H "Authorization: YOUR_ETAPI_TOKEN" \
+  "http://localhost:8080/etapi/metrics?format=json"
+

제공 지표

Prometheus 설정

prometheus.yml에 추가할 예시입니다.

scrape_configs:
+  - job_name: 'trilium'
+    static_configs:
+      - targets: ['localhost:8080']
+    metrics_path: '/etapi/metrics'
+    bearer_token: 'YOUR_ETAPI_TOKEN'
+    scrape_interval: 30s
+

오류 응답

400은 지원하지 않는 format 값입니다. 401은 토큰이 없거나 유효하지 않다는 뜻이며 500은 서버 내부 오류입니다.

Grafana 대시보드

Trilium 모니터링 대시보드

Grafana 대시보드 JSON을 가져오기 화면에 입력하세요.

대시보드 가져오기 메뉴

JSON을 붙여넣고 불러오기를 누릅니다.

대시보드 JSON 입력

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · Trilium 모니터링 대시보드

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 대시보드 가져오기 메뉴

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 대시보드 JSON 입력

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics/grafana-dashboard.json b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics/grafana-dashboard.json new file mode 100644 index 0000000..a2105b7 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics/grafana-dashboard.json @@ -0,0 +1,1335 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 549, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 100, + "panels": [], + "title": "🏠 Trilium 개요", + "type": "row" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "현재 Trilium 버전과 빌드 정보", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 101, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_info{job=~'$job',instance=~'$instance'}", + "format": "table", + "instant": true, + "refId": "A" + } + ], + "title": "📋 실행 환경 정보", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Value": true, + "__name__": true, + "instance": true, + "job": true + }, + "indexByName": {}, + "renameByName": { + "build_date": "빌드 날짜", + "build_revision": "Git 커밋", + "db_version": "데이터베이스 버전", + "node_version": "Node.js", + "sync_version": "동기화 버전", + "version": "버전" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "읽기 쉬운 단위로 표시한 데이터베이스 파일 크기", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 500000000 + }, + { + "color": "red", + "value": 1000000000 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 1 + }, + "id": 102, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_database_size_bytes{job=~'$job',instance=~'$instance'}", + "refId": "A" + } + ], + "title": "💾 데이터베이스 크기", + "type": "stat" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "현재 Trilium에서 사용 중인 전체 노트 수", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "yellow", + "value": 1000 + }, + { + "color": "red", + "value": 5000 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 1 + }, + "id": 103, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_notes_active{job=~'$job',instance=~'$instance'}", + "refId": "A" + } + ], + "title": "📝 사용 중인 노트", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 200, + "panels": [], + "title": "📊 주요 지표", + "type": "row" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "삭제된 노트를 포함한 전체 노트 수", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 8 + }, + "id": 201, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "values": [] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_notes_active{job=~'$job',instance=~'$instance'}", + "legendFormat": "사용 중인 노트", + "refId": "A" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_notes_deleted{job=~'$job',instance=~'$instance'}", + "legendFormat": "삭제된 노트", + "refId": "B" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_notes_protected{job=~'$job',instance=~'$instance'}", + "legendFormat": "보호된 노트", + "refId": "C" + } + ], + "title": "📝 노트 분포", + "type": "piechart" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "MIME 유형별 첨부 파일 분포", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 8 + }, + "id": 202, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": true, + "values": [] + }, + "pieType": "donut", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_attachments_by_type{job=~'$job',instance=~'$instance'}", + "legendFormat": "{{mime_type}}", + "refId": "A" + } + ], + "title": "🖼️ 유형별 첨부 파일", + "type": "piechart" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "내용 유형별 노트 분포", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 203, + "options": { + "legend": { + "displayMode": "table", + "placement": "right", + "showLegend": true, + "values": [ + "value", + "percent" + ] + }, + "pieType": "donut", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_notes_by_type{job=~'$job',instance=~'$instance'}", + "legendFormat": "{{type}}", + "refId": "A" + } + ], + "title": "📄 내용 유형별 노트", + "type": "piechart" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 300, + "panels": [], + "title": "📈 시간에 따른 변화", + "type": "row" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "시간에 따른 노트 수 변화", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 3, + "pointSize": 8, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "사용 중인 노트" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "전체 노트" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 301, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_notes_active{job=~'$job',instance=~'$instance'}", + "legendFormat": "사용 중인 노트", + "refId": "A" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_notes_total{job=~'$job',instance=~'$instance'}", + "legendFormat": "전체 노트", + "refId": "B" + } + ], + "title": "📈 시간에 따른 노트 수 변화", + "type": "timeseries" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "첨부 파일 저장량 변화", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 3, + "pointSize": 8, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "사용 중인 첨부 파일" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "전체 첨부 파일" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "orange", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 302, + "options": { + "legend": { + "calcs": [ + "last", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_attachments_active{job=~'$job',instance=~'$instance'}", + "legendFormat": "사용 중인 첨부 파일", + "refId": "A" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_attachments_total{job=~'$job',instance=~'$instance'}", + "legendFormat": "전체 첨부 파일", + "refId": "B" + } + ], + "title": "📎 시간에 따른 첨부 파일 수 변화", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "id": 400, + "panels": [], + "title": "🔧 고급 지표", + "type": "row" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "노트를 연결하는 가지 수", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 26 + }, + "id": 401, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_branches_total{job=~'$job',instance=~'$instance'}", + "refId": "A" + } + ], + "title": "🌳 전체 가지", + "type": "stat" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "노트 속성 수", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 6, + "y": 26 + }, + "id": 402, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_attributes_total{job=~'$job',instance=~'$instance'}", + "refId": "A" + } + ], + "title": "🏷️ 속성", + "type": "stat" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "노트 수정 이력 수", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 12, + "y": 26 + }, + "id": 403, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_revisions_total{job=~'$job',instance=~'$instance'}", + "refId": "A" + } + ], + "title": "🔄 수정 이력", + "type": "stat" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "ETAPI 토큰 수", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 18, + "y": 26 + }, + "id": 404, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_etapi_tokens_total{job=~'$job',instance=~'$instance'}", + "refId": "A" + } + ], + "title": "🔑 API 토큰", + "type": "stat" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "저장 공간과 시스템의 주요 지표", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "최근 노트" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 405, + "options": { + "legend": { + "calcs": [ + "last" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_blobs_total{job=~'$job',instance=~'$instance'}", + "legendFormat": "본문 데이터 레코드", + "refId": "A" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_recent_notes_total{job=~'$job',instance=~'$instance'}", + "legendFormat": "최근 노트", + "refId": "B" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_embeddings_total{job=~'$job',instance=~'$instance'}", + "legendFormat": "임베딩", + "refId": "C" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_embedding_providers_total{job=~'$job',instance=~'$instance'}", + "legendFormat": "임베딩 제공자", + "refId": "D" + } + ], + "title": "📊 저장 공간과 시스템 지표", + "type": "timeseries" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "description": "콘텐츠 생성 시각과 마지막 수정 시각", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "points", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 8, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "dateTimeAsIso" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 406, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "12.0.1", + "targets": [ + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_oldest_note_timestamp{job=~'$job',instance=~'$instance'} * 1000", + "legendFormat": "가장 오래된 노트", + "refId": "A" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_newest_note_timestamp{job=~'$job',instance=~'$instance'} * 1000", + "legendFormat": "가장 최근 노트", + "refId": "B" + }, + { + "datasource": { + "uid": "${datasource}" + }, + "expr": "trilium_last_modified_timestamp{job=~'$job',instance=~'$instance'} * 1000", + "legendFormat": "마지막 수정", + "refId": "C" + } + ], + "title": "⏰ 콘텐츠 생성 및 수정 시각", + "type": "timeseries" + } + ], + "preload": false, + "refresh": "1m", + "schemaVersion": 41, + "tags": [ + "trilium", + "notes", + "monitoring", + "enhanced" + ], + "templating": { + "list": [ + { + "current": { + "text": "myprom", + "value": "PA04845DA3A4B088E" + }, + "includeAll": false, + "label": "데이터 소스", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "//", + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "UID": "", + "type": "" + }, + "includeAll": true, + "label": "작업", + "multi": true, + "name": "job", + "options": [], + "query": "query_result(up)", + "refresh": 1, + "regex": "/job=\"([^\"]+)\"/", + "sort": 1, + "type": "query" + }, + { + "allValue": ".*", + "current": { + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "includeAll": true, + "label": "실행 환경", + "multi": true, + "name": "instance", + "options": [], + "query": "trilium_database_size_bytes", + "refresh": 1, + "regex": "/instance=\"([^\"]+)\"/", + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "TriliumNext 대시보드", + "uid": "06993f9b-a477-4723-bf18-47743393b382", + "version": 5 +} diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics_image.png new file mode 100644 index 0000000..ae68ddd Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Metrics_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note ID.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note ID.html new file mode 100644 index 0000000..07bff22 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note ID.html @@ -0,0 +1,2 @@ +

Trilium은 파일 이름 대신 노트 ID로 각 노트를 구분합니다. 일반적으로 새 노트를 만들 때 영문 대소문자와 숫자로 이루어진 12자리 ID를 무작위로 생성합니다.

가져오기와 내보내기의 영향

노트를 내보내면 ID도 메타데이터에 기록됩니다. 하지만 다시 가져올 때는 모든 노트에 새 ID를 부여합니다. 첨부 파일처럼 함께 가져오는 다른 항목도 새 ID를 받습니다.

ID 충돌

ID는 길이가 정해져 있고 무작위로 만들어지므로 비둘기집 원리에 따라 기존 노트와 같은 ID가 생성될 가능성이 있습니다.

사용할 수 있는 문자가 62개이고 길이가 12자리이므로 가능한 ID 수는 \(62^{12}\)개입니다. 원문은 Nano ID 충돌 계산기를 이용해 매시간 1000개의 노트를 약 900년 동안 만들어야 충돌 확률이 1% 정도가 된다고 설명합니다.

이처럼 가능성이 매우 작아 Trilium은 별도의 충돌 방지 절차를 두지 않습니다. 고유 해시를 사용하는 Git에도 비슷한 문제가 있습니다. 이론적으로 충돌이 발생하면 기존 노트를 새 노트가 덮어쓸 가능성이 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree m.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree m.png new file mode 100644 index 0000000..2d41fd6 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree m.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map).html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map).html new file mode 100644 index 0000000..c5cbd80 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note Map (Link map, Tree map).html @@ -0,0 +1,3 @@ +

노트 지도는 노트 사이의 연결을 시각적으로 보여 줍니다. 노트들이 어떤 구조로 묶여 있는지 파악할 수 있습니다.

다음 두 가지 보기가 있습니다.

링크 지도

노트 사이의 관계를 보여 줍니다.

링크 지도

트리 지도

노트의 상위·하위 구조를 보여 줍니다.

트리 지도

독립된 노트 유형

모든 노트에서 열 수 있는 지도 기능 외에 관계를 전체 화면에 표시하는 전용 노트를 만들 수도 있습니다. 노트 지도 유형을 참고하세요.

관련 기능

관계 지도는 비슷한 기능이지만 다음과 같은 차이가 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 링크 지도

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 트리 지도

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note source.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note source.html new file mode 100644 index 0000000..b9720b0 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note source.html @@ -0,0 +1,18 @@ +

노트의 내부 형식

본문을 저장하는 방식은 노트 유형마다 다릅니다.

일부 정보는 첨부 파일에 저장합니다. 캔버스는 사용자 라이브러리를 첨부하며 마인드맵 등은 다른 노트에 포함하거나 공유할 때 사용할 SVG 미리보기도 첨부합니다.

다음은 이 문서의 HTML 형식을 설명하는 예제입니다.

<h2>
+	노트의 내부 형식
+</h2>
+<p>
+	본문을 저장하는 방식은 다음 유형에 따라 다릅니다.&nbsp;
+	<a class="reference-link" href="#root/_help_KSZ04uQ2D1St">
+		노트 유형
+	</a>
+	.
+</p>

소스 보기

노트 메뉴에서 노트 소스를 선택하면 새 탭에서 열립니다. 텍스트 노트처럼 일부 유형은 읽기 편하도록 들여쓰기를 적용합니다.

노트 소스 화면

소스 수정

소스 보기 화면에서 직접 편집할 수는 없습니다. 수정하려면 노트 유형을 일반 텍스트나 JSON 또는 HTML 코드로 바꾸고 경고를 확인한 뒤 본문을 고치세요. 작업 후에는 원래 유형으로 되돌립니다.

형식을 잘못 수정하면 노트가 표시되지 않을 수 있습니다. 먼저 이전 버전을 저장하세요. 문제가 생기면 소스를 다시 수정하거나 이전 버전으로 복원합니다. 화면이 정상으로 돌아오지 않으면 새로고침이 필요할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 소스 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note source_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note source_image.png new file mode 100644 index 0000000..71f0ddf Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Note source_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing.html new file mode 100644 index 0000000..bb182ee --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing.html @@ -0,0 +1,14 @@ +

선택한 노트를 누구나 읽을 수 있는 웹문서로 공개합니다. 공유 화면은 읽기 전용입니다.

공유 페이지

기능과 제한

제목 검색과 모바일 화면을 지원합니다. 브라우저 설정에 따라 밝은 모드와 어두운 모드를 적용하며 직접 전환한 설정도 기억합니다. 트리를 접거나 펼치고 로고를 바꿀 수 있습니다. 이전·다음 노트 이동과 마지막 수정 날짜도 표시합니다.

공유 트리는 정적인 구조이며 보호된 노트는 공유할 수 없습니다.

공유하기

서버 설치가 필요합니다. 노트 화면에서 공유 스위치를 켜면 접근할 URL이 나타납니다.

노트 공유 스위치

표시된 링크를 브라우저에서 엽니다. 서버 주소 설정에 따라 localhost 주소가 보일 수도 있습니다. 외부 접속에는 외부에서 접근 가능한 서버 주소가 필요합니다.

하위 트리

노트를 공유하면 그 아래의 하위 노트도 함께 공유됩니다. 공유 노트 하위 트리 표시에서 전체 공개 목록을 확인할 수 있습니다.

접근 범위

별도 인증을 설정하지 않은 공유 문서는 URL을 아는 누구나 열 수 있습니다. 무작위 주소는 접근 제어를 대신하지 않습니다. 공개할 자료인지 확인하세요.

암호 설정

#shareCredentials="username:password" 형식으로 사용자 이름과 암호를 지정합니다. 하위 노트와 이미지에도 적용하려면 상속 가능으로 설정합니다.

공유 화면 꾸미기

CSS 코드 노트를 만들고 ~shareCss 관계로 연결합니다. 하위 트리 전체에 적용하려면 관계를 상속 가능으로 설정합니다. CSS 노트에 #shareHiddenFromTree를 추가하면 탐색 트리에서 숨깁니다. #shareOmitDefaultCss는 기본 스타일을 제외합니다.

JavaScript

~shareJs 관계로 스크립트를 넣습니다. fetchNote()로 노트 정보를 읽을 수 있습니다. 다음 예제는 상위 노트의 속성을 출력합니다.

const currentNote = await fetchNote();
+const parentNote = await fetchNote(currentNote.parentNoteIds[0]);
+
+for (const attr of parentNote.attributes) {
+    console.log(attr.type, attr.name, attr.value);
+}

읽기 쉬운 주소

보통 주소 끝에는 노트 ID가 붙습니다. #shareAlias=highlighting을 지정하면 http://domain.tld/share/highlighting처럼 사용할 수 있습니다. 별칭은 중복되지 않아야 하며 슬래시로 하위 경로를 만드는 방식은 지원하지 않습니다.

공유 목록 관리

공유 노트 영역에서 목록을 확인하고 이동이나 복제로 공유 상태를 관리할 수 있습니다.

공유 노트 목록

아이콘과 시작 페이지

~shareFavicon 관계로 .ico 같은 아이콘 파일 노트를 지정합니다. #shareRoot가 있는 노트는 http://domain.tld/share의 시작 페이지가 됩니다. #shareIndex를 함께 사용하면 공유 루트 목록을 보여 줄 수 있습니다.

속성 안내

제작에 도움을 준 프로젝트

0.95.0부터 기본 적용된 공유 테마는 Trilium Rocks!를 바탕으로 합니다. 원작자는 zerebos입니다. 모바일 화면과 밝기 전환 및 접을 수 있는 트리 등을 제공합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 공유 페이지

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 노트 공유 스위치

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 공유 노트 목록

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/1_Serving directly the conte.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/1_Serving directly the conte.png new file mode 100644 index 0000000..2359229 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/1_Serving directly the conte.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/Serving directly the conte.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/Serving directly the conte.png new file mode 100644 index 0000000..bab0f97 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/Serving directly the conte.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o.html new file mode 100644 index 0000000..d61b8dc --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing/Serving directly the content o.html @@ -0,0 +1,4 @@ +

공유 노트를 열면 기본적으로 웹페이지 형태로 표시됩니다. 스크립트에서 이용하거나 파일로 내려받을 때는 원본 내용을 그대로 제공하는 편이 나을 수 있습니다.

웹페이지로 표시한 노트원본 형식으로 표시한 노트
웹페이지 형태의 공유 노트원본 형식의 공유 노트

노트 속성으로 지정

#shareRaw 속성을 추가하면 공유 주소로 접근할 때 항상 원본 형식으로 제공합니다.

주소에 옵션 추가

주소 끝에 ?raw를 붙이면 #shareRaw 속성이 없어도 원본 형식으로 볼 수 있습니다.

주소로 원본 형식 요청

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 웹페이지 형태의 공유 노트

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 원본 형식의 공유 노트

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 주소로 원본 형식 요청

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing_image.png new file mode 100644 index 0000000..4c92b90 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing_share-single-note.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing_share-single-note.png new file mode 100644 index 0000000..87b99ca Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing_share-single-note.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing_shared-list.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing_shared-list.png new file mode 100644 index 0000000..8002303 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Sharing_shared-list.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used.html new file mode 100644 index 0000000..8c6c897 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used.html @@ -0,0 +1,2 @@ +

Trilium은 이미 개발된 여러 라이브러리를 활용해 다양한 노트 유형을 지원합니다.

하위 문서에서는 사용 중인 기술을 소개합니다. Trilium의 작동 방식을 이해하는 데 도움을 주고 각 기술을 만든 개발자들의 기여를 알리기 위한 문서입니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/CKEditor.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/CKEditor.html new file mode 100644 index 0000000..491b0b4 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/CKEditor.html @@ -0,0 +1 @@ +

편집기 구성

CKEditor는 텍스트 노트에서 사용하는 편집기입니다. 편집하는 화면과 결과가 같은 방식으로 표시됩니다. 공식 사이트는 ckeditor.com입니다.

CKEditor는 상용 제품이지만 핵심 코드는 오픈 소스로 제공됩니다. 공식 기능 안내에 설명된 기능 중 일부를 Trilium에서 사용합니다. 모든 기능이 활성화된 것은 아닙니다.

유료 기능

일부 기능은 별도의 상용 라이선스가 필요합니다. 원문 작성 당시에는 Trilium에서 이 기능들을 사용할 수 없었으며 슬래시 명령 같은 일부 기능의 사용 가능성을 CKEditor 팀과 논의 중이라고 설명했습니다.

플러그인

플러그인을 작성하면 편집기에 새로운 기능을 추가할 수 있습니다. Trilium에서는 다음 플러그인을 사용하거나 필요한 부분을 수정해 사용합니다.

Trilium 전용 기능도 플러그인으로 구현했습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw.html new file mode 100644 index 0000000..122597d --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/Excalidraw.html @@ -0,0 +1 @@ +

Excalidraw는 캔버스 노트에 사용하는 기술입니다. 소스 코드는 GitHub에서 확인할 수 있습니다.

수정하지 않은 원본 라이브러리를 사용하므로 원본에 알려진 문제가 여기에도 나타날 수 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/Leaflet.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/Leaflet.html new file mode 100644 index 0000000..02992fe --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/Leaflet.html @@ -0,0 +1 @@ +

Leaflet은 지도 노트에 사용하는 라이브러리입니다.

플러그인

외부 플러그인을 이용해 기능을 폭넓게 확장할 수 있습니다.

현재 다음 플러그인을 사용합니다:

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/MindElixir.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/MindElixir.html new file mode 100644 index 0000000..309369e --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Technologies used/MindElixir.html @@ -0,0 +1 @@ +

MindElixir는 마인드맵 노트에 사용하는 라이브러리입니다.

핵심 라이브러리는 GitHub의 mind-elixir-core에서 확인할 수 있습니다.

기본 배포판에서는 라이브러리를 추가 수정 없이 포함합니다.

라이브러리 자체의 기능에 문제가 있다면 일반적으로 원본 프로젝트에 보고하는 것이 좋습니다.

플러그인

MindElixir는 플러그인을 지원합니다. Trilium에서는 node-menu 플러그인을 이용해 항목의 글꼴과 색상 및 링크를 편집할 수 있게 합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates.html new file mode 100644 index 0000000..b842caa --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates.html @@ -0,0 +1,4 @@ +

템플릿은 다른 노트의 기본 구조를 정하는 노트입니다. 템플릿을 적용받는 노트에는 다음 효과가 있습니다.

예제

책 템플릿에는 출간 연도와 저자 같은 주요 속성을 넣고 주제와 결론 등의 독후감 틀을 작성할 수 있습니다. 인상 깊은 구절과 요약용 하위 노트도 함께 만들 수 있습니다.

책 템플릿

템플릿 적용 노트

메뉴에서 템플릿을 선택해 노트를 만들 수 있습니다.

하위 노트 템플릿 선택

선택 목록에 나오게 하려면 템플릿 노트에 #template 라벨을 지정하세요. 대상 노트를 연결하는 ~template 관계와는 다릅니다. 작업 공간에서만 표시하려면 #workspaceTemplate을 사용합니다.

이미 만든 노트도 ~template 관계를 추가하거나 바꿔 템플릿을 지정할 수 있습니다. 새 하위 노트의 기본 템플릿은 ~child:template로 지정합니다. ~child:child:template처럼 여러 단계에 적용할 수도 있습니다.

복사 상속은 노트를 만드는 시점에 적용됩니다. 상위 노트의 설정을 나중에 바꿔도 기존 하위 노트에 복사되어 있는 단계별 설정이 자동으로 갱신되지는 않습니다.

추가 활용

#iconClass와 #cssClass를 템플릿에 지정하면 관련 노트의 아이콘과 모양을 통일할 수 있습니다. 사용 예제의 관계 지도와 할 일 관리 및 날짜별 노트를 참고하세요.

기본 노트 제목의 제목 템플릿과 함께 사용할 수도 있습니다. 노트 템플릿에 #titleTemplate을 지정하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 책 템플릿

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 하위 노트 템플릿 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates_template-create-.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates_template-create-.png new file mode 100644 index 0000000..e0de7dc Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates_template-create-.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates_template.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates_template.png new file mode 100644 index 0000000..72af71a Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Advanced Usage/Templates_template.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/1_Zen mode_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/1_Zen mode_image.png new file mode 100644 index 0000000..347ade3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/1_Zen mode_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/2_Zen mode_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/2_Zen mode_image.png new file mode 100644 index 0000000..cd5a9cc Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/2_Zen mode_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/3_Zen mode_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/3_Zen mode_image.png new file mode 100644 index 0000000..e708d46 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/3_Zen mode_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote.html new file mode 100644 index 0000000..98983d4 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Evernote.html @@ -0,0 +1 @@ +

Trilium은 Evernote의 백업·내보내기 형식인 ENEX 파일을 가져올 수 있습니다. ENEX 파일 하나에는 노트북 하나의 노트와 관련 자료가 담깁니다.

Evernote에서 ENEX 내보내기

원문에서 안내하는 방식은 구형 Evernote 데스크톱 앱을 사용합니다. 웹이나 모바일 버전이 아닙니다. 노트북에서 마우스 오른쪽 버튼을 누르고 내보내기를 선택한 뒤 안내를 따르세요.

Trilium으로 ENEX 가져오기

가져올 위치의 노트에서 마우스 오른쪽 버튼을 누르세요. 가져오기를 선택한 뒤 ENEX 파일을 지정합니다.

완료되면 노트와 자료를 살펴 누락된 내용이 없는지 확인하세요.

제한 사항

이미지를 제외한 자료는 노트의 첨부 파일로 만들어집니다.

ENEX 내부의 HTML은 표준과 완전히 일치하지 않아 일부 서식이 달라지거나 사라질 수 있습니다. 큰 문제가 있으면 Trilium 문제 보고 페이지에 알려 주세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown.html new file mode 100644 index 0000000..b573676 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown.html @@ -0,0 +1,3 @@ +

Trilium은 호환성을 최대한 유지하면서 Markdown 가져오기와 내보내기를 지원합니다.

가져오기

클립보드에서 가져오기

일부 Markdown 내용을 복사했다면 편집기의 블록 메뉴에서 가져올 수 있습니다.

클립보드의 Markdown 가져오기

파일에서 가져오기

확장자가 .md인 파일 하나를 가져오거나 여러 파일의 폴더 구조를 압축 파일로 묶어 가져올 수 있습니다. 이 기능에서는 ZIP 형식을 사용하세요. 브라우저가 폴더를 직접 읽지 못하므로 7-Zip 같은 도구로 폴더를 ZIP으로 압축해야 합니다.

Markdown 파일 가져오기

내보내기

하위 트리 내보내기

하위 트리 전체를 ZIP으로 내보내면 노트 구조에 맞춰 폴더가 만들어집니다.

하위 트리의 Markdown 내보내기

노트 하나만 내보내기

하위 노트를 제외하고 현재 노트만 내보내려면 노트 작업 메뉴를 사용하세요.

현재 노트의 Markdown 내보내기

보호된 노트 내보내기

먼저 보호 세션을 시작해야 합니다. 내보낸 파일은 암호화되지 않습니다. 다시 가져온 노트도 필요하면 보호 설정을 다시 적용하세요.

지원 문법

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 클립보드의 Markdown 가져오기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · Markdown 파일 가져오기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 하위 트리의 Markdown 내보내기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · 현재 노트의 Markdown 내보내기

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-export-n.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-export-n.gif new file mode 100644 index 0000000..d1eb7c0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-export-n.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-export-s.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-export-s.gif new file mode 100644 index 0000000..13316bb Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-export-s.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-file-imp.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-file-imp.gif new file mode 100644 index 0000000..bcb2541 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-file-imp.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-inline-i.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-inline-i.gif new file mode 100644 index 0000000..bf27467 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/Markdown_markdown-inline-i.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote.html new file mode 100644 index 0000000..30a63d9 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Import & Export/OneNote.html @@ -0,0 +1 @@ +

OneNote 자료 준비

과거의 이전 절차

Evernote Legacy 보관 문서를 참고한 방법입니다. 당시에는 계정이 필요했지만 인터넷 연결 없이 가져올 수 있었으며 Evernote 서버에 노트를 동기화하지 않는 방식으로 설명되었습니다. 파일 → 가져오기 → OneNote에서 전자 필기장과 구역을 선택했습니다.

여러 구역을 한 번에 가져오면 폴더가 합쳐질 수 있습니다. 순서는 유지되므로 이후 다시 나눌 수 있습니다. 가져온 전자 필기장을 오른쪽 클릭해 노트 내보내기를 선택하고 ENEX로 저장합니다.

ENEX 정리

OneNote 페이지 머리말을 제거하려면 텍스트 편집기에서 정규식 .<div.*><h1을 찾아 <h1로 바꾸는 방법이 원문에 소개되어 있습니다. 원본을 보관하고 바뀌는 범위를 확인하세요.

Trilium으로 가져오기

상위 노트를 오른쪽 클릭해 가져오기를 선택하고 ENEX 파일을 지정합니다. 큰 파일은 몇 분이 걸릴 수 있습니다. 파일마다 반복하세요.

가져온 뒤 확인할 내용

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts.html new file mode 100644 index 0000000..b2220c5 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Keyboard Shortcuts.html @@ -0,0 +1,2 @@ +

일부 단축키는 트리나 편집기 등 특정 위치에서만 작동합니다. 기본 키는 버전에 따라 다를 수 있으므로 설정 → 단축키에서 현재 값을 확인하세요. global: 접두사는 앱에 초점이 없어도 동작하는 전역 단축키를 지정하며 앱을 다시 시작해야 적용됩니다.

노트 탐색

#keyboardShortcut 라벨에 키 조합을 지정하면 해당 노트로 바로 이동할 수 있습니다. 새로고침 후 적용됩니다. 노트 탐색 예제를 참고하세요.

탭

노트 링크를 Ctrl을 누른 채 클릭하거나 마우스 가운데 버튼으로 누르면 새 탭에서 엽니다. 데스크톱 앱에서는 Ctrl+T로 새 탭을 열고 Ctrl+W로 닫습니다. Ctrl+Tab과 Ctrl+Shift+Tab으로 다음·이전 탭을 선택합니다.

노트 만들기

Ctrl+O는 현재 노트 다음에 새 노트를 만듭니다. Ctrl+P는 하위 노트를 만듭니다. F2는 현재 가지의 접두사를 편집합니다.

이동과 복제

편집

텍스트 노트의 편집 단축키와 Markdown식 자동 서식도 참고하세요. 트리에서 Enter를 누르면 제목으로 이동하고 제목에서 Enter를 누르면 본문으로 이동합니다. Ctrl+.은 트리로 돌아갑니다.

실행 화면

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Jump to Note_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Jump to Note_image.png new file mode 100644 index 0000000..98ef4a0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Jump to Note_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Workspaces_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Workspaces_image.png new file mode 100644 index 0000000..ae10ee7 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/1_Workspaces_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.html new file mode 100644 index 0000000..9d9d201 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks.html @@ -0,0 +1,3 @@ +

자주 사용하는 노트를 북마크에 등록하면 빠르게 열 수 있습니다. 아래 예시를 참고하세요.

북마크 등록과 사용

북마크 폴더

왼쪽 영역의 공간은 한정되어 있습니다. 여러 노트를 등록하려면 폴더를 북마크로 지정해 그 안의 노트를 펼쳐 보는 방법이 있습니다.

북마크 폴더

폴더로 사용할 노트에 #bookmarkFolder 라벨을 추가하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 북마크 등록과 사용

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 북마크 폴더

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks_bookmark-folder.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks_bookmark-folder.png new file mode 100644 index 0000000..48e9a4a Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks_bookmark-folder.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks_bookmarks.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks_bookmarks.gif new file mode 100644 index 0000000..20fca91 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Bookmarks_bookmarks.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note.html new file mode 100644 index 0000000..70ef6a0 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note.html @@ -0,0 +1,5 @@ +

노트로 이동 창

노트로 이동 기능은 제목을 검색해 원하는 노트를 빠르게 엽니다. 전체 검색을 실행하거나 새 노트를 만들 수도 있습니다.

노트로 이동 열기

최근 노트

최근에 보거나 편집한 노트 목록에서 원하는 노트로 바로 이동할 수 있습니다. 위쪽의 노트로 이동 버튼을 누르고 검색어를 입력하지 않으면 최근 노트가 표시됩니다. 오른쪽의 시계 아이콘으로도 열 수 있습니다.

최근 노트 사용 예시

사용 방법

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트로 이동 창

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 최근 노트 사용 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note_image.png new file mode 100644 index 0000000..4304944 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note_recent-notes.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note_recent-notes.gif new file mode 100644 index 0000000..45d9902 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Jump to Note_recent-notes.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting.html new file mode 100644 index 0000000..43f2276 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting.html @@ -0,0 +1,3 @@ +

특정 노트와 그 하위 트리만 표시해 집중하는 기능입니다. 상위 노트와 같은 단계의 다른 노트를 숨겨 표시 범위를 좁힙니다.

하위 트리만 표시하는 기능

본문 검색과 노트로 이동 기능의 검색 범위도 현재 표시 중인 하위 트리로 제한됩니다.

이 기능을 확장한 작업 공간도 참고하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 하위 트리만 표시하는 기능

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting_note-hoistin.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting_note-hoistin.gif new file mode 100644 index 0000000..cafab4a Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Hoisting_note-hoistin.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation.html new file mode 100644 index 0000000..7f80c8b --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation.html @@ -0,0 +1,3 @@ +

Trilium은 노트 사이를 빠르고 편하게 이동할 수 있도록 설계되었습니다.

뒤로 가기와 앞으로 가기

Alt+←와 Alt+→를 누르면 이전에 본 노트 사이를 이동할 수 있습니다.

웹브라우저의 방문 기록 기능을 이용하므로 브라우저의 뒤로 가기와 앞으로 가기와 같은 방식으로 작동합니다.

노트 이동 버튼

노트로 이동

상단의 노트로 이동 버튼을 누르거나 Ctrl+J를 누르세요. 제목 일부를 입력하면 자동 완성 목록에서 원하는 노트를 골라 바로 열 수 있습니다.

자세한 내용은 노트로 이동을 참고하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 이동 버튼

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation_image.png new file mode 100644 index 0000000..2ea2690 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Note Navigation_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search.html new file mode 100644 index 0000000..f3ef710 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search.html @@ -0,0 +1,8 @@ +

빠른 검색

빠른 검색은 노트 제목뿐 아니라 본문까지 검색하고 결과를 바로 선택할 수 있게 보여 줍니다.

별도 탭에서 고급 조건으로 검색하려면 검색 기능을 사용하세요.

본문 대신 제목만 검색해 빠르게 이동하려면 노트로 이동 기능을 사용하세요.

화면 배치

세로 배치와 가로 배치에 따라 빠른 검색창의 위치가 달라집니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 빠른 검색

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search_image.png new file mode 100644 index 0000000..997ff79 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Quick search_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note.html new file mode 100644 index 0000000..d32f83e --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note.html @@ -0,0 +1,6 @@ +

노트 안에서 찾기

현재 표시된 노트 안에서 글자를 찾는 기능입니다.

다른 검색 기능과의 차이

검색 열기

찾기

찾을 내용을 입력하면 자동으로 검색합니다. 입력란 옆의 위아래 화살표로 결과 사이를 이동하세요.

바꾸기

찾을 내용과 바꿀 내용을 입력하세요. 바꾸기는 현재 결과 하나를 변경하며 모두 바꾸기는 일치하는 내용을 한 번에 변경합니다.

검색 옵션

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 안에서 찾기

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note_image.png new file mode 100644 index 0000000..762d1e5 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search in note_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search.html new file mode 100644 index 0000000..6988f61 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search.html @@ -0,0 +1,12 @@ +

노트 검색 화면

제목과 본문 및 속성을 검색합니다. 검색 조건을 저장하면 트리에 검색 노트가 생기고 결과가 하위 항목으로 나타납니다.

검색 열기

실행 도구 모음의 검색 버튼을 누릅니다. 특정 하위 트리만 찾으려면 노트 트리 메뉴의 하위 트리에서 검색 또는 Ctrl+Shift+S를 사용합니다. 단축키로도 검색 화면을 열 수 있습니다.

사용 방법

검색어를 입력합니다. 일반 단어뿐 아니라 속성과 노트 정보로 조건을 지정할 수 있습니다. 상위 노트를 지정하면 해당 노트와 하위 항목만 찾습니다. 확대해서 보는 노트나 작업 공간에서 열면 이 값이 미리 채워질 수 있습니다. 전체를 검색하려면 비웁니다. 깊이로 탐색할 하위 단계를 제한할 수 있습니다.

검색을 누르면 아래에 결과가 표시됩니다. 작업을 추가한 경우에는 검색 후 작업 실행 버튼을 사용할 수 있습니다. 노트로 저장은 조건을 저장된 검색 노트로 만듭니다.

검색 옵션

검색 옵션 추가에서 항목을 선택하고 세부 값을 지정합니다. 오른쪽 X로 제거합니다.

기본 검색 예제

고급 예제

~author.relations.son.title = '크리스토퍼 톨킨'은 저자 관계를 따라간 노트에서 다시 son 관계를 따라갔을 때 제목이 일치하는 노트를 찾습니다. 예를 들어 책의 author가 J. R. R. 톨킨을 가리키고 그 노트의 son이 크리스토퍼 톨킨을 가리키는 구조입니다.

~author.title *= 톨킨 OR (#publicationDate >= 1954 AND #publicationDate <= 1960)처럼 논리 연산과 괄호를 사용할 수 있습니다. 식 전체가 괄호로 시작할 때는 앞에 # 또는 ~ 구분자가 필요합니다.

노트 정보로 검색

note. 뒤에 속성명을 붙입니다. 예: note.type = code AND note.mime = 'application/json'. 사용할 수 있는 정보는 다음과 같습니다.

noteId dateModified dateCreated isProtected type title text content rawContent ownedLabelCount labelCount ownedRelationCount relationCount ownedRelationCountIncludingLinks relationCountIncludingLinks ownedAttributeCount attributeCount targetRelationCount targetRelationCountIncludingLinks parentCount childrenCount isArchived contentSize noteSize revisionCount

정렬과 결과 수 제한

#author=톨킨 orderBy #publicationDate desc, note.title limit 10

저자 라벨 값이 톨킨인 노트를 찾아 출판 날짜 내림차순으로 정렬합니다. 날짜가 같으면 제목을 기준으로 정렬하고 처음 10개만 표시합니다.

부정 조건

#book AND not(note.ancestors.title = '톨킨')

톨킨이라는 노트의 하위 트리에 속하지 않는 책 노트를 찾습니다.

검색식의 구성

라벨과 관계의 전체 문법은 다음과 같습니다.

note.labels.publicationYear = 1954
note.relations.author.title *=* 톨킨

자주 사용하는 형태는 짧게 쓸 수 있습니다.

#publicationYear = 1954
+~author.title *=* 톨킨

본문 검색과 속성 검색의 구분

톨킨 #book에서 톨킨은 본문 검색어이고 #book은 속성 조건입니다. #와 ~ 및 note. 같은 문법으로 구분합니다. 일반 텍스트로 찾으려면 따옴표로 감싸거나 역슬래시로 이스케이프합니다.

"note.txt" 
+\#hash 
+#myLabel = '"안녕하세요"라고 말하기'

특수문자와 따옴표

작은따옴표와 큰따옴표 및 백틱을 지원합니다.

"note.txt"
+\#hash
+#myLabel = '"안녕하세요"라고 말하기'

값의 형 변환

라벨은 문자열로 저장되지만 숫자 비교 연산에서는 숫자로 변환합니다. 다음 예제는 만든 날짜가 2019년 5월로 시작하는 노트를 찾습니다.

note.dateCreated =* '2019-05'

#publicationYear >= 1960은 출판 연도를 숫자로 비교합니다.

URL로 검색 실행

검색어를 URL 인코딩한 뒤 주소에 넣으면 앱을 열면서 검색할 수 있습니다. 예: http://localhost:8080/#?searchString=abc

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 검색 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search_image.png new file mode 100644 index 0000000..55f550c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Search_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes.html new file mode 100644 index 0000000..205cd2f --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes.html @@ -0,0 +1,4 @@ +

유사한 노트 목록

유사한 노트 기능은 본문 내용과 노트 사이의 관계 및 생성 날짜를 살펴 현재 노트와 관련된 노트를 찾습니다.

리본 메뉴에서 유사한 노트 탭을 누르면 목록을 볼 수 있습니다.

사용 방법

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 유사한 노트 목록

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes_image.png new file mode 100644 index 0000000..1e9ee56 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Similar Notes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts.html new file mode 100644 index 0000000..ea0e383 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Tree Concepts.html @@ -0,0 +1,2 @@ +

TriliumNext의 노트 트리 구조를 이해하는 데 필요한 기본 개념을 설명합니다.

노트

노트는 TriliumNext에서 정보를 담는 기본 단위입니다. 자세한 내용은 노트를 참고하세요.

가지

가지는 노트가 트리의 어느 위치에 놓이는지를 나타냅니다. parentNoteId와 noteId의 쌍으로 상위 노트와 하위 노트의 관계를 표현합니다.

한 노트에 여러 가지를 연결하면 같은 노트를 트리의 여러 위치에 놓을 수 있습니다. 이를 복제라고 합니다.

접두사

접두사는 특정 가지에서만 노트 제목 앞에 붙는 문구입니다. 같은 노트를 두 위치에 놓고 한쪽에서만 제목을 구분하고 싶을 때 사용합니다.

트리에서 노트를 마우스 오른쪽 버튼으로 클릭한 뒤 가지 접두사 편집을 선택하세요.

접두사는 노트 본문에 속하지 않으므로 노트를 보호해도 암호화되지 않습니다. 보호된 노트를 구분할 수 있도록 제목 일부를 트리에 계속 표시할 때 유용합니다.

하위 트리

하위 트리는 기준이 되는 노트와 그 아래에 속한 모든 노트를 포함합니다. 내보내기 같은 일부 작업은 하위 트리 전체에 적용할 수 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces.html new file mode 100644 index 0000000..760d5e0 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces.html @@ -0,0 +1,3 @@ +

작업 공간은 하위 트리만 표시하는 기능을 확장한 개념입니다. 개인 기록과 업무처럼 서로 구분되는 관심사를 나누고 현재 작업에 필요한 노트에 집중할 수 있습니다.

하위 트리 표시 범위를 작업 공간으로 제한할 수 있으며 전용 버튼으로 빠르게 들어갈 수 있습니다.

작업 공간 진입 버튼

탭의 아이콘과 배경색으로 현재 작업 공간을 구분할 수 있습니다.

탭에 표시된 작업 공간

설정 라벨

라벨설명
workspace노트를 작업 공간으로 지정하고 진입 버튼을 표시합니다.
workspaceIconClass이 작업 공간을 표시할 때 탭에서 사용할 Boxicons 아이콘의 CSS 클래스를 지정합니다.
workspaceTabBackgroundColor작업 공간 탭의 배경색입니다. lightblue나 #ddd처럼 CSS 색상 형식을 사용할 수 있습니다. CSS 색상 안내를 참고하세요.
workspaceCalendarRoot작업 공간에서 사용할 날짜별 노트의 별도 달력을 지정합니다. 지정하지 않으면 전체 달력을 사용합니다.
workspaceTemplate이 작업 공간 안에서 새 노트를 만들 때만 선택할 수 있는 템플릿으로 지정합니다.
workspaceSearchHome표시 범위가 이 노트의 상위 노트로 제한되어 있을 때 새 검색 노트를 이 노트 아래에 만듭니다.
workspaceInbox표시 범위가 이 노트의 상위 노트로 제한되어 있을 때 새 노트의 기본 수신함으로 사용합니다.
+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 작업 공간 진입 버튼

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 탭에 표시된 작업 공간

현재 작업 공간의 이름이 탭에 표시됩니다. 작업 공간을 바꾸면 해당 공간에 저장된 탭 구성을 불러옵니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces_image.png new file mode 100644 index 0000000..2401cf0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Navigation/Workspaces_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes.html new file mode 100644 index 0000000..b3db05c --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes.html @@ -0,0 +1,6 @@ +

노트는 Trilium에서 정보를 담는 기본 단위입니다. 주요 구성 요소는 제목과 본문입니다.

노트 유형

주로 사용하는 유형은 서식 있는 텍스트 노트입니다. 그림과 도표에는 캔버스와 Mermaid 도표를 사용할 수 있습니다. 저장된 검색과 HTML 표시 노트 같은 고급 유형도 있으며 스크립트와 함께 활용할 수 있습니다.

별도의 폴더 유형은 없습니다. 모든 노트는 하위 노트를 가질 수 있어 폴더 역할을 할 수 있습니다.

최상위 노트

노트 트리의 시작점인 최상위 노트가 하나 있습니다. 다른 모든 노트는 그 아래에 놓입니다.

트리 구조

노트 자체와 트리에서의 위치 정보는 별도로 관리됩니다. 노트 복제를 참고하세요. 파일 시스템과 비슷하지만 하나의 노트에 본문과 하위 노트가 함께 있을 수 있습니다. 하위 노트가 없는 노트를 말단 노트라고 합니다.

삭제와 복원

처음 삭제할 때는 제목과 본문 및 속성을 바로 지우지 않고 삭제 상태로 표시해 숨깁니다. 기본적으로 7일 동안 최근 변경 사항에서 삭제 취소 링크로 복원할 수 있습니다.

복원하면 본문과 속성도 되살아납니다. 같은 작업으로 삭제한 하위 노트도 함께 복원됩니다. 복원할 위치가 있어야 하므로 상위 노트부터 복원해야 합니다. 여러 차례에 걸쳐 삭제했다면 삭제한 순서의 반대로 복원하세요.

보관 기간이 지나면 제목과 본문 및 수정 이력과 속성이 영구 삭제됩니다. 이후에는 백업이 있어야 복구할 수 있습니다. 기본 7일인 보관 기간은 설정에서 바꿀 수 있습니다.

관련 문서

읽기 전용 노트

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Export as PDF_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Export as PDF_image.png new file mode 100644 index 0000000..a5d522d Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Export as PDF_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Note List_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Note List_image.png new file mode 100644 index 0000000..4f0329d Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/1_Note List_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/2_Note List_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/2_Note List_image.png new file mode 100644 index 0000000..4b581bb Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/2_Note List_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes.html new file mode 100644 index 0000000..e2258d1 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes.html @@ -0,0 +1,3 @@ +

보관된 노트는 archived 속성을 직접 지정했거나 상속받은 노트입니다.

기본적으로 자동 완성 목록과 본문 검색 결과에 나타나지 않습니다.

자주 사용하지는 않지만 보관할 가치가 있는 노트를 정리할 때 유용합니다. 필요한 정보는 남겨 두면서 평소 작업에 방해되지 않게 할 수 있습니다.

노트 트리에 보관된 노트를 표시할지는 설정에서 선택할 수 있습니다.

보관된 노트 표시 설정

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 보관된 노트 표시 설정

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes_hide-archiv.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes_hide-archiv.png new file mode 100644 index 0000000..82528ac Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Archived Notes_hide-archiv.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Attachments.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Attachments.html new file mode 100644 index 0000000..c0a34d9 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Attachments.html @@ -0,0 +1,3 @@ +

Trilium의 노트에는 이미지나 파일을 하나 이상 첨부할 수 있습니다. 첨부 파일은 해당 노트 안에 표시하거나 링크로 연결할 수 있습니다.

스크립트에 필요한 라이브러리를 포함할 때도 유용합니다. 체중 기록 예제에서는 스크립트 노트에 첨부한 Chart.js를 사용하는 방법을 보여 줍니다.

첨부 파일은 각각 하나의 노트에 속합니다. 다른 노트와 같은 첨부 파일을 공유하지 않습니다. 첨부 파일 링크를 다른 노트에 복사하면 파일도 복제되며 이후에는 서로 독립적으로 관리됩니다.

노트에 이미지를 넣을 때는 첨부 기능을 사용하는 것이 좋습니다. 이미지 첨부 파일은 해당 노트 본문에서 참조해야 합니다. 참조되지 않는 이미지는 설정된 유예 시간이 지나면 자동으로 삭제됩니다.

노트를 첨부 파일로 변환하기

파일 노트를 상위 노트의 첨부 파일로 바꿀 수 있습니다.

첨부 파일 미리보기

이미지와 동영상 및 PDF 등의 첨부 파일은 파일 노트와 같은 미리보기 기능을 사용합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes.html new file mode 100644 index 0000000..36f8cfc --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes.html @@ -0,0 +1,4 @@ +

여러 위치에 놓기

트리로 지식을 정리하다 보면 같은 노트를 여러 주제 아래에 두고 싶을 때가 있습니다. 예를 들어 기술 아래에 프로그래밍과 운영체제를 만들고 프로그래밍에는 Kotlin과 JavaScript를 두며 운영체제에는 Linux와 Windows를 둘 수 있습니다.

여기에 Bash를 공부한 기록을 넣는다면 프로그래밍 언어이면서 Linux 셸이기도 하므로 한 위치만 고르기 어렵습니다.

복제의 의미

Trilium은 같은 노트에 여러 상위 노트를 연결할 수 있습니다. 이를 복제라고 부릅니다. 별도의 사본을 만드는 것이 아니라 하나의 노트를 여러 위치에서 참조합니다. 따라서 한쪽에서 수정하면 다른 위치에서도 같은 내용을 보여 줍니다.

Bash 노트를 프로그래밍 아래와 Linux 아래에 함께 놓으면 됩니다. 하위 노트도 같은 구조와 내용을 공유합니다.

만드는 방법

노트 복제 예시

오른쪽 클릭 메뉴나 링크 추가 창으로 만들 수 있습니다. Ctrl+C와 Ctrl+V 단축키도 사용할 수 있습니다. 상단 리본의 노트 경로에서 연결된 모든 위치를 확인하세요. 트리 제목 옆의 별표는 다른 위치에도 있는 노트임을 뜻합니다.

복제된 노트 삭제

다른 위치에도 있는 노트라면 현재 위치의 연결만 제거하고 노트 자체와 다른 연결은 유지합니다. 마지막 연결을 삭제하면 노트 자체를 삭제합니다. 하위 노트에도 같은 규칙을 적용하므로 다른 위치에 연결된 하위 노트는 남습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 복제 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix.html new file mode 100644 index 0000000..3a5379b --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes/Branch prefix.html @@ -0,0 +1,3 @@ +

노트 복제 기능을 사용하면 하나의 노트가 노트 트리의 여러 위치에 나타날 수 있습니다. 어느 위치에서도 뜻이 통하는 제목을 사용하는 것이 좋습니다.

위치마다 다른 설명이 필요할 때는 가지 접두사를 사용할 수 있습니다. 노트 제목 앞에 해당 위치에 맞는 설명을 붙여 줍니다.

접두사는 위치별로 지정하며 노트 트리에서만 표시됩니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes_create-clone.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes_create-clone.gif new file mode 100644 index 0000000..7429e5e Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Cloning Notes_create-clone.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF.html new file mode 100644 index 0000000..a08af1c --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF.html @@ -0,0 +1,5 @@ +

PDF로 내보내기 메뉴

Trilium 데스크톱 앱에서는 노트를 PDF로 내보낼 수 있습니다. 서버와 모바일 PWA에서는 기술적인 제약으로 이 항목이 표시되지 않습니다.

노트 제목 오른쪽의 노트 메뉴 버튼을 누르고 PDF로 내보내기를 선택한 뒤 저장 위치를 지정하세요.

내보낸 파일 열기

저장이 끝나면 운영체제의 기본 프로그램으로 PDF를 엽니다. Linux의 GNOME 환경에서는 추천 프로그램 목록을 사용하므로 예상과 다른 프로그램이 열릴 수 있습니다. 다음 명령으로 PDF 연결 프로그램을 확인한 뒤 원하는 프로그램으로 설정하세요.

gio mime application/pdf

표시 문제 보고하기

표가 잘 맞지 않거나 글자가 잘리는 문제가 있다면 문제를 보고해 주세요. 노트 메뉴 버튼 → 노트 내보내기 → 이 노트와 모든 하위 노트 → HTML을 ZIP으로 내보내기로 재현용 자료를 만들 수 있습니다. 공유할 자료에 개인 정보가 없는지 확인하세요.

가로 방향

별도의 내보내기 설정 창은 없지만 #printLandscape 속성을 추가하면 해당 노트를 가로 방향으로 출력할 수 있습니다.

용지 크기

기본 용지는 Letter입니다. #printPageSize 값으로 A0부터 A6까지 지정할 수 있습니다. Legal과 Letter 및 Tabloid와 Ledger도 지원합니다.

단축키

설정의 단축키에서 exportAsPdf에 원하는 키 조합을 지정할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · PDF로 내보내기 메뉴

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF_image.png new file mode 100644 index 0000000..b205c18 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Export as PDF_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons.html new file mode 100644 index 0000000..38e14f9 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons.html @@ -0,0 +1,3 @@ +

아이콘을 사용하면 노트를 쉽게 구분할 수 있습니다. 내부적으로는 iconClass 속성으로 노트에 CSS 클래스를 지정합니다. 예를 들어 #iconClass="bx bx-calendar"는 기본 문서나 폴더 아이콘 대신 달력 아이콘을 표시합니다. 클래스 이름을 외울 필요는 없습니다. 노트를 편집하면서 제목 옆의 아이콘을 누르면 선택 창이 열립니다.

노트 아이콘 바꾸기

노트 아이콘 선택 창

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 아이콘 바꾸기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 노트 아이콘 선택 창

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons_note-icon-chang.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons_note-icon-chang.png new file mode 100644 index 0000000..dbd4268 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons_note-icon-chang.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons_note-icon-galle.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons_note-icon-galle.png new file mode 100644 index 0000000..a13cb2d Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Icons_note-icon-galle.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List.html new file mode 100644 index 0000000..f5a5e31 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List.html @@ -0,0 +1,10 @@ +

하위 노트가 있으면 본문 끝에 목록이 표시되어 쉽게 이동할 수 있습니다.

설정

특정 노트에서 숨기려면 hideChildrenOverview 라벨을 지정하세요. 격자 보기 등은 성능을 위해 여러 페이지로 나눠 표시합니다. pageSize로 한 페이지의 노트 수를 정할 수 있습니다.

보기 방식

기본은 격자 보기입니다. 책 노트에서는 상단 리본으로 바꿀 수 있습니다. 다른 노트 유형도 #viewType 속성으로 직접 지정할 수 있습니다.

격자 보기

격자 보기

하위 노트를 카드처럼 배치합니다. 텍스트 노트는 마우스 휠로 본문을 조금 더 볼 수 있습니다. 코드 노트에는 구문 강조를 적용합니다. 파일 노트는 오디오와 동영상 및 PDF 미리보기를 제공합니다. 본문이 없는 노트는 하위 노트 목록을 대신 표시합니다.

목록 보기

목록 보기

각 노트를 한 줄로 표시하며 기본적으로 제목과 아이콘만 보입니다. 펼치면 본문과 하위 노트를 확인할 수 있으며 더 아래 단계도 펼칠 수 있습니다.

달력 보기

달력 보기

하위 노트를 시작일이 있는 일정으로 표시합니다. 종료일도 지정할 수 있으며 일정을 옮기거나 새로 만들 수 있습니다. 달력 보기 안내를 참고하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 격자 보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 목록 보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 달력 보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/10_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/10_Calendar View_image.png new file mode 100644 index 0000000..875127d Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/10_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/11_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/11_Calendar View_image.png new file mode 100644 index 0000000..7bdf27a Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/11_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/1_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/1_Calendar View_image.png new file mode 100644 index 0000000..10ac2bb Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/1_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/2_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/2_Calendar View_image.png new file mode 100644 index 0000000..2c17bb4 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/2_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/3_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/3_Calendar View_image.png new file mode 100644 index 0000000..3bf9472 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/3_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/4_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/4_Calendar View_image.png new file mode 100644 index 0000000..0ec1e36 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/4_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/5_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/5_Calendar View_image.png new file mode 100644 index 0000000..3db9e77 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/5_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/6_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/6_Calendar View_image.png new file mode 100644 index 0000000..b147a79 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/6_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/7_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/7_Calendar View_image.png new file mode 100644 index 0000000..920ffc6 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/7_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/8_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/8_Calendar View_image.png new file mode 100644 index 0000000..e89fee4 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/8_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/9_Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/9_Calendar View_image.png new file mode 100644 index 0000000..ae9c9a3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/9_Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/Calendar View.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/Calendar View.html new file mode 100644 index 0000000..2238702 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/Calendar View.html @@ -0,0 +1,8 @@ +

책 노트의 달력 보기

시작 날짜가 있는 하위 노트를 일정으로 표시합니다. 종료 날짜도 지정할 수 있습니다. 주 보기는 요일별 열에 시간 지정 일정과 종일 일정을 표시합니다. 월 보기는 한 달의 일정을 보여 주며 종일 일정을 만들 수 있습니다. 연 보기는 한 해를 한눈에 보여 줍니다. 목록 보기는 한 달의 일정을 순서대로 나열합니다. 일정 생성과 이동도 지원합니다.

달력 만들기

노트 트리에서 다음에 노트 삽입 또는 하위 노트 삽입을 선택하고 책 유형으로 만듭니다.

책 노트 만들기

상단 리본의 책 속성에서 보기 유형을 달력으로 바꿉니다.

달력 보기 선택

일정 만들기

날짜를 누르고 새 노트 제목을 입력합니다. 창을 닫거나 Esc를 누르면 만들지 않습니다. 여러 날짜를 끌어 선택하면 시작일과 종료일을 함께 지정합니다.

여러 날짜를 선택해 일정 만들기

책 노트에 ~child:template 관계가 있으면 새 일정에 해당 템플릿을 적용합니다.

일정 조작

마우스를 올리면 노트 정보가 나타납니다.

일정 미리보기

왼쪽 버튼은 현재 화면에서 열고 가운데 버튼은 새 탭에서 엽니다. 오른쪽 메뉴에서는 분할 화면이나 새 창으로 열 수 있습니다. 일정을 끌어 날짜를 바꾸거나 오른쪽 가장자리를 끌어 기간을 바꿉니다.

달력 설정

한 주의 시작 요일은 앱 설정에서 일요일이나 월요일로 지정합니다.

일정별 속성

일정에 속성 표시

예: #weight="70" #Mood="좋음" #calendar:displayedAttributes="weight,Mood". 관계 예: ~assignee=@담당자 #calendar:displayedAttributes="assignee".

#calendar:startDate에 expiryDate처럼 다른 라벨 이름을 지정하면 그 값을 시작일로 사용합니다. 이름 앞에 #를 붙이지 않습니다. 지정한 라벨이 없으면 기본 속성을 사용합니다. 같은 방식으로 #calendar:endDate와 #calendar:startTime 및 #calendar:endTime도 바꿀 수 있습니다.

작동 방식

날짜 속성과 달력 일정

보통 #startDate가 있는 하위 노트를 표시하고 필요하면 #endDate를 사용합니다. 각 노트에서 날짜를 쉽게 편집하려면 책 노트에 다음 속성을 추가합니다.

#viewType=calendar #label:startDate(inheritable)="promoted,alias=시작일,single,date"
+#label:endDate(inheritable)="promoted,alias=종료일,single,date"
+#hidePromotedAttributes 

주요 속성으로 날짜 편집

일지 밖의 일반 달력은 여러 단계의 하위 노트까지 찾아 일정을 표시합니다.

일지와 함께 사용

일지 루트의 유형을 책으로 바꾸고 달력 보기를 선택합니다. #calendarRoot 또는 #workspaceCalendarRoot를 감지하면 다음과 같이 동작합니다.

일지의 달력 보기

다른 속성을 일정 제목으로 사용

달력 노트가 아닌 일정 노트에 #calendar:title을 지정합니다. 값에는 표시할 라벨 이름을 입력합니다. 템플릿 등으로 상속해도 됩니다. 해당 라벨이 없으면 노트 제목을 사용합니다.

#startDate=2025-02-11 #endDate=2025-02-13 #name="내 휴가" #calendar:title="name"

라벨 값을 일정 제목으로 표시

관계의 대상 제목 사용

관계 이름도 지정할 수 있습니다. 같은 이름의 관계가 여러 개면 하나의 노트에서 여러 일정으로 표시됩니다.

#startDate=2025-02-14 #endDate=2025-02-15 ~for=@김민수 ~for=@이서연 #calendar:title="for"

여러 관계 대상을 일정으로 표시

대상 노트에도 #calendar:title을 지정해 별도 라벨 값을 표시할 수 있습니다. 이 단계에서는 관계를 다시 따라가지 않습니다. 관계가 순환해 무한 반복되는 일을 막기 위한 제한입니다.

#calendar:title="shortName" #shortName="민수"

대상 노트의 짧은 이름 표시

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 책 노트의 달력 보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 책 노트 만들기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 달력 보기 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · 여러 날짜를 선택해 일정 만들기

달력에서 날짜 범위를 선택해 여러 날에 걸친 일정을 만드는 예시입니다.

이미지 5 · 일정 미리보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 6 · 일정에 속성 표시

달력의 일정에 노트 속성 값을 함께 표시한 모습입니다. 예제의 속성 이름과 값을 본문 설정과 비교하세요.

이미지 7 · 날짜 속성과 달력 일정

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 8 · 주요 속성으로 날짜 편집

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 9 · 일지의 달력 보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/Calendar View_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/Calendar View_image.png new file mode 100644 index 0000000..238efae Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List/Calendar View_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List_image.png new file mode 100644 index 0000000..b0a8e15 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note List_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html new file mode 100644 index 0000000..bbcde26 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html @@ -0,0 +1,4 @@ +

Trilium은 일정한 간격으로 노트의 상태를 저장해 이전 버전을 보관합니다.

이전 버전 저장 간격

설정 → 기타에서 저장 간격을 바꿀 수 있습니다. 간격이 짧을수록 더 많은 버전을 남기지만 저장 공간도 더 필요합니다.

특정 노트나 하위 트리의 버전 기록을 끄려면 disableVersioning 라벨을 추가하세요.

보관 개수 제한

설정 → 기타에서 노트마다 보관할 이전 버전의 최대 개수를 지정할 수 있습니다. -1은 제한 없음이며 0은 모든 이전 버전을 삭제한다는 뜻입니다. 개별 노트에는 versioningLimit=X 라벨로 따로 지정할 수 있습니다.

변경한 제한은 해당 노트를 수정할 때 적용됩니다.

초과한 이전 버전 지금 삭제 버튼을 누르면 즉시 적용할 수 있습니다.

이전 버전은 리본 메뉴 오른쪽의 버튼으로 확인할 수 있습니다.

이전 버전 보기

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 이전 버전 보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_note-revisi.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_note-revisi.png new file mode 100644 index 0000000..de3f17b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions_note-revisi.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes.html new file mode 100644 index 0000000..48f18a0 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes.html @@ -0,0 +1,3 @@ +

민감한 자료를 보관할 때 노트 보호 기능을 사용할 수 있습니다. 보호된 노트는 암호화되므로 데이터베이스 파일만으로 본문을 읽을 수 없습니다.

보호 노트를 열려면 비밀번호로 보호 세션을 시작해야 합니다. 기본적으로 10분 동안 사용하지 않으면 세션이 끝납니다. 보호 노트를 편집하는 동안에는 시간이 연장되며 일반 노트로 이동하면 유휴 시간이 계산됩니다.

보호 기능은 내용을 숨기는 기능입니다. 보호 세션 밖에서도 노트를 옮기거나 삭제할 수 있으므로 삭제 방지 기능과는 다릅니다.

보호 설정

기본적으로 노트는 보호되지 않습니다. 제목 옆 방패 아이콘으로 설정하세요.

보호 노트 설정과 열기

암호화 범위

제목과 본문 및 이미지와 첨부 파일은 암호화합니다. 트리 구조와 수정 시각 같은 메타데이터 및 속성은 암호화하지 않습니다. 보호 노트가 있다는 사실과 위치는 보일 수 있습니다.

암호화 과정

다음은 이 버전의 원문에 설명된 처리 과정입니다.

공유

보호 노트는 일반 노트처럼 공개 공유할 수 없습니다. 올바른 비밀번호로 보호 세션을 시작해야 내용을 볼 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 보호 노트 설정과 열기

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes_protecting.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes_protecting.gif new file mode 100644 index 0000000..23a6213 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Protected Notes_protecting.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.html new file mode 100644 index 0000000..98bfe0a --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes.html @@ -0,0 +1,4 @@ +

텍스트와 코드 등 일부 노트는 읽기 전용으로 설정할 수 있습니다. 편집할 수 없는 화면으로 열리지만 필요하면 일시적으로 편집 모드로 전환할 수 있습니다.

자동 읽기 전용

매우 긴 노트는 편집기 성능을 위해 자동으로 읽기 전용으로 열립니다. 노트별로 해제할 수 있으며 설정의 텍스트 노트와 코드 노트에서 적용 기준 글자 수를 바꿀 수 있습니다.

노트별 설정

상단 리본 → 기본 속성 → 편집 가능 여부에서 선택합니다.

편집 가능 여부가 표시되지 않으면 해당 유형은 읽기 전용 설정을 지원하지 않습니다. 라벨로 직접 지정할 수도 있습니다. readOnly는 읽기 전용이며 autoReadOnlyDisabled는 항상 편집 가능입니다.

잠시 편집하기

떠 있는 버튼 영역의 편집 버튼을 누르면 편집할 수 있습니다. 다른 노트로 이동한 뒤 다시 열면 읽기 전용으로 돌아갑니다.

유형별 동작

Mermaid 도표는 읽기 전용일 때 코드를 숨기고 도표를 전체 영역에 표시합니다. 떠 있는 버튼에서 편집 잠금을 켜거나 끌 수 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes_image.png new file mode 100644 index 0000000..53c447e Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Read-Only Notes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes.html new file mode 100644 index 0000000..79afc40 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Sorting Notes.html @@ -0,0 +1,2 @@ +

직접 정렬하기

노트 트리에서 상위 노트를 오른쪽 클릭하고 고급 → 노트 정렬을 선택하세요. 현재 노트만 정렬하며 이후 추가되는 노트까지 자동으로 정렬하지는 않습니다.

제목과 생성일 및 수정일을 기준으로 오름차순이나 내림차순으로 정렬할 수 있습니다. 폴더를 먼저 표시하거나 특정 언어의 규칙에 따른 자연 정렬을 선택할 수도 있습니다.

자동 정렬

상위 노트에 다음 라벨을 지정합니다.

정렬은 다음 우선순위를 따릅니다. 앞선 기준이 같을 때 다음 기준을 적용합니다.

자동 정렬은 문자열로 비교합니다. 예를 들어 1은 2보다 앞에 오지만 10도 2보다 앞에 옵니다. 날짜를 YYYY-MM-DD 형식으로 작성하면 시간순과 문자열 순서가 일치합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes.html new file mode 100644 index 0000000..c0f21f1 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes.html @@ -0,0 +1,59 @@ +

기본 테마

기본값은 밝은 테마입니다. 왼쪽 위 앱 메뉴에서 설정 → 모양을 열면 어두운 테마나 다른 테마로 바꿀 수 있습니다.

어두운 테마

CSS로 테마 만들기

코드 노트를 만들고 언어를 CSS로 지정합니다. 속성에 #appTheme=my-theme-name을 추가합니다. my-theme-name은 원하는 테마 이름으로 바꿉니다. 본문에 다음과 같은 스타일을 작성합니다.

@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  src: url('/custom/fonts/raleway.woff2') format('woff2');
+}
+
+:root {
+    --main-font-family: 'Raleway' !important;
+    --main-font-size: normal;
+    --tree-font-family: inherit;
+    --tree-font-size: normal;
+    --detail-font-family: inherit;
+    --detail-font-size: normal;
+    --detail-text-font-family: 'Garamond' !important;
+
+    --main-background-color: #404552;
+    --main-text-color: #AFB8C6;
+    --main-border-color: #AFB8C6;
+    --accented-background-color: #383C4A;
+    --more-accented-background-color: #2F343F;
+    --header-background-color: #383C4A;
+    --button-background-color: #2F343F;
+    --button-disabled-background-color: #404552;
+    --button-border-color: #333;
+    --button-text-color: #AFB8C6;
+    --button-border-radius: 2px;
+    --primary-button-background-color: #6c757d;
+    --primary-button-text-color: white;
+    --primary-button-border-color: #6c757d;
+    --muted-text-color: #86919F;
+    --input-text-color: #AFB8C6;
+    --input-background-color: #404552;
+    --hover-item-text-color: white;
+    --hover-item-background-color: #4877B1;
+    --active-item-text-color: white;
+    --active-item-background-color: #4877B1;
+    --menu-text-color: #AFB8C6;
+    --menu-background-color: #383C4A;
+    --tooltip-background-color: #383C4A;
+    --link-color: lightskyblue;
+    --modal-background-color: #404552;
+    --modal-backdrop-color: black;
+    --scrollbar-border-color: rgba(175, 184, 198, 0.5);
+}
+
+body .note-detail-text {
+    font-size: 120%;
+}
+
+body .CodeMirror {
+    filter: invert(100%) hue-rotate(180deg);
+}

테마 적용

설정 → 모양의 테마 목록에서 #appTheme 라벨에 지정한 이름을 선택합니다. CSS를 수정한 뒤에는 Ctrl+R로 화면을 새로고침합니다.

공유와 가져오기

원문에서 안내하는 테마 내보내기 형식은 .tar입니다. 외부 테마에는 실행 가능한 스크립트가 들어 있을 수 있으므로 신뢰할 수 있는 출처인지 확인하세요. 기본 예제에는 강철빛 파랑 테마가 있습니다.

강철빛 파랑 테마

화면 일부에 CSS 적용

테마와 별개로 특정 요소만 꾸밀 수도 있습니다. CSS 코드 노트를 만들고 #appCss 라벨을 추가한 다음 스타일을 작성합니다.

/* 특정 화면 요소에 적용할 CSS */
+.tree-item {
+    color: #ff6347; /* 트리 항목의 글자색 변경 */
+}

앱 화면이 시작될 때 appCss가 지정된 모든 노트의 CSS를 불러옵니다. 수정한 뒤 Ctrl+R로 새로고침하세요.

노트 트리에 사용자 스타일 적용

특정 노트 꾸미기

cssClass 속성의 값에 CSS 클래스 이름을 지정합니다. iconClass에는 Box Icons의 아이콘 클래스나 직접 만든 클래스를 지정할 수 있습니다. PNG 이미지 노트처럼 특정 유형에 적용하려면 type-image mime-image-png 같은 클래스를 사용합니다.

다른 사용자의 테마

테마 모음에서 커뮤니티가 만든 테마를 살펴보세요.

기본 파일 경로

기본 이미지 등을 참조할 때 버전 번호 대신 vX 별칭을 사용하면 업데이트에 대응하기 쉽습니다. 예를 들어 /assets/v0.57.0-beta/images/icon-grey.png 대신 /assets/vX/images/icon-grey.png를 사용합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 어두운 테마

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 강철빛 파랑 테마

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 노트 트리에 사용자 스타일 적용

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery.html new file mode 100644 index 0000000..f0bb828 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes/Theme Gallery.html @@ -0,0 +1 @@ +

사용자가 만들어 공개한 테마 목록입니다.

기존 테마 기반

원래 Trilium 테마를 바탕으로 만든 자료이며 새 버전과의 호환성은 각 프로젝트에서 확인해야 합니다.

테마제작자
미드나이트 (Midnight)tobealive
EOTEtobealive
Trilium 테마 모음Abourass
머티리얼 다크 (MaterialDark)ZMonk91
밝은 슬레이트 회색 (lightslategray)jaroet
멜론 4 (melon-4)raphwriter
네온 다크 (Neon_Dark)Engr-AllanG
코더 다크 (Coder_Dark)Engr-AllanG
벨벳 (velvet)idelem
다크 플러스 (Dark Plus)SADAVA
솔라라이즈드 (Solarized)WKSu
노르드 (Nord)en3r0
베어 노트 밝은 테마AllanZyne
베어 노트 어두운 테마AllanZyne
하츠네 미쿠Sebiann
미드나이트 (Midnight)cwilliams5
파랑 — 밝은 테마SiriusXT
파랑 — 어두운 테마SiriusXT

만든 테마를 목록에 소개하려면 작품 소개 게시판에 글을 남기세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes_dark-theme.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes_dark-theme.png new file mode 100644 index 0000000..8a3e857 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes_dark-theme.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes_image.png new file mode 100644 index 0000000..49df907 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes_steel-blue.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes_steel-blue.png new file mode 100644 index 0000000..4a5ed7b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Themes_steel-blue.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Options_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Options_image.png new file mode 100644 index 0000000..f51a0a0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Options_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Recent Changes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Recent Changes_image.png new file mode 100644 index 0000000..59a29f3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Recent Changes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Tabs_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Tabs_image.png new file mode 100644 index 0000000..14f7b9c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Tabs_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Vertical and horizontal la.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Vertical and horizontal la.png new file mode 100644 index 0000000..5fda8a0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/1_Vertical and horizontal la.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/2_Tabs_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/2_Tabs_image.png new file mode 100644 index 0000000..3395aab Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/2_Tabs_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/2_Vertical and horizontal la.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/2_Vertical and horizontal la.png new file mode 100644 index 0000000..17a6d28 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/2_Vertical and horizontal la.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/3_Vertical and horizontal la.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/3_Vertical and horizontal la.png new file mode 100644 index 0000000..2f200ca Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/3_Vertical and horizontal la.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/4_Vertical and horizontal la.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/4_Vertical and horizontal la.png new file mode 100644 index 0000000..257b8a8 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/4_Vertical and horizontal la.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/5_Vertical and horizontal la.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/5_Vertical and horizontal la.png new file mode 100644 index 0000000..a6a9c6f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/5_Vertical and horizontal la.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons.html new file mode 100644 index 0000000..6cea08c --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons.html @@ -0,0 +1,6 @@ +

노트별 추가 작업 버튼

현재 노트의 종류에 따라 리본 메뉴 바로 아래 오른쪽에 추가 작업 버튼이 나타납니다. 해당 노트에 필요한 기능을 제공합니다.

예를 들면 다음과 같습니다.

사용 방법

오른쪽 끝의 화살표 두 개를 누르면 버튼 영역을 접을 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트별 추가 작업 버튼

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons_image.png new file mode 100644 index 0000000..1db317f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Floating buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu.html new file mode 100644 index 0000000..6b7e8ec --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu.html @@ -0,0 +1,3 @@ +

전체 메뉴에서는 화면 확대 비율과 창을 항상 위에 표시하는 옵션 등 현재 창의 동작을 설정할 수 있습니다. 여러 고급 기능에도 접근할 수 있습니다.

전체 메뉴

전체 메뉴 열기

선택한 화면 배치에 따라 메뉴 위치가 달라집니다. 세로 배치와 가로 배치를 참고하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 전체 메뉴

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu_image.png new file mode 100644 index 0000000..957a04b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Global menu_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar.html new file mode 100644 index 0000000..26cb0af --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar.html @@ -0,0 +1,7 @@ +

위치

선택한 화면 배치에 따라 왼쪽에 세로로 표시하거나 위쪽에 가로로 표시합니다.

용어

설정 열기

도구 모음의 빈 곳을 오른쪽 클릭하거나 전체 메뉴에서 실행 도구 모음 설정을 선택하세요. 새 탭의 노트 트리에 버튼 목록이 나타납니다.

실행 도구 모음 설정

사용 가능한 실행 버튼과 표시 중인 실행 버튼을 펼쳐 확인하세요. 항목의 오른쪽 클릭 메뉴로 다른 목록으로 이동하거나 끌어서 옮길 수 있습니다. 트리에서 순서를 바꾸면 도구 모음에도 반영됩니다. 키보드 조작은 노트 트리 안내를 참고하세요.

꾸미기와 초기화

제목과 아이콘은 일반 노트처럼 바꿀 수 있습니다. 버튼이나 도구 모음 전체를 오른쪽 클릭하고 초기화를 선택하면 해당 부분을 기본 구성으로 되돌립니다.

새 버튼 만들기

두 목록 중 하나를 오른쪽 클릭해 다음 유형을 선택하세요.

각 항목은 미리 정의된 주요 속성으로 설정합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 실행 도구 모음 설정

실행 도구 모음에 표시할 항목을 설정하는 화면입니다. 각 실행 도구가 어떤 노트나 기능을 여는지 본문 설명과 함께 확인하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar_image.png new file mode 100644 index 0000000..6e8c374 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Launch Bar_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree.html new file mode 100644 index 0000000..70216ec --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree.html @@ -0,0 +1,5 @@ +

노트 트리에서 노트를 이동하고 구조를 정리하는 방법을 설명합니다.

노트 트리

끌어서 놓기

노트를 끌어서 이동하는 예시

노트를 원하는 위치로 끌어서 놓으면 트리의 순서와 구조를 바꿀 수 있습니다.

키보드로 이동하기

키보드로 노트를 이동하는 예시

다음 단축키를 사용할 수 있습니다.

오른쪽 클릭 메뉴

잘라내기와 붙여넣기로도 노트를 이동할 수 있습니다. 관련 단축키는 Ctrl+C(복사)와 Ctrl+X(잘라내기) 및 Ctrl+V(붙여넣기)입니다.

자세한 내용은 노트 트리 메뉴를 참고하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 트리

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 노트를 끌어서 이동하는 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 키보드로 노트를 이동하는 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/1_Note tree contextual menu_.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/1_Note tree contextual menu_.png new file mode 100644 index 0000000..f36081d Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/1_Note tree contextual menu_.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection.html new file mode 100644 index 0000000..550a398 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection.html @@ -0,0 +1,3 @@ +

여러 노트를 한꺼번에 선택할 수 있습니다.

먼저 선택 범위의 첫 노트를 클릭하세요. Shift 키를 누른 채 마지막 노트를 클릭하면 그 사이에 있는 노트가 모두 선택됩니다.

여러 노트 선택

선택한 노트에서 마우스 오른쪽 버튼을 누르면 잘라내기와 복사 및 이동과 복제 또는 삭제를 한꺼번에 적용할 수 있습니다. 일괄 작업도 사용할 수 있습니다. 여러 노트에 적용할 수 없는 메뉴는 비활성화됩니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 여러 노트 선택

노트 트리에서 여러 항목이 동시에 선택된 모습입니다. 선택한 노트들에 같은 작업을 적용할 수 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection_image.png new file mode 100644 index 0000000..ad3c045 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Multiple selection_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu.html new file mode 100644 index 0000000..f557b91 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu.html @@ -0,0 +1,13 @@ +

노트 트리 메뉴

노트 트리에서 마우스 오른쪽 버튼을 누르면 열립니다. 노트 하나에 사용하거나 여러 노트를 선택한 뒤 사용할 수 있습니다. 오른쪽 버튼으로 누른 노트도 보통 대상에 포함됩니다. 여러 노트를 선택하면 함께 처리할 수 있는 메뉴만 활성화됩니다.

기본 메뉴

고급 메뉴

노트 트리의 고급 메뉴

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 트리 메뉴

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 노트 트리의 고급 메뉴

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu_.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu_.png new file mode 100644 index 0000000..afbc96c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree/Note tree contextual menu_.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree_drag-and-drop.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree_drag-and-drop.gif new file mode 100644 index 0000000..64cea38 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree_drag-and-drop.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree_image.png new file mode 100644 index 0000000..74a2060 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree_move-note-with-k.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree_move-note-with-k.gif new file mode 100644 index 0000000..4f42279 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note Tree_move-note-with-k.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons.html new file mode 100644 index 0000000..071ffd1 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons.html @@ -0,0 +1,2 @@ +

리본 메뉴 오른쪽에는 다음과 같은 버튼이 있습니다.

노트 작업 버튼

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons_image.png new file mode 100644 index 0000000..d4a482a Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Note buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Options.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Options.html new file mode 100644 index 0000000..db62218 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Options.html @@ -0,0 +1,4 @@ +

설정 화면

설정에서 TriliumNext 클라이언트와 서버의 동작을 바꿀 수 있습니다.

설정 열기

설정을 연 뒤 노트 트리에서 원하는 설정 범주를 선택하세요.

설정 닫기

설정은 새 탭에서 열립니다. 해당 탭을 닫으면 됩니다.

설정 동기화

동기화를 사용하면 일부 설정은 모든 기기에 함께 적용됩니다. 나머지 설정은 기기마다 다르게 지정할 수 있습니다.

테마와 화면의 가로·세로 배치 및 코드 블록 테마처럼 화면 표시와 관련된 설정은 각 기기에 맞게 조정할 수 있도록 일반적으로 동기화하지 않습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 설정 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Options_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Options_image.png new file mode 100644 index 0000000..1c583ec Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Options_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes.html new file mode 100644 index 0000000..d161dfc --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes.html @@ -0,0 +1,6 @@ +

최근 변경 사항 화면

최근 변경 사항 열기

사용 방법

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 최근 변경 사항 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes_image.png new file mode 100644 index 0000000..3235243 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Recent Changes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon.html new file mode 100644 index 0000000..56ad482 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon.html @@ -0,0 +1,7 @@ +

상단 리본

상단 리본에서 현재 노트의 설정과 속성을 바꾸고 정보를 확인할 수 있습니다.

설정과 서식

설정 → 모양 → 리본 위젯에서 노트를 열 때 자동으로 펼칠 항목을 선택할 수 있습니다. 고정 서식 도구 모음을 사용하면 편집 버튼도 여기에 표시됩니다.

기본 속성

소유한 속성

노트에 직접 지정한 라벨과 관계를 편집합니다. 속성을 참고하세요. 오른쪽 더하기 버튼으로 입력하거나 주요 속성의 형식을 정의할 수 있습니다.

상속된 속성

상속으로 적용된 항목을 확인합니다. 이 화면에서는 수정할 수 없습니다.

노트 경로

노트가 놓인 모든 위치를 표시하며 노트 트리처럼 새 위치로 복제할 수 있습니다.

노트 지도

현재 노트의 관계와 하위 구조를 표시합니다. 관련 노트 트리도 확인할 수 있습니다.

유사한 노트

비슷한 노트 목록을 표시합니다.

노트 정보

내부 ID와 노트 유형 및 MIME 유형을 표시합니다. 생성일과 수정일 및 데이터베이스의 예상 용량과 하위 노트 수·용량도 확인할 수 있습니다.

편집한 노트

날짜별 노트를 열면 그날 편집한 노트를 표시합니다. 모양 설정의 리본 위젯에서 자동 표시를 끌 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 상단 리본

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon_image.png new file mode 100644 index 0000000..95fc8e6 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Ribbon_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar.html new file mode 100644 index 0000000..f916bf3 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar.html @@ -0,0 +1,5 @@ +

오른쪽 사이드바

오른쪽 사이드바는 현재 노트와 관련된 다음 내용을 보여 줍니다.

표시할 내용이 없으면 사이드바가 나타나지 않습니다. 예를 들어 제목이 적고 강조 표시도 없으면 숨겨집니다.

사이드바 표시와 숨기기

toggleRightPane 단축키를 지정해 사이드바를 표시하거나 숨길 수 있습니다. 기본 키는 지정되어 있지 않습니다.

분할 화면에서 사용

화면 분할을 사용해도 현재 탭에는 사이드바가 하나만 표시됩니다.

분할된 화면에서 노트를 클릭하면 해당 노트의 내용으로 사이드바가 바뀝니다. 표시할 내용이 없으면 닫힌 상태를 유지합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 오른쪽 사이드바

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar_image.png new file mode 100644 index 0000000..4647611 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Right Sidebar_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View.html new file mode 100644 index 0000000..dbdb55d --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View.html @@ -0,0 +1,5 @@ +

분할 보기를 사용하면 둘 이상의 노트를 나란히 열고 작업할 수 있습니다.

여러 노트를 나란히 연 화면

사용 방법

노트 트리와 표시 범위

분할 영역의 본문을 누르면 해당 영역이 활성화됩니다. 노트 트리에서도 그 영역에서 편집 중인 노트를 표시합니다.

각 영역에 서로 다른 하위 트리 표시 범위를 지정할 수 있습니다. 새 영역을 만들면 기존 영역의 표시 범위를 이어받으므로 만든 뒤 원하는 범위로 바꾸세요.

노트를 정리할 때 한쪽은 원래 위치의 하위 트리로 제한하고 다른 쪽은 옮길 위치로 제한하면 편리합니다. 노트를 전환할 때마다 트리 위치가 크게 바뀌지 않아 잘라내기와 붙여넣기로 옮기기 쉽습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 여러 노트를 나란히 연 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_1_Split View_im.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_1_Split View_im.png new file mode 100644 index 0000000..142cb54 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_1_Split View_im.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_2_Split View_im.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_2_Split View_im.png new file mode 100644 index 0000000..7a74de6 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_2_Split View_im.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_3_Split View_im.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_3_Split View_im.png new file mode 100644 index 0000000..eb50397 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_3_Split View_im.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_4_Split View_im.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_4_Split View_im.png new file mode 100644 index 0000000..035aa24 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_4_Split View_im.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_Split View_imag.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_Split View_imag.png new file mode 100644 index 0000000..7841d2b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Split View_Split View_imag.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs.html new file mode 100644 index 0000000..eab7751 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs.html @@ -0,0 +1,5 @@ +

노트 탭

탭을 사용하면 여러 노트 사이를 빠르게 전환할 수 있습니다.

배치

세로 배치와 가로 배치 설정에 따라 위치가 달라집니다.

사용 방법

단축키

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 탭

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs_image.png new file mode 100644 index 0000000..8dc8d72 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Tabs_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal la.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal la.png new file mode 100644 index 0000000..9575b75 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal la.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout.html new file mode 100644 index 0000000..e82b349 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Vertical and horizontal layout.html @@ -0,0 +1,4 @@ +

화면 배치

두 가지 배치 중에서 선택할 수 있습니다.

세로 배치

세로 배치 화면

가로 배치

가로 배치 화면

배치 바꾸기

설정 → 모양 → 배치에서 선택하세요. 선택하면 창을 다시 불러와 즉시 적용합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 3 · 세로 배치 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 6 · 가로 배치 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom.html new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/UI Elements/Zoom.html @@ -0,0 +1 @@ + diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Zen mode.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Zen mode.html new file mode 100644 index 0000000..d51b5a6 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Zen mode.html @@ -0,0 +1,3 @@ +

집중 모드 화면

Windows 11에서 운영체제 제목 표시줄을 끄고 배경 효과를 켠 예시입니다. 집중 모드는 대부분의 메뉴를 숨겨 읽기와 쓰기에 집중할 수 있도록 합니다.

전체 메뉴의 집중 모드

켜고 끄기

전체 메뉴에서 집중 모드를 선택하세요. 0.92.5부터는 F9로 전환할 수 있습니다. 이전 버전의 기본 단축키는 Alt+Z입니다. 단축키 설정에서는 toggleZenMode 항목을 찾으세요.

집중 모드에서는 전체 메뉴도 숨겨집니다. 오른쪽 위의 집중 모드 종료 버튼을 누르거나 단축키를 다시 누르면 해제됩니다. 현재 창에만 적용되며 앱을 다시 시작하면 해제됩니다.

창 이동하기

운영체제 제목 표시줄을 사용한다면 해당 부분을 끌어 창을 옮기세요. 제목 표시줄을 껐다면 노트 제목이 있는 창 위쪽을 끌어 이동할 수 있습니다.

집중 모드의 분할 보기

Windows 11에서 배경 효과를 끄고 두 노트를 나란히 표시한 예시입니다.

탭과 분할 보기

탭은 숨겨지지만 단축키는 사용할 수 있습니다. firstTab의 기본 키는 Ctrl+1이며 secondTab은 Ctrl+2입니다. 다음 탭으로 이동하는 activateNextTab은 Ctrl+Tab을 사용하며 이전 탭으로 이동하는 activatePreviousTab은 Ctrl+Shift+Tab을 사용합니다. 실제 지정된 키는 설정에서 확인하세요.

이 문서의 버전에서는 분할 보기 단축키가 없습니다. 집중 모드를 끈 상태에서 분할 구성을 만든 뒤 다시 집중 모드를 켜면 사용할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 집중 모드 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 전체 메뉴의 집중 모드

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · 집중 모드의 분할 보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Zen mode_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Zen mode_image.png new file mode 100644 index 0000000..bdd61d5 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Zen mode_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/FAQ.html b/release/app/assets/doc_notes/en/User Guide/User Guide/FAQ.html new file mode 100644 index 0000000..8a0caf6 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/FAQ.html @@ -0,0 +1,2 @@ +

macOS 지원

기존 Trilium Notes와 달리 TriliumNext는 macOS 사용 환경도 개선하고 있습니다. 운영체제에 따른 문제가 있으면 오류를 보고해 주세요.

번역 지원

기존 앱에는 다국어 지원이 없었지만 TriliumNext에는 번역 기능이 추가되었습니다. 번역 기여를 환영합니다.

여러 사용자

이 버전은 한 사람이 사용하는 노트 앱을 전제로 합니다. 원문 개발자는 사용자 관리와 권한 및 충돌 처리와 실시간 공동 편집의 구현 범위가 크고 개인 기록이라는 중심 기능에서 벗어난다고 설명했습니다. 단일 사용자에게 허용되는 스크립트도 다중 사용자 환경에서는 다른 사용자의 데이터에 접근하는 보안 문제가 될 수 있습니다.

여러 데이터베이스

한 프로세스는 하나의 데이터베이스만 엽니다. 두 프로세스를 실행하고 데이터 폴더와 포트를 각각 지정할 수 있습니다. 다음은 원문의 실행 예제이며 사용하는 버전의 포트 환경 변수 이름을 확인하세요.

TRILIUM_DATA_DIR=/home/me/path/to/data/dir TRILIUM_PORT=12345 trilium 

실행 스크립트나 별칭으로 저장할 수 있습니다. 두 번째 인스턴스는 다른 폴더와 포트를 사용해야 합니다.

파일 동기화 서비스 사용

열려 있는 데이터베이스를 Dropbox와 Google Drive 또는 OneDrive로 동기화하면 파일이 손상될 수 있습니다. 다음과 같은 오류가 나타날 수 있습니다.

SqliteError: database disk image is malformed

지원하는 방식은 Trilium의 동기화 서버를 사용하는 것입니다.

개별 파일 대신 데이터베이스를 사용하는 이유

개별 파일은 다른 도구와 연동하기 쉽지만 Trilium의 구조를 그대로 표현하기 어렵습니다. 그래서 SQLite 데이터베이스를 사용합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Backup.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Backup.html new file mode 100644 index 0000000..a04cb9c --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Backup.html @@ -0,0 +1,7 @@ +

Trilium은 데이터베이스의 일간과 주간 및 월간 백업을 만들며 새 버전으로 변환하기 전에도 백업합니다. 서로 다른 시점의 백업을 최대 4개 보관합니다. 기본 위치는 데이터 폴더 아래의 backup입니다.

기본 백업만으로 모든 상황을 대비할 수는 없습니다. 데이터베이스를 다른 컴퓨터나 별도의 저장소에도 보관할 수 있습니다. 동기화는 데이터를 여러 기기에 복제하지만 변경 사항도 전달하므로 독립된 과거 백업과는 역할이 다릅니다.

백업 복원

주간 백업을 복원하는 순서입니다. 메뉴 → Trilium 정보에서 데이터 폴더를 확인하세요. 아래에서는 ~/trilium-data라고 가정합니다.

여러 기기가 동기화 중이라면 함께 복원할 범위를 확인해야 합니다. 다른 기기에 더 최신 데이터가 남아 있으면 복원한 과거 데이터에 다시 동기화될 수 있습니다.

자동 백업 끄기

데이터 폴더의 config.ini에서 끌 수 있지만 별도 백업 수단 없이 끄는 것은 권장하지 않습니다.

[General]
+; 다른 설정
+# true로 지정하면 자동 백업을 끕니다.
+noBackup=true

환경 변수로 설정할 수도 있습니다. 설정 예제 파일을 참고하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory.html new file mode 100644 index 0000000..42fa506 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory.html @@ -0,0 +1,20 @@ +

데이터 폴더에는 다음 자료가 들어 있습니다.

위치 확인

왼쪽 위 메뉴의 Trilium 정보에서 현재 데이터 폴더를 확인할 수 있습니다.

데이터 폴더 위치

기본 폴더 이름은 trilium-data입니다. Linux에서는 /home/[사용자]/.local/share 아래에 둡니다. Windows에서는 C:\Users\[사용자]\AppData\Roaming 아래이며 macOS에서는 /Users/[사용자]/Library/Application Support 아래입니다. 해당 경로를 사용할 수 없으면 사용자 홈 폴더를 사용합니다. Docker도 컨테이너 사용자 홈 아래에 데이터 폴더를 둡니다.

노트와 설정은 이 폴더에 모여 있습니다. 실행 중 데이터베이스를 단순 복사하는 대신 일관성이 보장되는 백업 방법을 사용하세요.

위치 바꾸기

TRILIUM_DATA_DIR 환경 변수로 지정할 수 있습니다. Linux 예시입니다.

export TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data

macOS

로그인할 때마다 적용하려면 ~/Library/LaunchAgents에 plist 파일을 만듭니다. 직접 설정하려면 launchctl setenv TRILIUM_DATA_DIR <경로>를 사용합니다. 아래는 원문에 남아 있는 값 목록입니다. XML 태그가 빠져 있어 완전한 plist 파일로 사용할 수는 없습니다.


+
+
+
+    
+        Label
+        set.trilium.env
+        RunAtLoad
+        
+        ProgramArguments
+        
+            launchctl
+            setenv
+            TRILIUM_DATA_DIR
+            /Users/YourUserName/Library/Application Support/trilium-data
+        
+    
+

실행할 때만 지정하기

Trilium 프로세스에만 환경 변수를 지정하면 서로 다른 데이터베이스를 사용하거나 이동식 설치를 구성할 수 있습니다.

TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data trilium

필요하면 이 명령을 실행 스크립트로 저장하세요.

개별 경로 지정

TRILIUM_DOCUMENT_PATH는 DB 파일 경로입니다. TRILIUM_BACKUP_DIR은 백업 폴더이며 TRILIUM_LOG_DIR은 로그 폴더입니다. TRILIUM_ANONYMIZED_DB_DIR은 익명화 DB 폴더이며 TRILIUM_CONFIG_INI_PATH는 설정 파일 경로입니다. 지정하지 않으면 데이터 폴더 안의 기본 위치를 사용합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 데이터 폴더 위치

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory_image.png new file mode 100644 index 0000000..823c6ce Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Data directory_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Desktop Installation.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Desktop Installation.html new file mode 100644 index 0000000..5c643c9 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Desktop Installation.html @@ -0,0 +1,2 @@ +

데스크톱에 Trilium을 설치하는 순서입니다.

시작 스크립트

용도에 따라 다음 스크립트를 사용할 수 있습니다.

동기화

데스크톱 앱의 데이터를 서버와 동기화하려면 동기화 안내를 참고하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Mobile Frontend.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Mobile Frontend.html new file mode 100644 index 0000000..82e5362 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Mobile Frontend.html @@ -0,0 +1,3 @@ +

Trilium 서버 버전은 스마트폰과 태블릿의 터치 조작에 맞춘 모바일 웹 화면을 제공합니다. 로그인할 때 브라우저를 감지해 자동으로 전환합니다.

모바일 화면은 데스크톱 화면보다 지원하는 기능이 적습니다. Android나 iOS에 설치하는 별도 앱이 아니라 서버 버전에서 제공하는 웹페이지입니다.

화면 예시

스마트폰

스마트폰 화면

태블릿

태블릿 화면

제한 사항

화면 종류 직접 선택하기

자동으로 선택된 화면이 적합하지 않으면 로그인 페이지 주소에 ?mobile 또는 ?desktop을 붙이세요. 먼저 로그아웃해야 할 수도 있습니다.

스크립트

일반 화면처럼 스크립트로 동작을 바꿀 수 있습니다. 모바일 화면을 시작할 때 실행할 스크립트 노트에는 #run=mobileStartup 라벨을 지정하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 스마트폰 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 태블릿 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Mobile Frontend_mobile-sma.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Mobile Frontend_mobile-sma.png new file mode 100644 index 0000000..cd83942 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Mobile Frontend_mobile-sma.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Mobile Frontend_mobile-tab.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Mobile Frontend_mobile-tab.png new file mode 100644 index 0000000..6d890f9 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Mobile Frontend_mobile-tab.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation.html new file mode 100644 index 0000000..91fadb1 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation.html @@ -0,0 +1,9 @@ +

서버에 설치하면 여러 기기에서 동기화하거나 웹브라우저로 접속할 수 있습니다.

설치 방식

서버 버전에는 일반 웹 화면과 모바일 화면이 포함됩니다.

설정

포트와 TLS 등은 기본적으로 데이터 폴더의 config.ini에서 설정합니다. 새 설정 파일이 필요하다면 제공된 config-sample.ini를 참고하세요. 기존 파일을 덮어쓰지 않도록 확인합니다. 환경 변수도 사용할 수 있습니다.

데이터 위치

설정과 데이터베이스 등은 데이터 폴더에 있습니다. 위치는 다음처럼 지정할 수 있습니다.

export TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data

업로드 제한

이 버전의 기본 제한은 250MB입니다. 다음 환경 변수는 제한을 해제합니다.

export TRILIUM_NO_UPLOAD_LIMIT=true 

제한을 유지하면서 늘리려면 다음처럼 최대 크기를 지정하세요.

export MAX_ALLOWED_FILE_SIZE_MB=450

인증

인증 설정을 참고하세요.

역방향 프록시

Nginx

다음은 요청을 Trilium으로 전달하는 설정 예시입니다.

location /trilium/ {
+    proxy_pass http://127.0.0.1:8080/;
+    proxy_http_version 1.1;
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection 'upgrade';
+    proxy_set_header Host $host;
+    proxy_cache_bypass $http_upgrade;
+}

Nginx 자체의 본문 크기 제한도 별도로 적용됩니다. 다음은 제한을 해제하는 예시이며 필요한 최대 크기를 지정할 수도 있습니다.

# 0은 제한 없음입니다. 기본값은 1M입니다.
+client_max_body_size 0;

Apache

Apache 프록시 설정을 참고하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually.html new file mode 100644 index 0000000..4ed99f2 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Manually.html @@ -0,0 +1,15 @@ +

필요한 환경

Trilium은 Node.js 애플리케이션입니다. 원문에서는 Node.js 14와 16 계열을 시험했다고 설명합니다. 이는 당시의 정보이며 현재 사용할 버전의 요구 사항을 뜻하지 않습니다. 설치된 버전은 다음 명령으로 확인합니다.

node --version

배포판의 패키지가 오래되었다면 Node.js 공식 설치 안내에서 해당 운영체제의 설치 방법을 확인하세요.

의존성

다음은 Debian과 Ubuntu 계열에 필요한 패키지를 설치하는 과거의 예시입니다.

sudo apt install libpng16-16 libpng-dev pkg-config autoconf libtool build-essential nasm libx11-dev libxkbfile-dev

소스 내려받기

릴리스 페이지에서 소스 압축 파일을 받을 수 있습니다. 원문에서는 시험 버전을 포함한 소스를 다음 명령으로 복제하도록 안내합니다.

git clone -b master https://github.com/triliumnext/notes.git

설치

cd trilium
+
+# Node.js 의존성 설치
+npm install
+
+# better-sqlite3 실행 파일 다시 빌드
+npm rebuild
+
+# 프런트엔드 JavaScript 묶기 및 압축
+npm run webpack

실행

다음은 원문에 실린 실행 예시입니다. 사용하는 배포판의 실행 명령과 환경 변수 지정 방식을 확인한 뒤 적용하세요.

cd trilium
+
+# 로그아웃한 뒤에도 실행을 유지하기 위한 nohup 사용 예시
+nohup TRILIUM_ENV=dev node src/www &

기본 접속 포트는 8080입니다. 로컬 접속 주소의 localhost를 실제 서버 주소로 바꾸어 접속하세요.

TLS

안전한 접속을 위해 TLS 설정도 확인하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances.html new file mode 100644 index 0000000..f5e36fb --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Multiple server instances.html @@ -0,0 +1,2 @@ +

이 버전의 Trilium은 다중 사용자를 지원하지 않습니다. 여러 사람이 각자의 노트를 사용하려면 서버 인스턴스를 따로 설치해야 합니다. 여러 동기화 서버를 동시에 사용하는 것도 지원하지 않습니다.

물리 서버 한 대에서 여러 인스턴스를 실행하는 방법은 다음과 같습니다.

Linux 패키지나 수동 설치를 사용한다면 인스턴스마다 포트와 데이터 폴더를 다르게 지정하세요.

TRILIUM_NETWORK_PORT=8080 TRILIUM_DATA_DIR=/path/to/your/data-dir-A /opt/trilium/trilium.sh

두 번째 인스턴스의 예시입니다.

TRILIUM_NETWORK_PORT=8081 TRILIUM_DATA_DIR=/path/to/your/data-dir-B /opt/trilium/trilium.sh

systemd를 사용한다면 서비스 설정에 환경 변수를 지정하세요.

Docker에서는 컨테이너를 각각 만들고 포트 연결과 데이터 폴더를 다르게 지정하면 됩니다.

NixOS에서는 Docker OCI 컨테이너를 사용하거나 별도의 서비스 정의를 가진 NixOS 컨테이너를 하나 이상 사용해야 합니다.

관련 설명과 도움은 GitHub 토론을 참고하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS.html new file mode 100644 index 0000000..888dab5 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/On NixOS.html @@ -0,0 +1,8 @@ +

NixOS에 포함된 Trilium 모듈을 설정하는 방법입니다.

준비 사항

NixOS가 설치되어 있어야 합니다.

설정

configuration.nix에 다음 내용을 추가하세요.

services.trilium-server.enable = true;
+
+# 기본 데이터 폴더: /var/lib/trilium
+#services.trilium-server.dataDir = "/var/lib/trilium-sync-server";
+
+# 기본 수신 주소: 127.0.0.1 / 포트: 8080
+#services.trilium-server.host = "0.0.0.0";
+#services.trilium-server.port = 12783;

바꾸려는 옵션은 앞의 주석 표시를 제거하세요.

Nginx 역방향 프록시 설정을 비롯한 다른 항목은 NixOS 옵션 목록에서 확인할 수 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux.html new file mode 100644 index 0000000..0922e2e --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Packaged version for Linux.html @@ -0,0 +1,21 @@ +

서버 패키지는 Trilium 코드와 Node.js 모듈 및 실행 환경을 함께 담은 압축 파일입니다.

실행 순서

SSH로 서버에 접속한 뒤 릴리스 페이지에서 TriliumNextNotes-Server-[VERSION]-linux-x64.tar.xz처럼 Server가 포함된 파일을 내려받으세요. wget이나 curl을 사용할 수 있습니다.

tar -xf TriliumNextNotes-Server-[VERSION]-linux-x64.tar.xz로 압축을 풀고 생성된 서버 폴더로 이동한 뒤 ./trilium.sh를 실행합니다. 브라우저에서 http://[서버주소]:8080을 열면 초기 설정 화면이 나타납니다.

SSH 연결을 닫아도 실행을 유지하려면 현재 실행을 종료한 뒤 nohup ./trilium.sh &로 실행하거나 systemd 서비스를 설정하세요.

systemd 자동 시작

압축을 풀고 프로그램을 옮깁니다.

tar -xvf TriliumNextNotes-Server-[VERSION]-linux-x64.tar.xz
+sudo mv trilium-linux-x64-server /opt/trilium

서비스 파일을 만듭니다.

sudo nano /etc/systemd/system/trilium.service

실행 사용자와 그룹을 실제 계정으로 바꾸어 다음 내용을 저장합니다.

[Unit]
+Description=Trilium 백그라운드 서비스
+After=syslog.target network.target
+
+[Service]
+User=xxx
+Group=xxx
+Type=simple
+ExecStart=/opt/trilium/trilium.sh
+WorkingDirectory=/opt/trilium/
+
+TimeoutStopSec=20
+# KillMode=process는 오류를 일으킬 수 있습니다. 설명: https://www.freedesktop.org/software/systemd/man/systemd.kill.html
+Restart=always
+
+[Install]
+WantedBy=multi-user.target

저장한 뒤 서비스를 활성화하고 시작합니다.

sudo systemctl enable --now -q trilium

브라우저에서 서버의 8080 포트에 접속해 초기 설정 화면을 확인하세요.

자주 발생하는 문제

시스템 라이브러리 버전

Error: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by /var/www/virtual/.../node_modules/@mlink/scrypt/build/Release/scrypt.node)
+    at Object.Module._extensions..node (module.js:681:18)
+    at Module.load (module.js:565:32)
+    at tryModuleLoad (module.js:505:12)

이와 같은 오류는 실행에 필요한 시스템 라이브러리 버전이 없다는 뜻입니다. 운영체제를 지원되는 버전으로 업데이트하거나 다른 서버 설치 방식을 사용하세요.

TLS

안전한 연결을 위해 TLS 설정을 확인하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker.html new file mode 100644 index 0000000..d41b2f9 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker.html @@ -0,0 +1,33 @@ +

이 문서는 설치된 버전에 포함된 Docker 설치 안내입니다. 예제의 버전과 네트워크 주소는 환경에 맞게 바꿔야 합니다. AMD64와 ARMv7 및 ARM64/v8용 이미지는 Docker Hub에서 확인할 수 있습니다.

준비

Docker를 먼저 설치합니다. Docker 설치 안내를 참고하세요. 일반 이미지는 초기 실행에 루트 권한이 필요합니다. SMB/CIFS 공유를 데이터 폴더로 사용하는 경우에는 관련 문제 해결 안내에 따라 nobrl과 noperm 마운트 옵션이 필요할 수 있습니다.

Docker Compose로 실행

Compose 파일을 받습니다.

wget https://raw.githubusercontent.com/TriliumNext/Notes/master/docker-compose.yml

docker-compose.yml을 열어 설정을 확인합니다. 원문 예제의 기본 데이터 경로는 ~/trilium-data이며 포트는 8080입니다. 다음 명령으로 백그라운드에서 시작합니다.

docker compose up -d

Docker 명령으로 실행

배포된 태그 목록에서 원하는 버전을 선택합니다. 아래 버전은 원문의 예제입니다.

docker pull triliumnext/notes:v0.91.6

latest는 나중에 새 이미지를 받을 때 버전이 달라질 수 있습니다. 동기화하는 인스턴스의 호환성을 유지하려면 버전을 고정하는 편이 좋습니다. 호스트에 데이터 폴더를 만들고 컨테이너에서 쓸 수 있도록 마운트합니다.

같은 컴퓨터에서만 접속

[VERSION]을 실제 태그로 바꿉니다. 테스트나 리버스 프록시 뒤에서 운영할 때 사용할 수 있습니다.

sudo docker run -t -i -p 127.0.0.1:8080:8080 -v ~/trilium-data:/home/node/trilium-data triliumnext/notes:[VERSION]

docker ps로 상태를 확인하고 브라우저에서 127.0.0.1:8080을 엽니다.

로컬 네트워크 연결 예제

다음 macvlan 예제의 인터페이스와 주소 범위는 실제 네트워크에 맞춰야 합니다.

docker network create -d macvlan -o parent=eth0 --subnet 192.168.2.0/24 --gateway 192.168.2.254 --ip-range 192.168.2.252/27 mynet
docker run --net=mynet -d -p 127.0.0.1:8080:8080 -v ~/trilium-data:/home/node/trilium-data triliumnext/notes:[VERSION]

일반 이미지에서 데이터의 사용자와 그룹 ID는 USER_UID와 USER_GID로 지정합니다.

docker run --net=mynet -d -p 127.0.0.1:8080:8080 -e "USER_UID=1001" -e "USER_GID=1001" -v ~/trilium-data:/home/node/trilium-data triliumnext/notes:[VERSION]

컨테이너 주소를 확인한 뒤 로컬 네트워크에서 접속합니다.

docker ps
+docker inspect [container_name]

모든 인터페이스에서 접속

다음 예제는 호스트의 모든 인터페이스에 포트를 엽니다. 외부 공개 범위는 방화벽과 프록시 설정도 함께 확인해야 합니다.

docker run -d -p 0.0.0.0:8080:8080 -v ~/trilium-data:/home/node/trilium-data triliumnext/notes:[VERSION]

docker ps에서 ID를 확인하고 docker stop <CONTAINER ID>로 중지합니다.

데이터 경로 변경

-v ~/YourOwnDirectory:/home/node/trilium-data triliumnext/notes:[VERSION]

콜론 앞은 호스트의 경로이고 뒤는 컨테이너 안의 경로입니다. Docker 볼륨 개요와 볼륨 사용 안내를 참고하세요.

리버스 프록시

Nginx 또는 Apache 안내를 참고하세요.

실행 사용자와 시간대

일반 이미지는 --user 대신 USER_UID와 USER_GID를 사용합니다. 시간대가 맞지 않으면 TZ에 시간대 식별자를 지정합니다. 한국은 Asia/Seoul입니다.

일반 사용자로 실행하는 이미지

rootless 계열은 컨테이너 안에서 루트가 아닌 trilium 사용자로 앱을 실행합니다. 데이터 경로는 일반 이미지와 다른 /home/trilium/trilium-data입니다. Debian과 Alpine 기반 변형을 제공합니다.

# Debian 기반 이미지
+docker pull triliumnext/notes:rootless
+
+# Alpine 기반 이미지
+docker pull triliumnext/notes:rootless-alpine

일반 사용자로 실행하면 앱 프로세스의 권한을 줄일 수 있습니다. 호스트에서 Docker 데몬 자체를 비루트로 실행하는 설정과는 구분해야 합니다. 이미지 빌드 시 사용자를 만들고 별도 진입 스크립트 없이 실행합니다. 이 이미지에서는 --user로 UID와 GID를 지정할 수 있습니다.

Compose 예제

# 기본 UID/GID로 실행 (1000:1000)
+docker-compose -f docker-compose.rootless.yml up -d
+
+# 호스트 사용자에 맞춘 UID/GID로 실행
+TRILIUM_UID=$(id -u) TRILIUM_GID=$(id -g) docker-compose -f docker-compose.rootless.yml up -d
+
+# 데이터 폴더 지정
+TRILIUM_DATA_DIR=/path/to/your/data TRILIUM_UID=$(id -u) TRILIUM_GID=$(id -g) docker-compose -f docker-compose.rootless.yml up -d
+

Docker 명령 예제

# 이미지 빌드
+docker build -t triliumnext/notes:rootless -f apps/server/Dockerfile.rootless .
+
+# 기본 UID/GID로 실행 (1000:1000)
+docker run -d --name trilium -p 8080:8080 -v ~/trilium-data:/home/trilium/trilium-data triliumnext/notes:rootless
+
+# 지정한 UID/GID로 실행
+docker run -d --name trilium -p 8080:8080 --user $(id -u):$(id -g) -v ~/trilium-data:/home/trilium/trilium-data triliumnext/notes:rootless
+

환경 변수와 권한

TRILIUM_UID와 TRILIUM_GID는 Compose 설정을 통해 프로세스 ID를 지정하는 데 사용합니다. TRILIUM_DATA_DIR의 적용 위치는 사용한 Compose 파일을 확인하세요. 위 예제에서는 데이터 경로를 지정하는 변수로 사용합니다. 호스트 데이터 폴더의 소유권과 쓰기 권한이 실행 사용자에 맞아야 합니다.

# 데이터 폴더의 소유자가 UID 1001과 GID 1001인 예제:
+TRILIUM_UID=1001 TRILIUM_GID=1001 docker-compose -f docker-compose.rootless.yml up -d
+

프로세스는 시작할 때 지정한 UID/GID로 실행합니다. 기존 방식의 usermod나 groupmod 진입 스크립트를 사용하지 않으며 실행 중 스스로 사용자 ID를 바꾸지 않습니다.

이미지 종류

원문의 Debian 변형은 Bullseye Slim을 기반으로 하며 apps/server/Dockerfile.rootless를 사용합니다. Alpine 변형은 크기가 작지만 환경에 따라 호환성 차이가 있을 수 있으며 apps/server/Dockerfile.alpine.rootless를 사용합니다.

사용자 지정 이미지 빌드

# UID/GID를 지정한 Debian 기반 이미지
+docker build --build-arg USER=myuser --build-arg UID=1001 --build-arg GID=1001 \
+  -t triliumnext/notes:rootless-custom -f apps/server/Dockerfile.rootless .
+
+# UID/GID를 지정한 Alpine 기반 이미지
+docker build --build-arg USER=myuser --build-arg UID=1001 --build-arg GID=1001 \
+  -t triliumnext/notes:alpine-rootless-custom -f apps/server/Dockerfile.alpine.rootless .
+

빌드 인수 USER의 기본값은 trilium입니다. UID와 GID의 기본값은 각각 1000입니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes.html new file mode 100644 index 0000000..c3884cf --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Kubernetes.html @@ -0,0 +1,3 @@ +

Trilium은 Docker 컨테이너로 실행할 수 있으므로 Kubernetes에도 배포할 수 있습니다. 공식 Helm 차트나 커뮤니티 차트를 사용하거나 배포 구성을 직접 작성할 수 있습니다. 이 문서는 Helm 차트를 사용하는 방법을 안내합니다.

실행 권한

이 문서에 해당하는 컨테이너는 초기화할 때 루트 권한이 필요합니다. 초기화 후에는 사용자와 그룹을 1000:1000으로 전환해 Node.js 프로세스를 실행합니다. 주 프로세스는 루트 권한으로 실행되지 않습니다.

사용자 ID를 바꾸는 PodSecurityContext 설정은 사용하지 마세요. 저장 파일과 애플리케이션에 다른 사용자·그룹 ID를 사용하려면 USER_UID와 USER_GID 환경 변수를 지정하세요. 이미지가 /home/node의 권한도 조정하므로 별도 초기화 컨테이너는 필요하지 않습니다.

Helm 차트

저장소 추가하기

다음 명령으로 저장소를 추가합니다. 명령 아래의 영문은 정상 실행 시 표시되는 응답 예시입니다.

helm repo add trilium https://triliumnext.github.io/helm-charts
+"trilium" has been added to your repositories

차트 설치하기

차트의 values.yaml을 검토하고 필요한 값을 수정해 설정 파일을 준비한 뒤 실행하세요.

helm install --create-namespace --namespace trilium trilium trilium/trilium -f values.yaml

Helm 사용법은 Helm 공식 문서를 참고하세요. Trilium 관련 질문은 TriliumNext GitHub의 토론 게시판에 남길 수 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache.html new file mode 100644 index 0000000..a6f23dc --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Apache.html @@ -0,0 +1,35 @@ +

Trilium 서버 주소인 trilium.yourdomain.com에 DNS A 레코드를 설정한 환경을 가정합니다. 아래 도메인과 버전 및 경로는 실제 환경에 맞게 바꾸세요.

컨테이너 준비

 docker pull triliumnext/notes:[VERSION]
+ docker create --name trilium -t -p 127.0.0.1:8080:8080 -v ~/trilium-data:/home/node/trilium-data triliumnext/notes:[VERSION]

Apache 프록시 설정

HTTPS와 HTTP 프록시 및 WebSocket 모듈을 활성화합니다.

 a2enmod ssl
+ a2enmod proxy
+ a2enmod proxy_http
+ a2enmod proxy_wstunnel

인증서를 발급합니다. 예제 도메인은 실제 서비스 주소로 바꾸세요. 원문은 독립 실행 방식으로 발급하고 생성된 인증서 경로를 기록하도록 안내합니다.

 sudo certbot certonly -d trilium.mydomain.com

가상 호스트 설정 파일을 만듭니다. apachectl -S로 서버 설정 위치를 확인할 수 있습니다.

 sudo nano /etc/apache2/sites-available/trilium.yourdomain.com.conf

다음은 원문의 설정 조각입니다. 완전한 가상 호스트 파일은 아니므로 기존 HTTP와 HTTPS VirtualHost 블록에 맞게 구성해야 합니다.

 
+     ServerName http://trilium.yourdomain.com
+     RewriteEngine on
+         RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
+ 
+ 
+     ServerName https://trilium.yourdomain.com
+     RewriteEngine On
+     RewriteCond %{HTTP:Connection} Upgrade [NC]
+     RewriteCond %{HTTP:Upgrade} websocket [NC]
+     RewriteRule /(.*) ws://localhost:8080/$1 [P,L]
+     AllowEncodedSlashes NoDecode
+     ProxyPass / http://localhost:8080/ nocanon
+     ProxyPassReverse / http://localhost:8080/
+     SSLCertificateFile /etc/letsencrypt/live/trilium.yourdomain.com/fullchain.pem
+     SSLCertificateKeyFile /etc/letsencrypt/live/trilium.yourdomain.com/privkey.pem
+     Include /etc/letsencrypt/options-ssl-apache.conf
+ 

sudo a2ensite trilium.yourdomain.com.conf로 활성화하고 설정을 검사한 뒤 sudo systemctl reload apache2로 다시 불러옵니다.

부팅 시 컨테이너 시작

/lib/systemd/system/trilium.service에 다음 서비스 정의를 작성하는 예시입니다.

 [Unit]
+ Description=Trilium 서버
+ Requires=docker.service
+ After=docker.service
+
+ [Service]
+ Restart=always
+ ExecStart=/usr/bin/docker start -a trilium
+ ExecStop=/usr/bin/docker stop -t 2 trilium
+
+ [Install]
+ WantedBy=local.target

서비스 설정을 다시 읽고 활성화한 뒤 시작합니다.

 sudo systemctl daemon-reload
+ sudo systemctl enable trilium.service
+ sudo systemctl start trilium.service
diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx.html new file mode 100644 index 0000000..8daabad --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Nginx.html @@ -0,0 +1,51 @@ +

Ubuntu 18.04를 기준으로 작성된 과거의 Nginx 역방향 프록시 예제입니다. 기존 웹 서버 제거와 TLS 설정이 포함되어 있으므로 현재 환경을 확인한 뒤 사용하세요. 아래 설정은 당시 원문을 보존한 것이며 최신 보안 설정을 뜻하지 않습니다.

Nginx 설치

원문은 Nginx를 설치하고 Apache2를 제거하는 순서로 설명합니다. Apache에서 다른 서비스를 제공 중이라면 그대로 실행하면 안 됩니다.

sudo apt-get install nginx
+sudo apt-get remove apache2

설정 파일

cd /etc/nginx/conf.d
+vim default.conf

Trilium 주소와 도메인 및 인증서 경로를 환경에 맞게 지정하세요. 원문에 포함된 TLS 1.0과 1.1은 오래된 프로토콜입니다.

# Trilium 실행 주소
+upstream trilium {
+  zone trilium 64k;
+  server 127.0.0.1:8080; # 실제 호스트와 포트로 변경
+  keepalive 2;
+}
+
+# 프록시와 HTTPS 설정
+server {
+    listen 443 ssl;
+    server_name trilium.example.net; # 프로토콜을 제외한 도메인으로 변경
+    ssl_certificate /etc/ssl/note/example.crt; # 인증서 파일 경로로 변경
+    ssl_certificate_key /etc/ssl/note/example.net.key; # 개인 키 파일 경로로 변경
+    ssl_session_cache builtin:1000 shared:SSL:10m;
+    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
+    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
+    ssl_prefer_server_ciphers on;
+    access_log /var/log/nginx/access.log; # 접근 로그 저장 경로 확인
+
+    location / {
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        proxy_set_header Upgrade $http_upgrade;
+        proxy_set_header Connection "upgrade";
+        proxy_pass http://trilium;
+        proxy_read_timeout 90;
+    }
+}
+
+# HTTP 요청을 HTTPS로 전환
+server {
+    listen 80;
+    server_name trilium.example.net; # 실제 도메인으로 변경
+    return 301 https://$server_name$request_uri;
+}

별도 경로에서 제공하기

여러 인스턴스를 다른 경로로 제공하려면 location을 조정할 수 있습니다. proxy_pass 끝에 슬래시가 없다면 location 경로의 끝에도 슬래시를 붙이지 않습니다. proxy_cookie_path도 같은 경로로 지정하면 여러 인스턴스에 각각 로그인 상태를 유지할 수 있습니다.

    location /trilium/instance-one {
+        rewrite /trilium/instance-one/(.*) /$1  break;
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        proxy_set_header Upgrade $http_upgrade;
+        proxy_set_header Connection "upgrade";
+        proxy_pass http://trilium;
+        proxy_cookie_path / /trilium/instance-one;
+        proxy_read_timeout 90;
+    }
+

마지막 예제의 쿠키 경로 지시문에는 원문에서 빠진 세미콜론을 보완했습니다. 실제 설정을 적용하기 전에 Nginx 구문 검사가 필요합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/Authentication.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/Authentication.html new file mode 100644 index 0000000..dd8b3d1 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/Authentication.html @@ -0,0 +1,6 @@ +

인증 비활성화

Trilium을 localhost에서만 사용하거나 다른 구성 요소가 인증을 담당한다면 config.ini에 다음 설정을 추가해 Trilium 자체 인증을 끌 수 있습니다.

[General]
+noAuthentication=true

0.94.1부터는 인증을 끄면 다중 인증도 생략됩니다.

로그인 세션의 동작

로그인하면 브라우저에는 쿠키를 저장하고 서버에는 로그인 세션을 보관합니다.

로그인 상태 유지를 선택하면 기본적으로 21일 뒤 만료됩니다. config.ini의 Session.cookieMaxAge로 기간을 바꿀 수 있습니다. 하루 뒤 만료시키는 예시입니다.

[Session]
+cookieMaxAge=86400

로그인 상태 유지를 선택하지 않으면 브라우저 쿠키에 만료 시각을 지정하지 않으며 브라우저를 닫을 때 지워집니다. 서버의 세션은 애플리케이션을 마지막으로 사용한 시점부터 약 24시간 뒤 만료됩니다.

활성 세션 확인하기

로그인 세션은 사용자 데이터와 같은 데이터베이스에 저장됩니다. SQL 콘솔에서 다음 조회문으로 확인할 수 있습니다.

SELECT * FROM sessions

만료된 세션은 서버가 주기적으로 정리합니다. 일반적으로 한 시간 간격입니다.

관련 문서

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication.html new file mode 100644 index 0000000..45a4815 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/Multi-Factor Authentication.html @@ -0,0 +1 @@ +

다중 인증은 비밀번호 외에 추가 확인 수단을 요구합니다. 비밀번호가 유출되더라도 다른 사람이 접속하기 어렵게 합니다. 이 버전에서는 OpenID와 TOTP를 동시에 사용할 수 없습니다.

인증 방식

OpenID는 Google 같은 외부 서비스 계정으로 신원을 확인하는 방식입니다. TOTP는 인증 앱에서 짧은 시간마다 바뀌는 일회용 코드를 생성하는 방식입니다. 일반적으로 30초마다 코드가 바뀝니다.

설정

다중 인증은 서버 인스턴스에서 설정합니다. 원문 작성 당시에는 다중 인증이 켜진 서버와 새 데스크톱 앱의 최초 동기화에 문제가 있어 최초 동기화 동안만 끄는 임시 방법을 안내했습니다. 이는 해당 버전의 제약에 관한 설명입니다.

TOTP

OpenID

먼저 인증 제공자에 애플리케이션을 등록합니다. Google은 공식 OpenID 연결 안내를 참고하세요.

config.ini에 oauthBaseUrl과 oauthClientId 및 oauthClientSecret을 지정합니다. 설정 안내를 참고하세요. 환경 변수 TRILIUM_OAUTH_BASE_URL과 TRILIUM_OAUTH_CLIENT_ID 및 TRILIUM_OAUTH_CLIENT_SECRET도 사용할 수 있습니다.

서버를 다시 시작한 뒤 설정 → 다중 인증에서 사용을 켜고 OAuth/OpenID 방식을 선택하세요. 페이지를 새로고침한 뒤 제공자 계정으로 로그인합니다.

기본 제공자는 Google입니다. 다른 제공자는 oauthIssuerBaseUrl과 oauthIssuerName 및 oauthIssuerIcon으로 지정합니다. 대응하는 환경 변수는 TRILIUM_OAUTH_ISSUER_BASE_URL과 TRILIUM_OAUTH_ISSUER_NAME 및 TRILIUM_OAUTH_ISSUER_ICON입니다. 이름과 아이콘은 로그인 화면의 제공자 표시에도 필요합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/TLS Configuration.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/TLS Configuration.html new file mode 100644 index 0000000..0945e71 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/TLS Configuration.html @@ -0,0 +1,9 @@ +

이 문서는 서버 설치에서 Trilium 자체에 TLS를 설정하는 방법을 설명합니다. Nginx 같은 역방향 프록시에서 HTTPS 연결을 처리하는 방식도 사용할 수 있습니다. 원문에 연결된 역방향 프록시 설정 예제는 특정 Ubuntu 버전 기준입니다.

인증서 준비

신뢰할 수 있는 인증 기관이 서명한 인증서를 사용하는 것이 일반적입니다. Let’s Encrypt는 무료 인증서를 제공하며 Certbot 등의 도구로 발급과 갱신을 자동화할 수 있습니다. 자체 서명 인증서도 가능하지만 접속하는 기기마다 신뢰 설정이 필요합니다.

config.ini 설정

데이터 폴더의 설정 파일에 인증서와 키 경로를 지정합니다.

[Network]
+port=8080
+# HTTPS를 사용하려면 true로 지정합니다. false는 HTTP입니다.
+https=true
+# 인증서 경로입니다. 자체 서명 인증서 생성 예시는 bash bin/generate-cert.sh입니다.
+# https=true일 때 사용합니다.
+certPath=/[username]/.acme.sh/[hostname]/fullchain.cer
+keyPath=/[username]/.acme.sh/[hostname]/example.com.key

환경 변수 설정으로 같은 값을 전달할 수도 있습니다. 예제 경로는 ACME 도구를 사용한 환경의 예시이며 실제 파일 위치에 맞게 바꿔야 합니다. Docker에서는 컨테이너가 접근할 수 있는 마운트 경로를 지정하세요. 설정 후 Trilium을 다시 시작하고 HTTPS 주소로 접속합니다.

자체 서명 인증서

데스크톱 앱은 자체 서명 인증서를 기본적으로 신뢰하지 않습니다. 원문에는 다음처럼 인증서 검증을 끄는 방법도 소개되어 있습니다.

export NODE_TLS_REJECT_UNAUTHORIZED=0
+trilium

Windows의 trilium-no-cert-check.bat도 같은 용도의 시작 스크립트입니다. 인증서 검증을 끄면 서버의 신원을 확인하지 못하므로 연결 보안이 약해집니다. 이 설명은 기능 안내이며 이 한글화 작업에서는 해당 설정을 변경하지 않습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization.html new file mode 100644 index 0000000..4a8af9b --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization.html @@ -0,0 +1,3 @@ +

데스크톱 앱은 데이터를 로컬에 저장해 인터넷 연결 없이 사용할 수 있습니다. 서버와 동기화를 설정하면 여러 데스크톱 앱이 하나의 중앙 서버와 연결됩니다.

중앙 서버와 여러 클라이언트의 동기화 구조

설정 후에는 자동으로 계속 동기화합니다.

동기화 설정

서버에는 유효한 TLS 인증서를 사용해 HTTPS로 연결하세요.

기존 데스크톱 데이터를 새 서버로 보내기

서버를 설치하되 초기화하지 않은 상태로 둡니다. 기존 데스크톱 앱의 설정 → 동기화에서 서버 주소를 지정하고 저장하세요.

동기화 설정

동기화 시험을 누르면 연결을 확인하고 서버로 데이터를 보냅니다. 전송 중에도 앱을 사용할 수 있습니다. 서버에 로그인 화면이 나타나면 초기 동기화가 끝난 것입니다.

기존 서버에서 새 데스크톱으로 받기

데스크톱 앱을 설치하고 초기 설정에서 동기화 서버 사용을 선택하세요.

서버에서 동기화하는 초기 설정

서버 주소와 해당 버전에서 요구하는 인증 정보를 입력하고 설정 완료를 누릅니다.

초기 동기화 진행

완료하면 앱 화면으로 이동합니다.

프록시

설정 → 동기화에서 프록시를 직접 지정할 수 있습니다. 인증이 필요한 프록시는 지원하지 않습니다. 따로 지정하지 않으면 시스템 프록시 설정을 사용합니다.

문제 해결

시간

서버와 클라이언트의 시각 차이는 5분 이내여야 합니다.

인증서

자체 서명 인증서나 회사 프록시 때문에 인증서 검증이 실패할 수 있습니다. 원문에는 다음 환경 변수로 검증을 끄는 방법도 소개되어 있습니다.

export NODE_TLS_REJECT_UNAUTHORIZED=0

이 설정은 중간자 공격을 방어하는 인증서 검증을 끕니다. 유효한 인증서를 사용하는 것이 권장됩니다. 일부 배포판에는 같은 용도의 trilium-no-cert-check.sh가 있습니다.

충돌

동기화되기 전에 여러 기기에서 같은 노트를 수정하면 더 최근 변경을 유지합니다. 이전 내용은 노트 수정 이력에서 확인할 수 있습니다.

해시 검사

동기화 후 양쪽 데이터의 해시를 비교합니다. 다르면 자동 복구 절차를 시작합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 2 · 동기화 설정

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 서버에서 동기화하는 초기 설정

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · 초기 동기화 진행

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_image.png new file mode 100644 index 0000000..344262a Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_sync-confi.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_sync-confi.png new file mode 100644 index 0000000..d86942d Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_sync-confi.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_sync-in-pr.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_sync-in-pr.png new file mode 100644 index 0000000..9eb684b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_sync-in-pr.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_sync-init.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_sync-init.png new file mode 100644 index 0000000..ac9c1e3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Synchronization_sync-init.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Upgrading TriliumNext.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Upgrading TriliumNext.html new file mode 100644 index 0000000..c905961 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Upgrading TriliumNext.html @@ -0,0 +1 @@ +

Trilium을 새 버전으로 업그레이드하는 방법을 안내합니다.

업그레이드 방법

이 버전의 Trilium에는 자동 업그레이드 기능이 없습니다. 설치 방식에 따라 직접 업데이트하세요.

데이터베이스 호환성과 변환

새 버전을 실행하면 데이터베이스를 필요한 형식으로 자동 변환합니다. 변환된 데이터베이스는 이전 버전에서 읽지 못할 수 있습니다. 이전 버전으로 돌아가려면 변환 전에 생성한 백업을 복원하세요.

동기화 호환성

동기화에 사용하는 통신 규약에는 버전이 있습니다. 함께 동기화하는 모든 인스턴스는 같은 규약 버전을 사용해야 하므로 업그레이드할 때 다른 인스턴스도 함께 업데이트해야 할 수 있습니다. 규약 버전의 변경 여부는 릴리스 안내를 확인하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Web Clipper.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Web Clipper.html new file mode 100644 index 0000000..7ac8dc1 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Web Clipper.html @@ -0,0 +1,3 @@ +

웹 클리퍼 화면

Trilium Web Clipper는 웹페이지의 글자와 이미지 및 화면 캡처와 짧은 메모를 Trilium에 바로 저장하는 브라우저 확장 프로그램입니다. 프로젝트 저장소에서 소스를 확인할 수 있습니다.

Firefox와 Chrome을 지원합니다. Chrome용 배포판은 다른 Chromium 기반 브라우저에서도 사용할 수 있습니다.

주요 기능

저장한 자료는 클리퍼 수신함 노트의 하위 노트로 만들어집니다. 기본 위치는 오늘의 노트입니다. 다른 노트에 clipperInbox 라벨을 지정하면 저장 위치를 바꿀 수 있습니다.

같은 날 같은 페이지에서 여러 번 저장하면 하나의 노트에 모입니다.

확장 프로그램 내려받기

연결 설정

실행 중인 Trilium에 연결해야 합니다. 기본적으로 로컬 컴퓨터의 포트 범위를 확인해 데스크톱 앱을 찾습니다. 데스크톱 앱을 사용하지 않거나 종료한 상태에서도 저장하려면 서버 주소를 지정할 수 있습니다.

사용자 이름

0.50 이전 버전에서는 사용자 이름과 비밀번호가 필요했습니다. 이후 버전에서는 사용자 이름을 사용하지 않으므로 해당 입력란에 어떤 값을 넣어도 인증에 영향을 주지 않습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 웹 클리퍼 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Web Clipper_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Web Clipper_image.png new file mode 100644 index 0000000..de3c69b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Web Clipper_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types.html new file mode 100644 index 0000000..7f418d4 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types.html @@ -0,0 +1,7 @@ +

Trilium은 용도에 따라 여러 노트 유형을 지원합니다. 기본 유형은 텍스트입니다.

다른 유형으로 새 노트 만들기

노트 트리에서 기준 노트를 마우스 오른쪽 버튼으로 누릅니다. 다음에 노트 삽입은 같은 단계에 새 노트를 만들고 하위 노트 삽입은 선택한 노트 아래에 만듭니다.

노트 유형 선택

링크를 텍스트 노트에 추가할 때 새 제목을 입력하고 Enter를 누르면 유형을 선택할 수 있습니다. 새 탭에서도 같은 방법을 사용합니다.

기존 노트의 유형 변경

상단 리본의 기본 속성에서 변경합니다. 보통 내용이 없는 노트에서 변경하는 것이 좋습니다. 유형 변경으로 노트 소스를 편집할 수도 있습니다.

지원하는 유형

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 유형 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/10_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/10_Geo Map_image.png new file mode 100644 index 0000000..554e18c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/10_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/11_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/11_Geo Map_image.png new file mode 100644 index 0000000..4a463f1 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/11_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/12_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/12_Geo Map_image.png new file mode 100644 index 0000000..5c8cec0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/12_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/13_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/13_Geo Map_image.png new file mode 100644 index 0000000..96140df Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/13_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/14_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/14_Geo Map_image.png new file mode 100644 index 0000000..0c1519f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/14_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/15_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/15_Geo Map_image.png new file mode 100644 index 0000000..b99d116 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/15_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/16_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/16_Geo Map_image.png new file mode 100644 index 0000000..34685ce Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/16_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/17_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/17_Geo Map_image.png new file mode 100644 index 0000000..0831d8a Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/17_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/18_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/18_Geo Map_image.png new file mode 100644 index 0000000..0c4ec9b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/18_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Code_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Code_image.png new file mode 100644 index 0000000..7520e45 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Code_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_File_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_File_image.png new file mode 100644 index 0000000..18ce5be Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_File_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Geo Map_image.png new file mode 100644 index 0000000..e44ec6b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Mermaid Diagrams_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Mermaid Diagrams_image.png new file mode 100644 index 0000000..381504c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Mermaid Diagrams_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Relation Map_relation-map-.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Relation Map_relation-map-.gif new file mode 100644 index 0000000..8ff234f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Relation Map_relation-map-.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Relation Map_relation-map-.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Relation Map_relation-map-.png new file mode 100644 index 0000000..fb97d0e Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Relation Map_relation-map-.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Text_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Text_image.png new file mode 100644 index 0000000..278d44d Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/1_Text_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_File_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_File_image.png new file mode 100644 index 0000000..04478a3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_File_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_Geo Map_image.png new file mode 100644 index 0000000..9f25930 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_Mermaid Diagrams_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_Mermaid Diagrams_image.png new file mode 100644 index 0000000..ac8b0cf Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_Mermaid Diagrams_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_Text_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_Text_image.png new file mode 100644 index 0000000..8a68dcb Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/2_Text_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/3_File_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/3_File_image.png new file mode 100644 index 0000000..4988132 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/3_File_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/3_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/3_Geo Map_image.png new file mode 100644 index 0000000..6f9f0c1 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/3_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/4_File_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/4_File_image.png new file mode 100644 index 0000000..3dd5ceb Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/4_File_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/4_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/4_Geo Map_image.png new file mode 100644 index 0000000..1dd2925 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/4_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/5_File_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/5_File_image.png new file mode 100644 index 0000000..af5bdfd Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/5_File_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/5_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/5_Geo Map_image.png new file mode 100644 index 0000000..ab73988 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/5_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/6_File_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/6_File_image.png new file mode 100644 index 0000000..14044ba Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/6_File_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/6_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/6_Geo Map_image.png new file mode 100644 index 0000000..8b8ce92 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/6_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/7_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/7_Geo Map_image.png new file mode 100644 index 0000000..00c5e8c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/7_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/8_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/8_Geo Map_image.png new file mode 100644 index 0000000..c569957 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/8_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/9_Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/9_Geo Map_image.png new file mode 100644 index 0000000..c2317a8 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/9_Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Book.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Book.html new file mode 100644 index 0000000..20de994 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Book.html @@ -0,0 +1,4 @@ +

책 노트는 하위 노트의 내용을 차례로 보여 주는 특별한 노트 유형입니다. 여러 짧은 노트를 하나의 책처럼 이어서 읽을 때 유용합니다.

책 노트 예시

위 예시에서 왼쪽의 Node.js 노트에는 여러 하위 노트가 있습니다. 오른쪽에서는 그 내용을 하나의 연속된 문서로 보여 줍니다.

기능

여러 하위 노트의 내용을 한 화면에서 이어 볼 수 있습니다. 긴 내용을 관리하기 쉬운 단위로 나누어 작성한 뒤 읽을 때 편리합니다.

노트 목록 기능을 사용하므로 격자와 목록 및 달력 보기 중에서 선택할 수 있습니다.

보기 방식은 리본 메뉴의 책 속성 탭에서 바꾸세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 책 노트 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Book_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Book_image.png new file mode 100644 index 0000000..ba4e1dd Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Book_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Canvas.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Canvas.html new file mode 100644 index 0000000..2d72b58 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Canvas.html @@ -0,0 +1,3 @@ +

Trilium 0.52 버전부터 사용할 수 있습니다.

캔버스 노트는 Excalidraw를 사용합니다. 마우스와 펜 또는 터치로 무한한 캔버스 위에 필기할 수 있습니다. 간단한 도표와 글자 및 그림을 넣는 기능도 제공합니다.

캔버스 노트 예시

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 캔버스 노트 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Canvas_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Canvas_image.png new file mode 100644 index 0000000..9259c84 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Canvas_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Code.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Code.html new file mode 100644 index 0000000..cc1b516 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Code.html @@ -0,0 +1,5 @@ +

코드 노트에는 C++와 JavaScript 같은 프로그램 코드나 JSON과 XML 같은 구조화 자료 및 CSS 등을 저장할 수 있습니다. 구문 강조를 제공하며 JavaScript는 스크립트로 실행할 수도 있습니다. 구조화 자료는 스크립트의 데이터 저장에도 활용할 수 있습니다.

짧은 코드를 텍스트 노트 안에 넣으려면 코드 블록을 사용하세요.

코드 노트 화면

언어 선택

상단 리본의 노트 유형을 열고 코드 영역에서 언어를 선택하세요.

코드 언어 선택

언어 목록 설정

설정 → 코드 노트의 선택 목록에 표시할 MIME 유형에서 필요한 언어를 선택할 수 있습니다. 변경한 뒤 애플리케이션을 새로고침해야 목록에 반영됩니다. 이 목록은 코드 블록과 텍스트 노트에서도 함께 사용합니다.

색상 테마

0.94.0부터 설정 → 코드 노트 → 모양에서 색상 테마를 선택할 수 있습니다. 텍스트 노트의 코드 블록과는 다른 기술을 사용하므로 제공하는 테마 수가 다릅니다.

이 버전에서는 사용자가 코드 노트 테마를 직접 추가할 수 없습니다. 테마가 CSS가 아니라 JavaScript로 정의되기 때문입니다. 추가를 제안하려면 CodeMirror 5가 아닌 CodeMirror 6용 테마인지 확인하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 코드 노트 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 코드 언어 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Code_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Code_image.png new file mode 100644 index 0000000..f3ebaf6 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Code_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html new file mode 100644 index 0000000..9d68040 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/File.html @@ -0,0 +1,16 @@ +

파일 노트에는 이미지와 동영상 및 PDF 같은 외부 파일을 첨부할 수 있습니다.

파일 올리기

파일 노트는 유형을 선택해 직접 만들지 않습니다. 파일을 노트 트리로 끌어 놓거나 노트를 마우스 오른쪽 버튼으로 눌러 노트로 가져오기를 선택하세요.

지원하는 파일

PDF

PDF 보기

Trilium 안에서 바로 읽을 수 있습니다. 왼쪽 위 메뉴에서 페이지 미리보기와 문서에 포함된 목차를 엽니다. 위쪽에서 페이지 번호와 확대 비율을 바꾸거나 문서를 회전합니다. 추가 메뉴에서는 두 페이지 보기와 주석 표시 및 문서 속성을 사용할 수 있습니다.

이미지

이미지 보기

참조를 클립보드에 복사하면 텍스트 노트에 이미지를 넣을 수 있습니다. 이미지 참조를 참고하세요.

동영상

동영상 재생

파일을 스트리밍하므로 서버에서 전체 파일을 내려받기 전에도 재생할 수 있습니다. 다만 매우 큰 파일을 보관하는 용도로 설계된 기능은 아닙니다. 동영상이 크면 데이터베이스와 백업도 커지고 처음 올릴 때 지연될 수 있습니다. 데이터베이스가 크다는 이유만으로 일반적인 사용 속도가 크게 느려지는 것은 아닙니다.

음성

음성 재생

지원하는 음성 파일은 기본 재생기로 열립니다. 재생과 일시 정지 버튼을 사용하고 진행 막대를 누르거나 끌어 재생 위치를 바꿉니다. 음량을 조절할 수 있으며 음량 옆 메뉴에서 재생 속도도 바꿀 수 있습니다.

텍스트 파일

텍스트 파일 미리보기

텍스트로 인식한 파일은 내용 일부를 보여 줍니다. 외부 라이브러리나 자동 생성 자료처럼 본문 편집보다 파일 보관과 다운로드가 필요한 경우에 유용합니다.

보통 텍스트 파일을 가져오면 텍스트 또는 코드 노트가 됩니다. 파일 노트로 보관하려면 노트로 가져오기에서 HTML·Markdown·TXT를 텍스트 노트로 가져오는 옵션과 인식한 코드 파일을 코드 노트로 가져오는 옵션을 모두 해제하세요. 미리보기 길이는 제한되므로 전체 내용은 외부 앱에서 확인합니다.

알 수 없는 형식

미리보기를 지원하지 않는 파일

형식을 인식하지 못하면 본문 미리보기가 나오지 않습니다. 내려받기와 외부 앱으로 열기 등 기본 기능은 사용할 수 있습니다.

파일 관리

상단 리본의 이미지 또는 파일 탭에서 내려받기와 기본 앱으로 열기 및 새 버전 올리기를 사용할 수 있습니다. 파일 노트의 유형은 바꿀 수 없습니다. 첨부 파일로 바꾸려면 노트 메뉴를 사용합니다.

다른 노트에 표시

노트 목록에서도 파일 유형에 맞춰 표시됩니다.

노트 목록에 표시된 파일

이미지를 제외한 파일은 노트 포함으로 텍스트 노트에 읽기 전용 위젯으로 넣습니다. 이미지는 이미지 참조로 일반 이미지처럼 넣습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · PDF 보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 이미지 보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 동영상 재생

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · 음성 재생

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 5 · 텍스트 파일 미리보기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 6 · 미리보기를 지원하지 않는 파일

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 7 · 노트 목록에 표시된 파일

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/File_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/File_image.png new file mode 100644 index 0000000..0f01d19 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/File_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Geo Map.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Geo Map.html new file mode 100644 index 0000000..fb6f98a --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Geo Map.html @@ -0,0 +1,20 @@ +

지리 지도 예제

하위 노트의 위치 속성을 바탕으로 지도에 표시합니다. 지도에서 위치를 선택해 새 노트를 만들 수도 있습니다.

지도 만들기

노트 트리에서 마우스 오른쪽 메뉴의 하위 노트 삽입 → 지리 지도를 선택합니다.

지리 지도 만들기

처음에는 전 세계가 보이는 빈 지도가 열립니다.

새 지도

이동과 확대

지도를 끌어 이동합니다. 마우스 휠이나 터치패드 두 손가락 동작 또는 왼쪽 위의 더하기·빼기 버튼으로 확대 비율을 바꿉니다. 위치와 확대 비율은 노트에 저장되어 다음에 열 때 복원됩니다.

지도에서 표시점 추가

원하는 위치로 이동한 뒤 오른쪽 위 떠 있는 버튼 영역의 표시점 추가 버튼 버튼을 누릅니다. 보이지 않으면 버튼 영역 펼치기 버튼으로 펼칩니다.

표시점 삽입 모드

지도에서 위치를 누릅니다. 취소하려면 Esc를 누르세요.

표시점 이름 입력

이름을 입력하고 확인하면 표시점과 하위 노트가 만들어집니다.

표시점과 하위 노트 생성

위치 저장 방식

하위 노트의 #geolocation 속성에 위도와 경도를 쉼표로 구분해 저장합니다. 직접 입력할 수도 있습니다.

위치 속성

표시점 이동

표시점을 끌어서 옮기면 마우스를 놓는 즉시 저장됩니다. 이 버전에서는 이동을 실행 취소할 수 없습니다. 아직 마우스를 놓지 않았다면 Ctrl+R로 새로고침해 취소할 수 있습니다.

표시점 사용

마우스를 올리면 노트 내용이 보이고 제목을 누르면 현재 화면에서 엽니다. 마우스 가운데 버튼은 새 탭에서 엽니다. 오른쪽 메뉴에서는 새 탭·분할 화면·창으로 열거나 지원되는 외부 지도 앱으로 위치를 열 수 있습니다. 지도에서 제거는 #geolocation 속성을 지웁니다. 다시 표시하려면 좌표를 입력해야 합니다.

아이콘과 색상

표시점의 아이콘과 색상

노트와 같은 아이콘을 사용합니다. #color=green처럼 색상 속성을 지정할 수도 있습니다.

좌표 직접 추가

지도 아래에 노트를 만들고 #geolocation에 쉼표로 구분한 위도와 경도를 넣습니다.

Google 지도

원하는 위치를 마우스 오른쪽 버튼으로 누르고 첫 항목의 좌표를 복사합니다.

Google 지도에서 좌표 복사

Trilium 지도 아래에 노트를 만듭니다.

하위 노트 만들기

소유한 속성에 #geolocation="을 입력한 뒤 좌표를 붙이고 닫는 따옴표를 입력합니다. Enter로 확정합니다.

복사한 좌표를 속성에 입력

OpenStreetMap

원하는 위치의 오른쪽 메뉴에서 주소 표시를 선택합니다.

OpenStreetMap 주소 표시

왼쪽 위에 표시되는 좌표를 선택해 복사합니다.

좌표 복사

지도 하위 노트의 #geolocation 값에 넣으면 표시됩니다.

위치 속성에 붙여넣기

GPS 경로 파일

기본적인 GPX 경로 표시를 지원합니다. 노트 트리의 지도 노트 안으로 .gpx 파일을 끌어 놓습니다.

GPX 파일 가져오기

파일 유형이 application/gpx+xml인지 확인합니다.

GPX 파일 유형

지도에 경로와 시작·끝 표시점이 나타납니다.

지도에 표시된 경로

시작 표시점은 노트 제목과 아이콘 및 색상을 사용합니다. 끝 표시점은 다른 아이콘으로 구분합니다. GPX에 경유지가 있으면 함께 표시하며 이름이 있는 경유지는 마우스를 올렸을 때 이름이 나옵니다.

문제 해결

지도에 격자 선이 나타나는 현상

앱 확대 비율이 100%가 아니면 소수점 배율 때문에 지도 조각 사이에 선이 보일 수 있습니다. Ctrl+0으로 화면 확대를 100%로 되돌리세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 지리 지도 예제

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 지리 지도 만들기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 새 지도

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 6 · 표시점 삽입 모드

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 7 · 표시점 이름 입력

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 9 · 위치 속성

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 10 · 표시점의 아이콘과 색상

지도 위 표시점은 연결된 노트의 아이콘과 색상을 따릅니다. 표시점을 누르면 해당 노트를 열 수 있습니다.

이미지 11 · Google 지도에서 좌표 복사

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 12 · 하위 노트 만들기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 13 · 복사한 좌표를 속성에 입력

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 14 · OpenStreetMap 주소 표시

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 15 · 좌표 복사

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 16 · 위치 속성에 붙여넣기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 17 · GPX 파일 가져오기

GPX는 이동 경로를 저장하는 파일 형식입니다. 경로 파일을 지도 노트로 가져오는 과정을 보여 줍니다.

이미지 18 · GPX 파일 유형

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 19 · 지도에 표시된 경로

가져온 경로가 지도 위의 선으로 표시됩니다. 지도 지명과 경로 이름은 예제 데이터입니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Geo Map_image.jpg b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Geo Map_image.jpg new file mode 100644 index 0000000..41dcf5d Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Geo Map_image.jpg differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Geo Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Geo Map_image.png new file mode 100644 index 0000000..141f28b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Geo Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html new file mode 100644 index 0000000..386b3f2 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams.html @@ -0,0 +1,5 @@ +

Mermaid 도표 화면

Mermaid는 글자로 작성한 설명을 도표로 바꿉니다. 순서도와 시퀀스 및 클래스와 상태 도표 및 원형 차트 등을 만들 수 있습니다. 문법은 Mermaid 공식 안내를 참고하세요.

화면 배치

가로 배치는 왼쪽에 코드와 오른쪽에 미리보기를 둡니다. 세로 배치는 아래에 코드와 위에 미리보기를 둡니다. 떠 있는 버튼의 편집 영역 위치 전환 버튼으로 바꿀 수 있습니다.

편집과 미리보기

코드를 바꾸면 도표가 자동으로 갱신됩니다. 미리보기 오른쪽 아래의 확대와 축소 및 가운데 맞춤 버튼을 이용하거나 마우스 휠로 확대 비율을 바꾸세요. 왼쪽 버튼을 누른 채 끌면 이동합니다. 코드를 수정해도 확대 비율과 위치는 유지됩니다. 코드와 미리보기 사이 경계를 끌면 영역 크기를 바꿀 수 있습니다.

떠 있는 버튼에서 다음 기능을 사용할 수 있습니다.

문법 오류

코드에 오류가 있으면 안내 영역에 표시됩니다. 오류가 해결되기 전까지 미리보기에는 마지막으로 정상 표시된 도표가 남습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · Mermaid 도표 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout.html new file mode 100644 index 0000000..75cd998 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout.html @@ -0,0 +1,4 @@ +

Mermaid는 복잡한 다이어그램을 배치하는 데 사용할 수 있는 Eclipse Layout Kernel(ELK) 엔진을 지원합니다. Trilium에서도 사용할 수 있지만 기본적으로 켜져 있지는 않습니다.

다이어그램 맨 앞에 다음 YAML 머리말을 넣으면 ELK를 사용합니다.

---
+config:
+  layout: elk
+---
ELK를 사용하지 않은 배치ELK를 사용한 배치
ELK를 사용하지 않은 다이어그램ELK를 사용한 다이어그램
diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout_ELK off.svg b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout_ELK off.svg new file mode 100644 index 0000000..a6a8a01 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout_ELK off.svg @@ -0,0 +1 @@ +

Guarantee

User attributes

Master data

Exchange Rate

Profit Centers

Vendor Partners

Work Situation

Customer

Profit Centers

Guarantee

A

B

C

Interfaces for B
\ No newline at end of file diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout_ELK on.svg b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout_ELK on.svg new file mode 100644 index 0000000..1a40033 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams/ELK layout_ELK on.svg @@ -0,0 +1 @@ +

A

B

C

Guarantee

User attributes

Master data

Exchange Rate

Profit Centers

Vendor Partners

Work Situation

Customer

Profit Centers

Guarantee

Interfaces for B
\ No newline at end of file diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams_image.png new file mode 100644 index 0000000..c0cc4cd Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mermaid Diagrams_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mind Map.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mind Map.html new file mode 100644 index 0000000..dd27116 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mind Map.html @@ -0,0 +1,4 @@ +

마인드맵 예시

마인드맵은 떠오르는 생각을 빠르게 적고 계층 구조로 정리하는 노트입니다.

용어

사용 방법

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 마인드맵 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mind Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mind Map_image.png new file mode 100644 index 0000000..9e44818 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Mind Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Note Map.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Note Map.html new file mode 100644 index 0000000..278164f --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Note Map.html @@ -0,0 +1,4 @@ +
노트 지도 예시

노트 지도 유형은 노트 지도 기능을 독립된 노트로 제공합니다.

노트 지도를 만들면 노트 사이의 관계가 표시됩니다. 지도 노트의 상위 노트에 속한 노트와 그 하위 노트만 표시됩니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 노트 지도 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Note Map_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Note Map_image.png new file mode 100644 index 0000000..2ba7707 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Note Map_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Relation Map.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Relation Map.html new file mode 100644 index 0000000..f30c783 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Relation Map.html @@ -0,0 +1,5 @@ +

관계 지도는 노트와 노트 사이의 관계를 시각적으로 표시하는 유형입니다.

개발 과정 예제

개발 과정 관계 지도

개발 과정 관계 지도 만들기

개발 과정이라는 노트를 만들고 관계 지도 유형으로 바꿉니다. 요구 사항과 개발 및 시험과 시연 노트를 차례로 만들고 지도에서 위치를 선택하세요. 노트 사이에 관계를 끌어서 연결한 뒤 이름을 지정합니다. 지도 항목은 실제 하위 노트이므로 열어 본문을 작성할 수도 있습니다. 연결선은 관계 속성입니다.

가족 관계 예제

아래는 과거 영국 왕실 인물을 이용한 예제입니다. 인물의 호칭은 원문 작성 당시를 따릅니다.

가족 관계 지도

가족 관계 지도 만드는 과정

빈 지도에 필립 공과 엘리자베스 2세 노트를 끌어 놓습니다. 두 노트에 지정된 isPartnerOf 관계가 자동으로 표시됩니다. 양쪽 방향에 관계가 하나씩 있습니다.

찰스 왕자 노트를 만들고 두 사람을 향한 isChildOf 관계를 추가합니다. 관계 정의에서 역방향 관계를 설정했으므로 부모에서 자녀를 향하는 연결도 자동으로 생깁니다. 다이애나 비 노트를 만들고 배우자 관계를 연결하면 반대 방향도 함께 만들어집니다. 마지막으로 지도를 이동하고 확대 비율을 조정하세요.

관계 정의는 가족 관계도의 하위 노트에 적용된 인물 템플릿에서 가져옵니다. 기본 예제에서 직접 확인할 수 있습니다.

표시할 관계 선택

displayRelations 라벨에 관계 이름을 쉼표로 구분해 지정하면 해당 관계만 표시합니다. 반대로 hideRelations에 이름을 지정하면 해당 관계를 제외합니다. 이 쉼표는 설정 문법의 구분자입니다.

관련 문서

노트 지도도 비슷한 방식으로 노트 사이의 연결을 보여 줍니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 개발 과정 관계 지도

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 개발 과정 관계 지도 만들기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 가족 관계 지도

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · 가족 관계 지도 만드는 과정

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Relation Map_relation-map-.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Relation Map_relation-map-.gif new file mode 100644 index 0000000..8366855 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Relation Map_relation-map-.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Relation Map_relation-map-.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Relation Map_relation-map-.png new file mode 100644 index 0000000..86ea647 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Relation Map_relation-map-.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html new file mode 100644 index 0000000..da9e3af --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note.html @@ -0,0 +1,8 @@ +

HTML 표시 노트

HTML 표시 노트는 스크립트에서 활용하는 유형입니다. 관계 속성으로 연결된 코드 노트의 HTML을 화면에 표시합니다.

HTML 표시 노트 만들기

동적 내용 표시하기

스크립트로 HTML의 일부를 바꾸면 동적 화면을 만들 수 있습니다. 현재 날짜와 시각을 표시하는 예제를 만들어 보겠습니다.

먼저 다음 내용의 HTML 코드 노트를 만드세요.

<h1>현재 날짜와 시각</h1>
+현재 날짜와 시각: <span class="date"></span>

그 바로 아래에 프런트엔드 JavaScript 코드 노트를 만들고 다음 코드를 작성합니다.

const $dateEl = api.$container.find(".date");
+$dateEl.text(new Date().toLocaleString("ko-KR"));

원하는 위치에 HTML 표시 노트를 만들고 ~renderNote 관계로 HTML 노트를 연결하세요. 열면 현재 날짜와 시각이 한국어 형식으로 표시됩니다. 예: 현재 날짜와 시각 — 현재 날짜와 시각: 2025. 4. 6. 오후 3:26:29

관련 예제

체중 기록은 기본 사용 예제에 포함되어 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · HTML 표시 노트

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note_image.png new file mode 100644 index 0000000..75e246c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Render Note_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Saved Search.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Saved Search.html new file mode 100644 index 0000000..9d7d8dc --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Saved Search.html @@ -0,0 +1,4 @@ +

자주 사용하는 검색을 노트 트리에 저장할 수 있습니다. 검색 결과는 저장된 검색 노트 아래에 하위 노트처럼 표시됩니다.

검색 저장 예시

저장 위치

기본 저장 위치는 일일 노트입니다. 다른 곳에 저장하려면 원하는 노트에 #searchHome 라벨을 추가하세요. 작업 공간 안에서는 #workspaceSearchHome 라벨로 해당 작업 공간의 검색 저장 위치를 지정할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 검색 저장 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Saved Search_saved-search.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Saved Search_saved-search.gif new file mode 100644 index 0000000..72864f1 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Saved Search_saved-search.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html new file mode 100644 index 0000000..49b6e96 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text.html @@ -0,0 +1,6 @@ +

텍스트는 Trilium의 기본 노트 유형입니다. 글자 서식과 표 및 이미지와 안내 상자 등 다양한 기능을 제공합니다.

서식 도구 모음

떠 있는 도구 모음은 필요한 순간에 나타납니다. 문단용 도구와 글자를 선택했을 때 나타나는 도구가 있습니다.

문단 도구 모음

글자 도구 모음

고정 도구 모음은 여러 서식 버튼을 한곳에 표시합니다.

고정 도구 모음

서식 도구 모음 안내에서 선택 방법을 확인하세요.

지원 기능

읽기와 편집

보통 편집 모드로 열립니다. 본문이 매우 크거나 직접 지정한 경우에는 읽기 전용으로 열립니다.

단축키

키보드 단축키와 Markdown식 자동 서식으로 마우스 없이도 편집할 수 있습니다.

편집기

오픈 소스 기반을 가진 CKEditor를 사용합니다. 편집 화면에서 서식이 적용된 결과를 바로 확인할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 문단 도구 모음

문단 도구 모음에서 제목 단계와 목록 및 정렬 방식을 고릅니다. 아이콘 위에 마우스를 올리면 기능 이름을 확인할 수 있습니다.

이미지 2 · 글자 도구 모음

선택한 글자에 굵게와 기울임 및 밑줄 같은 서식을 적용하는 도구 모음입니다.

이미지 3 · 고정 도구 모음

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/10_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/10_Images_image.png new file mode 100644 index 0000000..32f99c3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/10_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/10_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/10_Lists_image.png new file mode 100644 index 0000000..1282f27 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/10_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/10_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/10_Tables_image.png new file mode 100644 index 0000000..5cf2cc5 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/10_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/11_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/11_Tables_image.png new file mode 100644 index 0000000..cde63c9 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/11_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/12_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/12_Tables_image.png new file mode 100644 index 0000000..9c512ee Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/12_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Block quotes & admonitions.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Block quotes & admonitions.png new file mode 100644 index 0000000..175c661 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Block quotes & admonitions.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Bookmarks_plus.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Bookmarks_plus.png new file mode 100644 index 0000000..84183c1 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Bookmarks_plus.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Developer-specific formatt.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Developer-specific formatt.png new file mode 100644 index 0000000..9580128 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Developer-specific formatt.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Footnotes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Footnotes_image.png new file mode 100644 index 0000000..64c876e Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Footnotes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Formatting toolbar_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Formatting toolbar_image.png new file mode 100644 index 0000000..bc6bd96 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Formatting toolbar_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_General formatting_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_General formatting_image.png new file mode 100644 index 0000000..295d3c8 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_General formatting_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Images_image.png new file mode 100644 index 0000000..a4e23ef Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Insert buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Insert buttons_image.png new file mode 100644 index 0000000..7ae8c13 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Insert buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Insert buttons_plus.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Insert buttons_plus.png new file mode 100644 index 0000000..723ca82 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Insert buttons_plus.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Links_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Links_image.png new file mode 100644 index 0000000..1bd071c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Links_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Lists_image.png new file mode 100644 index 0000000..fba0cc8 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Math Equations_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Math Equations_image.png new file mode 100644 index 0000000..e814870 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Math Equations_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Other features_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Other features_image.png new file mode 100644 index 0000000..6618b13 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Other features_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Tables_image.png new file mode 100644 index 0000000..4dacba1 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/1_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Block quotes & admonitions.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Block quotes & admonitions.png new file mode 100644 index 0000000..afc26f3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Block quotes & admonitions.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Developer-specific formatt.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Developer-specific formatt.png new file mode 100644 index 0000000..295d3c8 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Developer-specific formatt.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Formatting toolbar_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Formatting toolbar_image.png new file mode 100644 index 0000000..c7d879e Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Formatting toolbar_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_General formatting_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_General formatting_image.png new file mode 100644 index 0000000..aa65a36 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_General formatting_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Images_image.png new file mode 100644 index 0000000..08a40b0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Insert buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Insert buttons_image.png new file mode 100644 index 0000000..66cd278 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Insert buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Links_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Links_image.png new file mode 100644 index 0000000..03fdc67 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Links_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Lists_image.png new file mode 100644 index 0000000..ee7a6bd Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Other features_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Other features_image.png new file mode 100644 index 0000000..e6cd79c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Other features_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Tables_image.png new file mode 100644 index 0000000..5cc9f0b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/2_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Developer-specific formatt.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Developer-specific formatt.png new file mode 100644 index 0000000..67c4c43 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Developer-specific formatt.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Formatting toolbar_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Formatting toolbar_image.png new file mode 100644 index 0000000..3270223 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Formatting toolbar_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_General formatting_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_General formatting_image.png new file mode 100644 index 0000000..d19a5e7 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_General formatting_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Images_image.png new file mode 100644 index 0000000..297d49e Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Insert buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Insert buttons_image.png new file mode 100644 index 0000000..b6b4179 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Insert buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Links_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Links_image.png new file mode 100644 index 0000000..72b2415 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Links_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Lists_image.png new file mode 100644 index 0000000..3299276 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Other features_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Other features_image.png new file mode 100644 index 0000000..c3cead3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Other features_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Tables_image.png new file mode 100644 index 0000000..092a053 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/3_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Developer-specific formatt.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Developer-specific formatt.png new file mode 100644 index 0000000..ef28ed5 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Developer-specific formatt.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_General formatting_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_General formatting_image.png new file mode 100644 index 0000000..7d1208b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_General formatting_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Images_image.png new file mode 100644 index 0000000..9f8ecc3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Insert buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Insert buttons_image.png new file mode 100644 index 0000000..614c755 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Insert buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Lists_image.png new file mode 100644 index 0000000..8369a03 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Other features_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Other features_image.png new file mode 100644 index 0000000..3645073 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Other features_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Tables_image.png new file mode 100644 index 0000000..eaf4d96 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/4_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Developer-specific formatt.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Developer-specific formatt.png new file mode 100644 index 0000000..c0cf731 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Developer-specific formatt.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Images_image.png new file mode 100644 index 0000000..2e37305 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Insert buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Insert buttons_image.png new file mode 100644 index 0000000..1221e39 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Insert buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Lists_image.png new file mode 100644 index 0000000..ed6f4c3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Other features_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Other features_image.png new file mode 100644 index 0000000..ee7a6bd Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Other features_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Tables_image.png new file mode 100644 index 0000000..5df4b16 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/5_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Developer-specific formatt.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Developer-specific formatt.png new file mode 100644 index 0000000..ddc7e16 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Developer-specific formatt.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Images_image.png new file mode 100644 index 0000000..f8c5cf4 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Insert buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Insert buttons_image.png new file mode 100644 index 0000000..28711b3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Insert buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Lists_image.png new file mode 100644 index 0000000..0ab3052 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Other features_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Other features_image.png new file mode 100644 index 0000000..4c702d5 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Other features_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Tables_image.png new file mode 100644 index 0000000..3394d46 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/6_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Images_image.png new file mode 100644 index 0000000..731df83 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Insert buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Insert buttons_image.png new file mode 100644 index 0000000..68028bb Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Insert buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Lists_image.png new file mode 100644 index 0000000..3caf2d8 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Tables_image.png new file mode 100644 index 0000000..4b76702 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/7_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Images_image.png new file mode 100644 index 0000000..0167e75 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Insert buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Insert buttons_image.png new file mode 100644 index 0000000..20581df Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Insert buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Lists_image.png new file mode 100644 index 0000000..4a17f48 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Tables_image.png new file mode 100644 index 0000000..cde63c9 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/8_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/9_Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/9_Images_image.png new file mode 100644 index 0000000..8fa28fb Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/9_Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/9_Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/9_Lists_image.png new file mode 100644 index 0000000..2473cd3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/9_Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/9_Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/9_Tables_image.png new file mode 100644 index 0000000..099b253 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/9_Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Block quotes & admonitions.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Block quotes & admonitions.html new file mode 100644 index 0000000..f2a6971 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Block quotes & admonitions.html @@ -0,0 +1,15 @@ +

인용문

한 문단 이상을 인용할 때 사용할 수 있습니다. 서식 도구 모음의 인용문 버튼을 누르거나 줄 시작에서 > 뒤에 공백을 입력하세요. 인용문 안에는 표와 이미지 및 다른 인용문이나 안내 상자도 넣을 수 있습니다.

안내 상자

독자가 알아야 할 내용을 눈에 띄게 표시하는 상자입니다.

안내 상자의 종류

동작은 인용문과 비슷하며 제목과 표 및 이미지 등을 안에 넣을 수 있습니다.

만들기

서식 도구 모음에서 안내 상자를 선택하세요.

안내 상자 메뉴

!!! note는 참고 상자를 만듭니다. !!! tip은 도움말이며 !!! important는 중요입니다. !!! caution은 주의이며 !!! warning은 경고입니다. !!! 뒤에 다른 글자를 입력하면 참고 상자 안에 그 글자가 들어갑니다.

사용 방법

종류

참고와 도움말 및 중요와 주의와 경고의 다섯 종류를 제공합니다. GitHub의 안내 상자를 참고한 구성이며 이 버전에서는 종류를 추가하거나 사용자가 바꾸는 기능을 제공하지 않습니다.

Markdown

가져오기와 내보내기에서는 GitHub 형식을 사용합니다.

> [!NOTE]
+> 참고할 내용입니다.
+
+> [!TIP]
+> 도움이 되는 설명입니다.
+
+> [!IMPORTANT]
+> 중요한 내용입니다.
+
+> [!CAUTION]
+> 주의할 내용입니다.

편집 중 자동 변환에 쓰는 !!! note와 Markdown 파일의 문법은 다릅니다. Markdown 파일에서는 위의 GitHub 형식을 사용하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 2 · 안내 상자의 종류

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 안내 상자 메뉴

일반 인용문과 주의 사항 등의 안내 상자 모양을 고르는 메뉴입니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Block quotes & admonitions.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Block quotes & admonitions.png new file mode 100644 index 0000000..ee95e66 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Block quotes & admonitions.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks.html new file mode 100644 index 0000000..bb6c8b0 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks.html @@ -0,0 +1 @@ +

책갈피를 사용하면 특정 제목처럼 노트 안의 원하는 위치를 가리키는 링크를 만들 수 있습니다.

내부적으로는 HTML 앵커를 사용합니다. 이 기능은 TriliumNext 0.94.0에서 추가되었습니다.

사용 방법

책갈피 만들기

  1. 책갈피를 둘 위치에 커서를 놓으세요.
  2. 서식 도구 모음에서 책갈피 메뉴 버튼 버튼을 누른 뒤 새 책갈피 버튼 버튼을 선택하세요.

책갈피로 연결하기

  1. 링크를 넣을 위치에 커서를 놓으세요.
  2. 링크 창에서 책갈피 항목을 열고 원하는 책갈피를 선택하세요.

제한 사항

이 버전에서는 다른 노트의 책갈피로 연결할 수 없습니다. 내부 링크가 책갈피를 지원하도록 개선된 뒤 추가될 예정입니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks_plus.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks_plus.png new file mode 100644 index 0000000..b2dc917 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Bookmarks_plus.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Content language & Right-t.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Content language & Right-t.png new file mode 100644 index 0000000..dee7993 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Content language & Right-t.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Content language & Right-to-le.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Content language & Right-to-le.html new file mode 100644 index 0000000..09fd024 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Content language & Right-to-le.html @@ -0,0 +1,3 @@ +

본문 언어 설정

텍스트 노트에 작성 언어를 지정할 수 있습니다. 브라우저나 데스크톱 앱이 본문의 언어를 알 수 있어 맞춤법 검사 등에 도움이 됩니다. 아랍어나 히브리어처럼 오른쪽에서 왼쪽으로 쓰는 언어의 표시 방향도 이 설정에 따라 결정됩니다.

언어 지정

기본 속성에서 언어 항목을 찾으세요.

언어 목록 구성

처음에는 언어가 설정되어 있지 않습니다. 전체 설정에서 언어를 추가하거나 노트의 언어 선택 목록에서 언어 구성을 선택하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 본문 언어 설정

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Cut to subnote.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Cut to subnote.html new file mode 100644 index 0000000..5709a9a --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Cut to subnote.html @@ -0,0 +1,4 @@ +

선택한 내용을 하위 노트로 옮기기

문서가 너무 길어지면 내용을 하위 노트로 나눌 수 있습니다.

  1. 옮길 내용을 선택해 잘라냅니다.
  2. 새 하위 노트를 만들고 제목을 입력합니다.
  3. 잘라낸 내용을 하위 노트에 붙여 넣습니다.

Trilium은 이 과정을 한 번에 처리할 수 있습니다. 본문에서 내용을 선택한 뒤 선택 영역 도구 모음의 가위 아이콘을 눌러 하위 노트로 옮기기를 실행하세요. 선택한 내용의 제목을 감지해 새 노트 이름으로 사용합니다. 이 작업에 단축키를 지정할 수도 있습니다. 블록 도구 모음에서도 사용할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 선택한 내용을 하위 노트로 옮기기

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Cut to subnote_cut-to-subn.gif b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Cut to subnote_cut-to-subn.gif new file mode 100644 index 0000000..b71afd0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Cut to subnote_cut-to-subn.gif differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatt.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatt.png new file mode 100644 index 0000000..6ae0fd8 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatt.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting.html new file mode 100644 index 0000000..672d5ad --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting.html @@ -0,0 +1,4 @@ +

문장 안의 코드

코드 서식은 고정폭 글꼴을 사용해 문장 안의 코드나 파일 경로 같은 기술적인 내용을 구분합니다.

경로와 git 명령의 코드 서식 예시

다음 방법으로 적용할 수 있습니다.

코드 블록

여러 줄의 코드를 별도 블록으로 표시합니다.

JavaScript 구문 강조를 적용한 코드 블록

코드가 매우 길다면 전용 코드 노트를 사용하세요. 자세한 내용은 코드 블록을 참고하세요.

단축키 서식

글자를 키보드의 키처럼 표시하는 서식입니다.

단축키 서식 예시

서식 도구 모음에서 글자 서식 그룹을 열고 단축키 서식 버튼을 누르세요. 떠 있는 도구 모음에서는 글자를 선택하면 버튼이 나타납니다.

Ctrl+Alt+K로 선택한 글자에 적용할 수도 있습니다. 같은 버튼이나 단축키를 다시 누르면 해제됩니다. 서식 지우기 버튼으로도 서식을 지울 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 경로와 git 명령의 코드 서식 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · JavaScript 구문 강조를 적용한 코드 블록

코드 언어를 JavaScript로 지정한 예시입니다. 색으로 구분된 영문은 실행할 코드이므로 그대로 유지합니다.

이미지 4 · 단축키 서식 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/1_Code blocks_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/1_Code blocks_image.png new file mode 100644 index 0000000..ef28ed5 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/1_Code blocks_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/2_Code blocks_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/2_Code blocks_image.png new file mode 100644 index 0000000..6cd7f4b Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/2_Code blocks_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks.html new file mode 100644 index 0000000..39697ea --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks.html @@ -0,0 +1,7 @@ +

코드 블록 예시

텍스트 노트 안에 짧은 코드를 넣는 기능입니다. 전체 로그처럼 긴 내용은 코드 노트를 사용하세요.

삽입

서식 도구 모음의 코드 블록 버튼을 누르면 마지막으로 선택한 언어의 블록을 만듭니다. 처음에는 자동 감지입니다. 옆의 화살표로 다른 언어를 선택할 수 있습니다. 역따옴표 세 개를 입력하는 방법도 있으며 이때도 마지막으로 선택한 언어를 사용합니다.

구문 강조와 색상

0.90.12부터 코드 블록에 구문 강조를 적용합니다. 코드 노트와는 다른 기술을 사용합니다. 자동 감지는 내용을 보고 언어를 추정하며 잘못 감지하면 직접 언어를 선택하세요. 일반 텍스트를 선택하면 강조하지 않습니다.

편집 중에는 약 500줄 이상의 큰 블록에서 강조를 끕니다. 이 기준은 설정할 수 없습니다. 읽기 전용 노트에는 이 제한이 적용되지 않습니다. 설정 → 모양에서 Highlight.js 색상 테마와 줄바꿈을 선택할 수 있습니다. 구문 강조 없음을 선택하면 전체 노트에서 끕니다.

CKEditor의 검색 강조 등에 사용하는 API에 Highlight.js를 연결한 방식입니다. antoniotejada의 구문 강조 위젯을 바탕으로 설정과 기능을 확장했습니다.

기존 플러그인에서 전환

Trilium-SyntaxHighlightWidget 같은 기존 플러그인은 충돌을 피하도록 비활성화하세요. 문제가 지속되면 안전 모드로 실행해 확인할 수 있습니다.

언어 변경

블록 안을 클릭한 뒤 서식 도구 모음에서 언어를 바꿉니다.

코드 블록 언어 변경

언어 목록

코드 노트와 같은 목록을 사용합니다. 설정 → 코드 노트의 선택 목록에 표시할 MIME 유형에서 언어를 선택하거나 해제하세요. 새로고침 후 반영됩니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 코드 블록 예시

코드 블록에 입력한 프로그램 예시입니다. 영문 명령과 기호는 프로그램 문법이므로 원래 표기를 유지합니다.

이미지 3 · 코드 블록 언어 변경

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks_image.png new file mode 100644 index 0000000..cabd7f4 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Developer-specific formatting/Code blocks_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Footnotes.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Footnotes.html new file mode 100644 index 0000000..9011e5a --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Footnotes.html @@ -0,0 +1,5 @@ +

각주 예시

각주는 문단의 참고 자료나 보충 설명을 노트 아래쪽에 정리할 때 유용합니다.

사용 방법

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 각주 예시

본문의 작은 각주 번호와 아래쪽 각주 내용이 연결된 모습입니다. 예문 대신 원하는 설명을 입력하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Footnotes_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Footnotes_image.png new file mode 100644 index 0000000..8c69b7f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Footnotes_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Formatting toolbar.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Formatting toolbar.html new file mode 100644 index 0000000..8350df4 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Formatting toolbar.html @@ -0,0 +1,5 @@ +

텍스트 노트의 서식 도구 모음은 두 가지 방식 중에서 선택할 수 있습니다.

설정 → 텍스트 노트의 서식 도구 모음 항목에서 표시 방식을 바꾸세요.

떠 있는 도구 모음

평소에는 도구 모음을 숨기고 필요한 순간에 두 종류의 팝업으로 서식 옵션을 표시합니다.

문단 서식 팝업

편집 중인 문단 왼쪽에 점 모양 버튼이 나타납니다.

문단 서식 버튼

버튼을 누르면 제목과 목록 및 표처럼 문단 전체에 적용하는 옵션이 표시됩니다.

문단 서식 팝업

글자 서식 팝업

글자를 선택하면 자동으로 나타납니다.

글자 서식 팝업

글자 크기와 굵게 등 선택한 글자에만 적용하는 옵션을 제공합니다.

고정 도구 모음

서식을 자주 적용한다면 모든 옵션이 한곳에 표시되는 고정 도구 모음이 편리합니다. 상단 리본에 도구 모음이 표시됩니다.

고정 서식 도구 모음

화면 너비가 부족하면 나머지 옵션은 끝부분의 더 보기 메뉴에 모입니다. 서식 도구 모음 설정에서 여러 줄 표시를 선택하면 옵션을 여러 줄로 배치할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 2 · 문단 서식 팝업

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 글자 서식 팝업

글자를 선택하면 나타나는 서식 메뉴입니다. 원하는 아이콘을 눌러 선택한 부분의 서식을 바꿉니다.

이미지 4 · 고정 서식 도구 모음

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Formatting toolbar_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Formatting toolbar_image.png new file mode 100644 index 0000000..85578b7 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Formatting toolbar_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting.html new file mode 100644 index 0000000..9a0c712 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting.html @@ -0,0 +1,8 @@ +

제목

제목 서식 선택

본문은 제목 2~6으로 구분할 수 있습니다. 제목 1은 노트 제목에 사용합니다. 일반 문단으로 되돌리려면 본문을 선택하세요. ##부터 ######까지 입력해 제목 2~6을 만들 수도 있습니다.

글자 크기

글자 크기 선택

일부 글자를 선택하고 크기를 바꾸면 강조할 수 있습니다. 숫자 대신 매우 작게와 작게 같은 상대 크기를 사용합니다. 모든 노트를 크게 보고 싶다면 설정의 기본 글자 크기나 화면 확대를 조정하세요.

굵게와 기울임 및 밑줄과 취소선

글자 서식 버튼

각 버튼으로 적용하고 서식 지우기로 제거할 수 있습니다. 단축키는 굵게가 Ctrl+B이며 기울임은 Ctrl+I이고 밑줄은 Ctrl+U입니다. **글자**나 __글자__는 굵게입니다. *글자*나 _글자_는 기울임이며 ~~글자~~는 취소선입니다.

위 첨자와 아래 첨자

cm³ 같은 단위와 NaHCO₃ 같은 화학식에 사용할 수 있습니다. 복잡한 식은 수식 기능을 사용하세요.

글자색과 배경색

색상 선택

미리 지정된 색을 선택하거나 색상 선택기로 직접 정할 수 있습니다. 문서에서 사용한 색은 다시 고르기 쉽도록 목록에 나타납니다. 밝은 테마와 어두운 테마 사이를 전환해도 읽기 쉬운 대비인지 확인하세요. 색상 제거 또는 서식 지우기로 해제할 수 있습니다.

서식 지우기

서식 지우기 버튼은 선택한 글자의 굵기와 색상 및 크기 등을 지웁니다. 제거할 서식이 없으면 비활성화됩니다. 제목 서식은 별도로 본문으로 바꿔야 합니다. 붙여넣을 때부터 서식을 제외하려면 Ctrl+Shift+V를 사용하세요.

Markdown

Markdown으로 내보낼 때 제목과 굵게 및 기울임과 밑줄 등 대부분의 기본 서식을 유지합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 제목 서식 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 글자 크기 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · 색상 선택

글자색이나 배경색을 고르는 화면입니다. 색상 견본에서 원하는 색을 선택합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting_image.png new file mode 100644 index 0000000..1d1cfb3 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/General formatting_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Highlights list.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Highlights list.html new file mode 100644 index 0000000..3d15551 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Highlights list.html @@ -0,0 +1,6 @@ +

강조 목록 예시

목차와 비슷하지만 제목 대신 강조한 글자를 모아 보여 줍니다. 강조한 내용이 하나 이상 있으면 오른쪽 사이드바에 목록이 나타납니다.

다음 서식을 적용한 글자가 강조 목록에 포함됩니다.

사용 방법

전체 설정

텍스트 노트 설정의 강조 목록 항목에서 목록에 포함할 서식 종류를 선택할 수 있습니다.

노트별 설정

특정 노트에서 강조 목록을 숨기려면 속성에 #hideHighlightWidget 라벨을 추가하세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 강조 목록 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Highlights list_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Highlights list_image.png new file mode 100644 index 0000000..2115d49 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Highlights list_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images.html new file mode 100644 index 0000000..acccf67 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images.html @@ -0,0 +1,6 @@ +

JPEG와 PNG 및 GIF 이미지를 저장하고 표시할 수 있습니다. 노트의 첨부 파일로 넣거나 별도 이미지 노트로 노트 트리에 둘 수 있습니다. 참조를 텍스트 노트에 붙이면 본문에도 표시할 수 있습니다.

이미지 넣기

파일 탐색기에서 편집기로 이미지를 끌어 놓으세요.

이미지 끌어 놓기

블록 도구 모음에서 이미지 삽입을 선택할 수도 있습니다.

이미지 삽입 메뉴

웹의 이미지를 복사해 붙이면 이미지를 내려받아 본문에 포함합니다.

이미지 배치

이미지를 누르면 설정 팝업이 나타납니다.

이미지 설정

문장 안에 배치

문장 안에 배치 버튼

문장 안에 배치 예시

글자처럼 문단 안에 놓습니다. 끌어서 옮기거나 잘라내고 붙여넣을 수 있습니다.

가운데 배치

가운데 배치 버튼

가운데 배치 예시

별도 블록으로 가운데에 표시하며 좌우에 글자가 흐르지 않습니다.

글자로 둘러싸기

글자로 둘러싸기 버튼

글자로 둘러싸기 예시

글자의 왼쪽이나 오른쪽에 이미지를 표시합니다.

블록 정렬

블록 정렬 버튼

블록 정렬 예시

별도 블록을 왼쪽이나 오른쪽으로 정렬합니다. 이미지 옆에는 글자가 흐르지 않습니다.

압축

Trilium은 업로드한 이미지를 저장하기 전에 크기를 줄이고 압축하므로 품질이 달라질 수 있습니다. 설정 → 기타에서 기본 품질을 조정할 수 있습니다. 원본 해상도를 보존하려면 노트 메뉴 → 파일 가져오기로 첨부하세요.

이미지를 나란히 놓기

크기가 비슷하면 문장 안에 배치한 뒤 같은 줄로 끌어 놓으세요. 크기가 다르면 테두리를 숨긴 표의 각 칸에 넣을 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 이미지 끌어 놓기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 이미지 삽입 메뉴

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 5 · 문장 안에 배치 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 7 · 가운데 배치 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 9 · 글자로 둘러싸기 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 11 · 블록 정렬 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images/1_Image references_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images/1_Image references_image.png new file mode 100644 index 0000000..d6ca4aa Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images/1_Image references_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images/Image references.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images/Image references.html new file mode 100644 index 0000000..3aef379 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images/Image references.html @@ -0,0 +1,4 @@ +

이미지 참조 예시

이미지 참조를 사용하면 다른 유형의 노트 미리보기를 텍스트 노트에 넣을 수 있습니다.

지원하는 노트 유형

사용 순서

사용 방법

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 이미지 참조 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images/Image references_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images/Image references_image.png new file mode 100644 index 0000000..a54daef Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images/Image references_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images_image.png new file mode 100644 index 0000000..938a0d2 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Images_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Include Note.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Include Note.html new file mode 100644 index 0000000..5cb42ba --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Include Note.html @@ -0,0 +1 @@ +

텍스트 노트 안에 다른 노트를 읽기 전용 위젯으로 포함할 수 있습니다. 예를 들어 스크립트와 HTML 표시 노트로 만든 동적 차트를 본문 안에 넣을 수 있습니다.

노트 포함하기

서식 도구 모음에서 노트 포함 버튼 버튼을 찾으세요. 이 기능의 단축키 항목도 있지만 기본 키는 지정되어 있지 않습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Include Note_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Include Note_image.png new file mode 100644 index 0000000..6fb41a4 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Include Note_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Insert buttons.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Insert buttons.html new file mode 100644 index 0000000..d8a0c50 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Insert buttons.html @@ -0,0 +1,11 @@ +

서식 도구 모음의 삽입 메뉴 버튼을 누르면 기호와 수식 및 구분선 등을 넣을 수 있습니다.

북마크

북마크 안내를 참고하세요.

이모지

이모지 선택기

범주와 이모지를 선택하면 유니코드 문자로 삽입합니다. 이름으로 검색하고 오른쪽 선택 상자에서 피부색을 고를 수 있습니다. 이 한글화 적용본은 한국어 이름과 검색어를 제공합니다. : 뒤에 단축 이름을 입력하면 후보 목록이 나타납니다. 화살표로 선택하고 Enter로 넣으세요.

이모지 자동 완성

기호

기호 선택 창

기호 버튼을 누르면 키보드로 입력하기 어려운 문자 목록이 열립니다. 문자를 누르면 현재 위치에 들어갑니다. 창의 제목 부분을 끌어 옮기거나 범주로 목록을 좁힐 수 있습니다.

수식

수식 안내를 참고하세요.

Mermaid 도표

Mermaid 삽입 버튼으로 본문에 간단한 도표를 넣습니다. 전용 Mermaid 노트와 비슷한 기능입니다. 복잡한 도표는 전용 노트를 만들고 노트 포함으로 넣으세요.

본문 안의 Mermaid 도표

가로 구분선

서식 도구 모음의 가로 구분선 버튼을 누르거나 ---를 입력하세요.

가로 구분선

페이지 나누기

페이지 나누기 표시

인쇄하거나 PDF로 내보낼 때 다음 문단이나 표와 이미지를 새 페이지에서 시작하게 합니다. 편집기에는 페이지 나누기라고 표시되지만 이 문구는 인쇄되지 않습니다.

페이지 나누기 버튼으로 삽입합니다. 여러 곳에 넣으려면 먼저 만든 페이지 나누기를 선택해 복사한 뒤 필요한 위치에 붙여넣으세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 2 · 이모지 선택기

본문에 넣을 이모지를 검색하고 선택하는 창입니다. 현재 앱의 이모지 이름은 한국어로 표시됩니다.

이미지 3 · 이모지 자동 완성

이모지 이름을 입력했을 때 표시되는 후보 목록입니다. 원하는 후보를 선택하면 본문에 이모지가 들어갑니다.

이미지 4 · 기호 선택 창

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 7 · 본문 안의 Mermaid 도표

Mermaid 문법으로 작성한 도표를 본문 안에 표시한 예시입니다. 도표의 글자는 코드에 입력한 내용에 따라 달라집니다.

이미지 9 · 가로 구분선

문단 사이에 가로선을 넣어 내용을 구분한 예시입니다.

이미지 10 · 페이지 나누기 표시

인쇄할 때 새 페이지를 시작할 위치를 표시한 예시입니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Insert buttons_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Insert buttons_image.png new file mode 100644 index 0000000..b2bdcc5 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Insert buttons_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Insert buttons_plus.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Insert buttons_plus.png new file mode 100644 index 0000000..5cd65f1 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Insert buttons_plus.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Keyboard shortcuts.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Keyboard shortcuts.html new file mode 100644 index 0000000..4d3c9fa --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Keyboard shortcuts.html @@ -0,0 +1,2 @@ +

Trilium 편집 단축키

동작PCMac
글자·문단 도구 모음 열기. 좌우 방향키로 이동하고 Enter로 적용Alt+F10⌥+F10
외부 링크 만들기Ctrl+K⌘+K
내부 노트 링크 만들기Ctrl+L⌘+L
현재 날짜와 시간 삽입Alt+T⌥+T
문단 들여쓰기TabTab
문단 내어쓰기Shift+TabShift+Tab
선택한 글자를 단축키 모양으로 표시Ctrl+Alt+K⌘+⌥+K
수식 삽입Ctrl+M⌘+M
문단이나 목록을 위로 이동Alt+↑⌥+↑
문단이나 목록을 아래로 이동Alt+↓⌥+↓

공통 단축키

CKEditor의 공식 안내를 바탕으로 한 목록입니다. Trilium의 구성에 따라 일부 기능은 지원되지 않거나 다른 단축키와 겹칠 수 있습니다. Mac의 기능키는 Fn을 함께 눌러야 할 수 있습니다.

본문 편집

동작PCMac
새 문단EnterEnter
문단 안에서 줄바꿈Shift+EnterShift+Enter
복사Ctrl+C⌘+C
붙여넣기Ctrl+V⌘+V
일반 텍스트로 붙여넣기Ctrl+Shift+V⌘+Shift+V
실행 취소Ctrl+Z⌘+Z
다시 실행Ctrl+Y 또는 Ctrl+Shift+Z⌘+Y 또는 ⌘+Shift+Z
굵게Ctrl+B⌘+B
대소문자 바꾸기Shift+F3Shift+F3
링크 만들기Ctrl+K⌘+K
링크나 문장 안의 코드 서식에서 벗어나기← 두 번 또는 → 두 번← 두 번 또는 → 두 번
모두 선택Ctrl+A⌘+A
문서에서 찾기Ctrl+F⌘+F
서식 복사Ctrl+Shift+C⌘+Shift+C
서식 붙여넣기Ctrl+Shift+V⌘+Shift+V
기울임Ctrl+I⌘+I
취소선Ctrl+Shift+X⌘+Shift+X
밑줄Ctrl+U⌘+U
방금 적용한 자동 서식 취소BackspaceBackspace

이미지와 표 등 블록 요소

동작PCMac
위젯 바로 뒤에 문단 삽입EnterEnter
위젯 바로 앞에 문단 삽입Shift+EnterShift+Enter
위젯 앞에서 입력할 위치로 이동↑ 또는 ←↑ 또는 ←
위젯 뒤에서 입력할 위치로 이동↓ 또는 →↓ 또는 →
그림 설명 같은 내부 편집 영역에서 상위 위젯 선택Tab 다음 EscTab 다음 Esc
목록 항목 들여쓰기TabTab
목록 항목 내어쓰기Shift+TabShift+Tab
표의 다음 셀로 이동. 마지막 셀에서는 새 행 추가TabTab
표의 이전 셀로 이동Shift+TabShift+Tab
표 안에서 이동방향키방향키

화면 조작

동작PCMac
팝업과 목록 및 대화상자 닫기EscEsc
접근성 도움말 열기Alt+0⌥+0
입력란과 버튼 사이 이동Tab 또는 Shift+TabTab 또는 Shift+Tab
도구 모음으로 이동하거나 도구 모음 사이 전환Alt+F10⌥+F10
도구 모음과 메뉴 안에서 이동방향키방향키
편집기 밖의 다음·이전 요소로 이동Tab 또는 Shift+TabTab 또는 Shift+Tab
선택한 버튼 실행. 본문 관련 버튼은 실행 후 본문으로 초점 이동Enter 또는 SpaceEnter 또는 Space
열린 대화상자의 안팎으로 초점 이동Ctrl+F6⌘+F6
diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Links.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Links.html new file mode 100644 index 0000000..170db18 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Links.html @@ -0,0 +1,5 @@ +

외부 링크

위키백과의 남중국해 문서처럼 외부 웹페이지로 연결하는 링크입니다. 서식 도구 모음의 링크 버튼이나 Ctrl+K로 주소를 입력하고 Enter로 확정하세요. 주소를 붙여넣고 공백을 입력해 자동으로 만들 수도 있습니다.

다른 글자로 표시하려면 먼저 글자를 입력하고 선택한 뒤 링크 주소를 지정하세요. 선택한 글자 위에 주소를 붙여넣는 방법도 있습니다.

표시 글자는 나중에 바꿀 수 있습니다. 링크를 누른 뒤 링크 편집 버튼으로 주소를 수정하거나 연결 해제 버튼으로 링크를 없앱니다. 외부 링크를 두 번 클릭하거나 오른쪽 클릭 메뉴에서 새 탭으로 열기를 선택하면 이동합니다.

노트 사이의 링크

Ctrl+L이나 서식 도구 모음의 노트 링크 버튼을 누르고 대상 노트를 선택합니다. 없는 제목을 입력하고 하위 노트 만들기 및 연결을 선택해 새로 만들 수도 있습니다.

두 번 클릭하면 노트를 엽니다. 마우스를 올리면 읽기 전용 미리보기를 확인할 수 있습니다.

붙여넣기

노트 트리에서 노트를 복사한 뒤 본문에 붙이면 참조 링크가 됩니다. 글자를 선택한 상태에서 붙이면 일반 링크가 됩니다. 외부 주소도 글자 위에 붙여 링크로 바꿀 수 있습니다. 서식 있는 링크를 복사했다면 원래 표시 글자와 주소가 유지됩니다.

입력 중 연결

@ 뒤에 노트 제목 일부를 입력하면 자동 완성이 나타납니다. 원하는 노트를 선택하고 Enter를 누르세요.

노트 지도

들어오는 링크와 나가는 링크는 노트 지도에서 시각적으로 확인할 수 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Links_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Links_image.png new file mode 100644 index 0000000..87c31b0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Links_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Lists.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Lists.html new file mode 100644 index 0000000..8e60d74 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Lists.html @@ -0,0 +1,8 @@ +

텍스트 노트는 세 종류의 목록을 지원합니다.

목록 옵션을 누르면 사각형 기호나 로마 숫자 등으로 표시 방식을 바꿀 수 있습니다. 번호 목록은 시작 번호와 역순 번호 매기기도 설정할 수 있습니다.

키보드 사용

목록 안에 제목과 코드 블록 넣기

1. 목록을 만듭니다.

목록 안에 블록 넣기 1단계

2. Enter로 새 항목을 만듭니다.

목록 안에 블록 넣기 2단계

3. Backspace로 글머리 기호를 없앱니다. 커서는 목록 항목 안에 남습니다.

목록 안에 블록 넣기 3단계

4. 코드 블록이나 표 등 원하는 요소를 넣습니다.

목록 안에 블록 넣기 4단계

5. Enter를 눌러 요소 뒤의 빈 위치로 이동합니다.

목록 안에 블록 넣기 5단계

6. Enter를 다시 누르면 다음 글머리 기호가 만들어집니다.

목록 안에 블록 넣기 6단계

글머리 기호 목록과 번호 목록 및 체크리스트에서 같은 방법을 사용할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 6 · 목록 안에 블록 넣기 1단계

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 7 · 목록 안에 블록 넣기 2단계

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 8 · 목록 안에 블록 넣기 3단계

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 9 · 목록 안에 블록 넣기 4단계

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 10 · 목록 안에 블록 넣기 5단계

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 11 · 목록 안에 블록 넣기 6단계

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Lists_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Lists_image.png new file mode 100644 index 0000000..30a9511 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Lists_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Markdown-like formatting.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Markdown-like formatting.html new file mode 100644 index 0000000..62650e5 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Markdown-like formatting.html @@ -0,0 +1,3 @@ +

Markdown과 비슷한 문법을 입력하면 일부 서식이 자동으로 적용됩니다. 텍스트 노트 자체가 Markdown 형식으로 저장된다는 뜻은 아닙니다.

복잡한 서식은 Markdown에서 가져오기를 사용하세요. 문서 전체는 전용 가져오기 기능을 이용할 수 있습니다.

자동 서식을 취소하려면 Ctrl+Z를 누르세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Math Equations.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Math Equations.html new file mode 100644 index 0000000..bb7bf1e --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Math Equations.html @@ -0,0 +1,5 @@ +

수식 입력 창

텍스트 노트에서 서식 도구 모음의 수식 삽입 버튼으로 수식을 넣을 수 있습니다. 보통 삽입 버튼 그룹 안에 있습니다.

자주 사용한다면 Ctrl+M을 누르세요. $$나 \[를 입력해 창을 열 수도 있습니다. 이미 입력한 수식 양쪽에 $를 붙이거나 선택한 뒤 단축키를 누르는 자동 변환 방식은 지원하지 않습니다.

수식은 TeX 형식으로 작성합니다. 미리보기는 제공하지만 기호를 마우스로 조립하는 시각적 편집기는 없습니다.

별도 표시 모드를 선택하면 수식을 조금 크게 표시하고 가운데 정렬합니다. 합계 기호나 분수가 포함된 수식에서 차이가 뚜렷합니다. 이 모드의 수식은 문단이나 표처럼 독립된 블록이 되어 목록 안에도 넣을 수 있습니다. 일반 모드의 수식은 문장 안에 들어갑니다.

지원하는 수식

KaTeX 라이브러리를 사용하며 TeX 문법의 일부를 지원합니다. 공식 문서의 지원 함수와 지원 여부 표를 확인하세요.

Markdown 지원

Markdown으로 가져오거나 내보낼 때도 수식이 유지됩니다. 수식 구분 기호를 이용해 문장 안의 수식과 별도 블록 수식을 표현합니다.

수식을 가져오거나 내보내는 과정에서 문제가 생기면 해당 수식을 포함해 문제를 보고해 주세요.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 수식 입력 창

수식 원문을 입력하고 결과를 확인하는 창입니다. 수학 기호와 LaTeX 명령은 번역하지 않고 입력합니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Math Equations_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Math Equations_image.png new file mode 100644 index 0000000..ffd51f4 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Math Equations_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Other features.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Other features.html new file mode 100644 index 0000000..a4129a6 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Other features.html @@ -0,0 +1,8 @@ +

들여쓰기

들여쓰기 예시

서식 도구 모음에서 문단을 오른쪽으로 들여쓸 수 있습니다.

Markdown 가져오기

Markdown 원문을 복사한 뒤 Markdown 가져오기 버튼을 누르면 서식을 적용해 삽입합니다. # 제목처럼 작성된 원문을 사용해야 합니다. 이미 서식이 보이는 미리보기 화면의 내용을 복사했다면 일반 붙여넣기를 사용하세요. HTML 서식을 받아들입니다.

짧은 내용을 넣을 때 유용합니다. 문서 전체를 가져오려면 Markdown 가져오기와 내보내기를 사용하세요. 브라우저에서는 클립보드에 직접 접근하지 못하므로 별도 입력 화면이 나타납니다.

하위 노트로 잘라내기

하위 노트로 잘라내기 버튼을 누르면 선택한 내용으로 하위 노트를 만듭니다. 자세한 내용은 하위 노트로 잘라내기를 참고하세요.

찾기와 바꾸기

찾기와 바꾸기 화면

찾기와 바꾸기 버튼을 누르면 편집기의 검색 창이 열립니다. Ctrl+F로도 열 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 들여쓰기 예시

문단의 시작 위치를 안쪽으로 옮긴 모습입니다. 들여쓰기 늘리기와 줄이기로 깊이를 조절합니다.

이미지 6 · 찾기와 바꾸기 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Other features_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Other features_image.png new file mode 100644 index 0000000..63ff048 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Other features_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Table of contents.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Table of contents.html new file mode 100644 index 0000000..e43b5db --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Table of contents.html @@ -0,0 +1,4 @@ +

목차 예시

텍스트 노트에 여러 제목이 있으면 오른쪽 사이드바에 목차가 자동으로 표시됩니다.

사용 방법

전체 설정

텍스트 노트 설정의 목차 항목에서 목차를 표시하는 데 필요한 최소 제목 수를 지정할 수 있습니다.

노트별 설정

속성으로 특정 노트의 목차 표시 여부를 지정할 수 있습니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 목차 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Table of contents_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Table of contents_image.png new file mode 100644 index 0000000..ff11c55 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Table of contents_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Tables.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Tables.html new file mode 100644 index 0000000..1612cc8 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Tables.html @@ -0,0 +1,11 @@ +

텍스트 노트에서 표 버튼을 누르고 마우스로 행과 열 수를 선택하면 표를 만들 수 있습니다.

표의 행과 열 선택

서식 도구 모음

표를 선택하면 전용 도구 모음이 나타납니다.

표 서식 도구 모음

표 안에서 이동

셀을 누르면 해당 셀을 편집합니다. 표 위아래의 문단 삽입 버튼 버튼으로 빈 문단을 넣습니다. 왼쪽 위의 표 선택 버튼 버튼으로 표 전체를 선택해 복사하거나 잘라낼 수 있습니다. 버튼을 끌어 표를 옮길 수도 있습니다.

방향키로 셀 사이를 이동합니다. Tab은 다음 셀로 이동하고 Shift+Tab은 이전 셀로 이동합니다. 마지막 셀에서 Tab을 누르면 새 행이 생깁니다. Shift를 누른 채 방향키를 사용하면 여러 셀을 선택합니다.

셀 크기

열 경계를 끌면 너비를 바꿀 수 있습니다. 행 높이는 기본적으로 마우스로 조절하지 않으며 셀 속성에서 지정합니다. 셀 속성 버튼 버튼으로 픽셀이나 백분율 단위의 정확한 크기를 입력할 수 있습니다.

행과 열 추가

기준 셀을 선택하고 열 메뉴 버튼 버튼에서 왼쪽 또는 오른쪽에 열 삽입을 선택합니다. 행 메뉴 버튼 버튼에서는 위쪽 또는 아래쪽에 행 삽입을 선택합니다. 표 끝에서는 Tab으로도 새 행을 만듭니다.

셀 합치기와 나누기

여러 셀을 끌어서 선택하고 셀 합치기 버튼 버튼을 누릅니다. 옆 화살표를 누르면 인접한 위·아래·왼쪽·오른쪽 셀과 합치거나 셀을 가로 또는 세로로 나누는 메뉴가 나옵니다.

표 속성

표 속성 창

표 속성 버튼 버튼으로 표 전체의 바깥 테두리 모양과 색 및 두께를 바꿉니다. 배경색과 너비 및 높이도 지정할 수 있습니다. 크기는 % 또는 px 단위를 붙여 입력합니다. 왼쪽이나 오른쪽 정렬에서는 본문이 표 옆으로 흐릅니다. 가운데 정렬에서는 본문이 표 옆에 배치되지 않습니다. 변경 사항을 유지하려면 저장을 누르세요.

셀 속성

셀 속성 창

셀 속성 버튼 버튼은 선택한 셀에 적용됩니다. 테두리와 배경색 및 크기를 지정하고 셀 안쪽 여백을 조절합니다. 글자의 가로 정렬은 왼쪽·가운데·오른쪽·양쪽 맞춤을 지원합니다. 세로 정렬은 위·가운데·아래를 지원합니다. 변경 사항을 유지하려면 저장을 누르세요.

표 설명

표 설명 버튼 버튼을 누르면 표 위에 설명을 넣을 수 있습니다.

보이지 않는 테두리

글이나 이미지를 여러 칸으로 배치할 때 활용할 수 있습니다. 원하는 크기의 표를 만들고 전체를 선택합니다. 표 속성과 셀 속성에서 모두 테두리를 실선으로 지정하고 색을 transparent로 설정한 다음 두께를 1px로 입력합니다.

Markdown으로 가져오기와 내보내기

단순한 표는 |로 칸을 구분하는 GitHub 방식의 Markdown으로 내보냅니다. HTML 요소나 이미지 또는 별도 크기 설정이 들어간 복잡한 표는 HTML로 내보내 서식 손실을 줄입니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 9 · 표 속성 창

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 11 · 셀 속성 창

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Tables_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Tables_image.png new file mode 100644 index 0000000..63a9efa Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text/Tables_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text_image.png new file mode 100644 index 0000000..6e2befa Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Text_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Web View.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Web View.html new file mode 100644 index 0000000..8daf556 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types/Web View.html @@ -0,0 +1 @@ +

설정

웹 보기에서 열 주소는 webViewSrc 라벨로 지정합니다. 예시는 다음과 같습니다.

#webViewSrc="https://www.wikipedia.org"

서버와 데스크톱 앱의 차이

웹브라우저로 Trilium에 접속한 경우에도 웹 보기는 지정한 페이지를 표시하려고 시도합니다. 다만 브라우저의 보안 정책 때문에 데스크톱 앱보다 제약이 많습니다.

일부 웹사이트는 X-Frame-Options 헤더로 다른 사이트 안에 표시되는 것을 막습니다. Trilium에서 이 제한을 우회할 수 없으므로 해당 페이지는 표시되지 않습니다.

원인을 확인하려면 Trilium 페이지를 마우스 오른쪽 버튼으로 클릭해 검사를 연 뒤 개발자 도구의 콘솔 탭을 확인하세요. 다음과 같은 오류가 나타날 수 있습니다.

wikipedia.org처럼 표시를 허용하는 사이트도 있습니다.

서버 버전에서는 별도의 샌드박스 제한도 적용합니다. 위의 프레임 차단과 다른 문제가 있으면 문제를 보고해 주세요.

데스크톱 앱은 iframe 대신 webview 기술을 사용하므로 이와 같은 프레임 제약을 받지 않습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types_image.png new file mode 100644 index 0000000..d10e037 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Note Types_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Quick Start.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Quick Start.html new file mode 100644 index 0000000..3d6e87e --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Quick Start.html @@ -0,0 +1 @@ +

설치 방식 선택하기

컴퓨터 한 대에서 사용 — 데스크톱 앱을 설치하면 노트를 해당 컴퓨터에 저장합니다.

서버에 설치하고 웹으로 접속 — 서버에 애플리케이션을 설치하면 모바일을 포함한 여러 기기의 웹브라우저에서 접속할 수 있습니다.

서버와 데스크톱 앱을 함께 사용 — 서버는 웹 접속과 데이터 동기화를 담당합니다. 데스크톱 앱은 데이터를 동기화해 컴퓨터에도 저장하므로 인터넷에 연결되지 않은 상태에서도 사용할 수 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting.html new file mode 100644 index 0000000..aee81f2 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting.html @@ -0,0 +1,2 @@ +

코드 노트에는 프로그램 코드를 저장하고 구문 강조를 적용할 수 있습니다. JavaScript 코드 노트는 Trilium 안에서 실행할 수도 있습니다. 스크립트 API와 함께 사용하면 기능을 확장할 수 있습니다.

구조 이해하기

Trilium은 두 부분으로 이루어진 웹 애플리케이션입니다. 프런트엔드는 브라우저에서 HTML과 CSS 및 JavaScript로 화면을 표시하고 사용자 입력을 처리합니다. 백엔드는 Node.js에서 실행되며 노트 저장과 암호화 등을 담당합니다. 두 영역 모두 JavaScript를 사용하지만 역할과 API는 다릅니다.

활용 예

새 할 일 실행 버튼을 만드는 예제를 참고하세요.

동작 처리

노트를 데이터베이스에 저장하는 일은 백엔드가 담당합니다. 프런트엔드에서 백엔드에 노트 생성을 요청한 뒤 만들어진 노트를 열면 사용자가 제목과 속성을 입력할 수 있습니다.

스크립트 실행

코드 노트의 실행 버튼으로 스크립트를 실행할 수 있습니다. 다만 스크립트로 추가한 화면 요소는 앱을 다시 시작하면 사라집니다. 매번 자동으로 추가하려면 시작할 때 스크립트를 실행하도록 지정해야 합니다.

#run=frontendStartup 라벨이 있는 노트는 프런트엔드가 시작될 때 실행됩니다. 모바일 화면에서는 대신 #run=mobileStartup을 지정하세요.

더 살펴보기

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets.html new file mode 100644 index 0000000..6a03a23 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets.html @@ -0,0 +1 @@ +

사용자 지정 위젯을 만들어 원하는 내용을 표시할 수 있습니다. 다음 위치 중 하나에 배치하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets/Widget Basics.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets/Widget Basics.html new file mode 100644 index 0000000..d55d99f --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets/Widget Basics.html @@ -0,0 +1,56 @@ +

간단한 위젯을 만들고 버튼을 눌렀을 때 메시지를 표시하는 예제입니다. 원문에서 누락된 HTML 템플릿을 아래 예제에 보완했습니다.

1. 기본 구조

class MyWidget extends api.BasicWidget {
+    get position() { return 1; }
+    get parentWidget() { return "left-pane"; }
+    
+    doRender() {
+        this.$widget = $('<div id="my-widget"></div>');
+        return this.$widget;
+    }
+}
+
+module.exports = new MyWidget();

프런트엔드 JavaScript 코드 노트를 만들고 위 코드를 넣으세요. #widget 속성을 노트에 지정한 뒤 창을 새로고침합니다.

개발자 도구에서 document.querySelector("#my-widget")로 요소가 있는지 확인할 수 있습니다. 결과가 null이면 노트의 #widget 속성과 코드 오류를 확인하세요.

2. 버튼 추가

const template = `<div id="my-widget"><button>인사하기</button></div>`;
+
+class MyWidget extends api.BasicWidget {
+    get position() {return 1;}
+    get parentWidget() {return "left-pane"}
+
+    doRender() {
+        this.$widget = $(template);
+        return this.$widget;
+    }
+}
+
+module.exports = new MyWidget();

다시 불러오면 왼쪽 영역에 버튼이 나타납니다.

3. 모양과 위치

Trilium에 포함된 Boxicons를 사용해 아이콘을 표시할 수 있습니다.

const template = `<div id="my-widget"><button title="인사하기" aria-label="인사하기"><i class="bx bxs-magic-wand"></i></button></div>`;

CSS로 왼쪽 아래에 배치합니다.

class MyWidget extends api.BasicWidget {
+    get position() { return 1; }
+    get parentWidget() { return "left-pane"; }
+    
+    doRender() {
+        this.$widget = $(template);
+        this.cssBlock(`#my-widget {
+            position: absolute;
+            bottom: 40px;
+            left: 60px;
+            z-index: 1;
+        }`);
+        return this.$widget;
+    }
+}
+
+module.exports = new MyWidget();

4. 클릭 동작

스크립트 API의 api.showMessage를 사용합니다.

class MyWidget extends api.BasicWidget {
+    get position() { return 1; }
+    get parentWidget() { return "left-pane"; }
+    
+    doRender() {
+        this.$widget = $(template);
+        this.cssBlock(`#my-widget {
+            position: absolute;
+            bottom: 40px;
+            left: 60px;
+            z-index: 1;
+        }`);
+        this.$widget.find("button").on("click", () => api.showMessage("안녕하세요!"));
+        return this.$widget;
+    }
+}
+
+module.exports = new MyWidget();

새로고침한 뒤 버튼을 누르면 안녕하세요!라는 메시지가 나타납니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets/Word count widget.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets/Word count widget.html new file mode 100644 index 0000000..39d8828 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets/Word count widget.html @@ -0,0 +1,79 @@ +

이 위젯은 새 설치의 사용 예제에도 포함됩니다. 프런트엔드 JavaScript 코드 노트를 만들고 #widget 라벨을 지정하세요.

/*
+ * 현재 텍스트 노트의 단어 수와 글자 수를 표시하는 위젯입니다.
+ * 사용할 노트에 wordCount 라벨을 지정하세요. 상속을 켜면 하위 트리 전체에 적용됩니다.
+ * 
+ * 책 예제와 그 하위 노트에서 확인할 수 있습니다.
+ */
+const TPL = `<div style="padding: 10px; border-top: 1px solid var(--main-border-color); contain: none;">
+    <strong>단어 수: </strong>
+    <span class="word-count"></span>
+
+    &nbsp;
+
+    <strong>글자 수: </strong>
+    <span class="character-count"></span>
+</div`;
+
+class WordCountWidget extends api.NoteContextAwareWidget {
+    get position() { return 100; } // 값이 클수록 아래쪽이나 오른쪽에 배치합니다.
+    
+    get parentWidget() { return 'center-pane'; }
+    
+    doRender() {
+        this.$widget = $(TPL);
+        this.$wordCount = this.$widget.find('.word-count');
+        this.$characterCount = this.$widget.find('.character-count');
+        return this.$widget;
+    }
+    
+    async refreshWithNote(note) {
+        if (note.type !== 'text' || !note.hasLabel('wordCount')) { 
+            // 텍스트 노트에 wordCount 라벨이 있을 때만 표시합니다.
+            this.toggleInt(false); // 숨기기
+            
+            return;
+        }
+        
+        this.toggleInt(true); // 표시하기
+        
+        const {content} = await note.getNoteComplement();
+        
+        const text = $(content).text(); // 서식 없이 글자만 가져오기
+        
+        const counts = this.getCounts(text);
+
+        this.$wordCount.text(counts.words);
+        this.$characterCount.text(counts.characters);
+    }
+    
+    getCounts(text) {
+        const chunks = text
+            .split(/[\s-+:,/\\]+/)
+            .filter(chunk => chunk !== '');
+        
+        let words;
+        
+        if (chunks.length === 1 && chunks[0] === '') {
+            words = 0;
+        }
+        else {
+            words = chunks.length;
+        }
+        
+        const characters = chunks.join('').length;
+        
+        return {words, characters};
+    }
+    
+    async entitiesReloadedEvent({loadResults}) {
+        if (loadResults.isNoteContentReloaded(this.noteId)) {
+            this.refresh();
+        }
+    }
+}
+
+module.exports = new WordCountWidget();

변경한 뒤 화면 구성을 다시 만들도록 Trilium을 새로고침하세요. 노트 아래에 다음과 같이 표시됩니다.

단어 수와 글자 수 위젯

예제는 공백과 일부 기호로 나눈 조각을 단어로 셉니다. 한국어 형태소 분석에 따른 단어 수는 아닙니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 단어 수와 글자 수 위젯

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets/Word count widget_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets/Word count widget_image.png new file mode 100644 index 0000000..2f1e5e5 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Custom Widgets/Word count widget_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Events.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Events.html new file mode 100644 index 0000000..0457831 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Events.html @@ -0,0 +1,2 @@ +

스크립트는 이벤트에 따라 실행할 수 있습니다. 노트에 관계로 연결하는 항목별 이벤트는 백엔드 JavaScript 코드 노트를 대상으로 합니다.

전체 이벤트

run 라벨에 실행 시점을 지정합니다.

runOnInstance로 특정 Trilium 인스턴스에서만 실행하도록 지정할 수 있습니다. runAtHour는 #run=hourly와 함께 사용하며 여러 번 지정하면 하루에 여러 시각을 선택할 수 있습니다.

항목별 이벤트

다음 관계를 노트에 직접 지정하거나 상속하면 관련 작업이 발생할 때 스크립트를 실행합니다.

관계실행 시점
runOnNoteCreation백엔드에서 노트를 만들 때입니다. 하위 트리의 모든 새 노트에 적용하려면 상위 노트에 관계를 지정하고 상속을 켭니다.
runOnChildNoteCreation이 관계가 있는 노트 바로 아래에 새 노트를 만들 때입니다.
runOnNoteTitleChange제목을 바꿀 때입니다. 노트 생성도 포함합니다.
runOnNoteContentChange본문을 바꿀 때입니다. 노트 생성도 포함합니다.
runOnNoteChange노트 속성을 변경할 때입니다. 생성은 포함하지만 본문 변경은 포함하지 않습니다.
runOnNoteDeletion노트를 삭제할 때입니다.
runOnBranchCreation상위 노트와 하위 노트 사이의 가지를 만들 때입니다. 복제나 이동 과정에서도 발생합니다.
runOnBranchChange가지를 수정할 때입니다. 0.62부터 지원합니다.
runOnBranchDeletion가지를 삭제할 때입니다. 이동할 때 기존 위치의 연결을 제거하는 경우도 포함합니다.
runOnAttributeCreation해당 노트에 속성을 만들 때입니다.
runOnAttributeChange해당 노트의 속성을 바꾸거나 삭제할 때입니다.
diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/Downloading responses from Goo.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/Downloading responses from Goo.html new file mode 100644 index 0000000..6e0959e --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/Downloading responses from Goo.html @@ -0,0 +1,17 @@ +

Google 설문지의 스프레드시트 연결 기능을 이용해 응답을 내려받는 간단한 연동 예제입니다.

웹에 게시한 링크는 주소를 아는 누구나 열 수 있습니다. 주소를 추측하기 어렵더라도 공개된 자료이므로 민감한 정보를 게시하지 않도록 확인하세요.

CSV 주소 얻기

스크립트 만들기

프런트엔드 JavaScript 코드 노트를 만드세요.

const CSV_URL = "https://docs.google.com/spreadsheets/d/e/2PACX-1vTiwooLV2whjCSVa49dJ99p_G3_qhqHHRqttMjYCJVfLXVdTgUSNJu5K0rpqmaHYF2k7Vofi3o7gW82/pub?output=csv";
+
+async function fetchData() {
+    try {
+        const response = await fetch(CSV_URL);
+        return await response.text();
+    } catch (e) {
+        api.showError(e.message);
+    }
+}
+
+const data = await fetchData();
+console.log(data);
+// 이곳에서 내려받은 데이터를 처리합니다.

응답은 문자열로 전달됩니다. 이 예제에는 CSV 분석 라이브러리가 없으므로 아주 단순한 자료는 다음처럼 나눌 수 있습니다.

const content = data
+	.split("\n")
+	.slice(1)
+	.map((row) => row.split(","));

결과는 각 행을 배열로 담은 배열입니다. 따옴표로 감싼 값 안에 쉼표나 줄바꿈이 있는 일반적인 CSV는 이 방식으로 정확히 처리할 수 없습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/New Task launcher button.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/New Task launcher button.html new file mode 100644 index 0000000..0686e17 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/New Task launcher button.html @@ -0,0 +1,29 @@ +

기본 할 일 관리에 새 작업을 만들고 여는 실행 도구 모음 버튼을 추가합니다.

새 할 일 버튼

코드 노트 준비

프런트엔드 JavaScript 코드 노트를 만들고 속성에 #run=frontendStartup을 지정합니다.

전체 코드

api.addButtonToToolbar({
+	title: "새 할 일",
+    icon: "task",
+    shortcut: "alt+n",
+    action: async () => {
+    	const taskNoteId = await api.runOnBackend(() => {
+        	const todoRootNote = api.getNoteWithLabel("taskTodoRoot");
+            const resp = api.createTextNote(todoRootNote.noteId, "새 할 일", "")           
+            return resp.note.noteId;
+        });
+        
+        await api.waitUntilSynced();
+        await api.activateNewNote(taskNoteId);
+    }
+});

확인

시작할 때 실행하도록 지정했으므로 애플리케이션을 새로고침하면 버튼이 나타납니다.

코드 설명

api.addButtonToToolbar({
+	title: "새 할 일",
+    icon: "task",
+    shortcut: "alt+n",
+    action: async () => {
+    	// [...]
+    }
+});

프런트엔드 API로 실행 도구 모음에 버튼을 추가합니다. 제목과 bx- 접두사를 제외한 아이콘 이름 및 선택적인 단축키를 지정합니다. action은 클릭할 때 실행할 함수입니다.

const taskNoteId = await api.runOnBackend(() => {
+    // 아래에서 설명하는 백엔드 처리입니다.           
+    return resp.note.noteId;
+});

노트 생성은 서버의 역할이므로 백엔드에서 실행합니다. 반환한 노트 ID는 프런트엔드에서 받을 수 있습니다.

const todoRootNote = api.getNoteWithLabel("taskTodoRoot");

#taskTodoRoot 라벨로 할 일 관리의 저장 위치를 찾습니다. 대상이 없으면 null일 수 있지만 이 기본 예제에는 오류 처리가 생략되어 있습니다.

const resp = api.createTextNote(todoRootNote.noteId, "새 할 일", "")

첫 번째 인수는 상위 노트 ID입니다. 두 번째는 새 할 일이라는 제목이며 세 번째는 빈 본문입니다.

await api.waitUntilSynced();

서버에서 만든 노트가 프런트엔드에도 반영될 때까지 기다립니다.

await api.activateNewNote(taskNoteId);

생성된 노트의 ID로 새 노트를 엽니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/New Task launcher button_i.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/New Task launcher button_i.png new file mode 100644 index 0000000..cff2c36 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/New Task launcher button_i.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/Using promoted attributes .png b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/Using promoted attributes .png new file mode 100644 index 0000000..a260503 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/Using promoted attributes .png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/Using promoted attributes to c.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/Using promoted attributes to c.html new file mode 100644 index 0000000..64a1851 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Examples/Using promoted attributes to c.html @@ -0,0 +1,20 @@ +

주요 속성을 사용하면 스크립트에 필요한 값을 입력란으로 제공할 수 있습니다. 입력·출력 노트를 선택하게 하거나 체크박스로 동작을 바꾸는 데 유용합니다.

스크립트 설정용 주요 속성

체크박스로 기능 켜고 끄기

사용자가 코드의 논리값을 직접 수정하는 대신 체크박스를 제공할 수 있습니다. 먼저 다음 속성을 정의하세요.

#label:groupByExtension="promoted,alias=확장자별로 묶기,single,boolean"

스크립트에서는 다음처럼 값을 읽습니다.

const byExtension = api.currentNote.getLabelValue("groupByExtension") === "true";
+if (byExtension) {
+	// 선택한 경우에 실행할 작업을 작성합니다.
+}

이 방식은 프런트엔드와 백엔드 스크립트에서 모두 사용할 수 있습니다.

관계로 노트 선택하기

다른 노트에서 데이터를 읽고 결과를 별도 노트에 기록하려면 입력과 출력 관계를 주요 속성으로 정의합니다.

#relation:input="promoted,alias=입력 노트,single" #relation:output="promoted,alias=출력 노트,single"

필수 입력란이 비어 있는지 확인할 수 있습니다.

const inputNoteId = api.currentNote.getRelationValue("input");
+if (!inputNoteId) {
+	api.showError("입력 노트를 선택하세요.");
+    return;
+}
+
+const outputNoteId = api.currentNote.getRelationValue("output");
+if (!outputNoteId) {
+    api.showError("출력 노트를 선택하세요.");
+    return;
+}

api.showError는 프런트엔드에서만 사용할 수 있습니다. 백엔드 스크립트에서는 이 호출을 제거해야 합니다. 제거하면 사용자에게 오류 이유가 표시되지 않으므로 필요한 경우 별도의 안내 방식을 마련하세요.

선택한 노트와 본문은 다음처럼 읽습니다.

const note = api.getNote(inputNoteId);
+if (!note) {
+	return;
+}
+const content = note.getContent().toString("utf-8");
+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 스크립트 설정용 주요 속성

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics.html new file mode 100644 index 0000000..2c12e7d --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Frontend Basics.html @@ -0,0 +1,2 @@ +

프런트엔드 API

일반 스크립트는 현재 앱과 노트의 문맥에서 실행됩니다. 위젯은 객체를 내보내 화면 구성 요소로 사용합니다. 두 경우 모두 전역 변수 api로 프런트엔드 API를 사용할 수 있습니다. 스크립트 API를 참고하세요.

스크립트

실행 버튼으로 실행하거나 속성으로 실행 시점을 지정할 수 있습니다.

전체 이벤트

#run 값으로 frontendStartup은 일반 화면 시작을 지정하며 mobileStartup은 모바일 화면 시작을 지정합니다. backendStartup은 백엔드 시작입니다. hourly와 daily는 백엔드에서 매시간 또는 매일 실행합니다.

항목별 이벤트

다음 관계로 스크립트를 연결하거나 상속하면 해당 노트에서 이벤트가 발생할 때 실행합니다. 이 이벤트는 백엔드 스크립트를 대상으로 합니다.

위젯

BasicWidget이나 그 하위 클래스를 확장합니다. 새 인스턴스를 module.exports에 지정하고 parentWidget과 정수 position으로 위치를 정합니다. 코드 노트에는 #widget 라벨이 필요합니다.

BasicWidget과 NoteContextAwareWidget은 doRender()에서 this.$widget을 만들고 반환합니다. RightPanelWidget은 이 처리를 제공하므로 doRenderBody()에서 본문을 반환합니다.

배치 영역

위젯 기본 예제에서 구현 과정을 확인하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Script API.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Script API.html new file mode 100644 index 0000000..6e9af2b --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Script API.html @@ -0,0 +1 @@ +

Trilium은 스크립트 코드 노트에서 애플리케이션의 여러 기능을 사용할 수 있도록 API를 제공합니다.

API는 두 종류입니다.

두 API 모두 전역 변수 api를 통해 사용합니다. 스크립트 어디에서나 접근할 수 있습니다.

예를 들어 화면에 메시지를 표시하려면 다음 프런트엔드 스크립트를 사용합니다.

api.showMessage("안녕하세요.");
diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Script API/Backend API.dat b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Script API/Backend API.dat new file mode 100644 index 0000000..e69de29 diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Script API/Frontend API/FNote.dat b/release/app/assets/doc_notes/en/User Guide/User Guide/Scripting/Script API/Frontend API/FNote.dat new file mode 100644 index 0000000..e69de29 diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/1_Custom app-wide CSS_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/1_Custom app-wide CSS_image.png new file mode 100644 index 0000000..97b8fc1 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/1_Custom app-wide CSS_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/2_Custom app-wide CSS_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/2_Custom app-wide CSS_image.png new file mode 100644 index 0000000..582152f Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/2_Custom app-wide CSS_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme.html new file mode 100644 index 0000000..b6bbd5e --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme.html @@ -0,0 +1,5 @@ +

1. 테마를 모아 둘 노트 만들기

직접 만든 테마와 가져온 테마를 한곳에 모으면 관리하기 쉽습니다. 먼저 테마를 보관할 상위 노트를 만드세요.

테마 보관용 노트

2. 테마 노트 만들기

테마는 특별한 속성을 지정한 코드 노트입니다. 새 코드 노트를 만드세요.

새 코드 노트 만들기

노트 유형을 CSS 코드로 바꿉니다.

CSS 유형 선택

소유한 속성에 #appTheme를 추가하고 원하는 테마 이름을 값으로 지정하세요. 이 이름이 화면 설정의 테마 목록에 나타납니다.

테마 이름 지정

3. 테마 CSS 작성하기

다음 예제는 실행 도구 모음의 배경색을 파란색으로 바꿉니다.

:root {
+	--launcher-pane-background-color: #0d6efd;
+}

4. 테마 적용하기

Ctrl+Shift+R로 새로고침한 뒤 설정을 열면 새 테마가 목록에 나타납니다.

새 테마 선택

테마를 선택하면 새 모양으로 화면이 갱신됩니다.

테마 적용 결과

기본적으로 기존 테마를 바탕으로 합니다. 새 TriliumNext 테마를 기반으로 만들려면 테마 기반 선택을 참고하세요.

5. 테마 수정하기

테마 노트의 CSS를 수정한 뒤 Ctrl+Shift+R로 새로고침하면 반영됩니다. 창을 두 개 열어 한쪽에서는 편집하고 다른 쪽에서는 결과를 확인하면 편리합니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 테마 보관용 노트

사용자 지정 테마 코드를 보관할 노트입니다. 노트 제목과 CSS 코드를 구분해서 입력하세요.

이미지 2 · 새 코드 노트 만들기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · CSS 유형 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 4 · 테마 이름 지정

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 5 · 새 테마 선택

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 6 · 테마 적용 결과

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_1_.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_1_.png new file mode 100644 index 0000000..81a9d35 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_1_.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_2_.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_2_.png new file mode 100644 index 0000000..d352621 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_2_.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_3_.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_3_.png new file mode 100644 index 0000000..743d51c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_3_.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_4_.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_4_.png new file mode 100644 index 0000000..4f9583c Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_4_.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_5_.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_5_.png new file mode 100644 index 0000000..f2e63f1 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_5_.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_Cr.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_Cr.png new file mode 100644 index 0000000..94afbf4 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Creating a custom theme_Cr.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Custom app-wide CSS.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Custom app-wide CSS.html new file mode 100644 index 0000000..0fee0b4 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Custom app-wide CSS.html @@ -0,0 +1,13 @@ +

사용자가 선택한 테마와 관계없이 애플리케이션 전체에 적용할 CSS를 지정할 수 있습니다.

변경 사항 확인하기

애플리케이션 CSS 노트를 추가하거나 수정해도 바로 반영되지는 않습니다. Ctrl+Shift+R로 페이지를 새로고침하세요.

활용 예시: 인쇄 스타일 바꾸기

인쇄하거나 PDF로 내보낼 때의 모양은 @media 규칙을 사용하는 CSS 노트로 바꿀 수 있습니다. 다음 예제는 인쇄 글꼴을 명조 계열로 지정합니다.

@media print {
+
+	body {
+
+        --main-font-family: serif !important;
+
+        --detail-font-family: var(--main-font-family) !important;
+
+    }
+
+}
+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · CSS 노트 만들기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · appCss 라벨 지정

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · CSS 작성 예시

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Custom app-wide CSS_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Custom app-wide CSS_image.png new file mode 100644 index 0000000..dc6dcbe Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Custom app-wide CSS_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Customize the Next theme.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Customize the Next theme.html new file mode 100644 index 0000000..b52ea58 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Customize the Next theme.html @@ -0,0 +1,5 @@ +

사용자 지정 테마는 기본적으로 기존 밝은 테마를 바탕으로 합니다. TriliumNext 테마를 바탕으로 쓰려면 기존 테마 노트에 #appThemeBase=next 속성을 추가하세요. appTheme 속성도 있어야 합니다.

테마 기반 설정

appThemeBase에 사용할 수 있는 값은 다음과 같습니다.

스타일 덮어쓰기

TriliumNext 테마에는 기존 테마보다 우선순위가 높은 스타일 규칙이 더 있습니다. 변경한 스타일이 적용되지 않으면 값 뒤에 !important를 붙여 보세요.

:root {
+	--launcher-pane-background-color: #0d6efd !important;
+}
+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 테마 기반 설정

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Customize the Next theme_i.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Customize the Next theme_i.png new file mode 100644 index 0000000..e397c87 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Customize the Next theme_i.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Reference.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Reference.html new file mode 100644 index 0000000..ac24e2c --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Theme development/Reference.html @@ -0,0 +1,71 @@ +

모바일과 데스크톱 구분

body.mobile과 body.desktop으로 화면 유형을 구분합니다.

body.mobile #root-widget {
+	/* 모바일 화면에 적용할 스타일 */
+}
+
+body.desktop #root-widget {
+	/* 데스크톱 화면에 적용할 스타일 */
+}

모바일의 태블릿 배치는 미디어 쿼리로 구분합니다.

@media (max-width: 991px) {
+
+    #launcher-pane {
+
+        /* 모바일 배치에 적용할 스타일 */
+
+    }
+
+}
+
+
+
+@media (min-width: 992px) {
+
+    #launcher-pane {
+
+        /* 태블릿과 데스크톱 배치에 적용할 스타일 */
+
+    }
+
+}

가로 배치와 세로 배치

세로 배치에서는 실행 도구 모음이 왼쪽에 있습니다. 가로 배치에서는 위쪽에 있고 탭이 전체 너비를 사용합니다. body의 클래스로 구분합니다.

body.layout-vertical #left-pane {
+	/* 세로 배치에 적용할 스타일 */
+}
+
+body.layout-horizontal #center-pane {
+	/* 가로 배치에 적용할 스타일 */	
+}

#horizontal-main-container와 #vertical-main-container는 선택한 배치와 관계없이 DOM에 존재합니다. 해당 컨테이너로 본문 영역의 배경을 꾸밀 수 있습니다.

운영체제와 데스크톱 앱 구분

Windows에는 body.platform-win32를 사용하고 macOS에는 body.platform-darwin을 사용합니다. Electron 데스크톱 앱에만 적용하려면 다음과 같이 작성합니다.

body.electron {
+	background: blue;
+}

시스템 제목 표시줄

시스템 제목 표시줄 사용 여부도 body에서 구분합니다.

body.electron.native-titlebar {
+	/* 시스템 제목 표시줄에 적용할 스타일 */
+}
+
+body.electron:not(.native-titlebar) {
+	/* 사용자 제목 표시줄에 적용할 스타일 */
+}

시스템 창 버튼

시스템 제목 표시줄을 끈 상태에서도 운영체제의 창 버튼을 사용할 수 있습니다. 구현 과정과 화면은 시스템 창 버튼 구현 기록을 참고하세요.

Windows에서 버튼 영역의 글자색과 배경색은 RGB 16진수 값으로 지정합니다.

body {
+	--native-titlebar-foreground: #ffffff;
+	--native-titlebar-background: #ff0000;
+}

RGBA 값으로 투명도를 지정할 수도 있습니다. 이 경우 마우스를 올렸을 때의 색 표현이 제한될 수 있습니다.

body {
+	--native-titlebar-background: #ff0000aa;
+}

값은 창을 만들 때 읽으며 이후에는 밝은 모드와 어두운 모드 설정이 바뀔 때 갱신됩니다.

macOS에서는 시스템 제목 표시줄을 끄면 신호등 모양의 창 버튼이 기본으로 나타납니다. 위치는 다음과 같이 조정합니다.

body {
+    --native-titlebar-darwin-x-offset: 12;
+    --native-titlebar-darwin-y-offset: 14 !important;
+}

Windows의 Mica 배경 효과

Windows 11에서 body의 --background-material로 배경 효과를 설정합니다.

body.electron.platform-win32 {
+	--background-material: tabbed; 
+}

tabbed는 가로 배치에 적합하고 mica는 세로 배치에 적합합니다. 효과가 보이려면 상위 요소부터 하위 요소까지 배경을 투명하거나 반투명하게 해야 합니다. TriliumNext 테마를 참고하세요.

탭 아이콘과 작업 공간 색상

작업 공간 아이콘 대신 노트 아이콘을 표시하려면 다음 변수를 설정합니다.

:root {
+	--tab-note-icons: true;
+}

탭에서 작업 공간을 확대해 보고 있을 때 해당 작업 공간의 색을 가져올 수 있습니다. 다음 예제는 탭 전체 대신 위쪽의 가는 선에 색을 적용합니다.

.note-tab .note-tab-wrapper {
+    --tab-background-color: initial !important;
+}
+
+.note-tab .note-tab-wrapper::after {
+    content: "";
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    height: 3px;
+    background-color: var(--workspace-tab-background-color);
+}

사용자 글꼴

사용자 리소스 제공자를 사용합니다. 글꼴을 가져와 #customResourceProvider=fonts/myfont.ttf를 지정하고 CSS에서 /custom/fonts/myfont.ttf로 참조합니다. 서버가 루트 경로가 아닌 곳에서 실행된다면 ../../../custom/fonts/myfont.ttf를 사용합니다.

밝은 테마와 어두운 테마

밝은 테마는 다음과 같이 선언합니다. 어두운 테마는 값을 dark로 지정합니다.

:root {
+	--theme-style: light;
+}

prefers-color-scheme에 따라 자동 전환하는 테마는 현재 모드의 --theme-style과 함께 다음 변수도 지정합니다.

:root {
+
+    --theme-style-auto: true;
+
+}

Electron 앱이 운영체제에 색상 모드를 전달할 때 사용하는 정보입니다. Windows의 배경 효과 등에도 영향을 줍니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting.html new file mode 100644 index 0000000..9ad27c0 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting.html @@ -0,0 +1,5 @@ +

이 문서는 Trilium 사용 중 발생하는 문제를 해결하는 기본 절차입니다.

먼저 다시 불러오기

화면 문제는 Ctrl+R로 프런트엔드를 다시 불러오면 해결될 수 있습니다. 계속되거나 백엔드 문제라면 앱 전체를 다시 시작하세요. 데스크톱 앱은 닫았다 다시 열고 Docker는 컨테이너를 재시작합니다.

특정 노트를 열 때 종료되는 경우

잘못된 스크립트가 있는 노트를 시작할 때 다시 열면 오류가 반복될 수 있습니다. TRILIUM_START_NOTE_ID로 처음 열 노트를 지정해 탭을 초기화할 수 있습니다.

TRILIUM_START_NOTE_ID=root ./trilium

시작 스크립트 문제

시작 스크립트나 사용자 위젯 때문에 실행되지 않으면 안전 모드로 시작하세요.

TRILIUM_SAFE_MODE=true ./trilium

배포판에 따라 trilium-safe-mode.bat나 trilium-safe-mode.sh가 제공됩니다. 실행한 뒤 원인이 된 노트를 찾아 수정하거나 제거하세요.

일관성 검사

Trilium은 노트의 상위 연결 등 데이터베이스의 논리 구조를 주기적으로 확인합니다. 오류 알림이 나오면 문제를 보고하고 필요할 경우 익명화한 데이터베이스를 제공하세요.

백업 복원

문제가 심각하다면 백업에서 복원할 수 있습니다.

비밀번호를 잊은 경우

보호된 노트는 비밀번호 없이 복구할 수 없습니다. 아래는 보호하지 않은 노트에 다시 접근하기 위한 원문의 복구 절차입니다. 데이터베이스가 있는 데이터 폴더를 먼저 백업하고 앱을 종료한 뒤 SQLite 편집기로 document.db를 엽니다.

UPDATE options SET value = '77/twC5O00cuQgNC63VK32qOKKYwj21ev3jZDXoytVU=' WHERE name = 'passwordVerificationSalt';
+UPDATE options SET value = '710BMasZCAgibzIc07X4P9Q4TeBd4ONnqJOho+pWcBM=' WHERE name = 'passwordDerivedKeySalt';
+UPDATE options SET value = 'Eb8af1/T57b89lCRuS97tPEl4CwxsAWAU7YNJ77oY+s=' WHERE name = 'passwordVerificationHash';
+UPDATE options SET value = 'QpC8XoiYYeqHPtHKRtbNxfTHsk+pEBqVBODYp0FkPBa22tlBBKBMigdLu5GNX8Uu' WHERE name = 'encryptedDataKey';

변경 사항을 저장하면 로그인 비밀번호가 password로 바뀝니다. 이 절차로 기존 보호 노트가 복구되는 것은 아닙니다. 접근 가능한 노트를 내보내 새 데이터베이스로 옮기거나 기존 DB를 계속 사용한다면 설정에서 즉시 새 비밀번호를 지정하세요.

오류 보고

GitHub 문제 보고에 발생 상황을 적고 오류 로그 안내에 따라 필요한 정보를 함께 제공하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Anonymized Database.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Anonymized Database.html new file mode 100644 index 0000000..4a93697 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Anonymized Database.html @@ -0,0 +1,3 @@ +

데이터베이스 익명화 화면

오류를 조사할 때 데이터베이스 구조가 필요할 수 있습니다. 개인 노트가 담긴 데이터베이스 원본을 공유하는 대신 익명화 기능을 사용할 수 있습니다. 메뉴 → 설정 → 고급에서 실행하세요.

익명화 기능은 복사본을 만든 뒤 노트 제목과 본문 및 수정 이력과 사용 기록을 제거합니다. 일부 설정과 시스템용이 아닌 속성도 제거하며 구조와 수정 날짜 등의 메타데이터는 남깁니다. 이후 VACUUM 정리를 수행해 삭제된 데이터가 파일 내부에 남지 않도록 합니다.

결과는 데이터 폴더 아래의 anonymized 폴더에 저장됩니다. 원본은 이 과정에서 변경되지 않습니다.

정리된 복사본에도 구조와 날짜 등의 정보는 남습니다. 공유 전에 필요한 익명화 범위를 확인하세요. VACUUM 처리가 끝난 결과 파일의 위치는 데이터 폴더 안내에서도 확인할 수 있습니다.

명령줄에서 익명화하기

데이터베이스 문제로 Trilium을 시작할 수 없다면 다음 명령을 사용할 수 있습니다.

node src/anonymize.js

Trilium 소스 파일이 있는 폴더에서 실행하세요. 데스크톱 배포판에서는 일반적으로 resources/app 폴더입니다.

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 데이터베이스 익명화 화면

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Anonymized Database_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Anonymized Database_image.png new file mode 100644 index 0000000..fb640c0 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Anonymized Database_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs.html new file mode 100644 index 0000000..f83e287 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs.html @@ -0,0 +1,4 @@ +

오류 보고에 관련 로그를 함께 제공하면 원인을 파악하는 데 도움이 됩니다.

백엔드 로그

데이터 폴더의 log 하위 폴더에서 가장 최근 파일을 찾으세요. 이름은 trilium-2022-12-14.log와 같은 형식입니다. 전체 파일을 첨부하거나 마지막 부분과 관련된 내용을 복사할 수 있습니다.

파일을 찾기 어렵다면 왼쪽 위 메뉴 → 고급 → 백엔드 로그 보기를 사용하세요.

프런트엔드 로그

대부분의 브라우저와 데스크톱 앱에서는 Ctrl+Shift+I로 개발자 도구를 엽니다. 애플리케이션을 다시 시작하면 콘솔이 지워지므로 오류를 재현한 직후 로그를 복사하세요.

브라우저에서 개발자 도구 열기

개발자 도구의 콘솔 탭을 선택하세요.

개발자 도구 콘솔

로그를 복사하거나 화면을 캡처합니다. 오류 전후의 기록을 함께 제공하면 발생 상황을 이해하기 쉽습니다.

민감한 정보가 포함된 경우

공개 GitHub 이슈에 올리기 어려운 자료는 먼저 Matrix 지원 채널에서 개발자에게 전달 방법을 문의하세요. 가져오기 중 문제가 발생한 파일이나 이미지 및 ZIP 파일과 익명화한 데이터베이스도 원인 분석에 도움이 될 수 있습니다.

문제 재현용 하위 트리 내보내기

특정 노트에서만 발생하는 문제라면 해당 노트를 제공하는 것이 재현에 도움이 됩니다. 왼쪽 트리에서 관련 노트를 마우스 오른쪽 버튼으로 클릭한 뒤 내보내기 → HTML을 ZIP으로 내보내기를 선택하세요.

문제 재현용 노트 내보내기

+ +

예전 화면 이미지 읽는 법

아래 설명은 본문에 나온 이미지 순서에 맞췄습니다. 이미지는 원본을 유지했으므로 영문 메뉴가 보일 수 있습니다. 현재 앱에서는 한국어 메뉴를 사용합니다. 코드와 주소 및 제품 이름은 원래 표기를 따릅니다.

이미지 1 · 브라우저에서 개발자 도구 열기

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 2 · 개발자 도구 콘솔

화면에서 사용하는 주요 표현은 다음과 같습니다.

이미지 3 · 문제 재현용 노트 내보내기

화면에서 사용하는 주요 표현은 다음과 같습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs_error-logs-expo.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs_error-logs-expo.png new file mode 100644 index 0000000..65abe49 Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs_error-logs-expo.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs_error-logs-fire.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs_error-logs-fire.png new file mode 100644 index 0000000..a6c45bb Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs_error-logs-fire.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs_image.png b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs_image.png new file mode 100644 index 0000000..62a034e Binary files /dev/null and b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Error logs_image.png differ diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Refreshing the application.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Refreshing the application.html new file mode 100644 index 0000000..ad3007b --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Refreshing the application.html @@ -0,0 +1 @@ +

일부 변경 사항은 바로 적용되지 않습니다. 이때는 애플리케이션을 직접 새로고침해야 합니다.

Ctrl+Shift+R을 누르면 새로고침할 수 있습니다.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Reporting issues.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Reporting issues.html new file mode 100644 index 0000000..7742988 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Reporting issues.html @@ -0,0 +1 @@ +

TriliumNext 문제 보고 페이지에서 새 이슈를 만드는 버튼을 누르세요.

오류를 보고하려면 오류 보고 양식을 선택한 뒤 자세한 내용을 작성하세요.

diff --git a/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Synchronization fails with 504.html b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Synchronization fails with 504.html new file mode 100644 index 0000000..87080f5 --- /dev/null +++ b/release/app/assets/doc_notes/en/User Guide/User Guide/Troubleshooting/Synchronization fails with 504.html @@ -0,0 +1,4 @@ +

동기화 중에 갱신할 항목을 계산하는 데 시간이 오래 걸릴 수 있습니다. 역방향 프록시를 사용하는 환경에서는 이때 요청 시간이 초과될 수 있습니다.

프록시의 시간 제한을 늘리면 해결할 수 있습니다.

Nginx

설정 파일에 다음 내용을 추가하세요.

proxy_connect_timeout 300;
+proxy_send_timeout 300;
+proxy_read_timeout 300;
+send_timeout 300;

설정을 저장한 뒤 서버를 다시 시작하세요.

Nginx 설정에 관한 자세한 내용은 Nginx 프록시 설정을 참고하세요.

문제가 계속되면 시간 제한을 더 늘려 보세요.

diff --git a/release/app/assets/doc_notes/en/api-ko/backend.html b/release/app/assets/doc_notes/en/api-ko/backend.html new file mode 100644 index 0000000..58b2849 --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/backend.html @@ -0,0 +1,150 @@ +백엔드 스크립트 API

백엔드 스크립트 API

연결된 공식 문서의 한국어 사본입니다. 함수 이름과 코드 문법은 원문을 유지했습니다. 외부 문서는 운영 버전과 다를 수 있으므로 지원 여부를 확인하세요. 공식 원문 보기

인터페이스 Api

interface Api {
    __private: { becca: default };
    axios: AxiosStatic;
    cheerio: {
        default: CheerioAPI;
        version: string;
        contains(container: Element, contained: Element): boolean;
        html(options?: CheerioParserOptions): string;
        html(
            dom: string | Element | Cheerio,
            options?: CheerioParserOptions,
        ): string;
        load(
            html: string | Buffer<ArrayBufferLike>,
            options?: CheerioParserOptions,
        ): Root;
        load(element: Element | Element[], options?: CheerioParserOptions): Root;
        parseHTML(
            data: string,
            context?: null | Document,
            keepScripts?: boolean,
        ): Document[];
        root(): Cheerio;
        xml(dom?: string | Element | Cheerio): string;
    };
    currentNote: BNote;
    dayjs: __module;
    logMessages: Record<string, string[]>;
    logSpacedUpdates: Record<string, SpacedUpdate>;
    originEntity?: null | AbstractBeccaEntity<any>;
    sql: any;
    startNote?: null | BNote;
    xml2js: node_modules/@types/xml2js;
    backupNow(backupName: string): Promise<string>;
    createDataNote(
        parentNoteId: string,
        title: string,
        content: {},
    ): NoteAndBranch;
    createNewNote(params: NoteParams): NoteAndBranch;
    createNote(
        parentNoteId: string,
        title: string,
        content: string,
        extraOptions: Omit<
            NoteParams,
            "title"
            | "parentNoteId"
            | "content"
            | "type",
        > & { attributes?: AttributeRow[]; json?: boolean },
    ): NoteAndBranch;
    createOrUpdateLauncher(
        opts: {
            icon: string;
            id: string;
            isVisible: boolean;
            keyboardShortcut: string;
            scriptNoteId: string;
            targetNoteId: string;
            title: string;
            type: "script" | "note" | "customWidget";
            widgetNoteId?: string;
        },
    ): { note: BNote };
    createTextNote(
        parentNoteId: string,
        title: string,
        content: string,
    ): NoteAndBranch;
    ensureNoteIsAbsentFromParent(noteId: string, parentNoteId: string): void;
    ensureNoteIsPresentInParent(
        noteId: string,
        parentNoteId: string,
        prefix: string,
    ): { branch: null | BBranch };
    escapeHtml(string: string): string;
    exportSubtreeToZipFile(
        noteId: string,
        format: "html" | "markdown",
        zipFilePath: string,
    ): Promise<void>;
    getAppInfo(): {
        appVersion: string;
        buildDate: string;
        buildRevision: string;
        clipperProtocolVersion: string;
        dataDirectory: string;
        dbVersion: number;
        nodeVersion: string;
        syncVersion: number;
        utcDateTime: string;
    };
    getAttachment(attachmentId: string): null | BAttachment;
    getAttribute(attachmentId: string): null | BAttribute;
    getAttribute(attributeId: string): null | BAttribute;
    getBranch(branchId: string): null | BBranch;
    getDayNote(date: string, rootNote?: BNote): Promise<null | BNote>;
    getEtapiToken(etapiTokenId: string): null | BEtapiToken;
    getEtapiTokens(): BEtapiToken[];
    getInstanceName(): null | string;
    getMonthNote(date: string, rootNote: BNote): Promise<null | BNote>;
    getNote(noteId: string): null | BNote;
    getNotesWithLabel(name: string, 값?: string): BNote[];
    getNoteWithLabel(name: string, 값?: string): null | BNote;
    getOption(optionName: string): null | BOption;
    getOptions(): BOption[];
    getQuarterNote(date: string, rootNote: BNote): Promise<null | BNote>;
    getRevision(revisionId: string): null | BRevision;
    getRootCalendarNote(): null | BNote;
    getTodayNote(rootNote?: BNote): Promise<null | BNote>;
    getWeekFirstDayNote(date: string, rootNote: BNote): Promise<null | BNote>;
    getWeekNote(date: string, rootNote: BNote): Promise<null | BNote>;
    getYearNote(year: string, rootNote?: BNote): null | BNote;
    log(message: string): void;
    randomString(length: number): string;
    runOnFrontend(script: () => string | void, params: []): void;
    runOutsideOfSync(callback: () => void): Promise<void>;
    searchForNote(query: string, searchParams: SearchParams): null | BNote;
    searchForNotes(query: string, searchParams: SearchParams): BNote[];
    setNoteToParent(
        noteId: string,
        prefix: string,
        parentNoteId: null | string,
    ): void;
    sortNotes(
        parentNoteId: string,
        sortConfig: { foldersFirst?: boolean; reverse?: boolean; sortBy?: string },
    ): void;
    toggleNoteInParent(
        present: true,
        noteId: string,
        parentNoteId: string,
        prefix: string,
    ): void;
    transactional(func: () => void): any;
    unescapeHtml(string: string): string;
}
목차

속성

__private: { becca: default }

이 객체에는 다음 특성을 가진 고급 기능 객체가 들어 있습니다. "사용자가 영향을 판단해야 함" 및 "하위 호환성 보장 없음" 고급 사용 사례를 위한 객체입니다.

+

형식 선언

  • becca: default

    백엔드의 메모리 내 객체 그래프에 접근합니다. 참고: Becca

    +

HTTP 요청을 위한 Axios 라이브러리입니다. 참고: https://axios-http.com 라이브러리 사용 안내

+

대신 브라우저와 호환되는 기본 fetch()를 사용하세요.

+
cheerio: {
    default: CheerioAPI;
    version: string;
    contains(container: Element, contained: Element): boolean;
    html(options?: CheerioParserOptions): string;
    html(
        dom: string | Element | Cheerio,
        options?: CheerioParserOptions,
    ): string;
    load(
        html: string | Buffer<ArrayBufferLike>,
        options?: CheerioParserOptions,
    ): Root;
    load(element: Element | Element[], options?: CheerioParserOptions): Root;
    parseHTML(
        data: string,
        context?: null | Document,
        keepScripts?: boolean,
    ): Document[];
    root(): Cheerio;
    xml(dom?: string | Element | Cheerio): string;
}

HTML 분석과 처리를 위한 cheerio 라이브러리입니다. 참고: https://cheerio.js.org 라이브러리 사용 안내

+
currentNote: BNote

현재 스크립트가 실행 중인 노트입니다. 코드가 여러 노트로 나뉘어 있으면 처음 실행을 시작한 노트는 다음과 같습니다: "startNote"함수 호출을 통해 다른 노트인 currentNote로 실행 위치가 바뀔 수 있습니다. C 언어에서는 다음 개념과 비슷합니다: FILE +현재 화면에서 활성화된 노트와 혼동하지 마세요.

+
dayjs: __module

날짜 처리를 위한 day.js 라이브러리입니다. 참고: https://day.js.org 라이브러리 사용 안내

+
logMessages: Record<string, string[]>
logSpacedUpdates: Record<string, SpacedUpdate>
originEntity?: null | AbstractBeccaEntity<any>

이 실행을 시작하게 한 이벤트의 엔터티

+
sql: any

sql

+
startNote?: null | BNote

스크립트 실행이 시작된 노트입니다. C 언어로 비유하면 현재 프로세스의 main() 함수가 들어 있는 파일에 해당합니다.

+

XML 분석을 위한 xml2js 라이브러리입니다. 참고: https://github.com/Leonidas-from-XIV/node-xml2js 라이브러리 사용 안내

+

메서드

  • 매개변수

    • backupName: string

      예를 들어 backupName에 다음 값을 지정하면: "now"백업은 다음 이름으로 저장됩니다: "backup-now.db" 파일

      +

    반환값 Promise<string>

    백업이 끝나면 완료됩니다.

    +
  • JSON으로 직렬화할 수 있는 객체를 데이터 노트로 만듭니다. 생성되는 노트의 유형은 code이며 MIME 유형은 JSON입니다. 더 많은 옵션은 createNewNote()를 확인하세요.

    +

    매개변수

    • parentNoteId: string
    • title: string
    • content: {}

    반환값 NoteAndBranch

  • 매개변수

    • parentNoteId: string

      이 상위 노트 아래에 새 노트 생성

      +
    • title: string
    • content: string
    • extraOptions: Omit<NoteParams, "title" | "parentNoteId" | "content" | "type"> & {
          attributes?: AttributeRow[];
          json?: boolean;
      }
      • Optionalattributes?: AttributeRow[]
      • Optionaljson?: boolean

        노트에 JSON을 사용할지 여부

        +

    반환값 NoteAndBranch

    새로 생성한 노트와 가지 엔터티가 들어 있는 객체

    +

    간단한 용도에는 비슷한 API인 createTextNote()를 사용하고 복잡한 요구에는 createNewNote()를 사용하세요.

    +
  • 실행 도구 모음에 새 실행 도구를 만듭니다. 같은 ID가 있으면 변경합니다.

    +

    매개변수

    • opts: {
          icon: string;
          id: string;
          isVisible: boolean;
          keyboardShortcut: string;
          scriptNoteId: string;
          targetNoteId: string;
          title: string;
          type: "script" | "note" | "customWidget";
          widgetNoteId?: string;
      }
      • icon: string

        사용할 Boxicons 아이콘 이름. 예: "bx-time")

        +
      • id: string

        영문과 숫자로만 구성된 6자리 이상의 실행 도구 ID

        +
      • isVisible: boolean

        true이면 다음 위치에 생성합니다: "표시할 실행 도구"그 외에는 다음 위치에 생성합니다: "사용 가능한 실행 도구"

        +
      • keyboardShortcut: string

        누르면 대상 노트나 스크립트를 활성화할 단축키. 예: "ctrl+e"

        +
      • scriptNoteId: string

        해당 유형: "script"

        +
      • targetNoteId: string

        해당 유형: "note"

        +
      • title: string
      • type: "script" | "note" | "customWidget"

        다음 중 하나

        +
          +
        • "note" 실행 도구를 누르면 targetNoteId로 지정한 노트로 이동합니다.
        • +
        • "script" 실행 도구를 누르면 scriptNoteId로 지정한 스크립트를 실행합니다.
        • +
        • "customWidget" widgetNoteId로 지정한 사용자 지정 위젯으로 실행 도구를 표시합니다.
        • +
        +
      • OptionalwidgetNoteId?: string

        해당 유형: "customWidget"

        +

    반환값 { note: BNote }

  • 텍스트 노트를 만듭니다. 더 많은 옵션은 createNewNote()를 확인하세요.

    +

    매개변수

    • parentNoteId: string
    • title: string
    • content: string

    반환값 NoteAndBranch

  • 노트와 상위 노트 사이에 가지가 있으면 삭제합니다. 없으면 아무 작업도 하지 않습니다.

    +

    매개변수

    • noteId: string
    • parentNoteId: string

    반환값 void

  • 노트와 상위 노트 사이에 가지가 없으면 만듭니다. 이미 있으면 그대로 둡니다. 새 가지 또는 기존 가지를 반환합니다.

    +

    매개변수

    • noteId: string
    • parentNoteId: string
    • prefix: string

      노트와 상위 노트 사이에 가지를 새로 만들 때 지정할 접두사

      +

    반환값 { branch: null | BBranch }

  • 매개변수

    • noteId: string
    • format: "html" | "markdown"

      html 또는 markdown

      +
    • zipFilePath: string

    반환값 Promise<void>

  • 반환값 {
        appVersion: string;
        buildDate: string;
        buildRevision: string;
        clipperProtocolVersion: string;
        dataDirectory: string;
        dbVersion: number;
        nodeVersion: string;
        syncVersion: number;
        utcDateTime: string;
    }

  • 지정한 날짜의 일별 노트를 반환합니다. 없으면 만듭니다.

    +

    매개변수

    • date: string

      YYYY-MM-DD 형식

      +
    • OptionalrootNote: BNote

      달력 루트 노트를 지정합니다. 일반적으로 비워 두어 기본 달력을 사용합니다.

      +

    반환값 Promise<null | BNote>

  • 인스턴스 이름은 개별 Trilium 실행 환경을 구분합니다. 특정 인스턴스에서만 작업을 실행해야 하는 스크립트에 유용합니다.

    +

    반환값 null | string

  • 지정한 날짜의 월별 노트를 반환합니다. 없으면 만듭니다.

    +

    매개변수

    • date: string

      YYYY-MM 형식

      +
    • rootNote: BNote

      달력 루트 노트를 지정합니다. 일반적으로 비워 두어 기본 달력을 사용합니다.

      +

    반환값 Promise<null | BNote>

  • 지정한 라벨 이름을 가진 노트들을 조회합니다. & 값

    +

    매개변수

    • name: string

      속성 이름

      +
    • Optional값: string

      속성값

      +

    반환값 BNote[]

  • 지정한 라벨 이름을 가진 첫 번째 노트를 조회합니다. & 값

    +

    매개변수

    • name: string

      속성 이름

      +
    • Optional값: string

      속성값

      +

    반환값 null | BNote

  • 지정한 날짜의 분기별 노트를 반환합니다. 없으면 만듭니다.

    +

    매개변수

    • date: string

      YYYY-MM 형식

      +
    • rootNote: BNote

      달력 루트 노트를 지정합니다. 일반적으로 비워 두어 기본 달력을 사용합니다.

      +

    반환값 Promise<null | BNote>

  • 오늘의 일별 노트를 반환합니다. 없으면 만듭니다.

    +

    매개변수

    • OptionalrootNote: BNote

      달력 루트 노트를 지정합니다. 일반적으로 비워 두어 기본 달력을 사용합니다.

      +

    반환값 Promise<null | BNote>

  • 지정한 날짜가 속한 주의 첫날에 해당하는 노트를 반환합니다.

    +

    매개변수

    • date: string

      YYYY-MM-DD 형식

      +
    • rootNote: BNote

      달력 루트 노트를 지정합니다. 일반적으로 비워 두어 기본 달력을 사용합니다.

      +

    반환값 Promise<null | BNote>

  • 지정한 날짜의 주별 노트를 반환합니다. 없으면 만듭니다.

    +

    매개변수

    • date: string

      YYYY-MM-DD 형식

      +
    • rootNote: BNote

      달력 루트 노트를 지정합니다. 일반적으로 비워 두어 기본 달력을 사용합니다.

      +

    반환값 Promise<null | BNote>

  • 지정한 연도의 연도별 노트를 반환합니다. 없으면 만듭니다.

    +

    매개변수

    • year: string

      YYYY 형식

      +
    • OptionalrootNote: BNote

      달력 루트 노트를 지정합니다. 일반적으로 비워 두어 기본 달력을 사용합니다.

      +

    반환값 null | BNote

  • 지정한 메시지를 Trilium 로그와 화면의 로그 창에 기록합니다.

    +

    매개변수

    • message: string

    반환값 void

  • 지정한 길이의 임의 문자열을 반환합니다. 암호학적으로 안전한 난수를 만드는 함수가 아닙니다.

    +

    매개변수

    • length: number

      문자열 기준

      +

    반환값 string

    임의 문자열

    +
  • 지정한 익명 함수를 프런트엔드에서 실행합니다. 내부적으로 함수를 문자열로 직렬화한 뒤 WebSocket으로 전송합니다. 서로 다른 탭 등 여러 프런트엔드가 연결돼 있으면 모든 인스턴스에서 실행합니다.

    +

    매개변수

    • script: () => string | void

      프런트엔드에서 실행할 스크립트

      +
    • params: []

      프런트엔드로 보낼 익명 함수의 매개변수 목록

      +

    반환값 void

    반환값이 없습니다.

    +
  • 동기화 중에는 데이터가 일시적으로 일관되지 않을 수 있습니다. 강한 일관성이 필요한 스크립트는 이 함수로 진행 중인 동기화가 끝나기를 기다리고 실행 중 새 동기화가 시작되지 않게 할 수 있습니다.

    +

    비동기 처리이므로 내부 콜백에는 자동 트랜잭션 처리가 적용되지 않습니다. 데이터베이스를 변경하려면 api.transactional(...)로 호출을 감싸야 합니다.

    +

    매개변수

    • callback: () => void

      동기화가 실행되지 않는 동안 실행할 함수

      +

    반환값 Promise<void>

    콜백이 끝날 때까지 기다린 뒤 완료됩니다.

    +
  • noteId와 접두사로 노트를 찾아 지정한 parentNoteId 아래에 배치합니다. parentNoteId를 지정하지 않으면 가지를 삭제합니다.

    +

    toggleNoteInParent()와 비슷하지만 접두사로 가지를 찾는다는 차이가 있습니다.

    +

    매개변수

    • noteId: string
    • prefix: string
    • parentNoteId: null | string

    반환값 void

    동작을 혼동하기 쉬운 메서드이며 특수한 용도에만 사용합니다.

    +
  • 지정한 노트의 하위 노트를 정렬합니다.

    +

    매개변수

    • parentNoteId: string
    • sortConfig: { foldersFirst?: boolean; reverse?: boolean; sortBy?: string }

    반환값 void

  • 값에 따라 노트와 상위 노트 사이의 가지를 만들거나 삭제합니다.

    +

    매개변수

    • present: true

      가지를 유지하려면 true를 사용하고 없애려면 false를 사용합니다.

      +
    • noteId: string
    • parentNoteId: string
    • prefix: string

      노트와 상위 노트 사이에 가지를 새로 만들 때 지정할 접두사

      +

    반환값 void

  • 트랜잭션 안에서 실행할 코드를 감쌉니다. 이미 트랜잭션이 있으면 해당 트랜잭션을 사용합니다.

    +

    매개변수

    • func: () => void

    반환값 any

    func 콜백의 결과

    +
  • 매개변수

    • string: string

      이스케이프를 해제할 대상

      +

    반환값 string

    이스케이프를 해제한 문자열

    +
\ No newline at end of file diff --git a/release/app/assets/doc_notes/en/api-ko/etapi.json b/release/app/assets/doc_notes/en/api-ko/etapi.json new file mode 100644 index 0000000..1bae1f2 --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/etapi.json @@ -0,0 +1,1776 @@ +{ + "openapi": "3.0.3", + "info": { + "version": "1.0.0", + "title": "ETAPI", + "description": "Trilium 외부 API", + "contact": { + "name": "zadam", + "email": "zadam.apps@gmail.com", + "url": "https://github.com/zadam/trilium" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "servers": [ + { + "url": "/etapi", + "description": "현재 Trilium 서버" + } + ], + "security": [ + { + "EtapiTokenAuth": [] + }, + { + "EtapiBasicAuth": [] + } + ], + "paths": { + "/create-note": { + "post": { + "description": "노트를 만들고 노트 트리에 배치합니다.", + "operationId": "createNote", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateNoteDef" + } + } + } + }, + "responses": { + "201": { + "description": "노트 생성 완료", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/NoteWithBranch" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/notes": { + "get": { + "description": "노트 검색", + "operationId": "searchNotes", + "parameters": [ + { + "name": "search", + "in": "query", + "required": true, + "description": "https://triliumnext.github.io/Docs/Wiki/search.html 에 설명된 형식의 검색어", + "schema": { + "type": "string" + }, + "examples": { + "fulltext": { + "summary": "검색어로 전체 텍스트 검색. 정확히 일치할 필요는 없습니다.", + "value": "towers tolkien" + }, + "fulltextExactMatch": { + "summary": "정확히 일치하는 전체 텍스트 검색. 큰따옴표를 사용합니다.", + "value": "\"Two Towers\"" + }, + "fulltextWithLabel": { + "summary": "검색어와 라벨 조건을 모두 만족하는 전체 텍스트 검색", + "value": "towers #book" + } + } + }, + { + "name": "fastSearch", + "in": "query", + "required": false, + "description": "빠른 검색 사용. 전체 텍스트 검색에서 본문은 확인하지 않습니다.", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "includeArchivedNotes", + "in": "query", + "required": false, + "description": "기본적으로 보관된 노트는 검색하지 않습니다. true로 설정하면 검색 결과에 포함합니다.", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "ancestorNoteId", + "in": "query", + "required": false, + "description": "지정한 subtree 노트 ID의 하위 트리만 검색합니다. 기본값은 전체 트리입니다.", + "schema": { + "$ref": "#/components/schemas/EntityId" + } + }, + { + "name": "ancestorDepth", + "in": "query", + "required": false, + "description": "검색할 노트의 트리 깊이를 지정합니다.", + "schema": { + "type": "string" + }, + "examples": { + "directChildren": { + "summary": "기준 상위 노트에서 정확히 한 단계 아래인 직계 하위 노트. 기준을 지정하지 않으면 루트입니다.", + "value": "eq1" + }, + "grandGrandChildren": { + "summary": "기준 상위 노트에서 정확히 세 단계 아래. 기준을 지정하지 않으면 루트입니다.", + "value": "eq3" + }, + "lessThan4": { + "summary": "기준 상위 노트에서 네 단계 미만인 깊이 1~3. 기준을 지정하지 않으면 루트입니다.", + "value": "lt4" + }, + "greaterThan2": { + "summary": "기준 상위 노트에서 두 단계보다 깊은 위치. 깊이 3부터 해당하며 기준을 지정하지 않으면 루트입니다.", + "value": "gt4" + } + } + }, + { + "name": "orderBy", + "in": "query", + "required": false, + "description": "검색 결과 정렬에 사용할 속성 또는 라벨 이름", + "schema": { + "type": "string" + }, + "example": [ + "title", + "#publicationDate", + "isProtected", + "isArchived", + "dateCreated", + "dateModified", + "utcDateCreated", + "utcDateModified", + "parentCount", + "childrenCount", + "attributeCount", + "labelCount", + "ownedLabelCount", + "relationCount", + "ownedRelationCount", + "relationCountIncludingLinks", + "ownedRelationCountIncludingLinks", + "targetRelationCount", + "targetRelationCountIncludingLinks", + "contentSize", + "contentAndAttachmentsSize", + "contentAndAttachmentsAndRevisionsSize", + "revisionCount" + ] + }, + { + "name": "orderDirection", + "in": "query", + "required": false, + "description": "정렬 방향. 오름차순 또는 내림차순입니다.", + "schema": { + "type": "string", + "default": "asc", + "enum": [ + "asc", + "desc" + ] + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "description": "반환할 결과 수 제한", + "schema": { + "type": "integer" + }, + "example": 10 + }, + { + "name": "debug", + "in": "query", + "required": false, + "description": "true로 설정하면 검색어 구문 분석에 관한 디버깅 정보를 응답에 포함합니다.", + "schema": { + "type": "boolean", + "default": false + } + } + ], + "responses": { + "200": { + "description": "검색 응답", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/SearchResponse" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/notes/{noteId}": { + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + } + ], + "get": { + "description": "ID로 노트를 조회합니다.", + "operationId": "getNoteById", + "responses": { + "200": { + "description": "노트 응답", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Note" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "patch": { + "description": "noteId로 지정한 노트에 요청 본문의 변경 사항을 적용합니다.", + "operationId": "patchNoteById", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Note" + } + } + } + }, + "responses": { + "200": { + "description": "노트 변경 완료", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Note" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "description": "noteId로 지정한 노트 하나를 삭제합니다.", + "operationId": "deleteNoteById", + "responses": { + "204": { + "description": "노트 삭제 완료" + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/notes/{noteId}/content": { + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + } + ], + "get": { + "description": "ID로 노트 본문을 조회합니다.", + "operationId": "getNoteContent", + "responses": { + "200": { + "description": "노트 본문 응답", + "content": { + "text/html": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "put": { + "description": "ID로 지정한 노트의 본문을 변경합니다.", + "operationId": "putNoteContentById", + "requestBody": { + "description": "노트의 HTML 본문", + "required": true, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "responses": { + "204": { + "description": "노트 본문 변경 완료" + } + } + } + }, + "/notes/{noteId}/export": { + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + }, + { + "name": "format", + "in": "query", + "required": false, + "schema": { + "enum": [ + "html", + "markdown" + ], + "default": "html" + } + } + ], + "get": { + "description": "지정한 하위 노트 트리를 ZIP 파일로 내보냅니다. 전체 문서를 내보내려면 noteId에 \"root\"를 사용합니다.", + "operationId": "exportNoteSubtree", + "responses": { + "200": { + "description": "내보낸 ZIP 파일", + "content": { + "application/zip": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/notes/{noteId}/import": { + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + } + ], + "post": { + "description": "지정한 노트로 ZIP 파일을 가져옵니다.", + "operationId": "importZip", + "responses": { + "201": { + "description": "노트 생성 완료", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/NoteWithBranch" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/notes/{noteId}/revision": { + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + }, + { + "name": "format", + "in": "query", + "required": false, + "schema": { + "enum": [ + "html", + "markdown" + ], + "default": "html" + } + } + ], + "post": { + "description": "지정한 노트의 수정 이력을 만듭니다.", + "operationId": "createRevision", + "responses": { + "204": { + "description": "수정 이력 생성 완료" + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/branches": { + "post": { + "description": "가지를 만들어 같은 노트를 트리의 다른 위치에도 배치합니다. 상위 노트와 하위 노트 사이에 가지가 이미 있으면 기존 가지의 prefix와 notePosition 및 isExpanded를 변경합니다.", + "operationId": "postBranch", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Branch" + } + } + } + }, + "responses": { + "200": { + "description": "기존 가지 변경 완료. 상위 노트와 하위 노트 사이에 가지가 이미 있었습니다.", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Branch" + } + } + } + }, + "201": { + "description": "가지 생성 완료", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Branch" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/branches/{branchId}": { + "parameters": [ + { + "name": "branchId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + } + ], + "get": { + "description": "ID로 가지를 조회합니다.", + "operationId": "getBranchById", + "responses": { + "200": { + "description": "가지 응답", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Branch" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "patch": { + "description": "branchId로 지정한 가지에 요청 본문의 변경 사항을 적용합니다. prefix와 notePosition만 변경할 수 있습니다. 다른 속성을 바꾸려면 기존 가지를 삭제하고 새로 만들어야 합니다.", + "operationId": "patchBranchById", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Branch" + } + } + } + }, + "responses": { + "200": { + "description": "가지 변경 완료", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Branch" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "description": "branchId로 지정한 가지를 삭제합니다. 해당 하위 노트의 마지막 가지라면 노트도 삭제합니다.", + "operationId": "deleteBranchById", + "responses": { + "204": { + "description": "가지 삭제 완료" + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/attachments": { + "post": { + "description": "첨부 파일 생성", + "operationId": "postAttachment", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateAttachment" + } + } + } + }, + "responses": { + "201": { + "description": "첨부 파일 생성 완료", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Attachment" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/attachments/{attachmentId}": { + "parameters": [ + { + "name": "attachmentId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + } + ], + "get": { + "description": "ID로 첨부 파일을 조회합니다.", + "operationId": "getAttachmentById", + "responses": { + "200": { + "description": "첨부 파일 응답", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Attachment" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "patch": { + "description": "attachmentId로 지정한 첨부 파일에 요청 본문의 변경 사항을 적용합니다. role과 mime 및 title과 position만 변경할 수 있습니다.", + "operationId": "patchAttachmentById", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Attachment" + } + } + } + }, + "responses": { + "200": { + "description": "속성 변경 완료", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Attachment" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "description": "attachmentId로 지정한 첨부 파일을 삭제합니다.", + "operationId": "deleteAttachmentById", + "responses": { + "204": { + "description": "첨부 파일 삭제 완료" + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/attachments/{attachmentId}/content": { + "parameters": [ + { + "name": "attachmentId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + } + ], + "get": { + "description": "ID로 첨부 파일 내용을 조회합니다.", + "operationId": "getAttachmentContent", + "responses": { + "200": { + "description": "첨부 파일 내용 응답", + "content": { + "text/html": { + "schema": { + "type": "string" + } + } + } + } + } + }, + "put": { + "description": "ID로 지정한 첨부 파일의 내용을 변경합니다.", + "operationId": "putAttachmentContentById", + "requestBody": { + "description": "첨부 파일의 HTML 내용", + "required": true, + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "responses": { + "204": { + "description": "첨부 파일 내용 변경 완료" + } + } + } + }, + "/attributes": { + "post": { + "description": "지정한 노트에 속성 생성", + "operationId": "postAttribute", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Attribute" + } + } + } + }, + "responses": { + "201": { + "description": "속성 생성 완료", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Attribute" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/attributes/{attributeId}": { + "parameters": [ + { + "name": "attributeId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + } + ], + "get": { + "description": "ID로 속성을 조회합니다.", + "operationId": "getAttributeById", + "responses": { + "200": { + "description": "속성 응답", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Attribute" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "patch": { + "description": "attributeId로 지정한 속성에 요청 본문의 변경 사항을 적용합니다. 라벨은 value와 position만 변경할 수 있고 관계는 position만 변경할 수 있습니다. 다른 속성을 바꾸려면 기존 속성을 삭제하고 새로 만들어야 합니다.", + "operationId": "patchAttributeById", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Attribute" + } + } + } + }, + "responses": { + "200": { + "description": "속성 변경 완료", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Attribute" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "description": "attributeId로 지정한 속성을 삭제합니다.", + "operationId": "deleteAttributeById", + "responses": { + "204": { + "description": "속성 삭제 완료" + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/refresh-note-ordering/{parentNoteId}": { + "parameters": [ + { + "name": "parentNoteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/EntityId" + } + } + ], + "post": { + "description": "가지의 notePosition은 연결된 클라이언트에 자동으로 전달되지 않습니다. 변경한 순서를 즉시 반영하려면 notePosition을 설정한 뒤 이 기능을 호출하세요. 순서가 바뀐 가지의 parentNoteId를 전달해야 합니다.", + "operationId": "postRefreshNoteOrdering", + "responses": { + "204": { + "description": "연결된 모든 클라이언트에서 노트 순서를 비동기로 갱신합니다." + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/inbox/{date}": { + "get": { + "description": "새 노트를 넣을 수집함 노트를 반환합니다. 날짜 사용 여부는 수집함이 #inbox 라벨로 지정된 고정 노트인지 일지의 날짜별 노트인지에 따라 달라집니다.", + "operationId": "getInboxNote", + "parameters": [ + { + "name": "date", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "date" + }, + "example": "2022-02-22" + } + ], + "responses": { + "200": { + "description": "수집함 노트", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Note" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/calendar/days/{date}": { + "get": { + "description": "지정한 날짜의 일별 노트를 반환합니다. 없으면 새로 만듭니다.", + "operationId": "getDayNote", + "parameters": [ + { + "name": "date", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "date" + }, + "example": "2022-02-22" + } + ], + "responses": { + "200": { + "description": "일별 노트", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Note" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/calendar/weeks/{date}": { + "get": { + "description": "지정한 날짜의 주별 노트를 반환합니다. 없으면 새로 만듭니다.", + "operationId": "getWeekFirstDayNote", + "parameters": [ + { + "name": "date", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "date" + }, + "example": "2022-02-22" + } + ], + "responses": { + "200": { + "description": "주별 노트", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Note" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/calendar/months/{month}": { + "get": { + "description": "지정한 날짜의 주별 노트를 반환합니다. 없으면 새로 만듭니다.", + "operationId": "getMonthNote", + "parameters": [ + { + "name": "month", + "in": "path", + "required": true, + "schema": { + "type": "string", + "pattern": "[0-9]{4}-[0-9]{2}" + }, + "example": "2022-02" + } + ], + "responses": { + "200": { + "description": "월별 노트", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Note" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/calendar/years/{year}": { + "get": { + "description": "지정한 날짜의 주별 노트를 반환합니다. 없으면 새로 만듭니다.", + "operationId": "getYearNote", + "parameters": [ + { + "name": "year", + "in": "path", + "required": true, + "schema": { + "type": "string", + "pattern": "[0-9]{4}-[0-9]{2}" + }, + "example": "2022-02" + } + ], + "responses": { + "200": { + "description": "연도별 노트", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Note" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/auth/login": { + "post": { + "description": "비밀번호로 ETAPI 토큰을 발급받습니다. 이후 ETAPI 호출에 사용합니다.", + "operationId": "login", + "security": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "properties": { + "password": { + "type": "string", + "description": "Trilium 서버 로그인이나 노트 보호에 사용하는 사용자 비밀번호" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "인증 토큰", + "content": { + "application/json; charset=utf-8": { + "schema": { + "properties": { + "authToken": { + "type": "string", + "example": "Bc4bFn0Ffiok_4NpbVCDnFz7B2WU+pdhW8B5Ne3DiR5wXrEyqdjgRIsk=" + } + } + } + } + } + }, + "429": { + "description": "짧은 시간에 요청이 너무 많아 클라이언트 IP가 차단됐습니다. 인증 실패가 원인일 수 있습니다. 잠시 후 다시 시도하세요." + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/auth/logout": { + "post": { + "description": "ETAPI 토큰을 삭제하거나 비활성화하여 로그아웃합니다.", + "operationId": "logout", + "responses": { + "204": { + "description": "로그아웃 성공" + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/app-info": { + "get": { + "description": "실행 중인 Trilium 인스턴스 정보를 반환합니다.", + "operationId": "getAppInfo", + "responses": { + "200": { + "description": "앱 정보", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/AppInfo" + } + } + } + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/backup/{backupName}": { + "parameters": [ + { + "name": "backupName", + "in": "path", + "required": true, + "description": "예를 들어 backupName이 \"now\"이면 \"backup-now.db\" 파일에 백업합니다.", + "schema": { + "$ref": "#/components/schemas/StringId" + } + } + ], + "put": { + "description": "지정한 이름으로 데이터베이스를 백업합니다.", + "operationId": "createBackup", + "responses": { + "204": { + "description": "백업 생성 완료" + }, + "default": { + "description": "예기치 않은 오류", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "EtapiTokenAuth": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + }, + "EtapiBasicAuth": { + "type": "http", + "scheme": "basic", + "description": "HTTP 기본 인증에서 사용자 이름은 임의의 문자열을 사용하며 검사하지 않습니다. 예: trilium. 비밀번호 자리에는 발급받은 ETAPI 토큰을 넣습니다. Trilium 로그인 비밀번호는 사용할 수 없습니다. 설정의 ETAPI 항목에서 생성한 토큰을 사용하세요." + } + }, + "schemas": { + "CreateNoteDef": { + "type": "object", + "required": [ + "parentNoteId", + "title", + "type", + "content" + ], + "properties": { + "parentNoteId": { + "$ref": "#/components/schemas/EntityId", + "description": "트리에서 상위 노트의 ID" + }, + "title": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "text", + "code", + "file", + "image", + "search", + "book", + "relationMap", + "render" + ] + }, + "mime": { + "type": "string", + "description": "노트 유형이 code 또는 file 또는 image일 때만 지정하면 됩니다.", + "example": "application/json" + }, + "content": { + "type": "string" + }, + "notePosition": { + "type": "integer", + "description": "상위 노트 안에서의 순서입니다. 일반적인 순서는 10 단위로 증가합니다. 맨 앞에 넣으려면 5를 사용할 수 있고 두 번째는 15를 사용할 수 있습니다. 맨 뒤에 넣으려면 1000000처럼 큰 값을 사용하세요." + }, + "prefix": { + "type": "string", + "description": "prefix는 노트가 배치된 가지마다 따로 붙이는 제목 접두사입니다. 같은 노트를 두 곳에 배치하고 한쪽에서만 제목을 조금 다르게 표시하려면 접두사를 사용하세요." + }, + "isExpanded": { + "type": "boolean", + "description": "노트를 폴더처럼 펼쳐 표시하려면 true로 설정합니다." + }, + "noteId": { + "$ref": "#/components/schemas/EntityId", + "description": "특정 noteId를 강제로 지정하려는 경우에만 입력하세요." + }, + "branchId": { + "$ref": "#/components/schemas/EntityId", + "description": "특정 branchId를 강제로 지정하려는 경우에만 입력하세요." + }, + "dateCreated": { + "$ref": "#/components/schemas/LocalDateTime", + "description": "노트 생성 시각의 현지 타임스탬프입니다. 현재 시간대의 현재 시각이라는 기본값을 바꿀 때만 지정하세요." + }, + "utcDateCreated": { + "$ref": "#/components/schemas/UtcDateTime", + "description": "노트 생성 시각의 UTC 타임스탬프입니다. 현재 시각이라는 기본값을 바꿀 때만 지정하세요." + } + } + }, + "Note": { + "type": "object", + "properties": { + "noteId": { + "$ref": "#/components/schemas/EntityId", + "readOnly": true + }, + "title": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "text", + "code", + "render", + "file", + "image", + "search", + "relationMap", + "book", + "noteMap", + "mermaid", + "webView", + "shortcut", + "doc", + "contentWidget", + "launcher" + ] + }, + "mime": { + "type": "string" + }, + "isProtected": { + "type": "boolean", + "readOnly": true + }, + "blobId": { + "type": "string", + "description": "본문 해시 역할을 하는 데이터 객체의 ID" + }, + "attributes": { + "$ref": "#/components/schemas/AttributeList", + "readOnly": true + }, + "parentNoteIds": { + "$ref": "#/components/schemas/EntityIdList", + "readOnly": true + }, + "childNoteIds": { + "$ref": "#/components/schemas/EntityIdList", + "readOnly": true + }, + "parentBranchIds": { + "$ref": "#/components/schemas/EntityIdList", + "readOnly": true + }, + "childBranchIds": { + "$ref": "#/components/schemas/EntityIdList", + "readOnly": true + }, + "dateCreated": { + "$ref": "#/components/schemas/LocalDateTime" + }, + "dateModified": { + "$ref": "#/components/schemas/LocalDateTime", + "readOnly": true + }, + "utcDateCreated": { + "$ref": "#/components/schemas/UtcDateTime" + }, + "utcDateModified": { + "$ref": "#/components/schemas/UtcDateTime", + "readOnly": true + } + } + }, + "Branch": { + "type": "object", + "description": "가지는 노트를 트리에 배치하며 상위 노트와 하위 노트의 관계를 나타냅니다.", + "properties": { + "branchId": { + "$ref": "#/components/schemas/EntityId" + }, + "noteId": { + "$ref": "#/components/schemas/EntityId", + "readOnly": true, + "description": "하위 노트 식별자" + }, + "parentNoteId": { + "$ref": "#/components/schemas/EntityId", + "readOnly": true, + "description": "상위 노트 식별자" + }, + "prefix": { + "type": "string" + }, + "notePosition": { + "type": "integer", + "format": "int32" + }, + "isExpanded": { + "type": "boolean" + }, + "utcDateModified": { + "$ref": "#/components/schemas/UtcDateTime", + "readOnly": true + } + } + }, + "NoteWithBranch": { + "type": "object", + "properties": { + "note": { + "$ref": "#/components/schemas/Note" + }, + "branch": { + "$ref": "#/components/schemas/Branch" + } + } + }, + "Attachment": { + "type": "object", + "description": "첨부 파일은 노트에 속하며 제목과 내용을 가집니다.", + "properties": { + "attachmentId": { + "$ref": "#/components/schemas/EntityId", + "readOnly": true + }, + "ownerId": { + "$ref": "#/components/schemas/EntityId", + "description": "첨부 파일 소유자의 식별자. noteId 또는 revisionId입니다." + }, + "role": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "title": { + "type": "string" + }, + "position": { + "type": "integer", + "format": "int32" + }, + "blobId": { + "type": "string", + "description": "본문 해시 역할을 하는 데이터 객체의 ID" + }, + "dateModified": { + "$ref": "#/components/schemas/LocalDateTime", + "readOnly": true + }, + "utcDateModified": { + "$ref": "#/components/schemas/UtcDateTime", + "readOnly": true + }, + "utcDateScheduledForErasureSince": { + "$ref": "#/components/schemas/UtcDateTime", + "readOnly": true + }, + "contentLength": { + "type": "integer", + "format": "int32" + } + } + }, + "CreateAttachment": { + "type": "object", + "properties": { + "ownerId": { + "$ref": "#/components/schemas/EntityId", + "description": "첨부 파일 소유자의 식별자. noteId 또는 revisionId입니다." + }, + "role": { + "type": "string" + }, + "mime": { + "type": "string" + }, + "title": { + "type": "string" + }, + "content": { + "type": "string" + }, + "position": { + "type": "integer", + "format": "int32" + } + } + }, + "Attribute": { + "type": "object", + "description": "속성은 노트에 연결된 키와 값의 쌍이며 라벨과 관계로 나뉩니다.", + "properties": { + "attributeId": { + "$ref": "#/components/schemas/EntityId" + }, + "noteId": { + "$ref": "#/components/schemas/EntityId", + "readOnly": true, + "description": "하위 노트 식별자" + }, + "type": { + "type": "string", + "enum": [ + "label", + "relation" + ] + }, + "name": { + "type": "string", + "pattern": "^[^\\s]+", + "example": "shareCss" + }, + "value": { + "type": "string" + }, + "position": { + "type": "integer", + "format": "int32" + }, + "isInheritable": { + "type": "boolean" + }, + "utcDateModified": { + "$ref": "#/components/schemas/UtcDateTime", + "readOnly": true + } + } + }, + "AttributeList": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Attribute" + } + }, + "SearchResponse": { + "type": "object", + "required": [ + "results" + ], + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Note" + } + }, + "debugInfo": { + "type": "object", + "description": "&debug=true로 활성화한 검색어 구문 분석 디버깅 정보" + } + } + }, + "EntityId": { + "type": "string", + "pattern": "[a-zA-Z0-9_]{4,32}", + "example": "evnnmvHTCgIn" + }, + "StringId": { + "type": "string", + "pattern": "[a-zA-Z0-9_]{1,32}", + "example": "my_ID" + }, + "EntityIdList": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EntityId" + } + }, + "LocalDateTime": { + "type": "string", + "pattern": "[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}[\\+\\-][0-9]{4}", + "example": "2021-12-31 20:18:11.930+0100" + }, + "UtcDateTime": { + "type": "string", + "pattern": "[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z", + "example": "2021-12-31 19:18:11.930000+00:00" + }, + "AppInfo": { + "type": "object", + "properties": { + "appVersion": { + "type": "string", + "description": "Trilium 버전", + "example": "0.50.2" + }, + "dbVersion": { + "type": "integer", + "format": "int32", + "description": "데이터베이스 버전", + "example": 194 + }, + "syncVersion": { + "type": "integer", + "format": "int32", + "description": "동기화 프로토콜 버전", + "example": 25 + }, + "buildDate": { + "type": "string", + "format": "date-time", + "description": "빌드 날짜", + "example": "2022-02-09 22:52:36+01:00" + }, + "buildRevision": { + "type": "string", + "description": "빌드에 사용한 Git 커밋", + "example": "23daaa2387a0655685377f0a541d154aeec2aae8" + }, + "dataDirectory": { + "type": "string", + "description": "Trilium 파일을 저장하는 데이터 디렉토리", + "example": "/home/user/data" + }, + "clipperProtocolVersion": { + "type": "string", + "description": "지원하는 Trilium 웹 클리퍼 프로토콜 버전", + "example": 1 + }, + "utcDateTime": { + "type": "string", + "description": "현재 UTC 날짜와 시각", + "example": "2022-03-07 21:54:25.277000+00:00" + } + } + }, + "Error": { + "type": "object", + "required": [ + "status", + "code", + "message" + ], + "properties": { + "status": { + "type": "integer", + "format": "int32", + "description": "HTTP 응답에 사용한 것과 같은 HTTP 상태 코드", + "example": 400 + }, + "code": { + "type": "string", + "description": "고정된 문자열 상수", + "example": "NOTE_IS_PROTECTED" + }, + "message": { + "type": "string", + "description": "사람이 읽을 수 있는 오류 설명. 추가 정보가 포함될 수 있습니다.", + "example": "노트 'evnnmvHTCgIn'은 보호되어 있어 ETAPI로 변경할 수 없습니다." + } + } + } + } + } +} \ No newline at end of file diff --git a/release/app/assets/doc_notes/en/api-ko/fnote.html b/release/app/assets/doc_notes/en/api-ko/fnote.html new file mode 100644 index 0000000..8ea0e63 --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/fnote.html @@ -0,0 +1,184 @@ +프런트엔드 노트 객체 FNote

프런트엔드 노트 객체 FNote

연결된 공식 문서의 한국어 사본입니다. 함수 이름과 코드 문법은 원문을 유지했습니다. 외부 문서는 운영 버전과 다를 수 있으므로 지원 여부를 확인하세요. 공식 원문 보기

클래스 FNote

노트는 Trilium의 핵심 데이터 단위입니다.

+
목차

생성자

속성

접근자

메서드

생성자

속성

attachments: null | FAttachment[]
attributes: string[]
blobId: string
children: string[]
childToBranch: Record<string, string>
highlightedTokens?: string[]
isProtected: boolean
mime: string

콘텐츠 유형. 예: "application/json"

+
noteId: string
parents: string[]
parentToBranch: Record<string, string>
searchResultsLoaded?: boolean
targetRelations: string[]
title: string
type: NoteType

접근자

메서드

  • 매개변수

    • childNoteId: string
    • branchId: string
    • sort: boolean = true

    반환값 void

  • 매개변수

    • parentNoteId: string
    • branchId: string
    • sort: boolean = true

    반환값 void

  • 이 FNote를 프런트엔드 또는 백엔드 스크립트로 실행합니다.

    +

    반환값 Promise<any>

    스크립트 실행이 끝나면 완료되는 Promise입니다. 프런트엔드 노트라면 스크립트의 반환값도 포함합니다.

    +

    실행할 수 없는 노트 유형이나 MIME 유형이면 Error가 발생합니다.

    +
  • 이 노트에 도달하는 모든 노트 경로를 반환합니다. 검색 노트가 포함된 경로는 순환이 생길 수 있어 제외합니다.

    +

    반환값 string[][]

    노트 경로 배열입니다. 각 경로는 해당 경로를 이루는 노트 ID 배열로 표현합니다.

    +
  • 매개변수

    • type: AttributeType

      속성 유형. 예: label 또는 relation

      +
    • name: string

      속성 이름

      +

    반환값 null | string

    지정한 유형과 이름의 속성값입니다. 해당 속성이 없으면 null입니다.

    +
  • 가능한 노트 경로 중에서 다음 조건에 맞는 경로를 반환합니다: "가장 적절한 경로"

    +

    매개변수

    • OptionalhoistedNoteId: string = "root"

    반환값 string[]

    해당 노트 경로를 이루는 노트 ID 배열

    +
  • 가능한 노트 경로 중에서 다음 조건에 맞는 경로를 반환합니다: "가장 적절한 경로"

    +

    매개변수

    • OptionalhoistedNoteId: string = "root"

    반환값 string

    직렬화한 노트 경로. 예: root/a1h315/js725h

    +
  • 매개변수

    • name: string

      라벨 이름

      +

    반환값 null | string

    라벨이 있으면 라벨 값을 반환하고 없으면 null을 반환합니다.

    +
  • 매개변수

    • type: AttributeType

      속성 유형. 예: label 또는 relation

      +
    • name: string

      속성 이름

      +

    반환값 undefined | FAttribute

    지정한 유형과 이름의 속성입니다. 여러 개면 첫 번째를 반환합니다. 해당 노트에 이런 속성이 없으면 null입니다.

    +
  • 매개변수

    • type: AttributeType

      속성 유형. 예: label 또는 relation

      +
    • name: string

      속성 이름

      +

    반환값 null | string

    지정한 유형과 이름의 속성값입니다. 해당 속성이 없으면 null입니다.

    +
  • 매개변수

    • name: string

      라벨 이름

      +

    반환값 null | string

    라벨이 있으면 라벨 값을 반환하고 없으면 null을 반환합니다.

    +
  • 매개변수

    • name: string

      관계 이름

      +

    반환값 null | string

    관계가 있으면 관계 값을 반환하고 없으면 null을 반환합니다.

    +
  • 매개변수

    • name: string

    반환값 Promise<null | FNote>

    관계의 대상 노트입니다. 대상이 비어 있거나 노트를 찾지 못하면 null입니다.

    +
  • 매개변수

    • name: string

      관계 이름

      +

    반환값 null | string

    관계가 있으면 관계 값을 반환하고 없으면 null을 반환합니다.

    +
  • 반환값 null | "frontend" | "backend"

    JavaScript 실행 환경. 가능한 값: "frontend" or "backend"

    +
  • 매개변수

    • ancestorNoteId: string
    • followTemplates: boolean = false
    • visitedNoteIds: null | Set<string> = null

    반환값 boolean

  • 매개변수

    • type: AttributeType

      속성 유형. 예: label 또는 relation

      +
    • name: string

      속성 이름

      +

    반환값 boolean

    상속받은 속성을 포함해 지정한 유형과 이름의 속성이 있으면 true입니다.

    +
  • 매개변수

    • name: string

      라벨 이름

      +

    반환값 boolean

    상속받은 라벨을 포함해 해당 라벨이 있으면 true입니다.

    +
  • 매개변수

    • type: AttributeType

      속성 유형. 예: label 또는 relation

      +
    • name: string

      속성 이름

      +

    반환값 boolean

    상속받은 속성을 포함해 지정한 유형과 이름의 속성이 있으면 true입니다.

    +
  • 매개변수

    • name: string

      라벨 이름

      +

    반환값 boolean

    상속받은 라벨을 제외하고 해당 라벨이 있으면 true입니다.

    +
  • 매개변수

    • name: string

      관계 이름

      +

    반환값 boolean

    상속받은 관계를 제외하고 해당 관계가 있으면 true입니다.

    +
  • 매개변수

    • name: string

      관계 이름

      +

    반환값 boolean

    상속받은 관계를 포함해 해당 관계가 있으면 true입니다.

    +
  • 반환값 boolean

    숨겨지지 않은 경로가 없으면 true입니다. 즉 보이는 트리에 노트 복제본이 없다는 뜻입니다.

    +
  • 매개변수

    • name: string

      라벨 이름

      +

    반환값 boolean

    상속받은 라벨을 포함해 라벨이 존재하면서 다음 값이 아니면 true입니다: "false" value.

    +
\ No newline at end of file diff --git a/release/app/assets/doc_notes/en/api-ko/frontend.html b/release/app/assets/doc_notes/en/api-ko/frontend.html new file mode 100644 index 0000000..3341d7c --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/frontend.html @@ -0,0 +1,167 @@ +프런트엔드 스크립트 API

프런트엔드 스크립트 API

연결된 공식 문서의 한국어 사본입니다. 함수 이름과 코드 문법은 원문을 유지했습니다. 외부 문서는 운영 버전과 다를 수 있으므로 지원 여부를 확인하세요. 공식 원문 보기

인터페이스 Api

interface Api {
    $container: null | JQuery<HTMLElement>;
    BasicWidget: typeof BasicWidget;
    bindGlobalShortcut: (
        keyboardShortcut: string,
        handler: null | Handler,
        namespace?: null | string,
    ) => void;
    createLink: (
        notePath: undefined | string,
        options?: CreateLinkOptions,
    ) => Promise<JQuery<HTMLElement>>;
    createNoteLink: (
        notePath: undefined | string,
        options?: CreateLinkOptions,
    ) => Promise<JQuery<HTMLElement>>;
    currentNote: FNote;
    dayjs: __module;
    formatDateISO: (date: Date) => string;
    formatNoteSize: (size: number) => string;
    formatSize: (size: number) => string;
    getDayNote: (date: string) => Promise<null | FNote>;
    getMonthNote: (month: string) => Promise<null | FNote>;
    getQuarterNote: (quarter: string) => Promise<null | FNote>;
    getTodayNote: () => Promise<null | FNote>;
    getWeekFirstDayNote: (date: string) => Promise<null | FNote>;
    getWeekNote: (week: string) => Promise<null | FNote>;
    getYearNote: (year: string) => Promise<null | FNote>;
    logMessages: Record<string, string[]>;
    logSpacedUpdates: Record<string, default>;
    NoteContextAwareWidget: typeof NoteContextAwareWidget;
    originEntity: unknown;
    parseDate: (str: string) => Date;
    protectNote: (
        noteId: string,
        protect: boolean,
        includingSubtree: boolean,
    ) => Promise<void>;
    protectSubTree: (
        noteId: string,
        protect: boolean,
        includingSubtree: boolean,
    ) => Promise<void>;
    randomString: (len: number) => string;
    RightPanelWidget: typeof RightPanelWidget;
    setupElementTooltip: ($el: JQuery<HTMLElement>) => void;
    showConfirmDialog: (message: string) => Promise<unknown>;
    showError: (message: string, delay?: number) => void;
    showInfoDialog: (message: string) => Promise<unknown>;
    showMessage: (message: string, delay?: number) => void;
    showPromptDialog: (props: PromptDialogOptions) => Promise<null | string>;
    startNote: FNote;
    triggerCommand: <K extends keyof CommandMappings>(
        name: K,
        _data?: CommandMappings[K],
    ) => undefined | null | Promise<unknown>;
    triggerEvent: <K extends EventNames>(
        name: K,
        data: EventData<K>,
    ) => undefined | null | Promise<unknown>;
    waitUntilSynced: () => Promise<void>;
    activateNewNote(notePath: string): Promise<void>;
    activateNote(notePath: string): Promise<void>;
    addButtonToToolbar(opts: AddToToolbarOpts): void;
    addTextToActiveContextEditor(text: string): void;
    getActiveContext(): NoteContext;
    getActiveContextCodeEditor(): Promise<unknown>;
    getActiveContextNote(): FNote;
    getActiveContextNotePath(): null | string;
    getActiveContextTextEditor(): Promise<unknown>;
    getActiveMainContext(): NoteContext;
    getActiveNoteDetailWidget(): Promise<default>;
    getComponentByEl(el: HTMLElement): default;
    getInstanceName(): string;
    getMainNoteContexts(): NoteContext[];
    getNote(noteId: string): Promise<null | FNote>;
    getNoteContexts(): NoteContext[];
    getNotes(
        noteIds: string[],
        silentNotFoundError?: boolean,
    ): Promise<FNote[]>;
    log(message: string): void;
    openSplitWithNote(notePath: string, activate: boolean): Promise<void>;
    openTabWithNote(notePath: string, activate: boolean): Promise<void>;
    refreshIncludedNote(includedNoteId: string): void;
    reloadNotes(noteIds: string[]): Promise<void>;
    runAsyncOnBackendWithManualTransactionHandling(
        func: Func,
        params: unknown[],
    ): unknown;
    runOnBackend(func: Func, params: unknown[]): unknown;
    searchForNote(searchString: string): Promise<null | FNote>;
    searchForNotes(searchString: string): Promise<FNote[]>;
    setHoistedNoteId(noteId: string): void;
}
목차

속성

$container: null | JQuery<HTMLElement>

스크립트가 렌더링한 전체 내용을 담는 영역

+
BasicWidget: typeof BasicWidget
bindGlobalShortcut: (
    keyboardShortcut: string,
    handler: null | Handler,
    namespace?: null | string,
) => void

형식 선언

    • (
          keyboardShortcut: string,
          handler: null | Handler,
          namespace?: null | string,
      ): void
    • 매개변수

      • keyboardShortcut: string

        예: "ctrl+shift+a"

        +
      • handler: null | Handler
      • namespace: null | string = null

        같은 바인딩을 여러 번 호출할 수 있다면 처리 함수의 네임스페이스를 지정하세요. 같은 ID의 처리 함수가 있으면 새 함수로 교체합니다.

        +

      반환값 void

createLink: (
    notePath: undefined | string,
    options?: CreateLinkOptions,
) => Promise<JQuery<HTMLElement>>

지정한 노트를 가리키는 jQuery 링크 객체를 만듭니다.

+

형식 선언

    • (
          notePath: undefined | string,
          options?: CreateLinkOptions,
      ): Promise<JQuery<HTMLElement>>
    • 매개변수

      반환값 Promise<JQuery<HTMLElement>>

        +
      • 링크를 담은 jQuery 요소. 감싸는 요소: )
      • +
      +
createNoteLink: (
    notePath: undefined | string,
    options?: CreateLinkOptions,
) => Promise<JQuery<HTMLElement>>
    +
  • 대신 api.createLink()를 사용하세요.
  • +
+
currentNote: FNote

현재 실행 중인 소스 코드가 작성된 노트입니다.

+
dayjs: __module

날짜 처리를 위한 day.js 라이브러리입니다. 참고: https://day.js.org 라이브러리 사용 안내

+
formatDateISO: (date: Date) => string

형식 선언

    • (date: Date): string
    • 이 함수는 현지 시각을 반환합니다.

      +

      매개변수

      • date: Date

      반환값 string

YYYY-MM-DD 형식의 날짜

+
formatNoteSize: (size: number) => string

형식 선언

    • (size: number): string
    • 매개변수

      • size: number

        바이트 단위

        +

      반환값 string

      서식을 적용한 문자열

      +
    +
  • api.formatSize()를 사용하세요.
  • +
+
formatSize: (size: number) => string

형식 선언

    • (size: number): string
    • 매개변수

      • size: number

        바이트 단위

        +

      반환값 string

      서식을 적용한 문자열

      +
getDayNote: (date: string) => Promise<null | FNote>

지정한 날짜의 일별 노트를 반환합니다. 없으면 자동으로 만듭니다.

+

형식 선언

    • (date: string): Promise<null | FNote>
    • 매개변수

      • date: string

        예: "2019-04-29"

        +

      반환값 Promise<null | FNote>

getMonthNote: (month: string) => Promise<null | FNote>

월별 노트를 반환합니다. 없으면 자동으로 만듭니다.

+

형식 선언

    • (month: string): Promise<null | FNote>
    • 매개변수

      • month: string

        예: "2019-04"

        +

      반환값 Promise<null | FNote>

getQuarterNote: (quarter: string) => Promise<null | FNote>

지정한 날짜의 분기별 노트를 반환합니다. 없으면 자동으로 만듭니다.

+
getTodayNote: () => Promise<null | FNote>

오늘의 일별 노트를 반환합니다. 없으면 자동으로 만듭니다.

+
getWeekFirstDayNote: (date: string) => Promise<null | FNote>

지정한 날짜가 속한 주의 첫날에 해당하는 일별 노트를 반환합니다. 없으면 자동으로 만듭니다.

+

형식 선언

    • (date: string): Promise<null | FNote>
    • 매개변수

      • date: string

        예: "2019-04-29"

        +

      반환값 Promise<null | FNote>

getWeekNote: (week: string) => Promise<null | FNote>

지정한 날짜의 주별 노트를 반환합니다. 없으면 자동으로 만듭니다.

+
getYearNote: (year: string) => Promise<null | FNote>

연도별 노트를 반환합니다. 없으면 자동으로 만듭니다.

+

형식 선언

    • (year: string): Promise<null | FNote>
    • 매개변수

      • year: string

        예: "2019"

        +

      반환값 Promise<null | FNote>

logMessages: Record<string, string[]>
logSpacedUpdates: Record<string, default>
NoteContextAwareWidget: typeof NoteContextAwareWidget
originEntity: unknown

이 실행을 시작하게 한 이벤트의 엔터티

+
parseDate: (str: string) => Date
protectNote: (
    noteId: string,
    protect: boolean,
    includingSubtree: boolean,
) => Promise<void>

형식 선언

    • (noteId: string, protect: boolean, includingSubtree: boolean): Promise<void>
    • 매개변수

      • noteId: string
      • protect: boolean

        노트를 보호하려면 true를 사용하고 보호를 해제하려면 false를 사용합니다.

        +
      • includingSubtree: boolean

      반환값 Promise<void>

protectSubTree: (
    noteId: string,
    protect: boolean,
    includingSubtree: boolean,
) => Promise<void>

형식 선언

    • (noteId: string, protect: boolean, includingSubtree: boolean): Promise<void>
    • 매개변수

      • noteId: string
      • protect: boolean

        하위 트리를 보호하려면 true를 사용하고 보호를 해제하려면 false를 사용합니다.

        +
      • includingSubtree: boolean

      반환값 Promise<void>

randomString: (len: number) => string

지정한 길이의 임의 문자열을 반환합니다. 암호학적으로 안전한 난수를 만드는 함수가 아닙니다.

+

형식 선언

    • (len: number): string
    • 매개변수

      • len: number

      반환값 string

      임의 문자열

      +
RightPanelWidget: typeof RightPanelWidget
setupElementTooltip: ($el: JQuery<HTMLElement>) => void

형식 선언

    • ($el: JQuery<HTMLElement>): void
    • 매개변수

      • $el: JQuery<HTMLElement>

        도움말을 표시할 jQuery 객체

        +

      반환값 void

showConfirmDialog: (message: string) => Promise<unknown>

사용자에게 확인 대화상자를 표시합니다.

+

형식 선언

    • (message: string): Promise<unknown>
    • 매개변수

      • message: string

      반환값 Promise<unknown>

      사용자가 확인하면 true로 완료되는 Promise

      +
showError: (message: string, delay?: number) => void

사용자에게 오류 알림을 잠깐 표시합니다.

+
showInfoDialog: (message: string) => Promise<unknown>

사용자에게 정보 대화상자를 표시합니다.

+
showMessage: (message: string, delay?: number) => void

사용자에게 정보 알림을 잠깐 표시합니다.

+
showPromptDialog: (props: PromptDialogOptions) => Promise<null | string>

사용자에게 입력 대화상자를 표시합니다.

+

형식 선언

startNote: FNote

현재 스크립트 실행이 시작된 노트입니다. 이벤트의 진입점에 해당합니다.

+
triggerCommand: <K extends keyof CommandMappings>(
    name: K,
    _data?: CommandMappings[K],
) => undefined | null | Promise<unknown>

명령을 실행합니다. 매우 낮은 수준의 API이므로 가능하면 다른 방법을 사용하세요.

+
triggerEvent: <K extends EventNames>(
    name: K,
    data: EventData<K>,
) => undefined | null | Promise<unknown>

이벤트를 발생시킵니다. 매우 낮은 수준의 API이므로 가능하면 다른 방법을 사용하세요.

+
waitUntilSynced: () => Promise<void>

Trilium은 백엔드와 프런트엔드로 나뉘어 실행됩니다. 스크립트가 백엔드에서 변경한 내용은 프런트엔드에 비동기로 동기화됩니다.

+

이 메서드는 다음 과정이 모두 끝나면 완료되는 Promise를 반환합니다. 백엔드에서> 프런트엔드로의 동기화입니다. 새 노트를 만들었다면 프런트엔드에 동기화될 때까지 기다린 뒤 활성화하는 데 사용할 수 있습니다.

+

메서드

  • 새로 만든 노트를 활성화합니다. this.activateNote()와 달리 프런트엔드 동기화 완료까지 확인합니다.

    +

    매개변수

    • notePath: string

      (또는 noteId)

      +

    반환값 Promise<void>

  • 실행 도구 모음에 새 실행 도구를 추가합니다. 같은 ID가 있으면 변경합니다.

    +

    매개변수

    반환값 void

    이제 왼쪽 위 메뉴에서 실행 도구를 만들거나 변경할 수 있습니다. 메뉴 경로:> 실행 도구 모음 설정. 특수한 용도에는 백엔드 API의 createOrUpdateLauncher()도 사용할 수 있습니다.

    +
  • 편집기의 커서 위치에 지정한 글을 추가합니다.

    +

    매개변수

    • text: string

      일반 텍스트만 사용할 수 있습니다. HTML은 지원하지 않습니다.

      +

    반환값 void

  • 노트 상세 화면을 담당하는 위젯에 접근합니다. 사용할 수 있는 메서드의 예: getWidgetType() 및 getTypeWidget() 실제 위젯 유형의 구현체에 접근하는 데 사용합니다.

    +

    반환값 Promise<default>

  • 인스턴스 이름은 개별 Trilium 실행 환경을 구분합니다. 특정 인스턴스에서만 작업을 실행해야 하는 스크립트에 유용합니다.

    +

    반환값 string

  • 노트 목록을 반환합니다. 캐시에 없는 노트는 불러옵니다.

    +

    createLink() 등으로 노트를 하나씩 가져오는 대신 여러 노트를 한꺼번에 캐시에 채울 때 자주 사용합니다.

    +

    매개변수

    • noteIds: string[]
    • OptionalsilentNotFoundError: boolean

      노트를 찾지 못해도 오류를 보고하지 않음

      +

    반환값 Promise<FNote[]>

  • 새 분할 화면에서 노트를 엽니다.

    +

    매개변수

    • notePath: string

      (또는 noteId)

      +
    • activate: boolean

      새 분할 화면을 활성화하려면 true를 사용하고 현재 화면에 머무르려면 false를 사용합니다.

      +

    반환값 Promise<void>

  • 새 탭에서 노트를 엽니다.

    +

    매개변수

    • notePath: string

      (또는 noteId)

      +
    • activate: boolean

      새 탭을 활성화하려면 true를 사용하고 현재 탭에 머무르려면 false를 사용합니다.

      +

    반환값 Promise<void>

  • 매개변수로 지정한 노트를 포함하는 현재 열린 노트를 모두 새로 고칩니다.

    +

    매개변수

    • includedNoteId: string

      포함된 노트의 noteId

      +

    반환값 void

  • 백엔드의 내용을 바탕으로 프런트엔드 노트 트리 캐시를 갱신합니다.

    +

    매개변수

    • noteIds: string[]

    반환값 Promise<void>

  • 지정한 익명 함수를 백엔드에서 실행합니다. 내부적으로 함수를 문자열로 직렬화한 뒤 AJAX로 전송합니다. 비동기 함수가 필요한 고급 용도에 사용합니다. 요청 단위의 자동 트랜잭션 관리는 적용되지 않으므로 api.transactional()로 트랜잭션을 직접 지정해야 합니다.

    +

    동기 함수라면 api.runOnBackend()를 사용하세요.

    +

    매개변수

    • func: Func

      백엔드에서 실행할 동기 함수

      +
    • params: unknown[]

      백엔드로 보낼 익명 함수의 매개변수 목록

      +

    반환값 unknown

    백엔드에서 실행한 함수의 반환값

    +
  • 지정한 익명 함수를 백엔드에서 실행합니다. 내부적으로 함수를 문자열로 직렬화한 뒤 AJAX로 전송합니다. 트랜잭션 관리가 올바르게 작동하려면 동기 함수를 전달해야 합니다. 트랜잭션을 직접 관리할 수 있다면 api.runAsyncOnBackendWithManualTransactionHandling()을 사용할 수 있습니다.

    +

    매개변수

    • func: Func

      백엔드에서 실행할 동기 함수

      +
    • params: unknown[]

      백엔드로 보낼 익명 함수의 매개변수 목록

      +

    반환값 unknown

    백엔드에서 실행한 함수의 반환값

    +
\ No newline at end of file diff --git a/release/app/assets/doc_notes/en/api-ko/internal.json b/release/app/assets/doc_notes/en/api-ko/internal.json new file mode 100644 index 0000000..4cddd28 --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/internal.json @@ -0,0 +1,2712 @@ +{ + "openapi": "3.1.1", + "info": { + "title": "Trilium Notes 동기화 서버 API", + "version": "0.94.0", + "description": "Trilium Notes와 TriliumNext Notes에서 사용하는 내부 동기화 서버 API입니다.\n\n공식 지원 외부 API는 [ETAPI 안내](https://triliumnext.github.io/Docs/Wiki/etapi.html)를 참고하세요.\n\n이 문서에는 아직 모든 경로가 나와 있지 않습니다. 전체 목록은 [경로 제어 코드](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/routes.ts)를 확인하세요.", + "contact": { + "name": "TriliumNext 문제 신고", + "url": "https://github.com/TriliumNext/Notes/issues" + }, + "license": { + "name": "GNU Free Documentation License 1.3 (or later)", + "url": "https://www.gnu.org/licenses/fdl-1.3" + } + }, + "paths": { + "/api/setup/sync-seed": { + "get": { + "tags": [ + "auth" + ], + "summary": "documentSecret 값 동기화", + "description": "로그인의 첫 단계입니다.", + "operationId": "setup-sync-seed", + "responses": { + "200": { + "description": "작업 성공", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "syncVersion": { + "type": "integer", + "example": 34 + }, + "options": { + "type": "object", + "properties": { + "documentSecret": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "security": [ + { + "user-password": [] + } + ] + } + }, + "/api/anthropic/models": { + "post": { + "summary": "사용 가능한 Anthropic 모델 조회", + "operationId": "anthropic-list-models", + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "baseUrl": { + "type": "string", + "description": "사용자 지정 Anthropic API 기본 주소. 생략할 수 있습니다." + } + } + } + } + } + }, + "responses": { + "200": { + "description": "사용 가능한 Anthropic 모델 목록", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "chatModels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + }, + "embeddingModels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "500": { + "description": "모델 목록 조회 오류" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/app-info": { + "get": { + "summary": "설치 정보 조회", + "operationId": "app-info", + "externalDocs": { + "description": "서버 구현체", + "url": "https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/app_info.ts" + }, + "responses": { + "200": { + "description": "설치 정보", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "appVersion": { + "type": "string", + "example": "0.91.6" + }, + "dbVersion": { + "type": "integer", + "example": 228 + }, + "nodeVersion": { + "type": "string", + "description": "process.version 값" + }, + "syncVersion": { + "type": "integer", + "example": 34 + }, + "buildDate": { + "type": "string", + "example": "2024-09-07T18:36:34Z" + }, + "buildRevision": { + "type": "string", + "example": "7c0d6930fa8f20d269dcfbcbc8f636a25f6bb9a7" + }, + "dataDirectory": { + "type": "string", + "example": "/var/lib/trilium" + }, + "clipperProtocolVersion": { + "type": "string", + "example": "1.0" + }, + "utcDateTime": { + "$ref": "#/components/schemas/UtcDateTime" + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ] + } + }, + "/api/branches/{branchId}": { + "delete": { + "summary": "가지 삭제 (노트 복제본)", + "operationId": "branches-delete", + "parameters": [ + { + "name": "branchId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/BranchId" + } + }, + { + "name": "taskId", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "작업 그룹 식별자" + }, + { + "name": "eraseNotes", + "in": "query", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "노트를 즉시 지울지 여부" + }, + { + "name": "last", + "in": "query", + "schema": { + "type": "boolean" + }, + "required": true, + "description": "이 작업 그룹의 마지막 요청인지 여부" + } + ], + "responses": { + "200": { + "description": "가지 삭제 성공", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "noteDeleted": { + "type": "boolean", + "description": "마지막 노트 복제본이 삭제됐는지 여부" + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "data" + ] + } + }, + "/api/llm/embeddings/similar/{noteId}": { + "get": { + "summary": "주어진 노트 ID를 기준으로 비슷한 노트 찾기", + "operationId": "embeddings-similar-by-note", + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "providerId", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "default": "openai", + "description": "임베딩 제공자 ID" + }, + { + "name": "modelId", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "default": "text-embedding-3-small", + "description": "임베딩 모델 ID" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "default": 10, + "description": "반환할 비슷한 노트의 최대 개수" + }, + { + "name": "threshold", + "in": "query", + "required": false, + "schema": { + "type": "number", + "format": "float" + }, + "default": 0.7, + "description": "유사도 기준값 (0.0~1.0)" + } + ], + "responses": { + "200": { + "description": "비슷한 노트 목록", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "similarNotes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "noteId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "similarity": { + "type": "number", + "format": "float" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "잘못된 요청 매개변수" + }, + "404": { + "description": "노트를 찾을 수 없음" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/search": { + "post": { + "summary": "입력한 글과 비슷한 노트 검색", + "operationId": "embeddings-search-by-text", + "parameters": [ + { + "name": "providerId", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "default": "openai", + "description": "임베딩 제공자 ID" + }, + { + "name": "modelId", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "default": "text-embedding-3-small", + "description": "임베딩 모델 ID" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer" + }, + "default": 10, + "description": "반환할 비슷한 노트의 최대 개수" + }, + { + "name": "threshold", + "in": "query", + "required": false, + "schema": { + "type": "number", + "format": "float" + }, + "default": 0.7, + "description": "유사도 기준값 (0.0~1.0)" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "text": { + "type": "string", + "description": "검색에 사용할 글" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "비슷한 노트 목록", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "similarNotes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "noteId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "similarity": { + "type": "number", + "format": "float" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "잘못된 요청 매개변수" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/providers": { + "get": { + "summary": "사용 가능한 임베딩 제공자 조회", + "operationId": "embeddings-get-providers", + "responses": { + "200": { + "description": "사용 가능한 임베딩 제공자 목록", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "providers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "isEnabled": { + "type": "boolean" + }, + "priority": { + "type": "integer" + }, + "config": { + "type": "object" + } + } + } + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/providers/{providerId}": { + "patch": { + "summary": "임베딩 제공자 설정 변경", + "operationId": "embeddings-update-provider", + "parameters": [ + { + "name": "providerId", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "변경할 제공자 ID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "제공자 사용 여부" + }, + "priority": { + "type": "integer", + "description": "우선순위. 숫자가 작을수록 우선합니다." + }, + "config": { + "type": "object", + "description": "제공자별 설정" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "제공자 변경 성공", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + } + } + } + } + } + }, + "400": { + "description": "잘못된 제공자 ID 또는 설정" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/reprocess": { + "post": { + "summary": "모든 노트의 임베딩 다시 처리", + "operationId": "embeddings-reprocess-all", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "다시 처리할 때 사용할 제공자 ID" + }, + "modelId": { + "type": "string", + "description": "다시 처리할 때 사용할 모델 ID" + }, + "forceReprocess": { + "type": "boolean", + "description": "임베딩이 이미 있는 노트도 다시 처리할지 여부" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "다시 처리 시작", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "jobId": { + "type": "string" + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "잘못된 제공자 ID 또는 설정" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/queue-status": { + "get": { + "summary": "임베딩 처리 대기열 상태 조회", + "operationId": "embeddings-queue-status", + "parameters": [ + { + "name": "jobId", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "특정 처리 작업의 상태를 조회할 작업 ID. 생략할 수 있습니다." + } + ], + "responses": { + "200": { + "description": "대기열 상태 정보", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "status": { + "type": "string", + "enum": [ + "idle", + "processing", + "paused" + ] + }, + "progress": { + "type": "number", + "format": "float", + "description": "진행률 (0~100)" + }, + "details": { + "type": "object" + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/stats": { + "get": { + "summary": "임베딩 통계 조회", + "operationId": "embeddings-stats", + "responses": { + "200": { + "description": "임베딩 통계", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "stats": { + "type": "object", + "properties": { + "totalEmbeddings": { + "type": "integer" + }, + "providers": { + "type": "object" + }, + "modelCounts": { + "type": "object" + }, + "lastUpdated": { + "type": "string", + "format": "date-time" + } + } + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/failed": { + "get": { + "summary": "임베딩 생성에 실패한 노트 목록 조회", + "operationId": "embeddings-failed-notes", + "responses": { + "200": { + "description": "실패한 노트 목록", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "failedNotes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "noteId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "error": { + "type": "string" + }, + "failedAt": { + "type": "string", + "format": "date-time" + } + } + } + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/retry/{noteId}": { + "post": { + "summary": "실패한 노트의 임베딩 생성 재시도", + "operationId": "embeddings-retry-note", + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "다시 시도할 노트 ID" + }, + { + "name": "providerId", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "사용할 제공자 ID. 생략하면 설정된 기본 제공자를 사용합니다." + }, + { + "name": "modelId", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "사용할 모델 ID. 생략하면 제공자의 기본 모델을 사용합니다." + } + ], + "responses": { + "200": { + "description": "재시도 결과", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "잘못된 요청" + }, + "404": { + "description": "노트를 찾을 수 없음" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/retry-all-failed": { + "post": { + "summary": "실패한 모든 노트의 임베딩 생성 재시도", + "operationId": "embeddings-retry-all-failed", + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "사용할 제공자 ID. 생략하면 설정된 기본 제공자를 사용합니다." + }, + "modelId": { + "type": "string", + "description": "사용할 모델 ID. 생략하면 제공자의 기본 모델을 사용합니다." + } + } + } + } + } + }, + "responses": { + "200": { + "description": "재시도 시작", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "message": { + "type": "string" + }, + "jobId": { + "type": "string" + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/rebuild-index": { + "post": { + "summary": "벡터 저장소 색인 다시 만들기", + "operationId": "embeddings-rebuild-index", + "responses": { + "200": { + "description": "다시 만들기 시작", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "message": { + "type": "string" + }, + "jobId": { + "type": "string" + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/embeddings/index-rebuild-status": { + "get": { + "summary": "벡터 색인 다시 만들기 상태 조회", + "operationId": "embeddings-rebuild-status", + "parameters": [ + { + "name": "jobId", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "특정 색인 작업의 상태를 조회할 작업 ID. 생략할 수 있습니다." + } + ], + "responses": { + "200": { + "description": "색인 다시 만들기 상태 정보", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "status": { + "type": "string", + "enum": [ + "idle", + "in_progress", + "completed", + "failed" + ] + }, + "progress": { + "type": "number", + "format": "float", + "description": "진행률 (0~100)" + }, + "message": { + "type": "string" + }, + "details": { + "type": "object", + "properties": { + "startTime": { + "type": "string", + "format": "date-time" + }, + "processed": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/sessions": { + "post": { + "summary": "새 언어 모델 대화 생성", + "operationId": "llm-create-session", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "대화 제목" + }, + "systemPrompt": { + "type": "string", + "description": "도우미의 동작 방식을 지정할 시스템 메시지" + }, + "temperature": { + "type": "number", + "description": "언어 모델의 무작위성 설정값 (0.0~1.0)" + }, + "maxTokens": { + "type": "integer", + "description": "응답에서 생성할 최대 토큰 수" + }, + "model": { + "type": "string", + "description": "사용할 모델. 제공자에 따라 다릅니다." + }, + "provider": { + "type": "string", + "description": "사용할 언어 모델 제공자. 예: openai 또는 anthropic 또는 ollama" + }, + "contextNoteId": { + "type": "string", + "description": "대화의 참고 자료로 사용할 노트 ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "대화 생성 성공", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "sessionId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + }, + "get": { + "summary": "모든 대화 조회", + "operationId": "llm-list-sessions", + "responses": { + "200": { + "description": "대화 목록", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "title": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "lastActive": { + "type": "string", + "format": "date-time" + }, + "messageCount": { + "type": "integer" + } + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/sessions/{sessionId}": { + "get": { + "summary": "특정 대화 조회", + "operationId": "llm-get-session", + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "대화 상세 정보", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "title": { + "type": "string" + }, + "messages": { + "type": "array", + "items": { + "type": "object", + "properties": { + "role": { + "type": "string", + "enum": [ + "user", + "assistant", + "system" + ] + }, + "content": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + } + } + } + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "lastActive": { + "type": "string", + "format": "date-time" + } + } + } + } + } + }, + "404": { + "description": "대화를 찾을 수 없음" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + }, + "delete": { + "summary": "대화 삭제", + "operationId": "llm-delete-session", + "parameters": [ + { + "name": "sessionId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "대화 삭제 성공" + }, + "404": { + "description": "대화를 찾을 수 없음" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/chat/{chatNoteId}": { + "patch": { + "summary": "대화 설정 변경", + "operationId": "llm-update-chat", + "parameters": [ + { + "name": "chatNoteId", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "대화 노트 ID. 이전 이름은 sessionId입니다." + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "변경할 대화 제목" + }, + "systemPrompt": { + "type": "string", + "description": "변경할 시스템 프롬프트" + }, + "temperature": { + "type": "number", + "description": "변경할 무작위성 설정값" + }, + "maxTokens": { + "type": "integer", + "description": "변경할 최대 토큰 수" + }, + "model": { + "type": "string", + "description": "변경할 모델" + }, + "provider": { + "type": "string", + "description": "변경할 제공자" + }, + "contextNoteId": { + "type": "string", + "description": "참고 자료로 사용할 새 노트 ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "대화 변경 성공", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "title": { + "type": "string" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + } + } + } + } + } + }, + "404": { + "description": "대화를 찾을 수 없음" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/chat/{chatNoteId}/messages": { + "post": { + "summary": "언어 모델에 메시지를 보내고 응답 받기", + "operationId": "llm-send-message", + "parameters": [ + { + "name": "chatNoteId", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "대화 노트 ID. 이전 이름은 sessionId입니다." + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "언어 모델에 보낼 사용자 메시지" + }, + "options": { + "type": "object", + "description": "이 메시지에만 적용할 매개변수. 생략할 수 있습니다.", + "properties": { + "temperature": { + "type": "number" + }, + "maxTokens": { + "type": "integer" + }, + "model": { + "type": "string" + }, + "provider": { + "type": "string" + } + } + }, + "includeContext": { + "type": "boolean", + "description": "관련 노트를 참고 자료에 포함할지 여부" + }, + "useNoteContext": { + "type": "boolean", + "description": "대화에 지정된 참고 노트를 사용할지 여부" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "언어 모델 응답", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "response": { + "type": "string" + }, + "sources": { + "type": "array", + "items": { + "type": "object", + "properties": { + "noteId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "similarity": { + "type": "number" + } + } + } + }, + "sessionId": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "대화를 찾을 수 없음" + }, + "500": { + "description": "요청 처리 오류" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/indexes/stats": { + "get": { + "summary": "언어 모델 지식 자료의 색인 상태 통계 조회", + "operationId": "llm-index-stats", + "responses": { + "200": { + "description": "색인 통계 조회 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/indexes": { + "post": { + "summary": "지식 자료 색인 작업 시작 또는 계속하기", + "operationId": "llm-start-indexing", + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "force": { + "type": "boolean", + "description": "모든 노트의 색인을 강제로 다시 만들지 여부" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "색인 작업 시작 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/indexes/failed": { + "get": { + "summary": "색인에 실패한 노트 목록 조회", + "operationId": "llm-failed-indexes", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 100 + } + } + ], + "responses": { + "200": { + "description": "색인 실패 목록 조회 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + }, + "put": { + "summary": "실패한 모든 노트의 색인 재시도", + "operationId": "llm-retry-all-indexes", + "responses": { + "200": { + "description": "실패한 모든 색인 작업 재시도 시작 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/indexes/notes/{noteId}": { + "put": { + "summary": "이전에 실패한 특정 노트의 색인 재시도", + "operationId": "llm-retry-index", + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "색인 재시도 시작 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + }, + "post": { + "summary": "특정 노트를 언어 모델 지식 자료에 색인", + "operationId": "llm-index-note", + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "노트 색인 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/indexes/notes/similar": { + "get": { + "summary": "검색어와 비슷한 노트 찾기", + "operationId": "llm-find-similar-notes", + "parameters": [ + { + "name": "query", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "contextNoteId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 5 + } + } + ], + "responses": { + "200": { + "description": "비슷한 노트 검색 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/indexes/context": { + "get": { + "summary": "지식 자료를 바탕으로 언어 모델 질문의 참고 자료 생성", + "operationId": "llm-generate-context", + "parameters": [ + { + "name": "query", + "in": "query", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "contextNoteId", + "in": "query", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "depth", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 2 + } + } + ], + "responses": { + "200": { + "description": "참고 자료 생성 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/llm/chat/{chatNoteId}/messages/stream": { + "post": { + "summary": "WebSocket으로 언어 모델에 메시지를 보내고 응답을 순차 수신", + "operationId": "llm-stream-message", + "parameters": [ + { + "name": "chatNoteId", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "메시지를 보낼 대화 노트 ID. 이전 이름은 sessionId입니다." + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "content": { + "type": "string", + "description": "언어 모델에 보낼 사용자 메시지" + }, + "useAdvancedContext": { + "type": "boolean", + "description": "고급 참고 자료 추출 기능을 사용할지 여부" + }, + "showThinking": { + "type": "boolean", + "description": "응답에 생각 과정을 표시할지 여부" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "순차 전송 시작 성공" + }, + "404": { + "description": "대화를 찾을 수 없음" + }, + "500": { + "description": "요청 처리 오류" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/login/sync": { + "post": { + "tags": [ + "auth" + ], + "summary": "documentSecret으로 로그인", + "description": "`hash` 매개변수는 `documentSecret`과 `timestamp`를 사용한 HMAC으로 계산합니다.", + "operationId": "login-sync", + "externalDocs": { + "description": "HMAC 계산", + "url": "https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/utils.ts#L62-L66" + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "timestamp": { + "$ref": "#/components/schemas/UtcDateTime" + }, + "hash": { + "type": "string" + }, + "syncVersion": { + "type": "integer", + "example": 34 + } + } + } + } + } + }, + "responses": { + "200": { + "description": "작업 성공", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "syncVersion": { + "type": "integer", + "example": 34 + }, + "options": { + "type": "object", + "properties": { + "documentSecret": { + "type": "string" + } + } + } + } + } + } + } + }, + "400": { + "description": "동기화 버전 또는 문서 비밀 값 불일치", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "example": "동기화 버전이 다릅니다. 로컬 버전은 ${server syncVersion}이며 원격 버전은 ${requested syncVersion}입니다. 양쪽에서 같은 Trilium 버전을 사용하는 것이 좋습니다." + } + } + } + } + } + }, + "401": { + "description": "타임스탬프 불일치", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "example": "인증 요청 시각이 맞지 않습니다. 클라이언트와 서버의 시각이 올바른지 확인하세요. 두 시계의 차이는 5분 미만이어야 합니다." + } + } + } + } + } + } + } + } + }, + "/api/notes/{noteId}": { + "get": { + "summary": "노트 메타데이터 조회", + "operationId": "notes-get", + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/NoteId" + } + } + ], + "responses": { + "200": { + "description": "노트 메타데이터", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/Note" + }, + { + "$ref": "#/components/schemas/Timestamps" + } + ] + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "data" + ] + }, + "delete": { + "summary": "노트 삭제", + "operationId": "notes-delete", + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/NoteId" + } + }, + { + "name": "taskId", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "작업 그룹 식별자" + }, + { + "name": "eraseNotes", + "in": "query", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "노트를 즉시 지울지 여부" + }, + { + "name": "last", + "in": "query", + "schema": { + "type": "boolean" + }, + "required": true, + "description": "이 작업 그룹의 마지막 요청인지 여부" + } + ], + "responses": { + "200": { + "description": "노트 삭제 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "data" + ] + } + }, + "/api/notes/{noteId}/blob": { + "get": { + "summary": "노트 본문 조회", + "operationId": "notes-blob", + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/NoteId" + } + } + ], + "responses": { + "304": { + "description": "노트 본문", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Blob" + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "data" + ] + } + }, + "/api/notes/{noteId}/metadata": { + "get": { + "summary": "노트 메타데이터 조회 (시각 정보만)", + "operationId": "notes-metadata", + "parameters": [ + { + "name": "noteId", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/NoteId" + } + } + ], + "responses": { + "200": { + "description": "노트 메타데이터", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Timestamps" + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "data" + ] + } + }, + "/api/llm/providers/ollama/models": { + "get": { + "summary": "사용 가능한 Ollama 모델 조회", + "operationId": "ollama-list-models", + "parameters": [ + { + "name": "baseUrl", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "사용자 지정 Ollama API 기본 주소. 생략할 수 있습니다." + } + ], + "responses": { + "200": { + "description": "사용 가능한 Ollama 모델 목록", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "models": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "500": { + "description": "모델 목록 조회 오류" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/openai/models": { + "post": { + "summary": "사용 가능한 OpenAI 모델 조회", + "operationId": "openai-list-models", + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "baseUrl": { + "type": "string", + "description": "사용자 지정 OpenAI API 기본 주소. 생략할 수 있습니다." + } + } + } + } + } + }, + "responses": { + "200": { + "description": "사용 가능한 OpenAI 모델 목록", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + }, + "chatModels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + }, + "embeddingModels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "500": { + "description": "모델 목록 조회 오류" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "llm" + ] + } + }, + "/api/sync/changed": { + "get": { + "summary": "동기화 변경 사항 가져오기", + "operationId": "sync-changed", + "externalDocs": { + "description": "서버 구현체", + "url": "https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/sync.ts" + }, + "parameters": [ + { + "in": "query", + "name": "instanceId", + "required": true, + "schema": { + "type": "string" + }, + "description": "로컬 인스턴스 ID" + }, + { + "in": "query", + "name": "lastEntityChangeId", + "required": true, + "schema": { + "type": "integer" + }, + "description": "로컬에 있는 마지막 변경 ID" + }, + { + "in": "query", + "name": "logMarkerId", + "required": true, + "schema": { + "type": "string" + }, + "description": "서버 로그에서 이 요청을 구분할 표시" + } + ], + "responses": { + "200": { + "description": "동기화 변경 사항. 응답 크기는 약 1메가바이트로 제한됩니다.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "entityChanges": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EntityChange" + } + }, + "lastEntityChangeId": { + "type": "integer", + "description": "`outstandingPullCount > 0`이면 다음 요청의 매개변수에 이 값을 넣어 계속 가져옵니다." + }, + "outstandingPullCount": { + "type": "integer", + "example": 42, + "description": "원격 서버가 아직 반환하지 않은 변경 사항 수" + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "sync" + ] + } + }, + "/api/sync/update": { + "put": { + "summary": "동기화 변경 사항 보내기", + "description": "기본 사용법: `pageCount = 1`과 `pageIndex = 0`으로 설정하고 `requestId`는 생략합니다. 요청 본문에 엔터티 변경 사항을 넣습니다.", + "operationId": "sync-update", + "externalDocs": { + "description": "서버 구현체", + "url": "https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/sync.ts" + }, + "parameters": [ + { + "in": "header", + "name": "pageCount", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "in": "header", + "name": "pageIndex", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "in": "header", + "name": "requestId", + "schema": { + "type": "string", + "description": "여러 페이지로 나눈 요청을 구분할 ID" + } + }, + { + "in": "query", + "name": "logMarkerId", + "required": true, + "schema": { + "type": "string" + }, + "description": "서버 로그에서 이 요청을 구분할 표시" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "instanceId": { + "type": "string", + "description": "로컬 인스턴스 ID" + }, + "entities": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EntityChange" + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "변경 사항 처리 성공" + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "sync" + ] + } + }, + "/api/tree": { + "get": { + "summary": "트리 데이터 조회", + "operationId": "tree", + "externalDocs": { + "description": "서버 구현체", + "url": "https://github.com/TriliumNext/Notes/blob/v0.91.6/src/routes/api/tree.ts" + }, + "parameters": [ + { + "in": "query", + "name": "subTreeNoteId", + "required": false, + "schema": { + "type": "string" + }, + "description": "트리 데이터를 이 노트와 하위 노트로 제한" + } + ], + "responses": { + "200": { + "description": "노트와 가지 및 속성", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "branches": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Branch" + } + }, + "notes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Note" + } + }, + "attributes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Attribute" + } + } + } + } + } + } + } + }, + "security": [ + { + "session": [] + } + ], + "tags": [ + "data" + ] + } + }, + "/login": { + "post": { + "tags": [ + "auth" + ], + "summary": "비밀번호로 로그인", + "description": "일부 API 호출에 필요한 Trilium 세션을 발급합니다. 사용자가 TOTP 인증을 설정한 경우에만 `totpToken`이 필요합니다.", + "operationId": "login-normal", + "externalDocs": { + "description": "HMAC 계산", + "url": "https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/utils.ts#L62-L66" + }, + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "type": "object", + "required": [ + "password" + ], + "properties": { + "password": { + "type": "string" + }, + "totpToken": { + "type": "string" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "작업 성공" + }, + "401": { + "description": "비밀번호 또는 일회용 인증 번호 불일치" + } + } + } + } + }, + "components": { + "schemas": { + "Attribute": { + "type": "object", + "properties": { + "attributeId": { + "type": "string", + "example": "4G1DPrI58PAb" + }, + "noteId": { + "$ref": "#/components/schemas/NoteId" + }, + "type": { + "type": "string", + "enum": [ + "label", + "relation" + ] + }, + "name": { + "type": "string", + "example": "internalLink" + }, + "value": { + "type": "string", + "example": "hA8aHSpTRdZ6", + "description": "type이 \"relation\"이면 노트 ID입니다. 그 외에는 속성 내용입니다." + }, + "position": { + "type": "integer", + "example": 20 + }, + "isInheritable": { + "type": "boolean" + } + } + }, + "Blob": { + "type": "object", + "properties": { + "blobId": { + "type": "string", + "example": "8iqMIB8eiY1tPYmElfjm" + }, + "content": { + "type": [ + "string", + "null" + ], + "description": "텍스트가 아니면 `null`입니다." + }, + "contentLength": { + "type": "integer" + }, + "dateModified": { + "$ref": "#/components/schemas/DateTime" + }, + "utcDateModified": { + "$ref": "#/components/schemas/UtcDateTime" + } + } + }, + "Branch": { + "type": "object", + "required": [ + "branchId", + "noteId", + "parentNoteId", + "notePosition" + ], + "properties": { + "branchId": { + "$ref": "#/components/schemas/BranchId" + }, + "noteId": { + "$ref": "#/components/schemas/NoteId" + }, + "parentNoteId": { + "$ref": "#/components/schemas/NoteId" + }, + "notePosition": { + "type": "integer", + "example": 20 + }, + "prefix": { + "type": [ + "string", + "null" + ] + }, + "isExpanded": { + "type": "boolean" + } + } + }, + "BranchId": { + "type": "string", + "example": "WUjhaGp4EKah_ur11rSfHkzeV", + "description": "`{parentNoteId}_{noteId}`와 같습니다." + }, + "DateTime": { + "type": "string", + "example": "2025-02-14 08:19:59.203+0100" + }, + "EntityChange": { + "type": "object", + "properties": { + "entityChange": { + "type": "object", + "properties": { + "entityName": { + "type": "string", + "example": "notes", + "description": "이 엔터티의 데이터베이스 테이블" + }, + "changeId": { + "type": "string", + "example": "changeId9630", + "description": "`entity_changes` 테이블에서 참조하는 ID" + } + } + }, + "entity": { + "type": "object", + "description": "인코딩한 엔터티 데이터. 데이터베이스의 각 열에 대응하는 속성이 들어 있는 객체입니다." + } + } + }, + "Note": { + "type": "object", + "required": [ + "noteId", + "title", + "isProtected", + "type", + "mime", + "blobId" + ], + "properties": { + "noteId": { + "$ref": "#/components/schemas/NoteId" + }, + "title": { + "type": "string" + }, + "isProtected": { + "type": "boolean" + }, + "type": { + "type": "string", + "example": "text", + "enum": [ + "text", + "code", + "render", + "file", + "image", + "search", + "relationMap", + "book", + "noteMap", + "mermaid", + "canvas", + "webView", + "launcher", + "doc", + "contentWidget", + "mindMap", + "geoMap" + ], + "description": "[참고 목록](https://github.com/TriliumNext/Notes/blob/v0.91.6/src/services/note_types.ts)" + }, + "mime": { + "type": "string", + "example": "text/html" + }, + "blobId": { + "type": "string", + "example": "z4PhNX7vuL3xVChQ1m2A" + } + } + }, + "NoteId": { + "type": "string", + "example": "ur11rSfHkzeV", + "description": "12자리 노트 ID. 특수 값은 \"none\"과 \"root\"입니다." + }, + "Timestamps": { + "type": "object", + "properties": { + "dateCreated": { + "$ref": "#/components/schemas/DateTime" + }, + "dateModified": { + "$ref": "#/components/schemas/DateTime" + }, + "utcDateCreated": { + "$ref": "#/components/schemas/UtcDateTime" + }, + "utcDateModified": { + "$ref": "#/components/schemas/UtcDateTime" + } + } + }, + "UtcDateTime": { + "type": "string", + "example": "2025-02-13T07:42:47.698Z", + "description": "`new Date().toISOString().replace('T', ' ')`의 결과" + } + }, + "securitySchemes": { + "user-password": { + "type": "apiKey", + "name": "trilium-cred", + "in": "header", + "description": "`user:password` 형식의 사용자 이름과 비밀번호" + }, + "session": { + "type": "apiKey", + "in": "cookie", + "name": "trilium.sid" + } + } + }, + "tags": [ + { + "name": "auth", + "description": "인증" + }, + { + "name": "sync", + "description": "동기화" + }, + { + "name": "data" + } + ] +} \ No newline at end of file diff --git a/release/app/assets/doc_notes/en/api-ko/swagger/LICENSE b/release/app/assets/doc_notes/en/api-ko/swagger/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/swagger/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/release/app/assets/doc_notes/en/api-ko/swagger/NOTICE b/release/app/assets/doc_notes/en/api-ko/swagger/NOTICE new file mode 100644 index 0000000..ab788a2 --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/swagger/NOTICE @@ -0,0 +1,2 @@ +swagger-ui +Copyright 2020-2021 SmartBear Software Inc. diff --git a/release/app/assets/doc_notes/en/api-ko/swagger/favicon-16x16.png b/release/app/assets/doc_notes/en/api-ko/swagger/favicon-16x16.png new file mode 100644 index 0000000..8b194e6 Binary files /dev/null and b/release/app/assets/doc_notes/en/api-ko/swagger/favicon-16x16.png differ diff --git a/release/app/assets/doc_notes/en/api-ko/swagger/favicon-32x32.png b/release/app/assets/doc_notes/en/api-ko/swagger/favicon-32x32.png new file mode 100644 index 0000000..249737f Binary files /dev/null and b/release/app/assets/doc_notes/en/api-ko/swagger/favicon-32x32.png differ diff --git a/release/app/assets/doc_notes/en/api-ko/swagger/oauth2-redirect.html b/release/app/assets/doc_notes/en/api-ko/swagger/oauth2-redirect.html new file mode 100644 index 0000000..5640917 --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/swagger/oauth2-redirect.html @@ -0,0 +1,79 @@ + + + + Swagger UI: OAuth2 Redirect + + + + + diff --git a/release/app/assets/doc_notes/en/api-ko/swagger/package.json b/release/app/assets/doc_notes/en/api-ko/swagger/package.json new file mode 100644 index 0000000..4bf2be8 --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/swagger/package.json @@ -0,0 +1,20 @@ +{ + "name": "swagger-ui-dist", + "version": "5.21.0", + "main": "index.js", + "repository": "git@github.com:swagger-api/swagger-ui.git", + "contributors": [ + "(in alphabetical order)", + "Anna Bodnia ", + "Buu Nguyen ", + "Josh Ponelat ", + "Kyle Shockey ", + "Robert Barnwell ", + "Sahar Jafari " + ], + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + }, + "devDependencies": {} +} diff --git a/release/app/assets/doc_notes/en/api-ko/swagger/swagger-ui-bundle.js b/release/app/assets/doc_notes/en/api-ko/swagger/swagger-ui-bundle.js new file mode 100644 index 0000000..b703daa --- /dev/null +++ b/release/app/assets/doc_notes/en/api-ko/swagger/swagger-ui-bundle.js @@ -0,0 +1,2 @@ +/*! For license information please see swagger-ui-bundle.js.LICENSE.txt */ +!function webpackUniversalModuleDefinition(s,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define([],o):"object"==typeof exports?exports.SwaggerUIBundle=o():s.SwaggerUIBundle=o()}(this,(()=>(()=>{var s={251:(s,o)=>{o.read=function(s,o,i,a,u){var _,w,x=8*u-a-1,C=(1<>1,L=-7,B=i?u-1:0,$=i?-1:1,V=s[o+B];for(B+=$,_=V&(1<<-L)-1,V>>=-L,L+=x;L>0;_=256*_+s[o+B],B+=$,L-=8);for(w=_&(1<<-L)-1,_>>=-L,L+=a;L>0;w=256*w+s[o+B],B+=$,L-=8);if(0===_)_=1-j;else{if(_===C)return w?NaN:1/0*(V?-1:1);w+=Math.pow(2,a),_-=j}return(V?-1:1)*w*Math.pow(2,_-a)},o.write=function(s,o,i,a,u,_){var w,x,C,j=8*_-u-1,L=(1<>1,$=23===u?Math.pow(2,-24)-Math.pow(2,-77):0,V=a?0:_-1,U=a?1:-1,z=o<0||0===o&&1/o<0?1:0;for(o=Math.abs(o),isNaN(o)||o===1/0?(x=isNaN(o)?1:0,w=L):(w=Math.floor(Math.log(o)/Math.LN2),o*(C=Math.pow(2,-w))<1&&(w--,C*=2),(o+=w+B>=1?$/C:$*Math.pow(2,1-B))*C>=2&&(w++,C/=2),w+B>=L?(x=0,w=L):w+B>=1?(x=(o*C-1)*Math.pow(2,u),w+=B):(x=o*Math.pow(2,B-1)*Math.pow(2,u),w=0));u>=8;s[i+V]=255&x,V+=U,x/=256,u-=8);for(w=w<0;s[i+V]=255&w,V+=U,w/=256,j-=8);s[i+V-U]|=128*z}},462:(s,o,i)=>{"use strict";var a=i(40975);s.exports=a},659:(s,o,i)=>{var a=i(51873),u=Object.prototype,_=u.hasOwnProperty,w=u.toString,x=a?a.toStringTag:void 0;s.exports=function getRawTag(s){var o=_.call(s,x),i=s[x];try{s[x]=void 0;var a=!0}catch(s){}var u=w.call(s);return a&&(o?s[x]=i:delete s[x]),u}},694:(s,o,i)=>{"use strict";i(91599);var a=i(37257);i(12560),s.exports=a},953:(s,o,i)=>{"use strict";s.exports=i(53375)},1733:s=>{var o=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;s.exports=function asciiWords(s){return s.match(o)||[]}},1882:(s,o,i)=>{var a=i(72552),u=i(23805);s.exports=function isFunction(s){if(!u(s))return!1;var o=a(s);return"[object Function]"==o||"[object GeneratorFunction]"==o||"[object AsyncFunction]"==o||"[object Proxy]"==o}},1907:(s,o,i)=>{"use strict";var a=i(41505),u=Function.prototype,_=u.call,w=a&&u.bind.bind(_,_);s.exports=a?w:function(s){return function(){return _.apply(s,arguments)}}},2205:function(s,o,i){var a;a=void 0!==i.g?i.g:this,s.exports=function(s){if(s.CSS&&s.CSS.escape)return s.CSS.escape;var cssEscape=function(s){if(0==arguments.length)throw new TypeError("`CSS.escape` requires an argument.");for(var o,i=String(s),a=i.length,u=-1,_="",w=i.charCodeAt(0);++u=1&&o<=31||127==o||0==u&&o>=48&&o<=57||1==u&&o>=48&&o<=57&&45==w?"\\"+o.toString(16)+" ":0==u&&1==a&&45==o||!(o>=128||45==o||95==o||o>=48&&o<=57||o>=65&&o<=90||o>=97&&o<=122)?"\\"+i.charAt(u):i.charAt(u):_+="�";return _};return s.CSS||(s.CSS={}),s.CSS.escape=cssEscape,cssEscape}(a)},2209:(s,o,i)=>{"use strict";var a,u=i(9404),_=function productionTypeChecker(){invariant(!1,"ImmutablePropTypes type checking code is stripped in production.")};_.isRequired=_;var w=function getProductionTypeChecker(){return _};function getPropType(s){var o=typeof s;return Array.isArray(s)?"array":s instanceof RegExp?"object":s instanceof u.Iterable?"Immutable."+s.toSource().split(" ")[0]:o}function createChainableTypeChecker(s){function checkType(o,i,a,u,_,w){for(var x=arguments.length,C=Array(x>6?x-6:0),j=6;j>",null!=i[a]?s.apply(void 0,[i,a,u,_,w].concat(C)):o?new Error("Required "+_+" `"+w+"` was not specified in `"+u+"`."):void 0}var o=checkType.bind(null,!1);return o.isRequired=checkType.bind(null,!0),o}function createIterableSubclassTypeChecker(s,o){return function createImmutableTypeChecker(s,o){return createChainableTypeChecker((function validate(i,a,u,_,w){var x=i[a];if(!o(x)){var C=getPropType(x);return new Error("Invalid "+_+" `"+w+"` of type `"+C+"` supplied to `"+u+"`, expected `"+s+"`.")}return null}))}("Iterable."+s,(function(s){return u.Iterable.isIterable(s)&&o(s)}))}(a={listOf:w,mapOf:w,orderedMapOf:w,setOf:w,orderedSetOf:w,stackOf:w,iterableOf:w,recordOf:w,shape:w,contains:w,mapContains:w,orderedMapContains:w,list:_,map:_,orderedMap:_,set:_,orderedSet:_,stack:_,seq:_,record:_,iterable:_}).iterable.indexed=createIterableSubclassTypeChecker("Indexed",u.Iterable.isIndexed),a.iterable.keyed=createIterableSubclassTypeChecker("Keyed",u.Iterable.isKeyed),s.exports=a},2404:(s,o,i)=>{var a=i(60270);s.exports=function isEqual(s,o){return a(s,o)}},2523:s=>{s.exports=function baseFindIndex(s,o,i,a){for(var u=s.length,_=i+(a?1:-1);a?_--:++_{"use strict";var a=i(45951),u=Object.defineProperty;s.exports=function(s,o){try{u(a,s,{value:o,configurable:!0,writable:!0})}catch(i){a[s]=o}return o}},2694:(s,o,i)=>{"use strict";var a=i(6925);function emptyFunction(){}function emptyFunctionWithReset(){}emptyFunctionWithReset.resetWarningCache=emptyFunction,s.exports=function(){function shim(s,o,i,u,_,w){if(w!==a){var x=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw x.name="Invariant Violation",x}}function getShim(){return shim}shim.isRequired=shim;var s={array:shim,bigint:shim,bool:shim,func:shim,number:shim,object:shim,string:shim,symbol:shim,any:shim,arrayOf:getShim,element:shim,elementType:shim,instanceOf:getShim,node:shim,objectOf:getShim,oneOf:getShim,oneOfType:getShim,shape:getShim,exact:getShim,checkPropTypes:emptyFunctionWithReset,resetWarningCache:emptyFunction};return s.PropTypes=s,s}},2874:s=>{s.exports={}},2875:(s,o,i)=>{"use strict";var a=i(23045),u=i(80376);s.exports=Object.keys||function keys(s){return a(s,u)}},2955:(s,o,i)=>{"use strict";var a,u=i(65606);function _defineProperty(s,o,i){return(o=function _toPropertyKey(s){var o=function _toPrimitive(s,o){if("object"!=typeof s||null===s)return s;var i=s[Symbol.toPrimitive];if(void 0!==i){var a=i.call(s,o||"default");if("object"!=typeof a)return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===o?String:Number)(s)}(s,"string");return"symbol"==typeof o?o:String(o)}(o))in s?Object.defineProperty(s,o,{value:i,enumerable:!0,configurable:!0,writable:!0}):s[o]=i,s}var _=i(86238),w=Symbol("lastResolve"),x=Symbol("lastReject"),C=Symbol("error"),j=Symbol("ended"),L=Symbol("lastPromise"),B=Symbol("handlePromise"),$=Symbol("stream");function createIterResult(s,o){return{value:s,done:o}}function readAndResolve(s){var o=s[w];if(null!==o){var i=s[$].read();null!==i&&(s[L]=null,s[w]=null,s[x]=null,o(createIterResult(i,!1)))}}function onReadable(s){u.nextTick(readAndResolve,s)}var V=Object.getPrototypeOf((function(){})),U=Object.setPrototypeOf((_defineProperty(a={get stream(){return this[$]},next:function next(){var s=this,o=this[C];if(null!==o)return Promise.reject(o);if(this[j])return Promise.resolve(createIterResult(void 0,!0));if(this[$].destroyed)return new Promise((function(o,i){u.nextTick((function(){s[C]?i(s[C]):o(createIterResult(void 0,!0))}))}));var i,a=this[L];if(a)i=new Promise(function wrapForNext(s,o){return function(i,a){s.then((function(){o[j]?i(createIterResult(void 0,!0)):o[B](i,a)}),a)}}(a,this));else{var _=this[$].read();if(null!==_)return Promise.resolve(createIterResult(_,!1));i=new Promise(this[B])}return this[L]=i,i}},Symbol.asyncIterator,(function(){return this})),_defineProperty(a,"return",(function _return(){var s=this;return new Promise((function(o,i){s[$].destroy(null,(function(s){s?i(s):o(createIterResult(void 0,!0))}))}))})),a),V);s.exports=function createReadableStreamAsyncIterator(s){var o,i=Object.create(U,(_defineProperty(o={},$,{value:s,writable:!0}),_defineProperty(o,w,{value:null,writable:!0}),_defineProperty(o,x,{value:null,writable:!0}),_defineProperty(o,C,{value:null,writable:!0}),_defineProperty(o,j,{value:s._readableState.endEmitted,writable:!0}),_defineProperty(o,B,{value:function value(s,o){var a=i[$].read();a?(i[L]=null,i[w]=null,i[x]=null,s(createIterResult(a,!1))):(i[w]=s,i[x]=o)},writable:!0}),o));return i[L]=null,_(s,(function(s){if(s&&"ERR_STREAM_PREMATURE_CLOSE"!==s.code){var o=i[x];return null!==o&&(i[L]=null,i[w]=null,i[x]=null,o(s)),void(i[C]=s)}var a=i[w];null!==a&&(i[L]=null,i[w]=null,i[x]=null,a(createIterResult(void 0,!0))),i[j]=!0})),s.on("readable",onReadable.bind(null,i)),i}},3110:(s,o,i)=>{const a=i(5187),u=i(85015),_=i(98023),w=i(53812),x=i(23805),C=i(85105),j=i(86804);class Namespace{constructor(s){this.elementMap={},this.elementDetection=[],this.Element=j.Element,this.KeyValuePair=j.KeyValuePair,s&&s.noDefault||this.useDefault(),this._attributeElementKeys=[],this._attributeElementArrayKeys=[]}use(s){return s.namespace&&s.namespace({base:this}),s.load&&s.load({base:this}),this}useDefault(){return this.register("null",j.NullElement).register("string",j.StringElement).register("number",j.NumberElement).register("boolean",j.BooleanElement).register("array",j.ArrayElement).register("object",j.ObjectElement).register("member",j.MemberElement).register("ref",j.RefElement).register("link",j.LinkElement),this.detect(a,j.NullElement,!1).detect(u,j.StringElement,!1).detect(_,j.NumberElement,!1).detect(w,j.BooleanElement,!1).detect(Array.isArray,j.ArrayElement,!1).detect(x,j.ObjectElement,!1),this}register(s,o){return this._elements=void 0,this.elementMap[s]=o,this}unregister(s){return this._elements=void 0,delete this.elementMap[s],this}detect(s,o,i){return void 0===i||i?this.elementDetection.unshift([s,o]):this.elementDetection.push([s,o]),this}toElement(s){if(s instanceof this.Element)return s;let o;for(let i=0;i{const o=s[0].toUpperCase()+s.substr(1);this._elements[o]=this.elementMap[s]}))),this._elements}get serialiser(){return new C(this)}}C.prototype.Namespace=Namespace,s.exports=Namespace},3121:(s,o,i)=>{"use strict";var a=i(65482),u=Math.min;s.exports=function(s){var o=a(s);return o>0?u(o,9007199254740991):0}},3209:(s,o,i)=>{var a=i(91596),u=i(53320),_=i(36306),w="__lodash_placeholder__",x=128,C=Math.min;s.exports=function mergeData(s,o){var i=s[1],j=o[1],L=i|j,B=L<131,$=j==x&&8==i||j==x&&256==i&&s[7].length<=o[8]||384==j&&o[7].length<=o[8]&&8==i;if(!B&&!$)return s;1&j&&(s[2]=o[2],L|=1&i?0:4);var V=o[3];if(V){var U=s[3];s[3]=U?a(U,V,o[4]):V,s[4]=U?_(s[3],w):o[4]}return(V=o[5])&&(U=s[5],s[5]=U?u(U,V,o[6]):V,s[6]=U?_(s[5],w):o[6]),(V=o[7])&&(s[7]=V),j&x&&(s[8]=null==s[8]?o[8]:C(s[8],o[8])),null==s[9]&&(s[9]=o[9]),s[0]=o[0],s[1]=L,s}},3650:(s,o,i)=>{var a=i(74335)(Object.keys,Object);s.exports=a},3656:(s,o,i)=>{s=i.nmd(s);var a=i(9325),u=i(89935),_=o&&!o.nodeType&&o,w=_&&s&&!s.nodeType&&s,x=w&&w.exports===_?a.Buffer:void 0,C=(x?x.isBuffer:void 0)||u;s.exports=C},4509:(s,o,i)=>{var a=i(12651);s.exports=function mapCacheHas(s){return a(this,s).has(s)}},4640:s=>{"use strict";var o=String;s.exports=function(s){try{return o(s)}catch(s){return"Object"}}},4664:(s,o,i)=>{var a=i(79770),u=i(63345),_=Object.prototype.propertyIsEnumerable,w=Object.getOwnPropertySymbols,x=w?function(s){return null==s?[]:(s=Object(s),a(w(s),(function(o){return _.call(s,o)})))}:u;s.exports=x},4901:(s,o,i)=>{var a=i(72552),u=i(30294),_=i(40346),w={};w["[object Float32Array]"]=w["[object Float64Array]"]=w["[object Int8Array]"]=w["[object Int16Array]"]=w["[object Int32Array]"]=w["[object Uint8Array]"]=w["[object Uint8ClampedArray]"]=w["[object Uint16Array]"]=w["[object Uint32Array]"]=!0,w["[object Arguments]"]=w["[object Array]"]=w["[object ArrayBuffer]"]=w["[object Boolean]"]=w["[object DataView]"]=w["[object Date]"]=w["[object Error]"]=w["[object Function]"]=w["[object Map]"]=w["[object Number]"]=w["[object Object]"]=w["[object RegExp]"]=w["[object Set]"]=w["[object String]"]=w["[object WeakMap]"]=!1,s.exports=function baseIsTypedArray(s){return _(s)&&u(s.length)&&!!w[a(s)]}},4993:(s,o,i)=>{"use strict";var a=i(16946),u=i(74239);s.exports=function(s){return a(u(s))}},5187:s=>{s.exports=function isNull(s){return null===s}},5419:s=>{s.exports=function(s,o,i,a){var u=new Blob(void 0!==a?[a,s]:[s],{type:i||"application/octet-stream"});if(void 0!==window.navigator.msSaveBlob)window.navigator.msSaveBlob(u,o);else{var _=window.URL&&window.URL.createObjectURL?window.URL.createObjectURL(u):window.webkitURL.createObjectURL(u),w=document.createElement("a");w.style.display="none",w.href=_,w.setAttribute("download",o),void 0===w.download&&w.setAttribute("target","_blank"),document.body.appendChild(w),w.click(),setTimeout((function(){document.body.removeChild(w),window.URL.revokeObjectURL(_)}),200)}}},5556:(s,o,i)=>{s.exports=i(2694)()},5861:(s,o,i)=>{var a=i(55580),u=i(68223),_=i(32804),w=i(76545),x=i(28303),C=i(72552),j=i(47473),L="[object Map]",B="[object Promise]",$="[object Set]",V="[object WeakMap]",U="[object DataView]",z=j(a),Y=j(u),Z=j(_),ee=j(w),ie=j(x),ae=C;(a&&ae(new a(new ArrayBuffer(1)))!=U||u&&ae(new u)!=L||_&&ae(_.resolve())!=B||w&&ae(new w)!=$||x&&ae(new x)!=V)&&(ae=function(s){var o=C(s),i="[object Object]"==o?s.constructor:void 0,a=i?j(i):"";if(a)switch(a){case z:return U;case Y:return L;case Z:return B;case ee:return $;case ie:return V}return o}),s.exports=ae},6048:s=>{s.exports=function negate(s){if("function"!=typeof s)throw new TypeError("Expected a function");return function(){var o=arguments;switch(o.length){case 0:return!s.call(this);case 1:return!s.call(this,o[0]);case 2:return!s.call(this,o[0],o[1]);case 3:return!s.call(this,o[0],o[1],o[2])}return!s.apply(this,o)}}},6205:s=>{s.exports={ROOT:0,GROUP:1,POSITION:2,SET:3,RANGE:4,REPETITION:5,REFERENCE:6,CHAR:7}},6233:(s,o,i)=>{const a=i(6048),u=i(10316),_=i(92340);class ArrayElement extends u{constructor(s,o,i){super(s||[],o,i),this.element="array"}primitive(){return"array"}get(s){return this.content[s]}getValue(s){const o=this.get(s);if(o)return o.toValue()}getIndex(s){return this.content[s]}set(s,o){return this.content[s]=this.refract(o),this}remove(s){const o=this.content.splice(s,1);return o.length?o[0]:null}map(s,o){return this.content.map(s,o)}flatMap(s,o){return this.map(s,o).reduce(((s,o)=>s.concat(o)),[])}compactMap(s,o){const i=[];return this.forEach((a=>{const u=s.bind(o)(a);u&&i.push(u)})),i}filter(s,o){return new _(this.content.filter(s,o))}reject(s,o){return this.filter(a(s),o)}reduce(s,o){let i,a;void 0!==o?(i=0,a=this.refract(o)):(i=1,a="object"===this.primitive()?this.first.value:this.first);for(let o=i;o{s.bind(o)(i,this.refract(a))}))}shift(){return this.content.shift()}unshift(s){this.content.unshift(this.refract(s))}push(s){return this.content.push(this.refract(s)),this}add(s){this.push(s)}findElements(s,o){const i=o||{},a=!!i.recursive,u=void 0===i.results?[]:i.results;return this.forEach(((o,i,_)=>{a&&void 0!==o.findElements&&o.findElements(s,{results:u,recursive:a}),s(o,i,_)&&u.push(o)})),u}find(s){return new _(this.findElements(s,{recursive:!0}))}findByElement(s){return this.find((o=>o.element===s))}findByClass(s){return this.find((o=>o.classes.includes(s)))}getById(s){return this.find((o=>o.id.toValue()===s)).first}includes(s){return this.content.some((o=>o.equals(s)))}contains(s){return this.includes(s)}empty(){return new this.constructor([])}"fantasy-land/empty"(){return this.empty()}concat(s){return new this.constructor(this.content.concat(s.content))}"fantasy-land/concat"(s){return this.concat(s)}"fantasy-land/map"(s){return new this.constructor(this.map(s))}"fantasy-land/chain"(s){return this.map((o=>s(o)),this).reduce(((s,o)=>s.concat(o)),this.empty())}"fantasy-land/filter"(s){return new this.constructor(this.content.filter(s))}"fantasy-land/reduce"(s,o){return this.content.reduce(s,o)}get length(){return this.content.length}get isEmpty(){return 0===this.content.length}get first(){return this.getIndex(0)}get second(){return this.getIndex(1)}get last(){return this.getIndex(this.length-1)}}ArrayElement.empty=function empty(){return new this},ArrayElement["fantasy-land/empty"]=ArrayElement.empty,"undefined"!=typeof Symbol&&(ArrayElement.prototype[Symbol.iterator]=function symbol(){return this.content[Symbol.iterator]()}),s.exports=ArrayElement},6499:(s,o,i)=>{"use strict";var a=i(1907),u=0,_=Math.random(),w=a(1..toString);s.exports=function(s){return"Symbol("+(void 0===s?"":s)+")_"+w(++u+_,36)}},6925:s=>{"use strict";s.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},7057:(s,o,i)=>{"use strict";var a=i(11470).charAt,u=i(90160),_=i(64932),w=i(60183),x=i(59550),C="String Iterator",j=_.set,L=_.getterFor(C);w(String,"String",(function(s){j(this,{type:C,string:u(s),index:0})}),(function next(){var s,o=L(this),i=o.string,u=o.index;return u>=i.length?x(void 0,!0):(s=a(i,u),o.index+=s.length,x(s,!1))}))},7309:(s,o,i)=>{var a=i(62006)(i(24713));s.exports=a},7376:s=>{"use strict";s.exports=!0},7463:(s,o,i)=>{"use strict";var a=i(98828),u=i(62250),_=/#|\.prototype\./,isForced=function(s,o){var i=x[w(s)];return i===j||i!==C&&(u(o)?a(o):!!o)},w=isForced.normalize=function(s){return String(s).replace(_,".").toLowerCase()},x=isForced.data={},C=isForced.NATIVE="N",j=isForced.POLYFILL="P";s.exports=isForced},7666:(s,o,i)=>{var a=i(84851),u=i(953);function _extends(){var o;return s.exports=_extends=a?u(o=a).call(o):function(s){for(var o=1;o{const a=i(6205);o.wordBoundary=()=>({type:a.POSITION,value:"b"}),o.nonWordBoundary=()=>({type:a.POSITION,value:"B"}),o.begin=()=>({type:a.POSITION,value:"^"}),o.end=()=>({type:a.POSITION,value:"$"})},8068:s=>{"use strict";var o=(()=>{var s=Object.defineProperty,o=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getOwnPropertySymbols,u=Object.prototype.hasOwnProperty,_=Object.prototype.propertyIsEnumerable,__defNormalProp=(o,i,a)=>i in o?s(o,i,{enumerable:!0,configurable:!0,writable:!0,value:a}):o[i]=a,__spreadValues=(s,o)=>{for(var i in o||(o={}))u.call(o,i)&&__defNormalProp(s,i,o[i]);if(a)for(var i of a(o))_.call(o,i)&&__defNormalProp(s,i,o[i]);return s},__publicField=(s,o,i)=>(__defNormalProp(s,"symbol"!=typeof o?o+"":o,i),i),w={};((o,i)=>{for(var a in i)s(o,a,{get:i[a],enumerable:!0})})(w,{DEFAULT_OPTIONS:()=>C,DEFAULT_UUID_LENGTH:()=>x,default:()=>B});var x=6,C={dictionary:"alphanum",shuffle:!0,debug:!1,length:x,counter:0},j=class _ShortUniqueId{constructor(s={}){__publicField(this,"counter"),__publicField(this,"debug"),__publicField(this,"dict"),__publicField(this,"version"),__publicField(this,"dictIndex",0),__publicField(this,"dictRange",[]),__publicField(this,"lowerBound",0),__publicField(this,"upperBound",0),__publicField(this,"dictLength",0),__publicField(this,"uuidLength"),__publicField(this,"_digit_first_ascii",48),__publicField(this,"_digit_last_ascii",58),__publicField(this,"_alpha_lower_first_ascii",97),__publicField(this,"_alpha_lower_last_ascii",123),__publicField(this,"_hex_last_ascii",103),__publicField(this,"_alpha_upper_first_ascii",65),__publicField(this,"_alpha_upper_last_ascii",91),__publicField(this,"_number_dict_ranges",{digits:[this._digit_first_ascii,this._digit_last_ascii]}),__publicField(this,"_alpha_dict_ranges",{lowerCase:[this._alpha_lower_first_ascii,this._alpha_lower_last_ascii],upperCase:[this._alpha_upper_first_ascii,this._alpha_upper_last_ascii]}),__publicField(this,"_alpha_lower_dict_ranges",{lowerCase:[this._alpha_lower_first_ascii,this._alpha_lower_last_ascii]}),__publicField(this,"_alpha_upper_dict_ranges",{upperCase:[this._alpha_upper_first_ascii,this._alpha_upper_last_ascii]}),__publicField(this,"_alphanum_dict_ranges",{digits:[this._digit_first_ascii,this._digit_last_ascii],lowerCase:[this._alpha_lower_first_ascii,this._alpha_lower_last_ascii],upperCase:[this._alpha_upper_first_ascii,this._alpha_upper_last_ascii]}),__publicField(this,"_alphanum_lower_dict_ranges",{digits:[this._digit_first_ascii,this._digit_last_ascii],lowerCase:[this._alpha_lower_first_ascii,this._alpha_lower_last_ascii]}),__publicField(this,"_alphanum_upper_dict_ranges",{digits:[this._digit_first_ascii,this._digit_last_ascii],upperCase:[this._alpha_upper_first_ascii,this._alpha_upper_last_ascii]}),__publicField(this,"_hex_dict_ranges",{decDigits:[this._digit_first_ascii,this._digit_last_ascii],alphaDigits:[this._alpha_lower_first_ascii,this._hex_last_ascii]}),__publicField(this,"_dict_ranges",{_number_dict_ranges:this._number_dict_ranges,_alpha_dict_ranges:this._alpha_dict_ranges,_alpha_lower_dict_ranges:this._alpha_lower_dict_ranges,_alpha_upper_dict_ranges:this._alpha_upper_dict_ranges,_alphanum_dict_ranges:this._alphanum_dict_ranges,_alphanum_lower_dict_ranges:this._alphanum_lower_dict_ranges,_alphanum_upper_dict_ranges:this._alphanum_upper_dict_ranges,_hex_dict_ranges:this._hex_dict_ranges}),__publicField(this,"log",((...s)=>{const o=[...s];if(o[0]=`[short-unique-id] ${s[0]}`,!0===this.debug&&"undefined"!=typeof console&&null!==console)return console.log(...o)})),__publicField(this,"_normalizeDictionary",((s,o)=>{let i;if(s&&Array.isArray(s)&&s.length>1)i=s;else{let o;i=[],this.dictIndex=o=0;const a=`_${s}_dict_ranges`,u=this._dict_ranges[a];Object.keys(u).forEach((s=>{const a=s;for(this.dictRange=u[a],this.lowerBound=this.dictRange[0],this.upperBound=this.dictRange[1],this.dictIndex=o=this.lowerBound;this.lowerBound<=this.upperBound?othis.upperBound;this.dictIndex=this.lowerBound<=this.upperBound?o+=1:o-=1)i.push(String.fromCharCode(this.dictIndex))}))}if(o){const s=.5;i=i.sort((()=>Math.random()-s))}return i})),__publicField(this,"setDictionary",((s,o)=>{this.dict=this._normalizeDictionary(s,o),this.dictLength=this.dict.length,this.setCounter(0)})),__publicField(this,"seq",(()=>this.sequentialUUID())),__publicField(this,"sequentialUUID",(()=>{let s,o,i="";s=this.counter;do{o=s%this.dictLength,s=Math.trunc(s/this.dictLength),i+=this.dict[o]}while(0!==s);return this.counter+=1,i})),__publicField(this,"rnd",((s=this.uuidLength||x)=>this.randomUUID(s))),__publicField(this,"randomUUID",((s=this.uuidLength||x)=>{let o,i,a;if(null==s||s<1)throw new Error("Invalid UUID Length Provided");for(o="",a=0;athis.formattedUUID(s,o))),__publicField(this,"formattedUUID",((s,o)=>{const i={$r:this.randomUUID,$s:this.sequentialUUID,$t:this.stamp};return s.replace(/\$[rs]\d{0,}|\$t0|\$t[1-9]\d{1,}/g,(s=>{const a=s.slice(0,2),u=parseInt(s.slice(2),10);return"$s"===a?i[a]().padStart(u,"0"):"$t"===a&&o?i[a](u,o):i[a](u)}))})),__publicField(this,"availableUUIDs",((s=this.uuidLength)=>parseFloat(Math.pow([...new Set(this.dict)].length,s).toFixed(0)))),__publicField(this,"approxMaxBeforeCollision",((s=this.availableUUIDs(this.uuidLength))=>parseFloat(Math.sqrt(Math.PI/2*s).toFixed(20)))),__publicField(this,"collisionProbability",((s=this.availableUUIDs(this.uuidLength),o=this.uuidLength)=>parseFloat((this.approxMaxBeforeCollision(s)/this.availableUUIDs(o)).toFixed(20)))),__publicField(this,"uniqueness",((s=this.availableUUIDs(this.uuidLength))=>{const o=parseFloat((1-this.approxMaxBeforeCollision(s)/s).toFixed(20));return o>1?1:o<0?0:o})),__publicField(this,"getVersion",(()=>this.version)),__publicField(this,"stamp",((s,o)=>{const i=Math.floor(+(o||new Date)/1e3).toString(16);if("number"==typeof s&&0===s)return i;if("number"!=typeof s||s<10)throw new Error(["Param finalLength must be a number greater than or equal to 10,","or 0 if you want the raw hexadecimal timestamp"].join("\n"));const a=s-9,u=Math.round(Math.random()*(a>15?15:a)),_=this.randomUUID(a);return`${_.substring(0,u)}${i}${_.substring(u)}${u.toString(16)}`})),__publicField(this,"parseStamp",((s,o)=>{if(o&&!/t0|t[1-9]\d{1,}/.test(o))throw new Error("Cannot extract date from a formated UUID with no timestamp in the format");const i=o?o.replace(/\$[rs]\d{0,}|\$t0|\$t[1-9]\d{1,}/g,(s=>{const o={$r:s=>[...Array(s)].map((()=>"r")).join(""),$s:s=>[...Array(s)].map((()=>"s")).join(""),$t:s=>[...Array(s)].map((()=>"t")).join("")},i=s.slice(0,2),a=parseInt(s.slice(2),10);return o[i](a)})).replace(/^(.*?)(t{8,})(.*)$/g,((o,i,a)=>s.substring(i.length,i.length+a.length))):s;if(8===i.length)return new Date(1e3*parseInt(i,16));if(i.length<10)throw new Error("Stamp length invalid");const a=parseInt(i.substring(i.length-1),16);return new Date(1e3*parseInt(i.substring(a,a+8),16))})),__publicField(this,"setCounter",(s=>{this.counter=s})),__publicField(this,"validate",((s,o)=>{const i=o?this._normalizeDictionary(o):this.dict;return s.split("").every((s=>i.includes(s)))}));const o=__spreadValues(__spreadValues({},C),s);this.counter=0,this.debug=!1,this.dict=[],this.version="5.2.0";const{dictionary:i,shuffle:a,length:u,counter:_}=o;return this.uuidLength=u,this.setDictionary(i,a),this.setCounter(_),this.debug=o.debug,this.log(this.dict),this.log(`Generator instantiated with Dictionary Size ${this.dictLength} and counter set to ${this.counter}`),this.log=this.log.bind(this),this.setDictionary=this.setDictionary.bind(this),this.setCounter=this.setCounter.bind(this),this.seq=this.seq.bind(this),this.sequentialUUID=this.sequentialUUID.bind(this),this.rnd=this.rnd.bind(this),this.randomUUID=this.randomUUID.bind(this),this.fmt=this.fmt.bind(this),this.formattedUUID=this.formattedUUID.bind(this),this.availableUUIDs=this.availableUUIDs.bind(this),this.approxMaxBeforeCollision=this.approxMaxBeforeCollision.bind(this),this.collisionProbability=this.collisionProbability.bind(this),this.uniqueness=this.uniqueness.bind(this),this.getVersion=this.getVersion.bind(this),this.stamp=this.stamp.bind(this),this.parseStamp=this.parseStamp.bind(this),this}};__publicField(j,"default",j);var L,B=j;return L=w,((a,_,w,x)=>{if(_&&"object"==typeof _||"function"==typeof _)for(let C of i(_))u.call(a,C)||C===w||s(a,C,{get:()=>_[C],enumerable:!(x=o(_,C))||x.enumerable});return a})(s({},"__esModule",{value:!0}),L)})();s.exports=o.default,"undefined"!=typeof window&&(o=o.default)},9325:(s,o,i)=>{var a=i(34840),u="object"==typeof self&&self&&self.Object===Object&&self,_=a||u||Function("return this")();s.exports=_},9404:function(s){s.exports=function(){"use strict";var s=Array.prototype.slice;function createClass(s,o){o&&(s.prototype=Object.create(o.prototype)),s.prototype.constructor=s}function Iterable(s){return isIterable(s)?s:Seq(s)}function KeyedIterable(s){return isKeyed(s)?s:KeyedSeq(s)}function IndexedIterable(s){return isIndexed(s)?s:IndexedSeq(s)}function SetIterable(s){return isIterable(s)&&!isAssociative(s)?s:SetSeq(s)}function isIterable(s){return!(!s||!s[o])}function isKeyed(s){return!(!s||!s[i])}function isIndexed(s){return!(!s||!s[a])}function isAssociative(s){return isKeyed(s)||isIndexed(s)}function isOrdered(s){return!(!s||!s[u])}createClass(KeyedIterable,Iterable),createClass(IndexedIterable,Iterable),createClass(SetIterable,Iterable),Iterable.isIterable=isIterable,Iterable.isKeyed=isKeyed,Iterable.isIndexed=isIndexed,Iterable.isAssociative=isAssociative,Iterable.isOrdered=isOrdered,Iterable.Keyed=KeyedIterable,Iterable.Indexed=IndexedIterable,Iterable.Set=SetIterable;var o="@@__IMMUTABLE_ITERABLE__@@",i="@@__IMMUTABLE_KEYED__@@",a="@@__IMMUTABLE_INDEXED__@@",u="@@__IMMUTABLE_ORDERED__@@",_="delete",w=5,x=1<>>0;if(""+i!==o||4294967295===i)return NaN;o=i}return o<0?ensureSize(s)+o:o}function returnTrue(){return!0}function wholeSlice(s,o,i){return(0===s||void 0!==i&&s<=-i)&&(void 0===o||void 0!==i&&o>=i)}function resolveBegin(s,o){return resolveIndex(s,o,0)}function resolveEnd(s,o){return resolveIndex(s,o,o)}function resolveIndex(s,o,i){return void 0===s?i:s<0?Math.max(0,o+s):void 0===o?s:Math.min(o,s)}var $=0,V=1,U=2,z="function"==typeof Symbol&&Symbol.iterator,Y="@@iterator",Z=z||Y;function Iterator(s){this.next=s}function iteratorValue(s,o,i,a){var u=0===s?o:1===s?i:[o,i];return a?a.value=u:a={value:u,done:!1},a}function iteratorDone(){return{value:void 0,done:!0}}function hasIterator(s){return!!getIteratorFn(s)}function isIterator(s){return s&&"function"==typeof s.next}function getIterator(s){var o=getIteratorFn(s);return o&&o.call(s)}function getIteratorFn(s){var o=s&&(z&&s[z]||s[Y]);if("function"==typeof o)return o}function isArrayLike(s){return s&&"number"==typeof s.length}function Seq(s){return null==s?emptySequence():isIterable(s)?s.toSeq():seqFromValue(s)}function KeyedSeq(s){return null==s?emptySequence().toKeyedSeq():isIterable(s)?isKeyed(s)?s.toSeq():s.fromEntrySeq():keyedSeqFromValue(s)}function IndexedSeq(s){return null==s?emptySequence():isIterable(s)?isKeyed(s)?s.entrySeq():s.toIndexedSeq():indexedSeqFromValue(s)}function SetSeq(s){return(null==s?emptySequence():isIterable(s)?isKeyed(s)?s.entrySeq():s:indexedSeqFromValue(s)).toSetSeq()}Iterator.prototype.toString=function(){return"[Iterator]"},Iterator.KEYS=$,Iterator.VALUES=V,Iterator.ENTRIES=U,Iterator.prototype.inspect=Iterator.prototype.toSource=function(){return this.toString()},Iterator.prototype[Z]=function(){return this},createClass(Seq,Iterable),Seq.of=function(){return Seq(arguments)},Seq.prototype.toSeq=function(){return this},Seq.prototype.toString=function(){return this.__toString("Seq {","}")},Seq.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},Seq.prototype.__iterate=function(s,o){return seqIterate(this,s,o,!0)},Seq.prototype.__iterator=function(s,o){return seqIterator(this,s,o,!0)},createClass(KeyedSeq,Seq),KeyedSeq.prototype.toKeyedSeq=function(){return this},createClass(IndexedSeq,Seq),IndexedSeq.of=function(){return IndexedSeq(arguments)},IndexedSeq.prototype.toIndexedSeq=function(){return this},IndexedSeq.prototype.toString=function(){return this.__toString("Seq [","]")},IndexedSeq.prototype.__iterate=function(s,o){return seqIterate(this,s,o,!1)},IndexedSeq.prototype.__iterator=function(s,o){return seqIterator(this,s,o,!1)},createClass(SetSeq,Seq),SetSeq.of=function(){return SetSeq(arguments)},SetSeq.prototype.toSetSeq=function(){return this},Seq.isSeq=isSeq,Seq.Keyed=KeyedSeq,Seq.Set=SetSeq,Seq.Indexed=IndexedSeq;var ee,ie,ae,ce="@@__IMMUTABLE_SEQ__@@";function ArraySeq(s){this._array=s,this.size=s.length}function ObjectSeq(s){var o=Object.keys(s);this._object=s,this._keys=o,this.size=o.length}function IterableSeq(s){this._iterable=s,this.size=s.length||s.size}function IteratorSeq(s){this._iterator=s,this._iteratorCache=[]}function isSeq(s){return!(!s||!s[ce])}function emptySequence(){return ee||(ee=new ArraySeq([]))}function keyedSeqFromValue(s){var o=Array.isArray(s)?new ArraySeq(s).fromEntrySeq():isIterator(s)?new IteratorSeq(s).fromEntrySeq():hasIterator(s)?new IterableSeq(s).fromEntrySeq():"object"==typeof s?new ObjectSeq(s):void 0;if(!o)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+s);return o}function indexedSeqFromValue(s){var o=maybeIndexedSeqFromValue(s);if(!o)throw new TypeError("Expected Array or iterable object of values: "+s);return o}function seqFromValue(s){var o=maybeIndexedSeqFromValue(s)||"object"==typeof s&&new ObjectSeq(s);if(!o)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+s);return o}function maybeIndexedSeqFromValue(s){return isArrayLike(s)?new ArraySeq(s):isIterator(s)?new IteratorSeq(s):hasIterator(s)?new IterableSeq(s):void 0}function seqIterate(s,o,i,a){var u=s._cache;if(u){for(var _=u.length-1,w=0;w<=_;w++){var x=u[i?_-w:w];if(!1===o(x[1],a?x[0]:w,s))return w+1}return w}return s.__iterateUncached(o,i)}function seqIterator(s,o,i,a){var u=s._cache;if(u){var _=u.length-1,w=0;return new Iterator((function(){var s=u[i?_-w:w];return w++>_?iteratorDone():iteratorValue(o,a?s[0]:w-1,s[1])}))}return s.__iteratorUncached(o,i)}function fromJS(s,o){return o?fromJSWith(o,s,"",{"":s}):fromJSDefault(s)}function fromJSWith(s,o,i,a){return Array.isArray(o)?s.call(a,i,IndexedSeq(o).map((function(i,a){return fromJSWith(s,i,a,o)}))):isPlainObj(o)?s.call(a,i,KeyedSeq(o).map((function(i,a){return fromJSWith(s,i,a,o)}))):o}function fromJSDefault(s){return Array.isArray(s)?IndexedSeq(s).map(fromJSDefault).toList():isPlainObj(s)?KeyedSeq(s).map(fromJSDefault).toMap():s}function isPlainObj(s){return s&&(s.constructor===Object||void 0===s.constructor)}function is(s,o){if(s===o||s!=s&&o!=o)return!0;if(!s||!o)return!1;if("function"==typeof s.valueOf&&"function"==typeof o.valueOf){if((s=s.valueOf())===(o=o.valueOf())||s!=s&&o!=o)return!0;if(!s||!o)return!1}return!("function"!=typeof s.equals||"function"!=typeof o.equals||!s.equals(o))}function deepEqual(s,o){if(s===o)return!0;if(!isIterable(o)||void 0!==s.size&&void 0!==o.size&&s.size!==o.size||void 0!==s.__hash&&void 0!==o.__hash&&s.__hash!==o.__hash||isKeyed(s)!==isKeyed(o)||isIndexed(s)!==isIndexed(o)||isOrdered(s)!==isOrdered(o))return!1;if(0===s.size&&0===o.size)return!0;var i=!isAssociative(s);if(isOrdered(s)){var a=s.entries();return o.every((function(s,o){var u=a.next().value;return u&&is(u[1],s)&&(i||is(u[0],o))}))&&a.next().done}var u=!1;if(void 0===s.size)if(void 0===o.size)"function"==typeof s.cacheResult&&s.cacheResult();else{u=!0;var _=s;s=o,o=_}var w=!0,x=o.__iterate((function(o,a){if(i?!s.has(o):u?!is(o,s.get(a,j)):!is(s.get(a,j),o))return w=!1,!1}));return w&&s.size===x}function Repeat(s,o){if(!(this instanceof Repeat))return new Repeat(s,o);if(this._value=s,this.size=void 0===o?1/0:Math.max(0,o),0===this.size){if(ie)return ie;ie=this}}function invariant(s,o){if(!s)throw new Error(o)}function Range(s,o,i){if(!(this instanceof Range))return new Range(s,o,i);if(invariant(0!==i,"Cannot step a Range by 0"),s=s||0,void 0===o&&(o=1/0),i=void 0===i?1:Math.abs(i),oa?iteratorDone():iteratorValue(s,u,i[o?a-u++:u++])}))},createClass(ObjectSeq,KeyedSeq),ObjectSeq.prototype.get=function(s,o){return void 0===o||this.has(s)?this._object[s]:o},ObjectSeq.prototype.has=function(s){return this._object.hasOwnProperty(s)},ObjectSeq.prototype.__iterate=function(s,o){for(var i=this._object,a=this._keys,u=a.length-1,_=0;_<=u;_++){var w=a[o?u-_:_];if(!1===s(i[w],w,this))return _+1}return _},ObjectSeq.prototype.__iterator=function(s,o){var i=this._object,a=this._keys,u=a.length-1,_=0;return new Iterator((function(){var w=a[o?u-_:_];return _++>u?iteratorDone():iteratorValue(s,w,i[w])}))},ObjectSeq.prototype[u]=!0,createClass(IterableSeq,IndexedSeq),IterableSeq.prototype.__iterateUncached=function(s,o){if(o)return this.cacheResult().__iterate(s,o);var i=getIterator(this._iterable),a=0;if(isIterator(i))for(var u;!(u=i.next()).done&&!1!==s(u.value,a++,this););return a},IterableSeq.prototype.__iteratorUncached=function(s,o){if(o)return this.cacheResult().__iterator(s,o);var i=getIterator(this._iterable);if(!isIterator(i))return new Iterator(iteratorDone);var a=0;return new Iterator((function(){var o=i.next();return o.done?o:iteratorValue(s,a++,o.value)}))},createClass(IteratorSeq,IndexedSeq),IteratorSeq.prototype.__iterateUncached=function(s,o){if(o)return this.cacheResult().__iterate(s,o);for(var i,a=this._iterator,u=this._iteratorCache,_=0;_=a.length){var o=i.next();if(o.done)return o;a[u]=o.value}return iteratorValue(s,u,a[u++])}))},createClass(Repeat,IndexedSeq),Repeat.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},Repeat.prototype.get=function(s,o){return this.has(s)?this._value:o},Repeat.prototype.includes=function(s){return is(this._value,s)},Repeat.prototype.slice=function(s,o){var i=this.size;return wholeSlice(s,o,i)?this:new Repeat(this._value,resolveEnd(o,i)-resolveBegin(s,i))},Repeat.prototype.reverse=function(){return this},Repeat.prototype.indexOf=function(s){return is(this._value,s)?0:-1},Repeat.prototype.lastIndexOf=function(s){return is(this._value,s)?this.size:-1},Repeat.prototype.__iterate=function(s,o){for(var i=0;i=0&&o=0&&ii?iteratorDone():iteratorValue(s,_++,w)}))},Range.prototype.equals=function(s){return s instanceof Range?this._start===s._start&&this._end===s._end&&this._step===s._step:deepEqual(this,s)},createClass(Collection,Iterable),createClass(KeyedCollection,Collection),createClass(IndexedCollection,Collection),createClass(SetCollection,Collection),Collection.Keyed=KeyedCollection,Collection.Indexed=IndexedCollection,Collection.Set=SetCollection;var le="function"==typeof Math.imul&&-2===Math.imul(4294967295,2)?Math.imul:function imul(s,o){var i=65535&(s|=0),a=65535&(o|=0);return i*a+((s>>>16)*a+i*(o>>>16)<<16>>>0)|0};function smi(s){return s>>>1&1073741824|3221225471&s}function hash(s){if(!1===s||null==s)return 0;if("function"==typeof s.valueOf&&(!1===(s=s.valueOf())||null==s))return 0;if(!0===s)return 1;var o=typeof s;if("number"===o){if(s!=s||s===1/0)return 0;var i=0|s;for(i!==s&&(i^=4294967295*s);s>4294967295;)i^=s/=4294967295;return smi(i)}if("string"===o)return s.length>Se?cachedHashString(s):hashString(s);if("function"==typeof s.hashCode)return s.hashCode();if("object"===o)return hashJSObj(s);if("function"==typeof s.toString)return hashString(s.toString());throw new Error("Value type "+o+" cannot be hashed.")}function cachedHashString(s){var o=Pe[s];return void 0===o&&(o=hashString(s),xe===we&&(xe=0,Pe={}),xe++,Pe[s]=o),o}function hashString(s){for(var o=0,i=0;i0)switch(s.nodeType){case 1:return s.uniqueID;case 9:return s.documentElement&&s.documentElement.uniqueID}}var fe,ye="function"==typeof WeakMap;ye&&(fe=new WeakMap);var be=0,_e="__immutablehash__";"function"==typeof Symbol&&(_e=Symbol(_e));var Se=16,we=255,xe=0,Pe={};function assertNotInfinite(s){invariant(s!==1/0,"Cannot perform this action with an infinite size.")}function Map(s){return null==s?emptyMap():isMap(s)&&!isOrdered(s)?s:emptyMap().withMutations((function(o){var i=KeyedIterable(s);assertNotInfinite(i.size),i.forEach((function(s,i){return o.set(i,s)}))}))}function isMap(s){return!(!s||!s[Re])}createClass(Map,KeyedCollection),Map.of=function(){var o=s.call(arguments,0);return emptyMap().withMutations((function(s){for(var i=0;i=o.length)throw new Error("Missing value for key: "+o[i]);s.set(o[i],o[i+1])}}))},Map.prototype.toString=function(){return this.__toString("Map {","}")},Map.prototype.get=function(s,o){return this._root?this._root.get(0,void 0,s,o):o},Map.prototype.set=function(s,o){return updateMap(this,s,o)},Map.prototype.setIn=function(s,o){return this.updateIn(s,j,(function(){return o}))},Map.prototype.remove=function(s){return updateMap(this,s,j)},Map.prototype.deleteIn=function(s){return this.updateIn(s,(function(){return j}))},Map.prototype.update=function(s,o,i){return 1===arguments.length?s(this):this.updateIn([s],o,i)},Map.prototype.updateIn=function(s,o,i){i||(i=o,o=void 0);var a=updateInDeepMap(this,forceIterator(s),o,i);return a===j?void 0:a},Map.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):emptyMap()},Map.prototype.merge=function(){return mergeIntoMapWith(this,void 0,arguments)},Map.prototype.mergeWith=function(o){return mergeIntoMapWith(this,o,s.call(arguments,1))},Map.prototype.mergeIn=function(o){var i=s.call(arguments,1);return this.updateIn(o,emptyMap(),(function(s){return"function"==typeof s.merge?s.merge.apply(s,i):i[i.length-1]}))},Map.prototype.mergeDeep=function(){return mergeIntoMapWith(this,deepMerger,arguments)},Map.prototype.mergeDeepWith=function(o){var i=s.call(arguments,1);return mergeIntoMapWith(this,deepMergerWith(o),i)},Map.prototype.mergeDeepIn=function(o){var i=s.call(arguments,1);return this.updateIn(o,emptyMap(),(function(s){return"function"==typeof s.mergeDeep?s.mergeDeep.apply(s,i):i[i.length-1]}))},Map.prototype.sort=function(s){return OrderedMap(sortFactory(this,s))},Map.prototype.sortBy=function(s,o){return OrderedMap(sortFactory(this,o,s))},Map.prototype.withMutations=function(s){var o=this.asMutable();return s(o),o.wasAltered()?o.__ensureOwner(this.__ownerID):this},Map.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new OwnerID)},Map.prototype.asImmutable=function(){return this.__ensureOwner()},Map.prototype.wasAltered=function(){return this.__altered},Map.prototype.__iterator=function(s,o){return new MapIterator(this,s,o)},Map.prototype.__iterate=function(s,o){var i=this,a=0;return this._root&&this._root.iterate((function(o){return a++,s(o[1],o[0],i)}),o),a},Map.prototype.__ensureOwner=function(s){return s===this.__ownerID?this:s?makeMap(this.size,this._root,s,this.__hash):(this.__ownerID=s,this.__altered=!1,this)},Map.isMap=isMap;var Te,Re="@@__IMMUTABLE_MAP__@@",qe=Map.prototype;function ArrayMapNode(s,o){this.ownerID=s,this.entries=o}function BitmapIndexedNode(s,o,i){this.ownerID=s,this.bitmap=o,this.nodes=i}function HashArrayMapNode(s,o,i){this.ownerID=s,this.count=o,this.nodes=i}function HashCollisionNode(s,o,i){this.ownerID=s,this.keyHash=o,this.entries=i}function ValueNode(s,o,i){this.ownerID=s,this.keyHash=o,this.entry=i}function MapIterator(s,o,i){this._type=o,this._reverse=i,this._stack=s._root&&mapIteratorFrame(s._root)}function mapIteratorValue(s,o){return iteratorValue(s,o[0],o[1])}function mapIteratorFrame(s,o){return{node:s,index:0,__prev:o}}function makeMap(s,o,i,a){var u=Object.create(qe);return u.size=s,u._root=o,u.__ownerID=i,u.__hash=a,u.__altered=!1,u}function emptyMap(){return Te||(Te=makeMap(0))}function updateMap(s,o,i){var a,u;if(s._root){var _=MakeRef(L),w=MakeRef(B);if(a=updateNode(s._root,s.__ownerID,0,void 0,o,i,_,w),!w.value)return s;u=s.size+(_.value?i===j?-1:1:0)}else{if(i===j)return s;u=1,a=new ArrayMapNode(s.__ownerID,[[o,i]])}return s.__ownerID?(s.size=u,s._root=a,s.__hash=void 0,s.__altered=!0,s):a?makeMap(u,a):emptyMap()}function updateNode(s,o,i,a,u,_,w,x){return s?s.update(o,i,a,u,_,w,x):_===j?s:(SetRef(x),SetRef(w),new ValueNode(o,a,[u,_]))}function isLeafNode(s){return s.constructor===ValueNode||s.constructor===HashCollisionNode}function mergeIntoNode(s,o,i,a,u){if(s.keyHash===a)return new HashCollisionNode(o,a,[s.entry,u]);var _,x=(0===i?s.keyHash:s.keyHash>>>i)&C,j=(0===i?a:a>>>i)&C;return new BitmapIndexedNode(o,1<>>=1)w[C]=1&i?o[_++]:void 0;return w[a]=u,new HashArrayMapNode(s,_+1,w)}function mergeIntoMapWith(s,o,i){for(var a=[],u=0;u>1&1431655765))+(s>>2&858993459))+(s>>4)&252645135,s+=s>>8,127&(s+=s>>16)}function setIn(s,o,i,a){var u=a?s:arrCopy(s);return u[o]=i,u}function spliceIn(s,o,i,a){var u=s.length+1;if(a&&o+1===u)return s[o]=i,s;for(var _=new Array(u),w=0,x=0;x=$e)return createNodes(s,C,a,u);var V=s&&s===this.ownerID,U=V?C:arrCopy(C);return $?x?L===B-1?U.pop():U[L]=U.pop():U[L]=[a,u]:U.push([a,u]),V?(this.entries=U,this):new ArrayMapNode(s,U)}},BitmapIndexedNode.prototype.get=function(s,o,i,a){void 0===o&&(o=hash(i));var u=1<<((0===s?o:o>>>s)&C),_=this.bitmap;return _&u?this.nodes[popCount(_&u-1)].get(s+w,o,i,a):a},BitmapIndexedNode.prototype.update=function(s,o,i,a,u,_,x){void 0===i&&(i=hash(a));var L=(0===o?i:i>>>o)&C,B=1<=ze)return expandNodes(s,z,$,L,Z);if(V&&!Z&&2===z.length&&isLeafNode(z[1^U]))return z[1^U];if(V&&Z&&1===z.length&&isLeafNode(Z))return Z;var ee=s&&s===this.ownerID,ie=V?Z?$:$^B:$|B,ae=V?Z?setIn(z,U,Z,ee):spliceOut(z,U,ee):spliceIn(z,U,Z,ee);return ee?(this.bitmap=ie,this.nodes=ae,this):new BitmapIndexedNode(s,ie,ae)},HashArrayMapNode.prototype.get=function(s,o,i,a){void 0===o&&(o=hash(i));var u=(0===s?o:o>>>s)&C,_=this.nodes[u];return _?_.get(s+w,o,i,a):a},HashArrayMapNode.prototype.update=function(s,o,i,a,u,_,x){void 0===i&&(i=hash(a));var L=(0===o?i:i>>>o)&C,B=u===j,$=this.nodes,V=$[L];if(B&&!V)return this;var U=updateNode(V,s,o+w,i,a,u,_,x);if(U===V)return this;var z=this.count;if(V){if(!U&&--z0&&a=0&&s>>o&C;if(a>=this.array.length)return new VNode([],s);var u,_=0===a;if(o>0){var x=this.array[a];if((u=x&&x.removeBefore(s,o-w,i))===x&&_)return this}if(_&&!u)return this;var j=editableVNode(this,s);if(!_)for(var L=0;L>>o&C;if(u>=this.array.length)return this;if(o>0){var _=this.array[u];if((a=_&&_.removeAfter(s,o-w,i))===_&&u===this.array.length-1)return this}var x=editableVNode(this,s);return x.array.splice(u+1),a&&(x.array[u]=a),x};var Ye,Qe,et={};function iterateList(s,o){var i=s._origin,a=s._capacity,u=getTailOffset(a),_=s._tail;return iterateNodeOrLeaf(s._root,s._level,0);function iterateNodeOrLeaf(s,o,i){return 0===o?iterateLeaf(s,i):iterateNode(s,o,i)}function iterateLeaf(s,w){var C=w===u?_&&_.array:s&&s.array,j=w>i?0:i-w,L=a-w;return L>x&&(L=x),function(){if(j===L)return et;var s=o?--L:j++;return C&&C[s]}}function iterateNode(s,u,_){var C,j=s&&s.array,L=_>i?0:i-_>>u,B=1+(a-_>>u);return B>x&&(B=x),function(){for(;;){if(C){var s=C();if(s!==et)return s;C=null}if(L===B)return et;var i=o?--B:L++;C=iterateNodeOrLeaf(j&&j[i],u-w,_+(i<=s.size||o<0)return s.withMutations((function(s){o<0?setListBounds(s,o).set(0,i):setListBounds(s,0,o+1).set(o,i)}));o+=s._origin;var a=s._tail,u=s._root,_=MakeRef(B);return o>=getTailOffset(s._capacity)?a=updateVNode(a,s.__ownerID,0,o,i,_):u=updateVNode(u,s.__ownerID,s._level,o,i,_),_.value?s.__ownerID?(s._root=u,s._tail=a,s.__hash=void 0,s.__altered=!0,s):makeList(s._origin,s._capacity,s._level,u,a):s}function updateVNode(s,o,i,a,u,_){var x,j=a>>>i&C,L=s&&j0){var B=s&&s.array[j],$=updateVNode(B,o,i-w,a,u,_);return $===B?s:((x=editableVNode(s,o)).array[j]=$,x)}return L&&s.array[j]===u?s:(SetRef(_),x=editableVNode(s,o),void 0===u&&j===x.array.length-1?x.array.pop():x.array[j]=u,x)}function editableVNode(s,o){return o&&s&&o===s.ownerID?s:new VNode(s?s.array.slice():[],o)}function listNodeFor(s,o){if(o>=getTailOffset(s._capacity))return s._tail;if(o<1<0;)i=i.array[o>>>a&C],a-=w;return i}}function setListBounds(s,o,i){void 0!==o&&(o|=0),void 0!==i&&(i|=0);var a=s.__ownerID||new OwnerID,u=s._origin,_=s._capacity,x=u+o,j=void 0===i?_:i<0?_+i:u+i;if(x===u&&j===_)return s;if(x>=j)return s.clear();for(var L=s._level,B=s._root,$=0;x+$<0;)B=new VNode(B&&B.array.length?[void 0,B]:[],a),$+=1<<(L+=w);$&&(x+=$,u+=$,j+=$,_+=$);for(var V=getTailOffset(_),U=getTailOffset(j);U>=1<V?new VNode([],a):z;if(z&&U>V&&x<_&&z.array.length){for(var Z=B=editableVNode(B,a),ee=L;ee>w;ee-=w){var ie=V>>>ee&C;Z=Z.array[ie]=editableVNode(Z.array[ie],a)}Z.array[V>>>w&C]=z}if(j<_&&(Y=Y&&Y.removeAfter(a,0,j)),x>=U)x-=U,j-=U,L=w,B=null,Y=Y&&Y.removeBefore(a,0,x);else if(x>u||U>>L&C;if(ae!==U>>>L&C)break;ae&&($+=(1<u&&(B=B.removeBefore(a,L,x-$)),B&&Uu&&(u=x.size),isIterable(w)||(x=x.map((function(s){return fromJS(s)}))),a.push(x)}return u>s.size&&(s=s.setSize(u)),mergeIntoCollectionWith(s,o,a)}function getTailOffset(s){return s>>w<=x&&w.size>=2*_.size?(a=(u=w.filter((function(s,o){return void 0!==s&&C!==o}))).toKeyedSeq().map((function(s){return s[0]})).flip().toMap(),s.__ownerID&&(a.__ownerID=u.__ownerID=s.__ownerID)):(a=_.remove(o),u=C===w.size-1?w.pop():w.set(C,void 0))}else if(L){if(i===w.get(C)[1])return s;a=_,u=w.set(C,[o,i])}else a=_.set(o,w.size),u=w.set(w.size,[o,i]);return s.__ownerID?(s.size=a.size,s._map=a,s._list=u,s.__hash=void 0,s):makeOrderedMap(a,u)}function ToKeyedSequence(s,o){this._iter=s,this._useKeys=o,this.size=s.size}function ToIndexedSequence(s){this._iter=s,this.size=s.size}function ToSetSequence(s){this._iter=s,this.size=s.size}function FromEntriesSequence(s){this._iter=s,this.size=s.size}function flipFactory(s){var o=makeSequence(s);return o._iter=s,o.size=s.size,o.flip=function(){return s},o.reverse=function(){var o=s.reverse.apply(this);return o.flip=function(){return s.reverse()},o},o.has=function(o){return s.includes(o)},o.includes=function(o){return s.has(o)},o.cacheResult=cacheResultThrough,o.__iterateUncached=function(o,i){var a=this;return s.__iterate((function(s,i){return!1!==o(i,s,a)}),i)},o.__iteratorUncached=function(o,i){if(o===U){var a=s.__iterator(o,i);return new Iterator((function(){var s=a.next();if(!s.done){var o=s.value[0];s.value[0]=s.value[1],s.value[1]=o}return s}))}return s.__iterator(o===V?$:V,i)},o}function mapFactory(s,o,i){var a=makeSequence(s);return a.size=s.size,a.has=function(o){return s.has(o)},a.get=function(a,u){var _=s.get(a,j);return _===j?u:o.call(i,_,a,s)},a.__iterateUncached=function(a,u){var _=this;return s.__iterate((function(s,u,w){return!1!==a(o.call(i,s,u,w),u,_)}),u)},a.__iteratorUncached=function(a,u){var _=s.__iterator(U,u);return new Iterator((function(){var u=_.next();if(u.done)return u;var w=u.value,x=w[0];return iteratorValue(a,x,o.call(i,w[1],x,s),u)}))},a}function reverseFactory(s,o){var i=makeSequence(s);return i._iter=s,i.size=s.size,i.reverse=function(){return s},s.flip&&(i.flip=function(){var o=flipFactory(s);return o.reverse=function(){return s.flip()},o}),i.get=function(i,a){return s.get(o?i:-1-i,a)},i.has=function(i){return s.has(o?i:-1-i)},i.includes=function(o){return s.includes(o)},i.cacheResult=cacheResultThrough,i.__iterate=function(o,i){var a=this;return s.__iterate((function(s,i){return o(s,i,a)}),!i)},i.__iterator=function(o,i){return s.__iterator(o,!i)},i}function filterFactory(s,o,i,a){var u=makeSequence(s);return a&&(u.has=function(a){var u=s.get(a,j);return u!==j&&!!o.call(i,u,a,s)},u.get=function(a,u){var _=s.get(a,j);return _!==j&&o.call(i,_,a,s)?_:u}),u.__iterateUncached=function(u,_){var w=this,x=0;return s.__iterate((function(s,_,C){if(o.call(i,s,_,C))return x++,u(s,a?_:x-1,w)}),_),x},u.__iteratorUncached=function(u,_){var w=s.__iterator(U,_),x=0;return new Iterator((function(){for(;;){var _=w.next();if(_.done)return _;var C=_.value,j=C[0],L=C[1];if(o.call(i,L,j,s))return iteratorValue(u,a?j:x++,L,_)}}))},u}function countByFactory(s,o,i){var a=Map().asMutable();return s.__iterate((function(u,_){a.update(o.call(i,u,_,s),0,(function(s){return s+1}))})),a.asImmutable()}function groupByFactory(s,o,i){var a=isKeyed(s),u=(isOrdered(s)?OrderedMap():Map()).asMutable();s.__iterate((function(_,w){u.update(o.call(i,_,w,s),(function(s){return(s=s||[]).push(a?[w,_]:_),s}))}));var _=iterableClass(s);return u.map((function(o){return reify(s,_(o))}))}function sliceFactory(s,o,i,a){var u=s.size;if(void 0!==o&&(o|=0),void 0!==i&&(i===1/0?i=u:i|=0),wholeSlice(o,i,u))return s;var _=resolveBegin(o,u),w=resolveEnd(i,u);if(_!=_||w!=w)return sliceFactory(s.toSeq().cacheResult(),o,i,a);var x,C=w-_;C==C&&(x=C<0?0:C);var j=makeSequence(s);return j.size=0===x?x:s.size&&x||void 0,!a&&isSeq(s)&&x>=0&&(j.get=function(o,i){return(o=wrapIndex(this,o))>=0&&ox)return iteratorDone();var s=u.next();return a||o===V?s:iteratorValue(o,C-1,o===$?void 0:s.value[1],s)}))},j}function takeWhileFactory(s,o,i){var a=makeSequence(s);return a.__iterateUncached=function(a,u){var _=this;if(u)return this.cacheResult().__iterate(a,u);var w=0;return s.__iterate((function(s,u,x){return o.call(i,s,u,x)&&++w&&a(s,u,_)})),w},a.__iteratorUncached=function(a,u){var _=this;if(u)return this.cacheResult().__iterator(a,u);var w=s.__iterator(U,u),x=!0;return new Iterator((function(){if(!x)return iteratorDone();var s=w.next();if(s.done)return s;var u=s.value,C=u[0],j=u[1];return o.call(i,j,C,_)?a===U?s:iteratorValue(a,C,j,s):(x=!1,iteratorDone())}))},a}function skipWhileFactory(s,o,i,a){var u=makeSequence(s);return u.__iterateUncached=function(u,_){var w=this;if(_)return this.cacheResult().__iterate(u,_);var x=!0,C=0;return s.__iterate((function(s,_,j){if(!x||!(x=o.call(i,s,_,j)))return C++,u(s,a?_:C-1,w)})),C},u.__iteratorUncached=function(u,_){var w=this;if(_)return this.cacheResult().__iterator(u,_);var x=s.__iterator(U,_),C=!0,j=0;return new Iterator((function(){var s,_,L;do{if((s=x.next()).done)return a||u===V?s:iteratorValue(u,j++,u===$?void 0:s.value[1],s);var B=s.value;_=B[0],L=B[1],C&&(C=o.call(i,L,_,w))}while(C);return u===U?s:iteratorValue(u,_,L,s)}))},u}function concatFactory(s,o){var i=isKeyed(s),a=[s].concat(o).map((function(s){return isIterable(s)?i&&(s=KeyedIterable(s)):s=i?keyedSeqFromValue(s):indexedSeqFromValue(Array.isArray(s)?s:[s]),s})).filter((function(s){return 0!==s.size}));if(0===a.length)return s;if(1===a.length){var u=a[0];if(u===s||i&&isKeyed(u)||isIndexed(s)&&isIndexed(u))return u}var _=new ArraySeq(a);return i?_=_.toKeyedSeq():isIndexed(s)||(_=_.toSetSeq()),(_=_.flatten(!0)).size=a.reduce((function(s,o){if(void 0!==s){var i=o.size;if(void 0!==i)return s+i}}),0),_}function flattenFactory(s,o,i){var a=makeSequence(s);return a.__iterateUncached=function(a,u){var _=0,w=!1;function flatDeep(s,x){var C=this;s.__iterate((function(s,u){return(!o||x0}function zipWithFactory(s,o,i){var a=makeSequence(s);return a.size=new ArraySeq(i).map((function(s){return s.size})).min(),a.__iterate=function(s,o){for(var i,a=this.__iterator(V,o),u=0;!(i=a.next()).done&&!1!==s(i.value,u++,this););return u},a.__iteratorUncached=function(s,a){var u=i.map((function(s){return s=Iterable(s),getIterator(a?s.reverse():s)})),_=0,w=!1;return new Iterator((function(){var i;return w||(i=u.map((function(s){return s.next()})),w=i.some((function(s){return s.done}))),w?iteratorDone():iteratorValue(s,_++,o.apply(null,i.map((function(s){return s.value}))))}))},a}function reify(s,o){return isSeq(s)?o:s.constructor(o)}function validateEntry(s){if(s!==Object(s))throw new TypeError("Expected [K, V] tuple: "+s)}function resolveSize(s){return assertNotInfinite(s.size),ensureSize(s)}function iterableClass(s){return isKeyed(s)?KeyedIterable:isIndexed(s)?IndexedIterable:SetIterable}function makeSequence(s){return Object.create((isKeyed(s)?KeyedSeq:isIndexed(s)?IndexedSeq:SetSeq).prototype)}function cacheResultThrough(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):Seq.prototype.cacheResult.call(this)}function defaultComparator(s,o){return s>o?1:s=0;i--)o={value:arguments[i],next:o};return this.__ownerID?(this.size=s,this._head=o,this.__hash=void 0,this.__altered=!0,this):makeStack(s,o)},Stack.prototype.pushAll=function(s){if(0===(s=IndexedIterable(s)).size)return this;assertNotInfinite(s.size);var o=this.size,i=this._head;return s.reverse().forEach((function(s){o++,i={value:s,next:i}})),this.__ownerID?(this.size=o,this._head=i,this.__hash=void 0,this.__altered=!0,this):makeStack(o,i)},Stack.prototype.pop=function(){return this.slice(1)},Stack.prototype.unshift=function(){return this.push.apply(this,arguments)},Stack.prototype.unshiftAll=function(s){return this.pushAll(s)},Stack.prototype.shift=function(){return this.pop.apply(this,arguments)},Stack.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):emptyStack()},Stack.prototype.slice=function(s,o){if(wholeSlice(s,o,this.size))return this;var i=resolveBegin(s,this.size);if(resolveEnd(o,this.size)!==this.size)return IndexedCollection.prototype.slice.call(this,s,o);for(var a=this.size-i,u=this._head;i--;)u=u.next;return this.__ownerID?(this.size=a,this._head=u,this.__hash=void 0,this.__altered=!0,this):makeStack(a,u)},Stack.prototype.__ensureOwner=function(s){return s===this.__ownerID?this:s?makeStack(this.size,this._head,s,this.__hash):(this.__ownerID=s,this.__altered=!1,this)},Stack.prototype.__iterate=function(s,o){if(o)return this.reverse().__iterate(s);for(var i=0,a=this._head;a&&!1!==s(a.value,i++,this);)a=a.next;return i},Stack.prototype.__iterator=function(s,o){if(o)return this.reverse().__iterator(s);var i=0,a=this._head;return new Iterator((function(){if(a){var o=a.value;return a=a.next,iteratorValue(s,i++,o)}return iteratorDone()}))},Stack.isStack=isStack;var at,ct="@@__IMMUTABLE_STACK__@@",lt=Stack.prototype;function makeStack(s,o,i,a){var u=Object.create(lt);return u.size=s,u._head=o,u.__ownerID=i,u.__hash=a,u.__altered=!1,u}function emptyStack(){return at||(at=makeStack(0))}function mixin(s,o){var keyCopier=function(i){s.prototype[i]=o[i]};return Object.keys(o).forEach(keyCopier),Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(o).forEach(keyCopier),s}lt[ct]=!0,lt.withMutations=qe.withMutations,lt.asMutable=qe.asMutable,lt.asImmutable=qe.asImmutable,lt.wasAltered=qe.wasAltered,Iterable.Iterator=Iterator,mixin(Iterable,{toArray:function(){assertNotInfinite(this.size);var s=new Array(this.size||0);return this.valueSeq().__iterate((function(o,i){s[i]=o})),s},toIndexedSeq:function(){return new ToIndexedSequence(this)},toJS:function(){return this.toSeq().map((function(s){return s&&"function"==typeof s.toJS?s.toJS():s})).__toJS()},toJSON:function(){return this.toSeq().map((function(s){return s&&"function"==typeof s.toJSON?s.toJSON():s})).__toJS()},toKeyedSeq:function(){return new ToKeyedSequence(this,!0)},toMap:function(){return Map(this.toKeyedSeq())},toObject:function(){assertNotInfinite(this.size);var s={};return this.__iterate((function(o,i){s[i]=o})),s},toOrderedMap:function(){return OrderedMap(this.toKeyedSeq())},toOrderedSet:function(){return OrderedSet(isKeyed(this)?this.valueSeq():this)},toSet:function(){return Set(isKeyed(this)?this.valueSeq():this)},toSetSeq:function(){return new ToSetSequence(this)},toSeq:function(){return isIndexed(this)?this.toIndexedSeq():isKeyed(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return Stack(isKeyed(this)?this.valueSeq():this)},toList:function(){return List(isKeyed(this)?this.valueSeq():this)},toString:function(){return"[Iterable]"},__toString:function(s,o){return 0===this.size?s+o:s+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+o},concat:function(){return reify(this,concatFactory(this,s.call(arguments,0)))},includes:function(s){return this.some((function(o){return is(o,s)}))},entries:function(){return this.__iterator(U)},every:function(s,o){assertNotInfinite(this.size);var i=!0;return this.__iterate((function(a,u,_){if(!s.call(o,a,u,_))return i=!1,!1})),i},filter:function(s,o){return reify(this,filterFactory(this,s,o,!0))},find:function(s,o,i){var a=this.findEntry(s,o);return a?a[1]:i},forEach:function(s,o){return assertNotInfinite(this.size),this.__iterate(o?s.bind(o):s)},join:function(s){assertNotInfinite(this.size),s=void 0!==s?""+s:",";var o="",i=!0;return this.__iterate((function(a){i?i=!1:o+=s,o+=null!=a?a.toString():""})),o},keys:function(){return this.__iterator($)},map:function(s,o){return reify(this,mapFactory(this,s,o))},reduce:function(s,o,i){var a,u;return assertNotInfinite(this.size),arguments.length<2?u=!0:a=o,this.__iterate((function(o,_,w){u?(u=!1,a=o):a=s.call(i,a,o,_,w)})),a},reduceRight:function(s,o,i){var a=this.toKeyedSeq().reverse();return a.reduce.apply(a,arguments)},reverse:function(){return reify(this,reverseFactory(this,!0))},slice:function(s,o){return reify(this,sliceFactory(this,s,o,!0))},some:function(s,o){return!this.every(not(s),o)},sort:function(s){return reify(this,sortFactory(this,s))},values:function(){return this.__iterator(V)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some((function(){return!0}))},count:function(s,o){return ensureSize(s?this.toSeq().filter(s,o):this)},countBy:function(s,o){return countByFactory(this,s,o)},equals:function(s){return deepEqual(this,s)},entrySeq:function(){var s=this;if(s._cache)return new ArraySeq(s._cache);var o=s.toSeq().map(entryMapper).toIndexedSeq();return o.fromEntrySeq=function(){return s.toSeq()},o},filterNot:function(s,o){return this.filter(not(s),o)},findEntry:function(s,o,i){var a=i;return this.__iterate((function(i,u,_){if(s.call(o,i,u,_))return a=[u,i],!1})),a},findKey:function(s,o){var i=this.findEntry(s,o);return i&&i[0]},findLast:function(s,o,i){return this.toKeyedSeq().reverse().find(s,o,i)},findLastEntry:function(s,o,i){return this.toKeyedSeq().reverse().findEntry(s,o,i)},findLastKey:function(s,o){return this.toKeyedSeq().reverse().findKey(s,o)},first:function(){return this.find(returnTrue)},flatMap:function(s,o){return reify(this,flatMapFactory(this,s,o))},flatten:function(s){return reify(this,flattenFactory(this,s,!0))},fromEntrySeq:function(){return new FromEntriesSequence(this)},get:function(s,o){return this.find((function(o,i){return is(i,s)}),void 0,o)},getIn:function(s,o){for(var i,a=this,u=forceIterator(s);!(i=u.next()).done;){var _=i.value;if((a=a&&a.get?a.get(_,j):j)===j)return o}return a},groupBy:function(s,o){return groupByFactory(this,s,o)},has:function(s){return this.get(s,j)!==j},hasIn:function(s){return this.getIn(s,j)!==j},isSubset:function(s){return s="function"==typeof s.includes?s:Iterable(s),this.every((function(o){return s.includes(o)}))},isSuperset:function(s){return(s="function"==typeof s.isSubset?s:Iterable(s)).isSubset(this)},keyOf:function(s){return this.findKey((function(o){return is(o,s)}))},keySeq:function(){return this.toSeq().map(keyMapper).toIndexedSeq()},last:function(){return this.toSeq().reverse().first()},lastKeyOf:function(s){return this.toKeyedSeq().reverse().keyOf(s)},max:function(s){return maxFactory(this,s)},maxBy:function(s,o){return maxFactory(this,o,s)},min:function(s){return maxFactory(this,s?neg(s):defaultNegComparator)},minBy:function(s,o){return maxFactory(this,o?neg(o):defaultNegComparator,s)},rest:function(){return this.slice(1)},skip:function(s){return this.slice(Math.max(0,s))},skipLast:function(s){return reify(this,this.toSeq().reverse().skip(s).reverse())},skipWhile:function(s,o){return reify(this,skipWhileFactory(this,s,o,!0))},skipUntil:function(s,o){return this.skipWhile(not(s),o)},sortBy:function(s,o){return reify(this,sortFactory(this,o,s))},take:function(s){return this.slice(0,Math.max(0,s))},takeLast:function(s){return reify(this,this.toSeq().reverse().take(s).reverse())},takeWhile:function(s,o){return reify(this,takeWhileFactory(this,s,o))},takeUntil:function(s,o){return this.takeWhile(not(s),o)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=hashIterable(this))}});var ut=Iterable.prototype;ut[o]=!0,ut[Z]=ut.values,ut.__toJS=ut.toArray,ut.__toStringMapper=quoteString,ut.inspect=ut.toSource=function(){return this.toString()},ut.chain=ut.flatMap,ut.contains=ut.includes,mixin(KeyedIterable,{flip:function(){return reify(this,flipFactory(this))},mapEntries:function(s,o){var i=this,a=0;return reify(this,this.toSeq().map((function(u,_){return s.call(o,[_,u],a++,i)})).fromEntrySeq())},mapKeys:function(s,o){var i=this;return reify(this,this.toSeq().flip().map((function(a,u){return s.call(o,a,u,i)})).flip())}});var pt=KeyedIterable.prototype;function keyMapper(s,o){return o}function entryMapper(s,o){return[o,s]}function not(s){return function(){return!s.apply(this,arguments)}}function neg(s){return function(){return-s.apply(this,arguments)}}function quoteString(s){return"string"==typeof s?JSON.stringify(s):String(s)}function defaultZipper(){return arrCopy(arguments)}function defaultNegComparator(s,o){return so?-1:0}function hashIterable(s){if(s.size===1/0)return 0;var o=isOrdered(s),i=isKeyed(s),a=o?1:0;return murmurHashOfSize(s.__iterate(i?o?function(s,o){a=31*a+hashMerge(hash(s),hash(o))|0}:function(s,o){a=a+hashMerge(hash(s),hash(o))|0}:o?function(s){a=31*a+hash(s)|0}:function(s){a=a+hash(s)|0}),a)}function murmurHashOfSize(s,o){return o=le(o,3432918353),o=le(o<<15|o>>>-15,461845907),o=le(o<<13|o>>>-13,5),o=le((o=o+3864292196^s)^o>>>16,2246822507),o=smi((o=le(o^o>>>13,3266489909))^o>>>16)}function hashMerge(s,o){return s^o+2654435769+(s<<6)+(s>>2)}return pt[i]=!0,pt[Z]=ut.entries,pt.__toJS=ut.toObject,pt.__toStringMapper=function(s,o){return JSON.stringify(o)+": "+quoteString(s)},mixin(IndexedIterable,{toKeyedSeq:function(){return new ToKeyedSequence(this,!1)},filter:function(s,o){return reify(this,filterFactory(this,s,o,!1))},findIndex:function(s,o){var i=this.findEntry(s,o);return i?i[0]:-1},indexOf:function(s){var o=this.keyOf(s);return void 0===o?-1:o},lastIndexOf:function(s){var o=this.lastKeyOf(s);return void 0===o?-1:o},reverse:function(){return reify(this,reverseFactory(this,!1))},slice:function(s,o){return reify(this,sliceFactory(this,s,o,!1))},splice:function(s,o){var i=arguments.length;if(o=Math.max(0|o,0),0===i||2===i&&!o)return this;s=resolveBegin(s,s<0?this.count():this.size);var a=this.slice(0,s);return reify(this,1===i?a:a.concat(arrCopy(arguments,2),this.slice(s+o)))},findLastIndex:function(s,o){var i=this.findLastEntry(s,o);return i?i[0]:-1},first:function(){return this.get(0)},flatten:function(s){return reify(this,flattenFactory(this,s,!1))},get:function(s,o){return(s=wrapIndex(this,s))<0||this.size===1/0||void 0!==this.size&&s>this.size?o:this.find((function(o,i){return i===s}),void 0,o)},has:function(s){return(s=wrapIndex(this,s))>=0&&(void 0!==this.size?this.size===1/0||s{"use strict";i(71340);var a=i(92046);s.exports=a.Object.assign},9999:(s,o,i)=>{var a=i(37217),u=i(83729),_=i(16547),w=i(74733),x=i(43838),C=i(93290),j=i(23007),L=i(92271),B=i(48948),$=i(50002),V=i(83349),U=i(5861),z=i(76189),Y=i(77199),Z=i(35529),ee=i(56449),ie=i(3656),ae=i(87730),ce=i(23805),le=i(38440),pe=i(95950),de=i(37241),fe="[object Arguments]",ye="[object Function]",be="[object Object]",_e={};_e[fe]=_e["[object Array]"]=_e["[object ArrayBuffer]"]=_e["[object DataView]"]=_e["[object Boolean]"]=_e["[object Date]"]=_e["[object Float32Array]"]=_e["[object Float64Array]"]=_e["[object Int8Array]"]=_e["[object Int16Array]"]=_e["[object Int32Array]"]=_e["[object Map]"]=_e["[object Number]"]=_e[be]=_e["[object RegExp]"]=_e["[object Set]"]=_e["[object String]"]=_e["[object Symbol]"]=_e["[object Uint8Array]"]=_e["[object Uint8ClampedArray]"]=_e["[object Uint16Array]"]=_e["[object Uint32Array]"]=!0,_e["[object Error]"]=_e[ye]=_e["[object WeakMap]"]=!1,s.exports=function baseClone(s,o,i,Se,we,xe){var Pe,Te=1&o,Re=2&o,qe=4&o;if(i&&(Pe=we?i(s,Se,we,xe):i(s)),void 0!==Pe)return Pe;if(!ce(s))return s;var $e=ee(s);if($e){if(Pe=z(s),!Te)return j(s,Pe)}else{var ze=U(s),We=ze==ye||"[object GeneratorFunction]"==ze;if(ie(s))return C(s,Te);if(ze==be||ze==fe||We&&!we){if(Pe=Re||We?{}:Z(s),!Te)return Re?B(s,x(Pe,s)):L(s,w(Pe,s))}else{if(!_e[ze])return we?s:{};Pe=Y(s,ze,Te)}}xe||(xe=new a);var He=xe.get(s);if(He)return He;xe.set(s,Pe),le(s)?s.forEach((function(a){Pe.add(baseClone(a,o,i,a,s,xe))})):ae(s)&&s.forEach((function(a,u){Pe.set(u,baseClone(a,o,i,u,s,xe))}));var Xe=$e?void 0:(qe?Re?V:$:Re?de:pe)(s);return u(Xe||s,(function(a,u){Xe&&(a=s[u=a]),_(Pe,u,baseClone(a,o,i,u,s,xe))})),Pe}},10023:(s,o,i)=>{const a=i(6205),INTS=()=>[{type:a.RANGE,from:48,to:57}],WORDS=()=>[{type:a.CHAR,value:95},{type:a.RANGE,from:97,to:122},{type:a.RANGE,from:65,to:90}].concat(INTS()),WHITESPACE=()=>[{type:a.CHAR,value:9},{type:a.CHAR,value:10},{type:a.CHAR,value:11},{type:a.CHAR,value:12},{type:a.CHAR,value:13},{type:a.CHAR,value:32},{type:a.CHAR,value:160},{type:a.CHAR,value:5760},{type:a.RANGE,from:8192,to:8202},{type:a.CHAR,value:8232},{type:a.CHAR,value:8233},{type:a.CHAR,value:8239},{type:a.CHAR,value:8287},{type:a.CHAR,value:12288},{type:a.CHAR,value:65279}];o.words=()=>({type:a.SET,set:WORDS(),not:!1}),o.notWords=()=>({type:a.SET,set:WORDS(),not:!0}),o.ints=()=>({type:a.SET,set:INTS(),not:!1}),o.notInts=()=>({type:a.SET,set:INTS(),not:!0}),o.whitespace=()=>({type:a.SET,set:WHITESPACE(),not:!1}),o.notWhitespace=()=>({type:a.SET,set:WHITESPACE(),not:!0}),o.anyChar=()=>({type:a.SET,set:[{type:a.CHAR,value:10},{type:a.CHAR,value:13},{type:a.CHAR,value:8232},{type:a.CHAR,value:8233}],not:!0})},10043:(s,o,i)=>{"use strict";var a=i(54018),u=String,_=TypeError;s.exports=function(s){if(a(s))return s;throw new _("Can't set "+u(s)+" as a prototype")}},10124:(s,o,i)=>{var a=i(9325);s.exports=function(){return a.Date.now()}},10300:(s,o,i)=>{"use strict";var a=i(13930),u=i(82159),_=i(36624),w=i(4640),x=i(73448),C=TypeError;s.exports=function(s,o){var i=arguments.length<2?x(s):o;if(u(i))return _(a(i,s));throw new C(w(s)+" is not iterable")}},10316:(s,o,i)=>{const a=i(2404),u=i(55973),_=i(92340);class Element{constructor(s,o,i){o&&(this.meta=o),i&&(this.attributes=i),this.content=s}freeze(){Object.isFrozen(this)||(this._meta&&(this.meta.parent=this,this.meta.freeze()),this._attributes&&(this.attributes.parent=this,this.attributes.freeze()),this.children.forEach((s=>{s.parent=this,s.freeze()}),this),this.content&&Array.isArray(this.content)&&Object.freeze(this.content),Object.freeze(this))}primitive(){}clone(){const s=new this.constructor;return s.element=this.element,this.meta.length&&(s._meta=this.meta.clone()),this.attributes.length&&(s._attributes=this.attributes.clone()),this.content?this.content.clone?s.content=this.content.clone():Array.isArray(this.content)?s.content=this.content.map((s=>s.clone())):s.content=this.content:s.content=this.content,s}toValue(){return this.content instanceof Element?this.content.toValue():this.content instanceof u?{key:this.content.key.toValue(),value:this.content.value?this.content.value.toValue():void 0}:this.content&&this.content.map?this.content.map((s=>s.toValue()),this):this.content}toRef(s){if(""===this.id.toValue())throw Error("Cannot create reference to an element that does not contain an ID");const o=new this.RefElement(this.id.toValue());return s&&(o.path=s),o}findRecursive(...s){if(arguments.length>1&&!this.isFrozen)throw new Error("Cannot find recursive with multiple element names without first freezing the element. Call `element.freeze()`");const o=s.pop();let i=new _;const append=(s,o)=>(s.push(o),s),checkElement=(s,i)=>{i.element===o&&s.push(i);const a=i.findRecursive(o);return a&&a.reduce(append,s),i.content instanceof u&&(i.content.key&&checkElement(s,i.content.key),i.content.value&&checkElement(s,i.content.value)),s};return this.content&&(this.content.element&&checkElement(i,this.content),Array.isArray(this.content)&&this.content.reduce(checkElement,i)),s.isEmpty||(i=i.filter((o=>{let i=o.parents.map((s=>s.element));for(const o in s){const a=s[o],u=i.indexOf(a);if(-1===u)return!1;i=i.splice(0,u)}return!0}))),i}set(s){return this.content=s,this}equals(s){return a(this.toValue(),s)}getMetaProperty(s,o){if(!this.meta.hasKey(s)){if(this.isFrozen){const s=this.refract(o);return s.freeze(),s}this.meta.set(s,o)}return this.meta.get(s)}setMetaProperty(s,o){this.meta.set(s,o)}get element(){return this._storedElement||"element"}set element(s){this._storedElement=s}get content(){return this._content}set content(s){if(s instanceof Element)this._content=s;else if(s instanceof _)this.content=s.elements;else if("string"==typeof s||"number"==typeof s||"boolean"==typeof s||"null"===s||null==s)this._content=s;else if(s instanceof u)this._content=s;else if(Array.isArray(s))this._content=s.map(this.refract);else{if("object"!=typeof s)throw new Error("Cannot set content to given value");this._content=Object.keys(s).map((o=>new this.MemberElement(o,s[o])))}}get meta(){if(!this._meta){if(this.isFrozen){const s=new this.ObjectElement;return s.freeze(),s}this._meta=new this.ObjectElement}return this._meta}set meta(s){s instanceof this.ObjectElement?this._meta=s:this.meta.set(s||{})}get attributes(){if(!this._attributes){if(this.isFrozen){const s=new this.ObjectElement;return s.freeze(),s}this._attributes=new this.ObjectElement}return this._attributes}set attributes(s){s instanceof this.ObjectElement?this._attributes=s:this.attributes.set(s||{})}get id(){return this.getMetaProperty("id","")}set id(s){this.setMetaProperty("id",s)}get classes(){return this.getMetaProperty("classes",[])}set classes(s){this.setMetaProperty("classes",s)}get title(){return this.getMetaProperty("title","")}set title(s){this.setMetaProperty("title",s)}get description(){return this.getMetaProperty("description","")}set description(s){this.setMetaProperty("description",s)}get links(){return this.getMetaProperty("links",[])}set links(s){this.setMetaProperty("links",s)}get isFrozen(){return Object.isFrozen(this)}get parents(){let{parent:s}=this;const o=new _;for(;s;)o.push(s),s=s.parent;return o}get children(){if(Array.isArray(this.content))return new _(this.content);if(this.content instanceof u){const s=new _([this.content.key]);return this.content.value&&s.push(this.content.value),s}return this.content instanceof Element?new _([this.content]):new _}get recursiveChildren(){const s=new _;return this.children.forEach((o=>{s.push(o),o.recursiveChildren.forEach((o=>{s.push(o)}))})),s}}s.exports=Element},10392:s=>{s.exports=function getValue(s,o){return null==s?void 0:s[o]}},10776:(s,o,i)=>{var a=i(30756),u=i(95950);s.exports=function getMatchData(s){for(var o=u(s),i=o.length;i--;){var _=o[i],w=s[_];o[i]=[_,w,a(w)]}return o}},10866:(s,o,i)=>{const a=i(6048),u=i(92340);class ObjectSlice extends u{map(s,o){return this.elements.map((i=>s.bind(o)(i.value,i.key,i)))}filter(s,o){return new ObjectSlice(this.elements.filter((i=>s.bind(o)(i.value,i.key,i))))}reject(s,o){return this.filter(a(s.bind(o)))}forEach(s,o){return this.elements.forEach(((i,a)=>{s.bind(o)(i.value,i.key,i,a)}))}keys(){return this.map(((s,o)=>o.toValue()))}values(){return this.map((s=>s.toValue()))}}s.exports=ObjectSlice},11042:(s,o,i)=>{"use strict";var a=i(85582),u=i(1907),_=i(24443),w=i(87170),x=i(36624),C=u([].concat);s.exports=a("Reflect","ownKeys")||function ownKeys(s){var o=_.f(x(s)),i=w.f;return i?C(o,i(s)):o}},11091:(s,o,i)=>{"use strict";var a=i(45951),u=i(76024),_=i(92361),w=i(62250),x=i(13846).f,C=i(7463),j=i(92046),L=i(28311),B=i(61626),$=i(49724);i(36128);var wrapConstructor=function(s){var Wrapper=function(o,i,a){if(this instanceof Wrapper){switch(arguments.length){case 0:return new s;case 1:return new s(o);case 2:return new s(o,i)}return new s(o,i,a)}return u(s,this,arguments)};return Wrapper.prototype=s.prototype,Wrapper};s.exports=function(s,o){var i,u,V,U,z,Y,Z,ee,ie,ae=s.target,ce=s.global,le=s.stat,pe=s.proto,de=ce?a:le?a[ae]:a[ae]&&a[ae].prototype,fe=ce?j:j[ae]||B(j,ae,{})[ae],ye=fe.prototype;for(U in o)u=!(i=C(ce?U:ae+(le?".":"#")+U,s.forced))&&de&&$(de,U),Y=fe[U],u&&(Z=s.dontCallGetSet?(ie=x(de,U))&&ie.value:de[U]),z=u&&Z?Z:o[U],(i||pe||typeof Y!=typeof z)&&(ee=s.bind&&u?L(z,a):s.wrap&&u?wrapConstructor(z):pe&&w(z)?_(z):z,(s.sham||z&&z.sham||Y&&Y.sham)&&B(ee,"sham",!0),B(fe,U,ee),pe&&($(j,V=ae+"Prototype")||B(j,V,{}),B(j[V],U,z),s.real&&ye&&(i||!ye[U])&&B(ye,U,z)))}},11287:s=>{s.exports=function getHolder(s){return s.placeholder}},11331:(s,o,i)=>{var a=i(72552),u=i(28879),_=i(40346),w=Function.prototype,x=Object.prototype,C=w.toString,j=x.hasOwnProperty,L=C.call(Object);s.exports=function isPlainObject(s){if(!_(s)||"[object Object]"!=a(s))return!1;var o=u(s);if(null===o)return!0;var i=j.call(o,"constructor")&&o.constructor;return"function"==typeof i&&i instanceof i&&C.call(i)==L}},11470:(s,o,i)=>{"use strict";var a=i(1907),u=i(65482),_=i(90160),w=i(74239),x=a("".charAt),C=a("".charCodeAt),j=a("".slice),createMethod=function(s){return function(o,i){var a,L,B=_(w(o)),$=u(i),V=B.length;return $<0||$>=V?s?"":void 0:(a=C(B,$))<55296||a>56319||$+1===V||(L=C(B,$+1))<56320||L>57343?s?x(B,$):a:s?j(B,$,$+2):L-56320+(a-55296<<10)+65536}};s.exports={codeAt:createMethod(!1),charAt:createMethod(!0)}},11842:(s,o,i)=>{var a=i(82819),u=i(9325);s.exports=function createBind(s,o,i){var _=1&o,w=a(s);return function wrapper(){return(this&&this!==u&&this instanceof wrapper?w:s).apply(_?i:this,arguments)}}},12242:(s,o,i)=>{const a=i(10316);s.exports=class BooleanElement extends a{constructor(s,o,i){super(s,o,i),this.element="boolean"}primitive(){return"boolean"}}},12507:(s,o,i)=>{var a=i(28754),u=i(49698),_=i(63912),w=i(13222);s.exports=function createCaseFirst(s){return function(o){o=w(o);var i=u(o)?_(o):void 0,x=i?i[0]:o.charAt(0),C=i?a(i,1).join(""):o.slice(1);return x[s]()+C}}},12560:(s,o,i)=>{"use strict";i(99363);var a=i(19287),u=i(45951),_=i(14840),w=i(93742);for(var x in a)_(u[x],x),w[x]=w.Array},12651:(s,o,i)=>{var a=i(74218);s.exports=function getMapData(s,o){var i=s.__data__;return a(o)?i["string"==typeof o?"string":"hash"]:i.map}},12749:(s,o,i)=>{var a=i(81042),u=Object.prototype.hasOwnProperty;s.exports=function hashHas(s){var o=this.__data__;return a?void 0!==o[s]:u.call(o,s)}},13222:(s,o,i)=>{var a=i(77556);s.exports=function toString(s){return null==s?"":a(s)}},13846:(s,o,i)=>{"use strict";var a=i(39447),u=i(13930),_=i(22574),w=i(75817),x=i(4993),C=i(70470),j=i(49724),L=i(73648),B=Object.getOwnPropertyDescriptor;o.f=a?B:function getOwnPropertyDescriptor(s,o){if(s=x(s),o=C(o),L)try{return B(s,o)}catch(s){}if(j(s,o))return w(!u(_.f,s,o),s[o])}},13930:(s,o,i)=>{"use strict";var a=i(41505),u=Function.prototype.call;s.exports=a?u.bind(u):function(){return u.apply(u,arguments)}},14248:s=>{s.exports=function arraySome(s,o){for(var i=-1,a=null==s?0:s.length;++i{s.exports=function arrayPush(s,o){for(var i=-1,a=o.length,u=s.length;++i{const a=i(10316);s.exports=class RefElement extends a{constructor(s,o,i){super(s||[],o,i),this.element="ref",this.path||(this.path="element")}get path(){return this.attributes.get("path")}set path(s){this.attributes.set("path",s)}}},14744:s=>{"use strict";var o=function isMergeableObject(s){return function isNonNullObject(s){return!!s&&"object"==typeof s}(s)&&!function isSpecial(s){var o=Object.prototype.toString.call(s);return"[object RegExp]"===o||"[object Date]"===o||function isReactElement(s){return s.$$typeof===i}(s)}(s)};var i="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function cloneUnlessOtherwiseSpecified(s,o){return!1!==o.clone&&o.isMergeableObject(s)?deepmerge(function emptyTarget(s){return Array.isArray(s)?[]:{}}(s),s,o):s}function defaultArrayMerge(s,o,i){return s.concat(o).map((function(s){return cloneUnlessOtherwiseSpecified(s,i)}))}function getKeys(s){return Object.keys(s).concat(function getEnumerableOwnPropertySymbols(s){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(s).filter((function(o){return Object.propertyIsEnumerable.call(s,o)})):[]}(s))}function propertyIsOnObject(s,o){try{return o in s}catch(s){return!1}}function mergeObject(s,o,i){var a={};return i.isMergeableObject(s)&&getKeys(s).forEach((function(o){a[o]=cloneUnlessOtherwiseSpecified(s[o],i)})),getKeys(o).forEach((function(u){(function propertyIsUnsafe(s,o){return propertyIsOnObject(s,o)&&!(Object.hasOwnProperty.call(s,o)&&Object.propertyIsEnumerable.call(s,o))})(s,u)||(propertyIsOnObject(s,u)&&i.isMergeableObject(o[u])?a[u]=function getMergeFunction(s,o){if(!o.customMerge)return deepmerge;var i=o.customMerge(s);return"function"==typeof i?i:deepmerge}(u,i)(s[u],o[u],i):a[u]=cloneUnlessOtherwiseSpecified(o[u],i))})),a}function deepmerge(s,i,a){(a=a||{}).arrayMerge=a.arrayMerge||defaultArrayMerge,a.isMergeableObject=a.isMergeableObject||o,a.cloneUnlessOtherwiseSpecified=cloneUnlessOtherwiseSpecified;var u=Array.isArray(i);return u===Array.isArray(s)?u?a.arrayMerge(s,i,a):mergeObject(s,i,a):cloneUnlessOtherwiseSpecified(i,a)}deepmerge.all=function deepmergeAll(s,o){if(!Array.isArray(s))throw new Error("first argument should be an array");return s.reduce((function(s,i){return deepmerge(s,i,o)}),{})};var a=deepmerge;s.exports=a},14792:(s,o,i)=>{var a=i(13222),u=i(55808);s.exports=function capitalize(s){return u(a(s).toLowerCase())}},14840:(s,o,i)=>{"use strict";var a=i(52623),u=i(74284).f,_=i(61626),w=i(49724),x=i(54878),C=i(76264)("toStringTag");s.exports=function(s,o,i,j){var L=i?s:s&&s.prototype;L&&(w(L,C)||u(L,C,{configurable:!0,value:o}),j&&!a&&_(L,"toString",x))}},14974:s=>{s.exports=function safeGet(s,o){if(("constructor"!==o||"function"!=typeof s[o])&&"__proto__"!=o)return s[o]}},15287:(s,o)=>{"use strict";var i=Symbol.for("react.element"),a=Symbol.for("react.portal"),u=Symbol.for("react.fragment"),_=Symbol.for("react.strict_mode"),w=Symbol.for("react.profiler"),x=Symbol.for("react.provider"),C=Symbol.for("react.context"),j=Symbol.for("react.forward_ref"),L=Symbol.for("react.suspense"),B=Symbol.for("react.memo"),$=Symbol.for("react.lazy"),V=Symbol.iterator;var U={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},z=Object.assign,Y={};function E(s,o,i){this.props=s,this.context=o,this.refs=Y,this.updater=i||U}function F(){}function G(s,o,i){this.props=s,this.context=o,this.refs=Y,this.updater=i||U}E.prototype.isReactComponent={},E.prototype.setState=function(s,o){if("object"!=typeof s&&"function"!=typeof s&&null!=s)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,s,o,"setState")},E.prototype.forceUpdate=function(s){this.updater.enqueueForceUpdate(this,s,"forceUpdate")},F.prototype=E.prototype;var Z=G.prototype=new F;Z.constructor=G,z(Z,E.prototype),Z.isPureReactComponent=!0;var ee=Array.isArray,ie=Object.prototype.hasOwnProperty,ae={current:null},ce={key:!0,ref:!0,__self:!0,__source:!0};function M(s,o,a){var u,_={},w=null,x=null;if(null!=o)for(u in void 0!==o.ref&&(x=o.ref),void 0!==o.key&&(w=""+o.key),o)ie.call(o,u)&&!ce.hasOwnProperty(u)&&(_[u]=o[u]);var C=arguments.length-2;if(1===C)_.children=a;else if(1{var a=i(96131);s.exports=function arrayIncludes(s,o){return!!(null==s?0:s.length)&&a(s,o,0)>-1}},15340:()=>{},15389:(s,o,i)=>{var a=i(93663),u=i(87978),_=i(83488),w=i(56449),x=i(50583);s.exports=function baseIteratee(s){return"function"==typeof s?s:null==s?_:"object"==typeof s?w(s)?u(s[0],s[1]):a(s):x(s)}},15972:(s,o,i)=>{"use strict";var a=i(49724),u=i(62250),_=i(39298),w=i(92522),x=i(57382),C=w("IE_PROTO"),j=Object,L=j.prototype;s.exports=x?j.getPrototypeOf:function(s){var o=_(s);if(a(o,C))return o[C];var i=o.constructor;return u(i)&&o instanceof i?i.prototype:o instanceof j?L:null}},16038:(s,o,i)=>{var a=i(5861),u=i(40346);s.exports=function baseIsSet(s){return u(s)&&"[object Set]"==a(s)}},16426:s=>{s.exports=function(){var s=document.getSelection();if(!s.rangeCount)return function(){};for(var o=document.activeElement,i=[],a=0;a{var a=i(43360),u=i(75288),_=Object.prototype.hasOwnProperty;s.exports=function assignValue(s,o,i){var w=s[o];_.call(s,o)&&u(w,i)&&(void 0!==i||o in s)||a(s,o,i)}},16708:(s,o,i)=>{"use strict";var a,u=i(65606);function CorkedRequest(s){var o=this;this.next=null,this.entry=null,this.finish=function(){!function onCorkedFinish(s,o,i){var a=s.entry;s.entry=null;for(;a;){var u=a.callback;o.pendingcb--,u(i),a=a.next}o.corkedRequestsFree.next=s}(o,s)}}s.exports=Writable,Writable.WritableState=WritableState;var _={deprecate:i(94643)},w=i(40345),x=i(48287).Buffer,C=(void 0!==i.g?i.g:"undefined"!=typeof window?window:"undefined"!=typeof self?self:{}).Uint8Array||function(){};var j,L=i(75896),B=i(65291).getHighWaterMark,$=i(86048).F,V=$.ERR_INVALID_ARG_TYPE,U=$.ERR_METHOD_NOT_IMPLEMENTED,z=$.ERR_MULTIPLE_CALLBACK,Y=$.ERR_STREAM_CANNOT_PIPE,Z=$.ERR_STREAM_DESTROYED,ee=$.ERR_STREAM_NULL_VALUES,ie=$.ERR_STREAM_WRITE_AFTER_END,ae=$.ERR_UNKNOWN_ENCODING,ce=L.errorOrDestroy;function nop(){}function WritableState(s,o,_){a=a||i(25382),s=s||{},"boolean"!=typeof _&&(_=o instanceof a),this.objectMode=!!s.objectMode,_&&(this.objectMode=this.objectMode||!!s.writableObjectMode),this.highWaterMark=B(this,s,"writableHighWaterMark",_),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var w=!1===s.decodeStrings;this.decodeStrings=!w,this.defaultEncoding=s.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(s){!function onwrite(s,o){var i=s._writableState,a=i.sync,_=i.writecb;if("function"!=typeof _)throw new z;if(function onwriteStateUpdate(s){s.writing=!1,s.writecb=null,s.length-=s.writelen,s.writelen=0}(i),o)!function onwriteError(s,o,i,a,_){--o.pendingcb,i?(u.nextTick(_,a),u.nextTick(finishMaybe,s,o),s._writableState.errorEmitted=!0,ce(s,a)):(_(a),s._writableState.errorEmitted=!0,ce(s,a),finishMaybe(s,o))}(s,i,a,o,_);else{var w=needFinish(i)||s.destroyed;w||i.corked||i.bufferProcessing||!i.bufferedRequest||clearBuffer(s,i),a?u.nextTick(afterWrite,s,i,w,_):afterWrite(s,i,w,_)}}(o,s)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=!1!==s.emitClose,this.autoDestroy=!!s.autoDestroy,this.bufferedRequestCount=0,this.corkedRequestsFree=new CorkedRequest(this)}function Writable(s){var o=this instanceof(a=a||i(25382));if(!o&&!j.call(Writable,this))return new Writable(s);this._writableState=new WritableState(s,this,o),this.writable=!0,s&&("function"==typeof s.write&&(this._write=s.write),"function"==typeof s.writev&&(this._writev=s.writev),"function"==typeof s.destroy&&(this._destroy=s.destroy),"function"==typeof s.final&&(this._final=s.final)),w.call(this)}function doWrite(s,o,i,a,u,_,w){o.writelen=a,o.writecb=w,o.writing=!0,o.sync=!0,o.destroyed?o.onwrite(new Z("write")):i?s._writev(u,o.onwrite):s._write(u,_,o.onwrite),o.sync=!1}function afterWrite(s,o,i,a){i||function onwriteDrain(s,o){0===o.length&&o.needDrain&&(o.needDrain=!1,s.emit("drain"))}(s,o),o.pendingcb--,a(),finishMaybe(s,o)}function clearBuffer(s,o){o.bufferProcessing=!0;var i=o.bufferedRequest;if(s._writev&&i&&i.next){var a=o.bufferedRequestCount,u=new Array(a),_=o.corkedRequestsFree;_.entry=i;for(var w=0,x=!0;i;)u[w]=i,i.isBuf||(x=!1),i=i.next,w+=1;u.allBuffers=x,doWrite(s,o,!0,o.length,u,"",_.finish),o.pendingcb++,o.lastBufferedRequest=null,_.next?(o.corkedRequestsFree=_.next,_.next=null):o.corkedRequestsFree=new CorkedRequest(o),o.bufferedRequestCount=0}else{for(;i;){var C=i.chunk,j=i.encoding,L=i.callback;if(doWrite(s,o,!1,o.objectMode?1:C.length,C,j,L),i=i.next,o.bufferedRequestCount--,o.writing)break}null===i&&(o.lastBufferedRequest=null)}o.bufferedRequest=i,o.bufferProcessing=!1}function needFinish(s){return s.ending&&0===s.length&&null===s.bufferedRequest&&!s.finished&&!s.writing}function callFinal(s,o){s._final((function(i){o.pendingcb--,i&&ce(s,i),o.prefinished=!0,s.emit("prefinish"),finishMaybe(s,o)}))}function finishMaybe(s,o){var i=needFinish(o);if(i&&(function prefinish(s,o){o.prefinished||o.finalCalled||("function"!=typeof s._final||o.destroyed?(o.prefinished=!0,s.emit("prefinish")):(o.pendingcb++,o.finalCalled=!0,u.nextTick(callFinal,s,o)))}(s,o),0===o.pendingcb&&(o.finished=!0,s.emit("finish"),o.autoDestroy))){var a=s._readableState;(!a||a.autoDestroy&&a.endEmitted)&&s.destroy()}return i}i(56698)(Writable,w),WritableState.prototype.getBuffer=function getBuffer(){for(var s=this.bufferedRequest,o=[];s;)o.push(s),s=s.next;return o},function(){try{Object.defineProperty(WritableState.prototype,"buffer",{get:_.deprecate((function writableStateBufferGetter(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(s){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(j=Function.prototype[Symbol.hasInstance],Object.defineProperty(Writable,Symbol.hasInstance,{value:function value(s){return!!j.call(this,s)||this===Writable&&(s&&s._writableState instanceof WritableState)}})):j=function realHasInstance(s){return s instanceof this},Writable.prototype.pipe=function(){ce(this,new Y)},Writable.prototype.write=function(s,o,i){var a=this._writableState,_=!1,w=!a.objectMode&&function _isUint8Array(s){return x.isBuffer(s)||s instanceof C}(s);return w&&!x.isBuffer(s)&&(s=function _uint8ArrayToBuffer(s){return x.from(s)}(s)),"function"==typeof o&&(i=o,o=null),w?o="buffer":o||(o=a.defaultEncoding),"function"!=typeof i&&(i=nop),a.ending?function writeAfterEnd(s,o){var i=new ie;ce(s,i),u.nextTick(o,i)}(this,i):(w||function validChunk(s,o,i,a){var _;return null===i?_=new ee:"string"==typeof i||o.objectMode||(_=new V("chunk",["string","Buffer"],i)),!_||(ce(s,_),u.nextTick(a,_),!1)}(this,a,s,i))&&(a.pendingcb++,_=function writeOrBuffer(s,o,i,a,u,_){if(!i){var w=function decodeChunk(s,o,i){s.objectMode||!1===s.decodeStrings||"string"!=typeof o||(o=x.from(o,i));return o}(o,a,u);a!==w&&(i=!0,u="buffer",a=w)}var C=o.objectMode?1:a.length;o.length+=C;var j=o.length-1))throw new ae(s);return this._writableState.defaultEncoding=s,this},Object.defineProperty(Writable.prototype,"writableBuffer",{enumerable:!1,get:function get(){return this._writableState&&this._writableState.getBuffer()}}),Object.defineProperty(Writable.prototype,"writableHighWaterMark",{enumerable:!1,get:function get(){return this._writableState.highWaterMark}}),Writable.prototype._write=function(s,o,i){i(new U("_write()"))},Writable.prototype._writev=null,Writable.prototype.end=function(s,o,i){var a=this._writableState;return"function"==typeof s?(i=s,s=null,o=null):"function"==typeof o&&(i=o,o=null),null!=s&&this.write(s,o),a.corked&&(a.corked=1,this.uncork()),a.ending||function endWritable(s,o,i){o.ending=!0,finishMaybe(s,o),i&&(o.finished?u.nextTick(i):s.once("finish",i));o.ended=!0,s.writable=!1}(this,a,i),this},Object.defineProperty(Writable.prototype,"writableLength",{enumerable:!1,get:function get(){return this._writableState.length}}),Object.defineProperty(Writable.prototype,"destroyed",{enumerable:!1,get:function get(){return void 0!==this._writableState&&this._writableState.destroyed},set:function set(s){this._writableState&&(this._writableState.destroyed=s)}}),Writable.prototype.destroy=L.destroy,Writable.prototype._undestroy=L.undestroy,Writable.prototype._destroy=function(s,o){o(s)}},16946:(s,o,i)=>{"use strict";var a=i(1907),u=i(98828),_=i(45807),w=Object,x=a("".split);s.exports=u((function(){return!w("z").propertyIsEnumerable(0)}))?function(s){return"String"===_(s)?x(s,""):w(s)}:w},16962:(s,o)=>{o.aliasToReal={each:"forEach",eachRight:"forEachRight",entries:"toPairs",entriesIn:"toPairsIn",extend:"assignIn",extendAll:"assignInAll",extendAllWith:"assignInAllWith",extendWith:"assignInWith",first:"head",conforms:"conformsTo",matches:"isMatch",property:"get",__:"placeholder",F:"stubFalse",T:"stubTrue",all:"every",allPass:"overEvery",always:"constant",any:"some",anyPass:"overSome",apply:"spread",assoc:"set",assocPath:"set",complement:"negate",compose:"flowRight",contains:"includes",dissoc:"unset",dissocPath:"unset",dropLast:"dropRight",dropLastWhile:"dropRightWhile",equals:"isEqual",identical:"eq",indexBy:"keyBy",init:"initial",invertObj:"invert",juxt:"over",omitAll:"omit",nAry:"ary",path:"get",pathEq:"matchesProperty",pathOr:"getOr",paths:"at",pickAll:"pick",pipe:"flow",pluck:"map",prop:"get",propEq:"matchesProperty",propOr:"getOr",props:"at",symmetricDifference:"xor",symmetricDifferenceBy:"xorBy",symmetricDifferenceWith:"xorWith",takeLast:"takeRight",takeLastWhile:"takeRightWhile",unapply:"rest",unnest:"flatten",useWith:"overArgs",where:"conformsTo",whereEq:"isMatch",zipObj:"zipObject"},o.aryMethod={1:["assignAll","assignInAll","attempt","castArray","ceil","create","curry","curryRight","defaultsAll","defaultsDeepAll","floor","flow","flowRight","fromPairs","invert","iteratee","memoize","method","mergeAll","methodOf","mixin","nthArg","over","overEvery","overSome","rest","reverse","round","runInContext","spread","template","trim","trimEnd","trimStart","uniqueId","words","zipAll"],2:["add","after","ary","assign","assignAllWith","assignIn","assignInAllWith","at","before","bind","bindAll","bindKey","chunk","cloneDeepWith","cloneWith","concat","conformsTo","countBy","curryN","curryRightN","debounce","defaults","defaultsDeep","defaultTo","delay","difference","divide","drop","dropRight","dropRightWhile","dropWhile","endsWith","eq","every","filter","find","findIndex","findKey","findLast","findLastIndex","findLastKey","flatMap","flatMapDeep","flattenDepth","forEach","forEachRight","forIn","forInRight","forOwn","forOwnRight","get","groupBy","gt","gte","has","hasIn","includes","indexOf","intersection","invertBy","invoke","invokeMap","isEqual","isMatch","join","keyBy","lastIndexOf","lt","lte","map","mapKeys","mapValues","matchesProperty","maxBy","meanBy","merge","mergeAllWith","minBy","multiply","nth","omit","omitBy","overArgs","pad","padEnd","padStart","parseInt","partial","partialRight","partition","pick","pickBy","propertyOf","pull","pullAll","pullAt","random","range","rangeRight","rearg","reject","remove","repeat","restFrom","result","sampleSize","some","sortBy","sortedIndex","sortedIndexOf","sortedLastIndex","sortedLastIndexOf","sortedUniqBy","split","spreadFrom","startsWith","subtract","sumBy","take","takeRight","takeRightWhile","takeWhile","tap","throttle","thru","times","trimChars","trimCharsEnd","trimCharsStart","truncate","union","uniqBy","uniqWith","unset","unzipWith","without","wrap","xor","zip","zipObject","zipObjectDeep"],3:["assignInWith","assignWith","clamp","differenceBy","differenceWith","findFrom","findIndexFrom","findLastFrom","findLastIndexFrom","getOr","includesFrom","indexOfFrom","inRange","intersectionBy","intersectionWith","invokeArgs","invokeArgsMap","isEqualWith","isMatchWith","flatMapDepth","lastIndexOfFrom","mergeWith","orderBy","padChars","padCharsEnd","padCharsStart","pullAllBy","pullAllWith","rangeStep","rangeStepRight","reduce","reduceRight","replace","set","slice","sortedIndexBy","sortedLastIndexBy","transform","unionBy","unionWith","update","xorBy","xorWith","zipWith"],4:["fill","setWith","updateWith"]},o.aryRearg={2:[1,0],3:[2,0,1],4:[3,2,0,1]},o.iterateeAry={dropRightWhile:1,dropWhile:1,every:1,filter:1,find:1,findFrom:1,findIndex:1,findIndexFrom:1,findKey:1,findLast:1,findLastFrom:1,findLastIndex:1,findLastIndexFrom:1,findLastKey:1,flatMap:1,flatMapDeep:1,flatMapDepth:1,forEach:1,forEachRight:1,forIn:1,forInRight:1,forOwn:1,forOwnRight:1,map:1,mapKeys:1,mapValues:1,partition:1,reduce:2,reduceRight:2,reject:1,remove:1,some:1,takeRightWhile:1,takeWhile:1,times:1,transform:2},o.iterateeRearg={mapKeys:[1],reduceRight:[1,0]},o.methodRearg={assignInAllWith:[1,0],assignInWith:[1,2,0],assignAllWith:[1,0],assignWith:[1,2,0],differenceBy:[1,2,0],differenceWith:[1,2,0],getOr:[2,1,0],intersectionBy:[1,2,0],intersectionWith:[1,2,0],isEqualWith:[1,2,0],isMatchWith:[2,1,0],mergeAllWith:[1,0],mergeWith:[1,2,0],padChars:[2,1,0],padCharsEnd:[2,1,0],padCharsStart:[2,1,0],pullAllBy:[2,1,0],pullAllWith:[2,1,0],rangeStep:[1,2,0],rangeStepRight:[1,2,0],setWith:[3,1,2,0],sortedIndexBy:[2,1,0],sortedLastIndexBy:[2,1,0],unionBy:[1,2,0],unionWith:[1,2,0],updateWith:[3,1,2,0],xorBy:[1,2,0],xorWith:[1,2,0],zipWith:[1,2,0]},o.methodSpread={assignAll:{start:0},assignAllWith:{start:0},assignInAll:{start:0},assignInAllWith:{start:0},defaultsAll:{start:0},defaultsDeepAll:{start:0},invokeArgs:{start:2},invokeArgsMap:{start:2},mergeAll:{start:0},mergeAllWith:{start:0},partial:{start:1},partialRight:{start:1},without:{start:1},zipAll:{start:0}},o.mutate={array:{fill:!0,pull:!0,pullAll:!0,pullAllBy:!0,pullAllWith:!0,pullAt:!0,remove:!0,reverse:!0},object:{assign:!0,assignAll:!0,assignAllWith:!0,assignIn:!0,assignInAll:!0,assignInAllWith:!0,assignInWith:!0,assignWith:!0,defaults:!0,defaultsAll:!0,defaultsDeep:!0,defaultsDeepAll:!0,merge:!0,mergeAll:!0,mergeAllWith:!0,mergeWith:!0},set:{set:!0,setWith:!0,unset:!0,update:!0,updateWith:!0}},o.realToAlias=function(){var s=Object.prototype.hasOwnProperty,i=o.aliasToReal,a={};for(var u in i){var _=i[u];s.call(a,_)?a[_].push(u):a[_]=[u]}return a}(),o.remap={assignAll:"assign",assignAllWith:"assignWith",assignInAll:"assignIn",assignInAllWith:"assignInWith",curryN:"curry",curryRightN:"curryRight",defaultsAll:"defaults",defaultsDeepAll:"defaultsDeep",findFrom:"find",findIndexFrom:"findIndex",findLastFrom:"findLast",findLastIndexFrom:"findLastIndex",getOr:"get",includesFrom:"includes",indexOfFrom:"indexOf",invokeArgs:"invoke",invokeArgsMap:"invokeMap",lastIndexOfFrom:"lastIndexOf",mergeAll:"merge",mergeAllWith:"mergeWith",padChars:"pad",padCharsEnd:"padEnd",padCharsStart:"padStart",propertyOf:"get",rangeStep:"range",rangeStepRight:"rangeRight",restFrom:"rest",spreadFrom:"spread",trimChars:"trim",trimCharsEnd:"trimEnd",trimCharsStart:"trimStart",zipAll:"zip"},o.skipFixed={castArray:!0,flow:!0,flowRight:!0,iteratee:!0,mixin:!0,rearg:!0,runInContext:!0},o.skipRearg={add:!0,assign:!0,assignIn:!0,bind:!0,bindKey:!0,concat:!0,difference:!0,divide:!0,eq:!0,gt:!0,gte:!0,isEqual:!0,lt:!0,lte:!0,matchesProperty:!0,merge:!0,multiply:!0,overArgs:!0,partial:!0,partialRight:!0,propertyOf:!0,random:!0,range:!0,rangeRight:!0,subtract:!0,zip:!0,zipObject:!0,zipObjectDeep:!0}},17255:(s,o,i)=>{var a=i(47422);s.exports=function basePropertyDeep(s){return function(o){return a(o,s)}}},17285:s=>{function source(s){return s?"string"==typeof s?s:s.source:null}function lookahead(s){return concat("(?=",s,")")}function concat(...s){return s.map((s=>source(s))).join("")}function either(...s){return"("+s.map((s=>source(s))).join("|")+")"}s.exports=function xml(s){const o=concat(/[A-Z_]/,function optional(s){return concat("(",s,")?")}(/[A-Z0-9_.-]*:/),/[A-Z0-9_.-]*/),i={className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},a={begin:/\s/,contains:[{className:"meta-keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},u=s.inherit(a,{begin:/\(/,end:/\)/}),_=s.inherit(s.APOS_STRING_MODE,{className:"meta-string"}),w=s.inherit(s.QUOTE_STRING_MODE,{className:"meta-string"}),x={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin://,relevance:10,contains:[a,w,_,u,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[a,u,w,_]}]}]},s.COMMENT(//,{relevance:10}),{begin://,relevance:10},i,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:/)/,end:/>/,keywords:{name:"style"},contains:[x],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:/)/,end:/>/,keywords:{name:"script"},contains:[x],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:/<>|<\/>/},{className:"tag",begin:concat(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name",begin:o,relevance:0,starts:x}]},{className:"tag",begin:concat(/<\//,lookahead(concat(o,/>/))),contains:[{className:"name",begin:o,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}}},17400:(s,o,i)=>{var a=i(99374),u=1/0;s.exports=function toFinite(s){return s?(s=a(s))===u||s===-1/0?17976931348623157e292*(s<0?-1:1):s==s?s:0:0===s?s:0}},17533:s=>{s.exports=function yaml(s){var o="true false yes no null",i="[\\w#;/?:@&=+$,.~*'()[\\]]+",a={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[s.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},u=s.inherit(a,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),_={className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},w={end:",",endsWithParent:!0,excludeEnd:!0,keywords:o,relevance:0},x={begin:/\{/,end:/\}/,contains:[w],illegal:"\\n",relevance:0},C={begin:"\\[",end:"\\]",contains:[w],illegal:"\\n",relevance:0},j=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+i},{className:"type",begin:"!<"+i+">"},{className:"type",begin:"!"+i},{className:"type",begin:"!!"+i},{className:"meta",begin:"&"+s.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+s.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},s.HASH_COMMENT_MODE,{beginKeywords:o,keywords:{literal:o}},_,{className:"number",begin:s.C_NUMBER_RE+"\\b",relevance:0},x,C,a],L=[...j];return L.pop(),L.push(u),w.contains=L,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:j}}},17670:(s,o,i)=>{var a=i(12651);s.exports=function mapCacheDelete(s){var o=a(this,s).delete(s);return this.size-=o?1:0,o}},17965:(s,o,i)=>{"use strict";var a=i(16426),u={"text/plain":"Text","text/html":"Url",default:"Text"};s.exports=function copy(s,o){var i,_,w,x,C,j,L=!1;o||(o={}),i=o.debug||!1;try{if(w=a(),x=document.createRange(),C=document.getSelection(),(j=document.createElement("span")).textContent=s,j.ariaHidden="true",j.style.all="unset",j.style.position="fixed",j.style.top=0,j.style.clip="rect(0, 0, 0, 0)",j.style.whiteSpace="pre",j.style.webkitUserSelect="text",j.style.MozUserSelect="text",j.style.msUserSelect="text",j.style.userSelect="text",j.addEventListener("copy",(function(a){if(a.stopPropagation(),o.format)if(a.preventDefault(),void 0===a.clipboardData){i&&console.warn("unable to use e.clipboardData"),i&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var _=u[o.format]||u.default;window.clipboardData.setData(_,s)}else a.clipboardData.clearData(),a.clipboardData.setData(o.format,s);o.onCopy&&(a.preventDefault(),o.onCopy(a.clipboardData))})),document.body.appendChild(j),x.selectNodeContents(j),C.addRange(x),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");L=!0}catch(a){i&&console.error("unable to copy using execCommand: ",a),i&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(o.format||"text",s),o.onCopy&&o.onCopy(window.clipboardData),L=!0}catch(a){i&&console.error("unable to copy using clipboardData: ",a),i&&console.error("falling back to prompt"),_=function format(s){var o=(/mac os x/i.test(navigator.userAgent)?"⌘":"Ctrl")+"+C";return s.replace(/#{\s*key\s*}/g,o)}("message"in o?o.message:"Copy to clipboard: #{key}, Enter"),window.prompt(_,s)}}finally{C&&("function"==typeof C.removeRange?C.removeRange(x):C.removeAllRanges()),j&&document.body.removeChild(j),w()}return L}},18073:(s,o,i)=>{var a=i(85087),u=i(54641),_=i(70981);s.exports=function createRecurry(s,o,i,w,x,C,j,L,B,$){var V=8&o;o|=V?32:64,4&(o&=~(V?64:32))||(o&=-4);var U=[s,o,x,V?C:void 0,V?j:void 0,V?void 0:C,V?void 0:j,L,B,$],z=i.apply(void 0,U);return a(s)&&u(z,U),z.placeholder=w,_(z,s,o)}},19123:(s,o,i)=>{var a=i(65606),u=i(31499),_=i(88310).Stream;function resolve(s,o,i){var a,_=function create_indent(s,o){return new Array(o||0).join(s||"")}(o,i=i||0),w=s;if("object"==typeof s&&((w=s[a=Object.keys(s)[0]])&&w._elem))return w._elem.name=a,w._elem.icount=i,w._elem.indent=o,w._elem.indents=_,w._elem.interrupt=w,w._elem;var x,C=[],j=[];function get_attributes(s){Object.keys(s).forEach((function(o){C.push(function attribute(s,o){return s+'="'+u(o)+'"'}(o,s[o]))}))}switch(typeof w){case"object":if(null===w)break;w._attr&&get_attributes(w._attr),w._cdata&&j.push(("/g,"]]]]>")+"]]>"),w.forEach&&(x=!1,j.push(""),w.forEach((function(s){"object"==typeof s?"_attr"==Object.keys(s)[0]?get_attributes(s._attr):j.push(resolve(s,o,i+1)):(j.pop(),x=!0,j.push(u(s)))})),x||j.push(""));break;default:j.push(u(w))}return{name:a,interrupt:!1,attributes:C,content:j,icount:i,indents:_,indent:o}}function format(s,o,i){if("object"!=typeof o)return s(!1,o);var a=o.interrupt?1:o.content.length;function proceed(){for(;o.content.length;){var u=o.content.shift();if(void 0!==u){if(interrupt(u))return;format(s,u)}}s(!1,(a>1?o.indents:"")+(o.name?"":"")+(o.indent&&!i?"\n":"")),i&&i()}function interrupt(o){return!!o.interrupt&&(o.interrupt.append=s,o.interrupt.end=proceed,o.interrupt=!1,s(!0),!0)}if(s(!1,o.indents+(o.name?"<"+o.name:"")+(o.attributes.length?" "+o.attributes.join(" "):"")+(a?o.name?">":"":o.name?"/>":"")+(o.indent&&a>1?"\n":"")),!a)return s(!1,o.indent?"\n":"");interrupt(o)||proceed()}s.exports=function xml(s,o){"object"!=typeof o&&(o={indent:o});var i=o.stream?new _:null,u="",w=!1,x=o.indent?!0===o.indent?" ":o.indent:"",C=!0;function delay(s){C?a.nextTick(s):s()}function append(s,o){if(void 0!==o&&(u+=o),s&&!w&&(i=i||new _,w=!0),s&&w){var a=u;delay((function(){i.emit("data",a)})),u=""}}function add(s,o){format(append,resolve(s,x,x?1:0),o)}function end(){if(i){var s=u;delay((function(){i.emit("data",s),i.emit("end"),i.readable=!1,i.emit("close")}))}}return delay((function(){C=!1})),o.declaration&&function addXmlDeclaration(s){var o={version:"1.0",encoding:s.encoding||"UTF-8"};s.standalone&&(o.standalone=s.standalone),add({"?xml":{_attr:o}}),u=u.replace("/>","?>")}(o.declaration),s&&s.forEach?s.forEach((function(o,i){var a;i+1===s.length&&(a=end),add(o,a)})):add(s,end),i?(i.readable=!0,i):u},s.exports.element=s.exports.Element=function element(){var s={_elem:resolve(Array.prototype.slice.call(arguments)),push:function(s){if(!this.append)throw new Error("not assigned to a parent!");var o=this,i=this._elem.indent;format(this.append,resolve(s,i,this._elem.icount+(i?1:0)),(function(){o.append(!0)}))},close:function(s){void 0!==s&&this.push(s),this.end&&this.end()}};return s}},19219:s=>{s.exports=function cacheHas(s,o){return s.has(o)}},19287:s=>{"use strict";s.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},19358:(s,o,i)=>{"use strict";var a=i(85582),u=i(49724),_=i(61626),w=i(88280),x=i(79192),C=i(19595),j=i(54829),L=i(34084),B=i(32096),$=i(39259),V=i(85884),U=i(39447),z=i(7376);s.exports=function(s,o,i,Y){var Z="stackTraceLimit",ee=Y?2:1,ie=s.split("."),ae=ie[ie.length-1],ce=a.apply(null,ie);if(ce){var le=ce.prototype;if(!z&&u(le,"cause")&&delete le.cause,!i)return ce;var pe=a("Error"),de=o((function(s,o){var i=B(Y?o:s,void 0),a=Y?new ce(s):new ce;return void 0!==i&&_(a,"message",i),V(a,de,a.stack,2),this&&w(le,this)&&L(a,this,de),arguments.length>ee&&$(a,arguments[ee]),a}));if(de.prototype=le,"Error"!==ae?x?x(de,pe):C(de,pe,{name:!0}):U&&Z in ce&&(j(de,ce,Z),j(de,ce,"prepareStackTrace")),C(de,ce),!z)try{le.name!==ae&&_(le,"name",ae),le.constructor=de}catch(s){}return de}}},19570:(s,o,i)=>{var a=i(37334),u=i(93243),_=i(83488),w=u?function(s,o){return u(s,"toString",{configurable:!0,enumerable:!1,value:a(o),writable:!0})}:_;s.exports=w},19595:(s,o,i)=>{"use strict";var a=i(49724),u=i(11042),_=i(13846),w=i(74284);s.exports=function(s,o,i){for(var x=u(o),C=w.f,j=_.f,L=0;L{"use strict";var a=i(23034);s.exports=a},19846:(s,o,i)=>{"use strict";var a=i(20798),u=i(98828),_=i(45951).String;s.exports=!!Object.getOwnPropertySymbols&&!u((function(){var s=Symbol("symbol detection");return!_(s)||!(Object(s)instanceof Symbol)||!Symbol.sham&&a&&a<41}))},19931:(s,o,i)=>{var a=i(31769),u=i(68090),_=i(68969),w=i(77797);s.exports=function baseUnset(s,o){return o=a(o,s),null==(s=_(s,o))||delete s[w(u(o))]}},20181:(s,o,i)=>{var a=/^\s+|\s+$/g,u=/^[-+]0x[0-9a-f]+$/i,_=/^0b[01]+$/i,w=/^0o[0-7]+$/i,x=parseInt,C="object"==typeof i.g&&i.g&&i.g.Object===Object&&i.g,j="object"==typeof self&&self&&self.Object===Object&&self,L=C||j||Function("return this")(),B=Object.prototype.toString,$=Math.max,V=Math.min,now=function(){return L.Date.now()};function isObject(s){var o=typeof s;return!!s&&("object"==o||"function"==o)}function toNumber(s){if("number"==typeof s)return s;if(function isSymbol(s){return"symbol"==typeof s||function isObjectLike(s){return!!s&&"object"==typeof s}(s)&&"[object Symbol]"==B.call(s)}(s))return NaN;if(isObject(s)){var o="function"==typeof s.valueOf?s.valueOf():s;s=isObject(o)?o+"":o}if("string"!=typeof s)return 0===s?s:+s;s=s.replace(a,"");var i=_.test(s);return i||w.test(s)?x(s.slice(2),i?2:8):u.test(s)?NaN:+s}s.exports=function debounce(s,o,i){var a,u,_,w,x,C,j=0,L=!1,B=!1,U=!0;if("function"!=typeof s)throw new TypeError("Expected a function");function invokeFunc(o){var i=a,_=u;return a=u=void 0,j=o,w=s.apply(_,i)}function shouldInvoke(s){var i=s-C;return void 0===C||i>=o||i<0||B&&s-j>=_}function timerExpired(){var s=now();if(shouldInvoke(s))return trailingEdge(s);x=setTimeout(timerExpired,function remainingWait(s){var i=o-(s-C);return B?V(i,_-(s-j)):i}(s))}function trailingEdge(s){return x=void 0,U&&a?invokeFunc(s):(a=u=void 0,w)}function debounced(){var s=now(),i=shouldInvoke(s);if(a=arguments,u=this,C=s,i){if(void 0===x)return function leadingEdge(s){return j=s,x=setTimeout(timerExpired,o),L?invokeFunc(s):w}(C);if(B)return x=setTimeout(timerExpired,o),invokeFunc(C)}return void 0===x&&(x=setTimeout(timerExpired,o)),w}return o=toNumber(o)||0,isObject(i)&&(L=!!i.leading,_=(B="maxWait"in i)?$(toNumber(i.maxWait)||0,o):_,U="trailing"in i?!!i.trailing:U),debounced.cancel=function cancel(){void 0!==x&&clearTimeout(x),j=0,a=C=u=x=void 0},debounced.flush=function flush(){return void 0===x?w:trailingEdge(now())},debounced}},20317:s=>{s.exports=function mapToArray(s){var o=-1,i=Array(s.size);return s.forEach((function(s,a){i[++o]=[a,s]})),i}},20334:(s,o,i)=>{"use strict";var a=i(48287).Buffer;class NonError extends Error{constructor(s){super(NonError._prepareSuperMessage(s)),Object.defineProperty(this,"name",{value:"NonError",configurable:!0,writable:!0}),Error.captureStackTrace&&Error.captureStackTrace(this,NonError)}static _prepareSuperMessage(s){try{return JSON.stringify(s)}catch{return String(s)}}}const u=[{property:"name",enumerable:!1},{property:"message",enumerable:!1},{property:"stack",enumerable:!1},{property:"code",enumerable:!0}],_=Symbol(".toJSON called"),destroyCircular=({from:s,seen:o,to_:i,forceEnumerable:w,maxDepth:x,depth:C})=>{const j=i||(Array.isArray(s)?[]:{});if(o.push(s),C>=x)return j;if("function"==typeof s.toJSON&&!0!==s[_])return(s=>{s[_]=!0;const o=s.toJSON();return delete s[_],o})(s);for(const[i,u]of Object.entries(s))"function"==typeof a&&a.isBuffer(u)?j[i]="[object Buffer]":"function"!=typeof u&&(u&&"object"==typeof u?o.includes(s[i])?j[i]="[Circular]":(C++,j[i]=destroyCircular({from:s[i],seen:o.slice(),forceEnumerable:w,maxDepth:x,depth:C})):j[i]=u);for(const{property:o,enumerable:i}of u)"string"==typeof s[o]&&Object.defineProperty(j,o,{value:s[o],enumerable:!!w||i,configurable:!0,writable:!0});return j};s.exports={serializeError:(s,o={})=>{const{maxDepth:i=Number.POSITIVE_INFINITY}=o;return"object"==typeof s&&null!==s?destroyCircular({from:s,seen:[],forceEnumerable:!0,maxDepth:i,depth:0}):"function"==typeof s?`[Function: ${s.name||"anonymous"}]`:s},deserializeError:(s,o={})=>{const{maxDepth:i=Number.POSITIVE_INFINITY}=o;if(s instanceof Error)return s;if("object"==typeof s&&null!==s&&!Array.isArray(s)){const o=new Error;return destroyCircular({from:s,seen:[],to_:o,maxDepth:i,depth:0}),o}return new NonError(s)}}},20426:s=>{var o=Object.prototype.hasOwnProperty;s.exports=function baseHas(s,i){return null!=s&&o.call(s,i)}},20575:(s,o,i)=>{"use strict";var a=i(3121);s.exports=function(s){return a(s.length)}},20798:(s,o,i)=>{"use strict";var a,u,_=i(45951),w=i(96794),x=_.process,C=_.Deno,j=x&&x.versions||C&&C.version,L=j&&j.v8;L&&(u=(a=L.split("."))[0]>0&&a[0]<4?1:+(a[0]+a[1])),!u&&w&&(!(a=w.match(/Edge\/(\d+)/))||a[1]>=74)&&(a=w.match(/Chrome\/(\d+)/))&&(u=+a[1]),s.exports=u},20850:(s,o,i)=>{"use strict";s.exports=i(46076)},20999:(s,o,i)=>{var a=i(69302),u=i(36800);s.exports=function createAssigner(s){return a((function(o,i){var a=-1,_=i.length,w=_>1?i[_-1]:void 0,x=_>2?i[2]:void 0;for(w=s.length>3&&"function"==typeof w?(_--,w):void 0,x&&u(i[0],i[1],x)&&(w=_<3?void 0:w,_=1),o=Object(o);++a<_;){var C=i[a];C&&s(o,C,a,w)}return o}))}},21549:(s,o,i)=>{var a=i(22032),u=i(63862),_=i(66721),w=i(12749),x=i(35749);function Hash(s){var o=-1,i=null==s?0:s.length;for(this.clear();++o{var a=i(16547),u=i(43360);s.exports=function copyObject(s,o,i,_){var w=!i;i||(i={});for(var x=-1,C=o.length;++x{var a=i(51873),u=i(37828),_=i(75288),w=i(25911),x=i(20317),C=i(84247),j=a?a.prototype:void 0,L=j?j.valueOf:void 0;s.exports=function equalByTag(s,o,i,a,j,B,$){switch(i){case"[object DataView]":if(s.byteLength!=o.byteLength||s.byteOffset!=o.byteOffset)return!1;s=s.buffer,o=o.buffer;case"[object ArrayBuffer]":return!(s.byteLength!=o.byteLength||!B(new u(s),new u(o)));case"[object Boolean]":case"[object Date]":case"[object Number]":return _(+s,+o);case"[object Error]":return s.name==o.name&&s.message==o.message;case"[object RegExp]":case"[object String]":return s==o+"";case"[object Map]":var V=x;case"[object Set]":var U=1&a;if(V||(V=C),s.size!=o.size&&!U)return!1;var z=$.get(s);if(z)return z==o;a|=2,$.set(s,o);var Y=w(V(s),V(o),a,j,B,$);return $.delete(s),Y;case"[object Symbol]":if(L)return L.call(s)==L.call(o)}return!1}},22032:(s,o,i)=>{var a=i(81042);s.exports=function hashClear(){this.__data__=a?a(null):{},this.size=0}},22225:s=>{var o="\\ud800-\\udfff",i="\\u2700-\\u27bf",a="a-z\\xdf-\\xf6\\xf8-\\xff",u="A-Z\\xc0-\\xd6\\xd8-\\xde",_="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",w="["+_+"]",x="\\d+",C="["+i+"]",j="["+a+"]",L="[^"+o+_+x+i+a+u+"]",B="(?:\\ud83c[\\udde6-\\uddff]){2}",$="[\\ud800-\\udbff][\\udc00-\\udfff]",V="["+u+"]",U="(?:"+j+"|"+L+")",z="(?:"+V+"|"+L+")",Y="(?:['’](?:d|ll|m|re|s|t|ve))?",Z="(?:['’](?:D|LL|M|RE|S|T|VE))?",ee="(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?",ie="[\\ufe0e\\ufe0f]?",ae=ie+ee+("(?:\\u200d(?:"+["[^"+o+"]",B,$].join("|")+")"+ie+ee+")*"),ce="(?:"+[C,B,$].join("|")+")"+ae,le=RegExp([V+"?"+j+"+"+Y+"(?="+[w,V,"$"].join("|")+")",z+"+"+Z+"(?="+[w,V+U,"$"].join("|")+")",V+"?"+U+"+"+Y,V+"+"+Z,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",x,ce].join("|"),"g");s.exports=function unicodeWords(s){return s.match(le)||[]}},22551:(s,o,i)=>{"use strict";var a=i(96540),u=i(69982);function p(s){for(var o="https://reactjs.org/docs/error-decoder.html?invariant="+s,i=1;i