add high-dpi and webp images
|
@ -4,7 +4,7 @@
|
||||||
import Picker from "./Picker";
|
import Picker from "./Picker";
|
||||||
|
|
||||||
export let area;
|
export let area;
|
||||||
export let img;
|
export let images;
|
||||||
export let steps;
|
export let steps;
|
||||||
export let location;
|
export let location;
|
||||||
</script>
|
</script>
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
</title>
|
</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<Header {area} {img}>
|
<Header {area} {images}>
|
||||||
<slot />
|
<slot />
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,26 @@
|
||||||
import Area from "./Area";
|
import Area from "./Area";
|
||||||
import Landing from "./Landing";
|
import Landing from "./Landing";
|
||||||
|
|
||||||
import imgScreens from "./img/Screens.png";
|
// this is a little verbose, but dynamic imports aren't SSRed
|
||||||
import imgHeads from "./img/Heads.png";
|
// if we do this in more places, we could write a webpack loader
|
||||||
import imgIntroduction from "./img/Introduction.png";
|
import imgScreensPng from "./img/Screens.png";
|
||||||
import imgFoundation from "./img/Foundation.png";
|
import imgScreensWebp from "./img/Screens.webp";
|
||||||
import imgDots from "./img/Dots.png";
|
import imgScreens2xWebp from "./img/Screens@2x.webp";
|
||||||
import imgHands from "./img/Hands.png";
|
import imgHeadsPng from "./img/Heads.png";
|
||||||
|
import imgHeadsWebp from "./img/Heads.webp";
|
||||||
|
import imgHeads2xWebp from "./img/Heads@2x.webp";
|
||||||
|
import imgIntroductionPng from "./img/Introduction.png";
|
||||||
|
import imgIntroductionWebp from "./img/Introduction.webp";
|
||||||
|
import imgIntroduction2xWebp from "./img/Introduction@2x.webp";
|
||||||
|
import imgFoundationPng from "./img/Foundation.png";
|
||||||
|
import imgFoundationWebp from "./img/Foundation.webp";
|
||||||
|
import imgFoundation2xWebp from "./img/Foundation@2x.webp";
|
||||||
|
import imgDotsPng from "./img/Dots.png";
|
||||||
|
import imgDotsWebp from "./img/Dots.webp";
|
||||||
|
import imgDots2xWebp from "./img/Dots@2x.webp";
|
||||||
|
import imgHandsPng from "./img/Hands.png";
|
||||||
|
import imgHandsWebp from "./img/Hands.webp";
|
||||||
|
import imgHands2xWebp from "./img/Hands@2x.webp";
|
||||||
|
|
||||||
export let url = "";
|
export let url = "";
|
||||||
export let locale = "";
|
export let locale = "";
|
||||||
|
@ -18,7 +32,7 @@
|
||||||
<Route path="forum" let:location>
|
<Route path="forum" let:location>
|
||||||
<Area
|
<Area
|
||||||
area={gettext("Support forum")}
|
area={gettext("Support forum")}
|
||||||
img={imgHeads}
|
images={[imgHeadsPng, imgHeadsWebp, imgHeads2xWebp]}
|
||||||
{location}
|
{location}
|
||||||
steps={{
|
steps={{
|
||||||
steps: [
|
steps: [
|
||||||
|
@ -48,7 +62,11 @@
|
||||||
<Route path="kb" let:location>
|
<Route path="kb" let:location>
|
||||||
<Area
|
<Area
|
||||||
area={gettext("Support articles")}
|
area={gettext("Support articles")}
|
||||||
img={imgIntroduction}
|
images={[
|
||||||
|
imgIntroductionPng,
|
||||||
|
imgIntroductionWebp,
|
||||||
|
imgIntroduction2xWebp,
|
||||||
|
]}
|
||||||
{location}
|
{location}
|
||||||
steps={{
|
steps={{
|
||||||
steps: [
|
steps: [
|
||||||
|
@ -78,7 +96,7 @@
|
||||||
<Route path="l10n" let:location>
|
<Route path="l10n" let:location>
|
||||||
<Area
|
<Area
|
||||||
area={gettext("Localization")}
|
area={gettext("Localization")}
|
||||||
img={imgFoundation}
|
images={[imgFoundationPng, imgFoundationWebp, imgFoundation2xWebp]}
|
||||||
{location}
|
{location}
|
||||||
steps={{
|
steps={{
|
||||||
steps: [
|
steps: [
|
||||||
|
@ -110,7 +128,7 @@
|
||||||
<Route path="social" let:location>
|
<Route path="social" let:location>
|
||||||
<Area
|
<Area
|
||||||
area={gettext("Social support")}
|
area={gettext("Social support")}
|
||||||
img={imgDots}
|
images={[imgDotsPng, imgDotsWebp, imgDots2xWebp]}
|
||||||
{location}
|
{location}
|
||||||
steps={{
|
steps={{
|
||||||
steps: [
|
steps: [
|
||||||
|
@ -140,7 +158,7 @@
|
||||||
<Route path="play-store" let:location>
|
<Route path="play-store" let:location>
|
||||||
<Area
|
<Area
|
||||||
area={gettext("Play Store support")}
|
area={gettext("Play Store support")}
|
||||||
img={imgHands}
|
images={[imgHandsPng, imgHandsWebp, imgHands2xWebp]}
|
||||||
{location}
|
{location}
|
||||||
steps={{
|
steps={{
|
||||||
steps: [
|
steps: [
|
||||||
|
@ -172,7 +190,7 @@
|
||||||
</Area>
|
</Area>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/">
|
<Route path="/">
|
||||||
<Landing img={imgScreens} />
|
<Landing images={[imgScreensPng, imgScreensWebp, imgScreens2xWebp]} />
|
||||||
</Route>
|
</Route>
|
||||||
</Router>
|
</Router>
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import { Link } from "svelte-navigator";
|
import { Link } from "svelte-navigator";
|
||||||
|
import { srcset } from "../utils";
|
||||||
|
|
||||||
export let area = "";
|
export let area = "";
|
||||||
export let img;
|
export let images;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
|
@ -25,7 +26,13 @@
|
||||||
|
|
||||||
<div class="hero">
|
<div class="hero">
|
||||||
<div class="text"><slot /></div>
|
<div class="text"><slot /></div>
|
||||||
<img src={img} alt="" />
|
<picture>
|
||||||
|
<source
|
||||||
|
srcset={srcset(images[1], images[2])}
|
||||||
|
type="image/webp"
|
||||||
|
/>
|
||||||
|
<img srcset={srcset(images[0])} src={images[0]} alt="" />
|
||||||
|
</picture>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
@ -54,6 +61,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.text,
|
.text,
|
||||||
|
picture,
|
||||||
img {
|
img {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
<script>
|
<script>
|
||||||
import Header from "./Header";
|
import Header from "./Header";
|
||||||
import Picker from "./Picker";
|
import Picker from "./Picker";
|
||||||
import aboutImg from "./img/About Us.png";
|
import { srcset } from "../utils"
|
||||||
|
|
||||||
export let img;
|
import imgAboutPng from "./img/About Us.png";
|
||||||
|
import imgAboutWebp from "./img/About Us.webp";
|
||||||
|
import imgAbout2xWebp from "./img/About Us@2x.webp";
|
||||||
|
|
||||||
|
export let images;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>{gettext("Contribute")} | {gettext("Mozilla Support")}</title>
|
<title>{gettext("Contribute")} | {gettext("Mozilla Support")}</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<Header {img}>
|
<Header {images}>
|
||||||
<h1>{gettext("Save the world from the comfort of your couch")}</h1>
|
<h1>{gettext("Save the world from the comfort of your couch")}</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -39,10 +43,17 @@
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<img
|
<picture>
|
||||||
src={aboutImg}
|
<source
|
||||||
alt={gettext("Photo of Mozilla staff and volunteers.")}
|
srcset={srcset(imgAboutWebp, imgAbout2xWebp)}
|
||||||
/>
|
type="image/webp"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
srcset={srcset(imgAboutPng)}
|
||||||
|
src={imgAboutPng}
|
||||||
|
alt={gettext("Photo of Mozilla staff and volunteers.")}
|
||||||
|
/>
|
||||||
|
</picture>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -59,6 +70,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
img,
|
img,
|
||||||
|
picture,
|
||||||
.text {
|
.text {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
После Ширина: | Высота: | Размер: 51 KiB |
После Ширина: | Высота: | Размер: 156 KiB |
После Ширина: | Высота: | Размер: 49 KiB |
После Ширина: | Высота: | Размер: 152 KiB |
После Ширина: | Высота: | Размер: 51 KiB |
После Ширина: | Высота: | Размер: 166 KiB |
После Ширина: | Высота: | Размер: 39 KiB |
После Ширина: | Высота: | Размер: 120 KiB |
После Ширина: | Высота: | Размер: 55 KiB |
После Ширина: | Высота: | Размер: 182 KiB |
После Ширина: | Высота: | Размер: 40 KiB |
После Ширина: | Высота: | Размер: 122 KiB |
После Ширина: | Высота: | Размер: 62 KiB |
После Ширина: | Высота: | Размер: 202 KiB |
После Ширина: | Высота: | Размер: 45 KiB |
После Ширина: | Высота: | Размер: 149 KiB |
После Ширина: | Высота: | Размер: 56 KiB |
После Ширина: | Высота: | Размер: 186 KiB |
После Ширина: | Высота: | Размер: 63 KiB |
После Ширина: | Высота: | Размер: 198 KiB |
|
@ -0,0 +1,11 @@
|
||||||
|
const staticJinjaTag = "{{ STATIC_URL_WEBPACK }}";
|
||||||
|
|
||||||
|
export function srcset(...sources) {
|
||||||
|
return sources
|
||||||
|
.map(
|
||||||
|
(source, index) =>
|
||||||
|
encodeURI(source).replace(encodeURI(staticJinjaTag), staticJinjaTag) +
|
||||||
|
` ${index + 1}x`
|
||||||
|
)
|
||||||
|
.join(", ");
|
||||||
|
}
|
|
@ -72,7 +72,7 @@ module.exports = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(svg|png|gif|woff2?)$/,
|
test: /\.(svg|png|webp|gif|woff2?)$/,
|
||||||
type: "asset/resource",
|
type: "asset/resource",
|
||||||
},
|
},
|
||||||
// we copy these libraries from external sources, so define their exports here,
|
// we copy these libraries from external sources, so define their exports here,
|
||||||
|
|
|
@ -47,7 +47,7 @@ module.exports = mergeWithRules({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(svg|png|gif|woff2?)$/,
|
test: /\.(svg|png|webp|gif|woff2?)$/,
|
||||||
type: "asset/source",
|
type: "asset/source",
|
||||||
use: {
|
use: {
|
||||||
loader: path.resolve("./webpack/ssr-asset-loader"),
|
loader: path.resolve("./webpack/ssr-asset-loader"),
|
||||||
|
|