Skip to content

Commit 49684de

Browse files
committed
Merge branch 'main' into fix/contributor-header-relative-path-support
2 parents b81205b + f63e56c commit 49684de

File tree

87 files changed

+2523
-1207
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+2523
-1207
lines changed

.pnp.cjs

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ https://frontend-fundamentals.com/code-quality/en/
2020
- [Code Quality Fundamentals](https://frontend-fundamentals.com/code-quality/)
2121
- [Bundling Fundamentals](https://frontend-fundamentals.com/bundling/)
2222
- [A11y Fundamentals](https://frontend-fundamentals.com/a11y/)
23+
- [Debug Fundamentals](https://frontend-fundamentals.com/debug/)
2324

2425
## Contributing
2526

fundamentals/bundling/deep-dive/optimization/code-splitting.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ function App() {
9292

9393
[`SplitChunksPlugin`](https://webpack.kr/plugins/split-chunks-plugin/)을 사용하면 웹팩에서 코드 스플리팅을 자동화할 수 있어요. 이 플러그인을 활용하면 중복되는 모듈을 하나의 청크로 분리하거나, 특정 크기 이상의 파일을 자동으로 나눠 번들 크기를 최적화할 수 있어요.
9494

95-
Webpack 5부터 name 값을 `false` | `string` | `function` 만 받을 수 있돋록 더 strict하게 강화되었어요.
95+
Webpack 5부터 name 값을 `false` | `string` | `function` 만 받을 수 있도록 더 strict하게 강화되었어요.
9696
각각을 좀 더 자세하게 살펴볼게요.
9797

9898
::: 실습 전에 번들 파일의 이름을 동적으로 설정해주세요!

fundamentals/bundling/webpack-tutorial/environment.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ npm install --save-dev dotenv-webpack
3131

3232
`.env` 파일 예시:
3333

34-
```env
34+
```dotenv
3535
# API 설정
3636
API_URL=https://api.example.com
3737
API_KEY=your-api-key
@@ -108,7 +108,7 @@ const App: React.FC = () => {
108108
- `dotenv-webpack``safe` 옵션을 사용해요
109109
- `.env.example` 파일에 필수 변수를 정의해요:
110110

111-
```env
111+
```dotenv
112112
API_URL=
113113
API_KEY=
114114
DEBUG_MODE=

fundamentals/bundling/webpack-tutorial/make-first-bundle.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ document.addEventListener("DOMContentLoaded", function () {
113113

114114
지금까지 만들어진 파일 구조를 다시 살펴볼게요.
115115

116-
```{6-10}
116+
```text{6-10}
117117
example-project/
118118
├── index.html
119119
├── style.css

fundamentals/code-quality/.vitepress/shared.mts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ export const shared = defineConfig({
1919
{
2020
rel: "icon",
2121
type: "image/x-icon",
22-
href: "/code-quality/images/favicon.ico"
22+
href: "images/favicon.ico"
2323
}
2424
],
25-
["link", { rel: "manifest", href: "/images/site.webmanifest" }],
26-
["link", { rel: "apple-touch-icon", href: "/images/apple-touch-icon.png" }],
25+
["link", { rel: "manifest", href: "images/site.webmanifest" }],
26+
["link", { rel: "apple-touch-icon", href: "images/apple-touch-icon.png" }],
2727
[
2828
"link",
2929
{
@@ -80,13 +80,12 @@ export const shared = defineConfig({
8080

8181
head.push(["meta", { property: "og:title", content: title }]);
8282
head.push(["meta", { property: "og:description", content: description }]);
83-
head.push(["base", { href: "/code-quality/" }]);
8483

8584
return head;
8685
},
8786

8887
themeConfig: {
89-
logo: "/images/ff-symbol.svg",
88+
logo: "images/ff-symbol.svg",
9089
editLink: {
9190
pattern:
9291
"https://github.com/toss/frontend-fundamentals/edit/main/fundamentals/code-quality/:path"

fundamentals/debug/.vitepress/config.mts

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default defineConfig({
1414
description: "프론트엔드 접근성의 모든 것",
1515
ignoreDeadLinks: false,
1616
base: "/debug/",
17+
lastUpdated: true,
1718
locales: {
1819
// temporary
1920
en: {
@@ -130,8 +131,86 @@ export default defineConfig({
130131
text: "디버깅 실무 사례",
131132
items: [
132133
{
133-
text: "Suspense Error 디버깅 by.김형규",
134-
link: "/pages/contribute/suspense_debug_by_hyungkyu.md"
134+
text:"javascript",
135+
items:[
136+
{
137+
text: "MAX_SAFE_INTEGER 정밀도 손실",
138+
link: "/pages/contribute/javascript/javascript_max_number_error_debug.md"
139+
}]
140+
},
141+
{
142+
text:"react",
143+
items:[
144+
{
145+
text: "BroadcastQueryClient SuspenseError",
146+
link: "/pages/contribute/react/broadcast_suspense_error_debug.md"
147+
},
148+
{
149+
text: "React Suspense와 framer-motion UI 충돌",
150+
link: "/pages/contribute/react/react_suspense_and_framer_motion_ui_debug.md"
151+
}
152+
]
153+
},
154+
{
155+
text:'ios',
156+
items:[
157+
{
158+
text: "iOS 웹뷰 이미지 업로드 시 페이지가 새로고침 되는 현상",
159+
link: "/pages/contribute/ios/ios_webview_image_upload_refresh_debug.md"
160+
},
161+
{
162+
text: "iOS 웹뷰에서 스와이프 뒤로가기 시 회색 화면이 표시되는 현상",
163+
link: "/pages/contribute/ios/ios_webview_swipe_back_gray_screen_debug.md"
164+
},
165+
{
166+
text: "Safari에서 TradingView iframe 메모리 누수",
167+
link: "/pages/contribute/ios/tradingview_iframe_memory_leak_debug.md"
168+
}
169+
]
170+
},
171+
{text:'android',
172+
items:[
173+
{
174+
text: "Android에서 React Native 번들 로딩 시 SIGBUS 크래시",
175+
link: "/pages/contribute/android/android_react_native_bundle_loading_sigbus_crash_debug.md"
176+
},
177+
]
178+
},
179+
{
180+
text:'public',
181+
items:[
182+
{
183+
text: "토스아이디 OG 이미지에 타인의 프로필이 표시되는 현상",
184+
link: "/pages/contribute/public/tossid_og_image_other_profile_debug.md"
185+
},
186+
]
187+
},
188+
{
189+
text:'compile',
190+
items:[
191+
{
192+
text: "ESLint/TSC 파싱 콜스택 오버플로우",
193+
link: "/pages/contribute/compile/codegen_callstack_overflow_debug.md"
194+
}
195+
]
196+
},
197+
{
198+
text:'yarn',
199+
items:[
200+
{
201+
text: "Yarn Workspace에서 HMR이 동작하지 않는 현상",
202+
link: "/pages/contribute/yarn/yarn_workspace_hmr_debug.md"
203+
},
204+
]
205+
},
206+
{
207+
text:'cursor',
208+
items:[
209+
{
210+
text: "Cursor에서 Biome 포맷팅이 동작하지 않는 현상",
211+
link: "/pages/contribute/cursor/cursor_biome_formatting_debug.md"
212+
}
213+
]
135214
},
136215
{ text: "기여하기 탬플릿", link: "/pages/contribute/template.md" }
137216
]
@@ -152,7 +231,7 @@ export default defineConfig({
152231
{
153232
rel: "icon",
154233
type: "image/x-icon",
155-
href: "/bundling/images/favicon.ico"
234+
href: "/debug/images/favicon.ico"
156235
}
157236
],
158237
[

fundamentals/debug/.vitepress/shared.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export const sharedConfig = defineConfig({
7272
},
7373

7474
themeConfig: {
75+
logo: "/images/ff-symbol.svg",
7576
socialLinks: [
7677
{ icon: "github", link: "https://github.com/toss/frontend-fundamentals" }
7778
],

fundamentals/debug/.vitepress/theme/components/ContributorHeader.vue

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { computed } from "vue";
44
const props = defineProps<{
55
name: string;
66
avatar?: string;
7+
githubUrl?: string;
8+
date?: string;
9+
readingTime?: string;
710
size?: number;
811
}>();
912
@@ -36,16 +39,92 @@ const avatarSrc = computed(() => {
3639
</script>
3740

3841
<template>
39-
<div
40-
style="display: flex; align-items: center; gap: 12px; margin: 8px 0 24px"
41-
>
42+
<div class="contributor-header">
4243
<img
4344
:src="avatarSrc"
44-
:width="size ?? 40"
45-
:height="size ?? 40"
45+
:width="size || 50"
46+
:height="size || 50"
4647
:alt="name"
47-
style="border-radius: 50%; object-fit: cover"
48+
class="contributor-avatar"
4849
/>
49-
<strong>{{ name }}</strong>
50+
<div class="contributor-info">
51+
<a
52+
v-if="githubUrl"
53+
:href="githubUrl"
54+
target="_blank"
55+
class="contributor-name"
56+
>
57+
{{ name }}
58+
<svg
59+
viewBox="0 0 16 16"
60+
width="14"
61+
height="14"
62+
fill="currentColor"
63+
style="margin-left: 4px"
64+
>
65+
<path
66+
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
67+
/>
68+
</svg>
69+
</a>
70+
<strong v-else class="contributor-name">{{ name }}</strong>
71+
<div class="contributor-meta">
72+
<span v-if="date" class="meta-item">{{ date }}</span>
73+
<span v-if="readingTime" class="meta-item">{{ readingTime }}</span>
74+
</div>
75+
</div>
5076
</div>
5177
</template>
78+
79+
<style scoped>
80+
.contributor-header {
81+
display: flex;
82+
align-items: center;
83+
justify-content: flex-end;
84+
gap: 16px;
85+
margin: 24px 0 32px;
86+
}
87+
88+
.contributor-avatar {
89+
border-radius: 50%;
90+
object-fit: cover;
91+
flex-shrink: 0;
92+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
93+
order: 2;
94+
}
95+
96+
.contributor-info {
97+
display: flex;
98+
flex-direction: column;
99+
gap: 2px;
100+
min-width: 0;
101+
align-items: flex-end;
102+
order: 1;
103+
}
104+
105+
.contributor-name {
106+
display: inline-flex;
107+
align-items: center;
108+
font-size: 1.1em;
109+
font-weight: 600;
110+
color: var(--vp-c-text-1);
111+
text-decoration: none;
112+
transition: color 0.2s;
113+
}
114+
115+
.contributor-name:hover {
116+
color: var(--vp-c-text-2);
117+
}
118+
119+
.contributor-meta {
120+
display: flex;
121+
align-items: center;
122+
gap: 12px;
123+
font-size: 0.9em;
124+
color: var(--vp-c-text-2);
125+
}
126+
127+
.meta-item {
128+
display: inline-block;
129+
}
130+
</style>
1.45 MB
Loading

0 commit comments

Comments
 (0)