mirror of
https://github.com/dwmkerr/hacker-laws.git
synced 2025-12-18 13:14:55 +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"""
|
"""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 argparse
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@@ -50,10 +44,13 @@ def prepare_markdown(path: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def parse_markdown(markdown_content: 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 -->")
|
(_, content) = bisect_text(remains, "<!-- vim-markdown-toc -->")
|
||||||
|
|
||||||
md = markdown.Markdown(extensions=['toc'])
|
md = markdown.Markdown(extensions=['toc'])
|
||||||
|
links = md.convert(links)
|
||||||
|
print(f"links: {links}")
|
||||||
md.convert(content)
|
md.convert(content)
|
||||||
toc = md.toc
|
toc = md.toc
|
||||||
|
|
||||||
@@ -75,7 +72,7 @@ def parse_markdown(markdown_content: str):
|
|||||||
"full_content": full_content
|
"full_content": full_content
|
||||||
})
|
})
|
||||||
|
|
||||||
return (sections, toc)
|
return (links, toc, sections)
|
||||||
|
|
||||||
|
|
||||||
def extract_static_files(html_content, output_dir):
|
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."""
|
"""Generate the static HTML file from Markdown and Jinja2 template."""
|
||||||
|
|
||||||
template = load_template()
|
template = load_template()
|
||||||
(sections, toc) = parse_markdown(markdown_content)
|
(links, toc, sections) = parse_markdown(markdown_content)
|
||||||
|
|
||||||
# Ensure output directory exists
|
# Ensure output directory exists
|
||||||
os.makedirs(output_dir, exist_ok=True)
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
|
|
||||||
# Render HTML
|
# 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
|
# Save HTML to output directory
|
||||||
output_file = os.path.join(output_dir, "index.html")
|
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');
|
gtag('config', 'G-RGJ5TDHWY9');
|
||||||
</script>
|
</script>
|
||||||
|
<link rel="icon" href="favicon.svg" type="image/svg+xml">
|
||||||
<!-- Google Fonts -->
|
<!-- Google Fonts -->
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Libre+Baskerville:wght@400;700&family=Inter:wght@400;600&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Libre+Baskerville:wght@400;700&family=Inter:wght@400;600&display=swap" rel="stylesheet">
|
||||||
<!-- Bootstrap CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
@@ -45,18 +46,21 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="container">
|
<main class="container">
|
||||||
{{ toc }}
|
<!-- Quick links. -->
|
||||||
|
{{ links }}
|
||||||
|
<hr>
|
||||||
<!-- The table of contents. -->
|
<!-- The table of contents. -->
|
||||||
|
{{ toc }}
|
||||||
|
<hr>
|
||||||
|
|
||||||
<!-- Each of the sections - most of which are laws. -->
|
<!-- Each of the sections - most of which are laws. -->
|
||||||
{% for section in sections %}
|
{% for section in sections %}
|
||||||
<section id="{{ section.id }}" class="law-section">
|
<section id="{{ section.id }}" class="law-section">
|
||||||
{{ section.full_content | safe }}
|
{{ section.full_content | safe }}
|
||||||
<div class="social-sharing">
|
<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://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=#{{ section.id }}" title="Share on Facebook"><i class="bi bi-facebook"></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"><i class="bi bi-clipboard"></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>
|
||||||
<div class="back-to-top"><a href="#top">↑ Back to Top</a></div>
|
<div class="back-to-top"><a href="#top">↑ Back to Top</a></div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
1
.github/workflows/pages.yaml
vendored
1
.github/workflows/pages.yaml
vendored
@@ -35,6 +35,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd .github/website
|
cd .github/website
|
||||||
make build
|
make build
|
||||||
|
cp build/. '../pages'
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-pages-artifact@v3
|
uses: actions/upload-pages-artifact@v3
|
||||||
with:
|
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)
|
- 📖 Check out my new book [Effective Shell](https://effective-shell)
|
||||||
|
- 🌍 Check out the website [hacker-laws.com](https://hacker-laws.com)
|
||||||
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!
|
- ☕️ 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
|
## 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)
|
### 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