Skip to content

Commit 516689b

Browse files
authored
v5.0.0 릴리즈 (#78)
* Merge pull request #68 from hs-shell/refactor/content-components refactor: 코드 단순화, 폴더 구조 재정리 및 보안 취약점 해결 * feat: 다국어(i18n) 지원 및 LMS 파싱 다국어 대응 (#69) * feat: 다국어(i18n) 지원 추가 (ko, en, ja, zh) - react-i18next 도입 및 4개 네임스페이스(common, option, popover, player) 구성 - 한국어/영어/일본어/중국어 번역 파일 작성 - Chrome _locales 설정 및 manifest __MSG_*__ 적용 - 모든 UI 컴포넌트 하드코딩 문자열을 t() 함수로 교체 - dateUtils/stringUtils에서 i18n.t() 직접 사용 - TimeDifferenceResult에 status 필드 추가 (문자열 매칭 제거) - SummaryCard type prop 리팩터 (title.includes 패턴 제거) - 사이드바에 언어 전환 드롭다운 추가 * refactor: LMS 파싱 키워드를 lmsKeywords.ts로 분리 - NOT_SUBMITTED, BULK_APPROVED 배열을 별도 파일로 추출 - 새 LMS 언어 추가 시 배열에 문자열만 추가하면 동작 * feat: LMS 날짜 형식 다국어 정규화 추가 - normalizeLmsDate/normalizeLmsRange 함수로 ja/zh 날짜 형식 대응 - fetchAssign, fetchQuiz, fetchVodList에서 파싱 단계에서 날짜 정규화 * feat: mock 모드에서 실제 LMS fetch 테스트 지원 - VITE_MOCK_COURSES로 과목 지정 시 실제 scrapeCourseData 호출 - VITE_MOCK_SKIP_DATE_FILTER로 마감 필터링 비활성화 (지난 학기 테스트용) * feat: 팝오버 설정 탭 및 캘린더 연동 개선 (#70) * feat: popover 설정(Setting) 탭 추가 - Setting 컴포넌트 구현 (언어 전환 Select + 문의 링크) - shadcn Select/DropdownMenu Shadow DOM Portal 대응 - TabNavigation에 설정 탭 추가 (4칸 그리드) - DashboardHeader에서 Setting 탭일 때 검색/필터/새로고침 숨김 - 4개 언어 번역 파일에 setting, contact, refresh 키 추가 * feat: 팝오버 설정 탭 UI 개선 및 다국어 키 추가 - Setting 컴포넌트에 Google Calendar 배너, 문의하기, GitHub Star 배너 추가 - common.json에 calendar, bubble, github 번역 키 추가 (ko/en/ja/zh) - DashboardHeader, TabNavigation, Dashboard UI 개선 - InfoBubble 컴포넌트 추가 * feat: InfoBubble 등장 애니메이션 추가 및 언어 설정 UI 개선 - InfoBubble에 아래에서 올라오는 framer-motion fade-in 애니메이션 추가 - 언어 선택 드롭다운 화살표 아이콘 제거, 선택값 폰트 크기 증가 * feat: 팝오버에 구글 캘린더 연동 기능 추가 * chore: 옵션 페이지 삭제 * chore: 청킹 리밋 변경 * feat: InfoBubble UX 개선 및 새로고침 블로킹 제거 - deprecated @types/gapi.client.calendar를 @types/gapi.client.calendar-v3로 교체 - InfoBubble 멘트를 친근한 톤으로 변경 (4개 언어) - 최신화 시간 30분 이상 시 주황색 표시 - VOD 카운팅을 주차 그룹 기준으로 변경 - 팝오버 닫을 때 InfoBubble 복귀 (X 버튼 dismiss와 분리) - InfoBubble 그림자 강화 - PendingDialog 전체 화면 블로킹 제거 - 카카오 오픈채팅 링크 업데이트 * feat: 캘린더 동기화 개선 및 알림 시스템 추가 - NotificationBubble 컴포넌트 추가 (InfoBubble 스타일 통일) - popover 열림: content 상단에 표시 / 닫힘: trigger 위에 표시 - i18n key 기반 렌더링으로 언어 변경 즉시 반영 - loading/success/error/warning 4가지 타입 - 캘린더 일괄 전송 (동시 2건 + 500ms 딜레이) 및 실패 건 자동 재시도 - OAuth 401 토큰 만료 감지 및 재로그인 유도 알림 - getCalendarEvents 페이지네이션 (maxResults=2500) 지원 - DashboardHeader props를 FilterHandlers/HeaderActions로 그룹화 - TabNavigation 미완료 탭 빨간 dot 표시 - PendingDialog 삭제 - useCourseData deps에 useMockData 추가 - handleToggleOpen setTimeout cleanup 개선 - mock: 오늘 날짜 테스트 태스크 및 로그인 만료 알림 추가 * feat: 과목별 트래킹 선택 및 UX 개선 (#71) * feat: 과목별 트래킹 선택 및 UX 개선 - 커뮤니티 포함 전체 과목 파싱, DOM 토글로 트래킹 on/off - 강의 추가 시 해당 강의만 fetch, 삭제 시 storage에서 제거 - 캐시 TTL 24시간→1시간, visibilitychange 기반 자동 갱신 - 새로고침 시 NotificationBubble 알림 표시 - macOS 스타일 스크롤바 통일 (플랫폼 간 일관성) - 새로고침 버튼 제한 제거, i18n 번역 추가 * fix: trackedCourseIds 변경 감지 로직 개선 - Set 기반 비교로 배열 참조 동일성 문제 해결 - stale courseId 검증 추가 (allCourses에 없는 ID 무시) * feat: 퀴즈 제출 트래킹 및 태스크 숨김 기능 (#72) * feat: 퀴즈 제출 여부 트래킹 및 태스크 숨김 기능 추가 - 퀴즈 상세 페이지(view.php)를 fetch하여 제출 여부(isSubmit) 판단 - 마감된 퀴즈는 캐시된 isSubmit 값을 재사용하여 불필요한 요청 방지 - 퀴즈/과제 정렬: 미제출 우선 → 마감일순, dueDate null은 각 그룹 맨 뒤 - dueDate가 null인 과제/퀴즈도 홈 화면에 표시 - 우클릭 컨텍스트 메뉴로 VOD/과제/퀴즈 숨김 처리 (chrome.storage 저장) - VOD 카드 우클릭 시 그룹 전체 숨김, 개별 영상 우클릭 시 해당 영상만 숨김 - 설정 탭에서 숨긴 태스크 확인 및 해제 - 태스크 모두 완료 시 InfoBubble에 완료 메시지 표시 - 다국어(ko/en/ja/zh) 키 추가 * feat: 퀴즈 제출 필터 추가 퀴즈 탭에도 과제와 동일한 제출완료/제출필요 필터 적용 * feat: 강의 페이지 상태 배지 및 현재 주차 하이라이트 기능 (#73) - 강의 페이지(/course/view.php) 진입 시 VOD/과제/퀴즈 상태 배지 자동 표시 - 현재 주차 하이라이트 및 스크롤 이동 버튼 추가 (4개 언어 날짜 파싱) - 상단 상태 바로 fetch 로딩/성공/실패 표시 (navbar 밀어내기 애니메이션) - 트래킹/비트래킹 강의 모두 지원 (비트래킹은 임시 저장 후 1분 자동 삭제) - 뒤로가기/앞으로가기 시 캐시 사용으로 불필요한 재요청 방지 - storage에 전체 데이터 저장, 대시보드에서는 날짜 필터링 적용 - 숨김 처리된 태스크 배지 표시 - 시스템 폰트 스택 최적화 (Windows ClearType 대응) * test: Vitest 도입 및 유틸리티 함수 테스트 추가 (242 cases) (#74) Vitest + jsdom 환경을 설정하고, src/lib 하위 유틸리티 함수들에 대한 edge case 중심의 단위 테스트를 작성한다. 테스트 대상 모듈: - attendance, dateUtils, stringUtils, lmsKeywords - filterData, transformCourseData, transformCalendarEvents - summarizeCourseData, parseCourses, cache, generateKey - deduplicateInto, fetchHtml (getText/getHref) * docs: VitePress 문서 사이트 구축 및 다국어 지원 (#75) * docs: VitePress 문서 사이트 세팅 및 사용 설명서 작성 * docs: 다국어 문서 추가 및 배지/플레이어 설명 업데이트 - VitePress i18n 설정 (en/ja/zh 로케일) - 다국어 문서 생성 (간단/고급 가이드, 캘린더, 업데이트 로그) - 브라우저 언어 기반 자동 리다이렉트 - VOD 배지 테이블 추가 (출석/시청중/미시청/결석) - 과제/퀴즈 배지 좌우 배치 - 스마트 재생 info 블록 추가 - 새로고침 설명 수정 (5분 빨간 점, 1시간 자동 갱신) - 마감 임박 알림 기능 설명 제거 * docs: FAQ 페이지 추가 (ko/en/ja/zh) - 설치, 대시보드, 플레이어, 캘린더, 기타 카테고리별 FAQ - details 접기/펼치기 형식 - 사이드바 및 홈 hero 버튼에 FAQ 링크 추가 * feat: VOD 시청 진도 트래킹 및 배지 시스템 개선 (#76) - 커뮤니티 강좌 VOD 출석 트래킹 (user_progress.php 파싱) - 시청중 배지 추가 (프로그레스 시각화, 임박 시 빨간색) - 모든 강좌에서 시청 진도 데이터 수집 (fetchVodProgress) - 배지 텍스트 정리 (출석/시청중/미시청/결석) - 마감 임박 알림 기능 삭제 (alarms/notifications 권한 제거) - 빨간 점 표시 기준 60분 → 5분으로 변경 - 커뮤니티 강좌 ID 저장 및 isCommunity 분기 처리 * feat: CI 릴리즈 개선, 첫 설치 시 문서 페이지 이동, nav 설치 링크 추가 (#77) - 릴리즈 워크플로우: dist.zip 첨부, 커밋 내역 자동 생성, deprecated actions 업데이트 - manifest.config.ts에서 package.json 버전 참조하여 버전 관리 일원화 - 확장 프로그램 첫 설치 시 VitePress 문서 사이트로 이동 - VitePress nav에 Chrome 웹스토어 설치 링크 추가 (4개 언어) * fix: flatted 취약점 수정 (npm audit fix) * feat: 릴리즈 시 README 배지 버전 자동 업데이트 * test: 테스트 케이스 추가 (badge, currentWeek, calendarUtils, storage)
1 parent 8885e64 commit 516689b

198 files changed

Lines changed: 18230 additions & 9566 deletions

File tree

Some content is hidden

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

.github/workflows/deploy-docs.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Deploy Docs
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'docs/**'
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: read
12+
pages: write
13+
id-token: write
14+
15+
concurrency:
16+
group: pages
17+
cancel-in-progress: false
18+
19+
jobs:
20+
build:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0
27+
- name: Setup Node
28+
uses: actions/setup-node@v4
29+
with:
30+
node-version: 20
31+
cache: npm
32+
- name: Setup Pages
33+
uses: actions/configure-pages@v4
34+
- name: Install dependencies
35+
run: npm ci
36+
- name: Build with VitePress
37+
run: npm run docs:build
38+
- name: Upload artifact
39+
uses: actions/upload-pages-artifact@v3
40+
with:
41+
path: docs/.vitepress/dist
42+
43+
deploy:
44+
needs: build
45+
runs-on: ubuntu-latest
46+
steps:
47+
- name: Deploy to GitHub Pages
48+
id: deployment
49+
uses: actions/deploy-pages@v4

.github/workflows/versioning.yaml

Lines changed: 89 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: 버전 관리
1+
name: 버전 관리 및 릴리즈
22

33
on:
44
pull_request:
@@ -11,169 +11,115 @@ permissions:
1111
pull-requests: read
1212

1313
jobs:
14-
bump-version:
14+
release:
1515
runs-on: ubuntu-latest
16-
if: github.event.pull_request.merged == true # PR이 병합된 경우에만 실행
16+
if: github.event.pull_request.merged == true
1717

1818
steps:
19-
# 1단계: 리포지토리 체크아웃
2019
- name: 리포지토리 체크아웃
21-
uses: actions/checkout@v3
20+
uses: actions/checkout@v4
2221
with:
23-
fetch-depth: 0 # 모든 히스토리와 태그를 가져옴
22+
fetch-depth: 0
2423

25-
# 2단계: Node.js 설정
2624
- name: Node.js 설정
27-
uses: actions/setup-node@v3
25+
uses: actions/setup-node@v4
2826
with:
29-
node-version: '18' # Node.js 18 이상으로 설정
27+
node-version: '20'
3028

31-
# 3단계: 의존성 설치
3229
- name: 의존성 설치
3330
run: npm install
3431

35-
# 4단계: PR 번호 가져오기
36-
- name: PR 번호 가져오기
37-
id: get_pr_number
38-
uses: actions/github-script@v6
32+
- name: PR 라벨에서 버전 범프 결정
33+
id: version
34+
uses: actions/github-script@v7
3935
with:
4036
script: |
41-
const pr = context.payload.pull_request;
42-
if (!pr) {
43-
throw new Error('해당 커밋과 연관된 PR을 찾을 수 없습니다.');
37+
const labels = context.payload.pull_request.labels.map(l => l.name);
38+
let bump = 'patch';
39+
if (labels.includes('🔖 major')) bump = 'major';
40+
else if (labels.includes('🔖 minor')) bump = 'minor';
41+
42+
// 최신 태그에서 현재 버전 추출
43+
const { execSync } = require('child_process');
44+
let currentVersion;
45+
try {
46+
const latestTag = execSync('git describe --tags --abbrev=0', { encoding: 'utf-8' }).trim();
47+
currentVersion = latestTag.replace(/^v/, '');
48+
} catch {
49+
currentVersion = '0.0.0';
4450
}
45-
return pr.number;
4651
47-
# 5단계: PR 라벨 가져오기 (콤마로 구분된 문자열로 반환)
48-
- name: PR 라벨 가져오기
49-
id: get_labels
50-
uses: actions/github-script@v6
51-
with:
52-
script: |
53-
const prNumber = ${{ steps.get_pr_number.outputs.result }};
54-
const pr = await github.rest.pulls.get({
55-
owner: context.repo.owner,
56-
repo: context.repo.repo,
57-
pull_number: prNumber,
58-
});
59-
const labels = pr.data.labels.map(label => label.name).join(',');
60-
return labels;
61-
62-
# 6단계: PR 라벨 출력하기
63-
- name: PR 라벨 출력하기
64-
run: |
65-
echo "PR 라벨: ${{ steps.get_labels.outputs.result }}"
52+
const [major, minor, patch] = currentVersion.split('.').map(Number);
53+
let newVersion;
54+
if (bump === 'major') newVersion = `${major + 1}.0.0`;
55+
else if (bump === 'minor') newVersion = `${major}.${minor + 1}.0`;
56+
else newVersion = `${major}.${minor}.${patch + 1}`;
6657
67-
# 7단계: 파일 존재 확인 및 목록 출력
68-
- name: List files to verify manifest.config.ts
69-
run: |
70-
echo "현재 작업 디렉토리: $(pwd)"
71-
ls -al
72-
find . -name "manifest.config.ts"
58+
core.setOutput('new_version', newVersion);
59+
core.setOutput('bump', bump);
7360
74-
# 8단계: 다음 버전 결정
75-
- name: 다음 버전 결정
76-
id: version
77-
run: |
78-
set -euo pipefail
79-
IFS=$'\n\t'
80-
81-
# 최신 태그 가져오기
82-
LATEST_TAG=$(git describe --tags $(git rev-list --tags --max-count=1) 2>/dev/null || echo "v0.0.0")
83-
echo "최신 태그: $LATEST_TAG"
84-
85-
# 현재 버전 추출
86-
CURRENT_VERSION=${LATEST_TAG#v}
87-
echo "현재 버전: $CURRENT_VERSION"
88-
89-
# 버전 분할
90-
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"
91-
92-
# PR 라벨 가져오기 (콤마로 구분된 문자열)
93-
LABELS=$(echo "${{ steps.get_labels.outputs.result }}" | tr -d '"')
94-
echo "PR 라벨: $LABELS"
95-
96-
# 콤마를 기준으로 배열로 변환
97-
IFS=',' read -r -a LABEL_ARRAY <<< "$LABELS"
98-
99-
# 라벨에 따라 버전 증가 (우선순위: major > minor > patch)
100-
NEW_VERSION=""
101-
for label in "${LABEL_ARRAY[@]}"; do
102-
label=$(echo "$label" | xargs) # 공백 제거
103-
if [[ "$label" == "🔖 major" ]]; then
104-
NEW_MAJOR=$((MAJOR + 1))
105-
NEW_VERSION="$NEW_MAJOR.0.0"
106-
break
107-
elif [[ "$label" == "🔖 minor" ]]; then
108-
NEW_MINOR=$((MINOR + 1))
109-
NEW_VERSION="$MAJOR.$NEW_MINOR.0"
110-
break
111-
elif [[ "$label" == "🔖 patch" ]]; then
112-
NEW_PATCH=$((PATCH + 1))
113-
NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH"
114-
break
115-
fi
116-
done
117-
118-
# 라벨이 없거나 인식할 수 없는 경우 패치 버전 증가
119-
if [[ -z "$NEW_VERSION" ]]; then
120-
echo "라벨이 지정되지 않았거나 인식할 수 없습니다. 기본적으로 패치 버전을 증가시킵니다."
121-
NEW_PATCH=$((PATCH + 1))
122-
NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH"
123-
fi
124-
125-
echo "새 버전: $NEW_VERSION"
126-
127-
# 출력 설정
128-
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
129-
130-
# 9단계: package.json 및 manifest.config.ts 버전 업데이트
131-
- name: package.json 및 manifest.config.ts 버전 업데이트
132-
run: |
133-
NEW_VERSION=${{ steps.version.outputs.new_version }}
134-
echo "새 버전: $NEW_VERSION"
135-
136-
# package.json 업데이트
137-
echo "package.json을 버전 $NEW_VERSION으로 업데이트합니다."
138-
npm version $NEW_VERSION --no-git-tag-version
139-
140-
# manifest.config.ts 업데이트
141-
FILE_PATH="manifest.config.ts"
142-
if [ -f "$FILE_PATH" ]; then
143-
echo "manifest.config.ts를 버전 $NEW_VERSION으로 업데이트합니다."
144-
sed -i "s/\(version: '\)[0-9]\+\.[0-9]\+\.[0-9]\+'/\1$NEW_VERSION'/" "$FILE_PATH"
145-
echo "🔄 업데이트된 manifest.config.ts 내용:"
146-
cat "$FILE_PATH"
147-
else
148-
echo "❌ manifest.config.ts 파일을 찾을 수 없습니다!"
149-
exit 1
150-
fi
151-
152-
# 10단계: 변경 사항 커밋 및 푸시
153-
- name: 변경 사항 커밋 및 푸시
61+
- name: package.json 버전 업데이트
62+
run: npm version ${{ steps.version.outputs.new_version }} --no-git-tag-version
63+
64+
- name: 프로덕션 빌드
65+
run: npm run build
66+
67+
- name: dist 압축
68+
run: cd dist && zip -r ../dotbugi-v${{ steps.version.outputs.new_version }}.zip .
69+
70+
- name: README 배지 버전 업데이트
71+
run: sed -i "s/Chrome_Web_Store-v[0-9]\+\.[0-9]\+\.[0-9]\+/Chrome_Web_Store-v${{ steps.version.outputs.new_version }}/" README.md
72+
73+
- name: 변경사항 커밋 및 태그
15474
run: |
15575
git config user.name "github-actions[bot]"
15676
git config user.email "github-actions[bot]@users.noreply.github.com"
157-
git add package.json manifest.config.ts
158-
git commit -m "🔖 chore: bump version to v${{ steps.version.outputs.new_version }}"
159-
git push origin main
77+
git add package.json package-lock.json README.md
78+
git commit -m "chore: bump version to v${{ steps.version.outputs.new_version }}"
79+
git tag v${{ steps.version.outputs.new_version }}
80+
git push origin main --follow-tags
81+
82+
- name: 릴리즈 노트 생성
83+
id: changelog
84+
uses: actions/github-script@v7
85+
with:
86+
script: |
87+
const { execSync } = require('child_process');
88+
89+
// 이전 태그 찾기
90+
let prevTag;
91+
try {
92+
prevTag = execSync('git describe --tags --abbrev=0 HEAD~1', { encoding: 'utf-8' }).trim();
93+
} catch {
94+
prevTag = execSync('git rev-list --max-parents=0 HEAD', { encoding: 'utf-8' }).trim();
95+
}
16096
161-
# 11단계: 새 태그 생성 및 푸시
162-
- name: 새 태그 생성 및 푸시
163-
run: |
164-
NEW_VERSION=${{ steps.version.outputs.new_version }}
165-
git tag -a v$NEW_VERSION -m "Release v$NEW_VERSION"
166-
git push origin v$NEW_VERSION
167-
168-
# 12단계: 릴리스 생성
169-
- name: 릴리스 생성
170-
uses: actions/create-release@v1
171-
env:
172-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
97+
const newVersion = '${{ steps.version.outputs.new_version }}';
98+
99+
// PR에 포함된 커밋 가져오기
100+
const commits = execSync(
101+
`git log ${prevTag}..HEAD --pretty=format:"- %s (%h)" --no-merges`,
102+
{ encoding: 'utf-8' }
103+
).trim();
104+
105+
const pr = context.payload.pull_request;
106+
const body = [
107+
`## What's Changed`,
108+
``,
109+
`**PR:** #${pr.number} ${pr.title}`,
110+
``,
111+
`### Commits`,
112+
commits,
113+
``,
114+
`**Full Changelog:** https://github.com/${context.repo.owner}/${context.repo.repo}/compare/${prevTag}...v${newVersion}`,
115+
].join('\n');
116+
117+
core.setOutput('body', body);
118+
119+
- name: GitHub 릴리즈 생성
120+
uses: softprops/action-gh-release@v2
173121
with:
174122
tag_name: v${{ steps.version.outputs.new_version }}
175-
release_name: Release v${{ steps.version.outputs.new_version }}
176-
body: 'Release v${{ steps.version.outputs.new_version }}'
177-
draft: false
178-
prerelease: false
179-
generate_release_notes: true
123+
name: v${{ steps.version.outputs.new_version }}
124+
body: ${{ steps.changelog.outputs.body }}
125+
files: dotbugi-v${{ steps.version.outputs.new_version }}.zip

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ dist/
1212

1313
# 환경 설정 파일 (환경에 따라 사용)
1414
.env
15+
.env.*
1516
.env.local
1617
.env.development.local
1718
.env.test.local
@@ -46,4 +47,9 @@ temp/
4647
dist
4748

4849
*.md
49-
!README.md
50+
!README.md
51+
!docs/**/*.md
52+
53+
# VitePress
54+
docs/.vitepress/dist/
55+
docs/.vitepress/cache/

0 commit comments

Comments
 (0)