--- paths: - "src/apps/desktop/src/**" - "src/apps/desktop/tests/**" - "src/apps/desktop/index.html" - "src/apps/desktop/package.json" - "src/apps/desktop/tsconfig.json" --- # 프런트엔드(TypeScript · CSS) 규칙 프레임워크 없는 TypeScript. 화면은 문자열 템플릿으로 만들고 `root.innerHTML`에 넣은 뒤 `data-action`/`data-field` 속성으로 이벤트를 연결한다. `tsc --noEmit` strict와 `node --test`를 통과해야 한다. ## 모듈 구조 - `main.ts`는 상태와 조정(invoke 호출, render, action 분기)만 둔다. 화면 조각과 순수 로직은 별도 모듈로 뺀다: `start-screen.ts`, `registry-editor.ts`, `signing-editor.ts`, `project-transition.ts`, `window-chrome.ts`. - 새 탭·편집기는 `render(data, disabled): string`을 export하는 모듈로 만들고, `main.ts`에서는 import와 action 분기만 추가한다. - 테스트는 `tests/.test.mjs`에서 `.ts`를 직접 import한다. Node의 `--experimental-strip-types`로 실행되므로 **`enum`, `namespace`, 매개변수 프로퍼티, 데코레이터를 쓰지 않는다**. 타입은 `type` 별칭과 `import type`으로. - 순수 함수(그룹화, 경로 표시, 전환 판단)는 DOM 없이 호출 가능해야 테스트할 수 있다. `document`를 쓰는 코드와 분리한다. ## 보안 · 렌더링 - 템플릿에 들어가는 모든 동적 값은 `esc()`/`escape()`를 거친다. 프로젝트 이름, 경로, 오류 메시지, ID도 예외 없다. 테스트는 `` 같은 값이 이스케이프되는지 확인한다. - `tauri.conf.json`의 CSP는 `'self'`만 허용한다. 인라인 `