MediaWiki:Common.js: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 15: | Line 15: | ||
if (raw) user = JSON.parse(raw); | if (raw) user = JSON.parse(raw); | ||
} catch (e) {} | } catch (e) {} | ||
// ─── [추가] 페이지명 및 sysop 여부 ─── | |||
var pageName = mw.config.get("wgPageName"); | |||
var isSysop = (mw.config.get("wgUserGroups") || []).indexOf("sysop") !== -1; | |||
// proactive 토큰 갱신 | // proactive 토큰 갱신 | ||
| Line 400: | Line 404: | ||
sp(searchInput, "box-sizing", "border-box"); | sp(searchInput, "box-sizing", "border-box"); | ||
var suggestBox = document.createElement("div"); | var suggestBox = document.createElement("div"); | ||
sp(suggestBox, "position", "absolute"); | sp(suggestBox, "position", "absolute"); | ||
sp(suggestBox, "top", "calc(100% + 2px)"); | sp(suggestBox, "top", "calc(100% + 2px)"); | ||
| Line 485: | Line 489: | ||
subbar.appendChild(hbBtn); | subbar.appendChild(hbBtn); | ||
subbar.appendChild(searchWrap); | subbar.appendChild(searchWrap); | ||
// ─── [추가] 서브바 Create 버튼 (sysop only) ─── | |||
if (isSysop) { | |||
var createDocBtn = document.createElement("a"); | |||
createDocBtn.href = "/index.php?title=Erakh_Codex:Create"; | |||
createDocBtn.textContent = "+ Create"; | |||
sp(createDocBtn, "display", "flex"); | |||
sp(createDocBtn, "align-items", "center"); | |||
sp(createDocBtn, "height", "44px"); | |||
sp(createDocBtn, "padding", "0 1.25rem"); | |||
sp(createDocBtn, "margin-left", "auto"); | |||
sp(createDocBtn, "font-family", "'Inter', sans-serif"); | |||
sp(createDocBtn, "font-size", "0.8125rem"); | |||
sp(createDocBtn, "font-weight", "500"); | |||
sp(createDocBtn, "color", "#c8a060"); | |||
sp(createDocBtn, "text-decoration", "none"); | |||
sp(createDocBtn, "border-left", "1px solid #e2d9c8"); | |||
sp(createDocBtn, "flex-shrink", "0"); | |||
sp(createDocBtn, "box-sizing", "border-box"); | |||
sp(createDocBtn, "letter-spacing", "-0.01em"); | |||
createDocBtn.addEventListener("mouseover", function() { | |||
this.style.setProperty("background", "#e2d9c8", "important"); | |||
this.style.setProperty("color", "#a07840", "important"); | |||
}); | |||
createDocBtn.addEventListener("mouseout", function() { | |||
this.style.setProperty("background", "transparent", "important"); | |||
this.style.setProperty("color", "#c8a060", "important"); | |||
}); | |||
subbar.appendChild(createDocBtn); | |||
} | |||
// ─── 드로어 ─── | // ─── 드로어 ─── | ||
| Line 586: | Line 620: | ||
// ─── 3컬럼 레이아웃 (JS 직접 목차 빌드) ─── | // ─── 3컬럼 레이아웃 (JS 직접 목차 빌드) ─── | ||
function buildToc(headings) { | function buildToc(headings) { | ||
var toc = document.createElement( | var toc = document.createElement("nav"); | ||
toc.id = | toc.id = "erakh-toc"; | ||
var ul = document.createElement( | var ul = document.createElement("ul"); | ||
sp(ul, | sp(ul, "list-style", "none"); | ||
sp(ul, | sp(ul, "margin", "0"); | ||
sp(ul, | sp(ul, "padding", "0"); | ||
headings.forEach(function(h, i) { | headings.forEach(function(h, i) { | ||
var level = parseInt(h.tagName.replace( | var level = parseInt(h.tagName.replace("H", "")); | ||
var id = h.id || ( | var id = h.id || ("erakh-section-" + i); | ||
h.id = id; | h.id = id; | ||
var li = document.createElement( | var li = document.createElement("li"); | ||
li.style.setProperty( | li.style.setProperty("padding", "0.25rem 0 0.25rem " + (level === 2 ? "0.5rem" : "1.25rem"), "important"); | ||
li.style.setProperty( | li.style.setProperty("border-left", "2px solid transparent", "important"); | ||
li.style.setProperty( | li.style.setProperty("line-height", "1.4", "important"); | ||
li.dataset.id = id; | li.dataset.id = id; | ||
var a = document.createElement( | var a = document.createElement("a"); | ||
a.href = | a.href = "#" + id; | ||
a.textContent = h.textContent.replace(/\[edit\]/g, | a.textContent = h.textContent.replace(/\[edit\]/g, "").trim(); | ||
sp(a, | sp(a, "font-family", "'Inter', sans-serif"); | ||
sp(a, | sp(a, "font-size", level === 2 ? "0.78rem" : "0.74rem"); | ||
sp(a, | sp(a, "color", level === 2 ? "#6b5e4e" : "#9c8e80"); | ||
sp(a, | sp(a, "text-decoration", "none"); | ||
sp(a, | sp(a, "display", "block"); | ||
a.addEventListener( | a.addEventListener("mouseover", function() { this.style.setProperty("color", "#2a2218", "important"); }); | ||
a.addEventListener( | a.addEventListener("mouseout", function() { this.style.setProperty("color", level === 2 ? "#6b5e4e" : "#9c8e80", "important"); }); | ||
li.appendChild(a); | li.appendChild(a); | ||
| Line 624: | Line 658: | ||
function buildLayout() { | function buildLayout() { | ||
var content = document.querySelector( | // ─── [추가] Create 페이지에서는 레이아웃 빌드 스킵 ─── | ||
if (pageName === "Erakh_Codex:Create") return; | |||
var content = document.querySelector(".mw-body") || document.getElementById("content"); | |||
if (!content) return; | if (!content) return; | ||
var headings = Array.from(content.querySelectorAll( | var headings = Array.from(content.querySelectorAll("h2, h3")).filter(function(h) { | ||
return !h.closest( | return !h.closest("#toc"); | ||
}); | }); | ||
var layout = document.createElement( | var layout = document.createElement("div"); | ||
layout.className = | layout.className = "erakh-layout"; | ||
var colLeft = document.createElement( | var colLeft = document.createElement("aside"); | ||
colLeft.className = | colLeft.className = "erakh-col-left"; | ||
var colCenter = document.createElement( | var colCenter = document.createElement("div"); | ||
colCenter.className = | colCenter.className = "erakh-col-center"; | ||
var colRight = document.createElement( | var colRight = document.createElement("aside"); | ||
colRight.className = | colRight.className = "erakh-col-right"; | ||
var tocLabel = document.createElement( | var tocLabel = document.createElement("div"); | ||
tocLabel.className = | tocLabel.className = "erakh-toc-label"; | ||
tocLabel.textContent = | tocLabel.textContent = "Contents"; | ||
colLeft.appendChild(tocLabel); | colLeft.appendChild(tocLabel); | ||
| Line 652: | Line 689: | ||
colLeft.appendChild(toc); | colLeft.appendChild(toc); | ||
var items = colLeft.querySelectorAll("li[data-id]"); | |||
var items = colLeft.querySelectorAll( | window.addEventListener("scroll", function() { | ||
window.addEventListener( | |||
var scrollY = window.scrollY + 108; | var scrollY = window.scrollY + 108; | ||
var current = null; | var current = null; | ||
| Line 662: | Line 698: | ||
items.forEach(function(li) { | items.forEach(function(li) { | ||
if (li.dataset.id === current) { | if (li.dataset.id === current) { | ||
li.style.setProperty( | li.style.setProperty("border-left-color", "#c8a060", "important"); | ||
li.querySelector( | li.querySelector("a").style.setProperty("color", "#2a2218", "important"); | ||
li.querySelector( | li.querySelector("a").style.setProperty("font-weight", "500", "important"); | ||
} else { | } else { | ||
li.style.setProperty( | li.style.setProperty("border-left-color", "transparent", "important"); | ||
var level = li.style.paddingLeft === | var level = li.style.paddingLeft === "0.5rem" ? 2 : 3; | ||
li.querySelector( | li.querySelector("a").style.setProperty("color", level === 2 ? "#6b5e4e" : "#9c8e80", "important"); | ||
li.querySelector( | li.querySelector("a").style.setProperty("font-weight", "400", "important"); | ||
} | } | ||
}); | }); | ||
}); | }); | ||
} else { | } else { | ||
var emptyMsg = document.createElement( | var emptyMsg = document.createElement("div"); | ||
sp(emptyMsg, | sp(emptyMsg, "font-family", "'Inter', sans-serif"); | ||
sp(emptyMsg, | sp(emptyMsg, "font-size", "0.75rem"); | ||
sp(emptyMsg, | sp(emptyMsg, "color", "#9c8e80"); | ||
sp(emptyMsg, | sp(emptyMsg, "padding", "0.25rem 0.5rem"); | ||
emptyMsg.textContent = | emptyMsg.textContent = "—"; | ||
colLeft.appendChild(emptyMsg); | colLeft.appendChild(emptyMsg); | ||
} | } | ||
var sidebarLabel = document.createElement("div"); | |||
var sidebarLabel = document.createElement( | sidebarLabel.className = "erakh-sidebar-label"; | ||
sidebarLabel.className = | sidebarLabel.textContent = "위젯 영역"; | ||
sidebarLabel.textContent = | |||
colRight.appendChild(sidebarLabel); | colRight.appendChild(sidebarLabel); | ||
var ph1 = document.createElement( | var ph1 = document.createElement("div"); | ||
ph1.className = | ph1.className = "erakh-sidebar-placeholder"; | ||
ph1.textContent = | ph1.textContent = "인기 문서 위젯 예정"; | ||
colRight.appendChild(ph1); | colRight.appendChild(ph1); | ||
var ph2 = document.createElement( | var ph2 = document.createElement("div"); | ||
ph2.className = | ph2.className = "erakh-sidebar-placeholder"; | ||
ph2.textContent = | ph2.textContent = "최근 변경 위젯 예정"; | ||
colRight.appendChild(ph2); | colRight.appendChild(ph2); | ||
| Line 707: | Line 742: | ||
} | } | ||
if (document. | // ─── [추가] 문서 생성 페이지 UI ─── | ||
document.addEventListener('DOMContentLoaded | function buildCreatePage() { | ||
if (pageName !== "Erakh_Codex:Create") return; | |||
var CATEGORIES = [ | |||
{ label: "Characters", preload: "Template:Preload/Character" }, | |||
{ label: "Nations", preload: "Template:Preload/Nation" }, | |||
{ label: "Regions", preload: "Template:Preload/Region" }, | |||
{ label: "Races", preload: "Template:Preload/Race" }, | |||
{ label: "Organizations", preload: "Template:Preload/Organization" }, | |||
{ label: "Events", preload: "Template:Preload/Event" }, | |||
{ label: "Disciplines", preload: "Template:Preload/Discipline" }, | |||
{ label: "Culture", preload: "Template:Preload/Culture" }, | |||
{ label: "Artifacts", preload: "Template:Preload/Artifact" }, | |||
{ label: "Chronicle", preload: null }, | |||
]; | |||
// MW 기본 UI 숨김 | |||
var firstHeading = document.getElementById("firstHeading"); | |||
if (firstHeading) sp(firstHeading, "display", "none"); | |||
var parseOutput = document.querySelector(".mw-parser-output"); | |||
if (parseOutput) sp(parseOutput, "display", "none"); | |||
var noArticle = document.querySelector(".noarticletext"); | |||
if (noArticle) sp(noArticle, "display", "none"); | |||
// 편집 탭/액션 숨김 | |||
var pViews = document.getElementById("p-views"); | |||
if (pViews) sp(pViews, "display", "none"); | |||
var pCactions = document.getElementById("p-cactions"); | |||
if (pCactions) sp(pCactions, "display", "none"); | |||
var target = document.getElementById("mw-content-text"); | |||
if (!target) return; | |||
// 비sysop 접근 시 안내 | |||
if (!isSysop) { | |||
var denied = document.createElement("div"); | |||
sp(denied, "padding", "60px 40px"); | |||
sp(denied, "text-align", "center"); | |||
sp(denied, "font-family", "'Inter', sans-serif"); | |||
sp(denied, "font-size", "0.875rem"); | |||
sp(denied, "color", "#9c8e80"); | |||
denied.textContent = "Document creation is restricted to administrators."; | |||
target.appendChild(denied); | |||
return; | |||
} | |||
var selectedCat = null; | |||
// ── 컨테이너 | |||
var wrap = document.createElement("div"); | |||
sp(wrap, "max-width", "680px"); | |||
sp(wrap, "margin", "40px auto"); | |||
sp(wrap, "padding", "0 24px 48px"); | |||
sp(wrap, "font-family", "'Inter', sans-serif"); | |||
sp(wrap, "color", "#2a2218"); | |||
sp(wrap, "box-sizing", "border-box"); | |||
// ── 페이지 제목 | |||
var heading = document.createElement("h2"); | |||
heading.textContent = "Create New Document"; | |||
sp(heading, "font-size", "1.375rem"); | |||
sp(heading, "font-weight", "600"); | |||
sp(heading, "margin", "0 0 2rem 0"); | |||
sp(heading, "color", "#2a2218"); | |||
sp(heading, "letter-spacing", "-0.01em"); | |||
sp(heading, "font-family", "'Inter', sans-serif"); | |||
wrap.appendChild(heading); | |||
// ── 카테고리 레이블 | |||
var catLabel = document.createElement("p"); | |||
catLabel.textContent = "Select Category"; | |||
sp(catLabel, "font-size", "0.6875rem"); | |||
sp(catLabel, "font-weight", "500"); | |||
sp(catLabel, "color", "#9c8e80"); | |||
sp(catLabel, "margin", "0 0 0.625rem 0"); | |||
sp(catLabel, "letter-spacing", "0.1em"); | |||
sp(catLabel, "text-transform", "uppercase"); | |||
sp(catLabel, "font-family", "'Inter', sans-serif"); | |||
wrap.appendChild(catLabel); | |||
// ── 카테고리 그리드 | |||
var grid = document.createElement("div"); | |||
sp(grid, "display", "grid"); | |||
sp(grid, "grid-template-columns", "repeat(5, 1fr)"); | |||
sp(grid, "gap", "8px"); | |||
sp(grid, "margin-bottom", "0.625rem"); | |||
var catCards = []; | |||
CATEGORIES.forEach(function(cat) { | |||
var card = document.createElement("button"); | |||
card.textContent = cat.label; | |||
sp(card, "border", "1.5px solid #e2d9c8"); | |||
sp(card, "border-radius", "6px"); | |||
sp(card, "background", "#f9f6f0"); | |||
sp(card, "padding", "0.75rem 0.375rem"); | |||
sp(card, "font-size", "0.79rem"); | |||
sp(card, "font-weight", "500"); | |||
sp(card, "font-family", "'Inter', sans-serif"); | |||
sp(card, "color", "#2a2218"); | |||
sp(card, "cursor", "pointer"); | |||
sp(card, "text-align", "center"); | |||
sp(card, "line-height", "1.3"); | |||
sp(card, "box-sizing", "border-box"); | |||
card.addEventListener("mouseover", function() { | |||
if (selectedCat !== cat.label) { | |||
this.style.setProperty("background", "#f0ebe0", "important"); | |||
this.style.setProperty("border-color", "#c8b99a", "important"); | |||
} | |||
}); | |||
card.addEventListener("mouseout", function() { | |||
if (selectedCat !== cat.label) { | |||
this.style.setProperty("background", "#f9f6f0", "important"); | |||
this.style.setProperty("border-color", "#e2d9c8", "important"); | |||
} | |||
}); | |||
card.addEventListener("click", function() { | |||
catCards.forEach(function(c) { | |||
c.style.setProperty("background", "#f9f6f0", "important"); | |||
c.style.setProperty("border-color", "#e2d9c8", "important"); | |||
c.style.setProperty("color", "#2a2218", "important"); | |||
}); | |||
this.style.setProperty("background", "#c8a060", "important"); | |||
this.style.setProperty("border-color", "#c8a060", "important"); | |||
this.style.setProperty("color", "#ffffff", "important"); | |||
selectedCat = cat.label; | |||
if (cat.preload === null) { | |||
chronicleNotice.style.setProperty("display", "block", "important"); | |||
} else { | |||
chronicleNotice.style.setProperty("display", "none", "important"); | |||
} | |||
updateBtn(); | |||
}); | |||
catCards.push(card); | |||
grid.appendChild(card); | |||
}); | |||
wrap.appendChild(grid); | |||
// ── Chronicle 안내 | |||
var chronicleNotice = document.createElement("p"); | |||
chronicleNotice.textContent = "Chronicle documents use a timeline format. No infobox template will be applied."; | |||
sp(chronicleNotice, "display", "none"); | |||
sp(chronicleNotice, "font-size", "0.75rem"); | |||
sp(chronicleNotice, "color", "#9c8e80"); | |||
sp(chronicleNotice, "font-style", "italic"); | |||
sp(chronicleNotice, "margin", "0.375rem 0 0 0"); | |||
sp(chronicleNotice, "font-family", "'Inter', sans-serif"); | |||
wrap.appendChild(chronicleNotice); | |||
// ── 구분선 | |||
var divider = document.createElement("div"); | |||
sp(divider, "border-top", "1px solid #e2d9c8"); | |||
sp(divider, "margin", "1.5rem 0 1.25rem"); | |||
wrap.appendChild(divider); | |||
// ── 제목 레이블 | |||
var titleLabel = document.createElement("p"); | |||
titleLabel.textContent = "Document Title"; | |||
sp(titleLabel, "font-size", "0.6875rem"); | |||
sp(titleLabel, "font-weight", "500"); | |||
sp(titleLabel, "color", "#9c8e80"); | |||
sp(titleLabel, "margin", "0 0 0.5rem 0"); | |||
sp(titleLabel, "letter-spacing", "0.1em"); | |||
sp(titleLabel, "text-transform", "uppercase"); | |||
sp(titleLabel, "font-family", "'Inter', sans-serif"); | |||
wrap.appendChild(titleLabel); | |||
// ── 제목 입력 | |||
var titleInput = document.createElement("input"); | |||
titleInput.type = "text"; | |||
titleInput.placeholder = "Enter document title..."; | |||
sp(titleInput, "width", "100%"); | |||
sp(titleInput, "padding", "0.625rem 0.875rem"); | |||
sp(titleInput, "border", "1.5px solid #e2d9c8"); | |||
sp(titleInput, "border-radius", "6px"); | |||
sp(titleInput, "font-size", "0.9375rem"); | |||
sp(titleInput, "font-family", "'Inter', sans-serif"); | |||
sp(titleInput, "color", "#2a2218"); | |||
sp(titleInput, "background", "#ffffff"); | |||
sp(titleInput, "box-sizing", "border-box"); | |||
sp(titleInput, "outline", "none"); | |||
sp(titleInput, "margin-bottom", "1.25rem"); | |||
titleInput.addEventListener("focus", function() { this.style.setProperty("border-color", "#c8a060", "important"); }); | |||
titleInput.addEventListener("blur", function() { this.style.setProperty("border-color", "#e2d9c8", "important"); }); | |||
titleInput.addEventListener("input", updateBtn); | |||
wrap.appendChild(titleInput); | |||
// ── Create 버튼 | |||
var createBtn = document.createElement("button"); | |||
createBtn.textContent = "Create Article"; | |||
sp(createBtn, "display", "block"); | |||
sp(createBtn, "width", "100%"); | |||
sp(createBtn, "padding", "0.75rem"); | |||
sp(createBtn, "background", "#e2d9c8"); | |||
sp(createBtn, "border", "none"); | |||
sp(createBtn, "border-radius", "6px"); | |||
sp(createBtn, "font-size", "0.9375rem"); | |||
sp(createBtn, "font-weight", "600"); | |||
sp(createBtn, "font-family", "'Inter', sans-serif"); | |||
sp(createBtn, "color", "#9c8e80"); | |||
sp(createBtn, "cursor", "not-allowed"); | |||
sp(createBtn, "box-sizing", "border-box"); | |||
createBtn.addEventListener("click", function() { | |||
if (!selectedCat) return; | |||
var title = titleInput.value.trim(); | |||
if (!title) return; | |||
var catObj = null; | |||
for (var i = 0; i < CATEGORIES.length; i++) { | |||
if (CATEGORIES[i].label === selectedCat) { catObj = CATEGORIES[i]; break; } | |||
} | |||
if (!catObj) return; | |||
var url = "/index.php?title=" + encodeURIComponent(title) + "&action=edit"; | |||
if (catObj.preload) url += "&preload=" + encodeURIComponent(catObj.preload); | |||
window.location.href = url; | |||
}); | |||
wrap.appendChild(createBtn); | |||
target.appendChild(wrap); | |||
function updateBtn() { | |||
var ready = selectedCat && titleInput.value.trim().length > 0; | |||
if (ready) { | |||
createBtn.style.setProperty("background", "#c8a060", "important"); | |||
createBtn.style.setProperty("color", "#ffffff", "important"); | |||
createBtn.style.setProperty("cursor", "pointer", "important"); | |||
} else { | |||
createBtn.style.setProperty("background", "#e2d9c8", "important"); | |||
createBtn.style.setProperty("color", "#9c8e80", "important"); | |||
createBtn.style.setProperty("cursor", "not-allowed", "important"); | |||
} | |||
} | |||
} | |||
// ─── 실행 ─── | |||
if (document.readyState === "loading") { | |||
document.addEventListener("DOMContentLoaded", function() { | |||
buildLayout(); | |||
buildCreatePage(); | |||
}); | |||
} else { | } else { | ||
buildLayout(); | buildLayout(); | ||
buildCreatePage(); | |||
} | } | ||
})(); | })(); | ||
Revision as of 04:02, 10 May 2026
(function () {
var fontLink = document.createElement("link");
fontLink.rel = "stylesheet";
fontLink.href = "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap";
document.head.insertBefore(fontLink, document.head.firstChild);
function getCookie(name) {
var match = document.cookie.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
return match ? decodeURIComponent(match[1]) : null;
}
var user = null;
try {
var raw = getCookie("erakh_user");
if (raw) user = JSON.parse(raw);
} catch (e) {}
// ─── [추가] 페이지명 및 sysop 여부 ───
var pageName = mw.config.get("wgPageName");
var isSysop = (mw.config.get("wgUserGroups") || []).indexOf("sysop") !== -1;
// proactive 토큰 갱신
if (user && user.exp) {
var now = Math.floor(Date.now() / 1000);
var remaining = user.exp - now;
if (remaining < 5 * 60) {
fetch("https://erakh.com/api/auth/refresh", { method: "POST", credentials: "include" })
.catch(function() {});
} else {
var delay = (remaining - 5 * 60) * 1000;
setTimeout(function() {
fetch("https://erakh.com/api/auth/refresh", { method: "POST", credentials: "include" })
.catch(function() {});
}, delay);
}
}
function sp(el, prop, val) {
el.style.setProperty(prop, val, "important");
}
// ─── 헤더 ───
var header = document.createElement("header");
sp(header, "position", "fixed");
sp(header, "top", "0");
sp(header, "left", "0");
sp(header, "right", "0");
sp(header, "z-index", "9999");
sp(header, "width", "100%");
sp(header, "background", "#f9f6f0");
sp(header, "border-bottom", "1px solid #e2d9c8");
sp(header, "display", "flex");
sp(header, "align-items", "center");
sp(header, "justify-content", "space-between");
sp(header, "padding", "0 2rem");
sp(header, "height", "56px");
sp(header, "box-sizing", "border-box");
var left = document.createElement("div");
sp(left, "display", "flex");
sp(left, "align-items", "center");
sp(left, "gap", "1.75rem");
var logo = document.createElement("a");
logo.href = "https://erakh.com";
logo.textContent = "Erakh Archive";
sp(logo, "font-family", "'Inter', sans-serif");
sp(logo, "font-size", "1.125rem");
sp(logo, "font-weight", "500");
sp(logo, "color", "#2a2218");
sp(logo, "text-decoration", "none");
sp(logo, "letter-spacing", "-0.01em");
sp(logo, "text-transform", "none");
sp(logo, "font-variant", "normal");
sp(logo, "font-variant-caps", "normal");
sp(logo, "line-height", "1");
var nav = document.createElement("nav");
sp(nav, "display", "flex");
sp(nav, "align-items", "center");
sp(nav, "gap", "1.5rem");
var codexLink = document.createElement("a");
codexLink.href = "https://codex.erakh.com";
codexLink.textContent = "Codex";
sp(codexLink, "font-family", "'Inter', sans-serif");
sp(codexLink, "font-size", "1rem");
sp(codexLink, "color", "#6b5e4e");
sp(codexLink, "text-decoration", "none");
sp(codexLink, "text-transform", "none");
sp(codexLink, "font-variant", "normal");
sp(codexLink, "line-height", "1");
codexLink.addEventListener("mouseover", function() { this.style.setProperty("color", "#2a2218", "important"); });
codexLink.addEventListener("mouseout", function() { this.style.setProperty("color", "#6b5e4e", "important"); });
nav.appendChild(codexLink);
left.appendChild(logo);
left.appendChild(nav);
var right = document.createElement("div");
sp(right, "display", "flex");
sp(right, "align-items", "center");
if (user && user.nickname) {
var profile = document.createElement("div");
sp(profile, "position", "relative");
var avatar = document.createElement("div");
avatar.textContent = user.nickname.slice(0, 1).toUpperCase();
sp(avatar, "width", "32px");
sp(avatar, "height", "32px");
sp(avatar, "border-radius", "50%");
sp(avatar, "background", "#e2d9c8");
sp(avatar, "border", "1px solid #c8b99a");
sp(avatar, "display", "flex");
sp(avatar, "align-items", "center");
sp(avatar, "justify-content", "center");
sp(avatar, "cursor", "pointer");
sp(avatar, "font-family", "'Inter', sans-serif");
sp(avatar, "font-size", "0.75rem");
sp(avatar, "font-weight", "500");
sp(avatar, "color", "#2a2218");
sp(avatar, "box-sizing", "border-box");
var dropdown = document.createElement("div");
sp(dropdown, "display", "none");
sp(dropdown, "position", "absolute");
sp(dropdown, "top", "calc(100% + 8px)");
sp(dropdown, "right", "0");
sp(dropdown, "background", "#f9f6f0");
sp(dropdown, "border", "1px solid #e2d9c8");
sp(dropdown, "min-width", "220px");
sp(dropdown, "padding", "0");
sp(dropdown, "box-shadow", "0 4px 16px rgba(0,0,0,0.06)");
sp(dropdown, "z-index", "10000");
sp(dropdown, "box-sizing", "border-box");
var dpProfile = document.createElement("div");
sp(dpProfile, "padding", "1rem");
sp(dpProfile, "display", "flex");
sp(dpProfile, "flex-direction", "column");
sp(dpProfile, "align-items", "center");
sp(dpProfile, "gap", "0.25rem");
sp(dpProfile, "border-bottom", "1px solid #e2d9c8");
var dpAvatar = document.createElement("div");
dpAvatar.textContent = user.nickname.slice(0, 1).toUpperCase();
sp(dpAvatar, "width", "44px");
sp(dpAvatar, "height", "44px");
sp(dpAvatar, "border-radius", "50%");
sp(dpAvatar, "background", "#f0ebe0");
sp(dpAvatar, "border", "1px solid #c8b99a");
sp(dpAvatar, "display", "flex");
sp(dpAvatar, "align-items", "center");
sp(dpAvatar, "justify-content", "center");
sp(dpAvatar, "font-family", "'Inter', sans-serif");
sp(dpAvatar, "font-size", "1rem");
sp(dpAvatar, "font-weight", "500");
sp(dpAvatar, "color", "#c8a060");
sp(dpAvatar, "margin-bottom", "0.25rem");
var dpName = document.createElement("div");
dpName.textContent = user.nickname;
sp(dpName, "font-family", "'Inter', sans-serif");
sp(dpName, "font-size", "0.875rem");
sp(dpName, "font-weight", "500");
sp(dpName, "color", "#2a2218");
var dpTitle = document.createElement("div");
dpTitle.textContent = user.title || "Chronicler";
sp(dpTitle, "font-family", "'Inter', sans-serif");
sp(dpTitle, "font-size", "0.6875rem");
sp(dpTitle, "color", "#9c8e80");
sp(dpTitle, "font-style", "italic");
dpProfile.appendChild(dpAvatar);
dpProfile.appendChild(dpName);
dpProfile.appendChild(dpTitle);
var dpStats = document.createElement("div");
sp(dpStats, "display", "grid");
sp(dpStats, "grid-template-columns", "1fr 1fr");
sp(dpStats, "border-bottom", "1px solid #e2d9c8");
function makeStatCell(val, lbl, borderRight, borderBottom) {
var cell = document.createElement("div");
sp(cell, "padding", "0.5rem 0");
sp(cell, "text-align", "center");
if (borderRight) sp(cell, "border-right", "1px solid #e2d9c8");
if (borderBottom) sp(cell, "border-bottom", "1px solid #e2d9c8");
var valEl = document.createElement("div");
valEl.textContent = val;
valEl.className = "dp-stat-val";
sp(valEl, "font-family", "'Inter', sans-serif");
sp(valEl, "font-size", "0.8125rem");
sp(valEl, "font-weight", "500");
sp(valEl, "color", "#2a2218");
sp(valEl, "margin-bottom", "2px");
var lblEl = document.createElement("div");
lblEl.textContent = lbl;
sp(lblEl, "font-family", "'Inter', sans-serif");
sp(lblEl, "font-size", "0.5625rem");
sp(lblEl, "letter-spacing", "0.1em");
sp(lblEl, "color", "#9c8e80");
sp(lblEl, "text-transform", "uppercase");
cell.appendChild(valEl);
cell.appendChild(lblEl);
return cell;
}
var cellLevel = makeStatCell("—", "Level", true, true);
var cellExp = makeStatCell("—", "EXP", false, true);
var cellDays = makeStatCell("—", "Days Active", true, false);
var cellEdits = makeStatCell("—", "Edits", false, false);
dpStats.appendChild(cellLevel);
dpStats.appendChild(cellExp);
dpStats.appendChild(cellDays);
dpStats.appendChild(cellEdits);
var dpMenu = document.createElement("div");
sp(dpMenu, "padding", "0.25rem 0");
var profileLink = document.createElement("a");
profileLink.href = "https://erakh.com/profile";
profileLink.textContent = "Profile";
sp(profileLink, "display", "block");
sp(profileLink, "width", "100%");
sp(profileLink, "padding", "0.5rem 1rem");
sp(profileLink, "font-family", "'Inter', sans-serif");
sp(profileLink, "font-size", "0.8125rem");
sp(profileLink, "color", "#2a2218");
sp(profileLink, "text-decoration", "none");
sp(profileLink, "box-sizing", "border-box");
profileLink.addEventListener("mouseover", function() { this.style.setProperty("background", "#f0ebe0", "important"); });
profileLink.addEventListener("mouseout", function() { this.style.setProperty("background", "transparent", "important"); });
var signOutBtn = document.createElement("button");
signOutBtn.textContent = "Sign out";
sp(signOutBtn, "display", "block");
sp(signOutBtn, "width", "100%");
sp(signOutBtn, "padding", "0.5rem 1rem");
sp(signOutBtn, "font-family", "'Inter', sans-serif");
sp(signOutBtn, "font-size", "0.8125rem");
sp(signOutBtn, "color", "#a04040");
sp(signOutBtn, "text-align", "left");
sp(signOutBtn, "background", "transparent");
sp(signOutBtn, "border", "none");
sp(signOutBtn, "cursor", "pointer");
sp(signOutBtn, "box-sizing", "border-box");
signOutBtn.addEventListener("mouseover", function() { this.style.setProperty("background", "#f0ebe0", "important"); });
signOutBtn.addEventListener("mouseout", function() { this.style.setProperty("background", "transparent", "important"); });
signOutBtn.addEventListener("click", function () {
fetch("https://erakh.com/api/auth/logout", { method: "POST", credentials: "include" })
.then(function () { window.location.href = "https://erakh.com"; });
});
dpMenu.appendChild(profileLink);
dpMenu.appendChild(signOutBtn);
dropdown.appendChild(dpProfile);
dropdown.appendChild(dpStats);
dropdown.appendChild(dpMenu);
var profileLoaded = false;
avatar.addEventListener("click", function () {
var isHidden = dropdown.style.display === "none";
dropdown.style.display = isHidden ? "block" : "none";
if (isHidden && !profileLoaded) {
fetch("https://erakh.com/api/auth/me", { method: "GET", credentials: "include" })
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.isNew) return;
profileLoaded = true;
cellLevel.querySelector(".dp-stat-val").textContent = "Lv. " + data.level;
cellExp.querySelector(".dp-stat-val").textContent = data.exp_in_level + " / " + data.exp_to_next;
cellDays.querySelector(".dp-stat-val").textContent = data.login_days;
cellEdits.querySelector(".dp-stat-val").textContent = data.edit_count;
})
.catch(function() {});
}
});
document.addEventListener("click", function (e) {
if (!profile.contains(e.target)) {
dropdown.style.display = "none";
}
});
profile.appendChild(avatar);
profile.appendChild(dropdown);
right.appendChild(profile);
} else {
var loginBtn = document.createElement("a");
loginBtn.href = "https://erakh.com/login?redirect=" + encodeURIComponent(window.location.href);
loginBtn.textContent = "Sign in";
sp(loginBtn, "font-family", "'Inter', sans-serif");
sp(loginBtn, "font-size", "0.8125rem");
sp(loginBtn, "font-weight", "500");
sp(loginBtn, "color", "#2a2218");
sp(loginBtn, "text-decoration", "none");
sp(loginBtn, "padding", "0.4rem 1rem");
sp(loginBtn, "border", "1px solid #c8b99a");
sp(loginBtn, "background", "transparent");
sp(loginBtn, "cursor", "pointer");
sp(loginBtn, "box-sizing", "border-box");
sp(loginBtn, "line-height", "1");
loginBtn.addEventListener("mouseover", function() {
this.style.setProperty("border-color", "#c8a060", "important");
this.style.setProperty("background", "#f0ebe0", "important");
});
loginBtn.addEventListener("mouseout", function() {
this.style.setProperty("border-color", "#c8b99a", "important");
this.style.setProperty("background", "transparent", "important");
});
right.appendChild(loginBtn);
}
header.appendChild(left);
header.appendChild(right);
document.body.insertBefore(header, document.body.firstChild);
// ─── 서브바 ───
var subbar = document.createElement("div");
sp(subbar, "position", "fixed");
sp(subbar, "top", "56px");
sp(subbar, "left", "0");
sp(subbar, "right", "0");
sp(subbar, "z-index", "9998");
sp(subbar, "height", "44px");
sp(subbar, "background", "#f0ebe0");
sp(subbar, "border-bottom", "1px solid #e2d9c8");
sp(subbar, "display", "flex");
sp(subbar, "align-items", "center");
sp(subbar, "gap", "1rem");
sp(subbar, "padding", "0 1.5rem");
sp(subbar, "box-sizing", "border-box");
sp(subbar, "width", "100%");
// 햄버거 버튼
var hbBtn = document.createElement("button");
sp(hbBtn, "display", "flex");
sp(hbBtn, "flex-direction", "column");
sp(hbBtn, "justify-content", "center");
sp(hbBtn, "align-items", "center");
sp(hbBtn, "gap", "5px");
sp(hbBtn, "width", "32px");
sp(hbBtn, "height", "32px");
sp(hbBtn, "border", "none");
sp(hbBtn, "background", "transparent");
sp(hbBtn, "cursor", "pointer");
sp(hbBtn, "padding", "4px");
sp(hbBtn, "border-radius", "4px");
sp(hbBtn, "flex-shrink", "0");
sp(hbBtn, "box-sizing", "border-box");
function makeBar() {
var b = document.createElement("span");
b.style.setProperty("display", "block", "important");
b.style.setProperty("width", "18px", "important");
b.style.setProperty("height", "1.5px", "important");
b.style.setProperty("background", "#6b5e4e", "important");
b.style.setProperty("border-radius", "1px", "important");
return b;
}
hbBtn.appendChild(makeBar());
hbBtn.appendChild(makeBar());
hbBtn.appendChild(makeBar());
hbBtn.addEventListener("mouseover", function() { this.style.setProperty("background", "#e2d9c8", "important"); });
hbBtn.addEventListener("mouseout", function() { this.style.setProperty("background", "transparent", "important"); });
// 검색창
var searchWrap = document.createElement("div");
sp(searchWrap, "position", "relative");
sp(searchWrap, "flex", "1");
sp(searchWrap, "max-width", "520px");
var searchIconEl = document.createElement("span");
searchIconEl.innerHTML = "⚲";
sp(searchIconEl, "position", "absolute");
sp(searchIconEl, "left", "0.6rem");
sp(searchIconEl, "top", "50%");
sp(searchIconEl, "transform", "translateY(-50%)");
sp(searchIconEl, "font-size", "13px");
sp(searchIconEl, "color", "#9c8e80");
sp(searchIconEl, "pointer-events", "none");
sp(searchIconEl, "line-height", "1");
var searchInput = document.createElement("input");
searchInput.type = "text";
searchInput.placeholder = "Search Erakh Codex...";
sp(searchInput, "width", "100%");
sp(searchInput, "height", "30px");
sp(searchInput, "padding", "0 0.75rem 0 2rem");
sp(searchInput, "border", "1px solid #c8b99a");
sp(searchInput, "border-radius", "3px");
sp(searchInput, "background", "#f9f6f0");
sp(searchInput, "font-family", "'Inter', sans-serif");
sp(searchInput, "font-size", "0.8125rem");
sp(searchInput, "color", "#2a2218");
sp(searchInput, "outline", "none");
sp(searchInput, "box-sizing", "border-box");
var suggestBox = document.createElement("div");
sp(suggestBox, "position", "absolute");
sp(suggestBox, "top", "calc(100% + 2px)");
sp(suggestBox, "left", "0");
sp(suggestBox, "right", "0");
sp(suggestBox, "background", "#f9f6f0");
sp(suggestBox, "border", "1px solid #c8b99a");
sp(suggestBox, "border-radius", "3px");
sp(suggestBox, "z-index", "10001");
sp(suggestBox, "display", "none");
sp(suggestBox, "box-shadow", "0 4px 12px rgba(0,0,0,0.08)");
searchWrap.appendChild(suggestBox);
var suggestItems = [];
var suggestIndex = -1;
function renderSuggestions(titles) {
suggestBox.innerHTML = "";
suggestItems = titles;
suggestIndex = -1;
if (titles.length === 0) { suggestBox.style.setProperty("display", "none", "important"); return; }
titles.forEach(function(title, i) {
var item = document.createElement("div");
item.textContent = title;
sp(item, "padding", "0.4rem 0.75rem");
sp(item, "font-family", "'Inter', sans-serif");
sp(item, "font-size", "0.8125rem");
sp(item, "color", "#2a2218");
sp(item, "cursor", "pointer");
sp(item, "border-bottom", i < titles.length - 1 ? "1px solid #f0ebe0" : "none");
item.addEventListener("mouseover", function() { this.style.setProperty("background", "#f0ebe0", "important"); });
item.addEventListener("mouseout", function() { this.style.setProperty("background", "transparent", "important"); });
item.addEventListener("mousedown", function(e) {
e.preventDefault();
window.location.href = "/index.php?title=" + encodeURIComponent(title.replace(/ /g, "_"));
});
suggestBox.appendChild(item);
});
suggestBox.style.setProperty("display", "block", "important");
}
var suggestTimer = null;
searchInput.addEventListener("input", function() {
var q = this.value.trim();
clearTimeout(suggestTimer);
if (q.length < 2) { suggestBox.style.setProperty("display", "none", "important"); return; }
suggestTimer = setTimeout(function() {
fetch("/api.php?action=opensearch&search=" + encodeURIComponent(q) + "&limit=8&namespace=0&format=json")
.then(function(r) { return r.json(); })
.then(function(data) { renderSuggestions(data[1] || []); })
.catch(function() {});
}, 200);
});
searchInput.addEventListener("focus", function() { this.style.setProperty("border-color", "#c8a060", "important"); });
searchInput.addEventListener("blur", function() {
this.style.setProperty("border-color", "#c8b99a", "important");
setTimeout(function() { suggestBox.style.setProperty("display", "none", "important"); }, 150);
});
searchInput.addEventListener("keydown", function(e) {
var items = suggestBox.querySelectorAll("div");
if (e.key === "ArrowDown") {
e.preventDefault();
suggestIndex = Math.min(suggestIndex + 1, items.length - 1);
items.forEach(function(el, i) { el.style.setProperty("background", i === suggestIndex ? "#f0ebe0" : "transparent", "important"); });
} else if (e.key === "ArrowUp") {
e.preventDefault();
suggestIndex = Math.max(suggestIndex - 1, -1);
items.forEach(function(el, i) { el.style.setProperty("background", i === suggestIndex ? "#f0ebe0" : "transparent", "important"); });
} else if (e.key === "Enter") {
e.preventDefault();
if (suggestIndex >= 0 && suggestItems[suggestIndex]) {
window.location.href = "/index.php?title=" + encodeURIComponent(suggestItems[suggestIndex].replace(/ /g, "_"));
} else if (this.value.trim()) {
window.location.href = "/index.php?title=Special%3ASearch&search=" + encodeURIComponent(this.value.trim());
}
} else if (e.key === "Escape") {
suggestBox.style.setProperty("display", "none", "important");
}
});
searchWrap.appendChild(searchIconEl);
searchWrap.appendChild(searchInput);
subbar.appendChild(hbBtn);
subbar.appendChild(searchWrap);
// ─── [추가] 서브바 Create 버튼 (sysop only) ───
if (isSysop) {
var createDocBtn = document.createElement("a");
createDocBtn.href = "/index.php?title=Erakh_Codex:Create";
createDocBtn.textContent = "+ Create";
sp(createDocBtn, "display", "flex");
sp(createDocBtn, "align-items", "center");
sp(createDocBtn, "height", "44px");
sp(createDocBtn, "padding", "0 1.25rem");
sp(createDocBtn, "margin-left", "auto");
sp(createDocBtn, "font-family", "'Inter', sans-serif");
sp(createDocBtn, "font-size", "0.8125rem");
sp(createDocBtn, "font-weight", "500");
sp(createDocBtn, "color", "#c8a060");
sp(createDocBtn, "text-decoration", "none");
sp(createDocBtn, "border-left", "1px solid #e2d9c8");
sp(createDocBtn, "flex-shrink", "0");
sp(createDocBtn, "box-sizing", "border-box");
sp(createDocBtn, "letter-spacing", "-0.01em");
createDocBtn.addEventListener("mouseover", function() {
this.style.setProperty("background", "#e2d9c8", "important");
this.style.setProperty("color", "#a07840", "important");
});
createDocBtn.addEventListener("mouseout", function() {
this.style.setProperty("background", "transparent", "important");
this.style.setProperty("color", "#c8a060", "important");
});
subbar.appendChild(createDocBtn);
}
// ─── 드로어 ───
var drawerOverlay = document.createElement("div");
sp(drawerOverlay, "position", "fixed");
sp(drawerOverlay, "top", "100px");
sp(drawerOverlay, "left", "0");
sp(drawerOverlay, "right", "0");
sp(drawerOverlay, "bottom", "0");
sp(drawerOverlay, "background", "rgba(0,0,0,0.18)");
sp(drawerOverlay, "z-index", "9996");
sp(drawerOverlay, "display", "none");
var drawer = document.createElement("nav");
sp(drawer, "position", "fixed");
sp(drawer, "top", "100px");
sp(drawer, "left", "0");
sp(drawer, "bottom", "0");
sp(drawer, "width", "220px");
sp(drawer, "background", "#f9f6f0");
sp(drawer, "border-right", "1px solid #e2d9c8");
sp(drawer, "z-index", "9997");
sp(drawer, "display", "none");
sp(drawer, "overflow-y", "auto");
var drawerHead = document.createElement("div");
sp(drawerHead, "padding", "0.75rem 1rem 0.5rem");
sp(drawerHead, "border-bottom", "1px solid #e2d9c8");
var drawerLabel = document.createElement("span");
drawerLabel.textContent = "Menu";
sp(drawerLabel, "font-family", "'Inter', sans-serif");
sp(drawerLabel, "font-size", "0.78rem");
sp(drawerLabel, "font-weight", "500");
sp(drawerLabel, "color", "#2a2218");
sp(drawerLabel, "display", "inline-block");
sp(drawerLabel, "padding-bottom", "0.25rem");
sp(drawerLabel, "border-bottom", "2px solid #c8a060");
drawerHead.appendChild(drawerLabel);
drawer.appendChild(drawerHead);
var drawerMenus = [
{
items: [
{ label: "Main Page", href: "/" },
{ label: "Recent Changes", href: "/index.php?title=Special:RecentChanges" },
{ label: "Random Article", href: "/index.php?title=Special:Random" },
],
gold: true
},
{
items: [
{ label: "Editing Guide", href: "/index.php?title=Erakh_Codex:Editing_guide" },
{ label: "Policies & Guidelines", href: "/index.php?title=Erakh_Codex:Policies" },
{ label: "Help", href: "/index.php?title=Help:Contents" },
],
gold: false
},
{
items: [
{ label: "About Codex", href: "/index.php?title=Erakh_Codex:About" },
{ label: "Admin Requests", href: "/index.php?title=Erakh_Codex:Admin_requests" },
],
gold: false
}
];
drawerMenus.forEach(function(section, si) {
var sec = document.createElement("div");
sp(sec, "padding", "0.5rem 0");
if (si < drawerMenus.length - 1) sp(sec, "border-bottom", "1px solid #e2d9c8");
section.items.forEach(function(item) {
var a = document.createElement("a");
a.href = item.href;
a.textContent = item.label;
sp(a, "display", "block");
sp(a, "padding", "0.45rem 1.25rem");
sp(a, "font-family", "'Inter', sans-serif");
sp(a, "font-size", "0.8125rem");
sp(a, "color", section.gold ? "#c8a060" : "#6b5e4e");
sp(a, "text-decoration", "none");
a.addEventListener("mouseover", function() { this.style.setProperty("background", "#f0ebe0", "important"); });
a.addEventListener("mouseout", function() { this.style.setProperty("background", "transparent", "important"); });
sec.appendChild(a);
});
drawer.appendChild(sec);
});
var drawerOpen = false;
function toggleDrawer() {
drawerOpen = !drawerOpen;
drawer.style.setProperty("display", drawerOpen ? "block" : "none", "important");
drawerOverlay.style.setProperty("display", drawerOpen ? "block" : "none", "important");
}
hbBtn.addEventListener("click", toggleDrawer);
drawerOverlay.addEventListener("click", toggleDrawer);
document.body.insertBefore(subbar, document.body.children[1]);
document.body.appendChild(drawerOverlay);
document.body.appendChild(drawer);
// ─── 3컬럼 레이아웃 (JS 직접 목차 빌드) ───
function buildToc(headings) {
var toc = document.createElement("nav");
toc.id = "erakh-toc";
var ul = document.createElement("ul");
sp(ul, "list-style", "none");
sp(ul, "margin", "0");
sp(ul, "padding", "0");
headings.forEach(function(h, i) {
var level = parseInt(h.tagName.replace("H", ""));
var id = h.id || ("erakh-section-" + i);
h.id = id;
var li = document.createElement("li");
li.style.setProperty("padding", "0.25rem 0 0.25rem " + (level === 2 ? "0.5rem" : "1.25rem"), "important");
li.style.setProperty("border-left", "2px solid transparent", "important");
li.style.setProperty("line-height", "1.4", "important");
li.dataset.id = id;
var a = document.createElement("a");
a.href = "#" + id;
a.textContent = h.textContent.replace(/\[edit\]/g, "").trim();
sp(a, "font-family", "'Inter', sans-serif");
sp(a, "font-size", level === 2 ? "0.78rem" : "0.74rem");
sp(a, "color", level === 2 ? "#6b5e4e" : "#9c8e80");
sp(a, "text-decoration", "none");
sp(a, "display", "block");
a.addEventListener("mouseover", function() { this.style.setProperty("color", "#2a2218", "important"); });
a.addEventListener("mouseout", function() { this.style.setProperty("color", level === 2 ? "#6b5e4e" : "#9c8e80", "important"); });
li.appendChild(a);
ul.appendChild(li);
});
toc.appendChild(ul);
return toc;
}
function buildLayout() {
// ─── [추가] Create 페이지에서는 레이아웃 빌드 스킵 ───
if (pageName === "Erakh_Codex:Create") return;
var content = document.querySelector(".mw-body") || document.getElementById("content");
if (!content) return;
var headings = Array.from(content.querySelectorAll("h2, h3")).filter(function(h) {
return !h.closest("#toc");
});
var layout = document.createElement("div");
layout.className = "erakh-layout";
var colLeft = document.createElement("aside");
colLeft.className = "erakh-col-left";
var colCenter = document.createElement("div");
colCenter.className = "erakh-col-center";
var colRight = document.createElement("aside");
colRight.className = "erakh-col-right";
var tocLabel = document.createElement("div");
tocLabel.className = "erakh-toc-label";
tocLabel.textContent = "Contents";
colLeft.appendChild(tocLabel);
if (headings.length > 0) {
var toc = buildToc(headings);
colLeft.appendChild(toc);
var items = colLeft.querySelectorAll("li[data-id]");
window.addEventListener("scroll", function() {
var scrollY = window.scrollY + 108;
var current = null;
headings.forEach(function(h) {
if (h.offsetTop <= scrollY) current = h.id;
});
items.forEach(function(li) {
if (li.dataset.id === current) {
li.style.setProperty("border-left-color", "#c8a060", "important");
li.querySelector("a").style.setProperty("color", "#2a2218", "important");
li.querySelector("a").style.setProperty("font-weight", "500", "important");
} else {
li.style.setProperty("border-left-color", "transparent", "important");
var level = li.style.paddingLeft === "0.5rem" ? 2 : 3;
li.querySelector("a").style.setProperty("color", level === 2 ? "#6b5e4e" : "#9c8e80", "important");
li.querySelector("a").style.setProperty("font-weight", "400", "important");
}
});
});
} else {
var emptyMsg = document.createElement("div");
sp(emptyMsg, "font-family", "'Inter', sans-serif");
sp(emptyMsg, "font-size", "0.75rem");
sp(emptyMsg, "color", "#9c8e80");
sp(emptyMsg, "padding", "0.25rem 0.5rem");
emptyMsg.textContent = "—";
colLeft.appendChild(emptyMsg);
}
var sidebarLabel = document.createElement("div");
sidebarLabel.className = "erakh-sidebar-label";
sidebarLabel.textContent = "위젯 영역";
colRight.appendChild(sidebarLabel);
var ph1 = document.createElement("div");
ph1.className = "erakh-sidebar-placeholder";
ph1.textContent = "인기 문서 위젯 예정";
colRight.appendChild(ph1);
var ph2 = document.createElement("div");
ph2.className = "erakh-sidebar-placeholder";
ph2.textContent = "최근 변경 위젯 예정";
colRight.appendChild(ph2);
content.parentNode.insertBefore(layout, content);
colCenter.appendChild(content);
layout.appendChild(colLeft);
layout.appendChild(colCenter);
layout.appendChild(colRight);
}
// ─── [추가] 문서 생성 페이지 UI ───
function buildCreatePage() {
if (pageName !== "Erakh_Codex:Create") return;
var CATEGORIES = [
{ label: "Characters", preload: "Template:Preload/Character" },
{ label: "Nations", preload: "Template:Preload/Nation" },
{ label: "Regions", preload: "Template:Preload/Region" },
{ label: "Races", preload: "Template:Preload/Race" },
{ label: "Organizations", preload: "Template:Preload/Organization" },
{ label: "Events", preload: "Template:Preload/Event" },
{ label: "Disciplines", preload: "Template:Preload/Discipline" },
{ label: "Culture", preload: "Template:Preload/Culture" },
{ label: "Artifacts", preload: "Template:Preload/Artifact" },
{ label: "Chronicle", preload: null },
];
// MW 기본 UI 숨김
var firstHeading = document.getElementById("firstHeading");
if (firstHeading) sp(firstHeading, "display", "none");
var parseOutput = document.querySelector(".mw-parser-output");
if (parseOutput) sp(parseOutput, "display", "none");
var noArticle = document.querySelector(".noarticletext");
if (noArticle) sp(noArticle, "display", "none");
// 편집 탭/액션 숨김
var pViews = document.getElementById("p-views");
if (pViews) sp(pViews, "display", "none");
var pCactions = document.getElementById("p-cactions");
if (pCactions) sp(pCactions, "display", "none");
var target = document.getElementById("mw-content-text");
if (!target) return;
// 비sysop 접근 시 안내
if (!isSysop) {
var denied = document.createElement("div");
sp(denied, "padding", "60px 40px");
sp(denied, "text-align", "center");
sp(denied, "font-family", "'Inter', sans-serif");
sp(denied, "font-size", "0.875rem");
sp(denied, "color", "#9c8e80");
denied.textContent = "Document creation is restricted to administrators.";
target.appendChild(denied);
return;
}
var selectedCat = null;
// ── 컨테이너
var wrap = document.createElement("div");
sp(wrap, "max-width", "680px");
sp(wrap, "margin", "40px auto");
sp(wrap, "padding", "0 24px 48px");
sp(wrap, "font-family", "'Inter', sans-serif");
sp(wrap, "color", "#2a2218");
sp(wrap, "box-sizing", "border-box");
// ── 페이지 제목
var heading = document.createElement("h2");
heading.textContent = "Create New Document";
sp(heading, "font-size", "1.375rem");
sp(heading, "font-weight", "600");
sp(heading, "margin", "0 0 2rem 0");
sp(heading, "color", "#2a2218");
sp(heading, "letter-spacing", "-0.01em");
sp(heading, "font-family", "'Inter', sans-serif");
wrap.appendChild(heading);
// ── 카테고리 레이블
var catLabel = document.createElement("p");
catLabel.textContent = "Select Category";
sp(catLabel, "font-size", "0.6875rem");
sp(catLabel, "font-weight", "500");
sp(catLabel, "color", "#9c8e80");
sp(catLabel, "margin", "0 0 0.625rem 0");
sp(catLabel, "letter-spacing", "0.1em");
sp(catLabel, "text-transform", "uppercase");
sp(catLabel, "font-family", "'Inter', sans-serif");
wrap.appendChild(catLabel);
// ── 카테고리 그리드
var grid = document.createElement("div");
sp(grid, "display", "grid");
sp(grid, "grid-template-columns", "repeat(5, 1fr)");
sp(grid, "gap", "8px");
sp(grid, "margin-bottom", "0.625rem");
var catCards = [];
CATEGORIES.forEach(function(cat) {
var card = document.createElement("button");
card.textContent = cat.label;
sp(card, "border", "1.5px solid #e2d9c8");
sp(card, "border-radius", "6px");
sp(card, "background", "#f9f6f0");
sp(card, "padding", "0.75rem 0.375rem");
sp(card, "font-size", "0.79rem");
sp(card, "font-weight", "500");
sp(card, "font-family", "'Inter', sans-serif");
sp(card, "color", "#2a2218");
sp(card, "cursor", "pointer");
sp(card, "text-align", "center");
sp(card, "line-height", "1.3");
sp(card, "box-sizing", "border-box");
card.addEventListener("mouseover", function() {
if (selectedCat !== cat.label) {
this.style.setProperty("background", "#f0ebe0", "important");
this.style.setProperty("border-color", "#c8b99a", "important");
}
});
card.addEventListener("mouseout", function() {
if (selectedCat !== cat.label) {
this.style.setProperty("background", "#f9f6f0", "important");
this.style.setProperty("border-color", "#e2d9c8", "important");
}
});
card.addEventListener("click", function() {
catCards.forEach(function(c) {
c.style.setProperty("background", "#f9f6f0", "important");
c.style.setProperty("border-color", "#e2d9c8", "important");
c.style.setProperty("color", "#2a2218", "important");
});
this.style.setProperty("background", "#c8a060", "important");
this.style.setProperty("border-color", "#c8a060", "important");
this.style.setProperty("color", "#ffffff", "important");
selectedCat = cat.label;
if (cat.preload === null) {
chronicleNotice.style.setProperty("display", "block", "important");
} else {
chronicleNotice.style.setProperty("display", "none", "important");
}
updateBtn();
});
catCards.push(card);
grid.appendChild(card);
});
wrap.appendChild(grid);
// ── Chronicle 안내
var chronicleNotice = document.createElement("p");
chronicleNotice.textContent = "Chronicle documents use a timeline format. No infobox template will be applied.";
sp(chronicleNotice, "display", "none");
sp(chronicleNotice, "font-size", "0.75rem");
sp(chronicleNotice, "color", "#9c8e80");
sp(chronicleNotice, "font-style", "italic");
sp(chronicleNotice, "margin", "0.375rem 0 0 0");
sp(chronicleNotice, "font-family", "'Inter', sans-serif");
wrap.appendChild(chronicleNotice);
// ── 구분선
var divider = document.createElement("div");
sp(divider, "border-top", "1px solid #e2d9c8");
sp(divider, "margin", "1.5rem 0 1.25rem");
wrap.appendChild(divider);
// ── 제목 레이블
var titleLabel = document.createElement("p");
titleLabel.textContent = "Document Title";
sp(titleLabel, "font-size", "0.6875rem");
sp(titleLabel, "font-weight", "500");
sp(titleLabel, "color", "#9c8e80");
sp(titleLabel, "margin", "0 0 0.5rem 0");
sp(titleLabel, "letter-spacing", "0.1em");
sp(titleLabel, "text-transform", "uppercase");
sp(titleLabel, "font-family", "'Inter', sans-serif");
wrap.appendChild(titleLabel);
// ── 제목 입력
var titleInput = document.createElement("input");
titleInput.type = "text";
titleInput.placeholder = "Enter document title...";
sp(titleInput, "width", "100%");
sp(titleInput, "padding", "0.625rem 0.875rem");
sp(titleInput, "border", "1.5px solid #e2d9c8");
sp(titleInput, "border-radius", "6px");
sp(titleInput, "font-size", "0.9375rem");
sp(titleInput, "font-family", "'Inter', sans-serif");
sp(titleInput, "color", "#2a2218");
sp(titleInput, "background", "#ffffff");
sp(titleInput, "box-sizing", "border-box");
sp(titleInput, "outline", "none");
sp(titleInput, "margin-bottom", "1.25rem");
titleInput.addEventListener("focus", function() { this.style.setProperty("border-color", "#c8a060", "important"); });
titleInput.addEventListener("blur", function() { this.style.setProperty("border-color", "#e2d9c8", "important"); });
titleInput.addEventListener("input", updateBtn);
wrap.appendChild(titleInput);
// ── Create 버튼
var createBtn = document.createElement("button");
createBtn.textContent = "Create Article";
sp(createBtn, "display", "block");
sp(createBtn, "width", "100%");
sp(createBtn, "padding", "0.75rem");
sp(createBtn, "background", "#e2d9c8");
sp(createBtn, "border", "none");
sp(createBtn, "border-radius", "6px");
sp(createBtn, "font-size", "0.9375rem");
sp(createBtn, "font-weight", "600");
sp(createBtn, "font-family", "'Inter', sans-serif");
sp(createBtn, "color", "#9c8e80");
sp(createBtn, "cursor", "not-allowed");
sp(createBtn, "box-sizing", "border-box");
createBtn.addEventListener("click", function() {
if (!selectedCat) return;
var title = titleInput.value.trim();
if (!title) return;
var catObj = null;
for (var i = 0; i < CATEGORIES.length; i++) {
if (CATEGORIES[i].label === selectedCat) { catObj = CATEGORIES[i]; break; }
}
if (!catObj) return;
var url = "/index.php?title=" + encodeURIComponent(title) + "&action=edit";
if (catObj.preload) url += "&preload=" + encodeURIComponent(catObj.preload);
window.location.href = url;
});
wrap.appendChild(createBtn);
target.appendChild(wrap);
function updateBtn() {
var ready = selectedCat && titleInput.value.trim().length > 0;
if (ready) {
createBtn.style.setProperty("background", "#c8a060", "important");
createBtn.style.setProperty("color", "#ffffff", "important");
createBtn.style.setProperty("cursor", "pointer", "important");
} else {
createBtn.style.setProperty("background", "#e2d9c8", "important");
createBtn.style.setProperty("color", "#9c8e80", "important");
createBtn.style.setProperty("cursor", "not-allowed", "important");
}
}
}
// ─── 실행 ───
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", function() {
buildLayout();
buildCreatePage();
});
} else {
buildLayout();
buildCreatePage();
}
})();