Spellcheck для любого текста
Ошибки бывают не только в логике, но и в словах.
Особенно если проект мультиязычный или с большим количеством переменных, комментариев и документации.
cspell — это CLI-инструмент, который проверяет орфографию прямо в коде: в идентификаторах, строках, комментариях и текстовых ресурсах.
Работает быстро, легко настраивается и поддерживает словари для десятков языков.
Пример базовой настройки:
Так получаем проверку орфографии русских и английских слов за один проход по проекту.
Выше представлена базовая конфигурация. Ознакомившись с документацией, вы сможете:
- подключать словари технических терминов, определенных фреймворков и библиотек
- добавлять собственные словари
- создавать отдельные настройки под каждый язык программирования
- тонко настраивать правила, используя маску для разрешения или запрета определенных слов
Если вы хотите поддерживать порядок не только в коде, но и в текстах — cspell поможет избежать опечаток и сэкономит время ревьюеров.
#linters #npm
Ошибки бывают не только в логике, но и в словах.
Особенно если проект мультиязычный или с большим количеством переменных, комментариев и документации.
cspell — это CLI-инструмент, который проверяет орфографию прямо в коде: в идентификаторах, строках, комментариях и текстовых ресурсах.
Работает быстро, легко настраивается и поддерживает словари для десятков языков.
Пример базовой настройки:
npm install --save-dev cspell @cspell/dict-ru_ru
// package.json
{
"scripts": {
"lint:cspell": "cspell **"
}
}
// .cspell.json
{
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
"version": "0.2",
"language": "en,ru",
"import": ["@cspell/dict-ru_ru/cspell-ext.json"]
}
Так получаем проверку орфографии русских и английских слов за один проход по проекту.
Выше представлена базовая конфигурация. Ознакомившись с документацией, вы сможете:
- подключать словари технических терминов, определенных фреймворков и библиотек
- добавлять собственные словари
- создавать отдельные настройки под каждый язык программирования
- тонко настраивать правила, используя маску для разрешения или запрета определенных слов
Если вы хотите поддерживать порядок не только в коде, но и в текстах — cspell поможет избежать опечаток и сэкономит время ревьюеров.
#linters #npm
Типизированные customEvents
Наверно каждый разработчик хоть раз писал свой CustomEvent-сервис.
Вот и мы написали свой. Но хотя бы типизированный.
Мы используем
- обеспечить строгую типизацию названий событий и их
- иметь автодополнение при вызове событий
- заранее знать структуру
Как использовать:
Реализация:
Если вы обходитесь без глобального стора, не хотите лишних зависимостей и при этом цените строгую типизацию — возможно, вам подойдёт именно такой вариант.
#typescript #vue #vueuse
Наверно каждый разработчик хоть раз писал свой CustomEvent-сервис.
Вот и мы написали свой. Но хотя бы типизированный.
Мы используем
window.dispatchEvent()
и useEventListener()
из VueUse, но оборачиваем их, чтобы:- обеспечить строгую типизацию названий событий и их
payload
- иметь автодополнение при вызове событий
- заранее знать структуру
event.detail
без явных проверок и any
Как использовать:
dispatchCustomDashboardEvent("user-created", user.id);
useDashboardEventListener("user-created", ({ detail }) => {
state = detail; // string, не any
});
Реализация:
import { useEventListener, type Arrayable } from "@vueuse/core";
// Доступные события и payload описываются через интерфейс
export interface CustomDashboardEvent {
"user-created": User["id"]
"user-deleted": never
}
type DashboardEventName = keyof CustomDashboardEvent;
// Создание типизированного события
function createCustomDashboardEvent<EventName extends DashboardEventName>(
eventName: EventName,
payload?: CustomDashboardEvent[EventName]
): CustomEvent<CustomDashboardEvent[EventName]> {
return new CustomEvent<CustomDashboardEvent[EventName]>(eventName, { detail: payload });
}
// Вызов события
export function dispatchCustomDashboardEvent<EventName extends DashboardEventName>(
eventName: EventName,
...[payload]: CustomDashboardEvent[EventName] extends never ? [] : [CustomDashboardEvent[EventName]]
): void {
window.dispatchEvent(createCustomDashboardEvent(eventName, payload));
}
// Прослушивание событий
export function useDashboardEventListener<EventName extends DashboardEventName>(
eventName: Arrayable<EventName>,
callback: (eventData: CustomEventInit<CustomDashboardEvent[EventName]>) => void,
options?: AddEventListenerOptions
): void {
useEventListener(window, eventName, callback, options);
}
Если вы обходитесь без глобального стора, не хотите лишних зависимостей и при этом цените строгую типизацию — возможно, вам подойдёт именно такой вариант.
#typescript #vue #vueuse
This media is not supported in your browser
VIEW IN TELEGRAM
Быстрая очистка node_modules
npkill — это CLI-утилита, которая ищет каталоги
Запуск:
По умолчанию утилита просканирует текущую папку и все вложенные каталоги на наличие
Перемещаясь стрелками и нажимая
⚠️
Периодическая очистка зависимостей в неактуальных или забытых проектах может освободить десятки гигабайт.
#npm
npkill — это CLI-утилита, которая ищет каталоги
node_modules
и позволяет удалять их одним нажатием клавиши.Запуск:
npx npkill
По умолчанию утилита просканирует текущую папку и все вложенные каталоги на наличие
node_modules
.Перемещаясь стрелками и нажимая
Space
, можно тут же удалить любую найденную папку с пакетами.⚠️
npkill
удаляет каталоги без подтверждения. Убедитесь, что у вас остались lock
файлы, чтобы при необходимости быстро восстановить зависимости.Периодическая очистка зависимостей в неактуальных или забытых проектах может освободить десятки гигабайт.
npkill
позволит сделать это быстро и просто.#npm
Добавление иконки перед ссылкой
Чтобы ссылка на внешний ресурс выглядела более узнаваемо, можно добавить к ней иконку, используя только CSS:
Работает для всех ссылок, в
Отображение разных иконок для одного домена:
⚠️ Безопасность
Можно указать ссылку на
Но есть нюансы:
- такие запросы подчиняются CORS-политике, и браузер может заблокировать загрузку;
- запросы к
Поэтому рекомендуется хранить иконки на сервере, либо вставлять их в формате
#css
Чтобы ссылка на внешний ресурс выглядела более узнаваемо, можно добавить к ней иконку, используя только CSS:
a[href*="github.com"]::before {
display: inline-block;
width: 1em;
height: 1em;
margin-right: 0.3em;
content: "";
background-image: url('/assets/icons/github.svg');
background-repeat: no-repeat;
background-size: contain;
}
a[href*="t.me"]::before {
display: inline-block;
width: 1em;
height: 1em;
margin-right: 0.3em;
content: "";
background-image: url('/assets/icons/telegram.svg');
background-repeat: no-repeat;
background-size: contain;
}
Работает для всех ссылок, в
href
которых встречается нужный домен.Отображение разных иконок для одного домена:
a[href^="https://github.com"] {
--icon: url('/assets/icons/github-icon.svg');
&[href*="/pulls"] {
--icon: url('/assets/icons/github-pull-icon.svg');
}
&::before {
display: inline-block;
width: 1em;
height: 1em;
margin-right: 0.3em;
content: "";
background-image: var(--icon);
background-repeat: no-repeat;
background-size: contain;
}
}
⚠️ Безопасность
Можно указать ссылку на
favicon
напрямую:a[href*="github.com"]::before {
background-image: url("https://github.com/favicon.ico");
}
Но есть нюансы:
- такие запросы подчиняются CORS-политике, и браузер может заблокировать загрузку;
- запросы к
favicon
являются внешними — они могут обмениваться куками и оставлять след в логах целевого сайта.Поэтому рекомендуется хранить иконки на сервере, либо вставлять их в формате
base64
.#css
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 до поддержки
Полный текст с кодом и объяснениями — по ссылке.
#linters
На первый взгляд сделать это несложно, но на практике есть свои нюансы и подводные камни. В подробном разборе я рассказал о своём опыте, с примерами и ключевыми моментами реализации: от базового API до поддержки
autofix
.Полный текст с кодом и объяснениями — по ссылке.
#linters
JS F/k
Как я написал свой Stylelint-плагин
Как создать собственный Stylelint-плагин: от базового API до поддержки autofix. Обрабатываем CSS-токены и избавляемся от ручной замены значений с помощью PostCSS.
Почему можно (и нужно) отказаться от 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.
Подробнее в статье по ссылке.
#ci #git
В больших проектах удобно сортировать Merge Request по размеру: мелкие правки можно рассмотреть быстро, а крупные требуют отдельного внимания. Чтобы не выставлять метки вручную, можно добавить скрипт в GitLab CI, который автоматически будет присваивать их ориентируясь на количество строк в diff.
Подробнее в статье по ссылке.
#ci #git
JS F/k
Автоматические size-метки для Merge Request в GitLab CI
Как автоматически выставлять метки size/M и size/XL в Merge Request в GitLab CI на основе количества изменений.
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
npm
npm: eslint-plugin-compat
Lint browser compatibility of API used. Latest version: 6.0.2, last published: 7 months ago. Start using eslint-plugin-compat in your project by running `npm i eslint-plugin-compat`. There are 383 other projects in the npm registry using eslint-plugin-compat.
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/
Frontendmasters
The Figcaption Problem
When an image isn't
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-stripping
v22.7.0: Добавлен флаг
--experimental-transform-types
v23.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.