Public Source Viewer
비나래아카이브 개발자 포털
실제 서비스 구조를 살펴볼 수 있는 공개용 코드 뷰어입니다. 인증, 세션, 외부 연동, 토큰, 관리자 식별 등 보안상 민감한 구현은 파일 단위 또는 줄 단위로 검열됩니다.
view/hinana/partials/site-header.ejs
공개 가능
1
<%
2
const siteDark = typeof theme !== 'undefined' && theme === 'dark';
3
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
4
const sitePath = typeof uiPath !== 'undefined' && uiPath.startsWith('/') && !uiPath.startsWith('//') ? uiPath : '/hinana/index';
5
const sitePage = typeof uiPage !== 'undefined' ? uiPage : '';
6
const siteSection = ['login','signup','userInfo','admin','backups','monitor','securityDashboard','developer','forbidden'].includes(sitePage) || sitePage.startsWith('404') ? ''
7
: ['index','post','archiveSearch'].includes(sitePage) ? 'index'
8
: ['blog','blogpost','write','editPost'].includes(sitePage) ? 'blog'
9
: ['main','info','gallery','plaza','studio'].includes(sitePage) ? sitePage : 'lounge';
10
const siteLinks = [['main','/','홈','home'],['index','/hinana/index','아카이브','archive'],['blog','/hinana/blog','블로그','book'],['studio','/hinana/studio','Hinana Studio','spark'],['lounge','/hinana/lounge','라운지','cup'],['gallery','/hinana/gallery','갤러리','image'],['plaza','/hinana/plaza','광장','chat'],['info','/hinana/info','소개','note']];
11
const siteTools = [['works','/hinana/works','작품 일람','book'],['rail','/hinana/rail','히나나레일','train'],['japaneseLounge','/hinana/japanese-lounge','일본어 라운지','language']];
12
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
13
const siteRelated = {aiNotes:[['/hinana/ai','AI 대화'],['/hinana/personal-notes','개인 노트']],personalNotes:[['/hinana/ai/notes','AI 노트']],aiView:[['/hinana/ai','AI 대화로 돌아가기']],subway:[['/hinana/subway/map','지하철 노선도']],subwayMap:[['/hinana/subway','실시간 지하철']],exhibition:[['/hinana/gallery','갤러리']],monitor:[['/hinana/userInfo','내 정보']],blogpost:siteUser?[['/hinana/write','새 글 쓰기']]:[]}[sitePage] || [];
14
%>
15
<%- include('site-icons') %>
16
<a class="ui-skip" href="#ui-content">본문으로 건너뛰기</a>
17
<aside class="ui-sidebar" id="ui-sidebar" aria-label="사이트 메뉴">
18
<a class="ui-side-brand" href="/" aria-label="비나래 아카이브 홈"><img src="/image/<%= siteDark ? 'archive1.png' : 'archive.png' %>" alt="비나래 아카이브"></a>
19
<div class="ui-side-group"><div class="ui-side-label">ARCHIVE</div><nav aria-label="주요 메뉴">
20
<% siteLinks.forEach(([key,href,label,icon])=>{ %><a class="ui-side-link<%= siteSection===key?' is-current':'' %>" href="<%= href %>"<%- siteSection===key?' aria-current="page"':'' %>><svg aria-hidden="true"><use href="#ui-i-<%= icon %>"/></svg><span><%= label %></span></a><% }); %>
21
</nav></div>
22
<div class="ui-side-group"><div class="ui-side-label">작은 도구들</div><nav aria-label="도구 메뉴">
23
<% siteTools.forEach(([key,href,label,icon])=>{ %><a class="ui-side-link<%= sitePage===key?' is-current':'' %>" href="<%= href %>"<%- sitePage===key?' aria-current="page"':'' %>><svg aria-hidden="true"><use href="#ui-i-<%= icon %>"/></svg><span><%= label %></span></a><% }); %>
24
<% if(siteUser){ %><a class="ui-side-link<%= sitePage==='aiNotes'?' is-current':'' %>" href="/hinana/ai/notes"><svg aria-hidden="true"><use href="#ui-i-note"/></svg><span>AI 노트</span></a><% } %>
25
</nav></div>
26
<div class="ui-side-bottom">
27
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
28
<div class="ui-side-note"><strong>Archive My Memory</strong><span>취향과 기록이 모이는 작은 공간.</span><span>© 2024–2026 비나래 · hinana.moe</span></div>
29
</div>
30
</aside>
31
<button class="ui-sidebar-dim" id="ui-sidebar-dim" aria-label="메뉴 닫기" tabindex="-1" hidden></button>
32
<header class="ui-header">
33
<button type="button" class="ui-icon ui-mobile-menu" id="ui-menu-toggle" aria-label="메뉴 열기" aria-controls="ui-sidebar" aria-expanded="false"><svg aria-hidden="true"><use href="#ui-i-menu"/></svg></button>
34
<nav class="ui-breadcrumbs" aria-label="현재 위치"><a href="/">비나래 아카이브</a><span aria-hidden="true">/</span><span><%= siteLabels[sitePage] || (sitePage.startsWith('404')?'페이지를 찾을 수 없어요':'라운지') %></span></nav>
35
<form class="ui-global-search" action="/hinana/archive-search" method="GET" role="search"><svg aria-hidden="true"><use href="#ui-i-search"/></svg><input type="search" name="q" id="ui-global-search" aria-label="아카이브 통합 검색" placeholder="기록 검색..." value="<%= sitePage==='archiveSearch'&&typeof query!=='undefined'?query:'' %>" maxlength="120"><span class="ui-keycap" aria-hidden="true">⌘ K</span><button type="submit" class="ui-search-submit" aria-label="검색"><svg aria-hidden="true"><use href="#ui-i-arrow"/></svg></button></form>
36
<div class="ui-actions">
37
<% if(sitePage==='ai'){ %><button type="button" class="ui-icon btn-history-toggle" id="btn-history-toggle" aria-controls="ai-history-drawer" aria-expanded="false" title="대화 기록" aria-label="대화 기록" style="display:none"><svg aria-hidden="true"><use href="#ui-i-book"/></svg></button><% } %>
38
[SECURITY REDACTED] 민감한 설정/인증/토큰 관련 코드입니다.
39
<% if(siteUser){ %><details class="ui-account-menu"><summary class="ui-account" aria-label="<%= siteUser %> 계정 메뉴"><span class="ui-account-dot" aria-hidden="true"></span><span><%= siteUser %></span></summary><nav class="ui-account-panel" aria-label="계정 메뉴"><a href="/hinana/userInfo">내 정보</a><a href="/hinana/ai/notes">AI 노트</a><% if(siteUser==='비나래'){ %><a href="/hinana/personal-notes">개인 노트</a><a href="/hinana/security">보안 관제</a><a href="/hinana/backups">백업 센터</a><% } %><a href="/logout?redirect=<%= encodeURIComponent(sitePath) %>">로그아웃</a></nav></details>
40
<% }else{ %><a class="ui-account" href="/login?redirect=<%= encodeURIComponent(sitePath) %>"><span>로그인</span></a><% } %>
41
</div>
42
</header>
43
<% if(siteRelated.length){ %><nav class="ui-context" aria-label="관련 메뉴"><% siteRelated.forEach(([href,label])=>{ %><a href="<%= href %>"><%= label %><span aria-hidden="true"> →</span></a><% }); %></nav><% } %>
44
<script src="/js/site-app.js?v=1" defer></script>
45