Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ module.exports = {
path: `${__dirname}/src`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/static`,
},
},
{
resolve: 'gatsby-plugin-manifest',
options: {
Expand Down
3 changes: 3 additions & 0 deletions gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ exports.createPages = ({ graphql, actions }) => {
component: slash(articleTemplate),
context: {
id: edge.node.id,
image: (edge.node.pageAttributes.image || '')
.replace(/^\//, '')
.replace(/^static\//, ''),
},
});
});
Expand Down
38 changes: 36 additions & 2 deletions src/Components/Featured-contributor/FeaturedContributor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,41 @@ import React from 'react';
import { motion } from 'framer-motion';
import { Calendar, GitCommitHorizontal, MapPin } from 'lucide-react';
import './featured-contributor.css';
import { Link } from 'gatsby';
import { Link, graphql, useStaticQuery } from 'gatsby';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';

const FeaturedContributor = ({ contributor, darkmode }) => {
const data = useStaticQuery(graphql`
query FeaturedContributorImagesQuery {
allFile(
filter: {
sourceInstanceName: { eq: "images" }
extension: { in: ["jpg", "jpeg", "png", "webp", "avif"] }
}
) {
nodes {
relativePath
childImageSharp {
gatsbyImageData(width: 500, placeholder: BLURRED)
}
}
}
}
`);

if (!contributor) return null;

const pageAttributes = contributor?.node?.pageAttributes;
const { name, image, location, datepublished, intro, firstcommit } =
pageAttributes || {};
const normalizeImagePath = (value) =>
(value || '').replace(/^\//, '').replace(/^static\//, '');
const normalizedPath = normalizeImagePath(image);
const matchedImageNode = data.allFile.nodes.find(
(node) => node.relativePath === normalizedPath
);
const optimizedImageData = getImage(matchedImageNode);
const fallbackImageSrc = image;
const slug = contributor?.node?.fields?.slug;
return (
<motion.div
Expand All @@ -31,7 +58,14 @@ const FeaturedContributor = ({ contributor, darkmode }) => {
transition={{ delay: 0.2, duration: 0.4 }}
whileHover={{ scale: 1.02 }}
>
<img src={image} alt={name} />
{optimizedImageData ? (
<GatsbyImage
image={optimizedImageData}
alt={name}
/>
) : (
<img src={fallbackImageSrc} alt={name} />
)}
</motion.div>

<div className='featured-content'>
Expand Down
51 changes: 45 additions & 6 deletions src/Components/Search/SearchResults.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
import React from 'react';
import './search-result.css';
import { Link } from 'gatsby';
import { Link, graphql, useStaticQuery } from 'gatsby';
import { Github, Linkedin } from 'lucide-react';
import { motion } from 'framer-motion';
import XIcon from '../XIcon.jsx';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';

function SearchResults({ results, darkmode }) {
const data = useStaticQuery(graphql`
query SearchResultsImagesQuery {
allFile(
filter: {
sourceInstanceName: { eq: "images" }
extension: { in: ["jpg", "jpeg", "png", "webp", "avif"] }
}
) {
nodes {
relativePath
childImageSharp {
gatsbyImageData(
width: 50
height: 50
placeholder: BLURRED
)
}
}
}
}
`);

const normalizeImagePath = (value) =>
(value || '').replace(/^\//, '').replace(/^static\//, '');

if (!results || results.length === 0) {
return (
<div
Expand Down Expand Up @@ -48,14 +74,27 @@ function SearchResults({ results, darkmode }) {
<div className='results-container'>
{sortedResults.map(({ item, score }) => {
if (!item) return null;
const normalizedPath = normalizeImagePath(item?.image);
const matchedImageNode = data.allFile.nodes.find(
(node) => node.relativePath === normalizedPath
);
const optimizedImageData = getImage(matchedImageNode);
return (
<Link to={item?.slug} key={item?.id}>
<div className='result-card'>
<img
src={item?.image}
alt={item?.name}
className='result-avatar'
/>
{optimizedImageData ? (
<GatsbyImage
image={optimizedImageData}
alt={item?.name}
className='result-avatar'
/>
) : (
<img
src={item?.image}
alt={item?.name}
className='result-avatar'
/>
)}
<div className='result-content'>
<div className='result-header'>
<h3 className='result-name'>
Expand Down
90 changes: 76 additions & 14 deletions src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Helmet } from 'react-helmet';
import dayjs from 'dayjs';
import axios from 'axios';
import Papa from 'papaparse';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';
import ContributorsList from '../Components/Contributor/ContributorsList.jsx';
import FeaturedContributor from '../Components/Featured-contributor/FeaturedContributor.jsx';
import Search from '../Components/Search/Search.jsx';
Expand All @@ -15,10 +16,29 @@ const IndexPage = (props) => {
const isDesktop = useMediaQuery(theme.breakpoints.up('lg'));
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const { data } = props;
const normalizeImagePath = (value) =>
(value || '').replace(/^\//, '').replace(/^static\//, '');
const imageNodes = data?.allFile?.nodes || [];
const getOptimizedImageData = (value) => {
const normalizedPath = normalizeImagePath(value);
if (!normalizedPath) return null;

const matchedNode = imageNodes.find(
(node) => node.relativePath === normalizedPath
);
return getImage(matchedNode);
};

const contributors = data.allAsciidoc.edges;
const [thankYou, setThankYou] = React.useState([]);
const [darkmode, setDarkmode] = React.useState(null);

const jenkinsLogoImageData = getOptimizedImageData('/jenkins.png');
const randomContributorImagePath = thankYou[6]?.replace(/['"]+/g, '');
const randomContributorImageData = getOptimizedImageData(
randomContributorImagePath
);

useEffect(() => {
if (typeof window !== 'undefined') {
const mediaquery =
Expand Down Expand Up @@ -124,7 +144,14 @@ const IndexPage = (props) => {
continuous integration and delivery
</Typography>
<Box sx={{ paddingTop: 8 }}>
<img src='/jenkins.png' alt='Jenkins logo' />
{jenkinsLogoImageData ? (
<GatsbyImage
image={jenkinsLogoImageData}
alt='Jenkins logo'
/>
) : (
<img src='/jenkins.png' alt='Jenkins logo' />
)}
</Box>
</Box>

Expand Down Expand Up @@ -183,18 +210,40 @@ const IndexPage = (props) => {
alignItems: 'center',
}}
>
<img
src={thankYou[6]?.replace(/['"]+/g, '')}
alt='Random contributor'
width={isDesktop ? 100 : isMobile ? 36 : 90}
height={
isDesktop ? 100 : isMobile ? '100%' : 90
}
style={{
marginTop: 'auto',
marginBottom: 'auto',
}}
/>
{randomContributorImageData ? (
<GatsbyImage
image={randomContributorImageData}
alt='Random contributor'
style={{
marginTop: 'auto',
marginBottom: 'auto',
width: isDesktop
? 100
: isMobile
? 36
: 90,
height: isDesktop
? 100
: isMobile
? '100%'
: 90,
}}
imgStyle={{ objectFit: 'cover' }}
/>
) : (
<img
src={randomContributorImagePath}
alt='Random contributor'
width={isDesktop ? 100 : isMobile ? 36 : 90}
height={
isDesktop ? 100 : isMobile ? '100%' : 90
}
style={{
marginTop: 'auto',
marginBottom: 'auto',
}}
/>
)}
</Box>
<Box
sx={{
Expand Down Expand Up @@ -282,7 +331,7 @@ const IndexPage = (props) => {
export default IndexPage;

export const pageQuery = graphql`
query {
query IndexPageQuery {
allAsciidoc(limit: 1000, sort: { fields: { publicationDate: DESC } }) {
edges {
node {
Expand Down Expand Up @@ -312,5 +361,18 @@ export const pageQuery = graphql`
}
}
}
allFile(
filter: {
sourceInstanceName: { eq: "images" }
extension: { in: ["jpg", "jpeg", "png", "webp", "avif"] }
}
) {
nodes {
relativePath
childImageSharp {
gatsbyImageData(width: 120, placeholder: BLURRED)
}
}
}
}
`;
60 changes: 48 additions & 12 deletions src/templates/contributor-details.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Github, Linkedin, Mail } from 'lucide-react';
import XIcon from '../Components/XIcon.jsx';
import { motion } from 'framer-motion';
import './contributor-details.css';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';
function ContributorDetails(props) {
const theme = useTheme();
const isDesktop = useMediaQuery(theme.breakpoints.up('lg'));
Expand All @@ -18,9 +19,12 @@ function ContributorDetails(props) {
const title =
props.data.asciidoc.pageAttributes.name +
' - Jenkins Contributor Spotlight';
const imageData = getImage(props.data.imageFile);

// State for sanitized HTML
const [sanitizedHTML, setSanitizedHTML] = useState(props.data.asciidoc.html);
const [sanitizedHTML, setSanitizedHTML] = useState(
props.data.asciidoc.html
);

// Sanitize HTML on client side only
useEffect(() => {
Expand Down Expand Up @@ -99,16 +103,38 @@ function ContributorDetails(props) {
}}
>
<Box sx={{ paddingTop: isMobile ? 5 : 8 }}>
<img
src={
'../../../' +
props.data.asciidoc.pageAttributes.image
}
alt='Contributor avatar'
width={isDesktop ? 350 : isTablet ? 300 : 250}
height={isDesktop ? 350 : isTablet ? 300 : 250}
style={{ objectFit: 'cover', borderRadius: '50%' }}
/>
<Box
sx={{
width: isDesktop ? 350 : isTablet ? 300 : 250,
height: isDesktop ? 350 : isTablet ? 300 : 250,
borderRadius: '50%',
overflow: 'hidden',
}}
>
{imageData ? (
<GatsbyImage
image={imageData}
alt='Contributor avatar'
style={{ width: '100%', height: '100%' }}
imgStyle={{
objectFit: 'cover',
}}
/>
) : (
<img
src={
'../../../' +
props.data.asciidoc.pageAttributes.image
}
alt='Contributor avatar'
width='100%'
height='100%'
style={{
objectFit: 'cover',
}}
/>
)}
</Box>
</Box>
</Box>
<Box
Expand Down Expand Up @@ -270,7 +296,7 @@ function ContributorDetails(props) {
export default ContributorDetails;

export const pageQuery = graphql`
query ($id: String!) {
query ($id: String!, $image: String!) {
asciidoc(id: { eq: $id }) {
html
document {
Expand All @@ -293,5 +319,15 @@ export const pageQuery = graphql`
intro
}
}
imageFile: file(relativePath: { eq: $image }) {
childImageSharp {
gatsbyImageData(
width: 350
height: 350
placeholder: BLURRED
layout: FIXED
)
}
}
}
`;