아래는 Profile 페이지의 코드를 상세히 설명한 내용입니다. HTML, CSS, JavaScript로 구성된 Profile 페이지는 다양한 섹션을 포함하고 있으며, 각 섹션은 Markdown 파일에서 데이터를 동적으로 가져와 렌더링합니다.
### 디렉터리 구조
```
/profile
index.html
profile.css
profile.js
markdown
profile.md
```
### HTML (`index.html`)
Profile 페이지의 HTML 구조입니다. 공통된 header와 footer를 사용하고, main 태그 내부에 Markdown 데이터를 렌더링할 수 있는 container를 포함합니다.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Profile Page</title>
<link rel="stylesheet" href="../common/css/common.css">
<link rel="stylesheet" href="profile.css">
</head>
<body>
<!-- 공통 헤더 -->
<header>
<nav>
<ul>
<li><a href="../home/index.html">Home</a></li>
<li><a href="../profile/index.html">Profile</a></li>
<li><a href="../blog/index.html">Blog</a></li>
</ul>
</nav>
</header>
<!-- 메인 콘텐츠 -->
<main>
<section id="profile" class="section">
<div class="container">
<h3 class="section-title">Profile</h3>
<div class="markdown-content" id="profile-content"></div>
</div>
</section>
</main>
<!-- 공통 푸터 -->
<footer>
<p>© 2024 Your Name. All rights reserved.</p>
</footer>
<script src="profile.js"></script>
</body>
</html>
```
### CSS (`profile.css`)
Profile 페이지의 CSS입니다. 공통 스타일을 포함한 후, 각 섹션과 요소들의 스타일을 정의합니다.
```css
/* 공통 스타일을 사용하기 위해 common.css 포함 */
@import url('../common/css/common.css');
/* FontAwesome 사용을 위해 */
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css');
/* 공통 섹션 스타일 */
.section {
padding: 50px 0;
background: #f9f9f9; /* 기본 배경 색상 */
text-align: center; /* 글자 가운데 정렬 */
}
.section .container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 섹션에 그림자 추가 */
background: #fff; /* 섹션 배경 색상 */
border-radius: 10px; /* 모서리를 둥글게 */
padding: 20px;
}
.section-title {
font-size: 2em;
margin-bottom: 20px;
color: #333; /* 제목 색상 */
border-bottom: 2px solid #eee; /* 제목 아래에 구분선 */
padding-bottom: 10px;
}
/* Markdown 콘텐츠 스타일 */
.markdown-content h4.markdown-header {
font-weight: bold;
margin-top: 20px;
color: #444; /* 헤더 색상 */
}
.markdown-content ul {
list-style: disc;
padding-left: 20px;
margin-bottom: 20px;
text-align: left; /* 리스트 아이템은 왼쪽 정렬 */
}
.markdown-content li.markdown-list {
margin-bottom: 10px;
}
.markdown-content a.markdown-link {
color: #004080;
text-decoration: none;
transition: color 0.3s ease, transform 0.3s ease;
}
.markdown-content a.markdown-link:hover {
color: #007BFF;
transform: scale(1.1);
text-decoration: underline;
}
.markdown-content strong.markdown-bold {
font-weight: bold;
}
.markdown-content em.markdown-italic {
font-style: italic;
}
.markdown-content p.markdown-paragraph {
margin-bottom: 15px;
}
/* Profile Section 스타일 */
.section#profile {
background: linear-gradient(to right, #f0f8ff, #e0f7fa);
}
.section#profile .profile-card {
padding: 20px;
background: #f9f9f9;
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.section#profile .profile-links {
display: flex;
justify-content: center;
gap: 15px;
margin-top: 10px;
}
.profile-link {
display: flex;
align-items: center;
text-decoration: none;
color: #004080;
font-size: 1.1em;
transition: color 0.3s ease, transform 0.3s ease;
}
.profile-link i {
margin-right: 5px;
}
.profile-link:hover {
color: #007BFF;
transform: scale(1.1);
text-decoration: underline;
}
```
### JavaScript (`profile.js`)
Profile 페이지의 JavaScript입니다. Markdown 파일을 비동기적으로 읽어와서 HTML로 변환한 후 페이지에 삽입합니다.
```javascript
// profile.js
// Markdown을 HTML로 변환하는 함수
function markdownToHtml(markdown) {
// 제목 변환
markdown = markdown.replace(/^### (.*$)/gim, '<h4 class="markdown-header">$1</h4>');
markdown = markdown.replace(/^## (.*$)/gim, '<h3 class="markdown-header">$1</h3>');
markdown = markdown.replace(/^# (.*$)/gim, '<h2 class="markdown-header">$1</h2>');
// 리스트 변환
markdown = markdown.replace(/^\* (.*$)/gim, '<li class="markdown-list">$1</li>');
markdown = markdown.replace(/^\- (.*$)/gim, '<li class="markdown-list">$1</li>');
markdown = markdown.replace(/^(\d+)\. (.*$)/gim, '<li class="markdown-list">$2</li>');
// 링크 변환
markdown = markdown.replace(/\[([^\[]+)\]\(([^\)]+)\)/gim, '<a class="markdown-link" href="$2">$1</a>');
// 굵은 글씨 변환
markdown = markdown.replace(/\*\*(.*)\*\*/gim, '<strong class="markdown-bold">$1</strong>');
markdown = markdown.replace(/\*(.*)\*/gim, '<em class="markdown-italic">$1</em>');
// 단락 변환
markdown = markdown.replace(/^\s*(.*)/gm, '<p class="markdown-paragraph">$1</p>');
return markdown.trim();
}
// Markdown 파일을 비동기적으로 읽어오는 함수
async function fetchMarkdown(file) {
const response = await fetch(file);
const markdown = await response.text();
return markdownToHtml(markdown);
}
// 프로필 섹션을 별도로 생성하는 함수
function createProfileSection(markdown) {
const profileHtml = markdownToHtml(markdown);
const links = profileHtml.match(/<a class="markdown-link" href="([^"]+)">([^<]+)<\/a>/g);
const linksHtml = links ? links.map(link => {
const url = link.match(/href="([^"]+)"/)[1];
const text = link.match(/">([^<]+)<\/a>/)[1];
let icon;
if (text.toLowerCase().includes('linkedin')) {
icon = '<i class="fab fa-linkedin"></i>';
} else if (text.toLowerCase().includes('github')) {
icon = '<i class="fab fa-github"></i>';
} else if (text.toLowerCase().includes('twitter')) {
icon = '<i class="fab fa-twitter"></i>';
} else {
icon = '<i class="fas fa-link"></i>';
}
return `<a class="profile-link" href="${url}">${icon} ${text}</a>`;
}).join(' ') : '';
const description = profileHtml.replace(/<a class="markdown-link"[^>]*>[^<]*<\/a>/g, '');
return `
<div class="profile-card">
<div class="markdown-content">
${description}
</div>
<div class="profile-links">
${linksHtml}
</div>
</div>
`;
}
// 섹션을 동적으로 생성하는 함수
function createSections(markdown) {
const sections = markdown.split(/^## /gm).slice(1);
sections.forEach(section => {
const lines = section.split('\n');
const sectionTitle = lines[0].trim();
const sectionId = sectionTitle.toLowerCase().replace(/\s+/g, '');
const sectionContent = lines.slice(1).join('\n').trim();
let htmlContent;
if (sectionId === 'profile') {
htmlContent = createProfileSection(sectionContent);
} else {
htmlContent = markdownToHtml(sectionContent);
}
const sectionHtml = `
<section id="${sectionId}" class="section">
<div class="container">
<h3 class="section-title">${sectionTitle}</h3>
<div class="markdown-content">
${htmlContent}
</div>
</div>
</section>
`;
document.getElementById('profile-content').innerHTML += sectionHtml;
});
}
// Markdown 파일을 읽어와서 페이지에 삽입하는 함수
async function loadMarkdown() {
const response = await fetch('markdown/profile.md');
const markdown = await response.text();
// 섹션 생성
createSections(markdown);
}
// DOMContentLoaded 이벤트가 발생하면 loadMarkdown 함수 호출
document.addEventListener('DOMContentLoaded', () => {
loadMarkdown();
});
```
### Markdown 파일 예시 (`profile.md`)
```markdown
## Profile
### John Doe
- LinkedIn: [linkedin.com/in/johndoe](https://www.linkedin.com/in/johndoe)
- GitHub: [github.com/johndoe](https://github.com/johndoe)
### Bio
John Doe is a software engineer with over 10 years of experience...
## Experience
### Senior Developer at XYZ Company
*2020-2024*
- Description of responsibilities and achievements.
- Description of responsibilities and achievements.
- Description of responsibilities and achievements.
## Education
### Bachelor's Degree in Computer Science, University A
*2008-2012*
- Summary of the degree and key learnings.
- Summary of the degree and key learnings.
- Summary of the degree and key learnings.
## Projects
### Project 1
Description of the project, technologies used, and outcomes.
[GitHub](https://github.com/username/project1)
[Live Demo](https://username.github.io/project1)
## Skills
- HTML
- CSS
- JavaScript
- React
- Node.js
## Extra Activities
### Volunteer Web Developer
*Organization XYZ*
- Description of activities and impact.
- Description of activities and impact.
- Description of activities and impact.
```
이 코드는 `profile.md` 파일을 읽어와서 HTML로 변환한 후, Profile 페이지에 동적으로 삽입합니다. 각 섹션은 Markdown 파일에서 정의된 내용을 기반으로 렌더링됩니다.
'Javascript 프로젝트 > GitHub 웹 페이지' 카테고리의 다른 글
[GitHub 웹페이지] Blog 페이지 (0) | 2024.06.10 |
---|---|
[GitHub 웹페이지] 6. 프로필 페이지 - 와이어프레임 (0) | 2024.06.09 |
[GitHub 웹페이지] 5. 블로그 페이지 - 와이어프레임 (0) | 2024.06.09 |
[GitHub 웹페이지] 4. 홈페이지 - 와이어프레임 (0) | 2024.06.09 |
[GitHub 웹페이지] 2. 규칙 정하기 - Git Commit Message (0) | 2024.06.09 |