#доклад дня
Вот так живёшь и не знаешь, что коллега — Василий Рогин — выступил на HolyJS с докладом о том, как перенёс фанатские моду Fallout 2 — Nevada и Sonora — в браузер.
Не через стриминг или эмулятор, а с нативным кодом C/C++, собранным через Emscripten в WebAssembly.
Классика жизни.
Проект основан на fallout2-ce — декомпиляции оригинального движка. И вроде бы SDL2 + wasm = счастье, но на практике всё куда интереснее:
🧩 Основные сложности:
1. Цикл игры и цикл браузера не совпадают: приходилось выносить основной луп в requestAnimationFrame, чтобы всё работало без лагов.
2. Asyncify стал ключевым инструментом: позволил «притвориться», что WebAssembly поддерживает sleep() и обычную блокирующую логику, хотя на деле всё идёт через промисы.
3. Проблемы со звуком: в вебе нет привычных потоков, а WebAudio требует костылей вроде SDL_Sleep(1), чтобы не обгонять буфер.
4. Работа с файлами: пришлось изобретать файловую систему с подгрузкой ресурсов по запросу, Asyncfetchfs, IDBFS для сохранений, и обходить баги вроде __syscall_openat, создающего побочные эффекты.
5. Было ещё весело с WebWorker'ами, OffscreenCanvas и SharedArrayBuffer — всё поддерживается, но не вместе и не так, как хотелось бы.
Ссылка на видео доклада: https://www.youtube.com/watch?v=wYJN0pLDPRw
И на PDF: https://squidex.jugru.team/api/assets/srm/878900fe-502b-4b48-a6a9-478d526048dd/holyjs-fallout2-3-.pdf
Fallout 2 — не просто культовая игра, это важный культурный пласт. И круто, что теперь её ответвления (я так понимаю, тут сугубо проблема прав на контент) можно запускать из браузера. Васе большой респект.
А, ну и конечно же, давайте поиграем: https://fallout-nevada.ru/
#game #webassembly
Вот так живёшь и не знаешь, что коллега — Василий Рогин — выступил на HolyJS с докладом о том, как перенёс фанатские моду Fallout 2 — Nevada и Sonora — в браузер.
Не через стриминг или эмулятор, а с нативным кодом C/C++, собранным через Emscripten в WebAssembly.
Классика жизни.
Проект основан на fallout2-ce — декомпиляции оригинального движка. И вроде бы SDL2 + wasm = счастье, но на практике всё куда интереснее:
🧩 Основные сложности:
1. Цикл игры и цикл браузера не совпадают: приходилось выносить основной луп в requestAnimationFrame, чтобы всё работало без лагов.
2. Asyncify стал ключевым инструментом: позволил «притвориться», что WebAssembly поддерживает sleep() и обычную блокирующую логику, хотя на деле всё идёт через промисы.
3. Проблемы со звуком: в вебе нет привычных потоков, а WebAudio требует костылей вроде SDL_Sleep(1), чтобы не обгонять буфер.
4. Работа с файлами: пришлось изобретать файловую систему с подгрузкой ресурсов по запросу, Asyncfetchfs, IDBFS для сохранений, и обходить баги вроде __syscall_openat, создающего побочные эффекты.
5. Было ещё весело с WebWorker'ами, OffscreenCanvas и SharedArrayBuffer — всё поддерживается, но не вместе и не так, как хотелось бы.
Ссылка на видео доклада: https://www.youtube.com/watch?v=wYJN0pLDPRw
И на PDF: https://squidex.jugru.team/api/assets/srm/878900fe-502b-4b48-a6a9-478d526048dd/holyjs-fallout2-3-.pdf
Fallout 2 — не просто культовая игра, это важный культурный пласт. И круто, что теперь её ответвления (я так понимаю, тут сугубо проблема прав на контент) можно запускать из браузера. Васе большой респект.
А, ну и конечно же, давайте поиграем: https://fallout-nevada.ru/
#game #webassembly
👍15❤8
#баг дня или история одного апокалипсиса
Знаете, что происходит, если в Firefox ввести в
Он позволяет.
Да, вы видите эти lol, будто это валидное число. Только вот значение value в DOM превращается в пустую строку. Ну типа «я тебе это показал, но делать с этим ничего не буду». Гениально.
Баг #1398528 в Bugzilla живёт с 2017 года. Проблему признают: Firefox нарушает спецификацию WHATWG, согласно которой
Почему не фиксят?
Ответ классический: «а что, если у нас локаль с деванагари и арабскими цифрами, и вообще — как различать запятую и точку?». Ну и правда, лучше пусть вводится вся клавиатура, чем разбираться в сепараторах.
А теперь немного цирка из Chrome:
В Chrome
Ещё веселее: 1e- — тоже "нормально", но 1ee — уже нет. Картинку с барабаном вставите сами.
А если ты вводишь 1,5 в локали, где десятичный — это точка, Chrome может забраковать это, а может и нет — зависит от версии, луны и количества кофе у разработчика.
В итоге: у Firefox можно ввести хоть «привет», и он такой: «ну окей, но это не число». Chrome вроде бы фильтрует, но делает это через лунную призму.
Что же мы делаем? Пишем код, блять!
Мораль: в 2025 году проще создать свою валидацию под конкретный случай, чем надеяться, что браузеры когда-нибудь договорятся.
А баг тем временем отмечает 8 лет жизни, всё ещё «NEW», и, судя по комментариям, будет жить
Баг-репорт: https://bugzilla.mozilla.org/show_bug.cgi?id=1398528
Подпишитесь и следите, если вы, как и мы, верите (нет) в чудеса стандартизации.
P. S. тем временем Firefox пробивает дно за дном. В англоязычном интерфейсе выдаёт мне ошибки валидации на финском языке.
P. P. S. я молчу уже о том, что <input type="number"> вообще нахер не нужен и даже вреден: https://t.iss.one/htmlshit/2663
#firefox #bug #input #number
Знаете, что происходит, если в Firefox ввести в
<input type="number">
что-то вроде lol?Он позволяет.
Да, вы видите эти lol, будто это валидное число. Только вот значение value в DOM превращается в пустую строку. Ну типа «я тебе это показал, но делать с этим ничего не буду». Гениально.
Баг #1398528 в Bugzilla живёт с 2017 года. Проблему признают: Firefox нарушает спецификацию WHATWG, согласно которой
input type=number
должен принимать только корректные числовые строки. А на деле — буквы, кириллица, эмоджи — всё идёт в бой. Только вот под капотом — пусто. Т.е. ты видишь, что ввёл, но значение не считается валидным. UX? Ну, такое себе.Почему не фиксят?
Ответ классический: «а что, если у нас локаль с деванагари и арабскими цифрами, и вообще — как различать запятую и точку?». Ну и правда, лучше пусть вводится вся клавиатура, чем разбираться в сепараторах.
А теперь немного цирка из Chrome:
В Chrome
<input type="number">
иногда разрешает ввод e, ведь вдруг ты хочешь ввести 1e10 (научную запись). Но если ты просто набрал e, поле становится… валидным. Бинго!Ещё веселее: 1e- — тоже "нормально", но 1ee — уже нет. Картинку с барабаном вставите сами.
А если ты вводишь 1,5 в локали, где десятичный — это точка, Chrome может забраковать это, а может и нет — зависит от версии, луны и количества кофе у разработчика.
В итоге: у Firefox можно ввести хоть «привет», и он такой: «ну окей, но это не число». Chrome вроде бы фильтрует, но делает это через лунную призму.
Что же мы делаем? Пишем код, блять!
Мораль: в 2025 году проще создать свою валидацию под конкретный случай, чем надеяться, что браузеры когда-нибудь договорятся.
А баг тем временем отмечает 8 лет жизни, всё ещё «NEW», и, судя по комментариям, будет жить
Баг-репорт: https://bugzilla.mozilla.org/show_bug.cgi?id=1398528
Подпишитесь и следите, если вы, как и мы, верите (нет) в чудеса стандартизации.
P. S. тем временем Firefox пробивает дно за дном. В англоязычном интерфейсе выдаёт мне ошибки валидации на финском языке.
P. P. S. я молчу уже о том, что <input type="number"> вообще нахер не нужен и даже вреден: https://t.iss.one/htmlshit/2663
#firefox #bug #input #number
👍14❤9🫡4
This media is not supported in your browser
VIEW IN TELEGRAM
🎡 Встречаемся в Коломенском!
16 августа в Москве пройдёт ИТ-пикник — семейный open-air фестиваль для ИТ-специалистов и их близких. Организаторы: Т-Банк, CodeFest и Мельница. Здесь можно отдохнуть на природе, поговорить о технологиях с теми, кто вас точно поймёт, найти новые полезные знакомства и просто классно провести летний день!
📍 Место: музей-заповедник «Коломенское»
📅 Дата: 16 августа
Что будет:
— Лекции от руководителей продуктов, инженеров, аналитиков и исследователей
— Темы: от научпопа до платформенной инженерии
— Будет весело не только взрослым: для детей приготовят квесты, VR-зоны, игры с роботами и мастер-классы – всё, чтобы провести день так же увлекательно, как и родителям
— Живая музыка: на главной сцене выступят: тима ищет свет, Тося Чайкина, Второй Ка.
– Специальным гостем станет Диана Арбенина — впервые в живом исполнении молодых артистов пройдет ее трибьют-концерт: TRITIA, PLC, ПОЛ ПУНШ, Тося Чайкина и Лилу. И завершит вечер секретный артист.
💬 Как попасть:
Пройдите регистрацию на сайте и укажите свою специализацию (заявки будут проходить модерацию)
После этого на почту придёт письмо со ссылкой для оплаты:
→ 1500 ₽ — пожертвование в благотворительный фонд
→ 1500 ₽ — организационный взнос
Один билет даёт вход для вас, одного взрослого и до двух детей.
🔗 Зарегистрироваться и присоединиться
16 августа в Москве пройдёт ИТ-пикник — семейный open-air фестиваль для ИТ-специалистов и их близких. Организаторы: Т-Банк, CodeFest и Мельница. Здесь можно отдохнуть на природе, поговорить о технологиях с теми, кто вас точно поймёт, найти новые полезные знакомства и просто классно провести летний день!
📍 Место: музей-заповедник «Коломенское»
📅 Дата: 16 августа
Что будет:
— Лекции от руководителей продуктов, инженеров, аналитиков и исследователей
— Темы: от научпопа до платформенной инженерии
— Будет весело не только взрослым: для детей приготовят квесты, VR-зоны, игры с роботами и мастер-классы – всё, чтобы провести день так же увлекательно, как и родителям
— Живая музыка: на главной сцене выступят: тима ищет свет, Тося Чайкина, Второй Ка.
– Специальным гостем станет Диана Арбенина — впервые в живом исполнении молодых артистов пройдет ее трибьют-концерт: TRITIA, PLC, ПОЛ ПУНШ, Тося Чайкина и Лилу. И завершит вечер секретный артист.
💬 Как попасть:
Пройдите регистрацию на сайте и укажите свою специализацию (заявки будут проходить модерацию)
После этого на почту придёт письмо со ссылкой для оплаты:
→ 1500 ₽ — пожертвование в благотворительный фонд
→ 1500 ₽ — организационный взнос
Один билет даёт вход для вас, одного взрослого и до двух детей.
🔗 Зарегистрироваться и присоединиться
🤡6❤1
This media is not supported in your browser
VIEW IN TELEGRAM
#codepen дня
Ну что, кажется, настало то время, когда для стилизации радиокнопок и чекбоксов не нужно больше изгаляться с
Итак, смотрим на пример от Джона Кантнера: https://codepen.io/alinaki/pen/ExMXbqz
1. Для начала, обнуляем все браузерные стили и предположения браузера об внешнем виде радиокнопок вообще через
2. Я вам этого не говорил, но, технически, уже давно можно на поля ввода накладывать псевдоэлементы. Но не на select. Я всё хочу написать большой пост про реализацию select, пока вот так.
Благодаря этой возможности, собственно, можно стилизовать чекбокс как душе угодно:
3. Освободившиеся ресурсы мозга и тот факт, что теперь все элементы красиво вложены в label (как минимум, не нужны for и id), можно отправить на реализацию разных эффектов.
Например, проверить, есть ли лейбл с выделенным чекбоксом и подвинуть к нему рамку:
Обратите внимание, рамка — отдельный элемент, к ней обращаемся через селектор низлежащих соседей ~.
Не знаю, что меня больше впечатляет. Псевдоэлементы на полях ввода или :has.
И да, поддерживается везде.
#css #has #appearance #бородач
Ну что, кажется, настало то время, когда для стилизации радиокнопок и чекбоксов не нужно больше изгаляться с
input:checked+i
. Это освобождает мозг и руки для более приятных вещей.Итак, смотрим на пример от Джона Кантнера: https://codepen.io/alinaki/pen/ExMXbqz
1. Для начала, обнуляем все браузерные стили и предположения браузера об внешнем виде радиокнопок вообще через
appearance: none
.2. Я вам этого не говорил, но, технически, уже давно можно на поля ввода накладывать псевдоэлементы. Но не на select. Я всё хочу написать большой пост про реализацию select, пока вот так.
Благодаря этой возможности, собственно, можно стилизовать чекбокс как душе угодно:
::before, ::after, :checked::before, :checked::after
... В целом, лично я бы обошёлся радиальным градиентом и одним псевдоэлементом.3. Освободившиеся ресурсы мозга и тот факт, что теперь все элементы красиво вложены в label (как минимум, не нужны for и id), можно отправить на реализацию разных эффектов.
Например, проверить, есть ли лейбл с выделенным чекбоксом и подвинуть к нему рамку:
label:nth-of-type(2):has(input[type="radio"]:checked) ~ .selection {
transform: translateY(100%);
}
Обратите внимание, рамка — отдельный элемент, к ней обращаемся через селектор низлежащих соседей ~.
Не знаю, что меня больше впечатляет. Псевдоэлементы на полях ввода или :has.
И да, поддерживается везде.
#css #has #appearance #бородач
❤12👍4
Media is too big
VIEW IN TELEGRAM
#фишка дня
Когда я наткнулся на этот твит в обсуждении утилиты работы с цветами Андрея Ситника, я не сразу примерил его на себя. Но, как оказалось, стоило бы.
Итак, давайте поясню для тех, кто по ссылкам не ходит.
В азиатских иероглифических языках почти весь ввод с клавиатуры происходит в аккордном режиме или же в режиме т. н. композитинга, общее название — Input Method Editor.
TL;DR: На экране всплывает окошко с символами или их группами и пользователь может что-то выбрать.
На каких-то ОС оно вызывается долгим зажатием клавиши, где-то — по хоткею, а где-то — автоматически и сразу.
Так вот, одно дело азиатские языки (я очень рекомендую посмотреть сам твит), а другое — разные европейские. И речь о диакритических знаках: умляуты, акуты, ударения, птички и шапочки.
Так вот, я не имею финской раскладки, потому буквы ä, å и ö ввожу как раз в режиме композитинга, долгим зажатием «материнской» клавиши.
Собственно, так база для азиатских языков проникла и в мою жизнь.
Кстати, выбор Emoji из всплывающего окошка — туда же.
В JavaScript-событиях для этого режима имеется флаг isComposing. Поэтому если вы, как и я в примере на видео, решили реализовать ввод групп символов подобным образом — циклически перебирая поля ввода — стоит об этом подумать :)
Собственно, давайте и пример: https://codepen.io/alinaki/pen/MWMpdvO?editors=1010
И напишите в комментариях, как вы решаете проблему редкого ввода букв с диакритикой у себя в системе. Например, я не помню, как это происходит в Windows, а в Linux я использую клавишу Compose, она работает чуть иначе.
#javascript #composing #event #бородач
Когда я наткнулся на этот твит в обсуждении утилиты работы с цветами Андрея Ситника, я не сразу примерил его на себя. Но, как оказалось, стоило бы.
Итак, давайте поясню для тех, кто по ссылкам не ходит.
В азиатских иероглифических языках почти весь ввод с клавиатуры происходит в аккордном режиме или же в режиме т. н. композитинга, общее название — Input Method Editor.
TL;DR: На экране всплывает окошко с символами или их группами и пользователь может что-то выбрать.
На каких-то ОС оно вызывается долгим зажатием клавиши, где-то — по хоткею, а где-то — автоматически и сразу.
Так вот, одно дело азиатские языки (я очень рекомендую посмотреть сам твит), а другое — разные европейские. И речь о диакритических знаках: умляуты, акуты, ударения, птички и шапочки.
Так вот, я не имею финской раскладки, потому буквы ä, å и ö ввожу как раз в режиме композитинга, долгим зажатием «материнской» клавиши.
Собственно, так база для азиатских языков проникла и в мою жизнь.
Кстати, выбор Emoji из всплывающего окошка — туда же.
В JavaScript-событиях для этого режима имеется флаг isComposing. Поэтому если вы, как и я в примере на видео, решили реализовать ввод групп символов подобным образом — циклически перебирая поля ввода — стоит об этом подумать :)
Собственно, давайте и пример: https://codepen.io/alinaki/pen/MWMpdvO?editors=1010
И напишите в комментариях, как вы решаете проблему редкого ввода букв с диакритикой у себя в системе. Например, я не помню, как это происходит в Windows, а в Linux я использую клавишу Compose, она работает чуть иначе.
#javascript #composing #event #бородач
👍4❤3🤩1
#ссылка дня
Мы тут немного повеселились с XSS в разных продуктах и сайтах, результаты удивили. Распространяться я не буду, неприлично, но парочкой полезных ссылок поделюсь.
1. Расширение для Chrome, позволяющее быстро выбрать и вставить XSS-строку в нужное вам текстовое поле: https://chrome.google.com/webstore/detail/bug-magnet/efhedldbjahpgjcneebmbolkalbhckfi?hl=en
2. И репозиторий на ту же тему: https://github.com/minimaxir/big-list-of-naughty-strings
Впрочем, там не только XSS. Помните, например, в чатах люди свои ники пишут с “грязью”? Красиво поломать интерфейс — это туда. Вставить эмодзи, смайлы, управляющие символы.
Ломайте свои интерфейсы сами и избегайте XSS, котаны.
#xss #naughty #injection #бородач
Мы тут немного повеселились с XSS в разных продуктах и сайтах, результаты удивили. Распространяться я не буду, неприлично, но парочкой полезных ссылок поделюсь.
1. Расширение для Chrome, позволяющее быстро выбрать и вставить XSS-строку в нужное вам текстовое поле: https://chrome.google.com/webstore/detail/bug-magnet/efhedldbjahpgjcneebmbolkalbhckfi?hl=en
2. И репозиторий на ту же тему: https://github.com/minimaxir/big-list-of-naughty-strings
Впрочем, там не только XSS. Помните, например, в чатах люди свои ники пишут с “грязью”? Красиво поломать интерфейс — это туда. Вставить эмодзи, смайлы, управляющие символы.
Ломайте свои интерфейсы сами и избегайте XSS, котаны.
#xss #naughty #injection #бородач
❤6
#баг дня
Одна из моих любимых фишек инструментов разработчика Google Chrome или Firefox (aka девтулзов) — это возможность сделать скриншот ноды.
Нужен длинный скриншот страницы? Бахаешь на body или html и сидишь довольный.
Нужен лишь кусочек? Не вопрос, выдели нужную ноду мышкой и скриншоть себе на здоровье.
Но не обошлось без проблем. Ну честное слово, вот же вся страница, на экране. Бери да превращай в картинку. Нет...
Если в вашей ноде есть картинки, добавленные через тег img с атрибутом
Вот так вот неожиданно. Видимо кто-то где-то промис не разресолвил :)
Решается проблема удалением атрибута, прямо в девтулзах, и повторным скриншотом. Иногда достаточно и просто убедиться, что все картинки загружены — я пока паттерна не понял.
Но неприятный осадок всё-таки остался.
Сейчас ищу формальное описание бага в багтрекере. Если не найду — придётся заводить.
Демо: https://10web.io/blog/how-to-create-a-blog-on-wordpress/
Просто попробуйте сделать скриншот body, не скролля заранее.
Проверено на Chrome 138.0.7204.184. Столько времени прошло с предыдущей проверки...
В итоге, часть картинок может появиться, а часть — нет.
Вообще, я откровенно не люблю ленивую загрузку картинок и контента. Да, помогает на медленном интернете, но абсолютно мерзко и неудобно на нестабильном соединении. Например, в поезде.
P. S. В Firefox 141 баг тоже имеется.
#chrome #bug #async #бородач
Одна из моих любимых фишек инструментов разработчика Google Chrome или Firefox (aka девтулзов) — это возможность сделать скриншот ноды.
Нужен длинный скриншот страницы? Бахаешь на body или html и сидишь довольный.
Нужен лишь кусочек? Не вопрос, выдели нужную ноду мышкой и скриншоть себе на здоровье.
Но не обошлось без проблем. Ну честное слово, вот же вся страница, на экране. Бери да превращай в картинку. Нет...
Если в вашей ноде есть картинки, добавленные через тег img с атрибутом
decoding="async"
— они потеряются :(Вот так вот неожиданно. Видимо кто-то где-то промис не разресолвил :)
Решается проблема удалением атрибута, прямо в девтулзах, и повторным скриншотом. Иногда достаточно и просто убедиться, что все картинки загружены — я пока паттерна не понял.
Но неприятный осадок всё-таки остался.
Сейчас ищу формальное описание бага в багтрекере. Если не найду — придётся заводить.
Демо: https://10web.io/blog/how-to-create-a-blog-on-wordpress/
Просто попробуйте сделать скриншот body, не скролля заранее.
Проверено на Chrome 138.0.7204.184. Столько времени прошло с предыдущей проверки...
В итоге, часть картинок может появиться, а часть — нет.
Вообще, я откровенно не люблю ленивую загрузку картинок и контента. Да, помогает на медленном интернете, но абсолютно мерзко и неудобно на нестабильном соединении. Например, в поезде.
P. S. В Firefox 141 баг тоже имеется.
#chrome #bug #async #бородач
❤11
😈 Data Dojo | Питер | 26 августа
Это мероприятие Яндекса для сообщества ML-специалистов с обсуждением трендов, разбором реальных задач из соревнований и прикладными кейсами.
Зачем участвовать:
— послушать выступления экспертов: Николай Савушкин, руководитель команды рекомендательных технологий в Поиске, расскажет про генеративные нейросети в рекомендательных системах Яндекса, а Алексей Колесов,
руководитель команды NLP, поделится, какие вызовы стоят перед командой R&D в Яндексе
— разобрать задачи вместе с сообществом
— узнать, как попасть на стажировку и начать карьеру ML’щика в Яндексе
— завести новые знакомства и зажечь на afterparty
Заполняй форму до 20 августа.
Хочешь стать спикером? Поделись разбором ML-задачи через форму до 13 августа. Программный комитет пригласит одного спикера выступить на встрече.
🪷 Самураи действуют поодиночке, но учатся вместе. Присоединяйся.
Это мероприятие Яндекса для сообщества ML-специалистов с обсуждением трендов, разбором реальных задач из соревнований и прикладными кейсами.
Зачем участвовать:
— послушать выступления экспертов: Николай Савушкин, руководитель команды рекомендательных технологий в Поиске, расскажет про генеративные нейросети в рекомендательных системах Яндекса, а Алексей Колесов,
руководитель команды NLP, поделится, какие вызовы стоят перед командой R&D в Яндексе
— разобрать задачи вместе с сообществом
— узнать, как попасть на стажировку и начать карьеру ML’щика в Яндексе
— завести новые знакомства и зажечь на afterparty
Заполняй форму до 20 августа.
Хочешь стать спикером? Поделись разбором ML-задачи через форму до 13 августа. Программный комитет пригласит одного спикера выступить на встрече.
🪷 Самураи действуют поодиночке, но учатся вместе. Присоединяйся.
❤3🤡3👎1
#инструмент дня
Четыре (охереть) года назад я писал большую серию статей на тему того, как же тестировать WebKit aka Safari на Windows и Linux. Вот, можете почитать: https://t.iss.one/htmlshit/705
Дайте знать, если пора эту серию статей обновить!
И тогда мы остановились на том, что можно просто использовать... Browserstack!
Но не все могут себе позволить даже 150 долларов в год за фриланс-план… или всё же есть выход?
Выход правда есть!
Browserstack активно поддерживает open-source проекты и даёт бесплатные лицензии на год!
Если у вас есть такой — смело топайте на https://www.browserstack.com/open-source и вбивайте там ссылку на репозиторий.
Главное — чтобы была подходящая лицензия. Полного списка я не нашёл, но уверен, что GPL, BSD и MIT точно включены. Я же указал Creative Commons Attribution 4.0 International.
Ах да, что же у меня за проект такой опенсорс? Да просто сайт этого канала: https://github.com/HTMLShit/htmlshit.site
Он в анабиозе сейчас, но работу над ним можно и восстановить. Да и пульт мой я ещё подумываю открыть.
Так вот, доступ обновляется каждый год пока репозиторий доступен! У меня, выходит, уже 4 года.
После прохождения ручной модерации, мне пришло письмо. Я получил годовые планы тестирования браузера и мобильных с весьма вкусными условиями.
Короче, если вы ещё не начали свой проект – чего вы ждёте вообще?
#browserstack #testing
Четыре (охереть) года назад я писал большую серию статей на тему того, как же тестировать WebKit aka Safari на Windows и Linux. Вот, можете почитать: https://t.iss.one/htmlshit/705
Дайте знать, если пора эту серию статей обновить!
И тогда мы остановились на том, что можно просто использовать... Browserstack!
Но не все могут себе позволить даже 150 долларов в год за фриланс-план… или всё же есть выход?
Выход правда есть!
Browserstack активно поддерживает open-source проекты и даёт бесплатные лицензии на год!
Если у вас есть такой — смело топайте на https://www.browserstack.com/open-source и вбивайте там ссылку на репозиторий.
Главное — чтобы была подходящая лицензия. Полного списка я не нашёл, но уверен, что GPL, BSD и MIT точно включены. Я же указал Creative Commons Attribution 4.0 International.
Ах да, что же у меня за проект такой опенсорс? Да просто сайт этого канала: https://github.com/HTMLShit/htmlshit.site
Он в анабиозе сейчас, но работу над ним можно и восстановить. Да и пульт мой я ещё подумываю открыть.
Так вот, доступ обновляется каждый год пока репозиторий доступен! У меня, выходит, уже 4 года.
После прохождения ручной модерации, мне пришло письмо. Я получил годовые планы тестирования браузера и мобильных с весьма вкусными условиями.
Короче, если вы ещё не начали свой проект – чего вы ждёте вообще?
#browserstack #testing
1👍15
This media is not supported in your browser
VIEW IN TELEGRAM
#расширение дня
А что, если история гита может быть представлена не в виде вертикального списка?
А что, если можно правильно использовать анимации, акцентируя внимание на изменениях?
А что, если можно не открывать интерфейс git blame на каждый чих?
Именно так подумал Родриго Помбо и нафигачил прекрасное расширение для Visual Studio Code: Git File History.
Принцип действия понятен по виде, устанавливайте: https://marketplace.visualstudio.com/items?itemName=pomber.git-file-history
Всем git, котаны!
P. S. вы же в курсе, что устанавливать расширения можно из консоли?
Как-то так:
Если команда
#git #history #vscode #бородач
А что, если история гита может быть представлена не в виде вертикального списка?
А что, если можно правильно использовать анимации, акцентируя внимание на изменениях?
А что, если можно не открывать интерфейс git blame на каждый чих?
Именно так подумал Родриго Помбо и нафигачил прекрасное расширение для Visual Studio Code: Git File History.
Принцип действия понятен по виде, устанавливайте: https://marketplace.visualstudio.com/items?itemName=pomber.git-file-history
Всем git, котаны!
P. S. вы же в курсе, что устанавливать расширения можно из консоли?
Как-то так:
code --install-extension pomber.git-file-history
Если команда
code
недоступна, решение тут.#git #history #vscode #бородач
👍12❤3👎1
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня
Каждому смотрящему сериалы известно, что один из самых лучших способов сделать текст субтитров видимым на практически любом фоне — это добавить инверсную обводку.
Белый контур для чёрного текста, чёрный — для белого (внезапно).
Есть ли что-то подобное в CSS? Ну, конечно, есть! Как минимум, можно бросить тень aka text-shadow. Правда, синтаксис не очень интуитивный да и выглядит иногда странненько.
Какие ещё варианты? SVG text, очевидно, но там свои нюансы с доступностью и стилями.
И есть ещё!
Несмотря на префикс, Firefox тоже его поддерживает (спорное решение, но уж как есть).
Вот только как всегда есть нюанс. По-умолчанию, обводка будет нарисована перед слоем с текстом. Это очевидно, если понимать разницу между штрихом (stroke) и обводкой (outline), но всё же.
Поэтому
#css #stroke #outline
Каждому смотрящему сериалы известно, что один из самых лучших способов сделать текст субтитров видимым на практически любом фоне — это добавить инверсную обводку.
Белый контур для чёрного текста, чёрный — для белого (внезапно).
Есть ли что-то подобное в CSS? Ну, конечно, есть! Как минимум, можно бросить тень aka text-shadow. Правда, синтаксис не очень интуитивный да и выглядит иногда странненько.
Какие ещё варианты? SVG text, очевидно, но там свои нюансы с доступностью и стилями.
И есть ещё!
-webkit-text-stroke-color
Несмотря на префикс, Firefox тоже его поддерживает (спорное решение, но уж как есть).
Вот только как всегда есть нюанс. По-умолчанию, обводка будет нарисована перед слоем с текстом. Это очевидно, если понимать разницу между штрихом (stroke) и обводкой (outline), но всё же.
Поэтому
paint-order: stroke
нам в помощь! Таким образом, штрих будет отрисован первым, натуральным образом превратившись в обводку (при достаточной толщине, конечно же):
-webkit-text-stroke-color: white;
-webkit-text-stroke-width: var(--stroke);
paint-order: stroke;
#css #stroke #outline
❤15👍6🫡3
#такое дня
Вы, наверное, ждёте все, что я сообщу о выходе jQuery 4.0?
Ну так не вышла ещё, только RC1: https://blog.jquery.com/2025/08/11/jquery-4-0-0-release-candidate-1/
А так-то было известно ещё года 2 назад, что разработка продолжается и спрос до сих пор есть. Но всё же, хочется отметить другое.
В мире, в котором нет Internet Explorer, всё ещё есть Safari. И не сказать, что это плохой продукт — вроде целевой аудитории-то он даже нравится — но и хорошим не назвать.
И вот что интересно, плохая или, что даже хуже, неочевидная работа Safari и движка WebKit в частности (а точнее говоря, работа движка в конечном продукте интеграции) сформировала целую культуру длинных гневных комментариев!
Вы только посмотрите на пример на иллюстрации! Я уверен, я бы тоже написал нечто подобное (да и писал), если бы наткнулся сам.
Ну то есть суть всей проблемы: WebKit или зумит по двойному тапу, или скроллит, если зум отключён через CSS. И чтобы предотвратить скролл, надо просто объявить использование события двойного клика. Даже отменять поведение по-умолчанию не обязательно.
Тред по этому поводу, кстати, шикарный. Много исторических отсылок и примеров подобных комментариев заодно.
А какая особенность яблочного браузера раздражает вас больше всего, котаны?
#safari #bug #feature
Вы, наверное, ждёте все, что я сообщу о выходе jQuery 4.0?
Ну так не вышла ещё, только RC1: https://blog.jquery.com/2025/08/11/jquery-4-0-0-release-candidate-1/
А так-то было известно ещё года 2 назад, что разработка продолжается и спрос до сих пор есть. Но всё же, хочется отметить другое.
В мире, в котором нет Internet Explorer, всё ещё есть Safari. И не сказать, что это плохой продукт — вроде целевой аудитории-то он даже нравится — но и хорошим не назвать.
И вот что интересно, плохая или, что даже хуже, неочевидная работа Safari и движка WebKit в частности (а точнее говоря, работа движка в конечном продукте интеграции) сформировала целую культуру длинных гневных комментариев!
Вы только посмотрите на пример на иллюстрации! Я уверен, я бы тоже написал нечто подобное (да и писал), если бы наткнулся сам.
Ну то есть суть всей проблемы: WebKit или зумит по двойному тапу, или скроллит, если зум отключён через CSS. И чтобы предотвратить скролл, надо просто объявить использование события двойного клика. Даже отменять поведение по-умолчанию не обязательно.
Тред по этому поводу, кстати, шикарный. Много исторических отсылок и примеров подобных комментариев заодно.
А какая особенность яблочного браузера раздражает вас больше всего, котаны?
#safari #bug #feature
🤬7❤1🤩1
Media is too big
VIEW IN TELEGRAM
Как показать, что у компании сильная команда, интересные задачи, уникальный продукт, возможности роста и при этом развита культура доверия?
Команда AvitoTech собрала все клише корпоративных видео в одном месте… Чтобы показать, какая атмосфера действительно существует у них.
P.S. Отправляйте тому самому другу-инженеру, который ищет команду мечты☄️ Кстати, тут можно подробнее все прочитать.
Команда AvitoTech собрала все клише корпоративных видео в одном месте… Чтобы показать, какая атмосфера действительно существует у них.
P.S. Отправляйте тому самому другу-инженеру, который ищет команду мечты
Please open Telegram to view this post
VIEW IN TELEGRAM
🤡13❤2👍1
This media is not supported in your browser
VIEW IN TELEGRAM
#заметка дня
А помните (конечно же помните!) как мы с вами обсуждали CSS Custom Highlight API для реализации подсветки кода?
Ну вот же, положила: https://t.iss.one/htmlshit/2715
Так вот, а почему бы не объединить подсветку CSS с поиском по тексту? Ну в самом деле, интересно же, как это реализовано, например, в текстовых редакторах или браузерах при поиске по странице. Хотя бы на минимальном уровне.
А реализовано это через, простите, обход дерева!
Алгориииииитмы
Ладно, нам не придётся самим писать обходчик, он уже имеется! Вот: https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker
Главное — это понять, какой параметр фильтрации узлов передать. Ведь объектная модель документа она не только из тегов состоит, там как минимум параллельно идут атрибуты, текст, комментарии... Нам незачем искать вообще по всему.
Ну в нашем случае всё просто: NodeFilter.SHOW_TEXT — ищем по текстовым нодам, словам.
Ну а дальше всё просто: проверяем регуляркой на совпадения и запускаем подсветку. Уж это за нас теперь может и браузер делать: https://codepen.io/alinaki/pen/zxvPbRJ
Да, теперь можно и ваших камтомных селектах красиво подсветить результат фильтрации.
Пользуемся, котаны.
#css #highlight
А помните (конечно же помните!) как мы с вами обсуждали CSS Custom Highlight API для реализации подсветки кода?
Ну вот же, положила: https://t.iss.one/htmlshit/2715
Так вот, а почему бы не объединить подсветку CSS с поиском по тексту? Ну в самом деле, интересно же, как это реализовано, например, в текстовых редакторах или браузерах при поиске по странице. Хотя бы на минимальном уровне.
А реализовано это через, простите, обход дерева!
Алгориииииитмы
Ладно, нам не придётся самим писать обходчик, он уже имеется! Вот: https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker
Главное — это понять, какой параметр фильтрации узлов передать. Ведь объектная модель документа она не только из тегов состоит, там как минимум параллельно идут атрибуты, текст, комментарии... Нам незачем искать вообще по всему.
Ну в нашем случае всё просто: NodeFilter.SHOW_TEXT — ищем по текстовым нодам, словам.
Ну а дальше всё просто: проверяем регуляркой на совпадения и запускаем подсветку. Уж это за нас теперь может и браузер делать: https://codepen.io/alinaki/pen/zxvPbRJ
Да, теперь можно и ваших камтомных селектах красиво подсветить результат фильтрации.
Пользуемся, котаны.
#css #highlight
❤11👍7🤩2
Forwarded from Alfa Digital
Фронтендеры, общий сбор 🗣️
Московское сообщество JavaScript-разработчиков MoscowJS заглянет в гости к Альфа-Банку. Программа намечается такая:
🔢 От JavaScript к DeFi: как инженеры могут изменить мир финансов
Даниил Швецов, Full Stack Engineer
🔢 Архитектура микрофронтендов: от А до Single Spa
Павел Шлыков, Team Lead Frontend
🔢 Под капотом платформы
Антон Марченко, Ведущий разработчик
🔢 Гильдия: место, где разработчик перестаёт быть одиноким кузнецом
Владислав Сазонов, Head of Frontend
Регистрируйтесь по ссылке — а мы вас будем ждать:
🔴 28 августа, 19:00
🔴 Онлайн или офлайн в Москве в офисе Альфа-Банка
#анонс #frontend
➿ ➿ ➿ ➿ ➿ ➿
@alfadigital_jobs — канал о работе в IT и Digital в Альфа-Банке
Московское сообщество JavaScript-разработчиков MoscowJS заглянет в гости к Альфа-Банку. Программа намечается такая:
Даниил Швецов, Full Stack Engineer
Доклад познакомит JavaScript-инженеров с основами DeFi: ключевыми концепциями, математическими моделями и работой с JS SDK.
Павел Шлыков, Team Lead Frontend
Поговорим о микрофронтендах с нуля: от принципов и базовой реализации до инструментов вроде Module Federation и single-spa. Разберёмся, как всё устроено, и рассмотрим нестандартные подходы.
Антон Марченко, Ведущий разработчик
Доклад об опыте сборки платформы из готовых решений и объединения приложений через iframe, Module Federation и webview. Узнаете про выбор подходов и работу с командами.
Владислав Сазонов, Head of Frontend
Чувствуете себя одиноким фронтендером? Есть решение — гильдия. В докладе — о том, как этот формат помогает расти, делиться опытом и не выгорать, а также краткий исторический экскурс.
Регистрируйтесь по ссылке — а мы вас будем ждать:
#анонс #frontend
@alfadigital_jobs — канал о работе в IT и Digital в Альфа-Банке
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15👍10🤡2
#инструмент дня
Мозаики (паттерны) это всегда прекрасно. Но соблюсти симметрию, чтобы заполнить поле, может быть не совсем тривиально.
Симметрия, отражение и поворот станут вашими лучшими друзьями. Хотелось бы какой-нибудь простой инструмент для их настройки.
И такой есть!
https://patternico.com/
Можно заполнить встроенными иконками (Font Awesome или Line), а можно загрузить свои. Есть даже ссылка на вариант конструктора с эмодзи :) Правда, там убогонькие Emojione, но вдруг кому ок.
В общем, имеет право на жизнь. Только на мобиле работает не очень :(
#pattern #background #generator #бородач
Мозаики (паттерны) это всегда прекрасно. Но соблюсти симметрию, чтобы заполнить поле, может быть не совсем тривиально.
Симметрия, отражение и поворот станут вашими лучшими друзьями. Хотелось бы какой-нибудь простой инструмент для их настройки.
И такой есть!
https://patternico.com/
Можно заполнить встроенными иконками (Font Awesome или Line), а можно загрузить свои. Есть даже ссылка на вариант конструктора с эмодзи :) Правда, там убогонькие Emojione, но вдруг кому ок.
В общем, имеет право на жизнь. Только на мобиле работает не очень :(
#pattern #background #generator #бородач
❤8👍3
#заметка дня
Рубрика "Вы не спрашивали, но я всё равно отвечу!"
На самом деле, разговор произошёл в Твиттере, и я посчитал разумным, вынести его сюда.
Итак, вопрос:
Что бы убедиться: использование testid в end-2-end тестах для выборки элементов это анти-паттерн, верно? Следует тестировать с точки зрения пользователя: искать кнопку с неким текстом, например.
Знаете ли вы статьи или доклады, которые подкрепляют эту точку зрения?
Отвечаю:
Это не то чтобы антипаттерн, это просто бестолковое использование ресурсов, потому и продвигается как антипаттерн.
1. Надо тестировать то, что видит юзер
2. Если что-то не видит, значит, всё плохо
3. Если там иконка или нужен результат — искать надо по a11y атрибутам.
Сразу поясню за "бестолковость".
Когда ты что-то тестируешь, тесты становятся твоей документацией. Значит, в тестах закрепляется текущее поведение проекта. Даже строки не стоит импортировать (если ты только не тестируешь систему перевода).
А это значит, если кто-то случайно сломает систему перевода или неправильно переведёт строку без информирования остальных — тесты упадут и это правильно.
Дальше, решая проблему через ARIA-атрибуты, ты заодно решаешь вопрос доступности. Бесплатно. Поэтому data-testid и названы бестолковым использованием ресурсов.
Это же, кстати, касается систем трекинга вроде Datadog RUM.
Смысл фронтенда в том, чтобы пользователь мог с продуктом взаимодействовать. Для этого необходима визуальная и когнитивная поддержка. Кнопка может быть и видна, но на кнопке — упс — может не быть текста. Или она будет цвета фона (потому скриншот-тесты ещё не вымерли).
Подобный подход к тестировани применяется как в E2E, так и в юнит- и интеграционном тестировании. Вот, например, поясняющая статья от Testing Library, которая нынче стандарт де-факто для тестирования в вебе.
Тестируйте, котаны!
#web #testing #e2e #бородач
Рубрика "Вы не спрашивали, но я всё равно отвечу!"
На самом деле, разговор произошёл в Твиттере, и я посчитал разумным, вынести его сюда.
Итак, вопрос:
Что бы убедиться: использование testid в end-2-end тестах для выборки элементов это анти-паттерн, верно? Следует тестировать с точки зрения пользователя: искать кнопку с неким текстом, например.
Знаете ли вы статьи или доклады, которые подкрепляют эту точку зрения?
Отвечаю:
Это не то чтобы антипаттерн, это просто бестолковое использование ресурсов, потому и продвигается как антипаттерн.
1. Надо тестировать то, что видит юзер
2. Если что-то не видит, значит, всё плохо
3. Если там иконка или нужен результат — искать надо по a11y атрибутам.
Сразу поясню за "бестолковость".
Когда ты что-то тестируешь, тесты становятся твоей документацией. Значит, в тестах закрепляется текущее поведение проекта. Даже строки не стоит импортировать (если ты только не тестируешь систему перевода).
А это значит, если кто-то случайно сломает систему перевода или неправильно переведёт строку без информирования остальных — тесты упадут и это правильно.
Дальше, решая проблему через ARIA-атрибуты, ты заодно решаешь вопрос доступности. Бесплатно. Поэтому data-testid и названы бестолковым использованием ресурсов.
Это же, кстати, касается систем трекинга вроде Datadog RUM.
Смысл фронтенда в том, чтобы пользователь мог с продуктом взаимодействовать. Для этого необходима визуальная и когнитивная поддержка. Кнопка может быть и видна, но на кнопке — упс — может не быть текста. Или она будет цвета фона (потому скриншот-тесты ещё не вымерли).
Подобный подход к тестировани применяется как в E2E, так и в юнит- и интеграционном тестировании. Вот, например, поясняющая статья от Testing Library, которая нынче стандарт де-факто для тестирования в вебе.
Тестируйте, котаны!
#web #testing #e2e #бородач
Testing-Library
React Testing Library | Testing Library
React Testing Library builds on top of DOM Testing Library by adding
3👍6❤3
#статья дня
JSON.stringify в V8 теперь в два раза быстрее!
Пруф: https://v8.dev/blog/json-stringify
Ну и мы все с вами так любим применять
А еще клонирование! JSON.stringify => JSON.parse и вуаля!
Кто сказал
В V8 провели серьёзную работу и сделали функцию более чем в два раза быстрее!
Основные улучшения такие:
Срезание углов
Обычно при сериализации движок обязан быть очень осторожным: вдруг у объекта есть геттеры, собственный метод
Все эти проверки занимают время.
Теперь V8 научился определять случаи, когда объект «чистый», то есть просто содержит данные и не может неожиданно запустить код. В таких ситуациях сериализация идёт по короткому маршруту — без лишних проверок, что даёт значительный прирост скорости.
Убираем рекурсию
Прежняя реализация работала рекурсивно, из-за чего сериализация глубоко вложенных структур была и медленнее, и потенциально опасна переполнением стека. Теперь используется итеративный алгоритм: он быстрее и надёжнее, вне зависимости от глубины объекта.
Для разработчиков это значит, что операции с данными становятся заметно быстрее.
А как же structuredClone?
Конечно, для клонирования объектов нас есть современный инструмент —
Для обмена данными снаружи всё равно будет нужен
Теперь же, благодаря оптимизациям,
Вообще, там в статье еще много чего! Очень рекомендую.
#v8 #json #stringify #structuredClone
JSON.stringify в V8 теперь в два раза быстрее!
Пруф: https://v8.dev/blog/json-stringify
JSON.stringify
— одна из самых используемых функций в стандартной библиотеке JavaScript. Её используют для превращения объектов в JSON-строку. Надо ли объяснять, зачем? :)Ну и мы все с вами так любим применять
JSON.stringify
для сравнения объектов... ведь достаточно сериализовать оба и сравнить строки. До недавнего времени способа лучше просто не существовало.А еще клонирование! JSON.stringify => JSON.parse и вуаля!
Кто сказал
structuredClone
?В V8 провели серьёзную работу и сделали функцию более чем в два раза быстрее!
Основные улучшения такие:
Срезание углов
Обычно при сериализации движок обязан быть очень осторожным: вдруг у объекта есть геттеры, собственный метод
toJSON
, прокси или ещё какой-то механизм, который может вмешаться в процесс.Все эти проверки занимают время.
Теперь V8 научился определять случаи, когда объект «чистый», то есть просто содержит данные и не может неожиданно запустить код. В таких ситуациях сериализация идёт по короткому маршруту — без лишних проверок, что даёт значительный прирост скорости.
Убираем рекурсию
Прежняя реализация работала рекурсивно, из-за чего сериализация глубоко вложенных структур была и медленнее, и потенциально опасна переполнением стека. Теперь используется итеративный алгоритм: он быстрее и надёжнее, вне зависимости от глубины объекта.
Для разработчиков это значит, что операции с данными становятся заметно быстрее.
А как же structuredClone?
Конечно, для клонирования объектов нас есть современный инструмент —
structuredClone
. Его главное отличие в том, что он не превращает данные в строку, а создаёт точную копию структуры. Он умеет работать с типами, которые JSON.stringify
просто «теряет»: Map
, Set
, Date
, RegExp
, бинарные буферы и даже циклические ссылки.Для обмена данными снаружи всё равно будет нужен
JSON.stringify
, для внутренних операций удобнее и надёжнее использовать structuredClone
.Теперь же, благодаря оптимизациям,
JSON.stringify
остаётся такой же универсальной «рабочей лошадкой», но работает заметно быстрее.Вообще, там в статье еще много чего! Очень рекомендую.
#v8 #json #stringify #structuredClone
❤14👍1
Старт дан: сегодня SourceCraft от Яндекса открыл прием заявок на грантовую программу и конкурс репозиториев. Если у вас есть проект в опенсорсе — самое время показать его миру.
Бросайте код на платформу, собирайте оценки по новой многоуровневой шкале, наблюдайте, как растет ваш рейтинг. Ачивки с уникальным оформлением от нейросети будут напоминать, что каждый ваш вклад замечен.
И не забывайте — активность и высокие оценки приближают вас к поддержке. Сегодняшний день может стать отправной точкой для вашего проекта.
Информация об организаторе Акции, о правилах проведения Акции, количестве призов, сроках, месте и порядке их получения размещена по ссылке
Бросайте код на платформу, собирайте оценки по новой многоуровневой шкале, наблюдайте, как растет ваш рейтинг. Ачивки с уникальным оформлением от нейросети будут напоминать, что каждый ваш вклад замечен.
И не забывайте — активность и высокие оценки приближают вас к поддержке. Сегодняшний день может стать отправной точкой для вашего проекта.
Информация об организаторе Акции, о правилах проведения Акции, количестве призов, сроках, месте и порядке их получения размещена по ссылке
❤3🤡2👍1
#инструмент дня
Volta? nvm? asdf? fnm? n?
Вы же поняли? Да, это всё менеджеры версий node.js.
Ладно-ладно, asdf чуть шире штука.
И хорошо, если нестабильные версии ноды ставишь только ради проверки фишек...
Так вот, к чему это я?
А к тому, что наш любимый pnpm с версии 10.14 тоже стал таким менеджером!
Подробнее: https://pnpm.io/blog/releases/10.14
Поддерживаются Node.js, Deno, и Bun.
За что мы так любим pnpm? За воркспейсы в том числе. Так вот, теперь в разных воркспейсах могут быть и разные версии ноды!
Круто? Не то слово :)
#pnpm #nvm #volta #node #bun
Volta? nvm? asdf? fnm? n?
Вы же поняли? Да, это всё менеджеры версий node.js.
Ладно-ладно, asdf чуть шире штука.
И хорошо, если нестабильные версии ноды ставишь только ради проверки фишек...
Так вот, к чему это я?
А к тому, что наш любимый pnpm с версии 10.14 тоже стал таким менеджером!
Подробнее: https://pnpm.io/blog/releases/10.14
{
"devEngines": {
"runtime": {
"name": "node",
"version": "^24.4.0",
"onFail": "download" // we only support the "download" value for now
}
}
}
Поддерживаются Node.js, Deno, и Bun.
За что мы так любим pnpm? За воркспейсы в том числе. Так вот, теперь в разных воркспейсах могут быть и разные версии ноды!
Круто? Не то слово :)
#pnpm #nvm #volta #node #bun
1👍8❤4