위키위키위키 위키

테마

선택한 이력에서 위 이력으로 변경된 내용을 표시합니다.

+ 테마는 기본적으로 `wikiwikiwiki/`의 `assets/`, `templates/`, `i18n/`을 덮어쓰는 방식으로 작동합니다. 테마 폴더에 이름이 같은 파일이 있다면 테마 파일을 우선합니다. 테마 폴더명이 곧 테마명이 됩니다. 테마명에는 알파벳, 숫자, `-`, `_`만 사용할 수 있습니다.
+
+ ---
+
+ ## 시작하기
+
+ 가장 좋은 시작은 `assets/css/style.css`만 수정하는 것입니다. **설정 → 기본 → 테마**에서 `starter`를 지정하세요.
+
+ ---
+
+ ## 1단계: CSS
+
+ ```text
+ starter/
+ └── assets/
+ └── css/
+ └── style.css
+ ```
+
+ `assets/css/style.css`가 있으면 위키위키위키의 기본 CSS가 **완전히 교체**됩니다. 위키위키위키의 기본 템플릿에 사용되는 클래스명은 다음과 같습니다.
+
+ **레이아웃**
+
+ - `.document`, `.header`, `.main`, `.footer`, `.section`, `.section-header`, `.section-main`, `.section-footer`
+
+ **타이포그래피**
+
+ - `.title`, `.content`
+
+ **링크**
+
+ - `.exists`, `.not-exists`, `.external`, `.wikipedia`, `.tag`, `.iframe-link`
+
+ **폼**
+
+ - `.form`, `.form.is-fill`, `.fields`, `.field`, `.field.is-fill`, `.field-help`, `.label`, `.input`, `.textarea`
+
+ **버튼**
+
+ - `.buttons`, `.button`, `.button.is-primary`, `.button.is-danger`, `.button.is-link`
+
+ **탭**(계정 및 설정 페이지)
+
+ - `.tabs`, `.tab`, `.tab-content`
+
+ **Diff**(편집 충돌·히스토리 비교)
+
+ - `.diff`, `.diff-sign`, `.diff-line`, `.diff-add`, `.diff-remove`, `.diff-context`
+
+ **유틸리티**
+
+ - `.hidden`, `.skip`, `.flash`
+
+ **기타**
+
+ - `.table`
+
+ 페이지별 설계가 필요하다면 `base.php` `<body>`의 `id`를 활용할 수 있습니다. 현재 템플릿명(`view`, `edit`, `search`, `account`, `settings` 등)이 그대로 지정됩니다.
+
+ ```css
+ /* 문서 보기 페이지만 본문 글자 크기를 크게 */
+ body#view .content { font-size: 1.5rem; }
+ ```
+
+ ## 2단계: 문구
+
+ 버튼 텍스트나 안내 메시지를 바꾸고 싶다면 해당 언어 파일을 추가합니다.
+
+ ```text
+ starter/
+ └── i18n/
+ ├── ko.json
+ └── en.json
+ ```
+
+ 키가 같으면 테마의 값이 위키위키위키의 기본값을 덮어씁니다.
+
+ ```json
+ {
+ "button.save": "게시",
+ "button.edit": "수정"
+ }
+ ```
+
+ ## 3단계: 레이아웃
+
+ 헤더, 메인, 푸터 등 레이아웃을 직접 설계하려면 `templates/base.php`를 추가합니다. `base.php`는 모든 페이지를 아우르는 기본 레이아웃 파일입니다. 처음에는 `wikiwikiwiki/templates/base.php`를 복사해 시작하는 것이 좋습니다.
+
+ ```text
+ starter/
+ └── templates/
+ └── base.php
+ ```
+
+ `templates/`에 이름이 같은 파일을 추가하면 개별 페이지 템플릿까지 바꿀 수 있습니다. 특정 페이지만 구조를 바꾸고 싶을 때 유용합니다. 단, 레이아웃을 직접 설계하면 위키위키위키 업그레이드 시 `wikiwikiwiki/templates/base.php`의 변경 사항을 직접 반영해야 할 수 있습니다.
+
+ ```text
+ starter/
+ └── templates/
+ ├── base.php # 기본 레이아웃
+ ├── view.php # 문서 보기
+ ├── edit.php # 편집
+ ├── search.php # 검색
+ ├── discover.php # 둘러보기
+ ├── history.php # 편집 이력
+ ├── account.php # 계정
+ ├── settings.php # 설정(관리자)
+ ├── 404.php # 문서 없음
+ └── ... # 그 외 템플릿과 동일한 파일
+ ```
+
+ ### 템플릿에서 사용할 수 있는 함수
+
+ **출력/번역**
+
+ | 함수 | 설명 |
+ |---|---|
+ | `html($str)` | 문자열을 HTML 안전하게 출력 |
+ | `t($key)` | 번역 문자열 반환, 키가 없으면 키 자체를 반환 |
+
+ **URL/에셋**
+
+ | 함수 | 설명 |
+ |---|---|
+ | `url($path)` | 위키위키위키 기준 경로 URL 생성, `/search` 같은 경로 또는 문서 제목 전달 |
+ | `page_url($title)` | 문서 전체 URL 반환 |
+ | `asset($file)` | 에셋 URL 반환, 테마 파일이 있으면 테마 파일 우선 |
+ | `css($file)` | CSS `<link>` 태그 문자열 생성 |
+ | `js($file)` | JS `<script>` 태그 문자열 생성 |
+
+ **인증/권한**
+
+ | 함수 | 설명 |
+ |---|---|
+ | `is_logged_in()` | 로그인 여부 |
+ | `is_admin()` | 관리자 여부 |
+ | `is_public()` | 편집 권한이 공개(public)인지 여부 |
+ | `current_user()` | 현재 사용자명, 비로그인 시 `null` |
+ | `current_role()` | 현재 사용자 역할, `'admin'`, `'editor'`, 또는 빈 문자열 |
+
+ **폼/보안**
+
+ | 함수 | 설명 |
+ |---|---|
+ | `csrf_token()` | 폼 보안 토큰 문자열 반환 |
+ | `honeypot_field()` | 스팸 방지용 hidden input HTML 반환 |
+
+ **데이터**
+
+ | 함수 | 설명 |
+ |---|---|
+ | `page_recent($limit)` | 최근 편집 문서 목록 반환, 기본 10개 |
+ | `page_random($limit)` | 무작위 문서 목록 반환, 기본 10개 |
+
+ ### 템플릿에서 사용할 수 있는 변수
+
+ | 변수 | 설명 |
+ |---|---|
+ | `$wikiTitle` | 위키 제목 |
+ | `$wikiDescription` | 위키 설명 |
+ | `$pageTitle` | 현재 페이지 제목 |
+ | `$description` | 현재 페이지 설명, 없으면 빈 문자열 |
+ | `$language` | 언어 코드(예: `ko`) |
+ | `$languageCode` | 로케일 코드(예: `ko_KR`) |
+ | `$ogUrl` | 현재 페이지 전체 URL |
+ | `$basePath` | URL 기준 경로 |
+ | `$csrfToken` | 폼 보안 토큰 |
+ | `$flashes` | 알림 메시지 배열, 각 항목은 `type`과 `message` 키를 지님 |
+ | `$recentPages` | 최근 편집한 문서 배열, 기본 5개 |
+ | `$section` | 현재 페이지 본문 HTML, `base.php` 전용 변수 |
+ | `$template` | 현재 템플릿명, `<body id>` 속성에 사용, `base.php` 전용 변수 |
+
+ ## 4단계: 자바스크립트
+
+ `assets/js/script.js`를 추가하면 위키위키위키의 기본 자바스크립트가 **완전히 교체**됩니다.
+
+ ```text
+ starter/
+ └── assets/
+ └── js/
+ └── script.js
+ ```
+
+ 자바스크립트 파일을 직접 작성하면 다음 기능도 직접 구현해야 합니다.
+
+ ### 탭 전환
+
+ 계정 및 설정 페이지는 첫 번째 패널만 보이고, 나머지 패널은 `hidden` 상태로 시작합니다. 자바스크립트 없이 모두 표시하려면 `[hidden]` 처리까지 함께 재정의해야 합니다.
+
+ ```css
+ /* 자바스크립트 없이 모든 탭 내용 표시 */
+ .tab-content[hidden] { display: block; }
+ ```
+
+ ```javascript
+ // 최소 구현 예시
+ document.querySelectorAll('.tabs').forEach(tabList => {
+ const tabs = Array.from(tabList.querySelectorAll('.tab[data-target]'));
+ const container = tabList.parentElement;
+ if (!container) return;
+ const panes = Array.from(container.querySelectorAll(':scope > .tab-content[data-id]'));
+
+ tabs.forEach(tab => {
+ tab.addEventListener('click', () => {
+ const target = tab.dataset.target || '';
+ tabs.forEach(button => {
+ button.setAttribute('aria-selected', button === tab ? 'true' : 'false');
+ });
+ panes.forEach(pane => {
+ pane.hidden = (pane.dataset.id || '') !== target;
+ });
+ });
+ });
+ });
+ ```
+
+ ### 문서 삭제 및 복원 확인 메시지
+
+ `[data-confirm-message]` 속성이 있는 버튼에 `confirm`이 없으면 문서 삭제와 복원이 확인 없이 즉시 실행됩니다.
+
+ ```javascript
+ // 최소 구현 예시
+ document.addEventListener('submit', event => {
+ const form = event.target;
+ if (!(form instanceof HTMLFormElement)) return;
+ const submitter = event.submitter instanceof HTMLElement ? event.submitter : null;
+ const message = submitter?.dataset.confirmMessage || form.dataset.confirmMessage || '';
+ if (message && !confirm(message)) {
+ event.preventDefault();
+ }
+ });
+ ```
+
+ ---
+
+ ## 변경 사항이 적용되지 않을 때
+
+ - 먼저 **설정 → 기본 → 테마**에서 현재 테마를 선택했는지 확인하세요.
+ - 파일 경로가 `themes/{테마명}/assets/...`, `themes/{테마명}/templates/...`, `themes/{테마명}/i18n/...` 형태인지 확인하세요.
+ - `style.css` 또는 `script.js` 파일이 실제로 존재하고 저장됐는지 확인하세요.

검색