Compare commits
10 Commits
c7fafad8d4
...
8ac4c6b675
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ac4c6b675 | ||
|
|
e662c7cda4 | ||
|
|
78c41cc071 | ||
|
|
140552a35f | ||
|
|
dd3a0240f9 | ||
|
|
1ea47eb2da | ||
|
|
686ece4479 | ||
|
|
90340d03aa | ||
|
|
63869c3090 | ||
|
|
17fb355560 |
@@ -20,6 +20,8 @@ h1,h2,h3,h4,h5,h6 {
|
|||||||
color: get-color("dark");
|
color: get-color("dark");
|
||||||
font-family: $font-family-poppins;
|
font-family: $font-family-poppins;
|
||||||
font-weight: $font-weight-semi-bold;
|
font-weight: $font-weight-semi-bold;
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.theme-font-nunito {
|
.theme-font-nunito {
|
||||||
h1,h2,h3,h4,h5,h6 {
|
h1,h2,h3,h4,h5,h6 {
|
||||||
@@ -30,6 +32,7 @@ h1,h2,h3,h4,h5,h6 {
|
|||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
line-height: 1.74; /* 26px */
|
line-height: 1.74; /* 26px */
|
||||||
|
color: #000;
|
||||||
@include breakpoint-less(md) {
|
@include breakpoint-less(md) {
|
||||||
line-height: 1.6; /* 24px */
|
line-height: 1.6; /* 24px */
|
||||||
}
|
}
|
||||||
@@ -106,3 +109,4 @@ i {
|
|||||||
.icon-sm {
|
.icon-sm {
|
||||||
i { font-size: 0.9em; }
|
i { font-size: 0.9em; }
|
||||||
}
|
}
|
||||||
|
|
||||||
155
assets/css/scss/components/_breadcrumb.scss
Normal file
155
assets/css/scss/components/_breadcrumb.scss
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
// Breadcrumb Component
|
||||||
|
.breadcrumb-wrapper {
|
||||||
|
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||||||
|
border-bottom: 1px solid #dee2e6;
|
||||||
|
padding: 1rem 0;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 0.75rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
|
||||||
|
// &::after {
|
||||||
|
// content: "/";
|
||||||
|
// display: inline-block;
|
||||||
|
// color: #6c757d;
|
||||||
|
// margin-left: 0.75rem;
|
||||||
|
// opacity: 0.7;
|
||||||
|
// font-weight: 500;
|
||||||
|
|
||||||
|
// @media (max-width: 576px) {
|
||||||
|
// margin-left: 0.5rem;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #495057;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #007bff;
|
||||||
|
background-color: rgba(0, 123, 255, 0.1);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 2px solid #007bff;
|
||||||
|
outline-offset: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
i.fas {
|
||||||
|
margin-right: 0.375rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #6c757d;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
max-width: 200px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
max-width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
max-width: 120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsive truncation for long breadcrumbs
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.breadcrumb-item {
|
||||||
|
&:not(:last-child):not(:nth-last-child(2)) {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
& + .breadcrumb-item::before {
|
||||||
|
content: "...";
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
color: #6c757d;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dark mode support
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
background: linear-gradient(135deg, #343a40 0%, #495057 100%);
|
||||||
|
border-bottom-color: #6c757d;
|
||||||
|
|
||||||
|
.breadcrumb {
|
||||||
|
.breadcrumb-item {
|
||||||
|
&:not(:last-child):not(:only-child)::after {
|
||||||
|
color: #adb5bd;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #dee2e6;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #66b2ff;
|
||||||
|
background-color: rgba(102, 178, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline-color: #66b2ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #adb5bd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessibility improvements
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
144
assets/css/scss/components/_ez-toc.scss
Normal file
144
assets/css/scss/components/_ez-toc.scss
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/* Styles for ez-toc-container */
|
||||||
|
#ez-toc-container {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 16px 0;
|
||||||
|
box-shadow: none;
|
||||||
|
max-width: 100%;
|
||||||
|
margin: 16px 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.ez-toc-title {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-bottom: 2px solid #ddd;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-cssicon-toggle-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.ez-toc-icon-toggle-span {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-list {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
|
/* Base styles for all list items */
|
||||||
|
.ez-toc-link {
|
||||||
|
display: block;
|
||||||
|
padding: 8px 0;
|
||||||
|
color: #333;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hierarchy-based alignment */
|
||||||
|
.ez-toc-list-level-1 {
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
|
.ez-toc-link {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-list-level-2 {
|
||||||
|
padding-left: 20px;
|
||||||
|
|
||||||
|
.ez-toc-link {
|
||||||
|
font-size: 0.95em;
|
||||||
|
font-weight: 500;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-list-level-3 {
|
||||||
|
padding-left: 40px;
|
||||||
|
|
||||||
|
.ez-toc-link {
|
||||||
|
font-size: 0.9em;
|
||||||
|
font-weight: 400;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-list-level-4 {
|
||||||
|
padding-left: 60px;
|
||||||
|
|
||||||
|
.ez-toc-link {
|
||||||
|
font-size: 0.85em;
|
||||||
|
font-weight: 400;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add more levels if needed */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive styles */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
padding: 12px 0;
|
||||||
|
|
||||||
|
.ez-toc-title {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-link {
|
||||||
|
padding: 6px 0;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust hierarchy padding for tablets */
|
||||||
|
.ez-toc-list-level-2 {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-list-level-3 {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-list-level-4 {
|
||||||
|
padding-left: 45px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
padding: 10px 0;
|
||||||
|
|
||||||
|
.ez-toc-title {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-link {
|
||||||
|
padding: 4px 0;
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust hierarchy padding for mobile */
|
||||||
|
.ez-toc-list-level-2 {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-list-level-3 {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ez-toc-list-level-4 {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
assets/css/scss/components/_table.scss
Normal file
27
assets/css/scss/components/_table.scss
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/* Styles for tables */
|
||||||
|
figure.wp-block-table table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 1.25rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
|
||||||
|
thead {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
padding: 0.5rem;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #f1f3f5;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(odd) {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
//
|
//
|
||||||
// Button styles //
|
// Button styles //
|
||||||
//
|
//
|
||||||
a {
|
// a {
|
||||||
color: get-color("dark", 0.9);
|
// color: get-color("dark", 0.9);
|
||||||
text-decoration: none;
|
// text-decoration: none;
|
||||||
@include transition(linear 0.1s);
|
// @include transition(linear 0.1s);
|
||||||
&:hover {
|
// &:hover {
|
||||||
color: get-color("dark");
|
// color: get-color("dark");
|
||||||
text-decoration: none;
|
// text-decoration: none;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
button {
|
button {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
5
assets/css/scss/elements/_post-content.scss
Normal file
5
assets/css/scss/elements/_post-content.scss
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.post-content {
|
||||||
|
p {
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,31 @@
|
|||||||
//
|
//
|
||||||
// Text Link Styles //
|
// Text Link Styles //
|
||||||
//
|
//
|
||||||
|
|
||||||
|
a {
|
||||||
|
// color: #007bff;
|
||||||
|
// color: get-color("dark", 0.8);
|
||||||
|
color: #000;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #0056b3;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-content {
|
||||||
|
a {
|
||||||
|
// color: #007bff;
|
||||||
|
color: get-color("dark", 0.8);
|
||||||
|
text-decoration: underline;
|
||||||
|
&:hover {
|
||||||
|
color: #0056b3;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*[class*='text-link-'] {
|
*[class*='text-link-'] {
|
||||||
color: get-color("dark", 0.9);
|
color: get-color("dark", 0.9);
|
||||||
&:hover, &:focus {
|
&:hover, &:focus {
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
@import "elements/testimonial";
|
@import "elements/testimonial";
|
||||||
@import "elements/text-link";
|
@import "elements/text-link";
|
||||||
@import "elements/timeline";
|
@import "elements/timeline";
|
||||||
|
@import "elements/post-content";
|
||||||
|
|
||||||
//
|
//
|
||||||
// Import Components //
|
// Import Components //
|
||||||
@@ -49,10 +50,14 @@
|
|||||||
@import "components/fullscreen-menu";
|
@import "components/fullscreen-menu";
|
||||||
@import "components/gallery";
|
@import "components/gallery";
|
||||||
@import "components/header";
|
@import "components/header";
|
||||||
|
@import "components/breadcrumb";
|
||||||
@import "components/masonry";
|
@import "components/masonry";
|
||||||
@import "components/portfolio";
|
@import "components/portfolio";
|
||||||
|
@import "components/table";
|
||||||
@import "components/preloader";
|
@import "components/preloader";
|
||||||
@import "components/section";
|
@import "components/section";
|
||||||
|
@import "components/_ez-toc";
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Import Utilities //
|
// Import Utilities //
|
||||||
@@ -63,3 +68,34 @@
|
|||||||
// Import Custom Styles //
|
// Import Custom Styles //
|
||||||
//
|
//
|
||||||
@import "helpers/custom";
|
@import "helpers/custom";
|
||||||
|
|
||||||
|
ul.wp-block-list {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure.wp-block-image {
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Figcaption Styles //
|
||||||
|
//
|
||||||
|
figcaption, .wp-element-caption {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #aeaeae;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
// display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
// justify-content: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
figure.wp-block-image {
|
||||||
|
img {
|
||||||
|
margin: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/images/logo.png
Normal file
BIN
assets/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
BIN
assets/images/og-logo.png
Normal file
BIN
assets/images/og-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
BIN
assets/images/og-logo.xcf
Normal file
BIN
assets/images/og-logo.xcf
Normal file
Binary file not shown.
114
docs/SEO-IMPROVEMENTS.md
Normal file
114
docs/SEO-IMPROVEMENTS.md
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
# SEO Improvements Documentation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
This project has been enhanced with comprehensive SEO capabilities using a modular partial system in Hugo.
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
```
|
||||||
|
layouts/partials/seo/
|
||||||
|
├── seo-config.html # Main SEO configuration loader
|
||||||
|
├── seo-meta.html # Core SEO meta tags
|
||||||
|
├── opengraph.html # Open Graph tags for social media
|
||||||
|
├── twitter-cards.html # Twitter Card tags
|
||||||
|
├── structured-data.html # JSON-LD schema markup
|
||||||
|
└── favicons.html # Favicon variations and PWA support
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features Added
|
||||||
|
|
||||||
|
### 1. Core SEO Meta Tags
|
||||||
|
- Dynamic meta description
|
||||||
|
- Keywords (with fallback)
|
||||||
|
- Author information
|
||||||
|
- Canonical URLs
|
||||||
|
- Robots meta tags
|
||||||
|
- Dublin Core metadata
|
||||||
|
- Geo tags (if configured)
|
||||||
|
|
||||||
|
### 2. Open Graph Tags
|
||||||
|
- og:title, og:description, og:image
|
||||||
|
- og:type (article/website)
|
||||||
|
- og:site_name
|
||||||
|
- og:url
|
||||||
|
- Article-specific tags for blog posts
|
||||||
|
|
||||||
|
### 3. Twitter Cards
|
||||||
|
- twitter:card (summary_large_image)
|
||||||
|
- twitter:title, twitter:description
|
||||||
|
- twitter:image
|
||||||
|
- Site and creator handles
|
||||||
|
|
||||||
|
### 4. Structured Data (JSON-LD)
|
||||||
|
- WebSite schema
|
||||||
|
- Article schema for blog posts
|
||||||
|
- BreadcrumbList schema
|
||||||
|
- Organization schema
|
||||||
|
|
||||||
|
### 5. Favicon & PWA Support
|
||||||
|
- Multiple favicon sizes
|
||||||
|
- Apple Touch Icons
|
||||||
|
- Android icons
|
||||||
|
- PWA manifest.json
|
||||||
|
- Theme colors
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Hugo Configuration (hugo.toml)
|
||||||
|
```toml
|
||||||
|
[params.seo]
|
||||||
|
description = "Your site description"
|
||||||
|
keywords = ["keyword1", "keyword2"]
|
||||||
|
author = "Your Name"
|
||||||
|
theme_color = "#007bff"
|
||||||
|
default_image = "/images/og-default.jpg"
|
||||||
|
logo = "/images/logo.png"
|
||||||
|
|
||||||
|
[params.seo.twitter]
|
||||||
|
site = "@yourhandle"
|
||||||
|
creator = "@yourhandle"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Content Frontmatter
|
||||||
|
Add to your content's frontmatter:
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: "Your Post Title"
|
||||||
|
description: "Detailed description for SEO"
|
||||||
|
keywords: ["seo", "hugo", "optimization"]
|
||||||
|
author: "Author Name"
|
||||||
|
image: "/images/post-image.jpg"
|
||||||
|
robots: "index, follow"
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing & Validation
|
||||||
|
|
||||||
|
### Recommended Tools
|
||||||
|
- Google Rich Results Test: https://search.google.com/test/rich-results
|
||||||
|
- Facebook Sharing Debugger: https://developers.facebook.com/tools/debug/
|
||||||
|
- Twitter Card Validator: https://cards-dev.twitter.com/validator
|
||||||
|
- Schema.org Validator: https://validator.schema.org/
|
||||||
|
|
||||||
|
### Validation Checklist
|
||||||
|
- [ ] Meta tags present in page source
|
||||||
|
- [ ] Open Graph tags validate
|
||||||
|
- [ ] Twitter Cards validate
|
||||||
|
- [ ] JSON-LD schema validates
|
||||||
|
- [ ] Favicons load correctly
|
||||||
|
- [ ] Canonical URLs are correct
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
1. Generate favicon files for all sizes (use a favicon generator)
|
||||||
|
2. Create og-default.jpg and twitter-default.jpg images
|
||||||
|
3. Set up Google Search Console and add verification code
|
||||||
|
4. Set up Bing Webmaster Tools
|
||||||
|
5. Test with social media sharing
|
||||||
|
|
||||||
|
## Fallback Values
|
||||||
|
The system includes intelligent fallback values:
|
||||||
|
- Description: Page → Site → Title
|
||||||
|
- Keywords: Page → Site → Empty string
|
||||||
|
- Image: Page → Site → Default
|
||||||
|
- Author: Page → Site → Site Title
|
||||||
|
|
||||||
|
All SEO improvements have been successfully implemented!
|
||||||
43
hugo.toml
43
hugo.toml
@@ -13,6 +13,32 @@ ignoreLogs = ["warning-goldmark-raw-html"]
|
|||||||
[markup.goldmark.renderer]
|
[markup.goldmark.renderer]
|
||||||
unsafe = true
|
unsafe = true
|
||||||
|
|
||||||
|
# SEO Configuration
|
||||||
|
[params.seo]
|
||||||
|
description = "Mistergeek - Tutoriels et guides en informatique"
|
||||||
|
keywords = ["développement web", "technologies", "innovation", "solutions digitales", "mistergeek"]
|
||||||
|
author = "Mistergeek"
|
||||||
|
theme_color = "#007bff"
|
||||||
|
default_image = "/assets/images/og-logo.png"
|
||||||
|
logo = "/assets/images/logo.png"
|
||||||
|
|
||||||
|
# Social Media
|
||||||
|
[params.seo.twitter]
|
||||||
|
site = "@mistergeekfrance"
|
||||||
|
creator = "@mistergeekfrance"
|
||||||
|
|
||||||
|
# Search Engine Verification
|
||||||
|
# google_verification = "your-google-verification-code"
|
||||||
|
# bing_verification = "your-bing-verification-code"
|
||||||
|
# yandex_verification = "your-yandex-verification-code"
|
||||||
|
|
||||||
|
# Geo Location (if applicable)
|
||||||
|
# [params.seo.geo]
|
||||||
|
# region = "FR-IDF"
|
||||||
|
# placename = "Paris"
|
||||||
|
# latitude = "48.8566"
|
||||||
|
# longitude = "2.3522"
|
||||||
|
|
||||||
# WordPress API Configuration
|
# WordPress API Configuration
|
||||||
[params.wordpress]
|
[params.wordpress]
|
||||||
apiUrl = "https://www.mistergeek.net/wp-json/wp/v2"
|
apiUrl = "https://www.mistergeek.net/wp-json/wp/v2"
|
||||||
@@ -31,3 +57,20 @@ ignoreLogs = ["warning-goldmark-raw-html"]
|
|||||||
[[build.cachebusters]]
|
[[build.cachebusters]]
|
||||||
source = "assets/.*\\.(css|sass|scss)$"
|
source = "assets/.*\\.(css|sass|scss)$"
|
||||||
target = "css"
|
target = "css"
|
||||||
|
|
||||||
|
# Output formats for search index
|
||||||
|
[outputs]
|
||||||
|
home = ["HTML", "RSS", "JSON"]
|
||||||
|
|
||||||
|
[outputFormats]
|
||||||
|
[outputFormats.JSON]
|
||||||
|
mediaType = "application/json"
|
||||||
|
baseName = "search-index"
|
||||||
|
isPlainText = true
|
||||||
|
notAlternative = true
|
||||||
|
|
||||||
|
# Search configuration
|
||||||
|
[params.search]
|
||||||
|
enabled = true
|
||||||
|
minQueryLength = 2
|
||||||
|
maxResults = 10
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="{{ .Site.Language.Lang | default "en" }}">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="description" content="{{ if .Description }}{{ .Description }}{{ else }}{{ .Site.Title }}{{ end }}">
|
|
||||||
<meta name="keywords" content="">
|
<!-- SEO & Social Meta Tags -->
|
||||||
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} - {{ .Site.Title }}{{ end }}</title>
|
<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} - {{ .Site.Title }}{{ end }}</title>
|
||||||
<!-- Favicon -->
|
{{ partial "seo/seo-config.html" . }}
|
||||||
<link href="/assets/images/favicon.png" rel="shortcut icon">
|
|
||||||
<!-- CSS -->
|
<!-- CSS -->
|
||||||
<link href="/assets/plugins/bootstrap/bootstrap.min.css" rel="stylesheet">
|
<link href="/assets/plugins/bootstrap/bootstrap.min.css" rel="stylesheet">
|
||||||
<link href="/assets/plugins/owl-carousel/owl.carousel.min.css" rel="stylesheet">
|
<link href="/assets/plugins/owl-carousel/owl.carousel.min.css" rel="stylesheet">
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
<link href="/assets/plugins/scrollcue/scrollcue.css" rel="stylesheet">
|
<link href="/assets/plugins/scrollcue/scrollcue.css" rel="stylesheet">
|
||||||
<link href="/assets/plugins/swiper/swiper-bundle.min.css" rel="stylesheet">
|
<link href="/assets/plugins/swiper/swiper-bundle.min.css" rel="stylesheet">
|
||||||
<link href="/assets/css/theme.css" rel="stylesheet">
|
<link href="/assets/css/theme.css" rel="stylesheet">
|
||||||
|
<link href="/assets/css/theme-colors/theme-color-blue.css" rel="stylesheet">
|
||||||
<!-- Fonts/Icons -->
|
<!-- Fonts/Icons -->
|
||||||
<link href="/assets/plugins/bootstrap-icons/bootstrap-icons.css" rel="stylesheet">
|
<link href="/assets/plugins/bootstrap-icons/bootstrap-icons.css" rel="stylesheet">
|
||||||
<link href="/assets/plugins/font-awesome/css/all.css" rel="stylesheet">
|
<link href="/assets/plugins/font-awesome/css/all.css" rel="stylesheet">
|
||||||
@@ -25,34 +26,15 @@
|
|||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
{{ partial "header.html" . }}
|
{{ partial "header.html" . }}
|
||||||
|
|
||||||
|
<!-- Breadcrumb -->
|
||||||
|
{{ partial "breadcrumb.html" . }}
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
{{ block "main" . }}{{ end }}
|
{{ block "main" . }}{{ end }}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer>
|
<!-- Footer -->
|
||||||
<div class="section bg-dark">
|
{{ partial "footer.html" . }}
|
||||||
<div class="container">
|
|
||||||
<div class="row g-4 align-items-center">
|
|
||||||
<div class="col-12 col-md-6 text-center text-md-start">
|
|
||||||
<ul class="list-inline-dash">
|
|
||||||
<li><a href="/faq/">FAQ</a></li>
|
|
||||||
<li><a href="/careers/">Careers</a></li>
|
|
||||||
<li><a href="/clients/">Clients</a></li>
|
|
||||||
</ul>
|
|
||||||
<p class="mt-2">© {{ now.Format "2006" }} {{ .Site.Title }}, All Rights Reserved.</p>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-md-6 text-center text-md-end">
|
|
||||||
<ul class="list-inline">
|
|
||||||
<li><a href="#"><i class="bi bi-facebook"></i></a></li>
|
|
||||||
<li><a href="#"><i class="bi bi-twitter-x"></i></a></li>
|
|
||||||
<li><a href="#"><i class="bi bi-pinterest"></i></a></li>
|
|
||||||
<li><a href="#"><i class="bi bi-instagram"></i></a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div><!-- end row -->
|
|
||||||
</div><!-- end container -->
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<!-- Scroll to top button -->
|
<!-- Scroll to top button -->
|
||||||
<div class="scrolltotop icon-lg">
|
<div class="scrolltotop icon-lg">
|
||||||
@@ -64,5 +46,6 @@
|
|||||||
<script src="/assets/plugins/jquery.min.js"></script>
|
<script src="/assets/plugins/jquery.min.js"></script>
|
||||||
<script src="/assets/plugins/plugins.js"></script>
|
<script src="/assets/plugins/plugins.js"></script>
|
||||||
<script src="/assets/js/functions.js"></script>
|
<script src="/assets/js/functions.js"></script>
|
||||||
|
{{ partial "scripts.html" . }}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -14,8 +14,6 @@
|
|||||||
{{ range . }}
|
{{ range . }}
|
||||||
<li><a href="/categories/{{ . | urlize }}">{{ . }}</a></li>
|
<li><a href="/categories/{{ . | urlize }}">{{ . }}</a></li>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ else }}
|
|
||||||
<li><a href="/categories/non-classe">Non classé</a></li>
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<li><a href="#">{{ .Date.Format "Jan 2, 2006" }}</a></li>
|
<li><a href="#">{{ .Date.Format "Jan 2, 2006" }}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
70
layouts/partials/breadcrumb.html
Normal file
70
layouts/partials/breadcrumb.html
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<!-- Breadcrumb Navigation with SEO optimization -->
|
||||||
|
<div class="breadcrumb-wrapper">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb" itemscope itemtype="https://schema.org/BreadcrumbList">
|
||||||
|
|
||||||
|
<!-- Home/Accueil with SEO -->
|
||||||
|
<li class="breadcrumb-item" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
|
||||||
|
<a href="{{ "/" | relLangURL }}" itemprop="item" title="{{ i18n "home" | default "Accueil" }}">
|
||||||
|
<span itemprop="name">{{ i18n "home" | default "Accueil" }}</span>
|
||||||
|
</a>
|
||||||
|
<meta itemprop="position" content="1" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- Category with SEO and linking -->
|
||||||
|
{{ if or .Params.categories .Section }}
|
||||||
|
{{ $category := "" }}
|
||||||
|
{{ $categorySlug := "" }}
|
||||||
|
{{ $categoryUrl := "" }}
|
||||||
|
|
||||||
|
{{ if .Params.categories }}
|
||||||
|
{{ $category = index .Params.categories 0 }}
|
||||||
|
{{ $categorySlug = urlize $category }}
|
||||||
|
{{ $categoryUrl = printf "/categories/%s" $categorySlug }}
|
||||||
|
{{ else if .Section }}
|
||||||
|
{{ $category = humanize .Section }}
|
||||||
|
{{ $categorySlug = .Section }}
|
||||||
|
{{ $categoryUrl = printf "/%s" .Section }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if $category }}
|
||||||
|
<li class="breadcrumb-item active" itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem" aria-current="page">
|
||||||
|
<a href="{{ $categoryUrl | relLangURL }}" itemprop="item" title="{{ $category }}">
|
||||||
|
<span itemprop="name">{{ $category }}</span>
|
||||||
|
</a>
|
||||||
|
<meta itemprop="position" content="2" />
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- JSON-LD Structured Data for SEO -->
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "BreadcrumbList",
|
||||||
|
"itemListElement": [
|
||||||
|
{
|
||||||
|
"@type": "ListItem",
|
||||||
|
"position": 1,
|
||||||
|
"name": "{{ i18n "home" | default "Accueil" }}",
|
||||||
|
"item": "{{ "/" | absLangURL }}"
|
||||||
|
}{{ if or .Params.categories .Section }},
|
||||||
|
{
|
||||||
|
"@type": "ListItem",
|
||||||
|
"position": 2,
|
||||||
|
"name": "{{ if .Params.categories }}{{ index .Params.categories 0 }}{{ else }}{{ humanize .Section }}{{ end }}",
|
||||||
|
"item": "{{ if .Params.categories }}{{ printf "%s/categories/%s" (absLangURL "") (urlize (index .Params.categories 0)) }}{{ else }}{{ printf "%s/%s" (absLangURL "") .Section }}{{ end }}"
|
||||||
|
}{{ end }}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
66
layouts/partials/footer.html
Normal file
66
layouts/partials/footer.html
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<footer>
|
||||||
|
<div class="section-sm bg-dark">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-6 col-sm-6 col-lg-3">
|
||||||
|
<h3 class="uppercase letter-spacing-1">{{ .Site.Title }}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-6 col-sm-6 col-lg-3">
|
||||||
|
<h6 class="font-small fw-medium uppercase">Pages</h6>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li><a href="/">Accueil</a></li>
|
||||||
|
{{ if .Site.Data.wordpress }}
|
||||||
|
{{ range $index, $element := .Site.Data.wordpress.navigation }}
|
||||||
|
<li>
|
||||||
|
<a href="/{{ $element.slug }}">{{ $element.title }}</a>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-6 col-sm-6 col-lg-3">
|
||||||
|
<h6 class="font-small fw-medium uppercase">Toutes les catégories</h6>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
{{ if .Site.Data.wordpress }}
|
||||||
|
{{ $count := 0 }}
|
||||||
|
{{ range $index, $element := .Site.Data.wordpress.categories }}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/categories/{{ $element.slug }}">{{ $element.name }}</a>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-6 col-sm-6 col-lg-3">
|
||||||
|
<h6 class="font-small fw-medium uppercase">Contact Info</h6>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<li>121 King St, Melbourne VIC 3000</li>
|
||||||
|
<li>contact@example.com</li>
|
||||||
|
<li>+(123) 456 789 01</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div><!-- end row -->
|
||||||
|
</div><!-- end container -->
|
||||||
|
</div>
|
||||||
|
<div class="bg-black py-4">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row align-items-center g-2 g-lg-3">
|
||||||
|
<div class="col-12 col-md-6 text-center text-md-start">
|
||||||
|
<p>© {{ now.Format "2006" }} {{ .Site.Title }}, All Rights Reserved.</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 text-center text-md-end">
|
||||||
|
<ul class="list-inline-sm">
|
||||||
|
<li><a class="button-circle button-circle-sm button-circle-social-facebook" href="#"><i class="bi bi-facebook"></i></a></li>
|
||||||
|
<li><a class="button-circle button-circle-sm button-circle-social-twitter" href="#"><i class="bi bi-twitter-x"></i></a></li>
|
||||||
|
<li><a class="button-circle button-circle-sm button-circle-social-pinterest" href="#"><i class="bi bi-pinterest"></i></a></li>
|
||||||
|
<li><a class="button-circle button-circle-sm button-circle-social-instagram" href="#"><i class="bi bi-instagram"></i></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div><!-- end row -->
|
||||||
|
</div><!-- end container -->
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
46
layouts/partials/header.html
Normal file
46
layouts/partials/header.html
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<!-- Header -->
|
||||||
|
<div class="header center header-color-dark">
|
||||||
|
<div class="container">
|
||||||
|
<!-- Logo -->
|
||||||
|
<div class="header-logo">
|
||||||
|
<h3 class="uppercase letter-spacing-1"><a href="/">{{ .Site.Title }}</a></h3>
|
||||||
|
</div>
|
||||||
|
<!-- Menu -->
|
||||||
|
<div class="header-menu">
|
||||||
|
<ul class="nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/">Accueil</a>
|
||||||
|
</li>
|
||||||
|
{{ if .Site.Data.wordpress }}
|
||||||
|
{{ $count := 0 }}
|
||||||
|
{{ range $index, $element := .Site.Data.wordpress.categories }}
|
||||||
|
{{ if or (eq $element.name "Featured") (eq $element.name "Non classé") }}
|
||||||
|
{{ continue }}
|
||||||
|
{{ else if lt $count 5 }}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/categories/{{ $element.slug }}">{{ $element.name }}</a>
|
||||||
|
</li>
|
||||||
|
{{ $count = add $count 1 }}
|
||||||
|
{{ else }}
|
||||||
|
{{ break }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<!-- Menu Extra -->
|
||||||
|
{{/* <div class="header-menu-extra">
|
||||||
|
<ul class="list-inline-sm">
|
||||||
|
<li><a href="#"><i class="bi bi-facebook"></i></a></li>
|
||||||
|
<li><a href="#"><i class="bi bi-twitter-x"></i></a></li>
|
||||||
|
<li><a href="#"><i class="bi bi-linkedin"></i></a></li>
|
||||||
|
</ul>
|
||||||
|
</div> */}}
|
||||||
|
<!-- Menu Toggle -->
|
||||||
|
<button class="header-toggle">
|
||||||
|
<span></span>
|
||||||
|
</button>
|
||||||
|
</div><!-- end container -->
|
||||||
|
</div>
|
||||||
|
<!-- end Header -->
|
||||||
|
|
||||||
3
layouts/partials/scripts.html
Normal file
3
layouts/partials/scripts.html
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<!-- Search Scripts -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/lunr@2.3.9/lunr.min.js"></script>
|
||||||
|
<script src="/assets/js/search.js"></script>
|
||||||
32
layouts/partials/seo/favicons.html
Normal file
32
layouts/partials/seo/favicons.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<!-- Favicon -->
|
||||||
|
<link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico">
|
||||||
|
<link rel="shortcut icon" type="image/x-icon" href="/assets/images/favicon.ico">
|
||||||
|
|
||||||
|
<!-- Apple Touch Icons -->
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="/assets/images/apple-touch-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="/assets/images/apple-touch-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="/assets/images/apple-touch-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="/assets/images/apple-touch-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="/assets/images/apple-touch-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="/assets/images/apple-touch-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="/assets/images/apple-touch-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="/assets/images/apple-touch-icon-152x152.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/assets/images/apple-touch-icon-180x180.png">
|
||||||
|
|
||||||
|
<!-- Android Icons -->
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="/assets/images/android-icon-192x192.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="96x96" href="/assets/images/favicon-96x96.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon-16x16.png">
|
||||||
|
|
||||||
|
<!-- Microsoft Tiles -->
|
||||||
|
<meta name="msapplication-TileColor" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">
|
||||||
|
<meta name="msapplication-TileImage" content="/assets/images/ms-icon-144x144.png">
|
||||||
|
<meta name="msapplication-config" content="/assets/images/browserconfig.xml">
|
||||||
|
|
||||||
|
<!-- PWA Manifest -->
|
||||||
|
<link rel="manifest" href="/manifest.json">
|
||||||
|
|
||||||
|
<!-- Theme Color -->
|
||||||
|
<meta name="theme-color" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">
|
||||||
|
<meta name="msapplication-TileColor" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">
|
||||||
33
layouts/partials/seo/opengraph.html
Normal file
33
layouts/partials/seo/opengraph.html
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{{- $title := .Title | default .Site.Title -}}
|
||||||
|
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
|
||||||
|
{{- $image := .Params.image | default .Site.Params.seo.default_image | default "/assets/images/og-default.jpg" -}}
|
||||||
|
{{- $image = $image | absURL -}}
|
||||||
|
{{- $url := .Permalink | default .RelPermalink | absURL -}}
|
||||||
|
{{- $siteName := .Site.Title -}}
|
||||||
|
{{- $locale := .Site.Language.Lang | default "en_US" -}}
|
||||||
|
|
||||||
|
<!-- Open Graph / Facebook -->
|
||||||
|
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">
|
||||||
|
<meta property="og:site_name" content="{{ $siteName }}">
|
||||||
|
<meta property="og:title" content="{{ $title }}">
|
||||||
|
<meta property="og:description" content="{{ $description }}">
|
||||||
|
<meta property="og:url" content="{{ $url }}">
|
||||||
|
<meta property="og:locale" content="{{ $locale }}">
|
||||||
|
<meta property="og:image" content="{{ $image }}">
|
||||||
|
<meta property="og:image:alt" content="{{ $title }}">
|
||||||
|
<meta property="og:image:width" content="1200">
|
||||||
|
<meta property="og:image:height" content="630">
|
||||||
|
|
||||||
|
<!-- Article specific -->
|
||||||
|
{{ if .IsPage }}
|
||||||
|
<meta property="article:section" content="{{ .Section | default "general" }}">
|
||||||
|
<meta property="article:author" content="{{ .Params.author | default .Site.Params.author | default .Site.Title }}">
|
||||||
|
{{ range .Params.tags | default .Site.Params.tags }}
|
||||||
|
<meta property="article:tag" content="{{ . }}">
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<!-- Additional locales for multilingual sites -->
|
||||||
|
{{ range .Translations }}
|
||||||
|
<meta property="og:locale:alternate" content="{{ .Language.Lang | default "en_US" }}">
|
||||||
|
{{ end }}
|
||||||
42
layouts/partials/seo/seo-config.html
Normal file
42
layouts/partials/seo/seo-config.html
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{{- /* SEO Configuration Partial */ -}}
|
||||||
|
{{- /* This partial includes all SEO-related partials */ -}}
|
||||||
|
|
||||||
|
<!-- Core SEO Meta Tags -->
|
||||||
|
{{ partial "seo/seo-meta.html" . }}
|
||||||
|
|
||||||
|
<!-- Open Graph Tags -->
|
||||||
|
{{ partial "seo/opengraph.html" . }}
|
||||||
|
|
||||||
|
<!-- Twitter Cards -->
|
||||||
|
{{ partial "seo/twitter-cards.html" . }}
|
||||||
|
|
||||||
|
<!-- Structured Data (JSON-LD) -->
|
||||||
|
{{ partial "seo/structured-data.html" . }}
|
||||||
|
|
||||||
|
<!-- Favicons and PWA Support -->
|
||||||
|
{{ partial "seo/favicons.html" . }}
|
||||||
|
|
||||||
|
<!-- Additional SEO Tags -->
|
||||||
|
{{- if .Site.Params.seo.google_verification }}
|
||||||
|
<meta name="google-site-verification" content="{{ .Site.Params.seo.google_verification }}">
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{- if .Site.Params.seo.bing_verification }}
|
||||||
|
<meta name="msvalidate.01" content="{{ .Site.Params.seo.bing_verification }}">
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{- if .Site.Params.seo.yandex_verification }}
|
||||||
|
<meta name="yandex-verification" content="{{ .Site.Params.seo.yandex_verification }}">
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{- if .Site.Params.seo.alexa_verification }}
|
||||||
|
<meta name="alexaVerifyID" content="{{ .Site.Params.seo.alexa_verification }}">
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<!-- hreflang for multilingual sites -->
|
||||||
|
{{ range .Translations }}
|
||||||
|
<link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}">
|
||||||
|
{{ end }}
|
||||||
|
{{ if .IsTranslated }}
|
||||||
|
<link rel="alternate" hreflang="x-default" href="{{ .Permalink }}">
|
||||||
|
{{ end }}
|
||||||
40
layouts/partials/seo/seo-meta.html
Normal file
40
layouts/partials/seo/seo-meta.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
|
||||||
|
{{- $keywords := delimit (.Keywords | default .Site.Params.keywords | default (slice)) ", " -}}
|
||||||
|
{{- $author := .Params.author | default .Site.Params.author | default .Site.Title -}}
|
||||||
|
{{- $robots := .Params.robots | default "index, follow" -}}
|
||||||
|
{{- $canonical := .Permalink | default .RelPermalink -}}
|
||||||
|
|
||||||
|
<!-- Primary Meta Tags -->
|
||||||
|
<meta name="description" content="{{ $description }}">
|
||||||
|
<meta name="keywords" content="{{ $keywords }}">
|
||||||
|
<meta name="author" content="{{ $author }}">
|
||||||
|
<meta name="robots" content="{{ $robots }}">
|
||||||
|
<meta name="generator" content="Hugo {{ hugo.Version }}">
|
||||||
|
|
||||||
|
<!-- Canonical URL -->
|
||||||
|
<link rel="canonical" href="{{ $canonical }}">
|
||||||
|
|
||||||
|
<!-- Theme Color -->
|
||||||
|
<meta name="theme-color" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">
|
||||||
|
<meta name="msapplication-TileColor" content="{{ .Site.Params.seo.theme_color | default "#007bff" }}">
|
||||||
|
|
||||||
|
<!-- Additional SEO -->
|
||||||
|
<meta name="rating" content="general">
|
||||||
|
<meta name="language" content="{{ .Site.Language.Lang | default "en" }}">
|
||||||
|
<meta name="revisit-after" content="7 days">
|
||||||
|
<meta name="distribution" content="global">
|
||||||
|
<meta name="web_author" content="{{ .Site.Params.author | default .Site.Title }}">
|
||||||
|
|
||||||
|
<!-- Geo Tags (if location is specified) -->
|
||||||
|
{{ with .Site.Params.seo.geo }}
|
||||||
|
<meta name="geo.region" content="{{ .region }}">
|
||||||
|
<meta name="geo.placename" content="{{ .placename }}">
|
||||||
|
<meta name="geo.position" content="{{ .latitude }};{{ .longitude }}">
|
||||||
|
<meta name="ICBM" content="{{ .latitude }}, {{ .longitude }}">
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<!-- Dublin Core -->
|
||||||
|
<meta name="DC.Title" content="{{ .Title | default .Site.Title }}">
|
||||||
|
<meta name="DC.Creator" content="{{ $author }}">
|
||||||
|
<meta name="DC.Description" content="{{ $description }}">
|
||||||
|
<meta name="DC.Language" content="{{ .Site.Language.Lang | default "en" }}">
|
||||||
85
layouts/partials/seo/structured-data.html
Normal file
85
layouts/partials/seo/structured-data.html
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{{- $title := .Title | default .Site.Title -}}
|
||||||
|
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
|
||||||
|
{{- $image := .Params.image | default .Site.Params.seo.default_image | default "/assets/images/logo.png" -}}
|
||||||
|
{{- $image = $image | absURL -}}
|
||||||
|
{{- $url := .Permalink | default .RelPermalink | absURL -}}
|
||||||
|
{{- $siteName := .Site.Title -}}
|
||||||
|
{{- $logo := .Site.Params.seo.logo | default "/assets/images/logo.png" | absURL -}}
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "WebSite",
|
||||||
|
"name": "{{ $siteName }}",
|
||||||
|
"description": "{{ $description }}",
|
||||||
|
"url": "{{ .Site.BaseURL }}",
|
||||||
|
"logo": {
|
||||||
|
"@type": "ImageObject",
|
||||||
|
"url": "{{ $logo }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{{ if .IsPage }}
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Article",
|
||||||
|
"headline": "{{ $title }}",
|
||||||
|
"description": "{{ $description }}",
|
||||||
|
"image": "{{ $image }}",
|
||||||
|
"url": "{{ $url }}",
|
||||||
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"name": "{{ .Params.author | default .Site.Params.author | default .Site.Title }}"
|
||||||
|
},
|
||||||
|
"publisher": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "{{ $siteName }}",
|
||||||
|
"logo": {
|
||||||
|
"@type": "ImageObject",
|
||||||
|
"url": "{{ $logo }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<!-- Breadcrumb Schema -->
|
||||||
|
{{ if and .IsPage .Section }}
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "BreadcrumbList",
|
||||||
|
"itemListElement": [
|
||||||
|
{
|
||||||
|
"@type": "ListItem",
|
||||||
|
"position": 1,
|
||||||
|
"name": "Accueil",
|
||||||
|
"item": "{{ .Site.BaseURL }}"
|
||||||
|
}
|
||||||
|
{{ if .Section }}
|
||||||
|
,{
|
||||||
|
"@type": "ListItem",
|
||||||
|
"position": 2,
|
||||||
|
"name": "{{ .Section | humanize }}",
|
||||||
|
"item": "{{ .Site.BaseURL }}{{ .Section }}/"
|
||||||
|
}
|
||||||
|
,{
|
||||||
|
"@type": "ListItem",
|
||||||
|
"position": 3,
|
||||||
|
"name": "{{ $title }}",
|
||||||
|
"item": "{{ $url }}"
|
||||||
|
}
|
||||||
|
{{ else }}
|
||||||
|
,{
|
||||||
|
"@type": "ListItem",
|
||||||
|
"position": 2,
|
||||||
|
"name": "{{ $title }}",
|
||||||
|
"item": "{{ $url }}"
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{{ end }}
|
||||||
27
layouts/partials/seo/twitter-cards.html
Normal file
27
layouts/partials/seo/twitter-cards.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{{- $title := .Title | default .Site.Title -}}
|
||||||
|
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
|
||||||
|
{{- $image := .Params.image | default .Site.Params.seo.default_image | default "/assets/images/twitter-default.jpg" -}}
|
||||||
|
{{- $image = $image | absURL -}}
|
||||||
|
{{- $siteName := .Site.Title -}}
|
||||||
|
{{- $twitter := .Site.Params.seo.twitter -}}
|
||||||
|
|
||||||
|
<!-- Twitter Card -->
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="twitter:title" content="{{ $title }}">
|
||||||
|
<meta name="twitter:description" content="{{ $description }}">
|
||||||
|
<meta name="twitter:image" content="{{ $image }}">
|
||||||
|
<meta name="twitter:image:alt" content="{{ $title }}">
|
||||||
|
|
||||||
|
<!-- Twitter Site -->
|
||||||
|
{{ with $twitter.site }}
|
||||||
|
<meta name="twitter:site" content="{{ . }}">
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<!-- Twitter Creator -->
|
||||||
|
{{ with $twitter.creator }}
|
||||||
|
<meta name="twitter:creator" content="{{ . }}">
|
||||||
|
{{ else }}
|
||||||
|
{{ with .Params.author }}
|
||||||
|
<meta name="twitter:creator" content="{{ . }}">
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
510
package-lock.json
generated
510
package-lock.json
generated
@@ -10,6 +10,349 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"he": "^1.2.0",
|
"he": "^1.2.0",
|
||||||
"node-fetch": "^3.3.2"
|
"node-fetch": "^3.3.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"sass": "^1.90.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"detect-libc": "^1.0.3",
|
||||||
|
"is-glob": "^4.0.3",
|
||||||
|
"micromatch": "^4.0.5",
|
||||||
|
"node-addon-api": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@parcel/watcher-android-arm64": "2.5.1",
|
||||||
|
"@parcel/watcher-darwin-arm64": "2.5.1",
|
||||||
|
"@parcel/watcher-darwin-x64": "2.5.1",
|
||||||
|
"@parcel/watcher-freebsd-x64": "2.5.1",
|
||||||
|
"@parcel/watcher-linux-arm-glibc": "2.5.1",
|
||||||
|
"@parcel/watcher-linux-arm-musl": "2.5.1",
|
||||||
|
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
|
||||||
|
"@parcel/watcher-linux-arm64-musl": "2.5.1",
|
||||||
|
"@parcel/watcher-linux-x64-glibc": "2.5.1",
|
||||||
|
"@parcel/watcher-linux-x64-musl": "2.5.1",
|
||||||
|
"@parcel/watcher-win32-arm64": "2.5.1",
|
||||||
|
"@parcel/watcher-win32-ia32": "2.5.1",
|
||||||
|
"@parcel/watcher-win32-x64": "2.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-android-arm64": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-darwin-arm64": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-darwin-x64": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-freebsd-x64": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"freebsd"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-linux-arm-musl": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-linux-x64-musl": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-win32-arm64": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-win32-ia32": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@parcel/watcher-win32-x64": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/parcel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/braces": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fill-range": "^7.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chokidar": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"readdirp": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14.16.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/data-uri-to-buffer": {
|
"node_modules/data-uri-to-buffer": {
|
||||||
@@ -21,6 +364,20 @@
|
|||||||
"node": ">= 12"
|
"node": ">= 12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/detect-libc": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"bin": {
|
||||||
|
"detect-libc": "bin/detect-libc.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fetch-blob": {
|
"node_modules/fetch-blob": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
@@ -44,6 +401,20 @@
|
|||||||
"node": "^12.20 || >= 14.13"
|
"node": "^12.20 || >= 14.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fill-range": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/formdata-polyfill": {
|
"node_modules/formdata-polyfill": {
|
||||||
"version": "4.0.10",
|
"version": "4.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
@@ -65,6 +436,72 @@
|
|||||||
"he": "bin/he"
|
"he": "bin/he"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/immutable": {
|
||||||
|
"version": "5.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz",
|
||||||
|
"integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-glob": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromatch": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"braces": "^3.0.3",
|
||||||
|
"picomatch": "^2.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-addon-api": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/node-domexception": {
|
"node_modules/node-domexception": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
@@ -103,6 +540,79 @@
|
|||||||
"url": "https://opencollective.com/node-fetch"
|
"url": "https://opencollective.com/node-fetch"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readdirp": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14.18.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sass": {
|
||||||
|
"version": "1.90.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.90.0.tgz",
|
||||||
|
"integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": "^4.0.0",
|
||||||
|
"immutable": "^5.0.2",
|
||||||
|
"source-map-js": ">=0.6.2 <2.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"sass": "sass.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@parcel/watcher": "^2.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/source-map-js": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/web-streams-polyfill": {
|
"node_modules/web-streams-polyfill": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||||
|
|||||||
@@ -6,12 +6,16 @@
|
|||||||
"fetch-data": "node scripts/fetch-wordpress.js",
|
"fetch-data": "node scripts/fetch-wordpress.js",
|
||||||
"generate-content": "node scripts/generate-content.js",
|
"generate-content": "node scripts/generate-content.js",
|
||||||
"prebuild": "npm run fetch-data && npm run generate-content",
|
"prebuild": "npm run fetch-data && npm run generate-content",
|
||||||
"build": "hugo --minify",
|
"build": "npm run build:css && hugo --minify",
|
||||||
"dev": "npm run fetch-data && npm run generate-content && hugo server -D",
|
"build:css": "sass assets/css/scss:static/assets/css",
|
||||||
|
"dev": "npm run fetch-data && npm run generate-content && npm run build:css && hugo server -D",
|
||||||
"clean": "rm -rf data/wordpress content/posts public"
|
"clean": "rm -rf data/wordpress content/posts public"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"he": "^1.2.0",
|
"he": "^1.2.0",
|
||||||
"node-fetch": "^3.3.2"
|
"node-fetch": "^3.3.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"sass": "^1.69.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,32 +4,32 @@ const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch
|
|||||||
|
|
||||||
const WORDPRESS_API = 'https://www.mistergeek.net/wp-json/wp/v2';
|
const WORDPRESS_API = 'https://www.mistergeek.net/wp-json/wp/v2';
|
||||||
const OUTPUT_DIR = path.join(__dirname, '..', 'data', 'wordpress');
|
const OUTPUT_DIR = path.join(__dirname, '..', 'data', 'wordpress');
|
||||||
|
const HUGO_DATA_DIR = path.join(__dirname, '..', 'data');
|
||||||
|
|
||||||
async function fetchPosts(page = 1, perPage = 100) {
|
async function fetchAll(endpoint, perPage = 100) {
|
||||||
const response = await fetch(`${WORDPRESS_API}/posts?page=${page}&per_page=${perPage}&_embed`);
|
let page = 1;
|
||||||
const posts = await response.json();
|
let items = [];
|
||||||
|
|
||||||
if (response.headers.get('x-wp-totalpages') > page) {
|
while (true) {
|
||||||
const nextPosts = await fetchPosts(page + 1, perPage);
|
const url = `${WORDPRESS_API}/${endpoint}?page=${page}&per_page=${perPage}&_embed`;
|
||||||
return [...posts, ...nextPosts];
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
// If endpoint does not support paging or returns empty, break
|
||||||
|
if (!response.ok) {
|
||||||
|
// 400 often means "page out of range" for WP; stop paging
|
||||||
|
if (response.status === 400) break;
|
||||||
|
throw new Error(`Failed to fetch ${endpoint} (page ${page}): ${response.status} ${response.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return posts;
|
const batch = await response.json();
|
||||||
}
|
items = items.concat(batch);
|
||||||
|
|
||||||
async function fetchCategories() {
|
const totalPages = parseInt(response.headers.get('x-wp-totalpages') || '1', 10);
|
||||||
const response = await fetch(`${WORDPRESS_API}/categories?per_page=100`);
|
if (page >= totalPages) break;
|
||||||
return response.json();
|
page++;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchTags() {
|
return items;
|
||||||
const response = await fetch(`${WORDPRESS_API}/tags?per_page=100`);
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchAuthors() {
|
|
||||||
const response = await fetch(`${WORDPRESS_API}/users?per_page=100`);
|
|
||||||
return response.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateData() {
|
async function generateData() {
|
||||||
@@ -40,20 +40,44 @@ async function generateData() {
|
|||||||
|
|
||||||
console.log('Fetching WordPress data...');
|
console.log('Fetching WordPress data...');
|
||||||
|
|
||||||
const [posts, categories, tags, authors] = await Promise.all([
|
// Fetch all relevant endpoints concurrently (pages + posts + taxonomies + users)
|
||||||
fetchPosts(),
|
const [
|
||||||
fetchCategories(),
|
posts,
|
||||||
fetchTags(),
|
pages,
|
||||||
fetchAuthors()
|
categories,
|
||||||
|
tags,
|
||||||
|
authors
|
||||||
|
] = await Promise.all([
|
||||||
|
fetchAll('posts'),
|
||||||
|
fetchAll('pages'),
|
||||||
|
fetchAll('categories'),
|
||||||
|
fetchAll('tags'),
|
||||||
|
fetchAll('users')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Filter pages to only include published pages
|
||||||
|
const publishedPages = pages.filter(page => page.status === 'publish');
|
||||||
|
|
||||||
|
// Create navigation data from published pages
|
||||||
|
const navigationData = publishedPages.map(page => ({
|
||||||
|
id: page.id,
|
||||||
|
title: page.title?.rendered || page.slug,
|
||||||
|
slug: page.slug,
|
||||||
|
link: page.link,
|
||||||
|
date: page.date,
|
||||||
|
modified: page.modified
|
||||||
|
}));
|
||||||
|
|
||||||
// Save data as JSON files
|
// Save data as JSON files
|
||||||
fs.writeFileSync(path.join(OUTPUT_DIR, 'posts.json'), JSON.stringify(posts, null, 2));
|
fs.writeFileSync(path.join(OUTPUT_DIR, 'posts.json'), JSON.stringify(posts, null, 2));
|
||||||
|
fs.writeFileSync(path.join(OUTPUT_DIR, 'pages.json'), JSON.stringify(publishedPages, null, 2));
|
||||||
fs.writeFileSync(path.join(OUTPUT_DIR, 'categories.json'), JSON.stringify(categories, null, 2));
|
fs.writeFileSync(path.join(OUTPUT_DIR, 'categories.json'), JSON.stringify(categories, null, 2));
|
||||||
fs.writeFileSync(path.join(OUTPUT_DIR, 'tags.json'), JSON.stringify(tags, null, 2));
|
fs.writeFileSync(path.join(OUTPUT_DIR, 'tags.json'), JSON.stringify(tags, null, 2));
|
||||||
fs.writeFileSync(path.join(OUTPUT_DIR, 'authors.json'), JSON.stringify(authors, null, 2));
|
fs.writeFileSync(path.join(OUTPUT_DIR, 'authors.json'), JSON.stringify(authors, null, 2));
|
||||||
|
fs.writeFileSync(path.join(OUTPUT_DIR, 'navigation.json'), JSON.stringify(navigationData, null, 2));
|
||||||
|
|
||||||
console.log(`✅ Fetched ${posts.length} posts, ${categories.length} categories, ${tags.length} tags, ${authors.length} authors`);
|
console.log(`✅ Fetched ${posts.length} posts, ${publishedPages.length} pages, ${categories.length} categories, ${tags.length} tags, ${authors.length} authors`);
|
||||||
|
console.log(`✅ Generated navigation data with ${navigationData.length} items`);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateData().catch(console.error);
|
generateData().catch(console.error);
|
||||||
@@ -4,16 +4,23 @@ const he = require('he');
|
|||||||
|
|
||||||
const DATA_DIR = path.join(__dirname, '..', 'data', 'wordpress');
|
const DATA_DIR = path.join(__dirname, '..', 'data', 'wordpress');
|
||||||
const CONTENT_DIR = path.join(__dirname, '..', 'content');
|
const CONTENT_DIR = path.join(__dirname, '..', 'content');
|
||||||
|
const PAGES_DIR = path.join(CONTENT_DIR, 'pages');
|
||||||
|
|
||||||
function generateContent() {
|
function generateContent() {
|
||||||
const posts = JSON.parse(fs.readFileSync(path.join(DATA_DIR, 'posts.json'), 'utf8'));
|
const posts = JSON.parse(fs.readFileSync(path.join(DATA_DIR, 'posts.json'), 'utf8'));
|
||||||
|
const pages = JSON.parse(fs.readFileSync(path.join(DATA_DIR, 'pages.json'), 'utf8'));
|
||||||
|
|
||||||
// Ensure content directory exists
|
// Ensure content directories exist
|
||||||
if (!fs.existsSync(CONTENT_DIR)) {
|
if (!fs.existsSync(CONTENT_DIR)) {
|
||||||
fs.mkdirSync(CONTENT_DIR, { recursive: true });
|
fs.mkdirSync(CONTENT_DIR, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
posts.forEach(post => {
|
if (!fs.existsSync(PAGES_DIR)) {
|
||||||
|
fs.mkdirSync(PAGES_DIR, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process posts - only include published posts
|
||||||
|
posts.filter(post => post.status === 'publish').forEach(post => {
|
||||||
const slug = post.slug;
|
const slug = post.slug;
|
||||||
const date = new Date(post.date);
|
const date = new Date(post.date);
|
||||||
const year = date.getFullYear();
|
const year = date.getFullYear();
|
||||||
@@ -33,7 +40,7 @@ function generateContent() {
|
|||||||
const frontmatter = {
|
const frontmatter = {
|
||||||
title: he.decode(post.title.rendered),
|
title: he.decode(post.title.rendered),
|
||||||
date: post.date,
|
date: post.date,
|
||||||
draft: post.status !== 'publish',
|
draft: false,
|
||||||
slug: slug,
|
slug: slug,
|
||||||
wordpress_id: post.id,
|
wordpress_id: post.id,
|
||||||
excerpt: he.decode(post.excerpt.rendered.replace(/<[^>]*>/g, '')),
|
excerpt: he.decode(post.excerpt.rendered.replace(/<[^>]*>/g, '')),
|
||||||
@@ -47,21 +54,27 @@ function generateContent() {
|
|||||||
// Decode HTML entities in the content and clean up HTML tags
|
// Decode HTML entities in the content and clean up HTML tags
|
||||||
let contentHtml = he.decode(post.content.rendered);
|
let contentHtml = he.decode(post.content.rendered);
|
||||||
|
|
||||||
// Convert absolute URLs in a href to relative URLs
|
// Convert absolute URLs in a href to relative URLs (only for wp.mistergeek.net)
|
||||||
contentHtml = contentHtml.replace(/<a\s+[^>]*href="([^"]+)"[^>]*>/g, (match, href) => {
|
contentHtml = contentHtml.replace(/<a\s+[^>]*href="([^"]+)"[^>]*>/g, (match, href) => {
|
||||||
// Check if the href is an absolute URL (starts with http:// or https://)
|
// Check if the href is an absolute URL containing wp.mistergeek.net
|
||||||
if (href.startsWith('http://') || href.startsWith('https://')) {
|
if (href.startsWith('http://') || href.startsWith('https://')) {
|
||||||
// Extract the path part of the URL
|
try {
|
||||||
const url = new URL(href);
|
const url = new URL(href);
|
||||||
// Return the modified a tag with relative URL
|
if (url.hostname === 'wp.mistergeek.net' || url.hostname === 'www.wp.mistergeek.net') {
|
||||||
|
// Only convert wp.mistergeek.net URLs to relative paths
|
||||||
return match.replace(href, url.pathname);
|
return match.replace(href, url.pathname);
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// If URL parsing fails, return the original href
|
||||||
|
console.warn('Failed to parse URL:', href, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
|
|
||||||
contentHtml = contentHtml
|
contentHtml = contentHtml
|
||||||
.replace(/<p>\s*<\/p>/g, '') // Remove empty paragraphs
|
.replace(/<p>\s*<\/p>/g, '') // Remove empty paragraphs
|
||||||
.replace(/<\/p>\s*<p>/g, '\n\n') // Replace paragraph breaks with newlines
|
.replace(/<\/p>\s*<p>/g, '\n\n'); // Replace paragraph breaks with newlines
|
||||||
|
|
||||||
const content = `---
|
const content = `---
|
||||||
${Object.entries(frontmatter)
|
${Object.entries(frontmatter)
|
||||||
@@ -73,7 +86,67 @@ ${contentHtml.trim()}`;
|
|||||||
fs.writeFileSync(path.join(contentDir, 'index.md'), content);
|
fs.writeFileSync(path.join(contentDir, 'index.md'), content);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`✅ Generated ${posts.length} content files`);
|
// Process pages - only include published pages
|
||||||
|
pages.filter(page => page.status === 'publish').forEach(page => {
|
||||||
|
const slug = page.slug;
|
||||||
|
|
||||||
|
const contentDir = path.join(PAGES_DIR, slug);
|
||||||
|
|
||||||
|
if (!fs.existsSync(contentDir)) {
|
||||||
|
fs.mkdirSync(contentDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const frontmatter = {
|
||||||
|
title: he.decode(page.title.rendered),
|
||||||
|
slug: slug,
|
||||||
|
type: "pages",
|
||||||
|
layout: "single",
|
||||||
|
wordpress_id: page.id,
|
||||||
|
date: page.date,
|
||||||
|
modified: page.modified,
|
||||||
|
draft: false,
|
||||||
|
aliases: [`/${slug}/`]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Decode HTML entities in the content and clean up HTML tags
|
||||||
|
let contentHtml = he.decode(page.content.rendered);
|
||||||
|
|
||||||
|
// Convert absolute URLs in a href to relative URLs (only for wp.mistergeek.net)
|
||||||
|
contentHtml = contentHtml.replace(/<a\s+[^>]*href="([^"]+)"[^>]*>/g, (match, href) => {
|
||||||
|
// Check if the href is an absolute URL containing wp.mistergeek.net
|
||||||
|
if (href.startsWith('http://') || href.startsWith('https://')) {
|
||||||
|
try {
|
||||||
|
const url = new URL(href);
|
||||||
|
if (url.hostname === 'wp.mistergeek.net' || url.hostname === 'www.wp.mistergeek.net') {
|
||||||
|
// Only convert wp.mistergeek.net URLs to relative paths
|
||||||
|
return match.replace(href, url.pathname);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// If URL parsing fails, return the original href
|
||||||
|
console.warn('Failed to parse URL:', href, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
});
|
||||||
|
|
||||||
|
contentHtml = contentHtml
|
||||||
|
.replace(/<p>\s*<\/p>/g, '') // Remove empty paragraphs
|
||||||
|
.replace(/<\/p>\s*<p>/g, '\n\n'); // Replace paragraph breaks with newlines
|
||||||
|
|
||||||
|
const content = `---
|
||||||
|
${Object.entries(frontmatter)
|
||||||
|
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
|
||||||
|
.join('\n')}
|
||||||
|
---
|
||||||
|
${contentHtml.trim()}`;
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(contentDir, 'index.md'), content);
|
||||||
|
});
|
||||||
|
|
||||||
|
const publishedPosts = posts.filter(post => post.status === 'publish');
|
||||||
|
const publishedPages = pages.filter(page => page.status === 'publish');
|
||||||
|
console.log(`✅ Generated ${publishedPosts.length} content files`);
|
||||||
|
console.log(`✅ Generated ${publishedPages.length} page files`);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateContent();
|
generateContent();
|
||||||
File diff suppressed because it is too large
Load Diff
1
static/assets/css/theme.css.map
Normal file
1
static/assets/css/theme.css.map
Normal file
File diff suppressed because one or more lines are too long
39
test-table.html
Normal file
39
test-table.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Table Test</title>
|
||||||
|
<link rel="stylesheet" href="assets/css/scss/theme.scss">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<figure class="wp-block-table">
|
||||||
|
<table class="has-fixed-layout">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>TECHNOLOGIE</th>
|
||||||
|
<th>DÉBIT MAXIMUM THÉORIQUE (Mégabit/s)</th>
|
||||||
|
<th>REMARQUE(S)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><strong>FTTH (Fibre jusqu’à l’abonné)</strong></td>
|
||||||
|
<td>Jusqu’à 10 000 Mégabit/s</td>
|
||||||
|
<td>Débit symétrique, très haute performance.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>FTTLa (Fibre jusqu’au dernier amplificateur)</strong></td>
|
||||||
|
<td>Jusqu’à 1000 Mégabit/s</td>
|
||||||
|
<td>Débit variable selon la distance au point de raccordement.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Boucle Locale Radio</strong></td>
|
||||||
|
<td>Jusqu’à 100 Mégabit/s</td>
|
||||||
|
<td>Dépend de la qualité du signal et de l’environnement.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</figure>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
183
yarn.lock
183
yarn.lock
@@ -2,11 +2,119 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@parcel/watcher-android-arm64@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz"
|
||||||
|
integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==
|
||||||
|
|
||||||
|
"@parcel/watcher-darwin-arm64@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz"
|
||||||
|
integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==
|
||||||
|
|
||||||
|
"@parcel/watcher-darwin-x64@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz"
|
||||||
|
integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==
|
||||||
|
|
||||||
|
"@parcel/watcher-freebsd-x64@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz"
|
||||||
|
integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm-glibc@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz"
|
||||||
|
integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm-musl@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz"
|
||||||
|
integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm64-glibc@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz"
|
||||||
|
integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-arm64-musl@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz"
|
||||||
|
integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-x64-glibc@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz"
|
||||||
|
integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==
|
||||||
|
|
||||||
|
"@parcel/watcher-linux-x64-musl@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz"
|
||||||
|
integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==
|
||||||
|
|
||||||
|
"@parcel/watcher-win32-arm64@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz"
|
||||||
|
integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==
|
||||||
|
|
||||||
|
"@parcel/watcher-win32-ia32@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz"
|
||||||
|
integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==
|
||||||
|
|
||||||
|
"@parcel/watcher-win32-x64@2.5.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz"
|
||||||
|
integrity sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==
|
||||||
|
|
||||||
|
"@parcel/watcher@^2.4.1":
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz"
|
||||||
|
integrity sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==
|
||||||
|
dependencies:
|
||||||
|
detect-libc "^1.0.3"
|
||||||
|
is-glob "^4.0.3"
|
||||||
|
micromatch "^4.0.5"
|
||||||
|
node-addon-api "^7.0.0"
|
||||||
|
optionalDependencies:
|
||||||
|
"@parcel/watcher-android-arm64" "2.5.1"
|
||||||
|
"@parcel/watcher-darwin-arm64" "2.5.1"
|
||||||
|
"@parcel/watcher-darwin-x64" "2.5.1"
|
||||||
|
"@parcel/watcher-freebsd-x64" "2.5.1"
|
||||||
|
"@parcel/watcher-linux-arm-glibc" "2.5.1"
|
||||||
|
"@parcel/watcher-linux-arm-musl" "2.5.1"
|
||||||
|
"@parcel/watcher-linux-arm64-glibc" "2.5.1"
|
||||||
|
"@parcel/watcher-linux-arm64-musl" "2.5.1"
|
||||||
|
"@parcel/watcher-linux-x64-glibc" "2.5.1"
|
||||||
|
"@parcel/watcher-linux-x64-musl" "2.5.1"
|
||||||
|
"@parcel/watcher-win32-arm64" "2.5.1"
|
||||||
|
"@parcel/watcher-win32-ia32" "2.5.1"
|
||||||
|
"@parcel/watcher-win32-x64" "2.5.1"
|
||||||
|
|
||||||
|
braces@^3.0.3:
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz"
|
||||||
|
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
|
||||||
|
dependencies:
|
||||||
|
fill-range "^7.1.1"
|
||||||
|
|
||||||
|
chokidar@^4.0.0:
|
||||||
|
version "4.0.3"
|
||||||
|
resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz"
|
||||||
|
integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==
|
||||||
|
dependencies:
|
||||||
|
readdirp "^4.0.1"
|
||||||
|
|
||||||
data-uri-to-buffer@^4.0.0:
|
data-uri-to-buffer@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz"
|
resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz"
|
||||||
integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
|
integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
|
||||||
|
|
||||||
|
detect-libc@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz"
|
||||||
|
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
|
||||||
|
|
||||||
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz"
|
resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz"
|
||||||
@@ -15,6 +123,13 @@ fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
|||||||
node-domexception "^1.0.0"
|
node-domexception "^1.0.0"
|
||||||
web-streams-polyfill "^3.0.3"
|
web-streams-polyfill "^3.0.3"
|
||||||
|
|
||||||
|
fill-range@^7.1.1:
|
||||||
|
version "7.1.1"
|
||||||
|
resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz"
|
||||||
|
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
|
||||||
|
dependencies:
|
||||||
|
to-regex-range "^5.0.1"
|
||||||
|
|
||||||
formdata-polyfill@^4.0.10:
|
formdata-polyfill@^4.0.10:
|
||||||
version "4.0.10"
|
version "4.0.10"
|
||||||
resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz"
|
resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz"
|
||||||
@@ -27,6 +142,41 @@ he@^1.2.0:
|
|||||||
resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz"
|
resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz"
|
||||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||||
|
|
||||||
|
immutable@^5.0.2:
|
||||||
|
version "5.1.3"
|
||||||
|
resolved "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz"
|
||||||
|
integrity sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==
|
||||||
|
|
||||||
|
is-extglob@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz"
|
||||||
|
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
|
||||||
|
|
||||||
|
is-glob@^4.0.3:
|
||||||
|
version "4.0.3"
|
||||||
|
resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz"
|
||||||
|
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
|
||||||
|
dependencies:
|
||||||
|
is-extglob "^2.1.1"
|
||||||
|
|
||||||
|
is-number@^7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
|
||||||
|
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||||
|
|
||||||
|
micromatch@^4.0.5:
|
||||||
|
version "4.0.8"
|
||||||
|
resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz"
|
||||||
|
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
|
||||||
|
dependencies:
|
||||||
|
braces "^3.0.3"
|
||||||
|
picomatch "^2.3.1"
|
||||||
|
|
||||||
|
node-addon-api@^7.0.0:
|
||||||
|
version "7.1.1"
|
||||||
|
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz"
|
||||||
|
integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
|
||||||
|
|
||||||
node-domexception@^1.0.0:
|
node-domexception@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz"
|
||||||
@@ -41,6 +191,39 @@ node-fetch@^3.3.2:
|
|||||||
fetch-blob "^3.1.4"
|
fetch-blob "^3.1.4"
|
||||||
formdata-polyfill "^4.0.10"
|
formdata-polyfill "^4.0.10"
|
||||||
|
|
||||||
|
picomatch@^2.3.1:
|
||||||
|
version "2.3.1"
|
||||||
|
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
|
||||||
|
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||||
|
|
||||||
|
readdirp@^4.0.1:
|
||||||
|
version "4.1.2"
|
||||||
|
resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz"
|
||||||
|
integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==
|
||||||
|
|
||||||
|
sass@^1.90.0:
|
||||||
|
version "1.90.0"
|
||||||
|
resolved "https://registry.npmjs.org/sass/-/sass-1.90.0.tgz"
|
||||||
|
integrity sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==
|
||||||
|
dependencies:
|
||||||
|
chokidar "^4.0.0"
|
||||||
|
immutable "^5.0.2"
|
||||||
|
source-map-js ">=0.6.2 <2.0.0"
|
||||||
|
optionalDependencies:
|
||||||
|
"@parcel/watcher" "^2.4.1"
|
||||||
|
|
||||||
|
"source-map-js@>=0.6.2 <2.0.0":
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
|
||||||
|
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||||
|
|
||||||
|
to-regex-range@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
|
||||||
|
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
|
||||||
|
dependencies:
|
||||||
|
is-number "^7.0.0"
|
||||||
|
|
||||||
web-streams-polyfill@^3.0.3:
|
web-streams-polyfill@^3.0.3:
|
||||||
version "3.3.3"
|
version "3.3.3"
|
||||||
resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz"
|
resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz"
|
||||||
|
|||||||
Reference in New Issue
Block a user