Skip to content

Commit eac1e64

Browse files
authored
Merge pull request #73 from TheCodeRaccoons/main
Waterfall changes
2 parents 490c68f + bf0dca5 commit eac1e64

49 files changed

Lines changed: 9213 additions & 1432 deletions

Some content is hidden

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

.github/workflows/tests.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: tests
2+
3+
on:
4+
push:
5+
branches: [ "**" ]
6+
pull_request:
7+
branches: [ "**" ]
8+
9+
jobs:
10+
test:
11+
name: tests
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Node.js
18+
uses: actions/setup-node@v4
19+
with:
20+
node-version: 20
21+
cache: npm
22+
23+
- name: Install dependencies (lockfile)
24+
if: ${{ hashFiles('package-lock.json') != '' }}
25+
run: npm ci
26+
27+
- name: Install dependencies
28+
if: ${{ hashFiles('package-lock.json') == '' }}
29+
run: npm install
30+
31+
- name: Run tests with coverage
32+
run: npx jest --runInBand --coverage --coverageReporters=text-summary --coverageReporters=lcov --coverageReporters=json-summary
33+
34+
- name: Upload coverage artifact
35+
if: always() && hashFiles('coverage/coverage-summary.json') != ''
36+
uses: actions/upload-artifact@v4
37+
with:
38+
name: coverage
39+
path: coverage/**
40+
41+
- name: Add coverage summary to job summary
42+
if: always() && hashFiles('coverage/coverage-summary.json') != ''
43+
shell: bash
44+
run: |
45+
node <<'NODE'
46+
const fs = require('fs');
47+
const p = 'coverage/coverage-summary.json';
48+
const out = process.env.GITHUB_STEP_SUMMARY;
49+
if (!out) {
50+
console.log('GITHUB_STEP_SUMMARY not set; skipping');
51+
process.exit(0);
52+
}
53+
const s = JSON.parse(fs.readFileSync(p, 'utf8'));
54+
const c = s.total;
55+
const lines = [
56+
'## Coverage summary',
57+
'',
58+
`- Statements: ${c.statements.pct}% (${c.statements.covered}/${c.statements.total})`,
59+
`- Branches: ${c.branches.pct}% (${c.branches.covered}/${c.branches.total})`,
60+
`- Functions: ${c.functions.pct}% (${c.functions.covered}/${c.functions.total})`,
61+
`- Lines: ${c.lines.pct}% (${c.lines.covered}/${c.lines.total})`,
62+
'',
63+
];
64+
fs.appendFileSync(out, lines.join('\n'));
65+
NODE
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Update contributors in README
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
workflow_dispatch:
7+
schedule:
8+
- cron: '0 6 * * 1' # Weekly, Mondays at 06:00 UTC
9+
10+
jobs:
11+
update-contributors:
12+
runs-on: ubuntu-latest
13+
permissions:
14+
contents: write
15+
pull-requests: write
16+
steps:
17+
- name: Checkout repository
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Update contributors section in README
23+
uses: akhilmhdh/contributors-readme-action@v2.3.11
24+
env:
25+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26+
with:
27+
image_size: 80
28+
use_username: true
29+
pr_merge: true
30+
columns_per_row: 8
31+
commit_message: 'docs(readme): update contributors [skip ci]'

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules/
2+
.vscode/
3+
coverage/

CONTRIBUTING.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ Testing
7575
- Test your changes thoroughly before submitting.
7676
- Add examples in the examples/ folder for any new functionality.
7777
---
78+
79+
## Contributors
80+
This project is made possible by:
81+
82+
The contributor list (avatars + profile links) in `README.md` is updated automatically after merges to `main` via a GitHub Action. To appear there:
83+
1. Make at least one merged commit to the `main` branch (directly or via PR merge).
84+
2. Ensure your GitHub profile has a public avatar (default works fine).
85+
86+
Inactive or bot accounts may be filtered out automatically.
87+
88+
7889
## Join the Discussion
7990
Participate in ongoing discussions in [GitHub Discussions](https://github.com/TheCodeRaccoons/WebTricks/discussions).
8091
Share your feedback, ideas, and improvements.

Dist/Functional/CookieConsent.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,10 @@ if (/complete|interactive|loaded/.test(document.readyState)) {
173173
} else {
174174
window.addEventListener('DOMContentLoaded', InitializeCookieConsent);
175175
}
176+
177+
// Allow requiring this module in test environments
178+
try {
179+
if (typeof module !== 'undefined' && module.exports) {
180+
module.exports = { CookieConsent, InitializeCookieConsent };
181+
}
182+
} catch {}

Dist/Functional/CopyToClipboard.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class CopyToClipboard {
55
this.ctcTarget = this.ctcContainer.querySelector(`[wt-copycb-element="target"]`) || null;
66
this.textTarget = this.ctcTrigger.querySelector(`[wt-copycb-element="texttarget"]`) || null;
77
this.ctcDefaultTxt = this.ctcTrigger.innerText;
8-
this.textToCopy = this.ctcTarget.innerText;
8+
this.textToCopy = this.ctcTarget ? this.ctcTarget.innerText : '';
99
this.copiedTxt = this.ctcTrigger.getAttribute("wt-copycb-message") || null;
1010
this.activeClass = this.ctcTrigger.getAttribute('wt-copycb-active') || 'is-copy';
1111
this.timeOut = this.ctcTrigger.getAttribute('wt-copycb-timeout') || 2000;
@@ -54,3 +54,10 @@ if (/complete|interactive|loaded/.test(document.readyState)) {
5454
} else {
5555
window.addEventListener('DOMContentLoaded', initializeCopyToClipboard);
5656
}
57+
58+
// Allow requiring this module in test environments without affecting browser usage
59+
try {
60+
if (typeof module !== 'undefined' && module.exports) {
61+
module.exports = { CopyToClipboard, InitializeCopyToClipboard: initializeCopyToClipboard };
62+
}
63+
} catch {}

Dist/Functional/CountUp.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,10 @@ if (/complete|interactive|loaded/.test(document.readyState)) {
4545
} else {
4646
window.addEventListener('DOMContentLoaded', InitializeCountUp);
4747
}
48+
49+
// Allow requiring this module in test environments without affecting browser usage
50+
try {
51+
if (typeof module !== 'undefined' && module.exports) {
52+
module.exports = { CountUp, InitializeCountUp };
53+
}
54+
} catch {}

Dist/Functional/FormCheck.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,10 @@ if (/complete|interactive|loaded/.test(document.readyState)) {
126126
} else {
127127
window.addEventListener('DOMContentLoaded', initializeFormCheck)
128128
}
129+
130+
// Allow requiring this module in test environments without affecting browser usage
131+
try {
132+
if (typeof module !== 'undefined' && module.exports) {
133+
module.exports = { FormCheck, InitializeFormCheck: initializeFormCheck };
134+
}
135+
} catch {}

Dist/Functional/FormatNumbers.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,10 @@ if (/complete|interactive|loaded/.test(document.readyState)) {
8585
} else {
8686
window.addEventListener('DOMContentLoaded', InitializeFormatNumbers);
8787
}
88+
89+
// Allow requiring this module in test environments without affecting browser usage
90+
try {
91+
if (typeof module !== 'undefined' && module.exports) {
92+
module.exports = { NumberFormatter, InitializeFormatNumbers };
93+
}
94+
} catch {}

Dist/Functional/Marquee.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,21 @@ class Marquee {
3636

3737
fillContainer() {
3838
let totalSize = this.calculateTotalSize();
39-
const targetSize = this.parentSize * 1.5;
39+
const targetSize = this.parentSize * 1.5;
40+
// Safety guards: avoid infinite loop if sizes cannot be measured (e.g., 0 widths in tests/SSR)
41+
let iterations = 0;
42+
const maxIterations = 200; // cap to a reasonable number
4043

41-
while (totalSize < targetSize) {
44+
while (totalSize < targetSize && iterations < maxIterations) {
45+
const beforeSize = totalSize;
4246
this.elements.forEach(el => {
4347
const clone = el.cloneNode(true);
4448
this.container.appendChild(clone);
4549
});
4650
this.elements = Array.from(this.container.children);
4751
totalSize = this.calculateTotalSize();
52+
iterations++;
53+
if (totalSize <= beforeSize) break; // cannot grow, abort to prevent infinite loop
4854
}
4955
}
5056

@@ -135,3 +141,12 @@ if (/complete|interactive|loaded/.test(document.readyState)) {
135141
} else {
136142
window.addEventListener('DOMContentLoaded', InitializeMarquee);
137143
};
144+
145+
// Allow requiring this module in test environments without affecting browser usage
146+
try {
147+
if (typeof module !== 'undefined' && module.exports) {
148+
module.exports = { Marquee, InitializeMarquee };
149+
}
150+
} catch {
151+
// Suppress errors when module/module.exports are undefined (e.g., in browser environments).
152+
}

0 commit comments

Comments
 (0)