Optimizations

This commit is contained in:
Schmelczer András 2019-12-29 17:13:20 +01:00
parent 10015a4ebe
commit 3febd3fca8
24 changed files with 215 additions and 99 deletions

View file

@ -2,18 +2,22 @@
<dictionary name="Schme"> <dictionary name="Schme">
<words> <words>
<w>contenthash</w> <w>contenthash</w>
<w>cybersecurity</w>
<w>ffffff</w> <w>ffffff</w>
<w>gifsicle</w> <w>gifsicle</w>
<w>imagemin</w> <w>imagemin</w>
<w>jpegtran</w> <w>jpegtran</w>
<w>lato</w> <w>lato</w>
<w>markwon</w>
<w>mozjpeg</w> <w>mozjpeg</w>
<w>noquotes</w> <w>noquotes</w>
<w>opacify</w> <w>opacify</w>
<w>optipng</w> <w>optipng</w>
<w>pngquant</w> <w>pngquant</w>
<w>raleway</w> <w>raleway</w>
<w>screenshot</w>
<w>transparentize</w> <w>transparentize</w>
<w>webm</w>
<w>webp</w> <w>webp</w>
</words> </words>
</dictionary> </dictionary>

28
.idea/workspace.xml generated
View file

@ -2,28 +2,30 @@
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="8edc47ab-1265-4111-9771-536b24cc9310" name="Default Changelist" comment=""> <list default="true" id="8edc47ab-1265-4111-9771-536b24cc9310" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/src/static/media/forex.mp4" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/static/media/forex.webm" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/static/media/led.mp4" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/static/media/led.webm" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/dictionaries/Schme.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dictionaries/Schme.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/dictionaries/Schme.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dictionaries/Schme.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/custom.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/custom.d.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" /> <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.html" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/framework/helper.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/framework/helper.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/about/about.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/model/content.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/model/content.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/background/background.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/background.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/model/misc.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/model/misc.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/background/background.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/background.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/model/portfolio.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/model/portfolio.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/background/blob.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/background/blob.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/about/about.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.html.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/about/about.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/about/about.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/content/content.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/content/content.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/content/content.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/content/content.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/content/content.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/content/content.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/footer/footer.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.html.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/footer/footer.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.html.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/footer/footer.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/footer/footer.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/footer/footer.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/image-viewer/image-viewer.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/index.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/index.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.html.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.html.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.html.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline-element/timeline-element.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/portfolio.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/portfolio.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/page/timeline/timeline.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/page/timeline/timeline.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/static/media/led720.mp4" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/style/a.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/a.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/style/fonts.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/fonts.scss" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/style/fonts.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/fonts.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/style/mixins.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/mixins.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/style/vars.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/style/vars.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/styles.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/styles.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/webpack.config.js" beforeDir="false" afterPath="$PROJECT_DIR$/webpack.config.js" afterDir="false" /> <change beforePath="$PROJECT_DIR$/webpack.config.js" beforeDir="false" afterPath="$PROJECT_DIR$/webpack.config.js" afterDir="false" />
</list> </list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
@ -120,7 +122,7 @@
<workItem from="1577348003642" duration="4876000" /> <workItem from="1577348003642" duration="4876000" />
<workItem from="1577451432189" duration="11000" /> <workItem from="1577451432189" duration="11000" />
<workItem from="1577469180612" duration="18000" /> <workItem from="1577469180612" duration="18000" />
<workItem from="1577526744211" duration="38046000" /> <workItem from="1577526744211" duration="44201000" />
</task> </task>
<servers /> <servers />
</component> </component>

27
custom.d.ts vendored
View file

@ -1,34 +1,47 @@
declare module "*.svg" { declare module "*.svg" {
const content: string; import { url } from "src/model/misc";
const content: url;
export default content; export default content;
} }
declare module "*.png" { declare module "*.png" {
const content: string; import { ResponsiveImage } from "src/model/misc";
const content: ResponsiveImage;
export default content; export default content;
} }
declare module "*.jpg" { declare module "*.jpg" {
const content: string; import { ResponsiveImage } from "src/model/misc";
const content: ResponsiveImage;
export default content; export default content;
} }
declare module "*.jpeg" { declare module "*.jpeg" {
const content: string; import { ResponsiveImage } from "src/model/misc";
const content: ResponsiveImage;
export default content; export default content;
} }
declare module "*.gif" { declare module "*.gif" {
const content: string; import { url } from "src/model/misc";
const content: url;
export default content; export default content;
} }
declare module "*.mp4" { declare module "*.mp4" {
const content: string; import { url } from "src/model/misc";
const content: url;
export default content;
}
declare module "*.webm" {
import { url } from "src/model/misc";
const content: url;
export default content; export default content;
} }
declare module "*.pdf" { declare module "*.pdf" {
const content: string; import { url } from "src/model/misc";
const content: url;
export default content; export default content;
} }

View file

@ -4,7 +4,6 @@
"description": "An easily configurable portfolio.", "description": "An easily configurable portfolio.",
"private": true, "private": true,
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --mode development", "start": "webpack-dev-server --mode development",
"build": "webpack" "build": "webpack"
}, },
@ -35,7 +34,9 @@
"optimize-css-assets-webpack-plugin": "^5.0.3", "optimize-css-assets-webpack-plugin": "^5.0.3",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"resolve-url-loader": "^3.1.1", "resolve-url-loader": "^3.1.1",
"responsive-loader": "^1.2.0",
"sass-loader": "^8.0.0", "sass-loader": "^8.0.0",
"sharp": "^0.23.4",
"style-loader": "^1.0.2", "style-loader": "^1.0.2",
"svg-url-loader": "^3.0.3", "svg-url-loader": "^3.0.3",
"terser-webpack-plugin": "^2.3.1", "terser-webpack-plugin": "^2.3.1",

View file

@ -1,4 +1,4 @@
import { html } from "../model/misc"; import { html, ResponsiveImage } from "../model/misc";
export const createElement = (from: html): HTMLElement => { export const createElement = (from: html): HTMLElement => {
const element: HTMLElement = document.createElement("div"); const element: HTMLElement = document.createElement("div");
@ -88,3 +88,6 @@ export const range = ({
} }
}; };
}; };
export const last = <T>(list: Array<T>): T =>
list.length > 0 ? list[list.length - 1] : undefined;

View file

@ -1,4 +1,4 @@
import { url } from "./misc"; import { ResponsiveImage, url } from "./misc";
interface Anchor { interface Anchor {
type: "a"; type: "a";
@ -6,11 +6,19 @@ interface Anchor {
text: string; text: string;
} }
interface Video { export type Video = {
type: "video"; type: "video";
src: url; mp4: url;
} webm: url;
options?: string;
};
export type TypedContent = Anchor | Video; export type Image = {
type: "img";
alt: string;
image: ResponsiveImage;
};
export type TypedContent = Anchor | Video | Image;
export type Content = Array<String | TypedContent>; export type Content = Array<String | TypedContent>;

View file

@ -1,2 +1,16 @@
export type url = string; export type url = string;
export type html = string; export type html = string;
export type ResponsiveImage = {
srcSet: string;
src: url;
placeholder: string;
width: number;
height: number;
images: Array<{
path: url;
width: number;
height: number;
}>;
};

View file

@ -1,5 +1,5 @@
import { url } from "./misc"; import { url } from "./misc";
import { Content } from "./content"; import { Content, Image, Video } from "./content";
export interface Portfolio { export interface Portfolio {
config: Config; config: Config;
@ -11,19 +11,18 @@ export interface Portfolio {
export interface Config { export interface Config {
showMore: string; showMore: string;
showLess: string; showLess: string;
aPictureOf: string;
} }
export interface Header { export interface Header {
name: string; name: string;
picture: url; picture: Image;
about: Content; about: Content;
} }
export interface TimelineElement { export interface TimelineElement {
title: string; title: string;
date: string; date: string;
picture: url; figure: Image | Video;
description: string; description: string;
more?: Content; more?: Content;
link?: url; link?: url;
@ -34,8 +33,6 @@ export interface Footer {
email: string; email: string;
cv: url; cv: url;
cvName: string; cvName: string;
githubLinkName: string;
githubLink: url;
lastEditName: string; lastEditName: string;
lastEdit: Date; lastEdit: Date;
} }

View file

@ -1,13 +1,12 @@
import { Header } from "../../model/portfolio"; import { Header } from "../../model/portfolio";
import { html } from "../../model/misc"; import { html } from "../../model/misc";
import { PageContent } from "../content/content";
import "./about.scss"; import "./about.scss";
export const generate = ( export const generate = ({ name, picture }: Header): html => `
{ name, picture, about }: Header,
aPictureOf: string
): html => `
<section id="about"> <section id="about">
<img alt="${aPictureOf} ${name}" src="${picture}"/> ${PageContent.parseTypedContent(picture, true)}
<div class="placeholder"></div> <div class="placeholder"></div>
<h1>${name}</h1> <h1>${name}</h1>
</section>`; </section>`;

View file

@ -6,8 +6,8 @@ import { generate } from "./about.html";
import { createElement } from "../../framework/helper"; import { createElement } from "../../framework/helper";
export class PageHeader extends PageElement { export class PageHeader extends PageElement {
public constructor(header: Header, aPictureOf: string) { public constructor(header: Header) {
const root = createElement(generate(header, aPictureOf)); const root = createElement(generate(header));
const content = new PageContent(header.about); const content = new PageContent(header.about);
super([content]); super([content]);

View file

@ -11,3 +11,15 @@
text-align: left; text-align: left;
} }
} }
.image-container {
font-size: 0;
box-shadow: inset $shadow1, inset $shadow2;
pointer-events: none;
img {
pointer-events: all;
cursor: pointer;
position: relative;
z-index: -2;
}
}

View file

@ -1,13 +1,44 @@
import { Content, TypedContent } from "../../model/content"; import { Content, TypedContent } from "../../model/content";
import "./content.scss"; import "./content.scss";
import { PageElement } from "../../framework/page-element"; import { PageElement } from "../../framework/page-element";
import { createElement } from "../../framework/helper"; import { createElement, last } from "../../framework/helper";
import { html } from "../../model/misc";
export class PageContent extends PageElement { export class PageContent extends PageElement {
private static isTyped(content): content is TypedContent { private static isTyped(content): content is TypedContent {
return (content as TypedContent).type !== undefined; return (content as TypedContent).type !== undefined;
} }
public static parseTypedContent(
element: TypedContent,
disableInnerShadow?: boolean
): html {
if (element.type === "a") {
return `<a href="${element.href}" rel="noreferrer" target="_blank"> ${element.text} </a>`;
}
if (element.type === "video") {
return `
<video ${element.options}>
<source src="${element.webm}" type="video/webm"/>
<source src="${element.mp4}" type="video/mp4"/>
</video>
`;
}
if (element.type === "img") {
return `
${!disableInnerShadow ? `<div class="image-container">` : ""}
<img
srcset="${element.image.srcSet}"
src="${last(element.image.images).path}"
alt="${element.alt}"
/>
${!disableInnerShadow ? `</div>` : ""}
`;
}
throw new Error("Unhandled type.");
}
public constructor(content: Content) { public constructor(content: Content) {
super(); super();
@ -15,18 +46,11 @@ export class PageContent extends PageElement {
createElement(` createElement(`
<div class="content"> <div class="content">
${content ${content
.map(element => { .map(element =>
if (PageContent.isTyped(element)) { PageContent.isTyped(element)
if (element.type === "a") { ? PageContent.parseTypedContent(element)
return `<a href="${element.href}" rel="noreferrer" target="_blank"> ${element.text} </a>`; : `<p>${element}</p>`
} )
if (element.type === "video") {
return `<video controls><source src="${element.src}" /></video>`;
}
throw new Error("Unhandled type.");
}
return `<p>${element}</p>`;
})
.join("\n")} .join("\n")}
</div> </div>
`) `)

View file

@ -1,9 +1,9 @@
import { Footer } from "../../model/portfolio"; import { Footer } from "../../model/portfolio";
import { html, url } from "../../model/misc"; import { html } from "../../model/misc";
import emailIcon from "../../static/icons/at.svg";
import cvIcon from "../../static/icons/cv.svg";
import "./footer.scss"; import "./footer.scss";
import cvIcon from "../../static/icons/cv.svg";
import emailIcon from "../../static/icons/at.svg";
export const generate = ({ export const generate = ({
title, title,
@ -11,9 +11,7 @@ export const generate = ({
cv, cv,
cvName, cvName,
lastEditName, lastEditName,
lastEdit, lastEdit
githubLinkName,
githubLink
}: Footer): html => ` }: Footer): html => `
<footer id="page-footer"> <footer id="page-footer">
<h2>${title}</h2> <h2>${title}</h2>

View file

@ -43,7 +43,7 @@ footer#page-footer {
h6 { h6 {
@include insignificant-font(); @include insignificant-font();
opacity: 0.4; opacity: 0.6;
} }
} }
} }

View file

@ -7,7 +7,7 @@ import { PageImageViewer } from "./image-viewer/image-viewer";
import { Page } from "../framework/page"; import { Page } from "../framework/page";
export const create = ({ config, header, timeline, footer }: Portfolio) => { export const create = ({ config, header, timeline, footer }: Portfolio) => {
const pageHeader = new PageHeader(header, config.aPictureOf); const pageHeader = new PageHeader(header);
const pageFooter = new PageFooter(footer); const pageFooter = new PageFooter(footer);
const bg = new PageBackground(pageHeader, pageFooter); const bg = new PageBackground(pageHeader, pageFooter);

View file

@ -1,9 +1,11 @@
import { TimelineElement } from "../../../model/portfolio"; import { TimelineElement } from "../../../model/portfolio";
import { html } from "../../../model/misc"; import { html } from "../../../model/misc";
import { PageContent } from "../../content/content";
import "./timeline-element.scss"; import "./timeline-element.scss";
export const generate = ( export const generate = (
{ date, title, picture, description, more, link }: TimelineElement, { date, title, figure, description, more, link }: TimelineElement,
showMore: string, showMore: string,
showLess: string showLess: string
): html => ` ): html => `
@ -13,9 +15,7 @@ export const generate = (
</div> </div>
<div class="card"> <div class="card">
<h2>${title}</h2> <h2>${title}</h2>
<div class="image-container"> ${PageContent.parseTypedContent(figure)}
<img src="${picture}" alt="${picture}"/>
</div>
<p class="description">${description}</p> <p class="description">${description}</p>
${ ${
more more

View file

@ -75,18 +75,6 @@
@include sub-title-font(); @include sub-title-font();
} }
.image-container {
font-size: 0;
box-shadow: inset $shadow1, inset $shadow2;
pointer-events: none;
img {
pointer-events: all;
cursor: pointer;
position: relative;
z-index: -2;
}
}
.description { .description {
font-style: italic; font-style: italic;
} }

View file

@ -1,7 +1,8 @@
import { Portfolio } from "./model/portfolio"; import { Portfolio } from "./model/portfolio";
import me from "./static/media/me.jpg"; import me from "./static/media/me.jpg";
import forex from "./static/media/forex.gif"; import forexMP4 from "./static/media/forex.mp4";
import forexWEBM from "./static/media/forex.webm";
import myNotes from "./static/media/my-notes.jpg"; import myNotes from "./static/media/my-notes.jpg";
import processSimulator from "./static/media/process-simulator.jpg"; import processSimulator from "./static/media/process-simulator.jpg";
import processSimulatorInput from "./static/media/process-simulator-input.jpg"; import processSimulatorInput from "./static/media/process-simulator-input.jpg";
@ -11,17 +12,21 @@ import platform from "./static/media/platform.png";
import photos from "./static/media/photos.jpg"; import photos from "./static/media/photos.jpg";
import led from "./static/media/led.jpg"; import led from "./static/media/led.jpg";
import cv from "./static/cv/andras_schmelczer_cv_2020_01.pdf"; import cv from "./static/cv/andras_schmelczer_cv_2020_01.pdf";
import ledVideo from "./static/media/led720.mp4"; import ledMP4 from "./static/media/led.mp4";
import ledWEBM from "./static/media/led.webm";
export const portfolio: Portfolio = { export const portfolio: Portfolio = {
config: { config: {
showMore: `Show details`, showMore: `Show details`,
showLess: `Show less`, showLess: `Show less`
aPictureOf: `a picture of`
}, },
header: { header: {
name: `András Schmelczer`, name: `András Schmelczer`,
picture: me, picture: {
type: `img`,
image: me,
alt: `a picture of me`
},
about: [ about: [
`I have always been fascinated by the engineering feats that surround us. `I have always been fascinated by the engineering feats that surround us.
When I realized that someday I might be able to contribute to these achievements, When I realized that someday I might be able to contribute to these achievements,
@ -34,7 +39,12 @@ export const portfolio: Portfolio = {
{ {
title: `Predicting foreign exchange rates`, title: `Predicting foreign exchange rates`,
date: `2019 Autumn`, date: `2019 Autumn`,
picture: forex, figure: {
type: `video`,
options: `autoplay loop muted playsinline`,
webm: forexWEBM,
mp4: forexMP4
},
description: `From the animation we can see that my algorithm does a somewhat acceptable job at description: `From the animation we can see that my algorithm does a somewhat acceptable job at
predicting (blue graph) the EUR/USD rates (green graph).`, predicting (blue graph) the EUR/USD rates (green graph).`,
more: [ more: [
@ -49,7 +59,11 @@ export const portfolio: Portfolio = {
{ {
date: `2019 November`, date: `2019 November`,
title: `My Notes`, title: `My Notes`,
picture: myNotes, figure: {
type: `img`,
image: myNotes,
alt: `two screenshots of the application`
},
description: `A minimalist note organizer and editor powered by Markwon.`, description: `A minimalist note organizer and editor powered by Markwon.`,
more: [ more: [
{ {
@ -65,7 +79,11 @@ export const portfolio: Portfolio = {
{ {
date: `2018 October - November`, date: `2018 October - November`,
title: `Simulating the cooling system of a nuclear facility`, title: `Simulating the cooling system of a nuclear facility`,
picture: processSimulator, figure: {
type: `img`,
image: processSimulator,
alt: `a screenshot of the simulator`
},
description: `Dynamically calculating the temperatures and flow velocities description: `Dynamically calculating the temperatures and flow velocities
in a fluid based cooling system based on a simple model.`, in a fluid based cooling system based on a simple model.`,
more: [ more: [
@ -79,7 +97,11 @@ export const portfolio: Portfolio = {
{ {
date: `2018 October - November`, date: `2018 October - November`,
title: `Graph editing application`, title: `Graph editing application`,
picture: processSimulatorInput, figure: {
type: `img`,
image: processSimulatorInput,
alt: `a picture of the simulator's UI`
},
description: `An intuitive editor to create and edit input files for the nuclear facility simulator.`, description: `An intuitive editor to create and edit input files for the nuclear facility simulator.`,
more: [ more: [
`Nodes can be moved with drag&drop gestures. Editing the parameters of elements `Nodes can be moved with drag&drop gestures. Editing the parameters of elements
@ -91,7 +113,11 @@ export const portfolio: Portfolio = {
{ {
date: `2018 July - August`, date: `2018 July - August`,
title: `City simulation`, title: `City simulation`,
picture: citySimulation, figure: {
type: `img`,
image: citySimulation,
alt: `a picture of a low-poly city`
},
description: `Simulating a city where car crashes are more frequent than usual.`, description: `Simulating a city where car crashes are more frequent than usual.`,
more: [ more: [
`Through a REST API the state of the traffic lights can be changed. `Through a REST API the state of the traffic lights can be changed.
@ -109,7 +135,11 @@ export const portfolio: Portfolio = {
{ {
date: `2018 June`, date: `2018 June`,
title: `Photo color grader`, title: `Photo color grader`,
picture: color, figure: {
type: `img`,
image: color,
alt: `a picture of the app`
},
description: `An innovative (at least I thought so) color grader web application.`, description: `An innovative (at least I thought so) color grader web application.`,
more: [ more: [
`The most noteworthy feature of this application is the color selector UI. `The most noteworthy feature of this application is the color selector UI.
@ -126,7 +156,11 @@ export const portfolio: Portfolio = {
date: `2017 autumn`, date: `2017 autumn`,
title: `Platform game`, title: `Platform game`,
picture: platform, figure: {
type: `img`,
image: platform,
alt: `a picture of the app`
},
description: `A 3D game written in C with the help of SDL 1.2 (I haven't heard of GPU programming at the time).`, description: `A 3D game written in C with the help of SDL 1.2 (I haven't heard of GPU programming at the time).`,
more: [ more: [
`The maps are randomly generated and fully destroyable. `The maps are randomly generated and fully destroyable.
@ -137,14 +171,22 @@ export const portfolio: Portfolio = {
{ {
date: `2016 summer`, date: `2016 summer`,
title: `Photos`, title: `Photos`,
picture: photos, figure: {
type: `img`,
image: photos,
alt: `a picture of the website`
},
description: `A simple web page where you can view my photos.`, description: `A simple web page where you can view my photos.`,
link: `schmelczer.dev/photos` link: `schmelczer.dev/photos`
}, },
{ {
date: `2016 spring`, date: `2016 spring`,
title: `Lights synchronised to music`, title: `Lights synchronised to music`,
picture: led, figure: {
type: `img`,
image: led,
alt: `a picture from the video`
},
description: `A full stack application with a built-in description: `A full stack application with a built-in
music player which music controls the color of some RGB LED strips.`, music player which music controls the color of some RGB LED strips.`,
more: [ more: [
@ -154,7 +196,7 @@ export const portfolio: Portfolio = {
A quite simple frontend for accessing the music player and changing A quite simple frontend for accessing the music player and changing
the settings also got built using vanilla web development technologies.`, the settings also got built using vanilla web development technologies.`,
`Below is a video showing the system in work.`, `Below is a video showing the system in work.`,
{ type: `video`, src: ledVideo } { type: `video`, mp4: ledMP4, webm: ledWEBM, options: "controls" }
] ]
} }
], ],
@ -163,9 +205,7 @@ export const portfolio: Portfolio = {
cv, cv,
email: `andras@schmelczer.dev`, email: `andras@schmelczer.dev`,
cvName: `Curriculum vitae`, cvName: `Curriculum vitae`,
githubLinkName: `view source`,
githubLink: `https://github.com/schmelczerandras/timeline`,
lastEditName: `Last modified on `, lastEditName: `Last modified on `,
lastEdit: new Date(2019, 11, 27) // months are 0 indexed lastEdit: new Date(2019, 11, 29) // months are 0 indexed
} }
}; };

BIN
src/static/media/forex.mp4 Normal file

Binary file not shown.

BIN
src/static/media/forex.webm Normal file

Binary file not shown.

BIN
src/static/media/led.webm Normal file

Binary file not shown.

View file

@ -1,10 +1,12 @@
// https://google-webfonts-helper.herokuapp.com/fonts/montserrat?subsets=latin // https://google-webfonts-helper.herokuapp.com/fonts/montserrat?subsets=latin
// add font-display: swap;
/* lato-regular - latin */ /* lato-regular - latin */
@font-face { @font-face {
font-family: "Lato"; font-family: "Lato";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-display: swap;
src: url("../static/fonts/lato/lato-v16-latin-regular.eot"); /* IE9 Compat Modes */ src: url("../static/fonts/lato/lato-v16-latin-regular.eot"); /* IE9 Compat Modes */
src: local("Lato Regular"), local("Lato-Regular"), src: local("Lato Regular"), local("Lato-Regular"),
url("../static/fonts/lato/lato-v16-latin-regular.eot?#iefix") url("../static/fonts/lato/lato-v16-latin-regular.eot?#iefix")
@ -23,6 +25,7 @@
font-family: "Lato"; font-family: "Lato";
font-style: italic; font-style: italic;
font-weight: 400; font-weight: 400;
font-display: swap;
src: url("../static/fonts/lato/lato-v16-latin-italic.eot"); /* IE9 Compat Modes */ src: url("../static/fonts/lato/lato-v16-latin-italic.eot"); /* IE9 Compat Modes */
src: local("Lato Italic"), local("Lato-Italic"), src: local("Lato Italic"), local("Lato-Italic"),
url("../static/fonts/lato/lato-v16-latin-italic.eot?#iefix") url("../static/fonts/lato/lato-v16-latin-italic.eot?#iefix")
@ -42,6 +45,7 @@
font-family: "Montserrat"; font-family: "Montserrat";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-display: swap;
src: url("../static/fonts/montserrat/montserrat-v14-latin-regular.eot"); /* IE9 Compat Modes */ src: url("../static/fonts/montserrat/montserrat-v14-latin-regular.eot"); /* IE9 Compat Modes */
src: local("Montserrat Regular"), local("Montserrat-Regular"), src: local("Montserrat Regular"), local("Montserrat-Regular"),
url("../static/fonts/montserrat/montserrat-v14-latin-regular.eot?#iefix") url("../static/fonts/montserrat/montserrat-v14-latin-regular.eot?#iefix")

View file

@ -35,7 +35,17 @@ module.exports = {
module: { module: {
rules: [ rules: [
{ {
test: /\.(png|jpe?g|gif|mp4)$/i, test: /\.(jpe?g|png)$/i,
loader: "responsive-loader",
options: {
adapter: require("responsive-loader/sharp"),
outputPath: "static/",
sizes: [300, 600, 1200, 2000],
placeholder: false
}
},
{
test: /\.(webm|mp4)$/i,
use: [ use: [
{ {
loader: "file-loader", loader: "file-loader",
@ -49,7 +59,7 @@ module.exports = {
disable: !isProduction, disable: !isProduction,
mozjpeg: { mozjpeg: {
progressive: true, progressive: true,
quality: 65 quality: 45
}, },
optipng: { optipng: {
enabled: true enabled: true
@ -61,9 +71,8 @@ module.exports = {
gifsicle: { gifsicle: {
interlaced: false interlaced: false
}, },
// the webp option will enable WEBP
webp: { webp: {
quality: 75 quality: 65
} }
} }
} }