Changeset View
Standalone View
components/responsive-image/responsive-image.html.js
- This file was added.
const Component = require('../component.class'); | |||||
/* | |||||
image_path: string | |||||
out_path: string, output path | |||||
resolutions: array of sizes ie. [200, 150 ...] | |||||
quality: number, quality of the resized image | |||||
sizes_attr: string, sizes attribute for responsive img html tag | |||||
alt: string, img's alt attribute | |||||
options: options parameters for certain formats i.e | |||||
{ | |||||
jpg: { options }, | |||||
webp: { options } | |||||
.... | |||||
} | |||||
*/ | |||||
class ResponsiveImage extends Component { | |||||
async renderFn( | |||||
kuba-orlik: Trzeba jeszcze komponent dostosować do nowego API (klasa `Component` - zob. np. komponent… | |||||
s, | |||||
{ | |||||
image_path, | |||||
resolutions = [100, 400, 900, 1000, 1300], | |||||
quality = 80, | |||||
sizes_attr, | |||||
alt = '', | |||||
options = {}, | |||||
} | |||||
) { | |||||
const sharp = s.node_require('sharp'); | |||||
const path = s.node_require('path'); | |||||
const { promisify } = s.node_require('util'); | |||||
const locreq = s.node_require('locreq')(__dirname); | |||||
const fs = s.node_require('fs'); | |||||
const hashFile = s.node_require( | |||||
path.resolve(__dirname, '../../lib/hash-file.js') | |||||
); | |||||
if (!image_path) { | |||||
image_path = locreq.resolve('assets/sealpage-logo.png'); | |||||
} | |||||
const readFile = promisify(fs.readFile); | |||||
let image_basename = path.basename(image_path); //Extract file's name | |||||
const extension = path.extname(image_basename).slice(1); //Get the file extension | |||||
image_basename = path.basename(image_path, '.' + extension); | |||||
const file_hash = hashFile(locreq.resolve(image_path)).substring(0, 8); | |||||
Done Inline Actionsjeżeli źródłowy plik jest w png, to nie konwertujmy go do jpg, bo to może powodować niechciane artefakty. Proponuję abyśmy zawsze brali webp + format źródłowego zdjęcia. Np. webp+png, webp+jpeg. kuba-orlik: jeżeli źródłowy plik jest w png, to nie konwertujmy go do jpg, bo to może powodować niechciane… | |||||
const output_files = { | |||||
webp: {}, | |||||
[extension]: {}, | |||||
}; | |||||
for (let ext of ['webp', extension]) { | |||||
for (let resolution of resolutions) { | |||||
const base_name = `${image_basename}-${resolution}.${ext}`; | |||||
const path = await s.addOutputFile({ | |||||
output_subdir: 'images', | |||||
base_name, | |||||
Done Inline ActionsZastnawiam się czy nie powinniśmy sprawdzać jakoś sprytniej typu pliku, wyciągając jego mime type? Co w przypadku kiedy user poda plik image.jpg a będzie to miało mime type image/png, powinniśmy zabezpieczyć się przed taką sytuacją. arkadiusz-wieczorek: Zastnawiam się czy nie powinniśmy sprawdzać jakoś sprytniej typu pliku, wyciągając jego mime… | |||||
generator: async () => { | |||||
Done Inline Actionszamiast robić tu warunek specjalny dla webp proponuję w argsach podawać po prostu config osobno dla każdego formatu: { webp: {..}, png: {...} } kuba-orlik: zamiast robić tu warunek specjalny dla webp proponuję w argsach podawać po prostu config osobno… | |||||
const sharp_resized = await sharp( | |||||
locreq.resolve(image_path) | |||||
).resize(resolution); | |||||
return await sharp_resized | |||||
.toFormat(ext, { | |||||
quality, | |||||
...(options[ext] || {}), | |||||
Done Inline Actionspowinniśmy tutaj konfigurować jakosć . W webp jakość określa się w skali 1-100. Jeżeli podany plik jest plikiem png, to powinniśmy wybierać jakość 100 (bezstratne), jeżeli jest jpg, to dawajmy tak z 80%. Alternatywnie możemy po prostu dać parametr, czy pozwalamy na stratną kompresję, czy nie - i wtedy nie wnioskować tego na podstawie typu pliku wejściowego kuba-orlik: powinniśmy tutaj konfigurować jakosć . W webp jakość określa się w skali 1-100. Jeżeli podany… | |||||
Done Inline ActionsWait, widzę, że mamy już parametr quality. W takim razie proponuję go tutaj użyć - jak ktoś poda quality na 80 to używać go nie tylko do ustawiania jakość jpg, ale także przy konwersji do webp kuba-orlik: Wait, widzę, że mamy już parametr `quality`. W takim razie proponuję go tutaj użyć - jak ktoś… | |||||
Done Inline ActionsGeneralnie jak coś, to webp_options to obiekt, w którym możemy zawrzeć wszystkie ustawienia z dokumentacji sharpa dla metody webp(), w tym stratnośc kompresji. michal.starski: Generalnie jak coś, to `webp_options` to obiekt, w którym możemy zawrzeć wszystkie ustawienia… | |||||
Done Inline Actionsdo depsów trzeba też dodać config - wybraną dla aktualnego pliku rozdzielczość, format, jakość itp. Aby ich zmiana powodowała przerenderowanie kuba-orlik: do depsów trzeba też dodać config - wybraną dla aktualnego pliku rozdzielczość, format, jakość… | |||||
}) | |||||
.toBuffer(); | |||||
}, | |||||
deps: [ | |||||
file_hash, | |||||
resolutions, | |||||
quality, | |||||
Done Inline Actions{ i return są tutaj niepotrzebne, można zostawić gołe arrow function; ext => resolutions.map //... kuba-orlik: `{` i `return` są tutaj niepotrzebne, można zostawić gołe arrow function;
```
lang=js
ext =>… | |||||
Done Inline Actionsimage_path można stąd wyrzucić. Jeżeli file_hash się nie zmieniło, to nie ma potrzeby re-renderować tylko jak sie zmieni nazwa pliku kuba-orlik: `image_path` można stąd wyrzucić. Jeżeli file_hash się nie zmieniło, to nie ma potrzeby re… | |||||
sizes_attr, | |||||
options[ext] || {}, | |||||
], | |||||
}); | |||||
Done Inline Actionsalt też można wyrzucić z tej listy. nie ma wpływu na plik wynikowy kuba-orlik: `alt` też można wyrzucić z tej listy. nie ma wpływu na plik wynikowy | |||||
output_files[ext][resolution] = path; | |||||
Done Inline Actionstutaj najlepiej byłoby dać tylko te optionsy, które dotyczą aktualnie obrabianego typu pliku, np. tylko webp albo tylko jpg kuba-orlik: tutaj najlepiej byłoby dać tylko te optionsy, które dotyczą aktualnie obrabianego typu pliku… | |||||
} | |||||
} | |||||
const srcset = Object.keys(output_files).map(ext => | |||||
resolutions | |||||
.map( | |||||
resolution => | |||||
`${output_files[ext][resolution]} ${resolution}w` | |||||
) | |||||
.join(',\n') | |||||
); | |||||
const median_resolution = | |||||
resolutions[Math.round((resolutions.length - 1) / 2)]; | |||||
return /* HTML */ ` | |||||
<picture> | |||||
<source | |||||
srcset="${srcset[0]}" | |||||
sizes="${sizes_attr}" | |||||
alt="${alt}"/> | |||||
<source | |||||
srcset="${srcset[1]}" | |||||
sizes="${sizes_attr}" | |||||
alt="${alt}"/> | |||||
<img | |||||
src="${output_files[extension][median_resolution]}" | |||||
alt="${alt}" | |||||
/></picture> | |||||
`; | |||||
} | |||||
static propsControls() { | |||||
return { source_image: { control: 'image', label: 'Source image' } }; | |||||
} | |||||
} | |||||
module.exports = ResponsiveImage; | |||||
Not Done Inline Actionszbyt rozległy zapis. Wystarczy: renderFn: responsive_image_creator, kuba-orlik: zbyt rozległy zapis. Wystarczy:
```
lang=js
renderFn: responsive_image_creator,
``` |
Trzeba jeszcze komponent dostosować do nowego API (klasa Component - zob. np. komponent [Markdown](https://hub.sealcode.org/diffusion/SEALPAGE/browse/master/components/markdown/markdown.html.js)