mirror of
https://github.com/dwmkerr/hacker-laws.git
synced 2025-12-18 21:25:04 +01:00
fix build
This commit is contained in:
17
.github/website/generate.py
vendored
17
.github/website/generate.py
vendored
@@ -1,11 +1,5 @@
|
||||
"""Generate the Hacker Laws website from the Hacker Laws README"""
|
||||
|
||||
# TODO:
|
||||
# - favicon
|
||||
# - test share links
|
||||
# - rubbish at bottom of pate
|
||||
# - crosslink ES/HL/TAI
|
||||
# - 'back to top' better text
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
@@ -50,10 +44,13 @@ def prepare_markdown(path: str) -> str:
|
||||
|
||||
|
||||
def parse_markdown(markdown_content: str):
|
||||
(_, remains) = bisect_text(markdown_content, "<!-- vim-markdown-toc GFM -->")
|
||||
(_, remains) = bisect_text(markdown_content, "---")
|
||||
(links, remains) = bisect_text(remains, "---")
|
||||
(_, content) = bisect_text(remains, "<!-- vim-markdown-toc -->")
|
||||
|
||||
md = markdown.Markdown(extensions=['toc'])
|
||||
links = md.convert(links)
|
||||
print(f"links: {links}")
|
||||
md.convert(content)
|
||||
toc = md.toc
|
||||
|
||||
@@ -75,7 +72,7 @@ def parse_markdown(markdown_content: str):
|
||||
"full_content": full_content
|
||||
})
|
||||
|
||||
return (sections, toc)
|
||||
return (links, toc, sections)
|
||||
|
||||
|
||||
def extract_static_files(html_content, output_dir):
|
||||
@@ -123,13 +120,13 @@ def generate_site(markdown_content: str, output_dir: str):
|
||||
"""Generate the static HTML file from Markdown and Jinja2 template."""
|
||||
|
||||
template = load_template()
|
||||
(sections, toc) = parse_markdown(markdown_content)
|
||||
(links, toc, sections) = parse_markdown(markdown_content)
|
||||
|
||||
# Ensure output directory exists
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# Render HTML
|
||||
html_output = template.render(toc=toc, sections=sections)
|
||||
html_output = template.render(links=links, toc=toc, sections=sections)
|
||||
|
||||
# Save HTML to output directory
|
||||
output_file = os.path.join(output_dir, "index.html")
|
||||
|
||||
3
.github/website/src/favicon.svg
vendored
Normal file
3
.github/website/src/favicon.svg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 0C7.16 0 0 7.16 0 16C0 23.08 4.58 29.06 10.94 31.18C11.74 31.32 12.04 30.84 12.04 30.42C12.04 30.04 12.02 28.78 12.02 27.44C8 28.18 6.96 26.46 6.64 25.56C6.46 25.1 5.68 23.68 5 23.3C4.44 23 3.64 22.26 4.98 22.24C6.24 22.22 7.14 23.4 7.44 23.88C8.88 26.3 11.18 25.62 12.1 25.2C12.24 24.16 12.66 23.46 13.12 23.06C9.56 22.66 5.84 21.28 5.84 15.16C5.84 13.42 6.46 11.98 7.48 10.86C7.32 10.46 6.76 8.82 7.64 6.62C7.64 6.62 8.98 6.2 12.04 8.26C13.32 7.9 14.68 7.72 16.04 7.72C17.4 7.72 18.76 7.9 20.04 8.26C23.1 6.18 24.44 6.62 24.44 6.62C25.32 8.82 24.76 10.46 24.6 10.86C25.62 11.98 26.24 13.4 26.24 15.16C26.24 21.3 22.5 22.66 18.94 23.06C19.52 23.56 20.02 24.52 20.02 26.02C20.02 28.16 20 29.88 20 30.42C20 30.84 20.3 31.34 21.1 31.18C27.42 29.06 32 23.06 32 16C32 7.16 24.84 0 16 0V0Z" fill="#24292E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 959 B |
14
.github/website/src/index.html.jinja
vendored
14
.github/website/src/index.html.jinja
vendored
@@ -13,6 +13,7 @@
|
||||
|
||||
gtag('config', 'G-RGJ5TDHWY9');
|
||||
</script>
|
||||
<link rel="icon" href="favicon.svg" type="image/svg+xml">
|
||||
<!-- Google Fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Libre+Baskerville:wght@400;700&family=Inter:wght@400;600&display=swap" rel="stylesheet">
|
||||
<!-- Bootstrap CSS -->
|
||||
@@ -45,18 +46,21 @@
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
{{ toc }}
|
||||
|
||||
<!-- Quick links. -->
|
||||
{{ links }}
|
||||
<hr>
|
||||
<!-- The table of contents. -->
|
||||
{{ toc }}
|
||||
<hr>
|
||||
|
||||
<!-- Each of the sections - most of which are laws. -->
|
||||
{% for section in sections %}
|
||||
<section id="{{ section.id }}" class="law-section">
|
||||
{{ section.full_content | safe }}
|
||||
<div class="social-sharing">
|
||||
<a href="https://twitter.com/share?url=#{{ section.id }}" title="Share on Twitter"><i class="bi bi-twitter"></i></a>
|
||||
<a href="https://facebook.com/share?url=#{{ section.id }}" title="Share on Facebook"><i class="bi bi-facebook"></i></a>
|
||||
<a href="#" onclick="navigator.clipboard.writeText(window.location.href + '#{{ section.id }}'); alert('Copied!');" title="Copy Link"><i class="bi bi-clipboard"></i></a>
|
||||
<a href="https://twitter.com/intent/tweet?url=https://hacker-laws.com/#{{ section.id}}?hashtags=example" title="Share on Twitter" target="_blank"><i class="bi bi-twitter"></i></a>
|
||||
<a href="https://facebook.com/share?url=https://hacker-laws.com/#{{ section.id }}" title="Share on Facebook" target="_blank"><i class="bi bi-facebook"></i></a>
|
||||
<a href="#" onclick="navigator.clipboard.writeText(window.location.href + '#{{ section.id }}'); alert('Copied!');" title="Copy Link" target="_blank"><i class="bi bi-clipboard"></i></a>
|
||||
</div>
|
||||
<div class="back-to-top"><a href="#top">↑ Back to Top</a></div>
|
||||
</section>
|
||||
|
||||
1
.github/workflows/pages.yaml
vendored
1
.github/workflows/pages.yaml
vendored
@@ -35,6 +35,7 @@ jobs:
|
||||
run: |
|
||||
cd .github/website
|
||||
make build
|
||||
cp build/. '../pages'
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
|
||||
17
README.md
17
README.md
@@ -1,10 +1,14 @@
|
||||
# 💻📖 hacker-laws
|
||||
<h1 align="center">hacker-laws 💻📖 </h1>
|
||||
<h4 align="center">🧠 Laws, Theories, Principles and Patterns that developers will find useful.</h4>
|
||||
|
||||
Laws, Theories, Principles and Patterns that developers will find useful.
|
||||
---
|
||||
|
||||
[Translations](#translations): [🇮🇩](./translations/id.md) [🇧🇷](./translations/pt-BR.md) [🇨🇳](https://github.com/nusr/hacker-laws-zh) [🇩🇪](./translations/de.md) [🇫🇷](./translations/fr.md) [🇬🇷](./translations/el.md) [🇮🇹](https://github.com/csparpa/hacker-laws-it) [🇱🇻](./translations/lv.md) [🇰🇷](https://github.com/codeanddonuts/hacker-laws-kr) [🇵🇱](./translations/pl.md) [🇷🇺](https://github.com/solarrust/hacker-laws) [🇪🇸](./translations/es-ES.md) [🇹🇷](https://github.com/umutphp/hacker-laws-tr) [🇯🇵](./translations/jp.md) [🇺🇦](./translations/uk.md) [🇻🇳](./translations/vi.md)
|
||||
|
||||
Like this project? Please considering [sponsoring me](https://github.com/sponsors/dwmkerr) and the [translators](#translations). Also check out this podcast on [The Changelog - Laws for Hackers to Live By](https://changelog.com/podcast/403) to learn more about the project! You can also [download the latest PDF eBook](https://github.com/dwmkerr/hacker-laws/releases/latest/download/hacker-laws.pdf). Check the [Contributor Guide](./.github/contributing.md) if you are keen to contribute!
|
||||
- 📖 Check out my new book [Effective Shell](https://effective-shell)
|
||||
- 🌍 Check out the website [hacker-laws.com](https://hacker-laws.com)
|
||||
- ☕️ Like this project? Consider [buying me a coffee with a one-off donation](https://github.com/sponsors/dwmkerr?frequency=one-time)
|
||||
- 🧠 Check out my new project [Terminal AI](https://github.com/terminal-ai)
|
||||
- 🎧 Try the podcast [The Changelog - Laws for Hackers to Live By](https://changelog.com/podcast/403)
|
||||
- 📖 Download the [PDF eBook](https://github.com/dwmkerr/hacker-laws/releases/latest/download/hacker-laws.pd)
|
||||
|
||||
---
|
||||
|
||||
@@ -95,8 +99,7 @@ There are lots of laws which people discuss when talking about development. This
|
||||
|
||||
## Laws
|
||||
|
||||
And here we go!
|
||||
|
||||
Laws can be opinions on inevitabilities in the world of software engineering, or wry observations on unavoidable realities.
|
||||
|
||||
### 90–9–1 Principle (1% Rule)
|
||||
|
||||
|
||||
119
assets/site/index.html
Normal file
119
assets/site/index.html
Normal file
@@ -0,0 +1,119 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Interactive Hacker Laws Stack</title>
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
#stack {
|
||||
width: 400px;
|
||||
height: 500px;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
padding: 10px;
|
||||
}
|
||||
.law-item {
|
||||
text-align: left;
|
||||
padding: 4px;
|
||||
transition: transform 0.2s ease, opacity 0.2s;
|
||||
transform-origin: left;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
margin: 6px 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.law-item::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background-color: #aaa;
|
||||
margin-right: 8px;
|
||||
transition: height 0.2s, background-color 0.2s;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="stack" class="stack"></div>
|
||||
|
||||
<script>
|
||||
const laws = [
|
||||
"90–9–1 Principle (1% Rule)", "90–90 Rule", "Amdahl's Law", "The Broken Windows Theory",
|
||||
"Brooks' Law", "CAP Theorem (Brewer's Theorem)", "Clarke's Three Laws", "Conway's Law",
|
||||
"Cunningham's Law", "Dunbar's Number", "The Dunning-Kruger Effect", "Fitts' Law",
|
||||
"Gall's Law", "Goodhart's Law", "Hanlon's Razor", "Hofstadter's Law", "Hutber's Law",
|
||||
"The Hype Cycle & Amara's Law", "Hyrum's Law (The Law of Implicit Interfaces)",
|
||||
"Metcalfe's Law", "Moore's Law", "Murphy's Law / Sod's Law", "Occam's Razor",
|
||||
"Parkinson's Law", "Premature Optimization Effect", "Putt's Law", "Reed's Law",
|
||||
"The Law of Conservation of Complexity (Tesler's Law)", "The Law of Leaky Abstractions",
|
||||
"The Law of Triviality", "The Unix Philosophy", "The Spotify Model", "Wadler's Law",
|
||||
"Wheaton's Law", "The Dilbert Principle", "The Pareto Principle (The 80/20 Rule)",
|
||||
"The Peter Principle", "The Robustness Principle (Postel's Law)", "SOLID",
|
||||
"The Single Responsibility Principle", "The Open/Closed Principle", "The Liskov Substitution Principle",
|
||||
"The Interface Segregation Principle", "The Dependency Inversion Principle", "The DRY Principle",
|
||||
"The KISS Principle", "YAGNI"
|
||||
];
|
||||
|
||||
const stack = document.getElementById('stack');
|
||||
const maxZoom = 1.5;
|
||||
const minZoom = 0.6;
|
||||
|
||||
laws.forEach(title => {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'law-item';
|
||||
div.innerText = title;
|
||||
stack.appendChild(div);
|
||||
});
|
||||
|
||||
function updateScale(e) {
|
||||
const items = document.querySelectorAll('.law-item');
|
||||
|
||||
items.forEach(item => {
|
||||
const itemRect = item.getBoundingClientRect();
|
||||
const itemCenter = (itemRect.top + itemRect.bottom) / 2;
|
||||
const distance = Math.abs(e.clientY - itemCenter);
|
||||
const scale = Math.max(maxZoom - distance / 150, minZoom);
|
||||
const opacity = Math.max(1 - distance / 300, 0.3);
|
||||
|
||||
item.style.transform = `scale(${scale})`;
|
||||
item.style.opacity = opacity;
|
||||
|
||||
const dot = item.querySelector('::before');
|
||||
const barHeight = Math.max(6, 30 - distance / 10);
|
||||
item.style.setProperty('--dot-height', barHeight + 'px');
|
||||
item.style.setProperty('--dot-color', distance < 50 ? '#333' : '#aaa');
|
||||
item.querySelector('::before');
|
||||
item.style.setProperty('--dot-height', barHeight + 'px');
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', updateScale);
|
||||
|
||||
// Initial positioning
|
||||
updateScale({ clientY: window.innerHeight / 2 });
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.law-item::before {
|
||||
height: var(--dot-height, 6px);
|
||||
background-color: var(--dot-color, #aaa);
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
110
assets/site/index2.html
Normal file
110
assets/site/index2.html
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Interactive Hacker Laws Stack</title>
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
#stack {
|
||||
width: 400px;
|
||||
height: 500px;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
padding: 10px;
|
||||
}
|
||||
.law-item {
|
||||
text-align: left;
|
||||
padding: 2px 4px;
|
||||
transition: transform 0.2s ease, opacity 0.2s;
|
||||
transform-origin: left;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
margin: 4px 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.law-item::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: var(--bar-width, 6px);
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
background-color: var(--bar-color, #aaa);
|
||||
margin-right: 10px;
|
||||
transition: width 0.2s, background-color 0.2s;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="stack" class="stack"></div>
|
||||
|
||||
<script>
|
||||
const laws = [
|
||||
"90–9–1 Principle (1% Rule)", "90–90 Rule", "Amdahl's Law", "The Broken Windows Theory",
|
||||
"Brooks' Law", "CAP Theorem (Brewer's Theorem)", "Clarke's Three Laws", "Conway's Law",
|
||||
"Cunningham's Law", "Dunbar's Number", "The Dunning-Kruger Effect", "Fitts' Law",
|
||||
"Gall's Law", "Goodhart's Law", "Hanlon's Razor", "Hofstadter's Law", "Hutber's Law",
|
||||
"The Hype Cycle & Amara's Law", "Hyrum's Law (The Law of Implicit Interfaces)",
|
||||
"Metcalfe's Law", "Moore's Law", "Murphy's Law / Sod's Law", "Occam's Razor",
|
||||
"Parkinson's Law", "Premature Optimization Effect", "Putt's Law", "Reed's Law",
|
||||
"The Law of Conservation of Complexity (Tesler's Law)", "The Law of Leaky Abstractions",
|
||||
"The Law of Triviality", "The Unix Philosophy", "The Spotify Model", "Wadler's Law",
|
||||
"Wheaton's Law", "The Dilbert Principle", "The Pareto Principle (The 80/20 Rule)",
|
||||
"The Peter Principle", "The Robustness Principle (Postel's Law)", "SOLID",
|
||||
"The Single Responsibility Principle", "The Open/Closed Principle", "The Liskov Substitution Principle",
|
||||
"The Interface Segregation Principle", "The Dependency Inversion Principle", "The DRY Principle",
|
||||
"The KISS Principle", "YAGNI"
|
||||
];
|
||||
|
||||
const stack = document.getElementById('stack');
|
||||
const maxZoom = 1.8;
|
||||
const minZoom = 0.5;
|
||||
|
||||
laws.forEach(title => {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'law-item';
|
||||
div.innerText = title;
|
||||
stack.appendChild(div);
|
||||
});
|
||||
|
||||
function updateScale(e) {
|
||||
const items = document.querySelectorAll('.law-item');
|
||||
|
||||
items.forEach(item => {
|
||||
const itemRect = item.getBoundingClientRect();
|
||||
const itemCenter = (itemRect.top + itemRect.bottom) / 2;
|
||||
const distance = Math.abs(e.clientY - itemCenter);
|
||||
const scale = Math.max(maxZoom - distance / 120, minZoom);
|
||||
const opacity = Math.max(1 - distance / 250, 0.2);
|
||||
const barWidth = Math.max(6, 60 - distance / 5);
|
||||
|
||||
item.style.transform = `scale(${scale})`;
|
||||
item.style.opacity = opacity;
|
||||
item.style.setProperty('--bar-width', barWidth + 'px');
|
||||
item.style.setProperty('--bar-color', distance < 50 ? '#333' : '#aaa');
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', updateScale);
|
||||
|
||||
// Initial positioning
|
||||
updateScale({ clientY: window.innerHeight / 2 });
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
127
assets/site/index3.html
Normal file
127
assets/site/index3.html
Normal file
@@ -0,0 +1,127 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Interactive Hacker Laws Stack</title>
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
overflow: hidden;
|
||||
}
|
||||
#stack-container {
|
||||
width: 400px;
|
||||
height: 500px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
padding: 10px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
#stack {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
.law-item {
|
||||
text-align: left;
|
||||
padding: 2px 4px;
|
||||
transition: transform 0.2s ease, opacity 0.2s;
|
||||
transform-origin: left;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
margin: 4px 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.law-item::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: var(--bar-width, 6px);
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
background-color: var(--bar-color, #aaa);
|
||||
margin-right: 10px;
|
||||
transition: width 0.2s, background-color 0.2s;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="stack-container">
|
||||
<div id="stack"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const laws = [
|
||||
"90–9–1 Principle (1% Rule)", "90–90 Rule", "Amdahl's Law", "The Broken Windows Theory",
|
||||
"Brooks' Law", "CAP Theorem (Brewer's Theorem)", "Clarke's Three Laws", "Conway's Law",
|
||||
"Cunningham's Law", "Dunbar's Number", "The Dunning-Kruger Effect", "Fitts' Law",
|
||||
"Gall's Law", "Goodhart's Law", "Hanlon's Razor", "Hofstadter's Law", "Hutber's Law",
|
||||
"The Hype Cycle & Amara's Law", "Hyrum's Law (The Law of Implicit Interfaces)",
|
||||
"Metcalfe's Law", "Moore's Law", "Murphy's Law / Sod's Law", "Occam's Razor",
|
||||
"Parkinson's Law", "Premature Optimization Effect", "Putt's Law", "Reed's Law",
|
||||
"The Law of Conservation of Complexity (Tesler's Law)", "The Law of Leaky Abstractions",
|
||||
"The Law of Triviality", "The Unix Philosophy", "The Spotify Model", "Wadler's Law",
|
||||
"Wheaton's Law", "The Dilbert Principle", "The Pareto Principle (The 80/20 Rule)",
|
||||
"The Peter Principle", "The Robustness Principle (Postel's Law)", "SOLID",
|
||||
"The Single Responsibility Principle", "The Open/Closed Principle", "The Liskov Substitution Principle",
|
||||
"The Interface Segregation Principle", "The Dependency Inversion Principle", "The DRY Principle",
|
||||
"The KISS Principle", "YAGNI"
|
||||
];
|
||||
|
||||
const stack = document.getElementById('stack');
|
||||
const stackContainer = document.getElementById('stack-container');
|
||||
const maxZoom = 1.8;
|
||||
const minZoom = 0.5;
|
||||
let offsetY = 0;
|
||||
|
||||
laws.forEach(title => {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'law-item';
|
||||
div.innerText = title;
|
||||
stack.appendChild(div);
|
||||
});
|
||||
|
||||
function updateScale() {
|
||||
const items = document.querySelectorAll('.law-item');
|
||||
|
||||
items.forEach(item => {
|
||||
const itemRect = item.getBoundingClientRect();
|
||||
const containerRect = stackContainer.getBoundingClientRect();
|
||||
const itemCenter = (itemRect.top + itemRect.bottom) / 2;
|
||||
const containerCenter = (containerRect.top + containerRect.bottom) / 2;
|
||||
const distance = Math.abs(containerCenter - itemCenter);
|
||||
const scale = Math.max(maxZoom - distance / 120, minZoom);
|
||||
const opacity = Math.max(1 - distance / 300, 0.3);
|
||||
const barWidth = Math.max(6, 60 - distance / 3);
|
||||
|
||||
item.style.transform = `scale(${scale})`;
|
||||
item.style.opacity = opacity;
|
||||
item.style.setProperty('--bar-width', barWidth + 'px');
|
||||
item.style.setProperty('--bar-color', distance < 50 ? '#333' : '#aaa');
|
||||
});
|
||||
}
|
||||
|
||||
stackContainer.addEventListener('wheel', (e) => {
|
||||
e.preventDefault();
|
||||
offsetY = (offsetY + e.deltaY) % stack.scrollHeight;
|
||||
if (offsetY < 0) offsetY += stack.scrollHeight;
|
||||
stack.style.top = `${-offsetY}px`;
|
||||
updateScale();
|
||||
});
|
||||
|
||||
document.addEventListener('mousemove', updateScale);
|
||||
|
||||
updateScale();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
158
assets/site/index4.html
Normal file
158
assets/site/index4.html
Normal file
@@ -0,0 +1,158 @@
|
||||
<!--
|
||||
Interactive Hacker Laws Stack - Specification:
|
||||
|
||||
1. User Experience:
|
||||
- Display a vertically scrolling list of items ("laws") in a visually appealing, interactive format.
|
||||
- The list infinitely loops seamlessly; scrolling beyond the first or last item cycles continuously.
|
||||
- Mouse scrolling moves the entire list vertically within a fixed viewport (no internal scrollbar visible).
|
||||
- The item under the mouse cursor smoothly scales up (zooms) and becomes clearly highlighted.
|
||||
- Items further from the cursor scale down smoothly, fade out gradually, and become visually less prominent.
|
||||
- To the left of each text item, a horizontal bar visually represents the focus, forming a bell-curve-like effect.
|
||||
The bar is smallest (circular) when far from the cursor, and smoothly expands (rectangular with rounded corners) when close.
|
||||
|
||||
2. Sources:
|
||||
- Original Interaction Design Inspiration: https://press.stripe.com/
|
||||
- Data Source (list of "Hacker Laws"): https://github.com/dwmkerr/hacker-laws/
|
||||
|
||||
3. Technical Details:
|
||||
- Implemented using plain HTML, CSS, and JavaScript without third-party libraries.
|
||||
- Clearly defined parameters for customization:
|
||||
- `maxZoom`: maximum scale factor for the item closest to the cursor.
|
||||
- `minZoom`: minimum scale factor for items furthest from the cursor.
|
||||
- Styling is clean, minimalist, and customizable via CSS variables.
|
||||
|
||||
This specification allows easy adjustments, maintenance, and future enhancements of the interactive list.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Interactive Hacker Laws Stack</title>
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
overflow: hidden;
|
||||
}
|
||||
#stack-container {
|
||||
width: 400px;
|
||||
height: 500px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
padding: 10px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
#stack {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
.law-item {
|
||||
text-align: left;
|
||||
padding: 2px 4px;
|
||||
transition: transform 0.2s ease, opacity 0.2s;
|
||||
transform-origin: left;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
margin: 4px 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.law-item::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: var(--bar-width, 6px);
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
background-color: var(--bar-color, #aaa);
|
||||
margin-right: 10px;
|
||||
transition: width 0.2s, background-color 0.2s;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="stack-container">
|
||||
<div id="stack"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const laws = [
|
||||
"90–9–1 Principle (1% Rule)", "90–90 Rule", "Amdahl's Law", "The Broken Windows Theory",
|
||||
"Brooks' Law", "CAP Theorem (Brewer's Theorem)", "Clarke's Three Laws", "Conway's Law",
|
||||
"Cunningham's Law", "Dunbar's Number", "The Dunning-Kruger Effect", "Fitts' Law",
|
||||
"Gall's Law", "Goodhart's Law", "Hanlon's Razor", "Hofstadter's Law", "Hutber's Law",
|
||||
"The Hype Cycle & Amara's Law", "Hyrum's Law (The Law of Implicit Interfaces)",
|
||||
"Metcalfe's Law", "Moore's Law", "Murphy's Law / Sod's Law", "Occam's Razor",
|
||||
"Parkinson's Law", "Premature Optimization Effect", "Putt's Law", "Reed's Law",
|
||||
"The Law of Conservation of Complexity (Tesler's Law)", "The Law of Leaky Abstractions",
|
||||
"The Law of Triviality", "The Unix Philosophy", "The Spotify Model", "Wadler's Law",
|
||||
"Wheaton's Law", "The Dilbert Principle", "The Pareto Principle (The 80/20 Rule)",
|
||||
"The Peter Principle", "The Robustness Principle (Postel's Law)", "SOLID",
|
||||
"The Single Responsibility Principle", "The Open/Closed Principle", "The Liskov Substitution Principle",
|
||||
"The Interface Segregation Principle", "The Dependency Inversion Principle", "The DRY Principle",
|
||||
"The KISS Principle", "YAGNI"
|
||||
];
|
||||
|
||||
const stack = document.getElementById('stack');
|
||||
const stackContainer = document.getElementById('stack-container');
|
||||
const maxZoom = 1.8;
|
||||
const minZoom = 0.5;
|
||||
let offsetY = 0;
|
||||
|
||||
// Create seamless infinite scrolling
|
||||
const extendedLaws = [...laws, ...laws, ...laws];
|
||||
extendedLaws.forEach(title => {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'law-item';
|
||||
div.innerText = title;
|
||||
stack.appendChild(div);
|
||||
});
|
||||
|
||||
const totalHeight = stack.scrollHeight / 3;
|
||||
stack.style.top = `-${totalHeight}px`;
|
||||
offsetY = totalHeight;
|
||||
|
||||
function updateScale(e) {
|
||||
const items = document.querySelectorAll('.law-item');
|
||||
|
||||
items.forEach(item => {
|
||||
const itemRect = item.getBoundingClientRect();
|
||||
const distance = e.clientY ? Math.abs(e.clientY - (itemRect.top + itemRect.bottom) / 2) : 0;
|
||||
const scale = Math.max(maxZoom - distance / 120, minZoom);
|
||||
const opacity = Math.max(1 - distance / 300, 0.3);
|
||||
const barWidth = Math.max(6, 60 - distance / 3);
|
||||
|
||||
item.style.transform = `scale(${scale})`;
|
||||
item.style.opacity = opacity;
|
||||
item.style.setProperty('--bar-width', barWidth + 'px');
|
||||
item.style.setProperty('--bar-color', distance < 50 ? '#333' : '#aaa');
|
||||
});
|
||||
}
|
||||
|
||||
stackContainer.addEventListener('wheel', (e) => {
|
||||
e.preventDefault();
|
||||
offsetY += e.deltaY;
|
||||
if (offsetY >= totalHeight * 2) offsetY -= totalHeight;
|
||||
if (offsetY < totalHeight) offsetY += totalHeight;
|
||||
stack.style.top = `-${offsetY}px`;
|
||||
updateScale(e);
|
||||
});
|
||||
|
||||
stackContainer.addEventListener('mousemove', updateScale);
|
||||
|
||||
// Initial scale update
|
||||
updateScale({ clientY: window.innerHeight / 2 });
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user