- PVSM.RU - https://www.pvsm.ru -

Особая благодарность автору идеи @akopyl [1] Его статья [2]по теме.
Идея нехитрая, но очень заманчивая — пишешь CSS, пишется и CSS и HTML одновременно. Это ускорит и упростит разработку, да и реализовать несложно — HTML очень простой язык, по большому счёту состоящий из тегов, атрибутов и текста. У него есть и некоторые специфические особенности, вроде карт импорта [3] и shadow root [4], используемые нечасто, да и порой лишь с помощью скриптов, например, когда речь идёт о пользовательских элементах [5].
Попытка соединить функцию «разметки» и стилизации не выглядит сложной, уж очень простые языки.
Изначально идея имела реализации: раз [6], и даже две [7], но:
Одна (а то и обе, ибо ссылаются на API document), насколько я понял, работают исключительно в рамках веб‑страницы, то есть, не могут быть использованы, как самодостаточные библиотеки.
Криво реализуют текст в тегах — либо через псевдо‑элементы (sic!), либо через свойство content, что уже лучше, но не совсем валидно (теоретически, может произойти коллизия, по этой логике добавляли data-* атрибуты для HTML).
Писать атрибуты для элементов — сущий ад, ибо делается это только через селектор.
Автором статьи преследовалась цель создать улучшенный вариант библиотеки, которая работает вне рамок веб‑страницы (как отдельная библиотека), имеет усовершенствованные механизмы добавления тегов, текста… И по мелочи.
Проект на npm [8] и GitHub [9].
[8]Суть библиотеки в том, чтобы конвертировать это:
section#some-id {
--text: 'Это текст, товарищ!';
--attr-title: 'Заголовок';
background: red;
color: aliceblue;
}
section#some-id header[data-attribute='v'] {
--text: 'Это текст шапки';
color: blue;
}
section#some-id span {
--text: 'Это внутренний текст';
--text-after: 'А это текст после';
color: peru;
}
В это:
<section id="some-id" title="Заголовок">
Это текст, товарищ!
<header data-attribute="v">Это текст шапки</header>
<span> Это внутренний текст </span>А это текст после
</section>
Далее — принцип работы библиотеки невкратце.
Создать элемент можно через селектор:
div.classname#id[attr-1][attr-2='v'] {
/* Ни одна из частей селектора обязательной не является */
/* Но хоть что-то нужно оставить */
}
div {}
div span {
/* Поддерживается вложенность */
}
<div id="id" class="classname" attr-1 attr-2="v"></div>
<div>
<span></span>
</div>
Впрочем, порой нужно добавить стили, но не добавлять элемент. Для этого добавьте в селектор одно из:
Псевдо‑класс
Псевдо‑элемент
Один из этих селекторов: *, +, >, ||, |, ~
Или оберните в @at-rule
Пример — эти селекторы будут проигнорированы:
> div.classname#id[attr-1][attr-2='v'] {
}
div span * {
}
div::before {
/* Да, и этот тоже */
}
div:not(:has(span)) {
/* И этот тоже! */
}
@container (width > 1440px) {
span[data-a='Этот элемент будет проигнорирован тоже'] {}
}
Атрибуты можно задать через селектор (бывает полезно при стилизации), а можно через кастомные свойства [10] --attr-* и --attrs
/* В селекторе */
a[title='Title!']{
/* Точечно (внимание на то, что после attr-) */
--attr-href:'./index.html';
/* И массово! */
--attrs:'target="_self" rel="noopener noreferrer"';
}
<a title="Title!"
href="./index.html"
target="_self"
rel="noopener noreferrer"
></a>
Вписать текст в элемент не проблема - через специальное кастомное свойство:
div {
--text: 'И вновь продолжается бой';
}
<div> И вновь продолжается бой </div>
Если нужно вставить тег посреди текста, придётся немного вывернуться.
Технически, можно просто вписать тег в переменную текста:
div { --text: 'Никогда <span>не</span> делайте так!'; }
Но, как и указано, лучше так не делать.
Для этого есть специальные кастомные свойства, позволяющие вписать текст до и после тега:
div {
--text: 'Текст внутри div';
}
div span {
--text: 'Это текст внутри';
--text-before: '| до тега';
--text-after: '| после тега';
}
<div>
Текст внутри div | до тега<span> Это текст внутри </span>| после тега
</div>
Так‑с, с возможностями понятно, теперь об API.
Самый минимум для запуска выглядит так:
import { CssToHtml } from 'css2html'
let result = new CssToHtml({ css: "div{}", })
console.log(result.outputHTML)
Этот код выводит в терминал/консоль результат обработки простейшего CSS из одного тега.
Но это, конечно, не всё, это же минимум.
Для записи html непосредственно в файл, добавьте параметр write
(Внимание! Весь файл будет перезаписан)
new CssToHtml({
...,
write: {
in: "Ваш_путь_к_html_файлу",
},
})
Однако, есть один нюанс. Дело в том, что html имеет некоторый функционал, который через css передать так трудно, что лучше не пытаться. Например — скрипты написанные прямо в HTML или карты импорта.
А по умолчанию файл перезаписывается полностью, что ведёт к утрате бесценного кода, который не описать нормально в рамках css. В таких случаях нужно указывать конкретно, куда писать, вместо перезаписи всего.
С помощью параметров after и before как раз это и можно сделать — указывается область, которая будет доступна для перезаписи.
new CssToHtml({
...,
write: {
in: "Ваш_путь_к_html_файлу",
after: "<body>",
before: "</body>",
},
})
А ещё, HTML который создаёт библиотека кое‑как форматируется. За это отвечает плагин js‑beatify [11], которому можно передать параметры:
new CssToHtml({
...,
formatterOptions: {
indent_size: 2,
},
})
Вот и всё!
Но мне есть о чём порассуждать помимо библиотеки, ибо идея совмещения возможностей языков заманчиво выгодна.
Попытки объединить разметку, стилизацию и даже скрипты предпринимались неоднократно. JSX, описание стилей через JS‑объект [12], даже Tailwind [13] по сути занимается встраиванием стилей в HTML, брр…
Tailwind достоин отдельных тёплых слов, а по поводу остальных — попытки достойные, но результат недостаточный — они не объединяют. Они, грубо говоря, позволяют написать всё «в одну кучу» за счёт разбиения на зоны того или иного языка внутри одного файла. Это как взять кирпичи, бетон, стекло и пытаться сделать из них цельную стену.
Эта библиотека— попытка свести к минимуму или вовсе отказаться от одного из инструментов фронт‑энд разработки — HTML, перенеся его функции на другой инструмент — CSS. Можно пойти ещё дальше (за пределами этой библиотеки, естественно), соединив функции разметки, стилизации и скриптов — получился бы этакий единый язык веб‑страниц (название временное, придумано на "ход"у).
Очень большой соблазн повторить JSX — он кажется подходящим, но нет. Помимо причин, описанных выше, он слишком «жёсткий» для стилизации (либо через строки, либо через объекты, где селекторы в кавычках — отдельный «шедевр»), а попытки впилить в него ещё и CSS в чистом виде сделают его ещё больше походящим на кучу стройматериала.
Как и автор идеи этой библиотеки, я приведу свои мысли. На этот раз — по поводу языка, которого ещё нет.
Менять интернет из‑за нового языка никто не будет, ломать совместимость — последнее дело для таких больших структур. Лучше всего делать язык как препроцессор.
Язык должен одновременно описывать стили, разметку и логику используя одну лексику и грамматику, без разбиения на «диалекты».
Стоит вдохновиться чем-нибудь вроде 11l [14]. Честно, C‑образные языки уже достали, да и громоздкие они для таких задач. Желательно без однобуквенных операторов.
Сейчас мне на такую задачу не хватит времени. Посмотрим, хватит ли у кого смелости, желания и умения.
Автор: LeninIvanov
Источник [15]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/html/398275
Ссылки в тексте:
[1] @akopyl: https://www.pvsm.ru/users/akopyl
[2] статья : https://habr.com/ru/companies/selectel/articles/832868/
[3] карт импорта: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap
[4] shadow root: https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM
[5] пользовательских элементах: https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements
[6] раз: https://github.com/anatolykopyl/html-in-css
[7] две: https://www.npmjs.com/package/css-to-html
[8] npm: https://www.npmjs.com/package/css2html
[9] GitHub: https://github.com/Ulyanov-programmer/css2html
[10] кастомные свойства: https://developer.mozilla.org/ru/docs/Web/CSS/--*
[11] js‑beatify: https://github.com/beautifier/js-beautify
[12] описание стилей через JS‑объект: https://cssinjs.org/?v=v10.10.1
[13] Tailwind: https://tailwindcss.com/
[14] 11l: https://11l-lang.org
[15] Источник: https://habr.com/ru/articles/847542/?utm_source=habrahabr&utm_medium=rss&utm_campaign=847542
Нажмите здесь для печати.