496. Свой собственный Autoprefixer

Не решаласьСредняя

Вова работает в крупной сети магазинов по продаже двухколёсного транспорта «МыЛюбимВелосипеды.ру», в которой очень серьёзная служба информационной безопасности. Её сотрудники составили список разрешённых библиотек, в котором есть PostCSS, но, на удивление, отсутствует Autoprefixer.

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

К сожалению, с СИБом договориться не получилось, нет возможности расширить набор доступного ПО. Но наш герой не сдаётся, по жизни идёт и смеётся. Он решил, что можно написать Autoprefixer самостоятельно.

Помогите ему это сделать.

Autoprefixer — это плагин для PostCSS, который добавляет вендорные префиксы к CSS-свойствам.

Инструкция по написанию плагинов для PostCSS.

Плагин должен принимать объект vendorPrefixes, который содержит возможные префиксы для CSS-свойств и псевдоэлементов. Ключ объекта — это имя свойства или псевдоэлемента, а значение — массив с набором префиксов. Если ключ начинается с :: — значит, он содержит псевдоэлемент, иначе — свойство.

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

Примечания

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

Во время тестирования будет использован PostCSS версии 8.4.35.

Чтобы было легче разрабатывать плагин, мы сделали песочницу. Вы можете записать код вашего решения в файл plugin.js и запустить index.js, чтобы проверить работу.

Примеры

Пример объекта с вендорными префиксами:

const vendorPrefixes = {
  'display': ['webkit', 'moz'],
  'border-radius': ['webkit', 'moz', 'ms', 'o'],
  '::placeholder': ['ms-input', 'moz']
};

Пример исходного CSS:

.card {
  display: flex;
  align-items: center;
  padding: 16px;
  border-radius: 10px;
}

.secondary,
input::placeholder {
  color: #888;
}

Пример результата после обработки плагином:

.card {
  -webkit-display: flex;
  -moz-display: flex;
  display: flex;
  align-items: center;
  padding: 16px;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  -ms-border-radius: 10px;
  -o-border-radius: 10px;
  border-radius: 10px;
}

input::-ms-input-placeholder {
  color: #888;
}

input::-moz-placeholder {
  color: #888;
}

.secondary,
input::placeholder {
  color: #888;
}

Шаблон решения

module.exports = (opts = {vendorPrefixes: {}}) => {
  // Ваш плагин
};

module.exports.postcss = true;

Ограничения

Ограничение времени

1 с

Ограничение памяти

64 МБ

Пример 1

Ввод
// Vendor Prefixes
{
  "display": ["webkit", "moz"],
  "border-radius": ["webkit", "moz", "ms", "o"],
  "::placeholder": ["ms-input", "moz"]
}

// styles.css
.card {
  display: flex;
  align-items: center;
  padding: 16px;
  border-radius: 10px;
}

.secondary,
input::placeholder {
  color: #888;
}
Вывод
.card {
  -webkit-display: flex;
  -moz-display: flex;
  display: flex;
  align-items: center;
  padding: 16px;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  -ms-border-radius: 10px;
  -o-border-radius: 10px;
  border-radius: 10px;
}

input::-ms-input-placeholder {
  color: #888;
}

input::-moz-placeholder {
  color: #888;
}

.secondary,
input::placeholder {
  color: #888;
}

Пример 2

Ввод
// Vendor Prefixes
{
  "transform": ["webkit", "moz", "ms", "o"],
  "box-shadow": ["webkit", "moz"],
  "border-radius": ["webkit", "moz"],
  "margin": []
}

// styles.css
.center {
  position: relative;
  top: 50%;
  margin: 0 auto;
  transform: translateY(-50%);
}

.card {
  width: 300px;
  height: 300px;
  border-radius: 10px;
  background-color: crimson;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
Вывод
.center {
  position: relative;
  top: 50%;
  margin: 0 auto;
  -webkit-transform: translateY(-50%);
  -moz-transform: translateY(-50%);
  -ms-transform: translateY(-50%);
  -o-transform: translateY(-50%);
  transform: translateY(-50%);
}

.card {
  width: 300px;
  height: 300px;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
  background-color: crimson;
  -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

Пример 3

Ввод
// Vendor Prefixes
{
  "transform": ["webkit", "moz", "ms", "o"],
  "box-shadow": ["webkit", "moz"],
  "box-sizing": ["webkit", "moz"],
  "border-radius": ["webkit", "moz"],
  "justify-content": ["webkit"],
  "transition": ["webkit", "moz", "o"],
  "::placeholder": ["moz"],
  "margin": []
}

// styles.css
* {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  box-sizing: border-box;
}

.header {
  --header-height: 48px;
  
  display: flex;
  width: 100%;
  height: var(--header-height, 32px);
  padding: 0 16px;
  justify-content: space-between;
  background: crimson;
}

.menu__itemsList,
.menu__item{
  display: flex;
}

.menu__itemLink,
.header__signin {
  display: block;
  height: var(--header-height, 32px);
  padding: 0 16px;
  line-height: var(--header-height, 32px);
  text-decoration: none;
  color: #fff;
  transition: all 0.3 ease;
}

.menu__itemLink:hover {
  background: #810000;
}

.menu__itemLink:focus {
  outline: 2px dashed #fff;
  outline-offset: -2px;
}

@media (max-width: 720px) {
  .header {
    justify-content: center;
    background: darkgreen;
  }
}
Вывод
* {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.header {
  --header-height: 48px;
  
  display: flex;
  width: 100%;
  height: var(--header-height, 32px);
  padding: 0 16px;
  -webkit-justify-content: space-between;
  justify-content: space-between;
  background: crimson;
}

.menu__itemsList,
.menu__item{
  display: flex;
}

.menu__itemLink,
.header__signin {
  display: block;
  height: var(--header-height, 32px);
  padding: 0 16px;
  line-height: var(--header-height, 32px);
  text-decoration: none;
  color: #fff;
  -webkit-transition: all 0.3 ease;
  -moz-transition: all 0.3 ease;
  -o-transition: all 0.3 ease;
  transition: all 0.3 ease;
}

.menu__itemLink:hover {
  background: #810000;
}

.menu__itemLink:focus {
  outline: 2px dashed #fff;
  outline-offset: -2px;
}

@media (max-width: 720px) {
  .header {
    -webkit-justify-content: center;
    justify-content: center;
    background: darkgreen;
  }
}

Теги

JavaScript Node.js 20.14
Нужно войти, чтобы отправить решение.Войти