Forwarded from mefody.dev
llms.txt
Если готовить сайты для поисковиков мы уже давно научились (SSR, sitemap.xml, robots.txt и прочее), то для LLM пока только учимся.
Полина Гуртовая поделилась интересной ссылкой на пропозал 2024 года. Если сайт хочет быть обработанным LLM-краулером, то достаточно в корень сайта положить файл
Пока что это пропозал от отдельного комьюнити, формально в процесс стандартизации от W3C или WHATWG его даже тяжело поместить, так как сфера AI ещё слишком юная, стандарты придумываются на ходу. Но тем не менее даже без стандарта наличие такого файла не повредит. Скоро SEO превратится в LLMEO, можно начать готовиться.
https://llmstxt.org/
Если готовить сайты для поисковиков мы уже давно научились (SSR, sitemap.xml, robots.txt и прочее), то для LLM пока только учимся.
Полина Гуртовая поделилась интересной ссылкой на пропозал 2024 года. Если сайт хочет быть обработанным LLM-краулером, то достаточно в корень сайта положить файл
/llms.txt с текстовым представлением всего, что нужно знать о сайте. Оформлять можно в Markdown, роботы с ним очень хорошо работают.Пока что это пропозал от отдельного комьюнити, формально в процесс стандартизации от W3C или WHATWG его даже тяжело поместить, так как сфера AI ещё слишком юная, стандарты придумываются на ходу. Но тем не менее даже без стандарта наличие такого файла не повредит. Скоро SEO превратится в LLMEO, можно начать готовиться.
https://llmstxt.org/
llms-txt
The /llms.txt file – llms-txt
A proposal to standardise on using an /llms.txt file to provide information to help LLMs use a website at inference time.
Поиск влитых git-веток и связанных задач
В крупном репозитории, где одновременно работают несколько разработчиков, может быть до 30 активных веток, часть из которых на паузе, часть в работе, а часть размечены в предстоящий релиз.
После каждого релиза такие ветки нужно удалять, делать это вручную — занятие сомнительное.
Чтобы не пропустить ветку или не удалить нужную, можно воспользоваться
git-merged-branches — это CLI-утилита, которая показывает ветки, влитые в основную (master или main).
Работает локально, проста в использовании, не имеет дочерних зависимостей и доступна также под коротким алиасом
Главная фича — возможность просматривать ссылки на задачи из трекера прямо в списке веток, если в названии используются идентификаторы задач, такие как JIRA-123, BUG-42 и т.п.
Использование
Установить глобально:
Или запустить через
Вызвав
Настройка идентификаторов задач
Если вы используете префиксы задач в названиях веток, например TOKEN-123_fix-layout — можно настроить автоматическое добавление ссылок на трекер задач.
Что изменит вывод на такой:
#npm
В крупном репозитории, где одновременно работают несколько разработчиков, может быть до 30 активных веток, часть из которых на паузе, часть в работе, а часть размечены в предстоящий релиз.
После каждого релиза такие ветки нужно удалять, делать это вручную — занятие сомнительное.
Чтобы не пропустить ветку или не удалить нужную, можно воспользоваться
git-merged-branches.git-merged-branches — это CLI-утилита, которая показывает ветки, влитые в основную (master или main).
Работает локально, проста в использовании, не имеет дочерних зависимостей и доступна также под коротким алиасом
gmb.Главная фича — возможность просматривать ссылки на задачи из трекера прямо в списке веток, если в названии используются идентификаторы задач, такие как JIRA-123, BUG-42 и т.п.
Использование
Установить глобально:
npm install --global git-merged-branches
Или запустить через
npx:npx git-merged-branches
Вызвав
git-merged-branches, или алиас gmb, утилита определит базовую ветку (master или main) и выведет список веток, которые уже были в неё влиты:$ gmb
Branches merged into 'master':
bugfix/fix-crash-on-start
feature/add-new-feature
hotfix/urgent-fix
Настройка идентификаторов задач
Если вы используете префиксы задач в названиях веток, например TOKEN-123_fix-layout — можно настроить автоматическое добавление ссылок на трекер задач.
// package.json
{
"git-merged-branches": {
"issueUrlFormat": "https://jira.my-company.com/browse/{{prefix}}{{id}}",
"issueUrlPrefix": ["TOKEN-", "BUG-"]
}
}
Что изменит вывод на такой:
TOKEN-123_fix-layout <https://jira.my-company.com/browse/TOKEN-123>
BUG-56_add-tests <https://jira.my-company.com/browse/BUG-56>
git-merged-branches — минималистичная, но полезная утилита, которая позволит быстро почистить ветки, заодно проверив их статус в трекере.#npm
Скачиваем приложение с RuStore без регистрации
RuStore — российский магазин приложений, который требует обязательной регистрации для скачивания приложений. Однако у RuStore есть публичное API, с помощью которого можно получить данные о приложении и скачать APK даже без аккаунта.
Получение информации о приложении
Получаем в ответе подробные данные о приложении и нужный нам id в
Получение ссылки для скачивания APK
Ответ будет содержать URL в
Скачивание APK
Перейдя по
Подробные данные об эндпоинтах можно найти на gist.github.
Итог
С помощью пары запросов к API RuStore можно обойти требование регистрации и получить APK-файл напрямую. Это пригодится для автоматической загрузки обновлений, резервного копирования или анализа приложений. Всё что вам нужно — знать
#service
RuStore — российский магазин приложений, который требует обязательной регистрации для скачивания приложений. Однако у RuStore есть публичное API, с помощью которого можно получить данные о приложении и скачать APK даже без аккаунта.
Получение информации о приложении
GET https://backapi.rustore.ru/applicationData/overallInfo/{packageName}Получаем в ответе подробные данные о приложении и нужный нам id в
body.appId.Получение ссылки для скачивания APK
POST https://backapi.rustore.ru/applicationData/download-link{
"appId": "body.appId",
"firstInstall": true
}Ответ будет содержать URL в
body.apkUrl.Скачивание APK
Перейдя по
body.apkUrl будет загружен .zip файл с приложением, внутри которого будет нужный нам .apk файл.Подробные данные об эндпоинтах можно найти на gist.github.
Итог
С помощью пары запросов к API RuStore можно обойти требование регистрации и получить APK-файл напрямую. Это пригодится для автоматической загрузки обновлений, резервного копирования или анализа приложений. Всё что вам нужно — знать
packageName приложения.#service
Альтернатива Postman и Insomnia
Postman уже давно больше, чем простой REST-клиент: он оброс авторизацией, облаками и платными фичами. Когда-то легковесной альтернативой ему была Insomnia, но и она постепенно ушла в сторону усложнения и ограничения бесплатного доступа. Теперь для базовых задач это уже не тот инструмент.
Yaak новая попытка вернуться к простоте. Он работает локально, не требует регистрации и предлагает только базовый функционал. Если нужен простой и понятный REST-клиент без отвлекающих надстроек — Yaak может подойти. Больше контекста — в посте автора.
#app
Postman уже давно больше, чем простой REST-клиент: он оброс авторизацией, облаками и платными фичами. Когда-то легковесной альтернативой ему была Insomnia, но и она постепенно ушла в сторону усложнения и ограничения бесплатного доступа. Теперь для базовых задач это уже не тот инструмент.
Yaak новая попытка вернуться к простоте. Он работает локально, не требует регистрации и предлагает только базовый функционал. Если нужен простой и понятный REST-клиент без отвлекающих надстроек — Yaak может подойти. Больше контекста — в посте автора.
#app
Vue, TypeScript и импортированные типы: что может пойти не так?
Когда вы используете
Компилятор постарается сделать всё возможное, чтобы вывести эквивалентные параметры времени выполнения, основанные на аргументах типа. Но сработает это не всегда.
Проблема: неработающий Boolean при импорте
На момент
Пример
Результат
Как видно из примера — если не передавать в проп
Решение
Если поменять тип на локально объявленный, всё работает верно.
В таком случае TypeScript передаёт в Vue AST более полную информацию о локальных типах, и Vue корректно использует конструктор
Проверить самостоятельно
Если хотите поэкспериментировать: Открыть демо на Vue Playground
Итог
Если вы столкнулись с тем, что
Если вам известно другое решение — пишите, будет интересно разобраться!
#typescript #vue #unresolved
Когда вы используете
defineProps в Vue с TypeScript, компилятор Vue запускает обратную генерацию типов: из интерфейсов, аннотаций и значений по умолчанию (default) создаются JS-конструкторы — Boolean, String, Object и другие. Именно они потом используются в скомпилированном компоненте в рантайме.Компилятор постарается сделать всё возможное, чтобы вывести эквивалентные параметры времени выполнения, основанные на аргументах типа. Но сработает это не всегда.
Проблема: неработающий Boolean при импорте
На момент
vue@3.5.*, если типы пропов импортируются, а не определяются прямо в компоненте — Vue может некорректно вывести тип Boolean при использовании shorthand-синтаксиса.Пример
<!-- Comp.vue -->
<script setup lang="ts">
import { Props } from "./types";
withDefaults(defineProps<Props>(), {
disabled: false,
sampleBooleanProp: false
});
</script>
// types.ts
import { InputHTMLAttributes } from "vue";
export interface Props {
disabled?: InputHTMLAttributes["disabled"] // импортированный тип
sampleBooleanProp?: boolean
}
Результат
<!-- Пропы не указаны. Должны примениться значения по умолчанию -->
<Comp/>
<!-- ✅ Работает верно. disabled: false, sampleBooleanProp: false -->
<!-- Пропы указаны со значениями. Должны примениться значения true -->
<Comp :disabled="true" :sampleBooleanProp="true"/>
<!-- ✅ Работает верно. disabled: true, sampleBooleanProp: true -->
<!-- Пропы указаны со значениями. Должны примениться значения false -->
<Comp disabled="false" sampleBooleanProp="false"/>
<!-- ✅ Работает верно. disabled: false, sampleBooleanProp: false -->
<!-- Пропы указаны в shorthand-формате. Должны примениться значения true -->
<Comp disabled sampleBooleanProp/>
<!-- ❌ Ошибка. disabled: '' (пустая строка), sampleBooleanProp: true -->
Как видно из примера — если не передавать в проп
disabled значение, то вместо ожидаемого true, проп равен пустой строке. То есть Vue не сгенерировал конструктор Boolean для disabled — он не смог вывести правильный тип из импортированного интерфейса.Решение
Если поменять тип на локально объявленный, всё работает верно.
// types.ts
// локальный интерфейс, полностью идентичен InputHTMLAttributes
interface InputHTMLAttributes_Local { disabled: boolean | "true" | "false" }
export interface Props {
disabled?: InputHTMLAttributes_Local["disabled"] // локальный аналог
sampleBooleanProp?: boolean
}
В таком случае TypeScript передаёт в Vue AST более полную информацию о локальных типах, и Vue корректно использует конструктор
Boolean.Проверить самостоятельно
Если хотите поэкспериментировать: Открыть демо на Vue Playground
Итог
Если вы столкнулись с тем, что
shorthand-пропы ведут себя странно — вероятно, проблема в неправильно выведенном типе из импортированного интерфейса. Пока единственное решение — объявить типы локально или отказаться от shorthand-синтаксиса.Если вам известно другое решение — пишите, будет интересно разобраться!
#typescript #vue #unresolved
Как я написал свой Stylelint-плагин
На первый взгляд сделать это несложно, но на практике есть свои нюансы и подводные камни. В подробном разборе я рассказал о своём опыте, с примерами и ключевыми моментами реализации: от базового API до поддержки
https://js-f-k.netlify.app/articles/custom-stylelint-plugin
#linters
На первый взгляд сделать это несложно, но на практике есть свои нюансы и подводные камни. В подробном разборе я рассказал о своём опыте, с примерами и ключевыми моментами реализации: от базового API до поддержки
autofix.https://js-f-k.netlify.app/articles/custom-stylelint-plugin
#linters
Почему можно (и нужно) отказаться от Prettier
Когда-то Prettier был обязательным выбором при старте нового проекта. Но времена меняются — и теперь он скорее мешает, чем помогает.
Anthony Fu (core-member Vue, Nuxt, Vite) ещё в 2022 написал убедительную статью о том, почему больше не использует Prettier. Ниже — краткое изложение ключевых аргументов:
- Opinionated. У создателей Prettier своё мнение, как должен выглядеть код — и почти никаких настроек.
- Минимум гибкости. Помимо отсутствия возможности конфигурации правил, большинство из них нельзя даже отключить.
- Конфликты с ESLint. Prettier навязывает стиль, ESLint проверяет логику. Чтобы они работали вместе приходится ставить обвязки, вроде eslint-plugin-prettier.
- ESLint — современная альтернатива. В текущих реалиях сам ESLint справляется с форматированием ничуть не хуже, но при этом даёт полный контроль в одной экосистеме.
Мнение
Я сам начал использовать Prettier году в 2018, и уже тогда он вызывал неудобства. Ранее не было достойных альтернатив, и он действительно скорее экономил время. Но сейчас его время прошло. Если вам всё ещё приходится объяснять, что не так с Prettier — просто дайте ссылку на эту статью.
#linters
Когда-то Prettier был обязательным выбором при старте нового проекта. Но времена меняются — и теперь он скорее мешает, чем помогает.
Anthony Fu (core-member Vue, Nuxt, Vite) ещё в 2022 написал убедительную статью о том, почему больше не использует Prettier. Ниже — краткое изложение ключевых аргументов:
- Opinionated. У создателей Prettier своё мнение, как должен выглядеть код — и почти никаких настроек.
- Минимум гибкости. Помимо отсутствия возможности конфигурации правил, большинство из них нельзя даже отключить.
- Конфликты с ESLint. Prettier навязывает стиль, ESLint проверяет логику. Чтобы они работали вместе приходится ставить обвязки, вроде eslint-plugin-prettier.
- ESLint — современная альтернатива. В текущих реалиях сам ESLint справляется с форматированием ничуть не хуже, но при этом даёт полный контроль в одной экосистеме.
Мнение
Я сам начал использовать Prettier году в 2018, и уже тогда он вызывал неудобства. Ранее не было достойных альтернатив, и он действительно скорее экономил время. Но сейчас его время прошло. Если вам всё ещё приходится объяснять, что не так с Prettier — просто дайте ссылку на эту статью.
#linters
Автоматические size-метки для Merge Request в GitLab CI
В больших проектах удобно сортировать Merge Request по размеру: мелкие правки можно рассмотреть быстро, а крупные требуют отдельного внимания. Чтобы не выставлять метки вручную, можно добавить скрипт в GitLab CI, который автоматически будет присваивать их ориентируясь на количество строк в diff.
https://js-f-k.netlify.app/articles/gitlab-size-labels
#ci #git
В больших проектах удобно сортировать Merge Request по размеру: мелкие правки можно рассмотреть быстро, а крупные требуют отдельного внимания. Чтобы не выставлять метки вручную, можно добавить скрипт в GitLab CI, который автоматически будет присваивать их ориентируясь на количество строк в diff.
https://js-f-k.netlify.app/articles/gitlab-size-labels
#ci #git
ESLint плагины: compat
С постоянным развитием стандарта ECMAScript и Web API вы наверняка сталкивались с ситуацией, когда хочется использовать новую возможность языка или API, но возникает вопрос — заработает ли это у пользователей. Возможно, вы даже добавляли полифиллы пару лет назад, но теперь уже не помните какие из них всё ещё нужны.
Чтобы писать код и не задумываться об этом, можно воспользоваться плагином eslint-plugin-compat — он автоматически проверит, поддерживаются ли используемые функции в целевых браузерах.
Установка
Поддержка полифиллов
Если вы используете полифиллы, их нужно явно указать в настройках — плагин не будет реагировать на такие API:
Итог
⚠️ Не забывайте обновлять
#linters #npm
С постоянным развитием стандарта ECMAScript и Web API вы наверняка сталкивались с ситуацией, когда хочется использовать новую возможность языка или API, но возникает вопрос — заработает ли это у пользователей. Возможно, вы даже добавляли полифиллы пару лет назад, но теперь уже не помните какие из них всё ещё нужны.
Чтобы писать код и не задумываться об этом, можно воспользоваться плагином eslint-plugin-compat — он автоматически проверит, поддерживаются ли используемые функции в целевых браузерах.
Установка
npm install --save-dev eslint-plugin-compat
// eslint.config.js
import compat from "eslint-plugin-compat";
export default [
// ...
compat.configs["flat/recommended"]
];
// package.json / .browserslistrc
{
"browserslist": [
"last 3 Chrome versions",
"Firefox ESR"
]
}
Поддержка полифиллов
Если вы используете полифиллы, их нужно явно указать в настройках — плагин не будет реагировать на такие API:
// eslint.config.js
{
"settings": {
"polyfills": [
"Promise",
"WebAssembly.compile",
"fetch",
"Array.prototype.push"
]
}
}
Итог
eslint-plugin-compat поможет предотвратить ситуацию, когда в прод попадает код, не работающий у части ваших пользователей. Если вы знаете, какие браузеры поддерживаете — подключите этот плагин, и ESLint сам предупредит, если появятся проблемы.⚠️ Не забывайте обновлять
caniuse зависимости, чтобы browserslist всегда соответствовал актуальным данным.#linters #npm
ESLint плагины: markdownlint
Даже если вы не пишете код, то с Markdown всё равно сталкиваетесь — документация, README или статьи. Он проще HTML и надёжнее Word: незакрытый тег не сломает вёрстку, а добавление переноса не унесёт весь абзац в другое измерение. Но если тексты объемные, то в них быстро могут накапливаться стилистические ошибки и несогласованности: лишние пробелы, неправильные стили заголовков, нумерация списков и так далее. Это мелочи, но исправив их, текст станет гораздо проще для восприятия.
eslint-plugin-markdownlint помогает подсветить такие ошибки: он интегрирует проверку Markdown-файлов прямо в ESLint, используя правила markdownlint.
Установка
Возможности
- Плагин поддерживает проверку
- Использует ESLint инфраструктуру — не нужно ставить дополнительные библиотеки.
- Большинство правил поддерживают autofix через
- Можно адаптировать любые правила под свои нужды, либо отключить ненужные.
Что именно он проверяет?
Базовые правила покрывают самые частые ошибки и несоответствия:
- Заголовки:
- Списки и блоки:
- Отступы, пробелы и переносы строк:
- Код и ссылки:
- Общие стилистические правила:
- Вёрстка таблиц и inline-html:
Полный список правил.
Итог
Если в вашем проекте с Markdown уже используется ESLint — подключите этот плагин и пишите аккуратные тексты не отвлекаясь на стилистические правки.
#linters #npm
Даже если вы не пишете код, то с Markdown всё равно сталкиваетесь — документация, README или статьи. Он проще HTML и надёжнее Word: незакрытый тег не сломает вёрстку, а добавление переноса не унесёт весь абзац в другое измерение. Но если тексты объемные, то в них быстро могут накапливаться стилистические ошибки и несогласованности: лишние пробелы, неправильные стили заголовков, нумерация списков и так далее. Это мелочи, но исправив их, текст станет гораздо проще для восприятия.
eslint-plugin-markdownlint помогает подсветить такие ошибки: он интегрирует проверку Markdown-файлов прямо в ESLint, используя правила markdownlint.
Установка
npm install --save-dev eslint-plugin-markdownlint
// eslint.config.js
import markdownlintPlugin from "eslint-plugin-markdownlint";
import markdownlintParser from "eslint-plugin-markdownlint/parser.js";
const markdownlintPluginConfig = {
files: ["*.md", "*.mdx"],
plugins: { markdownlint: markdownlintPlugin },
languageOptions: { parser: markdownlintParser },
rules: markdownlintPlugin.configs.recommended.rules
};
export default [
// ...
markdownlintPluginConfig
];
Возможности
- Плагин поддерживает проверку
.mdx файлов.- Использует ESLint инфраструктуру — не нужно ставить дополнительные библиотеки.
- Большинство правил поддерживают autofix через
--fix.- Можно адаптировать любые правила под свои нужды, либо отключить ненужные.
Что именно он проверяет?
Базовые правила покрывают самые частые ошибки и несоответствия:
- Заголовки:
MD001, MD003, MD018, MD025 — стили, отступы, вложенность.- Списки и блоки:
MD004, MD005, MD007, MD030, MD032.- Отступы, пробелы и переносы строк:
MD009, MD010, MD012, MD047.- Код и ссылки:
MD014, MD040, MD042, MD052.- Общие стилистические правила:
MD026 (точка в заголовке), MD036 (курсив вместо заголовка), MD041 (H1 — первой строкой).- Вёрстка таблиц и inline-html:
MD033, MD055, MD058Полный список правил.
Итог
Если в вашем проекте с Markdown уже используется ESLint — подключите этот плагин и пишите аккуратные тексты не отвлекаясь на стилистические правки.
#linters #npm
npm
npm: eslint-plugin-markdownlint
Eslint plugin for markdownlint. Latest version: 0.9.0, last published: a month ago. Start using eslint-plugin-markdownlint in your project by running `npm i eslint-plugin-markdownlint`. There are 19 other projects in the npm registry using eslint-plugin-markdownlint.
ESLint плагины: pinia
Хранилища (далее сторы) в Pinia — это основа архитектуры любого Vue-приложения. Но чем больше проект, тем сложнее следить за тем, чтобы все
eslint-plugin-pinia поможет автоматизировать эти проверки: после подключения в ESLint плагин найдет потенциальные ошибки, несогласованный стиль и архитектурные несоответствия в ваших
Установка
Что проверяет?
Правила покрывают самые частые ошибки:
-
-
-
-
-
-
-
Итог
Если вы используете Pinia — этот небольшой плагин поможет избежать многих архитектурных проблем ещё на этапе написания кода. Особенно пригодится в командной работе: сторы будут оформлены единообразно, код станет предсказуемым, а ревью — быстрее и проще.
#linters #npm #pinia
Хранилища (далее сторы) в Pinia — это основа архитектуры любого Vue-приложения. Но чем больше проект, тем сложнее следить за тем, чтобы все
defineStore были реализованы одинаково, не было дублирующихся id, а свойства явно экспортировались.eslint-plugin-pinia поможет автоматизировать эти проверки: после подключения в ESLint плагин найдет потенциальные ошибки, несогласованный стиль и архитектурные несоответствия в ваших
stores.Установка
npm install --save-dev eslint-plugin-pinia
// eslint.config.js
import piniaPlugin from "eslint-plugin-pinia";
export default [
// ...
piniaPlugin.configs["all-flat"]
];
Что проверяет?
Правила покрывают самые частые ошибки:
-
never-export-initialized-store — запрещает экспортировать результат defineStore(), только саму функцию.-
no-duplicate-store-ids — проверка уникальности id у всех defineStore.-
no-return-global-properties — запрет возврата inject, useRouter, useRoute из стора напрямую.-
no-store-to-refs-in-store — storeToRefs() не должны использоваться внутри defineStore.-
prefer-single-store-per-file — один файл должен содержать один стор. Отключено по умолчанию-
prefer-use-store-naming-convention — названия сторов должны начинаться с use: useCartStore, useUserStore, и т.д. Отключено по умолчанию-
require-setup-store-properties-export — все свойства state в setup-сторе должны быть экспортированы.Итог
Если вы используете Pinia — этот небольшой плагин поможет избежать многих архитектурных проблем ещё на этапе написания кода. Особенно пригодится в командной работе: сторы будут оформлены единообразно, код станет предсказуемым, а ревью — быстрее и проще.
#linters #npm #pinia
npm
npm: eslint-plugin-pinia
ESLint plugin for Pinia best practices. Latest version: 0.4.1, last published: a year ago. Start using eslint-plugin-pinia in your project by running `npm i eslint-plugin-pinia`. There are 4 other projects in the npm registry using eslint-plugin-pinia.
Отслеживание метрик и зависимостей JS-проектов в GitHub
Если вы ведёте сразу несколько пет-проектов в GitHub, вам может быть сложно отслеживать все метрики.
GitHub Metrics собирает данные о репозиториях и показывает количество звёзд, форков, issues. Помимо этого, сервис парсит
Кроме того, генерируется таблица со списком всех зависимостей и их версий. Если вы стараетесь придерживаться единого стека, инструмент поможет быстро выявить устаревшие зависимости (например, старые major‑версии) или случаи, когда для одной задачи используются разные библиотеки.
GitHub Metrics — это не CI-утилита и не облачный билд-сервис, а простой и наглядный дашборд, который помогает навести порядок в зоопарке пет-проектов. Один раз настроив его, вы сможете быстро увидеть, где устарели пакеты, где забыли про лицензию или CI, а где появились новые звёзды.
#git #service
Если вы ведёте сразу несколько пет-проектов в GitHub, вам может быть сложно отслеживать все метрики.
GitHub Metrics собирает данные о репозиториях и показывает количество звёзд, форков, issues. Помимо этого, сервис парсит
package.json и отображает используемый пакетный менеджер, бандлер, фреймворки для тестов и статус последнего CI-билда. Передав токены, дополнительно можно подключить бейджи UptimeRobot и Netlify Deploy Status.Кроме того, генерируется таблица со списком всех зависимостей и их версий. Если вы стараетесь придерживаться единого стека, инструмент поможет быстро выявить устаревшие зависимости (например, старые major‑версии) или случаи, когда для одной задачи используются разные библиотеки.
GitHub Metrics — это не CI-утилита и не облачный билд-сервис, а простой и наглядный дашборд, который помогает навести порядок в зоопарке пет-проектов. Один раз настроив его, вы сможете быстро увидеть, где устарели пакеты, где забыли про лицензию или CI, а где появились новые звёзды.
#git #service
github-metrics.netlify.app
GitHub Metrics
Discover comprehensive insights into your GitHub repositories' metrics. Track stars, forks, and more, all conveniently stored locally.
Forwarded from mefody.dev
Проблема с figcaption
Представьте вполне себе привычную, довольно семантичную вёрстку для картинок с подписями.
Крис Койер задаётся вопросом, как сделать так, чтобы:
1. Картинка могла быть любой ширины, но не превышала размер контейнера.
2. Подпись в
3. Всей этой конструкции можно было добавить красивую обводку.
Простая на первый взгляд задача на самом деле имеет свои заморочки. В статье есть несколько решений.
https://frontendmasters.com/blog/the-figcaption-problem/
Представьте вполне себе привычную, довольно семантичную вёрстку для картинок с подписями.
<figure>
<img src="image.jpg" alt="доступное описание">
<figcaption>Длинный-длинный текст, который по ширине значительно превышает ширину самой картинки</figcaption>
</figure>
Крис Койер задаётся вопросом, как сделать так, чтобы:
1. Картинка могла быть любой ширины, но не превышала размер контейнера.
2. Подпись в
figcaption подстраивалась по размеру к ширине картинки.3. Всей этой конструкции можно было добавить красивую обводку.
Простая на первый взгляд задача на самом деле имеет свои заморочки. В статье есть несколько решений.
https://frontendmasters.com/blog/the-figcaption-problem/
Forwarded from mefody.dev
Креативность и цитаты
Энди Кларк задаётся вопросом, как можно стилизовать цитаты и врезки на сайте музыкального исполнителя. Начинает с базовой разметки, постепенно добавляет новые и новые стили, и в конце получает то оформление, которое его устраивает.
Мне понравилась заключительная мысль статьи: цитаты на странице тоже могут вызывать настроение через визуальные смыслы. И вполне нормально экспериментировать с их оформлением, чтобы получилось классно.
https://css-tricks.com/getting-creative-with-quotes/
Энди Кларк задаётся вопросом, как можно стилизовать цитаты и врезки на сайте музыкального исполнителя. Начинает с базовой разметки, постепенно добавляет новые и новые стили, и в конце получает то оформление, которое его устраивает.
Мне понравилась заключительная мысль статьи: цитаты на странице тоже могут вызывать настроение через визуальные смыслы. И вполне нормально экспериментировать с их оформлением, чтобы получилось классно.
https://css-tricks.com/getting-creative-with-quotes/
CSS-Tricks
Getting Creative With Quotes | CSS-Tricks
How do you design block quotes and pull quotes to reflect a brand’s visual identity and help tell its story? Here’s how I do it by styling the HTML blockquote element using borders, decorative quote marks, custom shapes, and a few unexpected properties.
Telegram Mini Apps: быстрый старт
Создавать мини-приложения для Telegram проще, чем кажется.
Всё, что нужно:
1. Зарегистрировать бота через @BotFather;
2. Указать ссылку на ваш сайт.
После этого сайт откроется прямо внутри Telegram — без сложной логики или интеграций. Фактически это тот же веб-сайт, только с запуском в мессенджере.
Хотите довести всё до идеала? Оптимизируйте страницу под размеры окна Telegram, сделайте отдельный быстрый лендинг или добавьте поддержку специфичных API. Подробный разбор с примерами таких улучшений есть в статье на Хабре: Telegram Mini App. Как создать Web App с нуля.
Главное — начать с простого, а детали можно освоить позже.
#service
Создавать мини-приложения для Telegram проще, чем кажется.
Всё, что нужно:
1. Зарегистрировать бота через @BotFather;
2. Указать ссылку на ваш сайт.
После этого сайт откроется прямо внутри Telegram — без сложной логики или интеграций. Фактически это тот же веб-сайт, только с запуском в мессенджере.
Хотите довести всё до идеала? Оптимизируйте страницу под размеры окна Telegram, сделайте отдельный быстрый лендинг или добавьте поддержку специфичных API. Подробный разбор с примерами таких улучшений есть в статье на Хабре: Telegram Mini App. Как создать Web App с нуля.
Главное — начать с простого, а детали можно освоить позже.
#service
Запуск TypeScript напрямую в Node.js
Хорошие новости: в новых версиях Node.js можно запускать
v22.6.0: Появилась базовая поддержка
v22.7.0: Добавлен флаг
v23.6.0: Удаление аннотации типов включено по умолчанию
v24.3.0: Функция больше не считается экспериментальной
Подробнее о нативной поддержке TypeScript в Node.js — в официальной документации.
Что изменилось
- Node.js сам удаляет аннотации типов (type stripping), оставляя чистый JavaScript.
- Флаг
- Если используются конструкции, требующие транспиляции (
Пример запуска
Как писать совместимый код
В TypeScript 5.8 появился новый флаг
Кому это пригодится?
Крупные проекты на TypeScript, которые активно используют
#build #typescript
Хорошие новости: в новых версиях Node.js можно запускать
.ts-файлы напрямую — без ts-node, tsx или ручной сборки.v22.6.0: Появилась базовая поддержка
type-strippingv22.7.0: Добавлен флаг
--experimental-transform-typesv23.6.0: Удаление аннотации типов включено по умолчанию
v24.3.0: Функция больше не считается экспериментальной
Подробнее о нативной поддержке TypeScript в Node.js — в официальной документации.
Что изменилось
- Node.js сам удаляет аннотации типов (type stripping), оставляя чистый JavaScript.
- Флаг
--experimental-strip-types теперь не обязателен — он активен по умолчанию. При необходимости его можно отключить с помощью --no-experimental-strip-types.- Если используются конструкции, требующие транспиляции (
enum, namespace), потребуется флаг --experimental-transform-types.Пример запуска
node --experimental-transform-types index.ts
Как писать совместимый код
В TypeScript 5.8 появился новый флаг
erasableSyntaxOnly. Он запрещает конструкции, которые Node.js не сможет вырезать. Добавив этот параметр в tsconfig.json, редактор предупредит вас о неподдерживаемом коде.Кому это пригодится?
Крупные проекты на TypeScript, которые активно используют
namespace, enum и прочие трансформируемые конструкции, всё равно останутся на привычных инструментах вроде ts-node, tsx или полноценной сборки через tsc — и это нормально. Но для маленьких утилит, тестовых скриптов и инструментов возможность просто запустить node script.ts — отличный способ сэкономить время и не настраивать дополнительное окружение.#build #typescript
nodejs.org
Node.js — Running TypeScript Natively
Node.js® is a free, open-source, cross-platform JavaScript runtime environment that lets developers create servers, web apps, command line tools and scripts.
Модульность и видимость экспортов
Разделение кода на мелкие модули — хорошая практика, но она сталкивается с тривиальной проблемой инкапсуляции: экспортированные из внутренних файлов сущности становятся видны по всему проекту. Если в нескольких подмодулях есть функция или переменная с одинаковым именем, IDE при автодополнении будет предлагать импорты из всех этих файлов.
Ни у платформы, ни у языкового стандарта пока нет простого механизма видимости по модулю — то есть способа пометить экспорт как доступный только внутри границ модуля/папки. На площадке обсуждения стандартов EcmaScript (Ecma Technical Committee 39) есть тред, где обсуждается идея директивы вроде
Иные варианты существуют, но они компромиссны: уникальные имена, явное указание
Решения на уровне стандарта и экосистемы были бы желательны, но если у вас есть идеи по реализации — предлагайте в обсуждении или непосредственно в треде на es.discourse.group.
#build #unresolved
Разделение кода на мелкие модули — хорошая практика, но она сталкивается с тривиальной проблемой инкапсуляции: экспортированные из внутренних файлов сущности становятся видны по всему проекту. Если в нескольких подмодулях есть функция или переменная с одинаковым именем, IDE при автодополнении будет предлагать импорты из всех этих файлов.
Ни у платформы, ни у языкового стандарта пока нет простого механизма видимости по модулю — то есть способа пометить экспорт как доступный только внутри границ модуля/папки. На площадке обсуждения стандартов EcmaScript (Ecma Technical Committee 39) есть тред, где обсуждается идея директивы вроде
'use internal' или модификатора internal, которые ограничивали бы область видимости экспортов, но это остаётся лишь предложением.Иные варианты существуют, но они компромиссны: уникальные имена, явное указание
namespace, отказ от реэкспорта конфликтующих сущностей через barrel export, linter-правила, настройка IDE для предпочтения локальных импортов. Все эти подходы имеют свои минусы и не дают системного, стандартного контроля видимости экспортов.Решения на уровне стандарта и экосистемы были бы желательны, но если у вас есть идеи по реализации — предлагайте в обсуждении или непосредственно в треде на es.discourse.group.
#build #unresolved
TC39
Module-Level Export Visibility: 'use internal' Directive or export internal Syntax
Let’s say we want to decouple something - some utilities, for example - into a separate file. If we have a main module called myModule.js, we can create a file named myModule.utils.js in the same directory. Inside this new file, we might write something…
Forwarded from Веб-стандарты (Vadim Makeev)
Baseline в Browserlist. Свежий релиз Browserlist 4.26.0 теперь позволяет настроить браузерную поддержку в терминах Baseline, например
https://browsersl.ist/#:~:text=select%20browser%20by%20baseline
"baseline widely available", "baseline newly available", а также более консервативый "baseline 2024" и раньше. #baseline #toolshttps://browsersl.ist/#:~:text=select%20browser%20by%20baseline
Forwarded from mefody.dev
Что мы можем делать при помощи corner-shape
Помню, как сильно радовался массовому внедрению в браузеры свойства
Но в дизайнах всё ещё бывают не только выпуклые круглые уголки. На данный момент без хаков можно играться с овальными формами границ. Ну или разбираться с
Дэниэл Шварц показывает, как мы сможем визуально создавать всевозможные формы блоков с помощью нового свойства
- впуклые уголки (инвертированный круг);
- скошенные уголки;
- вырезанные уголки;
- сквирклы (красивые более естественные скругления).
С демками.
https://css-tricks.com/what-can-we-actually-do-with-corner-shape/
Помню, как сильно радовался массовому внедрению в браузеры свойства
border-radius. Не нужно больше рисовать скруглённые уголки при помощи таблиц, кайф!Но в дизайнах всё ещё бывают не только выпуклые круглые уголки. На данный момент без хаков можно играться с овальными формами границ. Ну или разбираться с
border-image, который не самый developer friendly, на мой взгляд. Хотя в большинстве случаев этого всё-таки хватает.Дэниэл Шварц показывает, как мы сможем визуально создавать всевозможные формы блоков с помощью нового свойства
corner-shape, которое пока что работает только в Chrome:- впуклые уголки (инвертированный круг);
- скошенные уголки;
- вырезанные уголки;
- сквирклы (красивые более естественные скругления).
С демками.
https://css-tricks.com/what-can-we-actually-do-with-corner-shape/
CSS-Tricks
What Can We Actually Do With corner-shape? | CSS-Tricks
When I first started messing around with code, rounded corners required five background images or an image sprite likely created in Photoshop, so when
Типизация as const
В TypeScript
Посмотрим, как это работает на практике и какие подводные камни возникают при использовании обычной типизации и
Прямое указание типа
Свойство остаётся изменяемым. Видно, что обычное указание типа не защищает от изменений.
Использование as const
В названии поля допущена ошибка (
Комбинация as const и интерфейса
Кажется логичным совместить
На практике
Readonly
Такой способ защитит от изменения свойств, а переданный тип
ReadonlyDeep
Если вам достаточно
Решение
Чтобы одновременно зафиксировать значения и проверить правильность структуры, используется оператор
При использовании конструкции
Итог
#typescript
В TypeScript
as const позволяет фиксировать значения литералов и делать их максимально конкретными: строки не расширяются до string, числа — до number, а свойства объектов и массивы становятся readonly. Это удобно, когда нужно работать с неизменяемыми объектами или использовать их как "enum-подобные" конструкции. Документация: const assertionsПосмотрим, как это работает на практике и какие подводные камни возникают при использовании обычной типизации и
as const.Прямое указание типа
type Fruit = { name: string };
const Apple: Fruit = { name: "Apple" }; // создаём объект Apple и указываем, что он имеет тип Fruit
Apple.name = "Orange"; // ⚠️ нет ошибкиСвойство остаётся изменяемым. Видно, что обычное указание типа не защищает от изменений.
Использование as const
const Apple = { nme: "Apple" } as const; // объект неизменяемый
function isFruit(payload: unknown): payload is Fruit { return payload && "name" in payload; } // простейший type-guard для наглядности
isFruit(Apple); // ⚠️ falseВ названии поля допущена ошибка (
nme вместо name), поэтому проверка не сработала. Это показывает, что as const фиксирует значения, но не гарантирует соответствие интерфейсу — легко допустить опечатку или пропустить обязательное поле.Комбинация as const и интерфейса
Кажется логичным совместить
as const с интерфейсом:const Apple: Fruit = { name: "Apple" } as const;
Apple.name = "Orange"; // ⚠️ нет ошибкиНа практике
as const "теряется": тип сужается до { name: string }, и свойство снова становится изменяемым.Readonly
const Apple: Readonly<Fruit> = { name: "Apple" };
Apple.name = "Orange"; // ✅ ошибка компиляцииТакой способ защитит от изменения свойств, а переданный тип
Fruit не даст ошибиться в названиях полей. Но есть нюанс: IDE покажет тип Apple как { name: string }, а не конкретное значение { name: "Apple" }. Будет потерян "конкретный тип", ради которого обычно и используется as const.ReadonlyDeep
Если вам достаточно
Readonly, не забывайте, что он работает только на верхнем уровне объекта: вложенные объекты и массивы останутся изменяемыми. В таких случаях стоит использовать утилиту ReadonlyDeep из type-fest. Она рекурсивно обходит все уровни и делает все свойства неизменяемыми.Решение
Чтобы одновременно зафиксировать значения и проверить правильность структуры, используется оператор
satisfies. Он проверяет, что выражение совместимо с указанным типом, при этом сохраняя исходный (более конкретный) тип для вывода. Документация: satisfies operatorconst Apple = { name: "Apple" } as const satisfies Fruit;
Apple.name = "Orange"; // ✅ ошибка компиляцииПри использовании конструкции
as const satisfies %type% TypeScript корректно проверяет правильность полей в объекте, as const сохраняет неизменность значений, а попытка присвоить новое значение свойству ловится на этапе компиляции.Итог
as const satisfies — простой способ объединить две цели: сохранить значения объекта неизменными и убедиться, что его структура соответствует интерфейсу. Особенно полезно для крупных объектов, например конфигураций, где легко допустить опечатку или ошибку в типах.#typescript
Forwarded from mefody.dev
Динамический тултип
Темани Афиф делится коротким сниппетом, который позволяет собрать тултип на чистом CSS. Тултип пытается вместиться во вьюпорт любым легальным способом. И следует за якорем.
То, для чего мы сейчас используем JS-библиотеки на 200 килобайт, можно будет заменить на пару десятков строк CSS благодаря Anchor Positioning.
(Не забывайте проверять CanIUse)
https://css-tip.com/tooltip-anchor/
Темани Афиф делится коротким сниппетом, который позволяет собрать тултип на чистом CSS. Тултип пытается вместиться во вьюпорт любым легальным способом. И следует за якорем.
То, для чего мы сейчас используем JS-библиотеки на 200 килобайт, можно будет заменить на пару десятков строк CSS благодаря Anchor Positioning.
(Не забывайте проверять CanIUse)
https://css-tip.com/tooltip-anchor/
Css-Tip
Dynamic Tooltip Position with Anchor Positioning
A tootlip that follows its anchor while adjusting the position of its tail