104 заметки с тегом

javascript

Какие ещё графические форматы поддерживает ваш браузер?

Переложил на хостинг «Гитхаба» свой проект семилетней давности — «Какие графические форматы поддерживает ваш браузер?». Я его иногда обновляю и мне было бы проще это делать через репозиторий.

Из всего, что я там проверяю, сразу не сработала только проверка на AVIF — это новейший формат, у меня на компьютере его поддерживает пока только «Файерфокс», ему важно указание типа содержимого, а «Гитхаб» передаёт неправильное значение.

Браузеры (сверху вниз): «Сафари» 13, «Файерфокс» 78 и «Опера» 69

Я подумал, что наверняка есть какой-то способ указать правильный тип в файле конфигурации сайта, но нет, так это не работает, такой настройки в нём нет. В принципе, известно откуда «Гитхаб» берёт свою базу типов содержимого — из проекта mime-db. Но этот путь тоже не сработал — я добавил туда тип для AVIF больше недели назад, но ничего не изменилось. Видимо синхронизация изменений происходит нечасто.

Пришлось идти другим путём — вместо того, чтобы загружать файл картинки, внедрил его внутрь при помощи протокола data:, это позволило обойти проблему. Можете протестировать на своём браузере.

Ссылка на проект: https://bolknote.github.io/detect-browser-graphics-formats/
Ссылка не репозиторий проекта: https://github.com/bolknote/detect-browser-graphics-formats

 4 комментария    296   17 дн   avif   datauri   gif   html   javascript   jpeg   pdf   png   браузер   программирование

JUnix в книге

Пока ещё далеко не ушёл от этой темы, напишу.

Недавно выкладывал в открытый доступ свой проект начала нулевых — JUnix, «эмулятор» Линукса на ДжаваСкрипте. Заодно для интереса погуглил много ли ссылок осталось на прежний сайт проекта — junix.kzn.ru.

Ссылок оказалось немало, заодно нагуглилось несколько статей, которых я не видел, когда проект был жив. Но удивительнее всего было встретить упоминание моего «эмулятора» в бумажной книге — учебном пособии по операционным системам.

Книга, как оказалось, всё ещё выпускается и продаётся, правда есть ли в переизданиях упоминание «ДжУникса» выяснить не удалось — онлайн-магазины нужную главу не показывают, а тратить тысячу рублей на её покупку только ради этого мне не хочется.

Упоминание JUnix в книге «Операционные системы. Практикум. Учебное пособие», Назаров С.В., Гудыно Л.П., Кириченко А.А.

К слову, это не первая книжка, на страницы которой попал «ДжУникс». Первой была моя зачётная книжка. Поскольку во время увлечения этим проектом к учёбе я относился с прохладцей, пришлось совмещать приятное с полезным, и защищать «эмулятор» в качестве курсовой — как среду для обучения студентов операционной системе «Линукс».

Точную тему не помню, надо будет проверить по зачётке, благо я её не сдал после окончания учёбы.

 1 комментарий    253   2 мес   javascript   программирование

JUnix

Вкратце: выложил на гитхаб свой старый проект «эмулятора» Линукса, который я писал в 90-е и начале 2000-х

В 90-е мало кто видел потенциал применения ДжаваСкрипта в браузерах, тогда он, в основном, использовался для несложного интерактива — покрасить кнопки при наведении мышкой и прочие задачи того же уровня.

Мне тогда этот язык невероятно нравился, я был в бешеном восторге и такое вот несерьёзное к нему отношение меня очень задевало. Как-то я фантазировал на тему того, что можно было бы такого интересного сделать в браузере, чтобы показать значимость ДжаваСкрипта, и как-то мало-помалу в голову пришла идея запрограммировать эмулятор «Линукса» — я как раз активно изучал эту ОС в те годы.

Эта фантазия меня так увлекла, что примерно год я посвящал ей все вечера, в ущерб учёбе в Университете и личной жизни. Позже я ещё долго возвращался к этому проекту, правда моя активность всё угасала, пока в 2003-м году я не забросил эмулятор окончательно.

Старый, пыльный JUnix в современном браузере. Пришлось немного повозиться, чтобы запустить

Конечно настоящий эмулятор у меня не получился, да я и не пытался его создать, получилась имитация командной строки «Линукса» на том уровне знаний, который у меня был в те годы.

Реализованы кое-какие горячие клавиши, работа с историей и буфером обмена, основные команды (список выводится по команде «?»), перенаправление ввода-вывода, «пайп», работа с переменным, ветвления и циклы, виртуальная файловая система с возможностью написания плагинов и многое другое.

Поскольку шеллом по-умолчанию у меня тогда был tcsh, некоторые конструкции выглядят непривычно, кроме того, ряд команд я просто неправильно понимал и реализовал в соответствии со своими заблуждениями.

В своё время появление этого «эмулятора» понаделало шуму — о нём написали все основные российские сайты про программирование, а я каждый день получал письма от тех, кому понравилась моя игрушка.

Постепенно домен, на котором это всё располагалось, потерялся, а потом со старым винтом умер и бакап сайта. Осталась только копия в «Веб-архиве».

Так бы он там и лежал, но вчера в разговоре Леонидом Кагановым я случайно помянул почивший проект и Леонид, который его моментально вспомнил, предложил забрать сохранившееся с «Веб-архива» и куда-нибудь выложить.

Честно говоря, я и сам давно об этом думал — всё-таки, учитывая сколько души и времени вложено в этот «эмулятор», у меня с ним связано много хороших эмоций.

И вот вчера я наконец выкачал слепок первой попавшейся качалкой, поправил очевидные баги, чтобы всё заработало в современных браузерах — они всё-таки ушли далеко вперёд за это время, немного почистил от мусора и залил на «Гитхаб».

Кстати, если вам нравится в таком копаться, можете посмотреть сколько костылей в то время приходилось городить и как беден был раньше этот ДжаваСкрипт.

Я потестировал кое-какие основные команды, как будто теперь всё работает, но это не точно — всё-таки внутри больше пяти тысяч строк нетривиального кода без юнит-тестов. Интересующихся приглашаю ознакомиться с проектом по ссылкам ниже.

Репозиторий проекта: https://github.com/bolknote/junix.

Сайт проекта, где можно посмотреть всё в действии: https://bolknote.github.io/junix.

JavaScript и иврит

Выше прекрасный способ сломать мозг стыком трёх языков — английского, иврита и ДжаваСкрипта.

Как многим известно, в семитских языках текст записывается справа налево. Когда я лет 20 назад участвовал в разработке сайтов для некой арабской страны, это был тот ещё вызов моему внутреннему набору аксиом. Прокрутка слева, выделение текста в другую сторону, клавиша Backspace стирающая в противоположную сторону от стрелки, которая на ней нарисована, и прочие прелести.

Тогда кажется только Эксплорер умел поддерживать такое и переключался он атрибутом dir целиком, всем окном. Сейчас у нас есть Юникод и специальные коды смены направления текста. В одной строке можно сколько угодно его менять.

В ДжаваСкрипте выше именно это и сделано — английское const написано в привычном нам направлении, а дальше направление текста изменено и буквам иврита значения присваиваются справа налево. Выглядит психоделически, конечно.

Дополнение: в комментариях меня поправили. Оказывается коды смены направления тут не нужны — программы автоматически меняют направление, основываясь на том символы какого языка используются, просто в этот момент захватываются ещё и небуквенные символы — пунктуация, цифры и так далее.

Банан велик, а кожура еще больше

Много когда-то программировал на ДжаваСкрипте, поэтому многие его «особенности» просто заучил наизусть, даже не утруждая себя детальным пониманием почему и как это работает. В свою защиту хочу сказать, что многие вещи там просто «исторически сложились»

А тут братишка прислал в «Телеграм» кусок кода, который всплывает на «Стек Оверфлоу» не первый год:

console.log(0 >= null); // выведет true
console.log(0 > null || 0 == null); // выведет false

Странное поведение, как ни крути, ведь даже название операции «больше или равно» раскладывается на две — либо «больше», либо «равно». Казалось бы оба варианта должны давать одинаковый результат.

Решил я полюбопытствовать есть ли объяснение этому феномену.

Во всех браузерах работает одинаково странно, а это значит, что где-то в стандарте должно быть детально описано это поведение. И действительно, вот это место:

Let r be the result of performing abstract relational comparison lval < rval
If r is true or undefined, return false. Otherwise, return true

Что означает примерно следующее: если нам надо выполнить операцию «lval >= rval», то мы должны её преобразовать в «!(lval < rval)». То есть «0 >= null» преобразовывается в «!(0 < null)», результат операции внутри скобок — false (так как «ноль» не меньше, чем null), что после отрицания даёт нам true. Всё просто.

Что есть истина?

У нашего бывшего сотрудника в фейсбуке увидел ссылку на любопытную задачку — может ли (a == 1 && a == 2 && a == 3) быть «истиной» в ДжаваСкрипте?

Не заглядывая в статью, я предложил два варианта, вполне очевидный первый:

a = ((counter) => ({valueOf:() => ++counter}))(0)
// {valueOf: ƒ}
a == 1 && a == 2 && a == 3
// true

И второй — на суррогатных парах. Но по ссылке есть ряд других занимательных способов — через геттеры, похожие символы Юникода (мне приходил в голову такой вариант, но я не смог подобрать три символа, одинаковых на вид), другие специальные методы и прочее. Больше всех мне понравился такой способ:

a = [1,2,3];
a.join = a.shift;

a == 1 && a == 2 && a == 3
// true

Очень просто и элегантно — массив при преобразовании в скаляр в ДжаваСкрипте, всегда сначала преобразуется в строку значених, объединённых через запятую. В коде выше метод для объединения заменяется методом, который забирает из массива первый элемент. И всё работает как требуется — при каждом сравнении массива с числом, забирается первый элемент массива.

Что-то не вижу — быть или не быть?

Программа, выводящая монолог Гамлета (19.86КиБ)
Так выглядит программа, выводящая монолог Гамлета

Слово «выглядит» в подписи ко скриншоту выше упомянуто неслучайно — программа написана так, что видимое — только надводная часть айсберга.

Уже в те далёкие времена, когда я только ещё начинал писать на ДжаваСкрипте, программисты на форумах задавались вопросом можно ли как-то защитить свои программы на этом языке от обратной разработки. Помню «Микрософта» в своём браузере позволяла шифровать исходный код, но эту «защиту» довольно быстро поломали, очень уж она была простая.

Позже, когда производительность интерпретаторов ДжаваСкрипта стала стремительно повышаться, появились всяческие обсуфкаторы, сильно запутывающие программу за счёт удаления форматирования, внесения шума, замены имён переменных и функций и сжатия по словарю поверх всех замен.

С тех пор эти инструменты застыли примерно в том же состоянии, но теперь, мне кажется, в этом деле наметился прорыв.

Некто ФейкЮникод, разместил скрытое послание внутри суррогатных пар Юникода. Я когда-то делал что-то похожее на пробелах нулевой длины, но моим способом сильно не разбежишься — алфавит маленький.

Что такое суррогатные пары расписывать не буду, статей на эту тему предостаточно, главное, что их не видно и они могу быть частью (кроме первого символа) любого идентификатора ДжаваСкрипта.

Я попробовал использовать способ с суррогатными парами, чтобы скрыть монолог Гамлета внутри программы на ДжеЭсФаке (способ написания программ на ДжаваСкрипте, когда не используются алфавитно-цифровые знаки), плюс этими же парами закодировал имена переменных.

Получилась адская обфускация, глядя на которую и не заподозришь, что она после запуска выведет в консоль полтора килобайта английского текста.

F★ckJS на поло

Поло со значками (110.09КиБ)
Поло с программой на ДжаваСкрипте, написанной четыре года назад

Очень в тему к предыдущему посту на работе нашёлся мешок с поло размера XXL (из-за размера и сохранился, остальные разобрали).

На поло программа на ДжаваСкрипте, которую я писал к какому-то событию, должно быть готовились к какой-то конфереции — если её запустить в консоли браузера, появляется надпись «prihodite rabotat 88002005221». У меня в «исходящих» сохранилось письмо от 11 марта 2013 года, где я высылаю оригинал этой программы нашему дизайнеру, четыре года уже прошло, надо же.

«Странный» JS

В ДжаваСкрипте полно странностей, да, но популярная картинка, которая получила сейчас широкое хождение (не буду её приводить, просто суть перепишу) имеет отношение только к безграмотности её авторов. Суть такова:

[] + [] // массив + массив
"" // результат — пустая строка

[] + {} // массив + объект
"[object Object]" // В результате получаем объект? Ну ок

{} + [] // объект + массив
0 // 0? Реально?

{} + {} // объект + объект
NaN // Not a Number? WAT?

Выглядит очень всё ооочень странно, если думать, что происходит именно то, что написано в коментариях справа. На самом деле происходящее неверно интерпретировано авторами.

В ДжаваСкрипте фигурные скобки, помимо объекта, задают ещё и блок кода. В данном случае все «объекты» слева — на самом деле блоки кода. Откроем консоль и попробуем это доказать:

Вот что происходит на самом деле (9.90КиБ)

Как видите, в левый блок можно без труда добавить код и станет очевидно, что это не описание объекта. Так два последних обсуждаемых примера распадаются на две независимые команды — определение пустого блока кода, который ничего не выполнит и унарную операция «плюс» над пустым объектом или массивом.

С массивом, возвращающим пустоту при суммировании (конкатенации) всё ещё проще — в данном случае производится попытка вызвать метод toString, который у массива выводит строку его значений через запятую. Так как значений нет, строка пустая.

В общем, ничего сильно странного не происходит.

Как скачать документ из АИС ЦГАСО-2

Самарский архив видимо что-то у себя обновил и предыдущий способ для скачивания документов оттуда работать перестал. Очень жаль, удобство работы с интерфейсом архива оставляет желать лучшего, не говоря о скорости доступа к документам.

С просьбой что-то с этой проблемой сделать, мне написало около десятка человек, сегодня у меня наконец дошли руки посмотреть что изменилось. Как и в прошлый раз надо открыть окно консоли браузера и запустить скрипт (я проверял его в «Хроме»). Плохие новости в том, что скрипт будет работать относительно неспешно — 400 страниц обрабатывается примерно за 5—6 минут.

В конце работы в консоли будет длинная строка, начинающаяся с «dxo.itemsValue» и заканчивающаяся на «];». Её, как и в прошлый раз, надо будет скопировать в файл и передать в параметрах программе.

!function () {
    var id = '[id$=seadragonContainer] div div';
    var bt = '[id$=ForwardBtn]';
    var pages = {};
    var o = document.querySelector(id);

    !function _observe(undefined) {
        var ob = new MutationObserver(function() {
            var imgs = $(id+' img[src*=Pages]:first');
            if (imgs && imgs[0]) {
                var page = imgs[0].src.match(/id=([^&]+)/)[1];
                if (pages[page] == undefined) {
                    pages[page] = true;

                    ob.disconnect();

                    var next = $(bt);
                    if (next && next[0]) {
                        _observe();
                        next[0].click();
                    } else {
                        console.clear();
                        console.log("dxo.itemsValue=['" + Object.keys(pages).join("','")+"'];");
                    }
                }
            }
        });

        ob.observe(o, { childList: true, attributes: true, subtree: true });
    }();

    o.setAttribute('start', true);
}();

Вообще, можно было бы заморочиться и сильно ускорить сбор данных, но я не буду этого делать — меня результат вполне устраивает.

Внимание: скрипт должным образом я ещё не протестировал (просто не успел), так что на корректную работу пока не рассчитывайте!

Ранее Ctrl + ↓