@dytsou/resume-converter 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +6 -0
- package/.github/dependabot.yml +44 -0
- package/.github/workflows/ci.yml +73 -0
- package/.github/workflows/deploy.yml +56 -0
- package/.github/workflows/publish.yml +241 -0
- package/LICENSE +21 -0
- package/README.md +186 -0
- package/eslint.config.js +28 -0
- package/index.html +15 -0
- package/latex/resume.tex +273 -0
- package/package.json +39 -0
- package/scripts/convert-latex.mjs +774 -0
- package/src/App.tsx +47 -0
- package/src/components/DownloadFromDriveButton.tsx +104 -0
- package/src/index.css +122 -0
- package/src/main.tsx +10 -0
- package/src/utils/googleDriveUtils.ts +64 -0
- package/src/utils/resumeUtils.ts +26 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.app.json +24 -0
- package/tsconfig.json +7 -0
- package/tsconfig.node.json +22 -0
- package/vite.config.ts +10 -0
package/.env.example
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Enable version updates for npm (works with pnpm)
|
|
4
|
+
- package-ecosystem: "npm"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
day: "friday"
|
|
9
|
+
time: "09:00"
|
|
10
|
+
open-pull-requests-limit: 5
|
|
11
|
+
reviewers:
|
|
12
|
+
- "dytsou"
|
|
13
|
+
assignees:
|
|
14
|
+
- "dytsou"
|
|
15
|
+
labels:
|
|
16
|
+
- "dependencies"
|
|
17
|
+
commit-message:
|
|
18
|
+
prefix: "chore(deps):"
|
|
19
|
+
include: "scope"
|
|
20
|
+
# Group updates to reduce PR noise
|
|
21
|
+
groups:
|
|
22
|
+
production-dependencies:
|
|
23
|
+
dependency-type: "production"
|
|
24
|
+
development-dependencies:
|
|
25
|
+
dependency-type: "development"
|
|
26
|
+
|
|
27
|
+
# Enable version updates for GitHub Actions
|
|
28
|
+
- package-ecosystem: "github-actions"
|
|
29
|
+
directory: "/"
|
|
30
|
+
schedule:
|
|
31
|
+
interval: "weekly"
|
|
32
|
+
day: "friday"
|
|
33
|
+
time: "09:00"
|
|
34
|
+
open-pull-requests-limit: 5
|
|
35
|
+
reviewers:
|
|
36
|
+
- "dytsou"
|
|
37
|
+
assignees:
|
|
38
|
+
- "dytsou"
|
|
39
|
+
labels:
|
|
40
|
+
- "github-actions"
|
|
41
|
+
commit-message:
|
|
42
|
+
prefix: "ci"
|
|
43
|
+
include: "scope"
|
|
44
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
name: CI Checks
|
|
2
|
+
permissions:
|
|
3
|
+
contents: read
|
|
4
|
+
pull-requests: read
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push: # Runs on push to any branch
|
|
8
|
+
pull_request: # Also runs on PRs to any branch
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
lint:
|
|
12
|
+
name: Lint
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout
|
|
16
|
+
uses: actions/checkout@v6
|
|
17
|
+
|
|
18
|
+
- name: Setup Node.js
|
|
19
|
+
uses: actions/setup-node@v6
|
|
20
|
+
with:
|
|
21
|
+
node-version: 20
|
|
22
|
+
|
|
23
|
+
- name: Enable Corepack
|
|
24
|
+
run: corepack enable
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: pnpm install --frozen-lockfile
|
|
28
|
+
|
|
29
|
+
- name: Run ESLint
|
|
30
|
+
run: pnpm run lint
|
|
31
|
+
|
|
32
|
+
typecheck:
|
|
33
|
+
name: Type Check
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- name: Checkout
|
|
37
|
+
uses: actions/checkout@v6
|
|
38
|
+
|
|
39
|
+
- name: Setup Node.js
|
|
40
|
+
uses: actions/setup-node@v6
|
|
41
|
+
with:
|
|
42
|
+
node-version: 20
|
|
43
|
+
|
|
44
|
+
- name: Enable Corepack
|
|
45
|
+
run: corepack enable
|
|
46
|
+
|
|
47
|
+
- name: Install dependencies
|
|
48
|
+
run: pnpm install --frozen-lockfile
|
|
49
|
+
|
|
50
|
+
- name: Run TypeScript type check
|
|
51
|
+
run: pnpm run typecheck
|
|
52
|
+
|
|
53
|
+
build:
|
|
54
|
+
name: Build
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
steps:
|
|
57
|
+
- name: Checkout
|
|
58
|
+
uses: actions/checkout@v6
|
|
59
|
+
|
|
60
|
+
- name: Setup Node.js
|
|
61
|
+
uses: actions/setup-node@v6
|
|
62
|
+
with:
|
|
63
|
+
node-version: 20
|
|
64
|
+
|
|
65
|
+
- name: Enable Corepack
|
|
66
|
+
run: corepack enable
|
|
67
|
+
|
|
68
|
+
- name: Install dependencies
|
|
69
|
+
run: pnpm install --frozen-lockfile
|
|
70
|
+
|
|
71
|
+
- name: Build project
|
|
72
|
+
run: pnpm run build
|
|
73
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: Deploy to GitHub Pages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: pages
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout
|
|
22
|
+
uses: actions/checkout@v6
|
|
23
|
+
|
|
24
|
+
- name: Setup Node.js
|
|
25
|
+
uses: actions/setup-node@v6
|
|
26
|
+
with:
|
|
27
|
+
node-version: 20
|
|
28
|
+
|
|
29
|
+
- name: Enable Corepack
|
|
30
|
+
run: corepack enable
|
|
31
|
+
|
|
32
|
+
- name: Install dependencies
|
|
33
|
+
run: pnpm install --frozen-lockfile
|
|
34
|
+
|
|
35
|
+
- name: Build site (runs converter + vite)
|
|
36
|
+
run: pnpm run build
|
|
37
|
+
env:
|
|
38
|
+
GITHUB_PAGES: 'true'
|
|
39
|
+
VITE_GOOGLE_DRIVE_RESUME_LINK: ${{ vars.VITE_GOOGLE_DRIVE_RESUME_LINK }}
|
|
40
|
+
|
|
41
|
+
- name: Upload Pages artifact
|
|
42
|
+
uses: actions/upload-pages-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
path: dist
|
|
45
|
+
|
|
46
|
+
deploy:
|
|
47
|
+
needs: build
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
environment:
|
|
50
|
+
name: github-pages
|
|
51
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
52
|
+
steps:
|
|
53
|
+
- name: Deploy to GitHub Pages
|
|
54
|
+
id: deployment
|
|
55
|
+
uses: actions/deploy-pages@v4
|
|
56
|
+
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
name: Publish to npmjs & GitHub Packages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- 'package.json'
|
|
9
|
+
- 'scripts/convert-latex.mjs'
|
|
10
|
+
- 'index.html'
|
|
11
|
+
release:
|
|
12
|
+
types: [created]
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
publish:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
permissions:
|
|
19
|
+
contents: write
|
|
20
|
+
packages: write
|
|
21
|
+
id-token: write
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout code
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
with:
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
|
|
28
|
+
- name: Setup Node.js
|
|
29
|
+
uses: actions/setup-node@v4
|
|
30
|
+
with:
|
|
31
|
+
node-version: '20'
|
|
32
|
+
|
|
33
|
+
- name: Enable Corepack
|
|
34
|
+
run: corepack enable
|
|
35
|
+
|
|
36
|
+
- name: Get package version
|
|
37
|
+
id: package-version
|
|
38
|
+
run: |
|
|
39
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
40
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
41
|
+
echo "Current package version: $VERSION"
|
|
42
|
+
|
|
43
|
+
- name: Get package name
|
|
44
|
+
id: package-name
|
|
45
|
+
run: |
|
|
46
|
+
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
47
|
+
echo "name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
|
|
48
|
+
echo "Package name: $PACKAGE_NAME"
|
|
49
|
+
|
|
50
|
+
- name: Check if version exists on npmjs
|
|
51
|
+
id: check-npmjs
|
|
52
|
+
run: |
|
|
53
|
+
VERSION=${{ steps.package-version.outputs.version }}
|
|
54
|
+
PACKAGE_NAME=${{ steps.package-name.outputs.name }}
|
|
55
|
+
if npm view $PACKAGE_NAME@$VERSION version --registry=https://registry.npmjs.org >/dev/null 2>&1; then
|
|
56
|
+
echo "exists=true" >> $GITHUB_OUTPUT
|
|
57
|
+
echo "Version $VERSION already exists on npmjs, will skip npmjs publish"
|
|
58
|
+
else
|
|
59
|
+
echo "exists=false" >> $GITHUB_OUTPUT
|
|
60
|
+
echo "Version $VERSION is new on npmjs, will publish"
|
|
61
|
+
fi
|
|
62
|
+
continue-on-error: true
|
|
63
|
+
|
|
64
|
+
- name: Check if version exists on GitHub Packages
|
|
65
|
+
id: check-github
|
|
66
|
+
run: |
|
|
67
|
+
VERSION=${{ steps.package-version.outputs.version }}
|
|
68
|
+
PACKAGE_NAME=${{ steps.package-name.outputs.name }}
|
|
69
|
+
npm config set @dytsou:registry https://npm.pkg.github.com
|
|
70
|
+
npm config set //npm.pkg.github.com/:_authToken ${{ secrets.GITHUB_TOKEN }}
|
|
71
|
+
if npm view $PACKAGE_NAME@$VERSION version --registry=https://npm.pkg.github.com >/dev/null 2>&1; then
|
|
72
|
+
echo "exists=true" >> $GITHUB_OUTPUT
|
|
73
|
+
echo "Version $VERSION already exists on GitHub Packages, will skip GitHub Packages publish"
|
|
74
|
+
else
|
|
75
|
+
echo "exists=false" >> $GITHUB_OUTPUT
|
|
76
|
+
echo "Version $VERSION is new on GitHub Packages, will publish"
|
|
77
|
+
fi
|
|
78
|
+
continue-on-error: true
|
|
79
|
+
|
|
80
|
+
- name: Verify package
|
|
81
|
+
if: steps.check-npmjs.outputs.exists == 'false' || steps.check-github.outputs.exists == 'false'
|
|
82
|
+
run: |
|
|
83
|
+
npm pack --dry-run
|
|
84
|
+
|
|
85
|
+
# 1) Publish to npmjs
|
|
86
|
+
- name: Publish to npmjs
|
|
87
|
+
if: steps.check-npmjs.outputs.exists == 'false'
|
|
88
|
+
id: publish-npmjs
|
|
89
|
+
run: |
|
|
90
|
+
npm config set registry https://registry.npmjs.org
|
|
91
|
+
npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
|
|
92
|
+
npm publish --access public || {
|
|
93
|
+
PACKAGE_NAME=${{ steps.package-name.outputs.name }}
|
|
94
|
+
VERSION=${{ steps.package-version.outputs.version }}
|
|
95
|
+
if npm view $PACKAGE_NAME@$VERSION version --registry=https://registry.npmjs.org >/dev/null 2>&1; then
|
|
96
|
+
echo "Version already exists, skipping publish"
|
|
97
|
+
exit 0
|
|
98
|
+
else
|
|
99
|
+
echo "Publish failed for unknown reason"
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
}
|
|
103
|
+
env:
|
|
104
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
105
|
+
continue-on-error: true
|
|
106
|
+
|
|
107
|
+
# 2) Publish to GitHub Packages
|
|
108
|
+
- name: Publish to GitHub Packages
|
|
109
|
+
if: steps.check-github.outputs.exists == 'false'
|
|
110
|
+
id: publish-github
|
|
111
|
+
run: |
|
|
112
|
+
npm config set registry https://npm.pkg.github.com
|
|
113
|
+
npm config set @dytsou:registry https://npm.pkg.github.com
|
|
114
|
+
npm config set //npm.pkg.github.com/:_authToken ${{ secrets.GITHUB_TOKEN }}
|
|
115
|
+
npm publish || {
|
|
116
|
+
PACKAGE_NAME=${{ steps.package-name.outputs.name }}
|
|
117
|
+
VERSION=${{ steps.package-version.outputs.version }}
|
|
118
|
+
if npm view $PACKAGE_NAME@$VERSION version --registry=https://npm.pkg.github.com >/dev/null 2>&1; then
|
|
119
|
+
echo "Version already exists, skipping publish"
|
|
120
|
+
exit 0
|
|
121
|
+
else
|
|
122
|
+
echo "Publish failed for unknown reason"
|
|
123
|
+
exit 1
|
|
124
|
+
fi
|
|
125
|
+
}
|
|
126
|
+
env:
|
|
127
|
+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
128
|
+
continue-on-error: true
|
|
129
|
+
|
|
130
|
+
- name: Check if release should be created
|
|
131
|
+
id: should-create-release
|
|
132
|
+
run: |
|
|
133
|
+
NPMJS_PUBLISHED=false
|
|
134
|
+
GITHUB_PUBLISHED=false
|
|
135
|
+
NPMJS_SKIPPED=false
|
|
136
|
+
GITHUB_SKIPPED=false
|
|
137
|
+
|
|
138
|
+
# Check if npmjs was published in this run
|
|
139
|
+
if [ "${{ steps.check-npmjs.outputs.exists }}" == "false" ] && [ "${{ steps.publish-npmjs.outcome }}" == "success" ]; then
|
|
140
|
+
NPMJS_PUBLISHED=true
|
|
141
|
+
elif [ "${{ steps.check-npmjs.outputs.exists }}" == "true" ]; then
|
|
142
|
+
NPMJS_SKIPPED=true
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
# Check if GitHub Packages was published in this run
|
|
146
|
+
if [ "${{ steps.check-github.outputs.exists }}" == "false" ] && [ "${{ steps.publish-github.outcome }}" == "success" ]; then
|
|
147
|
+
GITHUB_PUBLISHED=true
|
|
148
|
+
elif [ "${{ steps.check-github.outputs.exists }}" == "true" ]; then
|
|
149
|
+
GITHUB_SKIPPED=true
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
# Create release if:
|
|
153
|
+
# 1. Any registry was published in this run, OR
|
|
154
|
+
# 2. GitHub Packages was published (even if npmjs was skipped because it already exists)
|
|
155
|
+
if [ "$NPMJS_PUBLISHED" == "true" ] || [ "$GITHUB_PUBLISHED" == "true" ]; then
|
|
156
|
+
echo "should_create=true" >> $GITHUB_OUTPUT
|
|
157
|
+
echo "Should create release: npmjs_published=$NPMJS_PUBLISHED, github_published=$GITHUB_PUBLISHED, npmjs_skipped=$NPMJS_SKIPPED, github_skipped=$GITHUB_SKIPPED"
|
|
158
|
+
else
|
|
159
|
+
echo "should_create=false" >> $GITHUB_OUTPUT
|
|
160
|
+
echo "Skipping release creation - no new publishes (both may already exist)"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
- name: Create GitHub Release
|
|
164
|
+
if: steps.should-create-release.outputs.should_create == 'true'
|
|
165
|
+
uses: softprops/action-gh-release@v1
|
|
166
|
+
with:
|
|
167
|
+
tag_name: v${{ steps.package-version.outputs.version }}
|
|
168
|
+
name: v${{ steps.package-version.outputs.version }}
|
|
169
|
+
prerelease: ${{ contains(steps.package-version.outputs.version, 'beta') || contains(steps.package-version.outputs.version, 'alpha') || contains(steps.package-version.outputs.version, 'rc') }}
|
|
170
|
+
body: |
|
|
171
|
+
## ${{ steps.package-name.outputs.name }}@${{ steps.package-version.outputs.version }}
|
|
172
|
+
|
|
173
|
+
**Published to multiple registries:**
|
|
174
|
+
|
|
175
|
+
- **npmjs.com**: https://www.npmjs.com/package/${{ steps.package-name.outputs.name }}
|
|
176
|
+
|
|
177
|
+
- **GitHub Packages**: https://github.com/${{ github.repository }}/packages
|
|
178
|
+
|
|
179
|
+
*Note: If a registry already had this version, it was skipped. Only missing registries were published.*
|
|
180
|
+
|
|
181
|
+
### Installation
|
|
182
|
+
|
|
183
|
+
**From npmjs (default):**
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
npm install -g ${{ steps.package-name.outputs.name }}
|
|
187
|
+
|
|
188
|
+
# or
|
|
189
|
+
|
|
190
|
+
pnpm install -g ${{ steps.package-name.outputs.name }}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**From GitHub Packages:**
|
|
194
|
+
|
|
195
|
+
First, create or update your `.npmrc` file:
|
|
196
|
+
|
|
197
|
+
```ini
|
|
198
|
+
@dytsou:registry=https://npm.pkg.github.com
|
|
199
|
+
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Then install:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
npm install -g ${{ steps.package-name.outputs.name }}
|
|
206
|
+
|
|
207
|
+
# or
|
|
208
|
+
|
|
209
|
+
pnpm install -g ${{ steps.package-name.outputs.name }}
|
|
210
|
+
```
|
|
211
|
+
generate_release_notes: true
|
|
212
|
+
draft: false
|
|
213
|
+
env:
|
|
214
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
215
|
+
|
|
216
|
+
- name: Publish summary
|
|
217
|
+
if: always()
|
|
218
|
+
run: |
|
|
219
|
+
echo "## Publish Summary"
|
|
220
|
+
echo "### npmjs"
|
|
221
|
+
if [ "${{ steps.check-npmjs.outputs.exists }}" == "true" ]; then
|
|
222
|
+
echo "Skipped - version already exists"
|
|
223
|
+
elif [ "${{ steps.publish-npmjs.outcome }}" == "success" ]; then
|
|
224
|
+
echo "Published successfully"
|
|
225
|
+
elif [ "${{ steps.publish-npmjs.outcome }}" == "failure" ]; then
|
|
226
|
+
echo "Failed to publish"
|
|
227
|
+
else
|
|
228
|
+
echo "Skipped - not attempted"
|
|
229
|
+
fi
|
|
230
|
+
echo ""
|
|
231
|
+
echo "### GitHub Packages"
|
|
232
|
+
if [ "${{ steps.check-github.outputs.exists }}" == "true" ]; then
|
|
233
|
+
echo "Skipped - version already exists"
|
|
234
|
+
elif [ "${{ steps.check-github.outputs.exists }}" == "false" ] && [ "${{ steps.publish-github.outcome }}" == "success" ]; then
|
|
235
|
+
echo "Published successfully"
|
|
236
|
+
elif [ "${{ steps.publish-github.outcome }}" == "failure" ]; then
|
|
237
|
+
echo "Failed to publish"
|
|
238
|
+
else
|
|
239
|
+
echo "Skipped - not attempted"
|
|
240
|
+
fi
|
|
241
|
+
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Tsou, Dong-You
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# LaTeX to HTML Converter with Automated Deployment
|
|
2
|
+
|
|
3
|
+
A specialized web application that converts LaTeX resume documents to clean, professional HTML and deploys them to GitHub Pages. The system automatically processes your LaTeX resume and creates a beautiful, responsive web version with proper styling and typography.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Automated LaTeX Resume Conversion**: Converts `.tex` resume files to professional HTML with proper formatting
|
|
8
|
+
- **Resume-Specific Styling**: Clean, professional presentation optimized for resume content
|
|
9
|
+
- **CI/CD Pipeline**: GitHub Actions workflow that validates and deploys automatically
|
|
10
|
+
- **Fail-Safe Deployment**: Blocks deployment if any LaTeX file fails to convert
|
|
11
|
+
- **Document Browser**: Browse all converted documents in a clean, responsive interface
|
|
12
|
+
- **MathJax Integration**: Proper rendering of mathematical formulas
|
|
13
|
+
|
|
14
|
+
## Project Structure
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
resume/
|
|
18
|
+
├── latex/ # Store your LaTeX resume files here
|
|
19
|
+
│ └── resume.tex # Main LaTeX resume document
|
|
20
|
+
├── scripts/
|
|
21
|
+
│ └── convert-latex.mjs # LaTeX to HTML conversion script
|
|
22
|
+
├── src/
|
|
23
|
+
│ ├── App.tsx # Main application
|
|
24
|
+
│ ├── main.tsx # React entry point
|
|
25
|
+
│ └── index.css # Global styles
|
|
26
|
+
├── public/
|
|
27
|
+
│ ├── converted-docs/ # Generated HTML files (created during build)
|
|
28
|
+
│ └── documents-manifest.json # Document metadata (created during build)
|
|
29
|
+
├── dist/ # Production build output
|
|
30
|
+
└── .github/
|
|
31
|
+
└── workflows/
|
|
32
|
+
└── deploy.yml # CI/CD pipeline configuration
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Getting Started
|
|
36
|
+
|
|
37
|
+
### 1. Add Your LaTeX Documents
|
|
38
|
+
|
|
39
|
+
Place your `.tex` files in the `latex/` directory. The converter will automatically process all files with a `.tex` extension.
|
|
40
|
+
|
|
41
|
+
Example structure:
|
|
42
|
+
```
|
|
43
|
+
latex/
|
|
44
|
+
├── my-research-paper.tex
|
|
45
|
+
├── math-notes.tex
|
|
46
|
+
└── thesis.tex
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 2. Test Locally
|
|
50
|
+
|
|
51
|
+
Convert and build the project:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pnpm install
|
|
55
|
+
pnpm run convert # Convert LaTeX files only
|
|
56
|
+
pnpm run build # Convert + build entire project
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 3. Set Up GitHub Pages
|
|
60
|
+
|
|
61
|
+
1. Go to your GitHub repository settings
|
|
62
|
+
2. Navigate to **Pages** section
|
|
63
|
+
3. Under **Source**, select "GitHub Actions"
|
|
64
|
+
|
|
65
|
+
### 4. Configure Environment Variables
|
|
66
|
+
|
|
67
|
+
Add your credentials as repository variables for GitHub Actions:
|
|
68
|
+
|
|
69
|
+
1. Go to **Settings** > **Variables** > **Variables** tab
|
|
70
|
+
2. Click **New repository variable**
|
|
71
|
+
3. Add the following variables:
|
|
72
|
+
- `VITE_GOOGLE_DRIVE_RESUME_LINK`: Your Google Drive share link for the resume (optional)
|
|
73
|
+
|
|
74
|
+
### 5. Push to Deploy
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git add .
|
|
78
|
+
git commit -m "Add LaTeX documents"
|
|
79
|
+
git push origin main
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The GitHub Actions workflow will:
|
|
83
|
+
1. Install dependencies
|
|
84
|
+
2. Convert all LaTeX files
|
|
85
|
+
3. Validate conversion success
|
|
86
|
+
4. Build the React application
|
|
87
|
+
5. Deploy to GitHub Pages (only if all conversions succeed)
|
|
88
|
+
|
|
89
|
+
## How It Works
|
|
90
|
+
|
|
91
|
+
### Conversion Process
|
|
92
|
+
|
|
93
|
+
1. **LaTeX Parsing**: Uses `@unified-latex` to parse LaTeX source
|
|
94
|
+
2. **HTML Generation**: Converts LaTeX AST to HTML with proper structure
|
|
95
|
+
3. **MathJax Integration**: Mathematical formulas are rendered client-side
|
|
96
|
+
4. **Styling**: Applies arXiv-inspired CSS for clean academic presentation
|
|
97
|
+
5. **Manifest Creation**: Generates a JSON file with document metadata
|
|
98
|
+
|
|
99
|
+
### CI/CD Pipeline
|
|
100
|
+
|
|
101
|
+
The GitHub Actions workflow (`.github/workflows/deploy.yml`) ensures:
|
|
102
|
+
|
|
103
|
+
- All LaTeX files convert successfully before deployment
|
|
104
|
+
- Build fails if any conversion errors occur
|
|
105
|
+
- Only successfully built sites are deployed to GitHub Pages
|
|
106
|
+
- Environment variables are properly injected during build
|
|
107
|
+
|
|
108
|
+
### Database Tracking
|
|
109
|
+
|
|
110
|
+
The Supabase database stores:
|
|
111
|
+
|
|
112
|
+
- **Documents Table**: Metadata about each LaTeX file (title, author, date)
|
|
113
|
+
- **Conversion Logs**: History of conversion attempts and errors
|
|
114
|
+
|
|
115
|
+
## Available Scripts
|
|
116
|
+
|
|
117
|
+
- `pnpm run dev` - Start development server
|
|
118
|
+
- `pnpm run convert` - Convert LaTeX files to HTML
|
|
119
|
+
- `pnpm run build` - Convert LaTeX + build production bundle
|
|
120
|
+
- `pnpm run preview` - Preview production build locally
|
|
121
|
+
- `pnpm run lint` - Run ESLint
|
|
122
|
+
|
|
123
|
+
## Customization
|
|
124
|
+
|
|
125
|
+
### Changing Base Path
|
|
126
|
+
|
|
127
|
+
If your repository name is different, update `vite.config.ts`:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
base: process.env.GITHUB_PAGES === 'true' ? '/your-repo-name/' : '/',
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Styling
|
|
134
|
+
|
|
135
|
+
Modify the CSS in `scripts/convert-latex.mjs` to customize the HTML output appearance.
|
|
136
|
+
|
|
137
|
+
### Document Metadata
|
|
138
|
+
|
|
139
|
+
The converter extracts metadata from LaTeX commands:
|
|
140
|
+
- `\title{...}` - Document title
|
|
141
|
+
- `\author{...}` - Author names
|
|
142
|
+
- `\date{...}` - Publication date
|
|
143
|
+
|
|
144
|
+
## Deployment
|
|
145
|
+
|
|
146
|
+
Your site will be available at:
|
|
147
|
+
```
|
|
148
|
+
https://<username>.github.io/<repository-name>/
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Troubleshooting
|
|
152
|
+
|
|
153
|
+
### Conversion Fails
|
|
154
|
+
|
|
155
|
+
Check the GitHub Actions logs to see which LaTeX file failed and why. Common issues:
|
|
156
|
+
- Unsupported LaTeX packages
|
|
157
|
+
- Syntax errors in LaTeX source
|
|
158
|
+
- Missing closing braces
|
|
159
|
+
|
|
160
|
+
### Deployment Blocked
|
|
161
|
+
|
|
162
|
+
If deployment is blocked, the CI/CD pipeline detected conversion failures. Fix the LaTeX files and push again.
|
|
163
|
+
|
|
164
|
+
### Local Testing
|
|
165
|
+
|
|
166
|
+
Run the conversion locally to debug issues:
|
|
167
|
+
```bash
|
|
168
|
+
pnpm run convert
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Check the generated files in `public/converted-docs/` and review `public/documents-manifest.json`.
|
|
172
|
+
|
|
173
|
+
## Technologies Used
|
|
174
|
+
|
|
175
|
+
- **React + TypeScript**: Frontend framework
|
|
176
|
+
- **Vite**: Build tool and dev server
|
|
177
|
+
- **@unified-latex**: LaTeX parsing and conversion
|
|
178
|
+
- **MathJax**: Mathematical notation rendering
|
|
179
|
+
- **Supabase**: Database for tracking conversions
|
|
180
|
+
- **GitHub Actions**: CI/CD automation
|
|
181
|
+
- **GitHub Pages**: Static site hosting
|
|
182
|
+
- **Source Sans Pro**: Typography
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import js from '@eslint/js';
|
|
2
|
+
import globals from 'globals';
|
|
3
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
4
|
+
import reactRefresh from 'eslint-plugin-react-refresh';
|
|
5
|
+
import tseslint from 'typescript-eslint';
|
|
6
|
+
|
|
7
|
+
export default tseslint.config(
|
|
8
|
+
{ ignores: ['dist'] },
|
|
9
|
+
{
|
|
10
|
+
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
11
|
+
files: ['**/*.{ts,tsx}'],
|
|
12
|
+
languageOptions: {
|
|
13
|
+
ecmaVersion: 2020,
|
|
14
|
+
globals: globals.browser,
|
|
15
|
+
},
|
|
16
|
+
plugins: {
|
|
17
|
+
'react-hooks': reactHooks,
|
|
18
|
+
'react-refresh': reactRefresh,
|
|
19
|
+
},
|
|
20
|
+
rules: {
|
|
21
|
+
...reactHooks.configs.recommended.rules,
|
|
22
|
+
'react-refresh/only-export-components': [
|
|
23
|
+
'warn',
|
|
24
|
+
{ allowConstantExport: true },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
);
|
package/index.html
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<link rel="icon" type="image/png" href="/assets/favicon.png" />
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
|
+
<title>Resume</title>
|
|
9
|
+
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
13
|
+
</body>
|
|
14
|
+
|
|
15
|
+
</html>
|