Some tweaks to improve CWV
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/deploy unknown status
ci/woodpecker/push/build Pipeline failed

This commit is contained in:
2026-02-14 19:45:11 -03:00
parent 01463952bb
commit 614aad4a8b
5 changed files with 163 additions and 103 deletions

View File

@@ -1,8 +1,8 @@
{ {
"semi": false, "semi": true,
"singleQuote": true, "singleQuote": true,
"tabWidth": 4, "tabWidth": 4,
"trailingComma": "none", "trailingComma": "all",
"overrides": [ "overrides": [
{ {
"files": "*.yml", "files": "*.yml",

View File

@@ -13,7 +13,15 @@ export default [
} }
}, },
rules: { rules: {
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }] 'no-undef': 'warn',
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'no-var': 'warn',
'prefer-arrow-callback': 'warn',
'prefer-const': 'warn',
'prefer-destructuring': 'warn',
'prefer-rest-params': 'warn',
'prefer-spread': 'warn',
'prefer-template': 'warn',
} }
}, },
prettierConfig prettierConfig

View File

@@ -1,11 +1,11 @@
;(function () { (function () {
var script = document.currentScript const script = document.currentScript;
var id = script && script.getAttribute('data-ga-id') const id = script && script.getAttribute('data-ga-id');
if (!id) return if (!id) return;
window.dataLayer = window.dataLayer || [] window.dataLayer = window.dataLayer || [];
function gtag() { function gtag(...args) {
window.dataLayer.push(arguments) window.dataLayer.push(...args);
} }
gtag('js', new Date()) gtag('js', new Date());
gtag('config', id, { anonymize_ip: true }) gtag('config', id, { anonymize_ip: true });
})() })();

View File

@@ -1,115 +1,119 @@
// --- theme toggle --- // --- theme toggle ---
const toggle = document.getElementById('theme-toggle') const toggle = document.getElementById('theme-toggle');
const root = document.documentElement const root = document.documentElement;
const saved = localStorage.getItem('dark-mode') const saved = window?.localStorage?.getItem('dark-mode');
const sysDark = window.matchMedia('(prefers-color-scheme: dark)').matches const sysDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (saved === 'true') { if (saved === 'true') {
root.classList.add('dark') root.classList.add('dark');
root.classList.remove('light') root.classList.remove('light');
} else if (saved === 'false') { } else if (saved === 'false') {
root.classList.add('light') root.classList.add('light');
root.classList.remove('dark') root.classList.remove('dark');
} else { } else {
if (sysDark) { if (sysDark) {
root.classList.add('dark') root.classList.add('dark');
root.classList.remove('light') root.classList.remove('light');
} else { } else {
root.classList.add('light') root.classList.add('light');
root.classList.remove('dark') root.classList.remove('dark');
} }
} }
toggle.addEventListener('click', () => { toggle.addEventListener('click', () => {
const isDark = root.classList.contains('dark') const isDark = root.classList.contains('dark');
root.classList.toggle('dark', !isDark) root.classList.toggle('dark', !isDark);
root.classList.toggle('light', isDark) root.classList.toggle('light', isDark);
localStorage.setItem('dark-mode', !isDark) window?.localStorage?.setItem('dark-mode', !isDark);
}) });
const body = document.body const { body } = document;
// --- lightbox base --- // --- lightbox base ---
const lb = document.getElementById('lightbox') const lb = document.getElementById('lightbox');
const lbCnt = document.getElementById('lb-content') const lbCnt = document.getElementById('lb-content');
const lbCap = document.getElementById('lb-caption') const lbCap = document.getElementById('lb-caption');
document.getElementById('lb-close').addEventListener('click', () => { document.getElementById('lb-close').addEventListener('click', () => {
lb.setAttribute('aria-hidden', 'true') lb.setAttribute('aria-hidden', 'true');
body.classList.remove('lightbox-open') body.classList.remove('lightbox-open');
lbCnt.innerHTML = '' lbCnt.innerHTML = '';
}) });
// --- build gallery --- // --- build gallery ---
const gallery = document.getElementById('gallery') const gallery = document.getElementById('gallery');
const mediaData = JSON.parse(document.getElementById('media-data').textContent) const mediaData = JSON.parse(document.getElementById('media-data').textContent);
const createPicture = (item) => { const createPicture = (item) => {
const pic = document.createElement('picture') const pic = document.createElement('picture');
;['desktop', 'tablet', 'mobile'].forEach((bp) => { ['desktop', 'tablet', 'mobile'].forEach((bp) => {
const src = document.createElement('source') const src = document.createElement('source');
const widthQuery = bp === 'desktop' ? 1024 : bp === 'tablet' ? 768 : 0 const widthQuery = bp === 'desktop' ? 1024 : bp === 'tablet' ? 768 : 0;
src.media = `(min-width:${widthQuery}px)` src.media = `(min-width:${widthQuery}px)`;
if (item.type === 'image') { if (item.type === 'image') {
src.srcset = src.srcset =
`assets/media/${bp}/${item.name}@1x.webp 1x, ` + `assets/media/${bp}/${item.name}@1x.webp 1x, ` +
`assets/media/${bp}/${item.name}.webp 2x` `assets/media/${bp}/${item.name}.webp 2x`;
} else { } else {
// video poster still // video poster still
src.srcset = src.srcset =
`assets/media/${bp}/${item.name}_still@1x.webp 1x, ` + `assets/media/${bp}/${item.name}_still@1x.webp 1x, ` +
`assets/media/${bp}/${item.name}_still.webp 2x` `assets/media/${bp}/${item.name}_still.webp 2x`;
} }
pic.appendChild(src) pic.appendChild(src);
}) });
// thumbnail fallback (always 300px/2×) // thumbnail fallback (always 300px/2×)
const img = document.createElement('img') const img = document.createElement('img');
img.src = `assets/media/thumbnail/${item.name}.webp` img.src = `assets/media/thumbnail/${item.name}.webp`;
img.alt = item.alt.replace(/[]/g, '') img.alt = item.alt.replace(/[]/g, '');
pic.appendChild(img) img.height = item.height || 300;
return pic img.width = item.width || 300;
} img.loading = item.loading || 'lazy';
pic.appendChild(img);
return pic;
};
mediaData.forEach((item) => { mediaData.forEach((item) => {
const fig = document.createElement('figure') const fig = document.createElement('figure');
fig.className = `gallery-item${item.type === 'video' ? ' video' : ''}` fig.className = `gallery-item${item.type === 'video' ? ' video' : ''}`;
fig.tabIndex = 0 fig.tabIndex = 0;
fig.dataset.name = item.name fig.dataset.name = item.name;
fig.dataset.type = item.type fig.dataset.type = item.type;
fig.dataset.caption = item.caption fig.dataset.caption = item.caption;
fig.appendChild(createPicture(item)) fig.appendChild(createPicture(item));
// overlay caption // overlay caption
const cap = document.createElement('figcaption') const cap = document.createElement('figcaption');
cap.textContent = item.caption cap.textContent = item.caption;
fig.appendChild(cap) fig.appendChild(cap);
// events // events
fig.addEventListener('click', () => openLightbox(item)) fig.addEventListener('click', () => openLightbox(item));
fig.addEventListener( fig.addEventListener(
'keypress', 'keypress',
(e) => e.key === 'Enter' && openLightbox(item) (e) => e.key === 'Enter' && openLightbox(item),
) );
gallery.appendChild(fig) gallery.appendChild(fig);
}) });
// --- video toggle --- // --- video toggle ---
const videoTgl = document.getElementById('show_video') const videoTgl = document.getElementById('show_video');
videoTgl.addEventListener('click', () => { videoTgl.addEventListener('click', () => {
openLightbox(mediaData.find((i) => i.type === 'video')) openLightbox(mediaData.find((i) => i.type === 'video'));
}) });
function openLightbox(item) { function openLightbox(item) {
lbCnt.innerHTML = '' lbCnt.innerHTML = '';
if (item.type === 'video') { if (item.type === 'video') {
const v = document.createElement('video') const v = document.createElement('video');
v.src = `assets/media/videos/${item.name}.mp4` v.src = `assets/media/videos/${item.name}.mp4`;
v.controls = true v.controls = true;
v.autoplay = true v.autoplay = true;
lbCnt.appendChild(v) v.loading = item.loading || 'lazy';
lbCnt.appendChild(v);
} else { } else {
lbCnt.appendChild(createPicture(item)) lbCnt.appendChild(createPicture(item));
} }
lbCap.textContent = item.caption lbCap.textContent = item.caption;
body.classList.add('lightbox-open') body.classList.add('lightbox-open');
lb.setAttribute('aria-hidden', 'false') lb.setAttribute('aria-hidden', 'false');
} }

View File

@@ -15,6 +15,11 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<title>64 Armandine St #3 Boston, Massachusetts</title> <title>64 Armandine St #3 Boston, Massachusetts</title>
<meta
name="description"
content="An inviting blend of comfort and curated art—relaxation guaranteed."
/>
<link <link
rel="icon" rel="icon"
type="image/png" type="image/png"
@@ -28,6 +33,7 @@
href="/assets/favicon-16x16.png" href="/assets/favicon-16x16.png"
/> />
<link rel="icon" type="image/x-icon" href="/assets/favicon.ico" /> <link rel="icon" type="image/x-icon" href="/assets/favicon.ico" />
<link rel="stylesheet" href="/assets/css/style.css" /> <link rel="stylesheet" href="/assets/css/style.css" />
</head> </head>
<body> <body>
@@ -71,121 +77,163 @@
"type": "image", "type": "image",
"name": "living_room_1", "name": "living_room_1",
"caption": "An inviting blend of comfort and curated art—relaxation guaranteed.", "caption": "An inviting blend of comfort and curated art—relaxation guaranteed.",
"alt": "Sunny living room with stylish seating and vibrant artwork." "alt": "Sunny living room with stylish seating and vibrant artwork.",
"height": 200,
"width": 300,
"loading": "eager"
}, },
{ {
"type": "image", "type": "image",
"name": "living_room_2", "name": "living_room_2",
"caption": "Relaxation elevated—your stylish living space awaits.", "caption": "Relaxation elevated—your stylish living space awaits.",
"alt": "Spacious living area featuring elegant furniture and tasteful decor." "alt": "Spacious living area featuring elegant furniture and tasteful decor.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "kitchen", "name": "kitchen",
"caption": "The culinary stage is set—snacking encouraged, style required.", "caption": "The culinary stage is set—snacking encouraged, style required.",
"alt": "Modern kitchen showcasing sleek appliances and contemporary design." "alt": "Modern kitchen showcasing sleek appliances and contemporary design.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "bedroom_suite_1", "name": "bedroom_suite_1",
"caption": "A bedroom suite designed to make snoozing irresistible.", "caption": "A bedroom suite designed to make snoozing irresistible.",
"alt": "Inviting bedroom suite with cozy bedding and warm lighting." "alt": "Inviting bedroom suite with cozy bedding and warm lighting.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "bedroom_suite_2", "name": "bedroom_suite_2",
"caption": "Style meets comfort—sleeping in has never been easier.", "caption": "Style meets comfort—sleeping in has never been easier.",
"alt": "Comfortable bedroom suite with elegant decor and soft tones." "alt": "Comfortable bedroom suite with elegant decor and soft tones.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "bedroom_suite_3", "name": "bedroom_suite_3",
"caption": "Where dreams get stylish—a bedroom that feels like home.", "caption": "Where dreams get stylish—a bedroom that feels like home.",
"alt": "Welcoming bedroom with soothing colors and inviting ambiance." "alt": "Welcoming bedroom with soothing colors and inviting ambiance.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "guest_bath", "name": "guest_bath",
"caption": "Your personal spa experience—right down the hall.", "caption": "Your personal spa experience—right down the hall.",
"alt": "Sophisticated guest bathroom with modern fixtures and clean lines." "alt": "Sophisticated guest bathroom with modern fixtures and clean lines.",
"height": 450,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "onsuite_1", "name": "onsuite_1",
"caption": "Luxury meets practicality—your private ensuite awaits.", "caption": "Luxury meets practicality—your private ensuite awaits.",
"alt": "Private ensuite bathroom featuring contemporary design and premium finishes." "alt": "Private ensuite bathroom featuring contemporary design and premium finishes.",
"height": 450,
"width": 300,
"loading": "eager"
}, },
{ {
"type": "image", "type": "image",
"name": "onsuite_2", "name": "onsuite_2",
"caption": "Everyday luxury, right at home—your ensuite oasis.", "caption": "Everyday luxury, right at home—your ensuite oasis.",
"alt": "Elegant ensuite with sleek fixtures and stylish decor." "alt": "Elegant ensuite with sleek fixtures and stylish decor.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "laundry", "name": "laundry",
"caption": "Laundry day reimagined—functional never looked so good.", "caption": "Laundry day reimagined—functional never looked so good.",
"alt": "Modern laundry room with washer, dryer, and organized storage." "alt": "Modern laundry room with washer, dryer, and organized storage.",
"height": 450,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "coat_closet", "name": "coat_closet",
"caption": "Organized and chic—your entryway's best friend.", "caption": "Organized and chic—your entryway's best friend.",
"alt": "Convenient coat closet with tidy storage solutions." "alt": "Convenient coat closet with tidy storage solutions.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "deck_1", "name": "deck_1",
"caption": "Outdoor comfort, just steps away—morning coffee optional.", "caption": "Outdoor comfort, just steps away—morning coffee optional.",
"alt": "Sunny deck with cozy seating and pleasant outdoor views." "alt": "Sunny deck with cozy seating and pleasant outdoor views.",
"height": 450,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "deck_2", "name": "deck_2",
"caption": "Your fresh-air escape—ideal for relaxing evenings.", "caption": "Your fresh-air escape—ideal for relaxing evenings.",
"alt": "Comfortable deck area perfect for unwinding or entertaining." "alt": "Comfortable deck area perfect for unwinding or entertaining.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "exterior", "name": "exterior",
"caption": "Curb appeal perfected—your new favorite place starts here.", "caption": "Curb appeal perfected—your new favorite place starts here.",
"alt": "Attractive home exterior with inviting architecture." "alt": "Attractive home exterior with inviting architecture.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "backyard_parking", "name": "backyard_parking",
"caption": "Convenience meets privacy—your personal backyard parking spot.", "caption": "Convenience meets privacy—your personal backyard parking spot.",
"alt": "Private backyard parking area offering secure convenience." "alt": "Private backyard parking area offering secure convenience.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "office_fitness_guest_1", "name": "office_fitness_guest_1",
"caption": "Productivity zone meets fitness corner—multitasking done right.", "caption": "Productivity zone meets fitness corner—multitasking done right.",
"alt": "Dual-purpose room featuring office setup and fitness equipment." "alt": "Dual-purpose room featuring office setup and fitness equipment.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "office_fitness_guest_2", "name": "office_fitness_guest_2",
"caption": "Work, workout, or unwind—the room of endless possibilities.", "caption": "Work, workout, or unwind—the room of endless possibilities.",
"alt": "Versatile office and fitness area with modern amenities." "alt": "Versatile office and fitness area with modern amenities.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "office_fitness_guest_3", "name": "office_fitness_guest_3",
"caption": "Stay focused or get fit—you decide.", "caption": "Stay focused or get fit—you decide.",
"alt": "Functional space combining a workspace and home fitness area." "alt": "Functional space combining a workspace and home fitness area.",
"height": 200,
"width": 300
}, },
{ {
"type": "image", "type": "image",
"name": "office_fitness_guest_4", "name": "office_fitness_guest_4",
"caption": "Room for every routine—your workspace meets wellness.", "caption": "Room for every routine—your workspace meets wellness.",
"alt": "Stylish office area seamlessly integrated with fitness features." "alt": "Stylish office area seamlessly integrated with fitness features.",
"height": 200,
"width": 300
}, },
{ {
"type": "video", "type": "video",
"name": "tour", "name": "tour",
"caption": "Take the scenic route—explore your the home's highlights with a virtual walkthrough.", "caption": "Take the scenic route—explore your the home's highlights with a virtual walkthrough.",
"alt": "Video tour showcasing the property." "alt": "Video tour showcasing the property.",
"height": 534,
"width": 300
} }
] ]
</script> </script>