Skip to content

Commit 66a93e6

Browse files
feat: eslint + prettier + ci/cd (#2)
* configure eslint and prettier * improve CI/CD * deploy to github pages from the pipeline
1 parent 15bf1f5 commit 66a93e6

19 files changed

+1559
-343
lines changed

.github/workflows/ci-cd.yml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: CI/CD Pipeline
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
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+
test:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
26+
- name: Set up Node.js
27+
uses: actions/setup-node@v4
28+
with:
29+
node-version: "24"
30+
31+
- name: Install dependencies
32+
run: npm ci
33+
34+
- name: Check code formatting
35+
run: npm run format:check
36+
37+
- name: Run ESLint
38+
run: npm run lint
39+
40+
- name: Run Tests
41+
run: npm test -- --coverage
42+
43+
- name: Upload Test Coverage Artifact
44+
uses: actions/upload-artifact@v4
45+
with:
46+
name: jest-coverage-report
47+
path: coverage/
48+
49+
build:
50+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
51+
runs-on: ubuntu-latest
52+
needs: test
53+
steps:
54+
- name: Checkout
55+
uses: actions/checkout@v4
56+
57+
- name: Setup Pages
58+
uses: actions/configure-pages@v4
59+
60+
- name: Upload artifact
61+
uses: actions/upload-pages-artifact@v3
62+
with:
63+
path: "./src"
64+
65+
deploy:
66+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
67+
environment:
68+
name: github-pages
69+
url: ${{ steps.deployment.outputs.page_url }}
70+
runs-on: ubuntu-latest
71+
needs: build
72+
steps:
73+
- name: Deploy to GitHub Pages
74+
id: deployment
75+
uses: actions/deploy-pages@v4

.github/workflows/ci.yml

Lines changed: 0 additions & 29 deletions
This file was deleted.

.prettierignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules/
2+
coverage/
3+
dist/
4+
build/
5+
*.min.js
6+
*.min.css
7+
package-lock.json

.prettierrc.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"semi": true,
3+
"singleQuote": false,
4+
"tabWidth": 4,
5+
"trailingComma": "none",
6+
"printWidth": 100,
7+
"arrowParens": "always"
8+
}

docs/project-instructions.md

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,60 +12,60 @@ This is a **static portfolio website** built with vanilla HTML, CSS, and JavaScr
1212

1313
This module manages all text updates, language detection, and metadata application without external libraries.
1414

15-
* **Logic:** Language priority is checked in this order: **Local Storage (key: 'language') → Browser Language → Fallback to English**.
16-
* **Data Structure:** Translations are stored in flat JSON files within the `/locales/` directory (e.g., `en.json`, `role`).
17-
* **HTML Attributes:** Elements are updated using custom `data-translate` attributes:
18-
* `data-translate="key"`: Updates element's **textContent**.
19-
* `data-translate-alt="key"`: Updates the **alt** attribute (essential for images and accessibility).
20-
* `data-translate-html="key"`: Updates **innerHTML** (supported, currently unused).
21-
* **SEO/Metadata:** The system dynamically updates the page `<title>`, `<meta name="description">`, and Open Graph (`og:title`, `og:description`) tags on language change.
22-
* **Performance:** Translations are loaded **asynchronously** (`async/await`) using the native `fetch` API.
15+
- **Logic:** Language priority is checked in this order: **Local Storage (key: 'language') → Browser Language → Fallback to English**.
16+
- **Data Structure:** Translations are stored in flat JSON files within the `/locales/` directory (e.g., `en.json`, `role`).
17+
- **HTML Attributes:** Elements are updated using custom `data-translate` attributes:
18+
- `data-translate="key"`: Updates element's **textContent**.
19+
- `data-translate-alt="key"`: Updates the **alt** attribute (essential for images and accessibility).
20+
- `data-translate-html="key"`: Updates **innerHTML** (supported, currently unused).
21+
- **SEO/Metadata:** The system dynamically updates the page `<title>`, `<meta name="description">`, and Open Graph (`og:title`, `og:description`) tags on language change.
22+
- **Performance:** Translations are loaded **asynchronously** (`async/await`) using the native `fetch` API.
2323

2424
### Custom Dropdown (`js/custom-select.js`)
2525

2626
This file implements the styled dropdown menu for language selection.
2727

28-
* **UI Implementation:** Uses vanilla JavaScript to handle dropdown toggle and visual state management (`.open`, `.selected` classes).
29-
* **Integration:** It integrates with the translation system by calling **`setLanguage(lang)`** from `translations.js` upon selection.
30-
* **Language Names:** Display names (e.g., 'English', 'Español') are hardcoded in the `languageNames` object within this file.
28+
- **UI Implementation:** Uses vanilla JavaScript to handle dropdown toggle and visual state management (`.open`, `.selected` classes).
29+
- **Integration:** It integrates with the translation system by calling **`setLanguage(lang)`** from `translations.js` upon selection.
30+
- **Language Names:** Display names (e.g., 'English', 'Español') are hardcoded in the `languageNames` object within this file.
3131

3232
### CSS Architecture (`css/style.css`)
3333

3434
The CSS follows a well-organized structure with clear separation of concerns.
3535

36-
* **Color Scheme:** Uses **CSS Variables** defined in `:root` (e.g., `--clr-navy`, `--clr-linkedin`) for easy theme consistency.
37-
* **Icon Styling Pattern:** Icons (SVGs) use CSS filters for color manipulation across different states:
38-
* White icon on dark background: `filter: brightness(0) invert(1)`
39-
* Dark icon on light background: `filter: brightness(0) invert(0)`
40-
* **Visual Pattern:** Elements like the language selector implement a "Glassmorphism" effect using `rgba()` combined with `backdrop-filter: blur(10px)`.
41-
* **Responsiveness:** Mobile-first approach using Bootstrap utility classes and media queries for specific adjustments below 992px and 576px.
36+
- **Color Scheme:** Uses **CSS Variables** defined in `:root` (e.g., `--clr-navy`, `--clr-linkedin`) for easy theme consistency.
37+
- **Icon Styling Pattern:** Icons (SVGs) use CSS filters for color manipulation across different states:
38+
- White icon on dark background: `filter: brightness(0) invert(1)`
39+
- Dark icon on light background: `filter: brightness(0) invert(0)`
40+
- **Visual Pattern:** Elements like the language selector implement a "Glassmorphism" effect using `rgba()` combined with `backdrop-filter: blur(10px)`.
41+
- **Responsiveness:** Mobile-first approach using Bootstrap utility classes and media queries for specific adjustments below 992px and 576px.
4242

4343
---
4444

4545
## Conventions & Development Workflow
4646

4747
### Development Setup
4848

49-
| Task | Detail |
50-
| :--- | :--- |
51-
| **Cross-Platform** | Developed and maintained across **Linux, Windows, and macOS**. |
52-
| **Dependencies** | Requires **Node.js/NPM** to run development tooling (Jest). The core site is dependency-free. |
53-
| **Local Testing** | The project is static: open `index.html` in the browser or use a simple HTTP server. |
54-
| **Deployment** | Git push to the main branch auto-deploys via GitHub Pages. |
49+
| Task | Detail |
50+
| :------------------ | :------------------------------------------------------------------------------------------------------- |
51+
| **Cross-Platform** | Developed and maintained across **Linux, Windows, and macOS**. |
52+
| **Dependencies** | Requires **Node.js/NPM** to run development tooling (Jest). The core site is dependency-free. |
53+
| **Local Testing** | The project is static: open `index.html` in the browser or use a simple HTTP server. |
54+
| **Deployment** | Git push to the main branch auto-deploys via GitHub Pages. |
5555
| **Version Control** | **`package-lock.json`** must be committed to Git to ensure dependency stability across all environments. |
5656

5757
### Testing
5858

59-
* **Unit Tests:** JavaScript logic (`translations.js`, `custom-select.js`) is validated by `*.test.js` files.
60-
* **Execution:** Tests must be run using **Jest** via the NPM script: `npm test`.
59+
- **Unit Tests:** JavaScript logic (`translations.js`, `custom-select.js`) is validated by `*.test.js` files.
60+
- **Execution:** Tests must be run using **Jest** via the NPM script: `npm test`.
6161

6262
### Adding New Content
6363

64-
* **New Translations:**
64+
- **New Translations:**
6565
1. Add the new key and value to **ALL** locale files (`en.json`, `es.json`, `fr.json`, `pt.json`).
6666
2. Apply the corresponding `data-translate="keyName"` attribute to the target HTML element.
67-
* **New Languages:**
67+
- **New Languages:**
6868
1. Create a new locale file in `/locales/{lang-code}.json` with **all** existing translation keys.
6969
2. Add the language code to the `supportedLangs` array in `js/translations.js`.
7070
3. Add the language name to the `languageNames` object in `js/custom-select.js`.
71-
4. Add the option element to the HTML selector in `index.html`.
71+
4. Add the option element to the HTML selector in `index.html`.

eslint.config.mjs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import js from "@eslint/js";
2+
import globals from "globals";
3+
import json from "@eslint/json";
4+
import prettier from "eslint-config-prettier";
5+
import prettierPlugin from "eslint-plugin-prettier";
6+
7+
export default [
8+
{
9+
ignores: ["coverage/**", "node_modules/**"]
10+
},
11+
{
12+
files: ["**/*.{js,mjs,cjs}"],
13+
languageOptions: {
14+
ecmaVersion: "latest",
15+
sourceType: "module",
16+
globals: globals.browser
17+
},
18+
rules: {
19+
...js.configs.recommended.rules,
20+
"no-unused-vars": "warn",
21+
"no-console": "off"
22+
}
23+
},
24+
{
25+
files: ["jest.config.js"],
26+
languageOptions: {
27+
ecmaVersion: "latest",
28+
sourceType: "commonjs",
29+
globals: globals.node
30+
},
31+
rules: {
32+
...js.configs.recommended.rules
33+
}
34+
},
35+
{
36+
files: ["**/*.test.js"],
37+
languageOptions: {
38+
ecmaVersion: "latest",
39+
sourceType: "module",
40+
globals: {
41+
...globals.browser,
42+
...globals.jest,
43+
...globals.node,
44+
setLanguage: "readonly",
45+
getCurrentLanguage: "readonly"
46+
}
47+
},
48+
rules: {
49+
...js.configs.recommended.rules
50+
}
51+
},
52+
{
53+
files: ["src/js/*.js"],
54+
ignores: ["src/js/*.test.js"],
55+
languageOptions: {
56+
ecmaVersion: "latest",
57+
sourceType: "module",
58+
globals: {
59+
...globals.browser,
60+
setLanguage: "readonly",
61+
getCurrentLanguage: "readonly"
62+
}
63+
},
64+
rules: {
65+
...js.configs.recommended.rules
66+
}
67+
},
68+
{
69+
files: ["**/*.json"],
70+
language: "json/json",
71+
...json.configs.recommended
72+
},
73+
prettier,
74+
{
75+
files: ["**/*.{js,mjs,cjs}"],
76+
plugins: {
77+
prettier: prettierPlugin
78+
},
79+
rules: {
80+
"prettier/prettier": "warn"
81+
}
82+
}
83+
];

jest.config.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
module.exports = {
2-
testEnvironment: 'jsdom',
3-
testMatch: ['**/*.test.js'],
4-
collectCoverageFrom: [
5-
'src/js/**/*.js',
6-
'!src/js/**/*.test.js'
7-
],
8-
coverageDirectory: 'coverage',
9-
verbose: true
2+
testEnvironment: "jsdom",
3+
testMatch: ["**/*.test.js"],
4+
collectCoverageFrom: ["src/js/**/*.js", "!src/js/**/*.test.js"],
5+
coverageDirectory: "coverage",
6+
verbose: true
107
};

0 commit comments

Comments
 (0)