diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..ea3fa04
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+max_line_length = 120
+insert_final_newline = true
+
+[*.ts]
+indent_style = space
+indent_size = 2
diff --git a/.github/workflows/html-validation.yml b/.github/workflows/html-validation.yml
new file mode 100644
index 0000000..1b91950
--- /dev/null
+++ b/.github/workflows/html-validation.yml
@@ -0,0 +1,21 @@
+name: HTML Validation
+
+on:
+ pull_request:
+ branches: [ '*' ]
+
+jobs:
+ validate:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Validate HTML
+ uses: Cyb3r-Jak3/html5validator-action@v7.2.0
+ with:
+ root: .
+ css: true
+ blacklist: .git,.github,node_modules
+ extra: >
+ --ignore _includes
diff --git a/.gitignore b/.gitignore
index e43b0f9..5f80c71 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
.DS_Store
+node_modules/
+.jekyll-cache/
+_site/
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..3625efa
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1,14 @@
+markdown: kramdown
+
+exclude:
+ - node_modules
+ - ts/
+ - web-studio/
+ - graph.py
+ - "*.json"
+ - "*.ts"
+ - "*.mts"
+ - README.md
+
+source: .
+destination: ./_site
diff --git a/_includes/youtube.html b/_includes/youtube.html
new file mode 100644
index 0000000..32d604e
--- /dev/null
+++ b/_includes/youtube.html
@@ -0,0 +1,17 @@
+{% assign is_shorts = include.type | default: '' %}
+{% if is_shorts == 'shorts' %}
+ {% assign embed_url = 'https://www.youtube.com/embed/shorts/' | append: include.id %}
+{% else %}
+ {% assign embed_url = 'https://www.youtube.com/embed/' | append: include.id | append: '?rel=0' %}
+{% endif %}
+
+
+
+
+
+
diff --git a/_layouts/article.html b/_layouts/article.html
new file mode 100644
index 0000000..b1cbaaa
--- /dev/null
+++ b/_layouts/article.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+ {{ page.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if page.date %}
+
{{ page.date | date: "%B %d, %Y" }} • -- min read
+ {% endif %}
+ {{ content }}
+
+
+
+
+
+
+
diff --git a/css/jekyll/article.css b/css/jekyll/article.css
new file mode 100644
index 0000000..906618b
--- /dev/null
+++ b/css/jekyll/article.css
@@ -0,0 +1,129 @@
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
+ line-height: 1.6;
+ max-width: 50%;
+ margin: 0 auto;
+ padding: 1.25em;
+ color: #333;
+ background: #f5f5f5;
+ font-size: 1rem;
+ transition: all 0.5s ease;
+}
+
+.container {
+ background: white;
+ padding: 1.5em;
+ border-radius: 0.5em;
+ box-shadow: 0 0.125em 0.25em rgba(0,0,0,0.1);
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #2c3e50;
+}
+
+h1 {
+ border-bottom: 3px solid #3498db;
+ padding-bottom: 0.625em;
+}
+
+h2 {
+ border-bottom: 2px solid #ecf0f1;
+ padding-bottom: 0.5em;
+}
+
+code {
+ background: #f4f4f4;
+ padding: 0.125em 0.375em;
+ border-radius: 0.1875em;
+ font-family: 'Monaco', 'Consolas', monospace;
+ font-size: 0.9em;
+}
+pre {
+ background: #0d1117;
+ padding: 1em;
+ border-radius: 0.375em;
+ overflow-x: auto;
+ margin: 1.25em 0;
+}
+pre code {
+ background: none;
+ color: inherit;
+ padding: 0;
+}
+a {
+ color: #3498db;
+ text-decoration: none;
+}
+a:hover {
+ text-decoration: underline;
+}
+table {
+ border-collapse: collapse;
+ width: 100%;
+ margin: 1.25em 0;
+}
+th, td {
+ border: 1px solid #ddd;
+ padding: 0.75em;
+ text-align: left;
+}
+
+th {
+ background: #3498db;
+ color: white;
+}
+
+tr:nth-child(even) {
+ background: #f9f9f9;
+}
+
+#date {
+ color: #7f8c8d;
+ font-style: italic;
+ text-align: right;
+ float: right;
+ margin: 0 0 0.5em 1em;
+ display: inline;
+}
+
+footer {
+ margin-top: 2em;
+ padding-top: 1em;
+ border-top: 1px solid #ecf0f1;
+ color: #7f8c8d;
+ font-size: 0.9em;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+#author {
+ margin: 0;
+}
+
+#thanks {
+ margin: 0;
+}
+#reading-time {
+ color: #7f8c8d;
+ font-size: 0.9em;
+ display: inline;
+}
+#scroll-progress {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 3px;
+ background: #3498db;
+ width: 0%;
+ transition: width 0.1s ease;
+ z-index: 9999;
+}
+
+@media only screen and (max-width: 1080px) {
+ body {
+ padding: 1em;
+ max-width: 100%;
+ transition: ease all 0.5s;
+ }
+}
diff --git a/css/styles.css b/css/styles.css
index a9779e5..355ba9f 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -1,6 +1,7 @@
:root {
--init-color: black;
--inv: 0;
+ --github-color: #004cff;
}
body {
@@ -17,6 +18,10 @@ h1 {
float: left;
}
+h2 {
+ text-decoration: underline;
+}
+
.about img {
width: 20%;
float: right;
@@ -43,6 +48,7 @@ body {
.icon-container svg, .icon-container img {
margin-right: 1rem;
+ margin-top: 0.8rem;
width: 3rem;
filter: contrast(0);
filter: brightness(0);
@@ -57,8 +63,8 @@ body {
transition: filter ease 0.7s;
}
-.icon-container i:hover, .icon-container svg:hover, .icon-container i.hover,
-.icon-container svg.hover {
+.icon-container i:hover, .icon-container svg:hover,
+.icon-container i.hover, .icon-container svg.hover {
filter: contrast(1);
filter: brightness(1);
transition: filter 0.7s;
@@ -160,16 +166,7 @@ body.light-mode-body {
}
header {
- height: 6rem;
- }
-
- header nav ul {
- display: flex;
- width: 100%;
- float: none !important;
- justify-content: center;
- align-items: center;
- padding: 1rem 0 0 0;
+ height: 4rem;
}
}
@@ -177,12 +174,6 @@ body.light-mode-body {
body {
margin: 1rem 1rem;
}
-
- header nav ul {
- justify-content: space-around;
- align-items: flex-end;
- }
-
}
/* de-emphasize underlines */
@@ -195,4 +186,4 @@ ol.proj-list li a:hover {
}
ol.proj-list li {
margin: 5px 0;
-}
\ No newline at end of file
+}
diff --git a/index.html b/index.html
index 30e3f97..8173ef9 100644
--- a/index.html
+++ b/index.html
@@ -12,7 +12,7 @@
+ crossorigin="anonymous" referrerpolicy="no-referrer">
Portfolio
@@ -28,18 +28,23 @@ About
Skills
-
+
-
+
-

+
+
+
+
@@ -63,8 +69,14 @@ Contact
@@ -77,8 +89,8 @@ Contact
-
-
-
+
+
+